@botbotgo/agent-harness 0.0.99 → 0.0.100

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.
Files changed (64) hide show
  1. package/README.md +3 -6
  2. package/README.zh.md +2 -2
  3. package/dist/benchmark/upstream-runtime-ab-benchmark.d.ts +1 -1
  4. package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -2
  5. package/dist/contracts/core.d.ts +2 -2
  6. package/dist/contracts/runtime.d.ts +1 -5
  7. package/dist/package-version.d.ts +1 -1
  8. package/dist/package-version.js +1 -1
  9. package/dist/runtime/adapter/deepagent-runnable-config.d.ts +30 -0
  10. package/dist/runtime/adapter/deepagent-runnable-config.js +22 -0
  11. package/dist/runtime/adapter/index.d.ts +0 -2
  12. package/dist/runtime/adapter/index.js +0 -2
  13. package/dist/runtime/adapter/invocation-result.d.ts +13 -0
  14. package/dist/runtime/adapter/invocation-result.js +40 -0
  15. package/dist/runtime/adapter/langchain-runnable-config.d.ts +25 -0
  16. package/dist/runtime/adapter/langchain-runnable-config.js +19 -0
  17. package/dist/runtime/adapter/local-tool-invocation.d.ts +23 -0
  18. package/dist/runtime/adapter/local-tool-invocation.js +64 -0
  19. package/dist/runtime/adapter/runtime-adapter-support.d.ts +18 -0
  20. package/dist/runtime/adapter/runtime-adapter-support.js +54 -0
  21. package/dist/runtime/adapter/stream-event-projection.d.ts +19 -0
  22. package/dist/runtime/adapter/stream-event-projection.js +79 -0
  23. package/dist/runtime/adapter/stream-text-consumption.d.ts +4 -0
  24. package/dist/runtime/adapter/stream-text-consumption.js +18 -0
  25. package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +64 -0
  26. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +144 -0
  27. package/dist/runtime/adapter/tool/tool-replay.d.ts +18 -0
  28. package/dist/runtime/adapter/tool/tool-replay.js +26 -0
  29. package/dist/runtime/agent-runtime-adapter.d.ts +1 -42
  30. package/dist/runtime/agent-runtime-adapter.js +94 -1425
  31. package/dist/runtime/harness/run/helpers.js +2 -8
  32. package/dist/runtime/harness/run/routing.d.ts +1 -3
  33. package/dist/runtime/harness/run/routing.js +2 -25
  34. package/dist/runtime/harness/run/run-lifecycle.d.ts +0 -11
  35. package/dist/runtime/harness/run/run-lifecycle.js +7 -50
  36. package/dist/runtime/harness/runtime-defaults.d.ts +4 -0
  37. package/dist/runtime/harness/runtime-defaults.js +39 -0
  38. package/dist/runtime/harness/system/inventory.js +2 -1
  39. package/dist/runtime/harness/system/skill-requirements.d.ts +1 -0
  40. package/dist/runtime/harness.d.ts +3 -7
  41. package/dist/runtime/harness.js +56 -69
  42. package/dist/runtime/index.d.ts +1 -12
  43. package/dist/runtime/index.js +1 -12
  44. package/dist/runtime/support/compiled-binding.d.ts +0 -2
  45. package/dist/runtime/support/compiled-binding.js +3 -22
  46. package/dist/runtime/support/harness-support.d.ts +0 -11
  47. package/dist/runtime/support/harness-support.js +1 -44
  48. package/dist/runtime/support/index.d.ts +1 -1
  49. package/dist/runtime/support/index.js +1 -1
  50. package/dist/workspace/agent-binding-compiler.js +9 -93
  51. package/dist/workspace/index.d.ts +0 -5
  52. package/dist/workspace/index.js +0 -5
  53. package/dist/workspace/object-loader.js +4 -21
  54. package/dist/workspace/support/agent-capabilities.js +2 -2
  55. package/dist/workspace/support/workspace-ref-utils.d.ts +0 -2
  56. package/dist/workspace/support/workspace-ref-utils.js +0 -17
  57. package/dist/workspace/validate.js +1 -1
  58. package/package.json +1 -1
  59. package/dist/config/workflows/langgraph-workflows.yaml +0 -570
  60. package/dist/config/workflows/runtime-profiles.yaml +0 -94
  61. package/dist/runtime/adapter/langgraph/presets.d.ts +0 -25
  62. package/dist/runtime/adapter/langgraph/presets.js +0 -165
  63. package/dist/runtime/adapter/langgraph/profiles.d.ts +0 -6
  64. package/dist/runtime/adapter/langgraph/profiles.js +0 -206
package/README.md CHANGED
@@ -79,7 +79,7 @@ Boundary documents live in:
79
79
  - `docs/model-layering.md`
80
80
  - `docs/coding-agent-guide.md`
81
81
 
82
- ACP is the intended future client protocol direction when external tools need a standard runtime boundary. The harness should become ACP-capable while keeping runtime lifecycle, persistence, recovery, and governance harness-owned.
82
+ `deepagents-acp` is the required external protocol direction when external tools need a standard runtime boundary. The harness should conform to `deepagents-acp` semantics at that boundary while keeping runtime lifecycle, persistence, recovery, and governance harness-owned.
83
83
 
84
84
  Recommended orchestration shape for long-running flows:
85
85
 
@@ -262,7 +262,7 @@ const result = await run(runtime, {
262
262
  });
263
263
  ```
264
264
 
265
- `agentId: "auto"` evaluates ordered routing rules in `config/runtime/workspace.yaml`, then `routing.defaultAgentId`, and only falls back to model routing when `routing.modelRouting: true`.
265
+ `agentId: "auto"` evaluates ordered routing rules in `config/runtime/workspace.yaml`, then `routing.defaultAgentId`, and otherwise falls back to the default runtime entry host.
266
266
 
267
267
  ### Stream Output And Events
268
268
 
@@ -416,8 +416,6 @@ Important fields:
416
416
  - `concurrency.maxConcurrentRuns`
417
417
  - `routing.defaultAgentId`
418
418
  - `routing.rules`
419
- - `routing.systemPrompt`
420
- - `routing.modelRouting`
421
419
  - `maintenance.checkpoints`
422
420
  - `maintenance.records`
423
421
  - `recovery.enabled`
@@ -444,7 +442,6 @@ spec:
444
442
  maxConcurrentRuns: 3
445
443
  routing:
446
444
  defaultAgentId: orchestra
447
- modelRouting: false
448
445
  maintenance:
449
446
  checkpoints:
450
447
  enabled: true
@@ -639,7 +636,7 @@ For backend-specific options, prefer the upstream concept directly inside `spec.
639
636
  - `agent-harness` is not a third agent framework
640
637
  - public runtime contract stays generic and small
641
638
  - application-level orchestration and lifecycle management stays in the harness
642
- - ACP should be the preferred future external client protocol instead of a parallel harness-only protocol
639
+ - the external protocol boundary should strictly conform to `deepagents-acp` instead of a parallel harness-only protocol
643
640
  - upstream LangChain v1 and DeepAgents concepts should be expressed as directly as possible in YAML
644
641
  - when a feature can be expressed in YAML, prefer YAML over expanding the public API
645
642
  - recovery, approvals, threads, runs, and events are runtime concepts, not backend escape hatches
package/README.zh.md CHANGED
@@ -79,7 +79,7 @@
79
79
  - `docs/model-layering.md`
80
80
  - `docs/coding-agent-guide.md`
81
81
 
82
- 当外部工具需要标准运行时边界时,ACP 是预期的未来客户端协议方向。`agent-harness` 应该具备 ACP 能力,同时继续把运行时生命周期、持久化、恢复与治理保留在 harness 内部。
82
+ 当外部工具需要标准运行时边界时,`deepagents-acp` 是必须遵循的外部协议方向。`agent-harness` 应在该边界上严格契合 `deepagents-acp` 语义,同时继续把运行时生命周期、持久化、恢复与治理保留在 harness 内部。
83
83
 
84
84
  长链路编排的推荐形态:
85
85
 
@@ -633,7 +633,7 @@ spec:
633
633
  - `agent-harness` 不是第三个 agent 框架
634
634
  - 公共运行时契约保持通用且精简
635
635
  - 应用级编排与生命周期管理留在 harness 中
636
- - ACP 应作为优先对齐的未来外部客户端协议,而不是再做一套并行的 harness 私有协议
636
+ - 外部协议边界应严格契合 `deepagents-acp`,而不是再做一套并行的 harness 私有协议
637
637
  - 应尽量在 YAML 中直接表达 LangChain v1 与 DeepAgents 的概念
638
638
  - 能用 YAML 表达的能力,优先 YAML 而非扩张公共 API
639
639
  - 恢复、审批、线程、运行与事件是运行时概念,不是后端逃生舱
@@ -1,4 +1,4 @@
1
- export declare const DEFAULT_UPSTREAM_BENCHMARK_PATHS: readonly ["harness", "raw-langchain-v1", "raw-langgraph", "raw-deepagent"];
1
+ export declare const DEFAULT_UPSTREAM_BENCHMARK_PATHS: readonly ["harness", "raw-langchain-v1", "raw-deepagent"];
2
2
  export declare const DEFAULT_UPSTREAM_BENCHMARK_WORKLOAD: "tool";
3
3
  export type UpstreamBenchmarkPath = (typeof DEFAULT_UPSTREAM_BENCHMARK_PATHS)[number];
4
4
  export type UpstreamBenchmarkWorkload = "tool" | "no-tool";
@@ -1,7 +1,6 @@
1
1
  export const DEFAULT_UPSTREAM_BENCHMARK_PATHS = Object.freeze([
2
2
  "harness",
3
3
  "raw-langchain-v1",
4
- "raw-langgraph",
5
4
  "raw-deepagent",
6
5
  ]);
7
6
  export const DEFAULT_UPSTREAM_BENCHMARK_WORKLOAD = "tool";
@@ -48,7 +47,7 @@ export function resolveUpstreamBenchmarkPaths(rawValue) {
48
47
  const parsed = rawValue
49
48
  .split(",")
50
49
  .map((value) => value.trim().toLowerCase())
51
- .filter((value) => value === "harness" || value === "raw-langchain-v1" || value === "raw-langgraph" || value === "raw-deepagent");
50
+ .filter((value) => value === "harness" || value === "raw-langchain-v1" || value === "raw-deepagent");
52
51
  return parsed.length > 0 ? parsed : [...DEFAULT_UPSTREAM_BENCHMARK_PATHS];
53
52
  }
54
53
  export function resolveUpstreamBenchmarkWorkload(rawValue) {
@@ -1,6 +1,6 @@
1
- export type ExecutionMode = "deepagent" | "langchain-v1" | "langgraph";
1
+ export type ExecutionMode = "deepagent" | "langchain-v1";
2
2
  export declare const AUTO_AGENT_ID = "auto";
3
- export type RuntimeModelSlot = "routing" | "planning" | "execution" | "review" | "final";
3
+ export type RuntimeModelSlot = "planning" | "execution" | "review" | "final";
4
4
  export type RuntimeModelRefMap = Partial<Record<RuntimeModelSlot, string>>;
5
5
  export type RuntimeCapabilities = {
6
6
  delegation?: boolean;
@@ -9,7 +9,7 @@ export type ThreadSummary = {
9
9
  status: RunState;
10
10
  };
11
11
  export type SessionRecord = ThreadSummary;
12
- export type KnownHarnessEventType = "run.created" | "run.queued" | "run.dequeued" | "run.state.changed" | "run.reviewed" | "run.resumed" | "approval.requested" | "approval.resolved" | "artifact.created" | "output.delta" | "reasoning.delta" | "runtime.health.changed" | "runtime.synthetic_fallback";
12
+ export type KnownHarnessEventType = "run.created" | "run.queued" | "run.dequeued" | "run.state.changed" | "run.resumed" | "approval.requested" | "approval.resolved" | "artifact.created" | "output.delta" | "reasoning.delta" | "runtime.health.changed" | "runtime.synthetic_fallback";
13
13
  export type HarnessEventType = KnownHarnessEventType | (string & {});
14
14
  export type HarnessEvent = {
15
15
  eventId: string;
@@ -190,8 +190,6 @@ export type RunStartOptions = {
190
190
  priority?: number;
191
191
  invocation?: InvocationEnvelope;
192
192
  listeners?: RunListeners;
193
- runtimeListeners?: RuntimeListeners;
194
- frontendListeners?: FrontendStreamListeners;
195
193
  };
196
194
  export type RunDecisionOptions = {
197
195
  threadId: string;
@@ -200,8 +198,6 @@ export type RunDecisionOptions = {
200
198
  decision: "approve" | "edit" | "reject";
201
199
  editedInput?: Record<string, unknown>;
202
200
  listeners?: RunListeners;
203
- runtimeListeners?: RuntimeListeners;
204
- frontendListeners?: FrontendStreamListeners;
205
201
  };
206
202
  export type RunOptions = RunStartOptions | RunDecisionOptions;
207
203
  export type HarnessStreamItem = {
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.98";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.99";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.98";
1
+ export const AGENT_HARNESS_VERSION = "0.0.99";
@@ -0,0 +1,30 @@
1
+ import type { DeepAgentParams } from "../../contracts/types.js";
2
+ export declare function buildDeepAgentRunnableConfig(params: {
3
+ compatibleParams: DeepAgentParams;
4
+ resolvedModel: unknown;
5
+ resolvedTools: unknown[];
6
+ resolvedMiddleware: unknown[];
7
+ resolvedSubagents: unknown[];
8
+ resolvedCheckpointer: unknown;
9
+ resolvedStore: unknown;
10
+ resolvedBackend: unknown;
11
+ resolvedInterruptOn: unknown;
12
+ resolvedSkills: string[];
13
+ }): {
14
+ model: never;
15
+ tools: never;
16
+ systemPrompt: string | undefined;
17
+ responseFormat: never;
18
+ contextSchema: never;
19
+ middleware: never;
20
+ subagents: never;
21
+ checkpointer: never;
22
+ store: never;
23
+ backend: never;
24
+ interruptOn: never;
25
+ name: string;
26
+ memory: string[];
27
+ skills: string[];
28
+ generalPurposeAgent: boolean | undefined;
29
+ taskDescription: string | undefined;
30
+ };
@@ -0,0 +1,22 @@
1
+ export function buildDeepAgentRunnableConfig(params) {
2
+ const { compatibleParams, resolvedModel, resolvedTools, resolvedMiddleware, resolvedSubagents, resolvedCheckpointer, resolvedStore, resolvedBackend, resolvedInterruptOn, resolvedSkills, } = params;
3
+ return {
4
+ ...(compatibleParams.passthrough ?? {}),
5
+ model: resolvedModel,
6
+ tools: resolvedTools,
7
+ systemPrompt: compatibleParams.systemPrompt,
8
+ responseFormat: compatibleParams.responseFormat,
9
+ contextSchema: compatibleParams.contextSchema,
10
+ middleware: resolvedMiddleware,
11
+ subagents: resolvedSubagents,
12
+ checkpointer: resolvedCheckpointer,
13
+ store: resolvedStore,
14
+ backend: resolvedBackend,
15
+ interruptOn: resolvedInterruptOn,
16
+ name: compatibleParams.name,
17
+ memory: compatibleParams.memory,
18
+ skills: resolvedSkills,
19
+ generalPurposeAgent: compatibleParams.generalPurposeAgent,
20
+ taskDescription: compatibleParams.taskDescription,
21
+ };
22
+ }
@@ -2,8 +2,6 @@ export * from "./tool/declared-middleware.js";
2
2
  export * from "./compat/deepagent-compat.js";
3
3
  export * from "./tool/interrupt-policy.js";
4
4
  export * from "./model/invocation-request.js";
5
- export * from "./langgraph/presets.js";
6
- export * from "./langgraph/profiles.js";
7
5
  export * from "./model/message-assembly.js";
8
6
  export * from "./model/model-providers.js";
9
7
  export * from "./compat/openai-compatible.js";
@@ -2,8 +2,6 @@ export * from "./tool/declared-middleware.js";
2
2
  export * from "./compat/deepagent-compat.js";
3
3
  export * from "./tool/interrupt-policy.js";
4
4
  export * from "./model/invocation-request.js";
5
- export * from "./langgraph/presets.js";
6
- export * from "./langgraph/profiles.js";
7
5
  export * from "./model/message-assembly.js";
8
6
  export * from "./model/model-providers.js";
9
7
  export * from "./compat/openai-compatible.js";
@@ -0,0 +1,13 @@
1
+ import type { RunResult } from "../../contracts/types.js";
2
+ export type ExecutedToolResult = {
3
+ toolName: string;
4
+ output: unknown;
5
+ isError?: boolean;
6
+ };
7
+ export declare function finalizeInvocationResult(params: {
8
+ bindingAgentId: string;
9
+ threadId: string;
10
+ runId: string;
11
+ result: Record<string, unknown>;
12
+ executedToolResults: ExecutedToolResult[];
13
+ }): RunResult;
@@ -0,0 +1,40 @@
1
+ import { extractContentBlocks, extractEmptyAssistantMessageFailure, extractOutputContent, extractToolFallbackContext, extractVisibleOutput, isLikelyToolArgsObject, sanitizeVisibleText, tryParseJson, } from "../parsing/output-parsing.js";
2
+ import { buildStateSnapshot } from "./model/message-assembly.js";
3
+ import { asRecord } from "./tool/resolved-tool.js";
4
+ export function finalizeInvocationResult(params) {
5
+ const { bindingAgentId, threadId, runId, result, executedToolResults } = params;
6
+ const interruptContent = Array.isArray(result.__interrupt__) && result.__interrupt__.length > 0 ? JSON.stringify(result.__interrupt__) : undefined;
7
+ const extractedOutput = extractVisibleOutput(result);
8
+ const visibleOutput = extractedOutput && !isLikelyToolArgsObject(tryParseJson(extractedOutput)) ? extractedOutput : "";
9
+ const emptyAssistantMessageFailure = extractEmptyAssistantMessageFailure(result);
10
+ const toolFallback = extractToolFallbackContext(result);
11
+ if (!visibleOutput && !toolFallback && emptyAssistantMessageFailure) {
12
+ throw new Error(emptyAssistantMessageFailure);
13
+ }
14
+ const output = visibleOutput || toolFallback || JSON.stringify(result, null, 2);
15
+ const finalMessageText = sanitizeVisibleText(output);
16
+ const outputContent = extractOutputContent(result);
17
+ const contentBlocks = extractContentBlocks(result);
18
+ const structuredResponse = result.structuredResponse;
19
+ return {
20
+ threadId,
21
+ runId,
22
+ agentId: bindingAgentId,
23
+ state: Array.isArray(result.__interrupt__) && result.__interrupt__.length > 0 ? "waiting_for_approval" : "completed",
24
+ interruptContent,
25
+ output: finalMessageText,
26
+ finalMessageText,
27
+ ...(outputContent !== undefined ? { outputContent } : {}),
28
+ ...(contentBlocks.length > 0 ? { contentBlocks } : {}),
29
+ ...(structuredResponse !== undefined ? { structuredResponse } : {}),
30
+ metadata: {
31
+ ...(executedToolResults.length > 0 ? { executedToolResults } : {}),
32
+ ...(structuredResponse !== undefined ? { structuredResponse } : {}),
33
+ ...(outputContent !== undefined ? { outputContent } : {}),
34
+ ...(contentBlocks.length > 0 ? { contentBlocks } : {}),
35
+ ...(asRecord(result.files) ? { files: asRecord(result.files) } : {}),
36
+ ...(buildStateSnapshot(result) ? { stateSnapshot: buildStateSnapshot(result) } : {}),
37
+ upstreamResult: result,
38
+ },
39
+ };
40
+ }
@@ -0,0 +1,25 @@
1
+ import type { LangChainAgentParams } from "../../contracts/types.js";
2
+ export declare function buildLangChainRunnableConfig(params: {
3
+ langchainParams: LangChainAgentParams;
4
+ resolvedModel: unknown;
5
+ resolvedTools: unknown[];
6
+ resolvedMiddleware: unknown[];
7
+ resolvedCheckpointer: unknown;
8
+ resolvedStore: unknown;
9
+ passthroughOverride?: Record<string, unknown>;
10
+ systemPromptOverride?: string;
11
+ }): {
12
+ model: never;
13
+ tools: never;
14
+ systemPrompt: string | undefined;
15
+ stateSchema: never;
16
+ responseFormat: never;
17
+ contextSchema: never;
18
+ middleware: never;
19
+ checkpointer: never;
20
+ store: never;
21
+ includeAgentName: "inline" | undefined;
22
+ version: "v1" | "v2" | undefined;
23
+ name: string | undefined;
24
+ description: string;
25
+ };
@@ -0,0 +1,19 @@
1
+ export function buildLangChainRunnableConfig(params) {
2
+ const { langchainParams, resolvedModel, resolvedTools, resolvedMiddleware, resolvedCheckpointer, resolvedStore, passthroughOverride, systemPromptOverride, } = params;
3
+ return {
4
+ ...(passthroughOverride ?? langchainParams.passthrough ?? {}),
5
+ model: resolvedModel,
6
+ tools: resolvedTools,
7
+ systemPrompt: systemPromptOverride ?? langchainParams.systemPrompt,
8
+ stateSchema: langchainParams.stateSchema,
9
+ responseFormat: langchainParams.responseFormat,
10
+ contextSchema: langchainParams.contextSchema,
11
+ middleware: resolvedMiddleware,
12
+ checkpointer: resolvedCheckpointer,
13
+ store: resolvedStore,
14
+ includeAgentName: langchainParams.includeAgentName,
15
+ version: langchainParams.version,
16
+ name: langchainParams.name,
17
+ description: langchainParams.description,
18
+ };
19
+ }
@@ -0,0 +1,23 @@
1
+ import type { CompiledAgentBinding, CompiledTool } from "../../contracts/types.js";
2
+ import { type ToolNameMapping } from "./tool/tool-name-mapping.js";
3
+ import type { ExecutedToolResult } from "./invocation-result.js";
4
+ type ExecutableTool = {
5
+ name: string;
6
+ schema: unknown;
7
+ invoke: (input: unknown) => Promise<unknown>;
8
+ };
9
+ type LocalToolInvocationParams = {
10
+ binding: CompiledAgentBinding;
11
+ request: unknown;
12
+ primaryTools: CompiledTool[];
13
+ toolNameMapping: ToolNameMapping;
14
+ executableTools: Map<string, ExecutableTool>;
15
+ builtinExecutableTools: Map<string, ExecutableTool>;
16
+ callRuntimeWithToolParseRecovery: (request: unknown) => Promise<Record<string, unknown>>;
17
+ };
18
+ type LocalToolInvocationResult = {
19
+ result: Record<string, unknown>;
20
+ executedToolResults: ExecutedToolResult[];
21
+ };
22
+ export declare function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, }: LocalToolInvocationParams): Promise<LocalToolInvocationResult>;
23
+ export {};
@@ -0,0 +1,64 @@
1
+ import { ToolMessage } from "@langchain/core/messages";
2
+ import { createModelFacingToolNameLookupCandidates, resolveModelFacingToolName } from "./tool/tool-name-mapping.js";
3
+ import { canReplayToolCallsLocally } from "./tool/tool-replay.js";
4
+ import { extractToolCallsFromResult, normalizeToolArgsForSchema, stringifyToolOutput } from "./tool/tool-arguments.js";
5
+ export async function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, }) {
6
+ const executedToolResults = [];
7
+ let activeRequest = request;
8
+ let currentMessages = Array.isArray(activeRequest.messages) ? [...activeRequest.messages] : [];
9
+ const maxToolIterations = 8;
10
+ let pendingResult;
11
+ let result;
12
+ for (let iteration = 0; iteration < maxToolIterations; iteration += 1) {
13
+ result = pendingResult ?? await callRuntimeWithToolParseRecovery(activeRequest);
14
+ pendingResult = undefined;
15
+ const toolCalls = extractToolCallsFromResult(result);
16
+ if (toolCalls.length === 0) {
17
+ break;
18
+ }
19
+ if (!canReplayToolCallsLocally(binding, toolCalls, primaryTools, toolNameMapping, executableTools, builtinExecutableTools)) {
20
+ break;
21
+ }
22
+ if (iteration + 1 === maxToolIterations) {
23
+ throw new Error(`Tool-calling loop exceeded the maximum of ${maxToolIterations} iterations`);
24
+ }
25
+ const resultMessages = result.messages;
26
+ const nextMessages = Array.isArray(resultMessages)
27
+ ? [...resultMessages]
28
+ : [...currentMessages];
29
+ for (let toolIndex = 0; toolIndex < toolCalls.length; toolIndex += 1) {
30
+ const toolCall = toolCalls[toolIndex];
31
+ const resolvedToolName = resolveModelFacingToolName(toolCall.name, toolNameMapping, primaryTools);
32
+ const executable = executableTools.get(toolCall.name) ?? executableTools.get(resolvedToolName);
33
+ const builtinExecutable = builtinExecutableTools.get(toolCall.name) ??
34
+ builtinExecutableTools.get(resolvedToolName) ??
35
+ createModelFacingToolNameLookupCandidates(toolCall.name)
36
+ .map((candidate) => builtinExecutableTools.get(candidate))
37
+ .find((candidate) => candidate !== undefined);
38
+ const activeExecutable = executable ?? builtinExecutable;
39
+ if (!activeExecutable) {
40
+ throw new Error(`Tool ${toolCall.name} is not configured for this agent.`);
41
+ }
42
+ const normalizedArgs = normalizeToolArgsForSchema(toolCall.args, activeExecutable.schema);
43
+ const toolResult = await activeExecutable.invoke(normalizedArgs);
44
+ executedToolResults.push({
45
+ toolName: activeExecutable.name,
46
+ output: toolResult,
47
+ });
48
+ nextMessages.push(new ToolMessage({
49
+ name: activeExecutable.name,
50
+ tool_call_id: toolCall.id ?? `tool-${iteration + 1}-${toolIndex + 1}`,
51
+ content: stringifyToolOutput(toolResult),
52
+ }));
53
+ }
54
+ currentMessages = nextMessages;
55
+ activeRequest = {
56
+ ...activeRequest,
57
+ messages: currentMessages,
58
+ };
59
+ }
60
+ if (!result) {
61
+ throw new Error("Agent invocation returned no result");
62
+ }
63
+ return { result, executedToolResults };
64
+ }
@@ -0,0 +1,18 @@
1
+ import type { CompiledAgentBinding } from "../../contracts/types.js";
2
+ export declare function countConfiguredTools(binding: CompiledAgentBinding): number;
3
+ export declare function asObject(value: unknown): Record<string, unknown> | undefined;
4
+ export declare function sleep(ms: number): Promise<void>;
5
+ export declare function hasConfiguredSubagentSupport(binding: CompiledAgentBinding): boolean;
6
+ export declare function hasConfiguredMiddlewareKind(binding: CompiledAgentBinding, kind: string): boolean;
7
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
8
+ export declare function isObject(value: unknown): value is Record<string, unknown>;
9
+ export declare function truncateLines(lines: string[], maxChars?: number): string;
10
+ export declare function summarizeBuiltinWriteTodosArgs(args: Record<string, unknown>): {
11
+ total: number;
12
+ pending: number;
13
+ completed: number;
14
+ items: Array<{
15
+ content: string;
16
+ status: string;
17
+ }>;
18
+ };
@@ -0,0 +1,54 @@
1
+ import { getBindingLangChainParams, getBindingMiddlewareConfigs, getBindingPrimaryTools } from "../support/compiled-binding.js";
2
+ export function countConfiguredTools(binding) {
3
+ return getBindingPrimaryTools(binding).length;
4
+ }
5
+ export function asObject(value) {
6
+ return typeof value === "object" && value ? value : undefined;
7
+ }
8
+ export function sleep(ms) {
9
+ return new Promise((resolve) => setTimeout(resolve, ms));
10
+ }
11
+ export function hasConfiguredSubagentSupport(binding) {
12
+ const params = getBindingLangChainParams(binding);
13
+ if (!params) {
14
+ return false;
15
+ }
16
+ return (params.subagents?.length ?? 0) > 0 || params.generalPurposeAgent === true || Boolean(params.taskDescription?.trim());
17
+ }
18
+ export function hasConfiguredMiddlewareKind(binding, kind) {
19
+ return getBindingMiddlewareConfigs(binding)?.some((entry) => entry.kind === kind) ?? false;
20
+ }
21
+ export function isRecord(value) {
22
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23
+ }
24
+ export function isObject(value) {
25
+ return isRecord(value);
26
+ }
27
+ export function truncateLines(lines, maxChars = 12_000) {
28
+ const joined = lines.join("\n");
29
+ if (joined.length <= maxChars) {
30
+ return joined;
31
+ }
32
+ return `${joined.slice(0, maxChars - 18)}\n...[truncated]`;
33
+ }
34
+ export function summarizeBuiltinWriteTodosArgs(args) {
35
+ const todos = Array.isArray(args.todos) ? args.todos : [];
36
+ const items = todos.flatMap((todo) => {
37
+ if (!isObject(todo)) {
38
+ return [];
39
+ }
40
+ const content = typeof todo.content === "string" && todo.content.trim().length > 0
41
+ ? todo.content.trim()
42
+ : typeof todo.description === "string" && todo.description.trim().length > 0
43
+ ? todo.description.trim()
44
+ : "";
45
+ const status = typeof todo.status === "string" && todo.status.trim().length > 0 ? todo.status.trim() : "pending";
46
+ return content ? [{ content, status }] : [];
47
+ });
48
+ return {
49
+ total: items.length,
50
+ pending: items.filter((item) => item.status !== "completed").length,
51
+ completed: items.filter((item) => item.status === "completed").length,
52
+ items,
53
+ };
54
+ }
@@ -0,0 +1,19 @@
1
+ import type { CompiledTool } from "../../contracts/types.js";
2
+ import { type RuntimeStreamChunk } from "../parsing/stream-event-parsing.js";
3
+ import { type ToolNameMapping } from "./tool/tool-name-mapping.js";
4
+ export type StreamEventProjectionState = {
5
+ emittedOutput: string;
6
+ emittedToolError: boolean;
7
+ emittedToolResult: boolean;
8
+ seenTerminalOutputs: Set<string>;
9
+ lastStep: string;
10
+ };
11
+ export declare function createStreamEventProjectionState(): StreamEventProjectionState;
12
+ export declare function projectRuntimeStreamEvent(params: {
13
+ event: unknown;
14
+ allowVisibleStreamDeltas: boolean;
15
+ includeStateStreamOutput: boolean;
16
+ toolNameMapping: ToolNameMapping;
17
+ primaryTools: CompiledTool[];
18
+ state: StreamEventProjectionState;
19
+ }): RuntimeStreamChunk[];
@@ -0,0 +1,79 @@
1
+ import { sanitizeVisibleText } from "../parsing/output-parsing.js";
2
+ import { computeIncrementalOutput, extractAgentStep, extractInterruptPayload, extractReasoningStreamOutput, extractStateStreamOutput, extractTerminalStreamOutput, extractToolResult, extractVisibleStreamOutput, normalizeTerminalOutputKey, normalizeUpstreamRuntimeEvent, } from "../parsing/stream-event-parsing.js";
3
+ import { resolveModelFacingToolName } from "./tool/tool-name-mapping.js";
4
+ export function createStreamEventProjectionState() {
5
+ return {
6
+ emittedOutput: "",
7
+ emittedToolError: false,
8
+ emittedToolResult: false,
9
+ seenTerminalOutputs: new Set(),
10
+ lastStep: "",
11
+ };
12
+ }
13
+ export function projectRuntimeStreamEvent(params) {
14
+ const { event, allowVisibleStreamDeltas, includeStateStreamOutput, toolNameMapping, primaryTools, state, } = params;
15
+ const chunks = [{
16
+ kind: "upstream-event",
17
+ event: normalizeUpstreamRuntimeEvent(event),
18
+ }];
19
+ const interruptPayload = extractInterruptPayload(event);
20
+ if (interruptPayload) {
21
+ chunks.push({ kind: "interrupt", content: interruptPayload });
22
+ return chunks;
23
+ }
24
+ const reasoning = extractReasoningStreamOutput(event);
25
+ if (reasoning) {
26
+ chunks.push({ kind: "reasoning", content: reasoning });
27
+ }
28
+ if (allowVisibleStreamDeltas) {
29
+ const visibleStreamOutput = extractVisibleStreamOutput(event);
30
+ if (visibleStreamOutput) {
31
+ const nextOutput = computeIncrementalOutput(state.emittedOutput, visibleStreamOutput);
32
+ state.emittedOutput = nextOutput.accumulated;
33
+ if (nextOutput.delta) {
34
+ chunks.push({ kind: "content", content: nextOutput.delta });
35
+ }
36
+ }
37
+ }
38
+ if (includeStateStreamOutput) {
39
+ const stateStreamOutput = extractStateStreamOutput(event);
40
+ if (stateStreamOutput) {
41
+ const nextOutput = computeIncrementalOutput(state.emittedOutput, sanitizeVisibleText(stateStreamOutput));
42
+ state.emittedOutput = nextOutput.accumulated;
43
+ if (nextOutput.delta) {
44
+ chunks.push({ kind: "content", content: nextOutput.delta });
45
+ }
46
+ }
47
+ }
48
+ const agentStep = extractAgentStep(event);
49
+ if (agentStep && agentStep !== state.lastStep) {
50
+ state.lastStep = agentStep;
51
+ chunks.push({ kind: "step", content: agentStep });
52
+ }
53
+ const toolResult = extractToolResult(event);
54
+ if (toolResult) {
55
+ state.emittedToolResult = true;
56
+ state.emittedToolError = state.emittedToolError || toolResult.isError === true;
57
+ chunks.push({
58
+ kind: "tool-result",
59
+ toolName: resolveModelFacingToolName(toolResult.toolName, toolNameMapping, primaryTools),
60
+ output: toolResult.output,
61
+ isError: toolResult.isError,
62
+ });
63
+ }
64
+ const output = extractTerminalStreamOutput(event);
65
+ if (output) {
66
+ const outputKey = normalizeTerminalOutputKey(output);
67
+ if (!outputKey || !state.seenTerminalOutputs.has(outputKey)) {
68
+ if (outputKey) {
69
+ state.seenTerminalOutputs.add(outputKey);
70
+ }
71
+ const nextOutput = computeIncrementalOutput(state.emittedOutput, sanitizeVisibleText(output));
72
+ state.emittedOutput = nextOutput.accumulated;
73
+ if (nextOutput.delta) {
74
+ chunks.push({ kind: "content", content: nextOutput.delta });
75
+ }
76
+ }
77
+ }
78
+ return chunks;
79
+ }
@@ -0,0 +1,4 @@
1
+ import { type RuntimeStreamChunk } from "../parsing/stream-event-parsing.js";
2
+ export declare function projectTextStreamChunks(stream: AsyncIterable<unknown>): AsyncGenerator<RuntimeStreamChunk, {
3
+ emittedContent: boolean;
4
+ }>;
@@ -0,0 +1,18 @@
1
+ import { extractReasoningText } from "../parsing/output-parsing.js";
2
+ import { readStreamDelta } from "../parsing/stream-event-parsing.js";
3
+ export async function* projectTextStreamChunks(stream) {
4
+ let emittedContent = false;
5
+ for await (const chunk of stream) {
6
+ const delta = readStreamDelta(chunk);
7
+ if (delta) {
8
+ emittedContent = true;
9
+ yield { kind: "content", content: delta };
10
+ continue;
11
+ }
12
+ const reasoning = extractReasoningText(chunk);
13
+ if (reasoning) {
14
+ yield { kind: "reasoning", content: reasoning };
15
+ }
16
+ }
17
+ return { emittedContent };
18
+ }