maka-agent 0.2.0-dev.6.20260830 → 0.2.0-dev.8.20260830
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/native/runtime-host-peer/prebuilds/win32-x64/maka_runtime_host_peer.node +0 -0
- package/node_modules/@maka/core/dist/agent-run.js +0 -2
- package/node_modules/@maka/core/dist/foreign-session.js +1 -1
- package/node_modules/@maka/core/dist/task-ledger.js +6 -134
- package/node_modules/@maka/core/dist/usage-record-schema.js +1 -0
- package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +3 -115
- package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +4 -18
- package/node_modules/@maka/runtime/dist/context-budget.js +0 -1
- package/node_modules/@maka/runtime/dist/plan-mode.js +0 -65
- package/node_modules/@maka/runtime/dist/run-trace.js +0 -10
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +0 -1
- package/node_modules/@maka/runtime/dist/sandbox/index.js +0 -1
- package/node_modules/@maka/runtime/dist/sandbox/linux-sandbox.js +0 -12
- package/node_modules/@maka/runtime/dist/sandbox/macos-seatbelt.js +0 -12
- package/node_modules/@maka/runtime/dist/sandbox/sandbox-manager.js +0 -35
- package/node_modules/@maka/runtime/dist/sandbox/windows-sandbox.js +0 -12
- package/node_modules/@maka/runtime/dist/shell-detect.js +3 -7
- package/node_modules/@maka/runtime/dist/shell-run-contract.js +0 -1
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +1 -39
- package/node_modules/@maka/runtime/dist/shell-tools.js +1 -1
- package/node_modules/@maka/runtime/dist/task-ledger-tools.js +2 -2
- package/node_modules/@maka/runtime/package.json +0 -1
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +1 -8
- package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +0 -6
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +2 -58
- package/package.json +1 -1
- package/node_modules/@maka/runtime/dist/sandbox/diagnostics.js +0 -285
- package/node_modules/@maka/runtime/dist/system-prompt/sandbox-context-prompt.js +0 -77
- package/node_modules/@maka/runtime/dist/system-prompt/session-environment-prompt.js +0 -47
|
Binary file
|
|
@@ -518,7 +518,7 @@ export function stripEnvelopeTags(text) {
|
|
|
518
518
|
}
|
|
519
519
|
/**
|
|
520
520
|
* Render a digest as an explicitly-untrusted data block for the handoff
|
|
521
|
-
* prompt. The envelope wording mirrors the
|
|
521
|
+
* prompt. The envelope wording mirrors the untrusted-context discipline:
|
|
522
522
|
* contents are reference data, never instructions. `safe()` is the
|
|
523
523
|
* authoritative gate every foreign-authored scalar passes through here —
|
|
524
524
|
* regardless of how the digest was built — sanitizing (NFC, control/bidi/
|
|
@@ -17,31 +17,24 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
// Session-scoped task ledger primitive for the main agent. The model manages a
|
|
20
|
-
// flat task list via task_create/task_update
|
|
21
|
-
//
|
|
20
|
+
// flat task list via task_create/task_update and reads it through task_list/task_get.
|
|
21
|
+
// The durable contract is intentionally narrow: task status,
|
|
22
22
|
// compact evidence/reason fields, append-only task events, and conservative
|
|
23
23
|
// resume trust diagnostics. Priority, dependencies, and assignee fields remain
|
|
24
24
|
// out of scope.
|
|
25
25
|
import { redactSecrets } from './redaction.js';
|
|
26
26
|
export const TASK_SUBJECT_MAX_CHARS = 200;
|
|
27
27
|
export const TASK_EVIDENCE_MAX_CHARS = 1000;
|
|
28
|
-
/**
|
|
29
|
-
* Hard cap on total tasks per session ledger (any status). The full ledger is
|
|
30
|
-
* re-injected into every turn tail, so an unbounded ledger burns context on
|
|
31
|
-
* every turn; this is a runaway guard on the total count, not a workflow quota
|
|
32
|
-
* — completing or cancelling tasks does not free capacity.
|
|
33
|
-
*/
|
|
28
|
+
/** Hard cap on total tasks per session ledger (any status). */
|
|
34
29
|
export const TASK_LEDGER_MAX_TASKS = 200;
|
|
35
30
|
export const TASK_ARCHIVE_AFTER_MS = 7 * 24 * 60 * 60 * 1000;
|
|
36
31
|
/**
|
|
37
32
|
* Max length of a task id accepted on both the write and read paths. The write
|
|
38
33
|
* path generates randomUUID (36 chars); the bound leaves headroom for a future
|
|
39
|
-
* id format while keeping
|
|
34
|
+
* id format while keeping model-visible fielded renders bounded.
|
|
40
35
|
*/
|
|
41
36
|
export const TASK_ID_MAX_CHARS = 64;
|
|
42
37
|
export const TASK_KEY_MAX_CHARS = 64;
|
|
43
|
-
export const TASK_LEDGER_PROMPT_MAX_CHARS = 8_000;
|
|
44
|
-
export const TASK_LEDGER_PROMPT_RECENT_TERMINAL = 3;
|
|
45
38
|
export const TASK_STATUSES = [
|
|
46
39
|
'pending',
|
|
47
40
|
'in_progress',
|
|
@@ -74,7 +67,7 @@ export function isResumeTrust(value) {
|
|
|
74
67
|
* ever rendered it: no angle brackets/slashes/quotes/parens/equals (a past
|
|
75
68
|
* whole-string tag strip would have eaten them; even the fielded renderer
|
|
76
69
|
* emits the id bare), no whitespace (would break the list-line structure), no
|
|
77
|
-
* huge length (would bloat
|
|
70
|
+
* huge length (would bloat model-visible results), and redaction-stable (a renderer
|
|
78
71
|
* that runs redactSecrets must not turn the id into [redacted] while the store
|
|
79
72
|
* keeps the real id -- a later task_update would miss). The whitelist
|
|
80
73
|
* (alphanumeric plus . _ : -, 1-64 chars) plus redactSecrets(id) === id enforces
|
|
@@ -95,19 +88,6 @@ export function isTaskKey(value) {
|
|
|
95
88
|
value.length <= TASK_KEY_MAX_CHARS &&
|
|
96
89
|
/^T[1-9]\d*(?:\.[1-9]\d*)*$/.test(value));
|
|
97
90
|
}
|
|
98
|
-
export function compareTaskKeys(left, right) {
|
|
99
|
-
const a = left.slice(1).split('.').map(Number);
|
|
100
|
-
const b = right.slice(1).split('.').map(Number);
|
|
101
|
-
for (let index = 0; index < Math.max(a.length, b.length); index += 1) {
|
|
102
|
-
if (a[index] === undefined)
|
|
103
|
-
return -1;
|
|
104
|
-
if (b[index] === undefined)
|
|
105
|
-
return 1;
|
|
106
|
-
if (a[index] !== b[index])
|
|
107
|
-
return a[index] - b[index];
|
|
108
|
-
}
|
|
109
|
-
return 0;
|
|
110
|
-
}
|
|
111
91
|
export function findTaskByRef(tasks, ref) {
|
|
112
92
|
return tasks.find((task) => task.id === ref || task.key === ref);
|
|
113
93
|
}
|
|
@@ -398,7 +378,7 @@ function validateTaskLedgerEventType(event, current) {
|
|
|
398
378
|
}
|
|
399
379
|
/**
|
|
400
380
|
* Safe-render the task ledger for any face that persists into history or is
|
|
401
|
-
*
|
|
381
|
+
* included in a model-visible tool result. Two invariants:
|
|
402
382
|
* - the canonical id is rendered verbatim, and the subject is a safe
|
|
403
383
|
* (redacted, tag-stripped) rendered payload of what the store holds; and
|
|
404
384
|
* - the model can unambiguously recover each task's id from what it sees, so
|
|
@@ -456,114 +436,6 @@ export function sanitizeTaskLedgerTask(task) {
|
|
|
456
436
|
: {}),
|
|
457
437
|
};
|
|
458
438
|
}
|
|
459
|
-
export function renderTaskLedgerPromptText(tasks, maxChars = TASK_LEDGER_PROMPT_MAX_CHARS) {
|
|
460
|
-
const byId = new Map(tasks.map((task) => [task.id, task]));
|
|
461
|
-
const selected = new Set();
|
|
462
|
-
const addWithAncestors = (task) => {
|
|
463
|
-
const chain = [];
|
|
464
|
-
let current = task;
|
|
465
|
-
const seen = new Set();
|
|
466
|
-
while (current && !seen.has(current.id)) {
|
|
467
|
-
seen.add(current.id);
|
|
468
|
-
chain.unshift(current);
|
|
469
|
-
current = current.parentId ? byId.get(current.parentId) : undefined;
|
|
470
|
-
}
|
|
471
|
-
for (const item of chain)
|
|
472
|
-
selected.add(item.id);
|
|
473
|
-
};
|
|
474
|
-
const active = tasks
|
|
475
|
-
.filter((task) => !isTerminalTaskStatus(task.status))
|
|
476
|
-
.sort(compareTaskPromptPriority);
|
|
477
|
-
for (const task of active)
|
|
478
|
-
addWithAncestors(task);
|
|
479
|
-
const recentTerminal = tasks
|
|
480
|
-
.filter((task) => isTerminalTaskStatus(task.status) && task.status !== 'cancelled')
|
|
481
|
-
.sort((a, b) => (b.endedAt ?? b.updatedAt) - (a.endedAt ?? a.updatedAt) || compareTaskKeys(a.key, b.key))
|
|
482
|
-
.slice(0, TASK_LEDGER_PROMPT_RECENT_TERMINAL);
|
|
483
|
-
for (const task of recentTerminal)
|
|
484
|
-
addWithAncestors(task);
|
|
485
|
-
const chosen = tasks.filter((task) => selected.has(task.id));
|
|
486
|
-
const ordered = orderTaskTree(chosen);
|
|
487
|
-
const lines = [];
|
|
488
|
-
const included = [];
|
|
489
|
-
const includedIds = new Set();
|
|
490
|
-
for (const task of ordered) {
|
|
491
|
-
if (task.parentId && !includedIds.has(task.parentId))
|
|
492
|
-
continue;
|
|
493
|
-
const depth = task.key.split('.').length - 1;
|
|
494
|
-
const fields = [
|
|
495
|
-
`key=${task.key}`,
|
|
496
|
-
`status=${task.status}`,
|
|
497
|
-
`subject=${JSON.stringify(safeTaskLedgerField(task.subject))}`,
|
|
498
|
-
];
|
|
499
|
-
if (task.blockedReason)
|
|
500
|
-
fields.push(`blockedReason=${JSON.stringify(safeTaskLedgerField(task.blockedReason))}`);
|
|
501
|
-
if (task.failureReason)
|
|
502
|
-
fields.push(`failureReason=${JSON.stringify(safeTaskLedgerField(task.failureReason))}`);
|
|
503
|
-
if (task.completionEvidence)
|
|
504
|
-
fields.push(`completionEvidence=${JSON.stringify(safeTaskLedgerField(task.completionEvidence))}`);
|
|
505
|
-
if (task.owner)
|
|
506
|
-
fields.push(`owner=${JSON.stringify(task.owner)}`);
|
|
507
|
-
const line = `${' '.repeat(depth)}${fields.join(' ')}`;
|
|
508
|
-
const nextLength = lines.length === 0 ? line.length : lines.join('\n').length + 1 + line.length;
|
|
509
|
-
if (nextLength > maxChars)
|
|
510
|
-
continue;
|
|
511
|
-
lines.push(line);
|
|
512
|
-
included.push(task);
|
|
513
|
-
includedIds.add(task.id);
|
|
514
|
-
}
|
|
515
|
-
return {
|
|
516
|
-
text: lines.join('\n'),
|
|
517
|
-
included,
|
|
518
|
-
omittedCount: tasks.length - included.length,
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
function compareTaskPromptPriority(left, right) {
|
|
522
|
-
return (taskStatusRank(left.status) - taskStatusRank(right.status) ||
|
|
523
|
-
compareTaskKeys(left.key, right.key));
|
|
524
|
-
}
|
|
525
|
-
function orderTaskTree(tasks) {
|
|
526
|
-
const byParent = new Map();
|
|
527
|
-
for (const task of tasks) {
|
|
528
|
-
const bucket = byParent.get(task.parentId) ?? [];
|
|
529
|
-
bucket.push(task);
|
|
530
|
-
byParent.set(task.parentId, bucket);
|
|
531
|
-
}
|
|
532
|
-
const branchRanks = new Map();
|
|
533
|
-
const branchRank = (task) => {
|
|
534
|
-
const cached = branchRanks.get(task.id);
|
|
535
|
-
if (cached !== undefined)
|
|
536
|
-
return cached;
|
|
537
|
-
const rank = Math.min(taskStatusRank(task.status), ...(byParent.get(task.id) ?? []).map(branchRank));
|
|
538
|
-
branchRanks.set(task.id, rank);
|
|
539
|
-
return rank;
|
|
540
|
-
};
|
|
541
|
-
const out = [];
|
|
542
|
-
const visit = (parentId) => {
|
|
543
|
-
for (const task of (byParent.get(parentId) ?? []).sort((left, right) => branchRank(left) - branchRank(right) || compareTaskKeys(left.key, right.key))) {
|
|
544
|
-
out.push(task);
|
|
545
|
-
visit(task.id);
|
|
546
|
-
}
|
|
547
|
-
};
|
|
548
|
-
visit(undefined);
|
|
549
|
-
return out;
|
|
550
|
-
}
|
|
551
|
-
function taskStatusRank(status) {
|
|
552
|
-
switch (status) {
|
|
553
|
-
case 'in_progress':
|
|
554
|
-
return 0;
|
|
555
|
-
case 'pending':
|
|
556
|
-
return 1;
|
|
557
|
-
case 'blocked':
|
|
558
|
-
return 2;
|
|
559
|
-
case 'completed':
|
|
560
|
-
return 3;
|
|
561
|
-
case 'failed':
|
|
562
|
-
return 4;
|
|
563
|
-
case 'cancelled':
|
|
564
|
-
return 5;
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
439
|
export function renderTaskLedgerDebugText(tasks) {
|
|
568
440
|
if (tasks.length === 0)
|
|
569
441
|
return '';
|
|
@@ -42,10 +42,8 @@ import { contextDiagnosticsCompactionOf, } from './context-diagnostics.js';
|
|
|
42
42
|
import { AiSdkCompaction, hasActiveToolResultPruneDiagnosticPatch, hasBlockingReplayDiagnostics, } from './ai-sdk-compaction.js';
|
|
43
43
|
import { openAiChatReasoningFieldFromProviderOptions } from './openai-chat-reasoning-transport.js';
|
|
44
44
|
import { RunTrace } from './run-trace.js';
|
|
45
|
-
import { toSandboxRunTraceProjection, } from './sandbox/diagnostics.js';
|
|
46
45
|
import { SandboxCommandError } from './sandbox/errors.js';
|
|
47
46
|
import { REQUEST_SANDBOX_BOUNDARY_TOOL_NAME, SANDBOX_BOUNDARY_DENIED_FOR_TURN, SANDBOX_BOUNDARY_FINALIZATION_PROMPT, } from './sandbox-boundary-tool.js';
|
|
48
|
-
import { renderSandboxTurnTailPrompt } from './system-prompt/sandbox-context-prompt.js';
|
|
49
47
|
import { computeCost } from './telemetry/cost.js';
|
|
50
48
|
import { getBuiltinPricing } from './telemetry/builtin-pricing.js';
|
|
51
49
|
import { buildRuntimeEventModelReplayPlan, buildSteeringEnvelope, collectToolActivityTurnIds, formatTextWithInlineRefs, steeringMessagesMissingFromBase, steeringModelMessage, steeringProviderOptions, } from './model-history.js';
|
|
@@ -621,7 +619,6 @@ export class AiSdkBackend {
|
|
|
621
619
|
createProviderRequestTracker: (trackerInput) => this.createProviderRequestTracker(trackerInput),
|
|
622
620
|
materializeRuntimeReplayPlan: (plan, imageBudget, checkpoint) => this.materializeRuntimeReplayPlan(plan, imageBudget, undefined, checkpoint),
|
|
623
621
|
canReplayProviderNative: (plan) => this.canReplayProviderNative(plan),
|
|
624
|
-
appendTurnTailPrompt: (content, turnTailPrompt) => this.appendTurnTailPrompt(content, turnTailPrompt),
|
|
625
622
|
});
|
|
626
623
|
if (input.tools.some((tool) => tool.name === MEMORY_REMEMBER_TOOL_NAME || tool.name === MEMORY_EXTRACT_TOOL_NAME)) {
|
|
627
624
|
throw new Error('Long-term Memory trigger tool names are reserved by Runtime');
|
|
@@ -1032,48 +1029,6 @@ export class AiSdkBackend {
|
|
|
1032
1029
|
});
|
|
1033
1030
|
}
|
|
1034
1031
|
}
|
|
1035
|
-
let sandboxDiagnosticsSnapshot;
|
|
1036
|
-
let sandboxPrompt;
|
|
1037
|
-
let sandboxContextStage = 'resolve';
|
|
1038
|
-
try {
|
|
1039
|
-
sandboxDiagnosticsSnapshot = this.input.sandboxDiagnostics
|
|
1040
|
-
? await raceWithTurnAbort(this.resolveTurnSandboxDiagnostics(), turnAbortController.signal)
|
|
1041
|
-
: undefined;
|
|
1042
|
-
sandboxContextStage = 'render';
|
|
1043
|
-
sandboxPrompt = sandboxDiagnosticsSnapshot
|
|
1044
|
-
? renderSandboxTurnTailPrompt(sandboxDiagnosticsSnapshot)
|
|
1045
|
-
: undefined;
|
|
1046
|
-
}
|
|
1047
|
-
catch (err) {
|
|
1048
|
-
if (scope.aborted || turnAbortController.signal.aborted) {
|
|
1049
|
-
queue.push({
|
|
1050
|
-
type: 'abort',
|
|
1051
|
-
id: this.newId(),
|
|
1052
|
-
turnId,
|
|
1053
|
-
ts: this.now(),
|
|
1054
|
-
reason: 'user_stop',
|
|
1055
|
-
});
|
|
1056
|
-
queue.push({
|
|
1057
|
-
type: 'complete',
|
|
1058
|
-
id: this.newId(),
|
|
1059
|
-
turnId,
|
|
1060
|
-
ts: this.now(),
|
|
1061
|
-
stopReason: 'user_stop',
|
|
1062
|
-
});
|
|
1063
|
-
queue.close();
|
|
1064
|
-
yield* this.drain(queue);
|
|
1065
|
-
return;
|
|
1066
|
-
}
|
|
1067
|
-
trace.sandboxContextFailed(sandboxContextStage, err);
|
|
1068
|
-
// This context is model guidance, not execution authority. Never fall
|
|
1069
|
-
// back to a stale snapshot; continue without the prompt while the live
|
|
1070
|
-
// ExecutionBoundary remains authoritative for every tool invocation.
|
|
1071
|
-
sandboxDiagnosticsSnapshot = undefined;
|
|
1072
|
-
sandboxPrompt = undefined;
|
|
1073
|
-
}
|
|
1074
|
-
if (sandboxDiagnosticsSnapshot) {
|
|
1075
|
-
trace.sandboxContextResolved(toSandboxRunTraceProjection(sandboxDiagnosticsSnapshot));
|
|
1076
|
-
}
|
|
1077
1032
|
const providerRequestTracker = this.createProviderRequestTracker({
|
|
1078
1033
|
turnId,
|
|
1079
1034
|
callKind: 'main',
|
|
@@ -1167,11 +1122,6 @@ export class AiSdkBackend {
|
|
|
1167
1122
|
await this.resolveSystemPrompt(scope),
|
|
1168
1123
|
scope.orchestration?.mode === 'swarm' ? renderSwarmModePrompt() : undefined,
|
|
1169
1124
|
scope.orchestration?.mode === 'graph' ? renderGraphModePrompt() : undefined,
|
|
1170
|
-
// A safe continuation deliberately has no new user message. Keep its
|
|
1171
|
-
// replay byte-for-byte intact and carry only the current authority fact
|
|
1172
|
-
// in the effective system envelope; ordinary volatile turn-tail facts
|
|
1173
|
-
// remain excluded from continuation.
|
|
1174
|
-
input.continuation ? sandboxPrompt : undefined,
|
|
1175
1125
|
]);
|
|
1176
1126
|
}
|
|
1177
1127
|
catch (err) {
|
|
@@ -1305,13 +1255,6 @@ export class AiSdkBackend {
|
|
|
1305
1255
|
next.start();
|
|
1306
1256
|
};
|
|
1307
1257
|
const activeTools = plan.activeTools;
|
|
1308
|
-
const turnTailPrompt = input.continuation
|
|
1309
|
-
? undefined
|
|
1310
|
-
: joinPromptFragments([
|
|
1311
|
-
await this.resolveTurnTailPrompt(turnId),
|
|
1312
|
-
await this.resolveShellRunContextSummary(),
|
|
1313
|
-
sandboxPrompt,
|
|
1314
|
-
]);
|
|
1315
1258
|
const currentUserContent = input.continuation
|
|
1316
1259
|
? undefined
|
|
1317
1260
|
: await this.buildCurrentUserContent(scope.imageBudget, input.text, input.attachments, input.quotes, input.headAnchorRuntimeEvent?.id);
|
|
@@ -1321,7 +1264,7 @@ export class AiSdkBackend {
|
|
|
1321
1264
|
...priorReplay.messages,
|
|
1322
1265
|
{
|
|
1323
1266
|
role: 'user',
|
|
1324
|
-
content:
|
|
1267
|
+
content: currentUserContent,
|
|
1325
1268
|
},
|
|
1326
1269
|
];
|
|
1327
1270
|
const settledModelOutputs = new Map();
|
|
@@ -1364,22 +1307,7 @@ export class AiSdkBackend {
|
|
|
1364
1307
|
(replayPlan.hasProviderNativeSemantics && !this.canReplayProviderNative(replayPlan))) {
|
|
1365
1308
|
throw new Error('durable current-run projection is not replayable');
|
|
1366
1309
|
}
|
|
1367
|
-
const
|
|
1368
|
-
let decoratedCurrentUser = false;
|
|
1369
|
-
const replayItems = replayPlan.items.map((item) => {
|
|
1370
|
-
if (item.kind !== 'text' || item.role !== 'user') {
|
|
1371
|
-
return item;
|
|
1372
|
-
}
|
|
1373
|
-
if (anchorEventId !== undefined ? item.eventId !== anchorEventId : decoratedCurrentUser) {
|
|
1374
|
-
return item;
|
|
1375
|
-
}
|
|
1376
|
-
decoratedCurrentUser = true;
|
|
1377
|
-
return {
|
|
1378
|
-
...item,
|
|
1379
|
-
content: this.appendTurnTailPrompt(item.content, turnTailPrompt),
|
|
1380
|
-
};
|
|
1381
|
-
});
|
|
1382
|
-
const currentTurnMessages = await this.materializeRuntimeReplayPlan({ ...replayPlan, items: replayItems }, scope.imageBudget, settledModelOutputs, projectionCheckpoint);
|
|
1310
|
+
const currentTurnMessages = await this.materializeRuntimeReplayPlan(replayPlan, scope.imageBudget, settledModelOutputs, projectionCheckpoint);
|
|
1383
1311
|
return projectionCheckpoint
|
|
1384
1312
|
? currentTurnMessages
|
|
1385
1313
|
: [...priorReplay.messages, ...currentTurnMessages];
|
|
@@ -1408,7 +1336,6 @@ export class AiSdkBackend {
|
|
|
1408
1336
|
...(input.attachments !== undefined ? { attachments: input.attachments } : {}),
|
|
1409
1337
|
...(input.quotes !== undefined ? { quotes: input.quotes } : {}),
|
|
1410
1338
|
}),
|
|
1411
|
-
turnTailPrompt,
|
|
1412
1339
|
}),
|
|
1413
1340
|
requestShape: computeRequestShapeDiagnostic({
|
|
1414
1341
|
connection: this.input.connection,
|
|
@@ -1460,7 +1387,7 @@ export class AiSdkBackend {
|
|
|
1460
1387
|
midTurnCompactDiagnosticPatch = mergeContextBudgetDiagnosticPatches(midTurnCompactDiagnosticPatch, patch);
|
|
1461
1388
|
};
|
|
1462
1389
|
const midTurnSystemPromptChars = systemPrompt?.length ?? 0;
|
|
1463
|
-
const midTurnCapacityHook = this.compaction.buildMidTurnCapacityCompactProjection(turnId, midTurnState, queue, providerTools, () => currentRepairToolNames(),
|
|
1390
|
+
const midTurnCapacityHook = this.compaction.buildMidTurnCapacityCompactProjection(turnId, midTurnState, queue, providerTools, () => currentRepairToolNames(), midTurnSystemPromptChars, onMidTurnDiagnosticPatch, scope, this.automaticMemoryCompactionSupported()
|
|
1464
1391
|
? () => this.automaticMemoryCompactionDecision()
|
|
1465
1392
|
: undefined, this.automaticMemoryCompactionSupported()
|
|
1466
1393
|
? (dispatch) => this.dispatchAutomaticMemoryCompaction(scope, dispatch)
|
|
@@ -1855,7 +1782,6 @@ export class AiSdkBackend {
|
|
|
1855
1782
|
providerTools,
|
|
1856
1783
|
activeTools: activeToolsForRequest,
|
|
1857
1784
|
systemPromptChars: midTurnSystemPromptChars,
|
|
1858
|
-
turnTailPrompt,
|
|
1859
1785
|
queue,
|
|
1860
1786
|
onDiagnosticPatch: onMidTurnDiagnosticPatch,
|
|
1861
1787
|
origin: scope,
|
|
@@ -3432,17 +3358,6 @@ export class AiSdkBackend {
|
|
|
3432
3358
|
}
|
|
3433
3359
|
return out;
|
|
3434
3360
|
}
|
|
3435
|
-
/** Append provider-visible volatile turn facts after the durable user content. */
|
|
3436
|
-
appendTurnTailPrompt(content, turnTailPrompt) {
|
|
3437
|
-
if (!turnTailPrompt)
|
|
3438
|
-
return content;
|
|
3439
|
-
if (typeof content === 'string')
|
|
3440
|
-
return `${content}\n\n${turnTailPrompt}`;
|
|
3441
|
-
return [
|
|
3442
|
-
...content,
|
|
3443
|
-
{ type: 'text', text: turnTailPrompt },
|
|
3444
|
-
];
|
|
3445
|
-
}
|
|
3446
3361
|
/** A decision key deduplicates re-materialization; no key charges each occurrence. */
|
|
3447
3362
|
chargeImageBudget(budget, bytes, decisionKey) {
|
|
3448
3363
|
if (decisionKey !== undefined) {
|
|
@@ -3558,39 +3473,12 @@ export class AiSdkBackend {
|
|
|
3558
3473
|
return await this.input.systemPrompt({
|
|
3559
3474
|
sessionId: this.sessionId,
|
|
3560
3475
|
turnId,
|
|
3561
|
-
...(scope.runId ? { runId: scope.runId } : {}),
|
|
3562
3476
|
cwd: this.input.header.cwd,
|
|
3563
|
-
workspaceRoot: this.input.header.workspaceRoot,
|
|
3564
3477
|
emitSkillCatalogTrace: (message, data) => scope.runTrace?.emit('skill', 'skill_catalog_built', message, data),
|
|
3565
3478
|
});
|
|
3566
3479
|
}
|
|
3567
3480
|
return this.input.systemPrompt;
|
|
3568
3481
|
}
|
|
3569
|
-
async resolveTurnSandboxDiagnostics() {
|
|
3570
|
-
const provider = this.input.sandboxDiagnostics;
|
|
3571
|
-
if (!provider)
|
|
3572
|
-
return undefined;
|
|
3573
|
-
const boundary = await this.input.readExecutionBoundary();
|
|
3574
|
-
if (boundary.kind === 'external')
|
|
3575
|
-
return undefined;
|
|
3576
|
-
return await provider.resolve(boundary.kind === 'managed'
|
|
3577
|
-
? { cwd: this.input.header.cwd, permissionProfile: boundary.profile }
|
|
3578
|
-
: { cwd: this.input.header.cwd, mode: 'bypass' });
|
|
3579
|
-
}
|
|
3580
|
-
async resolveTurnTailPrompt(turnId) {
|
|
3581
|
-
if (typeof this.input.turnTailPrompt === 'function') {
|
|
3582
|
-
return await this.input.turnTailPrompt({
|
|
3583
|
-
sessionId: this.sessionId,
|
|
3584
|
-
turnId,
|
|
3585
|
-
cwd: this.input.header.cwd,
|
|
3586
|
-
workspaceRoot: this.input.header.workspaceRoot,
|
|
3587
|
-
});
|
|
3588
|
-
}
|
|
3589
|
-
return this.input.turnTailPrompt;
|
|
3590
|
-
}
|
|
3591
|
-
async resolveShellRunContextSummary() {
|
|
3592
|
-
return await this.input.shellRunContextSummary?.();
|
|
3593
|
-
}
|
|
3594
3482
|
async *drain(queue) {
|
|
3595
3483
|
try {
|
|
3596
3484
|
for await (const ev of queue) {
|
|
@@ -37,7 +37,6 @@ export class AiSdkCompaction {
|
|
|
37
37
|
createProviderRequestTracker;
|
|
38
38
|
materializeRuntimeReplayPlan;
|
|
39
39
|
canReplayProviderNative;
|
|
40
|
-
appendTurnTailPrompt;
|
|
41
40
|
historyCompactAbortController = null;
|
|
42
41
|
/**
|
|
43
42
|
* Session-scoped circuit for exact malformed compaction inputs. A retry or
|
|
@@ -53,7 +52,6 @@ export class AiSdkCompaction {
|
|
|
53
52
|
this.createProviderRequestTracker = deps.createProviderRequestTracker;
|
|
54
53
|
this.materializeRuntimeReplayPlan = deps.materializeRuntimeReplayPlan;
|
|
55
54
|
this.canReplayProviderNative = deps.canReplayProviderNative;
|
|
56
|
-
this.appendTurnTailPrompt = deps.appendTurnTailPrompt;
|
|
57
55
|
}
|
|
58
56
|
/** Abort an in-flight manual history compaction (called by AiSdkBackend.stop). */
|
|
59
57
|
abortHistoryCompact() {
|
|
@@ -409,7 +407,7 @@ export class AiSdkCompaction {
|
|
|
409
407
|
* usage + a signed char/4 payload delta, tool schemas included) against
|
|
410
408
|
* `contextWindow - reserve`; over the high-water, fold a safe completed
|
|
411
409
|
* prefix into a durable mid_turn checkpoint and continue the same turn on
|
|
412
|
-
* `[compact block, verbatim head anchor
|
|
410
|
+
* `[compact block, verbatim head anchor]`.
|
|
413
411
|
*
|
|
414
412
|
* This hook never terminates the turn: every failure fails open with a
|
|
415
413
|
* diagnostic and records itself for the final-request estimate owner, which
|
|
@@ -420,7 +418,7 @@ export class AiSdkCompaction {
|
|
|
420
418
|
* approximate — a missed or spurious trigger is recoverable; the verdict is
|
|
421
419
|
* not, so it does not live here.
|
|
422
420
|
*/
|
|
423
|
-
buildMidTurnCapacityCompactProjection(turnId, state, queue, providerTools, fallbackActiveTools,
|
|
421
|
+
buildMidTurnCapacityCompactProjection(turnId, state, queue, providerTools, fallbackActiveTools, systemPromptChars, onDiagnosticPatch, origin, memoryCompactionDecision, onMemoryCompaction, abortSignal) {
|
|
424
422
|
if (!state)
|
|
425
423
|
return undefined;
|
|
426
424
|
const policy = this.input.contextBudget;
|
|
@@ -531,7 +529,6 @@ export class AiSdkCompaction {
|
|
|
531
529
|
providerTools,
|
|
532
530
|
activeToolsForStep,
|
|
533
531
|
systemPromptChars,
|
|
534
|
-
turnTailPrompt,
|
|
535
532
|
memoryCompactionDecision,
|
|
536
533
|
onMemoryCompaction,
|
|
537
534
|
abortSignal,
|
|
@@ -565,7 +562,7 @@ export class AiSdkCompaction {
|
|
|
565
562
|
* the pass/terminate verdict and the diagnostic emission are the caller's.
|
|
566
563
|
*/
|
|
567
564
|
async compactActiveRequestHistory(input) {
|
|
568
|
-
const { turnId, state, queue, providerTools, activeToolsForStep, systemPromptChars,
|
|
565
|
+
const { turnId, state, queue, providerTools, activeToolsForStep, systemPromptChars, abortSignal, } = input;
|
|
569
566
|
if (state.malformedSummaryFailure) {
|
|
570
567
|
return {
|
|
571
568
|
decision: 'fail',
|
|
@@ -726,17 +723,7 @@ export class AiSdkCompaction {
|
|
|
726
723
|
diagnosticReason: 'replacement_unmaterializable',
|
|
727
724
|
};
|
|
728
725
|
}
|
|
729
|
-
|
|
730
|
-
// user message: the initial request decorates it with the volatile turn
|
|
731
|
-
// tail (cwd, shell context, task state — see send()), which is not part
|
|
732
|
-
// of the durable anchor bytes. Reuse the same decoration owner
|
|
733
|
-
// (appendTurnTailPrompt) on the anchor's replay item so a replacement
|
|
734
|
-
// never silently drops that context — and never counts the drop as
|
|
735
|
-
// shrinkage in the guard below.
|
|
736
|
-
const replayItemsWithAnchorTail = replayPlan.items.map((item) => item.kind === 'text' && item.role === 'user' && item.eventId === state.headAnchor.id
|
|
737
|
-
? { ...item, content: this.appendTurnTailPrompt(item.content, turnTailPrompt) }
|
|
738
|
-
: item);
|
|
739
|
-
const replacementMessages = await this.materializeRuntimeReplayPlan({ ...replayPlan, items: replayItemsWithAnchorTail }, input.origin.imageBudget, plan.checkpoint);
|
|
726
|
+
const replacementMessages = await this.materializeRuntimeReplayPlan(replayPlan, input.origin.imageBudget, plan.checkpoint);
|
|
740
727
|
// Apply the shape only when it actually shrinks the request versus the
|
|
741
728
|
// reference payload (the incoming request for the proactive hook, the
|
|
742
729
|
// request that overflowed for reactive recovery): a materialized
|
|
@@ -848,7 +835,6 @@ export class AiSdkCompaction {
|
|
|
848
835
|
providerTools: input.providerTools,
|
|
849
836
|
activeToolsForStep: input.activeTools,
|
|
850
837
|
systemPromptChars: input.systemPromptChars,
|
|
851
|
-
turnTailPrompt: input.turnTailPrompt,
|
|
852
838
|
memoryCompactionDecision: input.memoryCompactionDecision,
|
|
853
839
|
onMemoryCompaction: input.onMemoryCompaction,
|
|
854
840
|
abortSignal: input.abortSignal,
|
|
@@ -93,7 +93,6 @@ export function buildPromptSegmentEstimates(input) {
|
|
|
93
93
|
: {}),
|
|
94
94
|
},
|
|
95
95
|
segment('current_user', input.currentUserContent.length, charsPerToken),
|
|
96
|
-
segment('turn_tail', input.turnTailPrompt?.length ?? 0, charsPerToken),
|
|
97
96
|
];
|
|
98
97
|
}
|
|
99
98
|
export function estimateModelMessagesChars(messages) {
|
|
@@ -83,68 +83,3 @@ export function renderPlanModePrompt(input = {}) {
|
|
|
83
83
|
'</collaboration_mode>',
|
|
84
84
|
].join('\n');
|
|
85
85
|
}
|
|
86
|
-
export function renderInterruptedPlanContext(input) {
|
|
87
|
-
const steps = input.execution.steps.map((step) => renderExecutionStep(step)).join('\n');
|
|
88
|
-
return [
|
|
89
|
-
'<interrupted_plan_context>',
|
|
90
|
-
`Plan: ${input.proposal.title}`,
|
|
91
|
-
`Plan ID: ${input.proposal.planId}`,
|
|
92
|
-
`Proposal: ${input.proposal.proposalId} (revision ${input.proposal.revision})`,
|
|
93
|
-
`Interrupted execution ID: ${input.execution.executionId}`,
|
|
94
|
-
input.execution.interruptionReason
|
|
95
|
-
? `Interruption reason: ${input.execution.interruptionReason}`
|
|
96
|
-
: '',
|
|
97
|
-
'Progress at interruption:',
|
|
98
|
-
steps,
|
|
99
|
-
input.fullAccess
|
|
100
|
-
? 'The user entered Plan Mode to replan the remaining work. Do not resume the interrupted execution automatically. Full access remains active; modify files or perform side effects only when the user explicitly requests them during replanning. A submitted proposal will supersede this interrupted execution when approved.'
|
|
101
|
-
: 'The user entered Plan Mode to replan the remaining work. Do not resume execution or modify files. A submitted proposal will supersede this interrupted execution when approved.',
|
|
102
|
-
'</interrupted_plan_context>',
|
|
103
|
-
]
|
|
104
|
-
.filter(Boolean)
|
|
105
|
-
.join('\n');
|
|
106
|
-
}
|
|
107
|
-
export function renderPlanExecutionPrompt(input) {
|
|
108
|
-
const steps = input.execution.steps.map((step) => renderExecutionStep(step)).join('\n');
|
|
109
|
-
return [
|
|
110
|
-
'<plan_execution_context>',
|
|
111
|
-
`Plan: ${input.proposal.title}`,
|
|
112
|
-
`Plan ID: ${input.proposal.planId}`,
|
|
113
|
-
`Proposal: ${input.proposal.proposalId} (revision ${input.proposal.revision})`,
|
|
114
|
-
`Execution ID: ${input.execution.executionId}`,
|
|
115
|
-
input.proposal.overview ? `Overview: ${input.proposal.overview}` : '',
|
|
116
|
-
'Approved steps:',
|
|
117
|
-
steps,
|
|
118
|
-
'Execute this approved plan. Before implementation, call update_plan with the first actionable step in_progress and every other step at its current status. Immediately after finishing a step, call update_plan again to mark it completed and move the next step to in_progress. Before the final response, update every finished or skipped step so the execution can close. If the user explicitly abandons the plan, call cancel_plan. Do not delegate to subagents while this execution is active.',
|
|
119
|
-
'</plan_execution_context>',
|
|
120
|
-
]
|
|
121
|
-
.filter(Boolean)
|
|
122
|
-
.join('\n');
|
|
123
|
-
}
|
|
124
|
-
function statusMark(status) {
|
|
125
|
-
if (status === 'completed')
|
|
126
|
-
return 'x';
|
|
127
|
-
if (status === 'in_progress')
|
|
128
|
-
return '>';
|
|
129
|
-
if (status === 'skipped')
|
|
130
|
-
return '-';
|
|
131
|
-
return ' ';
|
|
132
|
-
}
|
|
133
|
-
function renderExecutionStep(step) {
|
|
134
|
-
return [
|
|
135
|
-
'<step>',
|
|
136
|
-
`<id>${escapeXml(step.id)}</id>`,
|
|
137
|
-
`<title>${escapeXml(step.title)}</title>`,
|
|
138
|
-
`<description>${escapeXml(step.description)}</description>`,
|
|
139
|
-
`<status>${step.status}</status>`,
|
|
140
|
-
'</step>',
|
|
141
|
-
].join('\n');
|
|
142
|
-
}
|
|
143
|
-
function escapeXml(value) {
|
|
144
|
-
return value
|
|
145
|
-
.replaceAll('&', '&')
|
|
146
|
-
.replaceAll('<', '<')
|
|
147
|
-
.replaceAll('>', '>')
|
|
148
|
-
.replaceAll('"', '"')
|
|
149
|
-
.replaceAll("'", ''');
|
|
150
|
-
}
|
|
@@ -52,16 +52,6 @@ export class RunTrace {
|
|
|
52
52
|
...extra,
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
|
-
sandboxContextResolved(snapshot) {
|
|
56
|
-
this.emit('sandbox', 'sandbox_context_resolved', 'Sandbox context resolved', { snapshot });
|
|
57
|
-
}
|
|
58
|
-
sandboxContextFailed(stage, error) {
|
|
59
|
-
this.emit('sandbox', 'sandbox_context_failed', 'Sandbox context unavailable; continuing without prompt context', {
|
|
60
|
-
stage,
|
|
61
|
-
error: explainError(error),
|
|
62
|
-
...diagnoseError(error),
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
55
|
modelResolved() {
|
|
66
56
|
this.emit('model', 'model_resolved', 'Model resolved', {
|
|
67
57
|
connectionSlug: this.input.connectionSlug,
|
|
@@ -1689,7 +1689,6 @@ export class RuntimeKernel {
|
|
|
1689
1689
|
sessionId,
|
|
1690
1690
|
}),
|
|
1691
1691
|
allowMidTurnHistoryCompaction: Boolean(this.deps.runtimeEventStore),
|
|
1692
|
-
shellRunContextSummary: () => this.deps.shellRuns?.buildContextSummary(sessionId) ?? Promise.resolve(undefined),
|
|
1693
1692
|
});
|
|
1694
1693
|
await this.rejectCancelledBackendActivation(backend, header, execution);
|
|
1695
1694
|
const generation = this.createBackendGeneration(sessionId, backend, header);
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
export { SandboxManager } from './sandbox-manager.js';
|
|
20
|
-
export { createSandboxDiagnosticsProvider, toSandboxRunTraceProjection, } from './diagnostics.js';
|
|
21
20
|
export { SandboxCommandError, sandboxErrorMetadata, serializeSandboxError, } from './errors.js';
|
|
22
21
|
export { createBuiltinSandboxManager, createDefaultSandboxManager, isBuiltinFilesystemWorkerSandboxAvailable, } from './default-sandbox-manager.js';
|
|
23
22
|
export { LinuxBubblewrapBackend, buildBubblewrapArgv, buildNetworkSeccompFilter, discoverNestedProtectedMetadataPaths, } from './linux-sandbox.js';
|
|
@@ -41,18 +41,6 @@ export class LinuxBubblewrapBackend {
|
|
|
41
41
|
canEnforceProfile(profile) {
|
|
42
42
|
return validateLinuxProfile(profile, this.options.arch ?? process.arch).ok;
|
|
43
43
|
}
|
|
44
|
-
probe(request) {
|
|
45
|
-
const plan = this.plan(request);
|
|
46
|
-
if (!plan.ok)
|
|
47
|
-
return plan;
|
|
48
|
-
return {
|
|
49
|
-
ok: true,
|
|
50
|
-
executable: plan.bwrapPath,
|
|
51
|
-
sandboxType: 'linux',
|
|
52
|
-
requiresSandbox: true,
|
|
53
|
-
preference: plan.preference,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
44
|
transform(request) {
|
|
57
45
|
const { command } = request;
|
|
58
46
|
const plan = this.plan(request);
|
|
@@ -219,18 +219,6 @@ export function createSeatbeltExecArgs(input) {
|
|
|
219
219
|
}
|
|
220
220
|
export class MacosSeatbeltBackend {
|
|
221
221
|
type = 'macos-seatbelt';
|
|
222
|
-
probe(request) {
|
|
223
|
-
const transformed = this.transform(request);
|
|
224
|
-
if (!transformed.ok)
|
|
225
|
-
return transformed;
|
|
226
|
-
return {
|
|
227
|
-
ok: true,
|
|
228
|
-
executable: MACOS_SEATBELT_EXECUTABLE,
|
|
229
|
-
sandboxType: transformed.sandboxType,
|
|
230
|
-
requiresSandbox: transformed.requiresSandbox,
|
|
231
|
-
preference: transformed.preference,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
222
|
transform(request) {
|
|
235
223
|
const { command } = request;
|
|
236
224
|
const preference = request.preference ?? 'auto';
|