acpx 0.7.0 → 0.9.0

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.
Files changed (50) hide show
  1. package/README.md +14 -6
  2. package/dist/{cli-T-Z-9x6a.js → cli-Bf3yjqzE.js} +35 -10
  3. package/dist/cli-Bf3yjqzE.js.map +1 -0
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +724 -241
  7. package/dist/cli.js.map +1 -1
  8. package/dist/{client-COPilhO_.d.ts → client-BssohYqM.d.ts} +35 -4
  9. package/dist/client-BssohYqM.d.ts.map +1 -0
  10. package/dist/flags-C-rwARqg.js +260 -0
  11. package/dist/flags-C-rwARqg.js.map +1 -0
  12. package/dist/{flows-CF8w1rPI.js → flows-WLs26_5Y.js} +405 -337
  13. package/dist/flows-WLs26_5Y.js.map +1 -0
  14. package/dist/flows.d.ts +23 -2
  15. package/dist/flows.d.ts.map +1 -1
  16. package/dist/flows.js +1 -1
  17. package/dist/{prompt-turn-CVPMWdj1.js → live-checkpoint-D5d-K9s1.js} +2487 -609
  18. package/dist/live-checkpoint-D5d-K9s1.js.map +1 -0
  19. package/dist/output-DPg20dvn.js +4146 -0
  20. package/dist/output-DPg20dvn.js.map +1 -0
  21. package/dist/runtime.d.ts +56 -4
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +676 -393
  24. package/dist/runtime.js.map +1 -1
  25. package/dist/{types-CVBeQyi3.d.ts → session-options-CFudjdkU.d.ts} +62 -3
  26. package/dist/session-options-CFudjdkU.d.ts.map +1 -0
  27. package/package.json +30 -25
  28. package/skills/acpx/SKILL.md +211 -13
  29. package/dist/cli-T-Z-9x6a.js.map +0 -1
  30. package/dist/client-COPilhO_.d.ts.map +0 -1
  31. package/dist/flags-Dj-IXgo9.js +0 -163
  32. package/dist/flags-Dj-IXgo9.js.map +0 -1
  33. package/dist/flows-CF8w1rPI.js.map +0 -1
  34. package/dist/ipc-ABXlXzGP.js +0 -1290
  35. package/dist/ipc-ABXlXzGP.js.map +0 -1
  36. package/dist/jsonrpc-DSxh2w5R.js +0 -68
  37. package/dist/jsonrpc-DSxh2w5R.js.map +0 -1
  38. package/dist/output-DmHvT8vm.js +0 -807
  39. package/dist/output-DmHvT8vm.js.map +0 -1
  40. package/dist/perf-metrics-C2pXfxvR.js +0 -598
  41. package/dist/perf-metrics-C2pXfxvR.js.map +0 -1
  42. package/dist/prompt-turn-CVPMWdj1.js.map +0 -1
  43. package/dist/render-N5YwotCy.js +0 -172
  44. package/dist/render-N5YwotCy.js.map +0 -1
  45. package/dist/rolldown-runtime-CiIaOW0V.js +0 -13
  46. package/dist/session-CDaQe6BH.js +0 -1538
  47. package/dist/session-CDaQe6BH.js.map +0 -1
  48. package/dist/session-options-pCbHn_n7.d.ts +0 -13
  49. package/dist/session-options-pCbHn_n7.d.ts.map +0 -1
  50. package/dist/types-CVBeQyi3.d.ts.map +0 -1
@@ -1,1290 +0,0 @@
1
- import { H as QueueConnectionError, O as OUTPUT_ERROR_CODES, U as QueueProtocolError, a as recordPerfDuration, f as isPromptInput, g as textPrompt, i as measurePerf, k as OUTPUT_ERROR_ORIGINS, r as incrementPerfCounter, w as toAcpErrorPayload, x as normalizeOutputError } from "./perf-metrics-C2pXfxvR.js";
2
- import { n as isAcpJsonRpcMessage } from "./jsonrpc-DSxh2w5R.js";
3
- import path from "node:path";
4
- import fs from "node:fs/promises";
5
- import os from "node:os";
6
- import { createHash, randomInt, randomUUID } from "node:crypto";
7
- import net from "node:net";
8
- //#region src/cli/queue/paths.ts
9
- function shortHash(value, length) {
10
- return createHash("sha256").update(value).digest("hex").slice(0, length);
11
- }
12
- function queueKeyForSession(sessionId) {
13
- return shortHash(sessionId, 24);
14
- }
15
- function queueBaseDir(homeDir = os.homedir()) {
16
- return path.join(homeDir, ".acpx", "queues");
17
- }
18
- function queueSocketBaseDir(homeDir = os.homedir()) {
19
- if (process.platform === "win32") return;
20
- return path.join("/tmp", `acpx-${shortHash(homeDir, 10)}`);
21
- }
22
- function queueLockFilePath(sessionId, homeDir = os.homedir()) {
23
- return path.join(queueBaseDir(homeDir), `${queueKeyForSession(sessionId)}.lock`);
24
- }
25
- function queueSocketPath(sessionId, homeDir = os.homedir()) {
26
- const key = queueKeyForSession(sessionId);
27
- if (process.platform === "win32") return `\\\\.\\pipe\\acpx-${key}`;
28
- return path.join(queueSocketBaseDir(homeDir) ?? "/tmp", `${key}.sock`);
29
- }
30
- //#endregion
31
- //#region src/cli/queue/lease-store.ts
32
- const PROCESS_EXIT_GRACE_MS = 1500;
33
- const PROCESS_POLL_MS = 50;
34
- const QUEUE_OWNER_STALE_HEARTBEAT_MS = 15e3;
35
- function parseQueueOwnerRecord(raw) {
36
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
37
- const record = raw;
38
- if (!Number.isInteger(record.pid) || record.pid <= 0 || typeof record.sessionId !== "string" || typeof record.socketPath !== "string" || typeof record.createdAt !== "string" || typeof record.heartbeatAt !== "string" || !Number.isInteger(record.ownerGeneration) || record.ownerGeneration <= 0 || !Number.isInteger(record.queueDepth) || record.queueDepth < 0) return null;
39
- return {
40
- pid: record.pid,
41
- sessionId: record.sessionId,
42
- socketPath: record.socketPath,
43
- createdAt: record.createdAt,
44
- heartbeatAt: record.heartbeatAt,
45
- ownerGeneration: record.ownerGeneration,
46
- queueDepth: record.queueDepth
47
- };
48
- }
49
- function createOwnerGeneration() {
50
- return randomInt(1, 2 ** 48);
51
- }
52
- function nowIso() {
53
- return (/* @__PURE__ */ new Date()).toISOString();
54
- }
55
- function isQueueOwnerHeartbeatStale(owner) {
56
- const heartbeatMs = Date.parse(owner.heartbeatAt);
57
- if (!Number.isFinite(heartbeatMs)) return true;
58
- return Date.now() - heartbeatMs > QUEUE_OWNER_STALE_HEARTBEAT_MS;
59
- }
60
- async function ensureQueueDir() {
61
- const baseDir = queueBaseDir();
62
- await fs.mkdir(baseDir, {
63
- recursive: true,
64
- mode: 448
65
- });
66
- await fs.chmod(baseDir, 448);
67
- const socketDir = queueSocketBaseDir();
68
- if (socketDir) {
69
- await fs.mkdir(socketDir, {
70
- recursive: true,
71
- mode: 448
72
- });
73
- await fs.chmod(socketDir, 448);
74
- }
75
- }
76
- async function removeSocketFile(socketPath) {
77
- if (process.platform === "win32") return;
78
- try {
79
- await fs.unlink(socketPath);
80
- } catch (error) {
81
- if (error.code !== "ENOENT") throw error;
82
- }
83
- }
84
- async function waitForProcessExit(pid, timeoutMs) {
85
- const deadline = Date.now() + Math.max(0, timeoutMs);
86
- while (Date.now() <= deadline) {
87
- if (!isProcessAlive(pid)) return true;
88
- await waitMs(PROCESS_POLL_MS);
89
- }
90
- return !isProcessAlive(pid);
91
- }
92
- async function cleanupStaleQueueOwner(sessionId, owner) {
93
- const lockPath = queueLockFilePath(sessionId);
94
- await removeSocketFile(owner?.socketPath ?? queueSocketPath(sessionId)).catch(() => {});
95
- await fs.unlink(lockPath).catch((error) => {
96
- if (error.code !== "ENOENT") throw error;
97
- });
98
- }
99
- async function readQueueOwnerRecord(sessionId) {
100
- const lockPath = queueLockFilePath(sessionId);
101
- try {
102
- const payload = await fs.readFile(lockPath, "utf8");
103
- return parseQueueOwnerRecord(JSON.parse(payload)) ?? void 0;
104
- } catch {
105
- return;
106
- }
107
- }
108
- function isProcessAlive(pid) {
109
- if (!pid || !Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
110
- try {
111
- process.kill(pid, 0);
112
- return true;
113
- } catch {
114
- return false;
115
- }
116
- }
117
- async function terminateProcess(pid) {
118
- if (!isProcessAlive(pid)) return false;
119
- try {
120
- process.kill(pid, "SIGTERM");
121
- } catch {
122
- return false;
123
- }
124
- if (await waitForProcessExit(pid, PROCESS_EXIT_GRACE_MS)) return true;
125
- try {
126
- process.kill(pid, "SIGKILL");
127
- } catch {
128
- return false;
129
- }
130
- await waitForProcessExit(pid, PROCESS_EXIT_GRACE_MS);
131
- return true;
132
- }
133
- async function ensureOwnerIsUsable(sessionId, owner) {
134
- const alive = isProcessAlive(owner.pid);
135
- const stale = isQueueOwnerHeartbeatStale(owner);
136
- if (alive && !stale) return true;
137
- if (alive) await terminateProcess(owner.pid).catch(() => {});
138
- await cleanupStaleQueueOwner(sessionId, owner);
139
- return false;
140
- }
141
- async function readQueueOwnerStatus(sessionId) {
142
- const owner = await readQueueOwnerRecord(sessionId);
143
- if (!owner) return;
144
- const alive = await ensureOwnerIsUsable(sessionId, owner);
145
- if (!alive) return;
146
- return {
147
- pid: owner.pid,
148
- socketPath: owner.socketPath,
149
- heartbeatAt: owner.heartbeatAt,
150
- ownerGeneration: owner.ownerGeneration,
151
- queueDepth: owner.queueDepth,
152
- alive,
153
- stale: isQueueOwnerHeartbeatStale(owner)
154
- };
155
- }
156
- async function tryAcquireQueueOwnerLease(sessionId, nowIsoFactory = nowIso) {
157
- await ensureQueueDir();
158
- const lockPath = queueLockFilePath(sessionId);
159
- const socketPath = queueSocketPath(sessionId);
160
- const createdAt = nowIsoFactory();
161
- const ownerGeneration = createOwnerGeneration();
162
- const payload = JSON.stringify({
163
- pid: process.pid,
164
- sessionId,
165
- socketPath,
166
- createdAt,
167
- heartbeatAt: createdAt,
168
- ownerGeneration,
169
- queueDepth: 0
170
- }, null, 2);
171
- try {
172
- await fs.writeFile(lockPath, `${payload}\n`, {
173
- encoding: "utf8",
174
- flag: "wx"
175
- });
176
- await removeSocketFile(socketPath).catch(() => {});
177
- return {
178
- sessionId,
179
- lockPath,
180
- socketPath,
181
- createdAt,
182
- ownerGeneration
183
- };
184
- } catch (error) {
185
- if (error.code !== "EEXIST") throw error;
186
- const owner = await readQueueOwnerRecord(sessionId);
187
- if (!owner) {
188
- await cleanupStaleQueueOwner(sessionId, owner);
189
- return;
190
- }
191
- if (!isProcessAlive(owner.pid) || isQueueOwnerHeartbeatStale(owner)) {
192
- if (isProcessAlive(owner.pid)) await terminateProcess(owner.pid).catch(() => {});
193
- await cleanupStaleQueueOwner(sessionId, owner);
194
- }
195
- return;
196
- }
197
- }
198
- async function refreshQueueOwnerLease(lease, options, nowIsoFactory = nowIso) {
199
- const payload = JSON.stringify({
200
- pid: process.pid,
201
- sessionId: lease.sessionId,
202
- socketPath: lease.socketPath,
203
- createdAt: lease.createdAt,
204
- heartbeatAt: nowIsoFactory(),
205
- ownerGeneration: lease.ownerGeneration,
206
- queueDepth: Math.max(0, Math.round(options.queueDepth))
207
- }, null, 2);
208
- await fs.writeFile(lease.lockPath, `${payload}\n`, { encoding: "utf8" });
209
- }
210
- async function releaseQueueOwnerLease(lease) {
211
- await removeSocketFile(lease.socketPath).catch(() => {});
212
- await fs.unlink(lease.lockPath).catch((error) => {
213
- if (error.code !== "ENOENT") throw error;
214
- });
215
- }
216
- async function terminateQueueOwnerForSession(sessionId) {
217
- const owner = await readQueueOwnerRecord(sessionId);
218
- if (!owner) return;
219
- if (isProcessAlive(owner.pid)) await terminateProcess(owner.pid);
220
- await cleanupStaleQueueOwner(sessionId, owner);
221
- }
222
- async function waitMs(ms) {
223
- await new Promise((resolve) => {
224
- setTimeout(resolve, ms);
225
- });
226
- }
227
- //#endregion
228
- //#region src/cli/queue/ipc-transport.ts
229
- const QUEUE_CONNECT_ATTEMPTS = 40;
230
- const SOCKET_CONNECTION_TIMEOUT_MS = 5e3;
231
- function shouldRetryQueueConnect(error) {
232
- const code = error.code;
233
- return code === "ENOENT" || code === "ECONNREFUSED";
234
- }
235
- async function connectToSocket(socketPath, timeoutMs = SOCKET_CONNECTION_TIMEOUT_MS) {
236
- return await new Promise((resolve, reject) => {
237
- const socket = net.createConnection(socketPath);
238
- let settled = false;
239
- const timeout = setTimeout(() => {
240
- if (settled) return;
241
- settled = true;
242
- socket.destroy();
243
- reject(/* @__PURE__ */ new Error(`Connection to ${socketPath} timed out after ${timeoutMs}ms`));
244
- }, timeoutMs);
245
- const onConnect = () => {
246
- if (settled) return;
247
- settled = true;
248
- clearTimeout(timeout);
249
- socket.off("error", onError);
250
- resolve(socket);
251
- };
252
- const onError = (error) => {
253
- if (settled) return;
254
- settled = true;
255
- clearTimeout(timeout);
256
- socket.off("connect", onConnect);
257
- reject(error);
258
- };
259
- socket.once("connect", onConnect);
260
- socket.once("error", onError);
261
- });
262
- }
263
- async function connectToQueueOwner(owner, maxAttempts = QUEUE_CONNECT_ATTEMPTS) {
264
- let lastError;
265
- const attempts = Math.max(1, Math.trunc(maxAttempts));
266
- for (let attempt = 0; attempt < attempts; attempt += 1) try {
267
- return await measurePerf("queue.connect", async () => await connectToSocket(owner.socketPath));
268
- } catch (error) {
269
- lastError = error;
270
- if (!shouldRetryQueueConnect(error)) throw error;
271
- await waitMs(50);
272
- }
273
- if (lastError && !shouldRetryQueueConnect(lastError)) throw lastError;
274
- }
275
- //#endregion
276
- //#region src/cli/queue/ipc-health.ts
277
- async function probeQueueOwnerHealth(sessionId) {
278
- const ownerRecord = await readQueueOwnerRecord(sessionId);
279
- if (!ownerRecord) return {
280
- sessionId,
281
- hasLease: false,
282
- healthy: false,
283
- socketReachable: false,
284
- pidAlive: false
285
- };
286
- const owner = await readQueueOwnerStatus(sessionId);
287
- if (!owner) return {
288
- sessionId,
289
- hasLease: false,
290
- healthy: false,
291
- socketReachable: false,
292
- pidAlive: false
293
- };
294
- const pidAlive = owner.alive;
295
- let socketReachable = false;
296
- try {
297
- const socket = await connectToQueueOwner(ownerRecord, 2);
298
- if (socket) {
299
- socketReachable = true;
300
- if (!socket.destroyed) socket.end();
301
- }
302
- } catch {
303
- socketReachable = false;
304
- }
305
- return {
306
- sessionId,
307
- hasLease: true,
308
- healthy: socketReachable,
309
- socketReachable,
310
- pidAlive,
311
- pid: owner.pid,
312
- socketPath: owner.socketPath,
313
- ownerGeneration: owner.ownerGeneration,
314
- queueDepth: owner.queueDepth
315
- };
316
- }
317
- //#endregion
318
- //#region src/cli/queue/messages.ts
319
- function asRecord(value) {
320
- if (!value || typeof value !== "object" || Array.isArray(value)) return;
321
- return value;
322
- }
323
- function isPermissionMode(value) {
324
- return value === "approve-all" || value === "approve-reads" || value === "deny-all";
325
- }
326
- function isSessionResumePolicy(value) {
327
- return value === "allow-new" || value === "same-session-only";
328
- }
329
- function isNonInteractivePermissionPolicy(value) {
330
- return value === "deny" || value === "fail";
331
- }
332
- function isOutputErrorCode(value) {
333
- return typeof value === "string" && OUTPUT_ERROR_CODES.includes(value);
334
- }
335
- function isOutputErrorOrigin(value) {
336
- return typeof value === "string" && OUTPUT_ERROR_ORIGINS.includes(value);
337
- }
338
- function parseSessionOptions(value) {
339
- if (value == null) return;
340
- const record = asRecord(value);
341
- if (!record) return null;
342
- const sessionOptions = {};
343
- if (record.model != null) {
344
- if (typeof record.model !== "string" || record.model.trim().length === 0) return null;
345
- sessionOptions.model = record.model;
346
- }
347
- if (record.allowedTools != null) {
348
- if (!Array.isArray(record.allowedTools)) return null;
349
- const allowedTools = record.allowedTools.filter((tool) => typeof tool === "string");
350
- if (allowedTools.length !== record.allowedTools.length) return null;
351
- sessionOptions.allowedTools = allowedTools;
352
- }
353
- if (record.maxTurns != null) {
354
- if (typeof record.maxTurns !== "number" || !Number.isFinite(record.maxTurns)) return null;
355
- sessionOptions.maxTurns = Math.max(1, Math.round(record.maxTurns));
356
- }
357
- if (record.systemPrompt != null) if (typeof record.systemPrompt === "string") sessionOptions.systemPrompt = record.systemPrompt;
358
- else {
359
- const systemPrompt = asRecord(record.systemPrompt);
360
- if (!systemPrompt || typeof systemPrompt.append !== "string") return null;
361
- sessionOptions.systemPrompt = { append: systemPrompt.append };
362
- }
363
- return sessionOptions;
364
- }
365
- function parseOwnerGeneration(value) {
366
- if (value == null) return;
367
- if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) return null;
368
- return value;
369
- }
370
- function parseQueueRequest(raw) {
371
- const request = asRecord(raw);
372
- if (!request) return null;
373
- if (typeof request.type !== "string" || typeof request.requestId !== "string") return null;
374
- const ownerGeneration = parseOwnerGeneration(request.ownerGeneration);
375
- if (ownerGeneration === null) return null;
376
- const timeoutRaw = request.timeoutMs;
377
- const timeoutMs = typeof timeoutRaw === "number" && Number.isFinite(timeoutRaw) && timeoutRaw > 0 ? Math.round(timeoutRaw) : void 0;
378
- if (request.type === "submit_prompt") {
379
- const resumePolicy = request.resumePolicy == null ? void 0 : isSessionResumePolicy(request.resumePolicy) ? request.resumePolicy : null;
380
- const nonInteractivePermissions = request.nonInteractivePermissions == null ? void 0 : isNonInteractivePermissionPolicy(request.nonInteractivePermissions) ? request.nonInteractivePermissions : null;
381
- const suppressSdkConsoleErrors = request.suppressSdkConsoleErrors == null ? void 0 : typeof request.suppressSdkConsoleErrors === "boolean" ? request.suppressSdkConsoleErrors : null;
382
- const sessionOptions = parseSessionOptions(request.sessionOptions);
383
- const prompt = request.prompt == null ? void 0 : isPromptInput(request.prompt) ? request.prompt : null;
384
- if (typeof request.message !== "string" || !isPermissionMode(request.permissionMode) || resumePolicy === null || prompt === null || nonInteractivePermissions === null || suppressSdkConsoleErrors === null || sessionOptions === null || typeof request.waitForCompletion !== "boolean") return null;
385
- return {
386
- type: "submit_prompt",
387
- requestId: request.requestId,
388
- ownerGeneration,
389
- message: request.message,
390
- prompt: prompt ?? textPrompt(request.message),
391
- permissionMode: request.permissionMode,
392
- ...resumePolicy !== void 0 ? { resumePolicy } : {},
393
- nonInteractivePermissions,
394
- timeoutMs,
395
- ...suppressSdkConsoleErrors !== void 0 ? { suppressSdkConsoleErrors } : {},
396
- waitForCompletion: request.waitForCompletion,
397
- ...sessionOptions !== void 0 ? { sessionOptions } : {}
398
- };
399
- }
400
- if (request.type === "cancel_prompt") return {
401
- type: "cancel_prompt",
402
- requestId: request.requestId,
403
- ownerGeneration
404
- };
405
- if (request.type === "close_session") return {
406
- type: "close_session",
407
- requestId: request.requestId,
408
- ownerGeneration,
409
- timeoutMs
410
- };
411
- if (request.type === "set_mode") {
412
- if (typeof request.modeId !== "string" || request.modeId.trim().length === 0) return null;
413
- return {
414
- type: "set_mode",
415
- requestId: request.requestId,
416
- ownerGeneration,
417
- modeId: request.modeId,
418
- timeoutMs
419
- };
420
- }
421
- if (request.type === "set_model") {
422
- if (typeof request.modelId !== "string" || request.modelId.trim().length === 0) return null;
423
- return {
424
- type: "set_model",
425
- requestId: request.requestId,
426
- ownerGeneration,
427
- modelId: request.modelId,
428
- timeoutMs
429
- };
430
- }
431
- if (request.type === "set_config_option") {
432
- if (typeof request.configId !== "string" || request.configId.trim().length === 0 || typeof request.value !== "string" || request.value.trim().length === 0) return null;
433
- return {
434
- type: "set_config_option",
435
- requestId: request.requestId,
436
- ownerGeneration,
437
- configId: request.configId,
438
- value: request.value,
439
- timeoutMs
440
- };
441
- }
442
- return null;
443
- }
444
- function parseSessionSendResult(raw) {
445
- const result = asRecord(raw);
446
- if (!result) return null;
447
- if (typeof result.stopReason !== "string" || typeof result.sessionId !== "string" || typeof result.resumed !== "boolean") return null;
448
- const permissionStats = asRecord(result.permissionStats);
449
- const record = asRecord(result.record);
450
- if (!permissionStats || !record) return null;
451
- if (!(typeof permissionStats.requested === "number" && typeof permissionStats.approved === "number" && typeof permissionStats.denied === "number" && typeof permissionStats.cancelled === "number")) return null;
452
- if (!(typeof record.acpxRecordId === "string" && typeof record.acpSessionId === "string" && typeof record.agentCommand === "string" && typeof record.cwd === "string" && typeof record.createdAt === "string" && typeof record.lastUsedAt === "string" && Array.isArray(record.messages) && typeof record.updated_at === "string" && typeof record.lastSeq === "number" && Number.isInteger(record.lastSeq) && !!record.eventLog && typeof record.eventLog === "object")) return null;
453
- return result;
454
- }
455
- function parseQueueOwnerMessage(raw) {
456
- const message = asRecord(raw);
457
- if (!message || typeof message.type !== "string") return null;
458
- if (typeof message.requestId !== "string") return null;
459
- const ownerGeneration = parseOwnerGeneration(message.ownerGeneration);
460
- if (ownerGeneration === null) return null;
461
- if (message.type === "accepted") return {
462
- type: "accepted",
463
- requestId: message.requestId,
464
- ownerGeneration
465
- };
466
- if (message.type === "event") {
467
- if (!isAcpJsonRpcMessage(message.message)) return null;
468
- return {
469
- type: "event",
470
- requestId: message.requestId,
471
- ownerGeneration,
472
- message: message.message
473
- };
474
- }
475
- if (message.type === "result") {
476
- const parsedResult = parseSessionSendResult(message.result);
477
- if (!parsedResult) return null;
478
- return {
479
- type: "result",
480
- requestId: message.requestId,
481
- ownerGeneration,
482
- result: parsedResult
483
- };
484
- }
485
- if (message.type === "cancel_result") {
486
- if (typeof message.cancelled !== "boolean") return null;
487
- return {
488
- type: "cancel_result",
489
- requestId: message.requestId,
490
- ownerGeneration,
491
- cancelled: message.cancelled
492
- };
493
- }
494
- if (message.type === "set_mode_result") {
495
- if (typeof message.modeId !== "string") return null;
496
- return {
497
- type: "set_mode_result",
498
- requestId: message.requestId,
499
- ownerGeneration,
500
- modeId: message.modeId
501
- };
502
- }
503
- if (message.type === "set_model_result") {
504
- if (typeof message.modelId !== "string") return null;
505
- return {
506
- type: "set_model_result",
507
- requestId: message.requestId,
508
- ownerGeneration,
509
- modelId: message.modelId
510
- };
511
- }
512
- if (message.type === "set_config_option_result") {
513
- const response = asRecord(message.response);
514
- if (!response || !Array.isArray(response.configOptions)) return null;
515
- return {
516
- type: "set_config_option_result",
517
- requestId: message.requestId,
518
- ownerGeneration,
519
- response
520
- };
521
- }
522
- if (message.type === "error") {
523
- if (typeof message.message !== "string" || !isOutputErrorCode(message.code) || !isOutputErrorOrigin(message.origin)) return null;
524
- const detailCode = typeof message.detailCode === "string" && message.detailCode.trim().length > 0 ? message.detailCode : void 0;
525
- const retryable = typeof message.retryable === "boolean" ? message.retryable : void 0;
526
- const acp = toAcpErrorPayload(message.acp);
527
- const outputAlreadyEmitted = typeof message.outputAlreadyEmitted === "boolean" ? message.outputAlreadyEmitted : void 0;
528
- return {
529
- type: "error",
530
- requestId: message.requestId,
531
- ownerGeneration,
532
- code: message.code,
533
- detailCode,
534
- origin: message.origin,
535
- message: message.message,
536
- retryable,
537
- acp,
538
- ...outputAlreadyEmitted === void 0 ? {} : { outputAlreadyEmitted }
539
- };
540
- }
541
- return null;
542
- }
543
- //#endregion
544
- //#region src/cli/queue/ipc-server.ts
545
- function makeQueueOwnerError(requestId, message, detailCode, options = {}) {
546
- return {
547
- type: "error",
548
- requestId,
549
- ownerGeneration: void 0,
550
- code: "RUNTIME",
551
- detailCode,
552
- origin: "queue",
553
- retryable: options.retryable,
554
- message
555
- };
556
- }
557
- function makeQueueOwnerErrorFromUnknown(requestId, error, detailCode, options = {}) {
558
- const normalized = normalizeOutputError(error, {
559
- defaultCode: "RUNTIME",
560
- origin: "queue",
561
- detailCode,
562
- retryable: options.retryable
563
- });
564
- return {
565
- type: "error",
566
- requestId,
567
- code: normalized.code,
568
- detailCode: normalized.detailCode,
569
- origin: normalized.origin,
570
- message: normalized.message,
571
- retryable: normalized.retryable,
572
- acp: normalized.acp
573
- };
574
- }
575
- function writeQueueMessage(socket, message) {
576
- if (socket.destroyed || !socket.writable) return;
577
- socket.write(`${JSON.stringify(message)}\n`);
578
- }
579
- var SessionQueueOwner = class SessionQueueOwner {
580
- server;
581
- controlHandlers;
582
- ownerGeneration;
583
- maxQueueDepth;
584
- onQueueDepthChanged;
585
- pending = [];
586
- waiters = [];
587
- closed = false;
588
- constructor(server, controlHandlers, lease, options) {
589
- this.server = server;
590
- this.controlHandlers = controlHandlers;
591
- this.ownerGeneration = lease.ownerGeneration;
592
- this.maxQueueDepth = Math.max(1, Math.round(options.maxQueueDepth));
593
- this.onQueueDepthChanged = options.onQueueDepthChanged;
594
- }
595
- static async start(lease, controlHandlers, options = { maxQueueDepth: 16 }) {
596
- const ownerRef = { current: void 0 };
597
- const server = net.createServer((socket) => {
598
- ownerRef.current?.handleConnection(socket);
599
- });
600
- ownerRef.current = new SessionQueueOwner(server, controlHandlers, lease, options);
601
- await new Promise((resolve, reject) => {
602
- const onListening = () => {
603
- server.off("error", onError);
604
- resolve();
605
- };
606
- const onError = (error) => {
607
- server.off("listening", onListening);
608
- reject(error);
609
- };
610
- server.once("listening", onListening);
611
- server.once("error", onError);
612
- server.listen(lease.socketPath);
613
- });
614
- return ownerRef.current;
615
- }
616
- async close() {
617
- if (this.closed) return;
618
- this.closed = true;
619
- for (const waiter of this.waiters.splice(0)) waiter(void 0);
620
- for (const task of this.pending.splice(0)) {
621
- if (task.waitForCompletion) task.send(makeQueueOwnerError(task.requestId, "Queue owner shutting down before prompt execution", "QUEUE_OWNER_SHUTTING_DOWN", { retryable: true }));
622
- task.close();
623
- }
624
- this.emitQueueDepth();
625
- await new Promise((resolve) => {
626
- this.server.close(() => resolve());
627
- });
628
- }
629
- async nextTask(timeoutMs) {
630
- if (this.pending.length > 0) {
631
- const task = this.pending.shift();
632
- this.emitQueueDepth();
633
- if (task) recordPerfDuration("queue.owner.wait_ms", Date.now() - task.enqueuedAt);
634
- return task;
635
- }
636
- if (this.closed) return;
637
- return await new Promise((resolve) => {
638
- const timer = timeoutMs != null && setTimeout(() => {
639
- const index = this.waiters.indexOf(waiter);
640
- if (index >= 0) this.waiters.splice(index, 1);
641
- resolve(void 0);
642
- }, Math.max(0, timeoutMs));
643
- const waiter = (task) => {
644
- if (timer) clearTimeout(timer);
645
- resolve(task);
646
- };
647
- this.waiters.push(waiter);
648
- });
649
- }
650
- queueDepth() {
651
- return this.pending.length;
652
- }
653
- emitQueueDepth() {
654
- this.onQueueDepthChanged?.(this.pending.length);
655
- }
656
- enqueue(task) {
657
- if (this.closed) {
658
- if (task.waitForCompletion) task.send(makeQueueOwnerError(task.requestId, "Queue owner is shutting down", "QUEUE_OWNER_SHUTTING_DOWN", { retryable: true }));
659
- task.close();
660
- return;
661
- }
662
- const waiter = this.waiters.shift();
663
- if (waiter) {
664
- waiter(task);
665
- return;
666
- }
667
- if (this.pending.length >= this.maxQueueDepth) {
668
- if (task.waitForCompletion) task.send({
669
- ...makeQueueOwnerError(task.requestId, `Queue owner is overloaded (${this.pending.length}/${this.maxQueueDepth} queued)`, "QUEUE_OWNER_OVERLOADED", { retryable: true }),
670
- ownerGeneration: this.ownerGeneration
671
- });
672
- task.close();
673
- return;
674
- }
675
- this.pending.push(task);
676
- this.emitQueueDepth();
677
- }
678
- handleControlRequest(options) {
679
- writeQueueMessage(options.socket, {
680
- type: "accepted",
681
- requestId: options.requestId,
682
- ownerGeneration: this.ownerGeneration
683
- });
684
- options.run().then((message) => {
685
- writeQueueMessage(options.socket, {
686
- ...message,
687
- ownerGeneration: this.ownerGeneration
688
- });
689
- }).catch((error) => {
690
- writeQueueMessage(options.socket, {
691
- ...makeQueueOwnerErrorFromUnknown(options.requestId, error, "QUEUE_CONTROL_REQUEST_FAILED"),
692
- ownerGeneration: this.ownerGeneration
693
- });
694
- }).finally(() => {
695
- if (!options.socket.destroyed) options.socket.end();
696
- });
697
- }
698
- handleConnection(socket) {
699
- socket.setEncoding("utf8");
700
- if (this.closed) {
701
- writeQueueMessage(socket, makeQueueOwnerError("unknown", "Queue owner is closed", "QUEUE_OWNER_CLOSED", { retryable: true }));
702
- socket.end();
703
- return;
704
- }
705
- let buffer = "";
706
- let handled = false;
707
- const fail = (requestId, message, detailCode) => {
708
- writeQueueMessage(socket, {
709
- ...makeQueueOwnerError(requestId, message, detailCode, { retryable: false }),
710
- ownerGeneration: this.ownerGeneration
711
- });
712
- socket.end();
713
- };
714
- const processLine = (line) => {
715
- if (handled) return;
716
- handled = true;
717
- let parsed;
718
- try {
719
- parsed = JSON.parse(line);
720
- } catch {
721
- fail("unknown", "Invalid queue request payload", "QUEUE_REQUEST_PAYLOAD_INVALID_JSON");
722
- return;
723
- }
724
- const request = parseQueueRequest(parsed);
725
- if (!request) {
726
- fail("unknown", "Invalid queue request", "QUEUE_REQUEST_INVALID");
727
- return;
728
- }
729
- if (request.ownerGeneration !== void 0 && this.ownerGeneration !== void 0 && request.ownerGeneration !== this.ownerGeneration) {
730
- fail(request.requestId, "Queue request targeted a stale queue owner generation", "QUEUE_OWNER_GENERATION_MISMATCH");
731
- return;
732
- }
733
- if (request.type === "cancel_prompt") {
734
- this.handleControlRequest({
735
- socket,
736
- requestId: request.requestId,
737
- run: async () => ({
738
- type: "cancel_result",
739
- requestId: request.requestId,
740
- cancelled: await this.controlHandlers.cancelPrompt()
741
- })
742
- });
743
- return;
744
- }
745
- if (request.type === "close_session") {
746
- this.handleControlRequest({
747
- socket,
748
- requestId: request.requestId,
749
- run: async () => ({
750
- type: "close_session_result",
751
- requestId: request.requestId,
752
- closed: await this.controlHandlers.closeSession(request.timeoutMs)
753
- })
754
- });
755
- return;
756
- }
757
- if (request.type === "set_mode") {
758
- this.handleControlRequest({
759
- socket,
760
- requestId: request.requestId,
761
- run: async () => {
762
- await this.controlHandlers.setSessionMode(request.modeId, request.timeoutMs);
763
- return {
764
- type: "set_mode_result",
765
- requestId: request.requestId,
766
- modeId: request.modeId
767
- };
768
- }
769
- });
770
- return;
771
- }
772
- if (request.type === "set_model") {
773
- this.handleControlRequest({
774
- socket,
775
- requestId: request.requestId,
776
- run: async () => {
777
- await this.controlHandlers.setSessionModel(request.modelId, request.timeoutMs);
778
- return {
779
- type: "set_model_result",
780
- requestId: request.requestId,
781
- modelId: request.modelId
782
- };
783
- }
784
- });
785
- return;
786
- }
787
- if (request.type === "set_config_option") {
788
- this.handleControlRequest({
789
- socket,
790
- requestId: request.requestId,
791
- run: async () => ({
792
- type: "set_config_option_result",
793
- requestId: request.requestId,
794
- response: await this.controlHandlers.setSessionConfigOption(request.configId, request.value, request.timeoutMs)
795
- })
796
- });
797
- return;
798
- }
799
- const task = {
800
- requestId: request.requestId,
801
- message: request.message,
802
- prompt: request.prompt ?? textPrompt(request.message),
803
- permissionMode: request.permissionMode,
804
- resumePolicy: request.resumePolicy,
805
- nonInteractivePermissions: request.nonInteractivePermissions,
806
- timeoutMs: request.timeoutMs,
807
- suppressSdkConsoleErrors: request.suppressSdkConsoleErrors,
808
- sessionOptions: request.sessionOptions,
809
- waitForCompletion: request.waitForCompletion,
810
- enqueuedAt: Date.now(),
811
- send: (message) => {
812
- writeQueueMessage(socket, {
813
- ...message,
814
- ownerGeneration: this.ownerGeneration
815
- });
816
- },
817
- close: () => {
818
- if (!socket.destroyed) socket.end();
819
- }
820
- };
821
- writeQueueMessage(socket, {
822
- type: "accepted",
823
- requestId: request.requestId,
824
- ownerGeneration: this.ownerGeneration
825
- });
826
- if (!request.waitForCompletion) task.close();
827
- this.enqueue(task);
828
- };
829
- socket.on("data", (chunk) => {
830
- buffer += chunk;
831
- let index = buffer.indexOf("\n");
832
- while (index >= 0) {
833
- const line = buffer.slice(0, index).trim();
834
- buffer = buffer.slice(index + 1);
835
- if (line.length > 0) processLine(line);
836
- index = buffer.indexOf("\n");
837
- }
838
- });
839
- socket.on("error", () => {});
840
- }
841
- };
842
- //#endregion
843
- //#region src/cli/queue/ipc.ts
844
- const MAX_MESSAGE_BUFFER_SIZE = 10 * 1024 * 1024;
845
- const STALE_OWNER_PROTOCOL_DETAIL_CODES = new Set(["QUEUE_PROTOCOL_MALFORMED_MESSAGE", "QUEUE_PROTOCOL_UNEXPECTED_RESPONSE"]);
846
- async function maybeRecoverStaleOwnerAfterProtocolMismatch(params) {
847
- if (!(params.error instanceof QueueProtocolError)) return false;
848
- const detailCode = params.error.detailCode;
849
- if (!detailCode || !STALE_OWNER_PROTOCOL_DETAIL_CODES.has(detailCode)) return false;
850
- await terminateQueueOwnerForSession(params.sessionId).catch(() => {});
851
- incrementPerfCounter("queue.owner.stale_recovered");
852
- if (params.verbose) process.stderr.write(`[acpx] dropped stale queue owner metadata after protocol mismatch for session ${params.sessionId} (${detailCode})\n`);
853
- return true;
854
- }
855
- function assertOwnerGeneration(owner, message) {
856
- if (owner.ownerGeneration !== void 0 && message.ownerGeneration !== void 0 && message.ownerGeneration !== owner.ownerGeneration) throw new QueueProtocolError("Queue owner returned mismatched generation", {
857
- detailCode: "QUEUE_OWNER_GENERATION_MISMATCH",
858
- origin: "queue",
859
- retryable: true
860
- });
861
- return message;
862
- }
863
- function makeMalformedQueueMessageError() {
864
- return new QueueProtocolError("Queue owner sent malformed message", {
865
- detailCode: "QUEUE_PROTOCOL_MALFORMED_MESSAGE",
866
- origin: "queue",
867
- retryable: true
868
- });
869
- }
870
- function parseQueueOwnerResponseLine(owner, requestId, line) {
871
- let parsed;
872
- try {
873
- parsed = JSON.parse(line);
874
- } catch {
875
- throw new QueueProtocolError("Queue owner sent invalid JSON payload", {
876
- detailCode: "QUEUE_PROTOCOL_INVALID_JSON",
877
- origin: "queue",
878
- retryable: true
879
- });
880
- }
881
- const parsedMessage = parseQueueOwnerMessage(parsed);
882
- if (!parsedMessage) throw makeMalformedQueueMessageError();
883
- const message = assertOwnerGeneration(owner, parsedMessage);
884
- if (message.requestId !== requestId) throw makeMalformedQueueMessageError();
885
- return message;
886
- }
887
- async function runQueueOwnerRequest(options) {
888
- const socket = await connectToQueueOwner(options.owner);
889
- if (!socket) return;
890
- socket.setEncoding("utf8");
891
- return await new Promise((resolve, reject) => {
892
- let settled = false;
893
- let buffer = "";
894
- const state = { acknowledged: false };
895
- const finishResolve = (result) => {
896
- if (settled) return;
897
- settled = true;
898
- socket.removeAllListeners();
899
- if (!socket.destroyed) socket.end();
900
- resolve(result);
901
- };
902
- const finishReject = (error) => {
903
- if (settled) return;
904
- settled = true;
905
- socket.removeAllListeners();
906
- if (!socket.destroyed) socket.destroy();
907
- reject(error);
908
- };
909
- const controls = {
910
- state,
911
- resolve: finishResolve,
912
- reject: finishReject
913
- };
914
- const processLine = (line) => {
915
- let message;
916
- try {
917
- message = parseQueueOwnerResponseLine(options.owner, options.request.requestId, line);
918
- } catch (error) {
919
- finishReject(error);
920
- return;
921
- }
922
- if (message.type === "accepted") {
923
- state.acknowledged = true;
924
- options.onAccepted?.(controls);
925
- return;
926
- }
927
- options.onMessage(message, controls);
928
- };
929
- socket.on("data", (chunk) => {
930
- buffer += chunk;
931
- if (buffer.length > 10485760) {
932
- socket.destroy();
933
- finishReject(/* @__PURE__ */ new Error(`Message buffer exceeded ${MAX_MESSAGE_BUFFER_SIZE} bytes`));
934
- return;
935
- }
936
- let index = buffer.indexOf("\n");
937
- while (index >= 0) {
938
- const line = buffer.slice(0, index).trim();
939
- buffer = buffer.slice(index + 1);
940
- if (line.length > 0) processLine(line);
941
- index = buffer.indexOf("\n");
942
- }
943
- });
944
- socket.once("error", (error) => {
945
- finishReject(error);
946
- });
947
- socket.once("close", () => {
948
- if (settled) return;
949
- options.onClose(controls);
950
- });
951
- socket.write(`${JSON.stringify(options.request)}\n`);
952
- });
953
- }
954
- async function submitToQueueOwner(owner, options) {
955
- const requestId = randomUUID();
956
- const request = {
957
- type: "submit_prompt",
958
- requestId,
959
- ownerGeneration: owner.ownerGeneration,
960
- message: options.message,
961
- prompt: options.prompt,
962
- permissionMode: options.permissionMode,
963
- resumePolicy: options.resumePolicy,
964
- nonInteractivePermissions: options.nonInteractivePermissions,
965
- timeoutMs: options.timeoutMs,
966
- suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,
967
- waitForCompletion: options.waitForCompletion,
968
- sessionOptions: options.sessionOptions
969
- };
970
- options.outputFormatter.setContext({ sessionId: options.sessionId });
971
- return await runQueueOwnerRequest({
972
- owner,
973
- request,
974
- onAccepted: ({ resolve }) => {
975
- options.outputFormatter.setContext({ sessionId: options.sessionId });
976
- if (!options.waitForCompletion) resolve({
977
- queued: true,
978
- sessionId: options.sessionId,
979
- requestId
980
- });
981
- },
982
- onMessage: (message, { state, resolve, reject }) => {
983
- if (message.type === "error") {
984
- options.outputFormatter.setContext({ sessionId: options.sessionId });
985
- const queueErrorAlreadyEmitted = options.errorEmissionPolicy?.queueErrorAlreadyEmitted ?? true;
986
- if (!(message.outputAlreadyEmitted === true) || !queueErrorAlreadyEmitted) {
987
- options.outputFormatter.onError({
988
- code: message.code ?? "RUNTIME",
989
- detailCode: message.detailCode,
990
- origin: message.origin ?? "queue",
991
- message: message.message,
992
- retryable: message.retryable,
993
- acp: message.acp
994
- });
995
- options.outputFormatter.flush();
996
- }
997
- reject(new QueueConnectionError(message.message, {
998
- outputCode: message.code,
999
- detailCode: message.detailCode,
1000
- origin: message.origin ?? "queue",
1001
- retryable: message.retryable,
1002
- acp: message.acp,
1003
- ...queueErrorAlreadyEmitted ? { outputAlreadyEmitted: true } : {}
1004
- }));
1005
- return;
1006
- }
1007
- if (!state.acknowledged) {
1008
- reject(new QueueConnectionError("Queue owner did not acknowledge request", {
1009
- detailCode: "QUEUE_ACK_MISSING",
1010
- origin: "queue",
1011
- retryable: true
1012
- }));
1013
- return;
1014
- }
1015
- if (message.type === "event") {
1016
- options.outputFormatter.onAcpMessage(message.message);
1017
- return;
1018
- }
1019
- if (message.type === "result") {
1020
- options.outputFormatter.flush();
1021
- resolve(message.result);
1022
- return;
1023
- }
1024
- reject(new QueueProtocolError("Queue owner returned unexpected response", {
1025
- detailCode: "QUEUE_PROTOCOL_UNEXPECTED_RESPONSE",
1026
- origin: "queue",
1027
- retryable: true
1028
- }));
1029
- },
1030
- onClose: ({ state, resolve, reject }) => {
1031
- if (!state.acknowledged) {
1032
- reject(new QueueConnectionError("Queue owner disconnected before acknowledging request", {
1033
- detailCode: "QUEUE_DISCONNECTED_BEFORE_ACK",
1034
- origin: "queue",
1035
- retryable: true
1036
- }));
1037
- return;
1038
- }
1039
- if (!options.waitForCompletion) {
1040
- resolve({
1041
- queued: true,
1042
- sessionId: options.sessionId,
1043
- requestId
1044
- });
1045
- return;
1046
- }
1047
- reject(new QueueConnectionError("Queue owner disconnected before prompt completion", {
1048
- detailCode: "QUEUE_DISCONNECTED_BEFORE_COMPLETION",
1049
- origin: "queue",
1050
- retryable: true
1051
- }));
1052
- }
1053
- });
1054
- }
1055
- async function submitControlToQueueOwner(owner, request, isExpectedResponse) {
1056
- return await runQueueOwnerRequest({
1057
- owner,
1058
- request,
1059
- onMessage: (message, { state, resolve, reject }) => {
1060
- if (message.type === "error") {
1061
- reject(new QueueConnectionError(message.message, {
1062
- outputCode: message.code,
1063
- detailCode: message.detailCode,
1064
- origin: message.origin ?? "queue",
1065
- retryable: message.retryable,
1066
- acp: message.acp
1067
- }));
1068
- return;
1069
- }
1070
- if (!state.acknowledged) {
1071
- reject(new QueueConnectionError("Queue owner did not acknowledge request", {
1072
- detailCode: "QUEUE_ACK_MISSING",
1073
- origin: "queue",
1074
- retryable: true
1075
- }));
1076
- return;
1077
- }
1078
- if (!isExpectedResponse(message)) {
1079
- reject(new QueueProtocolError("Queue owner returned unexpected response", {
1080
- detailCode: "QUEUE_PROTOCOL_UNEXPECTED_RESPONSE",
1081
- origin: "queue",
1082
- retryable: true
1083
- }));
1084
- return;
1085
- }
1086
- resolve(message);
1087
- },
1088
- onClose: ({ state, reject }) => {
1089
- if (!state.acknowledged) {
1090
- reject(new QueueConnectionError("Queue owner disconnected before acknowledging request", {
1091
- detailCode: "QUEUE_DISCONNECTED_BEFORE_ACK",
1092
- origin: "queue",
1093
- retryable: true
1094
- }));
1095
- return;
1096
- }
1097
- reject(new QueueConnectionError("Queue owner disconnected before responding", {
1098
- detailCode: "QUEUE_DISCONNECTED_BEFORE_COMPLETION",
1099
- origin: "queue",
1100
- retryable: true
1101
- }));
1102
- }
1103
- });
1104
- }
1105
- async function submitCancelToQueueOwner(owner) {
1106
- const request = {
1107
- type: "cancel_prompt",
1108
- requestId: randomUUID(),
1109
- ownerGeneration: owner.ownerGeneration
1110
- };
1111
- const response = await submitControlToQueueOwner(owner, request, (message) => message.type === "cancel_result");
1112
- if (!response) return;
1113
- if (response.requestId !== request.requestId) throw new QueueProtocolError("Queue owner returned mismatched cancel response", {
1114
- detailCode: "QUEUE_PROTOCOL_MALFORMED_MESSAGE",
1115
- origin: "queue",
1116
- retryable: true
1117
- });
1118
- return response.cancelled;
1119
- }
1120
- async function submitSetModeToQueueOwner(owner, modeId, timeoutMs) {
1121
- const request = {
1122
- type: "set_mode",
1123
- requestId: randomUUID(),
1124
- ownerGeneration: owner.ownerGeneration,
1125
- modeId,
1126
- timeoutMs
1127
- };
1128
- const response = await submitControlToQueueOwner(owner, request, (message) => message.type === "set_mode_result");
1129
- if (!response) return;
1130
- if (response.requestId !== request.requestId) throw new QueueProtocolError("Queue owner returned mismatched set_mode response", {
1131
- detailCode: "QUEUE_PROTOCOL_MALFORMED_MESSAGE",
1132
- origin: "queue",
1133
- retryable: true
1134
- });
1135
- return true;
1136
- }
1137
- async function submitSetModelToQueueOwner(owner, modelId, timeoutMs) {
1138
- const request = {
1139
- type: "set_model",
1140
- requestId: randomUUID(),
1141
- ownerGeneration: owner.ownerGeneration,
1142
- modelId,
1143
- timeoutMs
1144
- };
1145
- const response = await submitControlToQueueOwner(owner, request, (message) => message.type === "set_model_result");
1146
- if (!response) return;
1147
- if (response.requestId !== request.requestId) throw new QueueProtocolError("Queue owner returned mismatched set_model response", {
1148
- detailCode: "QUEUE_PROTOCOL_MALFORMED_MESSAGE",
1149
- origin: "queue",
1150
- retryable: true
1151
- });
1152
- return true;
1153
- }
1154
- async function submitSetConfigOptionToQueueOwner(owner, configId, value, timeoutMs) {
1155
- const request = {
1156
- type: "set_config_option",
1157
- requestId: randomUUID(),
1158
- ownerGeneration: owner.ownerGeneration,
1159
- configId,
1160
- value,
1161
- timeoutMs
1162
- };
1163
- const response = await submitControlToQueueOwner(owner, request, (message) => message.type === "set_config_option_result");
1164
- if (!response) return;
1165
- if (response.requestId !== request.requestId) throw new QueueProtocolError("Queue owner returned mismatched set_config_option response", {
1166
- detailCode: "QUEUE_PROTOCOL_MALFORMED_MESSAGE",
1167
- origin: "queue",
1168
- retryable: true
1169
- });
1170
- return response.response;
1171
- }
1172
- async function submitCloseSessionToQueueOwner(owner, timeoutMs) {
1173
- const request = {
1174
- type: "close_session",
1175
- requestId: randomUUID(),
1176
- ownerGeneration: owner.ownerGeneration,
1177
- timeoutMs
1178
- };
1179
- const response = await submitControlToQueueOwner(owner, request, (message) => message.type === "close_session_result");
1180
- if (!response) return;
1181
- if (response.requestId !== request.requestId) throw new QueueProtocolError("Queue owner returned mismatched close_session response", {
1182
- detailCode: "QUEUE_PROTOCOL_MALFORMED_MESSAGE",
1183
- origin: "queue",
1184
- retryable: true
1185
- });
1186
- return response.closed;
1187
- }
1188
- async function trySubmitToRunningOwner(options) {
1189
- const owner = await readQueueOwnerRecord(options.sessionId);
1190
- if (!owner) return;
1191
- let submitted;
1192
- try {
1193
- submitted = await submitToQueueOwner(owner, options);
1194
- } catch (error) {
1195
- if (await maybeRecoverStaleOwnerAfterProtocolMismatch({
1196
- sessionId: options.sessionId,
1197
- owner,
1198
- error,
1199
- verbose: options.verbose
1200
- })) return;
1201
- throw error;
1202
- }
1203
- if (submitted) {
1204
- if (options.verbose) process.stderr.write(`[acpx] queued prompt on active owner pid ${owner.pid} for session ${options.sessionId}\n`);
1205
- return submitted;
1206
- }
1207
- if (!(await probeQueueOwnerHealth(options.sessionId)).hasLease) return;
1208
- throw new QueueConnectionError("Session queue owner is running but not accepting queue requests", {
1209
- detailCode: "QUEUE_NOT_ACCEPTING_REQUESTS",
1210
- origin: "queue",
1211
- retryable: true
1212
- });
1213
- }
1214
- async function tryCloseSessionOnRunningOwner(options) {
1215
- const owner = await readQueueOwnerRecord(options.sessionId);
1216
- if (!owner) return;
1217
- const closed = await submitCloseSessionToQueueOwner(owner, options.timeoutMs);
1218
- if (closed !== void 0) {
1219
- if (options.verbose) process.stderr.write(`[acpx] requested session/close on active owner pid ${owner.pid} for session ${options.sessionId}\n`);
1220
- return closed;
1221
- }
1222
- if (!(await probeQueueOwnerHealth(options.sessionId)).hasLease) return;
1223
- throw new QueueConnectionError("Session queue owner is running but not accepting close_session requests", {
1224
- detailCode: "QUEUE_NOT_ACCEPTING_REQUESTS",
1225
- origin: "queue",
1226
- retryable: true
1227
- });
1228
- }
1229
- async function tryCancelOnRunningOwner(options) {
1230
- const owner = await readQueueOwnerRecord(options.sessionId);
1231
- if (!owner) return;
1232
- const cancelled = await submitCancelToQueueOwner(owner);
1233
- if (cancelled !== void 0) {
1234
- if (options.verbose) process.stderr.write(`[acpx] requested cancel on active owner pid ${owner.pid} for session ${options.sessionId}\n`);
1235
- return cancelled;
1236
- }
1237
- if (!(await probeQueueOwnerHealth(options.sessionId)).hasLease) return;
1238
- throw new QueueConnectionError("Session queue owner is running but not accepting cancel requests", {
1239
- detailCode: "QUEUE_NOT_ACCEPTING_REQUESTS",
1240
- origin: "queue",
1241
- retryable: true
1242
- });
1243
- }
1244
- async function trySetModeOnRunningOwner(sessionId, modeId, timeoutMs, verbose) {
1245
- const owner = await readQueueOwnerRecord(sessionId);
1246
- if (!owner) return;
1247
- if (await submitSetModeToQueueOwner(owner, modeId, timeoutMs)) {
1248
- if (verbose) process.stderr.write(`[acpx] requested session/set_mode on owner pid ${owner.pid} for session ${sessionId}\n`);
1249
- return true;
1250
- }
1251
- if (!(await probeQueueOwnerHealth(sessionId)).hasLease) return;
1252
- throw new QueueConnectionError("Session queue owner is running but not accepting set_mode requests", {
1253
- detailCode: "QUEUE_NOT_ACCEPTING_REQUESTS",
1254
- origin: "queue",
1255
- retryable: true
1256
- });
1257
- }
1258
- async function trySetModelOnRunningOwner(sessionId, modelId, timeoutMs, verbose) {
1259
- const owner = await readQueueOwnerRecord(sessionId);
1260
- if (!owner) return;
1261
- if (await submitSetModelToQueueOwner(owner, modelId, timeoutMs)) {
1262
- if (verbose) process.stderr.write(`[acpx] requested session/set_model on owner pid ${owner.pid} for session ${sessionId}\n`);
1263
- return true;
1264
- }
1265
- if (!(await probeQueueOwnerHealth(sessionId)).hasLease) return;
1266
- throw new QueueConnectionError("Session queue owner is running but not accepting set_model requests", {
1267
- detailCode: "QUEUE_NOT_ACCEPTING_REQUESTS",
1268
- origin: "queue",
1269
- retryable: true
1270
- });
1271
- }
1272
- async function trySetConfigOptionOnRunningOwner(sessionId, configId, value, timeoutMs, verbose) {
1273
- const owner = await readQueueOwnerRecord(sessionId);
1274
- if (!owner) return;
1275
- const response = await submitSetConfigOptionToQueueOwner(owner, configId, value, timeoutMs);
1276
- if (response) {
1277
- if (verbose) process.stderr.write(`[acpx] requested session/set_config_option on owner pid ${owner.pid} for session ${sessionId}\n`);
1278
- return response;
1279
- }
1280
- if (!(await probeQueueOwnerHealth(sessionId)).hasLease) return;
1281
- throw new QueueConnectionError("Session queue owner is running but not accepting set_config_option requests", {
1282
- detailCode: "QUEUE_NOT_ACCEPTING_REQUESTS",
1283
- origin: "queue",
1284
- retryable: true
1285
- });
1286
- }
1287
- //#endregion
1288
- export { trySetModelOnRunningOwner as a, probeQueueOwnerHealth as c, releaseQueueOwnerLease as d, terminateProcess as f, waitMs as h, trySetModeOnRunningOwner as i, isProcessAlive as l, tryAcquireQueueOwnerLease as m, tryCloseSessionOnRunningOwner as n, trySubmitToRunningOwner as o, terminateQueueOwnerForSession as p, trySetConfigOptionOnRunningOwner as r, SessionQueueOwner as s, tryCancelOnRunningOwner as t, refreshQueueOwnerLease as u };
1289
-
1290
- //# sourceMappingURL=ipc-ABXlXzGP.js.map