@coralai/sps-cli 0.63.5 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README-CN.md +2 -0
- package/README.md +2 -0
- package/dist/commands/agentCommand.d.ts.map +1 -1
- package/dist/commands/agentCommand.js +4 -3
- package/dist/commands/agentCommand.js.map +1 -1
- package/dist/commands/agentRenderer.js +3 -3
- package/dist/commands/agentRenderer.js.map +1 -1
- package/dist/commands/cardDashboard.d.ts.map +1 -1
- package/dist/commands/cardDashboard.js +2 -2
- package/dist/commands/cardDashboard.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +0 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +15 -15
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/openaiAgent.d.ts +3 -0
- package/dist/commands/openaiAgent.d.ts.map +1 -0
- package/dist/commands/openaiAgent.js +81 -0
- package/dist/commands/openaiAgent.js.map +1 -0
- package/dist/commands/pipelineRunner.js.map +1 -1
- package/dist/commands/pipelineTick.js +1 -1
- package/dist/commands/pipelineTick.js.map +1 -1
- package/dist/commands/projectInit.d.ts +11 -1
- package/dist/commands/projectInit.d.ts.map +1 -1
- package/dist/commands/projectInit.js +38 -7
- package/dist/commands/projectInit.js.map +1 -1
- package/dist/commands/prune.d.ts +6 -0
- package/dist/commands/prune.d.ts.map +1 -0
- package/dist/commands/prune.js +87 -0
- package/dist/commands/prune.js.map +1 -0
- package/dist/commands/qaTick.js +1 -1
- package/dist/commands/qaTick.js.map +1 -1
- package/dist/commands/reset.d.ts.map +1 -1
- package/dist/commands/reset.js +3 -2
- package/dist/commands/reset.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +8 -1
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skillCommand.d.ts.map +1 -1
- package/dist/commands/skillCommand.js +2 -3
- package/dist/commands/skillCommand.js.map +1 -1
- package/dist/commands/status.js +2 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/stop.js +3 -3
- package/dist/commands/stop.js.map +1 -1
- package/dist/commands/tick.d.ts.map +1 -1
- package/dist/commands/tick.js +5 -2
- package/dist/commands/tick.js.map +1 -1
- package/dist/commands/workerDashboard.d.ts.map +1 -1
- package/dist/commands/workerDashboard.js +27 -26
- package/dist/commands/workerDashboard.js.map +1 -1
- package/dist/commands/workerLaunch.js +1 -1
- package/dist/commands/workerLaunch.js.map +1 -1
- package/dist/console/routes/chat.d.ts +18 -1
- package/dist/console/routes/chat.d.ts.map +1 -1
- package/dist/console/routes/chat.js +529 -40
- package/dist/console/routes/chat.js.map +1 -1
- package/dist/console/routes/fs.d.ts.map +1 -1
- package/dist/console/routes/fs.js +2 -1
- package/dist/console/routes/fs.js.map +1 -1
- package/dist/console/routes/logs.d.ts.map +1 -1
- package/dist/console/routes/logs.js +17 -5
- package/dist/console/routes/logs.js.map +1 -1
- package/dist/console/routes/projects.d.ts.map +1 -1
- package/dist/console/routes/projects.js +11 -2
- package/dist/console/routes/projects.js.map +1 -1
- package/dist/console/routes/workers.js +3 -3
- package/dist/console/routes/workers.js.map +1 -1
- package/dist/console-assets/assets/{ShowcasePage-BWHyDQhw.js → ShowcasePage-DFRO5bAO.js} +1 -1
- package/dist/console-assets/assets/{index-rQ_2k-G9.css → index-DZ28qAcd.css} +1 -1
- package/dist/console-assets/assets/{index-DH_TQHY4.js → index-De5GjRjY.js} +220 -215
- package/dist/console-assets/index.html +2 -2
- package/dist/core/agents/AgentBackend.d.ts +2 -2
- package/dist/core/agents/AgentBackend.d.ts.map +1 -1
- package/dist/core/agents/AgentBackend.js.map +1 -1
- package/dist/core/agents/DaemonBackend.d.ts +12 -2
- package/dist/core/agents/DaemonBackend.d.ts.map +1 -1
- package/dist/core/agents/DaemonBackend.js +68 -20
- package/dist/core/agents/DaemonBackend.js.map +1 -1
- package/dist/core/agents/resolveBackend.d.ts +4 -1
- package/dist/core/agents/resolveBackend.d.ts.map +1 -1
- package/dist/core/agents/resolveBackend.js +31 -1
- package/dist/core/agents/resolveBackend.js.map +1 -1
- package/dist/core/config.d.ts +5 -8
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +3 -9
- package/dist/core/config.js.map +1 -1
- package/dist/core/intel/agentsConfig.d.ts +9 -0
- package/dist/core/intel/agentsConfig.d.ts.map +1 -1
- package/dist/core/intel/agentsConfig.js +42 -0
- package/dist/core/intel/agentsConfig.js.map +1 -1
- package/dist/core/intel/types.d.ts +1 -0
- package/dist/core/intel/types.d.ts.map +1 -1
- package/dist/core/markerFile.d.ts.map +1 -1
- package/dist/core/markerFile.js +2 -2
- package/dist/core/markerFile.js.map +1 -1
- package/dist/core/openaiWorkerLog.d.ts +7 -0
- package/dist/core/openaiWorkerLog.d.ts.map +1 -0
- package/dist/core/openaiWorkerLog.js +98 -0
- package/dist/core/openaiWorkerLog.js.map +1 -0
- package/dist/core/paths.d.ts +1 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +9 -7
- package/dist/core/paths.js.map +1 -1
- package/dist/core/pipelineConfig.js +7 -7
- package/dist/core/pipelineConfig.js.map +1 -1
- package/dist/core/pipelineSession.d.ts +3 -1
- package/dist/core/pipelineSession.d.ts.map +1 -1
- package/dist/core/pipelineSession.js +8 -2
- package/dist/core/pipelineSession.js.map +1 -1
- package/dist/core/processInspect.d.ts +5 -0
- package/dist/core/processInspect.d.ts.map +1 -1
- package/dist/core/processInspect.js +41 -11
- package/dist/core/processInspect.js.map +1 -1
- package/dist/core/projectPipelineAdapter.d.ts.map +1 -1
- package/dist/core/projectPipelineAdapter.js +4 -4
- package/dist/core/projectPipelineAdapter.js.map +1 -1
- package/dist/core/runtimeSnapshot.d.ts +2 -2
- package/dist/core/runtimeSnapshot.d.ts.map +1 -1
- package/dist/core/runtimeSnapshot.js +2 -2
- package/dist/core/runtimeSnapshot.js.map +1 -1
- package/dist/core/runtimeStore.d.ts +12 -12
- package/dist/core/runtimeStore.d.ts.map +1 -1
- package/dist/core/runtimeStore.js +16 -16
- package/dist/core/runtimeStore.js.map +1 -1
- package/dist/core/runtimeTypes.d.ts +109 -24
- package/dist/core/runtimeTypes.d.ts.map +1 -1
- package/dist/core/runtimeTypes.js +1 -1
- package/dist/core/sessionCleanup.d.ts +1 -1
- package/dist/core/sessionCleanup.d.ts.map +1 -1
- package/dist/core/sessionCleanup.js +2 -2
- package/dist/core/sessionCleanup.js.map +1 -1
- package/dist/core/sessionContext.d.ts +2 -2
- package/dist/core/sessionContext.d.ts.map +1 -1
- package/dist/core/sessionContext.js +1 -1
- package/dist/core/sessionContext.js.map +1 -1
- package/dist/core/sessionLiveness.d.ts +7 -6
- package/dist/core/sessionLiveness.d.ts.map +1 -1
- package/dist/core/sessionLiveness.js +3 -4
- package/dist/core/sessionLiveness.js.map +1 -1
- package/dist/core/state.d.ts +13 -12
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/state.js +9 -1
- package/dist/core/state.js.map +1 -1
- package/dist/core/workerRuntimeSummary.js +2 -2
- package/dist/core/workerRuntimeSummary.js.map +1 -1
- package/dist/core/workspacePaths.d.ts +22 -0
- package/dist/core/workspacePaths.d.ts.map +1 -0
- package/dist/core/workspacePaths.js +73 -0
- package/dist/core/workspacePaths.js.map +1 -0
- package/dist/daemon/daemonClient.d.ts +19 -22
- package/dist/daemon/daemonClient.d.ts.map +1 -1
- package/dist/daemon/daemonClient.js +82 -2
- package/dist/daemon/daemonClient.js.map +1 -1
- package/dist/daemon/sessionDaemon.d.ts +52 -7
- package/dist/daemon/sessionDaemon.d.ts.map +1 -1
- package/dist/daemon/sessionDaemon.js +40 -24
- package/dist/daemon/sessionDaemon.js.map +1 -1
- package/dist/engines/EventHandler.js +1 -1
- package/dist/engines/EventHandler.js.map +1 -1
- package/dist/engines/MonitorEngine.d.ts +2 -2
- package/dist/engines/MonitorEngine.d.ts.map +1 -1
- package/dist/engines/MonitorEngine.js +15 -17
- package/dist/engines/MonitorEngine.js.map +1 -1
- package/dist/engines/StageEngine.d.ts +5 -3
- package/dist/engines/StageEngine.d.ts.map +1 -1
- package/dist/engines/StageEngine.js +33 -18
- package/dist/engines/StageEngine.js.map +1 -1
- package/dist/main.js +21 -1
- package/dist/main.js.map +1 -1
- package/dist/manager/makeBackendFactory.d.ts +11 -4
- package/dist/manager/makeBackendFactory.d.ts.map +1 -1
- package/dist/manager/makeBackendFactory.js +28 -15
- package/dist/manager/makeBackendFactory.js.map +1 -1
- package/dist/manager/runtime-coordinator.js.map +1 -1
- package/dist/manager/supervisor.d.ts +7 -7
- package/dist/manager/supervisor.d.ts.map +1 -1
- package/dist/manager/supervisor.js +7 -7
- package/dist/manager/supervisor.js.map +1 -1
- package/dist/manager/worker-manager-impl.d.ts +4 -4
- package/dist/manager/worker-manager-impl.d.ts.map +1 -1
- package/dist/manager/worker-manager-impl.js +56 -24
- package/dist/manager/worker-manager-impl.js.map +1 -1
- package/dist/manager/worker-manager.d.ts +6 -6
- package/dist/manager/worker-manager.d.ts.map +1 -1
- package/dist/openai-agent/agentFactory.d.ts +10 -0
- package/dist/openai-agent/agentFactory.d.ts.map +1 -0
- package/dist/openai-agent/agentFactory.js +26 -0
- package/dist/openai-agent/agentFactory.js.map +1 -0
- package/dist/openai-agent/eventMap.d.ts +11 -0
- package/dist/openai-agent/eventMap.d.ts.map +1 -0
- package/dist/openai-agent/eventMap.js +191 -0
- package/dist/openai-agent/eventMap.js.map +1 -0
- package/dist/openai-agent/hooks.d.ts +13 -0
- package/dist/openai-agent/hooks.d.ts.map +1 -0
- package/dist/openai-agent/hooks.js +63 -0
- package/dist/openai-agent/hooks.js.map +1 -0
- package/dist/openai-agent/instructions.d.ts +3 -0
- package/dist/openai-agent/instructions.d.ts.map +1 -0
- package/dist/openai-agent/instructions.js +63 -0
- package/dist/openai-agent/instructions.js.map +1 -0
- package/dist/openai-agent/interactions/broker.d.ts +23 -0
- package/dist/openai-agent/interactions/broker.d.ts.map +1 -0
- package/dist/openai-agent/interactions/broker.js +316 -0
- package/dist/openai-agent/interactions/broker.js.map +1 -0
- package/dist/openai-agent/mcp/managedMcp.d.ts +31 -0
- package/dist/openai-agent/mcp/managedMcp.d.ts.map +1 -0
- package/dist/openai-agent/mcp/managedMcp.js +95 -0
- package/dist/openai-agent/mcp/managedMcp.js.map +1 -0
- package/dist/openai-agent/protocolWriter.d.ts +29 -0
- package/dist/openai-agent/protocolWriter.d.ts.map +1 -0
- package/dist/openai-agent/protocolWriter.js +74 -0
- package/dist/openai-agent/protocolWriter.js.map +1 -0
- package/dist/openai-agent/providerCapabilities.d.ts +31 -0
- package/dist/openai-agent/providerCapabilities.d.ts.map +1 -0
- package/dist/openai-agent/providerCapabilities.js +49 -0
- package/dist/openai-agent/providerCapabilities.js.map +1 -0
- package/dist/openai-agent/providerFactory.d.ts +18 -0
- package/dist/openai-agent/providerFactory.d.ts.map +1 -0
- package/dist/openai-agent/providerFactory.js +38 -0
- package/dist/openai-agent/providerFactory.js.map +1 -0
- package/dist/openai-agent/request.d.ts +22 -0
- package/dist/openai-agent/request.d.ts.map +1 -0
- package/dist/openai-agent/request.js +89 -0
- package/dist/openai-agent/request.js.map +1 -0
- package/dist/openai-agent/runWorker.d.ts +25 -0
- package/dist/openai-agent/runWorker.d.ts.map +1 -0
- package/dist/openai-agent/runWorker.js +635 -0
- package/dist/openai-agent/runWorker.js.map +1 -0
- package/dist/openai-agent/sandbox/execution.d.ts +36 -0
- package/dist/openai-agent/sandbox/execution.d.ts.map +1 -0
- package/dist/openai-agent/sandbox/execution.js +239 -0
- package/dist/openai-agent/sandbox/execution.js.map +1 -0
- package/dist/openai-agent/sandbox/productionDocker.d.ts +17 -0
- package/dist/openai-agent/sandbox/productionDocker.d.ts.map +1 -0
- package/dist/openai-agent/sandbox/productionDocker.js +76 -0
- package/dist/openai-agent/sandbox/productionDocker.js.map +1 -0
- package/dist/openai-agent/sdkContract.d.ts +18 -0
- package/dist/openai-agent/sdkContract.d.ts.map +1 -0
- package/dist/openai-agent/sdkContract.js +2 -0
- package/dist/openai-agent/sdkContract.js.map +1 -0
- package/dist/openai-agent/storage/atomic.d.ts +10 -0
- package/dist/openai-agent/storage/atomic.d.ts.map +1 -0
- package/dist/openai-agent/storage/atomic.js +112 -0
- package/dist/openai-agent/storage/atomic.js.map +1 -0
- package/dist/openai-agent/storage/checkpoint.d.ts +38 -0
- package/dist/openai-agent/storage/checkpoint.d.ts.map +1 -0
- package/dist/openai-agent/storage/checkpoint.js +141 -0
- package/dist/openai-agent/storage/checkpoint.js.map +1 -0
- package/dist/openai-agent/storage/errors.d.ts +8 -0
- package/dist/openai-agent/storage/errors.d.ts.map +1 -0
- package/dist/openai-agent/storage/errors.js +11 -0
- package/dist/openai-agent/storage/errors.js.map +1 -0
- package/dist/openai-agent/storage/index.d.ts +12 -0
- package/dist/openai-agent/storage/index.d.ts.map +1 -0
- package/dist/openai-agent/storage/index.js +12 -0
- package/dist/openai-agent/storage/index.js.map +1 -0
- package/dist/openai-agent/storage/interaction.d.ts +45 -0
- package/dist/openai-agent/storage/interaction.d.ts.map +1 -0
- package/dist/openai-agent/storage/interaction.js +372 -0
- package/dist/openai-agent/storage/interaction.js.map +1 -0
- package/dist/openai-agent/storage/lock.d.ts +13 -0
- package/dist/openai-agent/storage/lock.d.ts.map +1 -0
- package/dist/openai-agent/storage/lock.js +95 -0
- package/dist/openai-agent/storage/lock.js.map +1 -0
- package/dist/openai-agent/storage/metrics.d.ts +34 -0
- package/dist/openai-agent/storage/metrics.d.ts.map +1 -0
- package/dist/openai-agent/storage/metrics.js +74 -0
- package/dist/openai-agent/storage/metrics.js.map +1 -0
- package/dist/openai-agent/storage/output.d.ts +22 -0
- package/dist/openai-agent/storage/output.d.ts.map +1 -0
- package/dist/openai-agent/storage/output.js +175 -0
- package/dist/openai-agent/storage/output.js.map +1 -0
- package/dist/openai-agent/storage/session.d.ts +38 -0
- package/dist/openai-agent/storage/session.d.ts.map +1 -0
- package/dist/openai-agent/storage/session.js +216 -0
- package/dist/openai-agent/storage/session.js.map +1 -0
- package/dist/openai-agent/storage/toolLedger.d.ts +64 -0
- package/dist/openai-agent/storage/toolLedger.d.ts.map +1 -0
- package/dist/openai-agent/storage/toolLedger.js +281 -0
- package/dist/openai-agent/storage/toolLedger.js.map +1 -0
- package/dist/openai-agent/storage/workerStorage.d.ts +21 -0
- package/dist/openai-agent/storage/workerStorage.d.ts.map +1 -0
- package/dist/openai-agent/storage/workerStorage.js +38 -0
- package/dist/openai-agent/storage/workerStorage.js.map +1 -0
- package/dist/openai-agent/storage/workspace.d.ts +17 -0
- package/dist/openai-agent/storage/workspace.d.ts.map +1 -0
- package/dist/openai-agent/storage/workspace.js +67 -0
- package/dist/openai-agent/storage/workspace.js.map +1 -0
- package/dist/openai-agent/testHelpers.d.ts +9 -0
- package/dist/openai-agent/testHelpers.d.ts.map +1 -0
- package/dist/openai-agent/testHelpers.js +35 -0
- package/dist/openai-agent/testHelpers.js.map +1 -0
- package/dist/openai-agent/tools/ledgerTools.d.ts +12 -0
- package/dist/openai-agent/tools/ledgerTools.d.ts.map +1 -0
- package/dist/openai-agent/tools/ledgerTools.js +151 -0
- package/dist/openai-agent/tools/ledgerTools.js.map +1 -0
- package/dist/providers/MarkdownTaskBackend.d.ts.map +1 -1
- package/dist/providers/MarkdownTaskBackend.js +2 -2
- package/dist/providers/MarkdownTaskBackend.js.map +1 -1
- package/dist/providers/RuntimeSessionRuntime.d.ts +35 -15
- package/dist/providers/RuntimeSessionRuntime.d.ts.map +1 -1
- package/dist/providers/RuntimeSessionRuntime.js +239 -22
- package/dist/providers/RuntimeSessionRuntime.js.map +1 -1
- package/dist/providers/llm/chatTools.d.ts.map +1 -1
- package/dist/providers/llm/chatTools.js +3 -3
- package/dist/providers/llm/chatTools.js.map +1 -1
- package/dist/providers/llm/codexAuth.d.ts +6 -1
- package/dist/providers/llm/codexAuth.d.ts.map +1 -1
- package/dist/providers/llm/codexAuth.js +45 -9
- package/dist/providers/llm/codexAuth.js.map +1 -1
- package/dist/providers/llm/codexModel.d.ts +4 -1
- package/dist/providers/llm/codexModel.d.ts.map +1 -1
- package/dist/providers/llm/codexModel.js +13 -3
- package/dist/providers/llm/codexModel.js.map +1 -1
- package/dist/providers/llm/localSubscription.d.ts +1 -1
- package/dist/providers/llm/localSubscription.d.ts.map +1 -1
- package/dist/providers/llm/localSubscription.js +2 -2
- package/dist/providers/llm/localSubscription.js.map +1 -1
- package/dist/providers/runtimeEventMap.d.ts +54 -5
- package/dist/providers/runtimeEventMap.d.ts.map +1 -1
- package/dist/providers/runtimeEventMap.js +110 -11
- package/dist/providers/runtimeEventMap.js.map +1 -1
- package/dist/runtime/agentd/client.d.ts +29 -0
- package/dist/runtime/agentd/client.d.ts.map +1 -0
- package/dist/runtime/agentd/client.js +131 -0
- package/dist/runtime/agentd/client.js.map +1 -0
- package/dist/runtime/agentd/main.d.ts +10 -0
- package/dist/runtime/agentd/main.d.ts.map +1 -0
- package/dist/runtime/agentd/main.js +49 -0
- package/dist/runtime/agentd/main.js.map +1 -0
- package/dist/runtime/agentd/protocol.d.ts +74 -0
- package/dist/runtime/agentd/protocol.d.ts.map +1 -0
- package/dist/runtime/agentd/protocol.js +21 -0
- package/dist/runtime/agentd/protocol.js.map +1 -0
- package/dist/runtime/agentd/server.d.ts +15 -0
- package/dist/runtime/agentd/server.d.ts.map +1 -0
- package/dist/runtime/agentd/server.js +116 -0
- package/dist/runtime/agentd/server.js.map +1 -0
- package/dist/runtime/backends/claude/ClaudeBackend.d.ts +155 -0
- package/dist/runtime/backends/claude/ClaudeBackend.d.ts.map +1 -0
- package/dist/runtime/backends/claude/ClaudeBackend.js +398 -0
- package/dist/runtime/backends/claude/ClaudeBackend.js.map +1 -0
- package/dist/runtime/backends/claude/ClaudeSessions.d.ts +23 -0
- package/dist/runtime/backends/claude/ClaudeSessions.d.ts.map +1 -0
- package/dist/runtime/backends/claude/ClaudeSessions.js +45 -0
- package/dist/runtime/backends/claude/ClaudeSessions.js.map +1 -0
- package/dist/runtime/backends/claude/inprocTools.d.ts +17 -0
- package/dist/runtime/backends/claude/inprocTools.d.ts.map +1 -0
- package/dist/runtime/backends/claude/inprocTools.js +14 -0
- package/dist/runtime/backends/claude/inprocTools.js.map +1 -0
- package/dist/runtime/backends/process/ExternalProcessBackend.d.ts +83 -0
- package/dist/runtime/backends/process/ExternalProcessBackend.d.ts.map +1 -0
- package/dist/runtime/backends/process/ExternalProcessBackend.js +642 -0
- package/dist/runtime/backends/process/ExternalProcessBackend.js.map +1 -0
- package/dist/runtime/contract/AgentBackend.d.ts +199 -0
- package/dist/runtime/contract/AgentBackend.d.ts.map +1 -0
- package/dist/runtime/contract/AgentBackend.js +2 -0
- package/dist/runtime/contract/AgentBackend.js.map +1 -0
- package/dist/runtime/contract/events.d.ts +96 -0
- package/dist/runtime/contract/events.d.ts.map +1 -0
- package/dist/runtime/contract/events.js +2 -0
- package/dist/runtime/contract/events.js.map +1 -0
- package/dist/runtime/contract/index.d.ts +13 -0
- package/dist/runtime/contract/index.d.ts.map +1 -0
- package/dist/runtime/contract/index.js +2 -0
- package/dist/runtime/contract/index.js.map +1 -0
- package/dist/runtime/contract/lifecycle.d.ts +26 -0
- package/dist/runtime/contract/lifecycle.d.ts.map +1 -0
- package/dist/runtime/contract/lifecycle.js +6 -0
- package/dist/runtime/contract/lifecycle.js.map +1 -0
- package/dist/runtime/contract/processProtocol.d.ts +263 -0
- package/dist/runtime/contract/processProtocol.d.ts.map +1 -0
- package/dist/runtime/contract/processProtocol.js +779 -0
- package/dist/runtime/contract/processProtocol.js.map +1 -0
- package/dist/runtime/contract/service.d.ts +85 -0
- package/dist/runtime/contract/service.d.ts.map +1 -0
- package/dist/runtime/contract/service.js +2 -0
- package/dist/runtime/contract/service.js.map +1 -0
- package/dist/runtime/contract/versioning.d.ts +44 -0
- package/dist/runtime/contract/versioning.d.ts.map +1 -0
- package/dist/runtime/contract/versioning.js +10 -0
- package/dist/runtime/contract/versioning.js.map +1 -0
- package/dist/runtime/index.d.ts +21 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +26 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/runtime.d.ts +21 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/runtime.js +34 -0
- package/dist/runtime/runtime.js.map +1 -0
- package/dist/runtime/service/AgentRuntime.d.ts +60 -0
- package/dist/runtime/service/AgentRuntime.d.ts.map +1 -0
- package/dist/runtime/service/AgentRuntime.js +396 -0
- package/dist/runtime/service/AgentRuntime.js.map +1 -0
- package/dist/runtime/service/FileRecordStore.d.ts +12 -0
- package/dist/runtime/service/FileRecordStore.d.ts.map +1 -0
- package/dist/runtime/service/FileRecordStore.js +48 -0
- package/dist/runtime/service/FileRecordStore.js.map +1 -0
- package/dist/runtime/service/backendFactory.d.ts +8 -0
- package/dist/runtime/service/backendFactory.d.ts.map +1 -0
- package/dist/runtime/service/backendFactory.js +20 -0
- package/dist/runtime/service/backendFactory.js.map +1 -0
- package/dist/runtime/stub/NoopBackend.d.ts +29 -0
- package/dist/runtime/stub/NoopBackend.d.ts.map +1 -0
- package/dist/runtime/stub/NoopBackend.js +56 -0
- package/dist/runtime/stub/NoopBackend.js.map +1 -0
- package/dist/runtime/stub/NoopService.d.ts +23 -0
- package/dist/runtime/stub/NoopService.d.ts.map +1 -0
- package/dist/runtime/stub/NoopService.js +136 -0
- package/dist/runtime/stub/NoopService.js.map +1 -0
- package/dist/runtime/stub/index.d.ts +8 -0
- package/dist/runtime/stub/index.d.ts.map +1 -0
- package/dist/runtime/stub/index.js +8 -0
- package/dist/runtime/stub/index.js.map +1 -0
- package/dist/runtime/versioning/VersionManager.d.ts +31 -0
- package/dist/runtime/versioning/VersionManager.d.ts.map +1 -0
- package/dist/runtime/versioning/VersionManager.js +142 -0
- package/dist/runtime/versioning/VersionManager.js.map +1 -0
- package/dist/services/ChatService.d.ts +11 -0
- package/dist/services/ChatService.d.ts.map +1 -1
- package/dist/services/ChatService.js +35 -5
- package/dist/services/ChatService.js.map +1 -1
- package/dist/services/LogService.d.ts +10 -4
- package/dist/services/LogService.d.ts.map +1 -1
- package/dist/services/LogService.js +26 -5
- package/dist/services/LogService.js.map +1 -1
- package/dist/services/ProjectService.d.ts +27 -0
- package/dist/services/ProjectService.d.ts.map +1 -1
- package/dist/services/ProjectService.js +74 -14
- package/dist/services/ProjectService.js.map +1 -1
- package/dist/services/WorkerService.d.ts +1 -0
- package/dist/services/WorkerService.d.ts.map +1 -1
- package/dist/services/WorkerService.js +72 -0
- package/dist/services/WorkerService.js.map +1 -1
- package/dist/services/executors.d.ts +1 -0
- package/dist/services/executors.d.ts.map +1 -1
- package/dist/services/executors.js +9 -1
- package/dist/services/executors.js.map +1 -1
- package/dist/services/promptPreview.d.ts.map +1 -1
- package/dist/services/promptPreview.js +4 -3
- package/dist/services/promptPreview.js.map +1 -1
- package/dist/shared/runtimePaths.d.ts +4 -0
- package/dist/shared/runtimePaths.d.ts.map +1 -1
- package/dist/shared/runtimePaths.js +8 -0
- package/dist/shared/runtimePaths.js.map +1 -1
- package/dist/shared/runtimeSchemas.d.ts +6 -2
- package/dist/shared/runtimeSchemas.d.ts.map +1 -1
- package/dist/shared/runtimeSchemas.js +3 -2
- package/dist/shared/runtimeSchemas.js.map +1 -1
- package/docs/openai-daemon-agent.md +144 -0
- package/package.json +15 -9
- package/project-template/.claude/hooks/openai/on-start.sh +6 -0
- package/project-template/.claude/hooks/openai/on-stop.sh +6 -0
|
@@ -32,9 +32,11 @@ import { resolveEligibleSkillNames, SkillsManager } from '../../core/skills/inde
|
|
|
32
32
|
import { chatTools } from '../../providers/llm/chatTools.js';
|
|
33
33
|
import { skillTools } from '../../providers/llm/skillTools.js';
|
|
34
34
|
import { createReviewerModel } from '../../providers/llm/modelFactory.js';
|
|
35
|
+
import { getAgentProvider } from '../../providers/llm/providers.js';
|
|
35
36
|
import { workerTools } from '../../providers/llm/workerTools.js';
|
|
36
37
|
import { toHttpStatus, toProblemJson } from '../../shared/errors.js';
|
|
37
|
-
import { chatAttachmentsDirFor, chatSessionsDir,
|
|
38
|
+
import { chatAttachmentsDirFor, chatSessionsDir, chatWorkspacesRoot } from '../../shared/runtimePaths.js';
|
|
39
|
+
import { workspacesRoot } from '../../core/workspacePaths.js';
|
|
38
40
|
import { listArtifacts } from '../../shared/artifacts.js';
|
|
39
41
|
import { sendResult } from '../lib/resultToJson.js';
|
|
40
42
|
const MAX_CONCURRENT_SESSIONS = 5;
|
|
@@ -168,6 +170,35 @@ function endTurn(sessionId) {
|
|
|
168
170
|
clearInterval(t.heartbeat);
|
|
169
171
|
activeStreams.delete(sessionId);
|
|
170
172
|
}
|
|
173
|
+
function appendInteractionBlock(sessionId, assistantId, blocks, event) {
|
|
174
|
+
const block = {
|
|
175
|
+
type: 'interaction',
|
|
176
|
+
id: event.interactionId,
|
|
177
|
+
kind: event.kind,
|
|
178
|
+
title: event.title,
|
|
179
|
+
schema: event.schema,
|
|
180
|
+
revision: event.revision ?? 1,
|
|
181
|
+
status: 'pending',
|
|
182
|
+
};
|
|
183
|
+
blocks.push(block);
|
|
184
|
+
chatBus.emit('chat.message.chunk.interaction', {
|
|
185
|
+
sessionId,
|
|
186
|
+
assistantId,
|
|
187
|
+
turnId: assistantId,
|
|
188
|
+
seq: bumpSeq(sessionId),
|
|
189
|
+
...block,
|
|
190
|
+
});
|
|
191
|
+
return block;
|
|
192
|
+
}
|
|
193
|
+
function findInteractionBlock(session, interactionId) {
|
|
194
|
+
for (let index = session.messages.length - 1; index >= 0; index--) {
|
|
195
|
+
const message = session.messages[index];
|
|
196
|
+
const block = message.blocks?.find((candidate) => candidate.type === 'interaction' && candidate.id === interactionId);
|
|
197
|
+
if (block)
|
|
198
|
+
return { message, block };
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
171
202
|
/** 取"最后一轮"状态:优先持久 lastTurn;旧文件无则从末条 assistant/error 消息推导(按已结束)。 */
|
|
172
203
|
function deriveLastTurn(s) {
|
|
173
204
|
if (s.lastTurn)
|
|
@@ -207,13 +238,17 @@ function reconcileStaleTurns(log) {
|
|
|
207
238
|
/* non-fatal */
|
|
208
239
|
}
|
|
209
240
|
}
|
|
210
|
-
async function streamAssistantResponse(sessionId, assistantId, userContent, log, attachments) {
|
|
211
|
-
|
|
212
|
-
|
|
241
|
+
async function streamAssistantResponse(sessionId, assistantId, userContent, log, attachments, dependencies = {}) {
|
|
242
|
+
const selected = readSession(sessionId);
|
|
243
|
+
// 旧 OpenAI 会话没有 agentMode,继续走历史 SDK 会话文件;只有显式 daemon 的
|
|
244
|
+
// 新会话才迁入统一宿主,避免升级后丢掉既有上下文。
|
|
245
|
+
if (selected?.agentKind === 'openai' &&
|
|
246
|
+
(selected.agentMode ?? 'sdk') === 'sdk') {
|
|
213
247
|
await streamOpenaiChat(sessionId, assistantId, userContent, log);
|
|
214
248
|
return;
|
|
215
249
|
}
|
|
216
|
-
|
|
250
|
+
const backend = selected?.agentKind === 'openai' ? 'openai' : 'claude';
|
|
251
|
+
if (!(await (dependencies.ensureDaemon ?? ensureDaemon)())) {
|
|
217
252
|
persistAndEmitComplete(sessionId, {
|
|
218
253
|
id: assistantId,
|
|
219
254
|
role: 'error',
|
|
@@ -223,11 +258,11 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
223
258
|
}, log);
|
|
224
259
|
return;
|
|
225
260
|
}
|
|
226
|
-
const client = new DaemonClient();
|
|
261
|
+
const client = dependencies.createDaemonClient?.() ?? new DaemonClient();
|
|
227
262
|
const slot = chatSlot(sessionId);
|
|
228
263
|
activeSessions.add(slot);
|
|
229
264
|
// v0.51.4: read per-session cwd; falls back to daemon's startup cwd when unset.
|
|
230
|
-
//
|
|
265
|
+
// RuntimeSessionRuntime resets the slot's session if cwdOverride differs from
|
|
231
266
|
// existing.cwd, so switching cwd between sessions is safe.
|
|
232
267
|
const persisted = readSession(sessionId);
|
|
233
268
|
const sessionCwd = persisted?.cwd ?? undefined;
|
|
@@ -240,12 +275,17 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
240
275
|
// · daemon/宿主重启过 → 适配器重 spawn 并 loadSession 重载完整历史
|
|
241
276
|
// B) transcript 不在 / loadSession 失败(SESSION_LOST)/ 老会话无 id 且底层已 offline
|
|
242
277
|
// → 用已持久 messages 把历史重建进 prompt 兜底。
|
|
243
|
-
const savedId =
|
|
278
|
+
const savedId = backend === 'openai'
|
|
279
|
+
? persisted?.runtimeSessionId
|
|
280
|
+
: persisted?.claudeSessionId;
|
|
244
281
|
let resumeSessionId;
|
|
245
282
|
let replayHistory = false;
|
|
246
283
|
if (savedId) {
|
|
247
|
-
if (
|
|
284
|
+
if (backend === 'claude' &&
|
|
285
|
+
sessionCwd &&
|
|
286
|
+
!jsonlExists(sessionCwd, savedId)) {
|
|
248
287
|
replayHistory = true;
|
|
288
|
+
}
|
|
249
289
|
else
|
|
250
290
|
resumeSessionId = savedId;
|
|
251
291
|
}
|
|
@@ -274,10 +314,20 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
274
314
|
const hasCwdModelSettings = cwdModel !== undefined;
|
|
275
315
|
let effModel = persisted?.model;
|
|
276
316
|
let effProviderId = persisted?.providerId;
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
317
|
+
const agentsConfig = loadAgentsConfig();
|
|
318
|
+
if (backend === 'openai') {
|
|
319
|
+
const openaiDefaults = agentsConfig.worker.agent === 'openai'
|
|
320
|
+
? agentsConfig.worker
|
|
321
|
+
: {
|
|
322
|
+
model: agentsConfig.reviewer.model,
|
|
323
|
+
providerId: agentsConfig.reviewer.providerId,
|
|
324
|
+
};
|
|
325
|
+
effModel ||= openaiDefaults.model;
|
|
326
|
+
effProviderId ||= openaiDefaults.providerId;
|
|
327
|
+
}
|
|
328
|
+
else if (!effModel && !effProviderId && !hasCwdModelSettings) {
|
|
329
|
+
effModel = agentsConfig.worker.model;
|
|
330
|
+
effProviderId = agentsConfig.worker.providerId;
|
|
281
331
|
}
|
|
282
332
|
// 🔴 端点走「写文件」这条稳路:cwd 无模型配置或同模型需补配置,且用非官方 provider(codex-proxy/三方)——**无论是
|
|
283
333
|
// 前端显式选的还是这里回落的**——都把 model+端点写进 cwd 的 .claude/settings.local.json,让 claude
|
|
@@ -287,7 +337,11 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
287
337
|
// 同一模型也重写一次以补齐 provider env(例如 Ollama 无 key 时所需的占位 token)。
|
|
288
338
|
// cwd 明确配置了其它模型时仍保持项目优先,不用全局/会话默认覆盖。
|
|
289
339
|
const mayWriteProviderSettings = !cwdModel || !effModel || cwdModel === effModel.trim();
|
|
290
|
-
if (
|
|
340
|
+
if (backend === 'claude' &&
|
|
341
|
+
sessionCwd &&
|
|
342
|
+
mayWriteProviderSettings &&
|
|
343
|
+
effProviderId &&
|
|
344
|
+
effProviderId !== 'official') {
|
|
291
345
|
try {
|
|
292
346
|
writeModelSettingsFile(sessionCwd, effModel, effProviderId);
|
|
293
347
|
}
|
|
@@ -295,13 +349,17 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
295
349
|
/* 写不了(只读目录等)→ 退回 extraEnv 注入兜底 */
|
|
296
350
|
}
|
|
297
351
|
}
|
|
298
|
-
const modelEnv =
|
|
352
|
+
const modelEnv = backend === 'claude'
|
|
353
|
+
? resolveWorkerModelEnv(effModel, effProviderId)
|
|
354
|
+
: {};
|
|
299
355
|
// codex-proxy:选它(或回落到它) → 先确保 sidecar 在跑;否则按 cwd 的 settings.local.json 探测(逐项目)。
|
|
300
356
|
try {
|
|
301
|
-
if (
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
357
|
+
if (backend === 'claude') {
|
|
358
|
+
if (effProviderId === CODEX_PROXY_ID)
|
|
359
|
+
await ensureCodexProxyRunning();
|
|
360
|
+
else
|
|
361
|
+
await ensureCodexProxyForCwd(sessionCwd);
|
|
362
|
+
}
|
|
305
363
|
}
|
|
306
364
|
catch (err) {
|
|
307
365
|
emitEnsureError(err);
|
|
@@ -323,6 +381,21 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
323
381
|
// 🔴 模型不在此——留 settings.local.json 原生读(跨平台稳,不走 env)。没配=不设 outputStyle。
|
|
324
382
|
const chatCfg = sessionCwd ? readProjectAgentConfig(sessionCwd, 'chat') : {};
|
|
325
383
|
const chatEnv = { SPS_MANAGED: '1', ...modelEnv };
|
|
384
|
+
const openaiProvider = getAgentProvider(effProviderId ?? '');
|
|
385
|
+
const provider = backend === 'openai'
|
|
386
|
+
? {
|
|
387
|
+
providerId: effProviderId ?? 'official',
|
|
388
|
+
model: effModel ?? 'gpt-5.4',
|
|
389
|
+
transport: effProviderId === 'codex'
|
|
390
|
+
? 'codex'
|
|
391
|
+
: effProviderId === 'official' || !effProviderId
|
|
392
|
+
? 'responses'
|
|
393
|
+
: 'chat_completions',
|
|
394
|
+
...(openaiProvider?.baseUrl
|
|
395
|
+
? { baseUrl: openaiProvider.baseUrl }
|
|
396
|
+
: {}),
|
|
397
|
+
}
|
|
398
|
+
: undefined;
|
|
326
399
|
const ensureOpts = { mcpServers, extraEnv: chatEnv };
|
|
327
400
|
if (resumeSessionId)
|
|
328
401
|
ensureOpts.resumeSessionId = resumeSessionId;
|
|
@@ -330,6 +403,8 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
330
403
|
ensureOpts.skills = skillWhitelist;
|
|
331
404
|
if (chatCfg.outputStyle)
|
|
332
405
|
ensureOpts.outputStyle = chatCfg.outputStyle;
|
|
406
|
+
if (provider)
|
|
407
|
+
ensureOpts.provider = provider;
|
|
333
408
|
const ensureArg = ensureOpts;
|
|
334
409
|
// resume 失败退回全新会话时:丢 resumeSessionId,保留 skills + 模型 env + MCP。
|
|
335
410
|
const retryOpts = { mcpServers, extraEnv: chatEnv };
|
|
@@ -337,10 +412,12 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
337
412
|
retryOpts.skills = skillWhitelist;
|
|
338
413
|
if (chatCfg.outputStyle)
|
|
339
414
|
retryOpts.outputStyle = chatCfg.outputStyle;
|
|
415
|
+
if (provider)
|
|
416
|
+
retryOpts.provider = provider;
|
|
340
417
|
const retryArg = retryOpts;
|
|
341
418
|
let rec;
|
|
342
419
|
try {
|
|
343
|
-
rec = await client.ensureSession(slot,
|
|
420
|
+
rec = await client.ensureSession(slot, backend, sessionCwd, ensureArg);
|
|
344
421
|
}
|
|
345
422
|
catch (err) {
|
|
346
423
|
// 可恢复失败 → 退回全新会话 + 重放历史兜底:
|
|
@@ -360,7 +437,7 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
360
437
|
}
|
|
361
438
|
replayHistory = true;
|
|
362
439
|
try {
|
|
363
|
-
rec = await client.ensureSession(slot,
|
|
440
|
+
rec = await client.ensureSession(slot, backend, sessionCwd, retryArg);
|
|
364
441
|
}
|
|
365
442
|
catch (err2) {
|
|
366
443
|
emitEnsureError(err2);
|
|
@@ -372,11 +449,14 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
372
449
|
return;
|
|
373
450
|
}
|
|
374
451
|
}
|
|
375
|
-
// 持久化底层
|
|
452
|
+
// 持久化底层 sessionId(首轮 / resume 后变更)→ 后续(含跨重启)可 resume。
|
|
376
453
|
if (rec?.sessionId && rec.sessionId !== savedId) {
|
|
377
454
|
const s = readSession(sessionId);
|
|
378
455
|
if (s) {
|
|
379
|
-
|
|
456
|
+
if (backend === 'openai')
|
|
457
|
+
s.runtimeSessionId = rec.sessionId;
|
|
458
|
+
else
|
|
459
|
+
s.claudeSessionId = rec.sessionId;
|
|
380
460
|
writeSession(s);
|
|
381
461
|
}
|
|
382
462
|
}
|
|
@@ -395,7 +475,25 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
395
475
|
if (replayHistory) {
|
|
396
476
|
log.info(`chat[${sessionId}]: durable resume 兜底 —— 用 ${persisted?.messages?.length ?? 0} 条持久消息重建上下文`);
|
|
397
477
|
}
|
|
398
|
-
|
|
478
|
+
// OpenAI 输出已 durable 化:先 startRun 确立新 runId,再按 cursor 订阅回放,
|
|
479
|
+
// 避免订阅时重放上一轮 terminal。Claude 无 durable sequence,仍先订阅再派活。
|
|
480
|
+
if (backend === 'openai') {
|
|
481
|
+
try {
|
|
482
|
+
await client.startRun(slot, fullPrompt, backend, sessionCwd);
|
|
483
|
+
}
|
|
484
|
+
catch (err) {
|
|
485
|
+
activeSessions.delete(slot);
|
|
486
|
+
persistAndEmitComplete(sessionId, {
|
|
487
|
+
id: assistantId,
|
|
488
|
+
role: 'error',
|
|
489
|
+
content: `startRun failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
490
|
+
ts: new Date().toISOString(),
|
|
491
|
+
status: 'error',
|
|
492
|
+
}, log);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
const subscription = client.subscribeRunResilient(slot);
|
|
399
497
|
// 复用 POST 时 startTurn 预登记的进行中回合(blocks 引用,后续就地追加);未预登记则退化自建(防御)。
|
|
400
498
|
const blocks = activeStreams.get(sessionId)?.blocks ?? startTurn(sessionId, assistantId);
|
|
401
499
|
let accumulatedText = '';
|
|
@@ -407,8 +505,14 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
407
505
|
// 据此写回 claudeSessionId = durable resume 锚(ACP 路在 ensureSession 已拿到,不发此事件)。
|
|
408
506
|
try {
|
|
409
507
|
const s = readSession(sessionId);
|
|
410
|
-
|
|
411
|
-
s
|
|
508
|
+
const currentId = backend === 'openai'
|
|
509
|
+
? s?.runtimeSessionId
|
|
510
|
+
: s?.claudeSessionId;
|
|
511
|
+
if (s && currentId !== evt.sessionId) {
|
|
512
|
+
if (backend === 'openai')
|
|
513
|
+
s.runtimeSessionId = evt.sessionId;
|
|
514
|
+
else
|
|
515
|
+
s.claudeSessionId = evt.sessionId;
|
|
412
516
|
writeSession(s);
|
|
413
517
|
}
|
|
414
518
|
}
|
|
@@ -493,15 +597,27 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
493
597
|
locations: evt.locations,
|
|
494
598
|
});
|
|
495
599
|
}
|
|
600
|
+
else if (evt.event === 'interaction') {
|
|
601
|
+
appendInteractionBlock(sessionId, assistantId, blocks, evt);
|
|
602
|
+
}
|
|
496
603
|
else if (evt.event === 'complete') {
|
|
497
604
|
const ts = new Date().toISOString();
|
|
498
605
|
const isError = evt.stopReason === 'failed';
|
|
499
606
|
const isCancelled = evt.stopReason === 'cancelled';
|
|
607
|
+
const isWaitingInput = evt.stopReason === 'waiting_input';
|
|
608
|
+
if (isWaitingInput) {
|
|
609
|
+
const pendingInteraction = [...blocks]
|
|
610
|
+
.reverse()
|
|
611
|
+
.find((block) => block.type === 'interaction' && block.status === 'pending');
|
|
612
|
+
if (pendingInteraction && typeof evt.sequence === 'number') {
|
|
613
|
+
pendingInteraction.resumeAfterSequence = evt.sequence;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
500
616
|
// 兜底:正常收尾(end_turn)但一段 text 都没流到,且本回合有过工具调用 —— 大概率是
|
|
501
617
|
// claude-agent-acp 丢了「工具后收尾文本」的 agent_message_chunk 推流(见 recoverTrailingText)。
|
|
502
618
|
// 从转录按「最后一次工具调用之后」精确捞回那段文本,补进 content + 尾随一个 text block。
|
|
503
619
|
if (!isError && !isCancelled && accumulatedText.trim() === '' &&
|
|
504
|
-
sessionCwd && rec?.sessionId) {
|
|
620
|
+
backend === 'claude' && sessionCwd && rec?.sessionId) {
|
|
505
621
|
const lastTool = [...blocks].reverse().find((b) => b.type === 'tool_use');
|
|
506
622
|
if (lastTool && lastTool.type === 'tool_use') {
|
|
507
623
|
try {
|
|
@@ -519,7 +635,13 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
519
635
|
id: assistantId,
|
|
520
636
|
role: isError ? 'error' : 'assistant',
|
|
521
637
|
content: accumulatedText.trim() ||
|
|
522
|
-
(isError
|
|
638
|
+
(isError
|
|
639
|
+
? evt.error ?? `stopped: ${evt.stopReason}`
|
|
640
|
+
: isCancelled
|
|
641
|
+
? '(已中断)'
|
|
642
|
+
: isWaitingInput
|
|
643
|
+
? '等待用户输入'
|
|
644
|
+
: ''),
|
|
523
645
|
blocks: blocks.length > 0 ? blocks : undefined,
|
|
524
646
|
truncated: truncated || undefined,
|
|
525
647
|
ts,
|
|
@@ -531,7 +653,9 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
531
653
|
}
|
|
532
654
|
})();
|
|
533
655
|
try {
|
|
534
|
-
|
|
656
|
+
if (backend === 'claude') {
|
|
657
|
+
await client.startRun(slot, fullPrompt, backend, sessionCwd);
|
|
658
|
+
}
|
|
535
659
|
}
|
|
536
660
|
catch (err) {
|
|
537
661
|
subscription.cancel();
|
|
@@ -579,6 +703,197 @@ async function streamAssistantResponse(sessionId, assistantId, userContent, log,
|
|
|
579
703
|
endTurn(sessionId); // 安全网:completepath 已 endTurn;此处兜底停心跳/撤快照(重复调用无害)
|
|
580
704
|
}
|
|
581
705
|
}
|
|
706
|
+
function openaiResumeEnsureArgs(sessionId, session) {
|
|
707
|
+
if (!session.runtimeSessionId) {
|
|
708
|
+
throw new Error('OpenAI runtime session id is missing');
|
|
709
|
+
}
|
|
710
|
+
const cwd = session.cwd ?? undefined;
|
|
711
|
+
const config = loadAgentsConfig();
|
|
712
|
+
const defaults = config.worker.agent === 'openai'
|
|
713
|
+
? config.worker
|
|
714
|
+
: {
|
|
715
|
+
model: config.reviewer.model,
|
|
716
|
+
providerId: config.reviewer.providerId,
|
|
717
|
+
};
|
|
718
|
+
const model = session.model || defaults.model;
|
|
719
|
+
const providerId = session.providerId || defaults.providerId || 'official';
|
|
720
|
+
const configuredProvider = getAgentProvider(providerId);
|
|
721
|
+
const spsMcp = spsMcpStdioConfig({
|
|
722
|
+
cwd: cwd ?? process.cwd(),
|
|
723
|
+
project: cwd ? basename(cwd) : 'chat',
|
|
724
|
+
agentId: sessionId,
|
|
725
|
+
});
|
|
726
|
+
return {
|
|
727
|
+
cwd,
|
|
728
|
+
resumeSessionId: session.runtimeSessionId,
|
|
729
|
+
opts: {
|
|
730
|
+
resumeSessionId: session.runtimeSessionId,
|
|
731
|
+
mcpServers: [
|
|
732
|
+
{ name: 'sps', command: spsMcp.command, args: spsMcp.args },
|
|
733
|
+
],
|
|
734
|
+
extraEnv: { SPS_MANAGED: '1' },
|
|
735
|
+
provider: {
|
|
736
|
+
providerId,
|
|
737
|
+
model,
|
|
738
|
+
transport: providerId === 'codex'
|
|
739
|
+
? 'codex'
|
|
740
|
+
: providerId === 'official'
|
|
741
|
+
? 'responses'
|
|
742
|
+
: 'chat_completions',
|
|
743
|
+
...(configuredProvider?.baseUrl
|
|
744
|
+
? { baseUrl: configuredProvider.baseUrl }
|
|
745
|
+
: {}),
|
|
746
|
+
},
|
|
747
|
+
},
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
async function streamInteractionResponse(sessionId, assistantId, client, slot, afterSequence, log) {
|
|
751
|
+
const blocks = activeStreams.get(sessionId)?.blocks ??
|
|
752
|
+
startTurn(sessionId, assistantId);
|
|
753
|
+
const subscription = client.subscribeRunResilient(slot, afterSequence);
|
|
754
|
+
let accumulatedText = '';
|
|
755
|
+
let truncated = false;
|
|
756
|
+
try {
|
|
757
|
+
for await (const evt of subscription) {
|
|
758
|
+
if (evt.event === 'text') {
|
|
759
|
+
if (truncated)
|
|
760
|
+
continue;
|
|
761
|
+
const budget = MAX_ASSISTANT_CONTENT_BYTES -
|
|
762
|
+
Buffer.byteLength(accumulatedText, 'utf8');
|
|
763
|
+
if (budget <= 0) {
|
|
764
|
+
truncated = true;
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
const piece = Buffer.byteLength(evt.text, 'utf8') <= budget
|
|
768
|
+
? evt.text
|
|
769
|
+
: Buffer.from(evt.text, 'utf8')
|
|
770
|
+
.subarray(0, budget)
|
|
771
|
+
.toString('utf8');
|
|
772
|
+
accumulatedText += piece;
|
|
773
|
+
const last = blocks[blocks.length - 1];
|
|
774
|
+
if (last?.type === 'text')
|
|
775
|
+
last.text += piece;
|
|
776
|
+
else
|
|
777
|
+
blocks.push({ type: 'text', text: piece });
|
|
778
|
+
chatBus.emit('chat.message.chunk.text', {
|
|
779
|
+
sessionId,
|
|
780
|
+
assistantId,
|
|
781
|
+
turnId: assistantId,
|
|
782
|
+
seq: bumpSeq(sessionId),
|
|
783
|
+
text: piece,
|
|
784
|
+
});
|
|
785
|
+
if (piece.length < evt.text.length)
|
|
786
|
+
truncated = true;
|
|
787
|
+
}
|
|
788
|
+
else if (evt.event === 'tool_use') {
|
|
789
|
+
const input = sanitizeToolInput(evt.input);
|
|
790
|
+
blocks.push({
|
|
791
|
+
type: 'tool_use',
|
|
792
|
+
id: evt.id,
|
|
793
|
+
title: evt.title,
|
|
794
|
+
kind: evt.kind,
|
|
795
|
+
status: evt.status,
|
|
796
|
+
input,
|
|
797
|
+
locations: evt.locations,
|
|
798
|
+
});
|
|
799
|
+
chatBus.emit('chat.message.chunk.tool_use', {
|
|
800
|
+
sessionId,
|
|
801
|
+
assistantId,
|
|
802
|
+
turnId: assistantId,
|
|
803
|
+
seq: bumpSeq(sessionId),
|
|
804
|
+
id: evt.id,
|
|
805
|
+
title: evt.title,
|
|
806
|
+
kind: evt.kind,
|
|
807
|
+
status: evt.status,
|
|
808
|
+
input,
|
|
809
|
+
locations: evt.locations,
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
else if (evt.event === 'tool_update') {
|
|
813
|
+
const tool = blocks.find((block) => block.type === 'tool_use' && block.id === evt.id);
|
|
814
|
+
const input = evt.input == null ? undefined : sanitizeToolInput(evt.input);
|
|
815
|
+
if (tool?.type === 'tool_use') {
|
|
816
|
+
tool.status = evt.status;
|
|
817
|
+
if (input !== undefined &&
|
|
818
|
+
!isEmptyToolInput(input) &&
|
|
819
|
+
isEmptyToolInput(tool.input)) {
|
|
820
|
+
tool.input = input;
|
|
821
|
+
}
|
|
822
|
+
if (evt.locations != null && tool.locations == null) {
|
|
823
|
+
tool.locations = evt.locations;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
chatBus.emit('chat.message.chunk.tool_update', {
|
|
827
|
+
sessionId,
|
|
828
|
+
assistantId,
|
|
829
|
+
turnId: assistantId,
|
|
830
|
+
seq: bumpSeq(sessionId),
|
|
831
|
+
id: evt.id,
|
|
832
|
+
status: evt.status,
|
|
833
|
+
input,
|
|
834
|
+
locations: evt.locations,
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
else if (evt.event === 'interaction') {
|
|
838
|
+
appendInteractionBlock(sessionId, assistantId, blocks, evt);
|
|
839
|
+
}
|
|
840
|
+
else if (evt.event === 'complete') {
|
|
841
|
+
const waitingInput = evt.stopReason === 'waiting_input';
|
|
842
|
+
const failed = evt.stopReason === 'failed';
|
|
843
|
+
const cancelled = evt.stopReason === 'cancelled';
|
|
844
|
+
if (waitingInput) {
|
|
845
|
+
const pending = [...blocks]
|
|
846
|
+
.reverse()
|
|
847
|
+
.find((block) => block.type === 'interaction' &&
|
|
848
|
+
block.status === 'pending');
|
|
849
|
+
if (pending && typeof evt.sequence === 'number') {
|
|
850
|
+
pending.resumeAfterSequence = evt.sequence;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
persistAndEmitComplete(sessionId, {
|
|
854
|
+
id: assistantId,
|
|
855
|
+
role: failed ? 'error' : 'assistant',
|
|
856
|
+
content: accumulatedText.trim() ||
|
|
857
|
+
(failed
|
|
858
|
+
? evt.error ?? 'interaction resume failed'
|
|
859
|
+
: cancelled
|
|
860
|
+
? '(已中断)'
|
|
861
|
+
: waitingInput
|
|
862
|
+
? '等待用户输入'
|
|
863
|
+
: ''),
|
|
864
|
+
blocks: blocks.length ? blocks : undefined,
|
|
865
|
+
truncated: truncated || undefined,
|
|
866
|
+
ts: new Date().toISOString(),
|
|
867
|
+
status: failed ? 'error' : 'complete',
|
|
868
|
+
}, log);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
throw new Error('Interaction event stream ended without a terminal event');
|
|
873
|
+
}
|
|
874
|
+
catch (error) {
|
|
875
|
+
if (activeStreams.has(sessionId)) {
|
|
876
|
+
persistAndEmitComplete(sessionId, {
|
|
877
|
+
id: assistantId,
|
|
878
|
+
role: 'error',
|
|
879
|
+
content: `interaction resume failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
880
|
+
ts: new Date().toISOString(),
|
|
881
|
+
status: 'error',
|
|
882
|
+
}, log);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
finally {
|
|
886
|
+
subscription.cancel();
|
|
887
|
+
try {
|
|
888
|
+
await client.clearRun(slot);
|
|
889
|
+
}
|
|
890
|
+
catch {
|
|
891
|
+
/* best effort */
|
|
892
|
+
}
|
|
893
|
+
activeSessions.delete(slot);
|
|
894
|
+
endTurn(sessionId);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
582
897
|
// ─── openai ChatBackend 适配器 ──────────────────────────────────────
|
|
583
898
|
// claude 走 daemon/ACP(上面);openai 走 in-process Agents SDK run(stream),
|
|
584
899
|
// 把文本流映射成与 claude 一致的 chunk 事件 + 同样 persistAndEmitComplete 落库。
|
|
@@ -776,7 +1091,7 @@ function persistAndEmitComplete(sessionId, msg, log) {
|
|
|
776
1091
|
}
|
|
777
1092
|
endTurn(sessionId); // 停心跳 + 撤销进行中快照(始终执行,含 session 缺失兜底)
|
|
778
1093
|
}
|
|
779
|
-
export function createChatRoute(log, chat) {
|
|
1094
|
+
export function createChatRoute(log, chat, dependencies = {}) {
|
|
780
1095
|
const app = new Hono();
|
|
781
1096
|
// v0.57:进程启动即对账 —— 上个进程遗留的 lastTurn=running(死回合)翻成 error,
|
|
782
1097
|
// 让轮询兜底(GET lastTurn)在宿主/进程重启后也讲真话,不永卡 running。
|
|
@@ -789,11 +1104,19 @@ export function createChatRoute(log, chat) {
|
|
|
789
1104
|
});
|
|
790
1105
|
app.post('/sessions', async (c) => {
|
|
791
1106
|
const body = (await c.req.json().catch(() => ({})));
|
|
1107
|
+
const agentKind = body.agentKind === 'openai' ? 'openai' : 'claude';
|
|
1108
|
+
const configuredWorker = loadAgentsConfig().worker;
|
|
1109
|
+
// 新建会话默认 daemon:openai 走真正的独立进程 agent(sps openai-agent,带 sandbox + 工具 + 技能)。
|
|
1110
|
+
// 旧会话(已持久 agentMode='sdk')不受影响,dispatch 侧仍按各自持久值走。
|
|
1111
|
+
const agentMode = body.agentMode ??
|
|
1112
|
+
(configuredWorker.agent === agentKind ? configuredWorker.mode : 'daemon');
|
|
792
1113
|
const r = await chat.create({
|
|
793
1114
|
title: body.title,
|
|
794
1115
|
project: body.project,
|
|
795
1116
|
cwd: body.cwd,
|
|
796
|
-
|
|
1117
|
+
namespace: body.namespace,
|
|
1118
|
+
agentKind,
|
|
1119
|
+
agentMode,
|
|
797
1120
|
model: body.model,
|
|
798
1121
|
providerId: body.providerId,
|
|
799
1122
|
dedicated: body.dedicated === true,
|
|
@@ -813,8 +1136,9 @@ export function createChatRoute(log, chat) {
|
|
|
813
1136
|
...r.value,
|
|
814
1137
|
model: displayChatModel(c.req.param('id'), r.value.agentKind, cwd),
|
|
815
1138
|
};
|
|
816
|
-
// P1
|
|
817
|
-
|
|
1139
|
+
// P1:对话专属工作目录才扫产物 —— 真项目 cwd 不扫(会列出整仓)。
|
|
1140
|
+
// 兼容新根 <WORKSPACES_ROOT> 与 legacy ~/.coral/chats(双读,不硬切)。
|
|
1141
|
+
if (cwd && (cwd.startsWith(workspacesRoot()) || cwd.startsWith(chatWorkspacesRoot()))) {
|
|
818
1142
|
detail.artifacts = listArtifacts(cwd);
|
|
819
1143
|
}
|
|
820
1144
|
return c.json(detail);
|
|
@@ -828,14 +1152,14 @@ export function createChatRoute(log, chat) {
|
|
|
828
1152
|
const r = await chat.delete(id);
|
|
829
1153
|
if (!r.ok)
|
|
830
1154
|
return c.json(toProblemJson(r.error), toHttpStatus(r.error));
|
|
831
|
-
// v0.51.8:删除该 session
|
|
832
|
-
//
|
|
1155
|
+
// v0.51.8:删除该 session 的私有附件暂存目录(best effort)。
|
|
1156
|
+
// 🔴 只清附件,**绝不删工作区目录**——目录是用户产物,且同一 cwd 可被多个 chat 共用;
|
|
1157
|
+
// 工作区的删除只走"项目管理"里用户显式选择的完整删除,不由 chat 删除触发。
|
|
833
1158
|
try {
|
|
834
1159
|
const { rmSync } = await import('node:fs');
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
}
|
|
1160
|
+
const attachments = chatAttachmentsDirFor(id);
|
|
1161
|
+
if (existsSync(attachments))
|
|
1162
|
+
rmSync(attachments, { recursive: true, force: true });
|
|
839
1163
|
}
|
|
840
1164
|
catch {
|
|
841
1165
|
/* non-fatal */
|
|
@@ -843,6 +1167,169 @@ export function createChatRoute(log, chat) {
|
|
|
843
1167
|
chatBus.emit('chat.session.deleted', { sessionId: id });
|
|
844
1168
|
return c.body(null, 204);
|
|
845
1169
|
});
|
|
1170
|
+
app.post('/sessions/:id/interactions/:interactionId', async (c) => {
|
|
1171
|
+
const id = c.req.param('id');
|
|
1172
|
+
const interactionId = c.req.param('interactionId');
|
|
1173
|
+
const session = readSession(id);
|
|
1174
|
+
if (!session) {
|
|
1175
|
+
return c.json({ type: 'not-found', title: 'Session not found', status: 404 }, 404);
|
|
1176
|
+
}
|
|
1177
|
+
if (session.agentKind !== 'openai' ||
|
|
1178
|
+
(session.agentMode ?? 'sdk') !== 'daemon') {
|
|
1179
|
+
return c.json({
|
|
1180
|
+
type: 'validation',
|
|
1181
|
+
title: 'Session does not support durable interactions',
|
|
1182
|
+
status: 422,
|
|
1183
|
+
}, 422);
|
|
1184
|
+
}
|
|
1185
|
+
const found = findInteractionBlock(session, interactionId);
|
|
1186
|
+
if (!found) {
|
|
1187
|
+
return c.json({ type: 'not-found', title: 'Interaction not found', status: 404 }, 404);
|
|
1188
|
+
}
|
|
1189
|
+
if (found.block.status !== 'pending') {
|
|
1190
|
+
return c.json({
|
|
1191
|
+
type: 'conflict',
|
|
1192
|
+
title: `Interaction is already ${found.block.status}`,
|
|
1193
|
+
status: 409,
|
|
1194
|
+
}, 409);
|
|
1195
|
+
}
|
|
1196
|
+
const body = (await c.req.json().catch(() => null));
|
|
1197
|
+
if (!body ||
|
|
1198
|
+
!Object.prototype.hasOwnProperty.call(body, 'answer') ||
|
|
1199
|
+
!Number.isInteger(body.expectedRevision)) {
|
|
1200
|
+
return c.json({
|
|
1201
|
+
type: 'validation',
|
|
1202
|
+
title: 'answer and integer expectedRevision are required',
|
|
1203
|
+
status: 422,
|
|
1204
|
+
}, 422);
|
|
1205
|
+
}
|
|
1206
|
+
if (body.expectedRevision !== found.block.revision) {
|
|
1207
|
+
return c.json({
|
|
1208
|
+
type: 'conflict',
|
|
1209
|
+
title: 'Interaction revision changed',
|
|
1210
|
+
status: 409,
|
|
1211
|
+
detail: `expected ${body.expectedRevision}, current ${found.block.revision}`,
|
|
1212
|
+
}, 409);
|
|
1213
|
+
}
|
|
1214
|
+
const afterSequence = found.block.resumeAfterSequence;
|
|
1215
|
+
if (!Number.isInteger(afterSequence)) {
|
|
1216
|
+
return c.json({
|
|
1217
|
+
type: 'conflict',
|
|
1218
|
+
title: 'Interaction checkpoint cursor is unavailable',
|
|
1219
|
+
status: 409,
|
|
1220
|
+
}, 409);
|
|
1221
|
+
}
|
|
1222
|
+
const slot = chatSlot(id);
|
|
1223
|
+
if (activeSessions.has(slot)) {
|
|
1224
|
+
return c.json({ type: 'conflict', title: 'session busy', status: 409 }, 409);
|
|
1225
|
+
}
|
|
1226
|
+
if (!(await (dependencies.ensureDaemon ?? ensureDaemon)())) {
|
|
1227
|
+
return c.json({ type: 'unavailable', title: 'Agent daemon unavailable', status: 503 }, 503);
|
|
1228
|
+
}
|
|
1229
|
+
const client = dependencies.createDaemonClient?.() ?? new DaemonClient();
|
|
1230
|
+
try {
|
|
1231
|
+
const ensure = openaiResumeEnsureArgs(id, session);
|
|
1232
|
+
await client.ensureSession(slot, 'openai', ensure.cwd, ensure.opts);
|
|
1233
|
+
await client.submitInteraction(slot, interactionId, body.answer, body.expectedRevision);
|
|
1234
|
+
}
|
|
1235
|
+
catch (error) {
|
|
1236
|
+
return c.json({
|
|
1237
|
+
type: 'interaction-resume',
|
|
1238
|
+
title: 'Interaction could not be resumed',
|
|
1239
|
+
status: 409,
|
|
1240
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
1241
|
+
}, 409);
|
|
1242
|
+
}
|
|
1243
|
+
const latest = readSession(id);
|
|
1244
|
+
const latestFound = latest
|
|
1245
|
+
? findInteractionBlock(latest, interactionId)
|
|
1246
|
+
: null;
|
|
1247
|
+
if (latest && latestFound) {
|
|
1248
|
+
latestFound.block.status = 'answered';
|
|
1249
|
+
latestFound.block.answer = body.answer;
|
|
1250
|
+
latestFound.block.revision += 1;
|
|
1251
|
+
writeSession(latest);
|
|
1252
|
+
}
|
|
1253
|
+
chatBus.emit('chat.message.interaction.updated', {
|
|
1254
|
+
sessionId: id,
|
|
1255
|
+
interactionId,
|
|
1256
|
+
status: 'answered',
|
|
1257
|
+
revision: found.block.revision + 1,
|
|
1258
|
+
answer: body.answer,
|
|
1259
|
+
});
|
|
1260
|
+
const assistantId = randomUUID();
|
|
1261
|
+
activeSessions.add(slot);
|
|
1262
|
+
startTurn(id, assistantId);
|
|
1263
|
+
chatBus.emit('chat.message.pending', {
|
|
1264
|
+
sessionId: id,
|
|
1265
|
+
assistantId,
|
|
1266
|
+
turnId: assistantId,
|
|
1267
|
+
seq: 0,
|
|
1268
|
+
ts: new Date().toISOString(),
|
|
1269
|
+
});
|
|
1270
|
+
void streamInteractionResponse(id, assistantId, client, slot, afterSequence, log);
|
|
1271
|
+
return c.json({ assistantId }, 202);
|
|
1272
|
+
});
|
|
1273
|
+
app.post('/sessions/:id/interactions/:interactionId/cancel', async (c) => {
|
|
1274
|
+
const id = c.req.param('id');
|
|
1275
|
+
const interactionId = c.req.param('interactionId');
|
|
1276
|
+
const session = readSession(id);
|
|
1277
|
+
if (!session) {
|
|
1278
|
+
return c.json({ type: 'not-found', title: 'Session not found', status: 404 }, 404);
|
|
1279
|
+
}
|
|
1280
|
+
const found = findInteractionBlock(session, interactionId);
|
|
1281
|
+
if (!found) {
|
|
1282
|
+
return c.json({ type: 'not-found', title: 'Interaction not found', status: 404 }, 404);
|
|
1283
|
+
}
|
|
1284
|
+
const body = (await c.req.json().catch(() => null));
|
|
1285
|
+
if (found.block.status !== 'pending' ||
|
|
1286
|
+
!body ||
|
|
1287
|
+
!Number.isInteger(body.expectedRevision) ||
|
|
1288
|
+
body.expectedRevision !== found.block.revision) {
|
|
1289
|
+
return c.json({
|
|
1290
|
+
type: 'conflict',
|
|
1291
|
+
title: 'Interaction is no longer pending at this revision',
|
|
1292
|
+
status: 409,
|
|
1293
|
+
}, 409);
|
|
1294
|
+
}
|
|
1295
|
+
if (!(await (dependencies.ensureDaemon ?? ensureDaemon)())) {
|
|
1296
|
+
return c.json({
|
|
1297
|
+
type: 'unavailable',
|
|
1298
|
+
title: 'Agent daemon unavailable',
|
|
1299
|
+
status: 503,
|
|
1300
|
+
}, 503);
|
|
1301
|
+
}
|
|
1302
|
+
const client = dependencies.createDaemonClient?.() ?? new DaemonClient();
|
|
1303
|
+
try {
|
|
1304
|
+
const ensure = openaiResumeEnsureArgs(id, session);
|
|
1305
|
+
await client.ensureSession(chatSlot(id), 'openai', ensure.cwd, ensure.opts);
|
|
1306
|
+
await client.cancelInteraction(chatSlot(id), interactionId, body.expectedRevision);
|
|
1307
|
+
}
|
|
1308
|
+
catch (error) {
|
|
1309
|
+
return c.json({
|
|
1310
|
+
type: 'interaction-cancel',
|
|
1311
|
+
title: 'Interaction could not be cancelled',
|
|
1312
|
+
status: 409,
|
|
1313
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
1314
|
+
}, 409);
|
|
1315
|
+
}
|
|
1316
|
+
const latest = readSession(id);
|
|
1317
|
+
const latestFound = latest
|
|
1318
|
+
? findInteractionBlock(latest, interactionId)
|
|
1319
|
+
: null;
|
|
1320
|
+
if (latest && latestFound) {
|
|
1321
|
+
latestFound.block.status = 'cancelled';
|
|
1322
|
+
latestFound.block.revision += 1;
|
|
1323
|
+
writeSession(latest);
|
|
1324
|
+
}
|
|
1325
|
+
chatBus.emit('chat.message.interaction.updated', {
|
|
1326
|
+
sessionId: id,
|
|
1327
|
+
interactionId,
|
|
1328
|
+
status: 'cancelled',
|
|
1329
|
+
revision: found.block.revision + 1,
|
|
1330
|
+
});
|
|
1331
|
+
return c.body(null, 204);
|
|
1332
|
+
});
|
|
846
1333
|
app.post('/sessions/:id/interrupt', async (c) => {
|
|
847
1334
|
const r = await chat.interrupt(c.req.param('id'));
|
|
848
1335
|
if (!r.ok)
|
|
@@ -933,7 +1420,7 @@ export function createChatRoute(log, chat) {
|
|
|
933
1420
|
seq: 0,
|
|
934
1421
|
ts: new Date().toISOString(),
|
|
935
1422
|
});
|
|
936
|
-
streamAssistantResponse(id, assistantId, body.content, log, attachments).catch((err) => {
|
|
1423
|
+
streamAssistantResponse(id, assistantId, body.content, log, attachments, dependencies).catch((err) => {
|
|
937
1424
|
log.error(`chat[${id}] stream error: ${err instanceof Error ? err.message : String(err)}`);
|
|
938
1425
|
// 极端:streamAssistantResponse 未走到任何 persistAndEmitComplete 就抛 → 兜底落错 + 收尾。
|
|
939
1426
|
if (activeStreams.has(id)) {
|
|
@@ -968,6 +1455,8 @@ export function createChatStreamRoute() {
|
|
|
968
1455
|
'chat.message.chunk.text',
|
|
969
1456
|
'chat.message.chunk.tool_use',
|
|
970
1457
|
'chat.message.chunk.tool_update',
|
|
1458
|
+
'chat.message.chunk.interaction',
|
|
1459
|
+
'chat.message.interaction.updated',
|
|
971
1460
|
'chat.message.complete',
|
|
972
1461
|
'chat.message.error', // v0.57:明确的回合异常终止(带 turnId)
|
|
973
1462
|
'chat.message.heartbeat', // v0.57:流式进行中心跳(带 turnId),区分"还在生成"vs"卡死"
|