var updateStreamingModeOptions = window.CrankStreamingForm.updateStreamingModeOptions; var updateStreamingConfigVisibility = window.CrankStreamingForm.updateStreamingConfigVisibility; function buildToolDescription() { return { title: textValue('tool-title') || textValue('tool-display-name') || textValue('tool-name'), description: textValue('tool-description'), tags: [], examples: [], }; } function collectWizardPayload() { var name = textValue('tool-name'); if (!name) throw new Error(tKey('wizard.error.tool_name')); var inputSchemaValue = parseStructuredText(textValue('tool-input-schema')); var outputSchemaValue = parseStructuredText(textValue('tool-output-schema')); var inputMappingValue = parseStructuredText(textValue('tool-input-mapping')); var outputMappingValue = parseStructuredText(textValue('tool-output-mapping')); return { name: name, display_name: textValue('tool-display-name') || name, category: 'general', protocol: wizardProtocol, target: buildTarget(), input_schema: convertJsonSchemaToCrankSchema(inputSchemaValue, []), output_schema: convertJsonSchemaToCrankSchema(outputSchemaValue, []), input_mapping: buildMappingSet(inputMappingValue, 'input'), output_mapping: buildMappingSet(outputMappingValue, 'output'), execution_config: parseExecutionConfig(textValue('tool-exec-config')), tool_description: buildToolDescription(), }; } async function saveOperation(stayOnPage) { try { await persistCurrentDraft(stayOnPage); } catch (error) { if (window.CrankUi) { window.CrankUi.error(error.message || tKey('wizard.error.save'), tKey('wizard.error.save_title')); } } } async function loadOperationForEdit() { if (!wizardWorkspaceId || !wizardEditId) return; var detail = await window.CrankApi.getOperation(wizardWorkspaceId, wizardEditId); wizardProtocol = detail.protocol || 'rest'; await loadWizardPanels([3]); var draftVersion = await window.CrankApi.getOperationVersion( wizardWorkspaceId, wizardEditId, detail.draft_version_ref.version ); wizardCurrentOperation = detail; wizardCurrentVersion = draftVersion; prefillWizardFromEdit(detail, draftVersion); } function setEditModePresentation() { var progressLabel = document.querySelector('.progress-label'); if (progressLabel) progressLabel.textContent = tKey('wizard.progress.edit'); renderSidebarBrand('edit'); } function selectProtocol(protocol) { wizardProtocol = protocol || 'rest'; document.querySelectorAll('.protocol-card').forEach(function(card) { var proto = card.dataset.protocol || (card.classList.contains('rest') ? 'rest' : card.classList.contains('graphql') ? 'graphql' : card.classList.contains('grpc') ? 'grpc' : card.classList.contains('websocket') ? 'websocket' : card.classList.contains('soap') ? 'soap' : 'rest'); var selected = proto === wizardProtocol; card.classList.toggle('selected', selected); card.setAttribute('aria-checked', selected ? 'true' : 'false'); }); var s3name = document.getElementById('sidebar-step-3-name'); if (s3name) { var step3Labels = window.CrankWizardState.step3Labels(); s3name.textContent = step3Labels[wizardProtocol] || tKey('wizard.step3.rest.label'); } updateWizardProtocolVisibility(); } function bindWizardLiveActions() { bindLiveAction('wizard-upload-input-sample', tKey('wizard.busy.input_sample'), uploadInputSampleFromWizard); bindLiveAction('wizard-upload-output-sample', tKey('wizard.busy.output_sample'), uploadOutputSampleFromWizard); bindLiveAction('wizard-generate-draft', tKey('wizard.busy.generate'), generateDraftFromWizard); bindLiveAction('wizard-run-test', tKey('wizard.busy.test'), runWizardTest); bindClick('wizard-copy-test-response', copyTestResponseToOutputSample); bindLiveAction('wizard-export-yaml', tKey('wizard.busy.export_yaml'), exportWizardYaml); bindLiveAction('wizard-import-yaml', tKey('wizard.busy.import_yaml'), importWizardYaml); bindLiveAction('wizard-publish-operation', tKey('wizard.busy.publish'), publishWizardOperation); bindClick('wizard-select-descriptor-set', function() { var input = document.getElementById('wizard-descriptor-set-input'); if (input) input.click(); }); bindLiveAction('wizard-upload-descriptor-set', tKey('wizard.busy.descriptor'), uploadDescriptorSetAndDiscover); bindClick('wizard-select-soap-wsdl', function() { var input = document.getElementById('wizard-soap-wsdl-input'); if (input) input.click(); }); bindClick('wizard-select-soap-xsd', function() { var input = document.getElementById('wizard-soap-xsd-input'); if (input) input.click(); }); bindLiveAction('wizard-upload-soap-contracts', tKey('wizard.busy.wsdl'), uploadSoapArtifactsAndInspect); bindClick('wizard-import-yaml-file-trigger', function() { var input = document.getElementById('wizard-import-yaml-file'); if (input) input.click(); }); var descriptorInput = document.getElementById('wizard-descriptor-set-input'); if (descriptorInput) descriptorInput.addEventListener('change', handleDescriptorSetSelection); var soapWsdlInput = document.getElementById('wizard-soap-wsdl-input'); if (soapWsdlInput) soapWsdlInput.addEventListener('change', handleSoapWsdlSelection); var soapXsdInput = document.getElementById('wizard-soap-xsd-input'); if (soapXsdInput) soapXsdInput.addEventListener('change', handleSoapXsdSelection); var yamlInput = document.getElementById('wizard-import-yaml-file'); if (yamlInput) yamlInput.addEventListener('change', handleImportYamlFileSelection); } function bindClick(id, handler) { var element = document.getElementById(id); if (!element) return; element.addEventListener('click', function(event) { event.preventDefault(); handler(); }); } function bindLiveAction(id, busyLabel, handler) { var element = document.getElementById(id); if (!element) return; element.addEventListener('click', function(event) { event.preventDefault(); runWizardLiveAction(element, busyLabel, handler); }); } async function runWizardLiveAction(button, busyLabel, handler) { if (!button || button.dataset.busy === 'true') { return; } var originalLabel = button.textContent; button.dataset.busy = 'true'; button.disabled = true; button.classList.add('is-busy'); button.textContent = busyLabel; try { await handler(); } catch (error) { showWizardLiveStatus( tKey('wizard.live.failed_title'), error && error.message ? error.message : tKey('wizard.live.failed_body'), true ); if (window.CrankUi) { window.CrankUi.error( error && error.message ? error.message : tKey('wizard.live.failed_body'), tKey('wizard.live.failed_title') ); } } finally { button.dataset.busy = 'false'; button.disabled = false; button.classList.remove('is-busy'); button.textContent = originalLabel; } } function updateWizardProtocolVisibility() { var grpcTools = document.getElementById('wizard-grpc-live-tools'); if (grpcTools) grpcTools.hidden = wizardProtocol !== 'grpc'; updateStreamingModeOptions(); updateStreamingConfigVisibility(); if (typeof window.renderEditionCapabilityHints === 'function' && window.CrankWizardState && typeof window.CrankWizardState.currentEditionCapabilities === 'function') { window.renderEditionCapabilityHints(window.CrankWizardState.currentEditionCapabilities()); } } function showWizardLiveStatus(title, text, isError) { var root = document.getElementById('wizard-live-status'); var titleEl = document.getElementById('wizard-live-status-title'); var textEl = document.getElementById('wizard-live-status-text'); if (!root || !titleEl || !textEl) return; titleEl.textContent = title; textEl.textContent = text; root.hidden = false; root.classList.toggle('is-error', !!isError); root.classList.toggle('is-success', !isError); } function currentDraftVersion() { if (wizardCurrentOperation && wizardCurrentOperation.draft_version_ref) { return wizardCurrentOperation.draft_version_ref.version; } if (wizardCurrentOperation && wizardCurrentOperation.current_draft_version) { return wizardCurrentOperation.current_draft_version; } if (wizardCurrentVersion && wizardCurrentVersion.version) { return wizardCurrentVersion.version; } return 1; } function updateOperationPayload(payload) { return { display_name: payload.display_name, category: payload.category, target: payload.target, input_schema: payload.input_schema, output_schema: payload.output_schema, input_mapping: payload.input_mapping, output_mapping: payload.output_mapping, execution_config: payload.execution_config, tool_description: payload.tool_description, }; } async function refreshCurrentOperationState() { if (!wizardWorkspaceId || !wizardEditId) return null; var detail = await window.CrankApi.getOperation(wizardWorkspaceId, wizardEditId); var versionNumber = detail.draft_version_ref ? detail.draft_version_ref.version : detail.current_draft_version; var versionDocument = await window.CrankApi.getOperationVersion( wizardWorkspaceId, wizardEditId, versionNumber ); wizardCurrentOperation = detail; wizardCurrentVersion = versionDocument; updateWizardProtocolVisibility(); return { detail: detail, version: versionDocument, }; } async function uploadPendingGrpcArtifacts(payload) { if (wizardProtocol !== 'grpc' || !wizardEditId) return; var descriptorResponse = null; if (wizardProtoUpload) { descriptorResponse = await window.CrankApi.uploadProtoFile( wizardWorkspaceId, wizardEditId, new TextEncoder().encode(wizardProtoUpload.content), wizardProtoUpload.fileName ); wizardProtoUpload = null; } if (wizardDescriptorSetUpload) { descriptorResponse = await window.CrankApi.uploadDescriptorSet( wizardWorkspaceId, wizardEditId, wizardDescriptorSetUpload.bytes, wizardDescriptorSetUpload.fileName ); wizardDescriptorSetUpload = null; var descriptorName = document.getElementById('wizard-descriptor-set-name'); if (descriptorName) descriptorName.textContent = tKey('wizard.descriptor.uploaded'); } if (!descriptorResponse) return; payload.target.descriptor_ref = descriptorResponse.descriptor_id; payload.target.descriptor_set_b64 = ''; await window.CrankApi.updateOperation( wizardWorkspaceId, wizardEditId, updateOperationPayload(payload) ); } async function uploadPendingSoapArtifacts(payload) { if (wizardProtocol !== 'soap' || !wizardEditId) return; var wsdlResponse = null; if (wizardSoapWsdlUpload) { wsdlResponse = await window.CrankApi.uploadWsdlFile( wizardWorkspaceId, wizardEditId, wizardSoapWsdlUpload.bytes, wizardSoapWsdlUpload.fileName ); wizardSoapWsdlUpload = null; var wsdlName = document.getElementById('wizard-soap-wsdl-name'); if (wsdlName) wsdlName.textContent = tKey('wizard.step3.soap.wsdl_uploaded'); } if (wizardSoapXsdUpload) { await window.CrankApi.uploadXsdFile( wizardWorkspaceId, wizardEditId, wizardSoapXsdUpload.bytes, wizardSoapXsdUpload.fileName ); wizardSoapXsdUpload = null; var xsdName = document.getElementById('wizard-soap-xsd-name'); if (xsdName) xsdName.textContent = tKey('wizard.step3.soap.xsd_uploaded'); } if (!wsdlResponse) return; payload.target.wsdl_ref = wsdlResponse.descriptor_id; await window.CrankApi.updateOperation( wizardWorkspaceId, wizardEditId, updateOperationPayload(payload) ); } async function persistCurrentDraft(stayOnPage) { if (!wizardWorkspaceId) { throw new Error(tKey('wizard.error.no_workspace')); } var payload = collectWizardPayload(); var response; var createdNow = false; if (wizardMode === 'edit' && wizardEditId) { response = await window.CrankApi.updateOperation( wizardWorkspaceId, wizardEditId, updateOperationPayload(payload) ); } else { response = await window.CrankApi.createOperation(wizardWorkspaceId, payload); createdNow = true; wizardEditId = response.operation_id; wizardMode = 'edit'; history.replaceState( {}, '', window.location.pathname + '?mode=edit&operationId=' + encodeURIComponent(wizardEditId) ); setEditModePresentation(); _doGoToStep(currentStep); var toolNameInput = document.getElementById('tool-name'); if (toolNameInput) toolNameInput.disabled = true; } await uploadPendingGrpcArtifacts(payload); await uploadPendingSoapArtifacts(payload); await refreshCurrentOperationState(); if (stayOnPage) { var saveDraftBtn = document.querySelector('.btn-save-draft'); if (saveDraftBtn) { var label = saveDraftBtn.textContent; saveDraftBtn.textContent = tKey('wizard.save.saved'); setTimeout(function() { saveDraftBtn.textContent = label; }, 1400); } } showWizardLiveStatus( createdNow ? tKey('wizard.save.created') : tKey('wizard.save.updated'), tKey('wizard.save.body') ); return response; } function safeStringify(value) { if (value === null || value === undefined) return ''; if (typeof value === 'string') return value; return JSON.stringify(value, null, 2); } function setTextareaValue(id, value) { var element = document.getElementById(id); if (!element) return; element.value = safeStringify(value); } function describeWizardTestResult(result) { if (wizardProtocol === 'websocket') { if (!result.ok && result.errors && result.errors.length) { var websocketError = result.errors[0] || {}; var websocketMessage = websocketError.message || ''; var websocketBody = tKey('wizard.test.websocket_failed_body'); if (/reconnect policy exhausted/i.test(websocketMessage)) { websocketBody = tKey('wizard.test.websocket_failed_reconnect_body'); } else if (/close frame before collection completed|closed before collection completed/i.test(websocketMessage)) { websocketBody = tKey('wizard.test.websocket_failed_closed_body'); } return { title: tKey('wizard.test.websocket_failed'), body: websocketBody, isError: true, }; } if (result.stream_session && result.stream_session.session_id) { return { title: tKey('wizard.test.websocket_session_started'), body: tfKey('wizard.test.websocket_session_started_body', { session_id: result.stream_session.session_id, poll_after_ms: result.stream_session.poll_after_ms, }), isError: false, }; } if (result.async_job && result.async_job.job_id) { return { title: tKey('wizard.test.websocket_async_job_started'), body: tfKey('wizard.test.websocket_async_job_started_body', { job_id: result.async_job.job_id, }), isError: false, }; } if (result.window) { var itemCount = Array.isArray(result.response_preview && result.response_preview.items) ? result.response_preview.items.length : 0; var websocketBodyParts = [ tfKey('wizard.test.websocket_window_completed_body', { items: itemCount }) ]; if (result.window.truncated) { websocketBodyParts.push(tKey('wizard.test.websocket_window_truncated_note')); } if (result.window.has_more) { websocketBodyParts.push(tKey('wizard.test.websocket_window_more_note')); } if (!result.window.window_complete) { websocketBodyParts.push(tKey('wizard.test.websocket_window_incomplete_note')); } return { title: result.ok ? tKey('wizard.test.websocket_window_completed') : tKey('wizard.test.websocket_failed'), body: websocketBodyParts.join(' '), isError: !result.ok, }; } } if (result.stream_session && result.stream_session.session_id) { return { title: tKey('wizard.test.session_started'), body: tfKey('wizard.test.session_started_body', { session_id: result.stream_session.session_id, poll_after_ms: result.stream_session.poll_after_ms }), isError: false, }; } if (result.async_job && result.async_job.job_id) { return { title: tKey('wizard.test.async_job_started'), body: tfKey('wizard.test.async_job_started_body', { job_id: result.async_job.job_id }), isError: false, }; } if (result.window) { var bodyParts = [ tKey('wizard.test.window_completed_body') ]; if (result.window.truncated) { bodyParts.push(tKey('wizard.test.window_truncated_note')); } if (result.window.has_more) { bodyParts.push(tKey('wizard.test.window_more_note')); } if (!result.window.window_complete) { bodyParts.push(tKey('wizard.test.window_incomplete_note')); } return { title: result.ok ? tKey('wizard.test.window_completed') : tKey('wizard.test.failed'), body: bodyParts.join(' '), isError: !result.ok, }; } return { title: result.ok ? tKey('wizard.test.completed') : tKey('wizard.test.failed'), body: result.ok ? tKey('wizard.test.completed_body') : tKey('wizard.test.failed_body'), isError: !result.ok, }; } async function uploadInputSampleFromWizard() { await persistCurrentDraft(true); await window.CrankApi.uploadInputSample( wizardWorkspaceId, wizardEditId, parseStructuredText(textValue('wizard-input-sample')) ); showWizardLiveStatus(tKey('wizard.sample.input_saved'), tKey('wizard.sample.input_saved_body')); } async function uploadOutputSampleFromWizard() { await persistCurrentDraft(true); await window.CrankApi.uploadOutputSample( wizardWorkspaceId, wizardEditId, parseStructuredText(textValue('wizard-output-sample')) ); showWizardLiveStatus(tKey('wizard.sample.output_saved'), tKey('wizard.sample.output_saved_body')); } async function generateDraftFromWizard() { await persistCurrentDraft(true); var generated = await window.CrankApi.generateDraft(wizardWorkspaceId, wizardEditId, {}); setValue('tool-input-schema', JSON.stringify(crankSchemaToJsonSchema(generated.input_schema), null, 2)); setValue('tool-output-schema', JSON.stringify(crankSchemaToJsonSchema(generated.output_schema), null, 2)); setValue('tool-input-mapping', mappingSetToEditorValue(generated.input_mapping, 'input', wizardProtocol)); setValue('tool-output-mapping', mappingSetToEditorValue(generated.output_mapping, 'output', wizardProtocol)); showWizardLiveStatus(tKey('wizard.sample.generated'), tKey('wizard.sample.generated_body')); } async function runWizardTest() { await persistCurrentDraft(true); var result = await window.CrankApi.runOperationTest(wizardWorkspaceId, wizardEditId, { version: currentDraftVersion(), input: parseStructuredText(textValue('wizard-test-input')), }); wizardTestResponsePreview = result.response_preview; setTextareaValue('wizard-test-request-preview', result.request_preview); setTextareaValue('wizard-test-response-preview', result.response_preview); setTextareaValue('wizard-test-errors', result.errors && result.errors.length ? result.errors : []); var status = describeWizardTestResult(result); showWizardLiveStatus( status.title, status.body, status.isError ); } function copyTestResponseToOutputSample() { if (!wizardTestResponsePreview) { showWizardLiveStatus(tKey('wizard.test.no_response'), tKey('wizard.test.no_response_body'), true); return; } setTextareaValue('wizard-output-sample', wizardTestResponsePreview); showWizardLiveStatus(tKey('wizard.test.response_copied'), tKey('wizard.test.response_copied_body')); } window.CrankWizardLive = { saveOperation: saveOperation, loadOperationForEdit: loadOperationForEdit, bindWizardLiveActions: bindWizardLiveActions, updateWizardProtocolVisibility: updateWizardProtocolVisibility, };