@downcity/agent 1.1.430 → 1.1.437
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/README.md +13 -11
- package/bin/agent/Agent.d.ts +3 -3
- package/bin/agent/Agent.d.ts.map +1 -1
- package/bin/agent/Agent.js +38 -8
- package/bin/agent/Agent.js.map +1 -1
- package/bin/agent/AgentInstructions.js +2 -2
- package/bin/agent/AgentInstructions.js.map +1 -1
- package/bin/agent/AgentMemoryStorage.d.ts.map +1 -1
- package/bin/agent/AgentMemoryStorage.js +1 -0
- package/bin/agent/AgentMemoryStorage.js.map +1 -1
- package/bin/agent/AgentSessions.d.ts +5 -1
- package/bin/agent/AgentSessions.d.ts.map +1 -1
- package/bin/agent/AgentSessions.js +17 -9
- package/bin/agent/AgentSessions.js.map +1 -1
- package/bin/executor/Executor.d.ts +9 -27
- package/bin/executor/Executor.d.ts.map +1 -1
- package/bin/executor/Executor.js +32 -127
- package/bin/executor/Executor.js.map +1 -1
- package/bin/executor/composer/system/default/SystemPromptAssets.d.ts +0 -4
- package/bin/executor/composer/system/default/SystemPromptAssets.d.ts.map +1 -1
- package/bin/executor/composer/system/default/SystemPromptAssets.js +0 -5
- package/bin/executor/composer/system/default/SystemPromptAssets.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineContextCompaction.d.ts +3 -9
- package/bin/executor/core-engine/CoreEngineContextCompaction.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineContextCompaction.js +4 -130
- package/bin/executor/core-engine/CoreEngineContextCompaction.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineRunner.d.ts +3 -30
- package/bin/executor/core-engine/CoreEngineRunner.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineRunner.js +38 -194
- package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineSignals.d.ts +6 -6
- package/bin/executor/core-engine/CoreEngineSignals.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineSignals.js +1 -1
- package/bin/executor/core-engine/CoreEngineSignals.js.map +1 -1
- package/bin/executor/messages/SessionAttachmentMapper.d.ts +2 -2
- package/bin/executor/messages/SessionAttachmentMapper.d.ts.map +1 -1
- package/bin/executor/messages/SessionAttachmentMapper.js.map +1 -1
- package/bin/executor/messages/SessionMessageLog.d.ts +3 -3
- package/bin/executor/messages/SessionMessageLog.d.ts.map +1 -1
- package/bin/executor/messages/SessionMessageLog.js.map +1 -1
- package/bin/executor/messages/SessionModelMessages.d.ts +0 -3
- package/bin/executor/messages/SessionModelMessages.d.ts.map +1 -1
- package/bin/executor/messages/SessionModelMessages.js +80 -97
- package/bin/executor/messages/SessionModelMessages.js.map +1 -1
- package/bin/executor/model/ModelStepRunner.d.ts +2 -6
- package/bin/executor/model/ModelStepRunner.d.ts.map +1 -1
- package/bin/executor/model/ModelStepRunner.js +0 -28
- package/bin/executor/model/ModelStepRunner.js.map +1 -1
- package/bin/executor/services/ExecutorRecoveryPolicy.d.ts +7 -64
- package/bin/executor/services/ExecutorRecoveryPolicy.d.ts.map +1 -1
- package/bin/executor/services/ExecutorRecoveryPolicy.js +29 -45
- package/bin/executor/services/ExecutorRecoveryPolicy.js.map +1 -1
- package/bin/executor/types/SessionHistoryMeta.d.ts +1 -3
- package/bin/executor/types/SessionHistoryMeta.d.ts.map +1 -1
- package/bin/executor/types/SessionHistoryMeta.js +1 -1
- package/bin/index.d.ts +9 -13
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +2 -4
- package/bin/index.js.map +1 -1
- package/bin/session/DefaultSessionComposer.d.ts +13 -7
- package/bin/session/DefaultSessionComposer.d.ts.map +1 -1
- package/bin/session/DefaultSessionComposer.js +26 -21
- package/bin/session/DefaultSessionComposer.js.map +1 -1
- package/bin/session/Session.d.ts +12 -19
- package/bin/session/Session.d.ts.map +1 -1
- package/bin/session/Session.js +70 -202
- package/bin/session/Session.js.map +1 -1
- package/bin/session/SessionComposition.d.ts +0 -2
- package/bin/session/SessionComposition.d.ts.map +1 -1
- package/bin/session/SessionComposition.js +30 -54
- package/bin/session/SessionComposition.js.map +1 -1
- package/bin/session/SessionLoop.d.ts +17 -16
- package/bin/session/SessionLoop.d.ts.map +1 -1
- package/bin/session/SessionLoop.js +217 -320
- package/bin/session/SessionLoop.js.map +1 -1
- package/bin/session/SessionMessages.d.ts +52 -44
- package/bin/session/SessionMessages.d.ts.map +1 -1
- package/bin/session/SessionMessages.js +285 -187
- package/bin/session/SessionMessages.js.map +1 -1
- package/bin/session/SessionQueue.d.ts +1 -1
- package/bin/session/SessionQueue.d.ts.map +1 -1
- package/bin/session/SessionQueue.js +2 -1
- package/bin/session/SessionQueue.js.map +1 -1
- package/bin/session/SessionState.d.ts +3 -7
- package/bin/session/SessionState.d.ts.map +1 -1
- package/bin/session/SessionState.js +50 -89
- package/bin/session/SessionState.js.map +1 -1
- package/bin/session/SessionSystem.d.ts +5 -1
- package/bin/session/SessionSystem.d.ts.map +1 -1
- package/bin/session/SessionSystem.js +40 -0
- package/bin/session/SessionSystem.js.map +1 -1
- package/bin/session/SessionTitle.d.ts +3 -3
- package/bin/session/SessionTitle.d.ts.map +1 -1
- package/bin/session/SessionTitle.js +2 -2
- package/bin/session/browse/Browse.d.ts +32 -46
- package/bin/session/browse/Browse.d.ts.map +1 -1
- package/bin/session/browse/Browse.js +104 -360
- package/bin/session/browse/Browse.js.map +1 -1
- package/bin/session/browse/SessionMessageTimeline.d.ts.map +1 -1
- package/bin/session/browse/SessionMessageTimeline.js +61 -37
- package/bin/session/browse/SessionMessageTimeline.js.map +1 -1
- package/bin/session/composer/policies/AdaptivePartContextPolicy.d.ts +35 -0
- package/bin/session/composer/policies/AdaptivePartContextPolicy.d.ts.map +1 -0
- package/bin/session/composer/policies/AdaptivePartContextPolicy.js +256 -0
- package/bin/session/composer/policies/AdaptivePartContextPolicy.js.map +1 -0
- package/bin/session/composer/policies/FullHistoryContextPolicy.d.ts +24 -0
- package/bin/session/composer/policies/FullHistoryContextPolicy.d.ts.map +1 -0
- package/bin/session/composer/policies/FullHistoryContextPolicy.js +31 -0
- package/bin/session/composer/policies/FullHistoryContextPolicy.js.map +1 -0
- package/bin/session/composer/policies/SessionSummaryPrompts.d.ts +16 -0
- package/bin/session/composer/policies/SessionSummaryPrompts.d.ts.map +1 -0
- package/bin/session/composer/policies/SessionSummaryPrompts.js +32 -0
- package/bin/session/composer/policies/SessionSummaryPrompts.js.map +1 -0
- package/bin/session/execution/SessionAssistantOutputAdapter.d.ts +15 -4
- package/bin/session/execution/SessionAssistantOutputAdapter.d.ts.map +1 -1
- package/bin/session/execution/SessionAssistantOutputAdapter.js +7 -3
- package/bin/session/execution/SessionAssistantOutputAdapter.js.map +1 -1
- package/bin/session/messages/{SessionActionMessageWriter.d.ts → SessionAgentActionPartWriter.d.ts} +7 -7
- package/bin/session/messages/SessionAgentActionPartWriter.d.ts.map +1 -0
- package/bin/session/messages/{SessionActionMessageWriter.js → SessionAgentActionPartWriter.js} +7 -7
- package/bin/session/messages/SessionAgentActionPartWriter.js.map +1 -0
- package/bin/session/messages/SessionAgentContent.d.ts +10 -0
- package/bin/session/messages/SessionAgentContent.d.ts.map +1 -0
- package/bin/session/messages/SessionAgentContent.js +44 -0
- package/bin/session/messages/SessionAgentContent.js.map +1 -0
- package/bin/session/messages/SessionAgentMessageState.d.ts +50 -0
- package/bin/session/messages/SessionAgentMessageState.d.ts.map +1 -0
- package/bin/session/messages/SessionAgentMessageState.js +283 -0
- package/bin/session/messages/SessionAgentMessageState.js.map +1 -0
- package/bin/session/messages/{SessionAssistantMessageWriter.d.ts → SessionAgentMessageWriter.d.ts} +22 -8
- package/bin/session/messages/SessionAgentMessageWriter.d.ts.map +1 -0
- package/bin/session/messages/{SessionAssistantMessageWriter.js → SessionAgentMessageWriter.js} +54 -42
- package/bin/session/messages/SessionAgentMessageWriter.js.map +1 -0
- package/bin/session/messages/SessionForkMessageFiles.d.ts +11 -0
- package/bin/session/messages/SessionForkMessageFiles.d.ts.map +1 -1
- package/bin/session/messages/SessionForkMessageFiles.js +8 -2
- package/bin/session/messages/SessionForkMessageFiles.js.map +1 -1
- package/bin/session/messages/SessionMessageInteractionWriter.d.ts +6 -6
- package/bin/session/messages/SessionMessageInteractionWriter.d.ts.map +1 -1
- package/bin/session/messages/SessionMessageInteractionWriter.js +4 -4
- package/bin/session/messages/SessionMessageInteractionWriter.js.map +1 -1
- package/bin/session/messages/SessionMessageText.d.ts +3 -3
- package/bin/session/messages/SessionMessageText.d.ts.map +1 -1
- package/bin/session/messages/SessionMessageText.js +0 -2
- package/bin/session/messages/SessionMessageText.js.map +1 -1
- package/bin/session/messages/SessionTurnFileDiffData.d.ts +3 -3
- package/bin/session/messages/SessionTurnFileDiffData.d.ts.map +1 -1
- package/bin/session/messages/SessionTurnFileDiffData.js.map +1 -1
- package/bin/session/messages/SessionUserMessage.d.ts +3 -3
- package/bin/session/messages/SessionUserMessage.d.ts.map +1 -1
- package/bin/session/messages/SessionUserMessage.js +6 -3
- package/bin/session/messages/SessionUserMessage.js.map +1 -1
- package/bin/session/preview/SessionMessagePreview.d.ts.map +1 -1
- package/bin/session/preview/SessionMessagePreview.js +25 -9
- package/bin/session/preview/SessionMessagePreview.js.map +1 -1
- package/bin/session/runtime/SessionTurnCompletion.d.ts +15 -0
- package/bin/session/runtime/SessionTurnCompletion.d.ts.map +1 -0
- package/bin/session/runtime/SessionTurnCompletion.js +126 -0
- package/bin/session/runtime/SessionTurnCompletion.js.map +1 -0
- package/bin/session/runtime/SessionTurnContext.d.ts.map +1 -1
- package/bin/session/runtime/SessionTurnContext.js +14 -19
- package/bin/session/runtime/SessionTurnContext.js.map +1 -1
- package/bin/session/runtime/SessionTurnFileDiff.d.ts +12 -0
- package/bin/session/runtime/SessionTurnFileDiff.d.ts.map +1 -0
- package/bin/session/runtime/SessionTurnFileDiff.js +71 -0
- package/bin/session/runtime/SessionTurnFileDiff.js.map +1 -0
- package/bin/session/storage/LocalSessionDataStore.d.ts +6 -41
- package/bin/session/storage/LocalSessionDataStore.d.ts.map +1 -1
- package/bin/session/storage/LocalSessionDataStore.js +19 -101
- package/bin/session/storage/LocalSessionDataStore.js.map +1 -1
- package/bin/session/storage/LocalSessionStore.d.ts +13 -5
- package/bin/session/storage/LocalSessionStore.d.ts.map +1 -1
- package/bin/session/storage/LocalSessionStore.js +153 -30
- package/bin/session/storage/LocalSessionStore.js.map +1 -1
- package/bin/session/storage/LocalStorePaths.d.ts +4 -16
- package/bin/session/storage/LocalStorePaths.d.ts.map +1 -1
- package/bin/session/storage/LocalStorePaths.js +7 -31
- package/bin/session/storage/LocalStorePaths.js.map +1 -1
- package/bin/session/storage/Metadata.d.ts +4 -4
- package/bin/session/storage/Metadata.d.ts.map +1 -1
- package/bin/session/storage/Metadata.js +3 -11
- package/bin/session/storage/Metadata.js.map +1 -1
- package/bin/session/storage/RuntimeSessionPort.d.ts +4 -4
- package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
- package/bin/session/storage/RuntimeSessionPort.js +3 -3
- package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
- package/bin/session/storage/SessionStorageCodec.d.ts +59 -0
- package/bin/session/storage/SessionStorageCodec.d.ts.map +1 -0
- package/bin/session/storage/SessionStorageCodec.js +331 -0
- package/bin/session/storage/SessionStorageCodec.js.map +1 -0
- package/bin/session/storage/SessionStorageSchema.d.ts +11 -0
- package/bin/session/storage/SessionStorageSchema.d.ts.map +1 -0
- package/bin/session/storage/SessionStorageSchema.js +131 -0
- package/bin/session/storage/SessionStorageSchema.js.map +1 -0
- package/bin/session/storage/SqliteSessionStorage.d.ts +120 -0
- package/bin/session/storage/SqliteSessionStorage.d.ts.map +1 -0
- package/bin/session/storage/SqliteSessionStorage.js +581 -0
- package/bin/session/storage/SqliteSessionStorage.js.map +1 -0
- package/bin/tools/ask/AskQuestionsTool.d.ts.map +1 -1
- package/bin/tools/ask/AskQuestionsTool.js +3 -1
- package/bin/tools/ask/AskQuestionsTool.js.map +1 -1
- package/bin/types/action/ActionResult.d.ts +9 -9
- package/bin/types/action/ActionResult.d.ts.map +1 -1
- package/bin/types/action/ActionResult.js +1 -1
- package/bin/types/agent/AgentOptions.d.ts +10 -0
- package/bin/types/agent/AgentOptions.d.ts.map +1 -1
- package/bin/types/agent/AgentStorage.d.ts +3 -1
- package/bin/types/agent/AgentStorage.d.ts.map +1 -1
- package/bin/types/agent/SessionActor.d.ts +0 -9
- package/bin/types/agent/SessionActor.d.ts.map +1 -1
- package/bin/types/agent/SessionTypes.d.ts +5 -5
- package/bin/types/agent/SessionTypes.d.ts.map +1 -1
- package/bin/types/executor/SessionAssistantOutput.d.ts +15 -4
- package/bin/types/executor/SessionAssistantOutput.d.ts.map +1 -1
- package/bin/types/executor/SessionTurnContext.d.ts +17 -19
- package/bin/types/executor/SessionTurnContext.d.ts.map +1 -1
- package/bin/types/sdk/AgentSessionAction.d.ts +1 -1
- package/bin/types/sdk/AgentSessionAction.js +1 -1
- package/bin/types/sdk/AgentSessionPrompt.d.ts +14 -5
- package/bin/types/sdk/AgentSessionPrompt.d.ts.map +1 -1
- package/bin/types/sdk/AgentSessionPrompt.js +1 -1
- package/bin/types/sdk/AgentSessionPrompt.js.map +1 -1
- package/bin/types/session/AdaptivePartContextPolicy.d.ts +31 -0
- package/bin/types/session/AdaptivePartContextPolicy.d.ts.map +1 -0
- package/bin/types/session/AdaptivePartContextPolicy.js +7 -0
- package/bin/types/session/AdaptivePartContextPolicy.js.map +1 -0
- package/bin/types/session/{SessionAssistantMessageState.d.ts → SessionAgentMessageState.d.ts} +7 -7
- package/bin/types/session/SessionAgentMessageState.d.ts.map +1 -0
- package/bin/types/session/{SessionAssistantMessageState.js → SessionAgentMessageState.js} +1 -1
- package/bin/types/session/SessionAgentMessageState.js.map +1 -0
- package/bin/types/session/SessionCommand.d.ts +19 -7
- package/bin/types/session/SessionCommand.d.ts.map +1 -1
- package/bin/types/session/SessionComposer.d.ts +43 -43
- package/bin/types/session/SessionComposer.d.ts.map +1 -1
- package/bin/types/session/SessionComposer.js +2 -2
- package/bin/types/session/SessionComposition.d.ts +2 -5
- package/bin/types/session/SessionComposition.d.ts.map +1 -1
- package/bin/types/session/SessionContextPolicy.d.ts +70 -0
- package/bin/types/session/SessionContextPolicy.d.ts.map +1 -0
- package/bin/types/session/SessionContextPolicy.js +8 -0
- package/bin/types/session/SessionContextPolicy.js.map +1 -0
- package/bin/types/session/SessionExecution.d.ts +5 -32
- package/bin/types/session/SessionExecution.d.ts.map +1 -1
- package/bin/types/session/SessionLoop.d.ts +3 -5
- package/bin/types/session/SessionLoop.d.ts.map +1 -1
- package/bin/types/session/SessionMessages.d.ts +18 -28
- package/bin/types/session/SessionMessages.d.ts.map +1 -1
- package/bin/types/session/SessionOptions.d.ts +5 -5
- package/bin/types/session/SessionOptions.d.ts.map +1 -1
- package/bin/types/session/SessionPort.d.ts +8 -9
- package/bin/types/session/SessionPort.d.ts.map +1 -1
- package/bin/types/session/SessionState.d.ts +2 -5
- package/bin/types/session/SessionState.d.ts.map +1 -1
- package/bin/types/session/SessionSystem.d.ts +14 -0
- package/bin/types/session/SessionSystem.d.ts.map +1 -1
- package/bin/types/session/SessionTool.d.ts +2 -2
- package/bin/types/session/SessionTool.d.ts.map +1 -1
- package/bin/types/session/SessionTurnCompletion.d.ts +23 -0
- package/bin/types/session/SessionTurnCompletion.d.ts.map +1 -0
- package/bin/types/session/SessionTurnCompletion.js +8 -0
- package/bin/types/session/SessionTurnCompletion.js.map +1 -0
- package/bin/types/session/SessionTurnFileDiff.d.ts +42 -0
- package/bin/types/session/SessionTurnFileDiff.d.ts.map +1 -0
- package/bin/types/session/SessionTurnFileDiff.js +8 -0
- package/bin/types/session/SessionTurnFileDiff.js.map +1 -0
- package/bin/types/store/LocalStore.d.ts +6 -13
- package/bin/types/store/LocalStore.d.ts.map +1 -1
- package/bin/types/store/LocalStore.js +1 -1
- package/bin/types/store/SessionStorage.d.ts +103 -0
- package/bin/types/store/SessionStorage.d.ts.map +1 -0
- package/bin/types/store/SessionStorage.js +8 -0
- package/bin/types/store/SessionStorage.js.map +1 -0
- package/bin/types/store/SessionStore.d.ts +5 -3
- package/bin/types/store/SessionStore.d.ts.map +1 -1
- package/package.json +2 -2
- package/scripts/core-engine-context-compaction.test.mjs +96 -219
- package/scripts/core-engine-model-stream.test.mjs +2 -4
- package/scripts/executor-failure-result.test.mjs +14 -17
- package/scripts/session-agent-message-part-order.test.mjs +63 -0
- package/scripts/session-initialization.test.mjs +141 -0
- package/scripts/session-message-timeline.test.mjs +5 -6
- package/scripts/session-messages-error-part.test.mjs +175 -0
- package/scripts/session-messages-error.test.mjs +47 -6
- package/scripts/session-prompt-idempotency.test.mjs +91 -0
- package/scripts/session-queue.test.mjs +13 -12
- package/scripts/session-storage-sqlite.test.mjs +209 -0
- package/scripts/session-turn-context.test.mjs +21 -33
- package/src/agent/Agent.ts +48 -12
- package/src/agent/AgentInstructions.ts +2 -2
- package/src/agent/AgentMemoryStorage.ts +1 -0
- package/src/agent/AgentSessions.ts +31 -12
- package/src/executor/Executor.ts +47 -184
- package/src/executor/README.md +12 -13
- package/src/executor/composer/system/default/SystemPromptAssets.ts +0 -6
- package/src/executor/core-engine/CoreEngineContextCompaction.ts +3 -135
- package/src/executor/core-engine/CoreEngineRunner.ts +51 -273
- package/src/executor/core-engine/CoreEngineSignals.ts +9 -9
- package/src/executor/messages/SessionAttachmentMapper.ts +4 -4
- package/src/executor/messages/SessionMessageLog.ts +3 -3
- package/src/executor/messages/SessionModelMessages.ts +85 -103
- package/src/executor/model/ModelStepRunner.ts +9 -41
- package/src/executor/services/ExecutorRecoveryPolicy.ts +34 -127
- package/src/executor/types/SessionHistoryMeta.ts +1 -3
- package/src/index.ts +39 -47
- package/src/session/DefaultSessionComposer.ts +33 -30
- package/src/session/Session.ts +96 -227
- package/src/session/SessionComposition.ts +28 -65
- package/src/session/SessionLoop.ts +267 -370
- package/src/session/SessionMessages.ts +363 -242
- package/src/session/SessionQueue.ts +3 -2
- package/src/session/SessionState.ts +55 -101
- package/src/session/SessionSystem.ts +51 -1
- package/src/session/SessionTitle.ts +4 -4
- package/src/session/browse/Browse.ts +182 -468
- package/src/session/browse/SessionMessageTimeline.ts +63 -38
- package/src/session/composer/policies/AdaptivePartContextPolicy.ts +307 -0
- package/src/session/composer/policies/FullHistoryContextPolicy.ts +36 -0
- package/src/session/composer/policies/SessionSummaryPrompts.ts +42 -0
- package/src/session/execution/SessionAssistantOutputAdapter.ts +25 -11
- package/src/session/messages/{SessionActionMessageWriter.ts → SessionAgentActionPartWriter.ts} +8 -8
- package/src/session/messages/SessionAgentContent.ts +56 -0
- package/src/session/messages/SessionAgentMessageState.ts +378 -0
- package/src/session/messages/{SessionAssistantMessageWriter.ts → SessionAgentMessageWriter.ts} +89 -60
- package/src/session/messages/SessionForkMessageFiles.ts +25 -1
- package/src/session/messages/SessionMessageInteractionWriter.ts +19 -19
- package/src/session/messages/SessionMessageText.ts +3 -4
- package/src/session/messages/SessionTurnFileDiffData.ts +3 -3
- package/src/session/messages/SessionUserMessage.ts +10 -7
- package/src/session/preview/SessionMessagePreview.ts +26 -9
- package/src/session/runtime/SessionTurnCompletion.ts +159 -0
- package/src/session/runtime/SessionTurnContext.ts +20 -21
- package/src/session/runtime/SessionTurnFileDiff.ts +105 -0
- package/src/session/storage/LocalSessionDataStore.ts +27 -176
- package/src/session/storage/LocalSessionStore.ts +170 -38
- package/src/session/storage/LocalStorePaths.ts +14 -86
- package/src/session/storage/Metadata.ts +4 -13
- package/src/session/storage/RuntimeSessionPort.ts +7 -7
- package/src/session/storage/SessionStorageCodec.ts +465 -0
- package/src/session/storage/SessionStorageSchema.ts +132 -0
- package/src/session/storage/SqliteSessionStorage.ts +776 -0
- package/src/tools/ask/AskQuestionsTool.ts +3 -1
- package/src/types/action/ActionResult.ts +10 -10
- package/src/types/agent/AgentOptions.ts +11 -0
- package/src/types/agent/AgentStorage.ts +3 -1
- package/src/types/agent/SessionActor.ts +0 -10
- package/src/types/agent/SessionTypes.ts +5 -5
- package/src/types/executor/SessionAssistantOutput.ts +15 -4
- package/src/types/executor/SessionTurnContext.ts +25 -22
- package/src/types/sdk/AgentSessionAction.ts +1 -1
- package/src/types/sdk/AgentSessionPrompt.ts +15 -5
- package/src/types/session/AdaptivePartContextPolicy.ts +37 -0
- package/src/types/session/{SessionAssistantMessageState.ts → SessionAgentMessageState.ts} +6 -6
- package/src/types/session/SessionCommand.ts +21 -7
- package/src/types/session/SessionComposer.ts +48 -48
- package/src/types/session/SessionComposition.ts +2 -5
- package/src/types/session/SessionContextPolicy.ts +77 -0
- package/src/types/session/SessionExecution.ts +11 -36
- package/src/types/session/SessionLoop.ts +3 -8
- package/src/types/session/SessionMessages.ts +19 -29
- package/src/types/session/SessionOptions.ts +5 -5
- package/src/types/session/SessionPort.ts +10 -10
- package/src/types/session/SessionState.ts +2 -5
- package/src/types/session/SessionSystem.ts +19 -0
- package/src/types/session/SessionTool.ts +2 -2
- package/src/types/session/SessionTurnCompletion.ts +24 -0
- package/src/types/session/SessionTurnFileDiff.ts +44 -0
- package/src/types/store/LocalStore.ts +6 -14
- package/src/types/store/SessionStorage.ts +121 -0
- package/src/types/store/SessionStore.ts +6 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.d.ts +0 -45
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.d.ts.map +0 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.js +0 -144
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.js.map +0 -1
- package/bin/executor/composer/system/SessionSystemComposer.d.ts +0 -23
- package/bin/executor/composer/system/SessionSystemComposer.d.ts.map +0 -1
- package/bin/executor/composer/system/SessionSystemComposer.js +0 -9
- package/bin/executor/composer/system/SessionSystemComposer.js.map +0 -1
- package/bin/executor/composer/system/default/DefaultSessionSystemComposer.d.ts +0 -43
- package/bin/executor/composer/system/default/DefaultSessionSystemComposer.d.ts.map +0 -1
- package/bin/executor/composer/system/default/DefaultSessionSystemComposer.js +0 -42
- package/bin/executor/composer/system/default/DefaultSessionSystemComposer.js.map +0 -1
- package/bin/executor/composer/system/default/PromptRenderer.d.ts +0 -35
- package/bin/executor/composer/system/default/PromptRenderer.d.ts.map +0 -1
- package/bin/executor/composer/system/default/PromptRenderer.js +0 -23
- package/bin/executor/composer/system/default/PromptRenderer.js.map +0 -1
- package/bin/executor/composer/system/default/SystemDomain.d.ts +0 -151
- package/bin/executor/composer/system/default/SystemDomain.d.ts.map +0 -1
- package/bin/executor/composer/system/default/SystemDomain.js +0 -162
- package/bin/executor/composer/system/default/SystemDomain.js.map +0 -1
- package/bin/executor/composer/system/default/assets/task.prompt.d.ts +0 -7
- package/bin/executor/composer/system/default/assets/task.prompt.d.ts.map +0 -1
- package/bin/executor/composer/system/default/assets/task.prompt.js +0 -8
- package/bin/executor/composer/system/default/assets/task.prompt.js.map +0 -1
- package/bin/executor/composer/system/default/variables/GeoContext.d.ts +0 -14
- package/bin/executor/composer/system/default/variables/GeoContext.d.ts.map +0 -1
- package/bin/executor/composer/system/default/variables/GeoContext.js +0 -150
- package/bin/executor/composer/system/default/variables/GeoContext.js.map +0 -1
- package/bin/executor/composer/system/default/variables/PromptTypes.d.ts +0 -36
- package/bin/executor/composer/system/default/variables/PromptTypes.d.ts.map +0 -1
- package/bin/executor/composer/system/default/variables/PromptTypes.js +0 -9
- package/bin/executor/composer/system/default/variables/PromptTypes.js.map +0 -1
- package/bin/executor/composer/system/default/variables/VariableReplacer.d.ts +0 -61
- package/bin/executor/composer/system/default/variables/VariableReplacer.d.ts.map +0 -1
- package/bin/executor/composer/system/default/variables/VariableReplacer.js +0 -93
- package/bin/executor/composer/system/default/variables/VariableReplacer.js.map +0 -1
- package/bin/executor/core-engine/CoreEngineMessageState.d.ts +0 -63
- package/bin/executor/core-engine/CoreEngineMessageState.d.ts.map +0 -1
- package/bin/executor/core-engine/CoreEngineMessageState.js +0 -81
- package/bin/executor/core-engine/CoreEngineMessageState.js.map +0 -1
- package/bin/session/SessionCommand.d.ts +0 -24
- package/bin/session/SessionCommand.d.ts.map +0 -1
- package/bin/session/SessionCommand.js +0 -35
- package/bin/session/SessionCommand.js.map +0 -1
- package/bin/session/messages/SessionActionMessageWriter.d.ts.map +0 -1
- package/bin/session/messages/SessionActionMessageWriter.js.map +0 -1
- package/bin/session/messages/SessionAssistantMessageState.d.ts +0 -49
- package/bin/session/messages/SessionAssistantMessageState.d.ts.map +0 -1
- package/bin/session/messages/SessionAssistantMessageState.js +0 -296
- package/bin/session/messages/SessionAssistantMessageState.js.map +0 -1
- package/bin/session/messages/SessionAssistantMessageWriter.d.ts.map +0 -1
- package/bin/session/messages/SessionAssistantMessageWriter.js.map +0 -1
- package/bin/session/messages/SessionMessageCompaction.d.ts +0 -29
- package/bin/session/messages/SessionMessageCompaction.d.ts.map +0 -1
- package/bin/session/messages/SessionMessageCompaction.js +0 -128
- package/bin/session/messages/SessionMessageCompaction.js.map +0 -1
- package/bin/session/runtime/SessionCompactOperation.d.ts +0 -29
- package/bin/session/runtime/SessionCompactOperation.d.ts.map +0 -1
- package/bin/session/runtime/SessionCompactOperation.js +0 -66
- package/bin/session/runtime/SessionCompactOperation.js.map +0 -1
- package/bin/session/runtime/SessionHistoryCompaction.d.ts +0 -22
- package/bin/session/runtime/SessionHistoryCompaction.d.ts.map +0 -1
- package/bin/session/runtime/SessionHistoryCompaction.js +0 -31
- package/bin/session/runtime/SessionHistoryCompaction.js.map +0 -1
- package/bin/session/storage/JsonlSessionMessageStore.d.ts +0 -77
- package/bin/session/storage/JsonlSessionMessageStore.d.ts.map +0 -1
- package/bin/session/storage/JsonlSessionMessageStore.js +0 -419
- package/bin/session/storage/JsonlSessionMessageStore.js.map +0 -1
- package/bin/session/storage/SessionMessageStoreFactory.d.ts +0 -12
- package/bin/session/storage/SessionMessageStoreFactory.d.ts.map +0 -1
- package/bin/session/storage/SessionMessageStoreFactory.js +0 -13
- package/bin/session/storage/SessionMessageStoreFactory.js.map +0 -1
- package/bin/types/common/Template.d.ts +0 -9
- package/bin/types/common/Template.d.ts.map +0 -1
- package/bin/types/common/Template.js +0 -9
- package/bin/types/common/Template.js.map +0 -1
- package/bin/types/sdk/AgentSessionCompact.d.ts +0 -30
- package/bin/types/sdk/AgentSessionCompact.d.ts.map +0 -1
- package/bin/types/sdk/AgentSessionCompact.js +0 -8
- package/bin/types/sdk/AgentSessionCompact.js.map +0 -1
- package/bin/types/session/SessionAssistantMessageState.d.ts.map +0 -1
- package/bin/types/session/SessionAssistantMessageState.js.map +0 -1
- package/bin/types/session/SessionSegment.d.ts +0 -57
- package/bin/types/session/SessionSegment.d.ts.map +0 -1
- package/bin/types/session/SessionSegment.js +0 -8
- package/bin/types/session/SessionSegment.js.map +0 -1
- package/bin/types/store/SessionDataStore.d.ts +0 -88
- package/bin/types/store/SessionDataStore.d.ts.map +0 -1
- package/bin/types/store/SessionDataStore.js +0 -9
- package/bin/types/store/SessionDataStore.js.map +0 -1
- package/bin/utils/Template.d.ts +0 -17
- package/bin/utils/Template.d.ts.map +0 -1
- package/bin/utils/Template.js +0 -24
- package/bin/utils/Template.js.map +0 -1
- package/scripts/session-compaction-prompts.test.mjs +0 -49
- package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.ts +0 -162
- package/src/executor/composer/system/SessionSystemComposer.ts +0 -25
- package/src/executor/composer/system/default/DefaultSessionSystemComposer.ts +0 -76
- package/src/executor/composer/system/default/PromptRenderer.ts +0 -52
- package/src/executor/composer/system/default/SystemDomain.ts +0 -301
- package/src/executor/composer/system/default/assets/task.prompt.ts +0 -9
- package/src/executor/composer/system/default/assets/task.prompt.ts.txt +0 -33
- package/src/executor/composer/system/default/variables/GeoContext.ts +0 -180
- package/src/executor/composer/system/default/variables/PromptTypes.ts +0 -37
- package/src/executor/composer/system/default/variables/VariableReplacer.ts +0 -154
- package/src/executor/core-engine/CoreEngineMessageState.ts +0 -117
- package/src/session/SessionCommand.ts +0 -42
- package/src/session/messages/SessionAssistantMessageState.ts +0 -392
- package/src/session/messages/SessionMessageCompaction.ts +0 -160
- package/src/session/runtime/SessionCompactOperation.ts +0 -93
- package/src/session/runtime/SessionHistoryCompaction.ts +0 -45
- package/src/session/storage/JsonlSessionMessageStore.ts +0 -513
- package/src/session/storage/SessionMessageStoreFactory.ts +0 -18
- package/src/types/common/Template.ts +0 -9
- package/src/types/sdk/AgentSessionCompact.ts +0 -32
- package/src/types/session/SessionSegment.ts +0 -62
- package/src/types/store/SessionDataStore.ts +0 -113
- package/src/utils/Template.ts +0 -28
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* - Queue 由 Session 持有;这里不解释配置种类,只执行出队 Command。
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
10
11
|
import { nanoid } from "nanoid";
|
|
11
|
-
import type {
|
|
12
|
+
import type { SessionAgentMessage, SessionUserMessage } from "@downcity/type";
|
|
12
13
|
import type { SessionActionEvent } from "@downcity/type";
|
|
13
14
|
import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
|
|
14
15
|
import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
|
|
@@ -18,7 +19,6 @@ import type {
|
|
|
18
19
|
} from "@/types/sdk/AgentSessionTurn.js";
|
|
19
20
|
import { is_agent_session_prompt_input_empty } from "@/types/sdk/AgentSessionPrompt.js";
|
|
20
21
|
import type {
|
|
21
|
-
SessionCompactHistory,
|
|
22
22
|
SessionExecutor,
|
|
23
23
|
SessionTurnExecutionResult,
|
|
24
24
|
} from "@/types/session/SessionExecution.js";
|
|
@@ -26,31 +26,37 @@ import type { SessionTurnContext } from "@/types/executor/SessionTurnContext.js"
|
|
|
26
26
|
import { create_session_turn_context } from "@/session/runtime/SessionTurnContext.js";
|
|
27
27
|
import { SessionEventHub } from "@/session/runtime/SessionEventHub.js";
|
|
28
28
|
import { SessionState } from "@/session/SessionState.js";
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
normalize_session_user_parts,
|
|
31
|
+
SessionMessages,
|
|
32
|
+
} from "@/session/SessionMessages.js";
|
|
30
33
|
import type { ShellApprovalGateway } from "@downcity/type";
|
|
31
34
|
import type {
|
|
32
35
|
SessionInteractionLifecycle,
|
|
33
36
|
SessionInteractionPort,
|
|
34
37
|
} from "@downcity/type";
|
|
35
38
|
import { SessionAssistantOutputAdapter } from "@/session/execution/SessionAssistantOutputAdapter.js";
|
|
36
|
-
import type { SessionAssistantOutput } from "@/types/executor/SessionAssistantOutput.js";
|
|
37
39
|
import { SessionQueue } from "@/session/SessionQueue.js";
|
|
38
|
-
import {
|
|
40
|
+
import { extract_session_message_text } from "@/session/messages/SessionMessageText.js";
|
|
39
41
|
import type {
|
|
40
42
|
ActiveSessionTurnState,
|
|
41
43
|
SessionDeferred,
|
|
42
44
|
SessionLoopOptions,
|
|
43
45
|
} from "@/types/session/SessionLoop.js";
|
|
44
|
-
import type {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
build_session_turn_file_diff_summary,
|
|
49
|
-
} from "@/session/messages/SessionTurnFileDiffBuilder.js";
|
|
50
|
-
import { SESSION_HOOK_POINTS } from "@/session/SessionHookPoints.js";
|
|
51
|
-
import type { SessionTurnCommittedHookValue } from "@downcity/type";
|
|
52
|
-
import type { JsonValue } from "@downcity/type";
|
|
46
|
+
import type {
|
|
47
|
+
SessionCommand,
|
|
48
|
+
SessionCommandCompletion,
|
|
49
|
+
} from "@/types/session/SessionCommand.js";
|
|
53
50
|
import { create_session_model_request_warning } from "@/session/runtime/SessionModelRequestWarning.js";
|
|
51
|
+
import {
|
|
52
|
+
complete_session_turn,
|
|
53
|
+
fail_session_turn,
|
|
54
|
+
} from "@/session/runtime/SessionTurnCompletion.js";
|
|
55
|
+
import {
|
|
56
|
+
append_session_turn_file_diff,
|
|
57
|
+
publish_session_turn_file_diff,
|
|
58
|
+
} from "@/session/runtime/SessionTurnFileDiff.js";
|
|
59
|
+
import type { SessionTurnCompletionOptions } from "@/types/session/SessionTurnCompletion.js";
|
|
54
60
|
|
|
55
61
|
const TURN_STOPPED_MESSAGE = "Turn stopped";
|
|
56
62
|
const QUEUED_PROMPT_CANCELLED_MESSAGE =
|
|
@@ -64,7 +70,7 @@ export class SessionLoop {
|
|
|
64
70
|
private readonly session_origin: SessionLoopOptions["session_origin"];
|
|
65
71
|
private readonly workspace_path: string;
|
|
66
72
|
private readonly executor: SessionExecutor;
|
|
67
|
-
private readonly
|
|
73
|
+
private readonly maintain_context: SessionLoopOptions["maintain_context"];
|
|
68
74
|
private readonly state: SessionState;
|
|
69
75
|
private readonly messages: SessionMessages;
|
|
70
76
|
private readonly events: SessionEventHub;
|
|
@@ -76,14 +82,15 @@ export class SessionLoop {
|
|
|
76
82
|
private pending_prompt_count = 0;
|
|
77
83
|
private processing_promise: Promise<void> | null = null;
|
|
78
84
|
private active_turn: ActiveSessionTurnState | null = null;
|
|
79
|
-
|
|
85
|
+
/** 尚未完成 canonical 接收的幂等 Prompt,防止进程内并发重复入队。 */
|
|
86
|
+
private readonly pending_request_handles = new Map<string, Promise<AgentSessionTurnHandle>>();
|
|
80
87
|
|
|
81
88
|
constructor(options: SessionLoopOptions) {
|
|
82
89
|
this.session_id = String(options.session_id || "").trim();
|
|
83
90
|
this.session_origin = options.session_origin;
|
|
84
91
|
this.workspace_path = String(options.workspace_path || "").trim();
|
|
85
92
|
this.executor = options.executor;
|
|
86
|
-
this.
|
|
93
|
+
this.maintain_context = options.maintain_context;
|
|
87
94
|
this.state = options.state;
|
|
88
95
|
this.messages = options.messages;
|
|
89
96
|
this.events = options.events;
|
|
@@ -107,21 +114,67 @@ export class SessionLoop {
|
|
|
107
114
|
throw new Error("session.prompt requires a non-empty query");
|
|
108
115
|
}
|
|
109
116
|
await this.state.ensure_runnable();
|
|
117
|
+
const request_identity = resolve_prompt_request_identity(this.session_id, input.request_id);
|
|
118
|
+
if (!request_identity) return await this.enqueue_prompt(input);
|
|
119
|
+
const pending_handle = this.pending_request_handles.get(request_identity.turn_id);
|
|
120
|
+
if (pending_handle) return await pending_handle;
|
|
121
|
+
const operation = this.prompt_with_identity(input, request_identity);
|
|
122
|
+
this.pending_request_handles.set(request_identity.turn_id, operation);
|
|
123
|
+
try {
|
|
124
|
+
return await operation;
|
|
125
|
+
} finally {
|
|
126
|
+
if (this.pending_request_handles.get(request_identity.turn_id) === operation) {
|
|
127
|
+
this.pending_request_handles.delete(request_identity.turn_id);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** 解析已有幂等结果,或把同一个稳定 Prompt 加入队列。 */
|
|
133
|
+
private async prompt_with_identity(
|
|
134
|
+
input: AgentSessionPromptInput,
|
|
135
|
+
request_identity: PromptRequestIdentity,
|
|
136
|
+
): Promise<AgentSessionTurnHandle> {
|
|
137
|
+
const existing_handle = await this.resolve_idempotent_prompt(request_identity);
|
|
138
|
+
if (existing_handle) return existing_handle;
|
|
139
|
+
const persisted_message = this.messages.get_message(request_identity.message_id);
|
|
140
|
+
return await this.enqueue_prompt(input, request_identity, persisted_message?.role === "user"
|
|
141
|
+
? persisted_message
|
|
142
|
+
: undefined);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** 把一个已校验的 Prompt 加入 Session FIFO。 */
|
|
146
|
+
private async enqueue_prompt(
|
|
147
|
+
input: AgentSessionPromptInput,
|
|
148
|
+
request_identity?: PromptRequestIdentity,
|
|
149
|
+
persisted_message?: SessionUserMessage,
|
|
150
|
+
): Promise<AgentSessionTurnHandle> {
|
|
110
151
|
const deferred_handle = create_deferred<AgentSessionTurnHandle>();
|
|
111
152
|
this.pending_prompt_count += 1;
|
|
112
|
-
this.
|
|
153
|
+
this.enqueue_command({
|
|
154
|
+
kind: "prompt",
|
|
155
|
+
...(request_identity ? { turn_id: request_identity.turn_id } : {}),
|
|
113
156
|
execute: async () => {
|
|
114
|
-
await this.execute_prompt_command(
|
|
157
|
+
await this.execute_prompt_command(
|
|
158
|
+
input,
|
|
159
|
+
deferred_handle,
|
|
160
|
+
request_identity?.message_id,
|
|
161
|
+
persisted_message,
|
|
162
|
+
);
|
|
115
163
|
},
|
|
116
164
|
cancel: () => {
|
|
117
165
|
this.pending_prompt_count = Math.max(0, this.pending_prompt_count - 1);
|
|
118
166
|
this.resolve_cancelled_prompt(deferred_handle);
|
|
119
167
|
},
|
|
120
|
-
})
|
|
121
|
-
this.ensure_processing();
|
|
168
|
+
});
|
|
122
169
|
return await deferred_handle.promise;
|
|
123
170
|
}
|
|
124
171
|
|
|
172
|
+
/** 追加 Command,并确保空闲 Session 也会主动消费维护操作。 */
|
|
173
|
+
enqueue_command(command: SessionCommand): void {
|
|
174
|
+
this.queue.enqueue_command(command);
|
|
175
|
+
this.ensure_processing();
|
|
176
|
+
}
|
|
177
|
+
|
|
125
178
|
/**
|
|
126
179
|
* 判断是否存在等待并入下一 Session step 的 prompt。
|
|
127
180
|
*/
|
|
@@ -154,7 +207,7 @@ export class SessionLoop {
|
|
|
154
207
|
* - Session 会用它阻止内部 direct execution 与 actor 模式并发混用。
|
|
155
208
|
*/
|
|
156
209
|
is_active(): boolean {
|
|
157
|
-
return this.processing_promise !== null || this.
|
|
210
|
+
return this.processing_promise !== null || this.has_pending_command();
|
|
158
211
|
}
|
|
159
212
|
|
|
160
213
|
/**
|
|
@@ -186,15 +239,22 @@ export class SessionLoop {
|
|
|
186
239
|
if (this.processing_promise) return;
|
|
187
240
|
this.processing_promise = this.process_loop().finally(() => {
|
|
188
241
|
this.processing_promise = null;
|
|
189
|
-
if (this.
|
|
242
|
+
if (this.has_pending_command()) {
|
|
190
243
|
this.ensure_processing();
|
|
191
244
|
}
|
|
192
245
|
});
|
|
193
246
|
}
|
|
194
247
|
|
|
195
248
|
private async process_loop(): Promise<void> {
|
|
196
|
-
while (this.
|
|
197
|
-
const
|
|
249
|
+
while (this.has_pending_command()) {
|
|
250
|
+
const command = this.queue.take_next();
|
|
251
|
+
if (!command) return;
|
|
252
|
+
if (command.kind === "maintenance") {
|
|
253
|
+
await this.execute_maintenance_command(command);
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const turn_id = command.turn_id || `turn:${this.session_id}:${Date.now()}:${nanoid(6)}`;
|
|
198
258
|
const active_turn = create_active_session_turn_state(turn_id);
|
|
199
259
|
this.active_turn = active_turn;
|
|
200
260
|
active_turn.turn_context = this.create_turn_context(active_turn);
|
|
@@ -208,20 +268,26 @@ export class SessionLoop {
|
|
|
208
268
|
created_at: Date.now(),
|
|
209
269
|
});
|
|
210
270
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
271
|
+
try {
|
|
272
|
+
await this.execute_command(command);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
await this.fail_active_turn(active_turn, error);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** 在没有 Active Turn 时执行 Session 级维护命令。 */
|
|
280
|
+
private async execute_maintenance_command(command: SessionCommand): Promise<void> {
|
|
281
|
+
try {
|
|
282
|
+
await this.execute_command(command);
|
|
283
|
+
} catch (error) {
|
|
284
|
+
try {
|
|
285
|
+
await this.logger.log("warn", "[agent] session maintenance command failed", {
|
|
286
|
+
session_id: this.session_id,
|
|
287
|
+
error: error instanceof Error ? error.message : String(error),
|
|
288
|
+
});
|
|
289
|
+
} catch {
|
|
290
|
+
// Maintenance Command 已经失败,日志失败不能阻止后续 Command 继续执行。
|
|
225
291
|
}
|
|
226
292
|
}
|
|
227
293
|
}
|
|
@@ -233,35 +299,26 @@ export class SessionLoop {
|
|
|
233
299
|
/**
|
|
234
300
|
* 在下一 Session step 检查点按入队顺序提交配置并持久化 steer。
|
|
235
301
|
*/
|
|
236
|
-
private async drain_queued_inputs(
|
|
237
|
-
active_turn: ActiveSessionTurnState,
|
|
238
|
-
): Promise<SessionUserMessage[]> {
|
|
302
|
+
private async drain_queued_inputs(): Promise<void> {
|
|
239
303
|
const drained = this.queue.drain();
|
|
240
|
-
if (drained.length <= 0) return
|
|
241
|
-
const merged: SessionUserMessage[] = [];
|
|
242
|
-
this.checkpoint_merged_messages = merged;
|
|
304
|
+
if (drained.length <= 0) return;
|
|
243
305
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
306
|
+
for (let index = 0; index < drained.length; index += 1) {
|
|
307
|
+
const command = drained[index];
|
|
308
|
+
try {
|
|
309
|
+
await this.execute_command(command);
|
|
310
|
+
} catch {
|
|
311
|
+
// Prompt 持久化失败时恢复尚未处理的对象;Action 自己负责失败观测。
|
|
312
|
+
this.queue.restore_front(drained.slice(index));
|
|
313
|
+
break;
|
|
254
314
|
}
|
|
255
|
-
} finally {
|
|
256
|
-
this.checkpoint_merged_messages = null;
|
|
257
315
|
}
|
|
258
|
-
|
|
259
|
-
return merged;
|
|
260
316
|
}
|
|
261
317
|
|
|
262
318
|
/** 执行 Command,并尽力持久化其声明的 canonical 完成信息。 */
|
|
263
319
|
private async execute_command(command: SessionCommand): Promise<void> {
|
|
264
|
-
|
|
320
|
+
await command.execute();
|
|
321
|
+
const completion = command.completion;
|
|
265
322
|
if (!completion) return;
|
|
266
323
|
await this.persist_command_completion(completion);
|
|
267
324
|
}
|
|
@@ -270,12 +327,12 @@ export class SessionLoop {
|
|
|
270
327
|
private async persist_command_completion(
|
|
271
328
|
completion: SessionCommandCompletion,
|
|
272
329
|
): Promise<void> {
|
|
273
|
-
const turn_id = this.
|
|
330
|
+
const turn_id = this.current_turn_id();
|
|
274
331
|
try {
|
|
275
332
|
await this.persist_action_event({
|
|
276
333
|
action_id: completion.id,
|
|
277
334
|
action_type: "command",
|
|
278
|
-
turn_id,
|
|
335
|
+
...(turn_id ? { turn_id } : {}),
|
|
279
336
|
title: completion.title,
|
|
280
337
|
...(completion.description
|
|
281
338
|
? { description: completion.description }
|
|
@@ -297,58 +354,22 @@ export class SessionLoop {
|
|
|
297
354
|
}
|
|
298
355
|
}
|
|
299
356
|
|
|
300
|
-
/** 在当前 Turn 上执行一次显式历史压缩。 */
|
|
301
|
-
async compact_history(
|
|
302
|
-
compact_id: string,
|
|
303
|
-
): ReturnType<SessionCompactHistory> {
|
|
304
|
-
const turn_id = this.require_active_turn().turn_id;
|
|
305
|
-
const result = await this.compact_history_handler({ turn_id });
|
|
306
|
-
if (
|
|
307
|
-
result.compacted &&
|
|
308
|
-
this.active_turn?.turn_context
|
|
309
|
-
) {
|
|
310
|
-
this.require_active_turn().history_reload_requested = true;
|
|
311
|
-
}
|
|
312
|
-
if (result.reason === "nothing_to_compact") {
|
|
313
|
-
try {
|
|
314
|
-
await this.persist_action_event({
|
|
315
|
-
action_id: compact_id,
|
|
316
|
-
action_type: "history-compaction",
|
|
317
|
-
turn_id,
|
|
318
|
-
title: "Session messages already compact",
|
|
319
|
-
description: "The Session has no active messages to compact.",
|
|
320
|
-
status: "completed",
|
|
321
|
-
});
|
|
322
|
-
} catch (error) {
|
|
323
|
-
try {
|
|
324
|
-
await this.logger.log("warn", "[agent] compact result persistence failed", {
|
|
325
|
-
session_id: this.session_id,
|
|
326
|
-
compact_id,
|
|
327
|
-
error: error instanceof Error ? error.message : String(error),
|
|
328
|
-
});
|
|
329
|
-
} catch {
|
|
330
|
-
// 领域结果已经确定,Action 与日志失败都不能把成功压缩改写为失败。
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
return result;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
357
|
/** 执行一个出队 Prompt;首条 Prompt 启动 Turn,后续 Prompt 作为 steer 合并。 */
|
|
338
358
|
private async execute_prompt_command(
|
|
339
359
|
input: AgentSessionPromptInput,
|
|
340
360
|
deferred_handle: SessionDeferred<AgentSessionTurnHandle>,
|
|
361
|
+
message_id?: string,
|
|
362
|
+
persisted_message?: SessionUserMessage,
|
|
341
363
|
): Promise<void> {
|
|
342
364
|
const active_turn = this.require_active_turn();
|
|
343
365
|
if (active_turn.prompt_started) {
|
|
344
366
|
const message = await this.persist_prompt_message(
|
|
345
367
|
input,
|
|
346
368
|
active_turn.turn_id,
|
|
347
|
-
"steer",
|
|
348
369
|
);
|
|
370
|
+
active_turn.turn_context?.input.observe_user_message(message);
|
|
349
371
|
this.pending_prompt_count = Math.max(0, this.pending_prompt_count - 1);
|
|
350
372
|
deferred_handle.resolve(create_turn_handle(active_turn));
|
|
351
|
-
this.checkpoint_merged_messages?.push(message);
|
|
352
373
|
return;
|
|
353
374
|
}
|
|
354
375
|
|
|
@@ -356,15 +377,25 @@ export class SessionLoop {
|
|
|
356
377
|
this.pending_prompt_count = Math.max(0, this.pending_prompt_count - 1);
|
|
357
378
|
let handle_resolved = false;
|
|
358
379
|
try {
|
|
359
|
-
await this.persist_prompt_message(
|
|
380
|
+
const message = persisted_message || await this.persist_prompt_message(
|
|
381
|
+
input,
|
|
382
|
+
active_turn.turn_id,
|
|
383
|
+
message_id,
|
|
384
|
+
);
|
|
385
|
+
active_turn.turn_context?.input.observe_user_message(message);
|
|
360
386
|
// 只有 canonical user message 已经写入 Session 后,调用方才认为输入被接收。
|
|
361
387
|
deferred_handle.resolve(create_turn_handle(active_turn));
|
|
362
388
|
handle_resolved = true;
|
|
363
389
|
const result = await this.execute_prompt_turn({
|
|
364
390
|
active_turn,
|
|
365
|
-
prompt_input: input,
|
|
366
391
|
});
|
|
367
|
-
await
|
|
392
|
+
const final_result = await complete_session_turn(
|
|
393
|
+
this.turn_completion_options(),
|
|
394
|
+
active_turn,
|
|
395
|
+
result,
|
|
396
|
+
);
|
|
397
|
+
if (this.active_turn === active_turn) this.active_turn = null;
|
|
398
|
+
active_turn.deferred_finished.resolve(final_result);
|
|
368
399
|
} catch (error) {
|
|
369
400
|
// 持久化失败时仍兑现句柄,让调用方可以观察到失败的 Turn,而不是永久等待。
|
|
370
401
|
if (!handle_resolved) deferred_handle.resolve(create_turn_handle(active_turn));
|
|
@@ -378,89 +409,18 @@ export class SessionLoop {
|
|
|
378
409
|
throw new Error("Session Command requires an active Turn");
|
|
379
410
|
}
|
|
380
411
|
|
|
381
|
-
/**
|
|
382
|
-
private async finish_active_turn(
|
|
383
|
-
active_turn: ActiveSessionTurnState,
|
|
384
|
-
result: SessionTurnExecutionResult,
|
|
385
|
-
): Promise<void> {
|
|
386
|
-
const stopped = active_turn.turn_context?.lifecycle.abort_signal.aborted === true;
|
|
387
|
-
const final_result: AgentSessionTurnResult = {
|
|
388
|
-
turn_id: active_turn.turn_id,
|
|
389
|
-
text: result.text,
|
|
390
|
-
success: stopped ? false : result.success,
|
|
391
|
-
...(stopped
|
|
392
|
-
? { error: TURN_STOPPED_MESSAGE }
|
|
393
|
-
: result.error ? { error: result.error } : {}),
|
|
394
|
-
};
|
|
395
|
-
active_turn.result = final_result;
|
|
396
|
-
this.events.publish({
|
|
397
|
-
mutation_id: nanoid(),
|
|
398
|
-
variant: "turn",
|
|
399
|
-
type: "finish",
|
|
400
|
-
session_id: this.session_id,
|
|
401
|
-
turn_id: active_turn.turn_id,
|
|
402
|
-
status: stopped ? "stopped" : final_result.success ? "completed" : "failed",
|
|
403
|
-
created_at: Date.now(),
|
|
404
|
-
text: final_result.text,
|
|
405
|
-
...(final_result.error ? { error: final_result.error } : {}),
|
|
406
|
-
});
|
|
407
|
-
await this.notify_turn_committed(
|
|
408
|
-
active_turn,
|
|
409
|
-
stopped ? "stopped" : final_result.success ? "completed" : "failed",
|
|
410
|
-
);
|
|
411
|
-
await this.dispose_turn_context(active_turn);
|
|
412
|
-
active_turn.deferred_finished.resolve(final_result);
|
|
413
|
-
if (this.active_turn === active_turn) this.active_turn = null;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/** 以失败结果结束当前 Active Turn,并尽力持久化 Error Message。 */
|
|
412
|
+
/** 以失败结果结束当前 Active Turn,并尽力持久化包含 Error Part 的 Agent Message。 */
|
|
417
413
|
private async fail_active_turn(
|
|
418
414
|
active_turn: ActiveSessionTurnState,
|
|
419
415
|
error: unknown,
|
|
420
416
|
): Promise<void> {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
const message = stopped
|
|
424
|
-
? TURN_STOPPED_MESSAGE
|
|
425
|
-
: error instanceof Error ? error.message : String(error);
|
|
426
|
-
const final_result: AgentSessionTurnResult = {
|
|
427
|
-
turn_id: active_turn.turn_id,
|
|
428
|
-
text: "",
|
|
429
|
-
success: false,
|
|
430
|
-
error: message,
|
|
431
|
-
};
|
|
432
|
-
active_turn.result = final_result;
|
|
433
|
-
if (message !== TURN_STOPPED_MESSAGE) {
|
|
434
|
-
try {
|
|
435
|
-
await this.messages.append_error_message({
|
|
436
|
-
scope: "turn",
|
|
437
|
-
turn_id: active_turn.turn_id,
|
|
438
|
-
code: "turn_execution_failed",
|
|
439
|
-
message,
|
|
440
|
-
recoverable: true,
|
|
441
|
-
});
|
|
442
|
-
} catch {
|
|
443
|
-
// Error Message 写入失败不能阻止 Turn Handle 收口。
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
this.events.publish({
|
|
447
|
-
mutation_id: nanoid(),
|
|
448
|
-
variant: "turn",
|
|
449
|
-
type: "finish",
|
|
450
|
-
session_id: this.session_id,
|
|
451
|
-
turn_id: active_turn.turn_id,
|
|
452
|
-
status: stopped ? "stopped" : "failed",
|
|
453
|
-
created_at: Date.now(),
|
|
454
|
-
text: "",
|
|
455
|
-
error: message,
|
|
456
|
-
});
|
|
457
|
-
await this.notify_turn_committed(
|
|
417
|
+
const final_result = await fail_session_turn(
|
|
418
|
+
this.turn_completion_options(),
|
|
458
419
|
active_turn,
|
|
459
|
-
|
|
420
|
+
error,
|
|
460
421
|
);
|
|
461
|
-
await this.dispose_turn_context(active_turn);
|
|
462
|
-
active_turn.deferred_finished.resolve(final_result);
|
|
463
422
|
if (this.active_turn === active_turn) this.active_turn = null;
|
|
423
|
+
active_turn.deferred_finished.resolve(final_result);
|
|
464
424
|
}
|
|
465
425
|
|
|
466
426
|
/** 为一条尚未执行的 Prompt 创建可观测取消结果。 */
|
|
@@ -503,7 +463,6 @@ export class SessionLoop {
|
|
|
503
463
|
/** 执行一个 Turn 内的模型与 Tool Step Loop。 */
|
|
504
464
|
private async execute_prompt_turn(input: {
|
|
505
465
|
active_turn: ActiveSessionTurnState;
|
|
506
|
-
prompt_input: AgentSessionPromptInput;
|
|
507
466
|
}): Promise<{
|
|
508
467
|
text: string;
|
|
509
468
|
success: boolean;
|
|
@@ -514,45 +473,34 @@ export class SessionLoop {
|
|
|
514
473
|
if (!turn_context || !assistant_output) {
|
|
515
474
|
throw new Error("Active Session Turn requires an initialized context");
|
|
516
475
|
}
|
|
517
|
-
const query = input.prompt_input.query;
|
|
518
|
-
const executor_query = typeof query === "string"
|
|
519
|
-
? query
|
|
520
|
-
: query
|
|
521
|
-
.flatMap((part) => part.type === "text" ? [part.text] : [])
|
|
522
|
-
.join("\n")
|
|
523
|
-
.trim();
|
|
524
476
|
let result: SessionTurnExecutionResult;
|
|
525
477
|
try {
|
|
526
|
-
result = await this.executor.execute({
|
|
527
|
-
query: executor_query,
|
|
528
|
-
turn_context,
|
|
529
|
-
});
|
|
478
|
+
result = await this.executor.execute({ turn_context });
|
|
530
479
|
} catch (error) {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
try {
|
|
537
|
-
await assistant_output.finish({
|
|
538
|
-
status: turn_context.lifecycle.abort_signal.aborted ? "stopped" : "failed",
|
|
539
|
-
error: error instanceof Error ? error.message : String(error),
|
|
540
|
-
});
|
|
541
|
-
} catch (finish_error) {
|
|
542
|
-
await this.log_file_diff_warning(
|
|
543
|
-
input.active_turn.turn_id,
|
|
544
|
-
"failed to close Assistant output after execution error",
|
|
545
|
-
finish_error,
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
throw error;
|
|
480
|
+
result = {
|
|
481
|
+
text: "",
|
|
482
|
+
success: false,
|
|
483
|
+
error: error instanceof Error ? error.message : String(error),
|
|
484
|
+
};
|
|
549
485
|
}
|
|
550
486
|
|
|
551
|
-
|
|
552
|
-
|
|
487
|
+
if (!result.success && !turn_context.lifecycle.abort_signal.aborted && result.error) {
|
|
488
|
+
await assistant_output.append_error({
|
|
489
|
+
scope: "turn",
|
|
490
|
+
code: "turn_execution_failed",
|
|
491
|
+
message: result.error,
|
|
492
|
+
recoverable: true,
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
await append_session_turn_file_diff({
|
|
497
|
+
session_id: this.session_id,
|
|
498
|
+
turn_id: input.active_turn.turn_id,
|
|
499
|
+
workspace_path: this.workspace_path,
|
|
553
500
|
turn_context,
|
|
554
501
|
assistant_output,
|
|
555
|
-
|
|
502
|
+
logger: this.logger,
|
|
503
|
+
});
|
|
556
504
|
|
|
557
505
|
await assistant_output.finish({
|
|
558
506
|
status: turn_context.lifecycle.abort_signal.aborted
|
|
@@ -563,24 +511,8 @@ export class SessionLoop {
|
|
|
563
511
|
...(result.error ? { error: result.error } : {}),
|
|
564
512
|
});
|
|
565
513
|
|
|
566
|
-
if (!result.success && !turn_context.lifecycle.abort_signal.aborted && result.error) {
|
|
567
|
-
await this.messages.append_error_message({
|
|
568
|
-
scope: "turn",
|
|
569
|
-
turn_id: input.active_turn.turn_id,
|
|
570
|
-
code: "turn_execution_failed",
|
|
571
|
-
message: result.error,
|
|
572
|
-
recoverable: true,
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
await this.state.touch_metadata();
|
|
576
|
-
const deferred_count = await this.messages.append_deferred_user_messages(
|
|
577
|
-
result.deferred_persisted_user_messages,
|
|
578
|
-
);
|
|
579
|
-
if (deferred_count > 0) await this.state.touch_metadata();
|
|
580
514
|
if (result.compact_required) {
|
|
581
|
-
await this.
|
|
582
|
-
turn_id: input.active_turn.turn_id,
|
|
583
|
-
});
|
|
515
|
+
await this.maintain_context();
|
|
584
516
|
}
|
|
585
517
|
return {
|
|
586
518
|
text: result.text,
|
|
@@ -589,56 +521,6 @@ export class SessionLoop {
|
|
|
589
521
|
};
|
|
590
522
|
}
|
|
591
523
|
|
|
592
|
-
/** 把当前 Turn 成功的结构化文件修改写入 canonical Assistant data part。 */
|
|
593
|
-
private async append_turn_file_diff(
|
|
594
|
-
turn_id: string,
|
|
595
|
-
turn_context: SessionTurnContext,
|
|
596
|
-
assistant_output: SessionAssistantOutput,
|
|
597
|
-
): Promise<void> {
|
|
598
|
-
try {
|
|
599
|
-
const file_diff = build_session_turn_file_diff(
|
|
600
|
-
this.workspace_path,
|
|
601
|
-
turn_context.effects.snapshot(),
|
|
602
|
-
);
|
|
603
|
-
if (!file_diff) return;
|
|
604
|
-
await assistant_output.append_result_parts([{
|
|
605
|
-
type: "data",
|
|
606
|
-
data_type: SESSION_TURN_FILE_DIFF_DATA_TYPE,
|
|
607
|
-
data_id: `turn-file-diff:${turn_id}`,
|
|
608
|
-
data: {
|
|
609
|
-
files: file_diff.files.map((file) => ({
|
|
610
|
-
file: file.file,
|
|
611
|
-
status: file.status,
|
|
612
|
-
additions: file.additions,
|
|
613
|
-
deletions: file.deletions,
|
|
614
|
-
patch: file.patch,
|
|
615
|
-
})),
|
|
616
|
-
additions: file_diff.additions,
|
|
617
|
-
deletions: file_diff.deletions,
|
|
618
|
-
},
|
|
619
|
-
}]);
|
|
620
|
-
} catch (error) {
|
|
621
|
-
await this.log_file_diff_warning(turn_id, "failed to persist structured file edits", error);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
/** 文件修改展示属于辅助观测能力,失败不能改变 Turn 结果。 */
|
|
626
|
-
private async log_file_diff_warning(
|
|
627
|
-
turn_id: string,
|
|
628
|
-
message: string,
|
|
629
|
-
error: unknown,
|
|
630
|
-
): Promise<void> {
|
|
631
|
-
try {
|
|
632
|
-
await this.logger.log("warn", `[agent] ${message}`, {
|
|
633
|
-
session_id: this.session_id,
|
|
634
|
-
turn_id,
|
|
635
|
-
error: error instanceof Error ? error.message : String(error),
|
|
636
|
-
});
|
|
637
|
-
} catch {
|
|
638
|
-
// 文件编辑观测失败不影响 canonical 对话执行。
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
524
|
/** 在 Turn 创建时建立其唯一执行上下文和 Assistant 输出端口。 */
|
|
643
525
|
private create_turn_context(
|
|
644
526
|
active_turn: ActiveSessionTurnState,
|
|
@@ -652,45 +534,33 @@ export class SessionLoop {
|
|
|
652
534
|
session_id: this.session_id,
|
|
653
535
|
session_origin: this.session_origin,
|
|
654
536
|
project_root: this.workspace_path,
|
|
655
|
-
|
|
656
|
-
const
|
|
657
|
-
|
|
658
|
-
|
|
537
|
+
commit_step_input: async () => {
|
|
538
|
+
const had_pending_prompt = this.has_pending_prompt();
|
|
539
|
+
await this.drain_queued_inputs();
|
|
540
|
+
if (had_pending_prompt) await assistant_output.close_current_message();
|
|
659
541
|
},
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
542
|
+
append_internal_user_message: async (parts) => {
|
|
543
|
+
const message = await this.messages.append_user_message({
|
|
544
|
+
turn_id: active_turn.turn_id,
|
|
545
|
+
visibility: "internal",
|
|
546
|
+
parts: normalize_session_user_parts([...parts]),
|
|
547
|
+
});
|
|
548
|
+
active_turn.turn_context?.input.observe_user_message(message);
|
|
549
|
+
return message;
|
|
665
550
|
},
|
|
551
|
+
has_pending_step_input: () => this.has_pending_prompt(),
|
|
666
552
|
assistant_output,
|
|
667
553
|
shell_approval_gateway: this.shell_approval_gateway,
|
|
668
554
|
interactions: this.interactions,
|
|
669
555
|
on_effects_changed: (effects) => {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
)
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
mutation_id: nanoid(),
|
|
679
|
-
variant: "file_diff",
|
|
680
|
-
session_id: this.session_id,
|
|
681
|
-
turn_id: active_turn.turn_id,
|
|
682
|
-
created_at: Date.now(),
|
|
683
|
-
files_count: summary.files_count,
|
|
684
|
-
additions: summary.additions,
|
|
685
|
-
deletions: summary.deletions,
|
|
686
|
-
});
|
|
687
|
-
} catch (error) {
|
|
688
|
-
void this.log_file_diff_warning(
|
|
689
|
-
active_turn.turn_id,
|
|
690
|
-
"failed to publish live file edit summary",
|
|
691
|
-
error,
|
|
692
|
-
);
|
|
693
|
-
}
|
|
556
|
+
publish_session_turn_file_diff({
|
|
557
|
+
session_id: this.session_id,
|
|
558
|
+
turn_id: active_turn.turn_id,
|
|
559
|
+
workspace_path: this.workspace_path,
|
|
560
|
+
effects,
|
|
561
|
+
publish: (mutation) => this.events.publish(mutation),
|
|
562
|
+
logger: this.logger,
|
|
563
|
+
});
|
|
694
564
|
},
|
|
695
565
|
publish_action: async (event) => {
|
|
696
566
|
await this.persist_action_event(event);
|
|
@@ -709,80 +579,52 @@ export class SessionLoop {
|
|
|
709
579
|
private async persist_prompt_message(
|
|
710
580
|
prompt: AgentSessionPromptInput,
|
|
711
581
|
turn_id: string,
|
|
712
|
-
|
|
582
|
+
message_id?: string,
|
|
713
583
|
): Promise<SessionUserMessage> {
|
|
714
584
|
const message = await this.messages.append_prompt_message({
|
|
715
585
|
project_root: this.workspace_path,
|
|
716
586
|
prompt,
|
|
717
587
|
turn_id,
|
|
718
|
-
|
|
588
|
+
...(message_id ? { message_id } : {}),
|
|
719
589
|
});
|
|
720
|
-
this.state.touch_metadata_in_background();
|
|
721
590
|
this.state.schedule_title_generation();
|
|
722
591
|
return message;
|
|
723
592
|
}
|
|
724
593
|
|
|
594
|
+
/** 解析已经持久化或仍在执行的幂等 Prompt。 */
|
|
595
|
+
private async resolve_idempotent_prompt(
|
|
596
|
+
identity: PromptRequestIdentity,
|
|
597
|
+
): Promise<AgentSessionTurnHandle | null> {
|
|
598
|
+
const existing_message = this.messages.get_message(identity.message_id);
|
|
599
|
+
if (!existing_message) return null;
|
|
600
|
+
if (existing_message.role !== "user" || existing_message.turn_id !== identity.turn_id) {
|
|
601
|
+
throw new Error("Session prompt request identity conflicts with canonical history");
|
|
602
|
+
}
|
|
603
|
+
if (this.active_turn?.turn_id === identity.turn_id) {
|
|
604
|
+
return create_turn_handle(this.active_turn);
|
|
605
|
+
}
|
|
606
|
+
const agent_message = await this.messages.read_latest_agent_message(identity.turn_id);
|
|
607
|
+
if (!agent_message || agent_message.state === "streaming") return null;
|
|
608
|
+
return create_completed_turn_handle(to_persisted_turn_result(identity.turn_id, agent_message));
|
|
609
|
+
}
|
|
610
|
+
|
|
725
611
|
/** 持久化 Executor Action,并同步刷新 Session metadata。 */
|
|
726
612
|
private async persist_action_event(
|
|
727
613
|
event: SessionActionEvent,
|
|
728
614
|
options?: { publish_mutation?: boolean },
|
|
729
615
|
): Promise<void> {
|
|
730
616
|
await this.messages.persist_action(event, options);
|
|
731
|
-
await this.state.touch_metadata();
|
|
732
617
|
}
|
|
733
618
|
|
|
734
|
-
/**
|
|
735
|
-
private
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
session_id: this.session_id,
|
|
744
|
-
turn_id: active_turn.turn_id,
|
|
745
|
-
error: error instanceof Error ? error.message : String(error),
|
|
746
|
-
});
|
|
747
|
-
} catch {
|
|
748
|
-
// Context 已进入释放流程,日志失败不能阻止 Turn Handle 收口。
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
/** 在释放当前 lease 前触发现有 Plugin effect point。 */
|
|
754
|
-
private async notify_turn_committed(
|
|
755
|
-
active_turn: ActiveSessionTurnState,
|
|
756
|
-
status: SessionTurnCommittedHookValue["status"],
|
|
757
|
-
): Promise<void> {
|
|
758
|
-
const extensions = active_turn.turn_context?.step.hooks;
|
|
759
|
-
if (!extensions) return;
|
|
760
|
-
try {
|
|
761
|
-
const messages = (await this.messages.list_history_messages())
|
|
762
|
-
.filter((message) => message.turn_id === active_turn.turn_id)
|
|
763
|
-
.map((message) => structuredClone(message));
|
|
764
|
-
const value: SessionTurnCommittedHookValue = {
|
|
765
|
-
session_id: this.session_id,
|
|
766
|
-
turn_id: active_turn.turn_id,
|
|
767
|
-
status,
|
|
768
|
-
messages: messages as SessionMessage[],
|
|
769
|
-
};
|
|
770
|
-
await extensions.effect(
|
|
771
|
-
SESSION_HOOK_POINTS.turn_committed,
|
|
772
|
-
value as unknown as JsonValue,
|
|
773
|
-
);
|
|
774
|
-
} catch (error) {
|
|
775
|
-
try {
|
|
776
|
-
await this.logger.log("warn", "[agent] session plugin effect failed", {
|
|
777
|
-
session_id: this.session_id,
|
|
778
|
-
turn_id: active_turn.turn_id,
|
|
779
|
-
point_name: SESSION_HOOK_POINTS.turn_committed,
|
|
780
|
-
error: error instanceof Error ? error.message : String(error),
|
|
781
|
-
});
|
|
782
|
-
} catch {
|
|
783
|
-
// Plugin effect 不改变已经确定的 Turn 结果。
|
|
784
|
-
}
|
|
785
|
-
}
|
|
619
|
+
/** 为 Turn 收口领域函数投影稳定依赖。 */
|
|
620
|
+
private turn_completion_options(): SessionTurnCompletionOptions {
|
|
621
|
+
return {
|
|
622
|
+
session_id: this.session_id,
|
|
623
|
+
messages: this.messages,
|
|
624
|
+
events: this.events,
|
|
625
|
+
logger: this.logger,
|
|
626
|
+
stopped_message: TURN_STOPPED_MESSAGE,
|
|
627
|
+
};
|
|
786
628
|
}
|
|
787
629
|
}
|
|
788
630
|
|
|
@@ -805,7 +647,6 @@ function create_active_session_turn_state(
|
|
|
805
647
|
result: null,
|
|
806
648
|
deferred_finished: create_deferred<AgentSessionTurnResult>(),
|
|
807
649
|
turn_context: null,
|
|
808
|
-
history_reload_requested: false,
|
|
809
650
|
prompt_started: false,
|
|
810
651
|
};
|
|
811
652
|
}
|
|
@@ -821,3 +662,59 @@ function create_turn_handle(
|
|
|
821
662
|
finished: active_turn.deferred_finished.promise,
|
|
822
663
|
};
|
|
823
664
|
}
|
|
665
|
+
|
|
666
|
+
/** 幂等 Prompt 在 canonical history 中使用的稳定身份。 */
|
|
667
|
+
interface PromptRequestIdentity {
|
|
668
|
+
/** 稳定 User Message ID。 */
|
|
669
|
+
message_id: string;
|
|
670
|
+
/** 稳定 Turn ID。 */
|
|
671
|
+
turn_id: string;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/** 把调用方业务键映射为不暴露原值的 Session 内稳定身份。 */
|
|
675
|
+
function resolve_prompt_request_identity(
|
|
676
|
+
session_id: string,
|
|
677
|
+
request_id_input: string | undefined,
|
|
678
|
+
): PromptRequestIdentity | null {
|
|
679
|
+
const request_id = String(request_id_input || "").trim();
|
|
680
|
+
if (!request_id) return null;
|
|
681
|
+
if (request_id.length > 512) {
|
|
682
|
+
throw new Error("session.prompt request_id must not exceed 512 characters");
|
|
683
|
+
}
|
|
684
|
+
const digest = createHash("sha256")
|
|
685
|
+
.update(session_id)
|
|
686
|
+
.update("\u0000")
|
|
687
|
+
.update(request_id)
|
|
688
|
+
.digest("hex");
|
|
689
|
+
return {
|
|
690
|
+
message_id: `user-request:${digest}`,
|
|
691
|
+
turn_id: `turn-request:${digest}`,
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/** 从已完成的 canonical Agent Message 恢复 Turn 结果。 */
|
|
696
|
+
function to_persisted_turn_result(
|
|
697
|
+
turn_id: string,
|
|
698
|
+
message: SessionAgentMessage,
|
|
699
|
+
): AgentSessionTurnResult {
|
|
700
|
+
const error_part = [...message.parts].reverse().find((part) => part.type === "error");
|
|
701
|
+
const error = error_part?.type === "error" ? error_part.message : undefined;
|
|
702
|
+
const success = !error;
|
|
703
|
+
return {
|
|
704
|
+
turn_id,
|
|
705
|
+
text: extract_session_message_text(message),
|
|
706
|
+
success,
|
|
707
|
+
...(!success ? { error } : {}),
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/** 为已经持久化完成的 Turn 创建立即兑现的句柄。 */
|
|
712
|
+
function create_completed_turn_handle(
|
|
713
|
+
result: AgentSessionTurnResult,
|
|
714
|
+
): AgentSessionTurnHandle {
|
|
715
|
+
return {
|
|
716
|
+
id: result.turn_id,
|
|
717
|
+
result,
|
|
718
|
+
finished: Promise.resolve(result),
|
|
719
|
+
};
|
|
720
|
+
}
|