maka-agent 0.2.0-dev.31.20260913 → 0.2.0-dev.32.20260914
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/dist/pi-transcript.js +3 -4
- 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-graph-schedule.js +15 -4
- package/node_modules/@maka/core/dist/executor-id.js +22 -0
- package/node_modules/@maka/core/dist/external-session.js +18 -0
- package/node_modules/@maka/core/dist/model-call-usage-projection.js +0 -13
- package/node_modules/@maka/core/dist/runtime-event.js +19 -3
- package/node_modules/@maka/core/dist/session-send-projection.js +6 -3
- package/node_modules/@maka/core/dist/session.js +8 -2
- package/node_modules/@maka/core/dist/shell-run-result.js +1 -0
- package/node_modules/@maka/core/dist/shell-run.js +4 -0
- package/node_modules/@maka/core/dist/work-board.js +94 -1
- package/node_modules/@maka/core/package.json +1 -0
- package/node_modules/@maka/eval/dist/fleet-simulation.js +270 -0
- package/node_modules/@maka/eval/dist/fleet-store.js +243 -0
- package/node_modules/@maka/eval/dist/fleet-worker.js +125 -0
- package/node_modules/@maka/eval/dist/fleet.js +329 -0
- package/node_modules/@maka/eval/dist/index.js +3 -0
- package/node_modules/@maka/runtime/dist/agent-run.js +2 -17
- package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +6 -2
- package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +36 -24
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +257 -330
- package/node_modules/@maka/runtime/dist/background-task-health-tool.js +104 -0
- package/node_modules/@maka/runtime/dist/history-compaction.js +3 -1
- package/node_modules/@maka/runtime/dist/local-web-fetch.js +1 -1
- package/node_modules/@maka/runtime/dist/model-adapter.js +62 -53
- package/node_modules/@maka/runtime/dist/model-history.js +1 -5
- package/node_modules/@maka/runtime/dist/plugin-executor-backend.js +311 -0
- package/node_modules/@maka/runtime/dist/plugin-executor-service.js +344 -0
- package/node_modules/@maka/runtime/dist/provider-error-classification.js +7 -1
- package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +35 -8
- package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +7 -1
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +1 -0
- package/node_modules/@maka/runtime/dist/runtime-invocation-route.js +49 -0
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +72 -150
- package/node_modules/@maka/runtime/dist/runtime-read-model.js +0 -2
- package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +3 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +100 -58
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +9 -3
- package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +1 -0
- package/node_modules/@maka/runtime/dist/stream-graph-schedule-reconcile.js +1 -0
- package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +26 -4
- package/node_modules/@maka/runtime/dist/subagent-tools.js +7 -0
- package/node_modules/@maka/runtime/dist/tool-runtime.js +45 -466
- package/node_modules/@maka/runtime/package.json +3 -0
- package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +7 -2
- package/node_modules/@maka/runtime-host/dist/client/session-catalog-summary.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/external-session.js +24 -3
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +4 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +42 -5
- package/node_modules/@maka/runtime-host/dist/protocol/session-catalog.js +31 -3
- package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/child-agent-composition.js +1 -0
- package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +1 -22
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +54 -8
- package/node_modules/@maka/runtime-host/dist/server/external-session-coordinator.js +14 -1
- package/node_modules/@maka/runtime-host/dist/server/host-session-availability.js +10 -2
- 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-catalog-coordinator.js +56 -16
- package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +4 -3
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/web-fetch-tool.js +37 -1
- package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +450 -234
- package/node_modules/@maka/storage/dist/claude-code-transcript-lineage.js +106 -77
- package/node_modules/@maka/storage/dist/legacy-run-header.js +2 -2
- package/node_modules/@maka/storage/dist/model-call-usage-sql.js +1 -1
- package/node_modules/@maka/storage/dist/session-store.js +12 -2
- package/node_modules/@maka/storage/dist/sqlite-long-term-memory-store.js +86 -12
- package/node_modules/@maka/storage/dist/work-board-store.js +40 -1
- package/package.json +1 -1
|
@@ -25,8 +25,7 @@ import { encodeToolStepProgress, ToolOutcomeUnknownError } from '@maka/core/even
|
|
|
25
25
|
import { isInteractionAnswerValidForRequest, projectInteractionFormRequest, } from '@maka/core/interaction';
|
|
26
26
|
import { computerUseModelCallArgs } from '@maka/core/computer-use';
|
|
27
27
|
import { redactSecrets } from '@maka/core/redaction';
|
|
28
|
-
import {
|
|
29
|
-
import { isDeepStrictEqual } from 'node:util';
|
|
28
|
+
import { TOOL_BOUNDARY_PROTOCOL_V1 } from '@maka/core/runtime-event';
|
|
30
29
|
import { recordToolArtifactsSafely } from './tool-artifacts.js';
|
|
31
30
|
import { computerActionFields, describeComputerUseArgsViolation } from './computer-use-codec.js';
|
|
32
31
|
import { createToolOutputDeltaEmitter } from './tool-output-delta.js';
|
|
@@ -74,12 +73,6 @@ class RuntimeCommitBoundaryError extends Error {
|
|
|
74
73
|
this.name = 'RuntimeCommitBoundaryError';
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
|
-
class RuntimeManagedMutationUnsettledError extends Error {
|
|
78
|
-
constructor(cause) {
|
|
79
|
-
super(`Managed workspace mutation remains unsettled: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
80
|
-
this.name = 'RuntimeManagedMutationUnsettledError';
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
76
|
class ToolResultLimitError extends Error {
|
|
84
77
|
constructor() {
|
|
85
78
|
super('Tool result byte limit exceeded');
|
|
@@ -514,18 +507,31 @@ export class ToolRuntime {
|
|
|
514
507
|
result: content,
|
|
515
508
|
isError: true,
|
|
516
509
|
}, this.input.sessionId) ?? DURABLE_TOOL_RESULT_PROJECTION_FAILURE;
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
type: 'tool_result',
|
|
520
|
-
id: durableOutcome?.id ?? this.input.newId(),
|
|
510
|
+
await this.commitAndPublishToolResult({
|
|
511
|
+
queue,
|
|
521
512
|
turnId,
|
|
522
|
-
ts: durableOutcome?.ts ?? this.input.now(),
|
|
523
513
|
toolUseId,
|
|
524
|
-
...(durableOutcome ? { operationId: durableOutcome.operationId } : {}),
|
|
525
514
|
isError: true,
|
|
526
515
|
content,
|
|
527
516
|
modelProjection,
|
|
528
|
-
|
|
517
|
+
activityIdentity,
|
|
518
|
+
durableAttempt,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
async commitAndPublishToolResult(input) {
|
|
522
|
+
const durableOutcome = await input.durableAttempt?.commitOutcome(input.content, input.isError, input.modelProjection, input.durationMs);
|
|
523
|
+
input.queue.push({
|
|
524
|
+
type: 'tool_result',
|
|
525
|
+
id: durableOutcome?.id ?? this.input.newId(),
|
|
526
|
+
turnId: input.turnId,
|
|
527
|
+
ts: durableOutcome?.ts ?? this.input.now(),
|
|
528
|
+
toolUseId: input.toolUseId,
|
|
529
|
+
...(durableOutcome ? { operationId: durableOutcome.operationId } : {}),
|
|
530
|
+
isError: input.isError,
|
|
531
|
+
content: input.content,
|
|
532
|
+
modelProjection: input.modelProjection,
|
|
533
|
+
...(input.durationMs !== undefined ? { durationMs: input.durationMs } : {}),
|
|
534
|
+
...input.activityIdentity,
|
|
529
535
|
});
|
|
530
536
|
}
|
|
531
537
|
async executeTool(tool, turnId, queue, args, ctx, stepId) {
|
|
@@ -903,38 +909,9 @@ export class ToolRuntime {
|
|
|
903
909
|
pauseTarget?.resume();
|
|
904
910
|
}
|
|
905
911
|
}
|
|
906
|
-
let managedMutationAdmission;
|
|
907
|
-
if (tool.durableExecutionProfile === 'managed_mutation_v1') {
|
|
908
|
-
if ((tool.name !== 'Write' && tool.name !== 'Edit') ||
|
|
909
|
-
tool.recoveryMode !== 'reconcile' ||
|
|
910
|
-
!tool.managedMutationTransform ||
|
|
911
|
-
!dispatchOperationId ||
|
|
912
|
-
!this.input.runtimeCommitSink ||
|
|
913
|
-
!this.input.admitManagedMutation) {
|
|
914
|
-
const reason = 'Managed workspace mutation admission is unavailable before T1';
|
|
915
|
-
await refuseBeforeDispatch(reason);
|
|
916
|
-
this.recordLoopGateOutcome(callSignature, true);
|
|
917
|
-
return this.errorReturn(reason);
|
|
918
|
-
}
|
|
919
|
-
try {
|
|
920
|
-
managedMutationAdmission = await this.input.admitManagedMutation({
|
|
921
|
-
operationId: dispatchOperationId,
|
|
922
|
-
toolName: tool.name,
|
|
923
|
-
persistedArgs: structuredClone(persistedArgs),
|
|
924
|
-
abortSignal: ctx.abortSignal,
|
|
925
|
-
});
|
|
926
|
-
}
|
|
927
|
-
catch (error) {
|
|
928
|
-
const reason = `Managed workspace mutation admission failed: ${formatSyntheticToolErrorText(error)}`;
|
|
929
|
-
await refuseBeforeDispatch(reason);
|
|
930
|
-
this.recordLoopGateOutcome(callSignature, true);
|
|
931
|
-
return this.errorReturn(reason);
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
912
|
const reservedSubagentSlot = this.reserveSubagentSlot(tool);
|
|
935
913
|
if (!reservedSubagentSlot) {
|
|
936
914
|
await preparedExecution?.cancel();
|
|
937
|
-
await disposeManagedMutationAdmission(managedMutationAdmission);
|
|
938
915
|
trace?.emit('tool', 'tool_failed', 'Tool execution rejected by runtime limit', {
|
|
939
916
|
toolUseId,
|
|
940
917
|
toolName: tool.name,
|
|
@@ -953,9 +930,6 @@ export class ToolRuntime {
|
|
|
953
930
|
persistedArgs,
|
|
954
931
|
modelFacingArgs,
|
|
955
932
|
abortSignal: ctx.abortSignal,
|
|
956
|
-
...(managedMutationAdmission
|
|
957
|
-
? { managedMutation: managedMutationAdmission.durableDispatch }
|
|
958
|
-
: {}),
|
|
959
933
|
...(invocationId ? { invocationId } : {}),
|
|
960
934
|
...(runId ? { runId } : {}),
|
|
961
935
|
});
|
|
@@ -964,7 +938,6 @@ export class ToolRuntime {
|
|
|
964
938
|
await preparedExecution?.cancel();
|
|
965
939
|
if (reservedSubagentSlot)
|
|
966
940
|
this.releaseSubagentSlot(tool);
|
|
967
|
-
await disposeManagedMutationAdmission(managedMutationAdmission);
|
|
968
941
|
throw error;
|
|
969
942
|
}
|
|
970
943
|
publishCallEvent(buildCallEvent('dispatch'));
|
|
@@ -1063,145 +1036,41 @@ export class ToolRuntime {
|
|
|
1063
1036
|
const invokeTool = () => preparedExecution
|
|
1064
1037
|
? preparedExecution.execute(toolContext)
|
|
1065
1038
|
: tool.impl(structuredClone(executionArgs), toolContext);
|
|
1066
|
-
const
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
const result = immutableSnapshot
|
|
1070
|
-
? snapshotManagedToolResult(rawResult, ctx.maxResultBytes)
|
|
1071
|
-
: rawResult;
|
|
1072
|
-
if (!immutableSnapshot &&
|
|
1073
|
-
ctx.maxResultBytes !== undefined &&
|
|
1039
|
+
const prepareOperationValue = async () => {
|
|
1040
|
+
const result = await invokeTool();
|
|
1041
|
+
if (ctx.maxResultBytes !== undefined &&
|
|
1074
1042
|
serializedByteLength(result, ctx.maxResultBytes) > ctx.maxResultBytes) {
|
|
1075
1043
|
throw new ToolResultLimitError();
|
|
1076
1044
|
}
|
|
1077
|
-
const content =
|
|
1078
|
-
? Object.freeze(coerceResultContent(result))
|
|
1079
|
-
: coerceResultContent(result);
|
|
1045
|
+
const content = coerceResultContent(result);
|
|
1080
1046
|
const projected = this.projectToolResult(tool, turnId, toolUseId, executionArgs, result);
|
|
1081
1047
|
const modelProjection = isPromiseLike(projected) ? await projected : projected;
|
|
1082
|
-
|
|
1048
|
+
return {
|
|
1049
|
+
result,
|
|
1083
1050
|
content,
|
|
1084
1051
|
isError: deriveToolResultStatus(content, result) !== 'success',
|
|
1085
1052
|
durationMs: this.input.now() - startedAt,
|
|
1086
1053
|
modelProjection,
|
|
1087
1054
|
};
|
|
1088
|
-
const value = {
|
|
1089
|
-
result,
|
|
1090
|
-
outcome: immutableSnapshot ? Object.freeze(outcome) : outcome,
|
|
1091
|
-
};
|
|
1092
|
-
return immutableSnapshot ? Object.freeze(value) : value;
|
|
1093
1055
|
};
|
|
1094
|
-
|
|
1095
|
-
if (managedMutationAdmission) {
|
|
1096
|
-
const operationLifecycle = { state: 'open' };
|
|
1097
|
-
let operationPromise;
|
|
1098
|
-
let runtimeOwnedValue;
|
|
1099
|
-
const executeManagedOperation = () => {
|
|
1100
|
-
if (operationLifecycle.state !== 'open') {
|
|
1101
|
-
if (operationLifecycle.state === 'closed') {
|
|
1102
|
-
return Promise.reject(new Error('Managed mutation operation capability is closed'));
|
|
1103
|
-
}
|
|
1104
|
-
return Promise.reject(new Error('Managed mutation owner invoked the operation more than once'));
|
|
1105
|
-
}
|
|
1106
|
-
operationLifecycle.state = 'running';
|
|
1107
|
-
operationPromise = (async () => {
|
|
1108
|
-
try {
|
|
1109
|
-
const value = await prepareOperationValue(true);
|
|
1110
|
-
runtimeOwnedValue = value;
|
|
1111
|
-
return {
|
|
1112
|
-
// The canonical content is already recursively immutable, so
|
|
1113
|
-
// the owner can read it without receiving a mutable alias.
|
|
1114
|
-
content: value.outcome.content,
|
|
1115
|
-
isError: value.outcome.isError,
|
|
1116
|
-
durationMs: value.outcome.durationMs,
|
|
1117
|
-
modelProjection: value.outcome.modelProjection,
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
1120
|
-
finally {
|
|
1121
|
-
if (operationLifecycle.state === 'running') {
|
|
1122
|
-
operationLifecycle.state = 'settled';
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
})();
|
|
1126
|
-
// Runtime also observes the promise so a careless owner cannot
|
|
1127
|
-
// turn an un-awaited operation rejection into an unhandled one.
|
|
1128
|
-
void operationPromise.catch(() => undefined);
|
|
1129
|
-
return operationPromise;
|
|
1130
|
-
};
|
|
1131
|
-
let settlement;
|
|
1132
|
-
let ownerFailed = false;
|
|
1133
|
-
let ownerError;
|
|
1134
|
-
try {
|
|
1135
|
-
settlement = await managedMutationAdmission.execute(executeManagedOperation);
|
|
1136
|
-
}
|
|
1137
|
-
catch (error) {
|
|
1138
|
-
ownerFailed = true;
|
|
1139
|
-
ownerError = error;
|
|
1140
|
-
}
|
|
1141
|
-
const ownerSettledWhileOperationRunning = operationLifecycle.state === 'running';
|
|
1142
|
-
if (ownerSettledWhileOperationRunning) {
|
|
1143
|
-
try {
|
|
1144
|
-
await operationPromise;
|
|
1145
|
-
}
|
|
1146
|
-
catch {
|
|
1147
|
-
// The terminal state is invalid regardless of how the detached
|
|
1148
|
-
// operation settles. Join it so no side effect can occur later.
|
|
1149
|
-
}
|
|
1150
|
-
finally {
|
|
1151
|
-
operationLifecycle.state = 'closed';
|
|
1152
|
-
}
|
|
1153
|
-
throw new RuntimeManagedMutationUnsettledError(new Error('Managed mutation owner settled before the operation completed', {
|
|
1154
|
-
...(ownerFailed ? { cause: ownerError } : {}),
|
|
1155
|
-
}));
|
|
1156
|
-
}
|
|
1157
|
-
operationLifecycle.state = 'closed';
|
|
1158
|
-
if (ownerFailed) {
|
|
1159
|
-
// Once managed T1 is durable, an admission/owner failure may never
|
|
1160
|
-
// fall through to the generic synthetic T2 path. Only the owner can
|
|
1161
|
-
// prove that a successor was accepted or the candidate was safely
|
|
1162
|
-
// discarded; every other failure remains unsettled for recovery.
|
|
1163
|
-
throw new RuntimeManagedMutationUnsettledError(ownerError);
|
|
1164
|
-
}
|
|
1165
|
-
const normalized = normalizeManagedMutationSettlement(settlement, ctx.maxResultBytes);
|
|
1166
|
-
if (normalized.kind === 'workspace_successor_committed') {
|
|
1167
|
-
if (!runtimeOwnedValue) {
|
|
1168
|
-
throw new RuntimeManagedMutationUnsettledError(new Error('Managed mutation owner committed success without executing the operation'));
|
|
1169
|
-
}
|
|
1170
|
-
settledExecution = {
|
|
1171
|
-
kind: 'managed',
|
|
1172
|
-
value: runtimeOwnedValue,
|
|
1173
|
-
durableOutcome: normalized.durableOutcome,
|
|
1174
|
-
};
|
|
1175
|
-
}
|
|
1176
|
-
else {
|
|
1177
|
-
settledExecution = {
|
|
1178
|
-
kind: 'managed',
|
|
1179
|
-
value: normalized.value,
|
|
1180
|
-
durableOutcome: normalized.durableOutcome,
|
|
1181
|
-
};
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
else {
|
|
1185
|
-
settledExecution = { kind: 'generic', value: await prepareOperationValue() };
|
|
1186
|
-
}
|
|
1187
|
-
const { result, outcome } = settledExecution.value;
|
|
1056
|
+
const { result, content, isError, durationMs, modelProjection } = await prepareOperationValue();
|
|
1188
1057
|
output.flush();
|
|
1189
|
-
const { content, durationMs, modelProjection } = outcome;
|
|
1190
1058
|
// Keep the full provider-facing terminal classification. `isError` is
|
|
1191
1059
|
// sufficient for the durable response envelope, but it intentionally
|
|
1192
1060
|
// collapses `aborted` into an error bit and therefore cannot drive live
|
|
1193
1061
|
// tool status, telemetry, or subagent lifecycle projection.
|
|
1194
1062
|
const toolResultStatus = deriveToolResultStatus(content, result);
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1063
|
+
await this.commitAndPublishToolResult({
|
|
1064
|
+
queue,
|
|
1065
|
+
turnId,
|
|
1066
|
+
toolUseId,
|
|
1067
|
+
isError,
|
|
1068
|
+
content,
|
|
1069
|
+
modelProjection,
|
|
1070
|
+
durationMs,
|
|
1071
|
+
activityIdentity,
|
|
1072
|
+
durableAttempt,
|
|
1073
|
+
});
|
|
1205
1074
|
if (hasSandboxDenial(content)) {
|
|
1206
1075
|
const denialKey = sandboxDenialKey(tool.name, this.input.header.cwd, executionArgs);
|
|
1207
1076
|
this.recentSandboxDenials.add(denialKey);
|
|
@@ -1216,19 +1085,6 @@ export class ToolRuntime {
|
|
|
1216
1085
|
commandHash: denialKey,
|
|
1217
1086
|
});
|
|
1218
1087
|
}
|
|
1219
|
-
queue.push({
|
|
1220
|
-
type: 'tool_result',
|
|
1221
|
-
id: durableOutcome?.id ?? this.input.newId(),
|
|
1222
|
-
turnId,
|
|
1223
|
-
ts: durableOutcome?.ts ?? this.input.now(),
|
|
1224
|
-
toolUseId,
|
|
1225
|
-
...(durableOutcome ? { operationId: durableOutcome.operationId } : {}),
|
|
1226
|
-
isError: toolResultStatus !== 'success',
|
|
1227
|
-
content,
|
|
1228
|
-
modelProjection,
|
|
1229
|
-
durationMs,
|
|
1230
|
-
...activityIdentity,
|
|
1231
|
-
});
|
|
1232
1088
|
this.input.recordToolInvocation?.({
|
|
1233
1089
|
sessionId: this.input.sessionId,
|
|
1234
1090
|
turnId,
|
|
@@ -1286,17 +1142,8 @@ export class ToolRuntime {
|
|
|
1286
1142
|
}
|
|
1287
1143
|
}
|
|
1288
1144
|
catch (err) {
|
|
1289
|
-
if (err instanceof RuntimeCommitBoundaryError
|
|
1290
|
-
err instanceof RuntimeManagedMutationUnsettledError) {
|
|
1145
|
+
if (err instanceof RuntimeCommitBoundaryError)
|
|
1291
1146
|
throw err;
|
|
1292
|
-
}
|
|
1293
|
-
// Admission exists only after the owner has selected managed mode and
|
|
1294
|
-
// Runtime has committed its T1 dispatch. From that point onward every
|
|
1295
|
-
// normalization, size check, adoption, publication, and telemetry error
|
|
1296
|
-
// is recovery-owned. It may never fall through to generic synthetic T2.
|
|
1297
|
-
if (managedMutationAdmission) {
|
|
1298
|
-
throw new RuntimeManagedMutationUnsettledError(err);
|
|
1299
|
-
}
|
|
1300
1147
|
if (isInteractionControlError(err))
|
|
1301
1148
|
throw err;
|
|
1302
1149
|
output.flush();
|
|
@@ -1323,19 +1170,16 @@ export class ToolRuntime {
|
|
|
1323
1170
|
const terminalResult = this.errorReturn(terminalFailure.message);
|
|
1324
1171
|
const projected = this.projectToolResult(tool, turnId, toolUseId, executionArgs, terminalFailure.content);
|
|
1325
1172
|
const modelProjection = isPromiseLike(projected) ? await projected : projected;
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
type: 'tool_result',
|
|
1329
|
-
id: durableOutcome?.id ?? this.input.newId(),
|
|
1173
|
+
await this.commitAndPublishToolResult({
|
|
1174
|
+
queue,
|
|
1330
1175
|
turnId,
|
|
1331
|
-
ts: durableOutcome?.ts ?? this.input.now(),
|
|
1332
1176
|
toolUseId,
|
|
1333
|
-
...(durableOutcome ? { operationId: durableOutcome.operationId } : {}),
|
|
1334
1177
|
isError: true,
|
|
1335
1178
|
content: terminalFailure.content,
|
|
1336
1179
|
modelProjection,
|
|
1337
1180
|
durationMs,
|
|
1338
|
-
|
|
1181
|
+
activityIdentity,
|
|
1182
|
+
durableAttempt,
|
|
1339
1183
|
});
|
|
1340
1184
|
this.input.recordToolInvocation?.({
|
|
1341
1185
|
sessionId: this.input.sessionId,
|
|
@@ -1404,7 +1248,6 @@ export class ToolRuntime {
|
|
|
1404
1248
|
this.recordLoopGateOutcome(callSignature, attemptFailed, attemptBoundaryKind, attemptBoundaryDetails);
|
|
1405
1249
|
if (reservedSubagentSlot)
|
|
1406
1250
|
this.releaseSubagentSlot(tool);
|
|
1407
|
-
await disposeManagedMutationAdmission(managedMutationAdmission);
|
|
1408
1251
|
}
|
|
1409
1252
|
}
|
|
1410
1253
|
async prepareDurableToolAttempt(input) {
|
|
@@ -1486,7 +1329,6 @@ export class ToolRuntime {
|
|
|
1486
1329
|
toolName: input.tool.name,
|
|
1487
1330
|
canonicalArgsHash,
|
|
1488
1331
|
recoveryMode,
|
|
1489
|
-
...(input.managedMutation ? { managedMutation: input.managedMutation } : {}),
|
|
1490
1332
|
},
|
|
1491
1333
|
},
|
|
1492
1334
|
refs: {
|
|
@@ -1501,22 +1343,6 @@ export class ToolRuntime {
|
|
|
1501
1343
|
},
|
|
1502
1344
|
};
|
|
1503
1345
|
try {
|
|
1504
|
-
if (input.managedMutation) {
|
|
1505
|
-
decodeRuntimeEvent(dispatchEvent);
|
|
1506
|
-
const persistedPath = input.persistedArgs &&
|
|
1507
|
-
typeof input.persistedArgs === 'object' &&
|
|
1508
|
-
!Array.isArray(input.persistedArgs)
|
|
1509
|
-
? input.persistedArgs.path
|
|
1510
|
-
: undefined;
|
|
1511
|
-
if ((input.tool.name !== 'Write' && input.tool.name !== 'Edit') ||
|
|
1512
|
-
typeof persistedPath !== 'string' ||
|
|
1513
|
-
input.managedMutation.expectedPath !== persistedPath ||
|
|
1514
|
-
input.managedMutation.pathPolicyVersion !== 3 ||
|
|
1515
|
-
input.managedMutation.executionProfileDigest !==
|
|
1516
|
-
MANAGED_MUTATION_EXECUTION_PROFILE_V1_DIGEST) {
|
|
1517
|
-
throw new Error('Managed mutation admission does not match the durable tool call');
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
1346
|
this.assertDurableDispatchNotAborted(input.tool.name, input.abortSignal);
|
|
1521
1347
|
const prepared = await sink.commitToolPrepared({
|
|
1522
1348
|
operationId,
|
|
@@ -1571,7 +1397,6 @@ export class ToolRuntime {
|
|
|
1571
1397
|
let committedOutcome;
|
|
1572
1398
|
return {
|
|
1573
1399
|
operationId,
|
|
1574
|
-
responseEventId: `${operationId}_response`,
|
|
1575
1400
|
commitOutcome: async (result, isError, modelProjection, durationMs) => {
|
|
1576
1401
|
if (committedOutcome)
|
|
1577
1402
|
return committedOutcome;
|
|
@@ -1607,17 +1432,6 @@ export class ToolRuntime {
|
|
|
1607
1432
|
this.durableToolAttempts.delete(durableAttemptKey(input.startEvent.turnId, input.startEvent.toolUseId));
|
|
1608
1433
|
return committedOutcome;
|
|
1609
1434
|
},
|
|
1610
|
-
adoptCommittedOutcome: (event, result, isError, modelProjection, durationMs) => {
|
|
1611
|
-
if (committedOutcome)
|
|
1612
|
-
return committedOutcome;
|
|
1613
|
-
const expected = buildResponseEvent(result, isError, modelProjection, durationMs, event.ts);
|
|
1614
|
-
if (!Number.isFinite(event.ts) || !isDeepStrictEqual(event, expected)) {
|
|
1615
|
-
throw new RuntimeCommitBoundaryError('T2', new Error('Managed mutation settlement returned a mismatched durable outcome'));
|
|
1616
|
-
}
|
|
1617
|
-
committedOutcome = { id: event.id, operationId, ts: event.ts };
|
|
1618
|
-
this.durableToolAttempts.delete(durableAttemptKey(input.startEvent.turnId, input.startEvent.toolUseId));
|
|
1619
|
-
return committedOutcome;
|
|
1620
|
-
},
|
|
1621
1435
|
};
|
|
1622
1436
|
}
|
|
1623
1437
|
admitToolForStep(tool, stepId) {
|
|
@@ -1755,6 +1569,7 @@ export class ToolRuntime {
|
|
|
1755
1569
|
toolCallId: input.toolUseId,
|
|
1756
1570
|
agentProfile: spawnInput.agentProfile,
|
|
1757
1571
|
...(spawnInput.subagentId ? { subagentId: spawnInput.subagentId } : {}),
|
|
1572
|
+
...(spawnInput.executorId ? { executorId: spawnInput.executorId } : {}),
|
|
1758
1573
|
prompt: spawnInput.prompt,
|
|
1759
1574
|
...(spawnInput.swarm ? { swarm: spawnInput.swarm } : {}),
|
|
1760
1575
|
abortSignal,
|
|
@@ -2577,64 +2392,6 @@ function uncertainOutcomeSignalFromError(error) {
|
|
|
2577
2392
|
retrySafe: false,
|
|
2578
2393
|
};
|
|
2579
2394
|
}
|
|
2580
|
-
function normalizeManagedMutationSettlement(settlement, maxResultBytes) {
|
|
2581
|
-
if (!settlement || typeof settlement !== 'object' || Array.isArray(settlement)) {
|
|
2582
|
-
throw new Error('Managed mutation owner returned an invalid settlement');
|
|
2583
|
-
}
|
|
2584
|
-
const record = settlement;
|
|
2585
|
-
const kind = record.kind;
|
|
2586
|
-
if (kind === 'unsettled') {
|
|
2587
|
-
throw new RuntimeManagedMutationUnsettledError(record.error);
|
|
2588
|
-
}
|
|
2589
|
-
if (kind !== 'workspace_successor_committed' &&
|
|
2590
|
-
kind !== 'no_workspace_change_committed' &&
|
|
2591
|
-
kind !== 'operation_failed_no_effect_committed') {
|
|
2592
|
-
throw new Error('Managed mutation owner returned an unknown settlement kind');
|
|
2593
|
-
}
|
|
2594
|
-
const durableOutcomeValue = Object.hasOwn(record, 'durableOutcome')
|
|
2595
|
-
? record.durableOutcome
|
|
2596
|
-
: undefined;
|
|
2597
|
-
if (!durableOutcomeValue ||
|
|
2598
|
-
typeof durableOutcomeValue !== 'object' ||
|
|
2599
|
-
Array.isArray(durableOutcomeValue)) {
|
|
2600
|
-
throw new Error('Managed mutation settlement has no durable outcome');
|
|
2601
|
-
}
|
|
2602
|
-
const durableOutcome = durableOutcomeValue;
|
|
2603
|
-
if (kind === 'workspace_successor_committed') {
|
|
2604
|
-
return {
|
|
2605
|
-
kind,
|
|
2606
|
-
durableOutcome,
|
|
2607
|
-
};
|
|
2608
|
-
}
|
|
2609
|
-
if (!Object.hasOwn(record, 'providerResult')) {
|
|
2610
|
-
throw new Error('Managed no-effect settlement has no provider result');
|
|
2611
|
-
}
|
|
2612
|
-
const providerResult = snapshotManagedToolResult(record.providerResult, maxResultBytes);
|
|
2613
|
-
const response = durableOutcome.content;
|
|
2614
|
-
const expectedError = kind === 'operation_failed_no_effect_committed';
|
|
2615
|
-
if (response?.kind !== 'function_response' ||
|
|
2616
|
-
response.modelProjection === undefined ||
|
|
2617
|
-
(expectedError ? response.isError !== true : response.isError === true)) {
|
|
2618
|
-
throw new Error('Managed no-effect settlement has the wrong durable outcome state');
|
|
2619
|
-
}
|
|
2620
|
-
const content = Object.freeze(coerceResultContent(providerResult));
|
|
2621
|
-
const outcome = Object.freeze({
|
|
2622
|
-
content,
|
|
2623
|
-
isError: expectedError,
|
|
2624
|
-
modelProjection: response.modelProjection,
|
|
2625
|
-
durationMs: typeof durableOutcome.actions?.stateDelta?.durationMs === 'number'
|
|
2626
|
-
? durableOutcome.actions.stateDelta.durationMs
|
|
2627
|
-
: 0,
|
|
2628
|
-
});
|
|
2629
|
-
return {
|
|
2630
|
-
kind,
|
|
2631
|
-
value: Object.freeze({
|
|
2632
|
-
result: providerResult,
|
|
2633
|
-
outcome,
|
|
2634
|
-
}),
|
|
2635
|
-
durableOutcome,
|
|
2636
|
-
};
|
|
2637
|
-
}
|
|
2638
2395
|
function coerceResultContent(raw) {
|
|
2639
2396
|
if (typeof raw === 'string')
|
|
2640
2397
|
return { kind: 'text', text: raw };
|
|
@@ -2654,175 +2411,6 @@ function coerceResultContent(raw) {
|
|
|
2654
2411
|
}
|
|
2655
2412
|
return { kind: 'text', text: String(raw ?? '') };
|
|
2656
2413
|
}
|
|
2657
|
-
/**
|
|
2658
|
-
* Builds the one durable JSON representation while enforcing its byte budget.
|
|
2659
|
-
* The walk stops at the first over-budget token and never retains a mutable
|
|
2660
|
-
* tool/owner-owned object alias.
|
|
2661
|
-
*/
|
|
2662
|
-
const MANAGED_RESULT_MAX_BYTES = MANAGED_MUTATION_EXECUTION_PROFILE_V1_SPEC.resultSnapshot.maxBytes;
|
|
2663
|
-
const MANAGED_RESULT_MAX_DEPTH = MANAGED_MUTATION_EXECUTION_PROFILE_V1_SPEC.resultSnapshot.maxDepth;
|
|
2664
|
-
const MANAGED_RESULT_MAX_NODES = MANAGED_MUTATION_EXECUTION_PROFILE_V1_SPEC.resultSnapshot.maxNodes;
|
|
2665
|
-
const MANAGED_RESULT_MAX_PROPERTIES = MANAGED_MUTATION_EXECUTION_PROFILE_V1_SPEC.resultSnapshot.maxProperties;
|
|
2666
|
-
const MANAGED_RESULT_MAX_ARRAY_LENGTH = MANAGED_MUTATION_EXECUTION_PROFILE_V1_SPEC.resultSnapshot.maxArrayLength;
|
|
2667
|
-
function snapshotManagedToolResult(value, maxBytes) {
|
|
2668
|
-
const budget = {
|
|
2669
|
-
bytes: 0,
|
|
2670
|
-
limit: maxBytes === undefined
|
|
2671
|
-
? MANAGED_RESULT_MAX_BYTES
|
|
2672
|
-
: Number.isFinite(maxBytes) && maxBytes >= 0
|
|
2673
|
-
? Math.min(Math.floor(maxBytes), MANAGED_RESULT_MAX_BYTES)
|
|
2674
|
-
: 0,
|
|
2675
|
-
nodes: 0,
|
|
2676
|
-
properties: 0,
|
|
2677
|
-
active: new WeakSet(),
|
|
2678
|
-
};
|
|
2679
|
-
return snapshotStrictJsonValue(value, budget, '$', 0);
|
|
2680
|
-
}
|
|
2681
|
-
function snapshotStrictJsonValue(value, budget, path, depth) {
|
|
2682
|
-
budget.nodes += 1;
|
|
2683
|
-
if (budget.nodes > MANAGED_RESULT_MAX_NODES || depth > MANAGED_RESULT_MAX_DEPTH) {
|
|
2684
|
-
throw new ToolResultLimitError();
|
|
2685
|
-
}
|
|
2686
|
-
if (value === null) {
|
|
2687
|
-
consumeManagedResultBytes(budget, 4);
|
|
2688
|
-
return null;
|
|
2689
|
-
}
|
|
2690
|
-
if (typeof value === 'string') {
|
|
2691
|
-
consumeManagedJsonStringBytes(budget, value);
|
|
2692
|
-
return value;
|
|
2693
|
-
}
|
|
2694
|
-
if (typeof value === 'boolean') {
|
|
2695
|
-
consumeManagedResultBytes(budget, value ? 4 : 5);
|
|
2696
|
-
return value;
|
|
2697
|
-
}
|
|
2698
|
-
if (typeof value === 'number') {
|
|
2699
|
-
if (!Number.isFinite(value)) {
|
|
2700
|
-
throw new Error(`Managed tool result must be strict JSON: ${path} is not finite`);
|
|
2701
|
-
}
|
|
2702
|
-
const canonical = Object.is(value, -0) ? 0 : value;
|
|
2703
|
-
consumeManagedResultBytes(budget, JSON.stringify(canonical).length);
|
|
2704
|
-
return canonical;
|
|
2705
|
-
}
|
|
2706
|
-
if (value === undefined) {
|
|
2707
|
-
throw new Error(`Managed tool result must be strict JSON: ${path} is undefined`);
|
|
2708
|
-
}
|
|
2709
|
-
if (typeof value !== 'object') {
|
|
2710
|
-
throw new Error(`Managed tool result must be strict JSON: ${path} has an unsupported type`);
|
|
2711
|
-
}
|
|
2712
|
-
if (budget.active.has(value)) {
|
|
2713
|
-
throw new Error(`Managed tool result must be strict JSON: ${path} is cyclic`);
|
|
2714
|
-
}
|
|
2715
|
-
if (!Array.isArray(value)) {
|
|
2716
|
-
const prototype = Object.getPrototypeOf(value);
|
|
2717
|
-
if (prototype !== Object.prototype && prototype !== null) {
|
|
2718
|
-
throw new Error(`Managed tool result must be strict JSON: ${path} is not a plain object`);
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
if ('toJSON' in value) {
|
|
2722
|
-
throw new Error(`Managed tool result must be strict JSON: ${path} defines toJSON`);
|
|
2723
|
-
}
|
|
2724
|
-
budget.active.add(value);
|
|
2725
|
-
try {
|
|
2726
|
-
if (Array.isArray(value)) {
|
|
2727
|
-
if (value.length > MANAGED_RESULT_MAX_ARRAY_LENGTH)
|
|
2728
|
-
throw new ToolResultLimitError();
|
|
2729
|
-
consumeManagedResultBytes(budget, 1);
|
|
2730
|
-
const output = [];
|
|
2731
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
2732
|
-
if (index > 0)
|
|
2733
|
-
consumeManagedResultBytes(budget, 1);
|
|
2734
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
2735
|
-
if (!descriptor) {
|
|
2736
|
-
throw new Error(`Managed tool result must be strict JSON: ${path} is a sparse array`);
|
|
2737
|
-
}
|
|
2738
|
-
if (!('value' in descriptor)) {
|
|
2739
|
-
throw new Error(`Managed tool result must be strict JSON: ${path}[${index}] is an accessor`);
|
|
2740
|
-
}
|
|
2741
|
-
output.push(snapshotStrictJsonValue(descriptor.value, budget, `${path}[${index}]`, depth + 1));
|
|
2742
|
-
}
|
|
2743
|
-
consumeManagedResultBytes(budget, 1);
|
|
2744
|
-
return Object.freeze(output);
|
|
2745
|
-
}
|
|
2746
|
-
consumeManagedResultBytes(budget, 1);
|
|
2747
|
-
const output = {};
|
|
2748
|
-
let emitted = 0;
|
|
2749
|
-
for (const key in value) {
|
|
2750
|
-
if (!Object.hasOwn(value, key))
|
|
2751
|
-
continue;
|
|
2752
|
-
budget.properties += 1;
|
|
2753
|
-
if (budget.properties > MANAGED_RESULT_MAX_PROPERTIES)
|
|
2754
|
-
throw new ToolResultLimitError();
|
|
2755
|
-
if (emitted > 0)
|
|
2756
|
-
consumeManagedResultBytes(budget, 1);
|
|
2757
|
-
consumeManagedJsonStringBytes(budget, key);
|
|
2758
|
-
consumeManagedResultBytes(budget, 1);
|
|
2759
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
2760
|
-
if (!descriptor || !('value' in descriptor)) {
|
|
2761
|
-
throw new Error(`Managed tool result must be strict JSON: ${path}.${key} is an accessor`);
|
|
2762
|
-
}
|
|
2763
|
-
Object.defineProperty(output, key, {
|
|
2764
|
-
configurable: true,
|
|
2765
|
-
enumerable: true,
|
|
2766
|
-
value: snapshotStrictJsonValue(descriptor.value, budget, `${path}.${key}`, depth + 1),
|
|
2767
|
-
writable: true,
|
|
2768
|
-
});
|
|
2769
|
-
emitted += 1;
|
|
2770
|
-
}
|
|
2771
|
-
consumeManagedResultBytes(budget, 1);
|
|
2772
|
-
return Object.freeze(output);
|
|
2773
|
-
}
|
|
2774
|
-
finally {
|
|
2775
|
-
budget.active.delete(value);
|
|
2776
|
-
}
|
|
2777
|
-
}
|
|
2778
|
-
function consumeManagedJsonStringBytes(budget, value) {
|
|
2779
|
-
consumeManagedResultBytes(budget, 1);
|
|
2780
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
2781
|
-
const code = value.charCodeAt(index);
|
|
2782
|
-
let bytes;
|
|
2783
|
-
if (code === 0x22 ||
|
|
2784
|
-
code === 0x5c ||
|
|
2785
|
-
code === 0x08 ||
|
|
2786
|
-
code === 0x09 ||
|
|
2787
|
-
code === 0x0a ||
|
|
2788
|
-
code === 0x0c ||
|
|
2789
|
-
code === 0x0d) {
|
|
2790
|
-
bytes = 2;
|
|
2791
|
-
}
|
|
2792
|
-
else if (code <= 0x1f) {
|
|
2793
|
-
bytes = 6;
|
|
2794
|
-
}
|
|
2795
|
-
else if (code >= 0xd800 && code <= 0xdbff) {
|
|
2796
|
-
const next = value.charCodeAt(index + 1);
|
|
2797
|
-
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
2798
|
-
bytes = 4;
|
|
2799
|
-
index += 1;
|
|
2800
|
-
}
|
|
2801
|
-
else {
|
|
2802
|
-
bytes = 6;
|
|
2803
|
-
}
|
|
2804
|
-
}
|
|
2805
|
-
else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
2806
|
-
bytes = 6;
|
|
2807
|
-
}
|
|
2808
|
-
else if (code <= 0x7f) {
|
|
2809
|
-
bytes = 1;
|
|
2810
|
-
}
|
|
2811
|
-
else if (code <= 0x7ff) {
|
|
2812
|
-
bytes = 2;
|
|
2813
|
-
}
|
|
2814
|
-
else {
|
|
2815
|
-
bytes = 3;
|
|
2816
|
-
}
|
|
2817
|
-
consumeManagedResultBytes(budget, bytes);
|
|
2818
|
-
}
|
|
2819
|
-
consumeManagedResultBytes(budget, 1);
|
|
2820
|
-
}
|
|
2821
|
-
function consumeManagedResultBytes(budget, bytes) {
|
|
2822
|
-
if (budget.bytes > budget.limit - bytes)
|
|
2823
|
-
throw new ToolResultLimitError();
|
|
2824
|
-
budget.bytes += bytes;
|
|
2825
|
-
}
|
|
2826
2414
|
function coerceTerminalFailure(tool, cwd, args, err) {
|
|
2827
2415
|
if (tool.name !== 'Bash' || !err || typeof err !== 'object')
|
|
2828
2416
|
return null;
|
|
@@ -2995,15 +2583,6 @@ function isAmbiguousComputerFailure(raw) {
|
|
|
2995
2583
|
function durableAttemptKey(turnId, toolUseId) {
|
|
2996
2584
|
return JSON.stringify([turnId, toolUseId]);
|
|
2997
2585
|
}
|
|
2998
|
-
async function disposeManagedMutationAdmission(admission) {
|
|
2999
|
-
try {
|
|
3000
|
-
await admission?.dispose();
|
|
3001
|
-
}
|
|
3002
|
-
catch {
|
|
3003
|
-
// Cleanup is best-effort. It must never rewrite a durable terminal outcome,
|
|
3004
|
-
// nor obscure the primary pre-T1 or execution failure.
|
|
3005
|
-
}
|
|
3006
|
-
}
|
|
3007
2586
|
function providerToolErrorMessage(output) {
|
|
3008
2587
|
if (!output || typeof output !== 'object' || Array.isArray(output))
|
|
3009
2588
|
return undefined;
|