@aexol/spectral 0.9.230 → 0.9.234
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 +2 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +89 -14
- package/dist/backend/generated-images.d.ts +1 -1
- package/dist/backend/generated-images.d.ts.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +12 -1
- package/dist/designer/data/skills/blog-post.d.ts +3 -0
- package/dist/designer/data/skills/blog-post.d.ts.map +1 -0
- package/dist/designer/data/skills/blog-post.js +84 -0
- package/dist/designer/data/skills/blog-post.ts +87 -0
- package/dist/designer/data/skills/critique.d.ts +3 -0
- package/dist/designer/data/skills/critique.d.ts.map +1 -0
- package/dist/designer/data/skills/critique.js +109 -0
- package/dist/designer/data/skills/critique.ts +112 -0
- package/dist/designer/data/skills/dashboard.d.ts +3 -0
- package/dist/designer/data/skills/dashboard.d.ts.map +1 -0
- package/dist/designer/data/skills/dashboard.js +165 -0
- package/dist/designer/data/skills/dashboard.ts +168 -0
- package/dist/designer/data/skills/design-brief.d.ts +3 -0
- package/dist/designer/data/skills/design-brief.d.ts.map +1 -0
- package/dist/designer/data/skills/design-brief.js +141 -0
- package/dist/designer/data/skills/design-brief.ts +144 -0
- package/dist/designer/data/skills/design-skill.d.ts +10 -0
- package/dist/designer/data/skills/design-skill.d.ts.map +1 -0
- package/dist/designer/data/skills/design-skill.js +1 -0
- package/dist/designer/data/skills/design-skill.ts +9 -0
- package/dist/designer/data/skills/docs-page.d.ts +3 -0
- package/dist/designer/data/skills/docs-page.d.ts.map +1 -0
- package/dist/designer/data/skills/docs-page.js +68 -0
- package/dist/designer/data/skills/docs-page.ts +71 -0
- package/dist/designer/data/skills/index.d.ts +3 -0
- package/dist/designer/data/skills/index.d.ts.map +1 -0
- package/dist/designer/data/skills/index.js +28 -0
- package/dist/designer/data/skills/index.ts +30 -0
- package/dist/designer/data/skills/magazine-poster.d.ts +3 -0
- package/dist/designer/data/skills/magazine-poster.d.ts.map +1 -0
- package/dist/designer/data/skills/magazine-poster.js +70 -0
- package/dist/designer/data/skills/magazine-poster.ts +73 -0
- package/dist/designer/data/skills/mobile-app.d.ts +3 -0
- package/dist/designer/data/skills/mobile-app.d.ts.map +1 -0
- package/dist/designer/data/skills/mobile-app.js +229 -0
- package/dist/designer/data/skills/mobile-app.ts +232 -0
- package/dist/designer/data/skills/motion-frames.d.ts +3 -0
- package/dist/designer/data/skills/motion-frames.d.ts.map +1 -0
- package/dist/designer/data/skills/motion-frames.js +121 -0
- package/dist/designer/data/skills/motion-frames.ts +124 -0
- package/dist/designer/data/skills/pricing-page.d.ts +3 -0
- package/dist/designer/data/skills/pricing-page.d.ts.map +1 -0
- package/dist/designer/data/skills/pricing-page.js +76 -0
- package/dist/designer/data/skills/pricing-page.ts +79 -0
- package/dist/designer/data/skills/saas-landing.d.ts +3 -0
- package/dist/designer/data/skills/saas-landing.d.ts.map +1 -0
- package/dist/designer/data/skills/saas-landing.js +71 -0
- package/dist/designer/data/skills/saas-landing.ts +74 -0
- package/dist/designer/data/skills/slide-deck.d.ts +3 -0
- package/dist/designer/data/skills/slide-deck.d.ts.map +1 -0
- package/dist/designer/data/skills/slide-deck.js +213 -0
- package/dist/designer/data/skills/slide-deck.ts +216 -0
- package/dist/designer/data/skills/social-carousel.d.ts +3 -0
- package/dist/designer/data/skills/social-carousel.d.ts.map +1 -0
- package/dist/designer/data/skills/social-carousel.js +135 -0
- package/dist/designer/data/skills/social-carousel.ts +138 -0
- package/dist/designer/data/skills/web-prototype.d.ts +3 -0
- package/dist/designer/data/skills/web-prototype.d.ts.map +1 -0
- package/dist/designer/data/skills/web-prototype.js +159 -0
- package/dist/designer/data/skills/web-prototype.ts +162 -0
- package/dist/designer/skills.d.ts +4 -10
- package/dist/designer/skills.d.ts.map +1 -1
- package/dist/designer/skills.js +2 -1643
- package/dist/extensions/logic-trace.d.ts +1 -1
- package/dist/extensions/logic-trace.d.ts.map +1 -1
- package/dist/extensions/logic-trace.js +199 -70
- package/dist/extensions/video-generation/index.d.ts +3 -0
- package/dist/extensions/video-generation/index.d.ts.map +1 -0
- package/dist/extensions/video-generation/index.js +299 -0
- package/dist/extensions/wizard/index.js +9 -1
- package/dist/generated/parser/ast/nodes.d.ts +115 -0
- package/dist/generated/parser/ast/nodes.d.ts.map +1 -0
- package/dist/generated/parser/ast/nodes.js +8 -0
- package/dist/generated/parser/lexer/lexer.d.ts +28 -0
- package/dist/generated/parser/lexer/lexer.d.ts.map +1 -0
- package/dist/generated/parser/{lexer.js → lexer/lexer.js} +1 -180
- package/dist/generated/parser/{lexer.d.ts → lexer/tokens.d.ts} +5 -24
- package/dist/generated/parser/lexer/tokens.d.ts.map +1 -0
- package/dist/generated/parser/lexer/tokens.js +187 -0
- package/dist/generated/parser/mod.d.ts +5 -7
- package/dist/generated/parser/mod.d.ts.map +1 -1
- package/dist/generated/parser/mod.js +2 -1
- package/dist/generated/parser/parser/cursor.d.ts +47 -0
- package/dist/generated/parser/parser/cursor.d.ts.map +1 -0
- package/dist/generated/parser/parser/cursor.js +12 -0
- package/dist/generated/parser/parser/definitions.d.ts +16 -0
- package/dist/generated/parser/parser/definitions.d.ts.map +1 -0
- package/dist/generated/parser/parser/definitions.js +353 -0
- package/dist/generated/parser/parser/expressions.d.ts +17 -0
- package/dist/generated/parser/parser/expressions.d.ts.map +1 -0
- package/dist/generated/parser/parser/expressions.js +165 -0
- package/dist/generated/parser/parser.d.ts +18 -133
- package/dist/generated/parser/parser.d.ts.map +1 -1
- package/dist/generated/parser/parser.js +9 -505
- package/dist/generated/parser/tokenizer.d.ts +1 -2
- package/dist/generated/parser/tokenizer.d.ts.map +1 -1
- package/dist/generated/parser/tokenizer.js +2 -1
- package/dist/generated/parser/validator.d.ts +1 -1
- package/dist/generated/parser/validator.d.ts.map +1 -1
- package/dist/generated/zeus/const.d.ts.map +1 -1
- package/dist/generated/zeus/const.js +30 -0
- package/dist/generated/zeus/index.d.ts +140 -0
- package/dist/generated/zeus/index.d.ts.map +1 -1
- package/dist/generated/zeus/index.js +5 -0
- package/dist/mcp/glimpse-ui.js +9 -1
- package/dist/relay/dispatcher.d.ts +23 -104
- package/dist/relay/dispatcher.d.ts.map +1 -1
- package/dist/relay/dispatcher.js +21 -1130
- package/dist/relay/rest.d.ts +31 -0
- package/dist/relay/rest.d.ts.map +1 -0
- package/dist/relay/rest.js +85 -0
- package/dist/relay/routing.d.ts +109 -0
- package/dist/relay/routing.d.ts.map +1 -0
- package/dist/relay/routing.js +669 -0
- package/dist/relay/wizard-login.d.ts +17 -0
- package/dist/relay/wizard-login.d.ts.map +1 -0
- package/dist/relay/wizard-login.js +419 -0
- package/dist/sdk/agent-core/agent-loop.d.ts +2 -9
- package/dist/sdk/agent-core/agent-loop.d.ts.map +1 -1
- package/dist/sdk/agent-core/agent-loop.js +17 -291
- package/dist/sdk/agent-core/agent.d.ts +11 -4
- package/dist/sdk/agent-core/agent.d.ts.map +1 -1
- package/dist/sdk/agent-core/agent.js +16 -4
- package/dist/sdk/agent-core/tool-call-registry.d.ts +75 -0
- package/dist/sdk/agent-core/tool-call-registry.d.ts.map +1 -0
- package/dist/sdk/agent-core/tool-call-registry.js +131 -0
- package/dist/sdk/agent-core/tool-execution.d.ts +33 -0
- package/dist/sdk/agent-core/tool-execution.d.ts.map +1 -0
- package/dist/sdk/agent-core/tool-execution.js +399 -0
- package/dist/sdk/agent-core/types.d.ts +15 -4
- package/dist/sdk/agent-core/types.d.ts.map +1 -1
- package/dist/sdk/ai/env-api-keys.js +9 -1
- package/dist/sdk/ai/index.d.ts +3 -0
- package/dist/sdk/ai/index.d.ts.map +1 -1
- package/dist/sdk/ai/index.js +3 -0
- package/dist/sdk/ai/providers/faux.d.ts.map +1 -1
- package/dist/sdk/ai/providers/faux.js +3 -0
- package/dist/sdk/ai/providers/leaked-tool-call-parser.d.ts +39 -6
- package/dist/sdk/ai/providers/leaked-tool-call-parser.d.ts.map +1 -1
- package/dist/sdk/ai/providers/leaked-tool-call-parser.js +159 -18
- package/dist/sdk/ai/providers/openai/reasoning-replay.d.ts +48 -0
- package/dist/sdk/ai/providers/openai/reasoning-replay.d.ts.map +1 -0
- package/dist/sdk/ai/providers/openai/reasoning-replay.js +209 -0
- package/dist/sdk/ai/providers/openai-completions.d.ts.map +1 -1
- package/dist/sdk/ai/providers/openai-completions.js +23 -211
- package/dist/sdk/ai/providers/openrouter-videos.d.ts +3 -0
- package/dist/sdk/ai/providers/openrouter-videos.d.ts.map +1 -0
- package/dist/sdk/ai/providers/openrouter-videos.js +412 -0
- package/dist/sdk/ai/providers/register-builtins.d.ts.map +1 -1
- package/dist/sdk/ai/providers/register-builtins.js +6 -0
- package/dist/sdk/ai/providers/simple-options.d.ts +1 -6
- package/dist/sdk/ai/providers/simple-options.d.ts.map +1 -1
- package/dist/sdk/ai/providers/simple-options.js +0 -22
- package/dist/sdk/ai/providers/transform-messages.d.ts.map +1 -1
- package/dist/sdk/ai/providers/transform-messages.js +52 -1
- package/dist/sdk/ai/types.d.ts +91 -10
- package/dist/sdk/ai/types.d.ts.map +1 -1
- package/dist/sdk/ai/video-models.d.ts +10 -0
- package/dist/sdk/ai/video-models.d.ts.map +1 -0
- package/dist/sdk/ai/video-models.generated.d.ts +440 -0
- package/dist/sdk/ai/video-models.generated.d.ts.map +1 -0
- package/dist/sdk/ai/video-models.generated.js +441 -0
- package/dist/sdk/ai/video-models.js +22 -0
- package/dist/sdk/ai/videos-api-registry.d.ts +14 -0
- package/dist/sdk/ai/videos-api-registry.d.ts.map +1 -0
- package/dist/sdk/ai/videos-api-registry.js +21 -0
- package/dist/sdk/ai/videos.d.ts +4 -0
- package/dist/sdk/ai/videos.d.ts.map +1 -0
- package/dist/sdk/ai/videos.js +13 -0
- package/dist/sdk/coding-agent/core/agent-session.d.ts +8 -0
- package/dist/sdk/coding-agent/core/agent-session.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/agent-session.js +11 -0
- package/dist/sdk/coding-agent/core/compaction/compaction.d.ts +6 -118
- package/dist/sdk/coding-agent/core/compaction/compaction.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/compaction/compaction.js +11 -733
- package/dist/sdk/coding-agent/core/compaction/cut-points.d.ts +58 -0
- package/dist/sdk/coding-agent/core/compaction/cut-points.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/compaction/cut-points.js +191 -0
- package/dist/sdk/coding-agent/core/compaction/dedupe.d.ts +28 -0
- package/dist/sdk/coding-agent/core/compaction/dedupe.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/compaction/dedupe.js +156 -0
- package/dist/sdk/coding-agent/core/compaction/summarize.d.ts +21 -0
- package/dist/sdk/coding-agent/core/compaction/summarize.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/compaction/summarize.js +181 -0
- package/dist/sdk/coding-agent/core/compaction/tokens.d.ts +47 -0
- package/dist/sdk/coding-agent/core/compaction/tokens.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/compaction/tokens.js +224 -0
- package/dist/sdk/coding-agent/core/extensions/loader.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/extensions/loader.js +14 -0
- package/dist/sdk/coding-agent/core/extensions/native-extensions.d.ts +26 -0
- package/dist/sdk/coding-agent/core/extensions/native-extensions.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/extensions/native-extensions.js +23 -0
- package/dist/sdk/coding-agent/core/extensions/session-events.d.ts +157 -0
- package/dist/sdk/coding-agent/core/extensions/session-events.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/extensions/session-events.js +13 -0
- package/dist/sdk/coding-agent/core/extensions/types.d.ts +10 -367
- package/dist/sdk/coding-agent/core/extensions/types.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/extensions/types.js +2 -10
- package/dist/sdk/coding-agent/core/extensions/ui-types.d.ts +219 -0
- package/dist/sdk/coding-agent/core/extensions/ui-types.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/extensions/ui-types.js +4 -0
- package/dist/sdk/coding-agent/core/messages.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/messages.js +42 -2
- package/dist/sdk/coding-agent/core/package/default-package-manager.d.ts +115 -0
- package/dist/sdk/coding-agent/core/package/default-package-manager.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/package/default-package-manager.js +1184 -0
- package/dist/sdk/coding-agent/core/package/discovery.d.ts +20 -0
- package/dist/sdk/coding-agent/core/package/discovery.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/package/discovery.js +283 -0
- package/dist/sdk/coding-agent/core/package/ignore.d.ts +29 -0
- package/dist/sdk/coding-agent/core/package/ignore.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/package/ignore.js +235 -0
- package/dist/sdk/coding-agent/core/package/types.d.ts +128 -0
- package/dist/sdk/coding-agent/core/package/types.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/package/types.js +18 -0
- package/dist/sdk/coding-agent/core/package/update-check.d.ts +43 -0
- package/dist/sdk/coding-agent/core/package/update-check.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/package/update-check.js +253 -0
- package/dist/sdk/coding-agent/core/package-manager.d.ts +2 -188
- package/dist/sdk/coding-agent/core/package-manager.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/package-manager.js +1 -1940
- package/dist/sdk/coding-agent/core/resource-loader.d.ts +11 -0
- package/dist/sdk/coding-agent/core/resource-loader.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/resource-loader.js +23 -6
- package/dist/sdk/coding-agent/core/sdk.d.ts +24 -2
- package/dist/sdk/coding-agent/core/sdk.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/sdk.js +15 -3
- package/dist/sdk/coding-agent/core/session/migrate.d.ts +18 -0
- package/dist/sdk/coding-agent/core/session/migrate.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/session/migrate.js +78 -0
- package/dist/sdk/coding-agent/core/session/types.d.ts +165 -0
- package/dist/sdk/coding-agent/core/session/types.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/session/types.js +4 -0
- package/dist/sdk/coding-agent/core/session-manager.d.ts +3 -161
- package/dist/sdk/coding-agent/core/session-manager.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/session-manager.js +4 -72
- package/dist/sdk/coding-agent/core/settings-manager.d.ts +0 -8
- package/dist/sdk/coding-agent/core/settings-manager.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/settings-manager.js +3 -3
- package/dist/sdk/coding-agent/index.d.ts +2 -2
- package/dist/sdk/coding-agent/index.d.ts.map +1 -1
- package/dist/sdk/coding-agent/index.js +1 -1
- package/dist/sdk-public.d.ts +96 -0
- package/dist/sdk-public.d.ts.map +1 -0
- package/dist/sdk-public.js +109 -0
- package/dist/server/agent-bridge/rehydrate.d.ts +2 -2
- package/dist/server/agent-bridge/rehydrate.d.ts.map +1 -1
- package/dist/server/agent-bridge/rehydrate.js +14 -0
- package/dist/server/agent-bridge.d.ts +8 -2
- package/dist/server/agent-bridge.d.ts.map +1 -1
- package/dist/server/agent-bridge.js +25 -2
- package/dist/server/session-stream.d.ts +19 -0
- package/dist/server/session-stream.d.ts.map +1 -1
- package/dist/server/session-stream.js +35 -0
- package/dist/server/wire.d.ts +13 -0
- package/dist/server/wire.d.ts.map +1 -1
- package/package.json +8 -2
- package/dist/generated/parser/lexer.d.ts.map +0 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Killable registry of in-flight tool executions for one agent run.
|
|
3
|
+
*
|
|
4
|
+
* The agent loop hands every `tool.execute()` a run-level abort signal, which
|
|
5
|
+
* makes whole-turn cancellation the only kill path. This registry adds a
|
|
6
|
+
* per-call controller chained from the run signal so a single hung/long-running
|
|
7
|
+
* tool call can be aborted on its own (`stopToolCall`) while its siblings keep
|
|
8
|
+
* running and the agent loop continues the turn.
|
|
9
|
+
*
|
|
10
|
+
* Lifecycle:
|
|
11
|
+
* - `register()` is called by the tool executor right before execution and
|
|
12
|
+
* returns a handle carrying the per-call abort signal.
|
|
13
|
+
* - `settle()` is called by the executor when the call finishes (success or
|
|
14
|
+
* error) — it removes the entry and resolves the handle's `settled` promise,
|
|
15
|
+
* which is what `stop()` awaits.
|
|
16
|
+
* - `stop()` marks a user-initiated stop (so the caught abort error is
|
|
17
|
+
* replaced by the synthesized user-stop tool result), aborts only the
|
|
18
|
+
* targeted call's controller, and resolves once the call settles.
|
|
19
|
+
*
|
|
20
|
+
* Chaining: when the run-level signal aborts (turn cancel), every per-call
|
|
21
|
+
* controller aborts too, so existing whole-turn cancel behavior is preserved.
|
|
22
|
+
*/
|
|
23
|
+
/** Default reason recorded on the handle when the caller passes none. */
|
|
24
|
+
export const DEFAULT_USER_STOP_REASON = "stopped by user";
|
|
25
|
+
/**
|
|
26
|
+
* Exactly-matching synthesized toolResult content per the `stop_tool_call`
|
|
27
|
+
* wire contract. The wire tool_result frame carries `stoppedByUser: true`.
|
|
28
|
+
*/
|
|
29
|
+
export const USER_STOP_TOOL_RESULT_TEXT = "Tool call stopped by user (was running too long)";
|
|
30
|
+
/**
|
|
31
|
+
* Per-run killable registry of in-flight tool executions.
|
|
32
|
+
* Keyed by toolCallId; one Agent owns one registry per run.
|
|
33
|
+
*/
|
|
34
|
+
export class ToolCallRegistry {
|
|
35
|
+
calls = new Map();
|
|
36
|
+
/**
|
|
37
|
+
* Register an in-flight call and return its handle. The returned
|
|
38
|
+
* controller's signal aborts when this call is stopped individually OR
|
|
39
|
+
* when the run-level signal aborts (turn cancel propagates).
|
|
40
|
+
*/
|
|
41
|
+
register(toolCallId, toolName, runSignal) {
|
|
42
|
+
const existing = this.calls.get(toolCallId);
|
|
43
|
+
if (existing)
|
|
44
|
+
return existing;
|
|
45
|
+
const controller = new AbortController();
|
|
46
|
+
let settle = () => { };
|
|
47
|
+
const settled = new Promise((resolve) => {
|
|
48
|
+
settle = resolve;
|
|
49
|
+
});
|
|
50
|
+
const handle = {
|
|
51
|
+
toolCallId,
|
|
52
|
+
toolName,
|
|
53
|
+
controller,
|
|
54
|
+
settled,
|
|
55
|
+
userStopRequested: false,
|
|
56
|
+
settle: () => {
|
|
57
|
+
this.calls.delete(toolCallId);
|
|
58
|
+
settle();
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
if (runSignal) {
|
|
62
|
+
if (runSignal.aborted) {
|
|
63
|
+
try {
|
|
64
|
+
controller.abort();
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// ignore — abort must never throw into the executor
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const onRunAbort = () => {
|
|
72
|
+
try {
|
|
73
|
+
controller.abort();
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// ignore
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
runSignal.addEventListener("abort", onRunAbort, { once: true });
|
|
80
|
+
void settled.then(() => runSignal.removeEventListener("abort", onRunAbort));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
this.calls.set(toolCallId, handle);
|
|
84
|
+
return handle;
|
|
85
|
+
}
|
|
86
|
+
/** Look up an in-flight call by id. Undefined for unknown/finished ids. */
|
|
87
|
+
get(toolCallId) {
|
|
88
|
+
return this.calls.get(toolCallId);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Mark a user-initiated stop and abort only this call's controller.
|
|
92
|
+
* Returns false for unknown/finished ids (no-op). Idempotent: a second
|
|
93
|
+
* stop for the same id keeps the first marker and reason.
|
|
94
|
+
*/
|
|
95
|
+
markUserStop(toolCallId, reason) {
|
|
96
|
+
const handle = this.calls.get(toolCallId);
|
|
97
|
+
if (!handle)
|
|
98
|
+
return false;
|
|
99
|
+
if (!handle.userStopRequested) {
|
|
100
|
+
handle.userStopRequested = true;
|
|
101
|
+
handle.userStopReason = reason ?? DEFAULT_USER_STOP_REASON;
|
|
102
|
+
try {
|
|
103
|
+
handle.controller.abort();
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// ignore — abort must never throw into the caller
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Abort only the targeted call and resolve once it settles.
|
|
113
|
+
* Returns false for unknown/finished ids (no-op).
|
|
114
|
+
*/
|
|
115
|
+
async stop(toolCallId, reason) {
|
|
116
|
+
if (!this.markUserStop(toolCallId, reason))
|
|
117
|
+
return false;
|
|
118
|
+
await this.calls.get(toolCallId)?.settled;
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
/** Settle an in-flight call. Called by the executor when execution ends. */
|
|
122
|
+
settle(toolCallId) {
|
|
123
|
+
this.calls.get(toolCallId)?.settle();
|
|
124
|
+
}
|
|
125
|
+
/** Settle and drop every tracked call. Called when a run starts/ends. */
|
|
126
|
+
clear() {
|
|
127
|
+
for (const handle of this.calls.values())
|
|
128
|
+
handle.settle();
|
|
129
|
+
this.calls.clear();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool call execution for the agent loop.
|
|
3
|
+
*
|
|
4
|
+
* `executeToolCalls` runs every tool call of an assistant message —
|
|
5
|
+
* sequentially (`toolExecution: "sequential"` or any tool declaring
|
|
6
|
+
* `executionMode: "sequential"`) or in parallel — and returns the
|
|
7
|
+
* `ToolResultMessage`s plus a `terminate` flag for the loop.
|
|
8
|
+
*
|
|
9
|
+
* Extracted from `sdk/agent-core/agent-loop.ts` — the loop module
|
|
10
|
+
* re-exports `hasMissingRequiredArguments` so existing imports keep
|
|
11
|
+
* working.
|
|
12
|
+
*/
|
|
13
|
+
import { type AssistantMessage, type ToolResultMessage } from "../ai/index.js";
|
|
14
|
+
import type { AgentContext, AgentLoopConfig, AgentTool, AgentToolCall } from "./types.js";
|
|
15
|
+
import type { AgentEventSink } from "./agent-loop.js";
|
|
16
|
+
/**
|
|
17
|
+
* Execute tool calls from an assistant message.
|
|
18
|
+
*/
|
|
19
|
+
export declare function executeToolCalls(currentContext: AgentContext, assistantMessage: AssistantMessage, config: AgentLoopConfig, signal: AbortSignal | undefined, emit: AgentEventSink): Promise<ExecutedToolCallBatch>;
|
|
20
|
+
type ExecutedToolCallBatch = {
|
|
21
|
+
messages: ToolResultMessage[];
|
|
22
|
+
terminate: boolean;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Detects whether a tool call is missing any required parameter, indicating the
|
|
26
|
+
* provider truncated the response before the tool arguments were fully emitted.
|
|
27
|
+
* Used together with `stopReason === "length"` to short-circuit tool validation
|
|
28
|
+
* when a streamed tool call is incomplete (which would otherwise throw
|
|
29
|
+
* `Validation failed ... You provided: {}`).
|
|
30
|
+
*/
|
|
31
|
+
export declare function hasMissingRequiredArguments(tool: AgentTool<any>, toolCall: AgentToolCall): boolean;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=tool-execution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../src/sdk/agent-core/tool-execution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EAEvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EACX,YAAY,EACZ,eAAe,EACf,SAAS,EACT,aAAa,EAEb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAOtD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,cAAc,EAAE,YAAY,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,qBAAqB,CAAC,CA2BhC;AAED,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AA0fF;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAYlG"}
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool call execution for the agent loop.
|
|
3
|
+
*
|
|
4
|
+
* `executeToolCalls` runs every tool call of an assistant message —
|
|
5
|
+
* sequentially (`toolExecution: "sequential"` or any tool declaring
|
|
6
|
+
* `executionMode: "sequential"`) or in parallel — and returns the
|
|
7
|
+
* `ToolResultMessage`s plus a `terminate` flag for the loop.
|
|
8
|
+
*
|
|
9
|
+
* Extracted from `sdk/agent-core/agent-loop.ts` — the loop module
|
|
10
|
+
* re-exports `hasMissingRequiredArguments` so existing imports keep
|
|
11
|
+
* working.
|
|
12
|
+
*/
|
|
13
|
+
import { validateToolArguments, } from "../ai/index.js";
|
|
14
|
+
import { USER_STOP_TOOL_RESULT_TEXT, } from "./tool-call-registry.js";
|
|
15
|
+
/**
|
|
16
|
+
* Execute tool calls from an assistant message.
|
|
17
|
+
*/
|
|
18
|
+
export async function executeToolCalls(currentContext, assistantMessage, config, signal, emit) {
|
|
19
|
+
const toolCalls = assistantMessage.content.filter((c) => c.type === "toolCall");
|
|
20
|
+
const hasSequentialToolCall = toolCalls.some((tc) => currentContext.tools?.find((t) => t.name === tc.name)?.executionMode ===
|
|
21
|
+
"sequential");
|
|
22
|
+
if (config.toolExecution === "sequential" || hasSequentialToolCall) {
|
|
23
|
+
return executeToolCallsSequential(currentContext, assistantMessage, toolCalls, config, signal, emit);
|
|
24
|
+
}
|
|
25
|
+
return executeToolCallsParallel(currentContext, assistantMessage, toolCalls, config, signal, emit);
|
|
26
|
+
}
|
|
27
|
+
async function executeToolCallsSequential(currentContext, assistantMessage, toolCalls, config, signal, emit) {
|
|
28
|
+
const finalizedCalls = [];
|
|
29
|
+
const messages = [];
|
|
30
|
+
const startedToolCallIds = new Set();
|
|
31
|
+
for (const toolCall of toolCalls) {
|
|
32
|
+
await emit({
|
|
33
|
+
type: "tool_execution_start",
|
|
34
|
+
toolCallId: toolCall.id,
|
|
35
|
+
toolName: toolCall.name,
|
|
36
|
+
args: toolCall.arguments,
|
|
37
|
+
});
|
|
38
|
+
startedToolCallIds.add(toolCall.id);
|
|
39
|
+
const preparation = await prepareToolCall(currentContext, assistantMessage, toolCall, config, signal);
|
|
40
|
+
let finalized;
|
|
41
|
+
if (preparation.kind === "immediate") {
|
|
42
|
+
finalized = {
|
|
43
|
+
toolCall,
|
|
44
|
+
result: preparation.result,
|
|
45
|
+
isError: preparation.isError,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const executed = await executePreparedToolCall(preparation, signal, emit, config.toolCallRegistry);
|
|
50
|
+
finalized = await finalizeExecutedToolCall(currentContext, assistantMessage, preparation, executed, config, signal);
|
|
51
|
+
}
|
|
52
|
+
await emitToolExecutionEnd(finalized, emit);
|
|
53
|
+
const toolResultMessage = createToolResultMessage(finalized);
|
|
54
|
+
await emitToolResultMessage(toolResultMessage, emit);
|
|
55
|
+
finalizedCalls.push(finalized);
|
|
56
|
+
messages.push(toolResultMessage);
|
|
57
|
+
if (signal?.aborted) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Protocol repair: on a turn abort, tool calls skipped by the loop above
|
|
62
|
+
// never executed and would otherwise remain orphaned tool_calls (no
|
|
63
|
+
// matching tool_result in the transcript). Synthesize an error tool result
|
|
64
|
+
// for each so the next LLM request stays well-formed.
|
|
65
|
+
const synthesized = await synthesizeAbortedToolResults(toolCalls, finalizedCalls, startedToolCallIds, signal, emit);
|
|
66
|
+
for (const finalized of synthesized) {
|
|
67
|
+
const toolResultMessage = createToolResultMessage(finalized);
|
|
68
|
+
await emitToolResultMessage(toolResultMessage, emit);
|
|
69
|
+
finalizedCalls.push(finalized);
|
|
70
|
+
messages.push(toolResultMessage);
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
messages,
|
|
74
|
+
terminate: shouldTerminateToolBatch(finalizedCalls),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function executeToolCallsParallel(currentContext, assistantMessage, toolCalls, config, signal, emit) {
|
|
78
|
+
const finalizedCalls = [];
|
|
79
|
+
const startedToolCallIds = new Set();
|
|
80
|
+
for (const toolCall of toolCalls) {
|
|
81
|
+
await emit({
|
|
82
|
+
type: "tool_execution_start",
|
|
83
|
+
toolCallId: toolCall.id,
|
|
84
|
+
toolName: toolCall.name,
|
|
85
|
+
args: toolCall.arguments,
|
|
86
|
+
});
|
|
87
|
+
startedToolCallIds.add(toolCall.id);
|
|
88
|
+
const preparation = await prepareToolCall(currentContext, assistantMessage, toolCall, config, signal);
|
|
89
|
+
if (preparation.kind === "immediate") {
|
|
90
|
+
const finalized = {
|
|
91
|
+
toolCall,
|
|
92
|
+
result: preparation.result,
|
|
93
|
+
isError: preparation.isError,
|
|
94
|
+
};
|
|
95
|
+
await emitToolExecutionEnd(finalized, emit);
|
|
96
|
+
finalizedCalls.push(finalized);
|
|
97
|
+
if (signal?.aborted) {
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
finalizedCalls.push(async () => {
|
|
103
|
+
const executed = await executePreparedToolCall(preparation, signal, emit, config.toolCallRegistry);
|
|
104
|
+
const finalized = await finalizeExecutedToolCall(currentContext, assistantMessage, preparation, executed, config, signal);
|
|
105
|
+
await emitToolExecutionEnd(finalized, emit);
|
|
106
|
+
return finalized;
|
|
107
|
+
});
|
|
108
|
+
if (signal?.aborted) {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const orderedFinalizedCalls = await Promise.all(finalizedCalls.map((entry) => typeof entry === "function" ? entry() : Promise.resolve(entry)));
|
|
113
|
+
const messages = [];
|
|
114
|
+
for (const finalized of orderedFinalizedCalls) {
|
|
115
|
+
const toolResultMessage = createToolResultMessage(finalized);
|
|
116
|
+
await emitToolResultMessage(toolResultMessage, emit);
|
|
117
|
+
messages.push(toolResultMessage);
|
|
118
|
+
}
|
|
119
|
+
// Protocol repair (same as the sequential path): on a turn abort, tool
|
|
120
|
+
// calls the preflight loop never pushed would remain orphaned tool_calls.
|
|
121
|
+
const synthesized = await synthesizeAbortedToolResults(toolCalls, orderedFinalizedCalls, startedToolCallIds, signal, emit);
|
|
122
|
+
for (const finalized of synthesized) {
|
|
123
|
+
const toolResultMessage = createToolResultMessage(finalized);
|
|
124
|
+
await emitToolResultMessage(toolResultMessage, emit);
|
|
125
|
+
messages.push(toolResultMessage);
|
|
126
|
+
}
|
|
127
|
+
if (synthesized.length > 0) {
|
|
128
|
+
orderedFinalizedCalls.push(...synthesized);
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
messages,
|
|
132
|
+
terminate: shouldTerminateToolBatch(orderedFinalizedCalls),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function shouldTerminateToolBatch(finalizedCalls) {
|
|
136
|
+
return (finalizedCalls.length > 0 &&
|
|
137
|
+
finalizedCalls.every((finalized) => finalized.result.terminate === true));
|
|
138
|
+
}
|
|
139
|
+
function prepareToolCallArguments(tool, toolCall) {
|
|
140
|
+
if (!tool.prepareArguments) {
|
|
141
|
+
return toolCall;
|
|
142
|
+
}
|
|
143
|
+
const preparedArguments = tool.prepareArguments(toolCall.arguments);
|
|
144
|
+
if (preparedArguments === toolCall.arguments) {
|
|
145
|
+
return toolCall;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
...toolCall,
|
|
149
|
+
arguments: preparedArguments,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
async function prepareToolCall(currentContext, assistantMessage, toolCall, config, signal) {
|
|
153
|
+
const tool = currentContext.tools?.find((t) => t.name === toolCall.name);
|
|
154
|
+
if (!tool) {
|
|
155
|
+
return {
|
|
156
|
+
kind: "immediate",
|
|
157
|
+
result: createErrorToolResult(`Tool ${toolCall.name} not found`),
|
|
158
|
+
isError: true,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
// If the provider truncated the response mid tool-call (stopReason "length"),
|
|
162
|
+
// the streaming JSON parser may have produced an empty or incomplete arguments
|
|
163
|
+
// object. Validating it would surface a raw `Validation failed ... You provided:
|
|
164
|
+
// {}` error to the model. Instead, return a soft error so the agent-session
|
|
165
|
+
// length-continuation path (which treats truncated tool calls as visible output)
|
|
166
|
+
// can resubmit and let the model re-emit the full tool call.
|
|
167
|
+
if (assistantMessage.stopReason === "length" && hasMissingRequiredArguments(tool, toolCall)) {
|
|
168
|
+
return {
|
|
169
|
+
kind: "immediate",
|
|
170
|
+
result: createErrorToolResult(`Tool "${toolCall.name}" was truncated before its arguments were fully emitted. ` +
|
|
171
|
+
`Retrying: please re-emit the complete tool call with all required parameters.`),
|
|
172
|
+
isError: true,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const preparedToolCall = prepareToolCallArguments(tool, toolCall);
|
|
177
|
+
const validatedArgs = validateToolArguments(tool, preparedToolCall);
|
|
178
|
+
if (config.beforeToolCall) {
|
|
179
|
+
const beforeResult = await config.beforeToolCall({
|
|
180
|
+
assistantMessage,
|
|
181
|
+
toolCall,
|
|
182
|
+
args: validatedArgs,
|
|
183
|
+
context: currentContext,
|
|
184
|
+
}, signal);
|
|
185
|
+
if (signal?.aborted) {
|
|
186
|
+
return {
|
|
187
|
+
kind: "immediate",
|
|
188
|
+
result: createErrorToolResult("Operation aborted"),
|
|
189
|
+
isError: true,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (beforeResult?.block) {
|
|
193
|
+
return {
|
|
194
|
+
kind: "immediate",
|
|
195
|
+
result: createErrorToolResult(beforeResult.reason || "Tool execution was blocked"),
|
|
196
|
+
isError: true,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (signal?.aborted) {
|
|
201
|
+
return {
|
|
202
|
+
kind: "immediate",
|
|
203
|
+
result: createErrorToolResult("Operation aborted"),
|
|
204
|
+
isError: true,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
kind: "prepared",
|
|
209
|
+
toolCall,
|
|
210
|
+
tool,
|
|
211
|
+
args: validatedArgs,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
return {
|
|
216
|
+
kind: "immediate",
|
|
217
|
+
result: createErrorToolResult(error instanceof Error ? error.message : String(error)),
|
|
218
|
+
isError: true,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async function executePreparedToolCall(prepared, signal, emit, registry) {
|
|
223
|
+
const updateEvents = [];
|
|
224
|
+
// Per-call kill handle: registers this execution so a user-initiated
|
|
225
|
+
// `stopToolCall` can abort ONLY this call. The returned controller's signal
|
|
226
|
+
// also aborts when the run-level signal aborts (turn cancel propagates).
|
|
227
|
+
// When no registry is configured, tools receive the run signal directly
|
|
228
|
+
// (existing behavior).
|
|
229
|
+
const handle = registry?.register(prepared.toolCall.id, prepared.toolCall.name, signal);
|
|
230
|
+
const callSignal = handle ? handle.controller.signal : signal;
|
|
231
|
+
try {
|
|
232
|
+
const result = await prepared.tool.execute(prepared.toolCall.id, prepared.args, callSignal, (partialResult) => {
|
|
233
|
+
updateEvents.push(Promise.resolve(emit({
|
|
234
|
+
type: "tool_execution_update",
|
|
235
|
+
toolCallId: prepared.toolCall.id,
|
|
236
|
+
toolName: prepared.toolCall.name,
|
|
237
|
+
args: prepared.toolCall.arguments,
|
|
238
|
+
partialResult,
|
|
239
|
+
})));
|
|
240
|
+
});
|
|
241
|
+
await Promise.all(updateEvents);
|
|
242
|
+
return { result, isError: false };
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
await Promise.all(updateEvents);
|
|
246
|
+
// User-initiated per-call stop: replace the raw "aborted"/transport error
|
|
247
|
+
// text with the exactly-matching synthesized user-stop result so the agent
|
|
248
|
+
// loop CONTINUES the turn with a well-formed tool result.
|
|
249
|
+
if (handle?.userStopRequested) {
|
|
250
|
+
return {
|
|
251
|
+
result: createUserStopToolResult(handle.userStopReason),
|
|
252
|
+
isError: true,
|
|
253
|
+
stoppedByUser: true,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
result: createErrorToolResult(error instanceof Error ? error.message : String(error)),
|
|
258
|
+
isError: true,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
finally {
|
|
262
|
+
registry?.settle(prepared.toolCall.id);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async function finalizeExecutedToolCall(currentContext, assistantMessage, prepared, executed, config, signal) {
|
|
266
|
+
let result = executed.result;
|
|
267
|
+
let isError = executed.isError;
|
|
268
|
+
let stoppedByUser = executed.stoppedByUser;
|
|
269
|
+
if (config.afterToolCall) {
|
|
270
|
+
try {
|
|
271
|
+
const afterResult = await config.afterToolCall({
|
|
272
|
+
assistantMessage,
|
|
273
|
+
toolCall: prepared.toolCall,
|
|
274
|
+
args: prepared.args,
|
|
275
|
+
result,
|
|
276
|
+
isError,
|
|
277
|
+
context: currentContext,
|
|
278
|
+
}, signal);
|
|
279
|
+
if (afterResult) {
|
|
280
|
+
result = {
|
|
281
|
+
content: afterResult.content ?? result.content,
|
|
282
|
+
details: afterResult.details ?? result.details,
|
|
283
|
+
terminate: afterResult.terminate ?? result.terminate,
|
|
284
|
+
};
|
|
285
|
+
isError = afterResult.isError ?? isError;
|
|
286
|
+
// An afterToolCall override replaces the executed result; the
|
|
287
|
+
// user-stop marker only survives when the override is not replacing
|
|
288
|
+
// the error with a different outcome.
|
|
289
|
+
if (afterResult.isError === false) {
|
|
290
|
+
stoppedByUser = undefined;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
result = createErrorToolResult(error instanceof Error ? error.message : String(error));
|
|
296
|
+
isError = true;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
toolCall: prepared.toolCall,
|
|
301
|
+
result,
|
|
302
|
+
isError,
|
|
303
|
+
stoppedByUser,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function createErrorToolResult(message) {
|
|
307
|
+
return {
|
|
308
|
+
content: [{ type: "text", text: message }],
|
|
309
|
+
details: {},
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Synthesized tool result for a user-initiated per-call stop. Content is the
|
|
314
|
+
* exactly-matching contract string; details carry the marker for the wire.
|
|
315
|
+
*/
|
|
316
|
+
function createUserStopToolResult(reason) {
|
|
317
|
+
return {
|
|
318
|
+
content: [{ type: "text", text: USER_STOP_TOOL_RESULT_TEXT }],
|
|
319
|
+
details: { stoppedByUser: true, ...(reason ? { reason } : {}) },
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
/** Synthesized tool result for a tool call the turn abort skipped entirely. */
|
|
323
|
+
function createAbortedBeforeStartToolResult() {
|
|
324
|
+
return createErrorToolResult("Tool call aborted before start");
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Protocol repair: synthesize tool results for tool calls that never produced
|
|
328
|
+
* one because the run-level abort skipped them. Without this, a turn abort
|
|
329
|
+
* leaves orphaned tool_calls in the transcript (assistant toolCall content
|
|
330
|
+
* blocks with no matching tool_result), which breaks the next LLM request.
|
|
331
|
+
* Calls that already emitted `tool_execution_start` also get a matching
|
|
332
|
+
* `tool_execution_end` so the event stream stays paired.
|
|
333
|
+
*/
|
|
334
|
+
async function synthesizeAbortedToolResults(toolCalls, finalizedCalls, startedToolCallIds, signal, emit) {
|
|
335
|
+
if (!signal?.aborted)
|
|
336
|
+
return [];
|
|
337
|
+
const finalizedIds = new Set(finalizedCalls.map((f) => f.toolCall.id));
|
|
338
|
+
const synthesized = [];
|
|
339
|
+
for (const toolCall of toolCalls) {
|
|
340
|
+
if (finalizedIds.has(toolCall.id))
|
|
341
|
+
continue;
|
|
342
|
+
const finalized = {
|
|
343
|
+
toolCall,
|
|
344
|
+
result: createAbortedBeforeStartToolResult(),
|
|
345
|
+
isError: true,
|
|
346
|
+
};
|
|
347
|
+
if (startedToolCallIds.has(toolCall.id)) {
|
|
348
|
+
await emitToolExecutionEnd(finalized, emit);
|
|
349
|
+
}
|
|
350
|
+
synthesized.push(finalized);
|
|
351
|
+
}
|
|
352
|
+
return synthesized;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Detects whether a tool call is missing any required parameter, indicating the
|
|
356
|
+
* provider truncated the response before the tool arguments were fully emitted.
|
|
357
|
+
* Used together with `stopReason === "length"` to short-circuit tool validation
|
|
358
|
+
* when a streamed tool call is incomplete (which would otherwise throw
|
|
359
|
+
* `Validation failed ... You provided: {}`).
|
|
360
|
+
*/
|
|
361
|
+
export function hasMissingRequiredArguments(tool, toolCall) {
|
|
362
|
+
const schema = tool.parameters;
|
|
363
|
+
const required = schema.required;
|
|
364
|
+
if (!Array.isArray(required) || required.length === 0)
|
|
365
|
+
return false;
|
|
366
|
+
const args = toolCall.arguments;
|
|
367
|
+
if (!args || typeof args !== "object")
|
|
368
|
+
return true;
|
|
369
|
+
return required.some((key) => !(key in args) ||
|
|
370
|
+
args[key] === undefined ||
|
|
371
|
+
args[key] === null ||
|
|
372
|
+
(typeof args[key] === "string" && args[key].trim() === ""));
|
|
373
|
+
}
|
|
374
|
+
async function emitToolExecutionEnd(finalized, emit) {
|
|
375
|
+
await emit({
|
|
376
|
+
type: "tool_execution_end",
|
|
377
|
+
toolCallId: finalized.toolCall.id,
|
|
378
|
+
toolName: finalized.toolCall.name,
|
|
379
|
+
result: finalized.result,
|
|
380
|
+
isError: finalized.isError,
|
|
381
|
+
...(finalized.stoppedByUser ? { stoppedByUser: true } : {}),
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
function createToolResultMessage(finalized) {
|
|
385
|
+
return {
|
|
386
|
+
role: "toolResult",
|
|
387
|
+
toolCallId: finalized.toolCall.id,
|
|
388
|
+
toolName: finalized.toolCall.name,
|
|
389
|
+
content: finalized.result.content,
|
|
390
|
+
details: finalized.result.details,
|
|
391
|
+
isError: finalized.isError,
|
|
392
|
+
...(finalized.stoppedByUser ? { stoppedByUser: true } : {}),
|
|
393
|
+
timestamp: Date.now(),
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
async function emitToolResultMessage(toolResultMessage, emit) {
|
|
397
|
+
await emit({ type: "message_start", message: toolResultMessage });
|
|
398
|
+
await emit({ type: "message_end", message: toolResultMessage });
|
|
399
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { AssistantMessage, AssistantMessageEvent, ImageContent, Message, Model, SimpleStreamOptions, streamSimple, TextContent, Tool, ToolResultMessage } from "../ai/index.js";
|
|
1
|
+
import type { AssistantMessage, AssistantMessageEvent, ImageContent, Message, Model, SimpleStreamOptions, streamSimple, TextContent, Tool, ToolResultMessage, VideoContent } from "../ai/index.js";
|
|
2
2
|
import type { Static, TSchema } from "typebox";
|
|
3
|
+
import type { ToolCallRegistry } from "./tool-call-registry.js";
|
|
3
4
|
/**
|
|
4
5
|
* Stream function used by the agent loop.
|
|
5
6
|
*
|
|
@@ -53,7 +54,7 @@ export interface BeforeToolCallResult {
|
|
|
53
54
|
* There is no deep merge for `content` or `details`.
|
|
54
55
|
*/
|
|
55
56
|
export interface AfterToolCallResult {
|
|
56
|
-
content?: (TextContent | ImageContent)[];
|
|
57
|
+
content?: (TextContent | ImageContent | VideoContent)[];
|
|
57
58
|
details?: unknown;
|
|
58
59
|
isError?: boolean;
|
|
59
60
|
/**
|
|
@@ -240,6 +241,15 @@ export interface AgentLoopConfig extends SimpleStreamOptions {
|
|
|
240
241
|
* The hook receives the agent abort signal and is responsible for honoring it.
|
|
241
242
|
*/
|
|
242
243
|
afterToolCall?: (context: AfterToolCallContext, signal?: AbortSignal) => Promise<AfterToolCallResult | undefined>;
|
|
244
|
+
/**
|
|
245
|
+
* Killable registry of in-flight tool executions for this run.
|
|
246
|
+
*
|
|
247
|
+
* Enables user-initiated per-call stops (`Agent.stopToolCall`): the executor
|
|
248
|
+
* registers each tool call here and passes the per-call abort signal to
|
|
249
|
+
* `tool.execute()`. Optional — when omitted, tools receive the run-level
|
|
250
|
+
* signal directly and per-call stops are unsupported.
|
|
251
|
+
*/
|
|
252
|
+
toolCallRegistry?: ToolCallRegistry;
|
|
243
253
|
}
|
|
244
254
|
/**
|
|
245
255
|
* Thinking/reasoning level for models that support it.
|
|
@@ -303,8 +313,8 @@ export interface AgentState {
|
|
|
303
313
|
}
|
|
304
314
|
/** Final or partial result produced by a tool. */
|
|
305
315
|
export interface AgentToolResult<T> {
|
|
306
|
-
/** Text or
|
|
307
|
-
content: (TextContent | ImageContent)[];
|
|
316
|
+
/** Text, image, or video content returned to the model/UI. */
|
|
317
|
+
content: (TextContent | ImageContent | VideoContent)[];
|
|
308
318
|
/** Arbitrary structured details for logs or UI rendering. */
|
|
309
319
|
details: T;
|
|
310
320
|
/**
|
|
@@ -390,5 +400,6 @@ export type AgentEvent = {
|
|
|
390
400
|
toolName: string;
|
|
391
401
|
result: any;
|
|
392
402
|
isError: boolean;
|
|
403
|
+
stoppedByUser?: boolean;
|
|
393
404
|
};
|
|
394
405
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sdk/agent-core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,OAAO,EACP,KAAK,EACL,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,iBAAiB,EACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sdk/agent-core/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
1
9
|
// NEVER convert to top-level imports - breaks browser/Vite builds
|
|
2
10
|
let _existsSync = null;
|
|
3
11
|
let _homedir = null;
|
|
4
12
|
let _join = null;
|
|
5
|
-
const dynamicImport = (specifier) => import(specifier);
|
|
13
|
+
const dynamicImport = (specifier) => import(__rewriteRelativeImportExtension(specifier));
|
|
6
14
|
const NODE_FS_SPECIFIER = "node:" + "fs";
|
|
7
15
|
const NODE_OS_SPECIFIER = "node:" + "os";
|
|
8
16
|
const NODE_PATH_SPECIFIER = "node:" + "path";
|