@vtxmacro/cli 2026.8.36 → 2026.8.37
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 +595 -120
- 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.37",
|
|
42
42
|
codex_package_name: "@openai/codex",
|
|
43
43
|
codex_version: "0.147.0",
|
|
44
44
|
platforms: {
|
|
@@ -29047,7 +29047,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
|
|
|
29047
29047
|
envelopePublicKey: options.envelopePublicKey
|
|
29048
29048
|
};
|
|
29049
29049
|
}
|
|
29050
|
-
var import_ajv, RUNTIME_RECEIPT_SCHEMA_VERSION, ATTEMPT_RECEIPT_SCHEMA_VERSION, DEFAULT_ADVERTISEMENT_TTL_MS, DEFAULT_ADVERTISEMENT_REFRESH_LEAD_MS, DEFAULT_HOST_HEARTBEAT_MS, DEFAULT_PROVIDER_RATE_LIMIT_REFRESH_MS, DEFAULT_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, MIN_SLEEP_MS, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, UNBOUNDED_AVAILABLE_SLOTS, buildCodexInferenceAdvertisedModels, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, providerWeeklyQuotaFromRateLimits, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, membershipFailureDisposition, safeFailureCode, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner;
|
|
29050
|
+
var import_ajv, RUNTIME_RECEIPT_SCHEMA_VERSION, ATTEMPT_RECEIPT_SCHEMA_VERSION, DEFAULT_ADVERTISEMENT_TTL_MS, DEFAULT_ADVERTISEMENT_REFRESH_LEAD_MS, DEFAULT_HOST_HEARTBEAT_MS, DEFAULT_PROVIDER_RATE_LIMIT_REFRESH_MS, DEFAULT_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, MIN_SLEEP_MS, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, UNBOUNDED_AVAILABLE_SLOTS, buildCodexInferenceAdvertisedModels, summarizeInferenceHostRuntimeRecovery, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, providerWeeklyQuotaFromRateLimits, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, membershipFailureDisposition, safeFailureCode, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner;
|
|
29051
29051
|
var init_runner = __esm({
|
|
29052
29052
|
"lib/inference-host/runner.ts"() {
|
|
29053
29053
|
"use strict";
|
|
@@ -29104,6 +29104,35 @@ var init_runner = __esm({
|
|
|
29104
29104
|
}
|
|
29105
29105
|
return models;
|
|
29106
29106
|
};
|
|
29107
|
+
summarizeInferenceHostRuntimeRecovery = (receipt) => {
|
|
29108
|
+
const phaseCounts = {
|
|
29109
|
+
claimed: 0,
|
|
29110
|
+
started: 0,
|
|
29111
|
+
dispatched: 0,
|
|
29112
|
+
terminal_pending: 0
|
|
29113
|
+
};
|
|
29114
|
+
const terminalOperations = [];
|
|
29115
|
+
for (const attempt of Object.values(receipt.attempts)) {
|
|
29116
|
+
phaseCounts[attempt.phase] += 1;
|
|
29117
|
+
const terminal = attempt.terminal_request;
|
|
29118
|
+
if (!terminal) continue;
|
|
29119
|
+
const failed = terminal.schema_version === "external_inference_job_fail_v1";
|
|
29120
|
+
terminalOperations.push({
|
|
29121
|
+
job_id: attempt.job_id,
|
|
29122
|
+
attempt_id: attempt.attempt_id,
|
|
29123
|
+
operation_kind: failed ? "fail" : "complete",
|
|
29124
|
+
dispatch_outcome: terminal.outcome.dispatch_outcome,
|
|
29125
|
+
failure_category: failed ? terminal.failure_category : null,
|
|
29126
|
+
failure_code: failed ? terminal.failure_code : null,
|
|
29127
|
+
retryable: failed ? terminal.retryable : null
|
|
29128
|
+
});
|
|
29129
|
+
}
|
|
29130
|
+
terminalOperations.sort((left, right) => left.job_id.localeCompare(right.job_id) || left.attempt_id.localeCompare(right.attempt_id));
|
|
29131
|
+
return {
|
|
29132
|
+
phase_counts: phaseCounts,
|
|
29133
|
+
terminal_operations: terminalOperations
|
|
29134
|
+
};
|
|
29135
|
+
};
|
|
29107
29136
|
FileInferenceHostRuntimeReceiptStore = class {
|
|
29108
29137
|
constructor(path, readPrivateFile = readInferencePrivateFile) {
|
|
29109
29138
|
this.path = path;
|
|
@@ -29744,6 +29773,22 @@ var init_runner = __esm({
|
|
|
29744
29773
|
} catch {
|
|
29745
29774
|
}
|
|
29746
29775
|
};
|
|
29776
|
+
const emitTerminalRecoveryFailure = (recovery, error48) => {
|
|
29777
|
+
const cause = error48 instanceof InferenceHostRunnerError && error48.code === "terminal_outcome_unconfirmed" && error48.cause ? error48.cause : error48;
|
|
29778
|
+
const rawCode = cause instanceof ExternalInferenceMcpError || cause instanceof InferenceHostRunnerError || cause instanceof CodexAppServerError ? cause.code : "terminal_recovery_failed";
|
|
29779
|
+
const terminal = recovery.terminal_request;
|
|
29780
|
+
emitDiagnostic("terminal_recovery_failed", {
|
|
29781
|
+
job_id: recovery.job_id,
|
|
29782
|
+
attempt_id: recovery.attempt_id,
|
|
29783
|
+
attempt_phase: recovery.phase,
|
|
29784
|
+
terminal_operation: terminal?.schema_version === "external_inference_job_fail_v1" ? "fail" : "complete",
|
|
29785
|
+
error_code: safeFailureCode(rawCode, "terminal_recovery_failed"),
|
|
29786
|
+
retryable: retryableRemoteError(cause),
|
|
29787
|
+
definitively_not_applied: Boolean(
|
|
29788
|
+
cause && typeof cause === "object" && "definitivelyNotApplied" in cause && cause.definitivelyNotApplied === true
|
|
29789
|
+
)
|
|
29790
|
+
});
|
|
29791
|
+
};
|
|
29747
29792
|
const accountKey = inferenceCredentialAccountKey({
|
|
29748
29793
|
issuer: localState.issuer,
|
|
29749
29794
|
clientId: localState.client_id,
|
|
@@ -30009,17 +30054,6 @@ var init_runner = __esm({
|
|
|
30009
30054
|
let nextClaimAt = Math.max(now(), providerRetryAtMs ?? 0);
|
|
30010
30055
|
let pendingClaimPromotions = 0;
|
|
30011
30056
|
let onceClaimed = false;
|
|
30012
|
-
emitDiagnostic("runtime_started", {
|
|
30013
|
-
max_concurrency: settings.maxConcurrency,
|
|
30014
|
-
active_attempts: active.size,
|
|
30015
|
-
provider_cooldown_reason: providerCooldownReason,
|
|
30016
|
-
provider_cooldown_until: providerRetryAtMs === null ? null : isoAt(providerRetryAtMs),
|
|
30017
|
-
provider_weekly_quota: providerWeeklyQuotaFromRateLimits(
|
|
30018
|
-
providerRateLimits,
|
|
30019
|
-
providerRateLimitsObservedAtMs,
|
|
30020
|
-
now()
|
|
30021
|
-
)
|
|
30022
|
-
});
|
|
30023
30057
|
const recoveryQueue = [];
|
|
30024
30058
|
const launchClaim = (claim, recovery, claimRequest) => {
|
|
30025
30059
|
if (!recovery) {
|
|
@@ -30114,6 +30148,10 @@ var init_runner = __esm({
|
|
|
30114
30148
|
}
|
|
30115
30149
|
}).catch((error48) => {
|
|
30116
30150
|
failed += 1;
|
|
30151
|
+
const recovery2 = receipt.attempts[attemptId];
|
|
30152
|
+
if (recovery2?.phase === "terminal_pending") {
|
|
30153
|
+
emitTerminalRecoveryFailure(recovery2, error48);
|
|
30154
|
+
}
|
|
30117
30155
|
requestDrain(controlPlaneFatal(error48) ? "authority_lost" : "attempt_terminal_unconfirmed");
|
|
30118
30156
|
}).finally(() => {
|
|
30119
30157
|
settleClaimPromotion();
|
|
@@ -30169,6 +30207,7 @@ var init_runner = __esm({
|
|
|
30169
30207
|
await this.dependencies.codexAdapter.acknowledgeAttempt?.(recovery.attempt_id);
|
|
30170
30208
|
await removeRecoveredAttempt(recovery.attempt_id);
|
|
30171
30209
|
} catch (error48) {
|
|
30210
|
+
emitTerminalRecoveryFailure(recovery, error48);
|
|
30172
30211
|
requestDrain(controlPlaneFatal(error48) ? "authority_lost" : "attempt_terminal_unconfirmed");
|
|
30173
30212
|
break;
|
|
30174
30213
|
}
|
|
@@ -30176,6 +30215,19 @@ var init_runner = __esm({
|
|
|
30176
30215
|
}
|
|
30177
30216
|
recoveryQueue.push(recovery);
|
|
30178
30217
|
}
|
|
30218
|
+
if (!drainRequested) {
|
|
30219
|
+
emitDiagnostic("runtime_started", {
|
|
30220
|
+
max_concurrency: settings.maxConcurrency,
|
|
30221
|
+
active_attempts: active.size,
|
|
30222
|
+
provider_cooldown_reason: providerCooldownReason,
|
|
30223
|
+
provider_cooldown_until: providerRetryAtMs === null ? null : isoAt(providerRetryAtMs),
|
|
30224
|
+
provider_weekly_quota: providerWeeklyQuotaFromRateLimits(
|
|
30225
|
+
providerRateLimits,
|
|
30226
|
+
providerRateLimitsObservedAtMs,
|
|
30227
|
+
now()
|
|
30228
|
+
)
|
|
30229
|
+
});
|
|
30230
|
+
}
|
|
30179
30231
|
while (!drainRequested && recoveryQueue.length > 0 && (settings.maxConcurrency === null || active.size < settings.maxConcurrency)) {
|
|
30180
30232
|
const recovery = recoveryQueue.shift();
|
|
30181
30233
|
launchClaim(recovery.claim, recovery);
|
|
@@ -30908,11 +30960,12 @@ var init_runner = __esm({
|
|
|
30908
30960
|
|
|
30909
30961
|
// lib/inference-host/service.ts
|
|
30910
30962
|
import { spawn as spawn5 } from "node:child_process";
|
|
30963
|
+
import { randomUUID } from "node:crypto";
|
|
30911
30964
|
import { createWriteStream, readFileSync } from "node:fs";
|
|
30912
30965
|
import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as rm4, writeFile as writeFile2 } from "node:fs/promises";
|
|
30913
30966
|
import { homedir as homedir2 } from "node:os";
|
|
30914
30967
|
import { dirname as dirname4, join as join5, resolve as resolve4 } from "node:path";
|
|
30915
|
-
var SERVICE_NAME, SYSTEMD_UNIT, LAUNCHD_LABEL, SERVICE_COOPERATIVE_STOP_SECONDS, inferenceHostServiceChildEnvironment, isWindowsSubsystemForLinux, inferenceHostServiceManifestPath, inferenceHostServiceDesiredPath, inferenceHostServiceLogPath, xmlEscape, plistEscape, systemdQuote, defaultRunCommand, managerName, assertRuntimeEnvironment, withoutConcurrencyLimit, assertServicePath, assertWorker, assertManifest, assertDesiredState, readInferenceHostServiceManifest, readInferenceHostServiceDesired, readDesiredAcrossAtomicReplacement, writeDesired, runtimeEnvironment, serviceArguments, windowsOwnedCommandLine, vbScriptString, windowsServiceLauncher, windowsTaskXml, systemdUnit, launchAgentPlist, InferenceHostServiceManager, appendServiceLog,
|
|
30968
|
+
var SERVICE_NAME, SYSTEMD_UNIT, LAUNCHD_LABEL, SERVICE_COOPERATIVE_STOP_SECONDS, INFERENCE_HOST_SERVICE_DRAIN_COMMAND, inferenceHostServiceChildEnvironment, isWindowsSubsystemForLinux, inferenceHostServiceManifestPath, inferenceHostServiceDesiredPath, inferenceHostServiceLogPath, inferenceHostServiceRuntimePath, xmlEscape, plistEscape, systemdQuote, defaultRunCommand, managerName, assertRuntimeEnvironment, withoutConcurrencyLimit, assertServicePath, manifestGeneration, assertWorker, assertManifest, assertServiceRuntimeState, assertDesiredState, readInferenceHostServiceManifest, readManifestAcrossAtomicReplacement, readInferenceHostServiceRuntime, readRuntimeAcrossAtomicReplacement, readInferenceHostServiceDesired, readDesiredAcrossAtomicReplacement, writeDesired, runtimeEnvironment, serviceArguments, windowsOwnedCommandLine, vbScriptString, windowsServiceLauncher, windowsTaskXml, systemdUnit, launchAgentPlist, sameWorker, sameServiceDefinition, sameWorkerSet, InferenceHostServiceManager, appendServiceLog, spawnInferenceHostServiceChild, runInferenceHostServiceSupervisor;
|
|
30916
30969
|
var init_service = __esm({
|
|
30917
30970
|
"lib/inference-host/service.ts"() {
|
|
30918
30971
|
"use strict";
|
|
@@ -30921,6 +30974,7 @@ var init_service = __esm({
|
|
|
30921
30974
|
SYSTEMD_UNIT = "vtx-inference-host.service";
|
|
30922
30975
|
LAUNCHD_LABEL = "com.vtxmacro.inference-host";
|
|
30923
30976
|
SERVICE_COOPERATIVE_STOP_SECONDS = 75;
|
|
30977
|
+
INFERENCE_HOST_SERVICE_DRAIN_COMMAND = "vtx-inference-host-service-drain-v1";
|
|
30924
30978
|
inferenceHostServiceChildEnvironment = (runtimeEnvironment2, inheritedEnvironment = process.env) => {
|
|
30925
30979
|
const environment = { ...inheritedEnvironment };
|
|
30926
30980
|
for (const key of Object.keys(environment)) {
|
|
@@ -30928,7 +30982,11 @@ var init_service = __esm({
|
|
|
30928
30982
|
delete environment[key];
|
|
30929
30983
|
}
|
|
30930
30984
|
}
|
|
30931
|
-
return {
|
|
30985
|
+
return {
|
|
30986
|
+
...environment,
|
|
30987
|
+
...runtimeEnvironment2,
|
|
30988
|
+
VTX_INFERENCE_HOST_SERVICE_CHILD: "1"
|
|
30989
|
+
};
|
|
30932
30990
|
};
|
|
30933
30991
|
isWindowsSubsystemForLinux = (env = process.env, kernelRelease) => Boolean(
|
|
30934
30992
|
String(env.WSL_INTEROP || "").trim() || String(env.WSL_DISTRO_NAME || "").trim() || /microsoft/iu.test(kernelRelease ?? (() => {
|
|
@@ -30942,6 +31000,7 @@ var init_service = __esm({
|
|
|
30942
31000
|
inferenceHostServiceManifestPath = (config2) => `${config2.supervisorStatePath}.service.json`;
|
|
30943
31001
|
inferenceHostServiceDesiredPath = (config2) => `${config2.supervisorStatePath}.service-desired.json`;
|
|
30944
31002
|
inferenceHostServiceLogPath = (config2) => `${config2.supervisorStatePath}.service.log`;
|
|
31003
|
+
inferenceHostServiceRuntimePath = (config2) => `${config2.supervisorStatePath}.service-runtime.json`;
|
|
30945
31004
|
xmlEscape = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30946
31005
|
plistEscape = xmlEscape;
|
|
30947
31006
|
systemdQuote = (value) => `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("%", "%%")}"`;
|
|
@@ -30992,6 +31051,7 @@ var init_service = __esm({
|
|
|
30992
31051
|
}
|
|
30993
31052
|
return value;
|
|
30994
31053
|
};
|
|
31054
|
+
manifestGeneration = (value, installedAt) => typeof value === "string" && /^[A-Za-z0-9._:-]{1,160}$/u.test(value) ? value : `legacy:${installedAt}`;
|
|
30995
31055
|
assertWorker = (value) => {
|
|
30996
31056
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
30997
31057
|
throw new Error("Inference-host service worker is invalid.");
|
|
@@ -31032,6 +31092,7 @@ var init_service = __esm({
|
|
|
31032
31092
|
});
|
|
31033
31093
|
return {
|
|
31034
31094
|
schema_version: "vtx_inference_service_v3",
|
|
31095
|
+
generation: manifestGeneration(void 0, legacy.installed_at),
|
|
31035
31096
|
installed_at: legacy.installed_at,
|
|
31036
31097
|
executable: assertServicePath(legacy.executable),
|
|
31037
31098
|
script: assertServicePath(legacy.script),
|
|
@@ -31065,6 +31126,7 @@ var init_service = __esm({
|
|
|
31065
31126
|
}
|
|
31066
31127
|
return {
|
|
31067
31128
|
schema_version: "vtx_inference_service_v3",
|
|
31129
|
+
generation: manifestGeneration(void 0, legacy.installed_at),
|
|
31068
31130
|
installed_at: legacy.installed_at,
|
|
31069
31131
|
executable: assertServicePath(legacy.executable),
|
|
31070
31132
|
script: assertServicePath(legacy.script),
|
|
@@ -31082,6 +31144,34 @@ var init_service = __esm({
|
|
|
31082
31144
|
if (new Set(workers.map((worker) => worker.instance_name)).size !== workers.length) {
|
|
31083
31145
|
throw new Error("Inference-host service worker names must be unique.");
|
|
31084
31146
|
}
|
|
31147
|
+
return {
|
|
31148
|
+
...record2,
|
|
31149
|
+
generation: manifestGeneration(record2.generation, String(record2.installed_at)),
|
|
31150
|
+
workers
|
|
31151
|
+
};
|
|
31152
|
+
};
|
|
31153
|
+
assertServiceRuntimeState = (value) => {
|
|
31154
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
31155
|
+
throw new Error("Inference-host service runtime state is invalid.");
|
|
31156
|
+
}
|
|
31157
|
+
const record2 = value;
|
|
31158
|
+
if (record2.schema_version !== "vtx_inference_service_runtime_v1" || typeof record2.manifest_generation !== "string" || record2.rejected_manifest_generation !== void 0 && record2.rejected_manifest_generation !== null && typeof record2.rejected_manifest_generation !== "string" || typeof record2.updated_at !== "string" || !Number.isFinite(Date.parse(record2.updated_at)) || !Array.isArray(record2.workers)) {
|
|
31159
|
+
throw new Error("Inference-host service runtime state is invalid.");
|
|
31160
|
+
}
|
|
31161
|
+
const workers = record2.workers.map((worker) => {
|
|
31162
|
+
if (!worker || typeof worker !== "object" || Array.isArray(worker)) {
|
|
31163
|
+
throw new Error("Inference-host service worker runtime state is invalid.");
|
|
31164
|
+
}
|
|
31165
|
+
const item = worker;
|
|
31166
|
+
if (typeof item.instance_name !== "string" || !["starting", "running", "failed", "draining"].includes(String(item.state)) || item.error !== null && typeof item.error !== "string") {
|
|
31167
|
+
throw new Error("Inference-host service worker runtime state is invalid.");
|
|
31168
|
+
}
|
|
31169
|
+
return {
|
|
31170
|
+
instance_name: item.instance_name,
|
|
31171
|
+
state: item.state,
|
|
31172
|
+
error: item.error
|
|
31173
|
+
};
|
|
31174
|
+
});
|
|
31085
31175
|
return { ...record2, workers };
|
|
31086
31176
|
};
|
|
31087
31177
|
assertDesiredState = (value) => {
|
|
@@ -31104,6 +31194,42 @@ var init_service = __esm({
|
|
|
31104
31194
|
throw error48;
|
|
31105
31195
|
}
|
|
31106
31196
|
};
|
|
31197
|
+
readManifestAcrossAtomicReplacement = async (path) => {
|
|
31198
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
31199
|
+
try {
|
|
31200
|
+
return await readInferenceHostServiceManifest(path);
|
|
31201
|
+
} catch (error48) {
|
|
31202
|
+
if (!(error48 instanceof Error) || !error48.message.includes("changed while it was opened")) {
|
|
31203
|
+
throw error48;
|
|
31204
|
+
}
|
|
31205
|
+
}
|
|
31206
|
+
}
|
|
31207
|
+
return await readInferenceHostServiceManifest(path);
|
|
31208
|
+
};
|
|
31209
|
+
readInferenceHostServiceRuntime = async (path) => {
|
|
31210
|
+
const raw = await readInferencePrivateFile(path, "Inference-host service runtime state");
|
|
31211
|
+
if (raw === null) return null;
|
|
31212
|
+
try {
|
|
31213
|
+
return assertServiceRuntimeState(JSON.parse(raw));
|
|
31214
|
+
} catch (error48) {
|
|
31215
|
+
if (error48 instanceof SyntaxError) {
|
|
31216
|
+
throw new Error("Inference-host service runtime state is not valid JSON.");
|
|
31217
|
+
}
|
|
31218
|
+
throw error48;
|
|
31219
|
+
}
|
|
31220
|
+
};
|
|
31221
|
+
readRuntimeAcrossAtomicReplacement = async (path) => {
|
|
31222
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
31223
|
+
try {
|
|
31224
|
+
return await readInferenceHostServiceRuntime(path);
|
|
31225
|
+
} catch (error48) {
|
|
31226
|
+
if (!(error48 instanceof Error) || !error48.message.includes("changed while it was opened")) {
|
|
31227
|
+
throw error48;
|
|
31228
|
+
}
|
|
31229
|
+
}
|
|
31230
|
+
}
|
|
31231
|
+
return await readInferenceHostServiceRuntime(path);
|
|
31232
|
+
};
|
|
31107
31233
|
readInferenceHostServiceDesired = async (path) => {
|
|
31108
31234
|
const raw = await readInferencePrivateFile(path, "Inference-host service desired state");
|
|
31109
31235
|
if (raw === null) return false;
|
|
@@ -31226,6 +31352,9 @@ WantedBy=default.target
|
|
|
31226
31352
|
<key>StandardErrorPath</key><string>${plistEscape(logPath)}</string>
|
|
31227
31353
|
</dict></plist>
|
|
31228
31354
|
`;
|
|
31355
|
+
sameWorker = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
31356
|
+
sameServiceDefinition = (left, right) => left.executable === right.executable && left.script === right.script && left.log_path === right.log_path;
|
|
31357
|
+
sameWorkerSet = (left, right) => left.workers.length === right.workers.length && left.workers.every((worker, index) => sameWorker(worker, right.workers[index]));
|
|
31229
31358
|
InferenceHostServiceManager = class {
|
|
31230
31359
|
constructor(config2, dependencies = {}) {
|
|
31231
31360
|
this.config = config2;
|
|
@@ -31242,6 +31371,8 @@ WantedBy=default.target
|
|
|
31242
31371
|
});
|
|
31243
31372
|
this.stopWaitAttempts = dependencies.stopWaitAttempts ?? SERVICE_COOPERATIVE_STOP_SECONDS * 4;
|
|
31244
31373
|
this.startWaitAttempts = dependencies.startWaitAttempts ?? 40;
|
|
31374
|
+
this.reconcileWaitAttempts = dependencies.reconcileWaitAttempts ?? SERVICE_COOPERATIVE_STOP_SECONDS * 4;
|
|
31375
|
+
this.confirmInitialReadiness = dependencies.confirmInitialReadiness ?? true;
|
|
31245
31376
|
this.acquireProcessLock = dependencies.acquireProcessLock ?? acquireInferenceHostProcessLock;
|
|
31246
31377
|
managerName(this.platform);
|
|
31247
31378
|
if (dependencies.platform === void 0 && this.platform === "linux" && isWindowsSubsystemForLinux()) {
|
|
@@ -31259,6 +31390,9 @@ WantedBy=default.target
|
|
|
31259
31390
|
logPath() {
|
|
31260
31391
|
return inferenceHostServiceLogPath(this.config);
|
|
31261
31392
|
}
|
|
31393
|
+
runtimePath() {
|
|
31394
|
+
return inferenceHostServiceRuntimePath(this.config);
|
|
31395
|
+
}
|
|
31262
31396
|
controlLockPath() {
|
|
31263
31397
|
return `${this.config.supervisorProcessLockPath}.service-control`;
|
|
31264
31398
|
}
|
|
@@ -31344,7 +31478,77 @@ WantedBy=default.target
|
|
|
31344
31478
|
}
|
|
31345
31479
|
throw new Error("Background service did not reach an active state within 10 seconds.");
|
|
31346
31480
|
}
|
|
31347
|
-
async
|
|
31481
|
+
async restoreRunningSupervisor(manifest) {
|
|
31482
|
+
const restoredManifest = assertManifest({
|
|
31483
|
+
...manifest,
|
|
31484
|
+
generation: randomUUID(),
|
|
31485
|
+
installed_at: this.now().toISOString()
|
|
31486
|
+
});
|
|
31487
|
+
await writeAtomicInferencePrivateFile(
|
|
31488
|
+
this.manifestPath(),
|
|
31489
|
+
`${JSON.stringify(restoredManifest, null, 2)}
|
|
31490
|
+
`
|
|
31491
|
+
);
|
|
31492
|
+
await writeDesired(this.desiredPath(), true, this.now());
|
|
31493
|
+
const result2 = await this.managerCommand("start");
|
|
31494
|
+
if (result2.exitCode !== 0 && !/already running|in progress|already loaded|service is already loaded/iu.test(`${result2.stdout}
|
|
31495
|
+
${result2.stderr}`)) {
|
|
31496
|
+
throw new Error(`Background service restoration failed: ${result2.stderr.trim()}`);
|
|
31497
|
+
}
|
|
31498
|
+
if (this.platform === "darwin") {
|
|
31499
|
+
const domain2 = `gui/${typeof process.getuid === "function" ? process.getuid() : 0}`;
|
|
31500
|
+
const kicked = await this.runCommand("launchctl", [
|
|
31501
|
+
"kickstart",
|
|
31502
|
+
`${domain2}/${LAUNCHD_LABEL}`
|
|
31503
|
+
]);
|
|
31504
|
+
if (kicked.exitCode !== 0) {
|
|
31505
|
+
throw new Error(`Background service restoration kickstart failed: ${kicked.stderr.trim()}`);
|
|
31506
|
+
}
|
|
31507
|
+
}
|
|
31508
|
+
await this.waitForManagerActive();
|
|
31509
|
+
if (!this.confirmInitialReadiness) return await this.status();
|
|
31510
|
+
const runtime = await this.waitForManifestApplied(restoredManifest);
|
|
31511
|
+
return await this.status(runtime);
|
|
31512
|
+
}
|
|
31513
|
+
async waitForManifestApplied(manifest, targetInstanceName) {
|
|
31514
|
+
let consecutiveReadyObservations = 0;
|
|
31515
|
+
for (let attempt = 0; attempt < this.reconcileWaitAttempts; attempt += 1) {
|
|
31516
|
+
let runtime = null;
|
|
31517
|
+
try {
|
|
31518
|
+
runtime = await readRuntimeAcrossAtomicReplacement(this.runtimePath());
|
|
31519
|
+
} catch (error48) {
|
|
31520
|
+
if (!(error48 instanceof Error) || !error48.message.includes("changed while it was opened")) {
|
|
31521
|
+
throw error48;
|
|
31522
|
+
}
|
|
31523
|
+
}
|
|
31524
|
+
if (runtime?.manifest_generation === manifest.generation) {
|
|
31525
|
+
const configuredNames = manifest.workers.map((worker) => worker.instance_name).sort();
|
|
31526
|
+
const runtimeNames = runtime.workers.map((worker) => worker.instance_name).sort();
|
|
31527
|
+
const exactWorkerSet = JSON.stringify(configuredNames) === JSON.stringify(runtimeNames);
|
|
31528
|
+
const target = targetInstanceName ? runtime.workers.find((worker) => worker.instance_name === targetInstanceName) : null;
|
|
31529
|
+
const allReady = runtime.workers.every((worker) => worker.state === "running");
|
|
31530
|
+
if (exactWorkerSet && (targetInstanceName ? target?.state === "running" : allReady)) {
|
|
31531
|
+
consecutiveReadyObservations += 1;
|
|
31532
|
+
if (consecutiveReadyObservations >= 2) return runtime;
|
|
31533
|
+
} else {
|
|
31534
|
+
consecutiveReadyObservations = 0;
|
|
31535
|
+
}
|
|
31536
|
+
if (exactWorkerSet && target?.state === "failed") {
|
|
31537
|
+
throw new Error(`Inference-host worker ${targetInstanceName} failed before readiness.`);
|
|
31538
|
+
}
|
|
31539
|
+
} else {
|
|
31540
|
+
consecutiveReadyObservations = 0;
|
|
31541
|
+
}
|
|
31542
|
+
if (runtime?.rejected_manifest_generation === manifest.generation) {
|
|
31543
|
+
throw new Error("Inference-host supervisor rejected the updated worker set.");
|
|
31544
|
+
}
|
|
31545
|
+
await this.sleep(250);
|
|
31546
|
+
}
|
|
31547
|
+
throw new Error(
|
|
31548
|
+
targetInstanceName ? `Inference-host supervisor did not confirm worker ${targetInstanceName} ready before timeout.` : "Inference-host supervisor did not confirm the updated worker set before timeout."
|
|
31549
|
+
);
|
|
31550
|
+
}
|
|
31551
|
+
async registerManifestUnlocked(manifest, desiredRunning, targetInstanceName) {
|
|
31348
31552
|
const args = serviceArguments(manifest.script, this.manifestPath());
|
|
31349
31553
|
const definition = this.platform === "win32" ? windowsTaskXml(this.windowsLauncherPath(), this.windowsDirectory, this.username) : this.platform === "darwin" ? launchAgentPlist(manifest.executable, args, manifest.log_path) : systemdUnit(manifest.executable, args);
|
|
31350
31554
|
let managerInstallAttempted = false;
|
|
@@ -31380,6 +31584,9 @@ ${started.stderr}`)) {
|
|
|
31380
31584
|
throw new Error(`Background service start failed: ${started.stderr.trim()}`);
|
|
31381
31585
|
}
|
|
31382
31586
|
await this.waitForManagerActive();
|
|
31587
|
+
if (this.confirmInitialReadiness) {
|
|
31588
|
+
await this.waitForManifestApplied(manifest, targetInstanceName);
|
|
31589
|
+
}
|
|
31383
31590
|
}
|
|
31384
31591
|
return await this.status();
|
|
31385
31592
|
} catch (error48) {
|
|
@@ -31404,22 +31611,80 @@ ${cleanup.stderr}`)) {
|
|
|
31404
31611
|
}
|
|
31405
31612
|
await rm4(this.manifestPath(), { force: true }).catch(() => void 0);
|
|
31406
31613
|
await rm4(this.desiredPath(), { force: true }).catch(() => void 0);
|
|
31614
|
+
await rm4(this.runtimePath(), { force: true }).catch(() => void 0);
|
|
31407
31615
|
if (this.platform === "linux") {
|
|
31408
31616
|
await this.runCommand("systemctl", ["--user", "daemon-reload"]).catch(() => void 0);
|
|
31409
31617
|
}
|
|
31410
31618
|
throw error48;
|
|
31411
31619
|
}
|
|
31412
31620
|
}
|
|
31413
|
-
async replaceManifestUnlocked(next, desiredRunning) {
|
|
31621
|
+
async replaceManifestUnlocked(next, desiredRunning, targetInstanceName) {
|
|
31414
31622
|
const previous = await readInferenceHostServiceManifest(this.manifestPath());
|
|
31415
31623
|
const previousDesired = previous ? await readInferenceHostServiceDesired(this.desiredPath()) : false;
|
|
31416
|
-
if (previous)
|
|
31624
|
+
if (previous && sameServiceDefinition(previous, next) && sameWorkerSet(previous, next) && previousDesired === desiredRunning) {
|
|
31625
|
+
return await this.status();
|
|
31626
|
+
}
|
|
31627
|
+
if (previous && previousDesired && desiredRunning && sameServiceDefinition(previous, next)) {
|
|
31628
|
+
const current = await this.status();
|
|
31629
|
+
const runtime = await readRuntimeAcrossAtomicReplacement(this.runtimePath()).catch(() => null);
|
|
31630
|
+
if (current.manager_active && runtime?.manifest_generation === previous.generation) {
|
|
31631
|
+
await writeAtomicInferencePrivateFile(
|
|
31632
|
+
this.manifestPath(),
|
|
31633
|
+
`${JSON.stringify(next, null, 2)}
|
|
31634
|
+
`
|
|
31635
|
+
);
|
|
31636
|
+
if (!this.confirmInitialReadiness) return await this.status();
|
|
31637
|
+
try {
|
|
31638
|
+
const confirmedRuntime = await this.waitForManifestApplied(next, targetInstanceName);
|
|
31639
|
+
return await this.status(confirmedRuntime);
|
|
31640
|
+
} catch (error48) {
|
|
31641
|
+
await writeAtomicInferencePrivateFile(
|
|
31642
|
+
this.manifestPath(),
|
|
31643
|
+
`${JSON.stringify(previous, null, 2)}
|
|
31644
|
+
`
|
|
31645
|
+
);
|
|
31646
|
+
try {
|
|
31647
|
+
await this.waitForManifestApplied(
|
|
31648
|
+
previous,
|
|
31649
|
+
targetInstanceName && previous.workers.some(
|
|
31650
|
+
(worker) => worker.instance_name === targetInstanceName
|
|
31651
|
+
) ? targetInstanceName : void 0
|
|
31652
|
+
);
|
|
31653
|
+
} catch (rollbackError) {
|
|
31654
|
+
throw new Error(
|
|
31655
|
+
"Inference-host live reconfiguration failed and rollback was not confirmed.",
|
|
31656
|
+
{ cause: new AggregateError([error48, rollbackError]) }
|
|
31657
|
+
);
|
|
31658
|
+
}
|
|
31659
|
+
throw new Error(
|
|
31660
|
+
"Inference-host live reconfiguration failed; the previous worker set was restored.",
|
|
31661
|
+
{ cause: error48 }
|
|
31662
|
+
);
|
|
31663
|
+
}
|
|
31664
|
+
}
|
|
31665
|
+
}
|
|
31666
|
+
if (previous) {
|
|
31667
|
+
try {
|
|
31668
|
+
await this.uninstallUnlocked();
|
|
31669
|
+
} catch (error48) {
|
|
31670
|
+
throw new Error(
|
|
31671
|
+
"Inference-host service reconfiguration could not stop the previous supervisor; its desired state was restored.",
|
|
31672
|
+
{ cause: error48 }
|
|
31673
|
+
);
|
|
31674
|
+
}
|
|
31675
|
+
}
|
|
31417
31676
|
try {
|
|
31418
|
-
return await this.registerManifestUnlocked(next, desiredRunning);
|
|
31677
|
+
return await this.registerManifestUnlocked(next, desiredRunning, targetInstanceName);
|
|
31419
31678
|
} catch (error48) {
|
|
31420
31679
|
if (!previous) throw error48;
|
|
31421
31680
|
try {
|
|
31422
|
-
await this.registerManifestUnlocked(
|
|
31681
|
+
await this.registerManifestUnlocked(
|
|
31682
|
+
previous,
|
|
31683
|
+
previousDesired,
|
|
31684
|
+
targetInstanceName && previous.workers.some(
|
|
31685
|
+
(worker) => worker.instance_name === targetInstanceName
|
|
31686
|
+
) ? targetInstanceName : void 0
|
|
31687
|
+
);
|
|
31423
31688
|
} catch (rollbackError) {
|
|
31424
31689
|
throw new Error(
|
|
31425
31690
|
"Inference-host service reconfiguration failed and the previous supervisor could not be restored.",
|
|
@@ -31476,6 +31741,7 @@ ${cleanup.stderr}`)) {
|
|
|
31476
31741
|
].sort((left, right) => left.instance_name.localeCompare(right.instance_name));
|
|
31477
31742
|
const manifest = assertManifest({
|
|
31478
31743
|
schema_version: "vtx_inference_service_v3",
|
|
31744
|
+
generation: randomUUID(),
|
|
31479
31745
|
installed_at: this.now().toISOString(),
|
|
31480
31746
|
executable: this.executable,
|
|
31481
31747
|
script: this.script,
|
|
@@ -31484,7 +31750,8 @@ ${cleanup.stderr}`)) {
|
|
|
31484
31750
|
});
|
|
31485
31751
|
return await this.replaceManifestUnlocked(
|
|
31486
31752
|
manifest,
|
|
31487
|
-
options.startImmediately !== false
|
|
31753
|
+
options.startImmediately !== false,
|
|
31754
|
+
this.config.instanceName
|
|
31488
31755
|
);
|
|
31489
31756
|
}
|
|
31490
31757
|
async start() {
|
|
@@ -31516,41 +31783,56 @@ ${result2.stderr}`)) {
|
|
|
31516
31783
|
if (!manifest) {
|
|
31517
31784
|
throw new Error("Inference-host service is not installed.");
|
|
31518
31785
|
}
|
|
31786
|
+
const restoreOnFailure = await readInferenceHostServiceDesired(this.desiredPath());
|
|
31519
31787
|
await writeDesired(this.desiredPath(), false, this.now());
|
|
31520
|
-
|
|
31521
|
-
|
|
31522
|
-
|
|
31523
|
-
|
|
31524
|
-
|
|
31525
|
-
|
|
31526
|
-
|
|
31527
|
-
|
|
31528
|
-
|
|
31529
|
-
|
|
31530
|
-
|
|
31531
|
-
|
|
31788
|
+
try {
|
|
31789
|
+
const serviceLockPath = `${this.config.supervisorProcessLockPath}.service`;
|
|
31790
|
+
let serviceReleased = false;
|
|
31791
|
+
for (let attempt = 0; attempt < this.stopWaitAttempts; attempt += 1) {
|
|
31792
|
+
try {
|
|
31793
|
+
const probe = await this.acquireProcessLock(serviceLockPath);
|
|
31794
|
+
await probe.release();
|
|
31795
|
+
serviceReleased = true;
|
|
31796
|
+
break;
|
|
31797
|
+
} catch (error48) {
|
|
31798
|
+
if (error48 instanceof Error && error48.message.includes("Another inference host process already owns")) {
|
|
31799
|
+
await this.sleep(250);
|
|
31800
|
+
continue;
|
|
31801
|
+
}
|
|
31802
|
+
throw error48;
|
|
31532
31803
|
}
|
|
31533
|
-
throw error48;
|
|
31534
31804
|
}
|
|
31535
|
-
|
|
31536
|
-
|
|
31537
|
-
|
|
31538
|
-
|
|
31539
|
-
|
|
31540
|
-
|
|
31541
|
-
|
|
31542
|
-
if (result2.exitCode !== 0 && !/not running|not found|does not exist|not loaded|cannot find|no such process/iu.test(`${result2.stdout}
|
|
31805
|
+
if (!serviceReleased) {
|
|
31806
|
+
throw new Error(
|
|
31807
|
+
`Inference-host workers did not stop cooperatively within ${SERVICE_COOPERATIVE_STOP_SECONDS} seconds; refusing forced termination while cleanup may be pending.`
|
|
31808
|
+
);
|
|
31809
|
+
}
|
|
31810
|
+
const result2 = await this.managerCommand("stop");
|
|
31811
|
+
if (result2.exitCode !== 0 && !/not running|not found|does not exist|not loaded|cannot find|no such process/iu.test(`${result2.stdout}
|
|
31543
31812
|
${result2.stderr}`)) {
|
|
31544
|
-
|
|
31545
|
-
|
|
31546
|
-
|
|
31547
|
-
|
|
31548
|
-
|
|
31813
|
+
throw new Error(`Background service stop failed: ${result2.stderr.trim()}`);
|
|
31814
|
+
}
|
|
31815
|
+
const status = await this.status();
|
|
31816
|
+
if (status.manager_active) {
|
|
31817
|
+
throw new Error("Background service manager still reports the service active after stop.");
|
|
31818
|
+
}
|
|
31819
|
+
return status;
|
|
31820
|
+
} catch (error48) {
|
|
31821
|
+
if (!restoreOnFailure) throw error48;
|
|
31822
|
+
try {
|
|
31823
|
+
await this.restoreRunningSupervisor(manifest);
|
|
31824
|
+
} catch (restoreError) {
|
|
31825
|
+
throw new Error(
|
|
31826
|
+
"Inference-host stop failed and the previous supervisor could not be restored.",
|
|
31827
|
+
{ cause: new AggregateError([error48, restoreError]) }
|
|
31828
|
+
);
|
|
31829
|
+
}
|
|
31830
|
+
throw error48;
|
|
31549
31831
|
}
|
|
31550
|
-
return status;
|
|
31551
31832
|
}
|
|
31552
|
-
async status() {
|
|
31833
|
+
async status(confirmedRuntime) {
|
|
31553
31834
|
const manifest = await readInferenceHostServiceManifest(this.manifestPath());
|
|
31835
|
+
const runtime = confirmedRuntime?.manifest_generation === manifest?.generation ? confirmedRuntime : await readRuntimeAcrossAtomicReplacement(this.runtimePath()).catch(() => null);
|
|
31554
31836
|
const desired = await readInferenceHostServiceDesired(this.desiredPath());
|
|
31555
31837
|
const result2 = await this.managerCommand("status");
|
|
31556
31838
|
const output3 = result2.stdout.trim();
|
|
@@ -31568,7 +31850,8 @@ ${result2.stderr}`)) {
|
|
|
31568
31850
|
display_name: worker.display_name,
|
|
31569
31851
|
max_concurrency: worker.max_concurrency,
|
|
31570
31852
|
authenticated_account_email: worker.authenticated_account_email,
|
|
31571
|
-
authenticated_account_plan: worker.authenticated_account_plan
|
|
31853
|
+
authenticated_account_plan: worker.authenticated_account_plan,
|
|
31854
|
+
runtime_state: runtime?.manifest_generation === manifest.generation && managerActive ? runtime.workers.find((item) => item.instance_name === worker.instance_name)?.state ?? "unknown" : "unknown"
|
|
31572
31855
|
})) ?? []
|
|
31573
31856
|
};
|
|
31574
31857
|
}
|
|
@@ -31606,6 +31889,7 @@ ${result2.stderr}`)) {
|
|
|
31606
31889
|
if (remaining.length === 0) return await this.uninstallUnlocked();
|
|
31607
31890
|
return await this.replaceManifestUnlocked({
|
|
31608
31891
|
...manifest,
|
|
31892
|
+
generation: randomUUID(),
|
|
31609
31893
|
installed_at: this.now().toISOString(),
|
|
31610
31894
|
workers: remaining
|
|
31611
31895
|
}, await readInferenceHostServiceDesired(this.desiredPath()));
|
|
@@ -31633,6 +31917,7 @@ ${result2.stderr}`)) {
|
|
|
31633
31917
|
if (this.platform === "linux") await this.runCommand("systemctl", ["--user", "daemon-reload"]);
|
|
31634
31918
|
await rm4(this.manifestPath(), { force: true });
|
|
31635
31919
|
await rm4(this.desiredPath(), { force: true });
|
|
31920
|
+
await rm4(this.runtimePath(), { force: true });
|
|
31636
31921
|
return {
|
|
31637
31922
|
installed: false,
|
|
31638
31923
|
desired_running: false,
|
|
@@ -31654,7 +31939,8 @@ ${result2.stderr}`)) {
|
|
|
31654
31939
|
`, resolvePromise);
|
|
31655
31940
|
});
|
|
31656
31941
|
};
|
|
31657
|
-
|
|
31942
|
+
spawnInferenceHostServiceChild = async (manifest, worker, signal, onReady = () => {
|
|
31943
|
+
}) => {
|
|
31658
31944
|
const args = [
|
|
31659
31945
|
manifest.script,
|
|
31660
31946
|
"inference-host",
|
|
@@ -31667,6 +31953,8 @@ ${result2.stderr}`)) {
|
|
|
31667
31953
|
const log = createWriteStream(manifest.log_path, { flags: "a", mode: 384 });
|
|
31668
31954
|
return await new Promise((resolvePromise, reject) => {
|
|
31669
31955
|
let stdout = "";
|
|
31956
|
+
let cooperativeStopTimedOut = false;
|
|
31957
|
+
let cooperativeStopTimer = null;
|
|
31670
31958
|
const pending = { stdout: "", stderr: "" };
|
|
31671
31959
|
const writeTaggedOutput = (stream, text, flush = false) => {
|
|
31672
31960
|
const lines = `${pending[stream]}${text}`.split(/\r?\n/u);
|
|
@@ -31679,6 +31967,7 @@ ${result2.stderr}`)) {
|
|
|
31679
31967
|
try {
|
|
31680
31968
|
const parsed = JSON.parse(line);
|
|
31681
31969
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
31970
|
+
if (parsed.event === "runtime_started") onReady();
|
|
31682
31971
|
log.write(`${JSON.stringify({
|
|
31683
31972
|
...parsed,
|
|
31684
31973
|
instance_name: worker.instance_name
|
|
@@ -31701,7 +31990,7 @@ ${result2.stderr}`)) {
|
|
|
31701
31990
|
const child = spawn5(manifest.executable, args, {
|
|
31702
31991
|
env: inferenceHostServiceChildEnvironment(worker.runtime_environment),
|
|
31703
31992
|
windowsHide: true,
|
|
31704
|
-
stdio: ["
|
|
31993
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
31705
31994
|
});
|
|
31706
31995
|
child.stdout.on("data", (chunk) => {
|
|
31707
31996
|
const text = chunk.toString("utf8");
|
|
@@ -31709,10 +31998,22 @@ ${result2.stderr}`)) {
|
|
|
31709
31998
|
stdout = `${stdout}${text}`.slice(-65536);
|
|
31710
31999
|
});
|
|
31711
32000
|
child.stderr.on("data", (chunk) => writeTaggedOutput("stderr", chunk.toString("utf8")));
|
|
31712
|
-
|
|
31713
|
-
|
|
32001
|
+
child.stdin.on("error", () => {
|
|
32002
|
+
});
|
|
32003
|
+
const onAbort = () => {
|
|
32004
|
+
child.stdin.end(`${INFERENCE_HOST_SERVICE_DRAIN_COMMAND}
|
|
32005
|
+
`);
|
|
32006
|
+
cooperativeStopTimer = setTimeout(() => {
|
|
32007
|
+
cooperativeStopTimedOut = true;
|
|
32008
|
+
child.kill("SIGKILL");
|
|
32009
|
+
}, SERVICE_COOPERATIVE_STOP_SECONDS * 1e3);
|
|
32010
|
+
cooperativeStopTimer.unref();
|
|
32011
|
+
};
|
|
32012
|
+
if (signal.aborted) onAbort();
|
|
32013
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
31714
32014
|
child.once("error", (error48) => {
|
|
31715
32015
|
signal.removeEventListener("abort", onAbort);
|
|
32016
|
+
if (cooperativeStopTimer) clearTimeout(cooperativeStopTimer);
|
|
31716
32017
|
writeTaggedOutput("stdout", "", true);
|
|
31717
32018
|
writeTaggedOutput("stderr", "", true);
|
|
31718
32019
|
log.end();
|
|
@@ -31720,6 +32021,7 @@ ${result2.stderr}`)) {
|
|
|
31720
32021
|
});
|
|
31721
32022
|
child.once("exit", (code) => {
|
|
31722
32023
|
signal.removeEventListener("abort", onAbort);
|
|
32024
|
+
if (cooperativeStopTimer) clearTimeout(cooperativeStopTimer);
|
|
31723
32025
|
writeTaggedOutput("stdout", "", true);
|
|
31724
32026
|
writeTaggedOutput("stderr", "", true);
|
|
31725
32027
|
log.end();
|
|
@@ -31739,81 +32041,231 @@ ${result2.stderr}`)) {
|
|
|
31739
32041
|
resolvePromise({
|
|
31740
32042
|
exitCode: code ?? 1,
|
|
31741
32043
|
uptimeMs: Date.now() - startedAt,
|
|
31742
|
-
drainReason
|
|
32044
|
+
drainReason,
|
|
32045
|
+
cooperativeStopTimedOut
|
|
31743
32046
|
});
|
|
31744
32047
|
});
|
|
31745
32048
|
});
|
|
31746
32049
|
};
|
|
31747
32050
|
runInferenceHostServiceSupervisor = async (manifestPath, options = {}) => {
|
|
31748
|
-
const
|
|
31749
|
-
if (!
|
|
32051
|
+
const initialManifest = await readInferenceHostServiceManifest(manifestPath);
|
|
32052
|
+
if (!initialManifest) throw new Error("Inference-host service manifest is missing.");
|
|
31750
32053
|
const desiredPath = manifestPath.replace(/\.service\.json$/u, ".service-desired.json");
|
|
32054
|
+
const runtimePath = manifestPath.replace(/\.service\.json$/u, ".service-runtime.json");
|
|
31751
32055
|
const signal = options.signal ?? new AbortController().signal;
|
|
31752
32056
|
const sleep4 = options.sleep ?? (async (milliseconds) => {
|
|
31753
32057
|
await new Promise((resolvePromise) => setTimeout(resolvePromise, milliseconds));
|
|
31754
32058
|
});
|
|
31755
|
-
const launch = options.runWorker ?? options.spawnChild ??
|
|
31756
|
-
await appendServiceLog(
|
|
32059
|
+
const launch = options.runWorker ?? options.spawnChild ?? spawnInferenceHostServiceChild;
|
|
32060
|
+
await appendServiceLog(initialManifest.log_path, "service_supervisor_started", {
|
|
31757
32061
|
adapter: "codex",
|
|
31758
|
-
instances:
|
|
32062
|
+
instances: initialManifest.workers.map((worker) => worker.instance_name)
|
|
31759
32063
|
});
|
|
31760
|
-
const
|
|
32064
|
+
const workers = /* @__PURE__ */ new Map();
|
|
32065
|
+
let appliedManifest = initialManifest;
|
|
32066
|
+
let rejectedManifestGeneration = null;
|
|
32067
|
+
let runtimeWriteChain = Promise.resolve();
|
|
32068
|
+
const persistRuntime = async () => {
|
|
32069
|
+
const state = {
|
|
32070
|
+
schema_version: "vtx_inference_service_runtime_v1",
|
|
32071
|
+
manifest_generation: appliedManifest.generation,
|
|
32072
|
+
rejected_manifest_generation: rejectedManifestGeneration,
|
|
32073
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32074
|
+
workers: [...workers.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([instanceName, record2]) => ({
|
|
32075
|
+
instance_name: instanceName,
|
|
32076
|
+
state: record2.state,
|
|
32077
|
+
error: record2.error
|
|
32078
|
+
}))
|
|
32079
|
+
};
|
|
32080
|
+
runtimeWriteChain = runtimeWriteChain.then(async () => {
|
|
32081
|
+
await writeAtomicInferencePrivateFile(runtimePath, `${JSON.stringify(state, null, 2)}
|
|
32082
|
+
`);
|
|
32083
|
+
});
|
|
32084
|
+
await runtimeWriteChain;
|
|
32085
|
+
};
|
|
32086
|
+
const updateRecord = async (record2, state, error48 = null) => {
|
|
32087
|
+
if (workers.get(record2.worker.instance_name) !== record2) return;
|
|
32088
|
+
record2.state = state;
|
|
32089
|
+
record2.error = error48;
|
|
32090
|
+
await persistRuntime();
|
|
32091
|
+
};
|
|
32092
|
+
const waitRetry = async (milliseconds, controller) => {
|
|
32093
|
+
if (controller.signal.aborted || signal.aborted) return;
|
|
32094
|
+
let finishAbort;
|
|
32095
|
+
const aborted2 = new Promise((resolvePromise) => {
|
|
32096
|
+
finishAbort = resolvePromise;
|
|
32097
|
+
});
|
|
32098
|
+
controller.signal.addEventListener("abort", finishAbort, { once: true });
|
|
32099
|
+
signal.addEventListener("abort", finishAbort, { once: true });
|
|
32100
|
+
try {
|
|
32101
|
+
await Promise.race([sleep4(milliseconds), aborted2]);
|
|
32102
|
+
} finally {
|
|
32103
|
+
controller.signal.removeEventListener("abort", finishAbort);
|
|
32104
|
+
signal.removeEventListener("abort", finishAbort);
|
|
32105
|
+
}
|
|
32106
|
+
};
|
|
32107
|
+
const superviseWorker = async (serviceManifest, record2) => {
|
|
31761
32108
|
let failures = 0;
|
|
31762
|
-
while (!signal.aborted && await readDesiredAcrossAtomicReplacement(desiredPath)) {
|
|
32109
|
+
while (!signal.aborted && !record2.controller.signal.aborted && await readDesiredAcrossAtomicReplacement(desiredPath)) {
|
|
31763
32110
|
try {
|
|
31764
|
-
|
|
31765
|
-
const
|
|
32111
|
+
await updateRecord(record2, "starting");
|
|
32112
|
+
const attemptController = new AbortController();
|
|
32113
|
+
const forwardAbort = () => attemptController.abort();
|
|
31766
32114
|
signal.addEventListener("abort", forwardAbort, { once: true });
|
|
31767
|
-
|
|
31768
|
-
let monitorError = null;
|
|
31769
|
-
const desiredMonitor = (async () => {
|
|
31770
|
-
while (!workerComplete && !workerController.signal.aborted) {
|
|
31771
|
-
await sleep4(500);
|
|
31772
|
-
if (!await readDesiredAcrossAtomicReplacement(desiredPath)) {
|
|
31773
|
-
workerController.abort();
|
|
31774
|
-
break;
|
|
31775
|
-
}
|
|
31776
|
-
}
|
|
31777
|
-
})().catch((error48) => {
|
|
31778
|
-
monitorError = error48;
|
|
31779
|
-
workerController.abort();
|
|
31780
|
-
});
|
|
32115
|
+
record2.controller.signal.addEventListener("abort", forwardAbort, { once: true });
|
|
31781
32116
|
let result2;
|
|
32117
|
+
let launchSettled = false;
|
|
32118
|
+
let readinessTask = Promise.resolve();
|
|
32119
|
+
let readinessSignalled = false;
|
|
31782
32120
|
try {
|
|
31783
|
-
result2 = await launch(
|
|
32121
|
+
result2 = await launch(
|
|
32122
|
+
serviceManifest,
|
|
32123
|
+
record2.worker,
|
|
32124
|
+
attemptController.signal,
|
|
32125
|
+
() => {
|
|
32126
|
+
if (readinessSignalled) return;
|
|
32127
|
+
readinessSignalled = true;
|
|
32128
|
+
readinessTask = (async () => {
|
|
32129
|
+
await sleep4(500);
|
|
32130
|
+
if (!launchSettled && !attemptController.signal.aborted && !record2.controller.signal.aborted && !signal.aborted) {
|
|
32131
|
+
await updateRecord(record2, "running");
|
|
32132
|
+
}
|
|
32133
|
+
})();
|
|
32134
|
+
}
|
|
32135
|
+
);
|
|
31784
32136
|
} finally {
|
|
31785
|
-
|
|
31786
|
-
|
|
32137
|
+
launchSettled = true;
|
|
32138
|
+
attemptController.abort();
|
|
31787
32139
|
signal.removeEventListener("abort", forwardAbort);
|
|
31788
|
-
|
|
32140
|
+
record2.controller.signal.removeEventListener("abort", forwardAbort);
|
|
32141
|
+
await readinessTask;
|
|
31789
32142
|
}
|
|
31790
|
-
if (
|
|
31791
|
-
|
|
32143
|
+
if (result2.cooperativeStopTimedOut) {
|
|
32144
|
+
await updateRecord(record2, "failed", "worker_cooperative_stop_timeout");
|
|
32145
|
+
await appendServiceLog(serviceManifest.log_path, "worker_cooperative_stop_timeout", {
|
|
32146
|
+
instance_name: record2.worker.instance_name
|
|
32147
|
+
});
|
|
32148
|
+
throw new Error("worker_cooperative_stop_timeout");
|
|
32149
|
+
}
|
|
32150
|
+
if (signal.aborted || record2.controller.signal.aborted || !await readDesiredAcrossAtomicReplacement(desiredPath)) break;
|
|
31792
32151
|
failures = result2.uptimeMs >= 6e4 ? 0 : failures + 1;
|
|
31793
32152
|
const retryAfterMs = Math.min(1e3 * 2 ** Math.min(failures, 5), 3e4);
|
|
31794
|
-
await
|
|
31795
|
-
|
|
32153
|
+
await updateRecord(record2, "failed", "worker_exited");
|
|
32154
|
+
await appendServiceLog(serviceManifest.log_path, "worker_exited", {
|
|
32155
|
+
instance_name: record2.worker.instance_name,
|
|
31796
32156
|
exit_code: result2.exitCode,
|
|
31797
32157
|
uptime_ms: result2.uptimeMs,
|
|
31798
32158
|
drain_reason: result2.drainReason ?? null,
|
|
31799
32159
|
retry_after_ms: retryAfterMs
|
|
31800
32160
|
});
|
|
31801
|
-
await
|
|
32161
|
+
await waitRetry(retryAfterMs, record2.controller);
|
|
31802
32162
|
} catch (error48) {
|
|
31803
|
-
if (
|
|
32163
|
+
if (error48 instanceof Error && error48.message === "worker_cooperative_stop_timeout") throw error48;
|
|
32164
|
+
if (signal.aborted || record2.controller.signal.aborted) break;
|
|
31804
32165
|
failures += 1;
|
|
31805
32166
|
const retryAfterMs = Math.min(1e3 * 2 ** Math.min(failures, 5), 3e4);
|
|
31806
|
-
await
|
|
31807
|
-
|
|
32167
|
+
await updateRecord(record2, "failed", "worker_launch_failed");
|
|
32168
|
+
await appendServiceLog(serviceManifest.log_path, "worker_launch_failed", {
|
|
32169
|
+
instance_name: record2.worker.instance_name,
|
|
31808
32170
|
error: error48 instanceof Error ? error48.message : "unknown",
|
|
31809
32171
|
retry_after_ms: retryAfterMs
|
|
31810
32172
|
});
|
|
31811
|
-
await
|
|
32173
|
+
await waitRetry(retryAfterMs, record2.controller);
|
|
32174
|
+
}
|
|
32175
|
+
}
|
|
32176
|
+
};
|
|
32177
|
+
const startWorker = (serviceManifest, worker) => {
|
|
32178
|
+
const record2 = {
|
|
32179
|
+
worker,
|
|
32180
|
+
controller: new AbortController(),
|
|
32181
|
+
promise: Promise.resolve(),
|
|
32182
|
+
state: "starting",
|
|
32183
|
+
error: null
|
|
32184
|
+
};
|
|
32185
|
+
workers.set(worker.instance_name, record2);
|
|
32186
|
+
record2.promise = superviseWorker(serviceManifest, record2);
|
|
32187
|
+
};
|
|
32188
|
+
const reconcile = async (next) => {
|
|
32189
|
+
const nextByName = new Map(next.workers.map((worker) => [worker.instance_name, worker]));
|
|
32190
|
+
const retiring = [...workers.values()].filter((record2) => {
|
|
32191
|
+
const nextWorker = nextByName.get(record2.worker.instance_name);
|
|
32192
|
+
return !nextWorker || !sameWorker(record2.worker, nextWorker);
|
|
32193
|
+
});
|
|
32194
|
+
for (const record2 of retiring) {
|
|
32195
|
+
await updateRecord(record2, "draining");
|
|
32196
|
+
record2.controller.abort();
|
|
32197
|
+
}
|
|
32198
|
+
const settled = await Promise.allSettled(retiring.map((record2) => record2.promise));
|
|
32199
|
+
const failedDrain = settled.find(
|
|
32200
|
+
(result2) => result2.status === "rejected"
|
|
32201
|
+
);
|
|
32202
|
+
if (failedDrain) {
|
|
32203
|
+
for (const record2 of retiring) workers.delete(record2.worker.instance_name);
|
|
32204
|
+
for (const worker of appliedManifest.workers) {
|
|
32205
|
+
if (!workers.has(worker.instance_name)) startWorker(appliedManifest, worker);
|
|
32206
|
+
}
|
|
32207
|
+
rejectedManifestGeneration = next.generation;
|
|
32208
|
+
await persistRuntime();
|
|
32209
|
+
await appendServiceLog(appliedManifest.log_path, "service_manifest_rejected", {
|
|
32210
|
+
manifest_generation: next.generation,
|
|
32211
|
+
reason: failedDrain.reason instanceof Error ? failedDrain.reason.message : "worker_cooperative_stop_failed"
|
|
32212
|
+
});
|
|
32213
|
+
return;
|
|
32214
|
+
}
|
|
32215
|
+
for (const record2 of retiring) workers.delete(record2.worker.instance_name);
|
|
32216
|
+
for (const worker of next.workers) {
|
|
32217
|
+
if (!workers.has(worker.instance_name)) startWorker(next, worker);
|
|
32218
|
+
}
|
|
32219
|
+
appliedManifest = next;
|
|
32220
|
+
rejectedManifestGeneration = null;
|
|
32221
|
+
await persistRuntime();
|
|
32222
|
+
await appendServiceLog(next.log_path, "service_manifest_applied", {
|
|
32223
|
+
manifest_generation: next.generation,
|
|
32224
|
+
instances: next.workers.map((worker) => worker.instance_name)
|
|
32225
|
+
});
|
|
32226
|
+
};
|
|
32227
|
+
const drainWorkers = async () => {
|
|
32228
|
+
const draining = [...workers.values()];
|
|
32229
|
+
for (const record2 of draining) {
|
|
32230
|
+
await updateRecord(record2, "draining");
|
|
32231
|
+
record2.controller.abort();
|
|
32232
|
+
}
|
|
32233
|
+
const settled = await Promise.allSettled(draining.map((record2) => record2.promise));
|
|
32234
|
+
const failedDrain = settled.find(
|
|
32235
|
+
(result2) => result2.status === "rejected"
|
|
32236
|
+
);
|
|
32237
|
+
if (failedDrain) throw failedDrain.reason;
|
|
32238
|
+
for (const record2 of draining) {
|
|
32239
|
+
if (workers.get(record2.worker.instance_name) === record2) {
|
|
32240
|
+
workers.delete(record2.worker.instance_name);
|
|
31812
32241
|
}
|
|
31813
32242
|
}
|
|
32243
|
+
await persistRuntime();
|
|
31814
32244
|
};
|
|
31815
|
-
await
|
|
31816
|
-
|
|
32245
|
+
await reconcile(initialManifest);
|
|
32246
|
+
try {
|
|
32247
|
+
while (!signal.aborted) {
|
|
32248
|
+
while (!signal.aborted && await readDesiredAcrossAtomicReplacement(desiredPath)) {
|
|
32249
|
+
const next = await readManifestAcrossAtomicReplacement(manifestPath);
|
|
32250
|
+
if (!next) throw new Error("Inference-host service manifest is missing.");
|
|
32251
|
+
if (next.generation !== appliedManifest.generation && next.generation !== rejectedManifestGeneration) await reconcile(next);
|
|
32252
|
+
await sleep4(250);
|
|
32253
|
+
}
|
|
32254
|
+
await drainWorkers();
|
|
32255
|
+
if (signal.aborted || !await readDesiredAcrossAtomicReplacement(desiredPath)) break;
|
|
32256
|
+
const restored = await readManifestAcrossAtomicReplacement(manifestPath);
|
|
32257
|
+
if (!restored) throw new Error("Inference-host service manifest is missing.");
|
|
32258
|
+
await reconcile(restored);
|
|
32259
|
+
await appendServiceLog(restored.log_path, "service_desired_state_restored", {
|
|
32260
|
+
manifest_generation: restored.generation,
|
|
32261
|
+
instances: restored.workers.map((worker) => worker.instance_name)
|
|
32262
|
+
});
|
|
32263
|
+
}
|
|
32264
|
+
} finally {
|
|
32265
|
+
await drainWorkers();
|
|
32266
|
+
await runtimeWriteChain;
|
|
32267
|
+
await appendServiceLog(appliedManifest.log_path, "service_supervisor_stopped");
|
|
32268
|
+
}
|
|
31817
32269
|
};
|
|
31818
32270
|
}
|
|
31819
32271
|
});
|
|
@@ -31822,9 +32274,10 @@ ${result2.stderr}`)) {
|
|
|
31822
32274
|
var cli_exports = {};
|
|
31823
32275
|
__export(cli_exports, {
|
|
31824
32276
|
INFERENCE_HOST_CLI_VERSION: () => INFERENCE_HOST_CLI_VERSION,
|
|
32277
|
+
registerInferenceHostServiceControlInput: () => registerInferenceHostServiceControlInput,
|
|
31825
32278
|
runInferenceHostCli: () => runInferenceHostCli
|
|
31826
32279
|
});
|
|
31827
|
-
import { randomUUID } from "node:crypto";
|
|
32280
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
31828
32281
|
import { spawn as spawn6 } from "node:child_process";
|
|
31829
32282
|
import { lstat as lstat4, realpath as realpath4, rm as rm5 } from "node:fs/promises";
|
|
31830
32283
|
import { join as join6, resolve as resolve5 } from "node:path";
|
|
@@ -31902,7 +32355,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
31902
32355
|
};
|
|
31903
32356
|
}
|
|
31904
32357
|
}
|
|
31905
|
-
var INFERENCE_HOST_CLI_VERSION, runtimeReceiptPath, codexRecoveryPath, codexGuardianReceiptRoot, revocationCheckpointPath, foregroundHostLockPath, AGENT_HEARTBEAT_INTERVAL_MS, AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS, retryableAgentHeartbeatError, assertRevocationCheckpoint, readRevocationCheckpoint, writeRevocationCheckpoint, clearRevocationCheckpoint, render, INFERENCE_HOST_HELP, parseHostConcurrency, parseInferenceHostArgs, defaultOpenBrowser, defaultRegisterLifecycleSignalHandlers, lifecycleCancellation, configuredCredentialStore, accountKeyForState, assertCredentialMatchesState2, revocationCheckpointForCredential, assertRevocationCheckpointMatchesLocalIdentity, fileExistsPrivately, inspectCodexAuthentication, clearLocalRuntimeArtifacts, assertDurableServiceUninstalled, assertLocalRuntimeArtifactsMayBeDiscarded, defaultRunForeground, login, codexLogin, codexLogout, localStatus, doctor, cleanupLogin, runHost, defaultReadStdin, parseAgentStdin, agentOperationId, agentSession, agentConnect, agentRun, agentNext, agentComplete, agentFail, withAgentCommandLock, serviceCommand, hasExplicitCredentialStoreConfiguration, commandUsesInstalledServiceCredentials, resolveInferenceHostCommandConfig;
|
|
32358
|
+
var INFERENCE_HOST_CLI_VERSION, runtimeReceiptPath, codexRecoveryPath, codexGuardianReceiptRoot, revocationCheckpointPath, foregroundHostLockPath, AGENT_HEARTBEAT_INTERVAL_MS, AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS, retryableAgentHeartbeatError, assertRevocationCheckpoint, readRevocationCheckpoint, writeRevocationCheckpoint, clearRevocationCheckpoint, render, INFERENCE_HOST_HELP, parseHostConcurrency, parseInferenceHostArgs, defaultOpenBrowser, registerInferenceHostServiceControlInput, defaultRegisterLifecycleSignalHandlers, lifecycleCancellation, configuredCredentialStore, accountKeyForState, assertCredentialMatchesState2, revocationCheckpointForCredential, assertRevocationCheckpointMatchesLocalIdentity, fileExistsPrivately, inspectCodexAuthentication, clearLocalRuntimeArtifacts, assertDurableServiceUninstalled, assertLocalRuntimeArtifactsMayBeDiscarded, defaultRunForeground, login, codexLogin, codexLogout, localStatus, doctor, cleanupLogin, runHost, defaultReadStdin, parseAgentStdin, agentOperationId, agentSession, agentConnect, agentRun, agentNext, agentComplete, agentFail, withAgentCommandLock, serviceCommand, hasExplicitCredentialStoreConfiguration, commandUsesInstalledServiceCredentials, resolveInferenceHostCommandConfig;
|
|
31906
32359
|
var init_cli = __esm({
|
|
31907
32360
|
"lib/inference-host/cli.ts"() {
|
|
31908
32361
|
"use strict";
|
|
@@ -32147,14 +32600,35 @@ Durable service:
|
|
|
32147
32600
|
});
|
|
32148
32601
|
child.unref();
|
|
32149
32602
|
};
|
|
32603
|
+
registerInferenceHostServiceControlInput = (input, abort) => {
|
|
32604
|
+
let pendingControlInput = "";
|
|
32605
|
+
const onControlInput = (chunk) => {
|
|
32606
|
+
pendingControlInput = `${pendingControlInput}${chunk.toString()}`.slice(-4096);
|
|
32607
|
+
const lines = pendingControlInput.split(/\r?\n/u);
|
|
32608
|
+
pendingControlInput = lines.pop() ?? "";
|
|
32609
|
+
if (lines.some((line) => line === INFERENCE_HOST_SERVICE_DRAIN_COMMAND)) {
|
|
32610
|
+
abort();
|
|
32611
|
+
}
|
|
32612
|
+
};
|
|
32613
|
+
input.on("data", onControlInput);
|
|
32614
|
+
input.resume();
|
|
32615
|
+
return () => {
|
|
32616
|
+
input.off("data", onControlInput);
|
|
32617
|
+
input.pause();
|
|
32618
|
+
};
|
|
32619
|
+
};
|
|
32150
32620
|
defaultRegisterLifecycleSignalHandlers = (abort) => {
|
|
32151
32621
|
const onSigint = () => abort("SIGINT");
|
|
32152
32622
|
const onSigterm = () => abort("SIGTERM");
|
|
32153
32623
|
process.on("SIGINT", onSigint);
|
|
32154
32624
|
process.on("SIGTERM", onSigterm);
|
|
32625
|
+
const serviceChild = process.env.VTX_INFERENCE_HOST_SERVICE_CHILD === "1";
|
|
32626
|
+
const unregisterControlInput = serviceChild ? registerInferenceHostServiceControlInput(process.stdin, onSigterm) : () => {
|
|
32627
|
+
};
|
|
32155
32628
|
return () => {
|
|
32156
32629
|
process.off("SIGINT", onSigint);
|
|
32157
32630
|
process.off("SIGTERM", onSigterm);
|
|
32631
|
+
unregisterControlInput();
|
|
32158
32632
|
};
|
|
32159
32633
|
};
|
|
32160
32634
|
lifecycleCancellation = (dependencies) => {
|
|
@@ -32321,7 +32795,7 @@ Durable service:
|
|
|
32321
32795
|
throw new Error("Inference host credential recovery is required before login.");
|
|
32322
32796
|
}
|
|
32323
32797
|
const keyPair = generateExternalInferenceEnvelopeKeyPair();
|
|
32324
|
-
const hostId =
|
|
32798
|
+
const hostId = randomUUID2();
|
|
32325
32799
|
const beginLogin = dependencies.beginLogin ?? beginInferenceOAuthLogin;
|
|
32326
32800
|
const pending = await beginLogin({
|
|
32327
32801
|
apiUrl: config2.apiUrl,
|
|
@@ -32544,6 +33018,7 @@ Waiting for approval...
|
|
|
32544
33018
|
registered: receipt.registered,
|
|
32545
33019
|
advertisement_generation: receipt.advertisement_generation,
|
|
32546
33020
|
pending_attempts: Object.keys(receipt.attempts).length + (receipt.pending_claim_request ? 1 : 0),
|
|
33021
|
+
recovery: summarizeInferenceHostRuntimeRecovery(receipt),
|
|
32547
33022
|
updated_at: receipt.updated_at
|
|
32548
33023
|
} : null,
|
|
32549
33024
|
agent_attempt: agentAttempt ? {
|
|
@@ -32855,7 +33330,7 @@ Waiting for approval...
|
|
|
32855
33330
|
}
|
|
32856
33331
|
return record2;
|
|
32857
33332
|
};
|
|
32858
|
-
agentOperationId = (kind) => `${kind}-${
|
|
33333
|
+
agentOperationId = (kind) => `${kind}-${randomUUID2()}`;
|
|
32859
33334
|
agentSession = async (config2, dependencies, warnings, signal) => {
|
|
32860
33335
|
if (await readRevocationCheckpoint(config2)) {
|
|
32861
33336
|
throw new Error("Inference host revocation recovery must finish first.");
|
|
@@ -33503,7 +33978,7 @@ var init_types = __esm({
|
|
|
33503
33978
|
});
|
|
33504
33979
|
|
|
33505
33980
|
// lib/agent-core/client.ts
|
|
33506
|
-
import { randomUUID as
|
|
33981
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
33507
33982
|
function normalizeApiUrl(value) {
|
|
33508
33983
|
const parsed = String(value || "").trim();
|
|
33509
33984
|
if (!parsed) {
|
|
@@ -33765,7 +34240,7 @@ var init_client = __esm({
|
|
|
33765
34240
|
return this.request("/trading/ai/runtime/decision", {
|
|
33766
34241
|
method: "POST",
|
|
33767
34242
|
profileId,
|
|
33768
|
-
idempotencyKey:
|
|
34243
|
+
idempotencyKey: randomUUID3(),
|
|
33769
34244
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
33770
34245
|
body: payload
|
|
33771
34246
|
});
|
|
@@ -33774,7 +34249,7 @@ var init_client = __esm({
|
|
|
33774
34249
|
return this.request("/trading/ai/runtime/trade-sync", {
|
|
33775
34250
|
method: "POST",
|
|
33776
34251
|
profileId,
|
|
33777
|
-
idempotencyKey:
|
|
34252
|
+
idempotencyKey: randomUUID3(),
|
|
33778
34253
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
33779
34254
|
body: payload
|
|
33780
34255
|
});
|
|
@@ -33783,7 +34258,7 @@ var init_client = __esm({
|
|
|
33783
34258
|
return this.request("/trading/ai/runtime/error", {
|
|
33784
34259
|
method: "POST",
|
|
33785
34260
|
profileId,
|
|
33786
|
-
idempotencyKey:
|
|
34261
|
+
idempotencyKey: randomUUID3(),
|
|
33787
34262
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
33788
34263
|
body: payload
|
|
33789
34264
|
});
|
|
@@ -33795,7 +34270,7 @@ var init_client = __esm({
|
|
|
33795
34270
|
return this.request("/trading/market-order", {
|
|
33796
34271
|
method: "POST",
|
|
33797
34272
|
profileId,
|
|
33798
|
-
idempotencyKey:
|
|
34273
|
+
idempotencyKey: randomUUID3(),
|
|
33799
34274
|
body: payload
|
|
33800
34275
|
});
|
|
33801
34276
|
}
|
|
@@ -33803,7 +34278,7 @@ var init_client = __esm({
|
|
|
33803
34278
|
return this.request("/trading/limit-order", {
|
|
33804
34279
|
method: "POST",
|
|
33805
34280
|
profileId,
|
|
33806
|
-
idempotencyKey:
|
|
34281
|
+
idempotencyKey: randomUUID3(),
|
|
33807
34282
|
body: payload
|
|
33808
34283
|
});
|
|
33809
34284
|
}
|
|
@@ -33811,7 +34286,7 @@ var init_client = __esm({
|
|
|
33811
34286
|
return this.request("/trading/cancel-order", {
|
|
33812
34287
|
method: "POST",
|
|
33813
34288
|
profileId,
|
|
33814
|
-
idempotencyKey:
|
|
34289
|
+
idempotencyKey: randomUUID3(),
|
|
33815
34290
|
body: payload
|
|
33816
34291
|
});
|
|
33817
34292
|
}
|
|
@@ -33830,7 +34305,7 @@ var init_client = __esm({
|
|
|
33830
34305
|
return this.request("/trading/ai/start", {
|
|
33831
34306
|
method: "POST",
|
|
33832
34307
|
profileId,
|
|
33833
|
-
idempotencyKey:
|
|
34308
|
+
idempotencyKey: randomUUID3(),
|
|
33834
34309
|
body: payload
|
|
33835
34310
|
});
|
|
33836
34311
|
}
|
|
@@ -33838,7 +34313,7 @@ var init_client = __esm({
|
|
|
33838
34313
|
return this.request("/trading/ai/stop", {
|
|
33839
34314
|
method: "POST",
|
|
33840
34315
|
profileId,
|
|
33841
|
-
idempotencyKey:
|
|
34316
|
+
idempotencyKey: randomUUID3(),
|
|
33842
34317
|
body: {}
|
|
33843
34318
|
});
|
|
33844
34319
|
}
|
|
@@ -33846,7 +34321,7 @@ var init_client = __esm({
|
|
|
33846
34321
|
return this.request("/trading/ai/assistant/start", {
|
|
33847
34322
|
method: "POST",
|
|
33848
34323
|
profileId,
|
|
33849
|
-
idempotencyKey:
|
|
34324
|
+
idempotencyKey: randomUUID3(),
|
|
33850
34325
|
body: {}
|
|
33851
34326
|
});
|
|
33852
34327
|
}
|
|
@@ -33854,7 +34329,7 @@ var init_client = __esm({
|
|
|
33854
34329
|
return this.request("/trading/ai/assistant/stop", {
|
|
33855
34330
|
method: "POST",
|
|
33856
34331
|
profileId,
|
|
33857
|
-
idempotencyKey:
|
|
34332
|
+
idempotencyKey: randomUUID3(),
|
|
33858
34333
|
body: {}
|
|
33859
34334
|
});
|
|
33860
34335
|
}
|
|
@@ -33862,7 +34337,7 @@ var init_client = __esm({
|
|
|
33862
34337
|
return this.request("/trading/ai/runtime/session/start", {
|
|
33863
34338
|
method: "POST",
|
|
33864
34339
|
profileId,
|
|
33865
|
-
idempotencyKey:
|
|
34340
|
+
idempotencyKey: randomUUID3(),
|
|
33866
34341
|
body: payload
|
|
33867
34342
|
});
|
|
33868
34343
|
}
|
|
@@ -33873,7 +34348,7 @@ var init_client = __esm({
|
|
|
33873
34348
|
return this.request("/trading/ai/runtime/session/stop", {
|
|
33874
34349
|
method: "POST",
|
|
33875
34350
|
profileId,
|
|
33876
|
-
idempotencyKey:
|
|
34351
|
+
idempotencyKey: randomUUID3(),
|
|
33877
34352
|
body: payload
|
|
33878
34353
|
});
|
|
33879
34354
|
}
|
|
@@ -33890,7 +34365,7 @@ var init_client = __esm({
|
|
|
33890
34365
|
}).request("/trading/ai/runtime/session/stop", {
|
|
33891
34366
|
method: "POST",
|
|
33892
34367
|
profileId,
|
|
33893
|
-
idempotencyKey:
|
|
34368
|
+
idempotencyKey: randomUUID3(),
|
|
33894
34369
|
body: payload
|
|
33895
34370
|
});
|
|
33896
34371
|
}
|
|
@@ -33899,7 +34374,7 @@ var init_client = __esm({
|
|
|
33899
34374
|
});
|
|
33900
34375
|
|
|
33901
34376
|
// lib/agent-core/headless-runtime.ts
|
|
33902
|
-
import { randomUUID as
|
|
34377
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
33903
34378
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
33904
34379
|
function objectOrNull2(value) {
|
|
33905
34380
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -33997,8 +34472,8 @@ async function runAndReportLocalWorkCycle(options, state, leaseToken, context) {
|
|
|
33997
34472
|
return Boolean(result2.decision || tradeSync || result2.afterDecision);
|
|
33998
34473
|
}
|
|
33999
34474
|
async function startHeadlessRuntime(options) {
|
|
34000
|
-
const runtimeSessionId =
|
|
34001
|
-
const deviceId = String(options.deviceId || "").trim() ||
|
|
34475
|
+
const runtimeSessionId = randomUUID4();
|
|
34476
|
+
const deviceId = String(options.deviceId || "").trim() || randomUUID4();
|
|
34002
34477
|
const startResponse = await options.client.startRuntime(options.profileId, {
|
|
34003
34478
|
session_id: runtimeSessionId,
|
|
34004
34479
|
device_id: deviceId,
|
|
@@ -50616,7 +51091,7 @@ var headless_local_worker_exports = {};
|
|
|
50616
51091
|
__export(headless_local_worker_exports, {
|
|
50617
51092
|
createHeadlessLocalWorker: () => createHeadlessLocalWorker
|
|
50618
51093
|
});
|
|
50619
|
-
import { randomUUID as
|
|
51094
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
50620
51095
|
function objectOrNull3(value) {
|
|
50621
51096
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
50622
51097
|
}
|
|
@@ -51029,7 +51504,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
51029
51504
|
const statusMatch = errorText.match(/\b([45]\d{2})\b/);
|
|
51030
51505
|
const statusCode = statusMatch ? Number(statusMatch[1]) : null;
|
|
51031
51506
|
const failedInvocation = normalizeAiInvocationTelemetry({
|
|
51032
|
-
client_invocation_id:
|
|
51507
|
+
client_invocation_id: randomUUID5(),
|
|
51033
51508
|
use_case: "trader",
|
|
51034
51509
|
role: "primary",
|
|
51035
51510
|
attempt_index: 0,
|
|
@@ -51085,7 +51560,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
51085
51560
|
billable_cached_input_tokens: normalizedUsage.cached_input_tokens
|
|
51086
51561
|
};
|
|
51087
51562
|
const invocation = normalizeAiInvocationTelemetry({
|
|
51088
|
-
client_invocation_id:
|
|
51563
|
+
client_invocation_id: randomUUID5(),
|
|
51089
51564
|
use_case: "trader",
|
|
51090
51565
|
role: "primary",
|
|
51091
51566
|
attempt_index: 0,
|
|
@@ -51290,7 +51765,7 @@ var vtx_exports = {};
|
|
|
51290
51765
|
__export(vtx_exports, {
|
|
51291
51766
|
runVtxCli: () => runVtxCli
|
|
51292
51767
|
});
|
|
51293
|
-
import { randomUUID as
|
|
51768
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
51294
51769
|
import { spawn as spawn7 } from "node:child_process";
|
|
51295
51770
|
function render2(value, json2) {
|
|
51296
51771
|
if (json2) {
|
|
@@ -51704,8 +52179,8 @@ async function runVtxCli(argv2, env = process.env) {
|
|
|
51704
52179
|
});
|
|
51705
52180
|
return { exitCode: 0, stdout: render2(redactCliOutput(response2), json2), stderr: "" };
|
|
51706
52181
|
}
|
|
51707
|
-
const runtimeSessionId =
|
|
51708
|
-
const deviceId = config2.runtimeDeviceId ??
|
|
52182
|
+
const runtimeSessionId = randomUUID6();
|
|
52183
|
+
const deviceId = config2.runtimeDeviceId ?? randomUUID6();
|
|
51709
52184
|
const response = await client.startRuntime(profileId, {
|
|
51710
52185
|
session_id: runtimeSessionId,
|
|
51711
52186
|
device_id: deviceId,
|