@slock-ai/daemon 0.55.1 → 0.55.2
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/chat-bridge.js +1 -1
- package/dist/{chunk-QQRU3GA6.js → chunk-IDDG4Q4Q.js} +805 -237
- package/dist/{chunk-VOZJ2ELH.js → chunk-M2KQBJR3.js} +37 -4
- package/dist/cli/index.js +172 -37
- package/dist/core.js +2 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
executeJsonRequest,
|
|
6
6
|
executeResponseRequest,
|
|
7
7
|
logger
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-M2KQBJR3.js";
|
|
9
9
|
|
|
10
10
|
// src/core.ts
|
|
11
11
|
import path16 from "path";
|
|
@@ -38,6 +38,244 @@ var CHANNEL_MESSAGE_RE = new RegExp(
|
|
|
38
38
|
"iu"
|
|
39
39
|
);
|
|
40
40
|
|
|
41
|
+
// ../shared/src/producerFactLineage.ts
|
|
42
|
+
var PRODUCER_FACT_TEXT_LABEL = "producerFactId";
|
|
43
|
+
function formatProducerFactLineageBracket(producerFactId) {
|
|
44
|
+
const id = normalizeProducerFactId(producerFactId);
|
|
45
|
+
return id ? ` [${PRODUCER_FACT_TEXT_LABEL}=${id}]` : "";
|
|
46
|
+
}
|
|
47
|
+
function normalizeProducerFactId(producerFactId) {
|
|
48
|
+
return typeof producerFactId === "string" ? producerFactId.trim() : "";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ../shared/src/apmHeldFreshness.ts
|
|
52
|
+
function buildApmFreshnessDecisionProducerFactId(agentId, input) {
|
|
53
|
+
const stableInput = {
|
|
54
|
+
agentId,
|
|
55
|
+
action: input.action,
|
|
56
|
+
decision: input.decision,
|
|
57
|
+
target: input.target ?? null,
|
|
58
|
+
reason: input.reason,
|
|
59
|
+
pendingMaxSeq: input.pendingMaxSeq ?? null,
|
|
60
|
+
modelSeenSeq: input.modelSeenSeq ?? null,
|
|
61
|
+
heldMessageCount: input.heldMessageCount ?? null,
|
|
62
|
+
omittedMessageCount: input.omittedMessageCount ?? null
|
|
63
|
+
};
|
|
64
|
+
return `freshness_decision_fact:${hashApmHeldFreshnessStable(stableInput)}`;
|
|
65
|
+
}
|
|
66
|
+
function projectApmHeldFreshnessEnvelope(input) {
|
|
67
|
+
const body = {
|
|
68
|
+
state: "held",
|
|
69
|
+
outcome: "held",
|
|
70
|
+
subtype: "freshness",
|
|
71
|
+
reason: "newer_messages_available",
|
|
72
|
+
producerFactId: input.producerFactId,
|
|
73
|
+
available_actions: apmHeldFreshnessAvailableActions(input.action),
|
|
74
|
+
heldMessages: input.heldMessages,
|
|
75
|
+
newMessageCount: input.newMessageCount,
|
|
76
|
+
shownMessageCount: input.heldMessages.length,
|
|
77
|
+
omittedMessageCount: input.omittedMessageCount,
|
|
78
|
+
seenUpToSeq: input.seenUpToSeq
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
clauseId: "SMR-006",
|
|
82
|
+
projector: "held-envelope",
|
|
83
|
+
surface: "agent-api-held-response",
|
|
84
|
+
producerFactId: input.producerFactId,
|
|
85
|
+
body
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function projectApmHeldFreshnessActivity(input) {
|
|
89
|
+
const title = input.action === "send" ? "Send held by freshness check" : input.action === "task_claim" ? "Task claim held by freshness check" : "Task update held by freshness check";
|
|
90
|
+
const text = [
|
|
91
|
+
input.target ? `target: ${input.target}` : null,
|
|
92
|
+
`new messages: ${input.messageCount} newer message${input.messageCount === 1 ? "" : "s"}`,
|
|
93
|
+
`decision: ${input.decision === "syncing_hold" ? "syncing hold" : "local hold"}; review the newer context before retrying`
|
|
94
|
+
].filter((line) => Boolean(line)).join("\n");
|
|
95
|
+
return {
|
|
96
|
+
clauseId: "SMR-006",
|
|
97
|
+
projector: "held-envelope",
|
|
98
|
+
surface: "agent:activity",
|
|
99
|
+
producerFactId: input.producerFactId,
|
|
100
|
+
entry: {
|
|
101
|
+
kind: "slock_action",
|
|
102
|
+
producerFactId: input.producerFactId,
|
|
103
|
+
title,
|
|
104
|
+
text
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function projectApmFreshnessDecisionTrace(input) {
|
|
109
|
+
return {
|
|
110
|
+
clauseId: "SMR-006",
|
|
111
|
+
projector: "held-envelope",
|
|
112
|
+
surface: "daemon-trace",
|
|
113
|
+
producerFactId: input.producerFactId,
|
|
114
|
+
attrs: {
|
|
115
|
+
producer_fact_id: input.producerFactId,
|
|
116
|
+
action: input.decision.action,
|
|
117
|
+
decision: input.decision.decision,
|
|
118
|
+
target: input.decision.target,
|
|
119
|
+
inbox_trust_state: input.decision.inboxTrustState,
|
|
120
|
+
reason: input.decision.reason,
|
|
121
|
+
pending_count: input.decision.pendingCount,
|
|
122
|
+
pending_max_seq: input.decision.pendingMaxSeq,
|
|
123
|
+
model_seen_seq: input.decision.modelSeenSeq,
|
|
124
|
+
held_message_count: input.decision.heldMessageCount,
|
|
125
|
+
omitted_message_count: input.decision.omittedMessageCount
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function apmHeldFreshnessAvailableActions(action) {
|
|
130
|
+
return action === "send" ? ["check_messages", "send_draft", "send_anyway"] : ["check_messages", "retry_action"];
|
|
131
|
+
}
|
|
132
|
+
function hashApmHeldFreshnessStable(value) {
|
|
133
|
+
return sha256HexUtf8(stableStringifyApmHeldFreshness(value));
|
|
134
|
+
}
|
|
135
|
+
function stableStringifyApmHeldFreshness(value) {
|
|
136
|
+
return JSON.stringify(stableNormalizeApmHeldFreshness(value));
|
|
137
|
+
}
|
|
138
|
+
function stableNormalizeApmHeldFreshness(value) {
|
|
139
|
+
if (Array.isArray(value)) return value.map((item) => stableNormalizeApmHeldFreshness(item));
|
|
140
|
+
if (!value || typeof value !== "object") return value;
|
|
141
|
+
const record = value;
|
|
142
|
+
const normalized = {};
|
|
143
|
+
for (const key of Object.keys(record).sort()) {
|
|
144
|
+
const child = record[key];
|
|
145
|
+
if (child === void 0) continue;
|
|
146
|
+
normalized[key] = stableNormalizeApmHeldFreshness(child);
|
|
147
|
+
}
|
|
148
|
+
return normalized;
|
|
149
|
+
}
|
|
150
|
+
var SHA256_INITIAL_STATE = [
|
|
151
|
+
1779033703,
|
|
152
|
+
3144134277,
|
|
153
|
+
1013904242,
|
|
154
|
+
2773480762,
|
|
155
|
+
1359893119,
|
|
156
|
+
2600822924,
|
|
157
|
+
528734635,
|
|
158
|
+
1541459225
|
|
159
|
+
];
|
|
160
|
+
var SHA256_K = [
|
|
161
|
+
1116352408,
|
|
162
|
+
1899447441,
|
|
163
|
+
3049323471,
|
|
164
|
+
3921009573,
|
|
165
|
+
961987163,
|
|
166
|
+
1508970993,
|
|
167
|
+
2453635748,
|
|
168
|
+
2870763221,
|
|
169
|
+
3624381080,
|
|
170
|
+
310598401,
|
|
171
|
+
607225278,
|
|
172
|
+
1426881987,
|
|
173
|
+
1925078388,
|
|
174
|
+
2162078206,
|
|
175
|
+
2614888103,
|
|
176
|
+
3248222580,
|
|
177
|
+
3835390401,
|
|
178
|
+
4022224774,
|
|
179
|
+
264347078,
|
|
180
|
+
604807628,
|
|
181
|
+
770255983,
|
|
182
|
+
1249150122,
|
|
183
|
+
1555081692,
|
|
184
|
+
1996064986,
|
|
185
|
+
2554220882,
|
|
186
|
+
2821834349,
|
|
187
|
+
2952996808,
|
|
188
|
+
3210313671,
|
|
189
|
+
3336571891,
|
|
190
|
+
3584528711,
|
|
191
|
+
113926993,
|
|
192
|
+
338241895,
|
|
193
|
+
666307205,
|
|
194
|
+
773529912,
|
|
195
|
+
1294757372,
|
|
196
|
+
1396182291,
|
|
197
|
+
1695183700,
|
|
198
|
+
1986661051,
|
|
199
|
+
2177026350,
|
|
200
|
+
2456956037,
|
|
201
|
+
2730485921,
|
|
202
|
+
2820302411,
|
|
203
|
+
3259730800,
|
|
204
|
+
3345764771,
|
|
205
|
+
3516065817,
|
|
206
|
+
3600352804,
|
|
207
|
+
4094571909,
|
|
208
|
+
275423344,
|
|
209
|
+
430227734,
|
|
210
|
+
506948616,
|
|
211
|
+
659060556,
|
|
212
|
+
883997877,
|
|
213
|
+
958139571,
|
|
214
|
+
1322822218,
|
|
215
|
+
1537002063,
|
|
216
|
+
1747873779,
|
|
217
|
+
1955562222,
|
|
218
|
+
2024104815,
|
|
219
|
+
2227730452,
|
|
220
|
+
2361852424,
|
|
221
|
+
2428436474,
|
|
222
|
+
2756734187,
|
|
223
|
+
3204031479,
|
|
224
|
+
3329325298
|
|
225
|
+
];
|
|
226
|
+
function sha256HexUtf8(value) {
|
|
227
|
+
const bytes = new TextEncoder().encode(value);
|
|
228
|
+
const paddedLength = Math.ceil((bytes.length + 9) / 64) * 64;
|
|
229
|
+
const padded = new Uint8Array(paddedLength);
|
|
230
|
+
padded.set(bytes);
|
|
231
|
+
padded[bytes.length] = 128;
|
|
232
|
+
const bitLength = bytes.length * 8;
|
|
233
|
+
const view = new DataView(padded.buffer);
|
|
234
|
+
view.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296));
|
|
235
|
+
view.setUint32(paddedLength - 4, bitLength >>> 0);
|
|
236
|
+
const h = [...SHA256_INITIAL_STATE];
|
|
237
|
+
const words = new Array(64);
|
|
238
|
+
for (let offset = 0; offset < paddedLength; offset += 64) {
|
|
239
|
+
for (let i = 0; i < 16; i += 1) {
|
|
240
|
+
words[i] = view.getUint32(offset + i * 4);
|
|
241
|
+
}
|
|
242
|
+
for (let i = 16; i < 64; i += 1) {
|
|
243
|
+
const s0 = rotateRight(words[i - 15], 7) ^ rotateRight(words[i - 15], 18) ^ words[i - 15] >>> 3;
|
|
244
|
+
const s1 = rotateRight(words[i - 2], 17) ^ rotateRight(words[i - 2], 19) ^ words[i - 2] >>> 10;
|
|
245
|
+
words[i] = words[i - 16] + s0 + words[i - 7] + s1 >>> 0;
|
|
246
|
+
}
|
|
247
|
+
let [a, b, c, d, e, f, g, hh] = h;
|
|
248
|
+
for (let i = 0; i < 64; i += 1) {
|
|
249
|
+
const s1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
|
|
250
|
+
const ch = e & f ^ ~e & g;
|
|
251
|
+
const temp1 = hh + s1 + ch + SHA256_K[i] + words[i] >>> 0;
|
|
252
|
+
const s0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
|
|
253
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
254
|
+
const temp2 = s0 + maj >>> 0;
|
|
255
|
+
hh = g;
|
|
256
|
+
g = f;
|
|
257
|
+
f = e;
|
|
258
|
+
e = d + temp1 >>> 0;
|
|
259
|
+
d = c;
|
|
260
|
+
c = b;
|
|
261
|
+
b = a;
|
|
262
|
+
a = temp1 + temp2 >>> 0;
|
|
263
|
+
}
|
|
264
|
+
h[0] = h[0] + a >>> 0;
|
|
265
|
+
h[1] = h[1] + b >>> 0;
|
|
266
|
+
h[2] = h[2] + c >>> 0;
|
|
267
|
+
h[3] = h[3] + d >>> 0;
|
|
268
|
+
h[4] = h[4] + e >>> 0;
|
|
269
|
+
h[5] = h[5] + f >>> 0;
|
|
270
|
+
h[6] = h[6] + g >>> 0;
|
|
271
|
+
h[7] = h[7] + hh >>> 0;
|
|
272
|
+
}
|
|
273
|
+
return h.map((part) => part.toString(16).padStart(8, "0")).join("");
|
|
274
|
+
}
|
|
275
|
+
function rotateRight(value, bits) {
|
|
276
|
+
return value >>> bits | value << 32 - bits;
|
|
277
|
+
}
|
|
278
|
+
|
|
41
279
|
// ../shared/src/tracing/index.ts
|
|
42
280
|
var DEFAULT_TRACE_FLAGS = "00";
|
|
43
281
|
var TRACEPARENT_VERSION = "00";
|
|
@@ -954,7 +1192,7 @@ var DISPLAY_PLAN_CONFIG = {
|
|
|
954
1192
|
// src/agentProcessManager.ts
|
|
955
1193
|
import { mkdirSync as mkdirSync4, readdirSync, statSync, writeFileSync as writeFileSync7 } from "fs";
|
|
956
1194
|
import { mkdir, writeFile, access, readdir as readdir2, stat as stat2, readFile, rm as rm2 } from "fs/promises";
|
|
957
|
-
import { createHash as
|
|
1195
|
+
import { createHash as createHash3 } from "crypto";
|
|
958
1196
|
import path12 from "path";
|
|
959
1197
|
import os5 from "os";
|
|
960
1198
|
|
|
@@ -1059,8 +1297,8 @@ Use the \`slock\` CLI for chat / task / attachment operations. The daemon inject
|
|
|
1059
1297
|
17. **\`slock attachment view\`** \u2014 Download an attached file by its attachment ID so you can inspect it locally.
|
|
1060
1298
|
18. **\`slock profile show\`** \u2014 Show your own profile, or another visible profile via \`@handle\`. Mirrors the canonical Slock profile view.
|
|
1061
1299
|
19. **\`slock profile update\`** \u2014 Update your own profile. Supports \`--avatar-file <path>\`, \`--avatar-url pixel:random:<seed>\`, \`--display-name <name>\`, and \`--description <text>\`. Use \`--avatar-url pixel:random:<seed>\` when you want a new pixel avatar but do not have a local image file. Values must be non-empty. Provide at least one flag per call; multiple flags can be combined.
|
|
1062
|
-
20. **\`slock integration list\`** \u2014 List registered third-party services and this agent's active Slock Agent Logins.
|
|
1063
|
-
21. **\`slock integration login\`** \u2014 Provision or reuse this agent's login for a registered third-party service.
|
|
1300
|
+
20. **\`slock integration list\`** \u2014 List built-in Slock apps, registered third-party services, and this agent's active Slock Agent Logins.
|
|
1301
|
+
21. **\`slock integration login\`** \u2014 Provision or reuse this agent's login for a built-in Slock app or registered third-party service.
|
|
1064
1302
|
22. **\`slock integration env\`** \u2014 Print per-agent local CLI environment for a manifest-backed service that requires isolated HOME/XDG state.
|
|
1065
1303
|
23. **\`slock reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
|
|
1066
1304
|
24. **\`slock reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
|
|
@@ -1174,9 +1412,9 @@ Each channel has a **name** and optionally a **description** that define its pur
|
|
|
1174
1412
|
- If unsure where something belongs, call ${serverInfoCmd} to review channel descriptions.`;
|
|
1175
1413
|
const thirdPartyIntegrationsSection = isCli ? `### Third-party integrations
|
|
1176
1414
|
|
|
1177
|
-
If a registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app, first run \`slock integration list\` and match the app to a
|
|
1415
|
+
If a built-in Slock app or registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app or built-in Slock app, first run \`slock integration list\` and match the app to a listed service before browsing the app. Use \`slock integration login --service <service>\` to provision or reuse your agent login for that service. If the service exposes an agent behavior manifest and you need to run its local CLI, run \`slock integration env --service <service>\` before invoking that CLI; if it prints exports, apply them first so service credentials stay under a per-agent profile HOME/XDG tree instead of the host user's global HOME. If it reports that no local env is required, do not invent HOME/XDG overrides. If it fails, do not run that local CLI with the host user's HOME; report that the service manifest is unsupported. Slock does not execute commands from remote manifests automatically. If the CLI reports that the \`integration\` command is unknown, the local daemon/CLI is too old for Slock Agent Login; report that the machine must be upgraded/restarted instead of calling internal HTTP endpoints yourself. When the command returns \`Agent login ready\` or \`Already logged in\`, the agent-side login is ready. If the output includes an app URL, open that URL as the service-provided app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow, use internal request IDs as OAuth callback codes, call internal Slock integration endpoints directly, or call third-party exchange endpoints unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use \`slock profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the listed service / Slock Agent Login path.` : `### Third-party integrations
|
|
1178
1416
|
|
|
1179
|
-
If a registered third-party service requires login, use Slock Agent Login through the available registered-service interface instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app, first inspect the registered-service interface and match the app to a
|
|
1417
|
+
If a built-in Slock app or registered third-party service requires login, use Slock Agent Login through the available registered-service interface instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app or built-in Slock app, first inspect the registered-service interface and match the app to a listed service before browsing the app. Once the registered-service interface reports the agent login is ready, the agent-side login is ready. If that interface provides an app URL, use it as the service-provided app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow or treat internal request IDs as OAuth callback codes unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use your Slock profile view. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the listed service / Slock Agent Login path.`;
|
|
1180
1418
|
const readingHistorySection = isCli ? `### Reading history
|
|
1181
1419
|
|
|
1182
1420
|
\`slock message read --channel "#channel-name"\` or \`slock message read --channel dm:@peer-name\` or \`slock message read --channel "#channel:shortid"\`
|
|
@@ -1544,6 +1782,258 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
1544
1782
|
import { randomBytes } from "crypto";
|
|
1545
1783
|
import http from "http";
|
|
1546
1784
|
import { URL as URL2 } from "url";
|
|
1785
|
+
|
|
1786
|
+
// src/apmStateMachine.ts
|
|
1787
|
+
import { createHash } from "crypto";
|
|
1788
|
+
var MAX_APM_GATED_STEERING_EVENTS = 12;
|
|
1789
|
+
function createInitialApmGatedSteeringState() {
|
|
1790
|
+
return {
|
|
1791
|
+
isIdle: false,
|
|
1792
|
+
expectedTerminationReason: null,
|
|
1793
|
+
phase: "idle",
|
|
1794
|
+
outstandingToolUses: 0,
|
|
1795
|
+
compacting: false,
|
|
1796
|
+
toolBoundaryFlushDisabled: false,
|
|
1797
|
+
lastFlushReason: null,
|
|
1798
|
+
recentEvents: []
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1801
|
+
function reduceApmIdleState(state, input) {
|
|
1802
|
+
return {
|
|
1803
|
+
nextState: {
|
|
1804
|
+
...state,
|
|
1805
|
+
isIdle: input.isIdle
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
function reduceApmGatedToolUse(state, input) {
|
|
1810
|
+
if (input.kind === "tool_call") {
|
|
1811
|
+
return {
|
|
1812
|
+
nextState: {
|
|
1813
|
+
isIdle: false,
|
|
1814
|
+
expectedTerminationReason: state.expectedTerminationReason,
|
|
1815
|
+
phase: "tool_wait",
|
|
1816
|
+
outstandingToolUses: state.outstandingToolUses + 1,
|
|
1817
|
+
compacting: state.compacting,
|
|
1818
|
+
toolBoundaryFlushDisabled: state.toolBoundaryFlushDisabled,
|
|
1819
|
+
lastFlushReason: state.lastFlushReason,
|
|
1820
|
+
recentEvents: state.recentEvents
|
|
1821
|
+
},
|
|
1822
|
+
hadOutstandingToolUse: state.outstandingToolUses > 0,
|
|
1823
|
+
shouldFlushToolBatch: false
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
const hadOutstandingToolUse = state.outstandingToolUses > 0;
|
|
1827
|
+
const outstandingToolUses = Math.max(0, state.outstandingToolUses - 1);
|
|
1828
|
+
return {
|
|
1829
|
+
nextState: {
|
|
1830
|
+
isIdle: false,
|
|
1831
|
+
expectedTerminationReason: state.expectedTerminationReason,
|
|
1832
|
+
phase: "tool_boundary",
|
|
1833
|
+
outstandingToolUses,
|
|
1834
|
+
compacting: state.compacting,
|
|
1835
|
+
toolBoundaryFlushDisabled: state.toolBoundaryFlushDisabled,
|
|
1836
|
+
lastFlushReason: state.lastFlushReason,
|
|
1837
|
+
recentEvents: state.recentEvents
|
|
1838
|
+
},
|
|
1839
|
+
hadOutstandingToolUse,
|
|
1840
|
+
shouldFlushToolBatch: hadOutstandingToolUse && outstandingToolUses === 0
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
function reduceApmGatedCompaction(state, input) {
|
|
1844
|
+
if (input.kind === "compaction_started") {
|
|
1845
|
+
return {
|
|
1846
|
+
nextState: {
|
|
1847
|
+
isIdle: false,
|
|
1848
|
+
expectedTerminationReason: state.expectedTerminationReason,
|
|
1849
|
+
phase: "compacting",
|
|
1850
|
+
outstandingToolUses: state.outstandingToolUses,
|
|
1851
|
+
compacting: true,
|
|
1852
|
+
toolBoundaryFlushDisabled: state.toolBoundaryFlushDisabled,
|
|
1853
|
+
lastFlushReason: state.lastFlushReason,
|
|
1854
|
+
recentEvents: state.recentEvents
|
|
1855
|
+
}
|
|
1856
|
+
};
|
|
1857
|
+
}
|
|
1858
|
+
if (input.kind === "compaction_interrupted") {
|
|
1859
|
+
return {
|
|
1860
|
+
nextState: {
|
|
1861
|
+
isIdle: false,
|
|
1862
|
+
expectedTerminationReason: state.expectedTerminationReason,
|
|
1863
|
+
phase: state.phase,
|
|
1864
|
+
outstandingToolUses: state.outstandingToolUses,
|
|
1865
|
+
compacting: false,
|
|
1866
|
+
toolBoundaryFlushDisabled: state.toolBoundaryFlushDisabled,
|
|
1867
|
+
lastFlushReason: state.lastFlushReason,
|
|
1868
|
+
recentEvents: state.recentEvents
|
|
1869
|
+
}
|
|
1870
|
+
};
|
|
1871
|
+
}
|
|
1872
|
+
return {
|
|
1873
|
+
nextState: {
|
|
1874
|
+
isIdle: false,
|
|
1875
|
+
expectedTerminationReason: state.expectedTerminationReason,
|
|
1876
|
+
phase: "assistant_continuation",
|
|
1877
|
+
outstandingToolUses: state.outstandingToolUses,
|
|
1878
|
+
compacting: false,
|
|
1879
|
+
toolBoundaryFlushDisabled: state.toolBoundaryFlushDisabled,
|
|
1880
|
+
lastFlushReason: state.lastFlushReason,
|
|
1881
|
+
recentEvents: state.recentEvents
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
function reduceApmGatedCompactionBoundaryFlush(_state, input) {
|
|
1886
|
+
if (!input.hasSession || !input.supportsStdinNotification || input.inboxLength === 0) {
|
|
1887
|
+
return { effects: [] };
|
|
1888
|
+
}
|
|
1889
|
+
if (input.pendingNotificationCount === 0) return { effects: [] };
|
|
1890
|
+
return {
|
|
1891
|
+
effects: [{
|
|
1892
|
+
kind: "notify_stdin",
|
|
1893
|
+
reason: "compaction_finished",
|
|
1894
|
+
stdinMode: "busy",
|
|
1895
|
+
clauseId: "SMR-002"
|
|
1896
|
+
}]
|
|
1897
|
+
};
|
|
1898
|
+
}
|
|
1899
|
+
function reduceApmGatedTurnEnd(_state, input = {}) {
|
|
1900
|
+
const shouldDeliverQueuedMessages = Boolean(
|
|
1901
|
+
input.inboxLength && input.inboxLength > 0 && input.supportsStdinNotification && input.hasSession
|
|
1902
|
+
);
|
|
1903
|
+
return {
|
|
1904
|
+
nextState: {
|
|
1905
|
+
isIdle: !shouldDeliverQueuedMessages,
|
|
1906
|
+
expectedTerminationReason: input.terminateProcessOnTurnEnd === true ? "turn_end" : _state.expectedTerminationReason,
|
|
1907
|
+
phase: "idle",
|
|
1908
|
+
outstandingToolUses: 0,
|
|
1909
|
+
compacting: false,
|
|
1910
|
+
toolBoundaryFlushDisabled: _state.toolBoundaryFlushDisabled,
|
|
1911
|
+
lastFlushReason: _state.lastFlushReason,
|
|
1912
|
+
recentEvents: _state.recentEvents
|
|
1913
|
+
},
|
|
1914
|
+
effects: shouldDeliverQueuedMessages ? [{
|
|
1915
|
+
kind: "deliver_stdin",
|
|
1916
|
+
reason: "turn_end",
|
|
1917
|
+
stdinMode: "idle",
|
|
1918
|
+
clauseId: "SMR-002"
|
|
1919
|
+
}] : []
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1922
|
+
function reduceApmGatedError(state, input = {}) {
|
|
1923
|
+
const shouldDisableToolBoundaryFlush = input.disableToolBoundaryFlush === true;
|
|
1924
|
+
return {
|
|
1925
|
+
nextState: {
|
|
1926
|
+
isIdle: input.terminalWakeable === true,
|
|
1927
|
+
expectedTerminationReason: state.expectedTerminationReason,
|
|
1928
|
+
phase: "error",
|
|
1929
|
+
outstandingToolUses: state.outstandingToolUses,
|
|
1930
|
+
compacting: false,
|
|
1931
|
+
toolBoundaryFlushDisabled: state.toolBoundaryFlushDisabled || shouldDisableToolBoundaryFlush,
|
|
1932
|
+
lastFlushReason: state.lastFlushReason,
|
|
1933
|
+
recentEvents: state.recentEvents
|
|
1934
|
+
},
|
|
1935
|
+
shouldDisableToolBoundaryFlush
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
function reduceApmGatedAssistantContinuation(state) {
|
|
1939
|
+
return {
|
|
1940
|
+
nextState: {
|
|
1941
|
+
isIdle: false,
|
|
1942
|
+
expectedTerminationReason: state.expectedTerminationReason,
|
|
1943
|
+
phase: "assistant_continuation",
|
|
1944
|
+
outstandingToolUses: state.outstandingToolUses,
|
|
1945
|
+
compacting: state.compacting,
|
|
1946
|
+
toolBoundaryFlushDisabled: state.toolBoundaryFlushDisabled,
|
|
1947
|
+
lastFlushReason: state.lastFlushReason,
|
|
1948
|
+
recentEvents: state.recentEvents
|
|
1949
|
+
}
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
function reduceApmStalledRecoveryTermination(state, input) {
|
|
1953
|
+
if (input.inboxLength === 0) {
|
|
1954
|
+
return { nextState: state, shouldTerminate: false, alreadyRecovering: false, blockedReason: "empty_inbox" };
|
|
1955
|
+
}
|
|
1956
|
+
if (state.expectedTerminationReason === "stalled_recovery") {
|
|
1957
|
+
return { nextState: state, shouldTerminate: false, alreadyRecovering: true, blockedReason: null };
|
|
1958
|
+
}
|
|
1959
|
+
const directStdinRuntime = input.supportsStdinNotification && input.busyDeliveryMode === "direct";
|
|
1960
|
+
const canRestartDirectStdinProcess = directStdinRuntime && input.hasSession && (state.outstandingToolUses === 0 || input.hasDirectStdinRecoveryEvidence);
|
|
1961
|
+
const canRestartStalledProcess = !input.supportsStdinNotification || canRestartDirectStdinProcess;
|
|
1962
|
+
if (!canRestartStalledProcess) {
|
|
1963
|
+
return { nextState: state, shouldTerminate: false, alreadyRecovering: false, blockedReason: "runtime_not_restartable" };
|
|
1964
|
+
}
|
|
1965
|
+
if (input.staleForMs < input.staleThresholdMs && !input.runtimeProgressIsStale) {
|
|
1966
|
+
return { nextState: state, shouldTerminate: false, alreadyRecovering: false, blockedReason: "runtime_progress_recent" };
|
|
1967
|
+
}
|
|
1968
|
+
return {
|
|
1969
|
+
nextState: {
|
|
1970
|
+
...state,
|
|
1971
|
+
expectedTerminationReason: "stalled_recovery"
|
|
1972
|
+
},
|
|
1973
|
+
shouldTerminate: true,
|
|
1974
|
+
alreadyRecovering: false,
|
|
1975
|
+
blockedReason: null
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1978
|
+
function reduceApmStartupTimeoutTermination(state, input) {
|
|
1979
|
+
if (input.hasRuntimeProgressEvent) {
|
|
1980
|
+
return {
|
|
1981
|
+
nextState: state,
|
|
1982
|
+
shouldTerminate: false,
|
|
1983
|
+
blockedReason: "runtime_progress_started"
|
|
1984
|
+
};
|
|
1985
|
+
}
|
|
1986
|
+
return {
|
|
1987
|
+
nextState: {
|
|
1988
|
+
...state,
|
|
1989
|
+
isIdle: false,
|
|
1990
|
+
expectedTerminationReason: "startup_timeout"
|
|
1991
|
+
},
|
|
1992
|
+
shouldTerminate: true,
|
|
1993
|
+
blockedReason: null
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
function reduceApmGatedFlush(state, input) {
|
|
1997
|
+
return {
|
|
1998
|
+
nextState: {
|
|
1999
|
+
...state,
|
|
2000
|
+
lastFlushReason: input.reason
|
|
2001
|
+
}
|
|
2002
|
+
};
|
|
2003
|
+
}
|
|
2004
|
+
function reduceApmGatedRecentEvent(state, input) {
|
|
2005
|
+
const summary = `${input.event}:${state.phase}:tools=${state.outstandingToolUses}:compact=${state.compacting}`;
|
|
2006
|
+
return {
|
|
2007
|
+
nextState: {
|
|
2008
|
+
...state,
|
|
2009
|
+
recentEvents: [...state.recentEvents, summary].slice(-MAX_APM_GATED_STEERING_EVENTS)
|
|
2010
|
+
}
|
|
2011
|
+
};
|
|
2012
|
+
}
|
|
2013
|
+
function reduceApmGatedFlushReadiness(state, input) {
|
|
2014
|
+
if (!input.isGated) return { shouldNotify: false, blockedReason: "non_gated", effects: [] };
|
|
2015
|
+
if (!input.hasSession) return { shouldNotify: false, blockedReason: "missing_session", effects: [] };
|
|
2016
|
+
if (input.inboxLength === 0) return { shouldNotify: false, blockedReason: "empty_inbox", effects: [] };
|
|
2017
|
+
if (state.toolBoundaryFlushDisabled) {
|
|
2018
|
+
return { shouldNotify: false, blockedReason: "tool_boundary_flush_disabled", effects: [] };
|
|
2019
|
+
}
|
|
2020
|
+
if (state.compacting) return { shouldNotify: false, blockedReason: "compacting", effects: [] };
|
|
2021
|
+
if (state.outstandingToolUses > 0) {
|
|
2022
|
+
return { shouldNotify: false, blockedReason: "outstanding_tool_uses", effects: [] };
|
|
2023
|
+
}
|
|
2024
|
+
return {
|
|
2025
|
+
shouldNotify: true,
|
|
2026
|
+
blockedReason: null,
|
|
2027
|
+
effects: [{
|
|
2028
|
+
kind: "notify_stdin",
|
|
2029
|
+
reason: input.reason,
|
|
2030
|
+
stdinMode: "busy",
|
|
2031
|
+
clauseId: "SMR-002"
|
|
2032
|
+
}]
|
|
2033
|
+
};
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
// src/agentCredentialProxy.ts
|
|
1547
2037
|
var registrations = /* @__PURE__ */ new Map();
|
|
1548
2038
|
var proxyServerState = null;
|
|
1549
2039
|
var proxyServerStartPromise = null;
|
|
@@ -1895,6 +2385,10 @@ function maxMessageSeq(messages) {
|
|
|
1895
2385
|
}
|
|
1896
2386
|
return maxSeq > 0 ? maxSeq : void 0;
|
|
1897
2387
|
}
|
|
2388
|
+
function resolveFreshnessBoundary(messages) {
|
|
2389
|
+
const seenUpToSeq = maxMessageSeq(messages);
|
|
2390
|
+
return typeof seenUpToSeq === "number" ? { ok: true, seenUpToSeq } : { ok: false, reason: "missing_seq_boundary" };
|
|
2391
|
+
}
|
|
1898
2392
|
function sortBySeq(messages) {
|
|
1899
2393
|
return [...messages].sort((a, b) => messageSeq(a) - messageSeq(b));
|
|
1900
2394
|
}
|
|
@@ -1963,35 +2457,29 @@ function localAgentApiEventsResponse(registration, target) {
|
|
|
1963
2457
|
}
|
|
1964
2458
|
};
|
|
1965
2459
|
}
|
|
1966
|
-
function
|
|
1967
|
-
|
|
1968
|
-
}
|
|
1969
|
-
function localHeldResponse(input) {
|
|
1970
|
-
if (input.messages.length === 0) return void 0;
|
|
2460
|
+
function localHeldContext(input) {
|
|
2461
|
+
if (input.messages.length === 0) return { ok: false, reason: "empty_context" };
|
|
1971
2462
|
const normalized = sortBySeq(normalizeVisibleMessages(input.messages, input.target));
|
|
1972
2463
|
const heldMessages = latestVisibleMessages(normalized, LOCAL_HELD_CONTEXT_LIMIT);
|
|
1973
2464
|
const omittedMessageCount = Math.max(0, normalized.length - heldMessages.length);
|
|
1974
|
-
const
|
|
1975
|
-
if (
|
|
2465
|
+
const boundary = resolveFreshnessBoundary(normalized);
|
|
2466
|
+
if (!boundary.ok) return boundary;
|
|
1976
2467
|
input.coordinator.consumeVisibleMessages({
|
|
1977
2468
|
target: input.target,
|
|
1978
2469
|
messages: heldMessages,
|
|
1979
|
-
boundarySeq: seenUpToSeq,
|
|
2470
|
+
boundarySeq: boundary.seenUpToSeq,
|
|
1980
2471
|
source: input.source
|
|
1981
2472
|
});
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
omittedMessageCount
|
|
2473
|
+
return {
|
|
2474
|
+
ok: true,
|
|
2475
|
+
context: {
|
|
2476
|
+
heldMessages,
|
|
2477
|
+
newMessageCount: normalized.length,
|
|
2478
|
+
shownMessageCount: heldMessages.length,
|
|
2479
|
+
omittedMessageCount,
|
|
2480
|
+
seenUpToSeq: boundary.seenUpToSeq
|
|
2481
|
+
}
|
|
1992
2482
|
};
|
|
1993
|
-
response.seenUpToSeq = seenUpToSeq;
|
|
1994
|
-
return response;
|
|
1995
2483
|
}
|
|
1996
2484
|
function recordFreshnessDecision(coordinator, decision) {
|
|
1997
2485
|
coordinator?.recordFreshnessDecision?.(decision);
|
|
@@ -2086,31 +2574,46 @@ async function prepareAgentApiSideEffectForward(registration, headers, rawBody,
|
|
|
2086
2574
|
}
|
|
2087
2575
|
const pending = coordinator.getPendingMessages(target);
|
|
2088
2576
|
if (pending.length > 0) {
|
|
2089
|
-
const
|
|
2090
|
-
|
|
2577
|
+
const modelSeenSeq = coordinator.getBoundary(target);
|
|
2578
|
+
const contextResult = localHeldContext({
|
|
2091
2579
|
target,
|
|
2092
2580
|
messages: pending,
|
|
2093
2581
|
coordinator,
|
|
2094
2582
|
source: "side_effect_preflight_context"
|
|
2095
2583
|
});
|
|
2096
|
-
if (
|
|
2097
|
-
|
|
2584
|
+
if (contextResult.ok) {
|
|
2585
|
+
const { context } = contextResult;
|
|
2586
|
+
const decision = {
|
|
2098
2587
|
action,
|
|
2099
2588
|
decision: "local_hold",
|
|
2100
2589
|
target,
|
|
2101
2590
|
inboxTrustState: "trusted",
|
|
2102
2591
|
reason: "exact_target_pending",
|
|
2103
2592
|
pendingCount: pending.length,
|
|
2104
|
-
pendingMaxSeq:
|
|
2105
|
-
modelSeenSeq
|
|
2106
|
-
heldMessageCount:
|
|
2107
|
-
omittedMessageCount:
|
|
2108
|
-
}
|
|
2593
|
+
pendingMaxSeq: context.seenUpToSeq,
|
|
2594
|
+
modelSeenSeq,
|
|
2595
|
+
heldMessageCount: context.shownMessageCount,
|
|
2596
|
+
omittedMessageCount: context.omittedMessageCount
|
|
2597
|
+
};
|
|
2598
|
+
const producerFactId = buildApmFreshnessDecisionProducerFactId(registration.agentId, decision);
|
|
2599
|
+
const localResponse = projectApmHeldFreshnessEnvelope({
|
|
2600
|
+
producerFactId,
|
|
2601
|
+
action,
|
|
2602
|
+
heldMessages: context.heldMessages,
|
|
2603
|
+
newMessageCount: context.newMessageCount,
|
|
2604
|
+
omittedMessageCount: context.omittedMessageCount,
|
|
2605
|
+
seenUpToSeq: context.seenUpToSeq
|
|
2606
|
+
}).body;
|
|
2607
|
+
recordFreshnessDecision(coordinator, { ...decision, producerFactId });
|
|
2608
|
+
return {
|
|
2609
|
+
bodyText: JSON.stringify(body),
|
|
2610
|
+
target,
|
|
2611
|
+
localResponse
|
|
2612
|
+
};
|
|
2109
2613
|
}
|
|
2110
2614
|
return {
|
|
2111
2615
|
bodyText: JSON.stringify(body),
|
|
2112
|
-
target
|
|
2113
|
-
localResponse
|
|
2616
|
+
target
|
|
2114
2617
|
};
|
|
2115
2618
|
}
|
|
2116
2619
|
const existingBoundary = typeof body.seenUpToSeq === "number" && Number.isFinite(body.seenUpToSeq) ? Math.max(0, Math.floor(body.seenUpToSeq)) : void 0;
|
|
@@ -2131,9 +2634,22 @@ async function prepareAgentApiSideEffectForward(registration, headers, rawBody,
|
|
|
2131
2634
|
}
|
|
2132
2635
|
const recent = await loadRecentTargetMessages(registration, headers, target);
|
|
2133
2636
|
if (recent.length > 0) {
|
|
2134
|
-
const
|
|
2637
|
+
const boundary2 = resolveFreshnessBoundary(recent);
|
|
2638
|
+
if (!boundary2.ok) {
|
|
2639
|
+
recordFreshnessDecision(coordinator, {
|
|
2640
|
+
action,
|
|
2641
|
+
decision: "forward",
|
|
2642
|
+
target,
|
|
2643
|
+
inboxTrustState: "untrusted",
|
|
2644
|
+
reason: "target_first_touch_recent_context_without_seq_boundary",
|
|
2645
|
+
pendingCount: 0,
|
|
2646
|
+
modelSeenSeq: 0
|
|
2647
|
+
});
|
|
2648
|
+
return { bodyText: JSON.stringify(body), target };
|
|
2649
|
+
}
|
|
2650
|
+
const { seenUpToSeq } = boundary2;
|
|
2135
2651
|
coordinator.consumeVisibleMessages({ target, messages: recent, boundarySeq: seenUpToSeq, source: "side_effect_preflight_context" });
|
|
2136
|
-
|
|
2652
|
+
const decision = {
|
|
2137
2653
|
action,
|
|
2138
2654
|
decision: "syncing_hold",
|
|
2139
2655
|
target,
|
|
@@ -2144,22 +2660,20 @@ async function prepareAgentApiSideEffectForward(registration, headers, rawBody,
|
|
|
2144
2660
|
modelSeenSeq: 0,
|
|
2145
2661
|
heldMessageCount: recent.length,
|
|
2146
2662
|
omittedMessageCount: 0
|
|
2147
|
-
}
|
|
2663
|
+
};
|
|
2664
|
+
const producerFactId = buildApmFreshnessDecisionProducerFactId(registration.agentId, decision);
|
|
2665
|
+
recordFreshnessDecision(coordinator, { ...decision, producerFactId });
|
|
2148
2666
|
return {
|
|
2149
2667
|
bodyText: JSON.stringify(body),
|
|
2150
2668
|
target,
|
|
2151
|
-
localResponse: {
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
subtype: "freshness",
|
|
2155
|
-
reason: "newer_messages_available",
|
|
2156
|
-
available_actions: heldAvailableActions(action),
|
|
2157
|
-
seenUpToSeq,
|
|
2669
|
+
localResponse: projectApmHeldFreshnessEnvelope({
|
|
2670
|
+
producerFactId,
|
|
2671
|
+
action,
|
|
2158
2672
|
heldMessages: recent,
|
|
2159
2673
|
newMessageCount: recent.length,
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
}
|
|
2674
|
+
omittedMessageCount: 0,
|
|
2675
|
+
seenUpToSeq
|
|
2676
|
+
}).body
|
|
2163
2677
|
};
|
|
2164
2678
|
}
|
|
2165
2679
|
recordFreshnessDecision(coordinator, {
|
|
@@ -5356,7 +5870,7 @@ async function deleteWorkspaceDirectory(dataDir, directoryName) {
|
|
|
5356
5870
|
}
|
|
5357
5871
|
|
|
5358
5872
|
// src/runtimeErrorDiagnostics.ts
|
|
5359
|
-
import { createHash } from "crypto";
|
|
5873
|
+
import { createHash as createHash2 } from "crypto";
|
|
5360
5874
|
var MAX_RUNTIME_ERROR_MESSAGE_EXCERPT_CHARS = 4096;
|
|
5361
5875
|
var RUNTIME_AUTH_ACTION_REQUIRED_PATTERNS = [
|
|
5362
5876
|
/access token could not be refreshed/i,
|
|
@@ -5506,7 +6020,7 @@ function runtimeDisplayName(runtimeId) {
|
|
|
5506
6020
|
}
|
|
5507
6021
|
function fingerprintRuntimeError(value) {
|
|
5508
6022
|
const normalized = value.toLowerCase().replace(/[0-9a-f]{12,}/g, "<hex>").replace(/\b\d+\b/g, "<num>").replace(/\s+/g, " ").trim();
|
|
5509
|
-
return
|
|
6023
|
+
return createHash2("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
5510
6024
|
}
|
|
5511
6025
|
function bucketLength(length) {
|
|
5512
6026
|
if (length === 0) return "0";
|
|
@@ -5612,6 +6126,9 @@ var RuntimeNotificationState = class {
|
|
|
5612
6126
|
var DEFAULT_MAX_CONCURRENT_AGENT_STARTS = 5;
|
|
5613
6127
|
var DEFAULT_AGENT_START_INTERVAL_MS = 500;
|
|
5614
6128
|
var RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS = 3;
|
|
6129
|
+
function assertNeverApmEffect(effect) {
|
|
6130
|
+
throw new Error(`Unhandled APM gated steering effect: ${String(effect)}`);
|
|
6131
|
+
}
|
|
5615
6132
|
var RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS = 250;
|
|
5616
6133
|
var WORKSPACE_TEXT_FILE_MAX_BYTES = 1048576;
|
|
5617
6134
|
var WORKSPACE_IMAGE_PREVIEW_MAX_BYTES = 5 * 1024 * 1024;
|
|
@@ -5917,7 +6434,8 @@ function formatIncomingMessage(message, driver) {
|
|
|
5917
6434
|
const senderType = formatVisibleActorType(message.sender_type);
|
|
5918
6435
|
const attachSuffix = message.attachments?.length ? ` [${message.attachments.length} attachment${message.attachments.length > 1 ? "s" : ""}: ${message.attachments.map((a) => `${a.filename} (id:${a.id})`).join(", ")} \u2014 use view_file to download]` : "";
|
|
5919
6436
|
const taskSuffix = message.task_status ? ` [task #${message.task_number} status=${message.task_status}${message.task_assignee_id ? ` assignee=${formatTaskAssigneeType(message.task_assignee_type)}:${message.task_assignee_id}` : ""}]` : "";
|
|
5920
|
-
const
|
|
6437
|
+
const lineageSuffix = formatProducerFactLineageBracket(message.producerFactId);
|
|
6438
|
+
const body = `[target=${target} msg=${msgId} time=${time}${senderType}] ${formatSenderHandle(message)}: ${message.content}${attachSuffix}${taskSuffix}${lineageSuffix}`;
|
|
5921
6439
|
return threadJoinPrefix ? `${threadJoinPrefix}
|
|
5922
6440
|
${body}` : body;
|
|
5923
6441
|
}
|
|
@@ -5959,6 +6477,8 @@ function buildUnreadSummary(messages, excludeChannel) {
|
|
|
5959
6477
|
var MAX_TRAJECTORY_TEXT = 2e3;
|
|
5960
6478
|
var TRAJECTORY_COALESCE_MS = 350;
|
|
5961
6479
|
var ACTIVITY_HEARTBEAT_MS = 6e4;
|
|
6480
|
+
var STDIN_NOTIFICATION_INITIAL_DELAY_MS = 3e3;
|
|
6481
|
+
var STDIN_NOTIFICATION_RETRY_DELAY_MS = 15e3;
|
|
5962
6482
|
var COMPACTION_STALE_MS = 5 * 6e4;
|
|
5963
6483
|
var RUNTIME_PROGRESS_STALE_MS = 15 * 6e4;
|
|
5964
6484
|
var DEFAULT_RUNTIME_START_TIMEOUT_MS = 2 * 6e4;
|
|
@@ -5967,7 +6487,6 @@ var MAX_STDOUT_LINES = 8;
|
|
|
5967
6487
|
var MAX_STDOUT_LINE_LENGTH = 240;
|
|
5968
6488
|
var MAX_STDERR_LINES = 8;
|
|
5969
6489
|
var MAX_STDERR_LINE_LENGTH = 240;
|
|
5970
|
-
var MAX_GATED_STEERING_EVENTS = 12;
|
|
5971
6490
|
var ONBOARDING_MEMORY_SEED_ENV = "SLOCK_ONBOARDING_MEMORY_SEED";
|
|
5972
6491
|
var FIRST_CINDY_SEED_MODE = "first-cindy";
|
|
5973
6492
|
function getOnboardingSeedMode(config) {
|
|
@@ -6383,13 +6902,8 @@ function stripManagedRunnerCredential(config) {
|
|
|
6383
6902
|
}
|
|
6384
6903
|
function createGatedSteeringState() {
|
|
6385
6904
|
return {
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
compacting: false,
|
|
6389
|
-
toolBoundaryFlushDisabled: process.env.SLOCK_CLAUDE_GATED_STEERING_TOOL_BOUNDARY === "0",
|
|
6390
|
-
lastFlushReason: null,
|
|
6391
|
-
recentEvents: [],
|
|
6392
|
-
inFlightBatch: null
|
|
6905
|
+
...createInitialApmGatedSteeringState(),
|
|
6906
|
+
toolBoundaryFlushDisabled: process.env.SLOCK_CLAUDE_GATED_STEERING_TOOL_BOUNDARY === "0"
|
|
6393
6907
|
};
|
|
6394
6908
|
}
|
|
6395
6909
|
var RUNTIME_PROFILE_MIGRATION_MESSAGE_PREFIX = "runtime-profile-migration-";
|
|
@@ -6408,7 +6922,7 @@ function runtimeProfileNotificationTitle(kind) {
|
|
|
6408
6922
|
}
|
|
6409
6923
|
function hashRuntimeProfileKey(key) {
|
|
6410
6924
|
if (!key) return void 0;
|
|
6411
|
-
return
|
|
6925
|
+
return createHash3("sha256").update(key).digest("hex").slice(0, 16);
|
|
6412
6926
|
}
|
|
6413
6927
|
function runtimeProfileTurnControl(kind, key, source) {
|
|
6414
6928
|
return {
|
|
@@ -6680,6 +7194,19 @@ function summarizeMessageInputBytes(messages) {
|
|
|
6680
7194
|
runtime_input_thread_context_content_bytes_bucket: bucketBytes(threadContextContentBytes)
|
|
6681
7195
|
};
|
|
6682
7196
|
}
|
|
7197
|
+
function messageProducerFactTraceAttrs(messages) {
|
|
7198
|
+
if (!messages || messages.length === 0) return {};
|
|
7199
|
+
const producerFactIds = /* @__PURE__ */ new Set();
|
|
7200
|
+
for (const message of messages) {
|
|
7201
|
+
const producerFactId = typeof message.producerFactId === "string" ? message.producerFactId.trim() : "";
|
|
7202
|
+
if (producerFactId) producerFactIds.add(producerFactId);
|
|
7203
|
+
}
|
|
7204
|
+
if (producerFactIds.size === 0) return {};
|
|
7205
|
+
return {
|
|
7206
|
+
message_producer_fact_count: producerFactIds.size,
|
|
7207
|
+
...producerFactIds.size === 1 ? { message_producer_fact_id: [...producerFactIds][0] } : {}
|
|
7208
|
+
};
|
|
7209
|
+
}
|
|
6683
7210
|
function buildRuntimeInputTraceAttrs(opts) {
|
|
6684
7211
|
return {
|
|
6685
7212
|
runtime_input_source: opts.source,
|
|
@@ -6748,6 +7275,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6748
7275
|
driverResolver;
|
|
6749
7276
|
defaultAgentEnvVarsProvider;
|
|
6750
7277
|
tracer;
|
|
7278
|
+
stdinNotificationRetryMs;
|
|
6751
7279
|
cliTransportTraceDir = null;
|
|
6752
7280
|
deliveryTraceContexts = /* @__PURE__ */ new WeakMap();
|
|
6753
7281
|
processExitTraceAttrs = /* @__PURE__ */ new WeakMap();
|
|
@@ -6763,6 +7291,10 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6763
7291
|
this.driverResolver = opts.driverResolver || getDriver;
|
|
6764
7292
|
this.defaultAgentEnvVarsProvider = opts.defaultAgentEnvVarsProvider || null;
|
|
6765
7293
|
this.tracer = opts.tracer ?? noopTracer;
|
|
7294
|
+
this.stdinNotificationRetryMs = Math.max(
|
|
7295
|
+
0,
|
|
7296
|
+
Math.floor(opts.stdinNotificationRetryMs ?? STDIN_NOTIFICATION_RETRY_DELAY_MS)
|
|
7297
|
+
);
|
|
6766
7298
|
this.maxConcurrentAgentStarts = Math.max(
|
|
6767
7299
|
1,
|
|
6768
7300
|
Math.floor(
|
|
@@ -6793,6 +7325,11 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6793
7325
|
getVisibleBoundary(agentId, target) {
|
|
6794
7326
|
return this.agentVisibleBoundaries.get(agentId)?.get(target);
|
|
6795
7327
|
}
|
|
7328
|
+
scheduleStdinNotification(agentId, ap, delayMs) {
|
|
7329
|
+
return ap.notifications.schedule(() => {
|
|
7330
|
+
this.sendStdinNotification(agentId);
|
|
7331
|
+
}, delayMs);
|
|
7332
|
+
}
|
|
6796
7333
|
allPendingVisibleMessages(agentId) {
|
|
6797
7334
|
const collect = (messages) => (messages ?? []).filter((message) => typeof message.seq === "number" && message.seq > 0);
|
|
6798
7335
|
return [
|
|
@@ -6888,20 +7425,16 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6888
7425
|
recordProxyFailure: (input) => this.recordAgentProxyFailure(agentId, input),
|
|
6889
7426
|
recordTransportNormalizedError: (input) => this.recordAgentProxyTransportNormalizedError(agentId, input),
|
|
6890
7427
|
recordFreshnessDecision: (input) => {
|
|
7428
|
+
const producerFactId = input.producerFactId ?? buildApmFreshnessDecisionProducerFactId(agentId, input);
|
|
7429
|
+
const trace = projectApmFreshnessDecisionTrace({
|
|
7430
|
+
producerFactId,
|
|
7431
|
+
decision: input
|
|
7432
|
+
});
|
|
6891
7433
|
this.recordDaemonTrace("daemon.agent.inbox.freshness_decision", {
|
|
6892
7434
|
agentId,
|
|
6893
|
-
|
|
6894
|
-
decision: input.decision,
|
|
6895
|
-
target: input.target,
|
|
6896
|
-
inbox_trust_state: input.inboxTrustState,
|
|
6897
|
-
reason: input.reason,
|
|
6898
|
-
pending_count: input.pendingCount,
|
|
6899
|
-
pending_max_seq: input.pendingMaxSeq,
|
|
6900
|
-
model_seen_seq: input.modelSeenSeq,
|
|
6901
|
-
held_message_count: input.heldMessageCount,
|
|
6902
|
-
omitted_message_count: input.omittedMessageCount
|
|
7435
|
+
...trace.attrs
|
|
6903
7436
|
});
|
|
6904
|
-
this.recordFreshnessDecisionActivity(agentId, input);
|
|
7437
|
+
this.recordFreshnessDecisionActivity(agentId, input, producerFactId);
|
|
6905
7438
|
}
|
|
6906
7439
|
};
|
|
6907
7440
|
}
|
|
@@ -6931,20 +7464,17 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6931
7464
|
upstream: input.upstream
|
|
6932
7465
|
}, "error");
|
|
6933
7466
|
}
|
|
6934
|
-
recordFreshnessDecisionActivity(agentId, input) {
|
|
7467
|
+
recordFreshnessDecisionActivity(agentId, input, producerFactId) {
|
|
6935
7468
|
if (input.decision !== "local_hold" && input.decision !== "syncing_hold") return;
|
|
6936
7469
|
const ap = this.agents.get(agentId);
|
|
6937
7470
|
const messageCount = input.pendingCount ?? input.heldMessageCount ?? 0;
|
|
6938
|
-
const
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
`decision: ${input.decision === "syncing_hold" ? "syncing hold" : "local hold"}; review the newer context before retrying`
|
|
6946
|
-
].filter((line) => Boolean(line)).join("\n")
|
|
6947
|
-
};
|
|
7471
|
+
const entry = projectApmHeldFreshnessActivity({
|
|
7472
|
+
producerFactId,
|
|
7473
|
+
action: input.action,
|
|
7474
|
+
decision: input.decision,
|
|
7475
|
+
target: input.target,
|
|
7476
|
+
messageCount
|
|
7477
|
+
}).entry;
|
|
6948
7478
|
if (ap) ap.activityClientSeq += 1;
|
|
6949
7479
|
this.sendToServer({
|
|
6950
7480
|
type: "agent:activity",
|
|
@@ -7353,7 +7883,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
7353
7883
|
notifications: new RuntimeNotificationState(),
|
|
7354
7884
|
activityHeartbeat: null,
|
|
7355
7885
|
startupTimeoutTimer: null,
|
|
7356
|
-
startupTimedOut: false,
|
|
7357
7886
|
compactionWatchdog: null,
|
|
7358
7887
|
compactionStartedAt: null,
|
|
7359
7888
|
runtimeProgress: new RuntimeProgressState(Date.now()),
|
|
@@ -7485,7 +8014,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
7485
8014
|
this.clearStalledRecoverySigtermWatchdog(ap);
|
|
7486
8015
|
const finalCode = ap.exitCode ?? code;
|
|
7487
8016
|
const finalSignal = ap.exitSignal ?? signal;
|
|
7488
|
-
const
|
|
8017
|
+
const startupTimeoutTermination = ap.expectedTerminationReason === "startup_timeout";
|
|
8018
|
+
const expectedTermination = Boolean(ap.expectedTerminationReason);
|
|
7489
8019
|
const processEndedCleanly = finalCode === 0 || expectedTermination && !ap.lastRuntimeError;
|
|
7490
8020
|
const terminalFailureDetail = processEndedCleanly ? null : classifyTerminalFailure(ap);
|
|
7491
8021
|
const resumeRecoveryReason = resumeSessionRecoveryReason(ap);
|
|
@@ -7589,7 +8119,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
7589
8119
|
});
|
|
7590
8120
|
logger.warn(`[Agent ${agentId}] Recoverable provider stream failure (${reason}) \u2014 keeping agent wakeable`);
|
|
7591
8121
|
this.sendAgentStatus(agentId, "active", ap.launchId);
|
|
7592
|
-
} else if (
|
|
8122
|
+
} else if (startupTimeoutTermination) {
|
|
7593
8123
|
logger.warn(`[Agent ${agentId}] Startup timeout cleanup completed (${reason})`);
|
|
7594
8124
|
} else {
|
|
7595
8125
|
this.idleAgentConfigs.delete(agentId);
|
|
@@ -7597,7 +8127,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
7597
8127
|
this.sendAgentStatus(agentId, "inactive", ap.launchId);
|
|
7598
8128
|
}
|
|
7599
8129
|
if (terminalFailureDetail) {
|
|
7600
|
-
if (!
|
|
8130
|
+
if (!startupTimeoutTermination) {
|
|
7601
8131
|
this.broadcastActivity(
|
|
7602
8132
|
agentId,
|
|
7603
8133
|
"error",
|
|
@@ -7795,9 +8325,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
7795
8325
|
pendingMessages: ap.inbox.length
|
|
7796
8326
|
});
|
|
7797
8327
|
} else if (!ap.notifications.hasTimer) {
|
|
7798
|
-
|
|
7799
|
-
this.sendStdinNotification(agentId);
|
|
7800
|
-
}, 3e3);
|
|
8328
|
+
this.scheduleStdinNotification(agentId, ap, STDIN_NOTIFICATION_INITIAL_DELAY_MS);
|
|
7801
8329
|
}
|
|
7802
8330
|
}
|
|
7803
8331
|
this.recordDaemonTrace("daemon.agent.runtime_profile.routed", {
|
|
@@ -7975,7 +8503,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
7975
8503
|
if (ap.isIdle && ap.driver.supportsStdinNotification && ap.sessionId) {
|
|
7976
8504
|
const nextMessages = ap.inbox.splice(0, ap.inbox.length);
|
|
7977
8505
|
nextMessages.push(message);
|
|
7978
|
-
|
|
8506
|
+
this.commitApmIdleState(agentId, ap, false);
|
|
7979
8507
|
this.startRuntimeTrace(agentId, ap, "stdin-idle-delivery", nextMessages);
|
|
7980
8508
|
this.broadcastActivity(agentId, "working", "Message received");
|
|
7981
8509
|
const stdinAccepted = this.deliverMessagesViaStdin(agentId, ap, nextMessages, "idle");
|
|
@@ -8059,9 +8587,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8059
8587
|
if (ap.driver.busyDeliveryMode === "gated") {
|
|
8060
8588
|
ap.notifications.add();
|
|
8061
8589
|
if (!ap.notifications.hasTimer) {
|
|
8062
|
-
|
|
8063
|
-
this.sendStdinNotification(agentId);
|
|
8064
|
-
}, 3e3);
|
|
8590
|
+
this.scheduleStdinNotification(agentId, ap, STDIN_NOTIFICATION_INITIAL_DELAY_MS);
|
|
8065
8591
|
}
|
|
8066
8592
|
this.recordGatedSteeringEvent(agentId, ap, "buffer", {
|
|
8067
8593
|
reason: "busy_message",
|
|
@@ -8082,9 +8608,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8082
8608
|
}
|
|
8083
8609
|
ap.notifications.add();
|
|
8084
8610
|
if (!ap.notifications.hasTimer) {
|
|
8085
|
-
|
|
8086
|
-
this.sendStdinNotification(agentId);
|
|
8087
|
-
}, 3e3);
|
|
8611
|
+
this.scheduleStdinNotification(agentId, ap, STDIN_NOTIFICATION_INITIAL_DELAY_MS);
|
|
8088
8612
|
}
|
|
8089
8613
|
this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
|
|
8090
8614
|
outcome: "queued_busy_notification",
|
|
@@ -8258,7 +8782,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8258
8782
|
return true;
|
|
8259
8783
|
}
|
|
8260
8784
|
if (ap?.sessionId && ap.driver.supportsStdinNotification && ap.isIdle) {
|
|
8261
|
-
|
|
8785
|
+
this.commitApmIdleState(agentId, ap, false);
|
|
8262
8786
|
this.startRuntimeTrace(agentId, ap, "runtime-profile", [message]);
|
|
8263
8787
|
const written = this.deliverMessagesViaStdin(agentId, ap, [message], "idle");
|
|
8264
8788
|
span.end(written ? "ok" : "error", {
|
|
@@ -8768,18 +9292,22 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8768
9292
|
if (!ap || !ap.compactionStartedAt) return;
|
|
8769
9293
|
this.clearCompactionWatchdog(ap);
|
|
8770
9294
|
this.broadcastActivity(agentId, "working", detail, [{ kind: "compaction_finished" }]);
|
|
8771
|
-
ap.gatedSteering
|
|
8772
|
-
this.
|
|
9295
|
+
const reduction = reduceApmGatedCompaction(ap.gatedSteering, { kind: "compaction_finished" });
|
|
9296
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, {
|
|
9297
|
+
event: "compaction_finished",
|
|
9298
|
+
inferred: true
|
|
9299
|
+
});
|
|
8773
9300
|
if (options.flushBoundaryMessages ?? true) {
|
|
8774
9301
|
this.flushCompactionBoundaryMessages(agentId, ap);
|
|
8775
9302
|
}
|
|
8776
|
-
|
|
9303
|
+
this.commitApmIdleState(agentId, ap, false);
|
|
8777
9304
|
}
|
|
8778
9305
|
interruptCompactionIfActive(agentId) {
|
|
8779
9306
|
const ap = this.agents.get(agentId);
|
|
8780
9307
|
if (!ap || !ap.compactionStartedAt && !ap.gatedSteering.compacting) return;
|
|
8781
9308
|
this.clearCompactionWatchdog(ap);
|
|
8782
|
-
ap.gatedSteering
|
|
9309
|
+
const reduction = reduceApmGatedCompaction(ap.gatedSteering, { kind: "compaction_interrupted" });
|
|
9310
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState);
|
|
8783
9311
|
}
|
|
8784
9312
|
messagesTraceAttrs(messages) {
|
|
8785
9313
|
if (!messages || messages.length === 0) return {};
|
|
@@ -8792,6 +9320,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8792
9320
|
message_id_present: Boolean(first.message_id),
|
|
8793
9321
|
deliveryId: context.deliveryId,
|
|
8794
9322
|
delivery_correlation_id: context.deliveryId,
|
|
9323
|
+
...messageProducerFactTraceAttrs(messages),
|
|
8795
9324
|
control_kind: notification.kind,
|
|
8796
9325
|
key_present: Boolean(notification.key),
|
|
8797
9326
|
runtime_profile_control_kind: notification.kind,
|
|
@@ -8804,7 +9333,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8804
9333
|
messageId: first.message_id,
|
|
8805
9334
|
message_id_present: Boolean(first.message_id),
|
|
8806
9335
|
deliveryId: context.deliveryId,
|
|
8807
|
-
delivery_correlation_id: context.deliveryId ?? first.message_id
|
|
9336
|
+
delivery_correlation_id: context.deliveryId ?? first.message_id,
|
|
9337
|
+
...messageProducerFactTraceAttrs(messages)
|
|
8808
9338
|
};
|
|
8809
9339
|
}
|
|
8810
9340
|
runtimeProfileTurnControlTraceAttrs(control) {
|
|
@@ -8893,10 +9423,11 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8893
9423
|
}
|
|
8894
9424
|
recordGatedSteeringEvent(agentId, ap, event, attrs = {}) {
|
|
8895
9425
|
if (ap.driver.busyDeliveryMode !== "gated") return;
|
|
8896
|
-
const
|
|
8897
|
-
ap.
|
|
8898
|
-
ap.gatedSteering.recentEvents = ap.gatedSteering.recentEvents.slice(-MAX_GATED_STEERING_EVENTS);
|
|
9426
|
+
const reduction = reduceApmGatedRecentEvent(ap.gatedSteering, { event });
|
|
9427
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState);
|
|
8899
9428
|
this.recordRuntimeTraceEvent(agentId, ap, `runtime.gated_steering.${event}`, {
|
|
9429
|
+
isIdle: ap.gatedSteering.isIdle,
|
|
9430
|
+
expectedTerminationReason: ap.gatedSteering.expectedTerminationReason,
|
|
8900
9431
|
phase: ap.gatedSteering.phase,
|
|
8901
9432
|
outstandingToolUses: ap.gatedSteering.outstandingToolUses,
|
|
8902
9433
|
compacting: ap.gatedSteering.compacting,
|
|
@@ -8905,63 +9436,110 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8905
9436
|
...attrs
|
|
8906
9437
|
});
|
|
8907
9438
|
}
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
ap.gatedSteering.
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
}
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
const
|
|
8925
|
-
ap.
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
);
|
|
8939
|
-
if (reason === "turn_end") {
|
|
8940
|
-
this.broadcastActivity(agentId, "working", "Message received");
|
|
8941
|
-
}
|
|
8942
|
-
if (this.deliverMessagesViaStdin(agentId, ap, nextMessages, reason === "turn_end" ? "idle" : "busy")) {
|
|
8943
|
-
return true;
|
|
9439
|
+
commitGatedSteeringDecisionState(agentId, ap, nextState, phaseEventAttrs) {
|
|
9440
|
+
ap.gatedSteering.phase = nextState.phase;
|
|
9441
|
+
ap.gatedSteering.outstandingToolUses = nextState.outstandingToolUses;
|
|
9442
|
+
ap.gatedSteering.compacting = nextState.compacting;
|
|
9443
|
+
ap.gatedSteering.toolBoundaryFlushDisabled = nextState.toolBoundaryFlushDisabled;
|
|
9444
|
+
ap.gatedSteering.lastFlushReason = nextState.lastFlushReason;
|
|
9445
|
+
ap.gatedSteering.recentEvents = nextState.recentEvents;
|
|
9446
|
+
ap.gatedSteering.isIdle = nextState.isIdle;
|
|
9447
|
+
ap.gatedSteering.expectedTerminationReason = nextState.expectedTerminationReason;
|
|
9448
|
+
ap.isIdle = nextState.isIdle;
|
|
9449
|
+
ap.expectedTerminationReason = nextState.expectedTerminationReason;
|
|
9450
|
+
if (phaseEventAttrs) {
|
|
9451
|
+
this.recordGatedSteeringEvent(agentId, ap, "phase", phaseEventAttrs);
|
|
9452
|
+
}
|
|
9453
|
+
}
|
|
9454
|
+
commitApmIdleState(agentId, ap, isIdle) {
|
|
9455
|
+
const reduction = reduceApmIdleState(ap.gatedSteering, { isIdle });
|
|
9456
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState);
|
|
9457
|
+
}
|
|
9458
|
+
notifyGatedSteeringBoundary(agentId, ap, reason) {
|
|
9459
|
+
const readiness = reduceApmGatedFlushReadiness(ap.gatedSteering, {
|
|
9460
|
+
isGated: ap.driver.busyDeliveryMode === "gated",
|
|
9461
|
+
hasSession: Boolean(ap.sessionId),
|
|
9462
|
+
inboxLength: ap.inbox.length,
|
|
9463
|
+
reason
|
|
9464
|
+
});
|
|
9465
|
+
if (readiness.effects.length === 0) return false;
|
|
9466
|
+
let didExecute = false;
|
|
9467
|
+
for (const effect of readiness.effects) {
|
|
9468
|
+
didExecute = this.executeApmGatedSteeringEffect(agentId, ap, effect) || didExecute;
|
|
8944
9469
|
}
|
|
8945
|
-
|
|
8946
|
-
|
|
9470
|
+
return didExecute;
|
|
9471
|
+
}
|
|
9472
|
+
recordApmGatedSteeringEffectTrace(agentId, ap, effect, attrs) {
|
|
9473
|
+
this.recordDaemonTrace("daemon.apm.gated_effect", {
|
|
9474
|
+
agentId,
|
|
9475
|
+
launchId: ap.launchId || void 0,
|
|
9476
|
+
runtime: ap.config.runtime,
|
|
9477
|
+
effect_kind: effect.kind,
|
|
9478
|
+
reason: effect.reason,
|
|
9479
|
+
target: "runtime-stdin",
|
|
9480
|
+
stdin_mode: effect.stdinMode,
|
|
9481
|
+
clause_id: effect.clauseId,
|
|
9482
|
+
pending_messages: ap.inbox.length,
|
|
9483
|
+
...attrs
|
|
9484
|
+
});
|
|
9485
|
+
}
|
|
9486
|
+
executeApmGatedSteeringEffect(agentId, ap, effect) {
|
|
9487
|
+
switch (effect.kind) {
|
|
9488
|
+
case "notify_stdin":
|
|
9489
|
+
this.recordGatedSteeringEvent(agentId, ap, "notify", {
|
|
9490
|
+
reason: effect.reason,
|
|
9491
|
+
pendingMessages: ap.inbox.length
|
|
9492
|
+
});
|
|
9493
|
+
{
|
|
9494
|
+
const written = this.sendStdinNotification(agentId);
|
|
9495
|
+
this.recordApmGatedSteeringEffectTrace(agentId, ap, effect, {
|
|
9496
|
+
outcome: written ? "written" : "not_written"
|
|
9497
|
+
});
|
|
9498
|
+
return written;
|
|
9499
|
+
}
|
|
9500
|
+
case "deliver_stdin": {
|
|
9501
|
+
const messages = ap.inbox.splice(0, ap.inbox.length);
|
|
9502
|
+
ap.notifications.clear();
|
|
9503
|
+
if (messages.length === 0) {
|
|
9504
|
+
this.recordApmGatedSteeringEffectTrace(agentId, ap, effect, {
|
|
9505
|
+
outcome: "empty",
|
|
9506
|
+
delivered_messages_count: 0
|
|
9507
|
+
});
|
|
9508
|
+
return true;
|
|
9509
|
+
}
|
|
9510
|
+
if (ap.driver.busyDeliveryMode === "gated") {
|
|
9511
|
+
const flushReduction = reduceApmGatedFlush(ap.gatedSteering, { reason: effect.reason });
|
|
9512
|
+
this.commitGatedSteeringDecisionState(agentId, ap, flushReduction.nextState);
|
|
9513
|
+
this.recordGatedSteeringEvent(agentId, ap, "flush", {
|
|
9514
|
+
reason: effect.reason,
|
|
9515
|
+
messageCount: messages.length
|
|
9516
|
+
});
|
|
9517
|
+
}
|
|
9518
|
+
this.broadcastActivity(agentId, "working", "Message received");
|
|
9519
|
+
const accepted = this.deliverMessagesViaStdin(agentId, ap, messages, effect.stdinMode);
|
|
9520
|
+
this.recordApmGatedSteeringEffectTrace(agentId, ap, effect, {
|
|
9521
|
+
outcome: accepted ? "written" : "not_written",
|
|
9522
|
+
delivered_messages_count: messages.length
|
|
9523
|
+
});
|
|
9524
|
+
return accepted;
|
|
9525
|
+
}
|
|
9526
|
+
default:
|
|
9527
|
+
return assertNeverApmEffect(effect);
|
|
8947
9528
|
}
|
|
8948
|
-
ap.notifications.add(pendingNotificationCount || pendingMessages);
|
|
8949
|
-
return false;
|
|
8950
9529
|
}
|
|
8951
9530
|
flushCompactionBoundaryMessages(agentId, ap) {
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
ap.
|
|
8955
|
-
|
|
8956
|
-
|
|
9531
|
+
const reduction = reduceApmGatedCompactionBoundaryFlush(ap.gatedSteering, {
|
|
9532
|
+
hasSession: Boolean(ap.sessionId),
|
|
9533
|
+
supportsStdinNotification: ap.driver.supportsStdinNotification,
|
|
9534
|
+
inboxLength: ap.inbox.length,
|
|
9535
|
+
pendingNotificationCount: ap.notifications.pendingCount
|
|
9536
|
+
});
|
|
9537
|
+
if (reduction.effects.length === 0) return false;
|
|
9538
|
+
ap.notifications.clearTimer();
|
|
9539
|
+
for (const effect of reduction.effects) {
|
|
9540
|
+
this.executeApmGatedSteeringEffect(agentId, ap, effect);
|
|
8957
9541
|
}
|
|
8958
|
-
return
|
|
8959
|
-
}
|
|
8960
|
-
clearGatedInFlightBatch(agentId, ap, reason) {
|
|
8961
|
-
if (ap.driver.busyDeliveryMode !== "gated" || !ap.gatedSteering.inFlightBatch) return;
|
|
8962
|
-
const messageCount = ap.gatedSteering.inFlightBatch.messages.length;
|
|
8963
|
-
ap.gatedSteering.inFlightBatch = null;
|
|
8964
|
-
this.recordGatedSteeringEvent(agentId, ap, "ack", { reason, messageCount });
|
|
9542
|
+
return true;
|
|
8965
9543
|
}
|
|
8966
9544
|
startRuntimeStartupTimeout(agentId, ap) {
|
|
8967
9545
|
const timeoutMs = runtimeStartTimeoutMs();
|
|
@@ -8979,14 +9557,17 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8979
9557
|
handleRuntimeStartupTimeout(agentId, ap, timeoutMs) {
|
|
8980
9558
|
const current = this.agents.get(agentId);
|
|
8981
9559
|
if (current !== ap) return;
|
|
8982
|
-
|
|
9560
|
+
const reduction = reduceApmStartupTimeoutTermination(ap.gatedSteering, {
|
|
9561
|
+
hasRuntimeProgressEvent: Boolean(ap.runtimeProgress.lastEventKind)
|
|
9562
|
+
});
|
|
9563
|
+
if (!reduction.shouldTerminate) {
|
|
8983
9564
|
this.clearRuntimeStartupTimeout(ap);
|
|
8984
9565
|
return;
|
|
8985
9566
|
}
|
|
8986
9567
|
this.clearRuntimeStartupTimeout(ap);
|
|
9568
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState);
|
|
8987
9569
|
const terminalFailureDetail = classifyTerminalFailure(ap);
|
|
8988
9570
|
const detail = terminalFailureDetail?.detail ?? formatRuntimeStartTimeoutMessage(ap.driver.id);
|
|
8989
|
-
ap.startupTimedOut = true;
|
|
8990
9571
|
ap.lastRuntimeError = detail;
|
|
8991
9572
|
ap.runtimeProgress.markStale();
|
|
8992
9573
|
const staleForMs = Math.max(timeoutMs, ap.runtimeProgress.ageMs());
|
|
@@ -9015,6 +9596,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9015
9596
|
try {
|
|
9016
9597
|
this.processExitTraceAttrs.set(ap.process, {
|
|
9017
9598
|
stop_source: "startup_timeout",
|
|
9599
|
+
expectedTerminationReason: "startup_timeout",
|
|
9018
9600
|
timeout_ms: timeoutMs
|
|
9019
9601
|
});
|
|
9020
9602
|
ap.process.kill("SIGTERM");
|
|
@@ -9023,18 +9605,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9023
9605
|
logger.warn(`[Agent ${agentId}] Failed to terminate startup-timed-out ${ap.driver.id} process: ${reason}`);
|
|
9024
9606
|
}
|
|
9025
9607
|
}
|
|
9026
|
-
requeueGatedInFlightBatch(agentId, ap, reason) {
|
|
9027
|
-
if (ap.driver.busyDeliveryMode !== "gated" || !ap.gatedSteering.inFlightBatch) return;
|
|
9028
|
-
const batch = ap.gatedSteering.inFlightBatch;
|
|
9029
|
-
ap.gatedSteering.inFlightBatch = null;
|
|
9030
|
-
ap.inbox.unshift(...batch.messages);
|
|
9031
|
-
ap.notifications.add(batch.messages.length);
|
|
9032
|
-
this.recordGatedSteeringEvent(agentId, ap, "requeue", {
|
|
9033
|
-
reason,
|
|
9034
|
-
originalFlushReason: batch.reason,
|
|
9035
|
-
messageCount: batch.messages.length
|
|
9036
|
-
});
|
|
9037
|
-
}
|
|
9038
9608
|
isThinkingBlockMutationError(message) {
|
|
9039
9609
|
return /thinking.*redacted_thinking|redacted_thinking.*thinking/i.test(message) && /cannot be modified/i.test(message);
|
|
9040
9610
|
}
|
|
@@ -9068,16 +9638,22 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9068
9638
|
return true;
|
|
9069
9639
|
}
|
|
9070
9640
|
recoverStaleProcessForQueuedMessageIfNeeded(agentId, ap) {
|
|
9071
|
-
|
|
9072
|
-
|
|
9641
|
+
const staleForMs = ap.runtimeProgress.ageMs();
|
|
9642
|
+
const reduction = reduceApmStalledRecoveryTermination(ap.gatedSteering, {
|
|
9643
|
+
inboxLength: ap.inbox.length,
|
|
9644
|
+
supportsStdinNotification: ap.driver.supportsStdinNotification,
|
|
9645
|
+
busyDeliveryMode: ap.driver.busyDeliveryMode,
|
|
9646
|
+
hasSession: Boolean(ap.sessionId),
|
|
9647
|
+
hasDirectStdinRecoveryEvidence: hasDirectStdinRecoveryEvidence(ap),
|
|
9648
|
+
runtimeProgressIsStale: ap.runtimeProgress.isStale,
|
|
9649
|
+
staleForMs,
|
|
9650
|
+
staleThresholdMs: RUNTIME_PROGRESS_STALE_MS
|
|
9651
|
+
});
|
|
9652
|
+
if (reduction.alreadyRecovering) {
|
|
9073
9653
|
return true;
|
|
9074
9654
|
}
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
const canRestartStalledProcess = !ap.driver.supportsStdinNotification || canRestartDirectStdinProcess;
|
|
9078
|
-
if (!canRestartStalledProcess) return false;
|
|
9079
|
-
const staleForMs = ap.runtimeProgress.ageMs();
|
|
9080
|
-
if (staleForMs < RUNTIME_PROGRESS_STALE_MS && !ap.runtimeProgress.isStale) return false;
|
|
9655
|
+
if (!reduction.shouldTerminate) return false;
|
|
9656
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState);
|
|
9081
9657
|
const staleForMinutes = Math.max(1, Math.floor(staleForMs / 6e4));
|
|
9082
9658
|
ap.runtimeProgress.markStale();
|
|
9083
9659
|
const diagnostic = buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes);
|
|
@@ -9103,7 +9679,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9103
9679
|
...runtimeTraceCounterAttrs(ap),
|
|
9104
9680
|
...this.finalizeRuntimeProfileTurnControl(agentId, ap, "runtime_stalled")
|
|
9105
9681
|
});
|
|
9106
|
-
ap.expectedTerminationReason = "stalled_recovery";
|
|
9107
9682
|
const runtimeLabel = ap.driver.id === "opencode" ? "OpenCode" : ap.driver.id;
|
|
9108
9683
|
logger.warn(
|
|
9109
9684
|
`[Agent ${agentId}] ${runtimeLabel} process stalled for ${staleForMinutes}m with ${ap.inbox.length} queued message(s); terminating for restart`
|
|
@@ -9169,31 +9744,32 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9169
9744
|
this.sendRuntimeProfileReport(agentId);
|
|
9170
9745
|
break;
|
|
9171
9746
|
case "thinking": {
|
|
9172
|
-
if (ap) this.clearGatedInFlightBatch(agentId, ap, "non_error_progress");
|
|
9173
9747
|
this.completeCompactionIfActive(agentId, "Context compaction finished (inferred from resumed output)");
|
|
9174
9748
|
this.queueTrajectoryText(agentId, "thinking", event.text);
|
|
9175
|
-
if (ap)
|
|
9176
|
-
|
|
9749
|
+
if (ap) {
|
|
9750
|
+
const reduction = reduceApmGatedAssistantContinuation(ap.gatedSteering);
|
|
9751
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "thinking" });
|
|
9752
|
+
}
|
|
9177
9753
|
break;
|
|
9178
9754
|
}
|
|
9179
9755
|
case "text": {
|
|
9180
|
-
if (ap) this.clearGatedInFlightBatch(agentId, ap, "non_error_progress");
|
|
9181
9756
|
this.completeCompactionIfActive(agentId, "Context compaction finished (inferred from resumed output)");
|
|
9182
9757
|
this.queueTrajectoryText(agentId, "text", event.text);
|
|
9183
|
-
if (ap)
|
|
9184
|
-
|
|
9758
|
+
if (ap) {
|
|
9759
|
+
const reduction = reduceApmGatedAssistantContinuation(ap.gatedSteering);
|
|
9760
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "text" });
|
|
9761
|
+
}
|
|
9185
9762
|
break;
|
|
9186
9763
|
}
|
|
9187
9764
|
case "tool_call": {
|
|
9188
|
-
if (ap) this.clearGatedInFlightBatch(agentId, ap, "non_error_progress");
|
|
9189
9765
|
this.completeCompactionIfActive(agentId, "Context compaction finished (inferred from resumed tool use)");
|
|
9190
9766
|
this.flushPendingTrajectory(agentId);
|
|
9191
9767
|
const invocation = normalizeToolDisplayInvocation(event.name, event.input);
|
|
9192
9768
|
if (ap) {
|
|
9193
|
-
ap.gatedSteering
|
|
9769
|
+
const reduction = reduceApmGatedToolUse(ap.gatedSteering, { kind: "tool_call" });
|
|
9194
9770
|
this.noteRuntimeProfileToolCall(agentId, ap, invocation.toolName);
|
|
9195
9771
|
this.recordRuntimeTraceEvent(agentId, ap, "tool.call.started", { tool: invocation.toolName });
|
|
9196
|
-
this.
|
|
9772
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, {
|
|
9197
9773
|
event: "tool_call",
|
|
9198
9774
|
tool: invocation.toolName
|
|
9199
9775
|
});
|
|
@@ -9205,23 +9781,20 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9205
9781
|
toolName: invocation.toolName,
|
|
9206
9782
|
toolInput: inputSummary
|
|
9207
9783
|
}]);
|
|
9208
|
-
if (ap) ap.isIdle = false;
|
|
9209
9784
|
break;
|
|
9210
9785
|
}
|
|
9211
9786
|
case "tool_output": {
|
|
9212
9787
|
const invocation = normalizeToolDisplayInvocation(event.name, {});
|
|
9213
9788
|
if (ap) {
|
|
9214
|
-
const
|
|
9215
|
-
ap.gatedSteering.outstandingToolUses = Math.max(0, ap.gatedSteering.outstandingToolUses - 1);
|
|
9789
|
+
const reduction = reduceApmGatedToolUse(ap.gatedSteering, { kind: "tool_output" });
|
|
9216
9790
|
this.recordRuntimeTraceEvent(agentId, ap, "tool.output.observed", { tool: invocation.toolName });
|
|
9217
9791
|
this.recordRuntimeTraceEvent(agentId, ap, "runtime.continuation.expected");
|
|
9218
|
-
this.
|
|
9792
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, {
|
|
9219
9793
|
event: "tool_output",
|
|
9220
9794
|
tool: invocation.toolName
|
|
9221
9795
|
});
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
this.tryFlushGatedSteering(agentId, ap, "tool_batch_complete");
|
|
9796
|
+
if (reduction.shouldFlushToolBatch) {
|
|
9797
|
+
this.notifyGatedSteeringBoundary(agentId, ap, "tool_batch_complete");
|
|
9225
9798
|
}
|
|
9226
9799
|
}
|
|
9227
9800
|
break;
|
|
@@ -9232,9 +9805,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9232
9805
|
if (ap) this.startCompactionWatchdog(agentId, ap);
|
|
9233
9806
|
this.broadcastActivity(agentId, "working", "Compacting context", [{ kind: "compaction_started" }]);
|
|
9234
9807
|
if (ap) {
|
|
9235
|
-
ap.gatedSteering
|
|
9236
|
-
this.
|
|
9237
|
-
ap.isIdle = false;
|
|
9808
|
+
const reduction = reduceApmGatedCompaction(ap.gatedSteering, { kind: "compaction_started" });
|
|
9809
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "compaction_started" });
|
|
9238
9810
|
}
|
|
9239
9811
|
break;
|
|
9240
9812
|
case "compaction_finished":
|
|
@@ -9243,10 +9815,9 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9243
9815
|
if (ap) this.clearCompactionWatchdog(ap);
|
|
9244
9816
|
this.broadcastActivity(agentId, "working", "Context compaction finished", [{ kind: "compaction_finished" }]);
|
|
9245
9817
|
if (ap) {
|
|
9246
|
-
ap.gatedSteering
|
|
9247
|
-
this.
|
|
9818
|
+
const reduction = reduceApmGatedCompaction(ap.gatedSteering, { kind: "compaction_finished" });
|
|
9819
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "compaction_finished" });
|
|
9248
9820
|
this.flushCompactionBoundaryMessages(agentId, ap);
|
|
9249
|
-
ap.isIdle = false;
|
|
9250
9821
|
}
|
|
9251
9822
|
break;
|
|
9252
9823
|
case "turn_end":
|
|
@@ -9256,28 +9827,21 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9256
9827
|
});
|
|
9257
9828
|
this.flushPendingTrajectory(agentId);
|
|
9258
9829
|
if (ap) {
|
|
9259
|
-
this.clearGatedInFlightBatch(agentId, ap, "turn_end");
|
|
9260
9830
|
if (event.sessionId) ap.sessionId = event.sessionId;
|
|
9261
|
-
ap.gatedSteering
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
});
|
|
9273
|
-
}
|
|
9274
|
-
this.broadcastActivity(agentId, "working", "Message received");
|
|
9275
|
-
if (!this.deliverMessagesViaStdin(agentId, ap, nextMessages, "idle")) {
|
|
9276
|
-
ap.isIdle = true;
|
|
9831
|
+
const reduction = reduceApmGatedTurnEnd(ap.gatedSteering, {
|
|
9832
|
+
inboxLength: ap.inbox.length,
|
|
9833
|
+
supportsStdinNotification: ap.driver.supportsStdinNotification,
|
|
9834
|
+
hasSession: Boolean(ap.sessionId),
|
|
9835
|
+
terminateProcessOnTurnEnd: ap.driver.terminateProcessOnTurnEnd === true
|
|
9836
|
+
});
|
|
9837
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "turn_end" });
|
|
9838
|
+
const deliverStdinEffect = reduction.effects.find((effect) => effect.kind === "deliver_stdin");
|
|
9839
|
+
if (deliverStdinEffect) {
|
|
9840
|
+
if (!this.executeApmGatedSteeringEffect(agentId, ap, deliverStdinEffect)) {
|
|
9841
|
+
this.commitApmIdleState(agentId, ap, true);
|
|
9277
9842
|
this.broadcastActivity(agentId, "online", "Idle");
|
|
9278
9843
|
}
|
|
9279
9844
|
} else {
|
|
9280
|
-
ap.isIdle = true;
|
|
9281
9845
|
if (ap.lastRuntimeError) {
|
|
9282
9846
|
this.broadcastActivity(agentId, "error", ap.lastRuntimeError);
|
|
9283
9847
|
} else {
|
|
@@ -9290,7 +9854,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9290
9854
|
...this.finalizeRuntimeProfileTurnControl(agentId, ap, "turn_end")
|
|
9291
9855
|
});
|
|
9292
9856
|
if (ap.driver.terminateProcessOnTurnEnd) {
|
|
9293
|
-
ap.expectedTerminationReason = "turn_end";
|
|
9294
9857
|
logger.info(`[Agent ${agentId}] Turn completed; terminating ${ap.driver.id} process`);
|
|
9295
9858
|
try {
|
|
9296
9859
|
this.processExitTraceAttrs.set(ap.process, {
|
|
@@ -9319,10 +9882,14 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9319
9882
|
if (runtimeErrorDiagnostics.spanAttrs.runtime_error_action_required === true) {
|
|
9320
9883
|
visibleErrorMessage = formatRuntimeLoginRequiredMessage(ap.driver.id);
|
|
9321
9884
|
}
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9885
|
+
const shouldDisableToolBoundaryFlush = ap.driver.busyDeliveryMode === "gated" && this.isThinkingBlockMutationError(event.message);
|
|
9886
|
+
const terminalFailure = classifyTerminalFailure(ap);
|
|
9887
|
+
const reduction = reduceApmGatedError(ap.gatedSteering, {
|
|
9888
|
+
disableToolBoundaryFlush: shouldDisableToolBoundaryFlush,
|
|
9889
|
+
terminalWakeable: Boolean(ap.driver.supportsStdinNotification && terminalFailure && !terminalFailure.actionRequired)
|
|
9890
|
+
});
|
|
9891
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "error" });
|
|
9892
|
+
if (reduction.shouldDisableToolBoundaryFlush) {
|
|
9326
9893
|
this.recordGatedSteeringEvent(agentId, ap, "disabled", {
|
|
9327
9894
|
reason: "thinking_block_mutation_error",
|
|
9328
9895
|
lastFlushReason: ap.gatedSteering.lastFlushReason,
|
|
@@ -9341,7 +9908,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9341
9908
|
...runtimeTraceCounterAttrs(ap),
|
|
9342
9909
|
...this.finalizeRuntimeProfileTurnControl(agentId, ap, "runtime_error")
|
|
9343
9910
|
});
|
|
9344
|
-
const terminalFailure = classifyTerminalFailure(ap);
|
|
9345
9911
|
if (ap.driver.supportsStdinNotification && terminalFailure) {
|
|
9346
9912
|
if (terminalFailure.actionRequired) {
|
|
9347
9913
|
logger.warn(`[Agent ${agentId}] ${ap.driver.id} auth requires user action; terminating runtime process`);
|
|
@@ -9356,7 +9922,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9356
9922
|
logger.warn(`[Agent ${agentId}] Failed to terminate ${ap.driver.id} after auth error: ${reason}`);
|
|
9357
9923
|
}
|
|
9358
9924
|
} else {
|
|
9359
|
-
ap.isIdle = true;
|
|
9360
9925
|
ap.notifications.clear();
|
|
9361
9926
|
logger.info(`[Agent ${agentId}] Marked ${ap.driver.id} wakeable after terminal runtime error`);
|
|
9362
9927
|
}
|
|
@@ -9471,6 +10036,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9471
10036
|
return true;
|
|
9472
10037
|
} else {
|
|
9473
10038
|
ap.notifications.add(count);
|
|
10039
|
+
const retryScheduled = ap.driver.busyDeliveryMode === "direct" ? this.scheduleStdinNotification(agentId, ap, this.stdinNotificationRetryMs) : false;
|
|
9474
10040
|
this.recordDaemonTrace("daemon.agent.stdin_notification", {
|
|
9475
10041
|
agentId,
|
|
9476
10042
|
runtime: ap.config.runtime,
|
|
@@ -9479,6 +10045,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9479
10045
|
outcome: "encode_failed",
|
|
9480
10046
|
mode: "busy",
|
|
9481
10047
|
pending_notification_count: count,
|
|
10048
|
+
retry_scheduled: retryScheduled,
|
|
10049
|
+
notification_timer_present: ap.notifications.hasTimer,
|
|
9482
10050
|
inbox_count: inboxCount,
|
|
9483
10051
|
session_id_present: true
|
|
9484
10052
|
}, "error");
|
|
@@ -9507,7 +10075,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9507
10075
|
});
|
|
9508
10076
|
if (messages.length === 0) {
|
|
9509
10077
|
if (mode === "idle") {
|
|
9510
|
-
|
|
10078
|
+
this.commitApmIdleState(agentId, ap, true);
|
|
9511
10079
|
}
|
|
9512
10080
|
return true;
|
|
9513
10081
|
}
|
|
@@ -9549,7 +10117,7 @@ ${RESPONSE_TARGET_HINT}`);
|
|
|
9549
10117
|
if (!encoded) {
|
|
9550
10118
|
ap.inbox.unshift(...messages);
|
|
9551
10119
|
if (mode === "idle") {
|
|
9552
|
-
|
|
10120
|
+
this.commitApmIdleState(agentId, ap, true);
|
|
9553
10121
|
}
|
|
9554
10122
|
logger.warn(
|
|
9555
10123
|
`[Agent ${agentId}] Failed to encode ${mode} stdin delivery; re-queued ${messages.length === 1 ? "message" : `${messages.length} messages`}`
|
|
@@ -9901,7 +10469,7 @@ var ReminderCache = class {
|
|
|
9901
10469
|
};
|
|
9902
10470
|
|
|
9903
10471
|
// src/machineLock.ts
|
|
9904
|
-
import { createHash as
|
|
10472
|
+
import { createHash as createHash4, randomUUID as randomUUID3 } from "crypto";
|
|
9905
10473
|
import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, rmSync as rmSync3, statSync as statSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
9906
10474
|
import os6 from "os";
|
|
9907
10475
|
import path13 from "path";
|
|
@@ -9917,7 +10485,7 @@ var DaemonMachineLockConflictError = class extends Error {
|
|
|
9917
10485
|
}
|
|
9918
10486
|
};
|
|
9919
10487
|
function apiKeyFingerprint(apiKey) {
|
|
9920
|
-
return
|
|
10488
|
+
return createHash4("sha256").update(apiKey).digest("hex");
|
|
9921
10489
|
}
|
|
9922
10490
|
function getDaemonMachineLockId(apiKey) {
|
|
9923
10491
|
return `machine-${apiKeyFingerprint(apiKey).slice(0, 16)}`;
|
|
@@ -10180,7 +10748,7 @@ function isDiagnosticErrorAttr(key) {
|
|
|
10180
10748
|
}
|
|
10181
10749
|
|
|
10182
10750
|
// src/traceBundleUpload.ts
|
|
10183
|
-
import { createHash as
|
|
10751
|
+
import { createHash as createHash6, randomUUID as randomUUID4 } from "crypto";
|
|
10184
10752
|
import { gzipSync } from "zlib";
|
|
10185
10753
|
import { mkdir as mkdir2, readFile as readFile2, readdir as readdir3, stat as stat3, writeFile as writeFile2 } from "fs/promises";
|
|
10186
10754
|
import path15 from "path";
|
|
@@ -10310,12 +10878,12 @@ async function uploadWithSignedCapability({
|
|
|
10310
10878
|
}
|
|
10311
10879
|
|
|
10312
10880
|
// src/traceJitter.ts
|
|
10313
|
-
import { createHash as
|
|
10881
|
+
import { createHash as createHash5 } from "crypto";
|
|
10314
10882
|
var INITIAL_UPLOAD_DELAY_SPAN_MS = 3e4;
|
|
10315
10883
|
var UPLOAD_INTERVAL_JITTER_SPAN_MS = 6e4;
|
|
10316
10884
|
var MAX_FILE_AGE_JITTER_SPAN_MS = 6e4;
|
|
10317
10885
|
function computeTraceJitter(lockId) {
|
|
10318
|
-
const seed =
|
|
10886
|
+
const seed = createHash5("sha256").update(lockId).digest();
|
|
10319
10887
|
return {
|
|
10320
10888
|
initialUploadDelayMs: seed.readUInt32BE(0) % INITIAL_UPLOAD_DELAY_SPAN_MS,
|
|
10321
10889
|
uploadIntervalJitterMs: seed.readUInt32BE(4) % UPLOAD_INTERVAL_JITTER_SPAN_MS,
|
|
@@ -10516,7 +11084,7 @@ var DaemonTraceBundleUploader = class {
|
|
|
10516
11084
|
}
|
|
10517
11085
|
};
|
|
10518
11086
|
function sha256Hex(body) {
|
|
10519
|
-
return
|
|
11087
|
+
return createHash6("sha256").update(body).digest("hex");
|
|
10520
11088
|
}
|
|
10521
11089
|
function readPositiveIntegerEnv2(name, fallback) {
|
|
10522
11090
|
const value = process.env[name];
|