@vtxmacro/cli 2026.9.19 → 2026.9.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -250,10 +250,22 @@ vtx inference-host agent-next --wait-seconds 50 --json
250
250
  That is the **Provider** loop. `agent-next` returns separate exact
251
251
  `system_prompt`, `user_prompt`,
252
252
  `context_json`, and `output_schema_json` fields. The agent reasons in its own
253
- session, then writes one JSON object to `agent-complete` stdin. At minimum that
254
- object contains a `result` string. If the harness exposes exact token usage,
255
- include the published usage object; otherwise VTX records usage as explicitly
256
- unavailable. For `agent-fail`, choose the truthful dispatch state and set
253
+ session, then writes one JSON object to `agent-complete` stdin. The CLI reports
254
+ its actual release version and negotiates `foreground_v1` Provider freshness.
255
+ Prewarm the harness before requesting work. For Server Mode jobs, the handoff includes
256
+ `provider_dispatch_not_after`, `provider_dispatch_local_not_after`, and
257
+ `provider_dispatch_freshness_remaining_ms`; the local deadline and remaining
258
+ budget account conservatively for RPC time and pending-request replay. Enforce
259
+ both deadlines immediately before the real provider request. If either expires
260
+ before dispatch, do not send stale work: use `agent-fail` with
261
+ `dispatch_outcome: not_dispatched`, `failure_category: freshness`,
262
+ `failure_code: provider_dispatch_freshness_expired`, and `retryable: false`.
263
+ Completion contains a `result` string; negotiated server jobs also require
264
+ `provider_dispatched_at`, the ISO 8601 timestamp captured at provider request
265
+ entry. This is harness-reported evidence, not provider attestation. If the harness
266
+ exposes exact token usage, include the published usage object; otherwise VTX
267
+ records usage as explicitly unavailable. For `agent-fail`, choose the truthful
268
+ dispatch state and set
257
269
  `retryable` true only when a fresh attempt is safe:
258
270
 
259
271
  ```json
@@ -16,7 +16,7 @@ import { fileURLToPath } from "node:url";
16
16
  // agent-cli-release.json
17
17
  var agent_cli_release_default = {
18
18
  package_name: "@vtxmacro/cli",
19
- package_version: "2026.9.19",
19
+ package_version: "2026.9.21",
20
20
  codex_package_name: "@openai/codex",
21
21
  codex_version: "0.153.3",
22
22
  copilot_sdk_package_name: "@github/copilot-sdk",
package/bin/vtx.js CHANGED
@@ -69,7 +69,7 @@ var init_agent_cli_release = __esm({
69
69
  "agent-cli-release.json"() {
70
70
  agent_cli_release_default = {
71
71
  package_name: "@vtxmacro/cli",
72
- package_version: "2026.9.19",
72
+ package_version: "2026.9.21",
73
73
  codex_package_name: "@openai/codex",
74
74
  codex_version: "0.153.3",
75
75
  copilot_sdk_package_name: "@github/copilot-sdk",
@@ -15014,12 +15014,16 @@ var init_external_inference_contract = __esm({
15014
15014
  authenticated_account_plan: safeCodeSchema.nullable().optional(),
15015
15015
  protocol_version: protocolVersionSchema,
15016
15016
  host_runtime_version: protocolVersionSchema.optional(),
15017
+ provider_dispatch_freshness_contract: external_exports.literal("foreground_v1").optional(),
15017
15018
  envelope_public_key: base64Url32BytesSchema,
15018
15019
  health: external_exports.enum(["healthy", "degraded", "draining"]),
15019
15020
  advertised_at: timestampSchema,
15020
15021
  expires_at: timestampSchema,
15021
15022
  models: external_exports.array(advertisedModelSchema).min(1).max(64)
15022
15023
  }).superRefine((value, context) => {
15024
+ if (value.provider_dispatch_freshness_contract !== void 0 && !/^\d+\.\d+\.\d+$/.test(value.host_runtime_version ?? "")) {
15025
+ context.addIssue({ code: "custom", message: "Foreground freshness contract requires a numeric runtime version." });
15026
+ }
15023
15027
  const modelIds = value.models.map((model) => model.model_id);
15024
15028
  if (new Set(modelIds).size !== modelIds.length) {
15025
15029
  context.addIssue({
@@ -15420,12 +15424,17 @@ var init_external_inference_contract = __esm({
15420
15424
  model_id: identifierSchema,
15421
15425
  model_label: displayNameSchema,
15422
15426
  reasoning_effort: reasoningEffortSchema,
15423
- requested_at: timestampSchema
15427
+ requested_at: timestampSchema,
15428
+ host_runtime_version: external_exports.string().regex(/^\d+\.\d+\.\d+$/).optional(),
15429
+ provider_dispatch_freshness_contract: external_exports.literal("foreground_v1").optional()
15430
+ }).refine((value) => value.host_runtime_version === void 0 === (value.provider_dispatch_freshness_contract === void 0), {
15431
+ message: "Foreground freshness negotiation requires the actual CLI version."
15424
15432
  });
15425
15433
  agentNextRequestSchema = external_exports.strictObject({
15426
15434
  operation_id: operationIdentifierSchema,
15427
15435
  host_id: identifierSchema,
15428
- requested_at: timestampSchema
15436
+ requested_at: timestampSchema,
15437
+ provider_dispatch_freshness_contract: external_exports.literal("foreground_v1").optional()
15429
15438
  });
15430
15439
  agentHeartbeatRequestSchema = external_exports.strictObject({
15431
15440
  operation_id: operationIdentifierSchema,
@@ -15449,6 +15458,9 @@ var init_external_inference_contract = __esm({
15449
15458
  requested_reasoning_effort: reasoningEffortSchema,
15450
15459
  output_schema_version: protocolVersionSchema,
15451
15460
  deadline_at: timestampSchema,
15461
+ provider_dispatch_freshness_contract: external_exports.literal("foreground_v1").optional(),
15462
+ provider_dispatch_not_after: timestampSchema.optional(),
15463
+ provider_dispatch_freshness_remaining_ms: nonNegativeSafeIntegerSchema.optional(),
15452
15464
  system_prompt: boundedPromptTextSchema,
15453
15465
  system_prompt_sha256: sha256HexSchema,
15454
15466
  user_prompt: boundedPromptTextSchema,
@@ -15458,6 +15470,14 @@ var init_external_inference_contract = __esm({
15458
15470
  output_schema_json: boundedJsonTextSchema,
15459
15471
  output_schema_sha256: sha256HexSchema
15460
15472
  }).superRefine((value, context) => {
15473
+ const freshnessFields = [
15474
+ value.provider_dispatch_freshness_contract,
15475
+ value.provider_dispatch_not_after,
15476
+ value.provider_dispatch_freshness_remaining_ms
15477
+ ];
15478
+ if (freshnessFields.some((field) => field !== void 0) && (freshnessFields.some((field) => field === void 0) || value.execution_mode !== "server")) {
15479
+ context.addIssue({ code: "custom", message: "Foreground freshness handoff is incomplete." });
15480
+ }
15461
15481
  for (const [field, exact, digest] of [
15462
15482
  ["system_prompt", value.system_prompt, value.system_prompt_sha256],
15463
15483
  ["user_prompt", value.user_prompt, value.user_prompt_sha256],
@@ -15489,7 +15509,8 @@ var init_external_inference_contract = __esm({
15489
15509
  time_to_first_token_ms: nonNegativeSafeIntegerSchema.nullable().optional(),
15490
15510
  finish_reason: safeCodeSchema.nullable().optional(),
15491
15511
  refusal_status: external_exports.enum(["none", "refused", "blocked", "unknown"]),
15492
- completed_at: timestampSchema
15512
+ completed_at: timestampSchema,
15513
+ provider_dispatched_at: timestampSchema.nullable().optional()
15493
15514
  }).superRefine((value, context) => {
15494
15515
  if (value.time_to_first_token_ms !== void 0 && value.time_to_first_token_ms !== null && value.time_to_first_token_ms > value.latency_ms) {
15495
15516
  context.addIssue({
@@ -17937,13 +17958,27 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
17937
17958
  }
17938
17959
  };
17939
17960
  }
17940
- var loadInferenceAgentDataRequestTimeoutMs, INFERENCE_CREDENTIAL_NAMESPACE, MAX_INFERENCE_PRIVATE_FILE_BYTES, WINDOWS_PRIVATE_ACL_BROKER_SCRIPT, WINDOWS_IDENTITY_COMMAND_TIMEOUT_MS, WINDOWS_PRIVATE_ACL_BROKER_STARTUP_TIMEOUT_MS, SMALL_IDENTITY_COMMAND_TIMEOUT_MS, windowsPowerShellEnvironment, windowsPrivateAclBrokerInvocation, WindowsPrivateAclBroker, defaultWindowsPrivateAclBroker, runWindowsPrivateAcl, windowsAclCache, windowsAclIdentity, aclCacheKey, secureWindowsPrivatePath, invalidateWindowsAclCache, rebindHardenedWindowsAclAfterRename, rebindHardenedWindowsDirectoryAfterOwnedMutation, isDefaultWindowsPrivatePath, secureExistingWindowsPath, linuxProcessIdentity, windowsProcessIdentityInvocation, windowsBootIdentityInvocation, windowsProcessIdentity, darwinProcessIdentity, runSmallIdentityCommand, cachedSystemBootIdentity, readInferenceSystemBootIdentity, defaultProcessIdentity, defaultCurrentProcessIdentity, processLockObservationCache, inferenceProcessIdentitiesMatch, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity, inferenceHostCredentialContextPath, inferenceHostCredentialContextTransitionPath, credentialContextForConfig, WINDOWS_PRIVATE_FILE_REPLACE_ERROR_CODES;
17961
+ var loadInferenceReceiptDurabilityTimeoutMs, loadInferenceAgentDataRequestTimeoutMs, INFERENCE_CREDENTIAL_NAMESPACE, MAX_INFERENCE_PRIVATE_FILE_BYTES, WINDOWS_PRIVATE_ACL_BROKER_SCRIPT, WINDOWS_IDENTITY_COMMAND_TIMEOUT_MS, WINDOWS_PRIVATE_ACL_BROKER_STARTUP_TIMEOUT_MS, SMALL_IDENTITY_COMMAND_TIMEOUT_MS, windowsPowerShellEnvironment, windowsPrivateAclBrokerInvocation, WindowsPrivateAclBroker, defaultWindowsPrivateAclBroker, runWindowsPrivateAcl, windowsAclCache, windowsAclIdentity, aclCacheKey, secureWindowsPrivatePath, invalidateWindowsAclCache, rebindHardenedWindowsAclAfterRename, rebindHardenedWindowsDirectoryAfterOwnedMutation, isDefaultWindowsPrivatePath, secureExistingWindowsPath, linuxProcessIdentity, windowsProcessIdentityInvocation, windowsBootIdentityInvocation, windowsProcessIdentity, darwinProcessIdentity, runSmallIdentityCommand, cachedSystemBootIdentity, readInferenceSystemBootIdentity, defaultProcessIdentity, defaultCurrentProcessIdentity, processLockObservationCache, inferenceProcessIdentitiesMatch, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity, inferenceHostCredentialContextPath, inferenceHostCredentialContextTransitionPath, credentialContextForConfig, WINDOWS_PRIVATE_FILE_REPLACE_ERROR_CODES;
17941
17962
  var init_config = __esm({
17942
17963
  "lib/inference-host/config.ts"() {
17943
17964
  "use strict";
17944
17965
  init_define_VTX_EXO_POLICY();
17945
17966
  init_define_VTX_PI_MODEL_POLICY();
17946
17967
  init_dist();
17968
+ loadInferenceReceiptDurabilityTimeoutMs = async () => {
17969
+ let configured;
17970
+ if (true) {
17971
+ configured = 5e3;
17972
+ } else {
17973
+ const config2 = parse4(await readFile(resolve(dirname(fileURLToPath(import.meta.url)), "../../../config.toml"), "utf8"));
17974
+ const inference = config2.external_inference;
17975
+ configured = Number(inference?.receipt_durability_timeout_seconds) * 1e3;
17976
+ }
17977
+ if (!Number.isSafeInteger(configured) || Number(configured) < 1) {
17978
+ throw new Error("Inference receipt durability timeout is missing or invalid.");
17979
+ }
17980
+ return Number(configured);
17981
+ };
17947
17982
  loadInferenceAgentDataRequestTimeoutMs = async () => {
17948
17983
  let configured;
17949
17984
  if (true) {
@@ -19850,7 +19885,7 @@ var init_mcp_client = __esm({
19850
19885
  const hasPublicToolErrorMarker = hasStructuredPublicToolErrorMarker || errorText.includes(PUBLIC_TOOL_ERROR_PREFIX);
19851
19886
  const completionEvidenceExpired = name === "inference.job.complete" && (publicToolError ? publicToolError.failure_code === "completion_evidence_expired" && publicToolError.phase === "validation" && publicToolError.retryable === false && publicToolError.terminal_before_execution === true : !hasPublicToolErrorMarker && errorText.includes("External inference completion evidence window expired"));
19852
19887
  const hostNotClaimable = name === "inference.job.claim" && publicToolError?.failure_code === "host_not_claimable" && publicToolError.phase === "admission" && publicToolError.retryable === true && publicToolError.terminal_before_execution === true;
19853
- 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.host.heartbeat" && errorText.includes("Heartbeat time is outside the allowed clock skew.") || name === "inference.job.claim" && (errorText.includes(
19888
+ const definitivelyNotApplied = name === "inference.agent.decision.submit" && publicToolError?.phase === "validation" && publicToolError.retryable === false && publicToolError.terminal_before_execution === true && (publicToolError.failure_code === "agent_decision_schema_invalid" || publicToolError.failure_code === "invalid_arguments" && publicToolError.reason_code === "schema_validation") || (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.host.heartbeat" && errorText.includes("Heartbeat time is outside the allowed clock skew.") || name === "inference.job.claim" && (errorText.includes(
19854
19889
  "External inference claim request was not applied before its generation became stale"
19855
19890
  ) || errorText.includes("External inference host advertisement is expired or superseded")) || name === "inference.job.complete" && completionEvidenceExpired;
19856
19891
  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"));
@@ -21222,6 +21257,19 @@ var init_agent_state = __esm({
21222
21257
  "received_at",
21223
21258
  "pending_terminal"
21224
21259
  ];
21260
+ const freshnessKeys = ["provider_dispatch_not_after", "provider_dispatch_local_not_after"];
21261
+ if ("execution_mode" in record3) {
21262
+ if (!["server", "client"].includes(String(record3.execution_mode))) {
21263
+ throw new Error("Agent-driven inference execution mode is invalid.");
21264
+ }
21265
+ exactKeys.push("execution_mode");
21266
+ }
21267
+ if (freshnessKeys.some((key) => key in record3)) {
21268
+ if (freshnessKeys.some((key) => typeof record3[key] !== "string" || !Number.isFinite(Date.parse(record3[key])))) {
21269
+ throw new Error("Agent-driven inference freshness recovery state is invalid.");
21270
+ }
21271
+ exactKeys.push(...freshnessKeys);
21272
+ }
21225
21273
  if (Object.keys(record3).sort().join("\0") !== exactKeys.slice().sort().join("\0") || record3.schema_version !== "vtx_inference_agent_attempt_v1" || typeof record3.host_id !== "string" || !record3.host_id || typeof record3.job_id !== "string" || !record3.job_id || typeof record3.attempt_id !== "string" || !record3.attempt_id || typeof record3.claim_handle !== "string" || !record3.claim_handle || typeof record3.completion_operation_id !== "string" || !record3.completion_operation_id || typeof record3.failure_operation_id !== "string" || !record3.failure_operation_id || typeof record3.requested_model !== "string" || !record3.requested_model || typeof record3.requested_reasoning_effort !== "string" || !record3.requested_reasoning_effort || !["provider_response", "decision_candidate"].includes(String(record3.response_mode)) || typeof record3.deadline_at !== "string" || !Number.isFinite(Date.parse(record3.deadline_at)) || typeof record3.received_at !== "string" || !Number.isFinite(Date.parse(record3.received_at))) {
21226
21274
  throw new Error("Agent-driven inference attempt state is invalid.");
21227
21275
  }
@@ -35740,6 +35788,11 @@ var init_runner = __esm({
35740
35788
  DEFAULT_ATTEMPT_HEARTBEAT_MS,
35741
35789
  "Attempt heartbeat interval"
35742
35790
  ),
35791
+ receiptDurabilityTimeoutMs: finitePositiveOption(
35792
+ options.receiptDurabilityTimeoutMs,
35793
+ options.receiptDurabilityTimeoutMs,
35794
+ "Receipt durability timeout"
35795
+ ),
35743
35796
  drainTimeoutMs: finitePositiveOption(
35744
35797
  options.drainTimeoutMs,
35745
35798
  DEFAULT_DRAIN_TIMEOUT_MS,
@@ -36059,7 +36112,10 @@ var init_runner = __esm({
36059
36112
  this.options = options;
36060
36113
  }
36061
36114
  async run() {
36062
- const settings = validateRunnerOptions(this.options);
36115
+ const settings = validateRunnerOptions({
36116
+ ...this.options,
36117
+ receiptDurabilityTimeoutMs: this.options.receiptDurabilityTimeoutMs ?? await loadInferenceReceiptDurabilityTimeoutMs()
36118
+ });
36063
36119
  const now = this.dependencies.now ?? Date.now;
36064
36120
  const sleep4 = this.dependencies.sleep ?? defaultSleep;
36065
36121
  const lock2 = await this.dependencies.acquireProcessLock();
@@ -36931,6 +36987,7 @@ var init_runner = __esm({
36931
36987
  retryExact,
36932
36988
  signal: controller.signal,
36933
36989
  attemptHeartbeatMs: settings.attemptHeartbeatMs,
36990
+ receiptDurabilityTimeoutMs: settings.receiptDurabilityTimeoutMs,
36934
36991
  sleep: sleep4,
36935
36992
  now,
36936
36993
  onProviderCooldown: ({ retryAtMs, reason, rateLimits }) => {
@@ -36998,9 +37055,9 @@ var init_runner = __esm({
36998
37055
  active_attempts: active.size
36999
37056
  });
37000
37057
  },
37001
- onProviderDispatchRecoveryRequired: () => {
37058
+ onProviderDispatchRecoveryRequired: (reason = "provider_dispatch_watchdog_expired") => {
37002
37059
  providerDispatchWatchdogDrainRequested = true;
37003
- requestDrain("provider_dispatch_watchdog_expired");
37060
+ requestDrain(reason);
37004
37061
  },
37005
37062
  startRetryCount: nextStartRetryCount,
37006
37063
  onAttemptStartRetry: (observation) => {
@@ -37704,14 +37761,35 @@ var init_runner = __esm({
37704
37761
  attemptAbort.abort();
37705
37762
  }, Math.max(MIN_SLEEP_MS, deadlineAtMs - now()));
37706
37763
  };
37707
- const awaitPreProviderDurability = async (operation) => Promise.race([
37708
- operation,
37709
- providerDispatchWatchdogSignal.then(() => {
37710
- throw new InferenceHostRecoveryRequiredError(
37711
- "Provider dispatch stopped because its durable receipt missed the freshness deadline."
37712
- );
37713
- })
37714
- ]);
37764
+ let receiptDurabilityUnhealthy = false;
37765
+ const awaitPreProviderDurability = async (operation) => {
37766
+ let timer;
37767
+ try {
37768
+ return await Promise.race([
37769
+ operation,
37770
+ new Promise((_resolve, reject) => {
37771
+ timer = setTimeout(() => {
37772
+ receiptDurabilityUnhealthy = true;
37773
+ options.onProviderDispatchRecoveryRequired?.("receipt_durability_timeout");
37774
+ reject(new InferenceHostRecoveryRequiredError(
37775
+ "Provider dispatch stopped because durable receipt storage did not settle."
37776
+ ));
37777
+ }, options.receiptDurabilityTimeoutMs);
37778
+ })
37779
+ ]);
37780
+ } finally {
37781
+ if (timer !== void 0) clearTimeout(timer);
37782
+ }
37783
+ };
37784
+ const requireDispatchFreshness = () => {
37785
+ if (providerDispatchNotAfterMs === void 0 || !providerDispatchWatchdogExpired && now() < providerDispatchNotAfterMs) return;
37786
+ providerDispatchWatchdogExpired = true;
37787
+ attemptAbort.abort();
37788
+ throw new InferenceHostRunnerError(
37789
+ "server_account_context_expired_before_provider_dispatch",
37790
+ "The Server account context expired before provider dispatch."
37791
+ );
37792
+ };
37715
37793
  const persistAttempt = async (changes, clearPendingClaim = false) => {
37716
37794
  const nextAttemptReceipt = validateAttemptReceipt({
37717
37795
  ...attemptReceipt,
@@ -37831,12 +37909,21 @@ var init_runner = __esm({
37831
37909
  membership_disposition: membershipFailureDisposition(failure2),
37832
37910
  failed_at: isoAt(now())
37833
37911
  });
37834
- void persistAttempt({
37912
+ const terminalDurability = persistAttempt({
37835
37913
  phase: "terminal_pending",
37836
37914
  dispatch_outcome: "not_dispatched",
37837
37915
  terminal_operation_id: failureId,
37838
37916
  terminal_request: failureRequest
37839
- }).catch(() => void 0);
37917
+ });
37918
+ if (receiptDurabilityUnhealthy) {
37919
+ void terminalDurability.catch(() => void 0);
37920
+ } else {
37921
+ try {
37922
+ await awaitPreProviderDurability(terminalDurability);
37923
+ } catch (error48) {
37924
+ if (!receiptDurabilityUnhealthy) throw error48;
37925
+ }
37926
+ }
37840
37927
  const evidenceDeadlineAtMs = Date.parse(jobInput.evidence_expires_at);
37841
37928
  const failureResult = await retryExact(() => mcp.callTool(
37842
37929
  "inference.job.fail",
@@ -37844,6 +37931,9 @@ var init_runner = __esm({
37844
37931
  { signal, deadlineAtMs: evidenceDeadlineAtMs }
37845
37932
  ), { signal, deadlineAtMs: evidenceDeadlineAtMs });
37846
37933
  assertTerminalResult(failureRequest, failureResult);
37934
+ if (!receiptDurabilityUnhealthy) {
37935
+ await awaitPreProviderDurability(removeAttempt());
37936
+ }
37847
37937
  options.onAttemptOutcome?.({
37848
37938
  outcome: "failed",
37849
37939
  failure_category: failureRequest.failure_category,
@@ -37984,6 +38074,7 @@ var init_runner = __esm({
37984
38074
  }
37985
38075
  }
37986
38076
  if (attemptReceipt.phase !== "dispatched") {
38077
+ requireDispatchFreshness();
37987
38078
  const providerDispatchable = inputValidationError === void 0 && outputContract !== null;
37988
38079
  reportPreProviderStage("receipt_persistence");
37989
38080
  await awaitPreProviderDurability(
@@ -37996,12 +38087,12 @@ var init_runner = __esm({
37996
38087
  ])
37997
38088
  );
37998
38089
  }
38090
+ if (options.resumeReceipt?.phase !== "dispatched") requireDispatchFreshness();
37999
38091
  reportPreProviderStage("thread_setup");
38000
38092
  } catch (error48) {
38001
38093
  clearProviderDispatchWatchdog();
38002
38094
  signal.removeEventListener("abort", relayAbort);
38003
38095
  if (providerDispatchWatchdogExpired) {
38004
- options.onProviderDispatchRecoveryRequired?.();
38005
38096
  return terminalizeProviderDispatchWatchdog();
38006
38097
  }
38007
38098
  throw error48;
@@ -41424,6 +41515,7 @@ Durable service:
41424
41515
  protocolVersion: EXTERNAL_INFERENCE_CONTRACT_VERSION,
41425
41516
  adapterRuntimeVersion: INFERENCE_HOST_CLI_VERSION,
41426
41517
  hostRuntimeVersion: INFERENCE_HOST_CLI_VERSION,
41518
+ receiptDurabilityTimeoutMs: await loadInferenceReceiptDurabilityTimeoutMs(),
41427
41519
  maxConcurrency: options.maxConcurrency,
41428
41520
  once: options.once,
41429
41521
  emitDiagnosticEvent: options.emitDiagnosticEvent,
@@ -41494,6 +41586,7 @@ Durable service:
41494
41586
  protocolVersion: EXTERNAL_INFERENCE_CONTRACT_VERSION,
41495
41587
  adapterRuntimeVersion: options.preflight.runtimeVersion,
41496
41588
  hostRuntimeVersion: INFERENCE_HOST_CLI_VERSION,
41589
+ receiptDurabilityTimeoutMs: await loadInferenceReceiptDurabilityTimeoutMs(),
41497
41590
  maxConcurrency: options.maxConcurrency,
41498
41591
  once: options.once,
41499
41592
  emitDiagnosticEvent: options.emitDiagnosticEvent,
@@ -42400,7 +42493,9 @@ Waiting for approval...
42400
42493
  model_id: parsed.modelId,
42401
42494
  model_label: parsed.modelLabel ?? parsed.modelId,
42402
42495
  reasoning_effort: parsed.reasoningEffort,
42403
- requested_at: now.toISOString()
42496
+ requested_at: now.toISOString(),
42497
+ host_runtime_version: INFERENCE_HOST_CLI_VERSION,
42498
+ provider_dispatch_freshness_contract: "foreground_v1"
42404
42499
  });
42405
42500
  return {
42406
42501
  exitCode: 0,
@@ -42771,6 +42866,14 @@ Waiting for approval...
42771
42866
  ` : ""
42772
42867
  };
42773
42868
  } catch (error48) {
42869
+ if (error48 instanceof ExternalInferenceMcpError && error48.definitivelyNotApplied) {
42870
+ await writeInferenceForegroundAgentControlState(config2.statePath, {
42871
+ ...state,
42872
+ pending_decision: null,
42873
+ updated_at: now().toISOString()
42874
+ });
42875
+ throw error48;
42876
+ }
42774
42877
  const checkedAt = now().toISOString();
42775
42878
  state = {
42776
42879
  ...state,
@@ -43031,11 +43134,14 @@ Waiting for approval...
43031
43134
  await writeInferenceAgentNextState(config2.statePath, pending);
43032
43135
  }
43033
43136
  let result2;
43137
+ const callStartedAtMs = now().getTime();
43138
+ const callStartedMonotonicMs = performance.now();
43034
43139
  try {
43035
43140
  result2 = await session.client.callTool("inference.agent.next", {
43036
43141
  operation_id: pending.operation_id,
43037
43142
  host_id: session.localState.host_id,
43038
- requested_at: pending.requested_at
43143
+ requested_at: pending.requested_at,
43144
+ provider_dispatch_freshness_contract: "foreground_v1"
43039
43145
  });
43040
43146
  } catch (error48) {
43041
43147
  const definitivelyNotApplied = Boolean(
@@ -43048,10 +43154,31 @@ Waiting for approval...
43048
43154
  }
43049
43155
  if (result2.claim_state === "claimed") {
43050
43156
  const receivedAt = now().toISOString();
43157
+ const receivedAtMs = Date.parse(receivedAt);
43158
+ const roundTripMs = Math.max(0, dependencies.now ? receivedAtMs - callStartedAtMs : performance.now() - callStartedMonotonicMs);
43159
+ let localDispatchDeadline;
43160
+ const validFreshness = result2.provider_dispatch_freshness_contract === "foreground_v1" && typeof result2.provider_dispatch_not_after === "string" && Number.isFinite(Date.parse(result2.provider_dispatch_not_after)) && Number.isSafeInteger(result2.provider_dispatch_freshness_remaining_ms) && Number(result2.provider_dispatch_freshness_remaining_ms) >= 0;
43161
+ if (result2.execution_mode === "server" && validFreshness) {
43162
+ const conservativeDeadline = Math.min(
43163
+ Date.parse(result2.provider_dispatch_not_after),
43164
+ receivedAtMs + Number(result2.provider_dispatch_freshness_remaining_ms) - roundTripMs,
43165
+ Date.parse(pending.requested_at) + Number(result2.provider_dispatch_freshness_remaining_ms),
43166
+ active?.provider_dispatch_local_not_after ? Date.parse(active.provider_dispatch_local_not_after) : Number.POSITIVE_INFINITY
43167
+ );
43168
+ localDispatchDeadline = new Date(conservativeDeadline).toISOString();
43169
+ }
43051
43170
  if (active) {
43052
- if (result2.job_id !== active.job_id || result2.attempt_id !== active.attempt_id || result2.claim_handle !== active.claim_handle || result2.requested_model !== active.requested_model || result2.requested_reasoning_effort !== active.requested_reasoning_effort || result2.response_mode !== active.response_mode || result2.deadline_at !== active.deadline_at) {
43171
+ if (result2.job_id !== active.job_id || result2.attempt_id !== active.attempt_id || result2.claim_handle !== active.claim_handle || result2.requested_model !== active.requested_model || result2.requested_reasoning_effort !== active.requested_reasoning_effort || result2.response_mode !== active.response_mode || result2.deadline_at !== active.deadline_at || active.provider_dispatch_not_after !== void 0 && result2.provider_dispatch_not_after !== active.provider_dispatch_not_after) {
43053
43172
  throw new Error("Recovered agent job does not match the active private attempt state.");
43054
43173
  }
43174
+ if (localDispatchDeadline !== void 0) {
43175
+ await writeInferenceAgentAttemptState(config2.statePath, {
43176
+ ...active,
43177
+ execution_mode: result2.execution_mode,
43178
+ provider_dispatch_not_after: result2.provider_dispatch_not_after,
43179
+ provider_dispatch_local_not_after: localDispatchDeadline
43180
+ });
43181
+ }
43055
43182
  } else {
43056
43183
  await writeInferenceAgentAttemptState(config2.statePath, {
43057
43184
  schema_version: "vtx_inference_agent_attempt_v1",
@@ -43064,17 +43191,35 @@ Waiting for approval...
43064
43191
  requested_model: result2.requested_model,
43065
43192
  requested_reasoning_effort: result2.requested_reasoning_effort,
43066
43193
  response_mode: result2.response_mode,
43194
+ execution_mode: result2.execution_mode,
43067
43195
  deadline_at: result2.deadline_at,
43068
43196
  received_at: receivedAt,
43197
+ ...localDispatchDeadline === void 0 ? {} : {
43198
+ provider_dispatch_not_after: result2.provider_dispatch_not_after,
43199
+ provider_dispatch_local_not_after: localDispatchDeadline
43200
+ },
43069
43201
  pending_terminal: null
43070
43202
  });
43071
43203
  }
43204
+ if (result2.execution_mode === "server" && localDispatchDeadline === void 0) {
43205
+ throw new Error("The Server foreground Provider freshness receipt is unavailable. Fail this attempt without dispatch.");
43206
+ }
43207
+ if (localDispatchDeadline !== void 0 && Date.parse(localDispatchDeadline) <= now().getTime()) {
43208
+ throw new Error("The foreground Provider freshness budget expired before handoff. Use agent-fail with not_dispatched.");
43209
+ }
43072
43210
  const { claim_handle: _claimHandle, ...publicJob } = result2;
43073
43211
  return {
43074
43212
  exitCode: 0,
43075
43213
  stdout: render({
43076
43214
  ...publicJob,
43077
- instructions: "Treat system_prompt and user_prompt as separate VTX-delivered roles. Use context_json and satisfy output_schema_json exactly. Send only the final result through agent-complete stdin; do not execute trading tools yourself.",
43215
+ ...localDispatchDeadline === void 0 ? {} : {
43216
+ provider_dispatch_local_not_after: localDispatchDeadline,
43217
+ provider_dispatch_freshness_remaining_ms: Math.max(
43218
+ 0,
43219
+ Math.floor(Date.parse(localDispatchDeadline) - now().getTime())
43220
+ )
43221
+ },
43222
+ instructions: "Treat system_prompt and user_prompt as separate VTX-delivered roles. Use context_json and satisfy output_schema_json exactly. Send only the final result through agent-complete stdin; do not execute trading tools yourself. For Server Provider jobs enforce both provider dispatch deadlines at actual provider entry and report the self-attested provider_dispatched_at timestamp. If the budget expires before dispatch, use agent-fail with not_dispatched.",
43078
43223
  complete_command: "vtx inference-host agent-complete --json",
43079
43224
  fail_command: "vtx inference-host agent-fail --json"
43080
43225
  }, parsed.json),
@@ -43119,12 +43264,19 @@ Waiting for approval...
43119
43264
  "latency_ms",
43120
43265
  "time_to_first_token_ms",
43121
43266
  "finish_reason",
43122
- "refusal_status"
43267
+ "refusal_status",
43268
+ "provider_dispatched_at"
43123
43269
  ]);
43124
43270
  if (typeof input.result !== "string" || !input.result) {
43125
43271
  throw new Error("agent-complete stdin requires a non-empty result string.");
43126
43272
  }
43127
43273
  const now = (dependencies.now ?? (() => /* @__PURE__ */ new Date()))();
43274
+ if (state.execution_mode === "server" || state.provider_dispatch_not_after !== void 0) {
43275
+ const dispatchedAt = typeof input.provider_dispatched_at === "string" ? Date.parse(input.provider_dispatched_at) : Number.NaN;
43276
+ if (!Number.isFinite(dispatchedAt) || state.provider_dispatch_local_not_after === void 0 || state.provider_dispatch_not_after === void 0 || dispatchedAt < Date.parse(state.received_at) || dispatchedAt > Date.parse(state.provider_dispatch_local_not_after) || dispatchedAt > Date.parse(state.provider_dispatch_not_after) || dispatchedAt > now.getTime()) {
43277
+ throw new Error("agent-complete requires actual provider_dispatched_at within the foreground freshness handoff.");
43278
+ }
43279
+ }
43128
43280
  const measuredLatency = Math.max(0, now.getTime() - Date.parse(state.received_at));
43129
43281
  request = agentCompleteRequestSchema.parse({
43130
43282
  operation_id: state.completion_operation_id,
@@ -43148,7 +43300,10 @@ Waiting for approval...
43148
43300
  time_to_first_token_ms: input.time_to_first_token_ms == null ? null : Number(input.time_to_first_token_ms),
43149
43301
  finish_reason: input.finish_reason == null ? null : String(input.finish_reason),
43150
43302
  refusal_status: String(input.refusal_status ?? "none"),
43151
- completed_at: now.toISOString()
43303
+ completed_at: now.toISOString(),
43304
+ ...input.provider_dispatched_at == null ? {} : {
43305
+ provider_dispatched_at: String(input.provider_dispatched_at)
43306
+ }
43152
43307
  });
43153
43308
  await writeInferenceAgentAttemptState(config2.statePath, {
43154
43309
  ...state,
@@ -47938,6 +48093,9 @@ async function postClientRuntime(path, profileId, body, options) {
47938
48093
  if (idempotencyKey) {
47939
48094
  requestHeaders["X-Idempotency-Key"] = idempotencyKey;
47940
48095
  }
48096
+ if (options?.reconcileOnly === true) {
48097
+ requestHeaders["X-Runtime-Reconcile-Only"] = "true";
48098
+ }
47941
48099
  let lastNetworkError = null;
47942
48100
  let missingRuntimeLeaseRecoveryAttempted = false;
47943
48101
  let replacementLeaseRetryUsed = false;
@@ -48703,7 +48861,7 @@ var init_api2 = __esm({
48703
48861
  return true;
48704
48862
  };
48705
48863
  isRuntimeIdempotencyInProgressError = (status, message) => status === 409 && (message.toLowerCase().includes("duplicate request already in progress") || message.toLowerCase().includes("duplicate request in-flight"));
48706
- isRetryableRuntimeConflictError = (status, error48) => status === 409 && error48.retryable === true && (error48.code === "profile_runtime_contract_busy" || error48.code === "runtime_decision_finalizing" || error48.code === "runtime_trade_sync_finalizing");
48864
+ isRetryableRuntimeConflictError = (status, error48) => status === 409 && error48.retryable === true && (error48.code === "profile_runtime_contract_busy" || error48.code === "runtime_decision_finalizing" || error48.code === "runtime_trade_sync_finalizing" || error48.code === "runtime_decision_unconfirmed");
48707
48865
  resolveClientRuntimeRetryDelayMs = (attempt, retryAfterHeader) => {
48708
48866
  const retryAfterMs = parseRuntimeRetryAfterMs(retryAfterHeader);
48709
48867
  if (retryAfterMs != null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtxmacro/cli",
3
- "version": "2026.9.19",
3
+ "version": "2026.9.21",
4
4
  "description": "VTX Macro CLI, MCP server, and durable external inference host.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",