@vtxmacro/cli 2026.8.19 → 2026.8.21
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/bin/vtx.js +270 -67
- package/package.json +1 -1
package/bin/vtx.js
CHANGED
|
@@ -38,7 +38,7 @@ var init_agent_cli_release = __esm({
|
|
|
38
38
|
"agent-cli-release.json"() {
|
|
39
39
|
agent_cli_release_default = {
|
|
40
40
|
package_name: "@vtxmacro/cli",
|
|
41
|
-
package_version: "2026.8.
|
|
41
|
+
package_version: "2026.8.21",
|
|
42
42
|
codex_package_name: "@openai/codex",
|
|
43
43
|
codex_version: "0.147.0",
|
|
44
44
|
platforms: {
|
|
@@ -19837,6 +19837,9 @@ child.once('close', async () => {
|
|
|
19837
19837
|
this.fatalListeners.add(listener);
|
|
19838
19838
|
return () => this.fatalListeners.delete(listener);
|
|
19839
19839
|
}
|
|
19840
|
+
isUsable() {
|
|
19841
|
+
return !this.closed && this.fatalError === null && this.process.exitCode === null;
|
|
19842
|
+
}
|
|
19840
19843
|
async readAccountSnapshot(deadlineAtMs, signal, refreshToken = false) {
|
|
19841
19844
|
const result2 = await this.request("account/read", { refreshToken }, {
|
|
19842
19845
|
timeoutMs: Math.max(1, deadlineAtMs - Date.now()),
|
|
@@ -20196,6 +20199,30 @@ child.once('close', async () => {
|
|
|
20196
20199
|
});
|
|
20197
20200
|
const startedAt = Date.now();
|
|
20198
20201
|
const unsubscribe = this.subscribe(({ method, params }) => {
|
|
20202
|
+
const eventThreadId = String(params.threadId || "");
|
|
20203
|
+
const scopedMethod = method.startsWith("thread/") || method.startsWith("turn/") || method.startsWith("item/") || method.startsWith("rawResponse") || method === "model/rerouted";
|
|
20204
|
+
if (scopedMethod && !eventThreadId) {
|
|
20205
|
+
terminalReject(new CodexAppServerError({
|
|
20206
|
+
message: "Codex notification omitted its thread scope.",
|
|
20207
|
+
category: "adapter",
|
|
20208
|
+
code: "missing_thread_notification_scope",
|
|
20209
|
+
retryable: false,
|
|
20210
|
+
dispatchOutcome: requestWritten ? turnId ? "confirmed_dispatched" : "outcome_unknown" : "not_dispatched"
|
|
20211
|
+
}));
|
|
20212
|
+
return;
|
|
20213
|
+
}
|
|
20214
|
+
if (scopedMethod && eventThreadId !== request.thread.threadId) {
|
|
20215
|
+
if (!this.threads.has(eventThreadId)) {
|
|
20216
|
+
terminalReject(new CodexAppServerError({
|
|
20217
|
+
message: "Codex notification crossed thread scope.",
|
|
20218
|
+
category: "adapter",
|
|
20219
|
+
code: "cross_thread_notification",
|
|
20220
|
+
retryable: false,
|
|
20221
|
+
dispatchOutcome: turnId ? "confirmed_dispatched" : "outcome_unknown"
|
|
20222
|
+
}));
|
|
20223
|
+
}
|
|
20224
|
+
return;
|
|
20225
|
+
}
|
|
20199
20226
|
if (forbiddenMethod(method)) {
|
|
20200
20227
|
terminalReject(new CodexAppServerError({
|
|
20201
20228
|
message: "Codex attempted to use forbidden child authority.",
|
|
@@ -20231,18 +20258,6 @@ child.once('close', async () => {
|
|
|
20231
20258
|
return;
|
|
20232
20259
|
}
|
|
20233
20260
|
}
|
|
20234
|
-
const eventThreadId = String(params.threadId || "");
|
|
20235
|
-
const scopedMethod = method.startsWith("thread/") || method.startsWith("turn/") || method.startsWith("item/") || method.startsWith("rawResponse") || method === "model/rerouted";
|
|
20236
|
-
if (scopedMethod && eventThreadId !== request.thread.threadId) {
|
|
20237
|
-
terminalReject(new CodexAppServerError({
|
|
20238
|
-
message: "Codex notification crossed thread scope.",
|
|
20239
|
-
category: "adapter",
|
|
20240
|
-
code: "cross_thread_notification",
|
|
20241
|
-
retryable: false,
|
|
20242
|
-
dispatchOutcome: turnId ? "confirmed_dispatched" : "outcome_unknown"
|
|
20243
|
-
}));
|
|
20244
|
-
return;
|
|
20245
|
-
}
|
|
20246
20261
|
const eventTurn = objectOrNull(params.turn);
|
|
20247
20262
|
const eventTurnId = String(params.turnId || eventTurn?.id || "");
|
|
20248
20263
|
const turnScopedMethod = method.startsWith("turn/") || method.startsWith("item/") || method.startsWith("rawResponse") || method === "model/rerouted";
|
|
@@ -20884,7 +20899,7 @@ var init_codex_adapter = __esm({
|
|
|
20884
20899
|
context.addIssue({ code: "custom", message: "Codex recovery thread identity is incomplete." });
|
|
20885
20900
|
}
|
|
20886
20901
|
const guardianManaged = value.processToken !== null || value.processReceiptPath !== null;
|
|
20887
|
-
if (value.processToken === null !== (value.processReceiptPath === null) || value.processState === "unmanaged" === guardianManaged || value.cleanupConfirmed &&
|
|
20902
|
+
if (value.processToken === null !== (value.processReceiptPath === null) || value.processState === "unmanaged" === guardianManaged || value.cleanupConfirmed && value.processState === "spawn_intent") {
|
|
20888
20903
|
context.addIssue({ code: "custom", message: "Codex recovery process identity is invalid." });
|
|
20889
20904
|
}
|
|
20890
20905
|
});
|
|
@@ -21293,8 +21308,114 @@ var init_codex_adapter = __esm({
|
|
|
21293
21308
|
CodexSubscriptionAdapter = class {
|
|
21294
21309
|
constructor(dependencies = {}) {
|
|
21295
21310
|
this.inFlightAttempts = /* @__PURE__ */ new Map();
|
|
21311
|
+
this.durableSession = null;
|
|
21312
|
+
this.durableSessionStart = null;
|
|
21313
|
+
this.closing = false;
|
|
21314
|
+
this.adapterClosePromise = null;
|
|
21296
21315
|
this.dependencies = dependencies;
|
|
21297
21316
|
}
|
|
21317
|
+
async startDurableSession(codexHome, deadlineAtMs) {
|
|
21318
|
+
const binary = await (this.dependencies.resolveBinary ?? resolvePinnedCodexBinary)();
|
|
21319
|
+
const guardianManaged = Boolean(
|
|
21320
|
+
this.dependencies.recoveryHooks && !this.dependencies.spawnProcess
|
|
21321
|
+
);
|
|
21322
|
+
const bootIdentity = guardianManaged ? await (this.dependencies.readBootIdentity ?? readInferenceSystemBootIdentity)() : null;
|
|
21323
|
+
const processToken = guardianManaged ? randomBytes3(32).toString("hex") : null;
|
|
21324
|
+
const guardianReceiptRoot = guardianManaged ? this.dependencies.guardianReceiptRoot ?? join4(tmpdir2(), "vtx-codex-guardian-receipts") : null;
|
|
21325
|
+
if (guardianReceiptRoot) await ensureInferencePrivateDirectory(guardianReceiptRoot);
|
|
21326
|
+
const processReceiptPath = guardianReceiptRoot && processToken ? join4(guardianReceiptRoot, `${processToken}.json`) : null;
|
|
21327
|
+
const session = await CodexAppServerSession.start({
|
|
21328
|
+
binary,
|
|
21329
|
+
codexHome,
|
|
21330
|
+
deadlineAtMs,
|
|
21331
|
+
spawnProcess: this.dependencies.spawnProcess,
|
|
21332
|
+
guardian: processToken && processReceiptPath ? { processToken, receiptPath: processReceiptPath, bootIdentity: bootIdentity ?? void 0 } : void 0
|
|
21333
|
+
});
|
|
21334
|
+
return {
|
|
21335
|
+
session,
|
|
21336
|
+
codexHome,
|
|
21337
|
+
processToken,
|
|
21338
|
+
processReceiptPath,
|
|
21339
|
+
bootIdentity,
|
|
21340
|
+
terminated: false,
|
|
21341
|
+
closePromise: null
|
|
21342
|
+
};
|
|
21343
|
+
}
|
|
21344
|
+
async acquireDurableSession(codexHome, deadlineAtMs, signal) {
|
|
21345
|
+
if (this.closing) {
|
|
21346
|
+
throw new CodexAppServerError({
|
|
21347
|
+
message: "Codex adapter is closing.",
|
|
21348
|
+
category: "transport",
|
|
21349
|
+
code: "transport_closed",
|
|
21350
|
+
retryable: true
|
|
21351
|
+
});
|
|
21352
|
+
}
|
|
21353
|
+
if (this.durableSession && this.durableSession.codexHome === codexHome && this.durableSession.session.isUsable()) return this.durableSession;
|
|
21354
|
+
if (this.durableSession && this.durableSession.codexHome !== codexHome) {
|
|
21355
|
+
await this.invalidateDurableSession(this.durableSession);
|
|
21356
|
+
}
|
|
21357
|
+
if (this.durableSession && !this.durableSession.session.isUsable()) {
|
|
21358
|
+
await this.invalidateDurableSession(this.durableSession);
|
|
21359
|
+
}
|
|
21360
|
+
if (!this.durableSessionStart) {
|
|
21361
|
+
const start2 = this.startDurableSession(codexHome, deadlineAtMs);
|
|
21362
|
+
this.durableSessionStart = start2;
|
|
21363
|
+
void start2.then((session) => {
|
|
21364
|
+
if (this.durableSessionStart === start2) this.durableSession = session;
|
|
21365
|
+
}).finally(() => {
|
|
21366
|
+
if (this.durableSessionStart === start2) this.durableSessionStart = null;
|
|
21367
|
+
}).catch(() => void 0);
|
|
21368
|
+
}
|
|
21369
|
+
const start = this.durableSessionStart;
|
|
21370
|
+
return await new Promise((resolveSession, reject) => {
|
|
21371
|
+
let settled = false;
|
|
21372
|
+
const finish = (callback) => {
|
|
21373
|
+
if (settled) return;
|
|
21374
|
+
settled = true;
|
|
21375
|
+
clearTimeout(timer);
|
|
21376
|
+
signal?.removeEventListener("abort", onAbort);
|
|
21377
|
+
callback();
|
|
21378
|
+
};
|
|
21379
|
+
const onAbort = () => finish(() => reject(new CodexAppServerError({
|
|
21380
|
+
message: "Codex session acquisition was cancelled.",
|
|
21381
|
+
category: "cancelled",
|
|
21382
|
+
code: "cancelled",
|
|
21383
|
+
retryable: false
|
|
21384
|
+
})));
|
|
21385
|
+
const timer = setTimeout(() => finish(() => reject(new CodexAppServerError({
|
|
21386
|
+
message: "Codex session acquisition exceeded the immutable deadline.",
|
|
21387
|
+
category: "timeout",
|
|
21388
|
+
code: "deadline_exceeded",
|
|
21389
|
+
retryable: false
|
|
21390
|
+
}))), Math.max(1, deadlineAtMs - Date.now()));
|
|
21391
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
21392
|
+
if (signal?.aborted) {
|
|
21393
|
+
onAbort();
|
|
21394
|
+
return;
|
|
21395
|
+
}
|
|
21396
|
+
void start.then(
|
|
21397
|
+
(session) => finish(() => resolveSession(session)),
|
|
21398
|
+
(error48) => finish(() => reject(error48))
|
|
21399
|
+
);
|
|
21400
|
+
});
|
|
21401
|
+
}
|
|
21402
|
+
async invalidateDurableSession(session) {
|
|
21403
|
+
if (this.durableSession === session) this.durableSession = null;
|
|
21404
|
+
if (!session.closePromise) {
|
|
21405
|
+
session.closePromise = (async () => {
|
|
21406
|
+
await session.session.close();
|
|
21407
|
+
if (session.processToken && session.processReceiptPath) {
|
|
21408
|
+
await waitForCodexGuardianState(
|
|
21409
|
+
{ processToken: session.processToken, receiptPath: session.processReceiptPath },
|
|
21410
|
+
"terminated",
|
|
21411
|
+
Date.now() + 5e3
|
|
21412
|
+
);
|
|
21413
|
+
}
|
|
21414
|
+
session.terminated = true;
|
|
21415
|
+
})();
|
|
21416
|
+
}
|
|
21417
|
+
await session.closePromise;
|
|
21418
|
+
}
|
|
21298
21419
|
runAttempt(input) {
|
|
21299
21420
|
const active = this.inFlightAttempts.get(input.attemptId);
|
|
21300
21421
|
if (active) {
|
|
@@ -21352,10 +21473,37 @@ var init_codex_adapter = __esm({
|
|
|
21352
21473
|
dispatchOutcome: checkpoint.dispatchOutcome
|
|
21353
21474
|
});
|
|
21354
21475
|
}
|
|
21355
|
-
await
|
|
21476
|
+
const receipt = await readCodexGuardianReceipt(checkpoint.processReceiptPath);
|
|
21477
|
+
if (checkpoint.processState === "terminated" || receipt === null || receipt.state === "terminated") {
|
|
21478
|
+
await rm3(checkpoint.processReceiptPath, { force: true });
|
|
21479
|
+
}
|
|
21356
21480
|
}
|
|
21357
21481
|
await recoveryHooks.clear(attemptId);
|
|
21358
21482
|
}
|
|
21483
|
+
async close() {
|
|
21484
|
+
if (!this.adapterClosePromise) {
|
|
21485
|
+
this.closing = true;
|
|
21486
|
+
this.adapterClosePromise = (async () => {
|
|
21487
|
+
const sessions = /* @__PURE__ */ new Set();
|
|
21488
|
+
if (this.durableSession) sessions.add(this.durableSession);
|
|
21489
|
+
const starting = this.durableSessionStart;
|
|
21490
|
+
if (starting) {
|
|
21491
|
+
const started = await starting.catch(() => null);
|
|
21492
|
+
if (started) sessions.add(started);
|
|
21493
|
+
}
|
|
21494
|
+
await Promise.all(
|
|
21495
|
+
[...sessions].map((session) => this.invalidateDurableSession(session))
|
|
21496
|
+
);
|
|
21497
|
+
await Promise.allSettled(
|
|
21498
|
+
[...this.inFlightAttempts.values()].map((attempt) => attempt.promise)
|
|
21499
|
+
);
|
|
21500
|
+
for (const session of sessions) {
|
|
21501
|
+
if (session.processReceiptPath) await rm3(session.processReceiptPath, { force: true });
|
|
21502
|
+
}
|
|
21503
|
+
})();
|
|
21504
|
+
}
|
|
21505
|
+
await this.adapterClosePromise;
|
|
21506
|
+
}
|
|
21359
21507
|
async executeAttempt(input) {
|
|
21360
21508
|
const validatedInput = validateAttemptInput(input);
|
|
21361
21509
|
const recoveryHooks = this.dependencies.recoveryHooks;
|
|
@@ -21406,6 +21554,7 @@ var init_codex_adapter = __esm({
|
|
|
21406
21554
|
});
|
|
21407
21555
|
}
|
|
21408
21556
|
let resources = null;
|
|
21557
|
+
let sessionLease = null;
|
|
21409
21558
|
let session = null;
|
|
21410
21559
|
let threadId = null;
|
|
21411
21560
|
let baseCheckpoint = null;
|
|
@@ -21413,22 +21562,20 @@ var init_codex_adapter = __esm({
|
|
|
21413
21562
|
let currentDispatchOutcome = "not_dispatched";
|
|
21414
21563
|
let completedResult = null;
|
|
21415
21564
|
let caughtError = null;
|
|
21565
|
+
let sessionInvalidationError = null;
|
|
21416
21566
|
try {
|
|
21417
|
-
const binary = await (this.dependencies.resolveBinary ?? resolvePinnedCodexBinary)();
|
|
21418
21567
|
resources = await (this.dependencies.createAttemptResources ?? ((attemptId) => createIsolatedCodexAttemptResources(
|
|
21419
21568
|
attemptId,
|
|
21420
21569
|
this.dependencies.codexHome
|
|
21421
21570
|
)))(input.attemptId);
|
|
21422
21571
|
await access2(resources.codexHome, fsConstants2.R_OK | fsConstants2.W_OK);
|
|
21423
21572
|
await access2(resources.workspacePath, fsConstants2.R_OK);
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
|
|
21428
|
-
|
|
21429
|
-
|
|
21430
|
-
}
|
|
21431
|
-
const processReceiptPath = guardianReceiptRoot && processToken ? join4(guardianReceiptRoot, `${processToken}.json`) : null;
|
|
21573
|
+
sessionLease = await this.acquireDurableSession(
|
|
21574
|
+
resources.codexHome,
|
|
21575
|
+
input.deadlineAtMs,
|
|
21576
|
+
input.signal
|
|
21577
|
+
);
|
|
21578
|
+
session = sessionLease.session;
|
|
21432
21579
|
baseCheckpoint = {
|
|
21433
21580
|
schemaVersion: "vtx_codex_attempt_recovery_v1",
|
|
21434
21581
|
attemptId: input.attemptId,
|
|
@@ -21438,10 +21585,10 @@ var init_codex_adapter = __esm({
|
|
|
21438
21585
|
workspacePath: resources.workspacePath,
|
|
21439
21586
|
threadId: null,
|
|
21440
21587
|
threadPath: null,
|
|
21441
|
-
processToken,
|
|
21442
|
-
processReceiptPath,
|
|
21443
|
-
processState:
|
|
21444
|
-
bootIdentity,
|
|
21588
|
+
processToken: sessionLease.processToken,
|
|
21589
|
+
processReceiptPath: sessionLease.processReceiptPath,
|
|
21590
|
+
processState: sessionLease.processToken ? "running" : "unmanaged",
|
|
21591
|
+
bootIdentity: sessionLease.bootIdentity,
|
|
21445
21592
|
cleanupConfirmed: false,
|
|
21446
21593
|
adapterRequestId: null,
|
|
21447
21594
|
adapterResponseId: null,
|
|
@@ -21450,19 +21597,6 @@ var init_codex_adapter = __esm({
|
|
|
21450
21597
|
};
|
|
21451
21598
|
latestCheckpoint = baseCheckpoint;
|
|
21452
21599
|
await recoveryHooks?.save(baseCheckpoint);
|
|
21453
|
-
session = await CodexAppServerSession.start({
|
|
21454
|
-
binary,
|
|
21455
|
-
codexHome: resources.codexHome,
|
|
21456
|
-
deadlineAtMs: input.deadlineAtMs,
|
|
21457
|
-
signal: input.signal,
|
|
21458
|
-
spawnProcess: this.dependencies.spawnProcess,
|
|
21459
|
-
guardian: processToken && processReceiptPath ? { processToken, receiptPath: processReceiptPath, bootIdentity: bootIdentity ?? void 0 } : void 0
|
|
21460
|
-
});
|
|
21461
|
-
if (guardianManaged) {
|
|
21462
|
-
baseCheckpoint = { ...baseCheckpoint, processState: "running" };
|
|
21463
|
-
latestCheckpoint = baseCheckpoint;
|
|
21464
|
-
await recoveryHooks?.save(baseCheckpoint);
|
|
21465
|
-
}
|
|
21466
21600
|
await session.requireManagedChatGptAuth(input.deadlineAtMs, input.signal);
|
|
21467
21601
|
await session.requireModel(
|
|
21468
21602
|
input.requestedModel,
|
|
@@ -21522,6 +21656,20 @@ var init_codex_adapter = __esm({
|
|
|
21522
21656
|
return result2;
|
|
21523
21657
|
} catch (error48) {
|
|
21524
21658
|
caughtError = error48;
|
|
21659
|
+
if (sessionLease && (!sessionLease.session.isUsable() || error48 instanceof CodexAppServerError && (error48.category === "transport" || [
|
|
21660
|
+
"rpc_rejected",
|
|
21661
|
+
"invalid_rpc_result",
|
|
21662
|
+
"rpc_timeout",
|
|
21663
|
+
"invalid_thread_provenance",
|
|
21664
|
+
"thread_cleanup_identity_missing",
|
|
21665
|
+
"thread_delete_unconfirmed"
|
|
21666
|
+
].includes(error48.code)))) {
|
|
21667
|
+
try {
|
|
21668
|
+
await this.invalidateDurableSession(sessionLease);
|
|
21669
|
+
} catch (invalidationError) {
|
|
21670
|
+
sessionInvalidationError = invalidationError;
|
|
21671
|
+
}
|
|
21672
|
+
}
|
|
21525
21673
|
if (error48 instanceof CodexAppServerError) {
|
|
21526
21674
|
const dispatchOutcome = error48.dispatchOutcome === "not_dispatched" ? currentDispatchOutcome : error48.dispatchOutcome;
|
|
21527
21675
|
if (baseCheckpoint && !completedResult) {
|
|
@@ -21584,7 +21732,7 @@ var init_codex_adapter = __esm({
|
|
|
21584
21732
|
}
|
|
21585
21733
|
throw classified;
|
|
21586
21734
|
} finally {
|
|
21587
|
-
let cleanupError =
|
|
21735
|
+
let cleanupError = sessionInvalidationError;
|
|
21588
21736
|
if (session && threadId) {
|
|
21589
21737
|
try {
|
|
21590
21738
|
await session.deleteThread(threadId);
|
|
@@ -21592,23 +21740,9 @@ var init_codex_adapter = __esm({
|
|
|
21592
21740
|
cleanupError = error48;
|
|
21593
21741
|
}
|
|
21594
21742
|
}
|
|
21595
|
-
|
|
21596
|
-
await session?.close();
|
|
21597
|
-
} catch (error48) {
|
|
21598
|
-
cleanupError ??= error48;
|
|
21599
|
-
}
|
|
21600
|
-
if (latestCheckpoint && recoveryHooks) {
|
|
21743
|
+
if (sessionLease && cleanupError) {
|
|
21601
21744
|
try {
|
|
21602
|
-
|
|
21603
|
-
await waitForCodexGuardianState(
|
|
21604
|
-
{
|
|
21605
|
-
processToken: latestCheckpoint.processToken,
|
|
21606
|
-
receiptPath: latestCheckpoint.processReceiptPath
|
|
21607
|
-
},
|
|
21608
|
-
"terminated",
|
|
21609
|
-
Date.now() + 5e3
|
|
21610
|
-
);
|
|
21611
|
-
}
|
|
21745
|
+
await this.invalidateDurableSession(sessionLease);
|
|
21612
21746
|
} catch (error48) {
|
|
21613
21747
|
cleanupError ??= error48;
|
|
21614
21748
|
}
|
|
@@ -21623,7 +21757,7 @@ var init_codex_adapter = __esm({
|
|
|
21623
21757
|
if (latestCheckpoint && recoveryHooks && cleanupError === null) {
|
|
21624
21758
|
latestCheckpoint = {
|
|
21625
21759
|
...latestCheckpoint,
|
|
21626
|
-
processState: latestCheckpoint.processToken ? "terminated" : "unmanaged",
|
|
21760
|
+
processState: latestCheckpoint.processToken ? sessionLease?.terminated ? "terminated" : "running" : "unmanaged",
|
|
21627
21761
|
cleanupConfirmed: true
|
|
21628
21762
|
};
|
|
21629
21763
|
try {
|
|
@@ -29377,7 +29511,11 @@ var init_runner = __esm({
|
|
|
29377
29511
|
} finally {
|
|
29378
29512
|
removeAbortListener();
|
|
29379
29513
|
unregisterSignals();
|
|
29380
|
-
|
|
29514
|
+
try {
|
|
29515
|
+
await this.dependencies.codexAdapter.close?.();
|
|
29516
|
+
} finally {
|
|
29517
|
+
await lock2.release();
|
|
29518
|
+
}
|
|
29381
29519
|
}
|
|
29382
29520
|
}
|
|
29383
29521
|
async persistReceipt(receipt, now) {
|
|
@@ -29825,7 +29963,7 @@ import { createWriteStream, readFileSync } from "node:fs";
|
|
|
29825
29963
|
import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as rm4, writeFile as writeFile2 } from "node:fs/promises";
|
|
29826
29964
|
import { homedir as homedir2 } from "node:os";
|
|
29827
29965
|
import { dirname as dirname4, join as join5, resolve as resolve4 } from "node:path";
|
|
29828
|
-
var SERVICE_NAME, SYSTEMD_UNIT, LAUNCHD_LABEL, SERVICE_COOPERATIVE_STOP_SECONDS, isWindowsSubsystemForLinux, inferenceHostServiceManifestPath, inferenceHostServiceDesiredPath, inferenceHostServiceLogPath, xmlEscape, plistEscape, systemdQuote, defaultRunCommand, managerName, assertManifest, assertDesiredState, readInferenceHostServiceManifest, readInferenceHostServiceDesired, readDesiredAcrossAtomicReplacement, writeDesired, runtimeEnvironment, serviceArguments, windowsTaskXml, systemdUnit, launchAgentPlist, InferenceHostServiceManager, appendServiceLog, spawnServiceChild, runInferenceHostServiceSupervisor;
|
|
29966
|
+
var SERVICE_NAME, SYSTEMD_UNIT, LAUNCHD_LABEL, SERVICE_COOPERATIVE_STOP_SECONDS, isWindowsSubsystemForLinux, inferenceHostServiceManifestPath, inferenceHostServiceDesiredPath, inferenceHostServiceLogPath, xmlEscape, plistEscape, systemdQuote, defaultRunCommand, managerName, assertManifest, assertDesiredState, readInferenceHostServiceManifest, readInferenceHostServiceDesired, readDesiredAcrossAtomicReplacement, writeDesired, runtimeEnvironment, serviceArguments, windowsOwnedCommandLine, vbScriptString, windowsServiceLauncher, windowsTaskXml, systemdUnit, launchAgentPlist, InferenceHostServiceManager, appendServiceLog, spawnServiceChild, runInferenceHostServiceSupervisor;
|
|
29829
29967
|
var init_service = __esm({
|
|
29830
29968
|
"lib/inference-host/service.ts"() {
|
|
29831
29969
|
"use strict";
|
|
@@ -29970,7 +30108,20 @@ var init_service = __esm({
|
|
|
29970
30108
|
"--service-manifest",
|
|
29971
30109
|
manifestPath
|
|
29972
30110
|
];
|
|
29973
|
-
|
|
30111
|
+
windowsOwnedCommandLine = (values) => {
|
|
30112
|
+
if (values.some((value) => value.includes('"') || value.includes("\0"))) {
|
|
30113
|
+
throw new Error("Windows inference-host service paths contain unsupported characters.");
|
|
30114
|
+
}
|
|
30115
|
+
return values.map((value) => `"${value}"`).join(" ");
|
|
30116
|
+
};
|
|
30117
|
+
vbScriptString = (value) => `"${value.replaceAll('"', '""')}"`;
|
|
30118
|
+
windowsServiceLauncher = (executable, args) => `Option Explicit\r
|
|
30119
|
+
Dim shell, exitCode\r
|
|
30120
|
+
Set shell = CreateObject("WScript.Shell")\r
|
|
30121
|
+
exitCode = shell.Run(${vbScriptString(windowsOwnedCommandLine([executable, ...args]))}, 0, True)\r
|
|
30122
|
+
WScript.Quit exitCode\r
|
|
30123
|
+
`;
|
|
30124
|
+
windowsTaskXml = (launcherPath, windowsDirectory, username) => `<?xml version="1.0" encoding="UTF-16"?>
|
|
29974
30125
|
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
29975
30126
|
<RegistrationInfo><Description>${xmlEscape(SERVICE_NAME)}</Description></RegistrationInfo>
|
|
29976
30127
|
<Triggers>
|
|
@@ -29984,13 +30135,14 @@ var init_service = __esm({
|
|
|
29984
30135
|
<Principals><Principal id="Author"><UserId>${xmlEscape(username)}</UserId><LogonType>InteractiveToken</LogonType><RunLevel>LeastPrivilege</RunLevel></Principal></Principals>
|
|
29985
30136
|
<Settings>
|
|
29986
30137
|
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
30138
|
+
<Hidden>true</Hidden>
|
|
29987
30139
|
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
29988
30140
|
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
29989
30141
|
<StartWhenAvailable>true</StartWhenAvailable>
|
|
29990
30142
|
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
|
|
29991
30143
|
<RestartOnFailure><Interval>PT1M</Interval><Count>255</Count></RestartOnFailure>
|
|
29992
30144
|
</Settings>
|
|
29993
|
-
<Actions Context="Author"><Exec><Command>${xmlEscape(
|
|
30145
|
+
<Actions Context="Author"><Exec><Command>${xmlEscape(`${windowsDirectory}\\System32\\wscript.exe`)}</Command><Arguments>${xmlEscape(`//B //NoLogo "${launcherPath}"`)}</Arguments></Exec></Actions>
|
|
29994
30146
|
</Task>
|
|
29995
30147
|
`;
|
|
29996
30148
|
systemdUnit = (executable, args) => `[Unit]
|
|
@@ -30031,6 +30183,7 @@ WantedBy=default.target
|
|
|
30031
30183
|
this.executable = resolve4(dependencies.executable ?? process.execPath);
|
|
30032
30184
|
this.script = resolve4(dependencies.script ?? process.argv[1] ?? "");
|
|
30033
30185
|
this.username = dependencies.username ?? ([process.env.USERDOMAIN, process.env.USERNAME].filter(Boolean).join("\\") || process.env.USER || "");
|
|
30186
|
+
this.windowsDirectory = (dependencies.windowsDirectory ?? process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows").replace(/[\\/]+$/u, "");
|
|
30034
30187
|
this.runCommand = dependencies.runCommand ?? defaultRunCommand;
|
|
30035
30188
|
this.now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
|
|
30036
30189
|
this.sleep = dependencies.sleep ?? (async (milliseconds) => {
|
|
@@ -30096,6 +30249,9 @@ WantedBy=default.target
|
|
|
30096
30249
|
if (this.platform === "darwin") return join5(this.home, "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
30097
30250
|
return join5(this.home, ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
30098
30251
|
}
|
|
30252
|
+
windowsLauncherPath() {
|
|
30253
|
+
return `${this.config.statePath}.service-launcher.vbs`;
|
|
30254
|
+
}
|
|
30099
30255
|
async managerCommand(action) {
|
|
30100
30256
|
const definition = this.definitionPath();
|
|
30101
30257
|
if (this.platform === "win32") {
|
|
@@ -30157,7 +30313,7 @@ WantedBy=default.target
|
|
|
30157
30313
|
runtime_environment: runtimeEnvironment(this.config)
|
|
30158
30314
|
});
|
|
30159
30315
|
const args = serviceArguments(this.script, this.manifestPath());
|
|
30160
|
-
const definition = this.platform === "win32" ? windowsTaskXml(this.
|
|
30316
|
+
const definition = this.platform === "win32" ? windowsTaskXml(this.windowsLauncherPath(), this.windowsDirectory, this.username) : this.platform === "darwin" ? launchAgentPlist(this.executable, args, this.logPath()) : systemdUnit(this.executable, args);
|
|
30161
30317
|
let managerInstallAttempted = false;
|
|
30162
30318
|
try {
|
|
30163
30319
|
await writeAtomicInferencePrivateFile(this.manifestPath(), `${JSON.stringify(manifest, null, 2)}
|
|
@@ -30165,6 +30321,10 @@ WantedBy=default.target
|
|
|
30165
30321
|
await writeDesired(this.desiredPath(), options.startImmediately !== false, this.now());
|
|
30166
30322
|
await mkdir3(dirname4(this.definitionPath()), { recursive: true, mode: 448 });
|
|
30167
30323
|
if (this.platform === "win32") {
|
|
30324
|
+
await writeAtomicInferencePrivateFile(
|
|
30325
|
+
this.windowsLauncherPath(),
|
|
30326
|
+
windowsServiceLauncher(this.executable, args)
|
|
30327
|
+
);
|
|
30168
30328
|
await writeFile2(this.definitionPath(), `\uFEFF${definition}`, {
|
|
30169
30329
|
encoding: "utf16le",
|
|
30170
30330
|
mode: 384
|
|
@@ -30205,6 +30365,9 @@ ${cleanup.stderr}`)) {
|
|
|
30205
30365
|
}
|
|
30206
30366
|
}
|
|
30207
30367
|
await rm4(this.definitionPath(), { force: true }).catch(() => void 0);
|
|
30368
|
+
if (this.platform === "win32") {
|
|
30369
|
+
await rm4(this.windowsLauncherPath(), { force: true }).catch(() => void 0);
|
|
30370
|
+
}
|
|
30208
30371
|
await rm4(this.manifestPath(), { force: true }).catch(() => void 0);
|
|
30209
30372
|
await rm4(this.desiredPath(), { force: true }).catch(() => void 0);
|
|
30210
30373
|
if (this.platform === "linux") {
|
|
@@ -30321,6 +30484,7 @@ ${result2.stderr}`)) {
|
|
|
30321
30484
|
throw new Error(`Background service uninstall failed: ${result2.stderr.trim()}`);
|
|
30322
30485
|
}
|
|
30323
30486
|
await rm4(this.definitionPath(), { force: true });
|
|
30487
|
+
if (this.platform === "win32") await rm4(this.windowsLauncherPath(), { force: true });
|
|
30324
30488
|
if (this.platform === "linux") await this.runCommand("systemctl", ["--user", "daemon-reload"]);
|
|
30325
30489
|
await rm4(this.manifestPath(), { force: true });
|
|
30326
30490
|
await rm4(this.desiredPath(), { force: true });
|
|
@@ -30356,11 +30520,18 @@ ${result2.stderr}`)) {
|
|
|
30356
30520
|
const startedAt = Date.now();
|
|
30357
30521
|
const log = createWriteStream(manifest.log_path, { flags: "a", mode: 384 });
|
|
30358
30522
|
return await new Promise((resolvePromise, reject) => {
|
|
30523
|
+
let stdout = "";
|
|
30359
30524
|
const child = spawn5(manifest.executable, args, {
|
|
30360
30525
|
env: { ...process.env, ...manifest.runtime_environment },
|
|
30361
30526
|
windowsHide: true,
|
|
30362
|
-
stdio: ["ignore",
|
|
30527
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
30528
|
+
});
|
|
30529
|
+
child.stdout.on("data", (chunk) => {
|
|
30530
|
+
const text = chunk.toString("utf8");
|
|
30531
|
+
log.write(text);
|
|
30532
|
+
stdout = `${stdout}${text}`.slice(-65536);
|
|
30363
30533
|
});
|
|
30534
|
+
child.stderr.on("data", (chunk) => log.write(chunk));
|
|
30364
30535
|
const onAbort = () => child.kill("SIGTERM");
|
|
30365
30536
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
30366
30537
|
child.once("error", (error48) => {
|
|
@@ -30371,7 +30542,24 @@ ${result2.stderr}`)) {
|
|
|
30371
30542
|
child.once("exit", (code) => {
|
|
30372
30543
|
signal.removeEventListener("abort", onAbort);
|
|
30373
30544
|
log.end();
|
|
30374
|
-
|
|
30545
|
+
let drainReason = null;
|
|
30546
|
+
for (const line of stdout.trim().split("\n").reverse()) {
|
|
30547
|
+
try {
|
|
30548
|
+
const parsed = JSON.parse(line);
|
|
30549
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && typeof parsed.drain_reason === "string" && /^[a-z0-9_]{1,96}$/u.test(
|
|
30550
|
+
parsed.drain_reason
|
|
30551
|
+
)) {
|
|
30552
|
+
drainReason = parsed.drain_reason;
|
|
30553
|
+
break;
|
|
30554
|
+
}
|
|
30555
|
+
} catch {
|
|
30556
|
+
}
|
|
30557
|
+
}
|
|
30558
|
+
resolvePromise({
|
|
30559
|
+
exitCode: code ?? 1,
|
|
30560
|
+
uptimeMs: Date.now() - startedAt,
|
|
30561
|
+
drainReason
|
|
30562
|
+
});
|
|
30375
30563
|
});
|
|
30376
30564
|
});
|
|
30377
30565
|
};
|
|
@@ -30421,6 +30609,7 @@ ${result2.stderr}`)) {
|
|
|
30421
30609
|
await appendServiceLog(manifest.log_path, "worker_exited", {
|
|
30422
30610
|
exit_code: result2.exitCode,
|
|
30423
30611
|
uptime_ms: result2.uptimeMs,
|
|
30612
|
+
drain_reason: result2.drainReason ?? null,
|
|
30424
30613
|
retry_after_ms: retryAfterMs
|
|
30425
30614
|
});
|
|
30426
30615
|
await sleep4(retryAfterMs);
|
|
@@ -31906,7 +32095,21 @@ Waiting for approval...
|
|
|
31906
32095
|
...dependencies,
|
|
31907
32096
|
registerLifecycleSignalHandlers: unregister
|
|
31908
32097
|
}, warnings);
|
|
31909
|
-
|
|
32098
|
+
let drainReason = null;
|
|
32099
|
+
try {
|
|
32100
|
+
const summary = JSON.parse(result2.stdout);
|
|
32101
|
+
if (summary && typeof summary === "object" && !Array.isArray(summary) && typeof summary.drain_reason === "string" && /^[a-z0-9_]{1,96}$/u.test(
|
|
32102
|
+
summary.drain_reason
|
|
32103
|
+
)) {
|
|
32104
|
+
drainReason = summary.drain_reason;
|
|
32105
|
+
}
|
|
32106
|
+
} catch {
|
|
32107
|
+
}
|
|
32108
|
+
return {
|
|
32109
|
+
exitCode: result2.exitCode,
|
|
32110
|
+
uptimeMs: Date.now() - startedAt,
|
|
32111
|
+
drainReason
|
|
32112
|
+
};
|
|
31910
32113
|
}
|
|
31911
32114
|
}
|
|
31912
32115
|
);
|