@botbotgo/agent-harness 0.0.95 → 0.0.96
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 +1 -114
- package/README.zh.md +1 -70
- package/dist/config/workflows/langgraph-workflows.yaml +363 -111
- package/dist/config/workflows/runtime-profiles.yaml +94 -0
- package/dist/contracts/types.d.ts +84 -2
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/agent-runtime-adapter.js +9 -8
- package/dist/runtime/harness.d.ts +1 -0
- package/dist/runtime/harness.js +33 -2
- package/dist/runtime/langgraph-presets.js +63 -63
- package/dist/runtime/langgraph-profiles.js +71 -71
- package/dist/runtime/parsing/stream-event-parsing.d.ts +6 -0
- package/dist/runtime/parsing/stream-event-parsing.js +231 -0
- package/dist/runtime/support/harness-support.js +14 -3
- package/dist/workspace/agent-binding-compiler.js +39 -3
- package/dist/workspace/object-loader.js +5 -1
- package/package.json +1 -1
|
@@ -28,28 +28,28 @@ function buildCodingRuntimeWorkflow(options) {
|
|
|
28
28
|
const verifierAgent = readStringOption(options, "verifierAgent");
|
|
29
29
|
const needsVerification = Boolean(verifierAgent) || options.runIntegrationVerification === true;
|
|
30
30
|
return {
|
|
31
|
-
entryNode: "
|
|
31
|
+
entryNode: "step1",
|
|
32
32
|
nodes: [
|
|
33
|
-
{ id: "
|
|
34
|
-
{ id: "
|
|
35
|
-
{ id: "
|
|
36
|
-
{ id: "
|
|
33
|
+
{ id: "step1", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
34
|
+
{ id: "step2", kind: "agent", agent: coderAgent },
|
|
35
|
+
{ id: "step3", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
|
|
36
|
+
{ id: "step4", kind: "llm", role: "replanner", prompt: DEFAULT_REPLANNER_PROMPT },
|
|
37
37
|
...(needsVerification
|
|
38
|
-
? [{ id: "
|
|
38
|
+
? [{ id: "step5", kind: "approval" }, { id: "step6", kind: "agent", agent: verifierAgent ?? coderAgent }]
|
|
39
39
|
: []),
|
|
40
|
-
{ id: "
|
|
40
|
+
{ id: "step7", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
41
41
|
],
|
|
42
42
|
edges: [
|
|
43
|
-
{ from: "
|
|
44
|
-
{ from: "
|
|
45
|
-
{ from: "
|
|
46
|
-
{ from: "
|
|
47
|
-
{ from: "
|
|
43
|
+
{ from: "step1", to: "step2" },
|
|
44
|
+
{ from: "step2", to: "step3", when: "has_result" },
|
|
45
|
+
{ from: "step3", to: needsVerification ? "step5" : "step7", when: "review_ok" },
|
|
46
|
+
{ from: "step3", to: "step4", when: "review_incomplete" },
|
|
47
|
+
{ from: "step4", to: "step2", when: "has_plan" },
|
|
48
48
|
...(needsVerification
|
|
49
49
|
? [
|
|
50
|
-
{ from: "
|
|
51
|
-
{ from: "
|
|
52
|
-
{ from: "
|
|
50
|
+
{ from: "step5", to: "step6", when: "approval_approved" },
|
|
51
|
+
{ from: "step5", to: "step6", when: "approval_edited" },
|
|
52
|
+
{ from: "step6", to: "step7", when: "has_result" },
|
|
53
53
|
]
|
|
54
54
|
: []),
|
|
55
55
|
],
|
|
@@ -61,21 +61,21 @@ function buildAssistantWorkflow(options) {
|
|
|
61
61
|
readStringOption(options, "defaultWritingAgent") ??
|
|
62
62
|
readStringOption(options, "defaultSchedulingAgent");
|
|
63
63
|
return {
|
|
64
|
-
entryNode: "
|
|
64
|
+
entryNode: "step1",
|
|
65
65
|
nodes: [
|
|
66
|
-
{ id: "
|
|
67
|
-
...(worker ? [{ id: "
|
|
68
|
-
{ id: "
|
|
69
|
-
{ id: "
|
|
70
|
-
{ id: "
|
|
66
|
+
{ id: "step1", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
67
|
+
...(worker ? [{ id: "step2", kind: "agent", agent: worker }] : [{ id: "step2", kind: "tool", tool: "repo_inventory" }]),
|
|
68
|
+
{ id: "step3", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
|
|
69
|
+
{ id: "step4", kind: "approval" },
|
|
70
|
+
{ id: "step5", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
71
71
|
],
|
|
72
72
|
edges: [
|
|
73
|
-
{ from: "
|
|
74
|
-
{ from:
|
|
75
|
-
{ from: "
|
|
76
|
-
{ from: "
|
|
77
|
-
{ from: "
|
|
78
|
-
{ from: "
|
|
73
|
+
{ from: "step1", to: "step2" },
|
|
74
|
+
{ from: "step2", to: "step3", when: "has_result" },
|
|
75
|
+
{ from: "step3", to: "step4", when: "review_incomplete" },
|
|
76
|
+
{ from: "step3", to: "step5", when: "review_ok" },
|
|
77
|
+
{ from: "step4", to: "step5", when: "approval_approved" },
|
|
78
|
+
{ from: "step4", to: "step5", when: "approval_edited" },
|
|
79
79
|
],
|
|
80
80
|
};
|
|
81
81
|
}
|
|
@@ -84,22 +84,22 @@ function buildResearchWorkflow(options) {
|
|
|
84
84
|
const analystAgent = requireAgentOption("research-runtime", options, "analystAgent");
|
|
85
85
|
const synthesizerAgent = readStringOption(options, "synthesizerAgent");
|
|
86
86
|
return {
|
|
87
|
-
entryNode: "
|
|
87
|
+
entryNode: "step1",
|
|
88
88
|
nodes: [
|
|
89
|
-
{ id: "
|
|
90
|
-
{ id: "
|
|
91
|
-
{ id: "
|
|
92
|
-
{ id: "
|
|
93
|
-
...(synthesizerAgent ? [{ id: "
|
|
94
|
-
{ id: "
|
|
89
|
+
{ id: "step1", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
90
|
+
{ id: "step2", kind: "agent", agent: gathererAgent },
|
|
91
|
+
{ id: "step3", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
|
|
92
|
+
{ id: "step4", kind: "agent", agent: analystAgent },
|
|
93
|
+
...(synthesizerAgent ? [{ id: "step5", kind: "agent", agent: synthesizerAgent }] : []),
|
|
94
|
+
{ id: "step6", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
95
95
|
],
|
|
96
96
|
edges: [
|
|
97
|
-
{ from: "
|
|
98
|
-
{ from: "
|
|
99
|
-
{ from: "
|
|
100
|
-
{ from: "
|
|
101
|
-
{ from: "
|
|
102
|
-
...(synthesizerAgent ? [{ from: "
|
|
97
|
+
{ from: "step1", to: "step2" },
|
|
98
|
+
{ from: "step2", to: "step3", when: "has_result" },
|
|
99
|
+
{ from: "step3", to: "step4", when: "review_ok" },
|
|
100
|
+
{ from: "step3", to: "step2", when: "review_incomplete" },
|
|
101
|
+
{ from: "step4", to: synthesizerAgent ? "step5" : "step6", when: "has_result" },
|
|
102
|
+
...(synthesizerAgent ? [{ from: "step5", to: "step6", when: "has_result" }] : []),
|
|
103
103
|
],
|
|
104
104
|
};
|
|
105
105
|
}
|
|
@@ -107,20 +107,20 @@ function buildApprovalReviewWorkflow(options) {
|
|
|
107
107
|
const preparerAgent = requireAgentOption("approval-review-runtime", options, "preparerAgent");
|
|
108
108
|
const reviewerAgent = readStringOption(options, "reviewerAgent");
|
|
109
109
|
return {
|
|
110
|
-
entryNode: "
|
|
110
|
+
entryNode: "step1",
|
|
111
111
|
nodes: [
|
|
112
|
-
{ id: "
|
|
113
|
-
{ id: "
|
|
114
|
-
...(reviewerAgent ? [{ id: "
|
|
115
|
-
{ id: "
|
|
116
|
-
{ id: "
|
|
112
|
+
{ id: "step1", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
113
|
+
{ id: "step2", kind: "agent", agent: preparerAgent },
|
|
114
|
+
...(reviewerAgent ? [{ id: "step3", kind: "agent", agent: reviewerAgent }] : [{ id: "step3", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT }]),
|
|
115
|
+
{ id: "step4", kind: "approval" },
|
|
116
|
+
{ id: "step5", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
117
117
|
],
|
|
118
118
|
edges: [
|
|
119
|
-
{ from: "
|
|
120
|
-
{ from: "
|
|
121
|
-
{ from:
|
|
122
|
-
{ from: "
|
|
123
|
-
{ from: "
|
|
119
|
+
{ from: "step1", to: "step2" },
|
|
120
|
+
{ from: "step2", to: "step3", when: "has_result" },
|
|
121
|
+
{ from: "step3", to: "step4", when: "has_result" },
|
|
122
|
+
{ from: "step4", to: "step5", when: "approval_approved" },
|
|
123
|
+
{ from: "step4", to: "step5", when: "approval_edited" },
|
|
124
124
|
],
|
|
125
125
|
};
|
|
126
126
|
}
|
|
@@ -133,30 +133,30 @@ function buildChatOperatorWorkflow(options) {
|
|
|
133
133
|
throw new Error("LangGraph profile chat-operator requires at least one target agent in with.assistantAgent, with.researchAgent, with.codingAgent, or with.approvalAgent");
|
|
134
134
|
}
|
|
135
135
|
return {
|
|
136
|
-
entryNode: "
|
|
136
|
+
entryNode: "step1",
|
|
137
137
|
nodes: [
|
|
138
|
-
{ id: "
|
|
139
|
-
{ id: "
|
|
140
|
-
{ id: "
|
|
138
|
+
{ id: "step1", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
139
|
+
{ id: "step2", kind: "agent", agent: routedAgent },
|
|
140
|
+
{ id: "step3", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
141
141
|
],
|
|
142
142
|
edges: [
|
|
143
|
-
{ from: "
|
|
144
|
-
{ from: "
|
|
143
|
+
{ from: "step1", to: "step2" },
|
|
144
|
+
{ from: "step2", to: "step3", when: "has_result" },
|
|
145
145
|
],
|
|
146
146
|
};
|
|
147
147
|
}
|
|
148
148
|
function buildCopilotSidecarWorkflow(options) {
|
|
149
149
|
const coderAgent = requireAgentOption("copilot-sidecar", options, "coderAgent");
|
|
150
150
|
return {
|
|
151
|
-
entryNode: "
|
|
151
|
+
entryNode: "step1",
|
|
152
152
|
nodes: [
|
|
153
|
-
{ id: "
|
|
154
|
-
{ id: "
|
|
155
|
-
{ id: "
|
|
153
|
+
{ id: "step1", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
154
|
+
{ id: "step2", kind: "agent", agent: coderAgent },
|
|
155
|
+
{ id: "step3", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
156
156
|
],
|
|
157
157
|
edges: [
|
|
158
|
-
{ from: "
|
|
159
|
-
{ from: "
|
|
158
|
+
{ from: "step1", to: "step2" },
|
|
159
|
+
{ from: "step2", to: "step3", when: "has_result" },
|
|
160
160
|
],
|
|
161
161
|
};
|
|
162
162
|
}
|
|
@@ -166,17 +166,17 @@ function buildDelegationHubWorkflow(options) {
|
|
|
166
166
|
throw new Error("LangGraph profile task-delegation-hub requires with.defaultWorkerFallback");
|
|
167
167
|
}
|
|
168
168
|
return {
|
|
169
|
-
entryNode: "
|
|
169
|
+
entryNode: "step1",
|
|
170
170
|
nodes: [
|
|
171
|
-
{ id: "
|
|
172
|
-
{ id: "
|
|
173
|
-
{ id: "
|
|
174
|
-
{ id: "
|
|
171
|
+
{ id: "step1", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
172
|
+
{ id: "step2", kind: "agent", agent: workerAgent },
|
|
173
|
+
{ id: "step3", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
|
|
174
|
+
{ id: "step4", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
175
175
|
],
|
|
176
176
|
edges: [
|
|
177
|
-
{ from: "
|
|
178
|
-
{ from: "
|
|
179
|
-
{ from: "
|
|
177
|
+
{ from: "step1", to: "step2" },
|
|
178
|
+
{ from: "step2", to: "step3", when: "has_result" },
|
|
179
|
+
{ from: "step3", to: "step4", when: "review_ok" },
|
|
180
180
|
],
|
|
181
181
|
};
|
|
182
182
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import type { CompatibleStreamPart, UpstreamRuntimeEvent } from "../../contracts/types.js";
|
|
1
2
|
export type RuntimeStreamChunk = {
|
|
3
|
+
kind: "upstream-event";
|
|
4
|
+
event: UpstreamRuntimeEvent;
|
|
5
|
+
} | {
|
|
2
6
|
kind: "content";
|
|
3
7
|
content: string;
|
|
4
8
|
} | {
|
|
@@ -16,6 +20,8 @@ export type RuntimeStreamChunk = {
|
|
|
16
20
|
output: unknown;
|
|
17
21
|
isError?: boolean;
|
|
18
22
|
};
|
|
23
|
+
export declare function normalizeUpstreamRuntimeEvent(event: unknown): UpstreamRuntimeEvent;
|
|
24
|
+
export declare function extractCustomCompatibleStreamPart(event: unknown): CompatibleStreamPart | null;
|
|
19
25
|
export declare function extractTerminalStreamOutput(event: unknown): string;
|
|
20
26
|
export declare function extractReasoningStreamOutput(event: unknown): string;
|
|
21
27
|
export declare function extractVisibleStreamOutput(event: unknown): string;
|
|
@@ -1,4 +1,235 @@
|
|
|
1
1
|
import { extractReasoningText, extractVisibleOutput, hasToolCalls, readTextContent } from "./output-parsing.js";
|
|
2
|
+
function asObject(value) {
|
|
3
|
+
return typeof value === "object" && value !== null ? value : undefined;
|
|
4
|
+
}
|
|
5
|
+
function extractCustomStreamData(event) {
|
|
6
|
+
const typed = asObject(event);
|
|
7
|
+
if (!typed) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const eventName = typeof typed.event === "string" ? typed.event : "";
|
|
11
|
+
const ns = Array.isArray(typed.ns) ? typed.ns.filter((item) => typeof item === "string") : undefined;
|
|
12
|
+
const data = asObject(typed.data);
|
|
13
|
+
if (eventName === "on_custom_event") {
|
|
14
|
+
return {
|
|
15
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
16
|
+
data: typed.data,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (eventName === "on_chain_stream" && data && "custom" in data) {
|
|
20
|
+
return {
|
|
21
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
22
|
+
data: data.custom,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
export function normalizeUpstreamRuntimeEvent(event) {
|
|
28
|
+
const typed = asObject(event);
|
|
29
|
+
const tags = Array.isArray(typed?.tags) ? typed.tags.filter((item) => typeof item === "string") : undefined;
|
|
30
|
+
const ns = Array.isArray(typed?.ns) ? typed.ns.filter((item) => typeof item === "string") : undefined;
|
|
31
|
+
const name = typeof typed?.name === "string" ? typed.name : undefined;
|
|
32
|
+
const eventName = typeof typed?.event === "string" ? typed.event : undefined;
|
|
33
|
+
const runType = typeof typed?.run_type === "string" ? typed.run_type : undefined;
|
|
34
|
+
const data = asObject(typed?.data);
|
|
35
|
+
const metadata = asObject(typed?.metadata);
|
|
36
|
+
const normalized = normalizeUpstreamEventShape({
|
|
37
|
+
raw: event,
|
|
38
|
+
event: eventName,
|
|
39
|
+
name,
|
|
40
|
+
runType,
|
|
41
|
+
metadata,
|
|
42
|
+
tags,
|
|
43
|
+
data,
|
|
44
|
+
ns,
|
|
45
|
+
});
|
|
46
|
+
const streamPart = normalizeCompatibleStreamPart({
|
|
47
|
+
raw: event,
|
|
48
|
+
event: eventName,
|
|
49
|
+
name,
|
|
50
|
+
runType,
|
|
51
|
+
metadata,
|
|
52
|
+
tags,
|
|
53
|
+
data,
|
|
54
|
+
ns,
|
|
55
|
+
normalized,
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
format: "langgraph-v2",
|
|
59
|
+
normalized,
|
|
60
|
+
raw: event,
|
|
61
|
+
event: eventName,
|
|
62
|
+
name,
|
|
63
|
+
runType,
|
|
64
|
+
data,
|
|
65
|
+
metadata,
|
|
66
|
+
...(tags && tags.length > 0 ? { tags } : {}),
|
|
67
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
68
|
+
streamPart,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function normalizeUpstreamEventShape(event) {
|
|
72
|
+
const nodeName = event.name;
|
|
73
|
+
const ns = event.ns;
|
|
74
|
+
const interruptPayload = extractInterruptPayload(event.raw);
|
|
75
|
+
if (interruptPayload) {
|
|
76
|
+
return {
|
|
77
|
+
kind: "interrupt",
|
|
78
|
+
interrupt: parseMaybeJson(interruptPayload),
|
|
79
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
80
|
+
...(nodeName ? { nodeName } : {}),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const reasoning = extractReasoningStreamOutput(event.raw);
|
|
84
|
+
if (reasoning) {
|
|
85
|
+
return {
|
|
86
|
+
kind: "reasoning-delta",
|
|
87
|
+
text: reasoning,
|
|
88
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
89
|
+
...(nodeName ? { nodeName } : {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const visibleText = extractVisibleStreamOutput(event.raw);
|
|
93
|
+
if (visibleText) {
|
|
94
|
+
return {
|
|
95
|
+
kind: "text-delta",
|
|
96
|
+
source: "model",
|
|
97
|
+
text: visibleText,
|
|
98
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
99
|
+
...(nodeName ? { nodeName } : {}),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const stateText = extractStateStreamOutput(event.raw);
|
|
103
|
+
if (stateText) {
|
|
104
|
+
return {
|
|
105
|
+
kind: "text-delta",
|
|
106
|
+
source: "state",
|
|
107
|
+
text: stateText,
|
|
108
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
109
|
+
...(nodeName ? { nodeName } : {}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (event.event === "on_tool_start" || (event.event === "on_chain_start" && event.runType === "tool")) {
|
|
113
|
+
return {
|
|
114
|
+
kind: "tool-start",
|
|
115
|
+
toolName: nodeName ?? "tool",
|
|
116
|
+
...(event.data && "input" in event.data ? { input: event.data.input } : {}),
|
|
117
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
118
|
+
...(nodeName ? { nodeName } : {}),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
const toolResult = extractToolResult(event.raw);
|
|
122
|
+
if (toolResult) {
|
|
123
|
+
return {
|
|
124
|
+
kind: "tool-end",
|
|
125
|
+
toolName: toolResult.toolName,
|
|
126
|
+
...(toolResult.output !== undefined ? { output: toolResult.output } : {}),
|
|
127
|
+
...(toolResult.isError !== undefined ? { isError: toolResult.isError } : {}),
|
|
128
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
129
|
+
...(nodeName ? { nodeName } : {}),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const agentStep = extractAgentStep(event.raw);
|
|
133
|
+
if (agentStep) {
|
|
134
|
+
return {
|
|
135
|
+
kind: "agent-step",
|
|
136
|
+
label: agentStep,
|
|
137
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
138
|
+
...(nodeName ? { nodeName } : {}),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
kind: "run-event",
|
|
143
|
+
eventName: event.event ?? "unknown",
|
|
144
|
+
...(event.data ? { data: event.data } : {}),
|
|
145
|
+
...(ns && ns.length > 0 ? { ns } : {}),
|
|
146
|
+
...(nodeName ? { nodeName } : {}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function normalizeCompatibleStreamPart(event) {
|
|
150
|
+
const custom = extractCustomCompatibleStreamPart(event.raw);
|
|
151
|
+
if (custom) {
|
|
152
|
+
return custom;
|
|
153
|
+
}
|
|
154
|
+
const ns = event.ns ?? [];
|
|
155
|
+
const messageChunk = extractMessageCompatibleStreamPart(event);
|
|
156
|
+
if (messageChunk) {
|
|
157
|
+
return {
|
|
158
|
+
type: "messages",
|
|
159
|
+
ns,
|
|
160
|
+
data: [messageChunk, buildStreamPartMetadata(event)],
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
type: "updates",
|
|
165
|
+
ns,
|
|
166
|
+
data: buildUpdateCompatiblePayload(event),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function buildStreamPartMetadata(event) {
|
|
170
|
+
return {
|
|
171
|
+
...(event.metadata ?? {}),
|
|
172
|
+
...(event.event ? { event: event.event } : {}),
|
|
173
|
+
...(event.name ? { name: event.name } : {}),
|
|
174
|
+
...(event.runType ? { run_type: event.runType } : {}),
|
|
175
|
+
...(event.tags && event.tags.length > 0 ? { tags: event.tags } : {}),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function extractMessageCompatibleStreamPart(event) {
|
|
179
|
+
const typed = asObject(event.raw);
|
|
180
|
+
const data = asObject(typed?.data);
|
|
181
|
+
if (event.event === "on_chat_model_stream" && data && "chunk" in data) {
|
|
182
|
+
return data.chunk;
|
|
183
|
+
}
|
|
184
|
+
if (event.normalized.kind === "tool-end") {
|
|
185
|
+
return {
|
|
186
|
+
type: "tool",
|
|
187
|
+
name: event.normalized.toolName,
|
|
188
|
+
content: event.normalized.output,
|
|
189
|
+
...(event.normalized.isError !== undefined ? { isError: event.normalized.isError } : {}),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
function buildUpdateCompatiblePayload(event) {
|
|
195
|
+
const key = event.name ?? event.event ?? "event";
|
|
196
|
+
return {
|
|
197
|
+
[key]: extractUpdateNodePayload(event),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function extractUpdateNodePayload(event) {
|
|
201
|
+
const data = event.data;
|
|
202
|
+
if (event.event === "on_chain_stream" && data && "chunk" in data) {
|
|
203
|
+
return data.chunk;
|
|
204
|
+
}
|
|
205
|
+
if ((event.event === "on_tool_start" || event.event === "on_chain_start") && data && "input" in data) {
|
|
206
|
+
return { input: data.input };
|
|
207
|
+
}
|
|
208
|
+
if ((event.event === "on_tool_end" || event.event === "on_chain_end" || event.event === "on_chat_model_end") && data && "output" in data) {
|
|
209
|
+
return data.output;
|
|
210
|
+
}
|
|
211
|
+
if ((event.event === "on_tool_error" || event.event === "on_chain_error") && data) {
|
|
212
|
+
return {
|
|
213
|
+
...(data.output !== undefined ? { output: data.output } : {}),
|
|
214
|
+
...(data.error !== undefined ? { error: data.error } : {}),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
if (event.normalized.kind === "interrupt") {
|
|
218
|
+
return { __interrupt__: event.normalized.interrupt };
|
|
219
|
+
}
|
|
220
|
+
return data ?? {};
|
|
221
|
+
}
|
|
222
|
+
export function extractCustomCompatibleStreamPart(event) {
|
|
223
|
+
const custom = extractCustomStreamData(event);
|
|
224
|
+
if (!custom) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
type: "custom",
|
|
229
|
+
ns: custom.ns ?? [],
|
|
230
|
+
data: custom.data,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
2
233
|
function formatStepValue(value, maxLength = 120) {
|
|
3
234
|
if (value == null)
|
|
4
235
|
return "";
|
|
@@ -133,14 +133,25 @@ export function inferRoutingBindings(workspace) {
|
|
|
133
133
|
const runtimeEntryBindings = Array.from(workspace.bindings.values()).filter((binding) => isRuntimeEntryBinding(binding));
|
|
134
134
|
const orchestrationHosts = runtimeEntryBindings.filter((binding) => binding.agent.executionMode === "deepagent" || binding.agent.executionMode === "langgraph" || Boolean(binding.deepAgentParams));
|
|
135
135
|
const routingHosts = orchestrationHosts.length > 0 ? orchestrationHosts : runtimeEntryBindings;
|
|
136
|
+
const deepAgentHosts = routingHosts.filter((binding) => binding.agent.executionMode === "deepagent" || Boolean(binding.deepAgentParams));
|
|
137
|
+
const nonDeepAgentHosts = routingHosts.filter((binding) => !deepAgentHosts.includes(binding));
|
|
136
138
|
const researchBinding = routingHosts.find((binding) => binding.agent.id === "research-lite" || binding.agent.id === "research");
|
|
137
139
|
const directBinding = routingHosts.find((binding) => binding.agent.id === "direct");
|
|
138
140
|
const delegationHosts = routingHosts.filter((binding) => isDelegationCapableBinding(binding));
|
|
141
|
+
const deepAgentDelegationHosts = deepAgentHosts.filter((binding) => isDelegationCapableBinding(binding));
|
|
142
|
+
const nonDeepAgentDelegationHosts = nonDeepAgentHosts.filter((binding) => isDelegationCapableBinding(binding));
|
|
139
143
|
const lightweightHosts = routingHosts.filter((binding) => !isDelegationCapableBinding(binding));
|
|
140
144
|
const defaultOrchestratingHost = routingHosts.find((binding) => binding.agent.id === "orchestra") ??
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
deepAgentDelegationHosts.find((binding) => (binding.deepAgentParams?.subagents.length ?? 0) > 0) ??
|
|
146
|
+
deepAgentDelegationHosts[0] ??
|
|
147
|
+
deepAgentHosts[0] ??
|
|
148
|
+
nonDeepAgentDelegationHosts.find((binding) => (binding.deepAgentParams?.subagents.length ?? 0) > 0) ??
|
|
149
|
+
nonDeepAgentDelegationHosts[0] ??
|
|
150
|
+
nonDeepAgentHosts[0];
|
|
151
|
+
const delegationPreferredSecondary = deepAgentDelegationHosts.find((binding) => (binding.deepAgentParams?.subagents.length ?? 0) > 0) ??
|
|
152
|
+
deepAgentDelegationHosts[0] ??
|
|
153
|
+
nonDeepAgentDelegationHosts.find((binding) => (binding.deepAgentParams?.subagents.length ?? 0) > 0) ??
|
|
154
|
+
nonDeepAgentDelegationHosts[0] ??
|
|
144
155
|
delegationHosts[0];
|
|
145
156
|
const genericLightweightHost = lightweightHosts.find((binding) => binding.agent.id !== researchBinding?.agent.id);
|
|
146
157
|
const primaryBinding = defaultOrchestratingHost ?? directBinding ?? genericLightweightHost ?? routingHosts[0] ?? runtimeEntryBindings[0];
|
|
@@ -261,6 +261,22 @@ function resolveLangGraphWorkflowConfig(agent, refs) {
|
|
|
261
261
|
agent.langchainAgentConfig.passthrough.with
|
|
262
262
|
? { ...agent.langchainAgentConfig.passthrough.with }
|
|
263
263
|
: undefined;
|
|
264
|
+
const workspaceProfile = profile ? getWorkspaceObject(refs, `runtime-profile/${profile}`) : undefined;
|
|
265
|
+
if (workspaceProfile && workspaceProfile.kind !== "runtime-profile") {
|
|
266
|
+
throw new Error(`Agent ${agent.id} profile ${profile} does not resolve to a RuntimeProfile object`);
|
|
267
|
+
}
|
|
268
|
+
const workspaceProfileValue = workspaceProfile?.value && typeof workspaceProfile.value === "object"
|
|
269
|
+
? workspaceProfile.value
|
|
270
|
+
: undefined;
|
|
271
|
+
const workspaceProfileDefaults = typeof workspaceProfileValue?.defaults === "object" && workspaceProfileValue.defaults
|
|
272
|
+
? workspaceProfileValue.defaults
|
|
273
|
+
: undefined;
|
|
274
|
+
const mergedProfileWith = workspaceProfileDefaults || profileWith
|
|
275
|
+
? {
|
|
276
|
+
...(workspaceProfileDefaults ?? {}),
|
|
277
|
+
...(profileWith ?? {}),
|
|
278
|
+
}
|
|
279
|
+
: undefined;
|
|
264
280
|
const preset = typeof agent.langchainAgentConfig?.preset === "string" && agent.langchainAgentConfig.preset.trim()
|
|
265
281
|
? agent.langchainAgentConfig.preset.trim()
|
|
266
282
|
: typeof agent.langchainAgentConfig?.passthrough === "object" &&
|
|
@@ -284,21 +300,41 @@ function resolveLangGraphWorkflowConfig(agent, refs) {
|
|
|
284
300
|
agent.langchainAgentConfig.passthrough.langgraph
|
|
285
301
|
? agent.langchainAgentConfig.passthrough.langgraph
|
|
286
302
|
: undefined;
|
|
303
|
+
const profileWorkflowRef = typeof workspaceProfileValue?.workflowRef === "string" && workspaceProfileValue.workflowRef.trim()
|
|
304
|
+
? workspaceProfileValue.workflowRef.trim()
|
|
305
|
+
: typeof workspaceProfileValue?.workflow === "string" && workspaceProfileValue.workflow.trim()
|
|
306
|
+
? workspaceProfileValue.workflow.trim()
|
|
307
|
+
: typeof workspaceProfileValue?.workflow === "object" &&
|
|
308
|
+
workspaceProfileValue.workflow &&
|
|
309
|
+
typeof workspaceProfileValue.workflow.ref === "string" &&
|
|
310
|
+
workspaceProfileValue.workflow.ref.trim()
|
|
311
|
+
? workspaceProfileValue.workflow.ref.trim()
|
|
312
|
+
: undefined;
|
|
313
|
+
const resolvedProfileWorkflowConfig = !workflowConfig && profileWorkflowRef
|
|
314
|
+
? materializeWorkspaceObjectConfig(refs, profileWorkflowRef, ["langgraph-workflow"], `Agent ${agent.id} profile ${profile} workflow`)
|
|
315
|
+
: undefined;
|
|
287
316
|
if (!workflowConfig) {
|
|
288
|
-
return profile || preset
|
|
317
|
+
return profile || preset || resolvedProfileWorkflowConfig
|
|
318
|
+
? {
|
|
319
|
+
...(profile ? { profile } : {}),
|
|
320
|
+
...(mergedProfileWith ? { with: mergedProfileWith } : {}),
|
|
321
|
+
...(preset ? { preset } : {}),
|
|
322
|
+
...(resolvedProfileWorkflowConfig ? { config: resolvedProfileWorkflowConfig } : {}),
|
|
323
|
+
}
|
|
324
|
+
: undefined;
|
|
289
325
|
}
|
|
290
326
|
if (isRefConfig(workflowConfig)) {
|
|
291
327
|
return {
|
|
292
328
|
config: materializeWorkspaceObjectConfig(refs, workflowConfig.ref, ["langgraph-workflow"], `Agent ${agent.id} workflow`),
|
|
293
329
|
...(profile ? { profile } : {}),
|
|
294
|
-
...(
|
|
330
|
+
...(mergedProfileWith ? { with: mergedProfileWith } : {}),
|
|
295
331
|
...(preset ? { preset } : {}),
|
|
296
332
|
};
|
|
297
333
|
}
|
|
298
334
|
return {
|
|
299
335
|
config: workflowConfig,
|
|
300
336
|
...(profile ? { profile } : {}),
|
|
301
|
-
...(
|
|
337
|
+
...(mergedProfileWith ? { with: mergedProfileWith } : {}),
|
|
302
338
|
...(preset ? { preset } : {}),
|
|
303
339
|
};
|
|
304
340
|
}
|
|
@@ -152,6 +152,8 @@ function normalizeKind(kind) {
|
|
|
152
152
|
return "runtime-memory";
|
|
153
153
|
case "LangGraphWorkflow":
|
|
154
154
|
return "langgraph-workflow";
|
|
155
|
+
case "RuntimeProfile":
|
|
156
|
+
return "runtime-profile";
|
|
155
157
|
case "Prompt":
|
|
156
158
|
return "prompt";
|
|
157
159
|
case "McpServer":
|
|
@@ -473,7 +475,9 @@ async function objectItemsFromDocument(document, sourcePath) {
|
|
|
473
475
|
? normalizeCatalogSpec(document, { defaultKind: "McpServer" })
|
|
474
476
|
: catalogKind === "LangGraphWorkflows"
|
|
475
477
|
? normalizeCatalogSpec(document, { defaultKind: "LangGraphWorkflow" })
|
|
476
|
-
:
|
|
478
|
+
: catalogKind === "RuntimeProfiles"
|
|
479
|
+
? normalizeCatalogSpec(document, { defaultKind: "RuntimeProfile" })
|
|
480
|
+
: [];
|
|
477
481
|
if (catalogItems.length > 0) {
|
|
478
482
|
return catalogItems;
|
|
479
483
|
}
|