@namzu/sdk 1.0.0 → 1.2.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 +253 -0
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +5 -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 +47 -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/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +2 -0
- package/dist/bridge/a2a/mapper.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +4 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- 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/{runtime/query → constants}/continuation.d.ts +5 -0
- package/dist/constants/continuation.d.ts.map +1 -0
- package/dist/{runtime/query → constants}/continuation.js +5 -0
- package/dist/constants/continuation.js.map +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +1 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +11 -0
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +30 -1
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/persona/assembler.d.ts.map +1 -1
- package/dist/persona/assembler.js +18 -9
- package/dist/persona/assembler.js.map +1 -1
- package/dist/provider/capabilities.d.ts +27 -0
- package/dist/provider/capabilities.d.ts.map +1 -0
- package/dist/provider/capabilities.js +29 -0
- package/dist/provider/capabilities.js.map +1 -0
- 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/index.d.ts +2 -0
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +1 -0
- package/dist/provider/index.js.map +1 -1
- package/dist/public-runtime.d.ts +4 -3
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +3 -3
- package/dist/public-runtime.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 +124 -21
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/registry/tool/execute.test.d.ts +9 -6
- package/dist/registry/tool/execute.test.d.ts.map +1 -1
- package/dist/registry/tool/execute.test.js +72 -10
- package/dist/registry/tool/execute.test.js.map +1 -1
- package/dist/registry/toolset/catalog.test.js +62 -0
- package/dist/registry/toolset/catalog.test.js.map +1 -1
- package/dist/run/reporter.d.ts.map +1 -1
- package/dist/run/reporter.js +8 -0
- package/dist/run/reporter.js.map +1 -1
- package/dist/runtime/query/__tests__/capability-negotiation.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/capability-negotiation.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/capability-negotiation.test.js +184 -0
- package/dist/runtime/query/__tests__/capability-negotiation.test.js.map +1 -0
- package/dist/runtime/query/__tests__/checkpoint-store.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/checkpoint-store.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/checkpoint-store.test.js +259 -0
- package/dist/runtime/query/__tests__/checkpoint-store.test.js.map +1 -0
- package/dist/runtime/query/__tests__/checkpoint.test.js +9 -3
- package/dist/runtime/query/__tests__/checkpoint.test.js.map +1 -1
- package/dist/runtime/query/__tests__/deferred-tools.test.js +43 -5
- package/dist/runtime/query/__tests__/deferred-tools.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__/orphan-task-turn-end.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/orphan-task-turn-end.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/orphan-task-turn-end.test.js +110 -0
- package/dist/runtime/query/__tests__/orphan-task-turn-end.test.js.map +1 -0
- package/dist/runtime/query/__tests__/prompt.test.js +15 -11
- package/dist/runtime/query/__tests__/prompt.test.js.map +1 -1
- package/dist/runtime/query/checkpoint.d.ts +16 -2
- package/dist/runtime/query/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/checkpoint.js +21 -7
- package/dist/runtime/query/checkpoint.js.map +1 -1
- package/dist/runtime/query/context.d.ts +7 -0
- package/dist/runtime/query/context.d.ts.map +1 -1
- package/dist/runtime/query/context.js +1 -0
- package/dist/runtime/query/context.js.map +1 -1
- package/dist/runtime/query/index.d.ts +29 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +98 -8
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +3 -55
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +260 -656
- 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 +24 -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 +13 -2
- 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/iteration/stream-turn.d.ts +35 -0
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -0
- package/dist/runtime/query/iteration/stream-turn.js +341 -0
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -0
- package/dist/runtime/query/replay/list.d.ts +17 -1
- package/dist/runtime/query/replay/list.d.ts.map +1 -1
- package/dist/runtime/query/replay/list.js +21 -4
- package/dist/runtime/query/replay/list.js.map +1 -1
- package/dist/runtime/query/replay/prepare.d.ts +10 -0
- package/dist/runtime/query/replay/prepare.d.ts.map +1 -1
- package/dist/runtime/query/replay/prepare.js +20 -4
- package/dist/runtime/query/replay/prepare.js.map +1 -1
- package/dist/session/workspace/__tests__/shared-run.test.js +1 -1
- package/dist/session/workspace/__tests__/shared-run.test.js.map +1 -1
- package/dist/session/workspace/shared-run.js +1 -0
- package/dist/session/workspace/shared-run.js.map +1 -1
- package/dist/skills/loader.test.js +8 -8
- package/dist/skills/loader.test.js.map +1 -1
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +1 -0
- package/dist/store/index.js.map +1 -1
- package/dist/store/run/checkpoint-disk.d.ts +28 -0
- package/dist/store/run/checkpoint-disk.d.ts.map +1 -0
- package/dist/store/run/checkpoint-disk.js +55 -0
- package/dist/store/run/checkpoint-disk.js.map +1 -0
- package/dist/streaming/coalesce.test.js.map +1 -1
- package/dist/tools/builtins/__tests__/payload-budget.test.js +48 -0
- package/dist/tools/builtins/__tests__/payload-budget.test.js.map +1 -1
- package/dist/tools/builtins/__tests__/read-file.test.js +9 -0
- package/dist/tools/builtins/__tests__/read-file.test.js.map +1 -1
- package/dist/tools/builtins/read-file.d.ts.map +1 -1
- package/dist/tools/builtins/read-file.js +50 -2
- 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 +32 -7
- package/dist/tools/builtins/search-tools.js.map +1 -1
- 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/index.d.ts +8 -0
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +195 -15
- package/dist/tools/coordinator/index.js.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 +15 -0
- package/dist/types/agent/reactive.d.ts.map +1 -1
- package/dist/types/agent/supervisor.d.ts +18 -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/provider/chat.d.ts +9 -0
- package/dist/types/provider/chat.d.ts.map +1 -1
- package/dist/types/provider/config.d.ts +18 -0
- package/dist/types/provider/config.d.ts.map +1 -1
- package/dist/types/provider/interface.d.ts +10 -0
- package/dist/types/provider/interface.d.ts.map +1 -1
- package/dist/types/run/checkpoint-store.d.ts +64 -0
- package/dist/types/run/checkpoint-store.d.ts.map +1 -0
- package/dist/types/run/checkpoint-store.js +12 -0
- package/dist/types/run/checkpoint-store.js.map +1 -0
- package/dist/types/run/config.d.ts +27 -0
- package/dist/types/run/config.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/run/index.d.ts +1 -0
- package/dist/types/run/index.d.ts.map +1 -1
- package/dist/types/run/index.js +1 -0
- package/dist/types/run/index.js.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +25 -4
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/src/agents/ReactiveAgent.ts +5 -0
- package/src/agents/SupervisorAgent.ts +56 -16
- package/src/agents/__tests__/supervisor-ledger.test.ts +185 -0
- package/src/bridge/a2a/mapper.ts +3 -0
- package/src/bridge/sse/mapper.ts +5 -0
- 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/{runtime/query → constants}/continuation.ts +5 -0
- package/src/constants/index.ts +1 -0
- package/src/manager/run/persistence.ts +34 -1
- package/src/persona/assembler.ts +18 -6
- package/src/provider/capabilities.ts +47 -0
- package/src/provider/collect.ts +4 -1
- package/src/provider/index.ts +5 -0
- package/src/public-runtime.ts +5 -0
- package/src/registry/tool/execute.test.ts +85 -10
- package/src/registry/tool/execute.ts +124 -21
- package/src/registry/toolset/catalog.test.ts +68 -0
- package/src/run/reporter.ts +9 -0
- package/src/runtime/query/__tests__/capability-negotiation.test.ts +248 -0
- package/src/runtime/query/__tests__/checkpoint-store.test.ts +322 -0
- package/src/runtime/query/__tests__/checkpoint.test.ts +15 -6
- package/src/runtime/query/__tests__/deferred-tools.test.ts +52 -5
- package/src/runtime/query/__tests__/long-document-flow.test.ts +180 -0
- package/src/runtime/query/__tests__/orphan-task-turn-end.test.ts +127 -0
- package/src/runtime/query/__tests__/prompt.test.ts +15 -11
- package/src/runtime/query/checkpoint.ts +23 -9
- package/src/runtime/query/context.ts +9 -0
- package/src/runtime/query/index.ts +148 -29
- package/src/runtime/query/iteration/index.ts +316 -831
- package/src/runtime/query/iteration/phases/checkpoint.ts +32 -2
- package/src/runtime/query/iteration/phases/compaction.ts +89 -3
- package/src/runtime/query/iteration/phases/context.ts +59 -3
- 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/iteration/stream-turn.ts +396 -0
- package/src/runtime/query/replay/list.ts +38 -4
- package/src/runtime/query/replay/prepare.ts +37 -4
- package/src/session/workspace/__tests__/shared-run.test.ts +1 -1
- package/src/session/workspace/shared-run.ts +1 -0
- package/src/skills/loader.test.ts +8 -8
- package/src/store/index.ts +1 -0
- package/src/store/run/checkpoint-disk.ts +67 -0
- package/src/streaming/coalesce.test.ts +3 -3
- package/src/tools/builtins/__tests__/payload-budget.test.ts +63 -0
- package/src/tools/builtins/__tests__/read-file.test.ts +12 -0
- package/src/tools/builtins/read-file.ts +50 -2
- package/src/tools/builtins/search-tools.ts +38 -7
- 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/index.ts +227 -17
- package/src/types/agent/index.ts +1 -0
- package/src/types/agent/reactive.ts +17 -0
- package/src/types/agent/supervisor.ts +20 -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/provider/chat.ts +10 -0
- package/src/types/provider/config.ts +18 -0
- package/src/types/provider/interface.ts +11 -0
- package/src/types/run/checkpoint-store.ts +72 -0
- package/src/types/run/config.ts +30 -0
- package/src/types/run/events.ts +13 -0
- package/src/types/run/index.ts +1 -0
- package/src/version.ts +26 -4
- package/dist/runtime/query/continuation.d.ts.map +0 -1
- package/dist/runtime/query/continuation.js.map +0 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
MCPJsonRpcMessage,
|
|
3
|
+
MCPStreamableHttpTransportConfig,
|
|
4
|
+
MCPTransport,
|
|
5
|
+
} from '../../types/connector/index.js'
|
|
6
|
+
import { type Logger, getRootLogger } from '../../utils/logger.js'
|
|
7
|
+
|
|
8
|
+
const DEFAULT_TIMEOUT_MS = 30_000
|
|
9
|
+
|
|
10
|
+
export class StreamableHttpTransport implements MCPTransport {
|
|
11
|
+
private messageHandlers: Array<(message: MCPJsonRpcMessage) => void> = []
|
|
12
|
+
private closeHandlers: Array<() => void> = []
|
|
13
|
+
private errorHandlers: Array<(error: Error) => void> = []
|
|
14
|
+
private connected = false
|
|
15
|
+
private sessionId: string | null = null
|
|
16
|
+
private log: Logger
|
|
17
|
+
|
|
18
|
+
constructor(private readonly config: MCPStreamableHttpTransportConfig) {
|
|
19
|
+
this.log = getRootLogger().child({ component: 'StreamableHttpTransport' })
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async connect(): Promise<void> {
|
|
23
|
+
if (this.connected) return
|
|
24
|
+
this.connected = true
|
|
25
|
+
this.log.info(`StreamableHttpTransport connected to ${this.config.url}`)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async close(): Promise<void> {
|
|
29
|
+
if (!this.connected) return
|
|
30
|
+
this.connected = false
|
|
31
|
+
for (const handler of this.closeHandlers) handler()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async send(message: MCPJsonRpcMessage): Promise<void> {
|
|
35
|
+
if (!this.connected) {
|
|
36
|
+
throw new Error('StreamableHttpTransport: not connected')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const controller = new AbortController()
|
|
40
|
+
const timeout = setTimeout(
|
|
41
|
+
() => controller.abort(),
|
|
42
|
+
this.config.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(this.config.url, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: this.buildHeaders(),
|
|
49
|
+
body: JSON.stringify(message),
|
|
50
|
+
signal: controller.signal,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
this.captureSessionId(response)
|
|
54
|
+
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
throw new Error(`StreamableHttpTransport: HTTP ${response.status}: ${response.statusText}`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
await this.dispatchResponseMessages(response)
|
|
60
|
+
} catch (err) {
|
|
61
|
+
const error = err instanceof Error ? err : new Error(String(err))
|
|
62
|
+
for (const handler of this.errorHandlers) handler(error)
|
|
63
|
+
throw error
|
|
64
|
+
} finally {
|
|
65
|
+
clearTimeout(timeout)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
onMessage(handler: (message: MCPJsonRpcMessage) => void): void {
|
|
70
|
+
this.messageHandlers.push(handler)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
onClose(handler: () => void): void {
|
|
74
|
+
this.closeHandlers.push(handler)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
onError(handler: (error: Error) => void): void {
|
|
78
|
+
this.errorHandlers.push(handler)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
isConnected(): boolean {
|
|
82
|
+
return this.connected
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private buildHeaders(): Record<string, string> {
|
|
86
|
+
const headers: Record<string, string> = {
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
Accept: 'application/json, text/event-stream',
|
|
89
|
+
...this.config.headers,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (this.sessionId) {
|
|
93
|
+
headers['Mcp-Session-Id'] = this.sessionId
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return headers
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private captureSessionId(response: Response): void {
|
|
100
|
+
const sessionId =
|
|
101
|
+
response.headers.get('mcp-session-id') ?? response.headers.get('Mcp-Session-Id')
|
|
102
|
+
if (sessionId && sessionId.length > 0) {
|
|
103
|
+
this.sessionId = sessionId
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private async dispatchResponseMessages(response: Response): Promise<void> {
|
|
108
|
+
const text = await response.text()
|
|
109
|
+
if (text.trim().length === 0) return
|
|
110
|
+
|
|
111
|
+
const contentType = response.headers.get('content-type') ?? ''
|
|
112
|
+
const messages = contentType.includes('text/event-stream')
|
|
113
|
+
? parseSseMessages(text)
|
|
114
|
+
: parseJsonMessages(text)
|
|
115
|
+
|
|
116
|
+
for (const message of messages) {
|
|
117
|
+
for (const handler of this.messageHandlers) handler(message)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function parseJsonMessages(raw: string): MCPJsonRpcMessage[] {
|
|
123
|
+
const parsed = JSON.parse(raw) as MCPJsonRpcMessage | MCPJsonRpcMessage[]
|
|
124
|
+
return Array.isArray(parsed) ? parsed : [parsed]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function parseSseMessages(raw: string): MCPJsonRpcMessage[] {
|
|
128
|
+
const normalized = raw.replace(/\r\n/g, '\n')
|
|
129
|
+
const events = normalized.split(/\n\n+/)
|
|
130
|
+
const messages: MCPJsonRpcMessage[] = []
|
|
131
|
+
|
|
132
|
+
for (const event of events) {
|
|
133
|
+
const dataLines = event
|
|
134
|
+
.split('\n')
|
|
135
|
+
.filter((line) => line.startsWith('data:'))
|
|
136
|
+
.map((line) => line.slice('data:'.length).trimStart())
|
|
137
|
+
|
|
138
|
+
if (dataLines.length === 0) continue
|
|
139
|
+
|
|
140
|
+
const data = dataLines.join('\n').trim()
|
|
141
|
+
if (data.length === 0 || data === '[DONE]') continue
|
|
142
|
+
|
|
143
|
+
const parsed = JSON.parse(data) as MCPJsonRpcMessage | MCPJsonRpcMessage[]
|
|
144
|
+
if (Array.isArray(parsed)) {
|
|
145
|
+
messages.push(...parsed)
|
|
146
|
+
} else {
|
|
147
|
+
messages.push(parsed)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return messages
|
|
152
|
+
}
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* that match this constant verbatim, so the run's `result` field
|
|
12
12
|
* concatenates the full multi-turn assistant output instead of only
|
|
13
13
|
* surfacing the trailing continuation chunk.
|
|
14
|
+
*
|
|
15
|
+
* Lives in `constants/` (not `runtime/query/`) because both the
|
|
16
|
+
* runtime iteration loop and `manager/run/persistence.ts` consume
|
|
17
|
+
* it — a manager→runtime import for a string constant would create
|
|
18
|
+
* a manager↔runtime directory cycle.
|
|
14
19
|
*/
|
|
15
20
|
export const AUTO_CONTINUATION_USER_MESSAGE =
|
|
16
21
|
'Continue exactly where you left off. Do not repeat content you already wrote — pick up at the next token.'
|
package/src/constants/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './rag/index.js'
|
|
|
7
7
|
export * from './tools/index.js'
|
|
8
8
|
export * from './telemetry/index.js'
|
|
9
9
|
export * from './agent/index.js'
|
|
10
|
+
export * from './continuation.js'
|
|
10
11
|
export * from './limits.js'
|
|
11
12
|
export * from './bus/index.js'
|
|
12
13
|
export * from './verification/index.js'
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { AUTO_CONTINUATION_USER_MESSAGE } from '../../constants/continuation.js'
|
|
1
2
|
import { EMPTY_TOKEN_USAGE } from '../../constants/limits.js'
|
|
2
|
-
import {
|
|
3
|
+
import { DiskCheckpointStore } from '../../store/run/checkpoint-disk.js'
|
|
3
4
|
import { RunDiskStore } from '../../store/run/disk.js'
|
|
4
5
|
import { type CostInfo, type TokenUsage, accumulateTokenUsage } from '../../types/common/index.js'
|
|
5
6
|
import type { RunId, SessionId, TenantId } from '../../types/ids/index.js'
|
|
6
7
|
import type { Message } from '../../types/message/index.js'
|
|
8
|
+
import type { CheckpointRunScope, CheckpointStore } from '../../types/run/checkpoint-store.js'
|
|
7
9
|
import type { EmergencySaveData } from '../../types/run/emergency.js'
|
|
8
10
|
import type { Run, RunPersistenceConfig, StopReason } from '../../types/run/index.js'
|
|
9
11
|
import type { ProjectId, ThreadId } from '../../types/session/ids.js'
|
|
@@ -14,6 +16,7 @@ import type { Logger } from '../../utils/logger.js'
|
|
|
14
16
|
export class RunPersistence {
|
|
15
17
|
private run: Run
|
|
16
18
|
private runStore: RunDiskStore
|
|
19
|
+
private checkpointStore: CheckpointStore
|
|
17
20
|
private pricing?: ModelPricing
|
|
18
21
|
private log: Logger
|
|
19
22
|
private readonly _sessionId: SessionId
|
|
@@ -34,6 +37,15 @@ export class RunPersistence {
|
|
|
34
37
|
logger: config.log,
|
|
35
38
|
})
|
|
36
39
|
|
|
40
|
+
// Checkpoints go through the injectable seam; the disk layout under
|
|
41
|
+
// `outputDir` (same tree the runStore writes to) stays the default.
|
|
42
|
+
this.checkpointStore =
|
|
43
|
+
config.checkpointStore ??
|
|
44
|
+
new DiskCheckpointStore({
|
|
45
|
+
baseDir: config.outputDir,
|
|
46
|
+
logger: config.log,
|
|
47
|
+
})
|
|
48
|
+
|
|
37
49
|
this.run = {
|
|
38
50
|
id: config.runId,
|
|
39
51
|
status: 'idle',
|
|
@@ -109,6 +121,27 @@ export class RunPersistence {
|
|
|
109
121
|
return this.runStore
|
|
110
122
|
}
|
|
111
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Checkpoint persistence for this run — the injected
|
|
126
|
+
* {@link CheckpointStore} when the host provided one, otherwise the
|
|
127
|
+
* disk default. Pair with {@link getRunScope} when constructing a
|
|
128
|
+
* `CheckpointManager`.
|
|
129
|
+
*/
|
|
130
|
+
getCheckpointStore(): CheckpointStore {
|
|
131
|
+
return this.checkpointStore
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Full five-layer scope key for this run's checkpoint operations. */
|
|
135
|
+
getRunScope(): CheckpointRunScope {
|
|
136
|
+
return {
|
|
137
|
+
tenantId: this._tenantId,
|
|
138
|
+
projectId: this._projectId,
|
|
139
|
+
sessionId: this._sessionId,
|
|
140
|
+
runId: this.run.id,
|
|
141
|
+
parentRunId: this.run.parentRunId,
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
112
145
|
getRunDir(): string | null {
|
|
113
146
|
return this.runStore.getRunDir()
|
|
114
147
|
}
|
package/src/persona/assembler.ts
CHANGED
|
@@ -48,17 +48,29 @@ export function renderSkillsSection(skills?: Skill[]): string | null {
|
|
|
48
48
|
|
|
49
49
|
const available = skills
|
|
50
50
|
.map((s) => {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
const lines = [
|
|
52
|
+
'<skill>',
|
|
53
|
+
`<name>${s.metadata.name}</name>`,
|
|
54
|
+
`<description>${s.metadata.description.trim()}</description>`,
|
|
55
|
+
`<location>${s.dirPath}/SKILL.md</location>`,
|
|
56
|
+
]
|
|
57
|
+
if (s.metadata.compatibility) {
|
|
58
|
+
lines.push(`<compatibility>${s.metadata.compatibility}</compatibility>`)
|
|
59
|
+
}
|
|
60
|
+
if (s.metadata.license) {
|
|
61
|
+
lines.push(`<license>${s.metadata.license}</license>`)
|
|
62
|
+
}
|
|
63
|
+
if (s.metadata.allowedTools) {
|
|
64
|
+
lines.push(`<allowed_tools>${s.metadata.allowedTools}</allowed_tools>`)
|
|
65
|
+
}
|
|
66
|
+
lines.push('</skill>')
|
|
67
|
+
return lines.join('\n')
|
|
56
68
|
})
|
|
57
69
|
.join('\n')
|
|
58
70
|
|
|
59
71
|
const loadedSkills = skills.filter((s) => s.body)
|
|
60
72
|
const sections = [
|
|
61
|
-
`## Available Skills\
|
|
73
|
+
`## Available Skills\nThe following block is a manifest, not the full skill content. Skill metadata is always visible; SKILL.md bodies are loaded only when the user's task matches the skill description.\n\n<available_skills>\n${available}\n</available_skills>\n\nSkill usage protocol:\n- Plain questions do not require a skill.\n- When a matching skill is already listed under Loaded Skills, apply its loaded instructions.\n- When a matching skill is not loaded and the runtime exposes filesystem or skill-loading tools, read the SKILL.md at its <location> before writing code, creating files, running shell commands for that workflow, or calling mutation tools guided by the skill.\n- Do not claim to have read a SKILL.md until its content is actually present in the prompt or returned by a tool.\n- Tool schemas and runtime permissions remain authoritative; skills provide guidance, not hidden tools.`,
|
|
62
74
|
]
|
|
63
75
|
|
|
64
76
|
if (loadedSkills.length > 0) {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { LLMProvider, ProviderCapabilities } from '../types/provider/index.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fully-resolved capability set: every flag present, no optionals left.
|
|
5
|
+
* What the query runtime branches on after applying the permissive default.
|
|
6
|
+
*/
|
|
7
|
+
export interface ResolvedProviderCapabilities {
|
|
8
|
+
supportsTools: boolean
|
|
9
|
+
supportsStreaming: boolean
|
|
10
|
+
supportsFunctionCalling: boolean
|
|
11
|
+
supportsVision: boolean
|
|
12
|
+
maxOutputTokens?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* THE permissive default: a provider that declares nothing is assumed to
|
|
17
|
+
* handle everything — exactly the pre-negotiation behavior, so third-party
|
|
18
|
+
* providers written before `LLMProvider.capabilities` existed keep working
|
|
19
|
+
* without a warning storm. Shipped drivers always declare explicitly.
|
|
20
|
+
*/
|
|
21
|
+
export const PERMISSIVE_PROVIDER_CAPABILITIES: ResolvedProviderCapabilities = {
|
|
22
|
+
supportsTools: true,
|
|
23
|
+
supportsStreaming: true,
|
|
24
|
+
supportsFunctionCalling: true,
|
|
25
|
+
supportsVision: true,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a provider's declared capabilities against the permissive
|
|
30
|
+
* default. Absent declaration ⇒ everything `true`; a partial declaration
|
|
31
|
+
* (e.g. one missing `supportsVision`, added later) fills the gap
|
|
32
|
+
* permissively per field.
|
|
33
|
+
*/
|
|
34
|
+
export function resolveProviderCapabilities(
|
|
35
|
+
provider: Pick<LLMProvider, 'capabilities'>,
|
|
36
|
+
): ResolvedProviderCapabilities {
|
|
37
|
+
const declared: ProviderCapabilities | undefined = provider.capabilities
|
|
38
|
+
return {
|
|
39
|
+
supportsTools: declared?.supportsTools ?? PERMISSIVE_PROVIDER_CAPABILITIES.supportsTools,
|
|
40
|
+
supportsStreaming:
|
|
41
|
+
declared?.supportsStreaming ?? PERMISSIVE_PROVIDER_CAPABILITIES.supportsStreaming,
|
|
42
|
+
supportsFunctionCalling:
|
|
43
|
+
declared?.supportsFunctionCalling ?? PERMISSIVE_PROVIDER_CAPABILITIES.supportsFunctionCalling,
|
|
44
|
+
supportsVision: declared?.supportsVision ?? PERMISSIVE_PROVIDER_CAPABILITIES.supportsVision,
|
|
45
|
+
maxOutputTokens: declared?.maxOutputTokens,
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/provider/collect.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { mergeTokenUsage } from '../types/common/index.js'
|
|
1
2
|
import type { ChatCompletionResponse } from '../types/provider/chat.js'
|
|
2
3
|
import type { StreamChunk } from '../types/provider/stream.js'
|
|
3
4
|
|
|
@@ -60,7 +61,9 @@ export async function collect(stream: AsyncIterable<StreamChunk>): Promise<ChatC
|
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
if (chunk.finishReason) finishReason = chunk.finishReason
|
|
63
|
-
|
|
64
|
+
// Merge (per-field max), not last-write-wins: a late frame that omits
|
|
65
|
+
// input/cache tokens must not zero the counts captured earlier in the stream.
|
|
66
|
+
if (chunk.usage) usage = mergeTokenUsage(usage, chunk.usage)
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
const toolCalls = [...toolBuckets.entries()]
|
package/src/provider/index.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
export { ProviderRegistry, UnknownProviderError, DuplicateProviderError } from './registry.js'
|
|
2
2
|
export { MockLLMProvider } from './mock.js'
|
|
3
3
|
export { registerMock, MOCK_CAPABILITIES } from './mock-register.js'
|
|
4
|
+
export {
|
|
5
|
+
PERMISSIVE_PROVIDER_CAPABILITIES,
|
|
6
|
+
resolveProviderCapabilities,
|
|
7
|
+
} from './capabilities.js'
|
|
8
|
+
export type { ResolvedProviderCapabilities } from './capabilities.js'
|
package/src/public-runtime.ts
CHANGED
|
@@ -99,6 +99,7 @@ export {
|
|
|
99
99
|
|
|
100
100
|
export {
|
|
101
101
|
ActivityStore,
|
|
102
|
+
DiskCheckpointStore,
|
|
102
103
|
DiskMemoryStore,
|
|
103
104
|
DiskTaskStore,
|
|
104
105
|
InMemoryMemoryIndex,
|
|
@@ -146,8 +147,10 @@ export {
|
|
|
146
147
|
DuplicateProviderError,
|
|
147
148
|
MOCK_CAPABILITIES,
|
|
148
149
|
MockLLMProvider,
|
|
150
|
+
PERMISSIVE_PROVIDER_CAPABILITIES,
|
|
149
151
|
ProviderRegistry,
|
|
150
152
|
registerMock,
|
|
153
|
+
resolveProviderCapabilities,
|
|
151
154
|
UnknownProviderError,
|
|
152
155
|
} from './provider/index.js'
|
|
153
156
|
|
|
@@ -194,6 +197,7 @@ export {
|
|
|
194
197
|
RemoteExecutionContext,
|
|
195
198
|
ScopedConnectorRegistry,
|
|
196
199
|
StdioTransport,
|
|
200
|
+
StreamableHttpTransport,
|
|
197
201
|
TenantConnectorManager,
|
|
198
202
|
toolDefinitionToMCPTool,
|
|
199
203
|
toolResultToMCPToolResult,
|
|
@@ -247,6 +251,7 @@ export {
|
|
|
247
251
|
|
|
248
252
|
export { wrapProviderWithProbes } from './provider/instrumentation.js'
|
|
249
253
|
export type { ProviderInstrumentationOptions } from './provider/instrumentation.js'
|
|
254
|
+
export type { ResolvedProviderCapabilities } from './provider/capabilities.js'
|
|
250
255
|
export { collect } from './provider/collect.js'
|
|
251
256
|
|
|
252
257
|
export { wrapVaultWithProbes } from './vault/instrumentation.js'
|
|
@@ -20,18 +20,21 @@
|
|
|
20
20
|
* reports true iff at least one tool is suspended.
|
|
21
21
|
* - `getAvailability(name)` returns 'active' as a default even for
|
|
22
22
|
* unknown names (this is non-obvious but is the current behavior).
|
|
23
|
-
* - `searchDeferred(q)`
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* - `searchDeferred(q)` is a RANKED weighted search over DEFERRED tools:
|
|
24
|
+
* per meaningful term (≥3 chars, not a stop token) the score is
|
|
25
|
+
* exact-name 12 / name-substring 8 / description 5 / argument-name 3;
|
|
26
|
+
* results sort score-descending with name ties broken alphabetically.
|
|
27
|
+
* Generic/short tokens (`clawtool`, `tool`, CRUD verbs like `list`,
|
|
28
|
+
* `read`, …) are stopped so they can't over-activate the catalog.
|
|
27
29
|
* - `assignTiers(mapping)` mutates `tool.tier` on existing tools;
|
|
28
30
|
* throws via `getOrThrow` on unknown name; throws if the tier id
|
|
29
31
|
* is not in `tierConfig.tiers`.
|
|
30
32
|
* - `toTierGuidance` returns null without a guidanceTemplate; calls
|
|
31
33
|
* the template with every defined tier otherwise.
|
|
32
34
|
* - `toPromptSection`: returns '' when no active or deferred tools;
|
|
33
|
-
* otherwise produces `<available_tools>`
|
|
34
|
-
*
|
|
35
|
+
* otherwise produces `<available_tools>` (name-only — descriptions
|
|
36
|
+
* already ride the runtime tools param) + `<deferred_tools>` (name +
|
|
37
|
+
* first-sentence hint ≤100 chars) fragments.
|
|
35
38
|
* - `toLLMTools`: converts active + suspended tools (filtered by
|
|
36
39
|
* `toolNames` if provided) into LLM tool schemas via
|
|
37
40
|
* `zodToJsonSchema`. When `tierConfig.labelInDescription` is true,
|
|
@@ -198,15 +201,59 @@ describe('ToolRegistry — searchDeferred', () => {
|
|
|
198
201
|
r.register([makeTool('clawtool_PeerRegister')], 'deferred')
|
|
199
202
|
r.register([makeTool('clawtool_PeerList')], 'deferred')
|
|
200
203
|
r.register([makeTool('clawtool_Unrelated')], 'deferred')
|
|
201
|
-
// A whole-phrase substring match would find none of these.
|
|
204
|
+
// A whole-phrase substring match would find none of these. Equal
|
|
205
|
+
// scores tie-break alphabetically by name (deterministic ranking).
|
|
202
206
|
expect(r.searchDeferred('A2aCard PeerRegister PeerList').map((t) => t.name)).toEqual([
|
|
203
207
|
'clawtool_A2aCard',
|
|
204
|
-
'clawtool_PeerRegister',
|
|
205
208
|
'clawtool_PeerList',
|
|
209
|
+
'clawtool_PeerRegister',
|
|
206
210
|
])
|
|
207
211
|
expect(r.searchDeferred(' ')).toEqual([])
|
|
208
212
|
})
|
|
209
213
|
|
|
214
|
+
it('ranks exact name above name substring above description-only matches', () => {
|
|
215
|
+
const r = new ToolRegistry()
|
|
216
|
+
r.register([makeTool('release_notes', { description: 'Write deploy notes.' })], 'deferred')
|
|
217
|
+
r.register([makeTool('deploy_preview', { description: 'Stage a preview build.' })], 'deferred')
|
|
218
|
+
r.register([makeTool('deploy', { description: 'Ship the current build.' })], 'deferred')
|
|
219
|
+
expect(r.searchDeferred('deploy').map((t) => t.name)).toEqual([
|
|
220
|
+
'deploy', // exact name → 12
|
|
221
|
+
'deploy_preview', // name substring → 8
|
|
222
|
+
'release_notes', // description only → 5
|
|
223
|
+
])
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
it('indexes argument names so a parameter term can locate a tool', () => {
|
|
227
|
+
const r = new ToolRegistry()
|
|
228
|
+
r.register(
|
|
229
|
+
[
|
|
230
|
+
makeTool('send_invoice', {
|
|
231
|
+
inputSchema: z.object({ customerEmail: z.string(), amount: z.number() }),
|
|
232
|
+
}),
|
|
233
|
+
],
|
|
234
|
+
'deferred',
|
|
235
|
+
)
|
|
236
|
+
r.register([makeTool('send_reminder')], 'deferred')
|
|
237
|
+
expect(r.searchDeferred('customerEmail').map((t) => t.name)).toEqual(['send_invoice'])
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
it('stops generic CRUD verbs so they cannot activate catalog slices', () => {
|
|
241
|
+
const r = new ToolRegistry()
|
|
242
|
+
r.register(
|
|
243
|
+
[makeTool('list_deals', { description: 'List the deals in an account.' })],
|
|
244
|
+
'deferred',
|
|
245
|
+
)
|
|
246
|
+
r.register([makeTool('list_workflows', { description: 'List workflows.' })], 'deferred')
|
|
247
|
+
r.register([makeTool('read_document', { description: 'Read a document body.' })], 'deferred')
|
|
248
|
+
// Bare CRUD verbs identify nothing.
|
|
249
|
+
expect(r.searchDeferred('list')).toEqual([])
|
|
250
|
+
expect(r.searchDeferred('read')).toEqual([])
|
|
251
|
+
expect(r.searchDeferred('create update delete')).toEqual([])
|
|
252
|
+
// The non-generic remainder carries the query.
|
|
253
|
+
expect(r.searchDeferred('list deals').map((t) => t.name)).toEqual(['list_deals'])
|
|
254
|
+
expect(r.searchDeferred('read document').map((t) => t.name)).toEqual(['read_document'])
|
|
255
|
+
})
|
|
256
|
+
|
|
210
257
|
it('does not over-activate on generic/shared tokens', () => {
|
|
211
258
|
const r = new ToolRegistry()
|
|
212
259
|
r.register([makeTool('clawtool_A2aCard', { description: 'peer card' })], 'deferred')
|
|
@@ -270,10 +317,38 @@ describe('ToolRegistry — toPromptSection + toLLMTools', () => {
|
|
|
270
317
|
expect(s).toContain('<tool_runtime_contract>')
|
|
271
318
|
expect(s).toContain('runtime tools parameter')
|
|
272
319
|
expect(s).toContain('<available_tools>')
|
|
273
|
-
|
|
320
|
+
// Active entries are NAME-ONLY: the description already rides the
|
|
321
|
+
// runtime tools param every request — repeating it double-bills.
|
|
322
|
+
expect(s).toContain('- a\n')
|
|
323
|
+
expect(s).not.toContain('- a: a tool')
|
|
274
324
|
expect(s).toContain('<deferred_tools>')
|
|
275
325
|
expect(s).toContain('Deferred tools are discoverable')
|
|
276
|
-
|
|
326
|
+
// Deferred entries carry a one-line hint — their schema is off the
|
|
327
|
+
// wire, so the hint is the model's only capability signal.
|
|
328
|
+
expect(s).toContain('- b: b tool')
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
it('toPromptSection truncates deferred hints to the first sentence, capped at 100 chars', () => {
|
|
332
|
+
const r = new ToolRegistry()
|
|
333
|
+
r.register(
|
|
334
|
+
[
|
|
335
|
+
makeTool('two_sentences', {
|
|
336
|
+
description: 'Reads the document. Second sentence that must not appear.',
|
|
337
|
+
}),
|
|
338
|
+
makeTool('long_sentence', {
|
|
339
|
+
description: `${'x'.repeat(150)} end`,
|
|
340
|
+
}),
|
|
341
|
+
],
|
|
342
|
+
'deferred',
|
|
343
|
+
)
|
|
344
|
+
const s = r.toPromptSection()
|
|
345
|
+
expect(s).toContain('- two_sentences: Reads the document.')
|
|
346
|
+
expect(s).not.toContain('Second sentence')
|
|
347
|
+
const longLine = s.split('\n').find((line) => line.startsWith('- long_sentence:'))
|
|
348
|
+
expect(longLine).toBeDefined()
|
|
349
|
+
const hint = (longLine ?? '').replace('- long_sentence: ', '')
|
|
350
|
+
expect(hint.length).toBeLessThanOrEqual(100)
|
|
351
|
+
expect(hint.endsWith('…')).toBe(true)
|
|
277
352
|
})
|
|
278
353
|
|
|
279
354
|
it('toPromptSection references search_tools only when it is active', () => {
|