@namzu/sdk 0.6.0 → 1.1.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 +529 -0
- package/dist/advisory/executor.d.ts.map +1 -1
- package/dist/advisory/executor.js +9 -2
- package/dist/advisory/executor.js.map +1 -1
- package/dist/advisory/executor.test.d.ts +2 -1
- package/dist/advisory/executor.test.d.ts.map +1 -1
- package/dist/advisory/executor.test.js +7 -4
- package/dist/advisory/executor.test.js.map +1 -1
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +7 -0
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts +22 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +54 -14
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/__tests__/supervisor-ledger.test.d.ts +2 -0
- package/dist/agents/__tests__/supervisor-ledger.test.d.ts.map +1 -0
- package/dist/agents/__tests__/supervisor-ledger.test.js +131 -0
- package/dist/agents/__tests__/supervisor-ledger.test.js.map +1 -0
- package/dist/bridge/sse/mapper.test.js +2 -2
- package/dist/config/runtime.d.ts +24 -0
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/runtime.js +9 -0
- package/dist/config/runtime.js.map +1 -1
- package/dist/connector/builtins/webhook.test.js +17 -0
- package/dist/connector/builtins/webhook.test.js.map +1 -1
- package/dist/connector/index.d.ts +1 -0
- package/dist/connector/index.d.ts.map +1 -1
- package/dist/connector/index.js +1 -0
- package/dist/connector/index.js.map +1 -1
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +4 -0
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/index.d.ts +1 -0
- package/dist/connector/mcp/index.d.ts.map +1 -1
- package/dist/connector/mcp/index.js +1 -0
- package/dist/connector/mcp/index.js.map +1 -1
- package/dist/connector/mcp/streamable-http.d.ts +22 -0
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -0
- package/dist/connector/mcp/streamable-http.js +128 -0
- package/dist/connector/mcp/streamable-http.js.map +1 -0
- package/dist/connector/mcp/streamable-http.test.d.ts +2 -0
- package/dist/connector/mcp/streamable-http.test.d.ts.map +1 -0
- package/dist/connector/mcp/streamable-http.test.js +132 -0
- package/dist/connector/mcp/streamable-http.test.js.map +1 -0
- package/dist/constants/compaction/index.d.ts.map +1 -1
- package/dist/constants/compaction/index.js +8 -3
- package/dist/constants/compaction/index.js.map +1 -1
- package/dist/constants/sandbox/index.d.ts +21 -0
- package/dist/constants/sandbox/index.d.ts.map +1 -1
- package/dist/constants/sandbox/index.js +30 -0
- package/dist/constants/sandbox/index.js.map +1 -1
- package/dist/constants/tools/index.d.ts.map +1 -1
- package/dist/constants/tools/index.js +33 -2
- package/dist/constants/tools/index.js.map +1 -1
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +35 -5
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/persona/assembler.d.ts +1 -0
- package/dist/persona/assembler.d.ts.map +1 -1
- package/dist/persona/assembler.js +37 -6
- package/dist/persona/assembler.js.map +1 -1
- package/dist/provider/collect.d.ts.map +1 -1
- package/dist/provider/collect.js +4 -1
- package/dist/provider/collect.js.map +1 -1
- package/dist/provider/collect.test.js +2 -2
- package/dist/public-runtime.d.ts +6 -5
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +6 -5
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +2 -0
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +2 -0
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +3 -0
- package/dist/public-types.d.ts.map +1 -1
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +1 -0
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/tool/execute.d.ts +27 -0
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +192 -7
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/registry/tool/execute.test.d.ts +9 -4
- package/dist/registry/tool/execute.test.d.ts.map +1 -1
- package/dist/registry/tool/execute.test.js +178 -7
- package/dist/registry/tool/execute.test.js.map +1 -1
- package/dist/registry/toolset/catalog.d.ts +42 -0
- package/dist/registry/toolset/catalog.d.ts.map +1 -0
- package/dist/registry/toolset/catalog.js +217 -0
- package/dist/registry/toolset/catalog.js.map +1 -0
- package/dist/registry/toolset/catalog.test.d.ts +2 -0
- package/dist/registry/toolset/catalog.test.d.ts.map +1 -0
- package/dist/registry/toolset/catalog.test.js +147 -0
- package/dist/registry/toolset/catalog.test.js.map +1 -0
- package/dist/runtime/query/__tests__/deferred-tools.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/deferred-tools.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/deferred-tools.test.js +185 -0
- package/dist/runtime/query/__tests__/deferred-tools.test.js.map +1 -0
- package/dist/runtime/query/__tests__/executor-concurrency.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/executor-concurrency.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/executor-concurrency.test.js +98 -0
- package/dist/runtime/query/__tests__/executor-concurrency.test.js.map +1 -0
- package/dist/runtime/query/__tests__/executor-plugin-hooks.test.js +38 -3
- package/dist/runtime/query/__tests__/executor-plugin-hooks.test.js.map +1 -1
- package/dist/runtime/query/__tests__/long-document-flow.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/long-document-flow.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/long-document-flow.test.js +154 -0
- package/dist/runtime/query/__tests__/long-document-flow.test.js.map +1 -0
- package/dist/runtime/query/__tests__/prompt.test.js +51 -2
- package/dist/runtime/query/__tests__/prompt.test.js.map +1 -1
- package/dist/runtime/query/__tests__/stream-recovery.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/stream-recovery.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/stream-recovery.test.js +126 -0
- package/dist/runtime/query/__tests__/stream-recovery.test.js.map +1 -0
- package/dist/runtime/query/continuation.d.ts +16 -0
- package/dist/runtime/query/continuation.d.ts.map +1 -0
- package/dist/runtime/query/continuation.js +16 -0
- package/dist/runtime/query/continuation.js.map +1 -0
- package/dist/runtime/query/executor.d.ts +3 -0
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +71 -3
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +9 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +42 -5
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +24 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +326 -66
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/checkpoint.js +2 -2
- package/dist/runtime/query/iteration/phases/checkpoint.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.d.ts +8 -0
- package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +84 -3
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +22 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js +53 -0
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/hitl-abort-race.test.d.ts +2 -0
- package/dist/runtime/query/iteration/phases/hitl-abort-race.test.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/hitl-abort-race.test.js +73 -0
- package/dist/runtime/query/iteration/phases/hitl-abort-race.test.js.map +1 -0
- package/dist/runtime/query/iteration/phases/hitl-answer-question.test.d.ts +2 -0
- package/dist/runtime/query/iteration/phases/hitl-answer-question.test.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/hitl-answer-question.test.js +120 -0
- package/dist/runtime/query/iteration/phases/hitl-answer-question.test.js.map +1 -0
- package/dist/runtime/query/iteration/phases/tool-review.d.ts +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +7 -2
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/phases/working-memory-compaction.test.d.ts +19 -0
- package/dist/runtime/query/iteration/phases/working-memory-compaction.test.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/working-memory-compaction.test.js +177 -0
- package/dist/runtime/query/iteration/phases/working-memory-compaction.test.js.map +1 -0
- package/dist/runtime/query/iteration/phases/working-memory.d.ts +31 -0
- package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/working-memory.js +81 -0
- package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -0
- package/dist/runtime/query/prompt.d.ts.map +1 -1
- package/dist/runtime/query/prompt.js +21 -1
- package/dist/runtime/query/prompt.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +1 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +1 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/sandbox/provider/local.d.ts.map +1 -1
- package/dist/sandbox/provider/local.js +32 -1
- package/dist/sandbox/provider/local.js.map +1 -1
- package/dist/session/workspace/__tests__/shared-run.test.d.ts +2 -0
- package/dist/session/workspace/__tests__/shared-run.test.d.ts.map +1 -0
- package/dist/session/workspace/__tests__/shared-run.test.js +147 -0
- package/dist/session/workspace/__tests__/shared-run.test.js.map +1 -0
- package/dist/session/workspace/index.d.ts +2 -0
- package/dist/session/workspace/index.d.ts.map +1 -1
- package/dist/session/workspace/index.js +1 -0
- package/dist/session/workspace/index.js.map +1 -1
- package/dist/session/workspace/shared-run.d.ts +81 -0
- package/dist/session/workspace/shared-run.d.ts.map +1 -0
- package/dist/session/workspace/shared-run.js +252 -0
- package/dist/session/workspace/shared-run.js.map +1 -0
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +36 -6
- package/dist/skills/loader.js.map +1 -1
- package/dist/skills/loader.test.d.ts +2 -0
- package/dist/skills/loader.test.d.ts.map +1 -0
- package/dist/skills/loader.test.js +65 -0
- package/dist/skills/loader.test.js.map +1 -0
- package/dist/streaming/coalesce.test.js +1 -1
- package/dist/streaming/coalesce.test.js.map +1 -1
- package/dist/tools/builtins/__tests__/edit.test.d.ts +2 -0
- package/dist/tools/builtins/__tests__/edit.test.d.ts.map +1 -0
- package/dist/tools/builtins/__tests__/edit.test.js +38 -0
- package/dist/tools/builtins/__tests__/edit.test.js.map +1 -0
- package/dist/tools/builtins/__tests__/payload-budget.test.d.ts +2 -0
- package/dist/tools/builtins/__tests__/payload-budget.test.d.ts.map +1 -0
- package/dist/tools/builtins/__tests__/payload-budget.test.js +70 -0
- package/dist/tools/builtins/__tests__/payload-budget.test.js.map +1 -0
- package/dist/tools/builtins/__tests__/read-file.test.d.ts +2 -0
- package/dist/tools/builtins/__tests__/read-file.test.d.ts.map +1 -0
- package/dist/tools/builtins/__tests__/read-file.test.js +33 -0
- package/dist/tools/builtins/__tests__/read-file.test.js.map +1 -0
- package/dist/tools/builtins/__tests__/verify-outputs.test.d.ts +2 -0
- package/dist/tools/builtins/__tests__/verify-outputs.test.d.ts.map +1 -0
- package/dist/tools/builtins/__tests__/verify-outputs.test.js +52 -0
- package/dist/tools/builtins/__tests__/verify-outputs.test.js.map +1 -0
- package/dist/tools/builtins/__tests__/write-file.test.d.ts +2 -0
- package/dist/tools/builtins/__tests__/write-file.test.d.ts.map +1 -0
- package/dist/tools/builtins/__tests__/write-file.test.js +74 -0
- package/dist/tools/builtins/__tests__/write-file.test.js.map +1 -0
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +40 -7
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/edit.d.ts +5 -2
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +114 -18
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/index.d.ts +1 -0
- package/dist/tools/builtins/index.d.ts.map +1 -1
- package/dist/tools/builtins/index.js +13 -13
- package/dist/tools/builtins/index.js.map +1 -1
- package/dist/tools/builtins/read-file.d.ts +1 -0
- package/dist/tools/builtins/read-file.d.ts.map +1 -1
- package/dist/tools/builtins/read-file.js +73 -10
- package/dist/tools/builtins/read-file.js.map +1 -1
- package/dist/tools/builtins/search-tools.d.ts.map +1 -1
- package/dist/tools/builtins/search-tools.js +35 -7
- package/dist/tools/builtins/search-tools.js.map +1 -1
- package/dist/tools/builtins/verify-outputs.d.ts +5 -0
- package/dist/tools/builtins/verify-outputs.d.ts.map +1 -0
- package/dist/tools/builtins/verify-outputs.js +103 -0
- package/dist/tools/builtins/verify-outputs.js.map +1 -0
- package/dist/tools/builtins/write-file.d.ts +3 -2
- package/dist/tools/builtins/write-file.d.ts.map +1 -1
- package/dist/tools/builtins/write-file.js +72 -12
- package/dist/tools/builtins/write-file.js.map +1 -1
- package/dist/tools/coordinator/__tests__/agent.test.d.ts +15 -0
- package/dist/tools/coordinator/__tests__/agent.test.d.ts.map +1 -0
- package/dist/tools/coordinator/__tests__/agent.test.js +142 -0
- package/dist/tools/coordinator/__tests__/agent.test.js.map +1 -0
- package/dist/tools/coordinator/__tests__/approve-plan.test.d.ts +2 -0
- package/dist/tools/coordinator/__tests__/approve-plan.test.d.ts.map +1 -0
- package/dist/tools/coordinator/__tests__/approve-plan.test.js +114 -0
- package/dist/tools/coordinator/__tests__/approve-plan.test.js.map +1 -0
- package/dist/tools/coordinator/__tests__/ask-user-question.test.d.ts +2 -0
- package/dist/tools/coordinator/__tests__/ask-user-question.test.d.ts.map +1 -0
- package/dist/tools/coordinator/__tests__/ask-user-question.test.js +309 -0
- package/dist/tools/coordinator/__tests__/ask-user-question.test.js.map +1 -0
- package/dist/tools/coordinator/__tests__/task-list.test.d.ts +13 -0
- package/dist/tools/coordinator/__tests__/task-list.test.d.ts.map +1 -0
- package/dist/tools/coordinator/__tests__/task-list.test.js +162 -0
- package/dist/tools/coordinator/__tests__/task-list.test.js.map +1 -0
- package/dist/tools/coordinator/agent.d.ts +34 -0
- package/dist/tools/coordinator/agent.d.ts.map +1 -0
- package/dist/tools/coordinator/agent.js +107 -0
- package/dist/tools/coordinator/agent.js.map +1 -0
- package/dist/tools/coordinator/index.d.ts +15 -0
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +305 -35
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/types/agent/base.d.ts +8 -0
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/index.d.ts +1 -0
- package/dist/types/agent/index.d.ts.map +1 -1
- package/dist/types/agent/index.js +1 -0
- package/dist/types/agent/index.js.map +1 -1
- package/dist/types/agent/reactive.d.ts +38 -0
- package/dist/types/agent/reactive.d.ts.map +1 -1
- package/dist/types/agent/supervisor.d.ts +32 -0
- package/dist/types/agent/supervisor.d.ts.map +1 -1
- package/dist/types/agent/working-memory.d.ts +29 -0
- package/dist/types/agent/working-memory.d.ts.map +1 -0
- package/dist/types/agent/working-memory.js +2 -0
- package/dist/types/agent/working-memory.js.map +1 -0
- package/dist/types/common/index.d.ts +10 -0
- package/dist/types/common/index.d.ts.map +1 -1
- package/dist/types/common/index.js +18 -0
- package/dist/types/common/index.js.map +1 -1
- package/dist/types/common/usage-merge.test.d.ts +2 -0
- package/dist/types/common/usage-merge.test.d.ts.map +1 -0
- package/dist/types/common/usage-merge.test.js +48 -0
- package/dist/types/common/usage-merge.test.js.map +1 -0
- package/dist/types/connector/mcp.d.ts +9 -2
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/hitl/index.d.ts +42 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js +11 -0
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/message/index.d.ts +22 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +7 -2
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/provider/chat.d.ts +11 -9
- package/dist/types/provider/chat.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +6 -0
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/sandbox/index.d.ts +193 -0
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/dist/types/skills/index.d.ts +2 -0
- package/dist/types/skills/index.d.ts.map +1 -1
- package/dist/types/tool/index.d.ts +22 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/toolset/index.d.ts +71 -0
- package/dist/types/toolset/index.d.ts.map +1 -0
- package/dist/types/toolset/index.js +2 -0
- package/dist/types/toolset/index.js.map +1 -0
- package/dist/types/workspace/index.d.ts +1 -0
- package/dist/types/workspace/index.d.ts.map +1 -1
- package/dist/types/workspace/shared-run.d.ts +61 -0
- package/dist/types/workspace/shared-run.d.ts.map +1 -0
- package/dist/types/workspace/shared-run.js +2 -0
- package/dist/types/workspace/shared-run.js.map +1 -0
- package/dist/verification/index.d.ts +1 -0
- package/dist/verification/index.d.ts.map +1 -1
- package/dist/verification/index.js +1 -0
- package/dist/verification/index.js.map +1 -1
- package/dist/verification/presets.d.ts +53 -0
- package/dist/verification/presets.d.ts.map +1 -0
- package/dist/verification/presets.js +70 -0
- package/dist/verification/presets.js.map +1 -0
- package/dist/verification/presets.test.d.ts +16 -0
- package/dist/verification/presets.test.d.ts.map +1 -0
- package/dist/verification/presets.test.js +79 -0
- package/dist/verification/presets.test.js.map +1 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +25 -4
- package/dist/version.js.map +1 -1
- package/package.json +3 -2
- package/src/advisory/executor.test.ts +7 -4
- package/src/advisory/executor.ts +11 -2
- package/src/agents/ReactiveAgent.ts +7 -0
- package/src/agents/SupervisorAgent.ts +63 -16
- package/src/agents/__tests__/supervisor-ledger.test.ts +185 -0
- package/src/bridge/sse/mapper.test.ts +2 -2
- package/src/config/runtime.ts +9 -0
- package/src/connector/builtins/webhook.test.ts +21 -0
- package/src/connector/index.ts +1 -0
- package/src/connector/mcp/client.ts +4 -0
- package/src/connector/mcp/index.ts +1 -0
- package/src/connector/mcp/streamable-http.test.ts +169 -0
- package/src/connector/mcp/streamable-http.ts +152 -0
- package/src/constants/compaction/index.ts +8 -3
- package/src/constants/sandbox/index.ts +37 -0
- package/src/constants/tools/index.ts +33 -2
- package/src/manager/run/persistence.ts +34 -6
- package/src/persona/assembler.ts +43 -8
- package/src/provider/collect.test.ts +2 -2
- package/src/provider/collect.ts +4 -1
- package/src/public-runtime.ts +15 -1
- package/src/public-tools.ts +2 -0
- package/src/public-types.ts +7 -0
- package/src/registry/index.ts +7 -0
- package/src/registry/tool/execute.test.ts +211 -7
- package/src/registry/tool/execute.ts +199 -11
- package/src/registry/toolset/catalog.test.ts +165 -0
- package/src/registry/toolset/catalog.ts +283 -0
- package/src/runtime/query/__tests__/deferred-tools.test.ts +230 -0
- package/src/runtime/query/__tests__/executor-concurrency.test.ts +122 -0
- package/src/runtime/query/__tests__/executor-plugin-hooks.test.ts +48 -3
- package/src/runtime/query/__tests__/long-document-flow.test.ts +180 -0
- package/src/runtime/query/__tests__/prompt.test.ts +55 -2
- package/src/runtime/query/__tests__/stream-recovery.test.ts +156 -0
- package/src/runtime/query/continuation.ts +16 -0
- package/src/runtime/query/executor.ts +82 -13
- package/src/runtime/query/index.ts +58 -5
- package/src/runtime/query/iteration/index.ts +361 -74
- package/src/runtime/query/iteration/phases/checkpoint.ts +7 -2
- package/src/runtime/query/iteration/phases/compaction.ts +89 -3
- package/src/runtime/query/iteration/phases/context.ts +68 -0
- package/src/runtime/query/iteration/phases/hitl-abort-race.test.ts +86 -0
- package/src/runtime/query/iteration/phases/hitl-answer-question.test.ts +139 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +7 -3
- package/src/runtime/query/iteration/phases/working-memory-compaction.test.ts +215 -0
- package/src/runtime/query/iteration/phases/working-memory.ts +86 -0
- package/src/runtime/query/prompt.ts +17 -1
- package/src/runtime/query/tooling.ts +2 -0
- package/src/sandbox/provider/local.ts +33 -0
- package/src/session/workspace/__tests__/shared-run.test.ts +181 -0
- package/src/session/workspace/index.ts +6 -0
- package/src/session/workspace/shared-run.ts +317 -0
- package/src/skills/loader.test.ts +89 -0
- package/src/skills/loader.ts +37 -6
- package/src/streaming/coalesce.test.ts +4 -4
- package/src/tools/builtins/__tests__/edit.test.ts +57 -0
- package/src/tools/builtins/__tests__/payload-budget.test.ts +92 -0
- package/src/tools/builtins/__tests__/read-file.test.ts +43 -0
- package/src/tools/builtins/__tests__/verify-outputs.test.ts +71 -0
- package/src/tools/builtins/__tests__/write-file.test.ts +97 -0
- package/src/tools/builtins/bash.ts +48 -7
- package/src/tools/builtins/edit.ts +162 -27
- package/src/tools/builtins/index.ts +13 -13
- package/src/tools/builtins/read-file.ts +81 -10
- package/src/tools/builtins/search-tools.ts +42 -7
- package/src/tools/builtins/verify-outputs.ts +126 -0
- package/src/tools/builtins/write-file.ts +83 -14
- package/src/tools/coordinator/__tests__/agent.test.ts +172 -0
- package/src/tools/coordinator/__tests__/approve-plan.test.ts +139 -0
- package/src/tools/coordinator/__tests__/ask-user-question.test.ts +370 -0
- package/src/tools/coordinator/__tests__/task-list.test.ts +182 -0
- package/src/tools/coordinator/agent.ts +157 -0
- package/src/tools/coordinator/index.ts +355 -39
- package/src/types/agent/base.ts +8 -0
- package/src/types/agent/index.ts +1 -0
- package/src/types/agent/reactive.ts +42 -0
- package/src/types/agent/supervisor.ts +36 -0
- package/src/types/agent/working-memory.ts +29 -0
- package/src/types/common/index.ts +19 -0
- package/src/types/common/usage-merge.test.ts +53 -0
- package/src/types/connector/mcp.ts +14 -2
- package/src/types/hitl/index.ts +52 -1
- package/src/types/message/index.ts +32 -2
- package/src/types/provider/chat.ts +12 -9
- package/src/types/run/events.ts +6 -0
- package/src/types/sandbox/index.ts +219 -0
- package/src/types/skills/index.ts +4 -0
- package/src/types/tool/index.ts +24 -0
- package/src/types/toolset/index.ts +86 -0
- package/src/types/workspace/index.ts +9 -0
- package/src/types/workspace/shared-run.ts +65 -0
- package/src/verification/index.ts +1 -0
- package/src/verification/presets.test.ts +112 -0
- package/src/verification/presets.ts +72 -0
- package/src/version.ts +26 -4
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { ActivityStore } from '../../../store/activity/memory.js'
|
|
3
|
+
import type { RunId } from '../../../types/ids/index.js'
|
|
4
|
+
import type { ChatCompletionResponse } from '../../../types/provider/index.js'
|
|
5
|
+
import type { RunEvent } from '../../../types/run/index.js'
|
|
6
|
+
import type { ToolRegistryContract } from '../../../types/tool/index.js'
|
|
7
|
+
import type { Logger } from '../../../utils/logger.js'
|
|
8
|
+
import { ToolExecutor } from '../executor.js'
|
|
9
|
+
|
|
10
|
+
const mockRunId = 'run_test' as RunId
|
|
11
|
+
|
|
12
|
+
function makeLogger(): Logger {
|
|
13
|
+
const stub = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }
|
|
14
|
+
return { ...stub, child: vi.fn(() => ({ ...stub, child: vi.fn() })) } as unknown as Logger
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const delay = (ms: number) => new Promise((r) => setTimeout(r, ms))
|
|
18
|
+
|
|
19
|
+
/** Two tool calls in one assistant message (one batch). */
|
|
20
|
+
function twoCallResponse(name: string, a: object, b: object): ChatCompletionResponse {
|
|
21
|
+
return {
|
|
22
|
+
message: {
|
|
23
|
+
role: 'assistant',
|
|
24
|
+
content: null,
|
|
25
|
+
toolCalls: [
|
|
26
|
+
{ id: 'c1', type: 'function', function: { name, arguments: JSON.stringify(a) } },
|
|
27
|
+
{ id: 'c2', type: 'function', function: { name, arguments: JSON.stringify(b) } },
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
finishReason: 'tool_calls',
|
|
31
|
+
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
32
|
+
} as ChatCompletionResponse
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe('ToolExecutor — concurrencySafe batching', () => {
|
|
36
|
+
let activityStore: ActivityStore
|
|
37
|
+
let emitEvent: (e: RunEvent) => Promise<void>
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
activityStore = new ActivityStore(mockRunId, {
|
|
41
|
+
enabled: true,
|
|
42
|
+
trackToolCalls: true,
|
|
43
|
+
trackLlmTurns: true,
|
|
44
|
+
})
|
|
45
|
+
emitEvent = async () => {}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('serializes concurrency-unsafe tools so read-modify-write does not race', async () => {
|
|
49
|
+
// Shared mutable state, mutated via read → await → write (like `edit`).
|
|
50
|
+
let file = 'A'
|
|
51
|
+
const execute = vi.fn(async (_name: string, input: unknown) => {
|
|
52
|
+
const current = file // read
|
|
53
|
+
await delay(10) // window a parallel run would exploit
|
|
54
|
+
file = current + (input as { add: string }).add // write
|
|
55
|
+
return { success: true, output: 'ok' }
|
|
56
|
+
})
|
|
57
|
+
const tools = {
|
|
58
|
+
register: vi.fn(),
|
|
59
|
+
unregister: vi.fn(),
|
|
60
|
+
execute,
|
|
61
|
+
// edit/write/bash declare concurrencySafe:false → isConcurrencySafe()=>false
|
|
62
|
+
get: vi.fn(() => ({ isConcurrencySafe: () => false })),
|
|
63
|
+
has: vi.fn(() => true),
|
|
64
|
+
listNames: vi.fn(() => []),
|
|
65
|
+
getAvailability: vi.fn(),
|
|
66
|
+
} as unknown as ToolRegistryContract
|
|
67
|
+
|
|
68
|
+
const exec = new ToolExecutor(
|
|
69
|
+
{
|
|
70
|
+
tools,
|
|
71
|
+
runId: mockRunId,
|
|
72
|
+
workingDirectory: '/tmp',
|
|
73
|
+
permissionMode: 'auto',
|
|
74
|
+
env: {},
|
|
75
|
+
abortSignal: new AbortController().signal,
|
|
76
|
+
},
|
|
77
|
+
activityStore,
|
|
78
|
+
emitEvent,
|
|
79
|
+
makeLogger(),
|
|
80
|
+
)
|
|
81
|
+
await exec.executeBatch(twoCallResponse('edit', { add: 'B' }, { add: 'C' }))
|
|
82
|
+
// Serialized: A→AB→ABC. A racing run would lose one append (e.g. 'AC').
|
|
83
|
+
expect(file).toBe('ABC')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('runs concurrency-safe tools in parallel', async () => {
|
|
87
|
+
let active = 0
|
|
88
|
+
let maxActive = 0
|
|
89
|
+
const execute = vi.fn(async () => {
|
|
90
|
+
active++
|
|
91
|
+
maxActive = Math.max(maxActive, active)
|
|
92
|
+
await delay(10)
|
|
93
|
+
active--
|
|
94
|
+
return { success: true, output: 'ok' }
|
|
95
|
+
})
|
|
96
|
+
const tools = {
|
|
97
|
+
register: vi.fn(),
|
|
98
|
+
unregister: vi.fn(),
|
|
99
|
+
execute,
|
|
100
|
+
get: vi.fn(() => ({ isConcurrencySafe: () => true })),
|
|
101
|
+
has: vi.fn(() => true),
|
|
102
|
+
listNames: vi.fn(() => []),
|
|
103
|
+
getAvailability: vi.fn(),
|
|
104
|
+
} as unknown as ToolRegistryContract
|
|
105
|
+
|
|
106
|
+
const exec = new ToolExecutor(
|
|
107
|
+
{
|
|
108
|
+
tools,
|
|
109
|
+
runId: mockRunId,
|
|
110
|
+
workingDirectory: '/tmp',
|
|
111
|
+
permissionMode: 'auto',
|
|
112
|
+
env: {},
|
|
113
|
+
abortSignal: new AbortController().signal,
|
|
114
|
+
},
|
|
115
|
+
activityStore,
|
|
116
|
+
emitEvent,
|
|
117
|
+
makeLogger(),
|
|
118
|
+
)
|
|
119
|
+
await exec.executeBatch(twoCallResponse('grep', { p: '1' }, { p: '2' }))
|
|
120
|
+
expect(maxActive).toBe(2) // both ran at once
|
|
121
|
+
})
|
|
122
|
+
})
|
|
@@ -18,7 +18,10 @@ function makeLogger(): Logger {
|
|
|
18
18
|
error: vi.fn(),
|
|
19
19
|
debug: vi.fn(),
|
|
20
20
|
}
|
|
21
|
-
return {
|
|
21
|
+
return {
|
|
22
|
+
...stub,
|
|
23
|
+
child: vi.fn(() => ({ ...stub, child: vi.fn() })),
|
|
24
|
+
} as unknown as Logger
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
function makeToolRegistry(execute: ToolRegistryContract['execute']): ToolRegistryContract {
|
|
@@ -93,6 +96,42 @@ describe('ToolExecutor plugin hooks', () => {
|
|
|
93
96
|
expect(batch.results[0]?.output).toBe('ok')
|
|
94
97
|
})
|
|
95
98
|
|
|
99
|
+
it('preserves tool stdout/stderr when a tool exits unsuccessfully', async () => {
|
|
100
|
+
const tools = makeToolRegistry(
|
|
101
|
+
vi.fn(async () => ({
|
|
102
|
+
success: false,
|
|
103
|
+
output: 'STDOUT:\npartial result\n\nSTDERR:\nboom',
|
|
104
|
+
error: 'Command exited with code 1',
|
|
105
|
+
})),
|
|
106
|
+
)
|
|
107
|
+
const exec = new ToolExecutor(
|
|
108
|
+
{
|
|
109
|
+
tools,
|
|
110
|
+
runId: mockRunId,
|
|
111
|
+
workingDirectory: '/tmp',
|
|
112
|
+
permissionMode: 'auto',
|
|
113
|
+
env: {},
|
|
114
|
+
abortSignal: new AbortController().signal,
|
|
115
|
+
},
|
|
116
|
+
activityStore,
|
|
117
|
+
emitEvent,
|
|
118
|
+
makeLogger(),
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
const batch = await exec.executeBatch(buildResponse('bash', { command: 'false' }))
|
|
122
|
+
expect(batch.results[0]?.output).toContain('STDOUT:\npartial result')
|
|
123
|
+
expect(batch.results[0]?.output).toContain('STDERR:\nboom')
|
|
124
|
+
expect(batch.results[0]?.output).toContain('Error: Command exited with code 1')
|
|
125
|
+
|
|
126
|
+
const completed = emitted.find((e) => e.type === 'tool_completed')
|
|
127
|
+
expect(completed).toMatchObject({
|
|
128
|
+
type: 'tool_completed',
|
|
129
|
+
toolName: 'bash',
|
|
130
|
+
result: expect.stringContaining('STDOUT:\npartial result'),
|
|
131
|
+
isError: true,
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
96
135
|
it('replaces input on pre_tool_use modify', async () => {
|
|
97
136
|
const executeMock = vi.fn(async () => ({ success: true, output: 'ok' }))
|
|
98
137
|
const tools = makeToolRegistry(executeMock)
|
|
@@ -120,7 +159,10 @@ describe('ToolExecutor plugin hooks', () => {
|
|
|
120
159
|
})
|
|
121
160
|
|
|
122
161
|
it('skips registry execution and synthesizes output on pre_tool_use skip', async () => {
|
|
123
|
-
const executeMock = vi.fn(async () => ({
|
|
162
|
+
const executeMock = vi.fn(async () => ({
|
|
163
|
+
success: true,
|
|
164
|
+
output: 'should-not-run',
|
|
165
|
+
}))
|
|
124
166
|
const tools = makeToolRegistry(executeMock)
|
|
125
167
|
const pluginManager = makePluginManager(async (event) =>
|
|
126
168
|
event === 'pre_tool_use'
|
|
@@ -223,7 +265,10 @@ describe('ToolExecutor plugin hooks', () => {
|
|
|
223
265
|
})
|
|
224
266
|
|
|
225
267
|
it('carries modified input into synthetic skip outcome (modify -> skip chain)', async () => {
|
|
226
|
-
const executeMock = vi.fn(async () => ({
|
|
268
|
+
const executeMock = vi.fn(async () => ({
|
|
269
|
+
success: true,
|
|
270
|
+
output: 'should-not-run',
|
|
271
|
+
}))
|
|
227
272
|
const tools = makeToolRegistry(executeMock)
|
|
228
273
|
const { PluginLifecycleManager } = await import('../../../plugin/lifecycle.js')
|
|
229
274
|
const realManager = new PluginLifecycleManager({
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { readFile, rm } from 'node:fs/promises'
|
|
2
|
+
import { mkdtemp } from 'node:fs/promises'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
6
|
+
|
|
7
|
+
import { ToolRegistry } from '../../../registry/tool/execute.js'
|
|
8
|
+
import { EditTool, WriteFileTool } from '../../../tools/builtins/index.js'
|
|
9
|
+
import type { SessionId, TenantId } from '../../../types/ids/index.js'
|
|
10
|
+
import { createUserMessage } from '../../../types/message/index.js'
|
|
11
|
+
import type { LLMProvider, StreamChunk } from '../../../types/provider/index.js'
|
|
12
|
+
import type { RunEvent } from '../../../types/run/index.js'
|
|
13
|
+
import type { ProjectId, ThreadId } from '../../../types/session/ids.js'
|
|
14
|
+
import { drainQuery } from '../index.js'
|
|
15
|
+
|
|
16
|
+
const ZERO_USAGE = {
|
|
17
|
+
promptTokens: 0,
|
|
18
|
+
completionTokens: 0,
|
|
19
|
+
totalTokens: 0,
|
|
20
|
+
cachedTokens: 0,
|
|
21
|
+
cacheWriteTokens: 0,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ToolStep {
|
|
25
|
+
readonly name: string
|
|
26
|
+
readonly input: Record<string, unknown>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
class ScriptedLongDocumentProvider implements LLMProvider {
|
|
30
|
+
readonly id = 'scripted-long-document'
|
|
31
|
+
readonly name = 'Scripted Long Document Provider'
|
|
32
|
+
calls = 0
|
|
33
|
+
|
|
34
|
+
constructor(private readonly steps: readonly ToolStep[]) {}
|
|
35
|
+
|
|
36
|
+
async *chatStream(): AsyncIterable<StreamChunk> {
|
|
37
|
+
const step = this.steps[this.calls]
|
|
38
|
+
this.calls += 1
|
|
39
|
+
|
|
40
|
+
if (!step) {
|
|
41
|
+
yield {
|
|
42
|
+
id: 'msg_done',
|
|
43
|
+
delta: { content: 'Long document created and verified.' },
|
|
44
|
+
finishReason: 'stop',
|
|
45
|
+
usage: ZERO_USAGE,
|
|
46
|
+
}
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
yield {
|
|
51
|
+
id: `msg_${this.calls}`,
|
|
52
|
+
delta: {
|
|
53
|
+
toolCalls: [
|
|
54
|
+
{
|
|
55
|
+
index: 0,
|
|
56
|
+
id: `toolu_${this.calls}`,
|
|
57
|
+
type: 'function',
|
|
58
|
+
function: { name: step.name },
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
yield {
|
|
64
|
+
id: `msg_${this.calls}`,
|
|
65
|
+
delta: {
|
|
66
|
+
toolCalls: [
|
|
67
|
+
{
|
|
68
|
+
index: 0,
|
|
69
|
+
id: `toolu_${this.calls}`,
|
|
70
|
+
function: { arguments: JSON.stringify(step.input) },
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
yield {
|
|
76
|
+
id: `msg_${this.calls}`,
|
|
77
|
+
delta: {},
|
|
78
|
+
finishReason: 'tool_calls',
|
|
79
|
+
usage: ZERO_USAGE,
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
describe('query long-document tool flow', () => {
|
|
85
|
+
const workdirs: string[] = []
|
|
86
|
+
|
|
87
|
+
afterEach(async () => {
|
|
88
|
+
await Promise.all(workdirs.map((dir) => rm(dir, { recursive: true, force: true })))
|
|
89
|
+
workdirs.length = 0
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('executes the canonical write skeleton plus bounded edit chunks flow end to end', async () => {
|
|
93
|
+
const workingDirectory = await mkdtemp(join(tmpdir(), 'namzu-query-long-doc-'))
|
|
94
|
+
workdirs.push(workingDirectory)
|
|
95
|
+
|
|
96
|
+
const chunks = Array.from({ length: 4 }, (_, sectionIndex) => {
|
|
97
|
+
const lines = Array.from({ length: 40 }, (_, lineIndex) => {
|
|
98
|
+
return `Section ${sectionIndex + 1}.${lineIndex + 1}: this content is intentionally long enough to require repeated bounded edit calls.`
|
|
99
|
+
})
|
|
100
|
+
const chunk = [`## Section ${sectionIndex + 1}`, ...lines, ''].join('\n')
|
|
101
|
+
expect(chunk.length).toBeLessThan(12_000)
|
|
102
|
+
return chunk
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const provider = new ScriptedLongDocumentProvider([
|
|
106
|
+
{
|
|
107
|
+
name: 'write',
|
|
108
|
+
input: {
|
|
109
|
+
path: 'outputs/long-document-flow.md',
|
|
110
|
+
content: '# Long document flow\n\n{{BODY}}\n',
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: 'edit',
|
|
115
|
+
input: {
|
|
116
|
+
path: 'outputs/long-document-flow.md',
|
|
117
|
+
oldStr: '{{BODY}}',
|
|
118
|
+
newStr: chunks[0],
|
|
119
|
+
replace_all: false,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
...chunks.slice(1).map((chunk) => ({
|
|
123
|
+
name: 'edit',
|
|
124
|
+
input: {
|
|
125
|
+
path: 'outputs/long-document-flow.md',
|
|
126
|
+
insertLine: 'end',
|
|
127
|
+
newStr: chunk,
|
|
128
|
+
replace_all: false,
|
|
129
|
+
},
|
|
130
|
+
})),
|
|
131
|
+
])
|
|
132
|
+
const tools = new ToolRegistry()
|
|
133
|
+
tools.register(WriteFileTool)
|
|
134
|
+
tools.register(EditTool)
|
|
135
|
+
const events: RunEvent[] = []
|
|
136
|
+
|
|
137
|
+
const run = await drainQuery(
|
|
138
|
+
{
|
|
139
|
+
provider,
|
|
140
|
+
tools,
|
|
141
|
+
runConfig: {
|
|
142
|
+
model: 'mock-model',
|
|
143
|
+
timeoutMs: 5_000,
|
|
144
|
+
tokenBudget: 100_000,
|
|
145
|
+
maxIterations: 8,
|
|
146
|
+
maxResponseTokens: 256,
|
|
147
|
+
},
|
|
148
|
+
agentId: 'agent_long_doc',
|
|
149
|
+
agentName: 'Long Document Agent',
|
|
150
|
+
messages: [createUserMessage('create a long document')],
|
|
151
|
+
workingDirectory,
|
|
152
|
+
sessionId: 'ses_long_document_flow' as SessionId,
|
|
153
|
+
threadId: 'thd_long_document_flow' as ThreadId,
|
|
154
|
+
projectId: 'prj_long_document_flow' as ProjectId,
|
|
155
|
+
tenantId: 'tnt_long_document_flow' as TenantId,
|
|
156
|
+
},
|
|
157
|
+
(event) => {
|
|
158
|
+
events.push(event)
|
|
159
|
+
},
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
const final = await readFile(join(workingDirectory, 'outputs/long-document-flow.md'), 'utf-8')
|
|
163
|
+
const executingTools = events
|
|
164
|
+
.filter(
|
|
165
|
+
(event): event is Extract<RunEvent, { type: 'tool_executing' }> =>
|
|
166
|
+
event.type === 'tool_executing',
|
|
167
|
+
)
|
|
168
|
+
.map((event) => event.toolName)
|
|
169
|
+
|
|
170
|
+
expect(run.status).toBe('completed')
|
|
171
|
+
expect(run.result).toBe('Long document created and verified.')
|
|
172
|
+
expect(provider.calls).toBe(6)
|
|
173
|
+
expect(executingTools).toEqual(['write', 'edit', 'edit', 'edit', 'edit'])
|
|
174
|
+
expect(final).not.toContain('{{BODY}}')
|
|
175
|
+
expect(final.split('\n').length).toBeGreaterThan(160)
|
|
176
|
+
expect(final).toContain('## Section 1')
|
|
177
|
+
expect(final).toContain('## Section 4')
|
|
178
|
+
expect(final).toContain('Section 4.40')
|
|
179
|
+
})
|
|
180
|
+
})
|
|
@@ -25,7 +25,7 @@ describe('PromptBuilder runtime context', () => {
|
|
|
25
25
|
label: 'test runtime',
|
|
26
26
|
outputDirectory: 'outputs/',
|
|
27
27
|
outputFileMarker: 'OUTPUT_FILE: <filename> - <description>',
|
|
28
|
-
notes: ['
|
|
28
|
+
notes: ['Register generated files after the turn.'],
|
|
29
29
|
},
|
|
30
30
|
}).build('full', '/tmp/work')
|
|
31
31
|
|
|
@@ -33,6 +33,59 @@ describe('PromptBuilder runtime context', () => {
|
|
|
33
33
|
expect(prompt).toContain('Working directory: /tmp/work')
|
|
34
34
|
expect(prompt).toContain('Output directory: outputs/')
|
|
35
35
|
expect(prompt).toContain('OUTPUT_FILE: <filename> - <description>')
|
|
36
|
-
expect(prompt).toContain('
|
|
36
|
+
expect(prompt).toContain('Register generated files after the turn.')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('discloses available skills even when the host supplies a systemPrompt', () => {
|
|
40
|
+
const prompt = new PromptBuilder({
|
|
41
|
+
systemPrompt: 'You are a project assistant.',
|
|
42
|
+
tools: makeToolRegistry(),
|
|
43
|
+
skills: [
|
|
44
|
+
{
|
|
45
|
+
metadata: {
|
|
46
|
+
name: 'delivery-briefing',
|
|
47
|
+
description: 'Draft and edit delivery briefings from grounded inputs.',
|
|
48
|
+
},
|
|
49
|
+
dirPath: '/repo/.agents/skills/delivery-briefing',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
}).build('full', '/tmp/work')
|
|
53
|
+
|
|
54
|
+
expect(prompt).toContain('You are a project assistant.')
|
|
55
|
+
expect(prompt).toContain('## Available Skills')
|
|
56
|
+
expect(prompt).toContain('<available_skills>')
|
|
57
|
+
expect(prompt).toContain('delivery-briefing')
|
|
58
|
+
expect(prompt).toContain('Draft and edit delivery briefings')
|
|
59
|
+
expect(prompt).toContain('<location>/repo/.agents/skills/delivery-briefing/SKILL.md</location>')
|
|
60
|
+
expect(prompt).toContain('The following block is a manifest')
|
|
61
|
+
expect(prompt).not.toContain('## Loaded Skills')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('includes loaded skill bodies with systemPrompt while preserving the metadata catalogue', () => {
|
|
65
|
+
const prompt = new PromptBuilder({
|
|
66
|
+
systemPrompt: 'You are a cowork supervisor.',
|
|
67
|
+
tools: makeToolRegistry(),
|
|
68
|
+
skills: [
|
|
69
|
+
{
|
|
70
|
+
metadata: {
|
|
71
|
+
name: 'structured-file-authoring',
|
|
72
|
+
description: 'Create structured files with bounded edit chunks.',
|
|
73
|
+
license: 'MIT',
|
|
74
|
+
compatibility: 'Requires file tools',
|
|
75
|
+
allowedTools: 'read write edit',
|
|
76
|
+
},
|
|
77
|
+
body: 'Use skeleton-first writes and bounded edit chunks.',
|
|
78
|
+
dirPath: '/repo/.agents/skills/structured-file-authoring',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
}).build('full', '/tmp/work')
|
|
82
|
+
|
|
83
|
+
expect(prompt).toContain('## Available Skills')
|
|
84
|
+
expect(prompt).toContain('<license>MIT</license>')
|
|
85
|
+
expect(prompt).toContain('<compatibility>Requires file tools</compatibility>')
|
|
86
|
+
expect(prompt).toContain('<allowed_tools>read write edit</allowed_tools>')
|
|
87
|
+
expect(prompt).toContain('read the SKILL.md at its <location> before writing code')
|
|
88
|
+
expect(prompt).toContain('## Loaded Skills')
|
|
89
|
+
expect(prompt).toContain('Use skeleton-first writes')
|
|
37
90
|
})
|
|
38
91
|
})
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { mkdtemp, rm } from 'node:fs/promises'
|
|
2
|
+
import { tmpdir } from 'node:os'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
5
|
+
import { z } from 'zod'
|
|
6
|
+
|
|
7
|
+
import { ToolRegistry } from '../../../registry/tool/execute.js'
|
|
8
|
+
import type { SessionId, TenantId } from '../../../types/ids/index.js'
|
|
9
|
+
import { createUserMessage } from '../../../types/message/index.js'
|
|
10
|
+
import type { LLMProvider, StreamChunk } from '../../../types/provider/index.js'
|
|
11
|
+
import type { RunEvent } from '../../../types/run/index.js'
|
|
12
|
+
import type { ProjectId, ThreadId } from '../../../types/session/ids.js'
|
|
13
|
+
import { drainQuery } from '../index.js'
|
|
14
|
+
|
|
15
|
+
const ZERO_USAGE = {
|
|
16
|
+
promptTokens: 0,
|
|
17
|
+
completionTokens: 0,
|
|
18
|
+
totalTokens: 0,
|
|
19
|
+
cachedTokens: 0,
|
|
20
|
+
cacheWriteTokens: 0,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class IdleDuringToolInputProvider implements LLMProvider {
|
|
24
|
+
readonly id = 'idle-during-tool-input'
|
|
25
|
+
readonly name = 'Idle During Tool Input Provider'
|
|
26
|
+
calls = 0
|
|
27
|
+
|
|
28
|
+
async *chatStream(): AsyncIterable<StreamChunk> {
|
|
29
|
+
this.calls += 1
|
|
30
|
+
|
|
31
|
+
if (this.calls === 1) {
|
|
32
|
+
yield {
|
|
33
|
+
id: 'msg_1',
|
|
34
|
+
delta: {
|
|
35
|
+
toolCalls: [
|
|
36
|
+
{
|
|
37
|
+
index: 0,
|
|
38
|
+
id: 'toolu_write_1',
|
|
39
|
+
type: 'function',
|
|
40
|
+
function: { name: 'write_file' },
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
yield {
|
|
46
|
+
id: 'msg_1',
|
|
47
|
+
delta: {
|
|
48
|
+
toolCalls: [
|
|
49
|
+
{
|
|
50
|
+
index: 0,
|
|
51
|
+
id: 'toolu_write_1',
|
|
52
|
+
function: {
|
|
53
|
+
arguments: '{"path":"/tmp/out.md","content":"partial',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
throw new Error('Anthropic stream idle for 90s')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
yield {
|
|
63
|
+
id: 'msg_2',
|
|
64
|
+
delta: { content: 'Recovered after retry guidance.' },
|
|
65
|
+
}
|
|
66
|
+
yield {
|
|
67
|
+
id: 'msg_2',
|
|
68
|
+
delta: {},
|
|
69
|
+
finishReason: 'stop',
|
|
70
|
+
usage: ZERO_USAGE,
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
describe('query stream recovery', () => {
|
|
76
|
+
let workdirs: string[] = []
|
|
77
|
+
|
|
78
|
+
afterEach(async () => {
|
|
79
|
+
await Promise.all(workdirs.map((dir) => rm(dir, { recursive: true, force: true })))
|
|
80
|
+
workdirs = []
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('turns an idle stream with partial tool JSON into retryable tool feedback', async () => {
|
|
84
|
+
const provider = new IdleDuringToolInputProvider()
|
|
85
|
+
const actualWrite = vi.fn(async () => ({ success: true, output: 'should not run' }))
|
|
86
|
+
const tools = new ToolRegistry()
|
|
87
|
+
tools.register({
|
|
88
|
+
name: 'write_file',
|
|
89
|
+
description: 'write a file',
|
|
90
|
+
inputSchema: z.object({
|
|
91
|
+
path: z.string(),
|
|
92
|
+
content: z.string(),
|
|
93
|
+
}),
|
|
94
|
+
execute: actualWrite,
|
|
95
|
+
})
|
|
96
|
+
const workingDirectory = await mkdtemp(join(tmpdir(), 'namzu-stream-recovery-'))
|
|
97
|
+
workdirs.push(workingDirectory)
|
|
98
|
+
const events: RunEvent[] = []
|
|
99
|
+
|
|
100
|
+
const run = await drainQuery(
|
|
101
|
+
{
|
|
102
|
+
provider,
|
|
103
|
+
tools,
|
|
104
|
+
runConfig: {
|
|
105
|
+
model: 'mock-model',
|
|
106
|
+
timeoutMs: 5_000,
|
|
107
|
+
tokenBudget: 100_000,
|
|
108
|
+
maxIterations: 3,
|
|
109
|
+
maxResponseTokens: 256,
|
|
110
|
+
},
|
|
111
|
+
agentId: 'agent_test',
|
|
112
|
+
agentName: 'Test Agent',
|
|
113
|
+
messages: [createUserMessage('write the file')],
|
|
114
|
+
workingDirectory,
|
|
115
|
+
sessionId: 'ses_stream_recovery' as SessionId,
|
|
116
|
+
threadId: 'thd_stream_recovery' as ThreadId,
|
|
117
|
+
projectId: 'prj_stream_recovery' as ProjectId,
|
|
118
|
+
tenantId: 'tnt_stream_recovery' as TenantId,
|
|
119
|
+
},
|
|
120
|
+
(event) => {
|
|
121
|
+
events.push(event)
|
|
122
|
+
},
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
expect(run.status).toBe('completed')
|
|
126
|
+
expect(run.result).toBe('Recovered after retry guidance.')
|
|
127
|
+
expect(provider.calls).toBe(2)
|
|
128
|
+
expect(actualWrite).not.toHaveBeenCalled()
|
|
129
|
+
|
|
130
|
+
expect(events.some((event) => event.type === 'run_failed')).toBe(false)
|
|
131
|
+
expect(
|
|
132
|
+
events.some(
|
|
133
|
+
(event) =>
|
|
134
|
+
event.type === 'tool_input_completed' &&
|
|
135
|
+
event.inputTruncated === true &&
|
|
136
|
+
JSON.stringify(event.input) === '{}',
|
|
137
|
+
),
|
|
138
|
+
).toBe(true)
|
|
139
|
+
expect(JSON.stringify(events)).not.toContain('__namzuTruncated')
|
|
140
|
+
|
|
141
|
+
const completedTool = events.find(
|
|
142
|
+
(event) => event.type === 'tool_completed' && event.toolUseId === 'toolu_write_1',
|
|
143
|
+
)
|
|
144
|
+
expect(completedTool).toMatchObject({
|
|
145
|
+
type: 'tool_completed',
|
|
146
|
+
toolName: 'write_file',
|
|
147
|
+
isError: true,
|
|
148
|
+
})
|
|
149
|
+
expect(completedTool?.type === 'tool_completed' ? completedTool.result : '').toContain(
|
|
150
|
+
'call was cut off',
|
|
151
|
+
)
|
|
152
|
+
expect(completedTool?.type === 'tool_completed' ? completedTool.result : '').toContain(
|
|
153
|
+
'extend it with edit using insertLine',
|
|
154
|
+
)
|
|
155
|
+
})
|
|
156
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synthetic user prompt injected by the iteration loop when a turn
|
|
3
|
+
* ends with `stop_reason: max_tokens` AND no tool_use. Mirrors
|
|
4
|
+
* Claude.ai's "Continue" affordance: the loop pushes this message
|
|
5
|
+
* back into the conversation and fires another iteration, letting
|
|
6
|
+
* the model pick up where it was cut off.
|
|
7
|
+
*
|
|
8
|
+
* The exact string is the marker used by `resolveResult` (in
|
|
9
|
+
* `manager/run/persistence.ts`) to detect auto-continuation
|
|
10
|
+
* boundaries: when walking the message tail it skips user messages
|
|
11
|
+
* that match this constant verbatim, so the run's `result` field
|
|
12
|
+
* concatenates the full multi-turn assistant output instead of only
|
|
13
|
+
* surfacing the trailing continuation chunk.
|
|
14
|
+
*/
|
|
15
|
+
export const AUTO_CONTINUATION_USER_MESSAGE =
|
|
16
|
+
'Continue exactly where you left off. Do not repeat content you already wrote — pick up at the next token.'
|