@botbotgo/agent-harness 0.0.297 → 0.0.299
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 +77 -37
- package/README.zh.md +79 -30
- package/dist/acp.d.ts +3 -0
- package/dist/acp.js +10 -2
- package/dist/api.d.ts +14 -2
- package/dist/api.js +19 -3
- package/dist/cli.d.ts +18 -1
- package/dist/cli.js +1408 -319
- package/dist/client/acp.d.ts +9 -3
- package/dist/client/acp.js +55 -1
- package/dist/client/in-process.d.ts +5 -2
- package/dist/client/in-process.js +4 -6
- package/dist/client/index.d.ts +1 -1
- package/dist/client/types.d.ts +6 -5
- package/dist/config/agents/direct.yaml +7 -17
- package/dist/config/agents/orchestra.yaml +9 -65
- package/dist/config/catalogs/embedding-models.yaml +1 -1
- package/dist/config/catalogs/stores.yaml +1 -1
- package/dist/config/knowledge/knowledge-runtime.yaml +36 -2
- package/dist/config/knowledge/procedural-memory-runtime.yaml +78 -0
- package/dist/config/{catalogs/models.yaml → models.yaml} +2 -2
- package/dist/config/prompts/direct-system.md +16 -0
- package/dist/config/prompts/orchestra-system.md +62 -0
- package/dist/config/prompts/routing-system.md +14 -0
- package/dist/config/runtime/runtime-memory.yaml +39 -5
- package/dist/config/runtime/workspace.yaml +7 -16
- package/dist/contracts/runtime.d.ts +242 -1
- package/dist/contracts/workspace.d.ts +2 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -1
- package/dist/init-project.js +178 -33
- package/dist/knowledge/contracts.d.ts +5 -0
- package/dist/knowledge/module.d.ts +5 -0
- package/dist/knowledge/module.js +340 -18
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.d.ts +5 -1
- package/dist/persistence/file-store.js +16 -0
- package/dist/persistence/sqlite-store.d.ts +4 -1
- package/dist/persistence/sqlite-store.js +88 -14
- package/dist/persistence/types.d.ts +4 -1
- package/dist/procedural/config.d.ts +63 -0
- package/dist/procedural/config.js +125 -0
- package/dist/procedural/index.d.ts +2 -0
- package/dist/procedural/index.js +1 -0
- package/dist/protocol/ag-ui/http.d.ts +3 -0
- package/dist/protocol/ag-ui/http.js +10 -0
- package/dist/request-events.d.ts +63 -0
- package/dist/request-events.js +400 -0
- package/dist/resource/isolation.js +11 -0
- package/dist/resource/resource-impl.d.ts +1 -0
- package/dist/resource/resource-impl.js +103 -12
- package/dist/resources/init-templates/agent-context/deep-research.md +5 -0
- package/dist/resources/init-templates/prompts/research-analyst-basic.md +1 -0
- package/dist/resources/init-templates/prompts/research-analyst-web-search.md +1 -0
- package/dist/resources/init-templates/prompts/research-host-deep-research-basic.md +1 -0
- package/dist/resources/init-templates/prompts/research-host-deep-research-web-search.md +1 -0
- package/dist/resources/init-templates/prompts/research-host-single-agent-basic.md +1 -0
- package/dist/resources/init-templates/prompts/research-host-single-agent-web-search.md +1 -0
- package/dist/resources/prompts/runtime/browser-capability-disclaimer-recovery.md +1 -0
- package/dist/resources/prompts/runtime/default-subagent.md +2 -0
- package/dist/resources/prompts/runtime/durable-memory-context.md +7 -0
- package/dist/resources/prompts/runtime/execution-with-tool-evidence-retry.md +1 -0
- package/dist/resources/prompts/runtime/execution-with-tool-evidence.md +1 -0
- package/dist/resources/prompts/runtime/invalid-tool-selection-recovery.md +1 -0
- package/dist/resources/prompts/runtime/memory-manager.md +31 -0
- package/dist/resources/prompts/runtime/memory-mutation-reconciliation.md +22 -0
- package/dist/resources/prompts/runtime/slash-command-skill.md +6 -0
- package/dist/resources/prompts/runtime/strict-tool-json.md +1 -0
- package/dist/resources/prompts/runtime/workspace-boundary-guidance.md +3 -0
- package/dist/resources/prompts/runtime/workspace-relative-path.md +1 -0
- package/dist/resources/prompts/runtime/write-todos-descriptive-content.md +1 -0
- package/dist/resources/prompts/runtime/write-todos-full-entry.md +1 -0
- package/dist/resources/prompts/runtime/write-todos-non-empty-initial-list.md +1 -0
- package/dist/resources/tools/_runtime_tool_helpers.mjs +152 -0
- package/dist/resources/tools/cancel_request.mjs +21 -0
- package/dist/resources/tools/fetch_url.mjs +23 -0
- package/dist/resources/tools/http_request.mjs +30 -0
- package/dist/resources/tools/inspect_approvals.mjs +27 -0
- package/dist/resources/tools/inspect_artifacts.mjs +21 -0
- package/dist/resources/tools/inspect_events.mjs +21 -0
- package/dist/resources/tools/inspect_requests.mjs +27 -0
- package/dist/resources/tools/inspect_sessions.mjs +21 -0
- package/dist/resources/tools/list_files.mjs +27 -0
- package/dist/resources/tools/read_artifact.mjs +22 -0
- package/dist/resources/tools/request_approval.mjs +27 -0
- package/dist/resources/tools/run_command.mjs +21 -0
- package/dist/resources/tools/schedule_task.mjs +76 -0
- package/dist/resources/tools/search_files.mjs +47 -0
- package/dist/resources/tools/send_message.mjs +23 -0
- package/dist/runtime/adapter/direct-builtin-utility.d.ts +1 -0
- package/dist/runtime/adapter/direct-builtin-utility.js +90 -0
- package/dist/runtime/adapter/flow/execution-context.d.ts +1 -1
- package/dist/runtime/adapter/flow/execution-context.js +1 -1
- package/dist/runtime/adapter/flow/invocation-flow.d.ts +1 -0
- package/dist/runtime/adapter/flow/invocation-flow.js +9 -1
- package/dist/runtime/adapter/flow/invoke-runtime.d.ts +1 -1
- package/dist/runtime/adapter/flow/stream-runtime.d.ts +5 -1
- package/dist/runtime/adapter/flow/stream-runtime.js +556 -35
- package/dist/runtime/adapter/invocation-result.js +3 -2
- package/dist/runtime/adapter/local-tool-invocation.d.ts +1 -1
- package/dist/runtime/adapter/local-tool-invocation.js +28 -4
- package/dist/runtime/adapter/middleware-assembly.js +3 -1
- package/dist/runtime/adapter/model/invocation-request.d.ts +4 -1
- package/dist/runtime/adapter/model/invocation-request.js +138 -16
- package/dist/runtime/adapter/model/message-assembly.js +2 -6
- package/dist/runtime/adapter/model/model-providers.js +103 -5
- package/dist/runtime/adapter/resilience.js +17 -2
- package/dist/runtime/adapter/runtime-adapter-support.d.ts +11 -7
- package/dist/runtime/adapter/runtime-adapter-support.js +39 -5
- package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +63 -1
- package/dist/runtime/adapter/tool/builtin-middleware-tools.js +193 -21
- package/dist/runtime/adapter/tool/tool-arguments.d.ts +3 -1
- package/dist/runtime/adapter/tool/tool-arguments.js +52 -17
- package/dist/runtime/adapter/tool-resolution.d.ts +1 -0
- package/dist/runtime/adapter/tool-resolution.js +4 -2
- package/dist/runtime/agent-runtime-adapter.d.ts +27 -0
- package/dist/runtime/agent-runtime-adapter.js +163 -11
- package/dist/runtime/harness/events/event-bus.d.ts +1 -0
- package/dist/runtime/harness/events/event-bus.js +3 -0
- package/dist/runtime/harness/events/event-sink.d.ts +3 -0
- package/dist/runtime/harness/events/event-sink.js +16 -7
- package/dist/runtime/harness/events/streaming.d.ts +18 -1
- package/dist/runtime/harness/events/streaming.js +23 -10
- package/dist/runtime/harness/run/inspection.js +26 -5
- package/dist/runtime/harness/run/stream-run.d.ts +13 -4
- package/dist/runtime/harness/run/stream-run.js +448 -4
- package/dist/runtime/harness/run/surface-semantics.js +7 -34
- package/dist/runtime/harness/system/runtime-memory-manager.d.ts +3 -0
- package/dist/runtime/harness/system/runtime-memory-manager.js +384 -69
- package/dist/runtime/harness/system/runtime-memory-policy.d.ts +20 -1
- package/dist/runtime/harness/system/runtime-memory-policy.js +65 -17
- package/dist/runtime/harness/system/runtime-memory-records.js +100 -0
- package/dist/runtime/harness/system/runtime-memory-sync.js +2 -2
- package/dist/runtime/harness/system/store.d.ts +4 -0
- package/dist/runtime/harness/system/store.js +153 -0
- package/dist/runtime/harness.d.ts +9 -1
- package/dist/runtime/harness.js +141 -7
- package/dist/runtime/maintenance/sqlite-checkpoint-saver.d.ts +8 -3
- package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +152 -53
- package/dist/runtime/parsing/output-parsing.d.ts +10 -2
- package/dist/runtime/parsing/output-parsing.js +223 -16
- package/dist/runtime/parsing/stream-event-parsing.d.ts +7 -0
- package/dist/runtime/parsing/stream-event-parsing.js +51 -1
- package/dist/runtime/scheduling/system-schedule-manager.d.ts +41 -0
- package/dist/runtime/scheduling/system-schedule-manager.js +532 -0
- package/dist/runtime/support/embedding-models.d.ts +1 -1
- package/dist/runtime/support/embedding-models.js +5 -2
- package/dist/runtime/support/runtime-factories.js +1 -1
- package/dist/runtime/support/runtime-layout.d.ts +3 -0
- package/dist/runtime/support/runtime-layout.js +10 -1
- package/dist/runtime/support/runtime-prompts.d.ts +30 -0
- package/dist/runtime/support/runtime-prompts.js +55 -0
- package/dist/runtime/support/vector-stores.d.ts +1 -1
- package/dist/runtime/support/vector-stores.js +5 -2
- package/dist/upstream-events.js +8 -7
- package/dist/utils/bundled-text.d.ts +3 -0
- package/dist/utils/bundled-text.js +25 -0
- package/dist/utils/id.js +3 -2
- package/dist/workspace/agent-binding-compiler.js +53 -13
- package/dist/workspace/object-loader.js +64 -2
- package/dist/workspace/support/workspace-ref-utils.d.ts +2 -1
- package/dist/workspace/support/workspace-ref-utils.js +24 -5
- package/dist/workspace/yaml-object-reader.d.ts +1 -0
- package/dist/workspace/yaml-object-reader.js +95 -17
- package/package.json +13 -6
|
@@ -1,9 +1,162 @@
|
|
|
1
1
|
import { AGENT_INTERRUPT_SENTINEL_PREFIX, RuntimeOperationTimeoutError } from "../../agent-runtime-adapter.js";
|
|
2
|
+
import { buildRequestPlanState, summarizeBuiltinWriteTodosArgs } from "../../adapter/runtime-adapter-support.js";
|
|
2
3
|
import { renderRuntimeFailure, renderToolFailure } from "../../support/harness-support.js";
|
|
3
4
|
import { getBindingPrimaryModel } from "../../support/compiled-binding.js";
|
|
4
5
|
import { createContentBlocksItem, createToolResultKey, } from "../events/streaming.js";
|
|
5
6
|
import { projectRuntimeSurfaceFromSingleUpstreamEvent } from "./inspection.js";
|
|
6
7
|
import { formatAgentName } from "../../../utils/agent-display.js";
|
|
8
|
+
function createInitialPlanState(sessionId, requestId, updatedAt) {
|
|
9
|
+
return {
|
|
10
|
+
sessionId,
|
|
11
|
+
requestId,
|
|
12
|
+
version: 0,
|
|
13
|
+
updatedAt,
|
|
14
|
+
items: [],
|
|
15
|
+
summary: {
|
|
16
|
+
total: 0,
|
|
17
|
+
pending: 0,
|
|
18
|
+
inProgress: 0,
|
|
19
|
+
completed: 0,
|
|
20
|
+
failed: 0,
|
|
21
|
+
cancelled: 0,
|
|
22
|
+
blocked: 0,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function getPlanStateFromToolResult(input) {
|
|
27
|
+
if (typeof input.output !== "object" || input.output === null) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const summary = input.output.summary;
|
|
31
|
+
if (summary && typeof summary === "object" && Array.isArray(summary.items)) {
|
|
32
|
+
const typedSummary = summary;
|
|
33
|
+
if (typedSummary.summary && typeof typedSummary.summary === "object") {
|
|
34
|
+
return {
|
|
35
|
+
sessionId: input.sessionId,
|
|
36
|
+
requestId: input.requestId,
|
|
37
|
+
version: input.version,
|
|
38
|
+
updatedAt: input.updatedAt,
|
|
39
|
+
items: typedSummary.items,
|
|
40
|
+
summary: typedSummary.summary,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const snapshot = summarizeBuiltinWriteTodosArgs(input.output);
|
|
45
|
+
return buildRequestPlanState({
|
|
46
|
+
sessionId: input.sessionId,
|
|
47
|
+
requestId: input.requestId,
|
|
48
|
+
updatedAt: input.updatedAt,
|
|
49
|
+
version: input.version,
|
|
50
|
+
snapshot,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function getStructuredPlanStateFromToolResult(input) {
|
|
54
|
+
if (typeof input.output !== "object" || input.output === null) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const summary = input.output.summary;
|
|
58
|
+
if (!summary || typeof summary !== "object" || !Array.isArray(summary.items)) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const typedSummary = summary;
|
|
62
|
+
if (!typedSummary.summary || typeof typedSummary.summary !== "object") {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
sessionId: input.sessionId,
|
|
67
|
+
requestId: input.requestId,
|
|
68
|
+
version: input.version,
|
|
69
|
+
updatedAt: input.updatedAt,
|
|
70
|
+
items: typedSummary.items,
|
|
71
|
+
summary: typedSummary.summary,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function buildPlanStateSignature(planState) {
|
|
75
|
+
return JSON.stringify({
|
|
76
|
+
items: planState.items,
|
|
77
|
+
summary: planState.summary,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function countStructuredTodoIds(items) {
|
|
81
|
+
return items.filter((item) => typeof item.id === "string" && item.id.length > 0).length;
|
|
82
|
+
}
|
|
83
|
+
function shouldEmitPlanState(currentPlanState, nextPlanState) {
|
|
84
|
+
if (!currentPlanState || currentPlanState.items.length === 0) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (nextPlanState.items.length === 0) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const currentStructuredIds = countStructuredTodoIds(currentPlanState.items);
|
|
91
|
+
const nextStructuredIds = countStructuredTodoIds(nextPlanState.items);
|
|
92
|
+
if (currentStructuredIds > 0
|
|
93
|
+
&& nextStructuredIds === 0
|
|
94
|
+
&& nextPlanState.items.length < currentPlanState.items.length) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
function extractTodosArray(value) {
|
|
100
|
+
if (typeof value !== "object" || value === null) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const record = value;
|
|
104
|
+
if (Array.isArray(record.todos)) {
|
|
105
|
+
return record.todos;
|
|
106
|
+
}
|
|
107
|
+
if (typeof record.output === "object" && record.output !== null) {
|
|
108
|
+
const nested = record.output.todos;
|
|
109
|
+
if (Array.isArray(nested)) {
|
|
110
|
+
return nested;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
function getPlanStateFromUpstreamEvent(input) {
|
|
116
|
+
if (typeof input.event !== "object" || input.event === null) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const typed = input.event;
|
|
120
|
+
const todos = extractTodosArray(typed.data?.output)
|
|
121
|
+
?? extractTodosArray(typed.data?.chunk);
|
|
122
|
+
if (!todos) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return buildRequestPlanState({
|
|
126
|
+
sessionId: input.sessionId,
|
|
127
|
+
requestId: input.requestId,
|
|
128
|
+
updatedAt: input.updatedAt,
|
|
129
|
+
version: input.version,
|
|
130
|
+
snapshot: summarizeBuiltinWriteTodosArgs({ todos }),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function getLatestPlanStateFromExecutedToolResults(input) {
|
|
134
|
+
const executedToolResults = Array.isArray(input.metadata?.executedToolResults)
|
|
135
|
+
? input.metadata.executedToolResults
|
|
136
|
+
: [];
|
|
137
|
+
for (const latest of [...executedToolResults].reverse()) {
|
|
138
|
+
const structured = getStructuredPlanStateFromToolResult({
|
|
139
|
+
sessionId: input.sessionId,
|
|
140
|
+
requestId: input.requestId,
|
|
141
|
+
output: latest.output,
|
|
142
|
+
version: input.version,
|
|
143
|
+
updatedAt: input.updatedAt,
|
|
144
|
+
});
|
|
145
|
+
if (structured) {
|
|
146
|
+
return structured;
|
|
147
|
+
}
|
|
148
|
+
if (latest.toolName === "write_todos") {
|
|
149
|
+
return getPlanStateFromToolResult({
|
|
150
|
+
sessionId: input.sessionId,
|
|
151
|
+
requestId: input.requestId,
|
|
152
|
+
output: latest.output,
|
|
153
|
+
version: input.version,
|
|
154
|
+
updatedAt: input.updatedAt,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
7
160
|
function normalizeStreamChunk(chunk) {
|
|
8
161
|
if (typeof chunk === "string") {
|
|
9
162
|
if (chunk.startsWith(AGENT_INTERRUPT_SENTINEL_PREFIX)) {
|
|
@@ -11,6 +164,9 @@ function normalizeStreamChunk(chunk) {
|
|
|
11
164
|
}
|
|
12
165
|
return { kind: "content", content: chunk };
|
|
13
166
|
}
|
|
167
|
+
if (chunk.kind === "commentary") {
|
|
168
|
+
return { kind: "commentary", content: chunk.content ?? "" };
|
|
169
|
+
}
|
|
14
170
|
if (chunk.kind === "upstream-event") {
|
|
15
171
|
return { kind: "upstream-event", event: (chunk.event ?? {}) };
|
|
16
172
|
}
|
|
@@ -28,8 +184,117 @@ function normalizeStreamChunk(chunk) {
|
|
|
28
184
|
isError: chunk.isError,
|
|
29
185
|
};
|
|
30
186
|
}
|
|
187
|
+
if (chunk.kind === "profile") {
|
|
188
|
+
return {
|
|
189
|
+
kind: "profile",
|
|
190
|
+
step: chunk.step,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
31
193
|
return { kind: "content", content: chunk.content ?? "" };
|
|
32
194
|
}
|
|
195
|
+
function normalizeCommentaryText(value) {
|
|
196
|
+
return value.replace(/\s+/g, " ").trim();
|
|
197
|
+
}
|
|
198
|
+
function ensureCommentarySentence(value) {
|
|
199
|
+
const normalized = normalizeCommentaryText(value);
|
|
200
|
+
if (!normalized) {
|
|
201
|
+
return normalized;
|
|
202
|
+
}
|
|
203
|
+
return /[.!?]$/.test(normalized) ? normalized : `${normalized}.`;
|
|
204
|
+
}
|
|
205
|
+
function summarizePlanState(planState) {
|
|
206
|
+
if (planState.summary.total <= 0) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
const counts = [
|
|
210
|
+
planState.summary.inProgress > 0 ? `${planState.summary.inProgress} in progress` : "",
|
|
211
|
+
planState.summary.pending > 0 ? `${planState.summary.pending} pending` : "",
|
|
212
|
+
planState.summary.completed > 0 ? `${planState.summary.completed} completed` : "",
|
|
213
|
+
planState.summary.blocked > 0 ? `${planState.summary.blocked} blocked` : "",
|
|
214
|
+
planState.summary.failed > 0 ? `${planState.summary.failed} failed` : "",
|
|
215
|
+
].filter((value) => value.length > 0);
|
|
216
|
+
if (counts.length === 0) {
|
|
217
|
+
counts.push(`${planState.summary.total} total`);
|
|
218
|
+
}
|
|
219
|
+
return `Plan updated: ${counts.join(", ")}.`;
|
|
220
|
+
}
|
|
221
|
+
function createSurfaceCommentary(surfaceItem) {
|
|
222
|
+
const name = normalizeCommentaryText(surfaceItem.name);
|
|
223
|
+
if (!name) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
if (surfaceItem.kind === "tool") {
|
|
227
|
+
if (surfaceItem.status === "started") {
|
|
228
|
+
return `Running tool ${name}.`;
|
|
229
|
+
}
|
|
230
|
+
if (surfaceItem.status === "completed") {
|
|
231
|
+
return `Tool ${name} completed.`;
|
|
232
|
+
}
|
|
233
|
+
if (surfaceItem.status === "failed") {
|
|
234
|
+
return `Tool ${name} failed.`;
|
|
235
|
+
}
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
if (surfaceItem.kind === "skill") {
|
|
239
|
+
if (surfaceItem.status === "started") {
|
|
240
|
+
return `Applying skill ${name}.`;
|
|
241
|
+
}
|
|
242
|
+
if (surfaceItem.status === "completed") {
|
|
243
|
+
return `Skill ${name} applied.`;
|
|
244
|
+
}
|
|
245
|
+
if (surfaceItem.status === "failed") {
|
|
246
|
+
return `Skill ${name} failed.`;
|
|
247
|
+
}
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
if (surfaceItem.kind === "agent") {
|
|
251
|
+
if (surfaceItem.status === "started") {
|
|
252
|
+
return `Delegating work to ${name}.`;
|
|
253
|
+
}
|
|
254
|
+
if (surfaceItem.status === "completed") {
|
|
255
|
+
return `Delegation to ${name} completed.`;
|
|
256
|
+
}
|
|
257
|
+
if (surfaceItem.status === "failed") {
|
|
258
|
+
return `Delegation to ${name} failed.`;
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
if (surfaceItem.kind === "llm") {
|
|
263
|
+
if (surfaceItem.status === "started") {
|
|
264
|
+
return `Running model ${name}.`;
|
|
265
|
+
}
|
|
266
|
+
if (surfaceItem.status === "completed") {
|
|
267
|
+
return `Model ${name} completed.`;
|
|
268
|
+
}
|
|
269
|
+
if (surfaceItem.status === "failed") {
|
|
270
|
+
return `Model ${name} failed.`;
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
if (surfaceItem.kind === "memory") {
|
|
275
|
+
if (surfaceItem.status === "started") {
|
|
276
|
+
return `Checking memory ${name}.`;
|
|
277
|
+
}
|
|
278
|
+
if (surfaceItem.status === "completed") {
|
|
279
|
+
return ensureCommentarySentence(`Finished checking memory ${name}`);
|
|
280
|
+
}
|
|
281
|
+
if (surfaceItem.status === "failed") {
|
|
282
|
+
return `Memory ${name} failed.`;
|
|
283
|
+
}
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
function createProfileStepCommentary(step) {
|
|
289
|
+
const name = normalizeCommentaryText(step.name);
|
|
290
|
+
if (!name || step.status !== "started") {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
if (step.kind === "memory") {
|
|
294
|
+
return `Checking memory ${name}.`;
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
33
298
|
function isOpenAICompatibleStreamingCompatibilityError(binding, error) {
|
|
34
299
|
const primaryModel = getBindingPrimaryModel(binding);
|
|
35
300
|
if (primaryModel?.provider !== "openai-compatible") {
|
|
@@ -38,33 +303,107 @@ function isOpenAICompatibleStreamingCompatibilityError(binding, error) {
|
|
|
38
303
|
const message = error instanceof Error ? error.message : String(error);
|
|
39
304
|
return message.toLowerCase().includes("received empty response from chat model call");
|
|
40
305
|
}
|
|
306
|
+
function createRuntimeMemoryRecallSteps(sessionId, requestId, items) {
|
|
307
|
+
if (items.length === 0) {
|
|
308
|
+
return [];
|
|
309
|
+
}
|
|
310
|
+
const timestamp = new Date().toISOString();
|
|
311
|
+
const scopes = Array.from(new Set(items.map((item) => item.scope)));
|
|
312
|
+
const primaryScope = scopes.length === 1 ? scopes[0] : "mixed";
|
|
313
|
+
const primarySummary = items[0]?.summary;
|
|
314
|
+
const name = scopes.length === 1 ? `durable ${primaryScope} memory` : "durable memory";
|
|
315
|
+
const detail = {
|
|
316
|
+
source: "runtime-durable-memory",
|
|
317
|
+
scope: primaryScope,
|
|
318
|
+
scopes,
|
|
319
|
+
count: items.length,
|
|
320
|
+
summaries: items.map((item) => item.summary).slice(0, 5),
|
|
321
|
+
...(primarySummary ? { summary: primarySummary } : {}),
|
|
322
|
+
};
|
|
323
|
+
const startedStep = {
|
|
324
|
+
id: `runtime-memory-recall:${requestId}:started`,
|
|
325
|
+
kind: "memory",
|
|
326
|
+
name,
|
|
327
|
+
action: "recall",
|
|
328
|
+
status: "started",
|
|
329
|
+
occurredAt: timestamp,
|
|
330
|
+
detail,
|
|
331
|
+
};
|
|
332
|
+
const completedStep = {
|
|
333
|
+
...startedStep,
|
|
334
|
+
id: `runtime-memory-recall:${requestId}:completed`,
|
|
335
|
+
status: "completed",
|
|
336
|
+
};
|
|
337
|
+
return [
|
|
338
|
+
{
|
|
339
|
+
type: "profile-step",
|
|
340
|
+
sessionId,
|
|
341
|
+
requestId,
|
|
342
|
+
step: startedStep,
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
type: "profile-step",
|
|
346
|
+
sessionId,
|
|
347
|
+
requestId,
|
|
348
|
+
step: completedStep,
|
|
349
|
+
},
|
|
350
|
+
];
|
|
351
|
+
}
|
|
41
352
|
export async function* streamHarnessRun(options) {
|
|
42
353
|
const priorHistoryPromise = Promise.resolve(options.isNewSession ? [] : undefined).then((historyHint) => historyHint ?? options.loadPriorHistory(options.sessionId, options.requestId));
|
|
43
354
|
yield { type: "event", event: await options.requestCreatedEventPromise };
|
|
355
|
+
let planStateVersion = 0;
|
|
356
|
+
let lastPlanStateSignature;
|
|
357
|
+
let currentPlanState = null;
|
|
44
358
|
let releaseRunSlot = async () => undefined;
|
|
45
359
|
let emitted = false;
|
|
46
360
|
let streamActivityObserved = false;
|
|
47
361
|
let nonUpstreamStreamActivityObserved = false;
|
|
362
|
+
let assistantOutput = "";
|
|
48
363
|
let currentAgentId = options.selectedAgentId;
|
|
49
364
|
let currentAgentName = formatAgentName(options.selectedAgentId);
|
|
50
365
|
let delegationChain = [options.selectedAgentId];
|
|
51
366
|
let upstreamEventOrdinal = 0;
|
|
52
367
|
let syntheticFallback;
|
|
368
|
+
const emittedCommentary = new Set();
|
|
369
|
+
const emitCommentary = function* (content) {
|
|
370
|
+
const normalized = normalizeCommentaryText(content);
|
|
371
|
+
if (!normalized || emittedCommentary.has(normalized)) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
emittedCommentary.add(normalized);
|
|
375
|
+
yield {
|
|
376
|
+
type: "commentary",
|
|
377
|
+
sessionId: options.sessionId,
|
|
378
|
+
requestId: options.requestId,
|
|
379
|
+
agentId: currentAgentId,
|
|
380
|
+
content: normalized,
|
|
381
|
+
};
|
|
382
|
+
};
|
|
53
383
|
try {
|
|
54
384
|
const [priorHistory, acquiredReleaseRunSlot] = await Promise.all([
|
|
55
385
|
priorHistoryPromise,
|
|
56
386
|
options.releaseRequestSlotPromise,
|
|
57
387
|
]).then(([loadedPriorHistory, resolvedReleaseRunSlot]) => [loadedPriorHistory, resolvedReleaseRunSlot]);
|
|
58
388
|
releaseRunSlot = acquiredReleaseRunSlot;
|
|
59
|
-
let assistantOutput = "";
|
|
60
389
|
const toolErrors = [];
|
|
61
390
|
let lastToolResultKey = null;
|
|
391
|
+
const recalledMemories = options.invocation.memoryRecall?.items ?? [];
|
|
392
|
+
for (const item of createRuntimeMemoryRecallSteps(options.sessionId, options.requestId, recalledMemories)) {
|
|
393
|
+
yield item;
|
|
394
|
+
if (item.type === "profile-step") {
|
|
395
|
+
const commentary = createProfileStepCommentary(item.step);
|
|
396
|
+
if (commentary) {
|
|
397
|
+
yield* emitCommentary(commentary);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
62
401
|
for await (const rawChunk of options.stream(options.binding, options.input, options.sessionId, priorHistory, {
|
|
63
402
|
context: options.invocation.context,
|
|
64
403
|
state: options.invocation.state,
|
|
65
404
|
files: options.invocation.files,
|
|
66
405
|
requestId: options.requestId,
|
|
67
|
-
memoryContext: options.invocation.
|
|
406
|
+
memoryContext: options.invocation.memoryRecall?.prompt,
|
|
68
407
|
})) {
|
|
69
408
|
if (!rawChunk) {
|
|
70
409
|
continue;
|
|
@@ -72,6 +411,32 @@ export async function* streamHarnessRun(options) {
|
|
|
72
411
|
streamActivityObserved = true;
|
|
73
412
|
const normalizedChunk = normalizeStreamChunk(rawChunk);
|
|
74
413
|
if (normalizedChunk.kind === "upstream-event") {
|
|
414
|
+
const upstreamPlanState = getPlanStateFromUpstreamEvent({
|
|
415
|
+
sessionId: options.sessionId,
|
|
416
|
+
requestId: options.requestId,
|
|
417
|
+
event: normalizedChunk.event,
|
|
418
|
+
version: planStateVersion + 1,
|
|
419
|
+
updatedAt: new Date().toISOString(),
|
|
420
|
+
});
|
|
421
|
+
if (upstreamPlanState) {
|
|
422
|
+
const signature = buildPlanStateSignature(upstreamPlanState);
|
|
423
|
+
if (signature !== lastPlanStateSignature && shouldEmitPlanState(currentPlanState, upstreamPlanState)) {
|
|
424
|
+
planStateVersion = upstreamPlanState.version;
|
|
425
|
+
lastPlanStateSignature = signature;
|
|
426
|
+
currentPlanState = upstreamPlanState;
|
|
427
|
+
yield {
|
|
428
|
+
type: "plan-state",
|
|
429
|
+
sessionId: options.sessionId,
|
|
430
|
+
requestId: options.requestId,
|
|
431
|
+
agentId: currentAgentId,
|
|
432
|
+
planState: upstreamPlanState,
|
|
433
|
+
};
|
|
434
|
+
const commentary = summarizePlanState(upstreamPlanState);
|
|
435
|
+
if (commentary) {
|
|
436
|
+
yield* emitCommentary(commentary);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
75
440
|
upstreamEventOrdinal += 1;
|
|
76
441
|
const projectionBinding = options.getBinding(currentAgentId) ?? options.binding;
|
|
77
442
|
const surfaceProjection = projectRuntimeSurfaceFromSingleUpstreamEvent({
|
|
@@ -121,6 +486,10 @@ export async function* streamHarnessRun(options) {
|
|
|
121
486
|
surfaceItem,
|
|
122
487
|
event: normalizedChunk.event,
|
|
123
488
|
};
|
|
489
|
+
const commentary = createSurfaceCommentary(surfaceItem);
|
|
490
|
+
if (commentary) {
|
|
491
|
+
yield* emitCommentary(commentary);
|
|
492
|
+
}
|
|
124
493
|
}
|
|
125
494
|
continue;
|
|
126
495
|
}
|
|
@@ -150,9 +519,26 @@ export async function* streamHarnessRun(options) {
|
|
|
150
519
|
};
|
|
151
520
|
return;
|
|
152
521
|
}
|
|
522
|
+
if (normalizedChunk.kind === "commentary") {
|
|
523
|
+
yield* emitCommentary(normalizedChunk.content);
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
153
526
|
if (normalizedChunk.kind === "reasoning") {
|
|
154
527
|
continue;
|
|
155
528
|
}
|
|
529
|
+
if (normalizedChunk.kind === "profile") {
|
|
530
|
+
yield {
|
|
531
|
+
type: "profile-step",
|
|
532
|
+
sessionId: options.sessionId,
|
|
533
|
+
requestId: options.requestId,
|
|
534
|
+
step: normalizedChunk.step,
|
|
535
|
+
};
|
|
536
|
+
const commentary = createProfileStepCommentary(normalizedChunk.step);
|
|
537
|
+
if (commentary) {
|
|
538
|
+
yield* emitCommentary(commentary);
|
|
539
|
+
}
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
156
542
|
if (normalizedChunk.kind === "tool-result") {
|
|
157
543
|
const toolResultKey = createToolResultKey(normalizedChunk.toolName, normalizedChunk.output, normalizedChunk.isError);
|
|
158
544
|
if (toolResultKey === lastToolResultKey) {
|
|
@@ -171,6 +557,39 @@ export async function* streamHarnessRun(options) {
|
|
|
171
557
|
output: normalizedChunk.output,
|
|
172
558
|
isError: normalizedChunk.isError,
|
|
173
559
|
};
|
|
560
|
+
const planState = normalizedChunk.toolName === "write_todos"
|
|
561
|
+
? getPlanStateFromToolResult({
|
|
562
|
+
sessionId: options.sessionId,
|
|
563
|
+
requestId: options.requestId,
|
|
564
|
+
output: normalizedChunk.output,
|
|
565
|
+
version: ++planStateVersion,
|
|
566
|
+
updatedAt: new Date().toISOString(),
|
|
567
|
+
})
|
|
568
|
+
: getStructuredPlanStateFromToolResult({
|
|
569
|
+
sessionId: options.sessionId,
|
|
570
|
+
requestId: options.requestId,
|
|
571
|
+
output: normalizedChunk.output,
|
|
572
|
+
version: ++planStateVersion,
|
|
573
|
+
updatedAt: new Date().toISOString(),
|
|
574
|
+
});
|
|
575
|
+
if (planState) {
|
|
576
|
+
const signature = buildPlanStateSignature(planState);
|
|
577
|
+
if (signature !== lastPlanStateSignature && shouldEmitPlanState(currentPlanState, planState)) {
|
|
578
|
+
lastPlanStateSignature = signature;
|
|
579
|
+
currentPlanState = planState;
|
|
580
|
+
yield {
|
|
581
|
+
type: "plan-state",
|
|
582
|
+
sessionId: options.sessionId,
|
|
583
|
+
requestId: options.requestId,
|
|
584
|
+
agentId: currentAgentId,
|
|
585
|
+
planState,
|
|
586
|
+
};
|
|
587
|
+
const commentary = summarizePlanState(planState);
|
|
588
|
+
if (commentary) {
|
|
589
|
+
yield* emitCommentary(commentary);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
174
593
|
continue;
|
|
175
594
|
}
|
|
176
595
|
emitted = true;
|
|
@@ -200,6 +619,32 @@ export async function* streamHarnessRun(options) {
|
|
|
200
619
|
assistantOutput = actual.output;
|
|
201
620
|
emitted = true;
|
|
202
621
|
}
|
|
622
|
+
const finalPlanState = getLatestPlanStateFromExecutedToolResults({
|
|
623
|
+
sessionId: options.sessionId,
|
|
624
|
+
requestId: options.requestId,
|
|
625
|
+
metadata: actual.metadata,
|
|
626
|
+
version: planStateVersion + 1,
|
|
627
|
+
updatedAt: new Date().toISOString(),
|
|
628
|
+
});
|
|
629
|
+
if (finalPlanState) {
|
|
630
|
+
const signature = buildPlanStateSignature(finalPlanState);
|
|
631
|
+
if (signature !== lastPlanStateSignature && shouldEmitPlanState(currentPlanState, finalPlanState)) {
|
|
632
|
+
planStateVersion = finalPlanState.version;
|
|
633
|
+
lastPlanStateSignature = signature;
|
|
634
|
+
currentPlanState = finalPlanState;
|
|
635
|
+
yield {
|
|
636
|
+
type: "plan-state",
|
|
637
|
+
sessionId: options.sessionId,
|
|
638
|
+
requestId: options.requestId,
|
|
639
|
+
agentId: currentAgentId,
|
|
640
|
+
planState: finalPlanState,
|
|
641
|
+
};
|
|
642
|
+
const commentary = summarizePlanState(finalPlanState);
|
|
643
|
+
if (commentary) {
|
|
644
|
+
yield* emitCommentary(commentary);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
203
648
|
}
|
|
204
649
|
await options.appendAssistantMessage(options.sessionId, options.requestId, assistantOutput);
|
|
205
650
|
const completedEvent = await options.setRequestStateAndEmit(options.sessionId, options.requestId, 6, "completed", {
|
|
@@ -222,8 +667,7 @@ export async function* streamHarnessRun(options) {
|
|
|
222
667
|
};
|
|
223
668
|
}
|
|
224
669
|
catch (error) {
|
|
225
|
-
const shouldRetryAfterStreamingCompatibilityError =
|
|
226
|
-
!nonUpstreamStreamActivityObserved &&
|
|
670
|
+
const shouldRetryAfterStreamingCompatibilityError = !assistantOutput &&
|
|
227
671
|
isOpenAICompatibleStreamingCompatibilityError(options.binding, error);
|
|
228
672
|
if ((emitted || streamActivityObserved) && !shouldRetryAfterStreamingCompatibilityError) {
|
|
229
673
|
const runtimeFailure = renderRuntimeFailure(error);
|
|
@@ -34,24 +34,18 @@ export function stripStepPrefix(label) {
|
|
|
34
34
|
.replace(/^Accessing memory\s+/i, "")
|
|
35
35
|
.replace(/^Completed memory\s+/i, "");
|
|
36
36
|
}
|
|
37
|
-
function isGenericMemoryMiddlewareName(value) {
|
|
38
|
-
return /^(memorymiddleware\.before[_\s]?agent|memory middleware before agent)$/i.test(normalizeLabel(value));
|
|
39
|
-
}
|
|
40
37
|
function canonicalMemoryName(memorySource) {
|
|
41
38
|
const normalized = normalizeLabel(memorySource.replace(/^memory\//i, ""));
|
|
42
39
|
const segments = normalized.split(/[\\/]/).filter(Boolean);
|
|
43
40
|
return (segments.at(-1) ?? normalized).toLowerCase() || "memory";
|
|
44
41
|
}
|
|
45
|
-
function isGenericSkillMiddlewareName(value) {
|
|
46
|
-
return /^(skillsmiddleware\.before[_\s]?agent|skills middleware before agent)$/i.test(normalizeLabel(value));
|
|
47
|
-
}
|
|
48
42
|
export function resolveSurfaceDisplayName(input) {
|
|
49
43
|
const baseName = stripStepPrefix(input.step) || formatAgentName(input.kind);
|
|
50
|
-
if (input.kind === "memory" && input.binding &&
|
|
44
|
+
if (input.kind === "memory" && input.binding && baseName.length === 0) {
|
|
51
45
|
const memorySources = getBindingMemorySources(input.binding).filter((name) => name.trim().length > 0);
|
|
52
46
|
return memorySources.length === 1 ? canonicalMemoryName(memorySources[0]) : baseName;
|
|
53
47
|
}
|
|
54
|
-
if (input.kind !== "skill" || !input.binding ||
|
|
48
|
+
if (input.kind !== "skill" || !input.binding || baseName.length > 0) {
|
|
55
49
|
return baseName;
|
|
56
50
|
}
|
|
57
51
|
const skillNames = getBindingSkills(input.binding)
|
|
@@ -59,32 +53,11 @@ export function resolveSurfaceDisplayName(input) {
|
|
|
59
53
|
.filter((name) => typeof name === "string" && name.trim().length > 0);
|
|
60
54
|
return skillNames.length === 1 ? skillNames[0] : baseName;
|
|
61
55
|
}
|
|
62
|
-
function
|
|
63
|
-
return value
|
|
64
|
-
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
65
|
-
.replace(/[.:/]+/g, " ")
|
|
66
|
-
.replace(/[_-]+/g, " ")
|
|
67
|
-
.replace(/\s+/g, " ")
|
|
68
|
-
.trim()
|
|
69
|
-
.toLowerCase();
|
|
70
|
-
}
|
|
71
|
-
function resolveMemoryAction(event, step) {
|
|
56
|
+
function resolveMemoryAction(event) {
|
|
72
57
|
const typed = asObject(event);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
typeof typed?.run_type === "string" ? typed.run_type : "",
|
|
77
|
-
...readStringArray(typed?.tags),
|
|
78
|
-
...readStringArray(typed?.ns),
|
|
79
|
-
step,
|
|
80
|
-
].map(normalizeActionHint);
|
|
81
|
-
if (hints.some((value) => /\b(store|memorize|sync|formation|ingestion|archive|write)\b/.test(value))) {
|
|
82
|
-
return "memorize";
|
|
83
|
-
}
|
|
84
|
-
if (hints.some((value) => /\b(recall|retrieve|memorymiddleware|before agent|checkpoint|context)\b/.test(value)
|
|
85
|
-
|| value.includes("accessing memory")
|
|
86
|
-
|| value.includes("access memory"))) {
|
|
87
|
-
return "recall";
|
|
58
|
+
const runType = typeof typed?.run_type === "string" ? typed.run_type.trim().toLowerCase() : "";
|
|
59
|
+
if (runType === "memory") {
|
|
60
|
+
return "access";
|
|
88
61
|
}
|
|
89
62
|
return "access";
|
|
90
63
|
}
|
|
@@ -99,7 +72,7 @@ export function resolveSurfaceAction(input) {
|
|
|
99
72
|
case "skill":
|
|
100
73
|
return "apply";
|
|
101
74
|
case "memory":
|
|
102
|
-
return resolveMemoryAction(input.event
|
|
75
|
+
return resolveMemoryAction(input.event);
|
|
103
76
|
default:
|
|
104
77
|
return "run";
|
|
105
78
|
}
|
|
@@ -10,6 +10,7 @@ export type ResolvedRuntimeMemoryFormationConfig = {
|
|
|
10
10
|
enabled: boolean;
|
|
11
11
|
strategy: "rules" | "model";
|
|
12
12
|
modelRef?: string;
|
|
13
|
+
prompt?: string;
|
|
13
14
|
maxContextRecords: number;
|
|
14
15
|
};
|
|
15
16
|
background: {
|
|
@@ -64,6 +65,8 @@ export declare function runModelMemoryManager(input: {
|
|
|
64
65
|
requestId: string;
|
|
65
66
|
recordedAt: string;
|
|
66
67
|
existingRecords: MemoryRecord[];
|
|
68
|
+
maxContextRecords?: number;
|
|
69
|
+
promptTemplate?: string;
|
|
67
70
|
modelResolver?: (modelId: string) => unknown;
|
|
68
71
|
}): Promise<MemoryCandidate[]>;
|
|
69
72
|
export declare function createRuntimeMemoryManager(input: {
|