maka-agent 0.2.0-dev.24.20260907 → 0.2.0-dev.25.20260908
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 +38 -19
- package/README.zh-CN.md +34 -19
- package/dist/pi-transcript-tools.js +6 -0
- package/dist/pi-tui-layout.js +56 -10
- package/dist/pi-tui-pickers.js +102 -1
- package/dist/pi-tui-runner.js +156 -42
- package/dist/pi-tui-todo.js +221 -0
- package/dist/pi-tui-transcript-viewer.js +134 -7
- package/dist/runtime-host-cli-context.js +70 -13
- package/dist/runtime-host-handoff-surface.js +51 -26
- package/dist/runtime-host-local-handoff.js +11 -1
- package/dist/runtime-host-service-manager.js +0 -3
- package/dist/runtime-host-session-channel.js +13 -0
- package/dist/runtime-host-session-driver.js +42 -1
- package/dist/tui-copy-catalog.js +79 -3
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/agent-run.js +1 -0
- package/node_modules/@maka/core/dist/attachments.js +3 -0
- package/node_modules/@maka/core/dist/canonical-json.js +27 -0
- package/node_modules/@maka/core/dist/capabilities.js +35 -0
- package/node_modules/@maka/core/dist/computer-use.js +0 -1
- package/node_modules/@maka/core/dist/display-redaction.js +18 -0
- package/node_modules/@maka/core/dist/llm-connections.js +13 -0
- package/node_modules/@maka/core/dist/model-call-attempt.js +2 -0
- package/node_modules/@maka/core/dist/model-metadata.js +4 -0
- package/node_modules/@maka/core/dist/redaction.js +35 -0
- package/node_modules/@maka/core/dist/run-composition.js +77 -2
- package/node_modules/@maka/core/dist/session.js +30 -4
- package/node_modules/@maka/core/dist/slash-command-catalog.js +1 -0
- package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
- package/node_modules/@maka/core/package.json +1 -0
- package/node_modules/@maka/eval/dist/experiment-directory.js +4 -13
- package/node_modules/@maka/runtime/dist/agent-run-inspect.js +0 -13
- package/node_modules/@maka/runtime/dist/agent-run.js +80 -1
- package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +16 -8
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +57 -50
- package/node_modules/@maka/runtime/dist/archive-read-tool.js +2 -2
- package/node_modules/@maka/runtime/dist/context-budget-helpers.js +0 -16
- package/node_modules/@maka/runtime/dist/conversation-copy.js +153 -11
- package/node_modules/@maka/runtime/dist/github-copilot-oauth-enrollment.js +3 -3
- package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +69 -1
- package/node_modules/@maka/runtime/dist/mcp-tools.js +7 -2
- package/node_modules/@maka/runtime/dist/model-fetcher.js +42 -2
- package/node_modules/@maka/runtime/dist/model-history.js +0 -112
- package/node_modules/@maka/runtime/dist/plugin-runtime.js +20 -10
- package/node_modules/@maka/runtime/dist/plugin-tool-service.js +205 -0
- package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +8 -1
- package/node_modules/@maka/runtime/dist/request-shape.js +23 -0
- package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +1 -1
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +4 -0
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +7 -0
- package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +21 -0
- package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +0 -5
- package/node_modules/@maka/runtime/dist/test-connection.js +0 -1
- package/node_modules/@maka/runtime/dist/tool-activation-identity.js +41 -0
- package/node_modules/@maka/runtime/dist/tool-availability.js +11 -1
- package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +63 -1
- package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +42 -12
- package/node_modules/@maka/runtime/dist/tool-result-archive.js +27 -4
- package/node_modules/@maka/runtime/package.json +1 -0
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +35 -12
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +2 -0
- package/node_modules/@maka/runtime-host/dist/client/session-subscription.js +19 -0
- package/node_modules/@maka/runtime-host/dist/control/endpoint.js +1 -3
- package/node_modules/@maka/runtime-host/dist/node-error.js +22 -0
- package/node_modules/@maka/runtime-host/dist/operator/managed-deployment.js +1 -3
- package/node_modules/@maka/runtime-host/dist/peer-mesh/limits.js +0 -1
- package/node_modules/@maka/runtime-host/dist/peer-mesh/model.js +1 -1
- package/node_modules/@maka/runtime-host/dist/peer-reachability/publisher.js +1 -3
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plan.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +27 -5
- package/node_modules/@maka/runtime-host/dist/protocol/project-catalog.js +2 -2
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +31 -2
- package/node_modules/@maka/runtime-host/dist/server/agent-graph-coordinator.js +0 -3
- package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +32 -32
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +44 -9
- package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +42 -14
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +47 -22
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/session-retirement-coordinator.js +5 -2
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +20 -2
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +13 -3
- package/node_modules/@maka/runtime-host/dist/server/workhub-message-attachments.js +46 -0
- package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +0 -1
- package/node_modules/@maka/storage/dist/codex-session-adapter.js +284 -196
- package/node_modules/@maka/storage/dist/git-exec.js +61 -0
- package/node_modules/@maka/storage/dist/git-worktree-child-executor.js +8 -35
- package/node_modules/@maka/storage/dist/goal-authority.js +2 -2
- package/node_modules/@maka/storage/dist/interaction-store.js +2 -2
- package/node_modules/@maka/storage/dist/project-catalog.js +2 -23
- package/node_modules/@maka/storage/dist/runtime-event-invariants.js +2 -2
- package/node_modules/@maka/storage/dist/runtime-policy/connection-catalog-document.js +8 -3
- package/node_modules/@maka/storage/dist/scheduled-task-store.js +249 -283
- package/node_modules/@maka/storage/dist/session-bundle-manifest.js +5 -17
- package/node_modules/@maka/storage/dist/session-bundle-policy.js +2 -1
- package/node_modules/@maka/storage/dist/session-copy-cleanup.js +2 -1
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +1 -2
- package/node_modules/@maka/storage/dist/storage-id.js +28 -0
- package/node_modules/@maka/storage/dist/tool-result-archive-evidence.js +31 -4
- package/node_modules/@maka/storage/dist/workspace-identity.js +2 -15
- package/node_modules/@maka/storage/dist/workspace-version-authority-internal.js +1 -8
- package/package.json +1 -1
|
@@ -19,13 +19,14 @@
|
|
|
19
19
|
import { randomUUID } from 'node:crypto';
|
|
20
20
|
import { link, mkdir, open, readFile, unlink } from 'node:fs/promises';
|
|
21
21
|
import { join } from 'node:path';
|
|
22
|
+
import { stableJsonStringify } from '@maka/core/canonical-json';
|
|
22
23
|
import { FileAttemptStore } from './attempt-store.js';
|
|
23
24
|
import { parseExperimentSpec } from './spec.js';
|
|
24
25
|
export async function openExperimentDirectory(root, spec) {
|
|
25
26
|
await mkdir(root, { recursive: true });
|
|
26
27
|
const specPath = join(root, 'experiment.json');
|
|
27
28
|
const temporaryPath = join(root, `.experiment-${randomUUID()}.tmp`);
|
|
28
|
-
const canonical = `${
|
|
29
|
+
const canonical = `${stableJsonStringify(spec)}\n`;
|
|
29
30
|
const temporary = await open(temporaryPath, 'wx', 0o600);
|
|
30
31
|
try {
|
|
31
32
|
await temporary.writeFile(canonical);
|
|
@@ -37,8 +38,9 @@ export async function openExperimentDirectory(root, spec) {
|
|
|
37
38
|
if (error.code !== 'EEXIST')
|
|
38
39
|
throw error;
|
|
39
40
|
const existing = parseExperimentSpec(JSON.parse(await readFile(specPath, 'utf8')));
|
|
40
|
-
if (
|
|
41
|
+
if (stableJsonStringify(existing) !== stableJsonStringify(spec)) {
|
|
41
42
|
throw new Error('experiment spec differs');
|
|
43
|
+
}
|
|
42
44
|
}
|
|
43
45
|
finally {
|
|
44
46
|
await temporary.close().catch(() => undefined);
|
|
@@ -46,14 +48,3 @@ export async function openExperimentDirectory(root, spec) {
|
|
|
46
48
|
}
|
|
47
49
|
return { root, specPath, attempts: new FileAttemptStore(join(root, 'attempts')) };
|
|
48
50
|
}
|
|
49
|
-
function canonicalJson(value) {
|
|
50
|
-
if (Array.isArray(value))
|
|
51
|
-
return `[${value.map(canonicalJson).join(',')}]`;
|
|
52
|
-
if (value && typeof value === 'object') {
|
|
53
|
-
return `{${Object.entries(value)
|
|
54
|
-
.sort(([left], [right]) => left.localeCompare(right))
|
|
55
|
-
.map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`)
|
|
56
|
-
.join(',')}}`;
|
|
57
|
-
}
|
|
58
|
-
return JSON.stringify(value);
|
|
59
|
-
}
|
|
@@ -61,19 +61,6 @@ export async function inspectAgentRunReadModel(runStore, runtimeEventStore, opti
|
|
|
61
61
|
diagnostics,
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
-
export async function inspectSessionRunReadModels(runStore, runtimeEventStore, sessionId, options = {}) {
|
|
65
|
-
const invocations = await runtimeEventStore.listSessionInvocations(sessionId);
|
|
66
|
-
const models = [];
|
|
67
|
-
for (const invocation of invocations) {
|
|
68
|
-
models.push(await inspectAgentRunReadModel(runStore, runtimeEventStore, {
|
|
69
|
-
sessionId,
|
|
70
|
-
runId: invocation.runId,
|
|
71
|
-
invocation,
|
|
72
|
-
...(options.isFatalReadError ? { isFatalReadError: options.isFatalReadError } : {}),
|
|
73
|
-
}));
|
|
74
|
-
}
|
|
75
|
-
return models;
|
|
76
|
-
}
|
|
77
64
|
// A run is not its invocation: a continuation is a new run on the invocation it
|
|
78
65
|
// resumes. This reader is addressed by run, so it looks the invocation up by the
|
|
79
66
|
// id it was actually given.
|
|
@@ -20,12 +20,13 @@ import { RUN_COMPOSITION_RECORDED_EVENT_TYPE } from '@maka/core/agent-run';
|
|
|
20
20
|
import { isRuntimeHandoffPause } from '@maka/core/runtime-handoff';
|
|
21
21
|
import { RunHandoffGate } from './run-handoff-gate.js';
|
|
22
22
|
import { preserveHandoffOpening } from './runtime-resume.js';
|
|
23
|
-
import { decodeRunCompositionSnapshot } from '@maka/core/run-composition';
|
|
23
|
+
import { createRequestCompositionSnapshot, decodeRequestCompositionSnapshot, decodeRunCompositionSnapshot, } from '@maka/core/run-composition';
|
|
24
24
|
import { DurableStoreWriteError, RunSealedError } from '@maka/core/runtime-event-store';
|
|
25
25
|
import { buildInvocationOpenedEvent, buildSyntheticTerminalRuntimeEvent, isSessionInlineInvocation, } from '@maka/core/runtime-invocation';
|
|
26
26
|
import { MODEL_PROJECTION_TRANSITION_EVENT_TYPE, } from '@maka/core/model-projection-transition';
|
|
27
27
|
import { isTerminalRuntimeEvent } from '@maka/core/runtime-event';
|
|
28
28
|
import { ToolLedgerCorruptionError, ToolLedgerRejectionError, } from '@maka/core/tool-ledger-scanner';
|
|
29
|
+
import { stableHash } from './request-shape.js';
|
|
29
30
|
import { Buffer } from 'node:buffer';
|
|
30
31
|
import { isDeepStrictEqual } from 'node:util';
|
|
31
32
|
import { redactSecrets } from '@maka/core/redaction';
|
|
@@ -79,6 +80,9 @@ export class AgentRun {
|
|
|
79
80
|
runComposition;
|
|
80
81
|
runCompositionWrite;
|
|
81
82
|
runCompositionCommitted = false;
|
|
83
|
+
requestComposition;
|
|
84
|
+
requestCompositionIndex;
|
|
85
|
+
requestCompositionIndexRead;
|
|
82
86
|
failureClass;
|
|
83
87
|
failureMessage;
|
|
84
88
|
lastTs = 0;
|
|
@@ -418,6 +422,72 @@ export class AgentRun {
|
|
|
418
422
|
throw new Error('Cooperative handoff requires a durably committed Run Composition');
|
|
419
423
|
}
|
|
420
424
|
}
|
|
425
|
+
/**
|
|
426
|
+
* Durably binds one logical model step to its effective request surface.
|
|
427
|
+
* Unchanged steps reuse the latest snapshot; a changed surface appends a full
|
|
428
|
+
* replacement before provider dispatch, matching DSH request/header epochs.
|
|
429
|
+
*/
|
|
430
|
+
async recordRequestComposition(input) {
|
|
431
|
+
if (!this.input.runStore) {
|
|
432
|
+
throw new Error('AgentRun store is not configured');
|
|
433
|
+
}
|
|
434
|
+
await this.loadRequestCompositionIndex();
|
|
435
|
+
const snapshot = createRequestCompositionSnapshot(input, this.requestCompositionIndex?.size ? 'change' : 'initial');
|
|
436
|
+
const surfaceHash = requestCompositionSurfaceHash(snapshot);
|
|
437
|
+
const existing = this.requestCompositionIndex?.get(surfaceHash);
|
|
438
|
+
if (existing) {
|
|
439
|
+
if (!sameRequestCompositionSurface(existing, snapshot)) {
|
|
440
|
+
throw new Error(`Request Composition surface hash collision: ${surfaceHash}`);
|
|
441
|
+
}
|
|
442
|
+
this.requestComposition = existing;
|
|
443
|
+
return existing.compositionId;
|
|
444
|
+
}
|
|
445
|
+
await this.enqueueRequiredRunStoreWrite('append request composition', async () => {
|
|
446
|
+
await this.input.runStore?.appendEvent(this.sessionId, this.runId, {
|
|
447
|
+
type: 'request_composition_resolved',
|
|
448
|
+
id: snapshot.compositionId,
|
|
449
|
+
runId: this.runId,
|
|
450
|
+
sessionId: this.sessionId,
|
|
451
|
+
turnId: this.turnId,
|
|
452
|
+
ts: this.input.now(),
|
|
453
|
+
data: { snapshot },
|
|
454
|
+
}, { durable: true });
|
|
455
|
+
});
|
|
456
|
+
this.requestComposition = snapshot;
|
|
457
|
+
this.requestCompositionIndex?.set(surfaceHash, snapshot);
|
|
458
|
+
return snapshot.compositionId;
|
|
459
|
+
}
|
|
460
|
+
async loadRequestCompositionIndex() {
|
|
461
|
+
if (this.requestCompositionIndex)
|
|
462
|
+
return;
|
|
463
|
+
if (this.requestCompositionIndexRead)
|
|
464
|
+
return await this.requestCompositionIndexRead;
|
|
465
|
+
const read = (async () => {
|
|
466
|
+
const index = new Map();
|
|
467
|
+
const events = await this.input.runStore?.readEvents(this.sessionId, this.runId);
|
|
468
|
+
for (const event of events ?? []) {
|
|
469
|
+
if (event.type !== 'request_composition_resolved')
|
|
470
|
+
continue;
|
|
471
|
+
const snapshot = decodeRequestCompositionSnapshot(event.data?.snapshot);
|
|
472
|
+
const surfaceHash = requestCompositionSurfaceHash(snapshot);
|
|
473
|
+
const existing = index.get(surfaceHash);
|
|
474
|
+
if (existing && !sameRequestCompositionSurface(existing, snapshot)) {
|
|
475
|
+
throw new Error(`Request Composition surface hash collision: ${surfaceHash}`);
|
|
476
|
+
}
|
|
477
|
+
index.set(surfaceHash, existing ?? snapshot);
|
|
478
|
+
this.requestComposition = snapshot;
|
|
479
|
+
}
|
|
480
|
+
this.requestCompositionIndex = index;
|
|
481
|
+
})();
|
|
482
|
+
this.requestCompositionIndexRead = read;
|
|
483
|
+
try {
|
|
484
|
+
await read;
|
|
485
|
+
}
|
|
486
|
+
finally {
|
|
487
|
+
if (this.requestCompositionIndexRead === read)
|
|
488
|
+
this.requestCompositionIndexRead = undefined;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
421
491
|
/**
|
|
422
492
|
* Canonical accounting record for one physical provider request (#1679).
|
|
423
493
|
*
|
|
@@ -1573,6 +1643,15 @@ function redactTraceString(value) {
|
|
|
1573
1643
|
function errorMessage(error) {
|
|
1574
1644
|
return redactTraceString(error instanceof Error ? error.message : String(error));
|
|
1575
1645
|
}
|
|
1646
|
+
function sameRequestCompositionSurface(current, candidate) {
|
|
1647
|
+
const { schemaVersion: _schemaVersion, compositionId: _compositionId, step: _step, reason: _reason, ...currentSurface } = current;
|
|
1648
|
+
const { schemaVersion: _candidateSchemaVersion, compositionId: _candidateCompositionId, step: _candidateStep, reason: _candidateReason, ...candidateSurface } = candidate;
|
|
1649
|
+
return isDeepStrictEqual(currentSurface, candidateSurface);
|
|
1650
|
+
}
|
|
1651
|
+
function requestCompositionSurfaceHash(snapshot) {
|
|
1652
|
+
const { schemaVersion: _schemaVersion, compositionId: _compositionId, step: _step, reason: _reason, ...surface } = snapshot;
|
|
1653
|
+
return stableHash(surface);
|
|
1654
|
+
}
|
|
1576
1655
|
function isInteractionResumeAck(event) {
|
|
1577
1656
|
return (event.type === 'sandbox_boundary_decision_ack' ||
|
|
1578
1657
|
event.type === 'user_question_answer_ack' ||
|
|
@@ -71,7 +71,8 @@ export class AiSdkBackend {
|
|
|
71
71
|
messageProjection;
|
|
72
72
|
providerTelemetry;
|
|
73
73
|
resolvedProviderOptions;
|
|
74
|
-
|
|
74
|
+
memoryTools;
|
|
75
|
+
applyPatchProfile;
|
|
75
76
|
/** Bounds outstanding Code Mode cells on this backend. */
|
|
76
77
|
codeCellAdmission = new AdmissionLimiter(MAX_ACTIVE_CODE_MODE_CELLS);
|
|
77
78
|
/**
|
|
@@ -147,6 +148,7 @@ export class AiSdkBackend {
|
|
|
147
148
|
beforeRunProviderDispatch: input.beforeRunProviderDispatch,
|
|
148
149
|
});
|
|
149
150
|
const applyPatchProfile = runtime.applyPatchProfile;
|
|
151
|
+
this.applyPatchProfile = applyPatchProfile;
|
|
150
152
|
this.messageProjection = new AiSdkMessageProjection({
|
|
151
153
|
modelAdapter: this.modelAdapter,
|
|
152
154
|
applyPatchProfile,
|
|
@@ -168,7 +170,7 @@ export class AiSdkBackend {
|
|
|
168
170
|
if (input.tools.some((tool) => tool.name === MEMORY_REMEMBER_TOOL_NAME || tool.name === MEMORY_EXTRACT_TOOL_NAME)) {
|
|
169
171
|
throw new Error('Long-term Memory trigger tool names are reserved by Runtime');
|
|
170
172
|
}
|
|
171
|
-
|
|
173
|
+
this.memoryTools = input.memoryExtraction
|
|
172
174
|
? buildMemoryExtractionTriggerTools({
|
|
173
175
|
capabilities: input.memoryExtraction,
|
|
174
176
|
snapshot: (trigger, context) => this.memorySourceSnapshot(trigger, context),
|
|
@@ -182,11 +184,17 @@ export class AiSdkBackend {
|
|
|
182
184
|
: {}),
|
|
183
185
|
})
|
|
184
186
|
: [];
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
}
|
|
188
|
+
snapshotToolAvailability() {
|
|
189
|
+
const hostTools = Object.freeze([...(this.input.resolveTools?.() ?? this.input.tools)]);
|
|
190
|
+
if (hostTools.some((tool) => tool.name === MEMORY_REMEMBER_TOOL_NAME || tool.name === MEMORY_EXTRACT_TOOL_NAME)) {
|
|
191
|
+
throw new Error('Long-term Memory trigger tool names are reserved by Runtime');
|
|
192
|
+
}
|
|
193
|
+
const modelTools = routeApplyPatchTools(hostTools, this.applyPatchProfile);
|
|
194
|
+
return {
|
|
195
|
+
hostTools,
|
|
196
|
+
runtime: new ToolAvailabilityRuntime(bindToolResultArchiveDecoder([...modelTools, ...this.memoryTools], this.input.toolResultArchive), this.input.toolAvailability, buildInvalidMakaTool()),
|
|
197
|
+
};
|
|
190
198
|
}
|
|
191
199
|
memorySourceSnapshot(trigger, context) {
|
|
192
200
|
if (trigger !== 'remember')
|
|
@@ -255,7 +263,7 @@ export class AiSdkBackend {
|
|
|
255
263
|
messageProjection: this.messageProjection,
|
|
256
264
|
providerTelemetry: this.providerTelemetry,
|
|
257
265
|
compaction: this.compaction,
|
|
258
|
-
|
|
266
|
+
snapshotToolAvailability: () => this.snapshotToolAvailability(),
|
|
259
267
|
codeCellAdmission: this.codeCellAdmission,
|
|
260
268
|
resolvedProviderOptions: this.resolvedProviderOptions,
|
|
261
269
|
session: this.turnSessionState,
|
|
@@ -37,7 +37,8 @@ import { hasActiveToolResultPruneDiagnosticPatch, hasBlockingReplayDiagnostics,
|
|
|
37
37
|
import { RunTrace } from './run-trace.js';
|
|
38
38
|
import { REQUEST_SANDBOX_BOUNDARY_TOOL_NAME, SANDBOX_BOUNDARY_DENIED_FOR_TURN, SANDBOX_BOUNDARY_FINALIZATION_PROMPT, } from './sandbox-boundary-tool.js';
|
|
39
39
|
import { buildRuntimeEventModelReplayPlan, buildSteeringEnvelope, collectToolActivityTurnIds, compatibleProviderReasoningReplayEventIds, formatTextWithInlineRefs, steeringMessagesMissingFromBase, steeringModelMessage, } from './model-history.js';
|
|
40
|
-
import { toolSchemaCharsForDiagnostics } from './request-shape.js';
|
|
40
|
+
import { toolSchemaCharsForDiagnostics, requestCompositionToolSchemas, stableHash, toolCatalogHash, } from './request-shape.js';
|
|
41
|
+
import { toolAvailabilityHash } from './tool-availability.js';
|
|
41
42
|
import { renderSwarmModePrompt } from './swarm-mode.js';
|
|
42
43
|
import { renderGraphModePrompt } from './graph-mode.js';
|
|
43
44
|
import { modelUsesNativeOpenAiResponses } from './model-runtime.js';
|
|
@@ -800,8 +801,8 @@ export class AiSdkTurn {
|
|
|
800
801
|
return;
|
|
801
802
|
}
|
|
802
803
|
// --- Build the provider-visible schema set. Tool execution stays in Runtime. ---
|
|
803
|
-
//
|
|
804
|
-
// Mutable activation belongs to this turn.
|
|
804
|
+
// Each logical step freezes its own scoped catalog and search projection.
|
|
805
|
+
// Mutable activation belongs to this turn and follows contribution identity.
|
|
805
806
|
const requiredOrchestrationTools = this.orchestration.mode === 'swarm'
|
|
806
807
|
? new Set([
|
|
807
808
|
'agent_list',
|
|
@@ -825,11 +826,22 @@ export class AiSdkTurn {
|
|
|
825
826
|
throw new Error(`Invalid tool mode: ${String(requestedToolMode)}`);
|
|
826
827
|
}
|
|
827
828
|
const toolMode = requestedToolMode;
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
829
|
+
const snapshotStepTools = () => {
|
|
830
|
+
const snapshot = this.deps.snapshotToolAvailability();
|
|
831
|
+
if (toolMode === 'code_mode' && snapshot.hostTools.some((tool) => tool.name === 'exec')) {
|
|
832
|
+
throw new Error('Tool name "exec" is reserved for Code Mode.');
|
|
833
|
+
}
|
|
834
|
+
const plan = projectToolModePlan(snapshot.runtime.prepare(this.activeTools, requiredOrchestrationTools), toolMode, codeModeExecTool);
|
|
835
|
+
const modelTools = {};
|
|
836
|
+
for (const tool of plan.providerTools) {
|
|
837
|
+
modelTools[tool.name] = tool.providerTool
|
|
838
|
+
? { kind: 'provider', providerTool: tool.providerTool }
|
|
839
|
+
: { kind: 'function', description: tool.description, inputSchema: tool.parameters };
|
|
840
|
+
}
|
|
841
|
+
toolRuntime.setGating(plan.gating);
|
|
842
|
+
return { plan, providerTools: plan.providerTools, modelTools };
|
|
843
|
+
};
|
|
844
|
+
let { plan, providerTools, modelTools } = snapshotStepTools();
|
|
833
845
|
let activeToolResultPruneDiagnosticPatch = {};
|
|
834
846
|
let midTurnCompactDiagnosticPatch;
|
|
835
847
|
// Tool names the repair path matches a mis-cased call against — follows the
|
|
@@ -843,44 +855,8 @@ export class AiSdkTurn {
|
|
|
843
855
|
: [...names];
|
|
844
856
|
};
|
|
845
857
|
const currentRepairToolNames = () => boundaryAwareToolNames(plan.currentRepairToolNames());
|
|
846
|
-
|
|
847
|
-
toolRuntime.setGating(plan.gating);
|
|
848
|
-
}
|
|
849
|
-
const modelTools = {};
|
|
850
|
-
for (const t of providerTools) {
|
|
851
|
-
modelTools[t.name] = t.providerTool
|
|
852
|
-
? { kind: 'provider', providerTool: t.providerTool }
|
|
853
|
-
: {
|
|
854
|
-
kind: 'function',
|
|
855
|
-
description: t.description,
|
|
856
|
-
inputSchema: t.parameters,
|
|
857
|
-
};
|
|
858
|
-
}
|
|
859
|
-
// Resolve the stable Provider envelope before automatic Compaction freezes
|
|
860
|
-
// its source. The same value is reused by the primary request; Memory does
|
|
861
|
-
// not resolve or mutate Agent configuration after the checkpoint commits.
|
|
858
|
+
let resolvedSystemPrompt = { sourceRevisions: [] };
|
|
862
859
|
let systemPrompt;
|
|
863
|
-
try {
|
|
864
|
-
systemPrompt = joinPromptFragments([
|
|
865
|
-
await this.resolveSystemPrompt(),
|
|
866
|
-
this.orchestration?.mode === 'swarm' ? renderSwarmModePrompt() : undefined,
|
|
867
|
-
this.orchestration?.mode === 'graph' ? renderGraphModePrompt() : undefined,
|
|
868
|
-
]);
|
|
869
|
-
}
|
|
870
|
-
catch (err) {
|
|
871
|
-
trace.modelStreamFailed(this.deps.modelAdapter.classifyError(err), err);
|
|
872
|
-
queue.push(this.makeErrorEvent(turnId, err));
|
|
873
|
-
queue.push({
|
|
874
|
-
type: 'complete',
|
|
875
|
-
id: this.deps.newId(),
|
|
876
|
-
turnId,
|
|
877
|
-
ts: this.deps.now(),
|
|
878
|
-
stopReason: 'error',
|
|
879
|
-
});
|
|
880
|
-
queue.close();
|
|
881
|
-
yield* this.drain(queue);
|
|
882
|
-
return;
|
|
883
|
-
}
|
|
884
860
|
// --- Build messages from RuntimeEvent history and its compatibility projection. ---
|
|
885
861
|
const priorReplayResult = await this.buildPriorMessages(input);
|
|
886
862
|
if (this.aborted) {
|
|
@@ -1083,7 +1059,8 @@ export class AiSdkTurn {
|
|
|
1083
1059
|
const onMidTurnDiagnosticPatch = (patch) => {
|
|
1084
1060
|
midTurnCompactDiagnosticPatch = mergeContextBudgetDiagnosticPatches(midTurnCompactDiagnosticPatch, patch);
|
|
1085
1061
|
};
|
|
1086
|
-
const
|
|
1062
|
+
const capacityProviderTools = [...providerTools];
|
|
1063
|
+
const midTurnCapacityHook = this.deps.compaction.buildMidTurnCapacityCompactProjection(turnId, midTurnState, queue, capacityProviderTools, onMidTurnDiagnosticPatch, this, this.automaticMemoryCompactionSupported()
|
|
1087
1064
|
? () => this.automaticMemoryCompactionDecision()
|
|
1088
1065
|
: undefined, this.automaticMemoryCompactionSupported()
|
|
1089
1066
|
? (dispatch) => this.dispatchAutomaticMemoryCompaction(dispatch)
|
|
@@ -1095,7 +1072,8 @@ export class AiSdkTurn {
|
|
|
1095
1072
|
pruneAppliedAtStep = runtimeSteps;
|
|
1096
1073
|
activeToolResultPruneDiagnosticPatch = mergeActiveToolResultPruneDiagnosticPatches(activeToolResultPruneDiagnosticPatch, patch);
|
|
1097
1074
|
});
|
|
1098
|
-
const
|
|
1075
|
+
const projectCurrentToolAvailability = (options) => plan.projectActiveTools?.(options);
|
|
1076
|
+
const shapedProjection = composeRequestProjection(projectCurrentToolAvailability, midTurnCapacityHook, activeToolResultPruneHook);
|
|
1099
1077
|
// Hooks shape; nothing measures the final payload. Whether it fits is
|
|
1100
1078
|
// the provider's answer (#4559).
|
|
1101
1079
|
const requestProjection = shapedProjection;
|
|
@@ -1111,6 +1089,14 @@ export class AiSdkTurn {
|
|
|
1111
1089
|
let finishReason = 'stop';
|
|
1112
1090
|
let terminalProviderError;
|
|
1113
1091
|
agentLoop: for (;;) {
|
|
1092
|
+
({ plan, providerTools, modelTools } = snapshotStepTools());
|
|
1093
|
+
resolvedSystemPrompt = await this.resolveSystemPrompt();
|
|
1094
|
+
systemPrompt = joinPromptFragments([
|
|
1095
|
+
resolvedSystemPrompt.text,
|
|
1096
|
+
this.orchestration.mode === 'swarm' ? renderSwarmModePrompt() : undefined,
|
|
1097
|
+
this.orchestration.mode === 'graph' ? renderGraphModePrompt() : undefined,
|
|
1098
|
+
]);
|
|
1099
|
+
capacityProviderTools.splice(0, capacityProviderTools.length, ...providerTools);
|
|
1114
1100
|
await this.drainSteeringInto(input, queue);
|
|
1115
1101
|
if (this.deps.backend.loadTurnRuntimeEvents) {
|
|
1116
1102
|
requestMessages = await loadDurableTurnProjection();
|
|
@@ -1159,7 +1145,20 @@ export class AiSdkTurn {
|
|
|
1159
1145
|
: undefined;
|
|
1160
1146
|
const projectedMessages = shaped?.messages ?? requestMessages;
|
|
1161
1147
|
const activeToolsForRequest = resolveDispatch(shaped?.activeTools).activeTools;
|
|
1162
|
-
|
|
1148
|
+
const requestCompositionId = this.runId && this.deps.backend.recordRequestComposition
|
|
1149
|
+
? await this.deps.backend.recordRequestComposition(this.runId, {
|
|
1150
|
+
compositionId: this.deps.newId(),
|
|
1151
|
+
step: runtimeSteps,
|
|
1152
|
+
sourceRevisions: resolvedSystemPrompt.sourceRevisions,
|
|
1153
|
+
systemPromptHash: stableHash(requestSystemPrompt ?? ''),
|
|
1154
|
+
toolCatalogHash: toolCatalogHash(providerTools),
|
|
1155
|
+
toolAvailabilityHash: toolAvailabilityHash(this.deps.backend.toolAvailability),
|
|
1156
|
+
providerOptionsHash: stableHash(this.deps.resolvedProviderOptions),
|
|
1157
|
+
toolNames: activeToolsForRequest,
|
|
1158
|
+
toolSchemas: requestCompositionToolSchemas(providerTools, activeToolsForRequest),
|
|
1159
|
+
})
|
|
1160
|
+
: undefined;
|
|
1161
|
+
providerRequestTracker?.setStep(runtimeSteps, requestCompositionId);
|
|
1163
1162
|
let attemptMessages = projectedMessages;
|
|
1164
1163
|
let providerAttempt = 1;
|
|
1165
1164
|
let idleWatchdogRetryCount = 0;
|
|
@@ -2488,14 +2487,22 @@ export class AiSdkTurn {
|
|
|
2488
2487
|
async resolveSystemPrompt() {
|
|
2489
2488
|
const turnId = this.turnId;
|
|
2490
2489
|
if (typeof this.deps.backend.systemPrompt === 'function') {
|
|
2491
|
-
|
|
2490
|
+
const resolved = await this.deps.backend.systemPrompt({
|
|
2492
2491
|
sessionId: this.deps.backend.sessionId,
|
|
2493
2492
|
turnId,
|
|
2494
2493
|
cwd: this.deps.backend.header.cwd,
|
|
2495
2494
|
emitSkillCatalogTrace: (message, data) => this.runTrace?.emit('skill', 'skill_catalog_built', message, data),
|
|
2496
2495
|
});
|
|
2496
|
+
return typeof resolved === 'string' || resolved === undefined
|
|
2497
|
+
? { ...(resolved === undefined ? {} : { text: resolved }), sourceRevisions: [] }
|
|
2498
|
+
: resolved;
|
|
2497
2499
|
}
|
|
2498
|
-
return
|
|
2500
|
+
return {
|
|
2501
|
+
...(this.deps.backend.systemPrompt === undefined
|
|
2502
|
+
? {}
|
|
2503
|
+
: { text: this.deps.backend.systemPrompt }),
|
|
2504
|
+
sourceRevisions: [],
|
|
2505
|
+
};
|
|
2499
2506
|
}
|
|
2500
2507
|
async *drain(queue) {
|
|
2501
2508
|
try {
|
|
@@ -25,7 +25,7 @@ export function buildArchiveReadTool(reader) {
|
|
|
25
25
|
.object({
|
|
26
26
|
ref: z
|
|
27
27
|
.string()
|
|
28
|
-
.describe('
|
|
28
|
+
.describe('The exact resourceRef returned in an archived tool-result placeholder (ledger or legacy archive)'),
|
|
29
29
|
operation: z
|
|
30
30
|
.enum(['inspect', 'read', 'query', 'search'])
|
|
31
31
|
.default('inspect')
|
|
@@ -82,7 +82,7 @@ export function buildArchiveReadTool(reader) {
|
|
|
82
82
|
name: ARCHIVE_READ_TOOL_NAME,
|
|
83
83
|
displayName: 'Read archived result',
|
|
84
84
|
activityKind: 'read',
|
|
85
|
-
description: 'Inspect, search, or page through a tool-result archive
|
|
85
|
+
description: 'Inspect, search, or page through a tool-result archive using its exact resourceRef. Both ledger and legacy archive references are supported. Start with inspect for a preview and the char/line coordinate space. Use operation "search" with a pattern to locate text, operation "read" with unit "line" for line-oriented terminal output, or operation "query" with an itemId for one agent_swarm item. Results are strictly bounded so reading an archive cannot immediately trigger another archive.',
|
|
86
86
|
parameters: jsonSchema(async () => await providerSchema.jsonSchema, {
|
|
87
87
|
validate: async (value) => {
|
|
88
88
|
const result = await parameters.safeParseAsync(value);
|
|
@@ -46,22 +46,9 @@ export function stableJsonLength(value) {
|
|
|
46
46
|
export function turnKey(event) {
|
|
47
47
|
return event.turnId || '<unknown-turn>';
|
|
48
48
|
}
|
|
49
|
-
export function uniqueSorted(values) {
|
|
50
|
-
return [...new Set(values.filter((value) => value.length > 0))].sort();
|
|
51
|
-
}
|
|
52
49
|
export function sha256(text) {
|
|
53
50
|
return createHash('sha256').update(text).digest('hex');
|
|
54
51
|
}
|
|
55
|
-
export function stableStringify(value) {
|
|
56
|
-
if (value === undefined)
|
|
57
|
-
return '';
|
|
58
|
-
try {
|
|
59
|
-
return JSON.stringify(value) ?? '';
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
return String(value);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
52
|
export function finitePositive(value) {
|
|
66
53
|
return typeof value === 'number' && Number.isFinite(value) && value > 0
|
|
67
54
|
? Math.floor(value)
|
|
@@ -70,6 +57,3 @@ export function finitePositive(value) {
|
|
|
70
57
|
export function utf8ByteLength(text) {
|
|
71
58
|
return Buffer.byteLength(text, 'utf8');
|
|
72
59
|
}
|
|
73
|
-
export function optionalNonNegativeFiniteNumber(value) {
|
|
74
|
-
return value === undefined || (typeof value === 'number' && Number.isFinite(value) && value >= 0);
|
|
75
|
-
}
|