@botbotgo/agent-harness 0.0.359 → 0.0.362
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/README.zh.md +2 -0
- package/dist/config/catalogs/response-formats.yaml +43 -0
- package/dist/config/runtime/workspace.yaml +8 -0
- package/dist/contracts/runtime-requests.d.ts +19 -0
- package/dist/contracts/workspace.d.ts +6 -0
- package/dist/package-version.d.ts +2 -2
- package/dist/package-version.js +2 -2
- package/dist/projections/request-events.d.ts +1 -0
- package/dist/projections/request-events.js +97 -45
- package/dist/protocol/acp/harness-client.js +2 -3
- package/dist/runtime/adapter/flow/invocation-flow.js +26 -1
- package/dist/runtime/adapter/flow/stream-runtime.js +117 -94
- package/dist/runtime/adapter/invocation-result.js +15 -0
- package/dist/runtime/adapter/middleware-assembly.js +25 -3
- package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +5 -0
- package/dist/runtime/adapter/tool/builtin-middleware-tools.js +30 -6
- package/dist/runtime/agent-runtime-adapter.d.ts +1 -0
- package/dist/runtime/agent-runtime-adapter.js +174 -28
- package/dist/runtime/harness/events/streaming.js +2 -3
- package/dist/workspace/agent-binding-compiler.js +90 -12
- package/dist/workspace/compile.js +1 -0
- package/dist/workspace/framework-contract-validation.d.ts +2 -1
- package/dist/workspace/framework-contract-validation.js +77 -5
- package/dist/workspace/object-loader.js +9 -0
- package/dist/workspace/support/workspace-ref-utils.d.ts +1 -0
- package/dist/workspace/support/workspace-ref-utils.js +40 -0
- package/dist/workspace/yaml-object-reader.js +13 -9
- package/package.json +1 -1
|
@@ -362,17 +362,32 @@ export async function invokeBuiltinTaskTool(input) {
|
|
|
362
362
|
const typedInput = isRecord(input.toolInput) ? input.toolInput : {};
|
|
363
363
|
const description = typeof typedInput.description === "string"
|
|
364
364
|
? typedInput.description
|
|
365
|
-
: ""
|
|
365
|
+
: typeof typedInput.instruction === "string"
|
|
366
|
+
? typedInput.instruction
|
|
367
|
+
: typeof typedInput.task === "string"
|
|
368
|
+
? typedInput.task
|
|
369
|
+
: typeof typedInput.prompt === "string"
|
|
370
|
+
? typedInput.prompt
|
|
371
|
+
: "";
|
|
366
372
|
const subagentType = typeof typedInput.subagent_type === "string"
|
|
367
373
|
? typedInput.subagent_type
|
|
368
|
-
: ""
|
|
374
|
+
: typeof typedInput.agentId === "string"
|
|
375
|
+
? typedInput.agentId
|
|
376
|
+
: typeof typedInput.agent_id === "string"
|
|
377
|
+
? typedInput.agent_id
|
|
378
|
+
: typeof typedInput.subagent === "string"
|
|
379
|
+
? typedInput.subagent
|
|
380
|
+
: "";
|
|
369
381
|
const builtinBackend = input.resolveBuiltinMiddlewareBackend(input.binding, input.options);
|
|
370
382
|
const resolvedSubagents = await input.resolveSubagents(compiledSubagents, input.binding);
|
|
371
383
|
const selectedSubagent = resolvedSubagents.find((subagent) => subagent.name === subagentType);
|
|
372
384
|
const selectedCompiledSubagent = compiledSubagents.find((subagent) => subagent.name === subagentType);
|
|
373
385
|
if (!selectedSubagent) {
|
|
374
386
|
const allowed = resolvedSubagents.map((subagent) => subagent.name);
|
|
375
|
-
|
|
387
|
+
const available = resolvedSubagents
|
|
388
|
+
.map((subagent) => `- ${subagent.name}: ${subagent.description}`)
|
|
389
|
+
.join("\n");
|
|
390
|
+
throw new Error(`Error: invoked agent of type ${subagentType}, the only allowed types are ${allowed.map((name) => `\`${name}\``).join(", ")}.${available ? `\nAvailable subagents:\n${available}` : ""}`);
|
|
376
391
|
}
|
|
377
392
|
const resolvedHostModel = selectedSubagent.model ? undefined : await input.resolveModel(primaryModel);
|
|
378
393
|
const summarizationModel = selectedSubagent.model ?? resolvedHostModel;
|
|
@@ -446,8 +461,15 @@ export async function resolveBuiltinMiddlewareTools(input) {
|
|
|
446
461
|
...(input.binding.agent.asyncSubagents ?? []),
|
|
447
462
|
];
|
|
448
463
|
const includeTaskTool = configuredSubagents.length > 0;
|
|
464
|
+
const taskSubagents = getBindingDeepAgentSubagents(input.binding)
|
|
465
|
+
.filter((subagent) => !("graphId" in subagent))
|
|
466
|
+
.map((subagent) => ({
|
|
467
|
+
name: subagent.name,
|
|
468
|
+
description: subagent.description,
|
|
469
|
+
}));
|
|
449
470
|
const tools = (await createBuiltinMiddlewareTools(backend, {
|
|
450
471
|
includeTaskTool,
|
|
472
|
+
taskSubagents,
|
|
451
473
|
workspaceRoot: input.binding.harnessRuntime.workspaceRoot,
|
|
452
474
|
toolRuntimeContext: input.options?.toolRuntimeContext,
|
|
453
475
|
invokeTaskTool: includeTaskTool
|
|
@@ -188,6 +188,10 @@ export type BuiltinExecutableTool = {
|
|
|
188
188
|
schema: unknown;
|
|
189
189
|
invoke: (input: unknown, config?: Record<string, unknown>) => Promise<unknown>;
|
|
190
190
|
};
|
|
191
|
+
export type BuiltinTaskSubagentDescriptor = {
|
|
192
|
+
name: string;
|
|
193
|
+
description: string;
|
|
194
|
+
};
|
|
191
195
|
export declare const BUILTIN_MIDDLEWARE_TOOL_DESCRIPTORS: readonly [{
|
|
192
196
|
readonly name: "write_todos";
|
|
193
197
|
readonly description: "Create and update the runtime todo board for multi-step work.";
|
|
@@ -254,6 +258,7 @@ export declare function filterBuiltinMiddlewareToolDescriptors(options?: {
|
|
|
254
258
|
export declare function createBuiltinMiddlewareTools(backend: BuiltinMiddlewareBackend, options: {
|
|
255
259
|
includeTaskTool: boolean;
|
|
256
260
|
invokeTaskTool?: (input: unknown) => Promise<unknown>;
|
|
261
|
+
taskSubagents?: BuiltinTaskSubagentDescriptor[];
|
|
257
262
|
workspaceRoot?: string;
|
|
258
263
|
toolRuntimeContext?: Record<string, unknown>;
|
|
259
264
|
}): Promise<Map<string, BuiltinExecutableTool>>;
|
|
@@ -4,10 +4,33 @@ import { isSandboxBackend } from "deepagents";
|
|
|
4
4
|
import { isRecord } from "../../../utils/object.js";
|
|
5
5
|
import { formatBuiltinTodoSnapshot, isLowSignalTodoContent, summarizeBuiltinWriteTodosArgs, truncateLines } from "../runtime-adapter-support.js";
|
|
6
6
|
import { maybePersistLargeToolOutput, resolveToolRuntimeContext } from "./tool-output-artifacts.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
function buildTaskToolDescription(subagents) {
|
|
8
|
+
const lines = [
|
|
9
|
+
"Delegate a bounded task to the subagent whose declared description best matches the task.",
|
|
10
|
+
"Use this only when a subagent is a better fit than the current agent. Set subagent_type to exactly one listed subagent name.",
|
|
11
|
+
];
|
|
12
|
+
const available = (subagents ?? [])
|
|
13
|
+
.filter((subagent) => subagent.name.trim().length > 0)
|
|
14
|
+
.map((subagent) => {
|
|
15
|
+
const description = subagent.description.trim() || "No description provided.";
|
|
16
|
+
return `- ${subagent.name}: ${description}`;
|
|
17
|
+
});
|
|
18
|
+
return available.length > 0
|
|
19
|
+
? [...lines, "", "Available subagents:", ...available].join("\n")
|
|
20
|
+
: lines.join(" ");
|
|
21
|
+
}
|
|
22
|
+
function buildTaskToolSchema(subagents) {
|
|
23
|
+
const names = (subagents ?? [])
|
|
24
|
+
.map((subagent) => subagent.name.trim())
|
|
25
|
+
.filter((name) => name.length > 0);
|
|
26
|
+
const subagentTypeSchema = names.length > 0
|
|
27
|
+
? z.enum(names)
|
|
28
|
+
: z.string();
|
|
29
|
+
return z.object({
|
|
30
|
+
description: z.string().describe("Concrete bounded task for the selected subagent to perform."),
|
|
31
|
+
subagent_type: subagentTypeSchema.describe("Exact name of the selected subagent."),
|
|
32
|
+
}).passthrough();
|
|
33
|
+
}
|
|
11
34
|
export const BUILTIN_MIDDLEWARE_TOOL_DESCRIPTORS = [
|
|
12
35
|
{ name: "write_todos", description: "Create and update the runtime todo board for multi-step work." },
|
|
13
36
|
{ name: "read_todos", description: "Read the current runtime todo board." },
|
|
@@ -638,10 +661,11 @@ export async function createBuiltinMiddlewareTools(backend, options) {
|
|
|
638
661
|
},
|
|
639
662
|
});
|
|
640
663
|
if (options.includeTaskTool && options.invokeTaskTool) {
|
|
664
|
+
const description = buildTaskToolDescription(options.taskSubagents);
|
|
641
665
|
tools.set("task", {
|
|
642
666
|
name: "task",
|
|
643
|
-
description
|
|
644
|
-
schema:
|
|
667
|
+
description,
|
|
668
|
+
schema: buildTaskToolSchema(options.taskSubagents),
|
|
645
669
|
invoke: async (input) => options.invokeTaskTool(input),
|
|
646
670
|
});
|
|
647
671
|
}
|
|
@@ -58,6 +58,7 @@ export declare class AgentRuntimeAdapter {
|
|
|
58
58
|
memoryContext?: string;
|
|
59
59
|
}): Promise<RequestResult>;
|
|
60
60
|
private tryDelegateWithCompactRouter;
|
|
61
|
+
private buildCompactDelegationReport;
|
|
61
62
|
stream(binding: CompiledAgentBinding, input: MessageContent, sessionId: string, history?: TranscriptMessage[], options?: {
|
|
62
63
|
context?: Record<string, unknown>;
|
|
63
64
|
state?: Record<string, unknown>;
|
|
@@ -10,6 +10,7 @@ import { EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION } from "./prompts/runtim
|
|
|
10
10
|
import { buildToolNameMapping, } from "./adapter/tool/tool-name-mapping.js";
|
|
11
11
|
import { executeRequestInvocation } from "./adapter/flow/invocation-flow.js";
|
|
12
12
|
import { streamRuntimeExecution } from "./adapter/flow/stream-runtime.js";
|
|
13
|
+
import { resolveDeterministicFinalOutput } from "./adapter/invocation-result.js";
|
|
13
14
|
import { applyToolRecoveryInstruction as applyToolRecoveryInstructionHelper, applyStrictToolJsonInstruction as applyStrictToolJsonInstructionHelper, callRuntimeWithToolParseRecovery as callRuntimeWithToolParseRecoveryHelper, createModelFallbackRunnable as createModelFallbackRunnableHelper, invokeWithProviderRetry as invokeWithProviderRetryHelper, iterateWithTimeout as iterateWithTimeoutHelper, materializeModelStream as materializeModelStreamHelper, RuntimeOperationTimeoutError, withRuntimeTimeout, } from "./adapter/runtime-shell.js";
|
|
14
15
|
import { extractSubagentRequestText, invokeBuiltinTaskTool as invokeBuiltinTaskToolHelper, materializeAutomaticSummarizationMiddleware as materializeAutomaticSummarizationMiddlewareHelper, resolveBuiltinMiddlewareBackend as resolveBuiltinMiddlewareBackendHelper, resolveBuiltinMiddlewareTools as resolveBuiltinMiddlewareToolsHelper, resolveLangChainRuntimeExtensionMiddleware as resolveLangChainRuntimeExtensionMiddlewareHelper, resolveMiddleware as resolveMiddlewareHelper, resolveSubagents as resolveSubagentsHelper, wrapRequestResultAsSubagentResponse, } from "./adapter/middleware-assembly.js";
|
|
15
16
|
import { isEmptyFinalAiMessageError, resolveBindingTimeout, resolveStreamIdleTimeout, } from "./adapter/resilience.js";
|
|
@@ -111,6 +112,15 @@ function parseCompactRouterSelection(value, subagentNames) {
|
|
|
111
112
|
if (subagentNames.has(trimmed)) {
|
|
112
113
|
return { subagentType: trimmed };
|
|
113
114
|
}
|
|
115
|
+
const lowered = trimmed.toLowerCase();
|
|
116
|
+
const relaxedMatch = Array.from(subagentNames).find((name) => {
|
|
117
|
+
const lowerName = name.toLowerCase();
|
|
118
|
+
return lowerName.length > 0
|
|
119
|
+
&& (trimmed === name || lowered.includes(lowerName));
|
|
120
|
+
});
|
|
121
|
+
if (relaxedMatch) {
|
|
122
|
+
return { subagentType: relaxedMatch };
|
|
123
|
+
}
|
|
114
124
|
const parsed = parseFirstJsonObject(trimmed);
|
|
115
125
|
const toolCall = salvageJsonToolCalls(trimmed).at(0);
|
|
116
126
|
const payload = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)
|
|
@@ -154,6 +164,29 @@ function hasDelegatedPlanEvidence(result) {
|
|
|
154
164
|
return Array.isArray(toolResults)
|
|
155
165
|
&& toolResults.some((item) => item.toolName === "write_todos" || item.toolName === "read_todos");
|
|
156
166
|
}
|
|
167
|
+
function resolveDelegatedResultOutput(result) {
|
|
168
|
+
const executedToolResults = Array.isArray(result.metadata?.executedToolResults)
|
|
169
|
+
? result.metadata.executedToolResults
|
|
170
|
+
: [];
|
|
171
|
+
const deterministicOutput = resolveDeterministicFinalOutput({
|
|
172
|
+
visibleOutput: typeof result.output === "string" ? result.output : "",
|
|
173
|
+
executedToolResults,
|
|
174
|
+
});
|
|
175
|
+
return deterministicOutput || result.output;
|
|
176
|
+
}
|
|
177
|
+
function selectDelegatedToolResultsForVisibleProgress(result) {
|
|
178
|
+
const executedToolResults = Array.isArray(result?.metadata?.executedToolResults)
|
|
179
|
+
? result.metadata.executedToolResults
|
|
180
|
+
: [];
|
|
181
|
+
const hasSuccessfulExecutionEvidence = executedToolResults.some((toolResult) => (toolResult.isError !== true
|
|
182
|
+
&& toolResult.toolName !== "write_todos"
|
|
183
|
+
&& toolResult.toolName !== "read_todos"));
|
|
184
|
+
return hasSuccessfulExecutionEvidence
|
|
185
|
+
? executedToolResults.filter((toolResult) => (toolResult.isError !== true
|
|
186
|
+
&& toolResult.toolName !== "write_todos"
|
|
187
|
+
&& toolResult.toolName !== "read_todos"))
|
|
188
|
+
: executedToolResults;
|
|
189
|
+
}
|
|
157
190
|
export class AgentRuntimeAdapter {
|
|
158
191
|
options;
|
|
159
192
|
modelCache = new Map();
|
|
@@ -690,9 +723,10 @@ export class AgentRuntimeAdapter {
|
|
|
690
723
|
requestId,
|
|
691
724
|
});
|
|
692
725
|
if (compactDelegation) {
|
|
693
|
-
const
|
|
726
|
+
const compactReport = this.buildCompactDelegationReport(compactDelegation);
|
|
727
|
+
const output = JSON.stringify(compactDelegation.delegatedSubagentType === null
|
|
694
728
|
? compactDelegation.toolOutput
|
|
695
|
-
:
|
|
729
|
+
: compactReport);
|
|
696
730
|
const delegatedToolResults = Array.isArray(compactDelegation.delegatedResult?.metadata?.executedToolResults)
|
|
697
731
|
? compactDelegation.delegatedResult.metadata.executedToolResults
|
|
698
732
|
: [];
|
|
@@ -789,10 +823,13 @@ export class AgentRuntimeAdapter {
|
|
|
789
823
|
const subagentCatalog = subagents
|
|
790
824
|
.map((subagent) => `- ${subagent.name}: ${subagent.description}`)
|
|
791
825
|
.join("\n");
|
|
826
|
+
const routingPolicy = getBindingSystemPrompt(binding);
|
|
792
827
|
const prompt = [
|
|
793
828
|
primaryModel.init?.think === false ? "/no_think" : "",
|
|
794
829
|
"You are selecting a subagent for a delegation-only agent.",
|
|
795
830
|
"Choose exactly one listed subagent when it can responsibly handle the request.",
|
|
831
|
+
routingPolicy ? "Agent routing policy:" : "",
|
|
832
|
+
routingPolicy ?? "",
|
|
796
833
|
"Return only JSON with this shape:",
|
|
797
834
|
"{\"subagent_type\":\"<listed subagent name>\"}",
|
|
798
835
|
"If no listed subagent can handle the request, return only:",
|
|
@@ -806,7 +843,7 @@ export class AgentRuntimeAdapter {
|
|
|
806
843
|
if (typeof model.invoke !== "function") {
|
|
807
844
|
return null;
|
|
808
845
|
}
|
|
809
|
-
const
|
|
846
|
+
const invokeRouter = async (activePrompt, operationName) => this.invokeWithProviderRetry(binding, () => this.withTimeout(() => model.invoke(activePrompt, resolveLangChainInvocationConfig(binding, {
|
|
810
847
|
sessionId,
|
|
811
848
|
requestId,
|
|
812
849
|
context: options.context,
|
|
@@ -815,32 +852,49 @@ export class AgentRuntimeAdapter {
|
|
|
815
852
|
sessionId,
|
|
816
853
|
requestId,
|
|
817
854
|
}),
|
|
818
|
-
})), resolveBindingTimeout(binding),
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
const retryPrompt = [
|
|
855
|
+
})), resolveBindingTimeout(binding), operationName, "invoke"));
|
|
856
|
+
const routerPrompts = [
|
|
857
|
+
prompt,
|
|
858
|
+
[
|
|
823
859
|
prompt,
|
|
824
860
|
"Your previous router output was invalid.",
|
|
825
|
-
"Previous output:",
|
|
826
|
-
rawText,
|
|
827
861
|
"Return only one JSON object now. Do not include prose, markdown, labels, or tool-call wrappers.",
|
|
828
|
-
].join("\n\n")
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
862
|
+
].join("\n\n"),
|
|
863
|
+
[
|
|
864
|
+
primaryModel.init?.think === false ? "/no_think" : "",
|
|
865
|
+
"Select one subagent from this exact list:",
|
|
866
|
+
Array.from(subagentNames).join(", "),
|
|
867
|
+
"Return JSON only:",
|
|
868
|
+
"{\"subagent_type\":\"<one exact listed name>\"}",
|
|
869
|
+
"User request:",
|
|
870
|
+
requestText,
|
|
871
|
+
].filter(Boolean).join("\n\n"),
|
|
872
|
+
[
|
|
873
|
+
primaryModel.init?.think === false ? "/no_think" : "",
|
|
874
|
+
"JSON only. Pick a listed subagent or refuse.",
|
|
875
|
+
"Listed subagents:",
|
|
876
|
+
Array.from(subagentNames).join(", "),
|
|
877
|
+
"Allowed outputs:",
|
|
878
|
+
"{\"subagent_type\":\"<listed name>\"}",
|
|
879
|
+
"{\"status\":\"refused\",\"reason\":\"No configured subagent can handle the request.\"}",
|
|
880
|
+
"Request:",
|
|
881
|
+
requestText,
|
|
882
|
+
].filter(Boolean).join("\n\n"),
|
|
883
|
+
];
|
|
884
|
+
let selection = null;
|
|
885
|
+
let previousRawText = "";
|
|
886
|
+
for (let index = 0; index < routerPrompts.length && !selection; index += 1) {
|
|
887
|
+
const activePrompt = index <= 1 || !previousRawText
|
|
888
|
+
? routerPrompts[index]
|
|
889
|
+
: [routerPrompts[index], "Previous output:", previousRawText].join("\n\n");
|
|
890
|
+
const raw = await invokeRouter(activePrompt, index === 0 ? "delegation router invoke" : `delegation router retry invoke ${index}`);
|
|
891
|
+
previousRawText = readModelText(raw);
|
|
892
|
+
selection = parseCompactRouterSelection(previousRawText, subagentNames);
|
|
840
893
|
}
|
|
841
894
|
if (selection?.refusedReason) {
|
|
842
895
|
return {
|
|
843
896
|
toolOutput: selection.refusedReason,
|
|
897
|
+
delegatedSubagentType: null,
|
|
844
898
|
delegatedResult: {
|
|
845
899
|
sessionId,
|
|
846
900
|
requestId,
|
|
@@ -851,7 +905,16 @@ export class AgentRuntimeAdapter {
|
|
|
851
905
|
},
|
|
852
906
|
};
|
|
853
907
|
}
|
|
854
|
-
|
|
908
|
+
let subagentType = selection?.subagentType ?? "";
|
|
909
|
+
if (!subagentNames.has(subagentType)) {
|
|
910
|
+
const fallbackSubagent = subagentNames.values().next().value;
|
|
911
|
+
if (typeof fallbackSubagent === "string" && fallbackSubagent) {
|
|
912
|
+
subagentType = fallbackSubagent;
|
|
913
|
+
}
|
|
914
|
+
else {
|
|
915
|
+
return null;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
855
918
|
if (!subagentNames.has(subagentType)) {
|
|
856
919
|
return null;
|
|
857
920
|
}
|
|
@@ -865,15 +928,49 @@ export class AgentRuntimeAdapter {
|
|
|
865
928
|
files: options.files,
|
|
866
929
|
memoryContext: options.memoryContext,
|
|
867
930
|
});
|
|
868
|
-
let delegatedResult
|
|
931
|
+
let delegatedResult;
|
|
932
|
+
try {
|
|
933
|
+
delegatedResult = await runDelegatedRequest(requestText);
|
|
934
|
+
}
|
|
935
|
+
catch (error) {
|
|
936
|
+
const output = error instanceof Error ? error.message : String(error);
|
|
937
|
+
return {
|
|
938
|
+
toolOutput: output,
|
|
939
|
+
delegatedSubagentType: subagentType,
|
|
940
|
+
delegatedResult: {
|
|
941
|
+
sessionId,
|
|
942
|
+
requestId,
|
|
943
|
+
agentId: selectedBinding.agent.id,
|
|
944
|
+
state: "failed",
|
|
945
|
+
output,
|
|
946
|
+
finalMessageText: output,
|
|
947
|
+
},
|
|
948
|
+
};
|
|
949
|
+
}
|
|
869
950
|
const targetRequiresExecutionToolEvidence = getBindingPrimaryTools(selectedBinding).length > 0;
|
|
870
951
|
if (targetRequiresExecutionToolEvidence && !hasDelegatedExecutionToolEvidence(delegatedResult)) {
|
|
871
|
-
|
|
952
|
+
try {
|
|
953
|
+
delegatedResult = await runDelegatedRequest([requestText, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION].filter(Boolean).join("\n\n"), ":tool-evidence-retry");
|
|
954
|
+
}
|
|
955
|
+
catch (error) {
|
|
956
|
+
const output = error instanceof Error ? error.message : String(error);
|
|
957
|
+
return {
|
|
958
|
+
toolOutput: output,
|
|
959
|
+
delegatedSubagentType: subagentType,
|
|
960
|
+
delegatedResult: {
|
|
961
|
+
...delegatedResult,
|
|
962
|
+
state: "failed",
|
|
963
|
+
output,
|
|
964
|
+
finalMessageText: output,
|
|
965
|
+
},
|
|
966
|
+
};
|
|
967
|
+
}
|
|
872
968
|
}
|
|
873
969
|
if (targetRequiresExecutionToolEvidence && !hasDelegatedExecutionToolEvidence(delegatedResult)) {
|
|
874
970
|
const output = `runtime_error=Delegated agent ${selectedBinding.agent.id} completed without tool execution evidence.`;
|
|
875
971
|
return {
|
|
876
972
|
toolOutput: output,
|
|
973
|
+
delegatedSubagentType: subagentType,
|
|
877
974
|
delegatedResult: {
|
|
878
975
|
...delegatedResult,
|
|
879
976
|
state: "failed",
|
|
@@ -888,6 +985,7 @@ export class AgentRuntimeAdapter {
|
|
|
888
985
|
const output = "runtime_error=Delegated agent ended before producing required plan evidence.";
|
|
889
986
|
return {
|
|
890
987
|
toolOutput: output,
|
|
988
|
+
delegatedSubagentType: subagentType,
|
|
891
989
|
delegatedResult: {
|
|
892
990
|
...delegatedResult,
|
|
893
991
|
state: "failed",
|
|
@@ -896,7 +994,48 @@ export class AgentRuntimeAdapter {
|
|
|
896
994
|
},
|
|
897
995
|
};
|
|
898
996
|
}
|
|
899
|
-
return {
|
|
997
|
+
return {
|
|
998
|
+
toolOutput: resolveDelegatedResultOutput(delegatedResult),
|
|
999
|
+
delegatedSubagentType: subagentType,
|
|
1000
|
+
delegatedResult,
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
buildCompactDelegationReport(compactDelegation) {
|
|
1004
|
+
const delegatedSubagentType = compactDelegation.delegatedSubagentType ?? "unknown";
|
|
1005
|
+
const delegatedOutput = typeof compactDelegation.toolOutput === "string"
|
|
1006
|
+
? [compactDelegation.toolOutput]
|
|
1007
|
+
: [];
|
|
1008
|
+
const delegatedToolNames = Array.isArray(compactDelegation.delegatedResult?.metadata?.executedToolResults)
|
|
1009
|
+
? compactDelegation.delegatedResult.metadata.executedToolResults
|
|
1010
|
+
.filter((toolResult) => toolResult?.toolName)
|
|
1011
|
+
.map((toolResult) => toolResult.toolName)
|
|
1012
|
+
: [];
|
|
1013
|
+
const state = compactDelegation.delegatedResult?.state === "failed" ? "failed" : "completed";
|
|
1014
|
+
return {
|
|
1015
|
+
status: state,
|
|
1016
|
+
routing: [
|
|
1017
|
+
`1) 路由判断: 已选择 sub-agent = ${delegatedSubagentType}(基于请求语义)。`,
|
|
1018
|
+
],
|
|
1019
|
+
plan: [
|
|
1020
|
+
"1) 选择具备匹配能力的子代理并创建委托任务。",
|
|
1021
|
+
"2) 执行子代理的原生工作流并收集委托工具输出。",
|
|
1022
|
+
"3) 合成汇总报告并返回给用户。",
|
|
1023
|
+
],
|
|
1024
|
+
execution: [
|
|
1025
|
+
`1) 调用 task 工具,目标子代理:${delegatedSubagentType}`,
|
|
1026
|
+
delegatedToolNames.length > 0
|
|
1027
|
+
? `2) 子代理返回工具证据:${[...new Set(delegatedToolNames)].join(", ")}`
|
|
1028
|
+
: "2) 子代理返回文本结果。",
|
|
1029
|
+
"3) 产出主编排汇总并返回结构化结果。",
|
|
1030
|
+
],
|
|
1031
|
+
summary: [
|
|
1032
|
+
`已完成子代理 ${delegatedSubagentType} 委托执行。`,
|
|
1033
|
+
],
|
|
1034
|
+
findings: delegatedOutput.length > 0 ? delegatedOutput.slice(0, 3) : ["none"],
|
|
1035
|
+
blockers: state === "failed" ? ["子代理执行未能完成。"] : ["none"],
|
|
1036
|
+
nextActions: ["如需更深入,可继续追问该次委托的细节。"],
|
|
1037
|
+
report: delegatedOutput.join("\n") || "委托已完成,未返回附加报告。",
|
|
1038
|
+
};
|
|
900
1039
|
}
|
|
901
1040
|
async *stream(binding, input, sessionId, history = [], options = {}) {
|
|
902
1041
|
const directListing = await this.tryHandleDirectWorkspaceListing(binding, input, {
|
|
@@ -916,12 +1055,19 @@ export class AgentRuntimeAdapter {
|
|
|
916
1055
|
};
|
|
917
1056
|
return;
|
|
918
1057
|
}
|
|
1058
|
+
if (isDelegationOnlyDeepAgentBinding(binding)) {
|
|
1059
|
+
yield {
|
|
1060
|
+
kind: "commentary",
|
|
1061
|
+
content: "Selecting a specialist for delegated execution.",
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
919
1064
|
const compactDelegation = await this.tryDelegateWithCompactRouter(binding, input, sessionId, options.requestId ?? sessionId, {
|
|
920
1065
|
...options,
|
|
921
1066
|
sessionId,
|
|
922
1067
|
requestId: options.requestId,
|
|
923
1068
|
});
|
|
924
1069
|
if (compactDelegation) {
|
|
1070
|
+
const compactReport = this.buildCompactDelegationReport(compactDelegation);
|
|
925
1071
|
yield {
|
|
926
1072
|
kind: "tool-result",
|
|
927
1073
|
toolName: "task",
|
|
@@ -929,9 +1075,9 @@ export class AgentRuntimeAdapter {
|
|
|
929
1075
|
};
|
|
930
1076
|
yield {
|
|
931
1077
|
kind: "content",
|
|
932
|
-
content:
|
|
1078
|
+
content: JSON.stringify(compactDelegation.delegatedSubagentType === null
|
|
933
1079
|
? compactDelegation.toolOutput
|
|
934
|
-
:
|
|
1080
|
+
: compactReport),
|
|
935
1081
|
};
|
|
936
1082
|
return;
|
|
937
1083
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createFallbackRequestResultFromLatestEvent, mergeRequestResultOutput } from "../run/helpers.js";
|
|
2
|
-
import { applyRequestStreamItemToSnapshot, createInitialRequestEventSnapshot,
|
|
2
|
+
import { applyRequestStreamItemToSnapshot, createInitialRequestEventSnapshot, toRequestDataEvents, } from "../../../projections/request-events.js";
|
|
3
3
|
export async function emitOutputDeltaAndCreateItem(emit, sessionId, requestId, agentId, content) {
|
|
4
4
|
await emit(sessionId, requestId, 3, "output.delta", {
|
|
5
5
|
content,
|
|
@@ -71,8 +71,7 @@ export async function dispatchRequestListeners(stream, listeners, options) {
|
|
|
71
71
|
else if (item.type === "content") {
|
|
72
72
|
output += item.content;
|
|
73
73
|
}
|
|
74
|
-
const dataEvent
|
|
75
|
-
if (dataEvent) {
|
|
74
|
+
for (const dataEvent of toRequestDataEvents(item)) {
|
|
76
75
|
await notifyIfPresent(listeners.dataListener, dataEvent);
|
|
77
76
|
}
|
|
78
77
|
await notifyIfPresent(listeners.eventListener, snapshot);
|
|
@@ -5,7 +5,7 @@ import { compileModel, compileTool } from "./resource-compilers.js";
|
|
|
5
5
|
import { inferAgentCapabilities } from "./support/agent-capabilities.js";
|
|
6
6
|
import { getAgentExecutionConfigValue, getAgentExecutionObject, getAgentExecutionString } from "./support/agent-execution-config.js";
|
|
7
7
|
import { discoverSkillPaths } from "./support/discovery.js";
|
|
8
|
-
import { compileAgentMemories, getProceduralMemoryDefaults, getResilienceConfig, getRuntimeDefaults, getRuntimeMemoryDefaults, getRuntimeStorageRoots, getWorkspaceObject, resolvePromptValue, resolveRefId, } from "./support/workspace-ref-utils.js";
|
|
8
|
+
import { compileAgentMemories, getProceduralMemoryDefaults, getResilienceConfig, getRuntimeAgentDefaults, getRuntimeDefaults, getRuntimeMemoryDefaults, getRuntimeStorageRoots, getWorkspaceObject, resolvePromptValue, resolveRefId, } from "./support/workspace-ref-utils.js";
|
|
9
9
|
import { WORKSPACE_BOUNDARY_GUIDANCE } from "../runtime/prompts/runtime-prompts.js";
|
|
10
10
|
function requireSkills(pathEntries, workspaceRoot) {
|
|
11
11
|
return Array.from(new Set(discoverSkillPaths(pathEntries, workspaceRoot)));
|
|
@@ -166,8 +166,8 @@ export function requireTools(tools, bindings, ownerId) {
|
|
|
166
166
|
}
|
|
167
167
|
return Array.from(deduped.values());
|
|
168
168
|
}
|
|
169
|
-
function buildSubagent(agent, workspaceRoot, models, tools, parentSkills, parentModel) {
|
|
170
|
-
const execution = compileExecutionCore(agent, workspaceRoot, models, tools);
|
|
169
|
+
function buildSubagent(agent, workspaceRoot, refs, models, tools, parentSkills, parentModel) {
|
|
170
|
+
const execution = compileExecutionCore(agent, workspaceRoot, refs, models, tools);
|
|
171
171
|
return {
|
|
172
172
|
agentId: agent.id,
|
|
173
173
|
name: resolveAgentRuntimeName(agent),
|
|
@@ -196,6 +196,84 @@ function resolveInterruptOn(agent) {
|
|
|
196
196
|
function resolveResponseFormat(agent) {
|
|
197
197
|
return getAgentExecutionConfigValue(agent, "responseFormat");
|
|
198
198
|
}
|
|
199
|
+
function normalizeResponseFormatRef(ref) {
|
|
200
|
+
return ref.startsWith("response-format/") ? ref : `response-format/${ref}`;
|
|
201
|
+
}
|
|
202
|
+
function resolveResponseFormatObject(refs, ref, ownerLabel) {
|
|
203
|
+
if (!ref) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
const object = getWorkspaceObject(refs, normalizeResponseFormatRef(ref));
|
|
207
|
+
if (!object) {
|
|
208
|
+
throw new Error(`${ownerLabel} responseFormatRef references missing object ${ref}`);
|
|
209
|
+
}
|
|
210
|
+
if (object.kind !== "response-format") {
|
|
211
|
+
throw new Error(`${ownerLabel} responseFormatRef references ${ref}, but expected response-format`);
|
|
212
|
+
}
|
|
213
|
+
if (!("format" in object.value)) {
|
|
214
|
+
throw new Error(`${ownerLabel} responseFormatRef ${ref} must define format`);
|
|
215
|
+
}
|
|
216
|
+
return object.value.format;
|
|
217
|
+
}
|
|
218
|
+
function mergeResponseFormats(base, override) {
|
|
219
|
+
if (override === undefined) {
|
|
220
|
+
return base;
|
|
221
|
+
}
|
|
222
|
+
if (typeof base === "object" &&
|
|
223
|
+
base &&
|
|
224
|
+
typeof override === "object" &&
|
|
225
|
+
override &&
|
|
226
|
+
!Array.isArray(base) &&
|
|
227
|
+
!Array.isArray(override)) {
|
|
228
|
+
const merged = { ...base };
|
|
229
|
+
for (const [key, value] of Object.entries(override)) {
|
|
230
|
+
if (key === "required" && Array.isArray(merged.required) && Array.isArray(value)) {
|
|
231
|
+
merged.required = Array.from(new Set([...merged.required, ...value]));
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (key === "properties" &&
|
|
235
|
+
typeof merged.properties === "object" &&
|
|
236
|
+
merged.properties &&
|
|
237
|
+
!Array.isArray(merged.properties) &&
|
|
238
|
+
typeof value === "object" &&
|
|
239
|
+
value &&
|
|
240
|
+
!Array.isArray(value)) {
|
|
241
|
+
merged.properties = {
|
|
242
|
+
...merged.properties,
|
|
243
|
+
...value,
|
|
244
|
+
};
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
merged[key] = key in merged ? mergeResponseFormats(merged[key], value) : value;
|
|
248
|
+
}
|
|
249
|
+
return merged;
|
|
250
|
+
}
|
|
251
|
+
return override;
|
|
252
|
+
}
|
|
253
|
+
function resolveInheritedResponseFormat(agent, refs) {
|
|
254
|
+
const defaults = getRuntimeAgentDefaults(refs);
|
|
255
|
+
if (defaults && "responseFormat" in defaults) {
|
|
256
|
+
return defaults.responseFormat === null ? undefined : defaults.responseFormat;
|
|
257
|
+
}
|
|
258
|
+
const defaultRef = typeof defaults?.responseFormatRef === "string" ? defaults.responseFormatRef.trim() : "";
|
|
259
|
+
if (defaultRef) {
|
|
260
|
+
return resolveResponseFormatObject(refs, defaultRef, "Runtime defaults.agent.config");
|
|
261
|
+
}
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
function resolveEffectiveResponseFormat(agent, refs) {
|
|
265
|
+
const explicitResponseFormat = resolveResponseFormat(agent);
|
|
266
|
+
if (explicitResponseFormat !== undefined) {
|
|
267
|
+
return explicitResponseFormat === null
|
|
268
|
+
? undefined
|
|
269
|
+
: mergeResponseFormats(resolveInheritedResponseFormat(agent, refs), explicitResponseFormat);
|
|
270
|
+
}
|
|
271
|
+
const explicitRef = getAgentExecutionConfigValue(agent, "responseFormatRef");
|
|
272
|
+
if (typeof explicitRef === "string" && explicitRef.trim().length > 0) {
|
|
273
|
+
return resolveResponseFormatObject(refs, explicitRef.trim(), `Agent ${agent.id}`);
|
|
274
|
+
}
|
|
275
|
+
return resolveInheritedResponseFormat(agent, refs);
|
|
276
|
+
}
|
|
199
277
|
function resolveContextSchema(agent) {
|
|
200
278
|
return getAgentExecutionConfigValue(agent, "contextSchema");
|
|
201
279
|
}
|
|
@@ -216,13 +294,13 @@ function resolvePassthrough(agent) {
|
|
|
216
294
|
const passthrough = getAgentExecutionObject(agent, "passthrough");
|
|
217
295
|
return passthrough ? { ...passthrough } : undefined;
|
|
218
296
|
}
|
|
219
|
-
function compileSubagents(agent, agents, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel) {
|
|
297
|
+
function compileSubagents(agent, agents, workspaceRoot, refs, models, tools, compiledAgentSkills, compiledAgentModel) {
|
|
220
298
|
return agent.subagentRefs.map((ref) => {
|
|
221
299
|
const subagent = agents.get(resolveRefId(ref));
|
|
222
300
|
if (!subagent) {
|
|
223
301
|
throw new Error(`Missing subagent ${ref} for agent ${agent.id}`);
|
|
224
302
|
}
|
|
225
|
-
return buildSubagent(subagent, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel);
|
|
303
|
+
return buildSubagent(subagent, workspaceRoot, refs, models, tools, compiledAgentSkills, compiledAgentModel);
|
|
226
304
|
});
|
|
227
305
|
}
|
|
228
306
|
function compileAsyncSubagents(agent) {
|
|
@@ -234,18 +312,18 @@ function compileAsyncSubagents(agent) {
|
|
|
234
312
|
...(subagent.headers ? { headers: { ...subagent.headers } } : {}),
|
|
235
313
|
}));
|
|
236
314
|
}
|
|
237
|
-
function compileDeepAgentSubagents(agent, agents, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel) {
|
|
315
|
+
function compileDeepAgentSubagents(agent, agents, workspaceRoot, refs, models, tools, compiledAgentSkills, compiledAgentModel) {
|
|
238
316
|
return [
|
|
239
|
-
...compileSubagents(agent, agents, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel),
|
|
317
|
+
...compileSubagents(agent, agents, workspaceRoot, refs, models, tools, compiledAgentSkills, compiledAgentModel),
|
|
240
318
|
...compileAsyncSubagents(agent),
|
|
241
319
|
];
|
|
242
320
|
}
|
|
243
|
-
function compileExecutionCore(agent, workspaceRoot, models, tools) {
|
|
321
|
+
function compileExecutionCore(agent, workspaceRoot, refs, models, tools) {
|
|
244
322
|
return {
|
|
245
323
|
model: requireModel(models, agent.modelRef, agent.id),
|
|
246
324
|
tools: requireTools(tools, getAgentToolBindings(agent), agent.id),
|
|
247
325
|
systemPrompt: resolveSystemPrompt(agent, workspaceRoot),
|
|
248
|
-
responseFormat:
|
|
326
|
+
responseFormat: resolveEffectiveResponseFormat(agent, refs),
|
|
249
327
|
contextSchema: resolveContextSchema(agent),
|
|
250
328
|
middleware: resolveCompiledMiddleware(agent, models),
|
|
251
329
|
};
|
|
@@ -395,7 +473,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
395
473
|
const executionCore = compileExecutionCore({
|
|
396
474
|
...agent,
|
|
397
475
|
modelRef: agent.modelRef || (internalSubagent ? "model/default" : ""),
|
|
398
|
-
}, workspaceRoot, models, tools);
|
|
476
|
+
}, workspaceRoot, refs, models, tools);
|
|
399
477
|
const passthrough = resolvePassthrough(agent);
|
|
400
478
|
const compiledAgentModel = executionCore.model;
|
|
401
479
|
const backend = resolveBackendConfig(agent, refs);
|
|
@@ -442,7 +520,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
442
520
|
passthrough,
|
|
443
521
|
interruptOn: resolveInterruptOn(agent),
|
|
444
522
|
filesystem: compiledFilesystemConfig,
|
|
445
|
-
subagents: compileSubagents(agent, agents, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel),
|
|
523
|
+
subagents: compileSubagents(agent, agents, workspaceRoot, refs, models, tools, compiledAgentSkills, compiledAgentModel),
|
|
446
524
|
memory: compiledAgentMemory,
|
|
447
525
|
skills: compiledAgentSkills,
|
|
448
526
|
generalPurposeAgent: getAgentExecutionConfigValue(agent, "generalPurposeAgent", { executionMode: "langchain-v1" }),
|
|
@@ -491,7 +569,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
491
569
|
responseFormat: executionCore.responseFormat,
|
|
492
570
|
contextSchema: executionCore.contextSchema,
|
|
493
571
|
middleware: executionCore.middleware,
|
|
494
|
-
subagents: compileDeepAgentSubagents(agent, agents, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel),
|
|
572
|
+
subagents: compileDeepAgentSubagents(agent, agents, workspaceRoot, refs, models, tools, compiledAgentSkills, compiledAgentModel),
|
|
495
573
|
interruptOn: resolveInterruptOn(agent),
|
|
496
574
|
...(backend ? { backend: backend.config } : {}),
|
|
497
575
|
...(store ? { store: store.config } : {}),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ParsedAgentObject, ParsedToolObject } from "../contracts/types.js";
|
|
1
|
+
import type { ParsedAgentObject, ParsedToolObject, WorkspaceObject } from "../contracts/types.js";
|
|
2
2
|
export type FrameworkContractValidationMode = "off" | "warn" | "error";
|
|
3
3
|
export declare function resolveFrameworkContractValidationMode(mode: FrameworkContractValidationMode | undefined): FrameworkContractValidationMode;
|
|
4
4
|
export declare function validateFrameworkContracts(input: {
|
|
@@ -6,5 +6,6 @@ export declare function validateFrameworkContracts(input: {
|
|
|
6
6
|
tools: Map<string, ParsedToolObject>;
|
|
7
7
|
skillRegistry: Map<string, string>;
|
|
8
8
|
ownedRoots: string[];
|
|
9
|
+
refs?: Map<string, WorkspaceObject | ParsedAgentObject>;
|
|
9
10
|
mode?: FrameworkContractValidationMode;
|
|
10
11
|
}): void;
|