@botbotgo/agent-harness 0.0.323 → 0.0.325
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/README.zh.md +2 -1
- package/dist/cli/chat-ui.js +3 -2
- package/dist/cli/main.js +84 -2
- package/dist/cli/managed-service.d.ts +2 -1
- package/dist/cli/managed-service.js +78 -2
- package/dist/cli/options-serve.d.ts +13 -0
- package/dist/cli/options-serve.js +116 -0
- package/dist/cli/options.d.ts +1 -1
- package/dist/cli/options.js +7 -1
- package/dist/cli/server-commands.d.ts +1 -1
- package/dist/cli/server-commands.js +28 -8
- package/dist/config/knowledge/knowledge-runtime.yaml +3 -2
- package/dist/config/prompts/orchestra-system.md +4 -0
- package/dist/config/runtime/runtime-memory.yaml +3 -2
- package/dist/knowledge/module.js +2 -1
- package/dist/package-version.d.ts +2 -1
- package/dist/package-version.js +2 -1
- package/dist/resource/isolation.js +28 -0
- package/dist/resources/prompts/runtime/autonomous-investigation-recovery.md +1 -1
- package/dist/resources/prompts/runtime/durable-memory-context.md +2 -0
- package/dist/resources/prompts/runtime/execution-with-tool-evidence-retry.md +1 -1
- package/dist/resources/prompts/runtime/write-todos-required-plan.md +1 -0
- package/dist/runtime/adapter/flow/stream-runtime.js +9 -141
- package/dist/runtime/adapter/model/invocation-request.js +1 -1
- package/dist/runtime/adapter/tool/builtin-middleware-tools.js +22 -8
- package/dist/runtime/harness/run/stream-run.js +17 -0
- package/dist/runtime/harness/system/runtime-memory-manager.js +4 -0
- package/dist/runtime/harness/system/runtime-memory-policy.d.ts +14 -0
- package/dist/runtime/harness/system/runtime-memory-policy.js +19 -0
- package/dist/runtime/parsing/output-parsing.d.ts +2 -1
- package/dist/runtime/parsing/output-parsing.js +2 -1
- package/dist/runtime/parsing/output-recovery.d.ts +4 -2
- package/dist/runtime/parsing/output-recovery.js +30 -264
- package/dist/runtime/prompts/runtime-prompts.d.ts +1 -0
- package/dist/runtime/prompts/runtime-prompts.js +1 -0
- package/dist/scaffold/init-project.js +6 -4
- package/dist/tools.js +25 -2
- package/package.json +1 -1
|
@@ -6,6 +6,10 @@ import { existsSync } from "node:fs";
|
|
|
6
6
|
import { cp, mkdir, readFile, stat, symlink } from "node:fs/promises";
|
|
7
7
|
const HARNESS_PACKAGE_NAME = "@botbotgo/agent-harness";
|
|
8
8
|
const HARNESS_PACKAGE_ROOT = path.resolve(import.meta.dirname, "..", "..");
|
|
9
|
+
const HARNESS_TOOL_AUTHORING_DEPENDENCIES = [
|
|
10
|
+
"@langchain/core",
|
|
11
|
+
"zod",
|
|
12
|
+
];
|
|
9
13
|
const isolatedResourceRootCache = new Map();
|
|
10
14
|
const isolatedResourceRootBuilds = new Map();
|
|
11
15
|
function isolationCacheRoot() {
|
|
@@ -91,6 +95,29 @@ async function linkHarnessPackage(isolatedRoot) {
|
|
|
91
95
|
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
92
96
|
await symlink(HARNESS_PACKAGE_ROOT, targetPath, "junction");
|
|
93
97
|
}
|
|
98
|
+
function resolveHarnessOwnedDependency(dependencyName) {
|
|
99
|
+
try {
|
|
100
|
+
const requireFromHarness = createRequire(path.join(HARNESS_PACKAGE_ROOT, "package.json"));
|
|
101
|
+
return dependencyPackageRoot(requireFromHarness.resolve(`${dependencyName}/package.json`));
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function linkHarnessToolAuthoringDependencies(isolatedRoot) {
|
|
108
|
+
for (const dependencyName of HARNESS_TOOL_AUTHORING_DEPENDENCIES) {
|
|
109
|
+
const targetPath = dependencyLinkPath(isolatedRoot, dependencyName);
|
|
110
|
+
if (existsSync(targetPath)) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const resolved = resolveHarnessOwnedDependency(dependencyName);
|
|
114
|
+
if (!resolved) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
118
|
+
await symlink(resolved, targetPath, "junction");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
94
121
|
async function buildIsolatedResourceRoot(packageRoot) {
|
|
95
122
|
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
96
123
|
const manifest = existsSync(packageJsonPath)
|
|
@@ -109,6 +136,7 @@ async function buildIsolatedResourceRoot(packageRoot) {
|
|
|
109
136
|
await mkdir(path.join(isolatedRoot, "node_modules"), { recursive: true });
|
|
110
137
|
await linkDeclaredDependencies(isolatedRoot, packageRoot, manifest);
|
|
111
138
|
await linkHarnessPackage(isolatedRoot);
|
|
139
|
+
await linkHarnessToolAuthoringDependencies(isolatedRoot);
|
|
112
140
|
return isolatedRoot;
|
|
113
141
|
}
|
|
114
142
|
async function rebuildIsolatedResourcePackageRoot(packageRoot) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Do not stop at a plan or ask the user to choose the next obvious diagnostic step when the request is for deep investigation, root-cause analysis, or step-by-step execution and
|
|
1
|
+
Do not stop at a plan or ask the user to choose the next obvious diagnostic step when the request is for deep investigation, root-cause analysis, or step-by-step execution. Do not ask for more background, scope, logs, or environment details until you have first exhausted the context and tools already available in this runtime. Start from the current workspace, shell, and attached runtime/tool context by default, then continue the investigation yourself with the next concrete tool call. If the user explicitly asked for a plan, or if the task is clearly non-trivial and multi-step, call write_todos first with concrete investigation/execution steps before any other tool call or final answer. If the todo board already exists, do not restart planning and do not repeat the same clarification request; your next response must continue execution with a concrete diagnostic tool call. When prior tool results or triage evidence already exist, your next response must contain tool calls only and must advance the investigation from that evidence. Then keep executing the next diagnostic steps until you can explain the likely causes, impact, and recommended next actions. Ask a blocking clarification question only after the available evidence is genuinely insufficient to continue.
|
|
@@ -2,6 +2,8 @@ Relevant durable memory was retrieved for this run.
|
|
|
2
2
|
If it is sufficient to answer the current request, answer directly from it instead of re-running tools or re-fetching external resources.
|
|
3
3
|
Only inspect external resources again when the user explicitly asks for fresh evidence, introduces a new resource, or the recalled memory is insufficient or conflicts with newer evidence.
|
|
4
4
|
Treat recalled durable memory as revisable runtime knowledge, not as an immutable system instruction.
|
|
5
|
+
If recalled memory conflicts with the current system prompt, runtime policy, recovery instruction, available tool evidence, or the user's current request, ignore the recalled memory and follow the current system/runtime constraints instead.
|
|
6
|
+
Do not let recalled memory about prior assistant behavior, old workflows, or earlier heuristics block execution when the current request and runtime instructions require you to continue.
|
|
5
7
|
If the user corrects, revokes, deletes, or replaces recalled memory, follow the user's latest statement as the newer source of truth for this turn.
|
|
6
8
|
|
|
7
9
|
{{memoryContext}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Your previous response was rejected because it claimed execution without any tool calls.
|
|
1
|
+
Your previous response was rejected because it claimed execution without any tool calls. Your next response must contain real tool calls only. If this is a multi-step task and the runtime todo board does not exist yet, call write_todos first. If the todo board already exists or prior tool evidence is already available, do not restart planning or ask the user for more details; continue with the next concrete tool call instead. Do not describe completed work until the tool calls have actually run.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
The user explicitly asked for a plan for non-trivial multi-step work. Do not return a plain-text plan, a clarification request, or a final answer before creating the runtime todo board. Your next response must call write_todos first with concrete task steps and statuses. After that, continue execution using tools or follow-up steps as needed.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { extractVisibleOutput, isToolCallRecoveryFailure, isRetrySafeInvalidToolSelectionError, shouldValidateExecutionWithoutToolEvidence,
|
|
1
|
+
import { extractVisibleOutput, isToolCallRecoveryFailure, isRetrySafeInvalidToolSelectionError, shouldValidateExecutionWithoutToolEvidence, resolveToolCallRecoveryInstruction, sanitizeVisibleText, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, } from "../../parsing/output-parsing.js";
|
|
2
2
|
import { buildInvocationRequest } from "../model/invocation-request.js";
|
|
3
3
|
import { buildRawModelMessages } from "../model/message-assembly.js";
|
|
4
4
|
import { projectRuntimeStreamEvent, createStreamEventProjectionState } from "../stream-event-projection.js";
|
|
@@ -49,7 +49,6 @@ export async function* streamRuntimeExecution(options) {
|
|
|
49
49
|
const shouldValidateStreamOutput = shouldValidateExecutionWithoutToolEvidence(request);
|
|
50
50
|
const deferredStreamContent = [];
|
|
51
51
|
let sawRetrySafeInvalidToolSelectionError = false;
|
|
52
|
-
let sawNonRetrySafeToolSideEffects = false;
|
|
53
52
|
const shouldDeferStreamContent = () => shouldValidateStreamOutput && !emittedUnsafeStreamSideEffects;
|
|
54
53
|
const flushDeferredStreamContent = async function* () {
|
|
55
54
|
while (deferredStreamContent.length > 0) {
|
|
@@ -248,7 +247,6 @@ export async function* streamRuntimeExecution(options) {
|
|
|
248
247
|
}
|
|
249
248
|
if (eventContainsNonTodoToolResult || eventContainsNonRetrySafeChunk) {
|
|
250
249
|
emittedUnsafeStreamSideEffects = true;
|
|
251
|
-
sawNonRetrySafeToolSideEffects = true;
|
|
252
250
|
}
|
|
253
251
|
if (chunk.kind === "content" && shouldDeferStreamContent()) {
|
|
254
252
|
deferredStreamContent.push(chunk);
|
|
@@ -280,53 +278,10 @@ export async function* streamRuntimeExecution(options) {
|
|
|
280
278
|
});
|
|
281
279
|
throw error;
|
|
282
280
|
}
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
?? (!emittedUnsafeStreamSideEffects && sawRetrySafeInvalidToolSelectionError ? INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION : null);
|
|
286
|
-
if (!emittedUnsafeStreamSideEffects && terminalRecoveryInstruction) {
|
|
287
|
-
const toolRecovery = startProfileStep({
|
|
288
|
-
id: "profile:agent:stream-output-recovery-fallback",
|
|
289
|
-
kind: "agent",
|
|
290
|
-
name: "stream output recovery fallback",
|
|
291
|
-
action: "invoke",
|
|
292
|
-
detail: {
|
|
293
|
-
recoveryInstruction: terminalRecoveryInstruction,
|
|
294
|
-
},
|
|
295
|
-
});
|
|
296
|
-
if (shouldProfile)
|
|
297
|
-
yield toolRecovery.chunk;
|
|
281
|
+
const terminalRecoveryInstruction = !emittedUnsafeStreamSideEffects && sawRetrySafeInvalidToolSelectionError ? INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION : null;
|
|
282
|
+
if (terminalRecoveryInstruction) {
|
|
298
283
|
let retried;
|
|
299
|
-
|
|
300
|
-
retried = await options.invoke(options.applyToolRecoveryInstruction(options.binding, terminalRecoveryInstruction), options.input, options.sessionId, options.runtimeOptions.requestId ?? options.sessionId, undefined, options.history, options.runtimeOptions);
|
|
301
|
-
if (shouldProfile)
|
|
302
|
-
yield finishProfileStep({
|
|
303
|
-
id: "profile:agent:stream-output-recovery-fallback",
|
|
304
|
-
kind: "agent",
|
|
305
|
-
name: "stream output recovery fallback",
|
|
306
|
-
action: "invoke",
|
|
307
|
-
startedAt: toolRecovery.startedAt,
|
|
308
|
-
status: "completed",
|
|
309
|
-
detail: {
|
|
310
|
-
recoveryInstruction: terminalRecoveryInstruction,
|
|
311
|
-
},
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
catch (retryError) {
|
|
315
|
-
if (shouldProfile)
|
|
316
|
-
yield finishProfileStep({
|
|
317
|
-
id: "profile:agent:stream-output-recovery-fallback",
|
|
318
|
-
kind: "agent",
|
|
319
|
-
name: "stream output recovery fallback",
|
|
320
|
-
action: "invoke",
|
|
321
|
-
startedAt: toolRecovery.startedAt,
|
|
322
|
-
status: "failed",
|
|
323
|
-
detail: {
|
|
324
|
-
recoveryInstruction: terminalRecoveryInstruction,
|
|
325
|
-
},
|
|
326
|
-
error: retryError,
|
|
327
|
-
});
|
|
328
|
-
throw retryError;
|
|
329
|
-
}
|
|
284
|
+
retried = await options.invoke(options.applyToolRecoveryInstruction(options.binding, terminalRecoveryInstruction), options.input, options.sessionId, options.runtimeOptions.requestId ?? options.sessionId, undefined, options.history, options.runtimeOptions);
|
|
330
285
|
const executedToolResults = Array.isArray(retried.metadata?.executedToolResults)
|
|
331
286
|
? retried.metadata.executedToolResults
|
|
332
287
|
: [];
|
|
@@ -340,9 +295,8 @@ export async function* streamRuntimeExecution(options) {
|
|
|
340
295
|
}
|
|
341
296
|
if (retried.output) {
|
|
342
297
|
const visible = toVisibleContent(retried.output);
|
|
343
|
-
if (visible)
|
|
298
|
+
if (visible)
|
|
344
299
|
yield { kind: "content", content: visible };
|
|
345
|
-
}
|
|
346
300
|
}
|
|
347
301
|
return;
|
|
348
302
|
}
|
|
@@ -492,49 +446,7 @@ export async function* streamRuntimeExecution(options) {
|
|
|
492
446
|
}
|
|
493
447
|
catch (error) {
|
|
494
448
|
if (!emittedUnsafeStreamSideEffects && options.isRetryableProviderError?.(options.binding, error)) {
|
|
495
|
-
const
|
|
496
|
-
id: "profile:agent:provider-retry-fallback",
|
|
497
|
-
kind: "agent",
|
|
498
|
-
name: "provider retry fallback",
|
|
499
|
-
action: "invoke",
|
|
500
|
-
detail: {
|
|
501
|
-
error: error instanceof Error ? error.message : String(error),
|
|
502
|
-
},
|
|
503
|
-
});
|
|
504
|
-
if (shouldProfile)
|
|
505
|
-
yield providerRetry.chunk;
|
|
506
|
-
let recovered;
|
|
507
|
-
try {
|
|
508
|
-
recovered = await options.invoke(options.binding, options.input, options.sessionId, options.runtimeOptions.requestId ?? options.sessionId, undefined, options.history, options.runtimeOptions);
|
|
509
|
-
if (shouldProfile)
|
|
510
|
-
yield finishProfileStep({
|
|
511
|
-
id: "profile:agent:provider-retry-fallback",
|
|
512
|
-
kind: "agent",
|
|
513
|
-
name: "provider retry fallback",
|
|
514
|
-
action: "invoke",
|
|
515
|
-
startedAt: providerRetry.startedAt,
|
|
516
|
-
status: "completed",
|
|
517
|
-
detail: {
|
|
518
|
-
error: error instanceof Error ? error.message : String(error),
|
|
519
|
-
},
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
catch (retryError) {
|
|
523
|
-
if (shouldProfile)
|
|
524
|
-
yield finishProfileStep({
|
|
525
|
-
id: "profile:agent:provider-retry-fallback",
|
|
526
|
-
kind: "agent",
|
|
527
|
-
name: "provider retry fallback",
|
|
528
|
-
action: "invoke",
|
|
529
|
-
startedAt: providerRetry.startedAt,
|
|
530
|
-
status: "failed",
|
|
531
|
-
detail: {
|
|
532
|
-
error: error instanceof Error ? error.message : String(error),
|
|
533
|
-
},
|
|
534
|
-
error: retryError,
|
|
535
|
-
});
|
|
536
|
-
throw retryError;
|
|
537
|
-
}
|
|
449
|
+
const recovered = await options.invoke(options.binding, options.input, options.sessionId, options.runtimeOptions.requestId ?? options.sessionId, undefined, options.history, options.runtimeOptions);
|
|
538
450
|
const executedToolResults = Array.isArray(recovered.metadata?.executedToolResults)
|
|
539
451
|
? recovered.metadata.executedToolResults
|
|
540
452
|
: [];
|
|
@@ -548,9 +460,8 @@ export async function* streamRuntimeExecution(options) {
|
|
|
548
460
|
}
|
|
549
461
|
if (recovered.output) {
|
|
550
462
|
const visible = toVisibleContent(recovered.output);
|
|
551
|
-
if (visible)
|
|
463
|
+
if (visible)
|
|
552
464
|
yield { kind: "content", content: visible };
|
|
553
|
-
}
|
|
554
465
|
}
|
|
555
466
|
return;
|
|
556
467
|
}
|
|
@@ -566,54 +477,11 @@ export async function* streamRuntimeExecution(options) {
|
|
|
566
477
|
if (!recoveryInstruction) {
|
|
567
478
|
throw error;
|
|
568
479
|
}
|
|
569
|
-
const
|
|
570
|
-
id: "profile:agent:tool-recovery-fallback",
|
|
571
|
-
kind: "agent",
|
|
572
|
-
name: "tool recovery fallback",
|
|
573
|
-
action: "invoke",
|
|
574
|
-
detail: {
|
|
575
|
-
recoveryInstruction,
|
|
576
|
-
},
|
|
577
|
-
});
|
|
578
|
-
if (shouldProfile)
|
|
579
|
-
yield toolRecovery.chunk;
|
|
580
|
-
let retried;
|
|
581
|
-
try {
|
|
582
|
-
retried = await options.invoke(options.applyToolRecoveryInstruction(options.binding, recoveryInstruction), options.input, options.sessionId, options.runtimeOptions.requestId ?? options.sessionId, undefined, options.history, options.runtimeOptions);
|
|
583
|
-
if (shouldProfile)
|
|
584
|
-
yield finishProfileStep({
|
|
585
|
-
id: "profile:agent:tool-recovery-fallback",
|
|
586
|
-
kind: "agent",
|
|
587
|
-
name: "tool recovery fallback",
|
|
588
|
-
action: "invoke",
|
|
589
|
-
startedAt: toolRecovery.startedAt,
|
|
590
|
-
status: "completed",
|
|
591
|
-
detail: {
|
|
592
|
-
recoveryInstruction,
|
|
593
|
-
},
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
catch (retryError) {
|
|
597
|
-
if (shouldProfile)
|
|
598
|
-
yield finishProfileStep({
|
|
599
|
-
id: "profile:agent:tool-recovery-fallback",
|
|
600
|
-
kind: "agent",
|
|
601
|
-
name: "tool recovery fallback",
|
|
602
|
-
action: "invoke",
|
|
603
|
-
startedAt: toolRecovery.startedAt,
|
|
604
|
-
status: "failed",
|
|
605
|
-
detail: {
|
|
606
|
-
recoveryInstruction,
|
|
607
|
-
},
|
|
608
|
-
error: retryError,
|
|
609
|
-
});
|
|
610
|
-
throw retryError;
|
|
611
|
-
}
|
|
480
|
+
const retried = await options.invoke(options.applyToolRecoveryInstruction(options.binding, recoveryInstruction), options.input, options.sessionId, options.runtimeOptions.requestId ?? options.sessionId, undefined, options.history, options.runtimeOptions);
|
|
612
481
|
if (retried.output) {
|
|
613
482
|
const visible = toVisibleContent(retried.output);
|
|
614
|
-
if (visible)
|
|
483
|
+
if (visible)
|
|
615
484
|
yield { kind: "content", content: visible };
|
|
616
|
-
}
|
|
617
485
|
}
|
|
618
486
|
}
|
|
619
487
|
}
|
|
@@ -123,7 +123,7 @@ function buildContextualFollowUpInstruction(inputText, hasDurableMemory) {
|
|
|
123
123
|
if (!hasDurableMemory || hasExplicitResourceReference(inputText)) {
|
|
124
124
|
return undefined;
|
|
125
125
|
}
|
|
126
|
-
return "Answer the user's current follow-up directly from the recalled context. If the current user turn corrects, revokes, deletes, or replaces recalled memory, treat the user's latest statement as newer than the recalled memory for this turn. Do not frame the reply as a fresh URL or page summary unless the current user turn explicitly includes a new resource to inspect.";
|
|
126
|
+
return "Answer the user's current follow-up directly from the recalled context when it remains relevant. If recalled memory conflicts with the current system prompt, runtime policy, recovery instruction, available tool evidence, or the user's current request, ignore the recalled memory for this turn. If the current user turn corrects, revokes, deletes, or replaces recalled memory, treat the user's latest statement as newer than the recalled memory for this turn. Do not frame the reply as a fresh URL or page summary unless the current user turn explicitly includes a new resource to inspect.";
|
|
127
127
|
}
|
|
128
128
|
export function buildSlashCommandSkillInstruction(binding, input) {
|
|
129
129
|
const inputText = extractMessageText(input).trim();
|
|
@@ -121,6 +121,27 @@ function formatHttpResponse(result) {
|
|
|
121
121
|
];
|
|
122
122
|
return lines.length > 0 ? lines.join("\n") : "Request completed.";
|
|
123
123
|
}
|
|
124
|
+
async function fetchUrlWithRuntimeFallback(backend, url) {
|
|
125
|
+
if (typeof backend.fetchUrl === "function") {
|
|
126
|
+
try {
|
|
127
|
+
const result = await Promise.resolve(backend.fetchUrl(url));
|
|
128
|
+
if (typeof result === "string") {
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
return formatHttpResponse(result);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Fall through to the runtime-owned network fetch below.
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const response = await fetch(url);
|
|
138
|
+
return formatHttpResponse({
|
|
139
|
+
status: response.status,
|
|
140
|
+
statusText: response.statusText,
|
|
141
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
142
|
+
body: await response.text(),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
124
145
|
function parseScheduleWhen(value) {
|
|
125
146
|
const normalized = value.trim().toLowerCase();
|
|
126
147
|
if (!normalized) {
|
|
@@ -388,15 +409,8 @@ export async function createBuiltinMiddlewareTools(backend, options) {
|
|
|
388
409
|
description: "Fetch a URL and return the response body.",
|
|
389
410
|
schema: z.object({ url: z.string() }).passthrough(),
|
|
390
411
|
invoke: async (input, toolConfig) => {
|
|
391
|
-
if (typeof backend.fetchUrl !== "function") {
|
|
392
|
-
return notAvailable("fetch_url", "URL fetching");
|
|
393
|
-
}
|
|
394
412
|
const typed = isRecord(input) ? input : {};
|
|
395
|
-
|
|
396
|
-
if (typeof result === "string") {
|
|
397
|
-
return finalizeOutput("fetch_url", result, toolConfig);
|
|
398
|
-
}
|
|
399
|
-
return finalizeOutput("fetch_url", formatHttpResponse(result), toolConfig);
|
|
413
|
+
return finalizeOutput("fetch_url", await fetchUrlWithRuntimeFallback(backend, typeof typed.url === "string" ? typed.url : ""), toolConfig);
|
|
400
414
|
},
|
|
401
415
|
});
|
|
402
416
|
tools.set("http_request", {
|
|
@@ -360,6 +360,7 @@ export async function* streamHarnessRun(options) {
|
|
|
360
360
|
let streamActivityObserved = false;
|
|
361
361
|
let nonUpstreamStreamActivityObserved = false;
|
|
362
362
|
let assistantOutput = "";
|
|
363
|
+
const bufferAssistantTextUntilCompletion = true;
|
|
363
364
|
let currentAgentId = options.selectedAgentId;
|
|
364
365
|
let currentAgentName = formatAgentName(options.selectedAgentId);
|
|
365
366
|
let delegationChain = [options.selectedAgentId];
|
|
@@ -594,6 +595,9 @@ export async function* streamHarnessRun(options) {
|
|
|
594
595
|
}
|
|
595
596
|
emitted = true;
|
|
596
597
|
assistantOutput += normalizedChunk.content;
|
|
598
|
+
if (bufferAssistantTextUntilCompletion) {
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
597
601
|
yield {
|
|
598
602
|
type: "event",
|
|
599
603
|
event: await options.emit(options.sessionId, options.requestId, 3, "output.delta", { content: normalizedChunk.content }),
|
|
@@ -646,6 +650,19 @@ export async function* streamHarnessRun(options) {
|
|
|
646
650
|
}
|
|
647
651
|
}
|
|
648
652
|
}
|
|
653
|
+
if (assistantOutput && bufferAssistantTextUntilCompletion) {
|
|
654
|
+
yield {
|
|
655
|
+
type: "event",
|
|
656
|
+
event: await options.emit(options.sessionId, options.requestId, 3, "output.delta", { content: assistantOutput }),
|
|
657
|
+
};
|
|
658
|
+
yield {
|
|
659
|
+
type: "content",
|
|
660
|
+
sessionId: options.sessionId,
|
|
661
|
+
requestId: options.requestId,
|
|
662
|
+
agentId: currentAgentId,
|
|
663
|
+
content: assistantOutput,
|
|
664
|
+
};
|
|
665
|
+
}
|
|
649
666
|
await options.appendAssistantMessage(options.sessionId, options.requestId, assistantOutput);
|
|
650
667
|
const completedEvent = await options.setRequestStateAndEmit(options.sessionId, options.requestId, 6, "completed", {
|
|
651
668
|
previousState: "running",
|
|
@@ -5,6 +5,7 @@ import { FileBackedStore } from "./store.js";
|
|
|
5
5
|
import { compileModel } from "../../../workspace/resource-compilers.js";
|
|
6
6
|
import { resolvePromptValue, resolveRefId } from "../../../workspace/support/workspace-ref-utils.js";
|
|
7
7
|
import { renderRuntimeMemoryManagerPrompt, renderRuntimeMemoryMutationReconciliationPrompt } from "../../prompts/runtime-prompts.js";
|
|
8
|
+
import { isNonDurableTranscriptWorkflowMemory } from "./runtime-memory-policy.js";
|
|
8
9
|
const FORMATION_EVENT_TYPES = new Set([
|
|
9
10
|
"request.state.changed",
|
|
10
11
|
"approval.resolved",
|
|
@@ -536,6 +537,9 @@ export async function runModelMemoryManager(input) {
|
|
|
536
537
|
}
|
|
537
538
|
const refinedCandidates = asCandidateOutputs(parsed, candidate, allowedScopes, input.recordedAt);
|
|
538
539
|
for (const refinedCandidate of refinedCandidates) {
|
|
540
|
+
if (isNonDurableTranscriptWorkflowMemory(refinedCandidate, candidate)) {
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
539
543
|
const reconciledCandidate = await reconcileKnowledgeMutation({
|
|
540
544
|
invoker: callableInvoker,
|
|
541
545
|
candidate: refinedCandidate,
|
|
@@ -29,6 +29,20 @@ export declare function resolveMemoryNamespace(template: string, values: Record<
|
|
|
29
29
|
export declare function hasExplicitResourceReference(text: string): boolean;
|
|
30
30
|
export declare function extractExplicitResourceReferences(text: string): string[];
|
|
31
31
|
export declare function shouldRecallDurableMemory(text: string): boolean;
|
|
32
|
+
export declare function isNonDurableTranscriptWorkflowMemory(input: {
|
|
33
|
+
content: string;
|
|
34
|
+
summary?: string;
|
|
35
|
+
kind?: string;
|
|
36
|
+
scope?: string;
|
|
37
|
+
sourceType?: string;
|
|
38
|
+
tags?: string[];
|
|
39
|
+
}, sourceCandidate?: {
|
|
40
|
+
content?: string;
|
|
41
|
+
summary?: string;
|
|
42
|
+
scope?: string;
|
|
43
|
+
sourceType?: string;
|
|
44
|
+
tags?: string[];
|
|
45
|
+
}): boolean;
|
|
32
46
|
export declare function collectMemoryCandidateLabels(candidate: {
|
|
33
47
|
kind?: string;
|
|
34
48
|
scope?: string;
|
|
@@ -110,6 +110,25 @@ export function shouldRecallDurableMemory(text) {
|
|
|
110
110
|
function normalizePolicyLabel(value) {
|
|
111
111
|
return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
112
112
|
}
|
|
113
|
+
function normalizeMemoryText(value) {
|
|
114
|
+
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
115
|
+
}
|
|
116
|
+
function hasTranscriptReflectionSource(input) {
|
|
117
|
+
const sourceType = normalizeMemoryText(input.sourceType);
|
|
118
|
+
void input.tags;
|
|
119
|
+
return sourceType === "runtime-transcript" || sourceType === "runtime-reflection";
|
|
120
|
+
}
|
|
121
|
+
export function isNonDurableTranscriptWorkflowMemory(input, sourceCandidate) {
|
|
122
|
+
if (!hasTranscriptReflectionSource({
|
|
123
|
+
sourceType: input.sourceType ?? sourceCandidate?.sourceType,
|
|
124
|
+
tags: [...(input.tags ?? []), ...(sourceCandidate?.tags ?? [])],
|
|
125
|
+
})) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
const kind = normalizeMemoryText(input.kind);
|
|
129
|
+
const scope = normalizeMemoryText(input.scope ?? sourceCandidate?.scope);
|
|
130
|
+
return kind === "procedural" || scope === "user" || scope === "workspace" || scope === "project";
|
|
131
|
+
}
|
|
113
132
|
export function collectMemoryCandidateLabels(candidate) {
|
|
114
133
|
return Array.from(new Set([
|
|
115
134
|
...(candidate.kind ? [normalizePolicyLabel(candidate.kind)] : []),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { appendToolRecoveryInstruction, isRepairableWriteTodosContentFailure, isRepairableWriteTodosEmptyFailure, isRepairableWriteTodosPlaceholderFailure, isRetrySafeInvalidToolSelectionError, isToolCallRecoveryFailure, isToolCallValidationFailure, isWorkspacePathScopeFailure, resolveExecutionWithoutToolEvidenceInstruction, resolveExecutionWithoutToolEvidenceTextInstruction, resolveToolCallRecoveryInstruction, shouldValidateExecutionWithoutToolEvidence, wrapResolvedModel, } from "./output-recovery.js";
|
|
2
|
+
export { BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION, } from "../prompts/runtime-prompts.js";
|
|
2
3
|
export { containsLikelySkillDocument, extractContentBlocks, extractEmptyAssistantMessageFailure, extractOutputContent, extractReasoningText, extractToolFallbackContext, extractVisibleOutput, hasToolCalls, readTextContent, sanitizeVisibleText, } from "./output-content.js";
|
|
3
4
|
export { isLikelyToolArgsObject, salvageToolArgs, tryParseJson, } from "./output-tool-args.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { appendToolRecoveryInstruction, isRepairableWriteTodosContentFailure, isRepairableWriteTodosEmptyFailure, isRepairableWriteTodosPlaceholderFailure, isRetrySafeInvalidToolSelectionError, isToolCallRecoveryFailure, isToolCallValidationFailure, isWorkspacePathScopeFailure, resolveExecutionWithoutToolEvidenceInstruction, resolveExecutionWithoutToolEvidenceTextInstruction, resolveToolCallRecoveryInstruction, shouldValidateExecutionWithoutToolEvidence, wrapResolvedModel, } from "./output-recovery.js";
|
|
2
|
+
export { BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION, } from "../prompts/runtime-prompts.js";
|
|
2
3
|
export { containsLikelySkillDocument, extractContentBlocks, extractEmptyAssistantMessageFailure, extractOutputContent, extractReasoningText, extractToolFallbackContext, extractVisibleOutput, hasToolCalls, readTextContent, sanitizeVisibleText, } from "./output-content.js";
|
|
3
4
|
export { isLikelyToolArgsObject, salvageToolArgs, tryParseJson, } from "./output-tool-args.js";
|
|
@@ -8,8 +8,10 @@ export declare function isToolCallRecoveryFailure(error: unknown): boolean;
|
|
|
8
8
|
export declare function isRetrySafeInvalidToolSelectionError(value: unknown): boolean;
|
|
9
9
|
export declare function shouldValidateExecutionWithoutToolEvidence(request: unknown): boolean;
|
|
10
10
|
export declare function resolveExecutionWithoutToolEvidenceInstruction(request: unknown, result: unknown): string | null;
|
|
11
|
-
export declare function resolveExecutionWithoutToolEvidenceTextInstruction(request: unknown, assistantText: string, toolCallEvidence?: boolean
|
|
11
|
+
export declare function resolveExecutionWithoutToolEvidenceTextInstruction(request: unknown, assistantText: string, toolCallEvidence?: boolean, resultEvidence?: {
|
|
12
|
+
hasWriteTodosEvidence?: boolean;
|
|
13
|
+
hasToolResultEvidence?: boolean;
|
|
14
|
+
}): string | null;
|
|
12
15
|
export declare function resolveToolCallRecoveryInstruction(error: unknown): string | null;
|
|
13
16
|
export declare function appendToolRecoveryInstruction(input: unknown, instruction: string): unknown;
|
|
14
17
|
export declare function wrapResolvedModel<T>(value: T): T;
|
|
15
|
-
export { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION, BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INTERNAL_RUNTIME_SPILL_PATH_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION } from "../prompts/runtime-prompts.js";
|