@vtxmacro/cli 2026.9.60 → 2026.9.62

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
@@ -95,11 +95,10 @@ with an uncertain outcome are fenced; same-attempt recovery is not supported.
95
95
  An explicitly capable model from a background service listed above can also
96
96
  control Main in **Agent** mode using the same VTX OAuth grant and its own local
97
97
  adapter-specific vendor credential: ChatGPT, Copilot, or Grok login, or a DeepSeek
98
- or Pi provider API key. VTX assigns the running bot but does not send a VTX-authored prompt or set
99
- the analysis cadence. The assigned runtime keeps a durable Agent thread,
100
- chooses when to wake, requests only the assignment-scoped VTX data it needs (or
101
- none), and submits the normal structured decision for VTX to validate and
102
- execute. Review and Screener remain Provider-only.
98
+ or Pi provider API key. VTX assigns the running bot and supplies canonical Agent instructions. The
99
+ assigned runtime keeps a durable thread, requests assignment-scoped data as
100
+ needed, and chooses whether to submit a structured decision. The model chooses
101
+ its next wake through its adapter. A wake never forces HOLD or trading JSON. Review and Screener remain Provider-only.
103
102
 
104
103
  Before the first Codex login, enable **Device code authorization for Codex** in
105
104
  ChatGPT Security settings. Only enter a device code from a login you initiated,
@@ -167,7 +166,7 @@ vtx inference-host service install --adapter pi --instance pi-1
167
166
 
168
167
  Pi uses the package-owned SDK and exact provider/model identities. The existing
169
168
  Provider / Agent controls apply: Provider receives VTX's prompt and has no
170
- tools; Main Agent keeps an isolated session and only the three VTX tools.
169
+ tools; Main Agent keeps an isolated session and the canonical VTX assignment tools.
171
170
  The initial qualified models use an OpenAI API key; the release embeds VTX's
172
171
  configured exact model IDs and SDK capability mappings. API compatibility alone
173
172
  does not qualify a provider. Ordinary Pi
@@ -319,7 +318,30 @@ schema plus `provenance` with `source: "external_agent"`, a stable
319
318
  `agent_run_id`, and the requested and actual model and reasoning effort. Use
320
319
  `agent-decision-status` after an uncertain submit response. Use
321
320
  `agent-assignment-release` only when intentionally ending the foreground Agent
322
- session; normal cadence is recorded with `agent-assignment-heartbeat`.
321
+ session; `agent-assignment-heartbeat` maintains the assignment lease.
322
+ Heartbeat metadata is not evidence that market data was checked.
323
+
324
+ For recurring checks, ask your harness to run this Agent workflow at the desired
325
+ cadence using its own scheduling facility. On each wake, fetch current VTX data,
326
+ inspect source timestamps, and decide whether to submit trading JSON. A check
327
+ may end without submitting anything, including HOLD. VTX does not configure a
328
+ second scheduler, and saved profile trading interval does not schedule Agent
329
+ turns. Keep `agent-run` open for heartbeats; it does not fetch market data or
330
+ wake or restart your harness.
331
+
332
+ Use a single active turn for the assignment. Long turns, sleep, outages, and
333
+ harness scheduling limits can delay checks; report missed checks and resume
334
+ with fresh data instead of replaying old scheduled work. Continuous operation
335
+ requires the harness and its host to remain available. Record actual successful
336
+ read times and source timestamps to verify cadence and freshness.
337
+
338
+ `prompt.variables` discovers every canonical trading prompt variable;
339
+ `prompt.context` reads selected names or all names for one owned profile.
340
+ Disabled indicators are available request-locally without settings changes.
341
+ Values share provider calculations, format instructions and unavailable
342
+ semantics, including future variables. Full ordinary Insights MCP access and
343
+ external tools remain separate authorized harness connections; the inference
344
+ grant does not expand into account-wide mutation permission.
323
345
 
324
346
  ## Exo foreground trading inference
325
347
 
@@ -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.60",
19
+ package_version: "2026.9.62",
20
20
  codex_package_name: "@openai/codex",
21
21
  codex_version: "0.155.0",
22
22
  copilot_sdk_package_name: "@github/copilot-sdk",
@@ -199,6 +199,9 @@ var runtime_policy_generated_default = {
199
199
  browser_presence_heartbeat_interval_ms: 3e4,
200
200
  host_liveness_heartbeat_interval_ms: 3e4,
201
201
  host_liveness_recovery_nudge_ttl_ms: 1e4
202
+ },
203
+ observability: {
204
+ deployment_reload_stall_warning_ms: 15e3
202
205
  }
203
206
  },
204
207
  server_runtime: {
@@ -344,6 +347,12 @@ import { constants } from "node:fs";
344
347
  import { lstat, mkdir, open, readFile, realpath, rename, rm } from "node:fs/promises";
345
348
  import { homedir } from "node:os";
346
349
  import { dirname, isAbsolute, join, relative, resolve, win32 as windowsPath } from "node:path";
350
+ var InferenceHostProcessLockBusyError = class extends Error {
351
+ constructor() {
352
+ super("Another inference host process already owns this local host.");
353
+ this.name = "InferenceHostProcessLockBusyError";
354
+ }
355
+ };
347
356
  var MAX_INFERENCE_PRIVATE_FILE_BYTES = 16 * 1024 * 1024;
348
357
  var WINDOWS_PRIVATE_ACL_BROKER_SCRIPT = `$ErrorActionPreference='Stop'
349
358
  $ProgressPreference='SilentlyContinue'
@@ -1056,7 +1065,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
1056
1065
  } catch (error) {
1057
1066
  if (error.code !== "EEXIST") throw error;
1058
1067
  if (acquisition > 0) {
1059
- throw new Error("Another inference host process already owns this local host.");
1068
+ throw new InferenceHostProcessLockBusyError();
1060
1069
  }
1061
1070
  let before;
1062
1071
  try {
@@ -1101,14 +1110,14 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
1101
1110
  } catch (error2) {
1102
1111
  if (error2.code === "ENOENT") continue;
1103
1112
  if (Date.now() - before.mtimeMs < 1e4) {
1104
- throw new Error("Another inference host process already owns this local host.");
1113
+ throw new InferenceHostProcessLockBusyError();
1105
1114
  }
1106
1115
  await reclaimPublicationResidue();
1107
1116
  continue;
1108
1117
  }
1109
1118
  if (staleOwner.schema_version !== 2 || !Number.isSafeInteger(staleOwner.pid) || Number(staleOwner.pid) < 1 || typeof staleOwner.owner_token !== "string" || !staleOwner.owner_token || typeof staleOwner.process_identity !== "string" || !staleOwner.process_identity || typeof staleOwner.boot_identity !== "string" || !staleOwner.boot_identity) {
1110
1119
  if (Date.now() - before.mtimeMs < 1e4) {
1111
- throw new Error("Another inference host process already owns this local host.");
1120
+ throw new InferenceHostProcessLockBusyError();
1112
1121
  }
1113
1122
  await reclaimPublicationResidue();
1114
1123
  continue;
@@ -1130,7 +1139,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
1130
1139
  observedAtMs: Date.now()
1131
1140
  });
1132
1141
  if (inferenceProcessIdentitiesMatch(staleOwner.process_identity, observedIdentity)) {
1133
- throw new Error("Another inference host process already owns this local host.");
1142
+ throw new InferenceHostProcessLockBusyError();
1134
1143
  }
1135
1144
  }
1136
1145
  let current;
@@ -82,6 +82,9 @@ var runtime_policy_generated_default = {
82
82
  browser_presence_heartbeat_interval_ms: 3e4,
83
83
  host_liveness_heartbeat_interval_ms: 3e4,
84
84
  host_liveness_recovery_nudge_ttl_ms: 1e4
85
+ },
86
+ observability: {
87
+ deployment_reload_stall_warning_ms: 15e3
85
88
  }
86
89
  },
87
90
  server_runtime: {
@@ -229,6 +232,12 @@ import { constants } from "node:fs";
229
232
  import { lstat, mkdir, open, readFile, realpath, rename, rm } from "node:fs/promises";
230
233
  import { homedir } from "node:os";
231
234
  import { dirname, isAbsolute, join, relative, resolve, win32 as windowsPath } from "node:path";
235
+ var InferenceHostProcessLockBusyError = class extends Error {
236
+ constructor() {
237
+ super("Another inference host process already owns this local host.");
238
+ this.name = "InferenceHostProcessLockBusyError";
239
+ }
240
+ };
232
241
  var MAX_INFERENCE_PRIVATE_FILE_BYTES = 16 * 1024 * 1024;
233
242
  var WINDOWS_PRIVATE_ACL_BROKER_SCRIPT = `$ErrorActionPreference='Stop'
234
243
  $ProgressPreference='SilentlyContinue'
@@ -941,7 +950,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
941
950
  } catch (error) {
942
951
  if (error.code !== "EEXIST") throw error;
943
952
  if (acquisition > 0) {
944
- throw new Error("Another inference host process already owns this local host.");
953
+ throw new InferenceHostProcessLockBusyError();
945
954
  }
946
955
  let before;
947
956
  try {
@@ -986,14 +995,14 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
986
995
  } catch (error2) {
987
996
  if (error2.code === "ENOENT") continue;
988
997
  if (Date.now() - before.mtimeMs < 1e4) {
989
- throw new Error("Another inference host process already owns this local host.");
998
+ throw new InferenceHostProcessLockBusyError();
990
999
  }
991
1000
  await reclaimPublicationResidue();
992
1001
  continue;
993
1002
  }
994
1003
  if (staleOwner.schema_version !== 2 || !Number.isSafeInteger(staleOwner.pid) || Number(staleOwner.pid) < 1 || typeof staleOwner.owner_token !== "string" || !staleOwner.owner_token || typeof staleOwner.process_identity !== "string" || !staleOwner.process_identity || typeof staleOwner.boot_identity !== "string" || !staleOwner.boot_identity) {
995
1004
  if (Date.now() - before.mtimeMs < 1e4) {
996
- throw new Error("Another inference host process already owns this local host.");
1005
+ throw new InferenceHostProcessLockBusyError();
997
1006
  }
998
1007
  await reclaimPublicationResidue();
999
1008
  continue;
@@ -1015,7 +1024,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
1015
1024
  observedAtMs: Date.now()
1016
1025
  });
1017
1026
  if (inferenceProcessIdentitiesMatch(staleOwner.process_identity, observedIdentity)) {
1018
- throw new Error("Another inference host process already owns this local host.");
1027
+ throw new InferenceHostProcessLockBusyError();
1019
1028
  }
1020
1029
  }
1021
1030
  let current;
package/bin/vtx.js CHANGED
@@ -77,7 +77,7 @@ var init_agent_cli_release = __esm({
77
77
  "agent-cli-release.json"() {
78
78
  agent_cli_release_default = {
79
79
  package_name: "@vtxmacro/cli",
80
- package_version: "2026.9.60",
80
+ package_version: "2026.9.62",
81
81
  codex_package_name: "@openai/codex",
82
82
  codex_version: "0.155.0",
83
83
  copilot_sdk_package_name: "@github/copilot-sdk",
@@ -18033,7 +18033,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
18033
18033
  } catch (error48) {
18034
18034
  if (error48.code !== "EEXIST") throw error48;
18035
18035
  if (acquisition > 0) {
18036
- throw new Error("Another inference host process already owns this local host.");
18036
+ throw new InferenceHostProcessLockBusyError();
18037
18037
  }
18038
18038
  let before;
18039
18039
  try {
@@ -18078,14 +18078,14 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
18078
18078
  } catch (error49) {
18079
18079
  if (error49.code === "ENOENT") continue;
18080
18080
  if (Date.now() - before.mtimeMs < 1e4) {
18081
- throw new Error("Another inference host process already owns this local host.");
18081
+ throw new InferenceHostProcessLockBusyError();
18082
18082
  }
18083
18083
  await reclaimPublicationResidue();
18084
18084
  continue;
18085
18085
  }
18086
18086
  if (staleOwner.schema_version !== 2 || !Number.isSafeInteger(staleOwner.pid) || Number(staleOwner.pid) < 1 || typeof staleOwner.owner_token !== "string" || !staleOwner.owner_token || typeof staleOwner.process_identity !== "string" || !staleOwner.process_identity || typeof staleOwner.boot_identity !== "string" || !staleOwner.boot_identity) {
18087
18087
  if (Date.now() - before.mtimeMs < 1e4) {
18088
- throw new Error("Another inference host process already owns this local host.");
18088
+ throw new InferenceHostProcessLockBusyError();
18089
18089
  }
18090
18090
  await reclaimPublicationResidue();
18091
18091
  continue;
@@ -18107,7 +18107,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
18107
18107
  observedAtMs: Date.now()
18108
18108
  });
18109
18109
  if (inferenceProcessIdentitiesMatch(staleOwner.process_identity, observedIdentity)) {
18110
- throw new Error("Another inference host process already owns this local host.");
18110
+ throw new InferenceHostProcessLockBusyError();
18111
18111
  }
18112
18112
  }
18113
18113
  let current;
@@ -18174,7 +18174,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
18174
18174
  }
18175
18175
  };
18176
18176
  }
18177
- 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;
18177
+ var loadInferenceReceiptDurabilityTimeoutMs, loadInferenceAgentDataRequestTimeoutMs, loadInferenceAgentCommandLockPolicy, InferenceHostProcessLockBusyError, 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;
18178
18178
  var init_config = __esm({
18179
18179
  "lib/inference-host/config.ts"() {
18180
18180
  "use strict";
@@ -18211,6 +18211,29 @@ var init_config = __esm({
18211
18211
  }
18212
18212
  return Number(configured);
18213
18213
  };
18214
+ loadInferenceAgentCommandLockPolicy = async () => {
18215
+ let waitTimeoutMs;
18216
+ let retryIntervalMs;
18217
+ if (true) {
18218
+ waitTimeoutMs = 3e4;
18219
+ retryIntervalMs = 50;
18220
+ } else {
18221
+ const config2 = parse4(await readFile(resolve(dirname(fileURLToPath(import.meta.url)), "../../../config.toml"), "utf8"));
18222
+ const inference = config2.external_inference;
18223
+ waitTimeoutMs = inference?.agent_command_lock_wait_timeout_milliseconds;
18224
+ retryIntervalMs = inference?.agent_command_lock_retry_interval_milliseconds;
18225
+ }
18226
+ if (!Number.isSafeInteger(waitTimeoutMs) || Number(waitTimeoutMs) < 1 || !Number.isSafeInteger(retryIntervalMs) || Number(retryIntervalMs) < 1 || Number(retryIntervalMs) > Number(waitTimeoutMs)) {
18227
+ throw new Error("Inference Agent command lock policy is missing or invalid.");
18228
+ }
18229
+ return { waitTimeoutMs: Number(waitTimeoutMs), retryIntervalMs: Number(retryIntervalMs) };
18230
+ };
18231
+ InferenceHostProcessLockBusyError = class extends Error {
18232
+ constructor() {
18233
+ super("Another inference host process already owns this local host.");
18234
+ this.name = "InferenceHostProcessLockBusyError";
18235
+ }
18236
+ };
18214
18237
  INFERENCE_CREDENTIAL_NAMESPACE = "vtxmacro-insights-inference";
18215
18238
  MAX_INFERENCE_PRIVATE_FILE_BYTES = 16 * 1024 * 1024;
18216
18239
  WINDOWS_PRIVATE_ACL_BROKER_SCRIPT = `$ErrorActionPreference='Stop'
@@ -20540,6 +20563,9 @@ var init_runtime_policy_generated = __esm({
20540
20563
  browser_presence_heartbeat_interval_ms: 3e4,
20541
20564
  host_liveness_heartbeat_interval_ms: 3e4,
20542
20565
  host_liveness_recovery_nudge_ttl_ms: 1e4
20566
+ },
20567
+ observability: {
20568
+ deployment_reload_stall_warning_ms: 15e3
20543
20569
  }
20544
20570
  },
20545
20571
  server_runtime: {
@@ -21590,7 +21616,7 @@ var init_mcp_client = __esm({
21590
21616
  const hasPublicToolErrorMarker = hasStructuredPublicToolErrorMarker || errorText.includes(PUBLIC_TOOL_ERROR_PREFIX);
21591
21617
  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"));
21592
21618
  const hostNotClaimable = name === "inference.job.claim" && publicToolError?.failure_code === "host_not_claimable" && publicToolError.phase === "admission" && publicToolError.retryable === true && publicToolError.terminal_before_execution === true;
21593
- 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(
21619
+ const definitivelyNotApplied = (name === "inference.agent.decision.submit" || name === "inference.agent.data.call") && publicToolError?.phase === "validation" && publicToolError.retryable === false && publicToolError.terminal_before_execution === true && (name === "inference.agent.decision.submit" && 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(
21594
21620
  "External inference claim request was not applied before its generation became stale"
21595
21621
  ) || errorText.includes("External inference host advertisement is expired or superseded")) || name === "inference.job.complete" && completionEvidenceExpired;
21596
21622
  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"));
@@ -30935,8 +30961,10 @@ var init_agent_state = __esm({
30935
30961
  "data_contract",
30936
30962
  "minimum_wake_seconds",
30937
30963
  "maximum_wake_seconds",
30938
- "lease_expires_at"
30964
+ "lease_expires_at",
30965
+ ..."system_prompt" in assignment ? ["system_prompt"] : []
30939
30966
  ]) || typeof assignment.assignment_id !== "string" || !assignment.assignment_id || !Number.isSafeInteger(assignment.assignment_generation) || Number(assignment.assignment_generation) < 1 || typeof assignment.model_id !== "string" || !assignment.model_id || typeof assignment.reasoning_effort !== "string" || !assignment.reasoning_effort || !["trader", "assistant"].includes(String(assignment.bot_mode)) || !["server", "client"].includes(String(assignment.execution_mode)) || !Array.isArray(assignment.allowed_symbols) || assignment.allowed_symbols.some((symbol2) => typeof symbol2 !== "string" || !symbol2) || !assignment.output_schema || typeof assignment.output_schema !== "object" || Array.isArray(assignment.output_schema) || !Array.isArray(assignment.data_contract) || assignment.data_contract.length === 0 || !Number.isSafeInteger(assignment.minimum_wake_seconds) || Number(assignment.minimum_wake_seconds) < 1 || !Number.isSafeInteger(assignment.maximum_wake_seconds) || Number(assignment.maximum_wake_seconds) < Number(assignment.minimum_wake_seconds) || !isIsoTimestamp(assignment.lease_expires_at)) throw new Error(message);
30967
+ if ("system_prompt" in assignment && typeof assignment.system_prompt !== "string") throw new Error(message);
30940
30968
  const ids = assignment.data_contract.map((value2) => {
30941
30969
  const descriptor = assertPlainObject(value2, message);
30942
30970
  if (!hasExactKeys(descriptor, [
@@ -34860,19 +34888,33 @@ var init_runner = __esm({
34860
34888
  if (call.tool === "vtx_get_data") {
34861
34889
  const capability = typeof call.arguments.capability === "string" ? call.arguments.capability.trim() : "";
34862
34890
  const args = call.arguments.arguments;
34863
- if (!capability || !assignment.data_contract.some((descriptor) => descriptor.id === capability) || !args || typeof args !== "object" || Array.isArray(args)) {
34891
+ const descriptor = assignment.data_contract.find((entry) => entry.id === capability);
34892
+ if (!capability || !descriptor || !args || typeof args !== "object" || Array.isArray(args)) {
34864
34893
  return { success: false, value: { error: "invalid_data_request" } };
34865
34894
  }
34866
- const value = await this.options.controlClient.dataCall({
34867
- operation_id: randomUUID(),
34868
- host_id: this.options.hostId,
34869
- assignment_id: assignment.assignment_id,
34870
- assignment_generation: assignment.assignment_generation,
34871
- capability,
34872
- arguments: args,
34873
- requested_at: nowIso()
34874
- }, { signal: turnAbort.signal, timeoutMs: dataRequestTimeoutMs, deadlineAtMs });
34875
- return { success: true, value };
34895
+ try {
34896
+ const value = await this.options.controlClient.dataCall({
34897
+ operation_id: randomUUID(),
34898
+ host_id: this.options.hostId,
34899
+ assignment_id: assignment.assignment_id,
34900
+ assignment_generation: assignment.assignment_generation,
34901
+ capability,
34902
+ arguments: args,
34903
+ requested_at: nowIso()
34904
+ }, { signal: turnAbort.signal, timeoutMs: dataRequestTimeoutMs, deadlineAtMs });
34905
+ turnAbort.signal.throwIfAborted();
34906
+ return { success: true, value };
34907
+ } catch (error48) {
34908
+ turnAbort.signal.throwIfAborted();
34909
+ if (error48 instanceof ExternalInferenceMcpError && error48.code === "tool_rejected" && error48.serverFailureCode === "invalid_arguments" && error48.definitivelyNotApplied) {
34910
+ return { success: false, value: {
34911
+ error: "invalid_data_arguments",
34912
+ capability,
34913
+ input_schema: descriptor.input_schema
34914
+ } };
34915
+ }
34916
+ throw error48;
34917
+ }
34876
34918
  }
34877
34919
  if (call.tool === "vtx_submit_decision") {
34878
34920
  const candidate = call.arguments.candidate;
@@ -42610,6 +42652,9 @@ var init_runtime_policy_generated2 = __esm({
42610
42652
  browser_presence_heartbeat_interval_ms: 3e4,
42611
42653
  host_liveness_heartbeat_interval_ms: 3e4,
42612
42654
  host_liveness_recovery_nudge_ttl_ms: 1e4
42655
+ },
42656
+ observability: {
42657
+ deployment_reload_stall_warning_ms: 15e3
42613
42658
  }
42614
42659
  },
42615
42660
  server_runtime: {
@@ -44372,6 +44417,7 @@ __export(cli_exports, {
44372
44417
  runInferenceHostCli: () => runInferenceHostCli
44373
44418
  });
44374
44419
  import { createHash as createHash12, randomUUID as randomUUID11 } from "node:crypto";
44420
+ import { setTimeout as delay } from "node:timers/promises";
44375
44421
  import { spawn as spawn11 } from "node:child_process";
44376
44422
  import { lstat as lstat9, realpath as realpath8, rm as rm13 } from "node:fs/promises";
44377
44423
  import { hostname as osHostname } from "node:os";
@@ -44426,7 +44472,8 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
44426
44472
  if (parsed.command === "agent-connect") {
44427
44473
  return await withAgentCommandLock(
44428
44474
  config2,
44429
- async () => await agentConnect(config2, parsed, dependencies, warnings)
44475
+ async () => await agentConnect(config2, parsed, dependencies, warnings),
44476
+ dependencies
44430
44477
  );
44431
44478
  }
44432
44479
  if (parsed.command === "agent-run") {
@@ -44435,55 +44482,56 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
44435
44482
  if (parsed.command === "agent-next") {
44436
44483
  return await withAgentCommandLock(
44437
44484
  config2,
44438
- async () => await agentNext(config2, parsed, dependencies, warnings)
44485
+ async () => await agentNext(config2, parsed, dependencies, warnings),
44486
+ dependencies
44439
44487
  );
44440
44488
  }
44441
44489
  if (parsed.command === "agent-complete") {
44442
44490
  return await withAgentCommandLock(
44443
44491
  config2,
44444
- async () => await agentComplete(config2, parsed, dependencies, warnings)
44492
+ async () => await agentComplete(config2, parsed, dependencies, warnings),
44493
+ dependencies
44445
44494
  );
44446
44495
  }
44447
44496
  if (parsed.command === "agent-fail") {
44448
44497
  return await withAgentCommandLock(
44449
44498
  config2,
44450
- async () => await agentFail(config2, parsed, dependencies, warnings)
44499
+ async () => await agentFail(config2, parsed, dependencies, warnings),
44500
+ dependencies
44451
44501
  );
44452
44502
  }
44453
44503
  if (parsed.command === "agent-assignment-next") {
44454
- return await withAgentCommandLock(
44455
- config2,
44456
- async () => await foregroundAssignmentNext(config2, parsed, dependencies, warnings)
44457
- );
44504
+ return await foregroundAssignmentNext(config2, parsed, dependencies, warnings);
44458
44505
  }
44459
44506
  if (parsed.command === "agent-assignment-heartbeat") {
44460
44507
  return await withAgentCommandLock(
44461
44508
  config2,
44462
- async () => await foregroundAssignmentHeartbeat(config2, parsed, dependencies, warnings)
44509
+ async () => await foregroundAssignmentHeartbeat(config2, parsed, dependencies, warnings),
44510
+ dependencies
44463
44511
  );
44464
44512
  }
44465
44513
  if (parsed.command === "agent-data-call") {
44466
- return await withAgentCommandLock(
44467
- config2,
44468
- async () => await foregroundDataCall(config2, parsed, dependencies, warnings)
44469
- );
44514
+ return await foregroundDataCall(config2, parsed, dependencies, warnings);
44470
44515
  }
44471
44516
  if (parsed.command === "agent-decision-submit") {
44472
44517
  return await withAgentCommandLock(
44473
44518
  config2,
44474
- async () => await foregroundDecisionSubmit(config2, parsed, dependencies, warnings)
44519
+ async () => await foregroundDecisionSubmit(config2, parsed, dependencies, warnings),
44520
+ dependencies
44475
44521
  );
44476
44522
  }
44477
44523
  if (parsed.command === "agent-decision-status") {
44478
44524
  return await withAgentCommandLock(
44479
44525
  config2,
44480
- async () => await foregroundDecisionStatus(config2, parsed, dependencies, warnings)
44526
+ async () => await foregroundDecisionStatus(config2, parsed, dependencies, warnings),
44527
+ dependencies
44481
44528
  );
44482
44529
  }
44483
44530
  if (parsed.command === "agent-assignment-release") {
44484
44531
  return await withAgentCommandLock(
44485
44532
  config2,
44486
- async () => await foregroundAssignmentRelease(config2, parsed, dependencies, warnings)
44533
+ async () => await foregroundAssignmentRelease(config2, parsed, dependencies, warnings),
44534
+ dependencies
44487
44535
  );
44488
44536
  }
44489
44537
  if (parsed.command === "service") {
@@ -46252,73 +46300,85 @@ Waiting for approval...
46252
46300
  execution_mode: result2.execution_mode,
46253
46301
  allowed_symbols: result2.allowed_symbols,
46254
46302
  data_contract: result2.data_contract,
46303
+ ...result2.system_prompt ? { system_prompt: result2.system_prompt } : {},
46255
46304
  output_schema: result2.output_schema,
46256
46305
  minimum_wake_seconds: result2.minimum_wake_seconds,
46257
46306
  maximum_wake_seconds: result2.maximum_wake_seconds,
46258
46307
  lease_expires_at: result2.lease_expires_at
46259
46308
  });
46260
46309
  foregroundAssignmentNext = async (config2, parsed, dependencies, warnings) => {
46310
+ if (await readCodexAgentRuntimeState(config2.statePath)) {
46311
+ throw new Error("Recover or release the managed Agent runtime before switching to foreground Agent control.");
46312
+ }
46261
46313
  const session = await agentSession(config2, dependencies, warnings);
46262
46314
  const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
46263
46315
  const sleep4 = dependencies.sleep ?? (async (milliseconds) => {
46264
46316
  await new Promise((resolve13) => setTimeout(resolve13, milliseconds));
46265
46317
  });
46266
46318
  const stopAt = now().getTime() + parsed.waitSeconds * 1e3;
46267
- let state = await readInferenceForegroundAgentControlState(config2.statePath) ?? foregroundAgentControlState(session.localState.host_id, now().toISOString());
46268
- if (state.host_id !== session.localState.host_id) {
46269
- throw new Error("Foreground Agent recovery state belongs to another inference host.");
46270
- }
46271
- if (state.pending_decision) {
46272
- throw new Error("Resolve the pending Agent decision before claiming another assignment.");
46273
- }
46274
46319
  while (true) {
46275
- if (!state.pending_next) {
46276
- const requestedAt = now().toISOString();
46277
- state = {
46278
- ...state,
46279
- pending_next: {
46280
- operation_id: agentOperationId("agent-assignment-next"),
46281
- requested_at: requestedAt
46282
- },
46283
- updated_at: requestedAt
46284
- };
46285
- await writeInferenceForegroundAgentControlState(config2.statePath, state);
46286
- }
46287
- const pending3 = state.pending_next;
46288
- let result2;
46289
- try {
46290
- result2 = await session.client.callTool("inference.agent.assignment.next", {
46291
- operation_id: pending3.operation_id,
46292
- host_id: session.localState.host_id,
46293
- requested_at: pending3.requested_at,
46294
- contract_version: "agent_assignment_v2",
46295
- ...state.assignment ? {
46296
- assignment_id: state.assignment.assignment_id,
46297
- assignment_generation: state.assignment.assignment_generation
46298
- } : {}
46299
- });
46300
- } catch (error48) {
46301
- if (error48 && typeof error48 === "object" && error48.definitivelyNotApplied === true) {
46320
+ const result2 = await withAgentCommandLock(config2, async () => {
46321
+ let state = await readInferenceForegroundAgentControlState(config2.statePath) ?? foregroundAgentControlState(session.localState.host_id, now().toISOString());
46322
+ if (state.host_id !== session.localState.host_id) {
46323
+ throw new Error("Foreground Agent recovery state belongs to another inference host.");
46324
+ }
46325
+ if (state.pending_decision) {
46326
+ throw new Error("Resolve the pending Agent decision before claiming another assignment.");
46327
+ }
46328
+ if (!state.pending_next) {
46329
+ const requestedAt = now().toISOString();
46330
+ state = {
46331
+ ...state,
46332
+ pending_next: {
46333
+ operation_id: agentOperationId("agent-assignment-next"),
46334
+ requested_at: requestedAt
46335
+ },
46336
+ updated_at: requestedAt
46337
+ };
46338
+ await writeInferenceForegroundAgentControlState(config2.statePath, state);
46339
+ }
46340
+ const pending3 = state.pending_next;
46341
+ let result3;
46342
+ try {
46343
+ result3 = await session.client.callTool("inference.agent.assignment.next", {
46344
+ operation_id: pending3.operation_id,
46345
+ host_id: session.localState.host_id,
46346
+ requested_at: pending3.requested_at,
46347
+ contract_version: "agent_assignment_v3",
46348
+ ...state.assignment ? {
46349
+ assignment_id: state.assignment.assignment_id,
46350
+ assignment_generation: state.assignment.assignment_generation
46351
+ } : {}
46352
+ });
46353
+ } catch (error48) {
46354
+ if (error48 && typeof error48 === "object" && error48.definitivelyNotApplied === true) {
46355
+ state = { ...state, pending_next: null, updated_at: now().toISOString() };
46356
+ await writeInferenceForegroundAgentControlState(config2.statePath, state);
46357
+ }
46358
+ throw error48;
46359
+ }
46360
+ if (result3.claim_state === "claimed") {
46361
+ const assignment = assignmentFromClaim(result3);
46362
+ state = {
46363
+ ...state,
46364
+ assignment,
46365
+ pending_next: null,
46366
+ next_wake_at: null,
46367
+ updated_at: now().toISOString()
46368
+ };
46369
+ await writeInferenceForegroundAgentControlState(config2.statePath, state);
46370
+ } else {
46302
46371
  state = { ...state, pending_next: null, updated_at: now().toISOString() };
46303
46372
  await writeInferenceForegroundAgentControlState(config2.statePath, state);
46304
46373
  }
46305
- throw error48;
46306
- }
46374
+ return result3;
46375
+ }, dependencies);
46307
46376
  if (result2.claim_state === "claimed") {
46308
- const assignment = assignmentFromClaim(result2);
46309
- state = {
46310
- ...state,
46311
- assignment,
46312
- pending_next: null,
46313
- next_wake_at: null,
46314
- updated_at: now().toISOString()
46315
- };
46316
- await writeInferenceForegroundAgentControlState(config2.statePath, state);
46317
46377
  return {
46318
46378
  exitCode: 0,
46319
46379
  stdout: render({
46320
46380
  ...result2,
46321
- instructions: "VTX supplied no trading prompt or prepared context. Choose your own cadence; use agent-data-call zero or more times, submit the exact output_schema through agent-decision-submit, then record the next wake with agent-assignment-heartbeat. Keep agent-run open for liveness.",
46381
+ instructions: "Use your harness scheduler for the requested cadence and keep agent-run open for liveness. Use agent-data-call for canonical VTX data and your authorized native Insights/external tools. Trading JSON is optional; submit a decision only when you choose, using the exact output_schema. The keeper does not schedule or restart your harness.",
46322
46382
  data_command: "vtx inference-host agent-data-call --json",
46323
46383
  decision_command: "vtx inference-host agent-decision-submit --json",
46324
46384
  decision_input: {
@@ -46339,8 +46399,6 @@ Waiting for approval...
46339
46399
  ` : ""
46340
46400
  };
46341
46401
  }
46342
- state = { ...state, pending_next: null, updated_at: now().toISOString() };
46343
- await writeInferenceForegroundAgentControlState(config2.statePath, state);
46344
46402
  const remaining = stopAt - now().getTime();
46345
46403
  if (remaining <= 0 || parsed.waitSeconds === 0) {
46346
46404
  return {
@@ -46392,7 +46450,11 @@ Waiting for approval...
46392
46450
  };
46393
46451
  foregroundDataCall = async (config2, parsed, dependencies, warnings) => {
46394
46452
  const session = await agentSession(config2, dependencies, warnings);
46395
- const state = await requireForegroundAgentState(config2, session.localState.host_id);
46453
+ const state = await withAgentCommandLock(
46454
+ config2,
46455
+ async () => requireForegroundAgentState(config2, session.localState.host_id),
46456
+ dependencies
46457
+ );
46396
46458
  const input = await parseAgentStdin(dependencies, ["capability", "arguments"]);
46397
46459
  const capability = typeof input.capability === "string" ? input.capability.trim() : "";
46398
46460
  if (!capability || !state.assignment.data_contract.some((item) => item.id === capability)) {
@@ -46401,6 +46463,7 @@ Waiting for approval...
46401
46463
  if (!input.arguments || typeof input.arguments !== "object" || Array.isArray(input.arguments)) {
46402
46464
  throw new Error("Agent data arguments must be one JSON object.");
46403
46465
  }
46466
+ const timeoutMs = await loadInferenceAgentDataRequestTimeoutMs();
46404
46467
  const result2 = await session.client.callTool("inference.agent.data.call", {
46405
46468
  operation_id: agentOperationId("agent-data-call"),
46406
46469
  host_id: session.localState.host_id,
@@ -46409,7 +46472,7 @@ Waiting for approval...
46409
46472
  capability,
46410
46473
  arguments: input.arguments,
46411
46474
  requested_at: (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString()
46412
- });
46475
+ }, { timeoutMs, deadlineAtMs: Date.now() + timeoutMs });
46413
46476
  return {
46414
46477
  exitCode: 0,
46415
46478
  stdout: render(result2, parsed.json),
@@ -46645,6 +46708,9 @@ Waiting for approval...
46645
46708
  let assignmentHeartbeatCount = 0;
46646
46709
  try {
46647
46710
  keeperLock = await acquireInferenceHostProcessLock(foregroundHostLockPath(config2));
46711
+ if (await readCodexAgentRuntimeState(config2.statePath)) {
46712
+ throw new Error("Recover or release the managed Agent runtime before running a foreground keeper.");
46713
+ }
46648
46714
  const store = configuredCredentialStore(config2, dependencies, (message) => {
46649
46715
  warnings.push(message);
46650
46716
  });
@@ -47101,8 +47167,30 @@ Waiting for approval...
47101
47167
  ` : ""
47102
47168
  };
47103
47169
  };
47104
- withAgentCommandLock = async (config2, operation) => {
47105
- const lock2 = await acquireInferenceHostProcessLock(config2.processLockPath);
47170
+ withAgentCommandLock = async (config2, operation, dependencies = {}) => {
47171
+ const policy2 = await loadInferenceAgentCommandLockPolicy();
47172
+ const cancellation = lifecycleCancellation(dependencies);
47173
+ const deadline = Date.now() + policy2.waitTimeoutMs;
47174
+ let lock2 = null;
47175
+ try {
47176
+ while (!lock2) {
47177
+ cancellation.signal.throwIfAborted();
47178
+ try {
47179
+ lock2 = await acquireInferenceHostProcessLock(config2.processLockPath);
47180
+ } catch (error48) {
47181
+ if (!(error48 instanceof InferenceHostProcessLockBusyError)) throw error48;
47182
+ const remaining = deadline - Date.now();
47183
+ if (remaining <= 0) throw new Error("Timed out waiting for the inference host command lock.");
47184
+ await delay(Math.min(policy2.retryIntervalMs, remaining), void 0, { signal: cancellation.signal });
47185
+ }
47186
+ }
47187
+ if (cancellation.signal.aborted) {
47188
+ await lock2.release();
47189
+ cancellation.signal.throwIfAborted();
47190
+ }
47191
+ } finally {
47192
+ cancellation.unregister();
47193
+ }
47106
47194
  try {
47107
47195
  return await operation();
47108
47196
  } finally {
@@ -48519,7 +48607,7 @@ var init_headless_runtime = __esm({
48519
48607
  });
48520
48608
 
48521
48609
  // lib/runtime/hyperliquid-market-symbol.ts
48522
- var configuredCaseSensitiveSymbols, normalizeCaseSensitiveSymbols, configureHyperliquidMarketSymbolCasing, canonicalBaseSymbol, normalizeHyperliquidMarketSymbol, getHyperliquidMarketDex;
48610
+ var configuredCaseSensitiveSymbols, isHyperliquidSpotSymbol, normalizeCaseSensitiveSymbols, configureHyperliquidMarketSymbolCasing, canonicalBaseSymbol, normalizeHyperliquidMarketSymbol, getHyperliquidMarketDex;
48523
48611
  var init_hyperliquid_market_symbol = __esm({
48524
48612
  "lib/runtime/hyperliquid-market-symbol.ts"() {
48525
48613
  "use strict";
@@ -48527,6 +48615,10 @@ var init_hyperliquid_market_symbol = __esm({
48527
48615
  init_define_VTX_GROK_POLICY();
48528
48616
  init_define_VTX_PI_MODEL_POLICY();
48529
48617
  configuredCaseSensitiveSymbols = [];
48618
+ isHyperliquidSpotSymbol = (value) => {
48619
+ const symbol2 = typeof value === "string" ? value.trim() : "";
48620
+ return symbol2.startsWith("@") || symbol2.includes("/");
48621
+ };
48530
48622
  normalizeCaseSensitiveSymbols = (symbols) => {
48531
48623
  if (!Array.isArray(symbols)) return [];
48532
48624
  const out = [];
@@ -52373,7 +52465,7 @@ async function postClientRuntime(path, profileId, body, options) {
52373
52465
  const resolvedSchedulerInstanceId = String(
52374
52466
  options?.schedulerInstanceId ?? requestContext.schedulerInstanceId ?? ""
52375
52467
  ).trim() || null;
52376
- const persistedRuntimeLease = getPersistedClientRuntimeServerLease(numericProfileId);
52468
+ const persistedRuntimeLease = options?.omitRuntimeLeaseToken === true ? null : getPersistedClientRuntimeServerLease(numericProfileId);
52377
52469
  if (resolvedRuntimeLeaseToken && persistedRuntimeLease?.schedulerInstanceId && !resolvedSchedulerInstanceId) {
52378
52470
  resolvedRuntimeLeaseToken = void 0;
52379
52471
  }
@@ -52907,6 +52999,17 @@ var init_api2 = __esm({
52907
52999
  if (code) {
52908
53000
  error48.code = code;
52909
53001
  }
53002
+ if (response.status === 409 && code === "snapshot_stale") {
53003
+ for (const [field, property] of [
53004
+ ["snapshot_age_seconds", "runtimeSnapshotAgeSeconds"],
53005
+ ["snapshot_max_age_seconds", "runtimeSnapshotMaxAgeSeconds"]
53006
+ ]) {
53007
+ const value = nestedDetail?.[field];
53008
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
53009
+ Object.assign(error48, { [property]: value });
53010
+ }
53011
+ }
53012
+ }
52910
53013
  const retryable = payload.retryable ?? nestedDetail?.retryable;
52911
53014
  if (typeof retryable === "boolean") {
52912
53015
  error48.retryable = retryable;
@@ -54478,8 +54581,8 @@ function unpercent(value) {
54478
54581
  return String.fromCharCode(parseInt(code, 16));
54479
54582
  }));
54480
54583
  }
54481
- function wait2(delay2) {
54482
- return new Promise((resolve13) => setTimeout(resolve13, delay2));
54584
+ function wait2(delay3) {
54585
+ return new Promise((resolve13) => setTimeout(resolve13, delay3));
54483
54586
  }
54484
54587
  var MAX_ATTEMPTS, SLOT_INTERVAL, defaultGetUrlFunc, reData, reIpfs, locked, Gateways, fetchSignals, FetchCancelSignal, FetchRequest, FetchResponse;
54485
54588
  var init_fetch = __esm({
@@ -54831,7 +54934,7 @@ var init_fetch = __esm({
54831
54934
  this.#throttle.maxAttempts = params.maxAttempts;
54832
54935
  }
54833
54936
  }
54834
- async #send(attempt, expires, delay2, _request, _response) {
54937
+ async #send(attempt, expires, delay3, _request, _response) {
54835
54938
  if (attempt >= this.#throttle.maxAttempts) {
54836
54939
  return _response.makeServerError("exceeded maximum retry limit");
54837
54940
  }
@@ -54840,8 +54943,8 @@ var init_fetch = __esm({
54840
54943
  reason: "timeout",
54841
54944
  request: _request
54842
54945
  });
54843
- if (delay2 > 0) {
54844
- await wait2(delay2);
54946
+ if (delay3 > 0) {
54947
+ await wait2(delay3);
54845
54948
  }
54846
54949
  let req = this.clone();
54847
54950
  const scheme = (req.url.split(":")[0] || "").toLowerCase();
@@ -54878,11 +54981,11 @@ var init_fetch = __esm({
54878
54981
  } else if (response.statusCode === 429) {
54879
54982
  if (this.retryFunc == null || await this.retryFunc(req, response, attempt)) {
54880
54983
  const retryAfter = response.headers["retry-after"];
54881
- let delay3 = this.#throttle.slotInterval * Math.trunc(Math.random() * Math.pow(2, attempt));
54984
+ let delay4 = this.#throttle.slotInterval * Math.trunc(Math.random() * Math.pow(2, attempt));
54882
54985
  if (typeof retryAfter === "string" && retryAfter.match(/^[1-9][0-9]*$/)) {
54883
- delay3 = parseInt(retryAfter);
54986
+ delay4 = parseInt(retryAfter);
54884
54987
  }
54885
- return req.clone().#send(attempt + 1, expires, delay3, _request, response);
54988
+ return req.clone().#send(attempt + 1, expires, delay4, _request, response);
54886
54989
  }
54887
54990
  }
54888
54991
  if (this.processFunc) {
@@ -54893,12 +54996,12 @@ var init_fetch = __esm({
54893
54996
  if (error48.throttle == null || typeof error48.stall !== "number") {
54894
54997
  response.makeServerError("error in post-processing function", error48).assertOk();
54895
54998
  }
54896
- let delay3 = this.#throttle.slotInterval * Math.trunc(Math.random() * Math.pow(2, attempt));
54999
+ let delay4 = this.#throttle.slotInterval * Math.trunc(Math.random() * Math.pow(2, attempt));
54897
55000
  ;
54898
55001
  if (error48.stall >= 0) {
54899
- delay3 = error48.stall;
55002
+ delay4 = error48.stall;
54900
55003
  }
54901
- return req.clone().#send(attempt + 1, expires, delay3, _request, response);
55004
+ return req.clone().#send(attempt + 1, expires, delay4, _request, response);
54902
55005
  }
54903
55006
  }
54904
55007
  return response;
@@ -84646,6 +84749,8 @@ var init_hyperliquid_client = __esm({
84646
84749
  if (!Array.isArray(payload)) {
84647
84750
  throw new Error("Malformed Hyperliquid frontendOpenOrders response.");
84648
84751
  }
84752
+ const isSpotOrder = (raw) => raw != null && typeof raw === "object" && !Array.isArray(raw) && isHyperliquidSpotSymbol(raw.coin);
84753
+ const perpOrders = payload.filter((raw) => !isSpotOrder(raw));
84649
84754
  const normalizeOpenOrder = (raw, inheritedCoin = "") => {
84650
84755
  if (raw == null || typeof raw !== "object" || Array.isArray(raw)) {
84651
84756
  throw new Error("Malformed Hyperliquid frontendOpenOrders member.");
@@ -84720,10 +84825,10 @@ var init_hyperliquid_client = __esm({
84720
84825
  };
84721
84826
  };
84722
84827
  if (input.includeChildren !== true) {
84723
- return payload.map((raw) => normalizeOpenOrder(raw));
84828
+ return perpOrders.map((raw) => normalizeOpenOrder(raw));
84724
84829
  }
84725
84830
  const canonicalOrders = /* @__PURE__ */ new Map();
84726
- const pendingOrders = payload.map((raw) => ({
84831
+ const pendingOrders = perpOrders.map((raw) => ({
84727
84832
  raw,
84728
84833
  inheritedCoin: "",
84729
84834
  depth: 0,
@@ -84735,6 +84840,9 @@ var init_hyperliquid_client = __esm({
84735
84840
  break;
84736
84841
  }
84737
84842
  const { raw, inheritedCoin, depth, ancestors } = pending3;
84843
+ if (isSpotOrder(raw)) {
84844
+ continue;
84845
+ }
84738
84846
  if (raw == null || typeof raw !== "object" || Array.isArray(raw)) {
84739
84847
  throw new Error("Malformed Hyperliquid frontendOpenOrders member.");
84740
84848
  }
@@ -86238,6 +86346,65 @@ var init_key_preview_contract = __esm({
86238
86346
  }
86239
86347
  });
86240
86348
 
86349
+ // lib/retired-model-source.ts
86350
+ var init_retired_model_source = __esm({
86351
+ "lib/retired-model-source.ts"() {
86352
+ "use strict";
86353
+ init_define_VTX_EXO_POLICY();
86354
+ init_define_VTX_GROK_POLICY();
86355
+ init_define_VTX_PI_MODEL_POLICY();
86356
+ }
86357
+ });
86358
+
86359
+ // lib/modelGrouping.ts
86360
+ var init_modelGrouping = __esm({
86361
+ "lib/modelGrouping.ts"() {
86362
+ "use strict";
86363
+ init_define_VTX_EXO_POLICY();
86364
+ init_define_VTX_GROK_POLICY();
86365
+ init_define_VTX_PI_MODEL_POLICY();
86366
+ init_byokProviderRegistry();
86367
+ }
86368
+ });
86369
+
86370
+ // lib/openai-compatible-capabilities.ts
86371
+ var init_openai_compatible_capabilities = __esm({
86372
+ "lib/openai-compatible-capabilities.ts"() {
86373
+ "use strict";
86374
+ init_define_VTX_EXO_POLICY();
86375
+ init_define_VTX_GROK_POLICY();
86376
+ init_define_VTX_PI_MODEL_POLICY();
86377
+ }
86378
+ });
86379
+
86380
+ // lib/local-ai.ts
86381
+ var LOCAL_CONTEXT_CACHE_TTL_MS, LOCAL_AI_SERVER_TYPE_ALIASES, normalizeLocalAiServerType;
86382
+ var init_local_ai = __esm({
86383
+ "lib/local-ai.ts"() {
86384
+ "use strict";
86385
+ init_define_VTX_EXO_POLICY();
86386
+ init_define_VTX_GROK_POLICY();
86387
+ init_define_VTX_PI_MODEL_POLICY();
86388
+ init_retired_model_source();
86389
+ init_modelGrouping();
86390
+ init_openai_compatible_capabilities();
86391
+ init_sort_utils();
86392
+ LOCAL_CONTEXT_CACHE_TTL_MS = 12 * 60 * 60 * 1e3;
86393
+ LOCAL_AI_SERVER_TYPE_ALIASES = {
86394
+ "openai-compatible": "openai-compatible",
86395
+ openai: "openai-compatible",
86396
+ compatible: "openai-compatible"
86397
+ };
86398
+ normalizeLocalAiServerType = (value) => {
86399
+ const normalized = String(value ?? "").trim().toLowerCase();
86400
+ if (!normalized) {
86401
+ return null;
86402
+ }
86403
+ return Object.prototype.hasOwnProperty.call(LOCAL_AI_SERVER_TYPE_ALIASES, normalized) ? "openai-compatible" : null;
86404
+ };
86405
+ }
86406
+ });
86407
+
86241
86408
  // lib/runtime/vault.ts
86242
86409
  function notifyVaultChanged(profileId) {
86243
86410
  window.dispatchEvent(new CustomEvent(CLIENT_VAULT_CHANGED_EVENT, { detail: profileId }));
@@ -86298,7 +86465,7 @@ function validateDeviceSecrets(value, options) {
86298
86465
  baseUrl: typeof rawLocalAi.baseUrl === "string" ? rawLocalAi.baseUrl : "",
86299
86466
  modelName: typeof rawLocalAi.modelName === "string" ? rawLocalAi.modelName : "",
86300
86467
  apiKey: typeof rawLocalAi.apiKey === "string" ? rawLocalAi.apiKey : "",
86301
- serverType: rawLocalAi.serverType === "ollama-native" ? "ollama-native" : rawLocalAi.serverType === "openai-compatible" ? "openai-compatible" : void 0
86468
+ serverType: typeof rawLocalAi.serverType === "string" ? rawLocalAi.serverType : void 0
86302
86469
  });
86303
86470
  const rawOpenAiCompatible = record5.openaiCompatible && typeof record5.openaiCompatible === "object" ? record5.openaiCompatible : {};
86304
86471
  const openaiCompatible = normalizeOpenAiCompatibleSecrets({
@@ -86306,7 +86473,7 @@ function validateDeviceSecrets(value, options) {
86306
86473
  modelName: typeof rawOpenAiCompatible.modelName === "string" ? rawOpenAiCompatible.modelName : "",
86307
86474
  apiKey: typeof rawOpenAiCompatible.apiKey === "string" ? rawOpenAiCompatible.apiKey : ""
86308
86475
  });
86309
- const hasLocalAiConfig = Boolean(localAi?.baseUrl);
86476
+ const hasLocalAiConfig = Boolean(localAi?.baseUrl && (!localAi.serverType || normalizeLocalAiServerType(localAi.serverType)));
86310
86477
  const hasOpenAiCompatibleConfig = Boolean(
86311
86478
  openaiCompatible?.baseUrl && openaiCompatible?.apiKey
86312
86479
  );
@@ -86354,7 +86521,7 @@ function validateDeviceSecrets(value, options) {
86354
86521
  missing: missing2
86355
86522
  };
86356
86523
  }
86357
- var VAULT_PREFIX, CLIENT_VAULT_CHANGED_EVENT, VAULT_DB_NAME, VAULT_DB_VERSION, VAULT_KEY_STORE, DEFAULT_DEVICE_SECRET_STORAGE, encoder, decoder, sessionVaultCache, runtimeSecretsInFlight, buildRuntimeSecretsRequestKey, fetchClientRuntimeSecretsSingleFlight, hasSecureVaultSupport, bytesToBase64, base64ToArrayBuffer, openVaultDb, withVaultStore, getVaultKey, getOrCreateVaultKey, deleteVaultKey, mapClientRuntimeSecretsToDeviceSecrets, normalizeDeviceSecretStorage, normalizeLocalAiSecrets, normalizeOpenAiCompatibleSecrets, hasAnySecretValues, hasAnyDeviceOnlyOptIn, mergeHydratedSecrets, preserveDeviceOnlySecrets, normalizeClientRuntimeSecretProvider, getResponseSecretVersion, getStoredSecretVersion, buildHydrationState, normalizeProfileIdForApi, ClientVault;
86524
+ var VAULT_PREFIX, CLIENT_VAULT_CHANGED_EVENT, VAULT_DB_NAME, VAULT_DB_VERSION, VAULT_KEY_STORE, DEFAULT_DEVICE_SECRET_STORAGE, encoder, decoder, sessionVaultCache, runtimeSecretsInFlight, buildRuntimeSecretsRequestKey, fetchClientRuntimeSecretsSingleFlight, hasSecureVaultSupport, bytesToBase64, base64ToArrayBuffer, openVaultDb, withVaultStore, getVaultKey, getOrCreateVaultKey, deleteVaultKey, mapClientRuntimeSecretsToDeviceSecrets, normalizeDeviceSecretStorage, normalizeLocalAiSecrets, normalizeOpenAiCompatibleSecrets, hasAnySecretValues, hasAnyDeviceOnlyOptIn, mergeHydratedSecrets, preserveDeviceOnlySecrets, normalizeClientRuntimeSecretProvider, getResponseSecretVersion, getStoredSecretMetadata, getStoredSecretVersion, buildHydrationState, normalizeProfileIdForApi, ClientVault;
86358
86525
  var init_vault = __esm({
86359
86526
  "lib/runtime/vault.ts"() {
86360
86527
  "use strict";
@@ -86368,6 +86535,7 @@ var init_vault = __esm({
86368
86535
  init_key_preview_contract();
86369
86536
  init_client_runtime_provider_visibility_contract();
86370
86537
  init_client_runtime_secret_rate_limit_contract();
86538
+ init_local_ai();
86371
86539
  init_byokProviderRegistry();
86372
86540
  VAULT_PREFIX = "vtx_vault_";
86373
86541
  CLIENT_VAULT_CHANGED_EVENT = "vtx-client-vault-changed";
@@ -86531,6 +86699,7 @@ var init_vault = __esm({
86531
86699
  }
86532
86700
  const localBaseUrl = typeof value.local_ai_base_url === "string" ? value.local_ai_base_url.trim() : "";
86533
86701
  const localApiKey = typeof value.local_ai_api_key === "string" ? value.local_ai_api_key.trim() : "";
86702
+ const localServerType = typeof value.local_ai_server_type === "string" ? value.local_ai_server_type.trim() : "";
86534
86703
  const oaiCompatBaseUrl = typeof value.openai_compatible_base_url === "string" ? value.openai_compatible_base_url.trim() : "";
86535
86704
  const oaiCompatApiKey = typeof value.openai_compatible_api_key === "string" ? value.openai_compatible_api_key.trim() : "";
86536
86705
  return {
@@ -86541,7 +86710,8 @@ var init_vault = __esm({
86541
86710
  ...Object.keys(providerBaseUrlSlots).length > 0 ? { providerBaseUrlSlots } : {},
86542
86711
  localAi: {
86543
86712
  ...localBaseUrl ? { baseUrl: localBaseUrl } : {},
86544
- ...localApiKey ? { apiKey: localApiKey } : {}
86713
+ ...localApiKey ? { apiKey: localApiKey } : {},
86714
+ ...localServerType ? { serverType: localServerType } : {}
86545
86715
  },
86546
86716
  openaiCompatible: oaiCompatBaseUrl || oaiCompatApiKey ? {
86547
86717
  ...oaiCompatBaseUrl ? { baseUrl: oaiCompatBaseUrl } : {},
@@ -86561,7 +86731,7 @@ var init_vault = __esm({
86561
86731
  const baseUrl = typeof value?.baseUrl === "string" ? value.baseUrl.trim() : "";
86562
86732
  const modelName = typeof value?.modelName === "string" ? value.modelName.trim() : "";
86563
86733
  const apiKey = typeof value?.apiKey === "string" ? value.apiKey.trim() : "";
86564
- const serverType = value?.serverType === "ollama-native" ? "ollama-native" : value?.serverType === "openai-compatible" ? "openai-compatible" : void 0;
86734
+ const serverType = typeof value?.serverType === "string" ? value.serverType.trim() || void 0 : void 0;
86565
86735
  if (!baseUrl && !modelName && !apiKey && !serverType) {
86566
86736
  return void 0;
86567
86737
  }
@@ -86598,11 +86768,11 @@ var init_vault = __esm({
86598
86768
  const mergedLocalAi = storage2.byok === "device" ? normalizeLocalAiSecrets({
86599
86769
  baseUrl: localNormalized?.localAi?.baseUrl,
86600
86770
  apiKey: localNormalized?.localAi?.apiKey,
86601
- serverType: localNormalized?.localAi?.serverType
86771
+ serverType: localNormalized?.localAi?.serverType ?? remoteNormalized?.localAi?.serverType
86602
86772
  }) : normalizeLocalAiSecrets({
86603
86773
  baseUrl: remoteNormalized?.localAi?.baseUrl,
86604
86774
  apiKey: remoteNormalized?.localAi?.apiKey ?? localNormalized?.localAi?.apiKey,
86605
- serverType: localNormalized?.localAi?.serverType
86775
+ serverType: remoteNormalized?.localAi?.serverType ?? localNormalized?.localAi?.serverType
86606
86776
  });
86607
86777
  const mergedOpenAiCompatible = storage2.byok === "device" ? normalizeOpenAiCompatibleSecrets({
86608
86778
  baseUrl: localNormalized?.openaiCompatible?.baseUrl,
@@ -86647,7 +86817,7 @@ var init_vault = __esm({
86647
86817
  getResponseSecretVersion = (value) => {
86648
86818
  return normalizeClientRuntimeSecretVersion(value.client_runtime_secret_version);
86649
86819
  };
86650
- getStoredSecretVersion = (profileId) => {
86820
+ getStoredSecretMetadata = (profileId) => {
86651
86821
  const encryptedRaw = localStorage.getItem(`${VAULT_PREFIX}${profileId}`);
86652
86822
  if (encryptedRaw) {
86653
86823
  try {
@@ -86655,14 +86825,19 @@ var init_vault = __esm({
86655
86825
  if (parsed && typeof parsed === "object" && "version" in parsed && parsed.version === 1 && "serverSecretVersion" in parsed) {
86656
86826
  const version3 = normalizeClientRuntimeSecretVersion(parsed.serverSecretVersion);
86657
86827
  if (version3) {
86658
- return version3;
86828
+ return { version: version3, allProviderKeysHydrated: parsed.allProviderKeysHydrated === true };
86659
86829
  }
86660
86830
  }
86661
86831
  } catch {
86662
86832
  }
86663
86833
  }
86664
- return normalizeClientRuntimeSecretVersion(sessionVaultCache.get(profileId)?.serverSecretVersion);
86834
+ const session = sessionVaultCache.get(profileId);
86835
+ return {
86836
+ version: normalizeClientRuntimeSecretVersion(session?.serverSecretVersion),
86837
+ allProviderKeysHydrated: session?.allProviderKeysHydrated === true
86838
+ };
86665
86839
  };
86840
+ getStoredSecretVersion = (profileId) => getStoredSecretMetadata(profileId).version;
86666
86841
  buildHydrationState = (response, secrets, persistence, localSecretVersion, options) => {
86667
86842
  const validation = validateDeviceSecrets(secrets, options);
86668
86843
  const metadata = projectClientRuntimeSecretMetadata(
@@ -86691,6 +86866,41 @@ var init_vault = __esm({
86691
86866
  return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
86692
86867
  };
86693
86868
  ClientVault = class _ClientVault {
86869
+ /** Refresh account-backed provider slots at a cycle boundary, keeping its bound signer. */
86870
+ static async refreshProviderSecretsForVersion(profileId, current, serverVersion) {
86871
+ const version3 = normalizeClientRuntimeSecretVersion(serverVersion);
86872
+ if (!version3 || current.storage?.byok === "device") return current;
86873
+ let savedSecrets;
86874
+ const stored = getStoredSecretMetadata(profileId);
86875
+ if (stored.version !== version3 || !stored.allProviderKeysHydrated) {
86876
+ const hydrated = await _ClientVault.hydrateFromServerWithState(profileId, {
86877
+ includeAllProviderKeys: true,
86878
+ requireProviderSecret: false
86879
+ });
86880
+ if (hydrated.hydrationState.serverSecretVersion !== version3) {
86881
+ throw new Error("Client provider credentials changed; account refresh is pending.");
86882
+ }
86883
+ savedSecrets = hydrated.secrets;
86884
+ if (savedSecrets && hydrated.hydrationState.localSecretVersion !== version3) {
86885
+ await _ClientVault.saveSecrets(profileId, savedSecrets, {
86886
+ serverSecretVersion: version3,
86887
+ allProviderKeysHydrated: true
86888
+ });
86889
+ }
86890
+ } else {
86891
+ savedSecrets = await _ClientVault.getSecrets(profileId);
86892
+ }
86893
+ return {
86894
+ ...current,
86895
+ providerKeys: savedSecrets?.providerKeys ?? {},
86896
+ providerKeySlots: savedSecrets?.providerKeySlots,
86897
+ providerBaseUrls: savedSecrets?.providerBaseUrls,
86898
+ providerBaseUrlSlots: savedSecrets?.providerBaseUrlSlots,
86899
+ localAi: savedSecrets?.localAi,
86900
+ openaiCompatible: savedSecrets?.openaiCompatible,
86901
+ storage: { ...current.storage, byok: savedSecrets?.storage?.byok ?? "server" }
86902
+ };
86903
+ }
86694
86904
  static async hydrateFromServer(profileId, options) {
86695
86905
  const result2 = await _ClientVault.hydrateFromServerWithState(profileId, options);
86696
86906
  return result2.secrets;
@@ -86755,7 +86965,8 @@ var init_vault = __esm({
86755
86965
  };
86756
86966
  }
86757
86967
  const persistence = await _ClientVault.saveSecrets(profileId, validation.normalized, {
86758
- serverSecretVersion: remoteSecretVersion
86968
+ serverSecretVersion: remoteSecretVersion,
86969
+ allProviderKeysHydrated: includeAllProviderKeys
86759
86970
  });
86760
86971
  return {
86761
86972
  secrets: validation.normalized,
@@ -86775,12 +86986,14 @@ var init_vault = __esm({
86775
86986
  throw new Error("Invalid device secrets payload.");
86776
86987
  }
86777
86988
  const serverSecretVersion = normalizeClientRuntimeSecretVersion(options?.serverSecretVersion);
86989
+ const allProviderKeysHydrated = options?.allProviderKeysHydrated === true;
86778
86990
  const vaultKey = await getOrCreateVaultKey(profileId);
86779
86991
  if (!vaultKey || !hasSecureVaultSupport()) {
86780
86992
  sessionVaultCache.set(profileId, {
86781
86993
  secrets: normalized,
86782
86994
  persistence: "session",
86783
- serverSecretVersion
86995
+ serverSecretVersion,
86996
+ allProviderKeysHydrated
86784
86997
  });
86785
86998
  localStorage.removeItem(key);
86786
86999
  notifyVaultChanged(profileId);
@@ -86799,7 +87012,8 @@ var init_vault = __esm({
86799
87012
  version: 1,
86800
87013
  iv: bytesToBase64(iv),
86801
87014
  ciphertext: bytesToBase64(new Uint8Array(encrypted)),
86802
- serverSecretVersion
87015
+ serverSecretVersion,
87016
+ allProviderKeysHydrated
86803
87017
  };
86804
87018
  localStorage.setItem(key, JSON.stringify(encryptedRecord));
86805
87019
  sessionVaultCache.delete(profileId);
@@ -92784,7 +92998,7 @@ var init_constraint_contract = __esm({
92784
92998
  });
92785
92999
 
92786
93000
  // lib/runtime/provider-observability.ts
92787
- var MAX_DIAGNOSTIC_LIST_ITEMS, record4, identifier, count3, normalizeProviderDiagnostics;
93001
+ var MAX_DIAGNOSTIC_LIST_ITEMS, record4, ERROR_TOKEN, ERROR_DOMAIN, ERROR_INPUT, ERROR_REDACTIONS, normalizeProviderError, identifier, count3, normalizeProviderDiagnostics;
92788
93002
  var init_provider_observability = __esm({
92789
93003
  "lib/runtime/provider-observability.ts"() {
92790
93004
  "use strict";
@@ -92793,6 +93007,45 @@ var init_provider_observability = __esm({
92793
93007
  init_define_VTX_PI_MODEL_POLICY();
92794
93008
  MAX_DIAGNOSTIC_LIST_ITEMS = 16;
92795
93009
  record4 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
93010
+ ERROR_TOKEN = /^[A-Z][A-Z0-9_]{0,63}$/;
93011
+ ERROR_DOMAIN = /^[a-z0-9][a-z0-9.-]{0,127}$/;
93012
+ ERROR_INPUT = /\b(?:prompt|contents|messages|system[_ ]?instruction|tools|request\s+body|input(?:\s+text)?)\s*[:=]|[{}]|```/i;
93013
+ ERROR_REDACTIONS = [
93014
+ [/https?:\/\/[^\s<>"']+/gi, "[REDACTED_URL]"],
93015
+ [/\b[A-Za-z0-9.!#$%&'*+/=?^_`{|}~-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g, "[REDACTED_EMAIL]"],
93016
+ [/\bBearer\s+[^\s,;]+/gi, "Bearer [REDACTED]"],
93017
+ [/\b(?:api[_ -]?key|x-goog-api-key|authorization|access[_ -]?token|token|secret|password|private[_ -]?key|key)\s*[:=]\s*(?:"[^"]*"|'[^']*'|[^\s,;]+)/gi, "[REDACTED]"],
93018
+ [/\b(?:AIza[A-Za-z0-9_-]+|sk-[A-Za-z0-9_-]+|AQ\.[A-Za-z0-9._-]+|0x[a-fA-F0-9]{64})\b/g, "[REDACTED]"],
93019
+ [/"[^"]*"|'[^'\r\n]*'/g, "[REDACTED]"]
93020
+ ];
93021
+ normalizeProviderError = (value) => {
93022
+ const raw = record4(value);
93023
+ const result2 = {};
93024
+ if (typeof raw.code === "number" && Number.isInteger(raw.code) && raw.code >= 100 && raw.code <= 599) result2.code = raw.code;
93025
+ if (typeof raw.status === "string" && ERROR_TOKEN.test(raw.status)) result2.status = raw.status;
93026
+ if (typeof raw.message === "string" && raw.message.trim()) {
93027
+ let message = raw.message;
93028
+ if (Array.from(message).length > 8192 || ERROR_INPUT.test(message)) message = "[REDACTED_INPUT]";
93029
+ else {
93030
+ for (const [pattern, replacement] of ERROR_REDACTIONS) message = message.replace(pattern, replacement);
93031
+ message = message.replace(/[\x00-\x1f\x7f]+/g, " ").replace(/\s+/g, " ").trim();
93032
+ }
93033
+ const characters = Array.from(message);
93034
+ result2.message = characters.slice(0, 512).join("");
93035
+ if (characters.length > 512 || raw.message_truncated === true) result2.message_truncated = true;
93036
+ }
93037
+ if (Array.isArray(raw.details)) {
93038
+ const details = raw.details.slice(0, 4).map((value2) => {
93039
+ const detail = record4(value2);
93040
+ return {
93041
+ ...typeof detail.reason === "string" && ERROR_TOKEN.test(detail.reason) ? { reason: detail.reason } : {},
93042
+ ...typeof detail.domain === "string" && ERROR_DOMAIN.test(detail.domain) ? { domain: detail.domain } : {}
93043
+ };
93044
+ }).filter((detail) => Object.keys(detail).length);
93045
+ if (details.length) result2.details = details;
93046
+ }
93047
+ return result2;
93048
+ };
92796
93049
  identifier = (v) => typeof v === "string" && /^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,255}$/.test(v) ? v : void 0;
92797
93050
  count3 = (v) => {
92798
93051
  if (typeof v !== "number" && (typeof v !== "string" || !v.trim())) return void 0;
@@ -92802,6 +93055,9 @@ var init_provider_observability = __esm({
92802
93055
  normalizeProviderDiagnostics = (value) => {
92803
93056
  const raw = record4(value);
92804
93057
  const result2 = {};
93058
+ if (raw.egress_route === "client_direct" || raw.egress_route === "node" || raw.egress_route === "server_direct") result2.egress_route = raw.egress_route;
93059
+ const providerError = normalizeProviderError(raw.provider_error);
93060
+ if (Object.keys(providerError).length) result2.provider_error = providerError;
92805
93061
  for (const key of ["retry_after_seconds", "retry_delay_seconds"]) {
92806
93062
  const n2 = count3(raw[key]);
92807
93063
  if (n2 !== void 0) result2[key] = n2;
@@ -94401,7 +94657,7 @@ Waiting for approval...
94401
94657
  if (polled.status === "denied") {
94402
94658
  throw new Error(polled.error || "CLI login was denied");
94403
94659
  }
94404
- await delay(Math.max(1, Number(started.interval || 2)) * 1e3);
94660
+ await delay2(Math.max(1, Number(started.interval || 2)) * 1e3);
94405
94661
  }
94406
94662
  throw new Error("Timed out waiting for CLI login approval");
94407
94663
  }
@@ -94657,7 +94913,7 @@ async function runVtxCli(argv2, env = process.env) {
94657
94913
  ` };
94658
94914
  }
94659
94915
  }
94660
- var VTX_CLI_HELP, WRITABLE_SECRET_FIELDS, delay;
94916
+ var VTX_CLI_HELP, WRITABLE_SECRET_FIELDS, delay2;
94661
94917
  var init_vtx = __esm({
94662
94918
  "lib/agent-cli/vtx.ts"() {
94663
94919
  "use strict";
@@ -94708,7 +94964,7 @@ Global options:
94708
94964
  "alibaba_cloud_model_studio_api_key",
94709
94965
  "lightning_api_key"
94710
94966
  ]);
94711
- delay = (ms) => new Promise((resolve13) => setTimeout(resolve13, ms));
94967
+ delay2 = (ms) => new Promise((resolve13) => setTimeout(resolve13, ms));
94712
94968
  }
94713
94969
  });
94714
94970
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtxmacro/cli",
3
- "version": "2026.9.60",
3
+ "version": "2026.9.62",
4
4
  "description": "VTX Macro CLI, MCP server, and durable external inference host.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",