@vtxmacro/cli 2026.8.54 → 2026.8.56

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 CHANGED
@@ -47,7 +47,7 @@ var init_agent_cli_release = __esm({
47
47
  "agent-cli-release.json"() {
48
48
  agent_cli_release_default = {
49
49
  package_name: "@vtxmacro/cli",
50
- package_version: "2026.8.54",
50
+ package_version: "2026.8.56",
51
51
  codex_package_name: "@openai/codex",
52
52
  codex_version: "0.147.0",
53
53
  copilot_sdk_package_name: "@github/copilot-sdk",
@@ -14442,7 +14442,7 @@ var init_zod = __esm({
14442
14442
  });
14443
14443
 
14444
14444
  // lib/external-inference-contract.ts
14445
- var EXTERNAL_INFERENCE_CONTRACT_VERSION, EXTERNAL_INFERENCE_CONTROLLER_SCHEMA_VERSION, EXTERNAL_INFERENCE_CONTROLLER_SCHEMA_VERSION_V2, EXTERNAL_INFERENCE_ADVERTISEMENT_SCHEMA_VERSION, EXTERNAL_INFERENCE_ENVELOPE_SCHEMA_VERSION, EXTERNAL_INFERENCE_JOB_INPUT_SCHEMA_VERSION, LEGACY_EXTERNAL_INFERENCE_JOB_INPUT_SCHEMA_VERSION, EXTERNAL_INFERENCE_USAGE_SCHEMA_VERSION, EXTERNAL_INFERENCE_INPUT_HASH_DOMAIN, MAX_EXTERNAL_INFERENCE_STATUS_HOSTS, MAX_GENERATION, MAX_SAFE_INTEGER, MAX_PROMPT_BYTES, MAX_IMMUTABLE_JOB_INPUT_BYTES, MAX_CANDIDATE_PLAINTEXT_BYTES, MAX_CIPHERTEXT_CHARS, SHA256_INITIAL_STATE, SHA256_ROUND_CONSTANTS, rotateRight, sha256BytesHex, sha256Utf8Hex, computeImmutableJobInputSha256, identifierSchema, operationIdentifierSchema, sha256HexSchema, generationSchema, zeroBasedGenerationSchema, nonNegativeSafeIntegerSchema, positiveSafeIntegerSchema, sqlIntegerTokenCountSchema, timestampSchema, safeCodeSchema, processExitCodeSchema, externalInferenceAdapterIdSchema, reasoningEffortSchema, modelNameSchema, displayNameSchema, authenticatedAccountEmailSchema, protocolVersionSchema, base64UrlAlphabet, isCanonicalBase64Url, base64Url32BytesSchema, base64UrlNonceSchema, base64UrlCiphertextSchema, claimHandleSchema, boundedJsonTextSchema, boundedPromptTextSchema, laneSchema, botModeSchema, executionModeSchema, responseModeSchema, controlModeSchema, dispatchOutcomeSchema, responseOutcomeSchema, nativeModelControllerSchema, legacyExternalAgentModelControllerSchema, externalAgentModelControllerSchema, boundExternalAgentModelControllerSchema, externalAgentUnboundControllerSchema, externalAgentUnboundControllerV2Schema, orderedFallbackHostIdsSchema, externalInferenceFallbackHostIdsSchema, liveModelControllerSchema, snapshotModelControllerSchema, modelIdentityMappingSchema, advertisedModelSchema, hostAdvertisementSchema, envelopeAadSchema, validateEnvelopeAad, commonEnvelopeShape, sealedKeyWrapEnvelopeSchema, sealedInputEnvelopeSchema, sealedCandidateEnvelopeSchema, sealedEnvelopeSchema, screenerCandidateRuntimeBindingSchema, screenerClientLeaseBindingSchema, screenerRuntimeBindingSchema, serverRuntimeBindingSchema, clientRuntimeBindingSchema, runtimeBindingSchema, immutableJobInputSchema, canonicalizeJsonValue, serializeImmutableJobInput, reportedTokenUsageSchema, unavailableTokenUsageSchema, tokenUsageSchema, agentConnectRequestSchema, agentNextRequestSchema, agentHeartbeatRequestSchema, emptyAgentNextResultSchema, claimedAgentNextResultSchema, agentNextResultSchema, agentCompleteRequestSchema, agentFailRequestSchema, requestedModelSelectionSchema, completedModelProvenanceSchema, attemptModelProvenanceSchema, providerWeeklyQuotaReadSchema, hostHeartbeatRequestSchema, jobClaimRequestSchema, emptyJobClaimSchema, claimedJobSchema, jobClaimResultSchema, attemptStartRequestSchema, jobHeartbeatRequestSchema, continueHeartbeatDirectiveSchema, cancelHeartbeatDirectiveSchema, jobHeartbeatResultSchema, adapterOutcomeEvidenceSchema, completionBaseShape, validateCompletion, providerResponseCompletionSchema, decisionCandidateCompletionSchema, jobCompleteRequestSchema, codexProcessExitDiagnosticsSchema, jobFailRequestSchema, jobCancelRequestSchema, jobCancellationReceiptSchema, jobDeliveryRequestSchema, deliveryBaseShape, validateDeliveryCandidate, providerResponseDeliverySchema, decisionCandidateDeliverySchema, jobDeliveryResultSchema, jobConsumptionRequestSchema, jobConsumptionReceiptSchema, jobStateSchema, jobStatusReadSchema, hostStatusReadSchema, controllerBindingStatusReadSchema, queueStatusReadSchema, outcomeStatusReadSchema, externalInferenceVolumeWindowReadSchema, externalInferenceFailureCountReadSchema, externalInferenceHostDiagnosticsReadSchema, externalInferenceProfileActivityReadSchema, externalInferenceStatusReadSchema, nativeResearchEvidenceSourceSchema, externalAgentResearchEvidenceSourceSchema, researchEvidenceSourceSchema, reportedResearchTokenUsageSchema, unavailableResearchTokenUsageSchema, researchTokenUsageSchema, externalInferenceProductLineageBaseShape, traderExternalInferenceProductLineageSchema, decisionChatExternalInferenceProductLineageSchema, screenerExternalInferenceProductLineageSchema, externalInferenceProductLineageSchema, normalProductLinkageSchema, evidenceMaterializationMarkerSchema, deliveredExternalAgentSourceIdentitySchema, deliveredRequestEvidenceSchema, researchEvidenceBaseShape, researchEvidenceBaseSchema, validateExactUtf8, validateResearchEvidence, providerResponseResearchEvidenceSchema, decisionCandidateResearchEvidenceSchema, researchEvidenceSchema;
14445
+ var EXTERNAL_INFERENCE_CONTRACT_VERSION, EXTERNAL_INFERENCE_CONTROLLER_SCHEMA_VERSION, EXTERNAL_INFERENCE_CONTROLLER_SCHEMA_VERSION_V2, EXTERNAL_INFERENCE_ADVERTISEMENT_SCHEMA_VERSION, EXTERNAL_INFERENCE_ENVELOPE_SCHEMA_VERSION, EXTERNAL_INFERENCE_JOB_INPUT_SCHEMA_VERSION, LEGACY_EXTERNAL_INFERENCE_JOB_INPUT_SCHEMA_VERSION, EXTERNAL_INFERENCE_USAGE_SCHEMA_VERSION, EXTERNAL_INFERENCE_INPUT_HASH_DOMAIN, MAX_EXTERNAL_INFERENCE_STATUS_HOSTS, MAX_PROFILE_EXTERNAL_INFERENCE_FALLBACKS_PER_LANE, MAX_GENERATION, MAX_SAFE_INTEGER, MAX_PROMPT_BYTES, MAX_IMMUTABLE_JOB_INPUT_BYTES, MAX_CANDIDATE_PLAINTEXT_BYTES, MAX_CIPHERTEXT_CHARS, SHA256_INITIAL_STATE, SHA256_ROUND_CONSTANTS, rotateRight, sha256BytesHex, sha256Utf8Hex, computeImmutableJobInputSha256, identifierSchema, operationIdentifierSchema, sha256HexSchema, generationSchema, zeroBasedGenerationSchema, nonNegativeSafeIntegerSchema, positiveSafeIntegerSchema, sqlIntegerTokenCountSchema, timestampSchema, safeCodeSchema, processExitCodeSchema, externalInferenceAdapterIdSchema, reasoningEffortSchema, modelNameSchema, displayNameSchema, authenticatedAccountEmailSchema, protocolVersionSchema, base64UrlAlphabet, isCanonicalBase64Url, base64Url32BytesSchema, base64UrlNonceSchema, base64UrlCiphertextSchema, claimHandleSchema, boundedJsonTextSchema, boundedPromptTextSchema, laneSchema, botModeSchema, executionModeSchema, responseModeSchema, controlModeSchema, dispatchOutcomeSchema, responseOutcomeSchema, nativeModelControllerSchema, legacyExternalAgentModelControllerSchema, externalAgentModelControllerSchema, boundExternalAgentModelControllerSchema, externalAgentUnboundControllerSchema, externalAgentUnboundControllerV2Schema, orderedFallbackHostIdsSchema, externalInferenceFallbackHostIdsSchema, liveModelControllerSchema, snapshotModelControllerSchema, modelIdentityMappingSchema, advertisedModelSchema, hostAdvertisementSchema, envelopeAadSchema, validateEnvelopeAad, commonEnvelopeShape, sealedKeyWrapEnvelopeSchema, sealedInputEnvelopeSchema, sealedCandidateEnvelopeSchema, sealedEnvelopeSchema, screenerCandidateRuntimeBindingSchema, screenerClientLeaseBindingSchema, screenerRuntimeBindingSchema, serverRuntimeBindingSchema, clientRuntimeBindingSchema, runtimeBindingSchema, immutableJobInputSchema, canonicalizeJsonValue, serializeImmutableJobInput, reportedTokenUsageSchema, unavailableTokenUsageSchema, tokenUsageSchema, agentConnectRequestSchema, agentNextRequestSchema, agentHeartbeatRequestSchema, emptyAgentNextResultSchema, claimedAgentNextResultSchema, agentNextResultSchema, agentCompleteRequestSchema, agentFailRequestSchema, requestedModelSelectionSchema, completedModelProvenanceSchema, attemptModelProvenanceSchema, providerWeeklyQuotaReadSchema, hostHeartbeatRequestSchema, jobClaimRequestSchema, emptyJobClaimSchema, claimedJobSchema, jobClaimResultSchema, attemptStartRequestSchema, jobHeartbeatRequestSchema, continueHeartbeatDirectiveSchema, cancelHeartbeatDirectiveSchema, jobHeartbeatResultSchema, adapterOutcomeEvidenceSchema, completionBaseShape, validateCompletion, providerResponseCompletionSchema, decisionCandidateCompletionSchema, jobCompleteRequestSchema, codexProcessExitDiagnosticsSchema, jobFailRequestSchema, jobCancelRequestSchema, jobCancellationReceiptSchema, jobDeliveryRequestSchema, deliveryBaseShape, validateDeliveryCandidate, providerResponseDeliverySchema, decisionCandidateDeliverySchema, jobDeliveryResultSchema, jobConsumptionRequestSchema, jobConsumptionReceiptSchema, jobStateSchema, jobStatusReadSchema, hostStatusReadSchema, controllerBindingStatusReadSchema, queueStatusReadSchema, outcomeStatusReadSchema, externalInferenceVolumeWindowReadSchema, externalInferenceFailureCountReadSchema, externalInferenceHostDiagnosticsReadSchema, externalInferenceProfileActivityReadSchema, externalInferenceStatusReadSchema, nativeResearchEvidenceSourceSchema, externalAgentResearchEvidenceSourceSchema, researchEvidenceSourceSchema, reportedResearchTokenUsageSchema, unavailableResearchTokenUsageSchema, researchTokenUsageSchema, externalInferenceProductLineageBaseShape, traderExternalInferenceProductLineageSchema, decisionChatExternalInferenceProductLineageSchema, screenerExternalInferenceProductLineageSchema, externalInferenceProductLineageSchema, normalProductLinkageSchema, evidenceMaterializationMarkerSchema, deliveredExternalAgentSourceIdentitySchema, deliveredRequestEvidenceSchema, researchEvidenceBaseShape, researchEvidenceBaseSchema, validateExactUtf8, validateResearchEvidence, providerResponseResearchEvidenceSchema, decisionCandidateResearchEvidenceSchema, researchEvidenceSchema;
14446
14446
  var init_external_inference_contract = __esm({
14447
14447
  "lib/external-inference-contract.ts"() {
14448
14448
  "use strict";
@@ -14457,6 +14457,7 @@ var init_external_inference_contract = __esm({
14457
14457
  EXTERNAL_INFERENCE_USAGE_SCHEMA_VERSION = "external_inference_usage_v1";
14458
14458
  EXTERNAL_INFERENCE_INPUT_HASH_DOMAIN = "vtx.external-inference.input-sha256.v1\0";
14459
14459
  MAX_EXTERNAL_INFERENCE_STATUS_HOSTS = 640;
14460
+ MAX_PROFILE_EXTERNAL_INFERENCE_FALLBACKS_PER_LANE = 127;
14460
14461
  MAX_GENERATION = 2147483647;
14461
14462
  MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
14462
14463
  MAX_PROMPT_BYTES = 3e5;
@@ -14738,7 +14739,7 @@ var init_external_inference_contract = __esm({
14738
14739
  control_mode_hint: controlModeSchema,
14739
14740
  binding_state: external_exports.literal("rebind_required")
14740
14741
  });
14741
- orderedFallbackHostIdsSchema = external_exports.array(identifierSchema).max(127).refine(
14742
+ orderedFallbackHostIdsSchema = external_exports.array(identifierSchema).max(MAX_PROFILE_EXTERNAL_INFERENCE_FALLBACKS_PER_LANE).refine(
14742
14743
  (values) => new Set(values).size === values.length,
14743
14744
  { message: "fallback host IDs must be unique" }
14744
14745
  );
@@ -15816,6 +15817,8 @@ var init_external_inference_contract = __esm({
15816
15817
  authenticated_account_identity: safeCodeSchema.nullable().optional(),
15817
15818
  authenticated_account_email: authenticatedAccountEmailSchema.nullable().optional(),
15818
15819
  authenticated_account_plan: safeCodeSchema.nullable().optional(),
15820
+ account_identity_status: external_exports.enum(["reported", "not_reported"]).default("not_reported"),
15821
+ membership_identity_sha256: sha256HexSchema.nullable().optional(),
15819
15822
  adapter: externalInferenceAdapterIdSchema,
15820
15823
  status: external_exports.enum(["online", "degraded", "offline", "draining", "revoked"]),
15821
15824
  host_generation: generationSchema,
@@ -15829,7 +15832,8 @@ var init_external_inference_contract = __esm({
15829
15832
  lane: laneSchema,
15830
15833
  controller: liveModelControllerSchema,
15831
15834
  availability: external_exports.enum(["available", "host_offline", "model_unavailable", "rebind_required"]),
15832
- reason_code: safeCodeSchema.nullable()
15835
+ reason_code: safeCodeSchema.nullable(),
15836
+ membership_host_ids: external_exports.array(identifierSchema).max(MAX_PROFILE_EXTERNAL_INFERENCE_FALLBACKS_PER_LANE + 1).default([])
15833
15837
  });
15834
15838
  queueStatusReadSchema = external_exports.strictObject({
15835
15839
  queued: nonNegativeSafeIntegerSchema,
@@ -33467,6 +33471,7 @@ var init_runner = __esm({
33467
33471
  }
33468
33472
  throw lastError;
33469
33473
  };
33474
+ let advertisementHandoff = null;
33470
33475
  const publishAdvertisement = async (health, forceAdvance, retryRemote = true, allowDefinitiveReseed = true) => {
33471
33476
  let advertisement = receipt.pending_advertisement;
33472
33477
  if (!advertisement) {
@@ -33515,6 +33520,11 @@ var init_runner = __esm({
33515
33520
  }
33516
33521
  const tool = receipt.registered ? "inference.host.advertise" : "inference.host.register";
33517
33522
  let result2;
33523
+ let releaseAdvertisementHandoff;
33524
+ const currentAdvertisementHandoff = new Promise((resolve6) => {
33525
+ releaseAdvertisementHandoff = resolve6;
33526
+ });
33527
+ advertisementHandoff = currentAdvertisementHandoff;
33518
33528
  try {
33519
33529
  const advertiseOperation = () => mcp.callTool(
33520
33530
  tool,
@@ -33522,6 +33532,15 @@ var init_runner = __esm({
33522
33532
  { signal: this.options.signal }
33523
33533
  );
33524
33534
  result2 = retryRemote ? await retryExact(advertiseOperation, { signal: this.options.signal }) : await advertiseOperation();
33535
+ assertAdvertisementResult(advertisement, result2);
33536
+ await mutateReceipt((current) => ({
33537
+ ...current,
33538
+ registered: true,
33539
+ advertisement_generation: result2.host.advertisement_generation,
33540
+ advertisement_expires_at: advertisement.expires_at,
33541
+ pending_advertisement: current.pending_advertisement?.operation_id === advertisement.operation_id ? null : current.pending_advertisement,
33542
+ updated_at: isoAt(now())
33543
+ }));
33525
33544
  } catch (error48) {
33526
33545
  const definitivelyNotApplied = error48 instanceof ExternalInferenceMcpError ? error48.definitivelyNotApplied : Boolean(error48 && typeof error48 === "object" && error48.definitivelyNotApplied === true);
33527
33546
  const expectedGeneration = receipt.registered ? receipt.advertisement_generation + 1 : receipt.advertisement_generation;
@@ -33534,16 +33553,12 @@ var init_runner = __esm({
33534
33553
  return await publishAdvertisement(health, forceAdvance, retryRemote, false);
33535
33554
  }
33536
33555
  throw error48;
33556
+ } finally {
33557
+ releaseAdvertisementHandoff();
33558
+ if (advertisementHandoff === currentAdvertisementHandoff) {
33559
+ advertisementHandoff = null;
33560
+ }
33537
33561
  }
33538
- assertAdvertisementResult(advertisement, result2);
33539
- await mutateReceipt((current) => ({
33540
- ...current,
33541
- registered: true,
33542
- advertisement_generation: result2.host.advertisement_generation,
33543
- advertisement_expires_at: advertisement.expires_at,
33544
- pending_advertisement: current.pending_advertisement?.operation_id === advertisement.operation_id ? null : current.pending_advertisement,
33545
- updated_at: isoAt(now())
33546
- }));
33547
33562
  };
33548
33563
  const wasRegistered = receipt.registered;
33549
33564
  await publishAdvertisement("healthy", wasRegistered);
@@ -33658,10 +33673,24 @@ var init_runner = __esm({
33658
33673
  if (drainRequested || hostHeartbeatAbort.signal.aborted) return;
33659
33674
  const heartbeatStartedAt = now();
33660
33675
  observeHostHeartbeatGap(heartbeatStartedAt);
33676
+ const pendingAdvertisementHandoff = advertisementHandoff;
33677
+ if (pendingAdvertisementHandoff !== null) {
33678
+ try {
33679
+ await Promise.race([
33680
+ pendingAdvertisementHandoff,
33681
+ sleep4(settings.hostHeartbeatMs, hostHeartbeatAbort.signal)
33682
+ ]);
33683
+ } catch (error48) {
33684
+ if (hostHeartbeatAbort.signal.aborted || drainRequested) return;
33685
+ throw error48;
33686
+ }
33687
+ }
33688
+ if (drainRequested || hostHeartbeatAbort.signal.aborted) return;
33689
+ const heartbeatAttemptedAt = now();
33661
33690
  const attemptedAdvertisementGeneration = receipt.advertisement_generation;
33662
33691
  try {
33663
33692
  const expiresAt = receipt.advertisement_expires_at ? Date.parse(receipt.advertisement_expires_at) : 0;
33664
- const refreshPendingAcrossExpiry = receipt.pending_advertisement !== null && expiresAt <= heartbeatStartedAt;
33693
+ const refreshPendingAcrossExpiry = receipt.pending_advertisement !== null && expiresAt <= heartbeatAttemptedAt;
33665
33694
  await hostHeartbeat(
33666
33695
  "healthy",
33667
33696
  { signal: hostHeartbeatAbort.signal },
@@ -35251,7 +35280,7 @@ import { createWriteStream, readFileSync } from "node:fs";
35251
35280
  import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as rm6, writeFile as writeFile2 } from "node:fs/promises";
35252
35281
  import { homedir as homedir2 } from "node:os";
35253
35282
  import { dirname as dirname5, join as join7, resolve as resolve4 } from "node:path";
35254
- 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;
35283
+ var SERVICE_NAME, SYSTEMD_UNIT, LAUNCHD_LABEL, SERVICE_COOPERATIVE_STOP_SECONDS, SERVICE_UPDATE_STARTUP_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, serviceBootstrapArguments, windowsOwnedCommandLine, vbScriptString, windowsServiceLauncher, windowsTaskXml, systemdUnit, launchAgentPlist, sameWorker, sameServiceDefinition, sameWorkerSet, InferenceHostServiceManager, appendServiceLog, spawnInferenceHostServiceChild, runInferenceHostServiceSupervisor;
35255
35284
  var init_service = __esm({
35256
35285
  "lib/inference-host/service.ts"() {
35257
35286
  "use strict";
@@ -35261,6 +35290,7 @@ var init_service = __esm({
35261
35290
  SYSTEMD_UNIT = "vtx-inference-host.service";
35262
35291
  LAUNCHD_LABEL = "com.vtxmacro.inference-host";
35263
35292
  SERVICE_COOPERATIVE_STOP_SECONDS = 75;
35293
+ SERVICE_UPDATE_STARTUP_SECONDS = 600;
35264
35294
  INFERENCE_HOST_SERVICE_DRAIN_COMMAND = "vtx-inference-host-service-drain-v1";
35265
35295
  inferenceHostServiceChildEnvironment = (runtimeEnvironment2, inheritedEnvironment = process.env) => {
35266
35296
  const environment = { ...inheritedEnvironment };
@@ -35565,13 +35595,12 @@ var init_service = __esm({
35565
35595
  }
35566
35596
  return result2;
35567
35597
  };
35568
- serviceArguments = (script, manifestPath) => [
35569
- script,
35570
- "inference-host",
35571
- "service",
35572
- "run-internal",
35598
+ serviceBootstrapArguments = (bootstrapScript, manifestPath, lockPath) => [
35599
+ bootstrapScript,
35573
35600
  "--service-manifest",
35574
- manifestPath
35601
+ manifestPath,
35602
+ "--service-lock",
35603
+ lockPath
35575
35604
  ];
35576
35605
  windowsOwnedCommandLine = (values) => {
35577
35606
  if (values.some((value) => value.includes('"') || value.includes("\0"))) {
@@ -35650,6 +35679,9 @@ WantedBy=default.target
35650
35679
  this.home = dependencies.homedir ?? homedir2();
35651
35680
  this.executable = resolve4(dependencies.executable ?? process.execPath);
35652
35681
  this.script = resolve4(dependencies.script ?? process.argv[1] ?? "");
35682
+ this.bootstrapScript = resolve4(
35683
+ dependencies.bootstrapScript ?? join7(dirname5(this.script), "vtx-service-bootstrap.js")
35684
+ );
35653
35685
  this.username = dependencies.username ?? ([process.env.USERDOMAIN, process.env.USERNAME].filter(Boolean).join("\\") || process.env.USER || "");
35654
35686
  this.windowsDirectory = (dependencies.windowsDirectory ?? process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows").replace(/[\\/]+$/u, "");
35655
35687
  this.runCommand = dependencies.runCommand ?? defaultRunCommand;
@@ -35681,6 +35713,21 @@ WantedBy=default.target
35681
35713
  runtimePath() {
35682
35714
  return inferenceHostServiceRuntimePath(this.config);
35683
35715
  }
35716
+ serviceBootstrapPath() {
35717
+ return `${this.config.supervisorStatePath}.service-bootstrap.js`;
35718
+ }
35719
+ serviceReleasePath() {
35720
+ return `${this.config.supervisorStatePath}.service-release.json`;
35721
+ }
35722
+ serviceReleaseRejectionPath() {
35723
+ return `${this.config.supervisorStatePath}.service-release-rejection.json`;
35724
+ }
35725
+ serviceReleasesPath() {
35726
+ return `${this.config.supervisorStatePath}.service-releases`;
35727
+ }
35728
+ serviceBootstrapLockPath() {
35729
+ return `${this.config.supervisorProcessLockPath}.service-bootstrap`;
35730
+ }
35684
35731
  controlLockPath() {
35685
35732
  return `${this.config.supervisorProcessLockPath}.service-control`;
35686
35733
  }
@@ -35725,6 +35772,18 @@ WantedBy=default.target
35725
35772
  windowsLauncherPath() {
35726
35773
  return `${this.config.supervisorStatePath}.service-launcher.vbs`;
35727
35774
  }
35775
+ async hasBootstrapDefinition() {
35776
+ try {
35777
+ await access3(this.serviceBootstrapPath());
35778
+ const definition = await readFile5(
35779
+ this.platform === "win32" ? this.windowsLauncherPath() : this.definitionPath(),
35780
+ "utf8"
35781
+ );
35782
+ return definition.includes(this.serviceBootstrapPath());
35783
+ } catch {
35784
+ return false;
35785
+ }
35786
+ }
35728
35787
  async managerCommand(action) {
35729
35788
  const definition = this.definitionPath();
35730
35789
  if (this.platform === "win32") {
@@ -35846,13 +35905,23 @@ ${result2.stderr}`)) {
35846
35905
  );
35847
35906
  }
35848
35907
  async registerManifestUnlocked(manifest, desiredRunning, targetInstanceName) {
35849
- const args = serviceArguments(manifest.script, this.manifestPath());
35908
+ await access3(this.bootstrapScript);
35909
+ const args = serviceBootstrapArguments(
35910
+ this.serviceBootstrapPath(),
35911
+ this.manifestPath(),
35912
+ this.serviceBootstrapLockPath()
35913
+ );
35850
35914
  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);
35851
35915
  let managerInstallAttempted = false;
35852
35916
  try {
35853
35917
  await writeAtomicInferencePrivateFile(this.manifestPath(), `${JSON.stringify(manifest, null, 2)}
35854
35918
  `);
35855
35919
  await writeDesired(this.desiredPath(), desiredRunning, this.now());
35920
+ await writeAtomicInferencePrivateFile(
35921
+ this.serviceBootstrapPath(),
35922
+ await readFile5(this.bootstrapScript, "utf8")
35923
+ );
35924
+ await chmod3(this.serviceBootstrapPath(), 448);
35856
35925
  await mkdir3(dirname5(this.definitionPath()), { recursive: true, mode: 448 });
35857
35926
  if (this.platform === "win32") {
35858
35927
  await writeAtomicInferencePrivateFile(
@@ -35882,7 +35951,11 @@ ${started.stderr}`)) {
35882
35951
  }
35883
35952
  await this.waitForManagerActive();
35884
35953
  if (this.confirmInitialReadiness) {
35885
- await this.waitForManifestApplied(manifest, targetInstanceName);
35954
+ await this.waitForManifestApplied(
35955
+ manifest,
35956
+ targetInstanceName,
35957
+ Math.max(this.reconcileWaitAttempts, SERVICE_UPDATE_STARTUP_SECONDS * 4)
35958
+ );
35886
35959
  }
35887
35960
  }
35888
35961
  return await this.status();
@@ -35909,6 +35982,7 @@ ${cleanup.stderr}`)) {
35909
35982
  await rm6(this.manifestPath(), { force: true }).catch(() => void 0);
35910
35983
  await rm6(this.desiredPath(), { force: true }).catch(() => void 0);
35911
35984
  await rm6(this.runtimePath(), { force: true }).catch(() => void 0);
35985
+ await rm6(this.serviceBootstrapPath(), { force: true }).catch(() => void 0);
35912
35986
  if (this.platform === "linux") {
35913
35987
  await this.runCommand("systemctl", ["--user", "daemon-reload"]).catch(() => void 0);
35914
35988
  }
@@ -35918,10 +35992,11 @@ ${cleanup.stderr}`)) {
35918
35992
  async replaceManifestUnlocked(next, desiredRunning, targetInstanceName) {
35919
35993
  const previous = await readInferenceHostServiceManifest(this.manifestPath());
35920
35994
  const previousDesired = previous ? await readInferenceHostServiceDesired(this.desiredPath()) : false;
35921
- if (previous && sameServiceDefinition(previous, next) && sameWorkerSet(previous, next) && previousDesired === desiredRunning) {
35995
+ const hasBootstrapDefinition = previous ? await this.hasBootstrapDefinition() : false;
35996
+ if (previous && sameServiceDefinition(previous, next) && sameWorkerSet(previous, next) && previousDesired === desiredRunning && hasBootstrapDefinition) {
35922
35997
  return await this.status();
35923
35998
  }
35924
- if (previous && previousDesired && desiredRunning && sameServiceDefinition(previous, next)) {
35999
+ if (previous && previousDesired && desiredRunning && sameServiceDefinition(previous, next) && hasBootstrapDefinition) {
35925
36000
  const current = await this.status();
35926
36001
  const runtime = await readRuntimeAcrossAtomicReplacement(this.runtimePath()).catch(() => null);
35927
36002
  if (current.manager_active && runtime?.manifest_generation === previous.generation) {
@@ -36041,6 +36116,7 @@ ${cleanup.stderr}`)) {
36041
36116
  }
36042
36117
  await access3(this.executable);
36043
36118
  await access3(this.script);
36119
+ await access3(this.bootstrapScript);
36044
36120
  const maxConcurrency = options.maxConcurrency ?? null;
36045
36121
  const workers = [
36046
36122
  ...existing?.workers.filter((worker) => worker.instance_name !== this.config.instanceName) ?? [],
@@ -36166,25 +36242,34 @@ ${result2.stderr}`)) {
36166
36242
  const restoreOnFailure = await readInferenceHostServiceDesired(this.desiredPath());
36167
36243
  await writeDesired(this.desiredPath(), false, this.now());
36168
36244
  try {
36169
- const serviceLockPath = `${this.config.supervisorProcessLockPath}.service`;
36245
+ const serviceLockPaths = [
36246
+ `${this.config.supervisorProcessLockPath}.service`,
36247
+ this.serviceBootstrapLockPath()
36248
+ ];
36170
36249
  let serviceReleased = false;
36171
36250
  for (let attempt = 0; attempt < this.stopWaitAttempts; attempt += 1) {
36172
- try {
36173
- const probe = await this.acquireProcessLock(serviceLockPath);
36174
- await probe.release();
36251
+ let allReleased = true;
36252
+ for (const serviceLockPath of serviceLockPaths) {
36253
+ try {
36254
+ const probe = await this.acquireProcessLock(serviceLockPath);
36255
+ await probe.release();
36256
+ } catch (error48) {
36257
+ if (error48 instanceof Error && error48.message.includes("Another inference host process already owns")) {
36258
+ allReleased = false;
36259
+ break;
36260
+ }
36261
+ throw error48;
36262
+ }
36263
+ }
36264
+ if (allReleased) {
36175
36265
  serviceReleased = true;
36176
36266
  break;
36177
- } catch (error48) {
36178
- if (error48 instanceof Error && error48.message.includes("Another inference host process already owns")) {
36179
- await this.sleep(250);
36180
- continue;
36181
- }
36182
- throw error48;
36183
36267
  }
36268
+ await this.sleep(250);
36184
36269
  }
36185
36270
  if (!serviceReleased) {
36186
36271
  throw new Error(
36187
- `Inference-host workers did not stop cooperatively within ${SERVICE_COOPERATIVE_STOP_SECONDS} seconds; refusing forced termination while cleanup may be pending.`
36272
+ `Inference-host updater or workers did not stop cooperatively within ${SERVICE_COOPERATIVE_STOP_SECONDS} seconds; refusing forced termination while cleanup may be pending.`
36188
36273
  );
36189
36274
  }
36190
36275
  const result2 = await this.managerCommand("stop");
@@ -36300,6 +36385,10 @@ ${result2.stderr}`)) {
36300
36385
  await rm6(this.manifestPath(), { force: true });
36301
36386
  await rm6(this.desiredPath(), { force: true });
36302
36387
  await rm6(this.runtimePath(), { force: true });
36388
+ await rm6(this.serviceBootstrapPath(), { force: true });
36389
+ await rm6(this.serviceReleasePath(), { force: true });
36390
+ await rm6(this.serviceReleaseRejectionPath(), { force: true });
36391
+ await rm6(this.serviceReleasesPath(), { recursive: true, force: true });
36303
36392
  return {
36304
36393
  installed: false,
36305
36394
  desired_running: false,
@@ -36432,8 +36521,11 @@ ${result2.stderr}`)) {
36432
36521
  });
36433
36522
  };
36434
36523
  runInferenceHostServiceSupervisor = async (manifestPath, options = {}) => {
36435
- const initialManifest = await readInferenceHostServiceManifest(manifestPath);
36436
- if (!initialManifest) throw new Error("Inference-host service manifest is missing.");
36524
+ const storedInitialManifest = await readInferenceHostServiceManifest(manifestPath);
36525
+ if (!storedInitialManifest) throw new Error("Inference-host service manifest is missing.");
36526
+ const serviceScript = options.serviceScript ? resolve4(options.serviceScript) : null;
36527
+ const withServiceScript = (manifest) => serviceScript ? { ...manifest, script: serviceScript } : manifest;
36528
+ const initialManifest = withServiceScript(storedInitialManifest);
36437
36529
  const desiredPath = manifestPath.replace(/\.service\.json$/u, ".service-desired.json");
36438
36530
  const runtimePath = manifestPath.replace(/\.service\.json$/u, ".service-runtime.json");
36439
36531
  const signal = options.signal ?? new AbortController().signal;
@@ -36630,15 +36722,17 @@ ${result2.stderr}`)) {
36630
36722
  try {
36631
36723
  while (!signal.aborted) {
36632
36724
  while (!signal.aborted && await readDesiredAcrossAtomicReplacement(desiredPath)) {
36633
- const next = await readManifestAcrossAtomicReplacement(manifestPath);
36634
- if (!next) throw new Error("Inference-host service manifest is missing.");
36725
+ const storedNext = await readManifestAcrossAtomicReplacement(manifestPath);
36726
+ if (!storedNext) throw new Error("Inference-host service manifest is missing.");
36727
+ const next = withServiceScript(storedNext);
36635
36728
  if (next.generation !== appliedManifest.generation && next.generation !== rejectedManifestGeneration) await reconcile(next);
36636
36729
  await sleep4(250);
36637
36730
  }
36638
36731
  await drainWorkers();
36639
36732
  if (signal.aborted || !await readDesiredAcrossAtomicReplacement(desiredPath)) break;
36640
- const restored = await readManifestAcrossAtomicReplacement(manifestPath);
36641
- if (!restored) throw new Error("Inference-host service manifest is missing.");
36733
+ const storedRestored = await readManifestAcrossAtomicReplacement(manifestPath);
36734
+ if (!storedRestored) throw new Error("Inference-host service manifest is missing.");
36735
+ const restored = withServiceScript(storedRestored);
36642
36736
  await reconcile(restored);
36643
36737
  await appendServiceLog(restored.log_path, "service_desired_state_restored", {
36644
36738
  manifest_generation: restored.generation,
@@ -39377,7 +39471,8 @@ Waiting for approval...
39377
39471
  await (dependencies.runServiceSupervisor ?? runInferenceHostServiceSupervisor)(
39378
39472
  parsed.serviceManifestPath,
39379
39473
  {
39380
- signal: cancellation.signal
39474
+ signal: cancellation.signal,
39475
+ serviceScript: resolve5(process.argv[1] ?? "")
39381
39476
  }
39382
39477
  );
39383
39478
  return { exitCode: 0, stdout: "", stderr: "" };
@@ -53931,11 +54026,11 @@ var init_error_surface_contract = __esm({
53931
54026
  );
53932
54027
  let message;
53933
54028
  if (resolvedReason === "private_node_stale") {
53934
- message = `\u26A0\uFE0F The ${orderLabel} was not sent: Hyperliquid private account data was too stale to validate the signing key.`;
54029
+ message = `\u26A0\uFE0F The ${orderLabel} was not sent: VTX could not verify this profile's signing-key authorization because required Hyperliquid account data was stale. No order was submitted, and the signing key was not rejected. VTX will try again automatically if the trader is running; no action is required.`;
53935
54030
  } else if (resolvedReason === "signer_validation_unavailable") {
53936
- message = `\u26A0\uFE0F The ${orderLabel} was not sent: Hyperliquid's private account service could not validate the signing key.`;
54031
+ message = `\u26A0\uFE0F The ${orderLabel} was not sent: VTX could not verify this profile's signing-key authorization because required Hyperliquid account data was temporarily unavailable. No order was submitted, and the signing key was not rejected. VTX will try again automatically if the trader is running; no action is required.`;
53937
54032
  } else if (resolvedReason === "wallet_not_authorized") {
53938
- message = `\u26A0\uFE0F The ${orderLabel} was not sent: the signing key is not authorized for the configured wallet.`;
54033
+ message = `\u26A0\uFE0F The ${orderLabel} was not sent: Hyperliquid confirmed that the signing key is not authorized for the configured wallet. No order was submitted. Stop the trader, then reconnect the correct wallet and signing key in System.`;
53939
54034
  } else if (resolvedReason === "credentials_missing") {
53940
54035
  message = `\u26A0\uFE0F The ${orderLabel} was not sent: a wallet address and authorized signing key are required for trading.`;
53941
54036
  } else if (resolvedReason === "local_safety_block") {
@@ -54856,13 +54951,28 @@ var init_hyperliquid_client = __esm({
54856
54951
  throw new Error("Malformed Hyperliquid userRole response.");
54857
54952
  }
54858
54953
  const response = payload;
54859
- const role = String(response.role || "").trim();
54860
- if (!role) {
54954
+ const role = response.role;
54955
+ if (typeof role !== "string" || !["missing", "user", "agent", "vault", "subAccount"].includes(role)) {
54956
+ throw new Error("Malformed Hyperliquid userRole response.");
54957
+ }
54958
+ const rawData = response.data;
54959
+ if (["missing", "user", "vault"].includes(role)) {
54960
+ if (rawData !== void 0 && rawData !== null) {
54961
+ throw new Error("Malformed Hyperliquid userRole response.");
54962
+ }
54963
+ return { role, data: null };
54964
+ }
54965
+ if (!rawData || typeof rawData !== "object" || Array.isArray(rawData)) {
54966
+ throw new Error("Malformed Hyperliquid userRole response.");
54967
+ }
54968
+ const data = rawData;
54969
+ const addressKey = role === "agent" ? "user" : "master";
54970
+ if (typeof data[addressKey] !== "string" || !/^0x[0-9a-f]{40}$/i.test(data[addressKey])) {
54861
54971
  throw new Error("Malformed Hyperliquid userRole response.");
54862
54972
  }
54863
54973
  return {
54864
54974
  role,
54865
- data: response.data && typeof response.data === "object" && !Array.isArray(response.data) ? response.data : null
54975
+ data
54866
54976
  };
54867
54977
  };
54868
54978
  fetchBrowserAccountState2 = async (input) => {
@@ -55961,7 +56071,7 @@ var init_hyperliquid_signer_binding = __esm({
55961
56071
  } catch (error48) {
55962
56072
  if (input.signal?.aborted) throw error48;
55963
56073
  throw new RuntimeExecutionError(
55964
- "Hyperliquid's private account service could not validate the signing key.",
56074
+ "VTX could not verify this profile's signing-key authorization because required Hyperliquid account data was temporarily unavailable. The signing key was not rejected. Try again later; reconnecting is not required.",
55965
56075
  "signer_validation_unavailable"
55966
56076
  );
55967
56077
  }
@@ -55976,7 +56086,7 @@ var init_hyperliquid_signer_binding = __esm({
55976
56086
  if (signerRole === "agent") {
55977
56087
  const masterWallet = extractRoleAddress(
55978
56088
  roleResponse.data,
55979
- ["user", "master", "masterAddress", "master_address"]
56089
+ ["user"]
55980
56090
  );
55981
56091
  if (masterWallet === walletAddress) {
55982
56092
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtxmacro/cli",
3
- "version": "2026.8.54",
3
+ "version": "2026.8.56",
4
4
  "description": "VTX Macro CLI, MCP server, and durable external inference host.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",