@botbotgo/agent-harness 0.0.95 → 0.0.97
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/api.d.ts +5 -5
- package/dist/config/workflows/langgraph-workflows.yaml +363 -111
- package/dist/config/workflows/runtime-profiles.yaml +94 -0
- package/dist/contracts/core.d.ts +9 -0
- package/dist/contracts/core.js +1 -0
- package/dist/contracts/runtime.d.ts +421 -0
- package/dist/contracts/runtime.js +1 -0
- package/dist/contracts/types.d.ts +3 -571
- package/dist/contracts/types.js +3 -1
- package/dist/contracts/workspace.d.ts +229 -0
- package/dist/contracts/workspace.js +1 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/adapter/compat/deepagent-compat.d.ts +16 -0
- package/dist/runtime/adapter/compat/deepagent-compat.js +45 -0
- package/dist/runtime/adapter/compat/openai-compatible.d.ts +2 -0
- package/dist/runtime/adapter/compat/openai-compatible.js +43 -0
- package/dist/runtime/adapter/index.d.ts +15 -0
- package/dist/runtime/adapter/index.js +15 -0
- package/dist/runtime/adapter/langgraph/presets.js +165 -0
- package/dist/runtime/{langgraph-profiles.d.ts → adapter/langgraph/profiles.d.ts} +1 -1
- package/dist/runtime/adapter/langgraph/profiles.js +206 -0
- package/dist/runtime/adapter/model/invocation-request.d.ts +10 -0
- package/dist/runtime/adapter/model/invocation-request.js +46 -0
- package/dist/runtime/adapter/model/message-assembly.d.ts +6 -0
- package/dist/runtime/adapter/model/message-assembly.js +21 -0
- package/dist/runtime/adapter/model/model-providers.d.ts +2 -0
- package/dist/runtime/adapter/model/model-providers.js +27 -0
- package/dist/runtime/adapter/resilience.d.ts +12 -0
- package/dist/runtime/adapter/resilience.js +60 -0
- package/dist/runtime/{declared-middleware.d.ts → adapter/tool/declared-middleware.d.ts} +1 -1
- package/dist/runtime/adapter/tool/interrupt-policy.d.ts +8 -0
- package/dist/runtime/adapter/tool/interrupt-policy.js +34 -0
- package/dist/runtime/adapter/tool/provider-tool.d.ts +2 -0
- package/dist/runtime/adapter/tool/provider-tool.js +25 -0
- package/dist/runtime/adapter/tool/resolved-tool.d.ts +18 -0
- package/dist/runtime/adapter/tool/resolved-tool.js +62 -0
- package/dist/runtime/adapter/tool/tool-arguments.d.ts +7 -0
- package/dist/runtime/adapter/tool/tool-arguments.js +87 -0
- package/dist/runtime/{tool-hitl.d.ts → adapter/tool/tool-hitl.d.ts} +2 -2
- package/dist/runtime/adapter/tool/tool-name-mapping.d.ts +13 -0
- package/dist/runtime/adapter/tool/tool-name-mapping.js +101 -0
- package/dist/runtime/agent-runtime-adapter.d.ts +5 -20
- package/dist/runtime/agent-runtime-adapter.js +42 -544
- package/dist/runtime/checkpoint-maintenance.d.ts +1 -45
- package/dist/runtime/checkpoint-maintenance.js +1 -259
- package/dist/runtime/file-checkpoint-saver.d.ts +1 -20
- package/dist/runtime/file-checkpoint-saver.js +1 -106
- package/dist/runtime/{event-bus.d.ts → harness/events/event-bus.d.ts} +1 -1
- package/dist/runtime/{event-sink.d.ts → harness/events/event-sink.d.ts} +1 -1
- package/dist/runtime/{event-sink.js → harness/events/event-sink.js} +1 -1
- package/dist/runtime/harness/events/events.d.ts +23 -0
- package/dist/runtime/harness/events/events.js +61 -0
- package/dist/runtime/harness/events/streaming.d.ts +19 -0
- package/dist/runtime/harness/events/streaming.js +96 -0
- package/dist/runtime/harness/index.d.ts +16 -0
- package/dist/runtime/harness/index.js +16 -0
- package/dist/runtime/harness/run/helpers.d.ts +33 -0
- package/dist/runtime/harness/run/helpers.js +74 -0
- package/dist/runtime/harness/run/resources.d.ts +7 -0
- package/dist/runtime/harness/run/resources.js +58 -0
- package/dist/runtime/harness/run/resume.d.ts +6 -0
- package/dist/runtime/harness/run/resume.js +56 -0
- package/dist/runtime/harness/run/routing.d.ts +12 -0
- package/dist/runtime/harness/run/routing.js +47 -0
- package/dist/runtime/harness/run/run-lifecycle.d.ts +37 -0
- package/dist/runtime/harness/run/run-lifecycle.js +109 -0
- package/dist/runtime/harness/run/run-queue.d.ts +17 -0
- package/dist/runtime/harness/run/run-queue.js +43 -0
- package/dist/runtime/{health-monitor.d.ts → harness/system/health-monitor.d.ts} +3 -3
- package/dist/runtime/{health-monitor.js → harness/system/health-monitor.js} +2 -2
- package/dist/runtime/{inventory.d.ts → harness/system/inventory.d.ts} +2 -2
- package/dist/runtime/{inventory.js → harness/system/inventory.js} +4 -4
- package/dist/runtime/{policy-engine.d.ts → harness/system/policy-engine.d.ts} +1 -1
- package/dist/runtime/{policy-engine.js → harness/system/policy-engine.js} +1 -1
- package/dist/runtime/{skill-requirements.d.ts → harness/system/skill-requirements.d.ts} +1 -1
- package/dist/runtime/{skill-requirements.js → harness/system/skill-requirements.js} +1 -1
- package/dist/runtime/{thread-memory-sync.d.ts → harness/system/thread-memory-sync.d.ts} +2 -2
- package/dist/runtime/{thread-memory-sync.js → harness/system/thread-memory-sync.js} +1 -1
- package/dist/runtime/harness.d.ts +2 -7
- package/dist/runtime/harness.js +158 -477
- package/dist/runtime/index.d.ts +7 -7
- package/dist/runtime/index.js +7 -7
- package/dist/runtime/maintenance/checkpoint-maintenance.d.ts +45 -0
- package/dist/runtime/maintenance/checkpoint-maintenance.js +259 -0
- package/dist/runtime/maintenance/file-checkpoint-saver.d.ts +20 -0
- package/dist/runtime/maintenance/file-checkpoint-saver.js +106 -0
- package/dist/runtime/maintenance/index.d.ts +4 -0
- package/dist/runtime/maintenance/index.js +4 -0
- package/dist/runtime/{runtime-record-maintenance.d.ts → maintenance/runtime-record-maintenance.d.ts} +1 -1
- package/dist/runtime/{runtime-record-maintenance.js → maintenance/runtime-record-maintenance.js} +2 -2
- package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.d.ts +9 -0
- package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.js +39 -0
- package/dist/runtime/parsing/stream-event-parsing.d.ts +6 -0
- package/dist/runtime/parsing/stream-event-parsing.js +231 -0
- package/dist/runtime/sqlite-maintained-checkpoint-saver.d.ts +1 -9
- package/dist/runtime/sqlite-maintained-checkpoint-saver.js +1 -39
- package/dist/runtime/support/harness-support.d.ts +4 -4
- package/dist/runtime/support/harness-support.js +14 -3
- package/dist/runtime/support/runtime-factories.d.ts +1 -1
- package/dist/runtime/support/runtime-factories.js +1 -1
- package/dist/workspace/agent-binding-compiler.js +39 -3
- package/dist/workspace/object-loader.js +5 -1
- package/package.json +4 -4
- package/dist/runtime/langgraph-presets.js +0 -165
- package/dist/runtime/langgraph-profiles.js +0 -206
- /package/dist/runtime/{langgraph-presets.d.ts → adapter/langgraph/presets.d.ts} +0 -0
- /package/dist/runtime/{declared-middleware.js → adapter/tool/declared-middleware.js} +0 -0
- /package/dist/runtime/{tool-hitl.js → adapter/tool/tool-hitl.js} +0 -0
- /package/dist/runtime/{event-bus.js → harness/events/event-bus.js} +0 -0
- /package/dist/runtime/{store.d.ts → harness/system/store.d.ts} +0 -0
- /package/dist/runtime/{store.js → harness/system/store.js} +0 -0
|
@@ -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 "";
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { RunnableConfig } from "@langchain/core/runnables";
|
|
3
|
-
export declare class ManagedSqliteSaver extends SqliteSaver {
|
|
4
|
-
constructor(db: ConstructorParameters<typeof SqliteSaver>[0]);
|
|
5
|
-
prepareMaintenance(): void;
|
|
6
|
-
setup(): void;
|
|
7
|
-
put(config: RunnableConfig, checkpoint: Parameters<SqliteSaver["put"]>[1], metadata: Parameters<SqliteSaver["put"]>[2]): Promise<RunnableConfig<Record<string, any>>>;
|
|
8
|
-
deleteThread(threadId: string): Promise<void>;
|
|
9
|
-
}
|
|
1
|
+
export * from "./maintenance/sqlite-maintained-checkpoint-saver.js";
|
|
@@ -1,39 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export class ManagedSqliteSaver extends SqliteSaver {
|
|
3
|
-
constructor(db) {
|
|
4
|
-
super(db);
|
|
5
|
-
}
|
|
6
|
-
prepareMaintenance() {
|
|
7
|
-
this.setup();
|
|
8
|
-
}
|
|
9
|
-
setup() {
|
|
10
|
-
super.setup();
|
|
11
|
-
this.db.exec(`
|
|
12
|
-
CREATE TABLE IF NOT EXISTS checkpoint_maintenance_meta (
|
|
13
|
-
thread_id TEXT NOT NULL,
|
|
14
|
-
checkpoint_ns TEXT NOT NULL DEFAULT '',
|
|
15
|
-
checkpoint_id TEXT NOT NULL,
|
|
16
|
-
created_at_ms INTEGER NOT NULL,
|
|
17
|
-
PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id)
|
|
18
|
-
);`);
|
|
19
|
-
}
|
|
20
|
-
async put(config, checkpoint, metadata) {
|
|
21
|
-
const result = await super.put(config, checkpoint, metadata);
|
|
22
|
-
const threadId = result.configurable?.thread_id;
|
|
23
|
-
const checkpointNs = result.configurable?.checkpoint_ns ?? "";
|
|
24
|
-
const checkpointId = result.configurable?.checkpoint_id;
|
|
25
|
-
if (!threadId || !checkpointId) {
|
|
26
|
-
throw new Error("Missing checkpoint identity after SqliteSaver.put");
|
|
27
|
-
}
|
|
28
|
-
this.db
|
|
29
|
-
.prepare(`INSERT OR IGNORE INTO checkpoint_maintenance_meta
|
|
30
|
-
(thread_id, checkpoint_ns, checkpoint_id, created_at_ms)
|
|
31
|
-
VALUES (?, ?, ?, ?)`)
|
|
32
|
-
.run(threadId, checkpointNs, checkpointId, Date.now());
|
|
33
|
-
return result;
|
|
34
|
-
}
|
|
35
|
-
async deleteThread(threadId) {
|
|
36
|
-
await super.deleteThread(threadId);
|
|
37
|
-
this.db.prepare(`DELETE FROM checkpoint_maintenance_meta WHERE thread_id = ?`).run(threadId);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
1
|
+
export * from "./maintenance/sqlite-maintained-checkpoint-saver.js";
|
|
@@ -21,8 +21,8 @@ export declare function heuristicRoute(input: string, primaryBinding?: {
|
|
|
21
21
|
export declare function createHarnessEvent(threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>, source?: HarnessEvent["source"]): HarnessEvent;
|
|
22
22
|
export declare function createPendingApproval(threadId: string, runId: string, checkpointRef: string, input: string, interruptContent?: string): InternalApprovalRecord;
|
|
23
23
|
export declare function inferRoutingBindings(workspace: WorkspaceBundle): {
|
|
24
|
-
primaryBinding: import("../../contracts/
|
|
25
|
-
secondaryBinding: import("../../contracts/
|
|
26
|
-
researchBinding: import("../../contracts/
|
|
27
|
-
hostBindings: import("../../contracts/
|
|
24
|
+
primaryBinding: import("../../contracts/workspace.js").CompiledAgentBinding;
|
|
25
|
+
secondaryBinding: import("../../contracts/workspace.js").CompiledAgentBinding | undefined;
|
|
26
|
+
researchBinding: import("../../contracts/workspace.js").CompiledAgentBinding | undefined;
|
|
27
|
+
hostBindings: import("../../contracts/workspace.js").CompiledAgentBinding[];
|
|
28
28
|
};
|
|
@@ -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];
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { type StoreLike } from "../store.js";
|
|
1
|
+
import { type StoreLike } from "../harness/system/store.js";
|
|
2
2
|
export declare function createStoreForConfig(storeConfig: Record<string, unknown>, runRoot: string): StoreLike;
|
|
3
3
|
export declare function createCheckpointerForConfig(checkpointerConfig: Record<string, unknown> | boolean, runRoot: string): unknown;
|
|
@@ -3,7 +3,7 @@ import { MemorySaver } from "@langchain/langgraph";
|
|
|
3
3
|
import { SqliteSaver } from "@langchain/langgraph-checkpoint-sqlite";
|
|
4
4
|
import { FileCheckpointSaver } from "../file-checkpoint-saver.js";
|
|
5
5
|
import { ManagedSqliteSaver } from "../sqlite-maintained-checkpoint-saver.js";
|
|
6
|
-
import { createInMemoryStore, FileBackedStore } from "../store.js";
|
|
6
|
+
import { createInMemoryStore, FileBackedStore } from "../harness/system/store.js";
|
|
7
7
|
export function createStoreForConfig(storeConfig, runRoot) {
|
|
8
8
|
const kind = typeof storeConfig.kind === "string" ? storeConfig.kind : "FileStore";
|
|
9
9
|
switch (kind) {
|
|
@@ -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
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.97",
|
|
4
4
|
"description": "Workspace runtime for multi-agent applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc -p tsconfig.json && cp -R config dist/",
|
|
55
55
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
56
|
-
"test": "vitest run
|
|
57
|
-
"test:upstream-ab-real": "vitest run test/upstream-runtime-ab-real.test.ts",
|
|
58
|
-
"test:real-providers": "vitest run test/real-provider-harness.test.ts",
|
|
56
|
+
"test": "vitest run $(find test -name '*.test.ts' -print | sort)",
|
|
57
|
+
"test:upstream-ab-real": "vitest run test/benchmark/upstream-runtime-ab-real.test.ts",
|
|
58
|
+
"test:real-providers": "vitest run test/providers/real-provider-harness.test.ts",
|
|
59
59
|
"release:prepare": "npm version patch --no-git-tag-version && node ./scripts/sync-example-version.mjs",
|
|
60
60
|
"release:pack": "npm pack --dry-run",
|
|
61
61
|
"release:publish": "npm publish --access public --registry https://registry.npmjs.org/"
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
const DEFAULT_PLANNER_PROMPT = "You are the workflow planner. Produce a concise execution plan for the user request before execution starts.";
|
|
2
|
-
const DEFAULT_REVIEWER_PROMPT = "Review the current result, call out missing verification or obvious gaps, and state whether the work looks sufficient.";
|
|
3
|
-
const DEFAULT_REPLANNER_PROMPT = "Refine the plan based on the reviewer feedback and current result. Return only the updated plan.";
|
|
4
|
-
const DEFAULT_FINALIZER_PROMPT = "Rewrite the current result into a concise user-facing final answer. Preserve facts and caveats.";
|
|
5
|
-
export const SUPPORTED_LANGGRAPH_PRESETS = [
|
|
6
|
-
"react",
|
|
7
|
-
"prompt-chaining",
|
|
8
|
-
"routing",
|
|
9
|
-
"parallelization",
|
|
10
|
-
"plan-execute",
|
|
11
|
-
"review-loop",
|
|
12
|
-
"evaluator-optimizer",
|
|
13
|
-
"approval-gate",
|
|
14
|
-
"handoff",
|
|
15
|
-
"orchestrator-workers",
|
|
16
|
-
];
|
|
17
|
-
function requireAgent(preset, options) {
|
|
18
|
-
if (typeof options.agent === "string" && options.agent.trim()) {
|
|
19
|
-
return options.agent.trim();
|
|
20
|
-
}
|
|
21
|
-
throw new Error(`LangGraph preset ${preset} requires config.agent`);
|
|
22
|
-
}
|
|
23
|
-
export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
|
|
24
|
-
switch (presetName) {
|
|
25
|
-
case undefined:
|
|
26
|
-
case "":
|
|
27
|
-
return undefined;
|
|
28
|
-
case "react":
|
|
29
|
-
return {
|
|
30
|
-
entryNode: "executor",
|
|
31
|
-
nodes: [
|
|
32
|
-
{ id: "executor", kind: "agent" },
|
|
33
|
-
],
|
|
34
|
-
edges: [],
|
|
35
|
-
};
|
|
36
|
-
case "prompt-chaining":
|
|
37
|
-
case "plan-execute":
|
|
38
|
-
return {
|
|
39
|
-
entryNode: "planner",
|
|
40
|
-
nodes: [
|
|
41
|
-
{ id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
42
|
-
{ id: "executor", kind: "agent" },
|
|
43
|
-
{ id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
44
|
-
],
|
|
45
|
-
edges: [
|
|
46
|
-
{ from: "planner", to: "executor" },
|
|
47
|
-
{ from: "executor", to: "finalizer", when: "has_result" },
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
case "routing": {
|
|
51
|
-
const agent = requireAgent("routing", options);
|
|
52
|
-
return {
|
|
53
|
-
entryNode: "planner",
|
|
54
|
-
nodes: [
|
|
55
|
-
{ id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
56
|
-
{ id: "worker", kind: "agent", agent },
|
|
57
|
-
{ id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
58
|
-
],
|
|
59
|
-
edges: [
|
|
60
|
-
{ from: "planner", to: "worker" },
|
|
61
|
-
{ from: "worker", to: "finalizer", when: "has_result" },
|
|
62
|
-
],
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
case "parallelization": {
|
|
66
|
-
const agent = requireAgent("parallelization", options);
|
|
67
|
-
return {
|
|
68
|
-
entryNode: "planner",
|
|
69
|
-
nodes: [
|
|
70
|
-
{ id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
71
|
-
{ id: "worker", kind: "agent", agent },
|
|
72
|
-
{ id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
|
|
73
|
-
{ id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
74
|
-
],
|
|
75
|
-
edges: [
|
|
76
|
-
{ from: "planner", to: "worker" },
|
|
77
|
-
{ from: "worker", to: "reviewer", when: "has_result" },
|
|
78
|
-
{ from: "reviewer", to: "finalizer", when: "review_ok" },
|
|
79
|
-
],
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
case "review-loop":
|
|
83
|
-
return {
|
|
84
|
-
entryNode: "planner",
|
|
85
|
-
nodes: [
|
|
86
|
-
{ id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
87
|
-
{ id: "executor", kind: "agent" },
|
|
88
|
-
{ id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
|
|
89
|
-
{ id: "replanner", kind: "llm", role: "replanner", prompt: DEFAULT_REPLANNER_PROMPT },
|
|
90
|
-
{ id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
91
|
-
],
|
|
92
|
-
edges: [
|
|
93
|
-
{ from: "planner", to: "executor" },
|
|
94
|
-
{ from: "executor", to: "reviewer", when: "has_result" },
|
|
95
|
-
{ from: "reviewer", to: "finalizer", when: "review_ok" },
|
|
96
|
-
{ from: "reviewer", to: "replanner", when: "review_incomplete" },
|
|
97
|
-
{ from: "replanner", to: "executor", when: "has_plan" },
|
|
98
|
-
],
|
|
99
|
-
};
|
|
100
|
-
case "evaluator-optimizer":
|
|
101
|
-
return {
|
|
102
|
-
entryNode: "executor",
|
|
103
|
-
nodes: [
|
|
104
|
-
{ id: "executor", kind: "agent" },
|
|
105
|
-
{ id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
|
|
106
|
-
{ id: "replanner", kind: "llm", role: "replanner", prompt: DEFAULT_REPLANNER_PROMPT },
|
|
107
|
-
{ id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
108
|
-
],
|
|
109
|
-
edges: [
|
|
110
|
-
{ from: "executor", to: "reviewer", when: "has_result" },
|
|
111
|
-
{ from: "reviewer", to: "finalizer", when: "review_ok" },
|
|
112
|
-
{ from: "reviewer", to: "replanner", when: "review_incomplete" },
|
|
113
|
-
{ from: "replanner", to: "executor", when: "has_plan" },
|
|
114
|
-
],
|
|
115
|
-
};
|
|
116
|
-
case "approval-gate":
|
|
117
|
-
return {
|
|
118
|
-
entryNode: "planner",
|
|
119
|
-
nodes: [
|
|
120
|
-
{ id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
121
|
-
{ id: "approval", kind: "approval" },
|
|
122
|
-
{ id: "executor", kind: "agent" },
|
|
123
|
-
{ id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
124
|
-
],
|
|
125
|
-
edges: [
|
|
126
|
-
{ from: "planner", to: "approval" },
|
|
127
|
-
{ from: "approval", to: "executor", when: "approval_approved" },
|
|
128
|
-
{ from: "approval", to: "executor", when: "approval_edited" },
|
|
129
|
-
{ from: "executor", to: "finalizer", when: "has_result" },
|
|
130
|
-
],
|
|
131
|
-
};
|
|
132
|
-
case "handoff": {
|
|
133
|
-
const agent = requireAgent("handoff", options);
|
|
134
|
-
return {
|
|
135
|
-
entryNode: "worker",
|
|
136
|
-
nodes: [
|
|
137
|
-
{ id: "worker", kind: "agent", agent },
|
|
138
|
-
{ id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
139
|
-
],
|
|
140
|
-
edges: [
|
|
141
|
-
{ from: "worker", to: "finalizer", when: "has_result" },
|
|
142
|
-
],
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
case "orchestrator-workers": {
|
|
146
|
-
const agent = requireAgent("orchestrator-workers", options);
|
|
147
|
-
return {
|
|
148
|
-
entryNode: "planner",
|
|
149
|
-
nodes: [
|
|
150
|
-
{ id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
|
|
151
|
-
{ id: "worker", kind: "agent", agent },
|
|
152
|
-
{ id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
|
|
153
|
-
{ id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
|
|
154
|
-
],
|
|
155
|
-
edges: [
|
|
156
|
-
{ from: "planner", to: "worker" },
|
|
157
|
-
{ from: "worker", to: "reviewer", when: "has_result" },
|
|
158
|
-
{ from: "reviewer", to: "finalizer", when: "review_ok" },
|
|
159
|
-
],
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
default:
|
|
163
|
-
throw new Error(`Unsupported LangGraph preset ${String(presetName)}. Supported presets: ${SUPPORTED_LANGGRAPH_PRESETS.join(", ")}`);
|
|
164
|
-
}
|
|
165
|
-
}
|