@vtxmacro/cli 2026.8.35 → 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 +821 -206
- 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: {
|
|
@@ -16619,66 +16619,86 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
|
|
|
16619
16619
|
}
|
|
16620
16620
|
};
|
|
16621
16621
|
}
|
|
16622
|
-
var INFERENCE_CREDENTIAL_NAMESPACE, MAX_INFERENCE_PRIVATE_FILE_BYTES,
|
|
16622
|
+
var INFERENCE_CREDENTIAL_NAMESPACE, MAX_INFERENCE_PRIVATE_FILE_BYTES, WINDOWS_PRIVATE_ACL_BROKER_SCRIPT, windowsPrivateAclBrokerInvocation, WindowsPrivateAclBroker, defaultWindowsPrivateAclBroker, runWindowsPrivateAcl, windowsAclCache, windowsAclIdentity, aclCacheKey, secureWindowsPrivatePath, invalidateWindowsAclCache, rebindHardenedWindowsAclAfterRename, rebindHardenedWindowsDirectoryAfterOwnedMutation, isDefaultWindowsPrivatePath, secureExistingWindowsPath, linuxProcessIdentity, windowsProcessIdentity, darwinProcessIdentity, runSmallIdentityCommand, cachedSystemBootIdentity, readInferenceSystemBootIdentity, defaultProcessIdentity, defaultCurrentProcessIdentity, processLockObservationCache, inferenceProcessIdentitiesMatch, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity;
|
|
16623
16623
|
var init_config = __esm({
|
|
16624
16624
|
"lib/inference-host/config.ts"() {
|
|
16625
16625
|
"use strict";
|
|
16626
16626
|
INFERENCE_CREDENTIAL_NAMESPACE = "vtxmacro-insights-inference";
|
|
16627
16627
|
MAX_INFERENCE_PRIVATE_FILE_BYTES = 16 * 1024 * 1024;
|
|
16628
|
-
|
|
16629
|
-
$
|
|
16630
|
-
$
|
|
16631
|
-
$
|
|
16632
|
-
|
|
16633
|
-
$
|
|
16634
|
-
$
|
|
16635
|
-
$
|
|
16636
|
-
|
|
16637
|
-
if($
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
|
|
16642
|
-
|
|
16643
|
-
|
|
16644
|
-
|
|
16645
|
-
|
|
16646
|
-
|
|
16647
|
-
|
|
16648
|
-
|
|
16649
|
-
|
|
16650
|
-
|
|
16651
|
-
|
|
16652
|
-
|
|
16653
|
-
|
|
16654
|
-
|
|
16655
|
-
|
|
16656
|
-
|
|
16657
|
-
|
|
16658
|
-
|
|
16659
|
-
}
|
|
16660
|
-
$
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16664
|
-
|
|
16665
|
-
$
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
}
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
|
|
16628
|
+
WINDOWS_PRIVATE_ACL_BROKER_SCRIPT = `$ErrorActionPreference='Stop'
|
|
16629
|
+
$ProgressPreference='SilentlyContinue'
|
|
16630
|
+
while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
16631
|
+
$requestId=$null
|
|
16632
|
+
try {
|
|
16633
|
+
if($line.Length -lt 2 -or $line.Length -gt 65536) { throw 'invalid request size' }
|
|
16634
|
+
$request=$line | ConvertFrom-Json
|
|
16635
|
+
$names=@($request.PSObject.Properties.Name | Sort-Object)
|
|
16636
|
+
if(($names -join ',') -ne 'id,kind,mode,path_b64') { throw 'invalid request shape' }
|
|
16637
|
+
if($request.id -isnot [long] -and $request.id -isnot [int]) { throw 'invalid request id' }
|
|
16638
|
+
$requestId=[long]$request.id
|
|
16639
|
+
if($requestId -lt 1) { throw 'invalid request id' }
|
|
16640
|
+
$kind=[string]$request.kind
|
|
16641
|
+
$mode=[string]$request.mode
|
|
16642
|
+
if($kind -ne 'directory' -and $kind -ne 'file') { throw 'invalid path kind' }
|
|
16643
|
+
if($mode -ne 'harden' -and $mode -ne 'verify' -and $mode -ne 'verify-owner') { throw 'invalid ACL mode' }
|
|
16644
|
+
$path=[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String([string]$request.path_b64))
|
|
16645
|
+
if([string]::IsNullOrWhiteSpace($path) -or $path.Length -gt 32767 -or $path.Contains([char]0)) { throw 'invalid path' }
|
|
16646
|
+
if(-not (Test-Path -LiteralPath $path)) {
|
|
16647
|
+
[Console]::Out.WriteLine((@{id=$requestId;status='missing'} | ConvertTo-Json -Compress))
|
|
16648
|
+
continue
|
|
16649
|
+
}
|
|
16650
|
+
$current=[Security.Principal.WindowsIdentity]::GetCurrent().User
|
|
16651
|
+
$system=New-Object Security.Principal.SecurityIdentifier('S-1-5-18')
|
|
16652
|
+
$admins=New-Object Security.Principal.SecurityIdentifier('S-1-5-32-544')
|
|
16653
|
+
$allowed=@($current.Value,$system.Value,$admins.Value)
|
|
16654
|
+
if($mode -eq 'harden') {
|
|
16655
|
+
$acl=Get-Acl -LiteralPath $path
|
|
16656
|
+
$existingOwner=(New-Object Security.Principal.NTAccount($acl.Owner)).Translate([Security.Principal.SecurityIdentifier]).Value
|
|
16657
|
+
if($existingOwner -ne $current.Value) { throw 'private ACL owner is invalid' }
|
|
16658
|
+
$acl.SetAccessRuleProtection($true,$false)
|
|
16659
|
+
foreach($existingRule in @($acl.Access)) { [void]$acl.RemoveAccessRuleSpecific($existingRule) }
|
|
16660
|
+
$inherit=if($kind -eq 'directory') {
|
|
16661
|
+
[Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit'
|
|
16662
|
+
} else { [Security.AccessControl.InheritanceFlags]::None }
|
|
16663
|
+
foreach($sid in @($current,$system,$admins)) {
|
|
16664
|
+
$rule=New-Object Security.AccessControl.FileSystemAccessRule(
|
|
16665
|
+
$sid,
|
|
16666
|
+
[Security.AccessControl.FileSystemRights]::FullControl,
|
|
16667
|
+
$inherit,
|
|
16668
|
+
[Security.AccessControl.PropagationFlags]::None,
|
|
16669
|
+
[Security.AccessControl.AccessControlType]::Allow
|
|
16670
|
+
)
|
|
16671
|
+
[void]$acl.AddAccessRule($rule)
|
|
16672
|
+
}
|
|
16673
|
+
(Get-Item -LiteralPath $path).SetAccessControl($acl)
|
|
16674
|
+
}
|
|
16675
|
+
$actual=Get-Acl -LiteralPath $path
|
|
16676
|
+
$owner=(New-Object Security.Principal.NTAccount($actual.Owner)).Translate([Security.Principal.SecurityIdentifier]).Value
|
|
16677
|
+
if($owner -ne $current.Value) { throw 'private ACL owner is invalid' }
|
|
16678
|
+
if($mode -ne 'verify-owner') {
|
|
16679
|
+
if(-not $actual.AreAccessRulesProtected) { throw 'private ACL inheritance is invalid' }
|
|
16680
|
+
$userFull=$false
|
|
16681
|
+
foreach($rule in $actual.Access) {
|
|
16682
|
+
$sid=$rule.IdentityReference.Translate([Security.Principal.SecurityIdentifier]).Value
|
|
16683
|
+
if($rule.IsInherited -or $allowed -notcontains $sid -or $rule.AccessControlType -ne [Security.AccessControl.AccessControlType]::Allow) {
|
|
16684
|
+
throw 'private ACL contains an unauthorized access rule'
|
|
16685
|
+
}
|
|
16686
|
+
if($sid -eq $current.Value -and (($rule.FileSystemRights -band [Security.AccessControl.FileSystemRights]::FullControl) -eq [Security.AccessControl.FileSystemRights]::FullControl)) { $userFull=$true }
|
|
16687
|
+
}
|
|
16688
|
+
if(-not $userFull) { throw 'private ACL does not grant the current user full control' }
|
|
16689
|
+
}
|
|
16690
|
+
[Console]::Out.WriteLine((@{id=$requestId;status='ok'} | ConvertTo-Json -Compress))
|
|
16691
|
+
} catch {
|
|
16692
|
+
[Console]::Out.WriteLine((@{id=$requestId;status='error'} | ConvertTo-Json -Compress))
|
|
16693
|
+
}
|
|
16694
|
+
}`;
|
|
16695
|
+
windowsPrivateAclBrokerInvocation = () => ({
|
|
16676
16696
|
args: [
|
|
16677
16697
|
"-NoLogo",
|
|
16678
16698
|
"-NoProfile",
|
|
16679
16699
|
"-NonInteractive",
|
|
16680
16700
|
"-EncodedCommand",
|
|
16681
|
-
Buffer.from(
|
|
16701
|
+
Buffer.from(WINDOWS_PRIVATE_ACL_BROKER_SCRIPT, "utf16le").toString("base64")
|
|
16682
16702
|
],
|
|
16683
16703
|
env: {
|
|
16684
16704
|
NODE_ENV: process.env.NODE_ENV,
|
|
@@ -16688,49 +16708,169 @@ if(-not $userFull) { throw 'private ACL does not grant the current user full con
|
|
|
16688
16708
|
PATHEXT: process.env.PATHEXT,
|
|
16689
16709
|
PSModulePath: process.env.PSModulePath,
|
|
16690
16710
|
TEMP: process.env.TEMP,
|
|
16691
|
-
TMP: process.env.TMP
|
|
16692
|
-
VTX_PRIVATE_PATH_B64: Buffer.from(path, "utf8").toString("base64"),
|
|
16693
|
-
VTX_PRIVATE_PATH_KIND: kind,
|
|
16694
|
-
VTX_PRIVATE_ACL_MODE: mode
|
|
16711
|
+
TMP: process.env.TMP
|
|
16695
16712
|
}
|
|
16696
16713
|
});
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
|
|
16707
|
-
|
|
16708
|
-
|
|
16709
|
-
|
|
16710
|
-
|
|
16711
|
-
|
|
16712
|
-
|
|
16713
|
-
|
|
16714
|
-
|
|
16715
|
-
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
|
|
16721
|
-
|
|
16714
|
+
WindowsPrivateAclBroker = class {
|
|
16715
|
+
constructor(dependencies = {}) {
|
|
16716
|
+
this.child = null;
|
|
16717
|
+
this.requestSequence = 0;
|
|
16718
|
+
this.queue = Promise.resolve();
|
|
16719
|
+
this.pending = null;
|
|
16720
|
+
this.outputBuffer = "";
|
|
16721
|
+
this.idleTimer = null;
|
|
16722
|
+
this.run = async (path, kind, mode) => {
|
|
16723
|
+
const operation = this.queue.then(
|
|
16724
|
+
() => this.dispatch(path, kind, mode),
|
|
16725
|
+
() => this.dispatch(path, kind, mode)
|
|
16726
|
+
);
|
|
16727
|
+
this.queue = operation.then(() => void 0, () => void 0);
|
|
16728
|
+
await operation;
|
|
16729
|
+
};
|
|
16730
|
+
this.requestTimeoutMs = dependencies.requestTimeoutMs ?? 15e3;
|
|
16731
|
+
this.idleShutdownMs = dependencies.idleShutdownMs ?? 3e4;
|
|
16732
|
+
this.spawnProcess = dependencies.spawnProcess ?? (() => {
|
|
16733
|
+
const invocation = windowsPrivateAclBrokerInvocation();
|
|
16734
|
+
return spawn("powershell.exe", [...invocation.args], {
|
|
16735
|
+
env: invocation.env,
|
|
16736
|
+
windowsHide: true,
|
|
16737
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
16738
|
+
});
|
|
16739
|
+
});
|
|
16740
|
+
}
|
|
16741
|
+
scheduleIdleShutdown() {
|
|
16742
|
+
if (this.idleTimer) clearTimeout(this.idleTimer);
|
|
16743
|
+
this.idleTimer = setTimeout(() => {
|
|
16744
|
+
this.idleTimer = null;
|
|
16745
|
+
const child = this.child;
|
|
16746
|
+
if (!child || this.pending) return;
|
|
16747
|
+
this.child = null;
|
|
16748
|
+
this.outputBuffer = "";
|
|
16749
|
+
child.stdin.end();
|
|
16750
|
+
const force = setTimeout(() => child.kill("SIGKILL"), 1e3);
|
|
16751
|
+
force.unref();
|
|
16752
|
+
child.once("exit", () => clearTimeout(force));
|
|
16753
|
+
}, this.idleShutdownMs);
|
|
16754
|
+
this.idleTimer.unref();
|
|
16755
|
+
}
|
|
16756
|
+
failChild(child, error48) {
|
|
16757
|
+
if (this.child !== child) return;
|
|
16758
|
+
this.child = null;
|
|
16759
|
+
this.outputBuffer = "";
|
|
16760
|
+
if (this.idleTimer) {
|
|
16761
|
+
clearTimeout(this.idleTimer);
|
|
16762
|
+
this.idleTimer = null;
|
|
16763
|
+
}
|
|
16764
|
+
const pending = this.pending;
|
|
16765
|
+
this.pending = null;
|
|
16766
|
+
if (pending) {
|
|
16767
|
+
clearTimeout(pending.timer);
|
|
16768
|
+
pending.reject(error48);
|
|
16769
|
+
}
|
|
16770
|
+
child.kill("SIGKILL");
|
|
16771
|
+
}
|
|
16772
|
+
acceptLine(child, line) {
|
|
16773
|
+
const pending = this.pending;
|
|
16774
|
+
if (!pending || !line || line.length > 4096) {
|
|
16775
|
+
this.failChild(child, new Error("Windows private ACL broker returned malformed output."));
|
|
16722
16776
|
return;
|
|
16723
16777
|
}
|
|
16724
|
-
|
|
16725
|
-
|
|
16778
|
+
let response;
|
|
16779
|
+
try {
|
|
16780
|
+
const parsed = JSON.parse(line);
|
|
16781
|
+
if (Object.keys(parsed).sort().join("\0") !== "id\0status" || parsed.id !== pending.id || !["ok", "missing", "error"].includes(String(parsed.status))) throw new Error("invalid response");
|
|
16782
|
+
response = parsed;
|
|
16783
|
+
} catch {
|
|
16784
|
+
this.failChild(child, new Error("Windows private ACL broker returned malformed output."));
|
|
16785
|
+
return;
|
|
16786
|
+
}
|
|
16787
|
+
this.pending = null;
|
|
16788
|
+
clearTimeout(pending.timer);
|
|
16789
|
+
if (response.status === "ok") {
|
|
16790
|
+
pending.resolve();
|
|
16791
|
+
} else if (response.status === "missing") {
|
|
16726
16792
|
const error48 = new Error("Windows private path no longer exists.");
|
|
16727
16793
|
error48.code = "ENOENT";
|
|
16728
|
-
|
|
16729
|
-
|
|
16794
|
+
pending.reject(error48);
|
|
16795
|
+
} else {
|
|
16796
|
+
pending.reject(new Error(`Windows private ACL ${pending.mode} failed.`));
|
|
16730
16797
|
}
|
|
16731
|
-
|
|
16732
|
-
}
|
|
16733
|
-
|
|
16798
|
+
this.scheduleIdleShutdown();
|
|
16799
|
+
}
|
|
16800
|
+
ensureChild() {
|
|
16801
|
+
if (this.child && this.child.exitCode === null && !this.child.killed) return this.child;
|
|
16802
|
+
const child = this.spawnProcess();
|
|
16803
|
+
this.child = child;
|
|
16804
|
+
this.outputBuffer = "";
|
|
16805
|
+
child.stdout.setEncoding("utf8");
|
|
16806
|
+
child.stdout.on("data", (chunk) => {
|
|
16807
|
+
if (this.child !== child) return;
|
|
16808
|
+
this.outputBuffer += chunk;
|
|
16809
|
+
if (this.outputBuffer.length > 65536) {
|
|
16810
|
+
this.failChild(child, new Error("Windows private ACL broker exceeded its output limit."));
|
|
16811
|
+
return;
|
|
16812
|
+
}
|
|
16813
|
+
while (this.child === child) {
|
|
16814
|
+
const newline = this.outputBuffer.indexOf("\n");
|
|
16815
|
+
if (newline < 0) break;
|
|
16816
|
+
const line = this.outputBuffer.slice(0, newline).trim();
|
|
16817
|
+
this.outputBuffer = this.outputBuffer.slice(newline + 1);
|
|
16818
|
+
this.acceptLine(child, line);
|
|
16819
|
+
}
|
|
16820
|
+
});
|
|
16821
|
+
child.stderr.on("data", () => void 0);
|
|
16822
|
+
child.once("error", () => {
|
|
16823
|
+
this.failChild(child, new Error("Windows private ACL broker failed to start."));
|
|
16824
|
+
});
|
|
16825
|
+
child.once("exit", () => {
|
|
16826
|
+
this.failChild(child, new Error("Windows private ACL broker exited before confirmation."));
|
|
16827
|
+
});
|
|
16828
|
+
child.unref();
|
|
16829
|
+
for (const stream of [child.stdin, child.stdout, child.stderr]) {
|
|
16830
|
+
stream.unref?.();
|
|
16831
|
+
}
|
|
16832
|
+
return child;
|
|
16833
|
+
}
|
|
16834
|
+
async dispatch(path, kind, mode) {
|
|
16835
|
+
if (this.idleTimer) {
|
|
16836
|
+
clearTimeout(this.idleTimer);
|
|
16837
|
+
this.idleTimer = null;
|
|
16838
|
+
}
|
|
16839
|
+
const id2 = ++this.requestSequence;
|
|
16840
|
+
const request = `${JSON.stringify({
|
|
16841
|
+
id: id2,
|
|
16842
|
+
kind,
|
|
16843
|
+
mode,
|
|
16844
|
+
path_b64: Buffer.from(path, "utf8").toString("base64")
|
|
16845
|
+
})}
|
|
16846
|
+
`;
|
|
16847
|
+
if (Buffer.byteLength(request, "utf8") > 65536) {
|
|
16848
|
+
throw new Error("Windows private ACL broker request exceeds its input limit.");
|
|
16849
|
+
}
|
|
16850
|
+
const child = this.ensureChild();
|
|
16851
|
+
await new Promise((resolvePromise, reject) => {
|
|
16852
|
+
const timer = setTimeout(() => {
|
|
16853
|
+
this.failChild(child, new Error("Windows private ACL broker request timed out."));
|
|
16854
|
+
}, this.requestTimeoutMs);
|
|
16855
|
+
this.pending = { id: id2, mode, resolve: resolvePromise, reject, timer };
|
|
16856
|
+
child.stdin.write(request, "utf8", (error48) => {
|
|
16857
|
+
if (error48) {
|
|
16858
|
+
this.failChild(child, new Error("Windows private ACL broker request failed."));
|
|
16859
|
+
}
|
|
16860
|
+
});
|
|
16861
|
+
});
|
|
16862
|
+
}
|
|
16863
|
+
close() {
|
|
16864
|
+
if (this.idleTimer) clearTimeout(this.idleTimer);
|
|
16865
|
+
this.idleTimer = null;
|
|
16866
|
+
const child = this.child;
|
|
16867
|
+
this.child = null;
|
|
16868
|
+
this.outputBuffer = "";
|
|
16869
|
+
if (child) child.stdin.end();
|
|
16870
|
+
}
|
|
16871
|
+
};
|
|
16872
|
+
defaultWindowsPrivateAclBroker = new WindowsPrivateAclBroker();
|
|
16873
|
+
runWindowsPrivateAcl = async (path, kind, mode) => await defaultWindowsPrivateAclBroker.run(path, kind, mode);
|
|
16734
16874
|
windowsAclCache = /* @__PURE__ */ new Map();
|
|
16735
16875
|
windowsAclIdentity = async (path) => {
|
|
16736
16876
|
const metadata = await lstat(path, { bigint: true });
|
|
@@ -28907,7 +29047,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
|
|
|
28907
29047
|
envelopePublicKey: options.envelopePublicKey
|
|
28908
29048
|
};
|
|
28909
29049
|
}
|
|
28910
|
-
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;
|
|
28911
29051
|
var init_runner = __esm({
|
|
28912
29052
|
"lib/inference-host/runner.ts"() {
|
|
28913
29053
|
"use strict";
|
|
@@ -28964,6 +29104,35 @@ var init_runner = __esm({
|
|
|
28964
29104
|
}
|
|
28965
29105
|
return models;
|
|
28966
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
|
+
};
|
|
28967
29136
|
FileInferenceHostRuntimeReceiptStore = class {
|
|
28968
29137
|
constructor(path, readPrivateFile = readInferencePrivateFile) {
|
|
28969
29138
|
this.path = path;
|
|
@@ -29604,6 +29773,22 @@ var init_runner = __esm({
|
|
|
29604
29773
|
} catch {
|
|
29605
29774
|
}
|
|
29606
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
|
+
};
|
|
29607
29792
|
const accountKey = inferenceCredentialAccountKey({
|
|
29608
29793
|
issuer: localState.issuer,
|
|
29609
29794
|
clientId: localState.client_id,
|
|
@@ -29869,17 +30054,6 @@ var init_runner = __esm({
|
|
|
29869
30054
|
let nextClaimAt = Math.max(now(), providerRetryAtMs ?? 0);
|
|
29870
30055
|
let pendingClaimPromotions = 0;
|
|
29871
30056
|
let onceClaimed = false;
|
|
29872
|
-
emitDiagnostic("runtime_started", {
|
|
29873
|
-
max_concurrency: settings.maxConcurrency,
|
|
29874
|
-
active_attempts: active.size,
|
|
29875
|
-
provider_cooldown_reason: providerCooldownReason,
|
|
29876
|
-
provider_cooldown_until: providerRetryAtMs === null ? null : isoAt(providerRetryAtMs),
|
|
29877
|
-
provider_weekly_quota: providerWeeklyQuotaFromRateLimits(
|
|
29878
|
-
providerRateLimits,
|
|
29879
|
-
providerRateLimitsObservedAtMs,
|
|
29880
|
-
now()
|
|
29881
|
-
)
|
|
29882
|
-
});
|
|
29883
30057
|
const recoveryQueue = [];
|
|
29884
30058
|
const launchClaim = (claim, recovery, claimRequest) => {
|
|
29885
30059
|
if (!recovery) {
|
|
@@ -29974,6 +30148,10 @@ var init_runner = __esm({
|
|
|
29974
30148
|
}
|
|
29975
30149
|
}).catch((error48) => {
|
|
29976
30150
|
failed += 1;
|
|
30151
|
+
const recovery2 = receipt.attempts[attemptId];
|
|
30152
|
+
if (recovery2?.phase === "terminal_pending") {
|
|
30153
|
+
emitTerminalRecoveryFailure(recovery2, error48);
|
|
30154
|
+
}
|
|
29977
30155
|
requestDrain(controlPlaneFatal(error48) ? "authority_lost" : "attempt_terminal_unconfirmed");
|
|
29978
30156
|
}).finally(() => {
|
|
29979
30157
|
settleClaimPromotion();
|
|
@@ -30029,6 +30207,7 @@ var init_runner = __esm({
|
|
|
30029
30207
|
await this.dependencies.codexAdapter.acknowledgeAttempt?.(recovery.attempt_id);
|
|
30030
30208
|
await removeRecoveredAttempt(recovery.attempt_id);
|
|
30031
30209
|
} catch (error48) {
|
|
30210
|
+
emitTerminalRecoveryFailure(recovery, error48);
|
|
30032
30211
|
requestDrain(controlPlaneFatal(error48) ? "authority_lost" : "attempt_terminal_unconfirmed");
|
|
30033
30212
|
break;
|
|
30034
30213
|
}
|
|
@@ -30036,6 +30215,19 @@ var init_runner = __esm({
|
|
|
30036
30215
|
}
|
|
30037
30216
|
recoveryQueue.push(recovery);
|
|
30038
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
|
+
}
|
|
30039
30231
|
while (!drainRequested && recoveryQueue.length > 0 && (settings.maxConcurrency === null || active.size < settings.maxConcurrency)) {
|
|
30040
30232
|
const recovery = recoveryQueue.shift();
|
|
30041
30233
|
launchClaim(recovery.claim, recovery);
|
|
@@ -30768,11 +30960,12 @@ var init_runner = __esm({
|
|
|
30768
30960
|
|
|
30769
30961
|
// lib/inference-host/service.ts
|
|
30770
30962
|
import { spawn as spawn5 } from "node:child_process";
|
|
30963
|
+
import { randomUUID } from "node:crypto";
|
|
30771
30964
|
import { createWriteStream, readFileSync } from "node:fs";
|
|
30772
30965
|
import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as rm4, writeFile as writeFile2 } from "node:fs/promises";
|
|
30773
30966
|
import { homedir as homedir2 } from "node:os";
|
|
30774
30967
|
import { dirname as dirname4, join as join5, resolve as resolve4 } from "node:path";
|
|
30775
|
-
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;
|
|
30776
30969
|
var init_service = __esm({
|
|
30777
30970
|
"lib/inference-host/service.ts"() {
|
|
30778
30971
|
"use strict";
|
|
@@ -30781,6 +30974,7 @@ var init_service = __esm({
|
|
|
30781
30974
|
SYSTEMD_UNIT = "vtx-inference-host.service";
|
|
30782
30975
|
LAUNCHD_LABEL = "com.vtxmacro.inference-host";
|
|
30783
30976
|
SERVICE_COOPERATIVE_STOP_SECONDS = 75;
|
|
30977
|
+
INFERENCE_HOST_SERVICE_DRAIN_COMMAND = "vtx-inference-host-service-drain-v1";
|
|
30784
30978
|
inferenceHostServiceChildEnvironment = (runtimeEnvironment2, inheritedEnvironment = process.env) => {
|
|
30785
30979
|
const environment = { ...inheritedEnvironment };
|
|
30786
30980
|
for (const key of Object.keys(environment)) {
|
|
@@ -30788,7 +30982,11 @@ var init_service = __esm({
|
|
|
30788
30982
|
delete environment[key];
|
|
30789
30983
|
}
|
|
30790
30984
|
}
|
|
30791
|
-
return {
|
|
30985
|
+
return {
|
|
30986
|
+
...environment,
|
|
30987
|
+
...runtimeEnvironment2,
|
|
30988
|
+
VTX_INFERENCE_HOST_SERVICE_CHILD: "1"
|
|
30989
|
+
};
|
|
30792
30990
|
};
|
|
30793
30991
|
isWindowsSubsystemForLinux = (env = process.env, kernelRelease) => Boolean(
|
|
30794
30992
|
String(env.WSL_INTEROP || "").trim() || String(env.WSL_DISTRO_NAME || "").trim() || /microsoft/iu.test(kernelRelease ?? (() => {
|
|
@@ -30802,6 +31000,7 @@ var init_service = __esm({
|
|
|
30802
31000
|
inferenceHostServiceManifestPath = (config2) => `${config2.supervisorStatePath}.service.json`;
|
|
30803
31001
|
inferenceHostServiceDesiredPath = (config2) => `${config2.supervisorStatePath}.service-desired.json`;
|
|
30804
31002
|
inferenceHostServiceLogPath = (config2) => `${config2.supervisorStatePath}.service.log`;
|
|
31003
|
+
inferenceHostServiceRuntimePath = (config2) => `${config2.supervisorStatePath}.service-runtime.json`;
|
|
30805
31004
|
xmlEscape = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30806
31005
|
plistEscape = xmlEscape;
|
|
30807
31006
|
systemdQuote = (value) => `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("%", "%%")}"`;
|
|
@@ -30852,6 +31051,7 @@ var init_service = __esm({
|
|
|
30852
31051
|
}
|
|
30853
31052
|
return value;
|
|
30854
31053
|
};
|
|
31054
|
+
manifestGeneration = (value, installedAt) => typeof value === "string" && /^[A-Za-z0-9._:-]{1,160}$/u.test(value) ? value : `legacy:${installedAt}`;
|
|
30855
31055
|
assertWorker = (value) => {
|
|
30856
31056
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
30857
31057
|
throw new Error("Inference-host service worker is invalid.");
|
|
@@ -30892,6 +31092,7 @@ var init_service = __esm({
|
|
|
30892
31092
|
});
|
|
30893
31093
|
return {
|
|
30894
31094
|
schema_version: "vtx_inference_service_v3",
|
|
31095
|
+
generation: manifestGeneration(void 0, legacy.installed_at),
|
|
30895
31096
|
installed_at: legacy.installed_at,
|
|
30896
31097
|
executable: assertServicePath(legacy.executable),
|
|
30897
31098
|
script: assertServicePath(legacy.script),
|
|
@@ -30925,6 +31126,7 @@ var init_service = __esm({
|
|
|
30925
31126
|
}
|
|
30926
31127
|
return {
|
|
30927
31128
|
schema_version: "vtx_inference_service_v3",
|
|
31129
|
+
generation: manifestGeneration(void 0, legacy.installed_at),
|
|
30928
31130
|
installed_at: legacy.installed_at,
|
|
30929
31131
|
executable: assertServicePath(legacy.executable),
|
|
30930
31132
|
script: assertServicePath(legacy.script),
|
|
@@ -30942,6 +31144,34 @@ var init_service = __esm({
|
|
|
30942
31144
|
if (new Set(workers.map((worker) => worker.instance_name)).size !== workers.length) {
|
|
30943
31145
|
throw new Error("Inference-host service worker names must be unique.");
|
|
30944
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
|
+
});
|
|
30945
31175
|
return { ...record2, workers };
|
|
30946
31176
|
};
|
|
30947
31177
|
assertDesiredState = (value) => {
|
|
@@ -30964,6 +31194,42 @@ var init_service = __esm({
|
|
|
30964
31194
|
throw error48;
|
|
30965
31195
|
}
|
|
30966
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
|
+
};
|
|
30967
31233
|
readInferenceHostServiceDesired = async (path) => {
|
|
30968
31234
|
const raw = await readInferencePrivateFile(path, "Inference-host service desired state");
|
|
30969
31235
|
if (raw === null) return false;
|
|
@@ -31086,6 +31352,9 @@ WantedBy=default.target
|
|
|
31086
31352
|
<key>StandardErrorPath</key><string>${plistEscape(logPath)}</string>
|
|
31087
31353
|
</dict></plist>
|
|
31088
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]));
|
|
31089
31358
|
InferenceHostServiceManager = class {
|
|
31090
31359
|
constructor(config2, dependencies = {}) {
|
|
31091
31360
|
this.config = config2;
|
|
@@ -31102,6 +31371,8 @@ WantedBy=default.target
|
|
|
31102
31371
|
});
|
|
31103
31372
|
this.stopWaitAttempts = dependencies.stopWaitAttempts ?? SERVICE_COOPERATIVE_STOP_SECONDS * 4;
|
|
31104
31373
|
this.startWaitAttempts = dependencies.startWaitAttempts ?? 40;
|
|
31374
|
+
this.reconcileWaitAttempts = dependencies.reconcileWaitAttempts ?? SERVICE_COOPERATIVE_STOP_SECONDS * 4;
|
|
31375
|
+
this.confirmInitialReadiness = dependencies.confirmInitialReadiness ?? true;
|
|
31105
31376
|
this.acquireProcessLock = dependencies.acquireProcessLock ?? acquireInferenceHostProcessLock;
|
|
31106
31377
|
managerName(this.platform);
|
|
31107
31378
|
if (dependencies.platform === void 0 && this.platform === "linux" && isWindowsSubsystemForLinux()) {
|
|
@@ -31119,6 +31390,9 @@ WantedBy=default.target
|
|
|
31119
31390
|
logPath() {
|
|
31120
31391
|
return inferenceHostServiceLogPath(this.config);
|
|
31121
31392
|
}
|
|
31393
|
+
runtimePath() {
|
|
31394
|
+
return inferenceHostServiceRuntimePath(this.config);
|
|
31395
|
+
}
|
|
31122
31396
|
controlLockPath() {
|
|
31123
31397
|
return `${this.config.supervisorProcessLockPath}.service-control`;
|
|
31124
31398
|
}
|
|
@@ -31204,7 +31478,77 @@ WantedBy=default.target
|
|
|
31204
31478
|
}
|
|
31205
31479
|
throw new Error("Background service did not reach an active state within 10 seconds.");
|
|
31206
31480
|
}
|
|
31207
|
-
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) {
|
|
31208
31552
|
const args = serviceArguments(manifest.script, this.manifestPath());
|
|
31209
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);
|
|
31210
31554
|
let managerInstallAttempted = false;
|
|
@@ -31240,6 +31584,9 @@ ${started.stderr}`)) {
|
|
|
31240
31584
|
throw new Error(`Background service start failed: ${started.stderr.trim()}`);
|
|
31241
31585
|
}
|
|
31242
31586
|
await this.waitForManagerActive();
|
|
31587
|
+
if (this.confirmInitialReadiness) {
|
|
31588
|
+
await this.waitForManifestApplied(manifest, targetInstanceName);
|
|
31589
|
+
}
|
|
31243
31590
|
}
|
|
31244
31591
|
return await this.status();
|
|
31245
31592
|
} catch (error48) {
|
|
@@ -31264,22 +31611,80 @@ ${cleanup.stderr}`)) {
|
|
|
31264
31611
|
}
|
|
31265
31612
|
await rm4(this.manifestPath(), { force: true }).catch(() => void 0);
|
|
31266
31613
|
await rm4(this.desiredPath(), { force: true }).catch(() => void 0);
|
|
31614
|
+
await rm4(this.runtimePath(), { force: true }).catch(() => void 0);
|
|
31267
31615
|
if (this.platform === "linux") {
|
|
31268
31616
|
await this.runCommand("systemctl", ["--user", "daemon-reload"]).catch(() => void 0);
|
|
31269
31617
|
}
|
|
31270
31618
|
throw error48;
|
|
31271
31619
|
}
|
|
31272
31620
|
}
|
|
31273
|
-
async replaceManifestUnlocked(next, desiredRunning) {
|
|
31621
|
+
async replaceManifestUnlocked(next, desiredRunning, targetInstanceName) {
|
|
31274
31622
|
const previous = await readInferenceHostServiceManifest(this.manifestPath());
|
|
31275
31623
|
const previousDesired = previous ? await readInferenceHostServiceDesired(this.desiredPath()) : false;
|
|
31276
|
-
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
|
+
}
|
|
31277
31676
|
try {
|
|
31278
|
-
return await this.registerManifestUnlocked(next, desiredRunning);
|
|
31677
|
+
return await this.registerManifestUnlocked(next, desiredRunning, targetInstanceName);
|
|
31279
31678
|
} catch (error48) {
|
|
31280
31679
|
if (!previous) throw error48;
|
|
31281
31680
|
try {
|
|
31282
|
-
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
|
+
);
|
|
31283
31688
|
} catch (rollbackError) {
|
|
31284
31689
|
throw new Error(
|
|
31285
31690
|
"Inference-host service reconfiguration failed and the previous supervisor could not be restored.",
|
|
@@ -31336,6 +31741,7 @@ ${cleanup.stderr}`)) {
|
|
|
31336
31741
|
].sort((left, right) => left.instance_name.localeCompare(right.instance_name));
|
|
31337
31742
|
const manifest = assertManifest({
|
|
31338
31743
|
schema_version: "vtx_inference_service_v3",
|
|
31744
|
+
generation: randomUUID(),
|
|
31339
31745
|
installed_at: this.now().toISOString(),
|
|
31340
31746
|
executable: this.executable,
|
|
31341
31747
|
script: this.script,
|
|
@@ -31344,7 +31750,8 @@ ${cleanup.stderr}`)) {
|
|
|
31344
31750
|
});
|
|
31345
31751
|
return await this.replaceManifestUnlocked(
|
|
31346
31752
|
manifest,
|
|
31347
|
-
options.startImmediately !== false
|
|
31753
|
+
options.startImmediately !== false,
|
|
31754
|
+
this.config.instanceName
|
|
31348
31755
|
);
|
|
31349
31756
|
}
|
|
31350
31757
|
async start() {
|
|
@@ -31376,41 +31783,56 @@ ${result2.stderr}`)) {
|
|
|
31376
31783
|
if (!manifest) {
|
|
31377
31784
|
throw new Error("Inference-host service is not installed.");
|
|
31378
31785
|
}
|
|
31786
|
+
const restoreOnFailure = await readInferenceHostServiceDesired(this.desiredPath());
|
|
31379
31787
|
await writeDesired(this.desiredPath(), false, this.now());
|
|
31380
|
-
|
|
31381
|
-
|
|
31382
|
-
|
|
31383
|
-
|
|
31384
|
-
|
|
31385
|
-
|
|
31386
|
-
|
|
31387
|
-
|
|
31388
|
-
|
|
31389
|
-
|
|
31390
|
-
|
|
31391
|
-
|
|
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;
|
|
31392
31803
|
}
|
|
31393
|
-
throw error48;
|
|
31394
31804
|
}
|
|
31395
|
-
|
|
31396
|
-
|
|
31397
|
-
|
|
31398
|
-
|
|
31399
|
-
|
|
31400
|
-
|
|
31401
|
-
|
|
31402
|
-
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}
|
|
31403
31812
|
${result2.stderr}`)) {
|
|
31404
|
-
|
|
31405
|
-
|
|
31406
|
-
|
|
31407
|
-
|
|
31408
|
-
|
|
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;
|
|
31409
31831
|
}
|
|
31410
|
-
return status;
|
|
31411
31832
|
}
|
|
31412
|
-
async status() {
|
|
31833
|
+
async status(confirmedRuntime) {
|
|
31413
31834
|
const manifest = await readInferenceHostServiceManifest(this.manifestPath());
|
|
31835
|
+
const runtime = confirmedRuntime?.manifest_generation === manifest?.generation ? confirmedRuntime : await readRuntimeAcrossAtomicReplacement(this.runtimePath()).catch(() => null);
|
|
31414
31836
|
const desired = await readInferenceHostServiceDesired(this.desiredPath());
|
|
31415
31837
|
const result2 = await this.managerCommand("status");
|
|
31416
31838
|
const output3 = result2.stdout.trim();
|
|
@@ -31428,7 +31850,8 @@ ${result2.stderr}`)) {
|
|
|
31428
31850
|
display_name: worker.display_name,
|
|
31429
31851
|
max_concurrency: worker.max_concurrency,
|
|
31430
31852
|
authenticated_account_email: worker.authenticated_account_email,
|
|
31431
|
-
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"
|
|
31432
31855
|
})) ?? []
|
|
31433
31856
|
};
|
|
31434
31857
|
}
|
|
@@ -31466,6 +31889,7 @@ ${result2.stderr}`)) {
|
|
|
31466
31889
|
if (remaining.length === 0) return await this.uninstallUnlocked();
|
|
31467
31890
|
return await this.replaceManifestUnlocked({
|
|
31468
31891
|
...manifest,
|
|
31892
|
+
generation: randomUUID(),
|
|
31469
31893
|
installed_at: this.now().toISOString(),
|
|
31470
31894
|
workers: remaining
|
|
31471
31895
|
}, await readInferenceHostServiceDesired(this.desiredPath()));
|
|
@@ -31493,6 +31917,7 @@ ${result2.stderr}`)) {
|
|
|
31493
31917
|
if (this.platform === "linux") await this.runCommand("systemctl", ["--user", "daemon-reload"]);
|
|
31494
31918
|
await rm4(this.manifestPath(), { force: true });
|
|
31495
31919
|
await rm4(this.desiredPath(), { force: true });
|
|
31920
|
+
await rm4(this.runtimePath(), { force: true });
|
|
31496
31921
|
return {
|
|
31497
31922
|
installed: false,
|
|
31498
31923
|
desired_running: false,
|
|
@@ -31514,7 +31939,8 @@ ${result2.stderr}`)) {
|
|
|
31514
31939
|
`, resolvePromise);
|
|
31515
31940
|
});
|
|
31516
31941
|
};
|
|
31517
|
-
|
|
31942
|
+
spawnInferenceHostServiceChild = async (manifest, worker, signal, onReady = () => {
|
|
31943
|
+
}) => {
|
|
31518
31944
|
const args = [
|
|
31519
31945
|
manifest.script,
|
|
31520
31946
|
"inference-host",
|
|
@@ -31527,6 +31953,8 @@ ${result2.stderr}`)) {
|
|
|
31527
31953
|
const log = createWriteStream(manifest.log_path, { flags: "a", mode: 384 });
|
|
31528
31954
|
return await new Promise((resolvePromise, reject) => {
|
|
31529
31955
|
let stdout = "";
|
|
31956
|
+
let cooperativeStopTimedOut = false;
|
|
31957
|
+
let cooperativeStopTimer = null;
|
|
31530
31958
|
const pending = { stdout: "", stderr: "" };
|
|
31531
31959
|
const writeTaggedOutput = (stream, text, flush = false) => {
|
|
31532
31960
|
const lines = `${pending[stream]}${text}`.split(/\r?\n/u);
|
|
@@ -31539,6 +31967,7 @@ ${result2.stderr}`)) {
|
|
|
31539
31967
|
try {
|
|
31540
31968
|
const parsed = JSON.parse(line);
|
|
31541
31969
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
31970
|
+
if (parsed.event === "runtime_started") onReady();
|
|
31542
31971
|
log.write(`${JSON.stringify({
|
|
31543
31972
|
...parsed,
|
|
31544
31973
|
instance_name: worker.instance_name
|
|
@@ -31561,7 +31990,7 @@ ${result2.stderr}`)) {
|
|
|
31561
31990
|
const child = spawn5(manifest.executable, args, {
|
|
31562
31991
|
env: inferenceHostServiceChildEnvironment(worker.runtime_environment),
|
|
31563
31992
|
windowsHide: true,
|
|
31564
|
-
stdio: ["
|
|
31993
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
31565
31994
|
});
|
|
31566
31995
|
child.stdout.on("data", (chunk) => {
|
|
31567
31996
|
const text = chunk.toString("utf8");
|
|
@@ -31569,10 +31998,22 @@ ${result2.stderr}`)) {
|
|
|
31569
31998
|
stdout = `${stdout}${text}`.slice(-65536);
|
|
31570
31999
|
});
|
|
31571
32000
|
child.stderr.on("data", (chunk) => writeTaggedOutput("stderr", chunk.toString("utf8")));
|
|
31572
|
-
|
|
31573
|
-
|
|
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 });
|
|
31574
32014
|
child.once("error", (error48) => {
|
|
31575
32015
|
signal.removeEventListener("abort", onAbort);
|
|
32016
|
+
if (cooperativeStopTimer) clearTimeout(cooperativeStopTimer);
|
|
31576
32017
|
writeTaggedOutput("stdout", "", true);
|
|
31577
32018
|
writeTaggedOutput("stderr", "", true);
|
|
31578
32019
|
log.end();
|
|
@@ -31580,6 +32021,7 @@ ${result2.stderr}`)) {
|
|
|
31580
32021
|
});
|
|
31581
32022
|
child.once("exit", (code) => {
|
|
31582
32023
|
signal.removeEventListener("abort", onAbort);
|
|
32024
|
+
if (cooperativeStopTimer) clearTimeout(cooperativeStopTimer);
|
|
31583
32025
|
writeTaggedOutput("stdout", "", true);
|
|
31584
32026
|
writeTaggedOutput("stderr", "", true);
|
|
31585
32027
|
log.end();
|
|
@@ -31599,81 +32041,231 @@ ${result2.stderr}`)) {
|
|
|
31599
32041
|
resolvePromise({
|
|
31600
32042
|
exitCode: code ?? 1,
|
|
31601
32043
|
uptimeMs: Date.now() - startedAt,
|
|
31602
|
-
drainReason
|
|
32044
|
+
drainReason,
|
|
32045
|
+
cooperativeStopTimedOut
|
|
31603
32046
|
});
|
|
31604
32047
|
});
|
|
31605
32048
|
});
|
|
31606
32049
|
};
|
|
31607
32050
|
runInferenceHostServiceSupervisor = async (manifestPath, options = {}) => {
|
|
31608
|
-
const
|
|
31609
|
-
if (!
|
|
32051
|
+
const initialManifest = await readInferenceHostServiceManifest(manifestPath);
|
|
32052
|
+
if (!initialManifest) throw new Error("Inference-host service manifest is missing.");
|
|
31610
32053
|
const desiredPath = manifestPath.replace(/\.service\.json$/u, ".service-desired.json");
|
|
32054
|
+
const runtimePath = manifestPath.replace(/\.service\.json$/u, ".service-runtime.json");
|
|
31611
32055
|
const signal = options.signal ?? new AbortController().signal;
|
|
31612
32056
|
const sleep4 = options.sleep ?? (async (milliseconds) => {
|
|
31613
32057
|
await new Promise((resolvePromise) => setTimeout(resolvePromise, milliseconds));
|
|
31614
32058
|
});
|
|
31615
|
-
const launch = options.runWorker ?? options.spawnChild ??
|
|
31616
|
-
await appendServiceLog(
|
|
32059
|
+
const launch = options.runWorker ?? options.spawnChild ?? spawnInferenceHostServiceChild;
|
|
32060
|
+
await appendServiceLog(initialManifest.log_path, "service_supervisor_started", {
|
|
31617
32061
|
adapter: "codex",
|
|
31618
|
-
instances:
|
|
32062
|
+
instances: initialManifest.workers.map((worker) => worker.instance_name)
|
|
31619
32063
|
});
|
|
31620
|
-
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) => {
|
|
31621
32108
|
let failures = 0;
|
|
31622
|
-
while (!signal.aborted && await readDesiredAcrossAtomicReplacement(desiredPath)) {
|
|
32109
|
+
while (!signal.aborted && !record2.controller.signal.aborted && await readDesiredAcrossAtomicReplacement(desiredPath)) {
|
|
31623
32110
|
try {
|
|
31624
|
-
|
|
31625
|
-
const
|
|
32111
|
+
await updateRecord(record2, "starting");
|
|
32112
|
+
const attemptController = new AbortController();
|
|
32113
|
+
const forwardAbort = () => attemptController.abort();
|
|
31626
32114
|
signal.addEventListener("abort", forwardAbort, { once: true });
|
|
31627
|
-
|
|
31628
|
-
let monitorError = null;
|
|
31629
|
-
const desiredMonitor = (async () => {
|
|
31630
|
-
while (!workerComplete && !workerController.signal.aborted) {
|
|
31631
|
-
await sleep4(500);
|
|
31632
|
-
if (!await readDesiredAcrossAtomicReplacement(desiredPath)) {
|
|
31633
|
-
workerController.abort();
|
|
31634
|
-
break;
|
|
31635
|
-
}
|
|
31636
|
-
}
|
|
31637
|
-
})().catch((error48) => {
|
|
31638
|
-
monitorError = error48;
|
|
31639
|
-
workerController.abort();
|
|
31640
|
-
});
|
|
32115
|
+
record2.controller.signal.addEventListener("abort", forwardAbort, { once: true });
|
|
31641
32116
|
let result2;
|
|
32117
|
+
let launchSettled = false;
|
|
32118
|
+
let readinessTask = Promise.resolve();
|
|
32119
|
+
let readinessSignalled = false;
|
|
31642
32120
|
try {
|
|
31643
|
-
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
|
+
);
|
|
31644
32136
|
} finally {
|
|
31645
|
-
|
|
31646
|
-
|
|
32137
|
+
launchSettled = true;
|
|
32138
|
+
attemptController.abort();
|
|
31647
32139
|
signal.removeEventListener("abort", forwardAbort);
|
|
31648
|
-
|
|
32140
|
+
record2.controller.signal.removeEventListener("abort", forwardAbort);
|
|
32141
|
+
await readinessTask;
|
|
32142
|
+
}
|
|
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");
|
|
31649
32149
|
}
|
|
31650
|
-
if (
|
|
31651
|
-
if (signal.aborted || !await readDesiredAcrossAtomicReplacement(desiredPath)) break;
|
|
32150
|
+
if (signal.aborted || record2.controller.signal.aborted || !await readDesiredAcrossAtomicReplacement(desiredPath)) break;
|
|
31652
32151
|
failures = result2.uptimeMs >= 6e4 ? 0 : failures + 1;
|
|
31653
32152
|
const retryAfterMs = Math.min(1e3 * 2 ** Math.min(failures, 5), 3e4);
|
|
31654
|
-
await
|
|
31655
|
-
|
|
32153
|
+
await updateRecord(record2, "failed", "worker_exited");
|
|
32154
|
+
await appendServiceLog(serviceManifest.log_path, "worker_exited", {
|
|
32155
|
+
instance_name: record2.worker.instance_name,
|
|
31656
32156
|
exit_code: result2.exitCode,
|
|
31657
32157
|
uptime_ms: result2.uptimeMs,
|
|
31658
32158
|
drain_reason: result2.drainReason ?? null,
|
|
31659
32159
|
retry_after_ms: retryAfterMs
|
|
31660
32160
|
});
|
|
31661
|
-
await
|
|
32161
|
+
await waitRetry(retryAfterMs, record2.controller);
|
|
31662
32162
|
} catch (error48) {
|
|
31663
|
-
if (
|
|
32163
|
+
if (error48 instanceof Error && error48.message === "worker_cooperative_stop_timeout") throw error48;
|
|
32164
|
+
if (signal.aborted || record2.controller.signal.aborted) break;
|
|
31664
32165
|
failures += 1;
|
|
31665
32166
|
const retryAfterMs = Math.min(1e3 * 2 ** Math.min(failures, 5), 3e4);
|
|
31666
|
-
await
|
|
31667
|
-
|
|
32167
|
+
await updateRecord(record2, "failed", "worker_launch_failed");
|
|
32168
|
+
await appendServiceLog(serviceManifest.log_path, "worker_launch_failed", {
|
|
32169
|
+
instance_name: record2.worker.instance_name,
|
|
31668
32170
|
error: error48 instanceof Error ? error48.message : "unknown",
|
|
31669
32171
|
retry_after_ms: retryAfterMs
|
|
31670
32172
|
});
|
|
31671
|
-
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);
|
|
31672
32241
|
}
|
|
31673
32242
|
}
|
|
32243
|
+
await persistRuntime();
|
|
31674
32244
|
};
|
|
31675
|
-
await
|
|
31676
|
-
|
|
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
|
+
}
|
|
31677
32269
|
};
|
|
31678
32270
|
}
|
|
31679
32271
|
});
|
|
@@ -31682,9 +32274,10 @@ ${result2.stderr}`)) {
|
|
|
31682
32274
|
var cli_exports = {};
|
|
31683
32275
|
__export(cli_exports, {
|
|
31684
32276
|
INFERENCE_HOST_CLI_VERSION: () => INFERENCE_HOST_CLI_VERSION,
|
|
32277
|
+
registerInferenceHostServiceControlInput: () => registerInferenceHostServiceControlInput,
|
|
31685
32278
|
runInferenceHostCli: () => runInferenceHostCli
|
|
31686
32279
|
});
|
|
31687
|
-
import { randomUUID } from "node:crypto";
|
|
32280
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
31688
32281
|
import { spawn as spawn6 } from "node:child_process";
|
|
31689
32282
|
import { lstat as lstat4, realpath as realpath4, rm as rm5 } from "node:fs/promises";
|
|
31690
32283
|
import { join as join6, resolve as resolve5 } from "node:path";
|
|
@@ -31762,7 +32355,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
31762
32355
|
};
|
|
31763
32356
|
}
|
|
31764
32357
|
}
|
|
31765
|
-
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;
|
|
31766
32359
|
var init_cli = __esm({
|
|
31767
32360
|
"lib/inference-host/cli.ts"() {
|
|
31768
32361
|
"use strict";
|
|
@@ -32007,14 +32600,35 @@ Durable service:
|
|
|
32007
32600
|
});
|
|
32008
32601
|
child.unref();
|
|
32009
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
|
+
};
|
|
32010
32620
|
defaultRegisterLifecycleSignalHandlers = (abort) => {
|
|
32011
32621
|
const onSigint = () => abort("SIGINT");
|
|
32012
32622
|
const onSigterm = () => abort("SIGTERM");
|
|
32013
32623
|
process.on("SIGINT", onSigint);
|
|
32014
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
|
+
};
|
|
32015
32628
|
return () => {
|
|
32016
32629
|
process.off("SIGINT", onSigint);
|
|
32017
32630
|
process.off("SIGTERM", onSigterm);
|
|
32631
|
+
unregisterControlInput();
|
|
32018
32632
|
};
|
|
32019
32633
|
};
|
|
32020
32634
|
lifecycleCancellation = (dependencies) => {
|
|
@@ -32181,7 +32795,7 @@ Durable service:
|
|
|
32181
32795
|
throw new Error("Inference host credential recovery is required before login.");
|
|
32182
32796
|
}
|
|
32183
32797
|
const keyPair = generateExternalInferenceEnvelopeKeyPair();
|
|
32184
|
-
const hostId =
|
|
32798
|
+
const hostId = randomUUID2();
|
|
32185
32799
|
const beginLogin = dependencies.beginLogin ?? beginInferenceOAuthLogin;
|
|
32186
32800
|
const pending = await beginLogin({
|
|
32187
32801
|
apiUrl: config2.apiUrl,
|
|
@@ -32404,6 +33018,7 @@ Waiting for approval...
|
|
|
32404
33018
|
registered: receipt.registered,
|
|
32405
33019
|
advertisement_generation: receipt.advertisement_generation,
|
|
32406
33020
|
pending_attempts: Object.keys(receipt.attempts).length + (receipt.pending_claim_request ? 1 : 0),
|
|
33021
|
+
recovery: summarizeInferenceHostRuntimeRecovery(receipt),
|
|
32407
33022
|
updated_at: receipt.updated_at
|
|
32408
33023
|
} : null,
|
|
32409
33024
|
agent_attempt: agentAttempt ? {
|
|
@@ -32715,7 +33330,7 @@ Waiting for approval...
|
|
|
32715
33330
|
}
|
|
32716
33331
|
return record2;
|
|
32717
33332
|
};
|
|
32718
|
-
agentOperationId = (kind) => `${kind}-${
|
|
33333
|
+
agentOperationId = (kind) => `${kind}-${randomUUID2()}`;
|
|
32719
33334
|
agentSession = async (config2, dependencies, warnings, signal) => {
|
|
32720
33335
|
if (await readRevocationCheckpoint(config2)) {
|
|
32721
33336
|
throw new Error("Inference host revocation recovery must finish first.");
|
|
@@ -33363,7 +33978,7 @@ var init_types = __esm({
|
|
|
33363
33978
|
});
|
|
33364
33979
|
|
|
33365
33980
|
// lib/agent-core/client.ts
|
|
33366
|
-
import { randomUUID as
|
|
33981
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
33367
33982
|
function normalizeApiUrl(value) {
|
|
33368
33983
|
const parsed = String(value || "").trim();
|
|
33369
33984
|
if (!parsed) {
|
|
@@ -33625,7 +34240,7 @@ var init_client = __esm({
|
|
|
33625
34240
|
return this.request("/trading/ai/runtime/decision", {
|
|
33626
34241
|
method: "POST",
|
|
33627
34242
|
profileId,
|
|
33628
|
-
idempotencyKey:
|
|
34243
|
+
idempotencyKey: randomUUID3(),
|
|
33629
34244
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
33630
34245
|
body: payload
|
|
33631
34246
|
});
|
|
@@ -33634,7 +34249,7 @@ var init_client = __esm({
|
|
|
33634
34249
|
return this.request("/trading/ai/runtime/trade-sync", {
|
|
33635
34250
|
method: "POST",
|
|
33636
34251
|
profileId,
|
|
33637
|
-
idempotencyKey:
|
|
34252
|
+
idempotencyKey: randomUUID3(),
|
|
33638
34253
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
33639
34254
|
body: payload
|
|
33640
34255
|
});
|
|
@@ -33643,7 +34258,7 @@ var init_client = __esm({
|
|
|
33643
34258
|
return this.request("/trading/ai/runtime/error", {
|
|
33644
34259
|
method: "POST",
|
|
33645
34260
|
profileId,
|
|
33646
|
-
idempotencyKey:
|
|
34261
|
+
idempotencyKey: randomUUID3(),
|
|
33647
34262
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
33648
34263
|
body: payload
|
|
33649
34264
|
});
|
|
@@ -33655,7 +34270,7 @@ var init_client = __esm({
|
|
|
33655
34270
|
return this.request("/trading/market-order", {
|
|
33656
34271
|
method: "POST",
|
|
33657
34272
|
profileId,
|
|
33658
|
-
idempotencyKey:
|
|
34273
|
+
idempotencyKey: randomUUID3(),
|
|
33659
34274
|
body: payload
|
|
33660
34275
|
});
|
|
33661
34276
|
}
|
|
@@ -33663,7 +34278,7 @@ var init_client = __esm({
|
|
|
33663
34278
|
return this.request("/trading/limit-order", {
|
|
33664
34279
|
method: "POST",
|
|
33665
34280
|
profileId,
|
|
33666
|
-
idempotencyKey:
|
|
34281
|
+
idempotencyKey: randomUUID3(),
|
|
33667
34282
|
body: payload
|
|
33668
34283
|
});
|
|
33669
34284
|
}
|
|
@@ -33671,7 +34286,7 @@ var init_client = __esm({
|
|
|
33671
34286
|
return this.request("/trading/cancel-order", {
|
|
33672
34287
|
method: "POST",
|
|
33673
34288
|
profileId,
|
|
33674
|
-
idempotencyKey:
|
|
34289
|
+
idempotencyKey: randomUUID3(),
|
|
33675
34290
|
body: payload
|
|
33676
34291
|
});
|
|
33677
34292
|
}
|
|
@@ -33690,7 +34305,7 @@ var init_client = __esm({
|
|
|
33690
34305
|
return this.request("/trading/ai/start", {
|
|
33691
34306
|
method: "POST",
|
|
33692
34307
|
profileId,
|
|
33693
|
-
idempotencyKey:
|
|
34308
|
+
idempotencyKey: randomUUID3(),
|
|
33694
34309
|
body: payload
|
|
33695
34310
|
});
|
|
33696
34311
|
}
|
|
@@ -33698,7 +34313,7 @@ var init_client = __esm({
|
|
|
33698
34313
|
return this.request("/trading/ai/stop", {
|
|
33699
34314
|
method: "POST",
|
|
33700
34315
|
profileId,
|
|
33701
|
-
idempotencyKey:
|
|
34316
|
+
idempotencyKey: randomUUID3(),
|
|
33702
34317
|
body: {}
|
|
33703
34318
|
});
|
|
33704
34319
|
}
|
|
@@ -33706,7 +34321,7 @@ var init_client = __esm({
|
|
|
33706
34321
|
return this.request("/trading/ai/assistant/start", {
|
|
33707
34322
|
method: "POST",
|
|
33708
34323
|
profileId,
|
|
33709
|
-
idempotencyKey:
|
|
34324
|
+
idempotencyKey: randomUUID3(),
|
|
33710
34325
|
body: {}
|
|
33711
34326
|
});
|
|
33712
34327
|
}
|
|
@@ -33714,7 +34329,7 @@ var init_client = __esm({
|
|
|
33714
34329
|
return this.request("/trading/ai/assistant/stop", {
|
|
33715
34330
|
method: "POST",
|
|
33716
34331
|
profileId,
|
|
33717
|
-
idempotencyKey:
|
|
34332
|
+
idempotencyKey: randomUUID3(),
|
|
33718
34333
|
body: {}
|
|
33719
34334
|
});
|
|
33720
34335
|
}
|
|
@@ -33722,7 +34337,7 @@ var init_client = __esm({
|
|
|
33722
34337
|
return this.request("/trading/ai/runtime/session/start", {
|
|
33723
34338
|
method: "POST",
|
|
33724
34339
|
profileId,
|
|
33725
|
-
idempotencyKey:
|
|
34340
|
+
idempotencyKey: randomUUID3(),
|
|
33726
34341
|
body: payload
|
|
33727
34342
|
});
|
|
33728
34343
|
}
|
|
@@ -33733,7 +34348,7 @@ var init_client = __esm({
|
|
|
33733
34348
|
return this.request("/trading/ai/runtime/session/stop", {
|
|
33734
34349
|
method: "POST",
|
|
33735
34350
|
profileId,
|
|
33736
|
-
idempotencyKey:
|
|
34351
|
+
idempotencyKey: randomUUID3(),
|
|
33737
34352
|
body: payload
|
|
33738
34353
|
});
|
|
33739
34354
|
}
|
|
@@ -33750,7 +34365,7 @@ var init_client = __esm({
|
|
|
33750
34365
|
}).request("/trading/ai/runtime/session/stop", {
|
|
33751
34366
|
method: "POST",
|
|
33752
34367
|
profileId,
|
|
33753
|
-
idempotencyKey:
|
|
34368
|
+
idempotencyKey: randomUUID3(),
|
|
33754
34369
|
body: payload
|
|
33755
34370
|
});
|
|
33756
34371
|
}
|
|
@@ -33759,7 +34374,7 @@ var init_client = __esm({
|
|
|
33759
34374
|
});
|
|
33760
34375
|
|
|
33761
34376
|
// lib/agent-core/headless-runtime.ts
|
|
33762
|
-
import { randomUUID as
|
|
34377
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
33763
34378
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
33764
34379
|
function objectOrNull2(value) {
|
|
33765
34380
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -33857,8 +34472,8 @@ async function runAndReportLocalWorkCycle(options, state, leaseToken, context) {
|
|
|
33857
34472
|
return Boolean(result2.decision || tradeSync || result2.afterDecision);
|
|
33858
34473
|
}
|
|
33859
34474
|
async function startHeadlessRuntime(options) {
|
|
33860
|
-
const runtimeSessionId =
|
|
33861
|
-
const deviceId = String(options.deviceId || "").trim() ||
|
|
34475
|
+
const runtimeSessionId = randomUUID4();
|
|
34476
|
+
const deviceId = String(options.deviceId || "").trim() || randomUUID4();
|
|
33862
34477
|
const startResponse = await options.client.startRuntime(options.profileId, {
|
|
33863
34478
|
session_id: runtimeSessionId,
|
|
33864
34479
|
device_id: deviceId,
|
|
@@ -50476,7 +51091,7 @@ var headless_local_worker_exports = {};
|
|
|
50476
51091
|
__export(headless_local_worker_exports, {
|
|
50477
51092
|
createHeadlessLocalWorker: () => createHeadlessLocalWorker
|
|
50478
51093
|
});
|
|
50479
|
-
import { randomUUID as
|
|
51094
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
50480
51095
|
function objectOrNull3(value) {
|
|
50481
51096
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
50482
51097
|
}
|
|
@@ -50889,7 +51504,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
50889
51504
|
const statusMatch = errorText.match(/\b([45]\d{2})\b/);
|
|
50890
51505
|
const statusCode = statusMatch ? Number(statusMatch[1]) : null;
|
|
50891
51506
|
const failedInvocation = normalizeAiInvocationTelemetry({
|
|
50892
|
-
client_invocation_id:
|
|
51507
|
+
client_invocation_id: randomUUID5(),
|
|
50893
51508
|
use_case: "trader",
|
|
50894
51509
|
role: "primary",
|
|
50895
51510
|
attempt_index: 0,
|
|
@@ -50945,7 +51560,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
50945
51560
|
billable_cached_input_tokens: normalizedUsage.cached_input_tokens
|
|
50946
51561
|
};
|
|
50947
51562
|
const invocation = normalizeAiInvocationTelemetry({
|
|
50948
|
-
client_invocation_id:
|
|
51563
|
+
client_invocation_id: randomUUID5(),
|
|
50949
51564
|
use_case: "trader",
|
|
50950
51565
|
role: "primary",
|
|
50951
51566
|
attempt_index: 0,
|
|
@@ -51150,7 +51765,7 @@ var vtx_exports = {};
|
|
|
51150
51765
|
__export(vtx_exports, {
|
|
51151
51766
|
runVtxCli: () => runVtxCli
|
|
51152
51767
|
});
|
|
51153
|
-
import { randomUUID as
|
|
51768
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
51154
51769
|
import { spawn as spawn7 } from "node:child_process";
|
|
51155
51770
|
function render2(value, json2) {
|
|
51156
51771
|
if (json2) {
|
|
@@ -51564,8 +52179,8 @@ async function runVtxCli(argv2, env = process.env) {
|
|
|
51564
52179
|
});
|
|
51565
52180
|
return { exitCode: 0, stdout: render2(redactCliOutput(response2), json2), stderr: "" };
|
|
51566
52181
|
}
|
|
51567
|
-
const runtimeSessionId =
|
|
51568
|
-
const deviceId = config2.runtimeDeviceId ??
|
|
52182
|
+
const runtimeSessionId = randomUUID6();
|
|
52183
|
+
const deviceId = config2.runtimeDeviceId ?? randomUUID6();
|
|
51569
52184
|
const response = await client.startRuntime(profileId, {
|
|
51570
52185
|
session_id: runtimeSessionId,
|
|
51571
52186
|
device_id: deviceId,
|