@vtxmacro/cli 2026.8.55 → 2026.8.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/vtx.js CHANGED
@@ -47,7 +47,7 @@ var init_agent_cli_release = __esm({
47
47
  "agent-cli-release.json"() {
48
48
  agent_cli_release_default = {
49
49
  package_name: "@vtxmacro/cli",
50
- package_version: "2026.8.55",
50
+ package_version: "2026.8.57",
51
51
  codex_package_name: "@openai/codex",
52
52
  codex_version: "0.147.0",
53
53
  copilot_sdk_package_name: "@github/copilot-sdk",
@@ -18756,7 +18756,8 @@ var init_mcp_client = __esm({
18756
18756
  const errorText = (callResult.content ?? []).filter((block) => block.type === "text").map((block) => block.text ?? "").join("\n");
18757
18757
  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(
18758
18758
  "External inference claim request was not applied before its generation became stale"
18759
- ) || errorText.includes("External inference host advertisement is expired or superseded"));
18759
+ ) || errorText.includes("External inference host advertisement is expired or superseded")) || name === "inference.job.complete" && errorText.includes("External inference completion evidence window expired");
18760
+ const completionEvidenceExpired = name === "inference.job.complete" && errorText.includes("External inference completion evidence window expired");
18760
18761
  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"));
18761
18762
  const retryableClaimRejection = name === "inference.job.claim" && !definitivelyNotApplied && (retryableInfrastructureRejection || errorText.includes("External inference host is not live enough to claim work") || errorText.includes("External inference host request generation is stale") || errorText.includes("External inference claim runtime fence is stale"));
18762
18763
  const retryableHeartbeatClockSkew = name === "inference.host.heartbeat" && definitivelyNotApplied;
@@ -18766,7 +18767,7 @@ var init_mcp_client = __esm({
18766
18767
  "External inference claim replay is no longer dispatchable"
18767
18768
  );
18768
18769
  throw new ExternalInferenceMcpError(
18769
- staleHostHeartbeatGeneration ? "generation_stale" : obsoleteClaimReplay ? "claim_replay_obsolete" : "tool_rejected",
18770
+ completionEvidenceExpired ? "completion_evidence_expired" : staleHostHeartbeatGeneration ? "generation_stale" : obsoleteClaimReplay ? "claim_replay_obsolete" : "tool_rejected",
18770
18771
  `Insights MCP rejected ${name}.`,
18771
18772
  {
18772
18773
  definitivelyNotApplied: definitivelyNotApplied || staleHostHeartbeatGeneration,
@@ -32426,7 +32427,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
32426
32427
  envelopePublicKey: options.envelopePublicKey
32427
32428
  };
32428
32429
  }
32429
- var import_ajv, RUNTIME_RECEIPT_SCHEMA_VERSION, ATTEMPT_RECEIPT_SCHEMA_VERSION, DEFAULT_ADVERTISEMENT_TTL_MS, DEFAULT_ADVERTISEMENT_REFRESH_LEAD_MS, DEFAULT_HOST_HEARTBEAT_MS, DEFAULT_PROVIDER_RATE_LIMIT_REFRESH_MS, DEFAULT_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, MIN_SLEEP_MS, MIN_HOST_HEARTBEAT_GAP_DIAGNOSTIC_MS, HOST_HEARTBEAT_GAP_DIAGNOSTIC_FACTOR, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, DEFAULT_AGENT_RATE_LIMIT_COOLDOWN_MS, DEFAULT_AGENT_QUOTA_COOLDOWN_MS, DEFAULT_AGENT_TRANSIENT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, MAX_ATTEMPT_START_RETRY_DELAY_MS, UNBOUNDED_AVAILABLE_SLOTS, buildInferenceAdvertisedModels, summarizeInferenceHostRuntimeRecovery, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, settlesWithin, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, providerWeeklyQuotaFromRateLimits, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, membershipFailureDisposition, safeFailureCode, attemptStartRetryFallbackMs, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner, createInferenceAgentControlClient, INFERENCE_AGENT_SYSTEM_PROMPT, INFERENCE_AGENT_WAKE_SCHEMA, parseInferenceAgentWake, InferenceAgentRuntime;
32430
+ var import_ajv, RUNTIME_RECEIPT_SCHEMA_VERSION, ATTEMPT_RECEIPT_SCHEMA_VERSION, DEFAULT_ADVERTISEMENT_TTL_MS, DEFAULT_ADVERTISEMENT_REFRESH_LEAD_MS, DEFAULT_HOST_HEARTBEAT_MS, DEFAULT_PROVIDER_RATE_LIMIT_REFRESH_MS, DEFAULT_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, MIN_SLEEP_MS, MIN_HOST_HEARTBEAT_GAP_DIAGNOSTIC_MS, HOST_HEARTBEAT_GAP_DIAGNOSTIC_FACTOR, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, DEFAULT_AGENT_RATE_LIMIT_COOLDOWN_MS, DEFAULT_AGENT_QUOTA_COOLDOWN_MS, DEFAULT_AGENT_TRANSIENT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, MAX_ATTEMPT_START_RETRY_DELAY_MS, UNBOUNDED_AVAILABLE_SLOTS, buildInferenceAdvertisedModels, summarizeInferenceHostRuntimeRecovery, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, settlesWithin, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, providerWeeklyQuotaFromRateLimits, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, membershipFailureDisposition, safeFailureCode, attemptStartRetryFallbackMs, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, isDefinitiveCompletionEvidenceExpiry, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner, createInferenceAgentControlClient, INFERENCE_AGENT_SYSTEM_PROMPT, INFERENCE_AGENT_WAKE_SCHEMA, parseInferenceAgentWake, InferenceAgentRuntime;
32430
32431
  var init_runner = __esm({
32431
32432
  "lib/inference-host/runner.ts"() {
32432
32433
  "use strict";
@@ -33050,6 +33051,7 @@ var init_runner = __esm({
33050
33051
  if (failure.state !== request.attempt_status || failure.failure_category !== request.failure_category || failure.failure_code !== request.failure_code) runnerIdentityMismatch("Job failure receipt");
33051
33052
  }
33052
33053
  };
33054
+ isDefinitiveCompletionEvidenceExpiry = (error48, terminal) => terminal?.schema_version === "external_inference_job_complete_v1" && error48 instanceof ExternalInferenceMcpError && error48.code === "completion_evidence_expired" && error48.definitivelyNotApplied;
33053
33055
  classifyFailure = (error48, result2) => {
33054
33056
  if (error48 instanceof CodexAppServerError) {
33055
33057
  const category2 = error48.code === "quota_exceeded" ? "quota" : error48.category;
@@ -33907,10 +33909,19 @@ var init_runner = __esm({
33907
33909
  }
33908
33910
  return attemptId;
33909
33911
  };
33910
- const removeRecoveredAttempt = async (attemptId) => {
33912
+ const removeRecoveredAttempt = async (recovery) => {
33911
33913
  await mutateReceipt((current) => {
33914
+ const persisted = current.attempts[recovery.attempt_id];
33915
+ const persistedTerminal = persisted?.terminal_request;
33916
+ const recoveryTerminal = recovery.terminal_request;
33917
+ const sameTerminalRequest = Boolean(
33918
+ persistedTerminal && recoveryTerminal && persistedTerminal.schema_version === recoveryTerminal.schema_version && (persistedTerminal.schema_version === "external_inference_job_complete_v1" && recoveryTerminal.schema_version === "external_inference_job_complete_v1" && persistedTerminal.completion_id === recoveryTerminal.completion_id || persistedTerminal.schema_version === "external_inference_job_fail_v1" && recoveryTerminal.schema_version === "external_inference_job_fail_v1" && persistedTerminal.failure_id === recoveryTerminal.failure_id)
33919
+ );
33920
+ if (persisted?.phase !== "terminal_pending" || persisted.job_id !== recovery.job_id || persisted.terminal_operation_id !== recovery.terminal_operation_id || !sameTerminalRequest) {
33921
+ return current;
33922
+ }
33912
33923
  const attempts = { ...current.attempts };
33913
- delete attempts[attemptId];
33924
+ delete attempts[recovery.attempt_id];
33914
33925
  return { ...current, attempts, updated_at: isoAt(now()) };
33915
33926
  });
33916
33927
  };
@@ -33936,8 +33947,22 @@ var init_runner = __esm({
33936
33947
  failed += 1;
33937
33948
  }
33938
33949
  await this.dependencies.codexAdapter.acknowledgeAttempt?.(recovery.attempt_id);
33939
- await removeRecoveredAttempt(recovery.attempt_id);
33950
+ await removeRecoveredAttempt(recovery);
33940
33951
  } catch (error48) {
33952
+ if (isDefinitiveCompletionEvidenceExpiry(error48, recovery.terminal_request)) {
33953
+ await this.dependencies.codexAdapter.acknowledgeAttempt?.(recovery.attempt_id);
33954
+ await removeRecoveredAttempt(recovery);
33955
+ failed += 1;
33956
+ emitDiagnostic("terminal_recovery_retired", {
33957
+ job_id: recovery.job_id,
33958
+ attempt_id: recovery.attempt_id,
33959
+ attempt_phase: recovery.phase,
33960
+ terminal_operation: "complete",
33961
+ error_code: error48.code,
33962
+ definitively_not_applied: true
33963
+ });
33964
+ continue;
33965
+ }
33941
33966
  emitTerminalRecoveryFailure(recovery, error48);
33942
33967
  requestDrain(controlPlaneFatal(error48) ? "authority_lost" : "attempt_terminal_unconfirmed");
33943
33968
  break;
@@ -34568,6 +34593,22 @@ var init_runner = __esm({
34568
34593
  assertTerminalResult(completion, completionResult);
34569
34594
  await this.dependencies.codexAdapter.acknowledgeAttempt?.(attemptId);
34570
34595
  } catch (error48) {
34596
+ if (isDefinitiveCompletionEvidenceExpiry(error48, completion)) {
34597
+ await this.dependencies.codexAdapter.acknowledgeAttempt?.(attemptId);
34598
+ await stopHeartbeat();
34599
+ await removeAttempt();
34600
+ options.onAttemptOutcome?.({
34601
+ outcome: "failed",
34602
+ failure_category: "deadline",
34603
+ failure_code: error48.code,
34604
+ retryable: false,
34605
+ dispatch_outcome: completion.outcome.dispatch_outcome,
34606
+ response_outcome: "none",
34607
+ latency_ms: completion.latency_ms,
34608
+ usage: completion.usage
34609
+ });
34610
+ return "failed";
34611
+ }
34571
34612
  throw new InferenceHostRunnerError(
34572
34613
  "terminal_outcome_unconfirmed",
34573
34614
  "The exact completion receipt could not be confirmed; redispatch is fenced.",
@@ -35280,7 +35321,7 @@ import { createWriteStream, readFileSync } from "node:fs";
35280
35321
  import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as rm6, writeFile as writeFile2 } from "node:fs/promises";
35281
35322
  import { homedir as homedir2 } from "node:os";
35282
35323
  import { dirname as dirname5, join as join7, resolve as resolve4 } from "node:path";
35283
- var SERVICE_NAME, SYSTEMD_UNIT, LAUNCHD_LABEL, SERVICE_COOPERATIVE_STOP_SECONDS, INFERENCE_HOST_SERVICE_DRAIN_COMMAND, inferenceHostServiceChildEnvironment, isWindowsSubsystemForLinux, inferenceHostServiceManifestPath, inferenceHostServiceDesiredPath, inferenceHostServiceLogPath, inferenceHostServiceRuntimePath, xmlEscape, plistEscape, systemdQuote, defaultRunCommand, managerName, assertRuntimeEnvironment, withoutConcurrencyLimit, assertServicePath, manifestGeneration, assertWorker, assertManifest, assertServiceRuntimeState, assertDesiredState, readInferenceHostServiceManifest, readManifestAcrossAtomicReplacement, readInferenceHostServiceRuntime, readRuntimeAcrossAtomicReplacement, readInferenceHostServiceDesired, readDesiredAcrossAtomicReplacement, writeDesired, runtimeEnvironment, serviceArguments, windowsOwnedCommandLine, vbScriptString, windowsServiceLauncher, windowsTaskXml, systemdUnit, launchAgentPlist, sameWorker, sameServiceDefinition, sameWorkerSet, InferenceHostServiceManager, appendServiceLog, spawnInferenceHostServiceChild, runInferenceHostServiceSupervisor;
35324
+ var SERVICE_NAME, SYSTEMD_UNIT, LAUNCHD_LABEL, SERVICE_COOPERATIVE_STOP_SECONDS, SERVICE_UPDATE_STARTUP_SECONDS, INFERENCE_HOST_SERVICE_DRAIN_COMMAND, inferenceHostServiceChildEnvironment, isWindowsSubsystemForLinux, inferenceHostServiceManifestPath, inferenceHostServiceDesiredPath, inferenceHostServiceLogPath, inferenceHostServiceRuntimePath, xmlEscape, plistEscape, systemdQuote, defaultRunCommand, managerName, assertRuntimeEnvironment, withoutConcurrencyLimit, assertServicePath, manifestGeneration, assertWorker, assertManifest, assertServiceRuntimeState, assertDesiredState, readInferenceHostServiceManifest, readManifestAcrossAtomicReplacement, readInferenceHostServiceRuntime, readRuntimeAcrossAtomicReplacement, readInferenceHostServiceDesired, readDesiredAcrossAtomicReplacement, writeDesired, runtimeEnvironment, serviceBootstrapArguments, windowsOwnedCommandLine, vbScriptString, windowsServiceLauncher, windowsTaskXml, systemdUnit, launchAgentPlist, sameWorker, sameServiceDefinition, sameWorkerSet, InferenceHostServiceManager, appendServiceLog, spawnInferenceHostServiceChild, runInferenceHostServiceSupervisor;
35284
35325
  var init_service = __esm({
35285
35326
  "lib/inference-host/service.ts"() {
35286
35327
  "use strict";
@@ -35290,6 +35331,7 @@ var init_service = __esm({
35290
35331
  SYSTEMD_UNIT = "vtx-inference-host.service";
35291
35332
  LAUNCHD_LABEL = "com.vtxmacro.inference-host";
35292
35333
  SERVICE_COOPERATIVE_STOP_SECONDS = 75;
35334
+ SERVICE_UPDATE_STARTUP_SECONDS = 600;
35293
35335
  INFERENCE_HOST_SERVICE_DRAIN_COMMAND = "vtx-inference-host-service-drain-v1";
35294
35336
  inferenceHostServiceChildEnvironment = (runtimeEnvironment2, inheritedEnvironment = process.env) => {
35295
35337
  const environment = { ...inheritedEnvironment };
@@ -35594,13 +35636,12 @@ var init_service = __esm({
35594
35636
  }
35595
35637
  return result2;
35596
35638
  };
35597
- serviceArguments = (script, manifestPath) => [
35598
- script,
35599
- "inference-host",
35600
- "service",
35601
- "run-internal",
35639
+ serviceBootstrapArguments = (bootstrapScript, manifestPath, lockPath) => [
35640
+ bootstrapScript,
35602
35641
  "--service-manifest",
35603
- manifestPath
35642
+ manifestPath,
35643
+ "--service-lock",
35644
+ lockPath
35604
35645
  ];
35605
35646
  windowsOwnedCommandLine = (values) => {
35606
35647
  if (values.some((value) => value.includes('"') || value.includes("\0"))) {
@@ -35679,6 +35720,9 @@ WantedBy=default.target
35679
35720
  this.home = dependencies.homedir ?? homedir2();
35680
35721
  this.executable = resolve4(dependencies.executable ?? process.execPath);
35681
35722
  this.script = resolve4(dependencies.script ?? process.argv[1] ?? "");
35723
+ this.bootstrapScript = resolve4(
35724
+ dependencies.bootstrapScript ?? join7(dirname5(this.script), "vtx-service-bootstrap.js")
35725
+ );
35682
35726
  this.username = dependencies.username ?? ([process.env.USERDOMAIN, process.env.USERNAME].filter(Boolean).join("\\") || process.env.USER || "");
35683
35727
  this.windowsDirectory = (dependencies.windowsDirectory ?? process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows").replace(/[\\/]+$/u, "");
35684
35728
  this.runCommand = dependencies.runCommand ?? defaultRunCommand;
@@ -35710,6 +35754,21 @@ WantedBy=default.target
35710
35754
  runtimePath() {
35711
35755
  return inferenceHostServiceRuntimePath(this.config);
35712
35756
  }
35757
+ serviceBootstrapPath() {
35758
+ return `${this.config.supervisorStatePath}.service-bootstrap.js`;
35759
+ }
35760
+ serviceReleasePath() {
35761
+ return `${this.config.supervisorStatePath}.service-release.json`;
35762
+ }
35763
+ serviceReleaseRejectionPath() {
35764
+ return `${this.config.supervisorStatePath}.service-release-rejection.json`;
35765
+ }
35766
+ serviceReleasesPath() {
35767
+ return `${this.config.supervisorStatePath}.service-releases`;
35768
+ }
35769
+ serviceBootstrapLockPath() {
35770
+ return `${this.config.supervisorProcessLockPath}.service-bootstrap`;
35771
+ }
35713
35772
  controlLockPath() {
35714
35773
  return `${this.config.supervisorProcessLockPath}.service-control`;
35715
35774
  }
@@ -35754,6 +35813,18 @@ WantedBy=default.target
35754
35813
  windowsLauncherPath() {
35755
35814
  return `${this.config.supervisorStatePath}.service-launcher.vbs`;
35756
35815
  }
35816
+ async hasBootstrapDefinition() {
35817
+ try {
35818
+ await access3(this.serviceBootstrapPath());
35819
+ const definition = await readFile5(
35820
+ this.platform === "win32" ? this.windowsLauncherPath() : this.definitionPath(),
35821
+ "utf8"
35822
+ );
35823
+ return definition.includes(this.serviceBootstrapPath());
35824
+ } catch {
35825
+ return false;
35826
+ }
35827
+ }
35757
35828
  async managerCommand(action) {
35758
35829
  const definition = this.definitionPath();
35759
35830
  if (this.platform === "win32") {
@@ -35875,13 +35946,23 @@ ${result2.stderr}`)) {
35875
35946
  );
35876
35947
  }
35877
35948
  async registerManifestUnlocked(manifest, desiredRunning, targetInstanceName) {
35878
- const args = serviceArguments(manifest.script, this.manifestPath());
35949
+ await access3(this.bootstrapScript);
35950
+ const args = serviceBootstrapArguments(
35951
+ this.serviceBootstrapPath(),
35952
+ this.manifestPath(),
35953
+ this.serviceBootstrapLockPath()
35954
+ );
35879
35955
  const definition = this.platform === "win32" ? windowsTaskXml(this.windowsLauncherPath(), this.windowsDirectory, this.username) : this.platform === "darwin" ? launchAgentPlist(manifest.executable, args, manifest.log_path) : systemdUnit(manifest.executable, args);
35880
35956
  let managerInstallAttempted = false;
35881
35957
  try {
35882
35958
  await writeAtomicInferencePrivateFile(this.manifestPath(), `${JSON.stringify(manifest, null, 2)}
35883
35959
  `);
35884
35960
  await writeDesired(this.desiredPath(), desiredRunning, this.now());
35961
+ await writeAtomicInferencePrivateFile(
35962
+ this.serviceBootstrapPath(),
35963
+ await readFile5(this.bootstrapScript, "utf8")
35964
+ );
35965
+ await chmod3(this.serviceBootstrapPath(), 448);
35885
35966
  await mkdir3(dirname5(this.definitionPath()), { recursive: true, mode: 448 });
35886
35967
  if (this.platform === "win32") {
35887
35968
  await writeAtomicInferencePrivateFile(
@@ -35911,7 +35992,11 @@ ${started.stderr}`)) {
35911
35992
  }
35912
35993
  await this.waitForManagerActive();
35913
35994
  if (this.confirmInitialReadiness) {
35914
- await this.waitForManifestApplied(manifest, targetInstanceName);
35995
+ await this.waitForManifestApplied(
35996
+ manifest,
35997
+ targetInstanceName,
35998
+ Math.max(this.reconcileWaitAttempts, SERVICE_UPDATE_STARTUP_SECONDS * 4)
35999
+ );
35915
36000
  }
35916
36001
  }
35917
36002
  return await this.status();
@@ -35938,6 +36023,7 @@ ${cleanup.stderr}`)) {
35938
36023
  await rm6(this.manifestPath(), { force: true }).catch(() => void 0);
35939
36024
  await rm6(this.desiredPath(), { force: true }).catch(() => void 0);
35940
36025
  await rm6(this.runtimePath(), { force: true }).catch(() => void 0);
36026
+ await rm6(this.serviceBootstrapPath(), { force: true }).catch(() => void 0);
35941
36027
  if (this.platform === "linux") {
35942
36028
  await this.runCommand("systemctl", ["--user", "daemon-reload"]).catch(() => void 0);
35943
36029
  }
@@ -35947,10 +36033,11 @@ ${cleanup.stderr}`)) {
35947
36033
  async replaceManifestUnlocked(next, desiredRunning, targetInstanceName) {
35948
36034
  const previous = await readInferenceHostServiceManifest(this.manifestPath());
35949
36035
  const previousDesired = previous ? await readInferenceHostServiceDesired(this.desiredPath()) : false;
35950
- if (previous && sameServiceDefinition(previous, next) && sameWorkerSet(previous, next) && previousDesired === desiredRunning) {
36036
+ const hasBootstrapDefinition = previous ? await this.hasBootstrapDefinition() : false;
36037
+ if (previous && sameServiceDefinition(previous, next) && sameWorkerSet(previous, next) && previousDesired === desiredRunning && hasBootstrapDefinition) {
35951
36038
  return await this.status();
35952
36039
  }
35953
- if (previous && previousDesired && desiredRunning && sameServiceDefinition(previous, next)) {
36040
+ if (previous && previousDesired && desiredRunning && sameServiceDefinition(previous, next) && hasBootstrapDefinition) {
35954
36041
  const current = await this.status();
35955
36042
  const runtime = await readRuntimeAcrossAtomicReplacement(this.runtimePath()).catch(() => null);
35956
36043
  if (current.manager_active && runtime?.manifest_generation === previous.generation) {
@@ -36070,6 +36157,7 @@ ${cleanup.stderr}`)) {
36070
36157
  }
36071
36158
  await access3(this.executable);
36072
36159
  await access3(this.script);
36160
+ await access3(this.bootstrapScript);
36073
36161
  const maxConcurrency = options.maxConcurrency ?? null;
36074
36162
  const workers = [
36075
36163
  ...existing?.workers.filter((worker) => worker.instance_name !== this.config.instanceName) ?? [],
@@ -36195,25 +36283,34 @@ ${result2.stderr}`)) {
36195
36283
  const restoreOnFailure = await readInferenceHostServiceDesired(this.desiredPath());
36196
36284
  await writeDesired(this.desiredPath(), false, this.now());
36197
36285
  try {
36198
- const serviceLockPath = `${this.config.supervisorProcessLockPath}.service`;
36286
+ const serviceLockPaths = [
36287
+ `${this.config.supervisorProcessLockPath}.service`,
36288
+ this.serviceBootstrapLockPath()
36289
+ ];
36199
36290
  let serviceReleased = false;
36200
36291
  for (let attempt = 0; attempt < this.stopWaitAttempts; attempt += 1) {
36201
- try {
36202
- const probe = await this.acquireProcessLock(serviceLockPath);
36203
- await probe.release();
36292
+ let allReleased = true;
36293
+ for (const serviceLockPath of serviceLockPaths) {
36294
+ try {
36295
+ const probe = await this.acquireProcessLock(serviceLockPath);
36296
+ await probe.release();
36297
+ } catch (error48) {
36298
+ if (error48 instanceof Error && error48.message.includes("Another inference host process already owns")) {
36299
+ allReleased = false;
36300
+ break;
36301
+ }
36302
+ throw error48;
36303
+ }
36304
+ }
36305
+ if (allReleased) {
36204
36306
  serviceReleased = true;
36205
36307
  break;
36206
- } catch (error48) {
36207
- if (error48 instanceof Error && error48.message.includes("Another inference host process already owns")) {
36208
- await this.sleep(250);
36209
- continue;
36210
- }
36211
- throw error48;
36212
36308
  }
36309
+ await this.sleep(250);
36213
36310
  }
36214
36311
  if (!serviceReleased) {
36215
36312
  throw new Error(
36216
- `Inference-host workers did not stop cooperatively within ${SERVICE_COOPERATIVE_STOP_SECONDS} seconds; refusing forced termination while cleanup may be pending.`
36313
+ `Inference-host updater or workers did not stop cooperatively within ${SERVICE_COOPERATIVE_STOP_SECONDS} seconds; refusing forced termination while cleanup may be pending.`
36217
36314
  );
36218
36315
  }
36219
36316
  const result2 = await this.managerCommand("stop");
@@ -36329,6 +36426,10 @@ ${result2.stderr}`)) {
36329
36426
  await rm6(this.manifestPath(), { force: true });
36330
36427
  await rm6(this.desiredPath(), { force: true });
36331
36428
  await rm6(this.runtimePath(), { force: true });
36429
+ await rm6(this.serviceBootstrapPath(), { force: true });
36430
+ await rm6(this.serviceReleasePath(), { force: true });
36431
+ await rm6(this.serviceReleaseRejectionPath(), { force: true });
36432
+ await rm6(this.serviceReleasesPath(), { recursive: true, force: true });
36332
36433
  return {
36333
36434
  installed: false,
36334
36435
  desired_running: false,
@@ -36461,8 +36562,11 @@ ${result2.stderr}`)) {
36461
36562
  });
36462
36563
  };
36463
36564
  runInferenceHostServiceSupervisor = async (manifestPath, options = {}) => {
36464
- const initialManifest = await readInferenceHostServiceManifest(manifestPath);
36465
- if (!initialManifest) throw new Error("Inference-host service manifest is missing.");
36565
+ const storedInitialManifest = await readInferenceHostServiceManifest(manifestPath);
36566
+ if (!storedInitialManifest) throw new Error("Inference-host service manifest is missing.");
36567
+ const serviceScript = options.serviceScript ? resolve4(options.serviceScript) : null;
36568
+ const withServiceScript = (manifest) => serviceScript ? { ...manifest, script: serviceScript } : manifest;
36569
+ const initialManifest = withServiceScript(storedInitialManifest);
36466
36570
  const desiredPath = manifestPath.replace(/\.service\.json$/u, ".service-desired.json");
36467
36571
  const runtimePath = manifestPath.replace(/\.service\.json$/u, ".service-runtime.json");
36468
36572
  const signal = options.signal ?? new AbortController().signal;
@@ -36659,15 +36763,17 @@ ${result2.stderr}`)) {
36659
36763
  try {
36660
36764
  while (!signal.aborted) {
36661
36765
  while (!signal.aborted && await readDesiredAcrossAtomicReplacement(desiredPath)) {
36662
- const next = await readManifestAcrossAtomicReplacement(manifestPath);
36663
- if (!next) throw new Error("Inference-host service manifest is missing.");
36766
+ const storedNext = await readManifestAcrossAtomicReplacement(manifestPath);
36767
+ if (!storedNext) throw new Error("Inference-host service manifest is missing.");
36768
+ const next = withServiceScript(storedNext);
36664
36769
  if (next.generation !== appliedManifest.generation && next.generation !== rejectedManifestGeneration) await reconcile(next);
36665
36770
  await sleep4(250);
36666
36771
  }
36667
36772
  await drainWorkers();
36668
36773
  if (signal.aborted || !await readDesiredAcrossAtomicReplacement(desiredPath)) break;
36669
- const restored = await readManifestAcrossAtomicReplacement(manifestPath);
36670
- if (!restored) throw new Error("Inference-host service manifest is missing.");
36774
+ const storedRestored = await readManifestAcrossAtomicReplacement(manifestPath);
36775
+ if (!storedRestored) throw new Error("Inference-host service manifest is missing.");
36776
+ const restored = withServiceScript(storedRestored);
36671
36777
  await reconcile(restored);
36672
36778
  await appendServiceLog(restored.log_path, "service_desired_state_restored", {
36673
36779
  manifest_generation: restored.generation,
@@ -39406,7 +39512,8 @@ Waiting for approval...
39406
39512
  await (dependencies.runServiceSupervisor ?? runInferenceHostServiceSupervisor)(
39407
39513
  parsed.serviceManifestPath,
39408
39514
  {
39409
- signal: cancellation.signal
39515
+ signal: cancellation.signal,
39516
+ serviceScript: resolve5(process.argv[1] ?? "")
39410
39517
  }
39411
39518
  );
39412
39519
  return { exitCode: 0, stdout: "", stderr: "" };
@@ -41762,12 +41869,13 @@ var init_hyperliquid_account_state_adapter = __esm({
41762
41869
  buildUserFillsStorageKey = (cacheKey) => {
41763
41870
  return `${USER_FILLS_CACHE_STORAGE_PREFIX}${cacheKey}`;
41764
41871
  };
41765
- buildAccountStateCacheKey = (apiUrl, walletAddress, symbol2, aggregatePerpDexs, dexNames, includeEffectiveTakerRate, includeExactAccountMode, includeActiveAssetData) => {
41872
+ buildAccountStateCacheKey = (apiUrl, walletAddress, symbol2, aggregatePerpDexs, scopeAccountSummaryToSelectedDex, dexNames, includeEffectiveTakerRate, includeExactAccountMode, includeActiveAssetData) => {
41766
41873
  return [
41767
41874
  apiUrl.replace(/\/$/, "").toLowerCase(),
41768
41875
  walletAddress.trim().toLowerCase(),
41769
41876
  normalizeHyperliquidMarketSymbol(symbol2),
41770
41877
  aggregatePerpDexs ? "aggregate" : "selected",
41878
+ scopeAccountSummaryToSelectedDex ? "selected-summary" : "aggregate-summary",
41771
41879
  includeEffectiveTakerRate ? "with-effective-taker-rate" : "without-effective-taker-rate",
41772
41880
  includeExactAccountMode ? "with-exact-account-mode" : "without-exact-account-mode",
41773
41881
  includeActiveAssetData ? "with-active-asset" : "without-active-asset",
@@ -42439,15 +42547,20 @@ var init_hyperliquid_account_state_adapter = __esm({
42439
42547
  const activeAssetCacheKey = buildActiveAssetCacheKey(apiUrl, walletAddress, symbol2);
42440
42548
  const activeAssetRequestTypes = getBrowserActiveAssetTypeCandidates(apiUrl, walletAddress, symbol2);
42441
42549
  const aggregatePerpDexs = input.aggregatePerpDexs !== false;
42550
+ const scopeAccountSummaryToSelectedDex = input.scopeAccountSummaryToSelectedDex === true;
42442
42551
  const includeEffectiveTakerRate = input.includeEffectiveTakerRate === true;
42443
42552
  const includeExactAccountMode = input.includeExactAccountMode === true;
42444
42553
  const includeActiveAssetData = input.includeActiveAssetData !== false;
42445
42554
  const dexNames = listPerpDexsForAccountState(input.config, dex, aggregatePerpDexs);
42555
+ if (scopeAccountSummaryToSelectedDex && dex && !dexNames.includes(dex)) {
42556
+ dexNames.push(dex);
42557
+ }
42446
42558
  const cacheKey = buildAccountStateCacheKey(
42447
42559
  apiUrl,
42448
42560
  walletAddress,
42449
42561
  symbol2,
42450
42562
  aggregatePerpDexs,
42563
+ scopeAccountSummaryToSelectedDex,
42451
42564
  dexNames,
42452
42565
  includeEffectiveTakerRate,
42453
42566
  includeExactAccountMode,
@@ -42475,6 +42588,7 @@ var init_hyperliquid_account_state_adapter = __esm({
42475
42588
  apiUrl,
42476
42589
  walletAddress,
42477
42590
  symbol: symbol2,
42591
+ selectedDex: dex,
42478
42592
  activeAssetCacheKey,
42479
42593
  activeAssetRequestTypes,
42480
42594
  dexNames,
@@ -42514,6 +42628,7 @@ var init_hyperliquid_account_state_adapter = __esm({
42514
42628
  apiUrl,
42515
42629
  walletAddress,
42516
42630
  symbol: symbol2,
42631
+ selectedDex,
42517
42632
  activeAssetCacheKey,
42518
42633
  activeAssetRequestTypes,
42519
42634
  dexNames,
@@ -42538,11 +42653,22 @@ var init_hyperliquid_account_state_adapter = __esm({
42538
42653
  if (input.includeEffectiveTakerRate === true) {
42539
42654
  requirePromptClearinghouseState(response, dexName);
42540
42655
  }
42541
- return prefixHip3PositionCoins(response, dexName);
42656
+ return {
42657
+ dex: dexName,
42658
+ payload: prefixHip3PositionCoins(response, dexName)
42659
+ };
42542
42660
  })
42543
42661
  );
42662
+ const selectedPayload = selectedDex ? dexResponses.find((entry) => entry.dex === selectedDex)?.payload : defaultResponse;
42663
+ if (!selectedPayload) {
42664
+ throw new Error(`Missing selected Hyperliquid clearinghouse state for DEX ${selectedDex}.`);
42665
+ }
42544
42666
  return {
42545
- payload: aggregateClearinghouseResponses([defaultResponse, ...dexResponses]),
42667
+ payload: aggregateClearinghouseResponses([
42668
+ defaultResponse,
42669
+ ...dexResponses.map((entry) => entry.payload)
42670
+ ]),
42671
+ selectedPayload,
42546
42672
  capturedAt: (/* @__PURE__ */ new Date()).toISOString()
42547
42673
  };
42548
42674
  })();
@@ -42625,6 +42751,7 @@ var init_hyperliquid_account_state_adapter = __esm({
42625
42751
  exactAccountModePromise
42626
42752
  ]);
42627
42753
  const perpsResponse = perpsResult.payload;
42754
+ const accountSummaryPerpsResponse = input.scopeAccountSummaryToSelectedDex === true ? perpsResult.selectedPayload : perpsResponse;
42628
42755
  const spotResponse = spotResult.payload;
42629
42756
  const userFeesResponse = userFeesResult?.payload ?? null;
42630
42757
  if (input.includeEffectiveTakerRate === true) {
@@ -42646,18 +42773,35 @@ var init_hyperliquid_account_state_adapter = __esm({
42646
42773
  takerRate = parsedUserCrossRate;
42647
42774
  }
42648
42775
  const accountStateConfig = input.config.client_runtime_hyperliquid_account_state;
42649
- const summaryPerpsResponse = exactAccountMode ? { ...perpsResponse, accountMode: exactAccountMode.accountMode } : perpsResponse;
42776
+ const summaryPerpsResponse = exactAccountMode ? { ...accountSummaryPerpsResponse, accountMode: exactAccountMode.accountMode } : accountSummaryPerpsResponse;
42650
42777
  const accountSummaryOptions = {
42651
42778
  spotDominatesMinTotalUsd: accountStateConfig?.spot_dominates_min_total_usd,
42652
42779
  spotDominatesPerpsMultiplier: accountStateConfig?.spot_dominates_perps_multiplier,
42653
42780
  mirroredAccountValueAbsoluteToleranceUsd: accountStateConfig?.mirrored_account_value_absolute_tolerance_usd,
42654
42781
  mirroredAccountValueRelativeTolerance: accountStateConfig?.mirrored_account_value_relative_tolerance
42655
42782
  };
42656
- const normalizedSummary = exactAccountMode ? buildServerPromptRescueAccountSummary(
42783
+ const walletSummary = exactAccountMode && input.scopeAccountSummaryToSelectedDex !== true ? buildServerPromptRescueAccountSummary(
42657
42784
  perpsResponse,
42658
42785
  spotResponse,
42659
42786
  exactAccountMode.accountMode,
42660
42787
  accountSummaryOptions
42788
+ ) : buildAccountSummaryFromInfoResponses(
42789
+ perpsResponse,
42790
+ spotResponse,
42791
+ accountSummaryOptions
42792
+ );
42793
+ const normalizedSummary = input.scopeAccountSummaryToSelectedDex === true ? {
42794
+ ...buildAccountSummaryFromInfoResponses(
42795
+ summaryPerpsResponse,
42796
+ {},
42797
+ accountSummaryOptions
42798
+ ),
42799
+ balances: walletSummary.balances
42800
+ } : exactAccountMode ? buildServerPromptRescueAccountSummary(
42801
+ accountSummaryPerpsResponse,
42802
+ spotResponse,
42803
+ exactAccountMode.accountMode,
42804
+ accountSummaryOptions
42661
42805
  ) : buildAccountSummaryFromInfoResponses(
42662
42806
  summaryPerpsResponse,
42663
42807
  spotResponse,
@@ -42667,7 +42811,7 @@ var init_hyperliquid_account_state_adapter = __esm({
42667
42811
  ...normalizedSummary,
42668
42812
  ...exactAccountMode == null ? {} : { account_mode: exactAccountMode.accountMode, mode_source: "canonical" },
42669
42813
  address: walletAddress,
42670
- dex: "all",
42814
+ dex: input.scopeAccountSummaryToSelectedDex === true ? selectedDex : "all",
42671
42815
  market_type: "perp"
42672
42816
  };
42673
42817
  const activeAssetPayload = activeAssetResult?.payload ?? null;
@@ -43504,9 +43648,12 @@ async function postClientRuntime(path, profileId, body, options) {
43504
43648
  const numericProfileId = toNumericProfileId(profileId);
43505
43649
  const keepalive = options?.keepalive === true;
43506
43650
  const signal = options?.signal;
43651
+ const parsedRequestTimeoutMs = Number(options?.requestTimeoutMs);
43652
+ const requestTimeoutMs = Number.isFinite(parsedRequestTimeoutMs) && parsedRequestTimeoutMs > 0 ? Math.round(parsedRequestTimeoutMs) : null;
43507
43653
  const maxAttempts = keepalive ? 1 : 3;
43508
43654
  const requestContext = parseClientRuntimeRequestContext(body);
43509
- const idempotencyKey = shouldAttachRuntimeIdempotencyKey(path) ? createIdempotencyKey(`runtime-${path.replace(/\//g, "-")}`) : null;
43655
+ const explicitIdempotencyKey = String(options?.idempotencyKey ?? "").trim();
43656
+ const idempotencyKey = shouldAttachRuntimeIdempotencyKey(path) ? explicitIdempotencyKey || createIdempotencyKey(`runtime-${path.replace(/\//g, "-")}`) : null;
43510
43657
  const requestHeaders = getProfileHeaders({
43511
43658
  "Content-Type": "application/json"
43512
43659
  }, numericProfileId);
@@ -43523,6 +43670,24 @@ async function postClientRuntime(path, profileId, body, options) {
43523
43670
  let missingRuntimeLeaseRecoveryAttempted = false;
43524
43671
  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
43525
43672
  let response = null;
43673
+ let requestTimedOut = false;
43674
+ let timeoutId = null;
43675
+ let relayCallerAbort = null;
43676
+ let requestSignal = signal;
43677
+ if (requestTimeoutMs !== null) {
43678
+ const timeoutController = new AbortController();
43679
+ relayCallerAbort = () => timeoutController.abort(signal?.reason);
43680
+ if (signal?.aborted) {
43681
+ relayCallerAbort();
43682
+ } else {
43683
+ signal?.addEventListener("abort", relayCallerAbort, { once: true });
43684
+ }
43685
+ timeoutId = globalThis.setTimeout(() => {
43686
+ requestTimedOut = true;
43687
+ timeoutController.abort(new DOMException("Runtime request timeout reached.", "TimeoutError"));
43688
+ }, requestTimeoutMs);
43689
+ requestSignal = timeoutController.signal;
43690
+ }
43526
43691
  const trace = startRuntimeNetworkDebugTrace({
43527
43692
  kind: "runtime",
43528
43693
  label: "client_runtime_api",
@@ -43535,7 +43700,7 @@ async function postClientRuntime(path, profileId, body, options) {
43535
43700
  method: "POST",
43536
43701
  credentials: "include",
43537
43702
  keepalive,
43538
- signal,
43703
+ signal: requestSignal,
43539
43704
  headers: { ...requestHeaders },
43540
43705
  body
43541
43706
  });
@@ -43543,7 +43708,11 @@ async function postClientRuntime(path, profileId, body, options) {
43543
43708
  const error48 = await createRuntimeRequestError(response, "Client runtime request failed");
43544
43709
  if (!resolvedRuntimeLeaseToken && !missingRuntimeLeaseRecoveryAttempted && shouldRecoverMissingRuntimeLease(path, requestContext, keepalive) && isMissingRuntimeLeaseError(response.status, error48.message)) {
43545
43710
  missingRuntimeLeaseRecoveryAttempted = true;
43546
- const recoveredRuntimeLeaseToken = await recoverMissingRuntimeLease(numericProfileId, requestContext);
43711
+ const recoveredRuntimeLeaseToken = await recoverMissingRuntimeLease(
43712
+ numericProfileId,
43713
+ requestContext,
43714
+ requestSignal
43715
+ );
43547
43716
  if (recoveredRuntimeLeaseToken) {
43548
43717
  resolvedRuntimeLeaseToken = recoveredRuntimeLeaseToken;
43549
43718
  attachRuntimeLeaseHeader(requestHeaders, resolvedRuntimeLeaseToken);
@@ -43561,7 +43730,7 @@ async function postClientRuntime(path, profileId, body, options) {
43561
43730
  hadRuntimeLeaseToken: Boolean(resolvedRuntimeLeaseToken),
43562
43731
  leaseCleared: shouldClearLease
43563
43732
  });
43564
- if (!keepalive && attempt < maxAttempts && !shouldClearLease && shouldRetryClientRuntimeHttpStatus(path, response.status)) {
43733
+ if (!keepalive && attempt < maxAttempts && !shouldClearLease && (shouldRetryClientRuntimeHttpStatus(path, response.status) || isRuntimeIdempotencyInProgressError(response.status, error48.message) || Boolean(idempotencyKey) && isRetryableRuntimeConflictError(response.status, error48))) {
43565
43734
  await sleep2(resolveClientRuntimeRetryDelayMs(attempt, response.headers.get("Retry-After")));
43566
43735
  continue;
43567
43736
  }
@@ -43576,10 +43745,11 @@ async function postClientRuntime(path, profileId, body, options) {
43576
43745
  trace.completeSuccess(response.status);
43577
43746
  return payload;
43578
43747
  } catch (error48) {
43579
- lastNetworkError = error48;
43580
- trace.completeError(error48, response?.status ?? null);
43581
- if (!isTransientNetworkFetchError(error48) || attempt >= maxAttempts) {
43582
- throw annotateRuntimeRequestError(error48, {
43748
+ const requestError = requestTimedOut && !signal?.aborted ? new TypeError("Runtime request timeout reached.") : error48;
43749
+ lastNetworkError = requestError;
43750
+ trace.completeError(requestError, response?.status ?? null);
43751
+ if (signal?.aborted || !requestTimedOut && !isTransientNetworkFetchError(requestError) || attempt >= maxAttempts) {
43752
+ throw annotateRuntimeRequestError(requestError, {
43583
43753
  path,
43584
43754
  method: "POST",
43585
43755
  attempt,
@@ -43591,6 +43761,13 @@ async function postClientRuntime(path, profileId, body, options) {
43591
43761
  }
43592
43762
  await sleep2(resolveClientRuntimeRetryDelayMs(attempt, null));
43593
43763
  continue;
43764
+ } finally {
43765
+ if (timeoutId !== null) {
43766
+ globalThis.clearTimeout(timeoutId);
43767
+ }
43768
+ if (signal && relayCallerAbort) {
43769
+ signal.removeEventListener("abort", relayCallerAbort);
43770
+ }
43594
43771
  }
43595
43772
  }
43596
43773
  if (lastNetworkError instanceof Error) {
@@ -43793,7 +43970,7 @@ async function reconcileActiveClientRuntimeExchangeMutation(profileId, requestOp
43793
43970
  }
43794
43971
  return rememberCompletedDeferredClientRuntimeStop(profileId, result2);
43795
43972
  }
43796
- var getApiUrl, API_URL, sleep2, isTransientNetworkFetchError, createIdempotencyKey, getErrorMessage, getErrorPayloadOrEmpty, getErrorPayloadOrFallbackDetail, getErrorMessageFromResponse, _activeProfileId, PROFILE_STORAGE_KEY, preferencesWriteQueue, CLIENT_SUPPORTED_PROMPT_CONTRACT_VERSION, completedDeferredClientRuntimeStops, rememberCompletedDeferredClientRuntimeStop, toNumericProfileId, shouldAttachRuntimeIdempotencyKey, attachRuntimeLeaseHeader, resolveRuntimeLeaseToken, persistRuntimeLeaseFromPayload, persistRuntimeLeaseStatusMetadata, shouldClearPersistedRuntimeLeaseOnError, isMissingRuntimeLeaseError, createRuntimeRequestError, parseClientRuntimeRequestContext, recordRuntimeAuthFailureBreadcrumb, classifyRuntimeRequestError, annotateRuntimeRequestError, parseRuntimeRetryAfterMs, shouldRecoverMissingRuntimeLease, recoverMissingRuntimeLease, isRetryableClientRuntimeStatus, shouldRetryClientRuntimeHttpStatus, resolveClientRuntimeRetryDelayMs, CLIENT_EXCHANGE_AUTHORITY_DEVICE_KEY, CLIENT_EXCHANGE_AUTHORITY_SESSION_KEY, getOrCreateClientExchangeAuthorityIdentity, resolveClientExchangeMutationAuthority, clientExchangeMutationAuthorityBody, isPendingClientExchangeMutationError, clientExchangeMutationReconciliationTimers, MAX_CLIENT_EXCHANGE_RECONCILIATION_DELAY_MS, CLIENT_EXCHANGE_RECONCILIATION_CLOCK_SKEW_MS, ClientExchangeMutationRebuildRequiredError, isTerminalClientExchangeMutation, clientExchangeMutationReconciliationKey, clearScheduledClientExchangeMutationReconciliation, snapshotClientExchangeMutationReconciliationAuthority, postClientExchangeMutationReconciliation, scheduleClientExchangeMutationReconciliation;
43973
+ var getApiUrl, API_URL, sleep2, isTransientNetworkFetchError, createIdempotencyKey, getErrorMessage, getErrorPayloadOrEmpty, getErrorPayloadOrFallbackDetail, getErrorMessageFromResponse, _activeProfileId, PROFILE_STORAGE_KEY, preferencesWriteQueue, CLIENT_SUPPORTED_PROMPT_CONTRACT_VERSION, completedDeferredClientRuntimeStops, rememberCompletedDeferredClientRuntimeStop, toNumericProfileId, shouldAttachRuntimeIdempotencyKey, attachRuntimeLeaseHeader, resolveRuntimeLeaseToken, persistRuntimeLeaseFromPayload, persistRuntimeLeaseStatusMetadata, shouldClearPersistedRuntimeLeaseOnError, isMissingRuntimeLeaseError, createRuntimeRequestError, parseClientRuntimeRequestContext, recordRuntimeAuthFailureBreadcrumb, classifyRuntimeRequestError, annotateRuntimeRequestError, parseRuntimeRetryAfterMs, shouldRecoverMissingRuntimeLease, recoverMissingRuntimeLease, isRetryableClientRuntimeStatus, shouldRetryClientRuntimeHttpStatus, isRuntimeIdempotencyInProgressError, isRetryableRuntimeConflictError, resolveClientRuntimeRetryDelayMs, CLIENT_EXCHANGE_AUTHORITY_DEVICE_KEY, CLIENT_EXCHANGE_AUTHORITY_SESSION_KEY, getOrCreateClientExchangeAuthorityIdentity, resolveClientExchangeMutationAuthority, clientExchangeMutationAuthorityBody, isPendingClientExchangeMutationError, clientExchangeMutationReconciliationTimers, MAX_CLIENT_EXCHANGE_RECONCILIATION_DELAY_MS, CLIENT_EXCHANGE_RECONCILIATION_CLOCK_SKEW_MS, ClientExchangeMutationRebuildRequiredError, isTerminalClientExchangeMutation, clientExchangeMutationReconciliationKey, clearScheduledClientExchangeMutationReconciliation, snapshotClientExchangeMutationReconciliationAuthority, postClientExchangeMutationReconciliation, scheduleClientExchangeMutationReconciliation;
43797
43974
  var init_api2 = __esm({
43798
43975
  "lib/api.ts"() {
43799
43976
  "use strict";
@@ -43992,7 +44169,9 @@ var init_api2 = __esm({
43992
44169
  };
43993
44170
  isMissingRuntimeLeaseError = (statusCode, message) => statusCode === 401 && String(message ?? "").trim().toLowerCase().includes("runtime lease required");
43994
44171
  createRuntimeRequestError = async (response, defaultMessage) => {
43995
- const rawMessage = await getErrorMessageFromResponse(response, defaultMessage);
44172
+ const payload = await getErrorPayloadOrEmpty(response);
44173
+ const nestedDetail = payload.detail && typeof payload.detail === "object" && !Array.isArray(payload.detail) ? payload.detail : null;
44174
+ const rawMessage = getErrorMessage(payload, defaultMessage);
43996
44175
  const walletCohortMessage = response.status === 409 ? {
43997
44176
  client_wallet_unavailable: "The active profile wallet is unavailable. Save a wallet for this profile, then try again.",
43998
44177
  client_wallet_mismatch: "The active profile wallet does not match this Client Mode session. Reload the profile, then try again.",
@@ -44001,6 +44180,15 @@ var init_api2 = __esm({
44001
44180
  const message = walletCohortMessage ?? rawMessage;
44002
44181
  const error48 = new Error(message);
44003
44182
  error48.status = response.status;
44183
+ error48.detail = payload.detail;
44184
+ const code = typeof payload.code === "string" ? payload.code.trim() : typeof nestedDetail?.code === "string" ? nestedDetail.code.trim() : "";
44185
+ if (code) {
44186
+ error48.code = code;
44187
+ }
44188
+ const retryable = payload.retryable ?? nestedDetail?.retryable;
44189
+ if (typeof retryable === "boolean") {
44190
+ error48.retryable = retryable;
44191
+ }
44004
44192
  return error48;
44005
44193
  };
44006
44194
  parseClientRuntimeRequestContext = (body) => {
@@ -44101,7 +44289,7 @@ var init_api2 = __esm({
44101
44289
  }
44102
44290
  return path === "/runtime/heartbeat" || path === "/runtime/analyze" || path === "/runtime/prompt-contract/metadata" || path === "/runtime/prompt-contract/derived-context" || path === "/runtime/prompt" || path === "/runtime/decision" || path === "/runtime/error" || path === "/runtime/trade-sync";
44103
44291
  };
44104
- recoverMissingRuntimeLease = async (profileId, requestContext) => {
44292
+ recoverMissingRuntimeLease = async (profileId, requestContext, signal) => {
44105
44293
  if (!requestContext.sessionId || !requestContext.deviceId) {
44106
44294
  return null;
44107
44295
  }
@@ -44115,6 +44303,7 @@ var init_api2 = __esm({
44115
44303
  method: "POST",
44116
44304
  credentials: "include",
44117
44305
  cache: "no-store",
44306
+ signal,
44118
44307
  headers,
44119
44308
  body: JSON.stringify({
44120
44309
  session_id: requestContext.sessionId,
@@ -44129,7 +44318,10 @@ var init_api2 = __esm({
44129
44318
  return null;
44130
44319
  }
44131
44320
  payload = await response.json();
44132
- } catch {
44321
+ } catch (error48) {
44322
+ if (signal?.aborted) {
44323
+ throw signal.reason ?? error48;
44324
+ }
44133
44325
  return null;
44134
44326
  }
44135
44327
  persistRuntimeLeaseFromPayload(payload);
@@ -44150,6 +44342,8 @@ var init_api2 = __esm({
44150
44342
  }
44151
44343
  return true;
44152
44344
  };
44345
+ isRuntimeIdempotencyInProgressError = (status, message) => status === 409 && (message.toLowerCase().includes("duplicate request already in progress") || message.toLowerCase().includes("duplicate request in-flight"));
44346
+ isRetryableRuntimeConflictError = (status, error48) => status === 409 && error48.retryable === true && (error48.code === "profile_runtime_contract_busy" || error48.code === "runtime_trade_sync_finalizing");
44153
44347
  resolveClientRuntimeRetryDelayMs = (attempt, retryAfterHeader) => {
44154
44348
  const retryAfterMs = parseRuntimeRetryAfterMs(retryAfterHeader);
44155
44349
  if (retryAfterMs != null) {