(function() { function tKey(key) { return typeof t === 'function' ? t(key) : key; } function currentProtocolCapabilities() { return window.CrankWizardState.currentProtocolCapabilities(); } function text(id) { var element = document.getElementById(id); return element ? String(element.value || '').trim() : ''; } function set(id, value) { var element = document.getElementById(id); if (element) { element.value = value || ''; } } function number(id) { var value = text(id); if (!value) return null; var parsed = Number(value); return Number.isFinite(parsed) ? parsed : null; } function lines(id) { var value = text(id); return value ? value.split('\n').map(function(item) { return item.trim(); }).filter(Boolean) : []; } function checked(id) { var element = document.getElementById(id); return !!(element && element.checked); } function selectedMode() { return text('streaming-mode') || 'unary'; } function transportOptionsForMode(mode) { var capabilities = currentProtocolCapabilities(); var behaviors = (capabilities.supports_transport_behaviors || []).slice(); if (mode === 'unary') return behaviors.filter(function(value) { return value === 'request_response'; }); if (mode === 'window') return behaviors.filter(function(value) { return value === 'request_response' || value === 'server_stream'; }); if (mode === 'session') return behaviors.filter(function(value) { return value === 'server_stream' || value === 'stateful_session'; }); if (mode === 'async_job') return behaviors.filter(function(value) { return value === 'deferred_result'; }); return behaviors; } function modeOptionsForProtocol() { var capabilities = currentProtocolCapabilities(); return (capabilities.supports_execution_modes || ['unary']).filter(function(mode) { return transportOptionsForMode(mode).length > 0 || mode === 'unary'; }); } function updateStreamingTransportOptions(preferredValue) { var element = document.getElementById('streaming-transport-behavior'); if (!element) return; var options = transportOptionsForMode(selectedMode()); element.innerHTML = ''; options.forEach(function(value) { var option = document.createElement('option'); option.value = value; option.textContent = tKey('wizard.streaming.transport.' + value); element.appendChild(option); }); if (preferredValue && options.indexOf(preferredValue) >= 0) { element.value = preferredValue; } else if (options.length) { element.value = options[0]; } } function updateStreamingModeOptions(preferredValue) { var element = document.getElementById('streaming-mode'); if (!element) return; var options = modeOptionsForProtocol(); element.innerHTML = ''; options.forEach(function(value) { var option = document.createElement('option'); option.value = value; option.textContent = tKey('wizard.streaming.mode.' + value); element.appendChild(option); }); if (preferredValue && options.indexOf(preferredValue) >= 0) { element.value = preferredValue; } else { element.value = options.indexOf('unary') >= 0 ? 'unary' : (options[0] || 'unary'); } updateStreamingTransportOptions(); } function ensureStreamingToolFamilyDefaults(mode) { var base = text('tool-name') || 'stream_tool'; if (mode === 'session') { if (!text('streaming-start-tool-name')) set('streaming-start-tool-name', base + '_start'); if (!text('streaming-poll-tool-name')) set('streaming-poll-tool-name', base + '_poll'); if (!text('streaming-stop-tool-name')) set('streaming-stop-tool-name', base + '_stop'); } if (mode === 'async_job') { if (!text('streaming-start-tool-name')) set('streaming-start-tool-name', base + '_start'); if (!text('streaming-status-tool-name')) set('streaming-status-tool-name', base + '_status'); if (!text('streaming-result-tool-name')) set('streaming-result-tool-name', base + '_result'); if (!text('streaming-cancel-tool-name')) set('streaming-cancel-tool-name', base + '_cancel'); } } function updateStreamingConfigVisibility() { var mode = selectedMode(); var card = document.getElementById('wizard-streaming-config-card'); var help = document.getElementById('streaming-mode-help'); var toolFamily = document.getElementById('streaming-tool-family-block'); var asyncRow = document.getElementById('streaming-async-tool-family-row'); if (!card) return; var isUnary = mode === 'unary'; var isSession = mode === 'session'; var isAsyncJob = mode === 'async_job'; [ 'streaming-window-duration-ms', 'streaming-poll-interval-ms', 'streaming-upstream-timeout-ms', 'streaming-idle-timeout-ms', 'streaming-session-lifetime-ms', 'streaming-max-items', 'streaming-max-bytes', 'streaming-max-field-length', 'streaming-sampling-rate', 'streaming-items-path', 'streaming-summary-path', 'streaming-done-path', 'streaming-cursor-path', 'streaming-status-path', 'streaming-redacted-paths', 'streaming-truncate-item-fields', 'streaming-drop-duplicates' ].forEach(function(id) { var node = document.getElementById(id); if (!node) return; var group = node.closest('.form-group') || node.closest('.checkbox-pill'); if (group) { group.hidden = isUnary; } }); if (help) { help.textContent = isUnary ? tKey('wizard.streaming.help.unary') : (isSession ? tKey('wizard.streaming.help.session') : (isAsyncJob ? tKey('wizard.streaming.help.async_job') : tKey('wizard.streaming.help.window'))); } if (toolFamily) toolFamily.hidden = !(isSession || isAsyncJob); if (asyncRow) asyncRow.hidden = !isAsyncJob; ensureStreamingToolFamilyDefaults(mode); } function bindStreamingConfigControls() { updateStreamingModeOptions(); updateStreamingConfigVisibility(); var mode = document.getElementById('streaming-mode'); if (mode) { mode.addEventListener('change', function() { updateStreamingTransportOptions(); updateStreamingConfigVisibility(); }); } } function serializeStreamingConfig() { if (selectedMode() === 'unary') { return null; } var config = { mode: selectedMode(), transport_behavior: text('streaming-transport-behavior') || 'request_response', aggregation_mode: text('streaming-aggregation-mode') || 'summary_plus_samples', window_duration_ms: number('streaming-window-duration-ms'), poll_interval_ms: number('streaming-poll-interval-ms'), upstream_timeout_ms: number('streaming-upstream-timeout-ms'), idle_timeout_ms: number('streaming-idle-timeout-ms'), max_session_lifetime_ms: number('streaming-session-lifetime-ms'), max_items: number('streaming-max-items'), max_bytes: number('streaming-max-bytes'), max_field_length: number('streaming-max-field-length'), sampling_rate: number('streaming-sampling-rate'), items_path: text('streaming-items-path') || null, summary_path: text('streaming-summary-path') || null, done_path: text('streaming-done-path') || null, cursor_path: text('streaming-cursor-path') || null, status_path: text('streaming-status-path') || null, redacted_paths: lines('streaming-redacted-paths'), truncate_item_fields: checked('streaming-truncate-item-fields'), drop_duplicates: checked('streaming-drop-duplicates'), tool_family: {}, }; if (config.mode === 'session') { config.tool_family.start_tool_name = text('streaming-start-tool-name') || null; config.tool_family.poll_tool_name = text('streaming-poll-tool-name') || null; config.tool_family.stop_tool_name = text('streaming-stop-tool-name') || null; } else if (config.mode === 'async_job') { config.tool_family.start_tool_name = text('streaming-start-tool-name') || null; config.tool_family.status_tool_name = text('streaming-status-tool-name') || null; config.tool_family.result_tool_name = text('streaming-result-tool-name') || null; config.tool_family.cancel_tool_name = text('streaming-cancel-tool-name') || null; } return config; } function validateStreamingConfig(capabilities) { var config = serializeStreamingConfig(); if (!config) { return { valid: true, errors: [] }; } var errors = []; var capability = (capabilities || []).find(function(item) { return item.protocol === window.wizardProtocol; }); if (capability && Array.isArray(capability.supports_execution_modes)) { var supported = capability.supports_execution_modes.map(String); if (supported.indexOf(config.mode) === -1) { errors.push('Selected execution mode is not supported by the current protocol.'); } } if (!config.max_items || config.max_items <= 0) { errors.push('Max items must be a positive integer.'); } if (!config.max_bytes || config.max_bytes <= 0) { errors.push('Max bytes must be a positive integer.'); } if (config.mode === 'window' && (!config.window_duration_ms || config.window_duration_ms <= 0)) { errors.push('Window duration must be set for window mode.'); } if (config.mode === 'session' && (!config.poll_interval_ms || config.poll_interval_ms <= 0)) { errors.push('Poll interval must be set for session mode.'); } if (config.mode === 'async_job' && (!config.max_session_lifetime_ms || config.max_session_lifetime_ms <= 0)) { errors.push('Session lifetime must be set for async job mode.'); } return { valid: errors.length === 0, errors: errors, config: config, }; } window.CrankStreamingForm = { selectedStreamingMode: selectedMode, bindStreamingConfigControls: bindStreamingConfigControls, collectStreamingConfig: serializeStreamingConfig, applyStreamingConfig: function(streaming) { updateStreamingModeOptions(streaming && streaming.mode ? streaming.mode : 'unary'); if (!streaming) { updateStreamingConfigVisibility(); return; } if (streaming.window_duration_ms != null) set('streaming-window-duration-ms', String(streaming.window_duration_ms)); if (streaming.poll_interval_ms != null) set('streaming-poll-interval-ms', String(streaming.poll_interval_ms)); if (streaming.upstream_timeout_ms != null) set('streaming-upstream-timeout-ms', String(streaming.upstream_timeout_ms)); if (streaming.idle_timeout_ms != null) set('streaming-idle-timeout-ms', String(streaming.idle_timeout_ms)); if (streaming.max_session_lifetime_ms != null) set('streaming-session-lifetime-ms', String(streaming.max_session_lifetime_ms)); if (streaming.max_items != null) set('streaming-max-items', String(streaming.max_items)); if (streaming.max_bytes != null) set('streaming-max-bytes', String(streaming.max_bytes)); if (streaming.max_field_length != null) set('streaming-max-field-length', String(streaming.max_field_length)); if (streaming.sampling_rate != null) set('streaming-sampling-rate', String(streaming.sampling_rate)); set('streaming-items-path', streaming.items_path || ''); set('streaming-summary-path', streaming.summary_path || ''); set('streaming-done-path', streaming.done_path || ''); set('streaming-cursor-path', streaming.cursor_path || ''); set('streaming-status-path', streaming.status_path || ''); set('streaming-redacted-paths', (streaming.redacted_paths || []).join('\n')); var truncate = document.getElementById('streaming-truncate-item-fields'); if (truncate) truncate.checked = !!streaming.truncate_item_fields; var dedupe = document.getElementById('streaming-drop-duplicates'); if (dedupe) dedupe.checked = !!streaming.drop_duplicates; set('streaming-aggregation-mode', streaming.aggregation_mode || 'summary_plus_samples'); updateStreamingTransportOptions(streaming.transport_behavior); var toolFamily = streaming.tool_family || {}; set('streaming-start-tool-name', toolFamily.start_tool_name || ''); set('streaming-poll-tool-name', toolFamily.poll_tool_name || ''); set('streaming-stop-tool-name', toolFamily.stop_tool_name || ''); set('streaming-status-tool-name', toolFamily.status_tool_name || ''); set('streaming-result-tool-name', toolFamily.result_tool_name || ''); set('streaming-cancel-tool-name', toolFamily.cancel_tool_name || ''); updateStreamingConfigVisibility(); }, serializeStreamingConfig: serializeStreamingConfig, deserializeStreamingConfig: function(streaming) { if (typeof window.applyStreamingConfig === 'function') { window.applyStreamingConfig(streaming); } }, validateStreamingConfig: validateStreamingConfig, }; }());