diff --git a/cli.js b/cli.js index 742b49aa..a9b022a0 100644 --- a/cli.js +++ b/cli.js @@ -249,6 +249,7 @@ const PROVIDER_CACHE_CURRENT_MODEL_FILES = Object.freeze([ ]); const PROVIDER_CACHE_MAX_FILE_BYTES = 256 * 1024; const CODEXMATE_PREFERENCES_FILE = path.join(CODEXMATE_DIR, 'preferences.json'); +const CODEXMATE_TASK_OPENAI_CHAT_PROVIDER_FILE = path.join(CODEXMATE_DIR, 'task-openai-chat-provider.json'); const CODEXMATE_OPENCODE_DIR = path.join(CODEXMATE_DIR, 'opencode'); const CODEXMATE_OPENCODE_PROVIDER_STORE_FILE = path.join(CODEXMATE_OPENCODE_DIR, 'providers.json'); const CODEXMATE_SESSIONS_DIR = path.join(CODEXMATE_DIR, 'sessions'); @@ -12521,6 +12522,9 @@ function createWebServer({ htmlPath, assetsDir, webDir, host, port, openBrowser case 'providers-health': result = await buildAllProvidersHealthReport(params || {}); break; + case 'save-task-openai-chat-provider': + result = saveTaskOpenAiChatProvider(params || {}); + break; case 'doctor': { const doctorParams = isPlainObject(params) ? params : {}; @@ -16198,27 +16202,107 @@ function pickTaskProviderTemperature(provider) { return value; } -function pickTaskOpenAiChatProviderName(config) { +function normalizeTaskOpenAiChatProviderStore(raw) { + const source = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {}; + const providersSource = source.providers && typeof source.providers === 'object' && !Array.isArray(source.providers) + ? source.providers + : {}; + const providers = {}; + Object.keys(providersSource).forEach((name) => { + const key = typeof name === 'string' ? name.trim() : ''; + const provider = providersSource[name]; + if (!key || !provider || typeof provider !== 'object' || Array.isArray(provider)) return; + providers[key] = { + name: typeof provider.name === 'string' && provider.name.trim() ? provider.name.trim() : key, + base_url: typeof provider.base_url === 'string' ? provider.base_url.trim() : '', + wire_api: 'chat_completions', + preferred_auth_method: typeof provider.preferred_auth_method === 'string' ? provider.preferred_auth_method.trim() : '', + models: Array.isArray(provider.models) ? provider.models.map((item) => String(item || '').trim()).filter(Boolean) : [], + temperature: Number.isFinite(Number(provider.temperature)) ? Number(provider.temperature) : undefined + }; + if (providers[key].temperature === undefined) delete providers[key].temperature; + }); + const selectedProvider = typeof source.selectedProvider === 'string' ? source.selectedProvider.trim() : ''; + return { + selectedProvider: selectedProvider && providers[selectedProvider] ? selectedProvider : (Object.keys(providers)[0] || ''), + providers + }; +} + +function readTaskOpenAiChatProviderStore() { + const parsed = readJsonObjectFromFile(CODEXMATE_TASK_OPENAI_CHAT_PROVIDER_FILE, {}); + return normalizeTaskOpenAiChatProviderStore(parsed && parsed.ok && parsed.data ? parsed.data : {}); +} + +function writeTaskOpenAiChatProviderStore(store) { + ensureDir(path.dirname(CODEXMATE_TASK_OPENAI_CHAT_PROVIDER_FILE)); + writeJsonAtomic(CODEXMATE_TASK_OPENAI_CHAT_PROVIDER_FILE, normalizeTaskOpenAiChatProviderStore(store)); +} + +function saveTaskOpenAiChatProvider(params = {}) { + const name = typeof params.name === 'string' ? params.name.trim() : ''; + const baseUrl = normalizeBaseUrl(params.url || params.baseUrl || ''); + const apiKey = typeof params.key === 'string' ? params.key.trim() : ''; + const model = typeof params.model === 'string' ? params.model.trim() : ''; + if (!name || !baseUrl || !apiKey || !model) { + return { error: 'Provider name, URL, API key and model are required' }; + } + if (!isValidProviderName(name)) { + return { error: 'Provider name only supports letters, numbers, dot, underscore and dash' }; + } + if (!isValidHttpUrl(baseUrl)) { + return { error: 'Provider URL only supports http/https' }; + } + const store = readTaskOpenAiChatProviderStore(); + store.providers[name] = { + name, + base_url: baseUrl, + wire_api: 'chat_completions', + preferred_auth_method: apiKey, + models: [model] + }; + store.selectedProvider = name; + writeTaskOpenAiChatProviderStore(store); + return { + success: true, + providerName: name, + model, + storePath: '~/.codexmate/task-openai-chat-provider.json' + }; +} + +function pickTaskOpenAiChatProviderName(config, taskProviderStore = null) { const taskProvider = typeof config.task_openai_chat_provider === 'string' ? config.task_openai_chat_provider.trim() : ''; if (taskProvider) { return taskProvider; } + const store = taskProviderStore && typeof taskProviderStore === 'object' + ? taskProviderStore + : readTaskOpenAiChatProviderStore(); + if (store && typeof store.selectedProvider === 'string' && store.selectedProvider.trim()) { + return store.selectedProvider.trim(); + } return typeof config.model_provider === 'string' ? config.model_provider.trim() : ''; } -function resolveTaskOpenAiChatConfig() { - const configResult = readConfigOrVirtualDefault(); - const config = configResult && configResult.config && typeof configResult.config === 'object' ? configResult.config : {}; - const providerName = pickTaskOpenAiChatProviderName(config); - if (!providerName) { - return { error: '未设置当前 OpenAI Chat 提供商' }; +function taskOpenAiChatProviderHasAuth(config) { + const hasApiKey = typeof config.apiKey === 'string' && config.apiKey.trim(); + const hasExtraHeaders = config.extraHeaders + && typeof config.extraHeaders === 'object' + && !Array.isArray(config.extraHeaders) + && Object.keys(config.extraHeaders).length > 0; + return !!(hasApiKey || hasExtraHeaders); +} + +function resolveTaskOpenAiChatProviderConfig(providerName, provider, config) { + const name = typeof providerName === 'string' ? providerName.trim() : ''; + if (!name) { + return { error: 'OpenAI Chat 提供商名称为空' }; } - const providers = config.model_providers && typeof config.model_providers === 'object' ? config.model_providers : {}; - const provider = providers[providerName]; if (!provider || typeof provider !== 'object') { - return { error: `OpenAI Chat 提供商不存在: ${providerName}` }; + return { error: `OpenAI Chat 提供商不存在: ${name}` }; } const bridgeType = typeof provider.codexmate_bridge === 'string' ? provider.codexmate_bridge.trim() : ''; @@ -16228,7 +16312,7 @@ function resolveTaskOpenAiChatConfig() { let apiKey = typeof provider.preferred_auth_method === 'string' ? provider.preferred_auth_method.trim() : ''; let extraHeaders = {}; if (isOpenaiBridgeProvider) { - const upstream = resolveOpenaiBridgeUpstream(OPENAI_BRIDGE_SETTINGS_FILE, providerName); + const upstream = resolveOpenaiBridgeUpstream(OPENAI_BRIDGE_SETTINGS_FILE, name); if (upstream && !upstream.error) { baseUrl = upstream.baseUrl || baseUrl; apiKey = upstream.apiKey || apiKey; @@ -16238,18 +16322,18 @@ function resolveTaskOpenAiChatConfig() { } } - const model = pickTaskProviderModel(providerName, provider, config); + const model = pickTaskProviderModel(name, provider, config); if (!baseUrl) { - return { error: `OpenAI Chat 提供商 ${providerName} 缺少 base_url` }; + return { error: `OpenAI Chat 提供商 ${name} 缺少 base_url` }; } if (!isValidHttpUrl(baseUrl)) { - return { error: `OpenAI Chat 提供商 ${providerName} 的 base_url 无效` }; + return { error: `OpenAI Chat 提供商 ${name} 的 base_url 无效` }; } if (!model) { - return { error: `OpenAI Chat 提供商 ${providerName} 未设置模型` }; + return { error: `OpenAI Chat 提供商 ${name} 未设置模型` }; } return { - providerName, + providerName: name, baseUrl, endpointUrl: buildOpenAiChatEndpointUrl(baseUrl), apiKey, @@ -16259,6 +16343,58 @@ function resolveTaskOpenAiChatConfig() { }; } +function resolveTaskOpenAiChatConfig() { + const configResult = readConfigOrVirtualDefault(); + const config = configResult && configResult.config && typeof configResult.config === 'object' ? configResult.config : {}; + const taskProviderStore = readTaskOpenAiChatProviderStore(); + const providerName = pickTaskOpenAiChatProviderName(config, taskProviderStore); + if (!providerName) { + return { error: '未设置当前 OpenAI Chat 提供商' }; + } + const configProviders = config.model_providers && typeof config.model_providers === 'object' ? config.model_providers : {}; + const taskProviders = taskProviderStore.providers && typeof taskProviderStore.providers === 'object' ? taskProviderStore.providers : {}; + const provider = taskProviders[providerName] || configProviders[providerName]; + return resolveTaskOpenAiChatProviderConfig(providerName, provider, config); +} + +function listTaskOpenAiChatConfigs() { + const configResult = readConfigOrVirtualDefault(); + const config = configResult && configResult.config && typeof configResult.config === 'object' ? configResult.config : {}; + const taskProviderStore = readTaskOpenAiChatProviderStore(); + const configProviders = config.model_providers && typeof config.model_providers === 'object' ? config.model_providers : {}; + const taskProviders = taskProviderStore.providers && typeof taskProviderStore.providers === 'object' ? taskProviderStore.providers : {}; + const providers = { ...configProviders, ...taskProviders }; + const primaryName = pickTaskOpenAiChatProviderName(config, taskProviderStore); + const orderedNames = []; + if (primaryName) orderedNames.push(primaryName); + Object.keys(providers).forEach((name) => { + if (!orderedNames.includes(name)) orderedNames.push(name); + }); + const configs = []; + const errors = []; + for (const name of orderedNames) { + const provider = providers[name]; + const isPrimary = name === primaryName; + const wireApi = typeof provider?.wire_api === 'string' ? provider.wire_api.trim() : ''; + const bridgeType = typeof provider?.codexmate_bridge === 'string' ? provider.codexmate_bridge.trim() : ''; + const baseUrl = typeof provider?.base_url === 'string' ? provider.base_url.trim() : ''; + const looksChatCompatible = isPrimary + || wireApi === 'chat_completions' + || bridgeType === 'openai' + || baseUrl.includes('/bridge/openai/'); + if (!looksChatCompatible) { + continue; + } + const resolved = resolveTaskOpenAiChatProviderConfig(name, provider, config); + if (resolved && resolved.error) { + if (isPrimary) errors.push(resolved.error); + continue; + } + resolved.primary = isPrimary; + configs.push(resolved); + } + return { configs, errors, primaryName }; +} function buildTaskOpenAiChatStatus() { const requestConfig = resolveTaskOpenAiChatConfig(); if (requestConfig && requestConfig.error) { @@ -16529,37 +16665,29 @@ function materializeOpenAiChatTaskArtifacts(text, options = {}) { } async function runOpenAiChatTaskNode(node, context = {}) { - const requestConfig = resolveTaskOpenAiChatConfig(); - if (requestConfig.error) { - return { - success: false, - error: requestConfig.error, - summary: requestConfig.error, - output: null, - logs: [{ at: toIsoTime(Date.now()), level: 'error', message: requestConfig.error }] - }; - } - const hasApiKey = typeof requestConfig.apiKey === 'string' && requestConfig.apiKey.trim(); - const hasExtraHeaders = requestConfig.extraHeaders - && typeof requestConfig.extraHeaders === 'object' - && !Array.isArray(requestConfig.extraHeaders) - && Object.keys(requestConfig.extraHeaders).length > 0; - if (!hasApiKey && !hasExtraHeaders) { - const error = `OpenAI Chat 提供商 ${requestConfig.providerName || ''} 缺少 API key 或额外 headers`; + const candidatesResult = listTaskOpenAiChatConfigs(); + const allCandidates = Array.isArray(candidatesResult.configs) ? candidatesResult.configs : []; + const requestCandidates = allCandidates.filter(taskOpenAiChatProviderHasAuth); + if (requestCandidates.length === 0) { + const firstConfig = allCandidates[0] || {}; + const error = allCandidates.length > 0 + ? `OpenAI Chat 提供商 ${firstConfig.providerName || candidatesResult.primaryName || ''} 缺少 API key 或额外 headers` + : ((candidatesResult.errors && candidatesResult.errors[0]) || '未找到可用 OpenAI Chat 提供商'); return { success: false, error, summary: error, - output: { - provider: requestConfig.providerName || '', - model: requestConfig.model || '', - endpoint: redactTaskEndpointUrl(requestConfig.endpointUrl || ''), + output: allCandidates.length > 0 ? { + provider: firstConfig.providerName || '', + model: firstConfig.model || '', + endpoint: redactTaskEndpointUrl(firstConfig.endpointUrl || ''), status: 0, text: '', response: null, durationMs: 0, - materializedFiles: [] - }, + materializedFiles: [], + attemptedProviders: allCandidates.map((item) => item.providerName).filter(Boolean) + } : null, logs: [{ at: toIsoTime(Date.now()), level: 'error', message: error }] }; } @@ -16607,25 +16735,57 @@ async function runOpenAiChatTaskNode(node, context = {}) { workspaceContext ].filter(Boolean).join('\n'); const startedAt = Date.now(); - const body = { - model: requestConfig.model, - messages: [ - { role: 'system', content: systemPrompt }, - ...historyMessages.map((message) => ({ - role: message.role === 'assistant' ? 'assistant' : 'user', - content: String(message.content || '') - })), - { role: 'user', content: currentUserMessage } - ], - temperature: Number.isFinite(requestConfig.temperature) ? requestConfig.temperature : 0.2, - stream: false - }; - const result = await postOpenAiChatCompletion(requestConfig, body, { - registerAbort: context.registerAbort - }); - const text = result.ok ? extractModelResponseText(result.payload) : ''; - const success = result.ok && !!text; - const errorMessage = success ? '' : (result.error || 'OpenAI Chat response did not contain text'); + const messages = [ + { role: 'system', content: systemPrompt }, + ...historyMessages.map((message) => ({ + role: message.role === 'assistant' ? 'assistant' : 'user', + content: String(message.content || '') + })), + { role: 'user', content: currentUserMessage } + ]; + const attemptLogs = []; + const attemptedProviders = []; + let requestConfig = requestCandidates[0]; + let result = { ok: false, status: 0, error: 'OpenAI Chat request was not attempted', payload: null, body: '' }; + let text = ''; + let success = false; + let errorMessage = ''; + for (let index = 0; index < requestCandidates.length; index += 1) { + const candidate = requestCandidates[index]; + attemptedProviders.push(candidate.providerName || ''); + const body = { + model: candidate.model, + messages, + temperature: Number.isFinite(candidate.temperature) ? candidate.temperature : 0.2, + stream: false + }; + const attemptResult = await postOpenAiChatCompletion(candidate, body, { + registerAbort: context.registerAbort + }); + const attemptText = attemptResult.ok ? extractModelResponseText(attemptResult.payload) : ''; + const attemptSuccess = attemptResult.ok && !!attemptText; + const attemptError = attemptSuccess ? '' : (attemptResult.error || 'OpenAI Chat response did not contain text'); + attemptLogs.push({ + at: toIsoTime(Date.now()), + level: attemptSuccess ? 'info' : 'warn', + message: `OpenAI Chat request provider=${candidate.providerName} model=${candidate.model} status=${attemptResult.status || 0}${attemptError ? ` error=${truncateTaskText(attemptError, 180)}` : ''}` + }); + requestConfig = candidate; + result = attemptResult; + text = attemptText; + success = attemptSuccess; + errorMessage = attemptError; + if (attemptSuccess) { + break; + } + if (index < requestCandidates.length - 1) { + attemptLogs.push({ + at: toIsoTime(Date.now()), + level: 'warn', + message: `OpenAI Chat provider fallback: ${candidate.providerName} -> ${requestCandidates[index + 1].providerName}` + }); + } + } const summary = truncateTaskText(text || errorMessage, 400); const safeEndpoint = redactTaskEndpointUrl(requestConfig.endpointUrl); const materialized = success && allowWrite @@ -16657,15 +16817,16 @@ async function runOpenAiChatTaskNode(node, context = {}) { text, response: result.payload || null, durationMs: Date.now() - startedAt, - messageCount: body.messages.length, + messageCount: messages.length, threadId, threadStore: threadAppend && threadAppend.file ? threadAppend.file : '', materializedFiles: materialized.files, - workspaceFiles: workspaceOperations.files + workspaceFiles: workspaceOperations.files, + attemptedProviders: attemptedProviders.filter(Boolean) }, logs: [ - { at: toIsoTime(Date.now()), level: 'info', message: `OpenAI Chat request provider=${requestConfig.providerName} model=${requestConfig.model} status=${result.status || 0}` }, - ...(threadId ? [{ at: toIsoTime(Date.now()), level: 'info', message: `workspace chat thread=${threadId} messages=${body.messages.length}` }] : []), + ...attemptLogs, + ...(threadId ? [{ at: toIsoTime(Date.now()), level: 'info', message: `workspace chat thread=${threadId} messages=${messages.length}` }] : []), ...(success ? [{ at: toIsoTime(Date.now()), level: 'info', message: truncateTaskText(text, 1200) }] : [{ at: toIsoTime(Date.now()), level: 'error', message: errorMessage }]), ...materialized.files.map((file) => ({ at: toIsoTime(Date.now()), level: 'info', message: `materialized artifact ${file.relativePath} (${file.bytes} bytes)` })), ...workspaceOperations.files.map((file) => ({ at: toIsoTime(Date.now()), level: 'info', message: `workspace ${file.operation} ${file.relativePath} (${file.bytes} bytes)` })), diff --git a/tests/e2e/test-task-orchestration.js b/tests/e2e/test-task-orchestration.js index bec7ad8e..d2843c77 100644 --- a/tests/e2e/test-task-orchestration.js +++ b/tests/e2e/test-task-orchestration.js @@ -118,6 +118,67 @@ process.on('SIGINT', () => server.close(() => process.exit(0))); throw new Error(`OpenAI Chat mock did not start: ${stderr}`); } +async function startFailingOpenAiChatMock(tmpHome, status = 401, message = 'Invalid token') { + const scriptPath = path.join(tmpHome, `task-openai-chat-failing-${status}.cjs`); + const portFile = path.join(tmpHome, `task-openai-chat-failing-${status}.port`); + fs.writeFileSync(scriptPath, ` +const http = require('http'); +const fs = require('fs'); +const portFile = process.argv[2]; +const status = Number(process.argv[3] || 401); +const message = process.argv[4] || 'Invalid token'; +const server = http.createServer((req, res) => { + req.resume(); + req.on('end', () => { + const body = JSON.stringify({ error: { message } }); + res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': Buffer.byteLength(body, 'utf-8') }); + res.end(body, 'utf-8'); + }); +}); +server.listen(0, '127.0.0.1', () => { + fs.writeFileSync(portFile, String(server.address().port), 'utf-8'); +}); +process.on('SIGTERM', () => server.close(() => process.exit(0))); +process.on('SIGINT', () => server.close(() => process.exit(0))); +`, 'utf-8'); + + const child = spawn(process.execPath, [scriptPath, portFile, String(status), message], { + stdio: ['ignore', 'ignore', 'pipe'] + }); + let stderr = ''; + child.stderr.on('data', chunk => { stderr += chunk.toString(); }); + for (let i = 0; i < 80; i += 1) { + if (fs.existsSync(portFile)) { + const port = Number(fs.readFileSync(portFile, 'utf-8').trim()); + if (Number.isFinite(port) && port > 0) { + return { + port, + close() { + return new Promise((resolve) => { + if (child.exitCode !== null || child.signalCode) return resolve(); + const timer = setTimeout(() => { + try { child.kill('SIGKILL'); } catch (_) {} + resolve(); + }, 2000); + child.once('exit', () => { + clearTimeout(timer); + resolve(); + }); + try { child.kill('SIGTERM'); } catch (_) { resolve(); } + }); + } + }; + } + } + if (child.exitCode !== null) { + throw new Error(`Failing OpenAI Chat mock exited early: ${stderr}`); + } + await sleep(100); + } + try { child.kill('SIGKILL'); } catch (_) {} + throw new Error(`Failing OpenAI Chat mock did not start: ${stderr}`); +} + function writeOpenAiChatConfig(tmpHome, baseUrl) { const configDir = path.join(tmpHome, '.codex'); fs.mkdirSync(configDir, { recursive: true }); @@ -145,6 +206,40 @@ function writeOpenAiChatConfig(tmpHome, baseUrl) { ].join('\n'), 'utf-8'); } +function writeOpenAiChatFallbackConfig(tmpHome, badBaseUrl, fallbackBaseUrl) { + const configDir = path.join(tmpHome, '.codex'); + fs.mkdirSync(configDir, { recursive: true }); + fs.writeFileSync(path.join(configDir, 'codexmate-init.json'), JSON.stringify({ version: 1, mode: 'task-openai-chat-fallback-e2e' }), 'utf-8'); + fs.writeFileSync(path.join(configDir, 'config.toml'), [ + 'model = "gpt-5.3-codex"', + 'model_provider = "local"', + 'task_openai_chat_provider = "bad-chat"', + '', + '[model_providers.local]', + 'name = "Local Codex"', + 'base_url = "http://127.0.0.1:9/v1"', + 'wire_api = "responses"', + 'preferred_auth_method = "sk-codex-tab-secret"', + 'models = ["gpt-5.3-codex"]', + '', + '[model_providers.bad-chat]', + 'name = "Bad Chat"', + `base_url = "${badBaseUrl}/v1"`, + 'wire_api = "chat_completions"', + 'preferred_auth_method = "sk-bad-token"', + 'models = ["bad-model"]', + '', + '[model_providers.new-api-chat]', + 'name = "New API Chat"', + `base_url = "${fallbackBaseUrl}/v1"`, + 'wire_api = "chat_completions"', + 'preferred_auth_method = "sk-task-e2e-secret"', + 'temperature = 0.7', + 'models = ["glm-5.2"]', + '' + ].join('\n'), 'utf-8'); +} + function assertOpenAiRunPayload(payload, label) { assert(payload && payload.run && payload.run.status === 'success', `${label} should succeed`); const nodes = Array.isArray(payload.run.nodes) ? payload.run.nodes : []; @@ -668,7 +763,35 @@ module.exports = async function testTaskOrchestration(ctx) { assert(Array.isArray(apiOpenAiOverview.runs), 'OpenAI Chat task-overview API should return runs after execution'); assert(apiOpenAiOverview.runs.some((item) => item.runId === apiOpenAiRun.runId), 'OpenAI Chat task-overview API should include API run'); - assertOpenAiRequests(openAiMock, 6, 'OpenAI Chat full chain'); + const failingOpenAiMock = await startFailingOpenAiChatMock(tmpHome, 401, 'Invalid token'); + try { + writeOpenAiChatFallbackConfig(tmpHome, `http://127.0.0.1:${failingOpenAiMock.port}`, `http://codex-user:codex-secret@127.0.0.1:${openAiMock.port}`); + const fallbackRunResult = runSync(node, [ + cliPath, + 'task', + 'run', + '--target', + 'OpenAI Chat provider fallback 链路', + '--engine', + 'openai-chat', + '--cwd', + path.join(tmpHome, 'task-fallback-workspace'), + '--thread-id', + 'thread-fallback-run', + '--json' + ], { env }); + assert(fallbackRunResult.status === 0, `OpenAI Chat fallback run failed: ${fallbackRunResult.stderr || fallbackRunResult.stdout}`); + const fallbackPayload = parseJsonOutput(fallbackRunResult.stdout); + assertOpenAiRunPayload(fallbackPayload, 'OpenAI Chat fallback run'); + const fallbackOutputs = fallbackPayload.run.nodes.map(item => item && item.output ? item.output : {}); + assert(fallbackOutputs.some(item => Array.isArray(item.attemptedProviders) && item.attemptedProviders.includes('bad-chat') && item.attemptedProviders.includes('new-api-chat')), 'OpenAI Chat fallback should record attempted providers'); + const fallbackLogs = JSON.stringify(fallbackPayload.run.nodes.flatMap(item => Array.isArray(item && item.logs) ? item.logs : [])); + assert(fallbackLogs.includes('provider fallback: bad-chat -> new-api-chat'), 'OpenAI Chat fallback should be visible in logs'); + } finally { + await failingOpenAiMock.close(); + } + + assertOpenAiRequests(openAiMock, 7, 'OpenAI Chat full chain'); } finally { await openAiMock.close(); } diff --git a/tests/unit/config-tabs-ui.test.mjs b/tests/unit/config-tabs-ui.test.mjs index 96152d4f..a2c51652 100644 --- a/tests/unit/config-tabs-ui.test.mjs +++ b/tests/unit/config-tabs-ui.test.mjs @@ -15,6 +15,7 @@ test('config template keeps expected config tabs in top and side navigation', () const usagePanel = readProjectFile('web-ui/partials/index/panel-usage.html'); const orchestrationPanel = readProjectFile('web-ui/partials/index/panel-orchestration.html'); const bundledScript = readBundledWebUiScript(); + const precompiledRender = readProjectFile('web-ui/res/web-ui-render.precompiled.js'); const baseTheme = readProjectFile('web-ui/styles/base-theme.css'); const controlsForms = readProjectFile('web-ui/styles/controls-forms.css'); const taskOrchestrationStyles = readProjectFile('web-ui/styles/task-orchestration.css'); @@ -91,177 +92,115 @@ test('config template keeps expected config tabs in top and side navigation', () assert.match(html, /:aria-selected="mainTab === 'orchestration'"/); assert.match(html, /id="panel-orchestration"/); assert.match(html, /v-show="mainTab === 'orchestration'"/); - assert.match(orchestrationPanel, /t\('orchestration\.hero\.kicker'\)/); - assert.match(orchestrationPanel, /t\('orchestration\.hero\.title'\)/); - assert.doesNotMatch(orchestrationPanel, /@click="previewTaskPlan\(\)"/); + assert.match(orchestrationPanel, /class="mode-content kilo-webview-mode"/); + assert.match(orchestrationPanel, /class="container kilo-webview-container kilo-chat-shell"/); + assert.match(orchestrationPanel, /class="chat-view kilo-chat-view"/); + assert.match(orchestrationPanel, /data-component="task-header"/); + assert.match(orchestrationPanel, //); + assert.doesNotMatch(orchestrationPanel, /data-slot="task-header-title-trigger"[^>]*(role="button"|tabindex="0")/); + assert.match(orchestrationPanel, /data-slot="task-header-title"/); + assert.match(orchestrationPanel, /data-slot="task-header-stats"/); + assert.match(orchestrationPanel, /class="chat-messages-wrapper"/); + assert.match(orchestrationPanel, /class="message-list" data-component="message-list" role="log" :aria-label="t\('orchestration\.chat\.thread\.aria'\)"/); + assert.match(orchestrationPanel, /class="chat-input"/); + assert.match(orchestrationPanel, /class="prompt-input-container"/); + assert.match(orchestrationPanel, /class="prompt-input-shell"/); + assert.match(orchestrationPanel, /data-component="permission-dock"/); + assert.match(orchestrationPanel, /data-component="error-dock"/); + assert.match(orchestrationPanel, /data-component="provider-setup-dock"/); + assert.match(orchestrationPanel, /taskOrchestrationProviderConfigRequired/); + assert.match(orchestrationPanel, /@click="openTaskProviderSetup"/); + assert.match(orchestrationPanel, /data-component="provider-setup-form"/); + assert.match(orchestrationPanel, /taskOrchestration\.providerSetupOpen \|\| taskOrchestrationProviderConfigRequired/); + assert.match(orchestrationPanel, /@submit.prevent="saveTaskOpenAiChatProvider"/); + assert.match(orchestrationPanel, /taskOrchestrationProviderConfigRequired \|\| taskOrchestration\.running/); + assert.match(orchestrationPanel, /taskKiloWebviewHostSnapshot\.title/); + assert.match(orchestrationPanel, /taskKiloWebviewHostSnapshot\.subtitle/); + assert.match(orchestrationPanel, /taskKiloWebviewHostSnapshot\.timelineBars/); + assert.match(orchestrationPanel, /@click="installTaskKiloWebviewShim\(\)"/); + assert.doesNotMatch(orchestrationPanel, /taskKiloWebviewHostSnapshot\.bridge\.allowedMessageTypes/); + assert.doesNotMatch(orchestrationPanel, /taskKiloWebviewHostSnapshot\.bridge\.blockedMessageTypes/); + assert.doesNotMatch(orchestrationPanel, /taskKiloWebviewHostSnapshot\.protocolRows/); + assert.doesNotMatch(orchestrationPanel, /task-kilo-sidebar|task-kilo-inspector|task-kilo-app-shell|task-kilo-activity-bar/); + assert.doesNotMatch(orchestrationPanel, /task-workbench|task-quick|task-agent|task-config-strip/); + assert.doesNotMatch(orchestrationPanel, new RegExp('@click="' + 'preview' + 'TaskPlan\\\\(\\\\)"')); + assert.doesNotMatch(orchestrationPanel, new RegExp('@click="' + 'preview' + 'TaskPlanFromChat\\\\(\\\\)"')); assert.doesNotMatch(orchestrationPanel, /@click="planAndRunTaskOrchestration\(\)"/); - assert.doesNotMatch(orchestrationPanel, /orchestration\.actions\.generatePlan/); - assert.match(orchestrationPanel, /@click="queueTaskOrchestrationAndStart\(\)"/); - assert.match(orchestrationPanel, /@click="startTaskQueueRunner\(\)"/); - assert.match(orchestrationPanel, /@click="retryTaskRunFromUi\(taskOrchestration.selectedRunId\)"/); - assert.match(orchestrationPanel, /class="selector-section task-hero-card"/); - assert.match(orchestrationPanel, /class="[^"]*task-layout-grid task-layout-grid-primary[^"]*"/); - assert.match(orchestrationPanel, /class="[^"]*task-quick-card[^"]*"/); - assert.doesNotMatch(orchestrationPanel, /class="task-panel-toolbar"/); - assert.doesNotMatch(orchestrationPanel, /class="task-chat-status-strip"/); - assert.doesNotMatch(orchestrationPanel, /class="task-quick-input-card task-chat-panel"[\s\S]*配置 \{\{ taskOrchestrationEngineLabel \}\}/); - assert.doesNotMatch(orchestrationPanel, /class="task-quick-input-card task-chat-panel"[\s\S]*运行中 \{\{ taskOrchestrationQueueStats\.running \}\}/); - assert.doesNotMatch(orchestrationPanel, /class="task-quick-input-card task-chat-panel"[\s\S]*历史 RUNS \{\{ taskOrchestration\.runs\.length \}\}/); - assert.match(orchestrationPanel, /class="task-quick-input-card task-chat-panel"\s*>\s*
/); - assert.doesNotMatch(orchestrationPanel, /class="task-project-list" role="listbox"/); - assert.match(orchestrationPanel, /v-for="workspace in taskOrchestrationWorkspaceItems"/); - assert.match(orchestrationPanel, /:aria-selected="workspace\.active \? 'true' : 'false'"/); - assert.match(orchestrationPanel, /@click="selectTaskWorkspace\(workspace\.path\)"/); - assert.match(orchestrationPanel, /@click="startNewTaskWorkspaceSession\(\)"/); - assert.match(orchestrationPanel, /v-for="session in taskOrchestrationWorkspaceSessions\.slice\(0, 8\)"/); - assert.match(orchestrationPanel, /@click="continueTaskWorkspaceSession\(session\)"/); - assert.match(orchestrationPanel, /
diff --git a/web-ui/res/web-ui-render.precompiled.js b/web-ui/res/web-ui-render.precompiled.js index c084e1d7..cf700d67 100644 --- a/web-ui/res/web-ui-render.precompiled.js +++ b/web-ui/res/web-ui-render.precompiled.js @@ -3995,1063 +3995,270 @@ return function render(_ctx, _cache) { (_ctx.taskOrchestrationTabEnabled) ? _withDirectives((_openBlock(), _createElementBlock("div", { key: 0, - class: "mode-content", + class: "mode-content kilo-webview-mode", id: "panel-orchestration", "data-active": _ctx.mainTab === 'orchestration' ? 'true' : 'false', role: "tabpanel", "aria-labelledby": "tab-orchestration" }, [ - _createElementVNode("section", { class: "selector-section task-hero-card" }, [ - _createElementVNode("div", { class: "task-hero-main" }, [ - _createElementVNode("div", null, [ - _createElementVNode("div", { class: "task-hero-kicker" }, _toDisplayString(_ctx.t('orchestration.hero.kicker')), 1 /* TEXT */), - _createElementVNode("div", { class: "selector-title" }, _toDisplayString(_ctx.t('orchestration.hero.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "skills-panel-note task-hero-copy" }, _toDisplayString(_ctx.t('orchestration.hero.subtitle')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-hero-actions settings-tab-actions task-header-actions" }, [ - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-tool-compact", - onClick: $event => (_ctx.loadTaskOrchestrationOverview({ forceRefresh: true, includeDetail: true })), - disabled: _ctx.taskOrchestration.loading - }, _toDisplayString(_ctx.taskOrchestration.loading ? _ctx.t('common.refreshing') : _ctx.t('common.refresh')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]), - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-tool-compact", - onClick: $event => (_ctx.resetTaskOrchestrationDraft()), - disabled: _ctx.taskOrchestration.running || _ctx.taskOrchestration.queueAdding || _ctx.taskOrchestration.planning - }, _toDisplayString(_ctx.t('orchestration.draft.reset')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]), - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-tool-compact", - onClick: $event => (_ctx.switchMainTab('dashboard')), - disabled: _ctx.loading || !!_ctx.initError - }, _toDisplayString(_ctx.t('dashboard.doctor.title')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]) - ]) - ]) - ]), - _createElementVNode("div", { class: "task-layout-grid task-layout-grid-primary task-quick-layout" }, [ - _createElementVNode("section", { class: "selector-section task-compose-flow-card task-quick-card" }, [ - _createElementVNode("aside", { - class: "task-project-sidebar", - "aria-label": _ctx.t('orchestration.workspace.aria') + _createElementVNode("div", { + class: "container kilo-webview-container kilo-chat-shell", + "data-kilo-webview": "orchestration" + }, [ + _createElementVNode("div", { class: "chat-view kilo-chat-view" }, [ + _createElementVNode("div", { + "data-component": "task-header", + class: "kilo-task-header" }, [ - _createElementVNode("div", { class: "task-project-sidebar-head" }, [ - _createElementVNode("div", null, [ - _createElementVNode("div", { class: "task-thread-card-label" }, _toDisplayString(_ctx.t('orchestration.workspace.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "skills-panel-note" }, _toDisplayString(_ctx.t('orchestration.workspace.subtitle')), 1 /* TEXT */) + _createElementVNode("div", { "data-slot": "task-header-title" }, [ + _createElementVNode("span", { "data-slot": "task-header-title-trigger" }, [ + _createElementVNode("span", { "data-slot": "task-header-title-label" }, _toDisplayString(_ctx.taskKiloWebviewHostSnapshot.title), 1 /* TEXT */) ]), + _createElementVNode("span", { "data-slot": "task-header-subtitle" }, _toDisplayString(_ctx.taskKiloWebviewHostSnapshot.subtitle), 1 /* TEXT */) + ]), + _createElementVNode("div", { "data-slot": "task-header-stats" }, [ + _createElementVNode("span", { + class: _normalizeClass(['pill', _ctx.taskKiloWebviewHostSnapshot.statusTone]) + }, _toDisplayString(_ctx.taskKiloWebviewHostSnapshot.status), 3 /* TEXT, CLASS */), + (_ctx.taskOrchestrationProviderConfigRequired) + ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.t('orchestration.openai.config.requiredTrace')), 1 /* TEXT */)) + : (_openBlock(), _createElementBlock("span", { key: 1 }, _toDisplayString(_ctx.t('orchestration.kilo.trace.counts', { runs: _ctx.taskOrchestrationWorkspaceRuns.length, queue: _ctx.taskOrchestrationWorkspaceQueue.length, nodes: _ctx.taskKiloWebviewHostSnapshot.stats.nodes })), 1 /* TEXT */)), _createElementVNode("button", { type: "button", - class: "btn-mini", + class: "kilo-icon-button", onClick: $event => (_ctx.loadTaskOrchestrationOverview({ forceRefresh: true, includeDetail: true })), - disabled: _ctx.taskOrchestration.loading - }, _toDisplayString(_ctx.taskOrchestration.loading ? _ctx.t('common.refreshing') : _ctx.t('common.refresh')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]) - ]), - _createElementVNode("div", { - class: "task-project-list", - "aria-label": _ctx.t('orchestration.workspace.selector') - }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestrationWorkspaceItems, (workspace) => { - return (_openBlock(), _createElementBlock("button", { - key: workspace.key, - type: "button", - class: _normalizeClass(['task-project-item', { active: workspace.active }]), - "aria-selected": workspace.active ? 'true' : 'false', - title: workspace.path ? _ctx.t('orchestration.workspace.pathHidden') : workspace.meta, - onClick: $event => (_ctx.selectTaskWorkspace(workspace.path)) - }, [ - _createElementVNode("span", { class: "task-project-item-title" }, _toDisplayString(workspace.label), 1 /* TEXT */), - _createElementVNode("span", { class: "task-project-item-meta" }, _toDisplayString(workspace.path ? _ctx.t('orchestration.workspace.pathHidden') : workspace.meta), 1 /* TEXT */), - _createElementVNode("span", { class: "task-project-item-stats" }, _toDisplayString(_ctx.t('orchestration.workspace.counts', { runs: workspace.runCount, queue: workspace.queueCount })), 1 /* TEXT */) - ], 10 /* CLASS, PROPS */, ["aria-selected", "title", "onClick"])) - }), 128 /* KEYED_FRAGMENT */)) - ], 8 /* PROPS */, ["aria-label"]), - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-primary task-project-new-session", - onClick: $event => (_ctx.startNewTaskWorkspaceSession()) - }, _toDisplayString(_ctx.t('orchestration.workspace.newSession')), 9 /* TEXT, PROPS */, ["onClick"]), - _createElementVNode("div", { class: "task-session-inbox" }, [ - _createElementVNode("div", { class: "task-session-inbox-head" }, [ - _createElementVNode("span", { class: "task-readiness-title" }, _toDisplayString(_ctx.t('orchestration.workspace.sessions.title')), 1 /* TEXT */), - _createElementVNode("span", { class: "pill neutral" }, _toDisplayString(_ctx.taskOrchestrationWorkspaceSessions.length), 1 /* TEXT */) - ]), - (!_ctx.taskOrchestrationWorkspaceSessions.length) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-empty-state task-session-empty" - }, [ - _createElementVNode("div", { class: "task-empty-title" }, _toDisplayString(_ctx.t('orchestration.workspace.sessions.empty.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-empty-copy" }, _toDisplayString(_ctx.t('orchestration.workspace.sessions.empty.subtitle')), 1 /* TEXT */) - ])) - : _createCommentVNode("v-if", true), - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestrationWorkspaceSessions.slice(0, 8), (session) => { - return (_openBlock(), _createElementBlock("button", { - key: session.id, - type: "button", - class: "task-session-inbox-item", - onClick: $event => (_ctx.continueTaskWorkspaceSession(session)) - }, [ - _createElementVNode("span", { class: "task-session-inbox-main" }, [ - _createElementVNode("span", { class: "task-session-inbox-title" }, _toDisplayString(session.type === 'queue' ? _ctx.t('orchestration.workspace.sessions.queueTitle') : _ctx.t('orchestration.workspace.sessions.runTitle')), 1 /* TEXT */), - _createElementVNode("span", { class: "task-session-inbox-meta" }, _toDisplayString(_ctx.t('orchestration.workspace.sessions.detailsHidden')), 1 /* TEXT */) - ]), - _createElementVNode("span", { - class: _normalizeClass(['pill', _ctx.taskRunStatusTone(session.status)]) - }, _toDisplayString(session.status), 3 /* TEXT, CLASS */) - ], 8 /* PROPS */, ["onClick"])) - }), 128 /* KEYED_FRAGMENT */)) - ]) - ], 8 /* PROPS */, ["aria-label"]), - _createElementVNode("div", { class: "task-quick-main" }, [ - _createElementVNode("div", { class: "task-quick-copy" }, [ - _createElementVNode("div", { class: "task-hero-kicker" }, _toDisplayString(_ctx.t('orchestration.quick.kicker')), 1 /* TEXT */), - _createElementVNode("div", { class: "selector-title task-quick-title" }, _toDisplayString(_ctx.t('orchestration.quick.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "skills-panel-note task-hero-copy" }, _toDisplayString(_ctx.t('orchestration.quick.subtitle')), 1 /* TEXT */) + disabled: _ctx.taskOrchestration.loading, + "aria-label": _ctx.taskOrchestration.loading ? _ctx.t('common.refreshing') : _ctx.t('common.refresh') + }, " ↻ ", 8 /* PROPS */, ["onClick", "disabled", "aria-label"]), + _createElementVNode("button", { + type: "button", + class: "kilo-icon-button", + onClick: $event => (_ctx.installTaskKiloWebviewShim()), + "aria-label": _ctx.t('orchestration.kilo.bridge.install') + }, " ⌘ ", 8 /* PROPS */, ["onClick", "aria-label"]) ]), - _createElementVNode("section", { - class: "task-agent-cockpit", - "aria-label": _ctx.t('orchestration.agent.aria') - }, [ - _createElementVNode("div", { class: "task-agent-cockpit-head" }, [ - _createElementVNode("div", null, [ - _createElementVNode("div", { class: "task-hero-kicker" }, _toDisplayString(_ctx.t('orchestration.agent.kicker')), 1 /* TEXT */), - _createElementVNode("div", { class: "selector-title task-agent-title" }, _toDisplayString(_ctx.t('orchestration.agent.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "skills-panel-note task-agent-copy" }, _toDisplayString(_ctx.t('orchestration.agent.subtitle')), 1 /* TEXT */) - ]), - _createElementVNode("span", { - class: _normalizeClass(['pill', _ctx.taskOrchestration.running || _ctx.taskOrchestration.planning ? 'warn' : (_ctx.taskOrchestrationSelectedRun && _ctx.taskOrchestrationSelectedRun.run ? _ctx.taskRunStatusTone(_ctx.taskOrchestrationSelectedRun.run.status) : 'neutral')]) - }, _toDisplayString(_ctx.taskOrchestration.running ? _ctx.t('orchestration.agent.state.running') : (_ctx.taskOrchestration.planning ? _ctx.t('orchestration.agent.state.planning') : (_ctx.taskOrchestrationSelectedRun && _ctx.taskOrchestrationSelectedRun.run ? _ctx.taskOrchestrationSelectedRun.run.status : _ctx.t('orchestration.agent.state.ready')))), 3 /* TEXT, CLASS */) - ]), - _createElementVNode("div", { class: "task-agent-surface-grid" }, [ - _createElementVNode("div", { class: "task-agent-surface-card" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.agent.surface.workspace')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationWorkspacePath ? _ctx.t('orchestration.privacy.workspace.selected') : _ctx.t('orchestration.chat.context.workspace.auto')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-agent-surface-card" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.agent.surface.session')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString((_ctx.taskOrchestration.threadId.trim() || (_ctx.taskOrchestrationSelectedRun && _ctx.taskOrchestrationSelectedRun.threadId)) ? _ctx.t('orchestration.privacy.thread.selected') : _ctx.t('orchestration.chat.context.thread.auto')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-agent-surface-card" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.agent.surface.mode')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.selectedEngine === 'workflow' ? _ctx.t('orchestration.engine.workflow') : _ctx.t('orchestration.engine.openaiChat')) + " · " + _toDisplayString(_ctx.taskOrchestration.runMode === 'dry-run' ? _ctx.t('orchestration.runMode.dryRun') : (_ctx.taskOrchestration.runMode === 'read' ? _ctx.t('orchestration.runMode.readOnly') : _ctx.t('orchestration.runMode.write'))), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-agent-surface-card" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.agent.surface.trace')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationWorkspaceRuns.length) + " " + _toDisplayString(_ctx.t('orchestration.agent.surface.runs')) + " · " + _toDisplayString(_ctx.taskOrchestrationWorkspaceQueue.length) + " " + _toDisplayString(_ctx.t('orchestration.agent.surface.queue')), 1 /* TEXT */) - ]) - ]) - ], 8 /* PROPS */, ["aria-label"]), - _createElementVNode("div", { class: "task-quick-input-card task-chat-panel" }, [ + _createElementVNode("div", { "data-slot": "task-header-progress" }, [ _createElementVNode("div", { - class: "task-chat-thread", - role: "log", - "aria-label": _ctx.t('orchestration.chat.thread.aria') + class: "kilo-task-timeline", + "aria-label": _ctx.t('orchestration.kilo.timeline.aria') }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestrationConversationMessages, (message) => { - return (_openBlock(), _createElementBlock("div", { - key: message.id, - class: _normalizeClass(['task-chat-bubble-row', message.role === 'user' ? 'is-user' : 'is-assistant']) - }, [ - _createElementVNode("div", { class: "task-chat-bubble" }, [ - _createElementVNode("div", { class: "task-chat-bubble-label" }, _toDisplayString(message.label), 1 /* TEXT */), - _createElementVNode("div", { class: "task-chat-bubble-text" }, _toDisplayString(message.text), 1 /* TEXT */), - (message.meta) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-chat-bubble-meta" - }, _toDisplayString(message.meta), 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ]) - ], 2 /* CLASS */)) - }), 128 /* KEYED_FRAGMENT */)), - (_ctx.taskOrchestration.plan || _ctx.taskOrchestration.planIssues.length || _ctx.taskOrchestration.planWarnings.length || _ctx.taskOrchestration.lastError) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-chat-bubble-row is-user task-thread-plan-request" - }, [ - _createElementVNode("div", { class: "task-chat-bubble" }, [ - _createElementVNode("div", { class: "task-chat-bubble-label" }, "You · /plan"), - _createElementVNode("div", { class: "task-chat-bubble-text" }, "/plan " + _toDisplayString(_ctx.taskOrchestration.target), 1 /* TEXT */), - (_ctx.taskOrchestrationDraftMetrics.followUpCount) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-chat-bubble-meta" - }, _toDisplayString(_ctx.t('orchestration.chat.input.sequenceHint', { count: _ctx.taskOrchestrationDraftMetrics.followUpCount + 1 })), 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ]) - ])) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestration.plan || _ctx.taskOrchestration.planIssues.length || _ctx.taskOrchestration.planWarnings.length || _ctx.taskOrchestration.lastError) - ? (_openBlock(), _createElementBlock("section", { - key: 1, - class: "selector-section task-plan-card task-thread-message-card task-thread-plan-card" - }, [ - _createElementVNode("div", { class: "task-thread-card-label" }, "AI · " + _toDisplayString(_ctx.t('orchestration.plan.title')), 1 /* TEXT */), - (_ctx.taskOrchestration.lastError) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-issue-item" - }, _toDisplayString(_ctx.taskOrchestration.lastError), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestration.plan) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-thread-run-summary task-thread-plan-summary" - }, [ - _createElementVNode("span", { class: "pill configured" }, "/plan"), - _createElementVNode("span", { class: "task-thread-run-summary-copy" }, _toDisplayString(_ctx.t('orchestration.chat.assistant.planSummary', { nodes: _ctx.taskOrchestration.plan.nodes.length, waves: _ctx.taskOrchestration.plan.waves.length })), 1 /* TEXT */) - ])) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestration.planIssues.length) - ? (_openBlock(), _createElementBlock("div", { - key: 2, - class: "task-issues-list" - }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestration.planIssues, (issue) => { - return (_openBlock(), _createElementBlock("div", { - key: issue.code + issue.message, - class: "task-issue-item" - }, _toDisplayString(issue.message), 1 /* TEXT */)) - }), 128 /* KEYED_FRAGMENT */)) - ])) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestration.planWarnings.length) - ? (_openBlock(), _createElementBlock("div", { - key: 3, - class: "task-warning-list" - }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestration.planWarnings, (warning) => { - return (_openBlock(), _createElementBlock("div", { - key: warning, - class: "task-warning-item" - }, _toDisplayString(warning), 1 /* TEXT */)) - }), 128 /* KEYED_FRAGMENT */)) - ])) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestration.plan) - ? (_openBlock(), _createElementBlock("details", { - key: 4, - class: "task-thread-run-details task-thread-plan-details" - }, [ - _createElementVNode("summary", null, "Plan details"), - _createElementVNode("div", { class: "task-plan-summary-strip" }, [ - _createElementVNode("div", { class: "task-plan-summary-item" }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.plan.summary.nodes')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.plan.nodes.length), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-plan-summary-item" }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.plan.summary.waves')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.plan.waves.length), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-plan-summary-item" }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.plan.summary.engine')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.plan.engine), 1 /* TEXT */) - ]), - (_ctx.taskOrchestration.plan.threadId) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-plan-summary-item" - }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.plan.summary.threadId')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.plan.threadId), 1 /* TEXT */) - ])) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestration.plan.cwd) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-plan-summary-item" - }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.plan.summary.cwd')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.plan.cwd), 1 /* TEXT */) - ])) - : _createCommentVNode("v-if", true) - ]), - _createElementVNode("div", { class: "task-wave-list" }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestration.plan.waves, (wave) => { - return (_openBlock(), _createElementBlock("div", { - key: wave.label, - class: "task-wave-card" - }, [ - _createElementVNode("div", { class: "task-wave-title" }, _toDisplayString(wave.label), 1 /* TEXT */), - _createElementVNode("div", { class: "task-wave-nodes" }, _toDisplayString(wave.nodeIds.join(', ')), 1 /* TEXT */) - ])) - }), 128 /* KEYED_FRAGMENT */)) - ]), - _createElementVNode("div", { class: "task-node-list" }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestration.plan.nodes, (node) => { - return (_openBlock(), _createElementBlock("div", { - key: node.id, - class: "task-node-card" - }, [ - _createElementVNode("div", { class: "task-node-head" }, [ - _createElementVNode("div", null, [ - _createElementVNode("div", { class: "task-node-title" }, _toDisplayString(node.title || node.id), 1 /* TEXT */), - _createElementVNode("div", { class: "task-node-meta" }, [ - _createTextVNode(_toDisplayString(node.id) + " · " + _toDisplayString(node.kind), 1 /* TEXT */), - (node.workflowId) - ? (_openBlock(), _createElementBlock("span", { key: 0 }, " · " + _toDisplayString(node.workflowId), 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ]) - ]), - _createElementVNode("span", { - class: _normalizeClass(['pill', node.write ? 'configured' : 'empty']) - }, _toDisplayString(node.write ? _ctx.t('orchestration.plan.node.write') : _ctx.t('orchestration.plan.node.readOnly')), 3 /* TEXT, CLASS */) - ]), - _createElementVNode("div", { class: "task-node-deps" }, _toDisplayString(_ctx.t('orchestration.labels.dependencies')) + _toDisplayString(_ctx.formatTaskNodeDependencies(node)), 1 /* TEXT */) - ])) - }), 128 /* KEYED_FRAGMENT */)) - ]) - ])) - : _createCommentVNode("v-if", true) - ])) - : _createCommentVNode("v-if", true) - ], 8 /* PROPS */, ["aria-label"]), - _createElementVNode("div", { class: "task-thread-composer" }, [ - _createElementVNode("label", { class: "task-quick-target-field task-chat-composer" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.chat.input.label')), 1 /* TEXT */), - _createElementVNode("span", { - class: "task-composer-prompt-glyph", - "aria-hidden": "true" - }, "›"), - _withDirectives(_createElementVNode("textarea", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.chatDraft) = $event), - class: "task-textarea task-textarea-goal task-quick-target", - rows: "3", - placeholder: _ctx.t('orchestration.chat.input.placeholder'), - onKeydown: _withKeys(_withModifiers($event => (_ctx.submitTaskOrchestrationChatMessage()), ["exact","prevent"]), ["enter"]) - }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onKeydown"]), [ - [_vModelText, _ctx.taskOrchestration.chatDraft] - ]), - _createElementVNode("span", { class: "task-field-hint" }, _toDisplayString(_ctx.t('orchestration.chat.input.hint')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-chat-send-row" }, [ - _createElementVNode("div", { class: "task-chat-action-buttons task-chat-primary-action" }, [ - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-primary task-chat-primary-button", - onClick: $event => (_ctx.planAndRunTaskOrchestrationFromChat()), - disabled: _ctx.taskOrchestration.running || _ctx.taskOrchestration.planning || (!_ctx.taskOrchestration.target.trim() && !_ctx.taskOrchestration.chatDraft.trim()) - }, _toDisplayString(_ctx.taskOrchestration.running ? _ctx.t('orchestration.actions.processing') : (_ctx.taskOrchestration.planning ? _ctx.t('orchestration.actions.planning') : _ctx.t('orchestration.chat.input.work'))), 9 /* TEXT, PROPS */, ["onClick", "disabled"]) - ]), - _createElementVNode("span", { class: "task-field-hint" }, _toDisplayString(_ctx.taskOrchestrationDraftMetrics.hasTarget ? _ctx.t('orchestration.chat.input.sequenceHint', { count: _ctx.taskOrchestrationDraftMetrics.followUpCount + 2 }) : _ctx.t('orchestration.chat.input.workHint')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-chat-execute-caption" }, _toDisplayString(_ctx.t('orchestration.chat.input.workCaption')), 1 /* TEXT */), - _createElementVNode("div", { - class: "task-chat-context-row task-chat-context-row-primary", - role: "group", - "aria-label": _ctx.t('orchestration.chat.context.aria') - }, [ - _createElementVNode("span", { class: "task-chat-context-chip task-chat-context-chip-strong" }, [ - _createElementVNode("small", null, _toDisplayString(_ctx.t('orchestration.plan.summary.cwd')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString((_ctx.taskOrchestrationWorkspacePath || _ctx.taskOrchestration.workspacePath.trim()) ? _ctx.t('orchestration.privacy.workspace.selected') : _ctx.t('orchestration.chat.context.workspace.auto')), 1 /* TEXT */) - ]), - _createElementVNode("span", { class: "task-chat-context-chip task-chat-context-chip-strong" }, [ - _createElementVNode("small", null, _toDisplayString(_ctx.t('orchestration.plan.summary.threadId')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString((_ctx.taskOrchestration.threadId.trim() || (_ctx.taskOrchestrationSelectedRun && _ctx.taskOrchestrationSelectedRun.threadId)) ? _ctx.t('orchestration.privacy.thread.selected') : _ctx.t('orchestration.chat.context.thread.auto')), 1 /* TEXT */) - ]), - _createElementVNode("span", { class: "task-chat-context-chip" }, _toDisplayString(_ctx.taskOrchestrationDraftMetrics.hasTarget ? _ctx.t('orchestration.chat.context.sequence.value', { count: _ctx.taskOrchestrationDraftMetrics.requestCount }) : _ctx.t('orchestration.chat.context.sequence.empty')), 1 /* TEXT */), - _createElementVNode("span", { class: "task-chat-context-chip" }, _toDisplayString(_ctx.taskOrchestration.runMode === 'dry-run' ? _ctx.t('orchestration.runMode.dryRun') : (_ctx.taskOrchestration.runMode === 'read' ? _ctx.t('orchestration.runMode.readOnly') : _ctx.t('orchestration.runMode.write') )), 1 /* TEXT */), - _createElementVNode("button", { - type: "button", - class: "task-chat-context-chip task-chat-context-action", - onClick: $event => (_ctx.taskOrchestration.settingsOpen = true) - }, _toDisplayString(_ctx.t('orchestration.advanced.open')), 9 /* TEXT, PROPS */, ["onClick"]) - ], 8 /* PROPS */, ["aria-label"]), - _createElementVNode("div", { class: "task-action-caption" }, _toDisplayString(_ctx.t('orchestration.quick.caption')), 1 /* TEXT */) - ]) + (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskKiloWebviewHostSnapshot.timelineBars, (bar) => { + return (_openBlock(), _createElementBlock("span", { + key: bar.key, + class: _normalizeClass(['kilo-task-timeline-bar', bar.tone]), + title: bar.label + }, null, 10 /* CLASS, PROPS */, ["title"])) + }), 128 /* KEYED_FRAGMENT */)) + ], 8 /* PROPS */, ["aria-label"]) ]) ]), - _createElementVNode("aside", { class: "task-quick-side-card" }, [ - _createElementVNode("section", { class: "selector-section task-workbench-card task-side-workbench-card" }, [ - _createElementVNode("div", { class: "task-thread-card-label" }, _toDisplayString(_ctx.t('orchestration.workbench.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-thread-run-summary" }, [ - (_ctx.taskOrchestrationSelectedRun && _ctx.taskOrchestrationSelectedRun.run) - ? (_openBlock(), _createElementBlock("span", { - key: 0, - class: _normalizeClass(['pill', _ctx.taskRunStatusTone(_ctx.taskOrchestrationSelectedRun.run.status)]) - }, _toDisplayString(_ctx.taskOrchestrationSelectedRun.run.status), 3 /* TEXT, CLASS */)) - : (_ctx.taskOrchestrationWorkspaceRuns.length) - ? (_openBlock(), _createElementBlock("span", { - key: 1, - class: _normalizeClass(['pill', _ctx.taskRunStatusTone(_ctx.taskOrchestrationWorkspaceRuns[0].status)]) - }, _toDisplayString(_ctx.taskOrchestrationWorkspaceRuns[0].status), 3 /* TEXT, CLASS */)) - : (_ctx.taskOrchestrationWorkspaceQueue.length) - ? (_openBlock(), _createElementBlock("span", { - key: 2, - class: "pill neutral" - }, _toDisplayString(_ctx.t('orchestration.workbench.queueCount', { count: _ctx.taskOrchestrationWorkspaceQueue.length })), 1 /* TEXT */)) - : (_openBlock(), _createElementBlock("span", { - key: 3, - class: "pill empty" - }, _toDisplayString(_ctx.t('orchestration.workbench.ready')), 1 /* TEXT */)), - (_ctx.taskOrchestrationSelectedRun && _ctx.taskOrchestrationSelectedRun.run) - ? (_openBlock(), _createElementBlock("span", { - key: 4, - class: "task-thread-run-summary-copy" - }, _toDisplayString(_ctx.taskOrchestrationSelectedRun.run.summary || _ctx.taskOrchestrationSelectedRun.run.runId || _ctx.taskOrchestration.selectedRunId), 1 /* TEXT */)) - : (_ctx.taskOrchestrationWorkspaceRuns.length) - ? (_openBlock(), _createElementBlock("span", { - key: 5, - class: "task-thread-run-summary-copy" - }, _toDisplayString(_ctx.taskOrchestrationWorkspaceRuns[0].summary || _ctx.taskOrchestrationWorkspaceRuns[0].runId), 1 /* TEXT */)) - : (_ctx.taskOrchestrationWorkspaceQueue.length) - ? (_openBlock(), _createElementBlock("span", { - key: 6, - class: "task-thread-run-summary-copy" - }, _toDisplayString(_ctx.taskOrchestrationWorkspaceQueue[0].title || _ctx.taskOrchestrationWorkspaceQueue[0].target || _ctx.taskOrchestrationWorkspaceQueue[0].taskId), 1 /* TEXT */)) - : (_openBlock(), _createElementBlock("span", { - key: 7, - class: "task-thread-run-summary-copy" - }, _toDisplayString(_ctx.t('orchestration.workbench.subtitle')), 1 /* TEXT */)) - ]), - _createElementVNode("details", { - class: "task-thread-run-details", - open: "" - }, [ - _createElementVNode("summary", null, _toDisplayString(_ctx.t('orchestration.agent.trace.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "settings-tab-actions task-header-actions task-thread-detail-actions" }, [ - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-tool-compact", - onClick: $event => (_ctx.loadTaskOrchestrationOverview({ forceRefresh: true, includeDetail: true })), - disabled: _ctx.taskOrchestration.loading - }, _toDisplayString(_ctx.taskOrchestration.loading ? _ctx.t('common.refreshing') : _ctx.t('common.refresh')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]), - (_ctx.taskOrchestrationWorkspaceQueue.length) - ? (_openBlock(), _createElementBlock("button", { - key: 0, - type: "button", - class: "btn-tool btn-tool-compact", - onClick: $event => (_ctx.startTaskQueueRunner()), - disabled: _ctx.taskOrchestration.queueStarting - }, _toDisplayString(_ctx.taskOrchestration.queueStarting ? _ctx.t('orchestration.queue.starting') : _ctx.t('orchestration.queue.start')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])) - : _createCommentVNode("v-if", true) - ]), - _createElementVNode("div", { class: "task-agent-trace-grid" }, [ - _createElementVNode("div", { class: "task-agent-trace-card" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.agent.trace.plan')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.plan ? _ctx.taskOrchestration.plan.nodes.length : 0), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-agent-trace-card" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.agent.trace.queue')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationWorkspaceQueue.length), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-agent-trace-card" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.agent.trace.runs')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationWorkspaceRuns.length), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-agent-trace-card" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.agent.trace.nodes')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationSelectedRunNodes.length), 1 /* TEXT */) - ]) - ]), - ((_ctx.taskOrchestrationWorkspaceQueue.length ? 1 : 0) + (_ctx.taskOrchestrationWorkspaceRuns.length ? 1 : 0) + ((_ctx.taskOrchestration.selectedRunId || _ctx.taskOrchestration.selectedRunError) ? 1 : 0) > 1) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-workbench-tabs", - role: "group", - "aria-label": _ctx.t('orchestration.workbench.tabs.aria') - }, [ - (_ctx.taskOrchestrationWorkspaceQueue.length) - ? (_openBlock(), _createElementBlock("button", { - key: 0, - type: "button", - class: _normalizeClass(["task-workbench-tab", { active: _ctx.taskOrchestration.workspaceTab === 'queue' }]), - onClick: $event => (_ctx.taskOrchestration.workspaceTab = 'queue') - }, _toDisplayString(_ctx.t('orchestration.workbench.tabs.queue', { count: _ctx.taskOrchestrationWorkspaceQueue.length })), 11 /* TEXT, CLASS, PROPS */, ["onClick"])) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestrationWorkspaceRuns.length) - ? (_openBlock(), _createElementBlock("button", { - key: 1, - type: "button", - class: _normalizeClass(["task-workbench-tab", { active: _ctx.taskOrchestration.workspaceTab === 'runs' }]), - onClick: $event => (_ctx.taskOrchestration.workspaceTab = 'runs') - }, _toDisplayString(_ctx.t('orchestration.workbench.tabs.runs', { count: _ctx.taskOrchestrationWorkspaceRuns.length })), 11 /* TEXT, CLASS, PROPS */, ["onClick"])) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestration.selectedRunId || _ctx.taskOrchestration.selectedRunError) - ? (_openBlock(), _createElementBlock("button", { - key: 2, - type: "button", - class: _normalizeClass(["task-workbench-tab", { active: _ctx.taskOrchestration.workspaceTab === 'detail' }]), - onClick: $event => (_ctx.taskOrchestration.workspaceTab = 'detail') - }, _toDisplayString(_ctx.t('orchestration.workbench.tabs.detail')), 11 /* TEXT, CLASS, PROPS */, ["onClick"])) - : _createCommentVNode("v-if", true) - ], 8 /* PROPS */, ["aria-label"])) - : _createCommentVNode("v-if", true), - ((_ctx.taskOrchestrationWorkspaceQueue.length && _ctx.taskOrchestration.workspaceTab === 'queue') || (!_ctx.taskOrchestrationWorkspaceRuns.length && !_ctx.taskOrchestration.selectedRunId && !_ctx.taskOrchestration.selectedRunError)) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-workbench-panel" - }, [ - (!_ctx.taskOrchestrationWorkspaceQueue.length) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-empty-state" - }, [ - _createElementVNode("div", { class: "task-empty-title" }, _toDisplayString(_ctx.t('orchestration.queue.empty.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-empty-copy" }, _toDisplayString(_ctx.t('orchestration.queue.empty.subtitle')), 1 /* TEXT */) - ])) - : (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-runtime-list" - }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestrationWorkspaceQueue, (item) => { - return (_openBlock(), _createElementBlock("div", { - key: item.taskId, - class: _normalizeClass(['task-runtime-item', { active: item.lastRunId && _ctx.taskOrchestration.selectedRunId === item.lastRunId, clickable: !!item.lastRunId }]), - role: item.lastRunId ? 'button' : null, - tabindex: item.lastRunId ? 0 : -1, - "aria-disabled": item.lastRunId ? null : 'true', - onClick: $event => (item.lastRunId ? (_ctx.taskOrchestration.workspaceTab = 'detail', _ctx.selectTaskRun(item.lastRunId)) : null), - onKeydown: [ - _withKeys(_withModifiers($event => (item.lastRunId ? (_ctx.taskOrchestration.workspaceTab = 'detail', _ctx.selectTaskRun(item.lastRunId)) : null), ["self","prevent"]), ["enter"]), - _withKeys(_withModifiers($event => (item.lastRunId ? (_ctx.taskOrchestration.workspaceTab = 'detail', _ctx.selectTaskRun(item.lastRunId)) : null), ["self","prevent"]), ["space"]) - ] + _createElementVNode("div", { class: "chat-messages-wrapper" }, [ + _createElementVNode("div", { class: "chat-messages" }, [ + _createElementVNode("div", { class: "message-list-container" }, [ + _createElementVNode("div", { + class: "message-list", + "data-component": "message-list", + role: "log", + "aria-label": _ctx.t('orchestration.chat.thread.aria') + }, [ + _createElementVNode("div", { + class: _normalizeClass(['message-list-content', { 'message-list-content-empty': !_ctx.taskOrchestrationConversationMessages.length && !_ctx.taskOrchestration.lastError }]) + }, [ + (!_ctx.taskOrchestrationConversationMessages.length && !_ctx.taskOrchestration.lastError) + ? (_openBlock(), _createElementBlock("div", { + key: 0, + class: "message-list-empty kilo-welcome-empty" + }, [ + _createElementVNode("div", { class: "kilo-logo" }, "K"), + _createElementVNode("h3", null, _toDisplayString(_ctx.t('orchestration.kilo.surface.title')), 1 /* TEXT */), + _createElementVNode("p", null, _toDisplayString(_ctx.t('orchestration.kilo.bridge.copy')), 1 /* TEXT */), + _createElementVNode("div", { class: "kilo-context-strip" }, [ + (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskKiloWebviewHostSnapshot.context, (item) => { + return (_openBlock(), _createElementBlock("span", { + key: item.key }, [ - _createElementVNode("div", { class: "task-runtime-item-main" }, [ - _createElementVNode("div", { class: "task-runtime-item-title" }, _toDisplayString(item.title || item.target || item.taskId), 1 /* TEXT */), - _createElementVNode("div", { class: "task-runtime-item-meta" }, _toDisplayString(item.taskId) + " · " + _toDisplayString(item.updatedAt || item.createdAt), 1 /* TEXT */), - (item.threadId || item.cwd) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-runtime-item-meta" - }, [ - (item.threadId) - ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.t('orchestration.plan.summary.threadId')) + ": " + _toDisplayString(item.threadId), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - (item.threadId && item.cwd) - ? (_openBlock(), _createElementBlock("span", { key: 1 }, " · ")) - : _createCommentVNode("v-if", true), - (item.cwd) - ? (_openBlock(), _createElementBlock("span", { key: 2 }, _toDisplayString(_ctx.t('orchestration.plan.summary.cwd')) + ": " + _toDisplayString(item.cwd), 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ])) - : _createCommentVNode("v-if", true), - (item.lastSummary) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-runtime-item-summary" - }, _toDisplayString(item.lastSummary), 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ]), - _createElementVNode("div", { class: "task-runtime-item-actions" }, [ - _createElementVNode("span", { - class: _normalizeClass(['pill', _ctx.taskRunStatusTone(item.status || item.runStatus)]) - }, _toDisplayString(item.status || item.runStatus), 3 /* TEXT, CLASS */), - (_ctx.isTaskRunActive(item.status || item.runStatus)) - ? (_openBlock(), _createElementBlock("button", { - key: 0, - type: "button", - class: "btn-mini", - onClick: _withModifiers($event => (_ctx.cancelTaskRunFromUi(item.taskId)), ["stop"]) - }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick"])) - : _createCommentVNode("v-if", true) - ]) - ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["role", "tabindex", "aria-disabled", "onClick", "onKeydown"])) + _createElementVNode("small", null, _toDisplayString(item.label), 1 /* TEXT */), + _createElementVNode("strong", null, _toDisplayString(item.value), 1 /* TEXT */) + ])) }), 128 /* KEYED_FRAGMENT */)) - ])) - ])) - : (_ctx.taskOrchestration.workspaceTab === 'runs' || (!_ctx.taskOrchestrationWorkspaceQueue.length && _ctx.taskOrchestrationWorkspaceRuns.length && !_ctx.taskOrchestration.selectedRunId && !_ctx.taskOrchestration.selectedRunError)) - ? (_openBlock(), _createElementBlock("div", { - key: 2, - class: "task-workbench-panel" - }, [ - (!_ctx.taskOrchestrationWorkspaceRuns.length) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-empty-state" - }, [ - _createElementVNode("div", { class: "task-empty-title" }, _toDisplayString(_ctx.t('orchestration.runs.empty.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-empty-copy" }, _toDisplayString(_ctx.t('orchestration.runs.empty.subtitle')), 1 /* TEXT */) - ])) - : (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-runtime-list" - }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestrationWorkspaceRuns, (item) => { - return (_openBlock(), _createElementBlock("button", { - key: item.runId, - type: "button", - class: _normalizeClass(['task-runtime-item', { active: _ctx.taskOrchestration.selectedRunId === item.runId }]), - onClick: $event => {_ctx.taskOrchestration.workspaceTab = 'detail'; _ctx.selectTaskRun(item.runId)} - }, [ - _createElementVNode("div", { class: "task-runtime-item-main" }, [ - _createElementVNode("div", { class: "task-runtime-item-title" }, _toDisplayString(item.title || item.taskId || item.runId), 1 /* TEXT */), - _createElementVNode("div", { class: "task-runtime-item-meta" }, _toDisplayString(item.runId) + " · " + _toDisplayString(item.durationMs || 0) + "ms", 1 /* TEXT */), - (item.threadId || item.cwd) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-runtime-item-meta" - }, [ - (item.threadId) - ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.t('orchestration.plan.summary.threadId')) + ": " + _toDisplayString(item.threadId), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - (item.threadId && item.cwd) - ? (_openBlock(), _createElementBlock("span", { key: 1 }, " · ")) - : _createCommentVNode("v-if", true), - (item.cwd) - ? (_openBlock(), _createElementBlock("span", { key: 2 }, _toDisplayString(_ctx.t('orchestration.plan.summary.cwd')) + ": " + _toDisplayString(item.cwd), 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ])) - : _createCommentVNode("v-if", true), - (item.summary) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-runtime-item-summary" - }, _toDisplayString(item.summary), 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ]), - _createElementVNode("div", { class: "task-runtime-item-actions" }, [ - _createElementVNode("span", { - class: _normalizeClass(['pill', _ctx.taskRunStatusTone(item.status)]) - }, _toDisplayString(item.status), 3 /* TEXT, CLASS */) - ]) - ], 10 /* CLASS, PROPS */, ["onClick"])) - }), 128 /* KEYED_FRAGMENT */)) - ])) - ])) - : (_openBlock(), _createElementBlock("div", { - key: 3, - class: "task-workbench-panel" + ]) + ])) + : _createCommentVNode("v-if", true), + (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestrationConversationMessages, (message) => { + return (_openBlock(), _createElementBlock("div", { + key: message.id, + class: "vscode-session-turn", + "data-row": message.role === 'user' ? 'user' : 'assistant' }, [ - _createElementVNode("div", { class: "task-detail-toolbar settings-tab-actions" }, [ - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-tool-compact", - onClick: $event => (_ctx.taskOrchestration.selectedRunId ? _ctx.loadTaskRunDetail(_ctx.taskOrchestration.selectedRunId) : null), - disabled: !_ctx.taskOrchestration.selectedRunId || _ctx.taskOrchestration.selectedRunLoading - }, _toDisplayString(_ctx.taskOrchestration.selectedRunLoading ? _ctx.t('common.refreshing') : _ctx.t('orchestration.detail.refresh')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]), - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-tool-compact", - onClick: $event => (_ctx.retryTaskRunFromUi(_ctx.taskOrchestration.selectedRunId)), - disabled: !_ctx.taskOrchestration.selectedRunId || _ctx.taskOrchestration.retrying - }, _toDisplayString(_ctx.taskOrchestration.retrying ? _ctx.t('orchestration.detail.retrying') : _ctx.t('orchestration.detail.retry')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]), - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-tool-compact", - onClick: _ctx.continueTaskThreadFromUi, - disabled: !_ctx.taskOrchestrationSelectedRun - }, _toDisplayString(_ctx.t('orchestration.detail.continueThread')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]), - (_ctx.taskOrchestrationSelectedRun && _ctx.taskOrchestrationSelectedRun.run && _ctx.isTaskRunActive(_ctx.taskOrchestrationSelectedRun.run.status)) - ? (_openBlock(), _createElementBlock("button", { + _createElementVNode("div", { + class: _normalizeClass(message.role === 'user' ? 'vscode-session-turn-user' : 'vscode-session-turn-assistant') + }, [ + _createElementVNode("div", { class: "kilo-message-heading" }, _toDisplayString(message.label), 1 /* TEXT */), + _createElementVNode("div", { class: "kilo-message-body" }, _toDisplayString(message.text), 1 /* TEXT */), + (message.meta) + ? (_openBlock(), _createElementBlock("div", { key: 0, - type: "button", - class: "btn-tool btn-tool-compact", - onClick: $event => (_ctx.cancelTaskRunFromUi(_ctx.taskOrchestration.selectedRunId)) - }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick"])) + class: "kilo-message-meta" + }, _toDisplayString(message.meta), 1 /* TEXT */)) : _createCommentVNode("v-if", true) - ]), - (_ctx.taskOrchestration.selectedRunError) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-issue-item" - }, _toDisplayString(_ctx.taskOrchestration.selectedRunError), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - (!_ctx.taskOrchestrationSelectedRun) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-empty-state" - }, [ - _createElementVNode("div", { class: "task-empty-title" }, _toDisplayString(_ctx.t('orchestration.detail.empty.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-empty-copy" }, _toDisplayString(_ctx.t('orchestration.detail.empty.subtitle')), 1 /* TEXT */) - ])) - : (_openBlock(), _createElementBlock(_Fragment, { key: 2 }, [ - _createElementVNode("div", { class: "task-detail-summary-strip" }, [ - _createElementVNode("div", { class: "task-plan-summary-item" }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.detail.summary.status')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationSelectedRun.run.status), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-plan-summary-item" }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.detail.summary.duration')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationSelectedRun.run.durationMs || 0) + "ms", 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-plan-summary-item" }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.detail.summary.nodes')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationSelectedRunNodes.length), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-plan-summary-item" }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.detail.summary.summary')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationSelectedRun.run.summary || _ctx.t('common.none')), 1 /* TEXT */) - ]), - (_ctx.taskOrchestrationSelectedRun.threadId) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-plan-summary-item" - }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.plan.summary.threadId')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationSelectedRun.threadId), 1 /* TEXT */) - ])) - : _createCommentVNode("v-if", true), - (_ctx.taskOrchestrationSelectedRun.cwd) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-plan-summary-item" - }, [ - _createElementVNode("span", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.plan.summary.cwd')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationSelectedRun.cwd), 1 /* TEXT */) - ])) - : _createCommentVNode("v-if", true) - ]), - (_ctx.taskOrchestrationSelectedRun.run.error) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-issue-item" - }, _toDisplayString(_ctx.taskOrchestrationSelectedRun.run.error), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - _createElementVNode("div", { class: "task-node-list" }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestrationSelectedRunNodes, (node) => { - return (_openBlock(), _createElementBlock("div", { - key: node.id, - class: "task-node-card task-node-card-detail" - }, [ - _createElementVNode("div", { class: "task-node-head" }, [ - _createElementVNode("div", null, [ - _createElementVNode("div", { class: "task-node-title" }, _toDisplayString(node.title || node.id), 1 /* TEXT */), - _createElementVNode("div", { class: "task-node-meta" }, _toDisplayString(_ctx.t('orchestration.detail.node.meta', { id: node.id, attempts: (node.attemptCount || 0), autoFix: (node.autoFixRounds || 0) })), 1 /* TEXT */) - ]), - _createElementVNode("span", { - class: _normalizeClass(['pill', _ctx.taskRunStatusTone(node.status)]) - }, _toDisplayString(node.status), 3 /* TEXT, CLASS */) - ]), - (node.summary) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-runtime-item-summary" - }, _toDisplayString(node.summary), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - (node.error && node.error !== node.summary) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-node-deps" - }, _toDisplayString(_ctx.t('orchestration.labels.error')) + _toDisplayString(node.error), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - _createElementVNode("div", { class: "task-node-deps" }, _toDisplayString(_ctx.t('orchestration.labels.dependencies')) + _toDisplayString(_ctx.formatTaskNodeDependencies(node)), 1 /* TEXT */), - (node.output && typeof node.output === 'object') - ? (_openBlock(), _createElementBlock("div", { - key: 2, - class: "task-node-output-card" - }, [ - _createElementVNode("div", { class: "task-node-output-head" }, [ - _createElementVNode("strong", null, _toDisplayString(_ctx.t('orchestration.detail.node.output')), 1 /* TEXT */), - (node.output.provider || node.output.model) - ? (_openBlock(), _createElementBlock("span", { - key: 0, - class: "task-node-output-meta" - }, [ - _createTextVNode(_toDisplayString(node.output.provider || ''), 1 /* TEXT */), - (node.output.provider && node.output.model) - ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [ - _createTextVNode(" · ") - ], 64 /* STABLE_FRAGMENT */)) - : _createCommentVNode("v-if", true), - _createTextVNode(_toDisplayString(node.output.model || ''), 1 /* TEXT */) - ])) - : _createCommentVNode("v-if", true) - ]), - _createElementVNode("div", { class: "task-node-output-facts" }, [ - (node.output.endpoint) - ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.t('orchestration.detail.node.endpoint')) + _toDisplayString(node.output.endpoint), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - (node.output.status) - ? (_openBlock(), _createElementBlock("span", { key: 1 }, "HTTP " + _toDisplayString(node.output.status), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - (node.output.durationMs) - ? (_openBlock(), _createElementBlock("span", { key: 2 }, _toDisplayString(node.output.durationMs) + "ms", 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ]), - _createElementVNode("pre", { class: "task-log-block task-output-block" }, _toDisplayString(_ctx.formatTaskNodeOutputText(node)), 1 /* TEXT */), - (node.output.materializedFiles && node.output.materializedFiles.length) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-materialized-files" - }, [ - _createElementVNode("div", { class: "task-node-deps" }, _toDisplayString(_ctx.t('orchestration.detail.node.materializedFiles')), 1 /* TEXT */), - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(node.output.materializedFiles, (file) => { - return (_openBlock(), _createElementBlock("div", { - key: file.path || file.relativePath, - class: "task-materialized-file" - }, _toDisplayString(file.relativePath || file.path) + " · " + _toDisplayString(file.bytes || 0) + " bytes", 1 /* TEXT */)) - }), 128 /* KEYED_FRAGMENT */)) - ])) - : _createCommentVNode("v-if", true), - (node.output.workspaceFiles && node.output.workspaceFiles.length) - ? (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-materialized-files task-workspace-files" - }, [ - _createElementVNode("div", { class: "task-node-deps" }, _toDisplayString(_ctx.t('orchestration.detail.node.workspaceFiles')), 1 /* TEXT */), - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(node.output.workspaceFiles, (file) => { - return (_openBlock(), _createElementBlock("div", { - key: file.path || file.relativePath, - class: "task-materialized-file" - }, _toDisplayString([String(file.operation || '').trim().toUpperCase(), String(file.relativePath || file.path || '').trim(), Number.isFinite(Number(file.bytes)) ? (Number(file.bytes) + ' bytes') : '', typeof file.existed === 'boolean' ? (file.existed ? 'existed' : 'new') : ''].filter(Boolean).join(' · ')), 1 /* TEXT */)) - }), 128 /* KEYED_FRAGMENT */)) - ])) - : _createCommentVNode("v-if", true) - ])) - : _createCommentVNode("v-if", true), - _createElementVNode("pre", { class: "task-log-block" }, _toDisplayString(_ctx.formatTaskNodeLogs(node.logs)), 1 /* TEXT */) - ])) - }), 128 /* KEYED_FRAGMENT */)) - ]) - ], 64 /* STABLE_FRAGMENT */)) - ])) + ], 2 /* CLASS */) + ], 8 /* PROPS */, ["data-row"])) + }), 128 /* KEYED_FRAGMENT */)), + (_ctx.taskOrchestration.lastError) + ? (_openBlock(), _createElementBlock("div", { + key: 1, + class: "vscode-session-turn", + "data-row": "assistant" + }, [ + _createElementVNode("div", { class: "vscode-session-turn-assistant kilo-status-response" }, [ + _createElementVNode("div", { class: "kilo-message-heading" }, "AI"), + _createElementVNode("div", { class: "kilo-redacted-block" }, _toDisplayString(_ctx.t('orchestration.privacy.detailsHidden')), 1 /* TEXT */) + ]) + ])) + : _createCommentVNode("v-if", true) + ], 2 /* CLASS */) + ], 8 /* PROPS */, ["aria-label"]) ]) - ]), - _createElementVNode("details", { - class: "selector-section task-side-settings-card task-advanced-panel task-quick-advanced", - open: _ctx.taskOrchestration.settingsOpen, - onToggle: $event => (_ctx.taskOrchestration.settingsOpen = $event.target.open) - }, [ - _createElementVNode("summary", { class: "task-advanced-summary" }, _toDisplayString(_ctx.t('orchestration.advanced.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-action-row-right task-action-row-right-prominent task-codex-queue-action" }, [ - _createElementVNode("button", { - type: "button", - class: "btn-tool", - onClick: $event => (_ctx.queueTaskOrchestrationAndStart()), - disabled: _ctx.taskOrchestration.queueAdding || _ctx.taskOrchestration.queueStarting || _ctx.taskOrchestration.planning || !_ctx.taskOrchestration.target.trim() - }, _toDisplayString((_ctx.taskOrchestration.queueAdding || _ctx.taskOrchestration.queueStarting) ? _ctx.t('orchestration.actions.processing') : _ctx.t('orchestration.actions.queueAndStart')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]) - ]), - _createElementVNode("div", { class: "selector-grid task-composer-grid task-composer-grid-secondary" }, [ - _createElementVNode("label", { class: "selector-field task-field-wide" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.title')), 1 /* TEXT */), - _withDirectives(_createElementVNode("input", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.title) = $event), - class: "model-input", - type: "text", - placeholder: _ctx.t('orchestration.fields.title.placeholder') - }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [ - [_vModelText, _ctx.taskOrchestration.title] - ]) - ]), - _createElementVNode("label", { class: "selector-field" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.engine')), 1 /* TEXT */), - _withDirectives(_createElementVNode("select", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.selectedEngine) = $event), - class: "provider-fast-switch-select", - onChange: $event => (_ctx.taskOrchestration.selectedEngine === 'workflow' ? null : _ctx.taskOrchestration.workflowIdsText = '') - }, [ - _createElementVNode("option", { value: "openai-chat" }, _toDisplayString(_ctx.t('orchestration.engine.openaiChat')), 1 /* TEXT */), - _createElementVNode("option", { value: "workflow" }, _toDisplayString(_ctx.t('orchestration.engine.workflow')), 1 /* TEXT */) - ], 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange"]), [ - [_vModelSelect, _ctx.taskOrchestration.selectedEngine] - ]) - ]), - _createElementVNode("label", { class: "selector-field" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.runMode')), 1 /* TEXT */), - _withDirectives(_createElementVNode("select", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.runMode) = $event), - class: "provider-fast-switch-select" - }, [ - _createElementVNode("option", { value: "write" }, _toDisplayString(_ctx.t('orchestration.runMode.write')), 1 /* TEXT */), - _createElementVNode("option", { value: "read" }, _toDisplayString(_ctx.t('orchestration.runMode.readOnly')), 1 /* TEXT */), - _createElementVNode("option", { value: "dry-run" }, _toDisplayString(_ctx.t('orchestration.runMode.dryRun')), 1 /* TEXT */) - ], 8 /* PROPS */, ["onUpdate:modelValue"]), [ - [_vModelSelect, _ctx.taskOrchestration.runMode] - ]) - ]), - _createElementVNode("label", { class: "selector-field task-field-wide" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.notes')), 1 /* TEXT */), - _withDirectives(_createElementVNode("textarea", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.notes) = $event), - class: "task-textarea", - rows: "3", - placeholder: _ctx.t('orchestration.fields.notes.placeholder') - }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [ - [_vModelText, _ctx.taskOrchestration.notes] - ]), - _createElementVNode("span", { class: "task-field-hint" }, _toDisplayString(_ctx.t('orchestration.fields.notes.hint')), 1 /* TEXT */) - ]), - _createElementVNode("label", { class: "selector-field task-field-wide" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.workspacePath')), 1 /* TEXT */), - _withDirectives(_createElementVNode("input", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.workspacePath) = $event), - class: "model-input", - type: "text", - placeholder: _ctx.t('orchestration.fields.workspacePath.placeholder') - }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [ - [_vModelText, _ctx.taskOrchestration.workspacePath] + ]) + ]), + _createElementVNode("div", { class: "chat-input" }, [ + (_ctx.taskOrchestration.lastError) + ? (_openBlock(), _createElementBlock("div", { + key: 0, + class: "kilo-error-dock", + "data-component": "error-dock" + }, [ + _createElementVNode("strong", null, _toDisplayString(_ctx.t('orchestration.toast.error.generic')), 1 /* TEXT */), + _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.privacy.detailsHidden')), 1 /* TEXT */) + ])) + : _createCommentVNode("v-if", true), + (_ctx.taskOrchestrationProviderConfigRequired) + ? (_openBlock(), _createElementBlock("div", { + key: 1, + class: "kilo-provider-setup-dock", + "data-component": "provider-setup-dock" + }, [ + _createElementVNode("div", null, [ + _createElementVNode("strong", null, _toDisplayString(_ctx.t('orchestration.openai.config.requiredTitle')), 1 /* TEXT */), + _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.openai.config.requiredBody')), 1 /* TEXT */) ]), - _createElementVNode("span", { class: "task-field-hint" }, _toDisplayString(_ctx.t('orchestration.fields.workspacePath.hint')), 1 /* TEXT */) - ]), - _createElementVNode("label", { class: "selector-field" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.threadId')), 1 /* TEXT */), - _withDirectives(_createElementVNode("input", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.threadId) = $event), - class: "model-input", - type: "text", - placeholder: _ctx.t('orchestration.fields.threadId.placeholder') - }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [ - [_vModelText, _ctx.taskOrchestration.threadId] + _createElementVNode("button", { + type: "button", + class: "kilo-secondary-button", + onClick: _ctx.openTaskProviderSetup + }, _toDisplayString(_ctx.t('orchestration.openai.config.action')), 9 /* TEXT, PROPS */, ["onClick"]) + ])) + : _createCommentVNode("v-if", true), + (_ctx.taskOrchestration.providerSetupOpen || _ctx.taskOrchestrationProviderConfigRequired) + ? (_openBlock(), _createElementBlock("form", { + key: 2, + class: "kilo-provider-setup-form", + "data-component": "provider-setup-form", + onSubmit: _withModifiers(_ctx.saveTaskOpenAiChatProvider, ["prevent"]) + }, [ + _createElementVNode("label", null, [ + _createElementVNode("span", null, _toDisplayString(_ctx.t('field.providerName')), 1 /* TEXT */), + _withDirectives(_createElementVNode("input", { + "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.providerSetupDraft.name) = $event), + class: "form-input", + autocomplete: "off", + spellcheck: "false", + placeholder: _ctx.t('placeholder.providerNameExample') + }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [ + [_vModelText, _ctx.taskOrchestration.providerSetupDraft.name] + ]) ]), - _createElementVNode("span", { class: "task-field-hint" }, _toDisplayString(_ctx.t('orchestration.fields.threadId.hint')), 1 /* TEXT */) - ]), - _createElementVNode("label", { class: "selector-field task-field-wide" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.followUps')), 1 /* TEXT */), - _withDirectives(_createElementVNode("textarea", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.followUpsText) = $event), - class: "task-textarea", - rows: "3", - placeholder: _ctx.t('orchestration.fields.followUps.placeholder') - }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [ - [_vModelText, _ctx.taskOrchestration.followUpsText] - ]) - ]), - _createElementVNode("label", { class: "selector-field" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.concurrency')), 1 /* TEXT */), - _withDirectives(_createElementVNode("input", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.concurrency) = $event), - class: "model-input", - type: "number", - min: "1", - max: "8" - }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [ - [_vModelText, _ctx.taskOrchestration.concurrency] + _createElementVNode("label", null, [ + _createElementVNode("span", null, _toDisplayString(_ctx.t('field.baseUrl')), 1 /* TEXT */), + _withDirectives(_createElementVNode("input", { + "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.providerSetupDraft.url) = $event), + class: "form-input", + autocomplete: "off", + spellcheck: "false", + placeholder: "https://api.example.com/v1" + }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [ + [_vModelText, _ctx.taskOrchestration.providerSetupDraft.url] + ]) ]), - _createElementVNode("span", { class: "task-field-hint" }, _toDisplayString(_ctx.t('orchestration.fields.concurrency.hint')), 1 /* TEXT */) - ]), - _createElementVNode("label", { class: "selector-field" }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.autoFixRounds')), 1 /* TEXT */), - _withDirectives(_createElementVNode("input", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.autoFixRounds) = $event), - class: "model-input", - type: "number", - min: "0", - max: "5" - }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [ - [_vModelText, _ctx.taskOrchestration.autoFixRounds] + _createElementVNode("label", null, [ + _createElementVNode("span", null, _toDisplayString(_ctx.t('field.model')), 1 /* TEXT */), + _withDirectives(_createElementVNode("input", { + "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.providerSetupDraft.model) = $event), + class: "form-input", + autocomplete: "off", + spellcheck: "false", + placeholder: "gpt-4o-mini" + }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [ + [_vModelText, _ctx.taskOrchestration.providerSetupDraft.model] + ]) ]), - _createElementVNode("span", { class: "task-field-hint" }, _toDisplayString(_ctx.t('orchestration.fields.autoFixRounds.hint')), 1 /* TEXT */) - ]), - (_ctx.taskOrchestration.selectedEngine === 'workflow') - ? (_openBlock(), _createElementBlock("label", { - key: 0, - class: "selector-field task-field-wide" - }, [ - _createElementVNode("span", { class: "selector-label" }, _toDisplayString(_ctx.t('orchestration.fields.workflowIds')), 1 /* TEXT */), - _withDirectives(_createElementVNode("textarea", { - "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.workflowIdsText) = $event), - class: "task-textarea", - rows: "3", - placeholder: _ctx.t('orchestration.fields.workflowIds.placeholder') - }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [ - [_vModelText, _ctx.taskOrchestration.workflowIdsText] - ]), - _createElementVNode("span", { class: "task-field-hint" }, _toDisplayString(_ctx.t('orchestration.fields.workflowIds.hint', { count: _ctx.taskOrchestration.workflows.length })), 1 /* TEXT */), - (_ctx.taskOrchestration.workflows.length) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-workflow-suggestions" - }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestration.workflows, (workflow) => { - return (_openBlock(), _createElementBlock("button", { - key: workflow.id || workflow.name, - type: "button", - class: "task-workflow-chip", - onClick: $event => (_ctx.appendTaskWorkflowId(workflow.id || workflow.name)) - }, [ - _createElementVNode("span", null, _toDisplayString(workflow.name || workflow.id), 1 /* TEXT */), - (workflow.stepCount) - ? (_openBlock(), _createElementBlock("small", { key: 0 }, _toDisplayString(_ctx.t('orchestration.workflow.stepCount', { count: workflow.stepCount })), 1 /* TEXT */)) - : _createCommentVNode("v-if", true) - ], 8 /* PROPS */, ["onClick"])) - }), 128 /* KEYED_FRAGMENT */)) - ])) - : _createCommentVNode("v-if", true) - ])) - : _createCommentVNode("v-if", true) - ]) - ], 40 /* PROPS, NEED_HYDRATION */, ["open", "onToggle"]), - _createElementVNode("div", { class: "task-provider-status-card" }, [ - _createElementVNode("div", { class: "task-readiness-title" }, _toDisplayString(_ctx.t('orchestration.openai.status.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-readiness-copy" }, _toDisplayString(_ctx.t('orchestration.openai.status.subtitle')), 1 /* TEXT */), - (_ctx.taskOrchestration.openAiChatStatus) - ? (_openBlock(), _createElementBlock("div", { - key: 0, - class: "task-provider-status-grid" - }, [ - _createElementVNode("div", { class: "task-provider-status-row" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.openai.status.provider')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.openAiChatStatus.providerName ? _ctx.t('orchestration.openai.status.configured') : _ctx.t('orchestration.openai.status.notSet')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-provider-status-row" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.openai.status.model')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.openAiChatStatus.model ? _ctx.t('orchestration.openai.status.configured') : _ctx.t('orchestration.openai.status.notSet')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-provider-status-row task-provider-status-row-wide" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.openai.status.endpoint')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.openAiChatStatus.endpoint ? _ctx.t('orchestration.openai.status.configured') : _ctx.t('orchestration.openai.status.notSet')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-provider-status-row" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.openai.status.apiKey')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.openAiChatStatus.hasApiKey ? _ctx.t('orchestration.openai.status.configured') : _ctx.t('orchestration.openai.status.missing')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-provider-status-row" }, [ - _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.openai.status.headers')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestration.openAiChatStatus.hasExtraHeaders ? _ctx.t('orchestration.openai.status.configured') : _ctx.t('orchestration.openai.status.notSet')), 1 /* TEXT */) + _createElementVNode("label", null, [ + _createElementVNode("span", null, _toDisplayString(_ctx.t('field.apiKey')), 1 /* TEXT */), + _withDirectives(_createElementVNode("input", { + "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.providerSetupDraft.key) = $event), + class: "form-input", + type: "password", + autocomplete: "new-password", + spellcheck: "false", + placeholder: "sk-..." + }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [ + [_vModelText, _ctx.taskOrchestration.providerSetupDraft.key] ]) - ])) - : (_openBlock(), _createElementBlock("div", { - key: 1, - class: "task-readiness-copy" - }, _toDisplayString(_ctx.t('orchestration.openai.status.notLoaded')), 1 /* TEXT */)), - (_ctx.taskOrchestration.openAiChatStatus && _ctx.taskOrchestration.openAiChatStatus.error) - ? (_openBlock(), _createElementBlock("div", { - key: 2, - class: "task-issue-item task-provider-status-error" - }, _toDisplayString(_ctx.taskOrchestration.openAiChatStatus.error), 1 /* TEXT */)) - : _createCommentVNode("v-if", true), - _createElementVNode("button", { - type: "button", - class: "btn-tool btn-tool-compact task-provider-config-button", - onClick: $event => (_ctx.openTaskOpenAiChatConfig()) - }, _toDisplayString(_ctx.t('orchestration.openai.status.configure')), 9 /* TEXT, PROPS */, ["onClick"]) + ]), + _createElementVNode("div", { class: "kilo-provider-setup-actions" }, [ + _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.openai.config.localStoreHint')), 1 /* TEXT */), + _createElementVNode("button", { + type: "button", + class: "kilo-secondary-button", + onClick: _ctx.closeTaskProviderSetup, + disabled: _ctx.taskOrchestration.providerSetupSaving + }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]), + _createElementVNode("button", { + type: "submit", + class: "kilo-primary-button", + disabled: _ctx.taskOrchestration.providerSetupSaving + }, _toDisplayString(_ctx.taskOrchestration.providerSetupSaving ? _ctx.t('common.saving') : _ctx.t('common.save')), 9 /* TEXT, PROPS */, ["disabled"]) + ]) + ], 40 /* PROPS, NEED_HYDRATION */, ["onSubmit"])) + : _createCommentVNode("v-if", true), + _createElementVNode("div", { + class: "permission-dock kilo-status-dock", + "data-component": "permission-dock" + }, [ + _createElementVNode("span", null, _toDisplayString((_ctx.taskOrchestrationWorkspacePath || _ctx.taskOrchestration.workspacePath.trim()) ? _ctx.t('orchestration.privacy.workspace.selected') : _ctx.t('orchestration.chat.context.workspace.auto')), 1 /* TEXT */), + _createElementVNode("span", null, _toDisplayString((_ctx.taskOrchestration.threadId.trim() || (_ctx.taskOrchestrationSelectedRun && _ctx.taskOrchestrationSelectedRun.threadId)) ? _ctx.t('orchestration.privacy.thread.selected') : _ctx.t('orchestration.chat.context.thread.auto')), 1 /* TEXT */), + _createElementVNode("span", null, _toDisplayString(_ctx.t('orchestration.kilo.engine.configured')), 1 /* TEXT */), + _createElementVNode("span", null, _toDisplayString(_ctx.taskOrchestration.runMode === 'dry-run' ? _ctx.t('orchestration.runMode.dryRun') : (_ctx.taskOrchestration.runMode === 'read' ? _ctx.t('orchestration.runMode.readOnly') : _ctx.t('orchestration.runMode.write'))), 1 /* TEXT */) ]), - _createElementVNode("div", { class: "task-readiness-head" }, [ - _createElementVNode("div", null, [ - _createElementVNode("div", { class: "task-readiness-title" }, _toDisplayString(_ctx.t('orchestration.quick.checklist.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-readiness-copy" }, _toDisplayString(_ctx.t('orchestration.quick.checklist.subtitle')), 1 /* TEXT */) + _createElementVNode("div", { class: "prompt-input-container" }, [ + _createElementVNode("label", { + class: "prompt-input-shell", + "aria-label": _ctx.t('orchestration.chat.input.label') + }, [ + _createElementVNode("span", { class: "prompt-input-prefix" }, "›"), + _withDirectives(_createElementVNode("textarea", { + "onUpdate:modelValue": $event => ((_ctx.taskOrchestration.chatDraft) = $event), + class: "prompt-input-textarea", + rows: "3", + placeholder: _ctx.t('orchestration.chat.input.placeholder'), + onKeydown: _withKeys(_withModifiers($event => (_ctx.planAndRunTaskOrchestrationFromChat()), ["exact","prevent"]), ["enter"]) + }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onKeydown"]), [ + [_vModelText, _ctx.taskOrchestration.chatDraft] + ]) + ], 8 /* PROPS */, ["aria-label"]), + _createElementVNode("div", { class: "prompt-input-actions" }, [ + _createElementVNode("span", null, _toDisplayString(_ctx.taskOrchestrationDraftMetrics.hasTarget ? _ctx.t('orchestration.chat.input.sequenceHint', { count: _ctx.taskOrchestrationDraftMetrics.followUpCount + 2 }) : _ctx.t('orchestration.chat.input.workHint')), 1 /* TEXT */), + _createElementVNode("button", { + type: "button", + class: "kilo-primary-button", + onClick: $event => (_ctx.planAndRunTaskOrchestrationFromChat()), + disabled: _ctx.taskOrchestrationProviderConfigRequired || _ctx.taskOrchestration.running || _ctx.taskOrchestration.planning || (!_ctx.taskOrchestration.target.trim() && !_ctx.taskOrchestration.chatDraft.trim()) + }, _toDisplayString(_ctx.taskOrchestration.running ? _ctx.t('orchestration.actions.processing') : (_ctx.taskOrchestration.planning ? _ctx.t('orchestration.actions.planning') : _ctx.t('orchestration.chat.input.work'))), 9 /* TEXT, PROPS */, ["onClick", "disabled"]) ]) - ]), - _createElementVNode("div", { class: "task-readiness-grid task-quick-checklist" }, [ - (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.taskOrchestrationDraftChecklist, (item) => { - return (_openBlock(), _createElementBlock("div", { - key: item.key, - class: _normalizeClass(['task-readiness-item', { done: item.done }]) - }, [ - _createElementVNode("strong", null, _toDisplayString(item.label), 1 /* TEXT */), - _createElementVNode("span", null, _toDisplayString(item.detail), 1 /* TEXT */) - ], 2 /* CLASS */)) - }), 128 /* KEYED_FRAGMENT */)) - ]), - _createElementVNode("div", { class: "task-quick-status-card" }, [ - _createElementVNode("div", { class: "task-plan-summary-label" }, _toDisplayString(_ctx.t('orchestration.quick.status.title')), 1 /* TEXT */), - _createElementVNode("strong", null, _toDisplayString(_ctx.taskOrchestrationDraftReadiness.title), 1 /* TEXT */), - _createElementVNode("span", null, _toDisplayString(_ctx.taskOrchestrationDraftReadiness.summary), 1 /* TEXT */) ]) ]) ]) - ]), - (!(_ctx.taskOrchestration.plan || _ctx.taskOrchestration.planIssues.length || _ctx.taskOrchestration.planWarnings.length || _ctx.taskOrchestration.lastError || _ctx.taskOrchestrationWorkspaceQueue.length || _ctx.taskOrchestrationWorkspaceRuns.length || _ctx.taskOrchestration.selectedRunId || _ctx.taskOrchestration.selectedRunError)) - ? (_openBlock(), _createElementBlock("section", { - key: 0, - class: "selector-section task-stage-card" - }, [ - _createElementVNode("div", { class: "task-stage-empty" }, [ - _createElementVNode("div", null, [ - _createElementVNode("div", { class: "selector-title" }, _toDisplayString(_ctx.t('orchestration.stage.title')), 1 /* TEXT */), - _createElementVNode("div", { class: "skills-panel-note" }, _toDisplayString(_ctx.t('orchestration.stage.subtitle')), 1 /* TEXT */) - ]), - _createElementVNode("div", { class: "task-stage-strip" }, [ - _createElementVNode("div", { class: "task-stage-pill" }, _toDisplayString(_ctx.t('orchestration.stage.pill.target')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-stage-pill" }, _toDisplayString(_ctx.t('orchestration.stage.pill.preview')), 1 /* TEXT */), - _createElementVNode("div", { class: "task-stage-pill" }, _toDisplayString(_ctx.t('orchestration.stage.pill.run')), 1 /* TEXT */) - ]) - ]) - ])) - : _createCommentVNode("v-if", true) + ]) ], 8 /* PROPS */, ["data-active"])), [ [_vShow, _ctx.mainTab === 'orchestration'] ]) diff --git a/web-ui/styles/task-orchestration.css b/web-ui/styles/task-orchestration.css index 7b6c7f7f..12557b0f 100644 --- a/web-ui/styles/task-orchestration.css +++ b/web-ui/styles/task-orchestration.css @@ -1,2979 +1,524 @@ -.task-layout-grid { - display: grid; - gap: 16px; - margin-bottom: 16px; +#panel-orchestration.kilo-webview-mode { + --kilo-workbench-shell-offset: 230px; + --kilo-workbench-min-height: 520px; + --kilo-reference-blue: #1e7fd3; + --kilo-reference-blue-dark: #176db6; + --kilo-reference-bg: #eef1f4; + --kilo-reference-border: #d8dee6; + --kilo-reference-text: #243447; + --kilo-reference-muted: #6b7785; + --kilo-shell-surface: #ffffff; + --kilo-shell-subtle: #f7f9fc; + --kilo-shell-focus: rgba(30, 127, 211, 0.18); + + display: flex; + min-height: min(var(--kilo-workbench-min-height), calc(100vh - var(--kilo-workbench-shell-offset))); + min-height: min(var(--kilo-workbench-min-height), calc(100dvh - var(--kilo-workbench-shell-offset))); + padding: 0; + background: var(--kilo-reference-bg); +} + +#panel-orchestration .kilo-webview-container { + width: 100%; + max-width: none; + margin: 0; + height: calc(100vh - var(--kilo-workbench-shell-offset)); + height: calc(100dvh - var(--kilo-workbench-shell-offset)); + min-height: 0; + overflow: hidden; + border: 0; + border-radius: 0; + background: var(--kilo-shell-surface); + color: var(--kilo-reference-text); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.72); } -.task-layout-grid-primary { - grid-template-columns: minmax(0, 1fr); +#panel-orchestration .kilo-chat-shell { + display: flex; + flex-direction: column; } -.task-layout-grid-secondary { - grid-template-columns: minmax(0, 1fr); +#panel-orchestration .kilo-chat-view { + display: flex; + height: 100%; + min-height: 0; + flex-direction: column; + background: var(--kilo-shell-surface); + color: var(--kilo-reference-text); + --vscode-descriptionForeground: var(--kilo-reference-muted); + --vscode-button-background: var(--kilo-reference-blue); + --vscode-button-foreground: #fff; + --vscode-button-hoverBackground: var(--kilo-reference-blue-dark); + --vscode-button-secondaryBackground: #f5f7fa; + --vscode-button-secondaryForeground: var(--kilo-reference-text); + --vscode-button-secondaryHoverBackground: #e9eef4; + --kilo-font-size-12: 12px; + --kilo-font-size-13: 13px; + --kilo-font-size-16: 16px; +} + +#panel-orchestration [data-component="task-header"] { + flex-shrink: 0; + border-bottom: 1px solid var(--kilo-reference-border); + background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%); + color: var(--kilo-reference-text); +} + +#panel-orchestration .kilo-task-header { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 6px 14px; + padding: 10px clamp(14px, 3vw, 34px) 8px; } -.task-hero-card, -.task-compose-flow-card, -.task-sidebar-card, -.task-plan-card, -.task-workbench-card, -.task-template-block, -.task-readiness-card, -.task-action-help, -.task-empty-state { +#panel-orchestration [data-slot="task-header-title"] { min-width: 0; - border: 1px solid var(--color-border-soft); - border-radius: 18px; - background: var(--color-surface); - box-shadow: var(--shadow-subtle); } -.task-hero-card { - padding: 18px; - margin-bottom: 16px; - background: linear-gradient(180deg, rgba(199, 116, 98, 0.10) 0%, rgba(199, 116, 98, 0.03) 100%), var(--color-surface); +#panel-orchestration [data-slot="task-header-title-label"] { + display: block; + overflow: hidden; + color: var(--kilo-reference-text); + font-size: 15px; + font-weight: 700; + text-overflow: ellipsis; + white-space: nowrap; +} + +#panel-orchestration [data-slot="task-header-subtitle"] { + display: block; + margin-top: 3px; + overflow: hidden; + color: var(--kilo-reference-muted); + font-size: 12px; + text-overflow: ellipsis; + white-space: nowrap; } -.task-hero-main { +#panel-orchestration [data-slot="task-header-stats"] { display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 16px; + align-items: center; + justify-content: flex-end; + gap: 8px; + color: var(--kilo-reference-muted); + font-size: 12px; } -.task-hero-kicker { - font-size: 11px; - font-weight: 700; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--color-text-secondary); - margin-bottom: 8px; +#panel-orchestration [data-slot="task-header-progress"] { + grid-column: 1 / -1; } -.task-hero-copy { - margin-top: 8px; - max-width: 760px; - line-height: 1.65; +#panel-orchestration .kilo-task-timeline { + display: grid; + grid-auto-flow: column; + grid-auto-columns: minmax(12px, 1fr); + gap: 3px; } -.task-hero-actions { - flex: 0 0 auto; - flex-wrap: nowrap; - align-self: flex-start; +#panel-orchestration .kilo-task-timeline-bar { + height: 3px; + border-radius: 999px; + background: #dce3ec; } -.task-hero-actions > .btn-tool + .btn-tool, -.task-hero-actions > .btn-tool-compact + .btn-tool, -.task-hero-actions > .btn-tool + .btn-tool-compact, -.task-hero-actions > .btn-tool-compact + .btn-tool-compact { - margin-top: 0; +#panel-orchestration .kilo-task-timeline-bar.success { background: #22c55e; } +#panel-orchestration .kilo-task-timeline-bar.warn { background: #f59e0b; } +#panel-orchestration .kilo-task-timeline-bar.error { background: #ef4444; } + +#panel-orchestration .kilo-icon-button, +#panel-orchestration .kilo-primary-button, +#panel-orchestration .kilo-secondary-button { + border: 1px solid transparent; + border-radius: 6px; + cursor: pointer; + font: inherit; } -.task-section-header .task-header-actions > .btn-tool + .btn-tool, -.task-section-header .task-header-actions > .btn-tool-compact + .btn-tool, -.task-section-header .task-header-actions > .btn-tool + .btn-tool-compact, -.task-section-header .task-header-actions > .btn-tool-compact + .btn-tool-compact { - margin-top: 0; +#panel-orchestration .kilo-icon-button { + display: grid; + width: 26px; + height: 26px; + place-items: center; + border-color: var(--kilo-reference-border); + background: #fff; + color: var(--kilo-reference-text); } -.task-action-row > .btn-tool + .btn-tool, -.task-action-row > .btn-tool-compact + .btn-tool, -.task-action-row > .btn-tool + .btn-tool-compact, -.task-action-row > .btn-tool-compact + .btn-tool-compact, -.task-action-row-right > .btn-tool + .btn-tool, -.task-action-row-right > .btn-tool-compact + .btn-tool, -.task-action-row-right > .btn-tool + .btn-tool-compact, -.task-action-row-right > .btn-tool-compact + .btn-tool-compact { - margin-top: 0; +#panel-orchestration .kilo-icon-button:hover { + background: #eef6ff; + border-color: rgba(30, 127, 211, 0.38); } -.task-detail-toolbar > .btn-tool + .btn-tool, -.task-detail-toolbar > .btn-tool-compact + .btn-tool, -.task-detail-toolbar > .btn-tool + .btn-tool-compact, -.task-detail-toolbar > .btn-tool-compact + .btn-tool-compact { - margin-top: 0; +#panel-orchestration .kilo-primary-button { + padding: 7px 12px; + background: var(--kilo-reference-blue); + color: #fff; + font-weight: 700; } -.task-hero-meta-strip { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-top: 14px; +#panel-orchestration .kilo-primary-button:hover { + background: var(--kilo-reference-blue-dark); } -.task-hero-meta { - display: inline-flex; - align-items: center; - gap: 6px; - min-height: 34px; - padding: 0 12px; - border-radius: 999px; - background: rgba(255, 255, 255, 0.56); - border: 1px solid rgba(199, 116, 98, 0.14); - color: var(--color-text-secondary); - font-size: 12px; - font-weight: 600; +#panel-orchestration .kilo-secondary-button { + padding: 7px 12px; + border-color: var(--kilo-reference-border); + background: #f6f8fb; + color: var(--kilo-reference-text); } -.task-hero-meta strong { - color: var(--color-text-primary); +#panel-orchestration .kilo-primary-button:disabled, +#panel-orchestration .kilo-secondary-button:disabled, +#panel-orchestration .kilo-icon-button:disabled { + cursor: not-allowed; + opacity: 0.48; } -.task-compose-flow-card, -.task-sidebar-card, -.task-plan-card, -.task-workbench-card { - padding: 18px; +#panel-orchestration .chat-messages-wrapper { + position: relative; + flex: 1; + min-height: 0; + overflow: hidden; + background: var(--kilo-shell-surface); } -.task-flow-section + .task-flow-section, -.task-sidebar-group + .task-sidebar-group { - margin-top: 18px; - padding-top: 18px; - border-top: 1px solid var(--color-border-soft); +#panel-orchestration .chat-messages, +#panel-orchestration .message-list-container { + height: 100%; + min-height: 0; + overflow: hidden; } -.task-flow-section-compact { - margin-top: 0; +#panel-orchestration .message-list { + height: 100%; + overflow-x: hidden; + overflow-y: auto; + padding: 16px clamp(18px, 4vw, 56px); + background: linear-gradient(180deg, #fff 0%, #fbfcfe 100%); + scrollbar-color: rgba(30, 127, 211, 0.35) transparent; + scrollbar-gutter: stable; + scrollbar-width: thin; } -.task-flow-head { +#panel-orchestration .message-list-content { display: flex; - align-items: flex-start; + min-height: 100%; + flex-direction: column; gap: 12px; - margin-bottom: 14px; + width: min(100%, 98ch); + margin: 0 auto; } -.task-flow-step { - width: 28px; - height: 28px; - border-radius: 999px; - background: var(--color-brand-light); - color: var(--color-brand-dark); - font-size: 13px; - font-weight: 700; - display: inline-flex; +#panel-orchestration .message-list-content-empty { align-items: center; justify-content: center; - flex: 0 0 auto; } -.task-flow-title, -.task-sidebar-title, -.task-readiness-title, -.task-empty-title, -.task-template-label { - font-size: 14px; - font-weight: 700; - color: var(--color-text-primary); +#panel-orchestration .message-list-empty { + display: flex; + max-width: 720px; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 14px; + color: var(--kilo-reference-muted); + text-align: center; } -.task-flow-copy, -.task-readiness-copy, -.task-field-hint, -.task-empty-copy, -.task-action-help-item { - font-size: 12px; - line-height: 1.6; - color: var(--color-text-secondary); +#panel-orchestration .kilo-logo { + display: grid; + width: 52px; + height: 52px; + place-items: center; + border: 1px solid rgba(30, 127, 211, 0.2); + border-radius: 14px; + background: #eef6ff; + color: var(--kilo-reference-blue); + font-size: 24px; + font-weight: 900; } -.task-template-block { - padding: 12px 14px; - background: var(--color-surface-alt); +#panel-orchestration .kilo-welcome-empty h3 { + margin: 0; + color: var(--kilo-reference-text); + font-size: 22px; } -.task-template-panel { - margin-bottom: 14px; - padding: 12px 14px; - border: 1px solid var(--color-border-soft); - border-radius: 16px; - background: var(--color-surface-alt); +#panel-orchestration .kilo-welcome-empty p { + max-width: 620px; + margin: 0; + line-height: 1.5; } -.task-template-chip-group, -.task-workflow-suggestions { +#panel-orchestration .prompt-input-actions, +#panel-orchestration .kilo-status-dock { display: flex; + align-items: center; flex-wrap: wrap; gap: 8px; - margin-top: 10px; -} - -.task-template-chip, -.task-workflow-chip, -.task-workbench-tab { - border: 1px solid var(--color-border); - background: var(--color-surface); - color: var(--color-text-primary); - border-radius: 999px; - padding: 7px 12px; - font-size: 12px; - font-weight: 600; - cursor: pointer; - transition: - background var(--transition-fast) var(--ease-smooth), - border-color var(--transition-fast) var(--ease-smooth), - color var(--transition-fast) var(--ease-smooth), - box-shadow var(--transition-fast) var(--ease-smooth); -} - -.task-template-chip:hover, -.task-workflow-chip:hover, -.task-workbench-tab:hover { - background: var(--color-brand-light); - border-color: var(--color-brand); - color: var(--color-brand-dark); } -.task-workflow-chip { - display: inline-flex; - align-items: center; +#panel-orchestration .kilo-context-strip { + display: grid; + width: min(100%, 760px); + grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; + margin-top: 4px; } -.task-workflow-chip small { - color: var(--color-text-secondary); - font-size: 11px; -} - -.task-composer-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 12px; +#panel-orchestration .kilo-context-strip span { + min-width: 0; + padding: 9px; + border: 1px solid var(--kilo-reference-border); + border-radius: 5px; + background: #f8fafc; + text-align: left; } -.task-composer-grid-primary { - grid-template-columns: minmax(0, 1fr); +#panel-orchestration .kilo-context-strip small, +#panel-orchestration .kilo-message-heading, +#panel-orchestration .kilo-message-meta { + display: block; + color: var(--kilo-reference-muted); + font-size: 11px; } -.task-composer-grid-compact { - grid-template-columns: minmax(180px, 240px) minmax(0, 1fr); - align-items: stretch; +#panel-orchestration .kilo-context-strip strong { + display: block; + overflow: hidden; + margin-top: 4px; + color: var(--kilo-reference-text); + font-size: 12px; + text-overflow: ellipsis; + white-space: nowrap; } -.task-composer-grid-inline { - grid-template-columns: repeat(2, minmax(0, 1fr)); +#panel-orchestration .vscode-session-turn { + display: flex; + flex-direction: column; + gap: 12px; + width: 100%; + min-width: 0; + padding: 0 4px 12px; } -.task-field-wide { - grid-column: 1 / -1; +#panel-orchestration .vscode-session-turn-user, +#panel-orchestration .vscode-session-turn-assistant { + max-width: min(100%, 92ch); + border-radius: 8px; + color: var(--kilo-reference-text); } -.task-goal-field { - padding: 16px; - border-radius: 16px; - background: var(--color-surface-alt); - border: 1px solid var(--color-border-soft); +#panel-orchestration .vscode-session-turn-user { + align-self: flex-end; + width: min(100%, 76ch); + padding: 10px 12px; + border: 1px solid rgba(30, 127, 211, 0.18); + background: #eef6ff; } -.task-textarea, -.task-log-block { - width: 100%; - min-height: 92px; - resize: vertical; +#panel-orchestration .vscode-session-turn-assistant { + align-self: flex-start; + width: min(100%, 92ch); padding: 10px 12px; - border-radius: 12px; - border: 1px solid var(--color-border); - background: var(--color-surface); - color: var(--color-text-primary); - font: inherit; - box-sizing: border-box; + border: 1px solid var(--kilo-reference-border); + background: #fff; } -.task-textarea-goal { - min-height: 132px; - font-size: 14px; - line-height: 1.65; +#panel-orchestration .kilo-message-heading { + margin-bottom: 4px; + font-weight: 700; } -.task-toggle-card { - padding: 14px; - border-radius: 16px; - border: 1px solid var(--color-border-soft); - background: var(--color-surface-alt); +#panel-orchestration .kilo-message-body { + color: var(--kilo-reference-text); + font-size: 13px; + line-height: 1.55; + white-space: pre-wrap; } -.task-toggle-stack { - display: flex; - flex-direction: column; - gap: 10px; - margin-top: 8px; +#panel-orchestration .kilo-redacted-block, +#panel-orchestration .kilo-error-dock { + border: 1px solid rgba(245, 158, 11, 0.28); + border-radius: 8px; + background: #fff8e6; + color: #9a5b00; + padding: 8px; + font-size: 12px; } -.task-toggle-inline { - display: flex; - flex-wrap: wrap; - gap: 12px; +#panel-orchestration .kilo-redacted-block { margin-top: 8px; } -.task-toggle-card-inline { - min-height: 100%; -} - -.task-toggle { - display: inline-flex; +#panel-orchestration .kilo-error-dock, +#panel-orchestration .kilo-provider-setup-dock { + display: flex; align-items: center; + justify-content: space-between; gap: 8px; - color: var(--color-text-secondary); - font-size: 13px; -} - -.task-config-strip { - display: flex; - flex-wrap: wrap; - gap: 10px; -} - -.task-config-strip-vertical { - flex-direction: column; + margin: 0 auto 8px; + width: min(100%, 98ch); } -.task-config-pill { - display: inline-flex; - align-items: center; - min-height: 34px; - padding: 0 12px; - border-radius: 999px; - background: var(--color-surface-alt); - border: 1px solid var(--color-border); - color: var(--color-text-secondary); +#panel-orchestration .kilo-provider-setup-dock { + border: 1px solid rgba(30, 127, 211, 0.24); + border-radius: 8px; + background: #eef6ff; + color: var(--kilo-reference-text); + padding: 8px 10px; font-size: 12px; - font-weight: 600; -} - -.task-readiness-card, -.task-action-help, -.task-empty-state, -.task-stage-card { - padding: 14px; - background: var(--color-surface-alt); -} - -.task-draft-overview, -.task-draft-inline, -.task-advanced-panel { - margin-top: 14px; - padding: 14px; - border: 1px solid var(--color-border-soft); - border-radius: 16px; - background: var(--color-surface-alt); } -.task-draft-inline { +#panel-orchestration .kilo-provider-setup-dock div { display: flex; + min-width: 0; flex-direction: column; - gap: 12px; -} - -.task-draft-inline-head { - display: flex; - align-items: center; - gap: 10px; - flex-wrap: wrap; + gap: 2px; } -.task-draft-inline-copy { - min-width: 0; +#panel-orchestration .kilo-provider-setup-dock span { + color: var(--kilo-reference-muted); } -.task-draft-overview-head { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 12px; -} -.task-checklist-inline { +#panel-orchestration .kilo-provider-setup-form { display: grid; + width: min(100%, 98ch); + margin: 0 auto 8px; grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 10px; - margin-top: 12px; + gap: 8px; + border: 1px solid rgba(30, 127, 211, 0.24); + border-radius: 8px; + background: #fff; + padding: 10px; } -.task-check-chip { +#panel-orchestration .kilo-provider-setup-form label { display: flex; + min-width: 0; flex-direction: column; gap: 4px; - padding: 12px; - border-radius: 14px; - border: 1px solid var(--color-border); - background: var(--color-surface); -} - -.task-check-chip strong { - font-size: 12px; - color: var(--color-text-primary); -} - -.task-check-chip span { - font-size: 12px; - line-height: 1.5; - color: var(--color-text-secondary); -} - -.task-check-chip.done { - border-color: rgba(81, 154, 91, 0.24); - background: rgba(81, 154, 91, 0.08); -} - -.task-draft-overview .task-config-strip { - margin-top: 12px; + color: var(--kilo-reference-muted); + font-size: 11px; + font-weight: 700; } -.task-advanced-panel[open] { - box-shadow: var(--shadow-subtle); +#panel-orchestration .kilo-provider-setup-form .form-input { + width: 100%; + min-width: 0; } -.task-advanced-summary { +#panel-orchestration .kilo-provider-setup-actions { display: flex; + grid-column: 1 / -1; align-items: center; - justify-content: space-between; - cursor: pointer; - font-size: 13px; - font-weight: 700; - color: var(--color-text-primary); - list-style: none; - min-height: 36px; - padding: 0 10px; - border-radius: 12px; - background: rgba(255, 255, 255, 0.64); - border: 1px solid var(--color-border-soft); - transition: - border-color var(--transition-fast) var(--ease-smooth), - background var(--transition-fast) var(--ease-smooth), - box-shadow var(--transition-fast) var(--ease-smooth); -} - -.task-advanced-summary:hover { - border-color: var(--color-border-strong); - background: rgba(255, 255, 255, 0.86); -} - -.task-advanced-panel[open] > .task-advanced-summary { - border-color: rgba(199, 116, 98, 0.4); - box-shadow: var(--shadow-subtle); + justify-content: flex-end; + gap: 8px; + color: var(--kilo-reference-muted); + font-size: 11px; } -.task-advanced-summary::-webkit-details-marker { - display: none; +#panel-orchestration .kilo-provider-setup-actions span { + margin-right: auto; } -.task-advanced-panel > .task-composer-grid, -.task-advanced-panel > .selector-grid { - margin-top: 12px; +#panel-orchestration .chat-input { + flex-shrink: 0; + border-top: 1px solid var(--kilo-reference-border); + background: var(--kilo-shell-subtle); + padding: 10px clamp(18px, 4vw, 56px) 14px; } -.task-readiness-head { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 12px; +#panel-orchestration .kilo-status-dock { + width: min(100%, 98ch); + margin: 0 auto 8px; + color: var(--kilo-reference-muted); + font-size: 11px; } -.task-readiness-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 10px; - margin-top: 12px; +#panel-orchestration .kilo-status-dock span { + border: 1px solid var(--kilo-reference-border); + border-radius: 999px; + background: #fff; + padding: 3px 8px; } -.task-readiness-item { +#panel-orchestration .prompt-input-container { display: flex; + width: min(100%, 98ch); + margin: 0 auto; flex-direction: column; - gap: 4px; - padding: 12px; - border-radius: 14px; - border: 1px solid var(--color-border); - background: var(--color-surface); -} - -.task-readiness-item strong { - font-size: 12px; - color: var(--color-text-primary); + gap: 8px; + border: 1px solid var(--kilo-reference-border); + border-radius: 8px; + background: #fff; + box-shadow: 0 8px 24px rgba(24, 48, 84, 0.08); } -.task-readiness-item span { - font-size: 12px; - color: var(--color-text-secondary); - line-height: 1.5; +#panel-orchestration .prompt-input-container:focus-within { + border-color: var(--kilo-reference-blue); + box-shadow: 0 0 0 3px var(--kilo-shell-focus), 0 8px 24px rgba(24, 48, 84, 0.08); } -.task-readiness-item.done { - border-color: rgba(81, 154, 91, 0.24); - background: rgba(81, 154, 91, 0.08); +#panel-orchestration .prompt-input-shell { + display: grid; + grid-template-columns: 22px minmax(0, 1fr); + gap: 8px; + padding: 9px 10px 0; } -.task-action-row, -.task-plan-summary-strip, -.task-detail-summary-strip { - display: flex; - flex-wrap: wrap; - gap: 10px; +#panel-orchestration .prompt-input-prefix { + color: var(--kilo-reference-blue); + font-size: 20px; + font-weight: 900; + line-height: 1.25; } -.task-action-row-prominent { - align-items: center; - margin-top: 4px; +#panel-orchestration .prompt-input-textarea { + min-height: 62px; + width: 100%; + border: 0; + outline: 0; + resize: vertical; + background: transparent; + color: var(--kilo-reference-text); + font: inherit; + font-size: 13px; + line-height: 1.5; } -.task-action-row > .btn-tool, -.task-action-row-right > .btn-tool { - width: auto; - min-height: 36px; - height: 36px; - display: inline-flex; - align-items: center; - justify-content: center; - box-sizing: border-box; +#panel-orchestration .prompt-input-actions { + justify-content: flex-end; + border-top: 1px solid #eef2f7; + color: var(--kilo-reference-muted); + font-size: 12px; + padding: 8px 10px 9px; } - -.task-action-row-right { - display: flex; - flex-wrap: wrap; - gap: 10px; +#panel-orchestration .prompt-input-actions span { + flex: 1; + min-width: 180px; } -.task-action-row-right-prominent > .btn-tool { - min-width: 104px; -} +@media (max-width: 820px) { + #panel-orchestration.kilo-webview-mode { + --kilo-workbench-shell-offset: 184px; + --kilo-workbench-min-height: 420px; + } -.task-action-help-prominent, -.task-action-help-sidebar { - display: flex; - flex-direction: column; - gap: 8px; - margin-top: 12px; -} + #panel-orchestration .kilo-task-header, + #panel-orchestration .kilo-context-strip { + grid-template-columns: 1fr; + } -.task-section-header { - align-items: center; - justify-content: space-between; - gap: 12px; -} - -.task-section-header > :first-child { - flex: 1 1 auto; - min-width: 0; -} - -.task-header-actions, -.task-section-header .settings-tab-actions, -.task-detail-toolbar { - display: flex; - flex-wrap: wrap; - gap: 8px; - align-items: center; - justify-content: flex-end; - margin-left: auto; -} - -.task-workbench-tabs { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-top: 14px; -} - -.task-workbench-tab.active { - background: var(--color-brand-light); - border-color: var(--color-brand); - color: var(--color-brand-dark); - box-shadow: var(--shadow-subtle); -} - -.task-workbench-panel { - margin-top: 14px; -} - -.task-action-caption { - margin-top: 12px; - font-size: 12px; - line-height: 1.6; - color: var(--color-text-secondary); -} - -.task-stage-empty { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; -} - -.task-stage-strip { - display: flex; - flex-wrap: wrap; - gap: 8px; - justify-content: flex-end; -} - -.task-stage-pill { - padding: 8px 12px; - border-radius: 999px; - border: 1px solid var(--color-border-soft); - background: var(--color-surface); - font-size: 12px; - font-weight: 600; - color: var(--color-text-secondary); -} - -.task-plan-summary-item { - min-width: 120px; - padding: 12px; - border-radius: 14px; - border: 1px solid var(--color-border); - background: var(--color-surface-alt); - display: flex; - flex-direction: column; - gap: 4px; -} - -.task-plan-summary-label { - font-size: 11px; - color: var(--color-text-muted); - text-transform: uppercase; - letter-spacing: 0.06em; -} - -.task-wave-list, -.task-node-list, -.task-runtime-list, -.task-warning-list, -.task-issues-list { - display: flex; - flex-direction: column; - gap: 10px; - margin-top: 12px; -} - -.task-wave-card, -.task-node-card, -.task-runtime-item, -.task-warning-item, -.task-issue-item { - border: 1px solid var(--color-border); - border-radius: 14px; - background: var(--color-surface-alt); -} - -.task-wave-card, -.task-node-card { - padding: 14px; -} - -.task-warning-item, -.task-issue-item { - padding: 10px 12px; - font-size: 13px; -} - -.task-warning-item { - color: var(--color-text-secondary); - background: rgba(255, 244, 220, 0.7); -} - -.task-issue-item { - color: #8f2d21; - background: rgba(255, 232, 228, 0.75); -} - -.task-wave-title, -.task-node-title, -.task-runtime-item-title { - font-weight: 700; - color: var(--color-text-primary); -} - -.task-wave-nodes, -.task-node-meta, -.task-node-deps, -.task-runtime-item-meta, -.task-runtime-item-summary { - font-size: 12px; - color: var(--color-text-secondary); - line-height: 1.55; -} - -.task-node-head, -.task-runtime-item, -.task-runtime-item-actions { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 10px; -} - -.task-runtime-item { - width: 100%; - padding: 14px; - cursor: default; - text-align: left; -} - -.task-runtime-item.clickable { - cursor: pointer; -} - -.task-runtime-item.active { - border-color: rgba(199, 116, 98, 0.3); - background: var(--color-brand-light); -} - -.task-runtime-item-main { - min-width: 0; - flex: 1; - display: flex; - flex-direction: column; - gap: 4px; -} - -.task-runtime-item-actions { - flex-direction: row; - align-items: center; - justify-content: flex-end; - flex-wrap: nowrap; - flex: 0 0 auto; -} - -.task-runtime-item-actions .btn-mini { - min-width: 72px; - min-height: 30px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - box-sizing: border-box; -} - -.pill.success { - background: rgba(81, 154, 91, 0.14); - color: #285d31; -} - -.pill.warn { - background: rgba(214, 153, 58, 0.16); - color: #7a5110; -} - -.pill.error { - background: rgba(194, 73, 63, 0.16); - color: #8f2d21; -} - -.pill.neutral { - background: rgba(116, 126, 138, 0.14); - color: #45515e; -} - -.task-log-block { - margin: 10px 0 0; - min-height: 120px; - white-space: pre-wrap; - word-break: break-word; - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; - font-size: 12px; - line-height: 1.55; -} - -.task-node-output-card { - margin-top: 12px; - padding: 12px; - border-radius: 16px; - border: 1px solid rgba(100, 116, 139, 0.16); - background: #F8FAFC; -} - -.task-node-output-head, -.task-node-output-facts { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - flex-wrap: wrap; -} - -.task-node-output-head strong { - font-size: 13px; - color: var(--color-text-primary); -} - -.task-node-output-meta, -.task-node-output-facts, -.task-materialized-file { - font-size: 12px; - line-height: 1.55; - color: var(--color-text-secondary); -} - -.task-node-output-facts { - justify-content: flex-start; - margin-top: 6px; -} - -.task-output-block { - max-height: 260px; - min-height: 96px; - overflow: auto; - background: #FFFFFF; -} - -.task-materialized-files { - margin-top: 10px; - display: flex; - flex-direction: column; - gap: 4px; -} - -.task-workspace-files { - padding: 10px; - border: 1px solid rgba(199, 116, 98, 0.2); - border-radius: 14px; - background: #FFFDFC; -} - -.task-workspace-files .task-node-deps { - color: var(--color-brand-dark); - font-weight: 800; -} - -@media (max-width: 1200px) { - .task-layout-grid-primary, - .task-layout-grid-secondary, - .task-chat-context-row-primary { - grid-template-columns: 1fr; - } -} - -@media (max-width: 720px) { - .task-composer-grid, - .task-readiness-grid, - .task-checklist-inline, - .task-composer-grid-compact { - grid-template-columns: 1fr; - } - - .task-hero-main, - .task-flow-head, - .task-draft-overview-head, - .task-stage-empty, - .task-readiness-head, - .task-section-header, - .task-node-head, - .task-runtime-item, - .task-runtime-item-actions { - flex-direction: column; - align-items: stretch; - } - - .task-header-actions, - .task-section-header .settings-tab-actions, - .task-detail-toolbar, - .task-action-row-right { - margin-left: 0; - width: 100%; + #panel-orchestration [data-slot="task-header-stats"], + #panel-orchestration .prompt-input-actions { justify-content: flex-start; } - .task-hero-actions { - flex-wrap: wrap; - } -} - -.task-quick-layout { - margin-bottom: 18px; -} - -.task-quick-card { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(260px, 340px); - gap: 18px; - align-items: stretch; -} - -.task-quick-main { - min-width: 0; - display: flex; - flex-direction: column; - gap: 14px; -} - -.task-quick-copy { - max-width: 780px; -} - -.task-quick-title { - font-size: clamp(22px, 2vw, 30px); - line-height: 1.18; -} - -.task-quick-input-card { - padding: 18px; - border-radius: 22px; - border: 1px solid var(--color-border-soft); - background: #F8FAFC; - box-shadow: var(--shadow-subtle); -} - -.task-quick-target-field { - display: block; -} - -.task-chat-composer .selector-label { - font-size: 12px; - letter-spacing: 0.04em; - text-transform: uppercase; -} - -.task-quick-target { - min-height: 88px; - border-radius: 18px; - background: var(--color-surface); - font-size: 15px; -} - - -.task-chat-panel { - display: flex; - flex-direction: column; - gap: 14px; -} - -.task-chat-thread { - display: flex; - flex-direction: column; - gap: 10px; - max-height: 420px; - overflow-x: hidden; - overflow-y: auto; - overscroll-behavior: contain; - scrollbar-width: thin; - scrollbar-color: transparent transparent; - padding: 12px; - border-radius: 20px; - border: 1px solid var(--color-border-soft); - background: rgba(255, 255, 255, 0.74); - transition: scrollbar-color 0.16s ease; -} - -.task-chat-thread:hover, -.task-chat-thread:focus-within { - scrollbar-color: rgba(100, 116, 139, 0.28) transparent; -} - -.task-chat-thread::-webkit-scrollbar { - width: 6px; - height: 6px; -} - -.task-chat-thread::-webkit-scrollbar-track { - background: transparent; -} - -.task-chat-thread::-webkit-scrollbar-thumb { - border-radius: 999px; - background: transparent; -} - -.task-chat-thread:hover::-webkit-scrollbar-thumb, -.task-chat-thread:focus-within::-webkit-scrollbar-thumb { - background: rgba(100, 116, 139, 0.28); -} - -.task-chat-thread::-webkit-scrollbar-thumb:hover { - background: rgba(100, 116, 139, 0.42); -} - -.task-chat-bubble-row { - display: flex; - width: 100%; -} - -.task-chat-bubble-row.is-assistant { - justify-content: flex-start; -} - -.task-chat-bubble-row.is-user { - justify-content: flex-end; -} - -.task-chat-bubble { - max-width: min(76%, 680px); - padding: 11px 13px; - border-radius: 18px; - border: 1px solid var(--color-border-soft); - background: var(--color-surface); - box-shadow: 0 8px 24px rgba(36, 24, 20, 0.06); -} - -.task-chat-bubble-row.is-user .task-chat-bubble { - border-color: rgba(199, 116, 98, 0.28); - background: var(--color-brand-light); - color: var(--color-brand-dark); - border-bottom-right-radius: 6px; -} - -.task-chat-bubble-row.is-assistant .task-chat-bubble { - border-bottom-left-radius: 6px; -} - -.task-chat-bubble-label { - font-size: 11px; - font-weight: 800; - letter-spacing: 0.04em; - text-transform: uppercase; - color: var(--color-text-muted); - margin-bottom: 5px; -} - -.task-chat-bubble-text { - font-size: 14px; - line-height: 1.55; - color: var(--color-text-primary); - white-space: pre-wrap; - overflow-wrap: anywhere; -} - -.task-chat-bubble-row.is-user .task-chat-bubble-text, -.task-chat-bubble-row.is-user .task-chat-bubble-label, -.task-chat-bubble-row.is-user .task-chat-bubble-meta { - color: var(--color-brand-dark); -} - -.task-chat-bubble-meta { - margin-top: 6px; - font-size: 11px; - line-height: 1.45; - color: var(--color-text-secondary); -} - -.task-chat-send-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - flex-wrap: wrap; -} - -.task-chat-action-buttons { - display: flex; - flex-wrap: wrap; - gap: 8px; -} - -.task-chat-primary-action { - flex: 1 1 180px; - display: grid; - place-items: center; - align-self: stretch; -} - -.task-chat-primary-button { - min-width: 168px; - min-height: 44px; - justify-content: center; - font-weight: 800; -} - -.task-chat-execute-caption { - margin-top: 8px; - color: var(--color-text-secondary); - font-size: 12px; - line-height: 1.45; -} - -.task-chat-context-row { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-top: 12px; -} - -.task-chat-context-row-primary { - display: grid; - grid-template-columns: minmax(260px, 1.2fr) minmax(220px, 0.8fr) repeat(3, minmax(96px, auto)); - align-items: stretch; - padding: 10px; - border: 1px solid rgba(199, 116, 98, 0.18); - border-radius: 18px; - background: #FFFFFF; -} - -.task-chat-context-chip { - display: inline-flex; - align-items: center; - min-height: 30px; - max-width: 100%; - padding: 0 10px; - border-radius: 999px; - border: 1px solid rgba(199, 116, 98, 0.18); - background: rgba(255, 255, 255, 0.68); - color: var(--color-text-secondary); - font-size: 12px; - font-weight: 600; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.task-chat-context-chip-strong { - display: flex; - align-items: flex-start; - flex-direction: column; - justify-content: center; - gap: 2px; - min-height: 42px; - border-radius: 14px; - background: #FFFDFC; - color: var(--color-text-primary); - white-space: normal; -} - -.task-chat-context-chip-strong small { - color: var(--color-text-muted); - font-size: 10px; - font-weight: 800; - letter-spacing: 0.06em; - text-transform: uppercase; -} - -.task-chat-context-chip-strong strong { - max-width: 100%; - overflow-wrap: anywhere; - word-break: break-word; - font-size: 12px; - line-height: 1.35; -} - -.task-chat-context-action { - cursor: pointer; - font: inherit; -} - -.task-chat-context-action:hover, -.task-chat-context-action:focus-visible { - border-color: rgba(199, 116, 98, 0.38); - color: var(--color-brand-dark); - outline: none; -} - -.task-quick-readiness { - margin-top: 14px; - background: rgba(255, 255, 255, 0.58); -} - -.task-quick-template-block { - padding: 14px; -} - -.task-quick-template-grid { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 10px; - margin-top: 10px; -} - -.task-quick-template-card { - min-width: 0; - padding: 14px; - border-radius: 16px; - border: 1px solid var(--color-border-soft); - background: var(--color-surface); - color: var(--color-text-primary); - text-align: left; - cursor: pointer; - transition: - transform var(--transition-fast) var(--ease-smooth), - border-color var(--transition-fast) var(--ease-smooth), - box-shadow var(--transition-fast) var(--ease-smooth), - background var(--transition-fast) var(--ease-smooth); -} - -.task-quick-template-card:hover { - transform: translateY(-1px); - border-color: rgba(199, 116, 98, 0.34); - background: var(--color-brand-light); - box-shadow: var(--shadow-subtle); -} - -.task-quick-template-card strong, -.task-quick-template-card span { - display: block; -} - -.task-quick-template-card strong { - font-size: 13px; - color: var(--color-text-primary); -} - -.task-quick-template-card span { - margin-top: 6px; - font-size: 12px; - line-height: 1.5; - color: var(--color-text-secondary); -} - -.task-quick-advanced { - margin-top: 0; -} - -.task-quick-side-card { - min-width: 0; - padding: 16px; - border-radius: 20px; - border: 1px solid var(--color-border-soft); - background: var(--color-surface-alt); - box-shadow: var(--shadow-subtle); -} - -.task-provider-status-card { - margin-bottom: 14px; - padding: 14px; - border-radius: 16px; - border: 1px solid rgba(100, 116, 139, 0.16); - background: #FFFFFF; - display: flex; - flex-direction: column; - gap: 10px; -} - -.task-provider-status-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 8px; -} - -.task-provider-status-row { - min-width: 0; - padding: 9px 10px; - border-radius: 12px; - background: #F8FAFC; - border: 1px solid rgba(100, 116, 139, 0.10); -} - -.task-provider-status-row-wide { - grid-column: 1 / -1; -} - -.task-provider-status-row span, -.task-provider-status-row strong { - display: block; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.task-provider-status-row span { - font-size: 11px; - color: var(--color-text-muted); -} - -.task-provider-status-row strong { - margin-top: 3px; - font-size: 12px; - color: var(--color-text-primary); -} - -.task-provider-status-error { - margin: 0; -} - -.task-provider-config-button { - align-self: flex-start; -} - -.task-quick-checklist { - grid-template-columns: 1fr; -} - -.task-quick-status-card { - margin-top: 14px; - padding: 14px; - border-radius: 16px; - border: 1px solid rgba(199, 116, 98, 0.18); - background: var(--color-surface); - display: flex; - flex-direction: column; - gap: 6px; -} - -.task-quick-status-card strong { - color: var(--color-text-primary); -} - -.task-quick-status-card span { - font-size: 12px; - line-height: 1.55; - color: var(--color-text-secondary); -} - -@media (max-width: 1200px) { - .task-quick-card { - grid-template-columns: 1fr; - } - - .task-quick-checklist { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } -} - -@media (max-width: 720px) { - .task-quick-template-grid, - .task-quick-checklist { - grid-template-columns: 1fr; - } -} - -/* Codex-style orchestration simplification: keep the chat thread as the main surface. */ -#panel-orchestration { - --task-orchestration-main-width: 1200px; - --task-orchestration-context-width: 260px; -} - -#panel-orchestration .task-hero-card { - max-width: var(--task-orchestration-main-width); - margin: -4px auto 14px; - padding: 16px 18px; - box-shadow: none; -} - -#panel-orchestration .task-hero-main { - align-items: center; -} - -#panel-orchestration .task-hero-copy, -#panel-orchestration .task-hero-meta-strip, -#panel-orchestration .task-quick-copy, -#panel-orchestration .task-template-block, -#panel-orchestration .task-stage-card { - display: none; -} - -#panel-orchestration .task-layout-grid-primary, -#panel-orchestration .task-layout-grid-secondary { - max-width: var(--task-orchestration-main-width); - margin-left: auto; - margin-right: auto; -} - -#panel-orchestration .task-quick-card { - display: grid; - grid-template-columns: minmax(0, 1fr) var(--task-orchestration-context-width); - gap: 14px; - align-items: start; - padding: 0; - border: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-quick-main { - display: block; - min-width: 0; -} - -#panel-orchestration { - min-height: calc(100vh - 96px); -} - -#panel-orchestration .task-hero-card { - padding: 10px 14px; - border-radius: 16px; - background: rgba(255, 255, 255, 0.62); - box-shadow: none; -} - -#panel-orchestration .task-hero-main { - align-items: center; - gap: 12px; -} - -#panel-orchestration .task-hero-card .selector-title { - font-size: 1rem; - line-height: 1.25; -} - -#panel-orchestration .task-hero-card .task-hero-copy, -#panel-orchestration .task-hero-card .task-hero-kicker { - display: none; -} - -#panel-orchestration .task-quick-card { - display: grid; - grid-template-columns: minmax(0, 1fr) var(--task-orchestration-context-width); - gap: 14px; - align-items: start; - padding: 0; - border: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-quick-main { - display: flex; - flex-direction: column; - gap: 10px; - min-width: 0; -} - -#panel-orchestration .task-chat-panel { - display: flex; - flex-direction: column; - gap: 12px; - height: min(780px, calc(100vh - 170px)); - min-height: 620px; - margin: 0; - padding: 12px; - overflow: hidden; - border: 1px solid rgba(199, 116, 98, 0.16); - border-radius: 22px; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(255, 252, 248, 0.7)), - rgba(255, 255, 255, 0.6); - box-shadow: 0 18px 52px rgba(86, 58, 39, 0.08); -} - -#panel-orchestration .task-chat-thread { - flex: 1 1 auto; - min-height: 0; - max-height: none; - margin: 0; - padding: 10px 8px 16px; - gap: 12px; - overflow-y: auto; - border: 0; - background: transparent; -} - -#panel-orchestration .task-thread-message-card { - position: relative; - align-self: flex-start; - width: min(100%, 760px); - margin: 2px 0 4px 44px; - padding: 14px; - border: 1px solid rgba(199, 116, 98, 0.18); - border-radius: 20px; - background: rgba(255, 255, 255, 0.84); - box-shadow: 0 12px 30px rgba(86, 58, 39, 0.09); -} - -#panel-orchestration .task-thread-message-card::before { - content: 'AI'; - position: absolute; - left: -40px; - top: 12px; - display: grid; - width: 30px; - height: 30px; - place-items: center; - border-radius: 999px; - background: var(--color-brand-light); - color: var(--color-brand-dark); - font-size: 11px; - font-weight: 800; - letter-spacing: 0.04em; -} - -#panel-orchestration .task-thread-message-card .selector-header { - margin-bottom: 10px; -} - -#panel-orchestration .task-thread-message-card .selector-title { - font-size: 0.98rem; -} - -#panel-orchestration .task-thread-message-card .skills-panel-note { - font-size: 0.82rem; -} - -#panel-orchestration .task-thread-composer { - flex: 0 0 auto; - position: sticky; - bottom: 0; - z-index: 2; - width: min(100%, 800px); - align-self: center; - margin-top: 0; - padding: 10px; - border: 1px solid rgba(199, 116, 98, 0.18); - border-radius: 18px 18px 20px 20px; - background: rgba(255, 255, 255, 0.96); - box-shadow: 0 -10px 34px rgba(86, 58, 39, 0.13); -} - -#panel-orchestration .task-thread-composer .selector-label { - font-size: 0.78rem; -} - -#panel-orchestration .task-thread-composer .task-textarea-goal { - min-height: 76px; - resize: vertical; - border: 0; - border-radius: 12px; - background: rgba(255, 248, 241, 0.48); - font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); - font-size: 15px; - line-height: 1.55; - box-shadow: none; -} - -#panel-orchestration .task-thread-composer .task-textarea-goal:focus { - box-shadow: none; -} - -#panel-orchestration .task-thread-composer .task-chat-send-row, -#panel-orchestration .task-thread-composer .task-chat-context-row, -#panel-orchestration .task-thread-composer .task-draft-inline, -#panel-orchestration .task-thread-composer .task-action-row-prominent { - margin-top: 8px; -} - -#panel-orchestration .task-thread-composer .task-draft-inline { - padding: 8px 10px; - border-radius: 14px; - background: rgba(255, 248, 241, 0.58); -} - -#panel-orchestration .task-thread-composer .task-action-row-prominent { - padding-top: 0; - border-top: 1px solid rgba(199, 116, 98, 0.12); -} - -#panel-orchestration .task-thread-composer .task-action-row-right { - margin-left: auto; -} - -#panel-orchestration .task-thread-composer .task-field-hint { - font-size: 0.75rem; -} - -#panel-orchestration .task-plan-summary-strip, -#panel-orchestration .task-wave-list, -#panel-orchestration .task-node-list, -#panel-orchestration .task-runtime-list { - gap: 8px; -} - -#panel-orchestration .task-quick-advanced { - margin-top: 8px; - border: 1px solid rgba(148, 163, 184, 0.14); - background: rgba(255, 255, 255, 0.46); - box-shadow: none; -} - -#panel-orchestration .task-codex-queue-action { - justify-content: flex-start; - margin: 0 0 12px; -} - -#panel-orchestration .task-quick-side-card { - position: sticky; - top: 14px; - padding: 12px; - border-radius: 18px; - background: rgba(255, 255, 255, 0.42); - opacity: 0.82; - box-shadow: none; -} - -#panel-orchestration .task-provider-status-card, -#panel-orchestration .task-quick-status-card, -#panel-orchestration .task-quick-side-card .task-readiness-item { - background: rgba(255, 255, 255, 0.48); - border-color: rgba(148, 163, 184, 0.16); - box-shadow: none; -} - -#panel-orchestration .task-provider-status-card, -#panel-orchestration .task-quick-status-card { - margin-bottom: 10px; - padding: 10px; - border-radius: 14px; -} - -#panel-orchestration .task-provider-status-grid { - grid-template-columns: 1fr; - gap: 6px; -} - -#panel-orchestration .task-provider-status-row { - padding: 7px 8px; - border-radius: 10px; - background: rgba(248, 250, 252, 0.62); -} - -#panel-orchestration .task-provider-status-card .task-readiness-copy, -#panel-orchestration .task-readiness-head .task-readiness-copy { - display: none; -} - -#panel-orchestration .task-readiness-grid.task-quick-checklist { - grid-template-columns: 1fr; - gap: 7px; - margin-top: 8px; -} - -#panel-orchestration .task-readiness-item { - padding: 9px 10px; - border-radius: 12px; -} - -#panel-orchestration .task-quick-status-card { - margin-top: 10px; -} - -@media (max-width: 1180px) { - #panel-orchestration .task-quick-card { - grid-template-columns: minmax(0, 1fr); - } - - #panel-orchestration .task-thread-message-card { - width: 100%; - margin-left: 0; - } - - #panel-orchestration .task-thread-message-card::before { - display: none; - } - - #panel-orchestration .task-quick-side-card { - position: static; - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 10px; - } - - #panel-orchestration .task-provider-status-card, - #panel-orchestration .task-quick-status-card { - margin-bottom: 0; - } -} - -@media (max-width: 760px) { - #panel-orchestration .task-hero-main, - #panel-orchestration .task-action-row-prominent, - #panel-orchestration .task-action-row-prominent .task-action-row-right { - align-items: stretch; - flex-direction: column; - } - - #panel-orchestration .task-action-row-prominent .btn-tool, - #panel-orchestration .task-action-row-prominent .task-action-row-right { - width: 100%; - } - - #panel-orchestration .task-quick-side-card, - #panel-orchestration .task-template-block, - #panel-orchestration .task-quick-copy, - #panel-orchestration .task-stage-card { - display: none; - } - - #panel-orchestration .task-chat-panel { - height: calc(100vh - 126px); - min-height: 620px; - padding: 10px; - border-radius: 18px; - } - - #panel-orchestration .task-chat-thread { - padding: 10px 6px 14px; - } - - #panel-orchestration .task-thread-message-card { - padding: 12px; - border-radius: 18px; - } - - #panel-orchestration .task-thread-composer { - width: 100%; - padding: 8px; - border-radius: 16px; - box-shadow: 0 -8px 26px rgba(86, 58, 39, 0.12); - } - - #panel-orchestration .task-thread-composer .task-textarea-goal { - min-height: 56px; - max-height: 120px; - } - - #panel-orchestration .task-thread-composer .task-chat-context-row, - #panel-orchestration .task-thread-composer .task-draft-inline, - #panel-orchestration .task-thread-composer .task-action-caption, - #panel-orchestration .task-thread-composer .task-field-hint { - display: none; - } - - #panel-orchestration .task-thread-composer .task-chat-send-row, - #panel-orchestration .task-thread-composer .task-action-row-prominent { - margin-top: 6px; - } - - #panel-orchestration .task-thread-composer .btn-tool { - min-height: 34px; - padding: 0 12px; - font-size: 0.78rem; - } -} - -/* Codex-style transcript final pass: the task flow is a chat, not a dashboard. */ -#panel-orchestration { - --task-orchestration-main-width: 920px; - --task-orchestration-context-width: 0px; - - min-height: calc(100vh - 72px); - padding-bottom: 188px; -} - -#panel-orchestration .task-hero-card, -#panel-orchestration .task-quick-copy, -#panel-orchestration .task-stage-card { - display: none; -} - -#panel-orchestration .task-layout-grid, -#panel-orchestration .task-layout-grid-primary, -#panel-orchestration .task-layout-grid-secondary, -#panel-orchestration .task-quick-card { - max-width: var(--task-orchestration-main-width); - width: min(100%, var(--task-orchestration-main-width)); - margin-left: auto; - margin-right: auto; -} - -#panel-orchestration .task-layout-grid { - gap: 0; - margin-bottom: 0; -} - -#panel-orchestration .task-quick-card { - display: block; - padding: 0; - border: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-quick-main { - display: block; - min-width: 0; -} - -#panel-orchestration .task-template-block { - display: block; -} - -#panel-orchestration .task-chat-panel { - display: flex; - flex-direction: column; - gap: 8px; - height: auto; - min-height: 0; - margin: 0 auto; - padding: 0; - overflow: visible; - border: 0; - border-radius: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-chat-thread { - flex: 0 0 auto; - min-height: 0; - max-height: none; - margin: 0; - padding: 8px 8px 188px; - gap: 7px; - overflow: visible; - border: 0; - background: transparent; - scroll-padding-bottom: 188px; -} - -#panel-orchestration .task-chat-bubble-row { - position: relative; - justify-content: flex-start; - gap: 8px; - margin: 0; - padding: 1px 0 6px 28px; -} - -#panel-orchestration .task-chat-bubble-row::before { - content: '•'; - position: absolute; - top: 4px; - left: 8px; - color: #64748B; - font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); - font-size: 16px; - font-weight: 800; - line-height: 1; -} - -#panel-orchestration .task-chat-bubble-row.is-user::before { - content: '›'; - top: 2px; - color: #2563EB; - font-size: 20px; -} - -#panel-orchestration .task-chat-bubble { - max-width: min(100%, 760px); - padding: 0 0 5px; - border: 0; - border-radius: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-chat-bubble-row.is-user .task-chat-bubble, -#panel-orchestration .task-chat-bubble-row.is-assistant .task-chat-bubble { - border-radius: 0; - background: transparent; -} - -#panel-orchestration .task-chat-bubble-label { - margin-bottom: 3px; - color: #64748B; - font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); - font-size: 10px; - letter-spacing: 0.04em; - text-transform: uppercase; -} - -#panel-orchestration .task-chat-bubble-text { - color: #0F172A; - font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); - font-size: 14px; - line-height: 1.5; -} - -#panel-orchestration .task-chat-bubble-meta { - margin-top: 5px; - color: #64748B; - font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); -} - -#panel-orchestration .task-thread-plan-request { - margin-top: 2px; -} - -#panel-orchestration .task-thread-plan-request .task-chat-bubble { - max-width: min(100%, 760px); -} - -#panel-orchestration .task-thread-message-card { - position: relative; - align-self: flex-start; - width: min(100%, 660px); - margin: 0 0 2px 34px; - padding: 8px 10px; - border: 1px solid rgba(148, 163, 184, 0.18); - border-left: 3px solid rgba(199, 116, 98, 0.32); - border-radius: 14px 14px 14px 5px; - background: rgba(255, 255, 255, 0.50); - box-shadow: none; -} - -#panel-orchestration .task-thread-message-card::before { - content: 'AI'; - position: absolute; - left: -34px; - top: 8px; - display: grid; - width: 24px; - height: 24px; - place-items: center; - border-radius: 999px; - background: var(--color-brand-light); - color: var(--color-brand-dark); - font-size: 9px; - font-weight: 800; - letter-spacing: 0.04em; -} - -#panel-orchestration .task-thread-card-label { - margin-bottom: 6px; - color: var(--color-text-secondary); - font-size: 10px; - font-weight: 800; - letter-spacing: 0.07em; - text-transform: uppercase; -} - -#panel-orchestration .task-thread-message-card .selector-header { - margin-bottom: 6px; - padding-bottom: 0; - border-bottom: 0; -} - -#panel-orchestration .task-thread-message-card .selector-title { - font-size: 0.9rem; - line-height: 1.2; -} - -#panel-orchestration .task-side-settings-card .task-advanced-summary { - margin: 0 0 8px; - color: var(--color-text-primary); - font-size: 0.86rem; - font-weight: 750; -} - -#panel-orchestration .task-side-settings-card:not([open]) { - padding: 8px 10px; -} - -#panel-orchestration .task-side-settings-card .selector-grid { - margin-top: 8px; -} - -#panel-orchestration .task-side-settings-card .task-codex-queue-action { - justify-content: flex-start; - margin: 8px 0 0; -} - -#panel-orchestration .task-thread-message-card .skills-panel-note { - font-size: 0.76rem; - line-height: 1.45; -} - -#panel-orchestration .task-thread-message-card .task-plan-summary-strip { - display: flex; - flex-wrap: wrap; - gap: 5px; - margin-top: 5px; -} - -#panel-orchestration .task-thread-message-card .task-plan-summary-item { - min-width: 0; - padding: 0; - border: 0; - border-radius: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-thread-message-card .task-plan-summary-label { - font-size: 9px; -} - -#panel-orchestration .task-thread-plan-card .task-wave-list, -#panel-orchestration .task-runtime-list { - gap: 5px; - margin-top: 7px; -} - -#panel-orchestration .task-thread-plan-card .task-wave-list { - display: none; -} - -#panel-orchestration .task-thread-plan-card .task-node-list { - display: none; -} - -#panel-orchestration .task-thread-plan-card .task-plan-summary-item:nth-child(n+3) { - display: none; -} - -#panel-orchestration .task-thread-plan-card .task-wave-card, -#panel-orchestration .task-thread-plan-card .task-node-card, -#panel-orchestration .task-thread-message-card .task-runtime-item { - padding: 4px 0; - border: 0; - border-radius: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-thread-plan-card .task-wave-nodes, -#panel-orchestration .task-thread-plan-card .task-node-meta, -#panel-orchestration .task-thread-plan-card .task-node-deps { - display: none; -} - -#panel-orchestration .task-thread-plan-card .task-node-head { - align-items: center; -} - -#panel-orchestration .task-thread-plan-card .pill { - padding: 3px 7px; - font-size: 10px; -} - -#panel-orchestration .task-thread-plan-card .task-node-title, -#panel-orchestration .task-thread-plan-card .task-wave-title, -#panel-orchestration .task-thread-message-card .task-runtime-item-title { - font-size: 0.8rem; - font-weight: 650; -} - -#panel-orchestration .task-thread-message-card .task-runtime-item-meta { - font-size: 0.72rem; - line-height: 1.4; -} - -#panel-orchestration .task-side-workbench-card, -#panel-orchestration .task-side-settings-card { - max-height: min(560px, calc(100vh - 220px)); - margin-bottom: 8px; - overflow: auto; -} - -#panel-orchestration .task-side-workbench-card .task-node-list { - max-height: 320px; - overflow: auto; - padding-right: 4px; -} - -#panel-orchestration .task-quick-side-card { - width: min(100%, 660px); - margin: 8px auto 0; - padding: 10px 12px; - border: 1px solid rgba(148, 163, 184, 0.18); - border-left: 3px solid rgba(100, 116, 139, 0.24); - border-radius: 14px; - background: rgba(255, 255, 255, 0.42); - box-shadow: none; -} - -#panel-orchestration .task-quick-side-card .task-provider-status-card { - margin-bottom: 8px; - padding: 0; - border: 0; - background: transparent; -} - -#panel-orchestration .task-quick-side-card .task-readiness-head, -#panel-orchestration .task-quick-side-card .task-readiness-grid, -#panel-orchestration .task-quick-side-card .task-quick-status-card { - display: none; -} - -#panel-orchestration .task-quick-side-card .task-provider-status-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); -} - -#panel-orchestration .task-thread-composer { - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - grid-template-rows: auto auto; - align-items: stretch; - gap: 6px; - flex: 0 0 auto; - position: fixed; - right: 50%; - bottom: 16px; - z-index: 20; - width: min(872px, calc(100vw - 48px)); - transform: translateX(50%); - margin-top: 0; - padding: 6px 8px; - border: 1px solid rgba(148, 163, 184, 0.20); - border-radius: 14px; - background: rgba(255, 255, 255, 0.92); - box-shadow: 0 14px 36px rgba(15, 23, 42, 0.13); -} - -#panel-orchestration .task-thread-composer .selector-label, -#panel-orchestration .task-thread-composer .task-chat-context-row, -#panel-orchestration .task-thread-composer .task-draft-inline, -#panel-orchestration .task-thread-composer .task-action-caption, -#panel-orchestration .task-thread-composer .task-field-hint { - display: none; -} - -#panel-orchestration .task-thread-composer .task-chat-composer { - grid-column: 1; - grid-row: 1 / span 2; - display: grid; - grid-template-columns: auto minmax(0, 1fr); - align-items: start; - gap: 8px; -} - -#panel-orchestration .task-thread-composer .task-composer-prompt-glyph { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 18px; - padding-top: 7px; - color: #2563EB; - font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); - font-size: 22px; - font-weight: 800; - line-height: 1; -} - -#panel-orchestration .task-thread-composer .task-textarea-goal { - min-height: 48px; - max-height: 92px; - padding: 8px 10px; - resize: vertical; - border: 0; - border-radius: 12px; - background: rgba(248, 250, 252, 0.66); - font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); - font-size: 14px; - line-height: 1.35; - box-shadow: none; -} - -#panel-orchestration .task-thread-composer .task-textarea-goal:focus { - box-shadow: none; -} - -#panel-orchestration .task-thread-composer .task-chat-send-row { - grid-column: 2; - grid-row: 1 / span 2; - display: flex; - align-items: center; - justify-content: center; - align-self: center; - margin-top: 0; -} - -#panel-orchestration .task-thread-composer .task-chat-execute-caption { - grid-column: 1 / -1; - grid-row: 3; - margin: -1px 2px 0 28px; - color: #64748B; - font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); - font-size: 11px; - line-height: 1.35; -} - -#panel-orchestration .task-thread-composer .task-action-row-prominent { - grid-column: 2; - grid-row: 2; - display: flex; - align-items: center; - justify-content: flex-end; - gap: 7px; - margin-top: 0; - padding-top: 0; - border-top: 0; -} - -#panel-orchestration .task-thread-composer .task-action-row-right { - margin-left: 0; -} - -#panel-orchestration .task-thread-composer .btn-tool { - display: inline-flex; - align-items: center; - justify-content: center; - min-height: 32px; - padding: 5px 10px; - font-size: 0.78rem; -} - -@media (max-width: 760px) { - #panel-orchestration { - --task-orchestration-main-width: 100%; - - min-height: calc(100vh - 52px); - padding-bottom: 208px; - } - - #panel-orchestration .task-layout-grid, - #panel-orchestration .task-layout-grid-primary, - #panel-orchestration .task-layout-grid-secondary, - #panel-orchestration .task-quick-card { - width: 100%; - max-width: 100%; - } - - #panel-orchestration .task-template-block, - #panel-orchestration .task-quick-advanced, - #panel-orchestration .task-quick-side-card { - display: block; - } - - #panel-orchestration .task-chat-panel { - height: auto; - min-height: 0; - } - - #panel-orchestration .task-chat-thread { - padding: 8px 4px 16px; - gap: 7px; - scroll-padding-bottom: 28px; - } - - #panel-orchestration .task-chat-bubble, - #panel-orchestration .task-thread-plan-request .task-chat-bubble { - max-width: 92%; - } - - #panel-orchestration .task-thread-message-card { - width: 100%; - margin-left: 0; - padding: 9px 10px; - border-radius: 15px; - } - - #panel-orchestration .task-thread-message-card::before { - display: none; - } - - #panel-orchestration .task-thread-message-card .task-plan-summary-item { - min-width: calc(50% - 4px); - } - - #panel-orchestration .task-side-workbench-card { - max-height: calc(100vh - 190px); - } - - #panel-orchestration .task-side-workbench-card .task-node-list { - max-height: 260px; - } - - #panel-orchestration .task-chat-thread { - padding-bottom: 208px; - scroll-padding-bottom: 208px; - } - - #panel-orchestration .task-thread-composer { - grid-template-columns: minmax(0, 1fr) auto; - grid-template-rows: auto; - right: 10px; - bottom: calc(env(safe-area-inset-bottom, 0px) + 8px); - left: 10px; - width: auto; - transform: none; - padding: 7px; - border-radius: 14px; - box-shadow: 0 14px 34px rgba(15, 23, 42, 0.16); - } - - #panel-orchestration .task-thread-composer .task-chat-composer { - grid-column: 1; - grid-row: 1; - } - - #panel-orchestration .task-thread-composer .task-chat-send-row { - grid-column: 2; - grid-row: 1; - align-self: center; - } - - #panel-orchestration .task-thread-composer .task-action-row-prominent, - #panel-orchestration .task-thread-composer .task-action-row-prominent .task-action-row-right, - #panel-orchestration .task-thread-composer .task-action-row-prominent .btn-tool { - width: 100%; - } - -#panel-orchestration .task-thread-composer .task-textarea-goal { - min-height: 52px; - max-height: 118px; - } -} - -/* Chat-alignment correction: keep the transcript clean while preserving a - separate side rail for settings, history, and run details. */ -#panel-orchestration { - padding-bottom: 240px; -} - -#panel-orchestration .task-chat-thread { - padding-bottom: 240px; - scroll-padding-bottom: 240px; -} - -#panel-orchestration .task-thread-message-card { - width: min(100%, 620px); - padding: 10px 12px; - border-color: rgba(148, 163, 184, 0.14); - border-left-color: rgba(199, 116, 98, 0.26); - background: rgba(255, 255, 255, 0.62); -} - -#panel-orchestration .task-thread-plan-card, -#panel-orchestration .task-side-workbench-card { - overflow: visible; - max-height: none; -} - -#panel-orchestration .task-thread-message-card .selector-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - margin-bottom: 8px; -} - -#panel-orchestration .task-thread-message-card .selector-title { - font-size: 0.86rem; -} - -#panel-orchestration .task-thread-plan-card .skills-panel-note, -#panel-orchestration .task-side-workbench-card .skills-panel-note { - display: none; -} - -#panel-orchestration .task-thread-plan-card .task-plan-summary-strip, -#panel-orchestration .task-side-workbench-card .task-detail-summary-strip { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin: 6px 0 0; -} - -#panel-orchestration .task-thread-plan-card .task-plan-summary-item, -#panel-orchestration .task-side-workbench-card .task-plan-summary-item { - min-width: auto; - padding: 4px 7px; - border: 1px solid rgba(148, 163, 184, 0.12); - border-radius: 999px; - background: rgba(248, 250, 252, 0.60); -} - -#panel-orchestration .task-thread-plan-card .task-plan-summary-label, -#panel-orchestration .task-side-workbench-card .task-plan-summary-label { - display: inline; - margin-right: 4px; - color: var(--color-text-muted); - font-size: 9px; -} - -#panel-orchestration .task-thread-plan-card .task-plan-summary-item strong, -#panel-orchestration .task-side-workbench-card .task-plan-summary-item strong { - display: inline; - color: var(--color-text-primary); - font-size: 11px; - font-weight: 700; -} - -#panel-orchestration .task-side-workbench-card .task-header-actions, -#panel-orchestration .task-side-workbench-card .task-detail-toolbar, -#panel-orchestration .task-side-workbench-card .task-workbench-tabs { - margin: 0; - padding: 0; - border: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-side-workbench-card .task-header-actions .btn-tool, -#panel-orchestration .task-side-workbench-card .task-detail-toolbar .btn-tool, -#panel-orchestration .task-side-workbench-card .task-workbench-tab { - min-height: 26px; - padding: 3px 7px; - border-radius: 999px; - font-size: 0.7rem; -} - -#panel-orchestration .task-side-workbench-card .task-workbench-panel { - margin-top: 8px; - padding: 0; - border: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-thread-run-summary { - display: flex; - align-items: center; - gap: 8px; - margin-top: 4px; - color: var(--color-text-secondary); - font-size: 0.82rem; - line-height: 1.45; -} - -#panel-orchestration .task-thread-run-summary-copy { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -#panel-orchestration .task-thread-run-details { - margin-top: 8px; - color: var(--color-text-secondary); -} - -#panel-orchestration .task-thread-run-details > summary { - width: fit-content; - cursor: pointer; - border-radius: 999px; - padding: 4px 9px; - background: rgba(248, 250, 252, 0.70); - color: var(--color-text-muted); - font-size: 0.72rem; - font-weight: 700; -} - -#panel-orchestration .task-thread-run-details:not([open]) { - margin-bottom: 0; -} - -#panel-orchestration .task-thread-run-details[open] > summary { - margin-bottom: 8px; -} - -#panel-orchestration .task-thread-detail-actions { - justify-content: flex-start; - margin-bottom: 8px; -} - -#panel-orchestration .task-thread-plan-details .task-plan-summary-strip { - margin-top: 0; -} - -#panel-orchestration .task-side-workbench-card .task-runtime-list, -#panel-orchestration .task-side-workbench-card .task-node-list { - max-height: none; - gap: 6px; - padding-right: 0; - overflow: visible; -} - -#panel-orchestration .task-side-workbench-card .task-node-card, -#panel-orchestration .task-side-workbench-card .task-runtime-item, -#panel-orchestration .task-side-workbench-card .task-node-output-card { - padding: 7px 0; - border-width: 1px 0 0; - border-radius: 0; - background: transparent; - box-shadow: none; -} - -#panel-orchestration .task-side-workbench-card .task-node-output-card, -#panel-orchestration .task-side-workbench-card .task-log-block { - max-height: 120px; - overflow: auto; - border-radius: 10px; - background: rgba(15, 23, 42, 0.04); -} - -#panel-orchestration .task-thread-composer { - bottom: 20px; - background: rgba(255, 255, 255, 0.97); - box-shadow: 0 8px 26px rgba(15, 23, 42, 0.13); -} - -@media (max-width: 760px) { - #panel-orchestration { - padding-bottom: 72px; - } - - #panel-orchestration .task-chat-thread { - padding-bottom: 16px; - scroll-padding-bottom: 130px; - } - - #panel-orchestration .task-thread-message-card { - width: calc(100% - 10px); - margin-left: 0; - } - - #panel-orchestration .task-side-workbench-card .task-node-output-card, - #panel-orchestration .task-side-workbench-card .task-log-block { - max-height: 96px; - } - - #panel-orchestration .task-thread-composer { - bottom: calc(env(safe-area-inset-bottom, 0px) + 10px); - } -} - - -/* Workspace selector + records rail: project context belongs beside the chat, not inside it. */ -#panel-orchestration { - --task-orchestration-main-width: 1360px; - --task-orchestration-project-width: 260px; - --task-orchestration-records-width: 320px; -} - -#panel-orchestration .task-layout-grid, -#panel-orchestration .task-layout-grid-primary, -#panel-orchestration .task-layout-grid-secondary, -#panel-orchestration .task-quick-card { - max-width: var(--task-orchestration-main-width); - width: min(100%, var(--task-orchestration-main-width)); -} - -#panel-orchestration .task-quick-card { - display: grid; - grid-template-columns: var(--task-orchestration-project-width) minmax(0, 1fr) var(--task-orchestration-records-width); - align-items: start; - gap: 16px; -} - -#panel-orchestration .task-project-sidebar, -#panel-orchestration .task-quick-side-card { - position: sticky; - top: 84px; - align-self: start; - max-height: calc(100vh - 112px); - overflow: auto; - scrollbar-width: thin; -} - -#panel-orchestration .task-project-sidebar, -#panel-orchestration .task-quick-side-card > .selector-section, -#panel-orchestration .task-quick-side-card > details, -#panel-orchestration .task-provider-status-card { - border: 1px solid rgba(148, 163, 184, 0.16); - border-radius: 18px; - background: rgba(255, 255, 255, 0.62); - box-shadow: none; -} - -#panel-orchestration .task-project-sidebar { - display: flex; - flex-direction: column; - gap: 12px; - padding: 12px; -} - -#panel-orchestration .task-project-sidebar-head, -#panel-orchestration .task-session-inbox-head { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 10px; -} - -#panel-orchestration .task-project-sidebar .skills-panel-note { - margin-top: 2px; - font-size: 0.76rem; - line-height: 1.4; -} - -#panel-orchestration .task-project-list, -#panel-orchestration .task-session-inbox { - display: flex; - flex-direction: column; - gap: 7px; -} - -#panel-orchestration .task-project-item, -#panel-orchestration .task-session-inbox-item { - width: 100%; - min-width: 0; - border: 1px solid rgba(148, 163, 184, 0.14); - border-radius: 14px; - background: rgba(248, 250, 252, 0.58); - color: var(--color-text-primary); - text-align: left; - cursor: pointer; - transition: border-color 0.16s ease, background 0.16s ease, transform 0.16s ease; -} - -#panel-orchestration .task-project-item { - display: grid; - gap: 3px; - padding: 9px 10px; -} - -#panel-orchestration .task-project-item:hover, -#panel-orchestration .task-session-inbox-item:hover, -#panel-orchestration .task-project-item.active { - border-color: rgba(199, 116, 98, 0.34); - background: rgba(255, 255, 255, 0.86); -} - -#panel-orchestration .task-project-item.active { - box-shadow: inset 3px 0 0 rgba(199, 116, 98, 0.56); -} - -#panel-orchestration .task-project-item-title, -#panel-orchestration .task-session-inbox-title { - display: block; - min-width: 0; - overflow: hidden; - color: var(--color-text-primary); - font-size: 0.86rem; - font-weight: 800; - text-overflow: ellipsis; - white-space: nowrap; -} - -#panel-orchestration .task-project-item-meta, -#panel-orchestration .task-session-inbox-meta, -#panel-orchestration .task-project-item-stats { - display: block; - min-width: 0; - overflow: hidden; - color: var(--color-text-muted); - font-size: 0.72rem; - line-height: 1.35; - text-overflow: ellipsis; - white-space: nowrap; -} - -#panel-orchestration .task-project-new-session { - width: 100%; - justify-content: center; -} - -#panel-orchestration .task-session-inbox { - padding-top: 2px; -} - -#panel-orchestration .task-session-inbox-item { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - padding: 8px 9px; -} - -#panel-orchestration .task-session-inbox-main { - min-width: 0; -} - -#panel-orchestration .task-session-empty { - padding: 10px; - border-radius: 14px; - background: rgba(248, 250, 252, 0.52); -} - -#panel-orchestration .task-quick-main { - min-width: 0; -} - -#panel-orchestration .task-quick-side-card { - display: flex; - flex-direction: column; - gap: 10px; - width: auto; - margin: 0; - padding: 0; - border: 0; - background: transparent; -} - -#panel-orchestration .task-quick-side-card > .selector-section, -#panel-orchestration .task-quick-side-card > details, -#panel-orchestration .task-provider-status-card { - margin: 0; - padding: 12px; -} - -#panel-orchestration .task-side-workbench-card, -#panel-orchestration .task-side-settings-card { - max-height: none; -} - -#panel-orchestration .task-side-workbench-card .task-runtime-list, -#panel-orchestration .task-side-workbench-card .task-node-list { - max-height: 340px; - overflow: auto; -} - -#panel-orchestration .task-thread-composer { - width: min(700px, calc(100vw - 680px)); - min-width: 520px; -} - -@media (max-width: 1180px) { - #panel-orchestration { - --task-orchestration-main-width: 100%; - } - - #panel-orchestration .task-quick-card { - grid-template-columns: minmax(220px, 0.34fr) minmax(0, 0.66fr); - } - - #panel-orchestration .task-quick-side-card { - grid-column: 1 / -1; - position: static; - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - #panel-orchestration .task-project-sidebar { - position: sticky; - } - - #panel-orchestration .task-thread-composer { - width: min(680px, calc(100vw - 360px)); - min-width: 420px; - } -} - -@media (max-width: 760px) { - #panel-orchestration .task-quick-card, - #panel-orchestration .task-quick-side-card { - display: flex; - flex-direction: column; - } - - #panel-orchestration .task-project-sidebar, - #panel-orchestration .task-quick-side-card { - position: static; - max-height: none; - } - - #panel-orchestration .task-thread-composer { - right: auto; - bottom: 10px; - left: auto; - width: 100%; - min-width: 0; - transform: none; - } -} - -/* Web Agent cockpit pass: the orchestration tab is an agent workbench, not a hidden task form. */ -#panel-orchestration { - --task-orchestration-main-width: 1440px; - --task-orchestration-project-width: 270px; - --task-orchestration-records-width: 340px; - - padding-bottom: 40px; -} - -#panel-orchestration .task-hero-card { - display: block; - max-width: var(--task-orchestration-main-width); - margin: -2px auto 14px; - border-color: rgba(59, 130, 246, 0.12); - background: - radial-gradient(circle at 12% 10%, rgba(59, 130, 246, 0.08), transparent 26%), - linear-gradient(135deg, rgba(255, 255, 255, 0.92), rgba(248, 250, 252, 0.76)); -} - -#panel-orchestration .task-hero-card .task-hero-kicker, -#panel-orchestration .task-hero-card .task-hero-copy { - display: block; -} - -#panel-orchestration .task-quick-card { - grid-template-columns: var(--task-orchestration-project-width) minmax(0, 1fr) var(--task-orchestration-records-width); - gap: 18px; -} - -#panel-orchestration .task-project-sidebar, -#panel-orchestration .task-quick-side-card { - top: 92px; - max-height: calc(100vh - 120px); -} - -#panel-orchestration .task-agent-cockpit { - margin-bottom: 12px; - padding: 14px; - border: 1px solid rgba(59, 130, 246, 0.14); - border-radius: 20px; - background: - linear-gradient(135deg, rgba(255, 255, 255, 0.92), rgba(239, 246, 255, 0.54)), - var(--color-surface); - box-shadow: 0 14px 38px rgba(15, 23, 42, 0.07); -} - -#panel-orchestration .task-agent-cockpit-head { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 12px; -} - -#panel-orchestration .task-agent-title { - font-size: clamp(18px, 1.45vw, 24px); - line-height: 1.18; -} - -#panel-orchestration .task-agent-copy { - display: block; - margin-top: 6px; - max-width: 760px; - line-height: 1.5; -} - -#panel-orchestration .task-agent-surface-grid, -#panel-orchestration .task-agent-trace-grid { - display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 8px; - margin-top: 12px; -} - -#panel-orchestration .task-agent-surface-card, -#panel-orchestration .task-agent-trace-card { - min-width: 0; - padding: 10px; - border: 1px solid rgba(148, 163, 184, 0.16); - border-radius: 14px; - background: rgba(255, 255, 255, 0.72); -} - -#panel-orchestration .task-agent-surface-card span, -#panel-orchestration .task-agent-trace-card span { - display: block; - color: var(--color-text-muted); - font-size: 10px; - font-weight: 800; - letter-spacing: 0.06em; - text-transform: uppercase; -} - -#panel-orchestration .task-agent-surface-card strong, -#panel-orchestration .task-agent-trace-card strong { - display: block; - min-width: 0; - margin-top: 5px; - overflow: hidden; - color: var(--color-text-primary); - font-size: 12px; - font-weight: 800; - line-height: 1.35; - text-overflow: ellipsis; - white-space: nowrap; -} - -#panel-orchestration .task-agent-trace-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - margin: 10px 0 2px; -} - -#panel-orchestration .task-agent-trace-card { - padding: 8px 9px; - background: rgba(248, 250, 252, 0.72); -} - -#panel-orchestration .task-agent-trace-card strong { - font-size: 18px; -} - -#panel-orchestration .task-chat-panel { - min-height: calc(100vh - 330px); - border-radius: 22px; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(248, 250, 252, 0.66)), - var(--color-surface); -} - -#panel-orchestration .task-chat-thread { - padding-bottom: 18px; - scroll-padding-bottom: 120px; -} - -#panel-orchestration .task-thread-composer { - grid-template-columns: minmax(0, 1fr) auto; - right: auto; - bottom: 14px; - left: auto; - width: min(100%, 760px); - min-width: 0; - margin-top: 10px; - transform: none; - align-self: center; - border-color: rgba(59, 130, 246, 0.16); - border-radius: 18px; -} - -#panel-orchestration .task-chat-action-buttons { - justify-content: center; -} - -#panel-orchestration .task-chat-action-buttons .btn-tool { - min-width: 168px; -} - -#panel-orchestration .task-chat-action-buttons .btn-primary { - min-width: 168px; -} - -#panel-orchestration .task-chat-primary-button { - border-color: #1D4ED8; - background: #2563EB; - color: #FFFFFF; - box-shadow: 0 10px 22px rgba(37, 99, 235, 0.24); -} - -#panel-orchestration .task-chat-primary-button:hover:not(:disabled), -#panel-orchestration .task-chat-primary-button:focus-visible:not(:disabled) { - border-color: #1E40AF; - background: #1D4ED8; - color: #FFFFFF; -} - -#panel-orchestration .task-side-workbench-card .task-thread-run-details { - margin-top: 10px; -} - -#panel-orchestration .task-side-workbench-card .task-thread-run-details > summary { - background: rgba(239, 246, 255, 0.76); - color: #1D4ED8; -} - -#panel-orchestration .task-side-workbench-card .task-workbench-panel, -#panel-orchestration .task-side-workbench-card .task-runtime-list, -#panel-orchestration .task-side-workbench-card .task-node-list { - max-height: 360px; - overflow: auto; -} - -#panel-orchestration .task-side-settings-card { - border-style: dashed; -} - -@media (max-width: 1180px) { - #panel-orchestration .task-quick-card { - grid-template-columns: minmax(220px, 0.35fr) minmax(0, 0.65fr); - } - - #panel-orchestration .task-agent-surface-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - #panel-orchestration .task-thread-composer { - width: min(100%, 720px); - min-width: 0; - } -} - -@media (max-width: 760px) { - #panel-orchestration { - padding-bottom: 72px; - } - - #panel-orchestration .task-hero-card { - margin-bottom: 10px; - padding: 12px; - } - - #panel-orchestration .task-agent-cockpit { - padding: 12px; - border-radius: 18px; - } - - #panel-orchestration .task-agent-cockpit-head { - flex-direction: column; - align-items: stretch; - } - - #panel-orchestration .task-agent-surface-grid, - #panel-orchestration .task-agent-trace-grid { - grid-template-columns: 1fr; - } - - #panel-orchestration .task-chat-thread { - padding-bottom: 16px; - scroll-padding-bottom: 130px; - } - - #panel-orchestration .task-thread-composer { - right: auto; - bottom: 10px; - left: auto; - width: 100%; - min-width: 0; - transform: none; - } - - #panel-orchestration .task-chat-action-buttons { - flex-direction: column; - gap: 6px; - } - - #panel-orchestration .task-chat-action-buttons .btn-tool { - width: 100%; - min-width: 0; + #panel-orchestration .message-list, + #panel-orchestration .chat-input { + padding-inline: 12px; } }