@vtxmacro/cli 2026.8.15 → 2026.8.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/bin/vtx.js +135 -50
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -127,7 +127,7 @@ object to `vtx inference-host agent-fail --json`.
127
127
  Keep `agent-run` open in a separate terminal and keep calling `agent-next`
128
128
  while the host should remain available. The independent keeper preserves
129
129
  truthful liveness while the harness reasons. This same loop
130
- supports Main, Review, and Screener; Provider response and Decision candidate;
130
+ supports Main, Review, and Screener; Provider and Decision;
131
131
  and normally running VTX Client Mode or Server Mode bots. Server Mode keeps the
132
132
  normal VTX call fee. Client Mode has no VTX platform fee. Neither mode falls back
133
133
  to another model when the agent host is unavailable.
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.15",
41
+ package_version: "2026.8.17",
42
42
  codex_package_name: "@openai/codex",
43
43
  codex_version: "0.147.0",
44
44
  platforms: {
@@ -17303,7 +17303,7 @@ var init_mcp_client = __esm({
17303
17303
  }
17304
17304
  if (name === "inference.job.claim") {
17305
17305
  if (result2.claim_request_id !== request.claim_request_id) invalidBoundResult(name);
17306
- if (result2.claim_state === "claimed" && (result2.host_id !== request.host_id || result2.host_generation !== request.host_generation || result2.advertisement_generation !== request.advertisement_generation || result2.key_generation !== request.key_generation)) invalidBoundResult(name);
17306
+ if (result2.claim_state === "claimed" && (result2.host_id !== request.host_id || result2.host_generation !== request.host_generation || result2.advertisement_generation > request.advertisement_generation || result2.key_generation !== request.key_generation)) invalidBoundResult(name);
17307
17307
  return;
17308
17308
  }
17309
17309
  if (name === "inference.job.start") {
@@ -17403,11 +17403,22 @@ var init_mcp_client = __esm({
17403
17403
  }).passthrough().parse(rawResult);
17404
17404
  if (callResult.isError === true) {
17405
17405
  const errorText = (callResult.content ?? []).filter((block) => block.type === "text").map((block) => block.text ?? "").join("\n");
17406
- const definitivelyNotApplied = (name === "inference.host.register" || name === "inference.host.advertise") && errorText.includes("Advertisement is already expired.") || (name === "inference.agent.next" || name === "inference.agent.heartbeat") && (errorText.includes("Advertisement time is outside the allowed clock skew.") || errorText.includes("Advertisement is already expired.") || errorText.includes("Heartbeat time is outside the allowed clock skew."));
17406
+ const definitivelyNotApplied = (name === "inference.host.register" || name === "inference.host.advertise") && (errorText.includes("Advertisement time is outside the allowed clock skew.") || errorText.includes("Advertisement is already expired.")) || (name === "inference.agent.next" || name === "inference.agent.heartbeat") && (errorText.includes("Advertisement time is outside the allowed clock skew.") || errorText.includes("Advertisement is already expired.") || errorText.includes("Heartbeat time is outside the allowed clock skew.")) || name === "inference.job.claim" && (errorText.includes(
17407
+ "External inference claim request was not applied before its generation became stale"
17408
+ ) || errorText.includes("External inference host advertisement is expired or superseded"));
17409
+ const retryableInfrastructureRejection = EXTERNAL_INFERENCE_AUTOMATED_HOST_TOOLS.includes(name) && (errorText.includes("External inference polling is at its configured concurrency limit") || errorText.includes("The Insights action reached the response timeout") || errorText.includes("Insights capability failed without exposing private runtime details"));
17410
+ const retryableClaimRejection = name === "inference.job.claim" && !definitivelyNotApplied && (retryableInfrastructureRejection || errorText.includes("External inference host is not live enough to claim work") || errorText.includes("External inference host request generation is stale"));
17407
17411
  throw new ExternalInferenceMcpError(
17408
17412
  "tool_rejected",
17409
17413
  `Insights MCP rejected ${name}.`,
17410
- { definitivelyNotApplied }
17414
+ {
17415
+ definitivelyNotApplied,
17416
+ // Claim polling is an idempotent control-plane operation. During an
17417
+ // API rotation the MCP server can return a tool error after the
17418
+ // request reached the application boundary, so retain and replay
17419
+ // the exact request unless the server proves it was not applied.
17420
+ retryable: retryableInfrastructureRejection || retryableClaimRejection
17421
+ }
17411
17422
  );
17412
17423
  }
17413
17424
  const structured = inlineStructuredContentSchema.parse(callResult.structuredContent);
@@ -17515,11 +17526,13 @@ var init_mcp_client = __esm({
17515
17526
  const remoteError = external_exports.object({ code: external_exports.number().int() }).passthrough().safeParse(
17516
17527
  document2.error
17517
17528
  );
17529
+ const remoteCode = remoteError.success ? remoteError.data.code : null;
17518
17530
  throw new ExternalInferenceMcpError(
17519
17531
  "remote_error",
17520
17532
  "Insights MCP rejected the JSON-RPC request.",
17521
17533
  {
17522
- definitivelyNotApplied: remoteError.success && [-32700, -32600, -32601, -32602].includes(remoteError.data.code)
17534
+ definitivelyNotApplied: remoteCode !== null && [-32700, -32600, -32601, -32602].includes(remoteCode),
17535
+ retryable: remoteCode === -32603 || remoteCode !== null && remoteCode >= -32099 && remoteCode <= -32e3
17523
17536
  }
17524
17537
  );
17525
17538
  }
@@ -27700,7 +27713,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
27700
27713
  envelopePublicKey: options.envelopePublicKey
27701
27714
  };
27702
27715
  }
27703
- 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_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, DEFAULT_MAX_CONCURRENCY, MIN_SLEEP_MS, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, CODEX_INFERENCE_ADVERTISED_MODEL, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, safeFailureCode, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner;
27716
+ 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_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, DEFAULT_MAX_CONCURRENCY, MIN_SLEEP_MS, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, CODEX_INFERENCE_ADVERTISED_MODEL, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, safeFailureCode, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner;
27704
27717
  var init_runner = __esm({
27705
27718
  "lib/inference-host/runner.ts"() {
27706
27719
  "use strict";
@@ -27724,6 +27737,7 @@ var init_runner = __esm({
27724
27737
  DEFAULT_MAX_CONCURRENCY = 1;
27725
27738
  MIN_SLEEP_MS = 10;
27726
27739
  DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS = 5 * 60 * 1e3;
27740
+ MIN_CLAIM_START_WINDOW_MS = 5e3;
27727
27741
  CODEX_INFERENCE_ADVERTISED_MODEL = Object.freeze({
27728
27742
  model_id: INITIAL_CODEX_INFERENCE_MODEL,
27729
27743
  label: "Codex GPT-5.6 Sol",
@@ -27877,7 +27891,7 @@ var init_runner = __esm({
27877
27891
  throw new Error("Inference host runtime receipt is invalid.");
27878
27892
  }
27879
27893
  const record2 = value;
27880
- if (!exactObjectKeys(record2, [
27894
+ const legacyKeys = [
27881
27895
  "schema_version",
27882
27896
  "host_id",
27883
27897
  "host_generation",
@@ -27890,10 +27904,16 @@ var init_runner = __esm({
27890
27904
  "claim_sequence",
27891
27905
  "attempts",
27892
27906
  "updated_at"
27893
- ]) || record2.schema_version !== RUNTIME_RECEIPT_SCHEMA_VERSION || typeof record2.host_id !== "string" || !record2.host_id || !safeInteger(record2.host_generation, 1) || !safeInteger(record2.key_generation, 1) || !safeInteger(record2.advertisement_generation, 1) || record2.advertisement_expires_at !== null && !validIso(record2.advertisement_expires_at) || typeof record2.registered !== "boolean" || !safeInteger(record2.host_heartbeat_sequence, 0) || !safeInteger(record2.claim_sequence, 0) || !record2.attempts || typeof record2.attempts !== "object" || Array.isArray(record2.attempts) || !validIso(record2.updated_at)) {
27907
+ ];
27908
+ const currentKeys = [...legacyKeys, "pending_claim_request"];
27909
+ if (!(exactObjectKeys(record2, legacyKeys) || exactObjectKeys(record2, currentKeys)) || record2.schema_version !== RUNTIME_RECEIPT_SCHEMA_VERSION || typeof record2.host_id !== "string" || !record2.host_id || !safeInteger(record2.host_generation, 1) || !safeInteger(record2.key_generation, 1) || !safeInteger(record2.advertisement_generation, 1) || record2.advertisement_expires_at !== null && !validIso(record2.advertisement_expires_at) || typeof record2.registered !== "boolean" || !safeInteger(record2.host_heartbeat_sequence, 0) || !safeInteger(record2.claim_sequence, 0) || !record2.attempts || typeof record2.attempts !== "object" || Array.isArray(record2.attempts) || !validIso(record2.updated_at)) {
27894
27910
  throw new Error("Inference host runtime receipt is invalid.");
27895
27911
  }
27896
27912
  const pendingAdvertisement = record2.pending_advertisement === null ? null : hostAdvertisementSchema.parse(record2.pending_advertisement);
27913
+ const pendingClaimRequest = record2.pending_claim_request == null ? null : jobClaimRequestSchema.parse(record2.pending_claim_request);
27914
+ if (pendingClaimRequest && (pendingClaimRequest.host_id !== record2.host_id || pendingClaimRequest.host_generation !== record2.host_generation || pendingClaimRequest.key_generation !== record2.key_generation || pendingClaimRequest.advertisement_generation > Number(record2.advertisement_generation))) {
27915
+ throw new Error("Inference host pending claim receipt is invalid.");
27916
+ }
27897
27917
  const attempts = Object.fromEntries(
27898
27918
  Object.entries(record2.attempts).map(([key, attempt]) => {
27899
27919
  const validated = validateAttemptReceipt(attempt);
@@ -27906,6 +27926,7 @@ var init_runner = __esm({
27906
27926
  return {
27907
27927
  ...record2,
27908
27928
  pending_advertisement: pendingAdvertisement,
27929
+ pending_claim_request: pendingClaimRequest,
27909
27930
  attempts
27910
27931
  };
27911
27932
  };
@@ -28154,7 +28175,7 @@ var init_runner = __esm({
28154
28175
  if (result2.claim_request_id !== request.claim_request_id) {
28155
28176
  runnerIdentityMismatch("Job claim");
28156
28177
  }
28157
- if (result2.claim_state === "claimed" && (result2.host_id !== request.host_id || result2.host_generation !== request.host_generation || result2.advertisement_generation !== request.advertisement_generation || result2.key_generation !== request.key_generation)) runnerIdentityMismatch("Job claim");
28178
+ if (result2.claim_state === "claimed" && (result2.host_id !== request.host_id || result2.host_generation !== request.host_generation || result2.advertisement_generation > request.advertisement_generation || result2.key_generation !== request.key_generation)) runnerIdentityMismatch("Job claim");
28158
28179
  };
28159
28180
  assertStartResult = (request, result2) => {
28160
28181
  if (result2.job_id !== request.job_id || result2.attempt_id !== request.attempt_id || result2.attempt_index !== request.attempt_index || result2.state !== "dispatch_intent") runnerIdentityMismatch("Job start");
@@ -28350,7 +28371,7 @@ var init_runner = __esm({
28350
28371
  await mcp.initialize({ signal: this.options.signal });
28351
28372
  const existingReceipt = await this.dependencies.receiptStore.read();
28352
28373
  const identityMatches = existingReceipt && existingReceipt.host_id === localState.host_id && existingReceipt.host_generation === localState.host_generation && existingReceipt.key_generation === localState.key_generation;
28353
- if (existingReceipt && !identityMatches && Object.keys(existingReceipt.attempts).length > 0) {
28374
+ if (existingReceipt && !identityMatches && (Object.keys(existingReceipt.attempts).length > 0 || existingReceipt.pending_claim_request !== null)) {
28354
28375
  throw new InferenceHostRecoveryRequiredError(
28355
28376
  "A prior attempt belongs to another host generation and must be reconciled before takeover."
28356
28377
  );
@@ -28371,6 +28392,7 @@ var init_runner = __esm({
28371
28392
  advertisement_expires_at: null,
28372
28393
  registered: false,
28373
28394
  pending_advertisement: null,
28395
+ pending_claim_request: null,
28374
28396
  host_heartbeat_sequence: 0,
28375
28397
  claim_sequence: 0,
28376
28398
  attempts: {},
@@ -28416,7 +28438,7 @@ var init_runner = __esm({
28416
28438
  }
28417
28439
  throw lastError;
28418
28440
  };
28419
- const publishAdvertisement = async (health, forceAdvance, retryRemote = true) => {
28441
+ const publishAdvertisement = async (health, forceAdvance, retryRemote = true, allowDefinitiveReseed = true) => {
28420
28442
  let advertisement = receipt.pending_advertisement;
28421
28443
  if (!advertisement) {
28422
28444
  const generation = receipt.registered && forceAdvance ? receipt.advertisement_generation + 1 : receipt.advertisement_generation;
@@ -28470,14 +28492,14 @@ var init_runner = __esm({
28470
28492
  } catch (error48) {
28471
28493
  const definitivelyNotApplied = error48 instanceof ExternalInferenceMcpError ? error48.definitivelyNotApplied : Boolean(error48 && typeof error48 === "object" && error48.definitivelyNotApplied === true);
28472
28494
  const expectedGeneration = receipt.registered ? receipt.advertisement_generation + 1 : receipt.advertisement_generation;
28473
- if (definitivelyNotApplied && Date.parse(advertisement.expires_at) <= now() && advertisement.advertisement_generation === expectedGeneration) {
28495
+ if (definitivelyNotApplied && advertisement.advertisement_generation === expectedGeneration && allowDefinitiveReseed) {
28474
28496
  receipt = {
28475
28497
  ...receipt,
28476
28498
  pending_advertisement: null,
28477
28499
  updated_at: isoAt(now())
28478
28500
  };
28479
28501
  await this.persistReceipt(receipt, now);
28480
- return await publishAdvertisement(health, forceAdvance, retryRemote);
28502
+ return await publishAdvertisement(health, forceAdvance, retryRemote, false);
28481
28503
  }
28482
28504
  throw error48;
28483
28505
  }
@@ -28540,8 +28562,9 @@ var init_runner = __esm({
28540
28562
  let nextAdvertisementAttemptAt = 0;
28541
28563
  let providerRetryAtMs = this.options.codexRateLimits && codexAccountRateLimitReached(this.options.codexRateLimits) ? codexRateLimitRetryAtMs(this.options.codexRateLimits) ?? now() + DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS : null;
28542
28564
  let nextClaimAt = Math.max(now(), providerRetryAtMs ?? 0);
28565
+ let pendingClaimPromotions = 0;
28543
28566
  let onceClaimed = false;
28544
- const launchClaim = (claim, recovery) => {
28567
+ const launchClaim = (claim, recovery, claimRequest) => {
28545
28568
  if (!recovery) {
28546
28569
  claimed += 1;
28547
28570
  onceClaimed = true;
@@ -28555,6 +28578,13 @@ var init_runner = __esm({
28555
28578
  ]);
28556
28579
  const controller = new AbortController();
28557
28580
  attemptControllers.set(attemptId, controller);
28581
+ let claimPromotionSettled = claimRequest === void 0;
28582
+ const settleClaimPromotion = () => {
28583
+ if (claimPromotionSettled) return;
28584
+ claimPromotionSettled = true;
28585
+ pendingClaimPromotions = Math.max(0, pendingClaimPromotions - 1);
28586
+ };
28587
+ if (claimRequest) pendingClaimPromotions += 1;
28558
28588
  const promise2 = this.executeClaim({
28559
28589
  claim,
28560
28590
  attemptId,
@@ -28582,7 +28612,9 @@ var init_runner = __esm({
28582
28612
  providerRetryAtMs = Math.max(providerRetryAtMs ?? 0, retryAtMs);
28583
28613
  nextClaimAt = Math.max(nextClaimAt, providerRetryAtMs);
28584
28614
  },
28585
- resumeReceipt: recovery
28615
+ resumeReceipt: recovery,
28616
+ claimRequest,
28617
+ onClaimPersisted: settleClaimPromotion
28586
28618
  }).then((outcome) => {
28587
28619
  if (outcome === "completed") completed += 1;
28588
28620
  else failed += 1;
@@ -28590,6 +28622,7 @@ var init_runner = __esm({
28590
28622
  failed += 1;
28591
28623
  requestDrain(controlPlaneFatal(error48) ? "authority_lost" : "attempt_terminal_unconfirmed");
28592
28624
  }).finally(() => {
28625
+ settleClaimPromotion();
28593
28626
  active.delete(attemptId);
28594
28627
  attemptControllers.delete(attemptId);
28595
28628
  });
@@ -28686,29 +28719,33 @@ var init_runner = __esm({
28686
28719
  const recovery = recoveryQueue.shift();
28687
28720
  launchClaim(recovery.claim, recovery);
28688
28721
  }
28689
- while (!drainRequested && recoveryQueue.length === 0 && (!this.options.once || !onceClaimed) && active.size < settings.maxConcurrency && now() >= nextClaimAt) {
28690
- const claimSequence = receipt.claim_sequence + 1;
28691
- const request = {
28692
- schema_version: "external_inference_job_claim_v1",
28693
- contract_version: EXTERNAL_INFERENCE_CONTRACT_VERSION,
28694
- host_id: localState.host_id,
28695
- host_generation: localState.host_generation,
28696
- advertisement_generation: receipt.advertisement_generation,
28697
- key_generation: localState.key_generation,
28698
- claim_request_id: stableOperationId("claim", [
28699
- localState.host_id,
28700
- localState.host_generation,
28701
- receipt.advertisement_generation,
28702
- claimSequence
28703
- ]),
28704
- requested_at: isoAt(now())
28705
- };
28706
- receipt = {
28707
- ...receipt,
28708
- claim_sequence: claimSequence,
28709
- updated_at: isoAt(now())
28710
- };
28711
- await this.persistReceipt(receipt, now);
28722
+ while (!drainRequested && recoveryQueue.length === 0 && (!this.options.once || !onceClaimed) && active.size < settings.maxConcurrency && pendingClaimPromotions === 0 && now() >= nextClaimAt) {
28723
+ if (!receipt.pending_claim_request) {
28724
+ const claimSequence = receipt.claim_sequence + 1;
28725
+ const pendingClaimRequest = {
28726
+ schema_version: "external_inference_job_claim_v1",
28727
+ contract_version: EXTERNAL_INFERENCE_CONTRACT_VERSION,
28728
+ host_id: localState.host_id,
28729
+ host_generation: localState.host_generation,
28730
+ advertisement_generation: receipt.advertisement_generation,
28731
+ key_generation: localState.key_generation,
28732
+ claim_request_id: stableOperationId("claim", [
28733
+ localState.host_id,
28734
+ localState.host_generation,
28735
+ receipt.advertisement_generation,
28736
+ claimSequence
28737
+ ]),
28738
+ requested_at: isoAt(now())
28739
+ };
28740
+ receipt = {
28741
+ ...receipt,
28742
+ claim_sequence: claimSequence,
28743
+ pending_claim_request: pendingClaimRequest,
28744
+ updated_at: isoAt(now())
28745
+ };
28746
+ await this.persistReceipt(receipt, now);
28747
+ }
28748
+ const request = receipt.pending_claim_request;
28712
28749
  let claim;
28713
28750
  try {
28714
28751
  claim = await mcp.callTool(
@@ -28720,6 +28757,18 @@ var init_runner = __esm({
28720
28757
  } catch (error48) {
28721
28758
  if (!this.options.signal?.aborted && controlPlaneFatal(error48)) {
28722
28759
  requestDrain("authority_lost");
28760
+ } else if (!this.options.signal?.aborted && error48 instanceof ExternalInferenceMcpError && error48.definitivelyNotApplied) {
28761
+ if (request.advertisement_generation < receipt.advertisement_generation) {
28762
+ receipt = {
28763
+ ...receipt,
28764
+ pending_claim_request: null,
28765
+ updated_at: isoAt(now())
28766
+ };
28767
+ await this.persistReceipt(receipt, now);
28768
+ nextClaimAt = now();
28769
+ } else {
28770
+ requestDrain("claim_failed");
28771
+ }
28723
28772
  } else if (!this.options.signal?.aborted && retryableRemoteError(error48)) {
28724
28773
  nextClaimAt = now() + remoteRetryAfterMs(error48, 1e3);
28725
28774
  } else if (!this.options.signal?.aborted) {
@@ -28728,11 +28777,27 @@ var init_runner = __esm({
28728
28777
  break;
28729
28778
  }
28730
28779
  if (claim.claim_state === "empty") {
28780
+ receipt = {
28781
+ ...receipt,
28782
+ pending_claim_request: null,
28783
+ updated_at: isoAt(now())
28784
+ };
28785
+ await this.persistReceipt(receipt, now);
28731
28786
  nextClaimAt = now() + Math.max(MIN_SLEEP_MS, claim.retry_after_ms);
28732
28787
  if (this.options.once) requestDrain("once_empty");
28733
28788
  break;
28734
28789
  }
28735
- launchClaim(claim);
28790
+ if (Date.parse(claim.lease_expires_at) <= now() + MIN_CLAIM_START_WINDOW_MS || Date.parse(claim.deadline_at) <= now() + MIN_CLAIM_START_WINDOW_MS) {
28791
+ receipt = {
28792
+ ...receipt,
28793
+ pending_claim_request: null,
28794
+ updated_at: isoAt(now())
28795
+ };
28796
+ await this.persistReceipt(receipt, now);
28797
+ nextClaimAt = now();
28798
+ break;
28799
+ }
28800
+ launchClaim(claim, void 0, request);
28736
28801
  if (this.options.once) requestDrain("once_complete");
28737
28802
  }
28738
28803
  if (drainRequested) break;
@@ -28805,7 +28870,7 @@ var init_runner = __esm({
28805
28870
  const sealCandidate = this.dependencies.sealCandidate ?? sealExternalInferenceCandidate;
28806
28871
  const validateOutput = this.dependencies.validateOutput ?? defaultValidateOutput;
28807
28872
  const activeReceipt = options.receipt();
28808
- if (claim.host_id !== localState.host_id || claim.host_generation !== localState.host_generation || (options.resumeReceipt ? claim.advertisement_generation > activeReceipt.advertisement_generation : claim.advertisement_generation !== activeReceipt.advertisement_generation) || claim.key_generation !== localState.key_generation) {
28873
+ if (claim.host_id !== localState.host_id || claim.host_generation !== localState.host_generation || (options.resumeReceipt || options.claimRequest ? claim.advertisement_generation > activeReceipt.advertisement_generation : claim.advertisement_generation !== activeReceipt.advertisement_generation) || claim.key_generation !== localState.key_generation) {
28809
28874
  throw new InferenceHostRunnerError(
28810
28875
  "claim_generation_mismatch",
28811
28876
  "The claimed job crossed the active host generation fence."
@@ -28839,11 +28904,15 @@ var init_runner = __esm({
28839
28904
  );
28840
28905
  }
28841
28906
  if (!options.resumeReceipt) {
28907
+ const currentReceipt = options.receipt();
28908
+ const pendingClaimRequest = options.claimRequest && currentReceipt.pending_claim_request?.claim_request_id === options.claimRequest.claim_request_id ? null : currentReceipt.pending_claim_request ?? null;
28842
28909
  await options.updateReceipt({
28843
- ...options.receipt(),
28844
- attempts: { ...options.receipt().attempts, [attemptId]: attemptReceipt },
28910
+ ...currentReceipt,
28911
+ pending_claim_request: pendingClaimRequest,
28912
+ attempts: { ...currentReceipt.attempts, [attemptId]: attemptReceipt },
28845
28913
  updated_at: isoAt(now())
28846
28914
  });
28915
+ options.onClaimPersisted?.();
28847
28916
  }
28848
28917
  const updateAttempt = async (changes) => {
28849
28918
  attemptReceipt = validateAttemptReceipt({
@@ -28867,12 +28936,28 @@ var init_runner = __esm({
28867
28936
  });
28868
28937
  };
28869
28938
  if (attemptReceipt.phase === "claimed") {
28870
- const attemptDeadlineAtMs = Date.parse(claim.deadline_at);
28871
- const startResult = await retryExact(() => mcp.callTool(
28872
- "inference.job.start",
28873
- startRequest,
28874
- { signal, deadlineAtMs: attemptDeadlineAtMs }
28875
- ), { signal, deadlineAtMs: attemptDeadlineAtMs });
28939
+ const attemptDeadlineAtMs = Math.min(
28940
+ Date.parse(claim.deadline_at),
28941
+ Date.parse(claim.lease_expires_at)
28942
+ );
28943
+ if (attemptDeadlineAtMs <= now() + MIN_CLAIM_START_WINDOW_MS) {
28944
+ await removeAttempt();
28945
+ return "failed";
28946
+ }
28947
+ let startResult;
28948
+ try {
28949
+ startResult = await retryExact(() => mcp.callTool(
28950
+ "inference.job.start",
28951
+ startRequest,
28952
+ { signal, deadlineAtMs: attemptDeadlineAtMs }
28953
+ ), { signal, deadlineAtMs: attemptDeadlineAtMs });
28954
+ } catch (error48) {
28955
+ if (attemptDeadlineAtMs <= now() + MIN_CLAIM_START_WINDOW_MS) {
28956
+ await removeAttempt();
28957
+ return "failed";
28958
+ }
28959
+ throw error48;
28960
+ }
28876
28961
  assertStartResult(startRequest, startResult);
28877
28962
  await updateAttempt({ phase: "started" });
28878
28963
  }
@@ -29582,7 +29667,7 @@ private-file fallback. See https://vtxmacro.com/insights#subscription-inference.
29582
29667
  const receipt = await new FileInferenceHostRuntimeReceiptStore(
29583
29668
  runtimeReceiptPath(config2)
29584
29669
  ).read();
29585
- const pendingAttempts = receipt ? Object.keys(receipt.attempts).length : 0;
29670
+ const pendingAttempts = receipt ? Object.keys(receipt.attempts).length + (receipt.pending_claim_request ? 1 : 0) : 0;
29586
29671
  const codexRecoveryPresent = await fileExistsPrivately(
29587
29672
  codexRecoveryPath(config2),
29588
29673
  "Codex attempt recovery file"
@@ -29873,7 +29958,7 @@ Waiting for approval...
29873
29958
  runtime: receipt ? {
29874
29959
  registered: receipt.registered,
29875
29960
  advertisement_generation: receipt.advertisement_generation,
29876
- pending_attempts: Object.keys(receipt.attempts).length,
29961
+ pending_attempts: Object.keys(receipt.attempts).length + (receipt.pending_claim_request ? 1 : 0),
29877
29962
  updated_at: receipt.updated_at
29878
29963
  } : null,
29879
29964
  agent_attempt: agentAttempt ? {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtxmacro/cli",
3
- "version": "2026.8.15",
3
+ "version": "2026.8.17",
4
4
  "description": "VTX Macro CLI, MCP server, and foreground subscription inference host.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",