@vtxmacro/cli 2026.10.10 → 2026.10.11

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
@@ -113,7 +113,7 @@ var init_routing = __esm({
113
113
  var agent_cli_release_default;
114
114
  var init_agent_cli_release = __esm({
115
115
  "agent-cli-release.json"() {
116
- agent_cli_release_default = { package_name: "@vtxmacro/cli", package_version: "2026.10.10", codex_package_name: "@openai/codex", codex_version: "0.155.0", copilot_sdk_package_name: "@github/copilot-sdk", copilot_sdk_version: "1.0.0-beta.8", copilot_cli_package_name: "@github/copilot", copilot_cli_version: "1.0.80", deepseek_harness_version: "0.1.1-rc.2", deepseek_harness_packages: ["@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-agent-instructions", "@deepseek-ai/dsh-agent-loop", "@deepseek-ai/dsh-agent-spine-demo", "@deepseek-ai/dsh-anonymous-user-id", "@deepseek-ai/dsh-atomic-write", "@deepseek-ai/dsh-attachment", "@deepseek-ai/dsh-brand", "@deepseek-ai/dsh-code-runtime", "@deepseek-ai/dsh-credentials", "@deepseek-ai/dsh-fs", "@deepseek-ai/dsh-goal", "@deepseek-ai/dsh-goal-round-driver", "@deepseek-ai/dsh-home-paths", "@deepseek-ai/dsh-invariants", "@deepseek-ai/dsh-jobs", "@deepseek-ai/dsh-jobs-local", "@deepseek-ai/dsh-launch-environment", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-llm-deepseek", "@deepseek-ai/dsh-llm-retry", "@deepseek-ai/dsh-output-retention", "@deepseek-ai/dsh-sandbox", "@deepseek-ai/dsh-sandbox-policy", "@deepseek-ai/dsh-scope", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-session-checkpoint-policy", "@deepseek-ai/dsh-session-persistence", "@deepseek-ai/dsh-session-persistence-jsonl", "@deepseek-ai/dsh-session-projection", "@deepseek-ai/dsh-session-title", "@deepseek-ai/dsh-settings", "@deepseek-ai/dsh-shell", "@deepseek-ai/dsh-shell-env", "@deepseek-ai/dsh-skill", "@deepseek-ai/dsh-skill-filesystem", "@deepseek-ai/dsh-subprocess", "@deepseek-ai/dsh-system-prompt", "@deepseek-ai/dsh-timeout", "@deepseek-ai/dsh-tool-bash", "@deepseek-ai/dsh-tool-goal", "@deepseek-ai/dsh-tool-jobs", "@deepseek-ai/dsh-tool-skill", "@deepseek-ai/dsh-tools", "@deepseek-ai/dsh-typert-protocol", "@deepseek-ai/dsh-user-approval"], deepseek_cordis_package_name: "@deepseek-ai/cordis", deepseek_cordis_version: "4.0.1", deepseek_support_packages: { "@deepseek-ai/cordis-plugin-timer": "1.1.3" }, platforms: { "linux-x64": { package_name: "@openai/codex-linux-x64", target: "x86_64-unknown-linux-musl", binary_name: "codex", sha256: "660e159a49e823ac8e5986cb238f73158ce4b957d40d9292f8de90862644b501" }, "win32-x64": { package_name: "@openai/codex-win32-x64", target: "x86_64-pc-windows-msvc", binary_name: "codex.exe", sha256: "e4c11374bd9de8ad5c3b7617fd4654bb7839901edb0863f9930666863c7a021b" } }, pi_coding_agent_package_name: "@earendil-works/pi-coding-agent", pi_ai_package_name: "@earendil-works/pi-ai", pi_version: "0.85.1", pi_support_packages: ["@earendil-works/pi-agent-core", "@earendil-works/pi-telemetry", "@earendil-works/pi-tui", "@earendil-works/chord"], grok_version: "1.0.30", grok_platforms: { "linux-x64": { package_name: "@xai-official/grok-linux-x64", binary_name: "grok", sha256: "504dd6546ab991b75d36698242875ce461489cd1f8cd84285873cb55bd5c7d54" }, "win32-x64": { package_name: "@xai-official/grok-win32-x64", binary_name: "grok.exe", sha256: "48736d1a4342a801ea26d0ecde4c516b653f791399065adaa55973f83abd8867" } } };
116
+ agent_cli_release_default = { package_name: "@vtxmacro/cli", package_version: "2026.10.11", codex_package_name: "@openai/codex", codex_version: "0.155.0", copilot_sdk_package_name: "@github/copilot-sdk", copilot_sdk_version: "1.0.0-beta.8", copilot_cli_package_name: "@github/copilot", copilot_cli_version: "1.0.80", deepseek_harness_version: "0.1.1-rc.2", deepseek_harness_packages: ["@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-agent-instructions", "@deepseek-ai/dsh-agent-loop", "@deepseek-ai/dsh-agent-spine-demo", "@deepseek-ai/dsh-anonymous-user-id", "@deepseek-ai/dsh-atomic-write", "@deepseek-ai/dsh-attachment", "@deepseek-ai/dsh-brand", "@deepseek-ai/dsh-code-runtime", "@deepseek-ai/dsh-credentials", "@deepseek-ai/dsh-fs", "@deepseek-ai/dsh-goal", "@deepseek-ai/dsh-goal-round-driver", "@deepseek-ai/dsh-home-paths", "@deepseek-ai/dsh-invariants", "@deepseek-ai/dsh-jobs", "@deepseek-ai/dsh-jobs-local", "@deepseek-ai/dsh-launch-environment", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-llm-deepseek", "@deepseek-ai/dsh-llm-retry", "@deepseek-ai/dsh-output-retention", "@deepseek-ai/dsh-sandbox", "@deepseek-ai/dsh-sandbox-policy", "@deepseek-ai/dsh-scope", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-session-checkpoint-policy", "@deepseek-ai/dsh-session-persistence", "@deepseek-ai/dsh-session-persistence-jsonl", "@deepseek-ai/dsh-session-projection", "@deepseek-ai/dsh-session-title", "@deepseek-ai/dsh-settings", "@deepseek-ai/dsh-shell", "@deepseek-ai/dsh-shell-env", "@deepseek-ai/dsh-skill", "@deepseek-ai/dsh-skill-filesystem", "@deepseek-ai/dsh-subprocess", "@deepseek-ai/dsh-system-prompt", "@deepseek-ai/dsh-timeout", "@deepseek-ai/dsh-tool-bash", "@deepseek-ai/dsh-tool-goal", "@deepseek-ai/dsh-tool-jobs", "@deepseek-ai/dsh-tool-skill", "@deepseek-ai/dsh-tools", "@deepseek-ai/dsh-typert-protocol", "@deepseek-ai/dsh-user-approval"], deepseek_cordis_package_name: "@deepseek-ai/cordis", deepseek_cordis_version: "4.0.1", deepseek_support_packages: { "@deepseek-ai/cordis-plugin-timer": "1.1.3" }, platforms: { "linux-x64": { package_name: "@openai/codex-linux-x64", target: "x86_64-unknown-linux-musl", binary_name: "codex", sha256: "660e159a49e823ac8e5986cb238f73158ce4b957d40d9292f8de90862644b501" }, "win32-x64": { package_name: "@openai/codex-win32-x64", target: "x86_64-pc-windows-msvc", binary_name: "codex.exe", sha256: "e4c11374bd9de8ad5c3b7617fd4654bb7839901edb0863f9930666863c7a021b" } }, pi_coding_agent_package_name: "@earendil-works/pi-coding-agent", pi_ai_package_name: "@earendil-works/pi-ai", pi_version: "0.85.1", pi_support_packages: ["@earendil-works/pi-agent-core", "@earendil-works/pi-telemetry", "@earendil-works/pi-tui", "@earendil-works/chord"], grok_version: "1.0.30", grok_platforms: { "linux-x64": { package_name: "@xai-official/grok-linux-x64", binary_name: "grok", sha256: "504dd6546ab991b75d36698242875ce461489cd1f8cd84285873cb55bd5c7d54" }, "win32-x64": { package_name: "@xai-official/grok-win32-x64", binary_name: "grok.exe", sha256: "48736d1a4342a801ea26d0ecde4c516b653f791399065adaa55973f83abd8867" } } };
117
117
  }
118
118
  });
119
119
 
@@ -50219,7 +50219,7 @@ function getProfileHeaders(baseHeaders = {}, explicitProfileId) {
50219
50219
  if (profileId) headers["x-profile-id"] = profileId.toString();
50220
50220
  return headers;
50221
50221
  }
50222
- var configuredApiTransport, getApiUrl, apiFetch, sleep, inFlightClientGetRequests, recentClientGetResponses, clientGetRequestGenerations, initializedClientGetRequestKeys, CLIENT_GET_DEDUPE_TTL_MS, CLIENT_LLM_CONFIG_PRIME_TTL_MS, AUTH_BOOTSTRAP_GET_MAX_ATTEMPTS, AUTH_BOOTSTRAP_RETRY_JITTER_MS, canUseClientGetRequestCache, invalidateClientGetRequestCache, raceWithAbortSignal, shareClientGetRequest, clientGetRequestKey, clientPreferencesRequestKey, invalidateClientPreferencesCache, parseRetryAfterMs2, resolveAuthBootstrapRetryDelayMs, fetchAuthBootstrapGetWithRetry, annotateMarketDataRequestError, buildMarketDataFetchError, buildMarketDataNetworkError, buildMarketDataResponseBodyError, isTransientNetworkFetchError, createIdempotencyKey, getErrorMessage, getErrorPayloadOrEmpty, getErrorPayloadOrFallbackDetail, getErrorMessageFromResponse, throwUnauthorizedIfNeeded, activeProfileId, PROFILE_STORAGE_KEY;
50222
+ var configuredApiTransport, getApiUrl, apiFetch, sleep, inFlightClientGetRequests, recentClientGetResponses, clientGetRequestGenerations, initializedClientGetRequestKeys, CLIENT_GET_DEDUPE_TTL_MS, CLIENT_RUNTIME_STATUSES_DEDUPE_TTL_MS, CLIENT_LLM_CONFIG_PRIME_TTL_MS, AUTH_BOOTSTRAP_GET_MAX_ATTEMPTS, AUTH_BOOTSTRAP_RETRY_JITTER_MS, canUseClientGetRequestCache, invalidateClientGetRequestCache, raceWithAbortSignal, shareClientGetRequest, clientGetRequestKey, clientPreferencesRequestKey, invalidateClientPreferencesCache, parseRetryAfterMs2, resolveAuthBootstrapRetryDelayMs, fetchAuthBootstrapGetWithRetry, annotateMarketDataRequestError, buildMarketDataFetchError, buildMarketDataNetworkError, buildMarketDataResponseBodyError, isTransientNetworkFetchError, createIdempotencyKey, getErrorMessage, getErrorPayloadOrEmpty, getErrorPayloadOrFallbackDetail, getErrorMessageFromResponse, throwUnauthorizedIfNeeded, activeProfileId, PROFILE_STORAGE_KEY;
50223
50223
  var init_shared = __esm({
50224
50224
  "lib/api/shared.ts"() {
50225
50225
  "use strict";
@@ -50259,6 +50259,7 @@ var init_shared = __esm({
50259
50259
  clientGetRequestGenerations = /* @__PURE__ */ new Map();
50260
50260
  initializedClientGetRequestKeys = /* @__PURE__ */ new Set();
50261
50261
  CLIENT_GET_DEDUPE_TTL_MS = 2e3;
50262
+ CLIENT_RUNTIME_STATUSES_DEDUPE_TTL_MS = 5e3;
50262
50263
  CLIENT_LLM_CONFIG_PRIME_TTL_MS = 1e4;
50263
50264
  AUTH_BOOTSTRAP_GET_MAX_ATTEMPTS = runtime_policy_generated_default2.ui.auth_bootstrap_retry.max_attempts;
50264
50265
  AUTH_BOOTSTRAP_RETRY_JITTER_MS = runtime_policy_generated_default2.ui.auth_bootstrap_retry.jitter_milliseconds;
@@ -84600,7 +84601,7 @@ var init_hyperliquid_signer = __esm({
84600
84601
  });
84601
84602
 
84602
84603
  // lib/runtime/hyperliquid-client.ts
84603
- var HyperliquidExchangeRejectionError, durableMutationAuthorityArgs, assertFreshPreparedExecutionContext, normalizeSymbol, HYPERLIQUID_NONCE_STORAGE_KEY, HYPERLIQUID_NONCE_LOCK_NAME, lastGeneratedNonce, readBrowserStoredHyperliquidNonce, writeBrowserStoredHyperliquidNonce, browserNonceCoordinator, allocateHyperliquidNonce, hostNonceAllocator, allocateActionNonce, generateHyperliquidNonce, normalizeDecimalString, HYPERLIQUID_PRICE_SIGNIFICANT_FIGURES, HYPERLIQUID_INTEGER_PRICE_MINIMUM, shortestDecimalParts, formatHyperliquidPerpPriceGrid, formatHyperliquidTriggerPriceWire, hyperliquidOrderPriceRounding, formatHyperliquidOrderPriceWire, countSignificantDigits, countDecimalPlaces, validateHyperliquidPerpPriceWire, validateHyperliquidSizeWire, formatSizeWire, inferApiUrl, inferIsTestnet, postHyperliquidInfoRead, postHyperliquidInfo, fetchBrowserHyperliquidInfoPayload, fetchBrowserHyperliquidInfoText, toFiniteNumber, OPEN_ORDER_NUMERIC_STRING, OPEN_ORDER_ID_STRING, parseCanonicalOpenOrderId, parseOpenOrderFiniteNumber, parseOpenOrderPositiveNumber, parseOpenOrderPresentationNumber, readOpenOrderField, firstFiniteNumber, parseFundingUsdcFromInfoPosition, isExchangeIsolatedOnly, computeHip3AssetId, getPerpDexIndexMap, buildAssetInfosFromMetaResponse, requireWalletAddress, assertPositiveInteger, assertPositiveNumber, normalizeOrderSide, normalizeHyperliquidClientOrderId, resolveAssets, findResolvedAsset, normalizeExecutionAssetMetadata, resolveHyperliquidAsset, resolveHyperliquidAssetIndex, decimalUnits, quantizeHyperliquidOrderSizeValue, hyperliquidSignedSizeMatchesRequestedSize, finitePositive, readDevicePrivateExecutionContext, quantizeHyperliquidOrderSize, fetchBrowserAvailableAssets, fetchBrowserAllMids, fetchBrowserSymbolMidPrice, fetchBrowserOpenOrders, parseCanonicalHyperliquidOrderStatusEvidence, fetchBrowserOrderStatusEvidence, fetchBrowserUserRole, fetchBrowserAccountState, fetchBrowserPosition, buildHyperliquidOrderWire, buildHyperliquidTriggerOrderWire, signHyperliquidPayload, signHyperliquidPreparedAction, buildHyperliquidCancelPayload, buildHyperliquidUpdateLeveragePayload, buildHyperliquidMarketOrderPayload, buildHyperliquidLimitOrderPayload, buildHyperliquidTriggerOrderPayload, buildHyperliquidOrderBatchPayload, buildHyperliquidModifyOrderPayload, extractHyperliquidExchangeError, resolveHyperliquidTriggerAcknowledgements, isDefinitiveHyperliquidExchangeResponse, extractDefinitiveHyperliquidOrderId, CANONICAL_POSITIVE_DECIMAL_PATTERN, extractCanonicalHyperliquidOrderStateAcknowledgement, extractCanonicalHyperliquidOrderStateAcknowledgements, extractCanonicalHyperliquidFilledOrderAcknowledgement, extractDefinitiveHyperliquidOrderMemberResults, buildHyperliquidOrderDiagnostics, loadClientExecutionReferenceEvidence, sha256Hex, extractSignedPayloadClientOrderId, extractSignedPayloadMutationCorrelation, assertDurableMutationMatchesSignedAction, exchangeRejectionReason, exchangeActionPriority, submitHyperliquidExchangePayload;
84604
+ var HyperliquidExchangeRejectionError, durableMutationAuthorityArgs, assertFreshPreparedExecutionContext, normalizeSymbol, HYPERLIQUID_NONCE_STORAGE_KEY, HYPERLIQUID_NONCE_LOCK_NAME, lastGeneratedNonce, readBrowserStoredHyperliquidNonce, writeBrowserStoredHyperliquidNonce, browserNonceCoordinator, allocateHyperliquidNonce, hostNonceAllocator, allocateActionNonce, generateHyperliquidNonce, normalizeDecimalString, HYPERLIQUID_PRICE_SIGNIFICANT_FIGURES, HYPERLIQUID_INTEGER_PRICE_MINIMUM, shortestDecimalParts, formatHyperliquidPerpPriceGrid, formatHyperliquidTriggerPriceWire, hyperliquidOrderPriceRounding, formatHyperliquidOrderPriceWire, countSignificantDigits, countDecimalPlaces, validateHyperliquidPerpPriceWire, validateHyperliquidSizeWire, formatSizeWire, inferApiUrl, inferIsTestnet, postHyperliquidInfoRead, postHyperliquidInfo, fetchBrowserHyperliquidInfoPayload, fetchBrowserHyperliquidInfoRead, fetchBrowserHyperliquidInfoText, toFiniteNumber, OPEN_ORDER_NUMERIC_STRING, OPEN_ORDER_ID_STRING, parseCanonicalOpenOrderId, parseOpenOrderFiniteNumber, parseOpenOrderPositiveNumber, parseOpenOrderPresentationNumber, readOpenOrderField, firstFiniteNumber, parseFundingUsdcFromInfoPosition, isExchangeIsolatedOnly, computeHip3AssetId, getPerpDexIndexMap, buildAssetInfosFromMetaResponse, requireWalletAddress, assertPositiveInteger, assertPositiveNumber, normalizeOrderSide, normalizeHyperliquidClientOrderId, resolveAssets, findResolvedAsset, normalizeExecutionAssetMetadata, resolveHyperliquidAsset, resolveHyperliquidAssetIndex, decimalUnits, quantizeHyperliquidOrderSizeValue, hyperliquidSignedSizeMatchesRequestedSize, finitePositive, readDevicePrivateExecutionContext, quantizeHyperliquidOrderSize, fetchBrowserAvailableAssets, fetchBrowserAllMids, fetchBrowserSymbolMidPrice, fetchBrowserOpenOrders, parseCanonicalHyperliquidOrderStatusEvidence, fetchBrowserOrderStatusEvidence, fetchBrowserUserRole, fetchBrowserAccountState, fetchBrowserPosition, buildHyperliquidOrderWire, buildHyperliquidTriggerOrderWire, signHyperliquidPayload, signHyperliquidPreparedAction, buildHyperliquidCancelPayload, buildHyperliquidUpdateLeveragePayload, buildHyperliquidMarketOrderPayload, buildHyperliquidLimitOrderPayload, buildHyperliquidTriggerOrderPayload, buildHyperliquidOrderBatchPayload, buildHyperliquidModifyOrderPayload, extractHyperliquidExchangeError, resolveHyperliquidTriggerAcknowledgements, isDefinitiveHyperliquidExchangeResponse, extractDefinitiveHyperliquidOrderId, CANONICAL_POSITIVE_DECIMAL_PATTERN, extractCanonicalHyperliquidOrderStateAcknowledgement, extractCanonicalHyperliquidOrderStateAcknowledgements, extractCanonicalHyperliquidFilledOrderAcknowledgement, extractDefinitiveHyperliquidOrderMemberResults, buildHyperliquidOrderDiagnostics, loadClientExecutionReferenceEvidence, sha256Hex, extractSignedPayloadClientOrderId, extractSignedPayloadMutationCorrelation, assertDurableMutationMatchesSignedAction, exchangeRejectionReason, exchangeActionPriority, submitHyperliquidExchangePayload;
84604
84605
  var init_hyperliquid_client = __esm({
84605
84606
  "lib/runtime/hyperliquid-client.ts"() {
84606
84607
  "use strict";
@@ -84852,13 +84853,14 @@ var init_hyperliquid_client = __esm({
84852
84853
  url: requestUrl
84853
84854
  });
84854
84855
  try {
84855
- const { payload, bodyText } = await readHyperliquidPublicInfo(apiUrl, body, {
84856
+ const { payload, bodyText, fetchedAtMs } = await readHyperliquidPublicInfo(apiUrl, body, {
84856
84857
  signal: input.signal,
84857
84858
  publicRequestPriority: input.publicRequestPriority,
84858
- includeBodyText
84859
+ includeBodyText,
84860
+ ...input.cacheAccountMode ? { cacheAccountMode: true } : {}
84859
84861
  });
84860
84862
  trace.completeSuccess(200);
84861
- return { payload, bodyText };
84863
+ return { payload, bodyText, fetchedAtMs };
84862
84864
  } catch (error48) {
84863
84865
  const sanitizedError = toSanitizedRuntimeError(error48);
84864
84866
  trace.completeError(sanitizedError, error48?.status ?? null);
@@ -84867,6 +84869,10 @@ var init_hyperliquid_client = __esm({
84867
84869
  };
84868
84870
  postHyperliquidInfo = async (input, body, label2) => (await postHyperliquidInfoRead(input, body, label2)).payload;
84869
84871
  fetchBrowserHyperliquidInfoPayload = (input, body, label2) => postHyperliquidInfo(input, body, label2);
84872
+ fetchBrowserHyperliquidInfoRead = async (input, body, label2) => {
84873
+ const { payload, fetchedAtMs } = await postHyperliquidInfoRead(input, body, label2);
84874
+ return { payload, fetchedAtMs };
84875
+ };
84870
84876
  fetchBrowserHyperliquidInfoText = async (input, body, label2) => {
84871
84877
  const { bodyText } = await postHyperliquidInfoRead(input, body, label2, true);
84872
84878
  if (typeof bodyText !== "string") throw new Error("Hyperliquid returned no response text.");
@@ -86928,14 +86934,14 @@ var init_exchange_mutation_evidence = __esm({
86928
86934
  const wallet = String(input.required.wallet_address ?? "").trim();
86929
86935
  if (!wallet) throw new Error("Missing wallet address for reconciliation evidence.");
86930
86936
  const apiUrl = await resolveHyperliquidApiUrl(input.profileId, input.required.hyperliquid_api_url, input.signal);
86931
- const readInput2 = { apiUrl, signal: input.signal, publicRequestPriority: "trading_reconcile" };
86937
+ const readInput = { apiUrl, signal: input.signal, publicRequestPriority: "trading_reconcile" };
86932
86938
  const startedAtMonotonicMs = monotonicNowMs();
86933
86939
  const observedAt = (/* @__PURE__ */ new Date()).toISOString();
86934
86940
  const orderStatuses = await Promise.all((input.required.order_refs ?? []).map(async (ref) => {
86935
86941
  const orderRef = String(ref).trim();
86936
86942
  const oid = /^\d+$/.test(orderRef) ? Number(orderRef) : orderRef;
86937
86943
  const response = await fetchBrowserHyperliquidInfoPayload(
86938
- readInput2,
86944
+ readInput,
86939
86945
  { type: "orderStatus", user: wallet, oid },
86940
86946
  "hyperliquid.orderStatus"
86941
86947
  );
@@ -86943,7 +86949,7 @@ var init_exchange_mutation_evidence = __esm({
86943
86949
  }));
86944
86950
  const coin = String(input.required.active_asset_coin ?? "").trim();
86945
86951
  const activeAssetData = coin ? await fetchBrowserHyperliquidInfoPayload(
86946
- readInput2,
86952
+ readInput,
86947
86953
  { type: "activeAssetData", user: wallet, coin },
86948
86954
  "hyperliquid.activeAssetData"
86949
86955
  ) : null;
@@ -86961,6 +86967,27 @@ var init_exchange_mutation_evidence = __esm({
86961
86967
  });
86962
86968
 
86963
86969
  // lib/api.ts
86970
+ async function reportServerBackupReadiness(profileId, ready, hostId, signal, power) {
86971
+ const response = await apiFetch(`${getApiUrl()}/trading/ai/client/server-backup/readiness`, {
86972
+ method: "POST",
86973
+ headers: getProfileHeaders({ "Content-Type": "application/json" }, profileId),
86974
+ credentials: "include",
86975
+ // A host too low on battery to take a runtime over is not ready to take a backup back.
86976
+ body: JSON.stringify({
86977
+ ready,
86978
+ host_id: hostId,
86979
+ ...power ? {
86980
+ power_source: power.source,
86981
+ ...typeof power.batteryPercent === "number" ? { battery_percent: power.batteryPercent } : {}
86982
+ } : {}
86983
+ }),
86984
+ signal
86985
+ });
86986
+ if (!response.ok) {
86987
+ throw new Error(await getErrorMessageFromResponse(response, "Failed to report client readiness"));
86988
+ }
86989
+ return response.json();
86990
+ }
86964
86991
  function relayNativeProviderRequest(provider, apiKey, payload, options = {}) {
86965
86992
  return apiFetch(`${getApiUrl()}/llm/native-provider-relay`, {
86966
86993
  method: "POST",
@@ -87031,6 +87058,21 @@ async function getClientRuntimeSecrets(profileId, options) {
87031
87058
  client_runtime_secret_version: fetchedPayload.client_runtime_secret_version
87032
87059
  };
87033
87060
  }
87061
+ async function getLocalAiEndpointSecret(baseUrl, profileId, signal) {
87062
+ const params = new URLSearchParams({ base_url: baseUrl });
87063
+ const response = await apiFetch(`${getApiUrl()}/auth/me/local-ai-endpoint-secret?${params.toString()}`, {
87064
+ method: "GET",
87065
+ cache: "no-store",
87066
+ headers: clientRuntimeSecretHeaders(profileId),
87067
+ credentials: "include",
87068
+ signal
87069
+ });
87070
+ if (!response.ok) {
87071
+ const message = await getErrorMessageFromResponse(response, "Failed to fetch Local AI endpoint secret", { fallbackDetail: true });
87072
+ throw new Error(message);
87073
+ }
87074
+ return response.json();
87075
+ }
87034
87076
  async function getPreferences(cookie, profileId, signal, includeTradeLayouts = false, runtimeAuthority) {
87035
87077
  const effectiveProfileId = profileId ?? getActiveProfileId() ?? null;
87036
87078
  const schedulerInstanceId = String(runtimeAuthority?.schedulerInstanceId ?? "").trim() || void 0;
@@ -87099,7 +87141,8 @@ async function pollCopyTradingRuntimeSource(profileId, options) {
87099
87141
  body: JSON.stringify({
87100
87142
  dry_run: Boolean(options?.dryRun),
87101
87143
  force_refresh: Boolean(options?.forceRefresh),
87102
- ...options?.maxEvents ? { max_events: options.maxEvents } : {}
87144
+ ...options?.maxEvents ? { max_events: options.maxEvents } : {},
87145
+ ...options?.accountEvidence ? { account_evidence: options.accountEvidence } : {}
87103
87146
  }),
87104
87147
  credentials: "include",
87105
87148
  cache: "no-store",
@@ -87522,6 +87565,10 @@ async function claimClientRuntime(profileId, payload, options) {
87522
87565
  kind: payload.kind,
87523
87566
  takeover: payload.kind === "explicit" && payload.takeover === true,
87524
87567
  ...payload.claimSurface ? { claim_surface: payload.claimSurface } : {},
87568
+ ...payload.power ? {
87569
+ power_source: payload.power.source,
87570
+ ...typeof payload.power.batteryPercent === "number" ? { battery_percent: payload.power.batteryPercent } : {}
87571
+ } : {},
87525
87572
  // This build signs server-issued TP/SL actions; a profile whose
87526
87573
  // protection the server owns admits only claims that say so.
87527
87574
  client_protection_capability_version: CLIENT_PROTECTION_CAPABILITY_VERSION
@@ -88440,6 +88487,41 @@ async function fetchClientRuntimeKillswitchContext(profileId, payload, options)
88440
88487
  options
88441
88488
  );
88442
88489
  }
88490
+ async function getClientRuntimeStatuses(profileIds, signal, options) {
88491
+ const normalizedProfileIds = [...new Set(profileIds)].sort((left, right) => left - right);
88492
+ const params = new URLSearchParams();
88493
+ for (const profileId of normalizedProfileIds) {
88494
+ params.append("profile_id", String(profileId));
88495
+ }
88496
+ const viewer = resolveClientRuntimeStatusViewerHeaders(options?.runtimeViewer);
88497
+ const requestKey = `client-runtime-statuses:${normalizedProfileIds.join(",")}${viewer.requestKey}`;
88498
+ return shareClientGetRequest(requestKey, async () => {
88499
+ const headers = { ...viewer.headers };
88500
+ const response = await apiFetch(
88501
+ `${getApiUrl()}/trading/ai/runtime/statuses?${params.toString()}`,
88502
+ {
88503
+ method: "GET",
88504
+ credentials: "include",
88505
+ cache: "no-store",
88506
+ headers,
88507
+ // Without the browser's shared request a caller's abort ends the request too.
88508
+ signal: typeof window === "undefined" ? signal : void 0
88509
+ }
88510
+ );
88511
+ if (!response.ok) {
88512
+ const error48 = await createRuntimeRequestError(response, "Failed to fetch client runtime statuses");
88513
+ throw error48;
88514
+ }
88515
+ return response.json();
88516
+ }, {
88517
+ signal,
88518
+ shareAbortScoped: true,
88519
+ // A host-named read decides whether that host claims: it must see an
88520
+ // intent change made a moment ago, so it shares only an in-flight read
88521
+ // and never reuses a finished one.
88522
+ ttlMs: viewer.requestKey ? 0 : CLIENT_RUNTIME_STATUSES_DEDUPE_TTL_MS
88523
+ });
88524
+ }
88443
88525
  var clientRuntimeSecretHeaders, preferencesWriteQueue, getCopyTradingRuntimeLeaseToken, getCopyTradingSchedulerInstanceId, resolveClientRuntimeStatusViewerHeaders, CLIENT_SUPPORTED_PROMPT_CONTRACT_VERSION, CLIENT_PROTECTION_CAPABILITY_VERSION, completedDeferredClientRuntimeStops, rememberCompletedDeferredClientRuntimeStop, consumeCompletedDeferredClientRuntimeStop, toNumericProfileId, buildClientRuntimeBody, shouldAttachRuntimeIdempotencyKey, attachRuntimeLeaseHeader, attachRuntimeSchedulerInstanceHeader, resolveRuntimeLeaseToken, resolveSchedulerBoundRuntimeLeaseToken, persistRuntimeLeaseFromPayload, persistRuntimeLeaseStatusMetadata, shouldClearPersistedRuntimeLeaseOnError, createRuntimeRequestError, parseClientRuntimeRequestContext, recordRuntimeAuthFailureBreadcrumb, classifyRuntimeRequestError, annotateRuntimeRequestError, parseRuntimeRetryAfterMs, isRetryableClientRuntimeStatus, shouldRetryClientRuntimeHttpStatus, isRuntimeIdempotencyInProgressError, isRetryableRuntimeConflictError, resolveClientRuntimeRetryDelayMs, reconcilePendingClientExchangeMutation, CLIENT_RUNTIME_CLAIM_EXCHANGE_MUTATION_WAIT_CODES, CLIENT_EXCHANGE_AUTHORITY_DEVICE_KEY, CLIENT_EXCHANGE_AUTHORITY_SESSION_KEY, getOrCreateClientExchangeAuthorityIdentity, resolveClientExchangeMutationAuthority, pinClientExchangeMutationAuthority, CLIENT_EXCHANGE_MUTATION_AUTHORITY_MISMATCH, isClientExchangeMutationAuthorityConflict, handOffClientExchangeMutationToReconciliation, clientExchangeMutationAuthorityBody, isPendingClientExchangeMutationError, isMissingActiveClientExchangeMutationError, clientExchangeMutationReconciliationTimers, MAX_CLIENT_EXCHANGE_RECONCILIATION_DELAY_MS, CLIENT_EXCHANGE_RECONCILIATION_CLOCK_SKEW_MS, ClientExchangeMutationRebuildRequiredError, isTerminalClientExchangeMutation, clientExchangeMutationReconciliationKey, clearScheduledClientExchangeMutationReconciliation, snapshotClientExchangeMutationReconciliationAuthority, completeClientExchangeMutationReconciliation, protectiveBoundClientExchangeMutations, rememberProtectiveBoundClientExchangeMutation, isProtectiveBoundClientExchangeMutation, postClientExchangeMutationReconciliation, scheduleClientExchangeMutationReconciliation;
88444
88526
  var init_api2 = __esm({
88445
88527
  "lib/api.ts"() {
@@ -88495,10 +88577,17 @@ var init_api2 = __esm({
88495
88577
  if (!deviceId) return { headers: {}, requestKey: "" };
88496
88578
  const sessionId = String(viewer?.sessionId ?? "").trim();
88497
88579
  const surface = String(viewer?.surface ?? "").trim();
88580
+ const power = viewer?.power?.source ?? "";
88581
+ const batteryPercent = viewer?.power?.batteryPercent;
88498
88582
  const headers = { "x-client-runtime-device-id": deviceId };
88499
88583
  if (sessionId) headers["x-client-runtime-session-id"] = sessionId;
88500
88584
  if (surface) headers["x-client-runtime-surface"] = surface;
88501
- return { headers, requestKey: `:viewer:${deviceId}:${sessionId}:${surface}` };
88585
+ if (power) headers["x-client-runtime-power"] = power;
88586
+ if (typeof batteryPercent === "number") headers["x-client-runtime-battery-percent"] = String(batteryPercent);
88587
+ return {
88588
+ headers,
88589
+ requestKey: `:viewer:${deviceId}:${sessionId}:${surface}:${power}:${batteryPercent ?? ""}`
88590
+ };
88502
88591
  };
88503
88592
  CLIENT_SUPPORTED_PROMPT_CONTRACT_VERSION = String(
88504
88593
  process.env.NEXT_PUBLIC_CLIENT_RUNTIME_PROMPT_CONTRACT_VERSION || "2026-08-24.1"
@@ -89481,7 +89570,7 @@ var init_sort_utils = __esm({
89481
89570
  });
89482
89571
 
89483
89572
  // lib/local-ai.ts
89484
- var LOCAL_SOURCE_ALIASES, LOCAL_CONTEXT_CACHE_TTL_MS, LOCAL_AI_SERVER_TYPE_ALIASES, LOCAL_AI_ROOT_SUFFIXES, normalizeLocalAiServerType, assertSupportedLocalAiServerType, resolveLocalAiServerTypeInput, stripLocalAiKnownSuffix, getLocalAiRootUrl, normalizeLocalModelSource, isLocalModelSource, isClientOnlyModelSource, normalizeLocalAiBaseUrl, endpointOrigin, sameEndpointOriginKey, normalizeOpenAiCompatibleBaseUrl;
89573
+ var LOCAL_SOURCE_ALIASES, LOCAL_CONTEXT_CACHE_TTL_MS, LOCAL_AI_SERVER_TYPE_ALIASES, LOCAL_AI_ROOT_SUFFIXES, normalizeLocalAiServerType, assertSupportedLocalAiServerType, resolveLocalAiServerTypeInput, stripLocalAiKnownSuffix, getLocalAiRootUrl, normalizeLocalModelSource, isLocalModelSource, isClientOnlyModelSource, normalizeLocalAiBaseUrl, endpointOrigin, sameEndpointOriginKey, normalizeOpenAiCompatibleBaseUrl, buildLocalAiModelsEndpointForServerType;
89485
89574
  var init_local_ai = __esm({
89486
89575
  "lib/local-ai.ts"() {
89487
89576
  "use strict";
@@ -89608,6 +89697,14 @@ var init_local_ai = __esm({
89608
89697
  return null;
89609
89698
  }
89610
89699
  };
89700
+ buildLocalAiModelsEndpointForServerType = (baseUrl, serverType) => {
89701
+ assertSupportedLocalAiServerType(serverType);
89702
+ const normalizedBaseUrl = normalizeLocalAiBaseUrl(baseUrl);
89703
+ if (!normalizedBaseUrl) {
89704
+ return null;
89705
+ }
89706
+ return normalizedBaseUrl.toLowerCase().endsWith("/models") ? normalizedBaseUrl : `${normalizedBaseUrl}/models`;
89707
+ };
89611
89708
  }
89612
89709
  });
89613
89710
 
@@ -92161,7 +92258,7 @@ var init_hyperliquid_account_state_adapter = __esm({
92161
92258
  });
92162
92259
 
92163
92260
  // lib/runtime/protective-evidence.ts
92164
- var protectivePolicy, MAX_PROTECTIVE_EVIDENCE_ITEMS_PER_REPORT, EVIDENCE_FAILURE_BACKOFF_MS, STALE_EVIDENCE_CODE, SHARED_ACCOUNT_READ_MS, sharedAccountReads, EVIDENCE_READ_PRIORITY, MIN_EVIDENCE_SWEEP_DELAY_MS, evidenceBackoffUntil, errorCode, parseDueAtMs, boundedEvidenceSweepAtMs, authorityArgs, dexBody, readInput, evidenceItems, readOrNull, reportBody, readEvidenceBatch, withEvidenceReporterLock, reportDueClientProtectiveEvidence, readClientProtectiveOpenOrdersEvidence, openOrdersEvidenceForUpload;
92261
+ var protectivePolicy, MAX_PROTECTIVE_EVIDENCE_ITEMS_PER_REPORT, EVIDENCE_FAILURE_BACKOFF_MS, STALE_EVIDENCE_CODE, SHARED_ACCOUNT_READ_MS, sharedAccountReads, EVIDENCE_READ_PRIORITY, MIN_EVIDENCE_SWEEP_DELAY_MS, evidenceBackoffUntil, errorCode, parseDueAtMs, boundedEvidenceSweepAtMs, authorityArgs, dexBody, isEvidenceOrderRef, orderStatusOid, evidenceReadInput, evidenceItems, readOrNull, reportBody, readEvidenceBatch, withEvidenceReporterLock, reportDueClientProtectiveEvidence, readClientProtectiveOpenOrdersEvidence, openOrdersEvidenceForUpload;
92165
92262
  var init_protective_evidence = __esm({
92166
92263
  "lib/runtime/protective-evidence.ts"() {
92167
92264
  "use strict";
@@ -92201,7 +92298,9 @@ var init_protective_evidence = __esm({
92201
92298
  return scheduler ? [session, lease, device, scheduler] : [session, lease, device];
92202
92299
  };
92203
92300
  dexBody = (dex) => dex ? { dex } : {};
92204
- readInput = (context) => {
92301
+ isEvidenceOrderRef = (orderRef) => /^\d+$/.test(orderRef) && Number.isSafeInteger(Number(orderRef)) || /^0x[0-9a-fA-F]{32}$/.test(orderRef);
92302
+ orderStatusOid = (orderRef) => /^\d+$/.test(orderRef) ? Number(orderRef) : orderRef;
92303
+ evidenceReadInput = (context) => {
92205
92304
  const apiUrl = String(context.hyperliquidApiUrl ?? "").trim();
92206
92305
  return {
92207
92306
  config: context.config,
@@ -92216,7 +92315,7 @@ var init_protective_evidence = __esm({
92216
92315
  const dex = String(request.dex ?? "").trim();
92217
92316
  if (request.kind === "order_status") {
92218
92317
  const orderRef = String(request.order_ref ?? "").trim();
92219
- if (!/^\d+$/.test(orderRef) && !/^0x[0-9a-fA-F]{32}$/.test(orderRef)) continue;
92318
+ if (!isEvidenceOrderRef(orderRef)) continue;
92220
92319
  const key = `order_status:${orderRef}`;
92221
92320
  const existing = items.get(key);
92222
92321
  items.set(key, {
@@ -92257,7 +92356,7 @@ var init_protective_evidence = __esm({
92257
92356
  observed_age_ms: monotonicAgeMs(batch.startedAtMonotonicMs)
92258
92357
  });
92259
92358
  readEvidenceBatch = async (context, wallet, batch) => {
92260
- const input = readInput(context);
92359
+ const input = evidenceReadInput(context);
92261
92360
  let startedAtMonotonicMs = monotonicNowMs();
92262
92361
  const observedAt = (/* @__PURE__ */ new Date()).toISOString();
92263
92362
  const perDex = /* @__PURE__ */ new Map();
@@ -92289,7 +92388,7 @@ var init_protective_evidence = __esm({
92289
92388
  const markets = [];
92290
92389
  await Promise.all(batch.map(async (item) => {
92291
92390
  if (item.kind === "order_status") {
92292
- const oid = /^\d+$/.test(item.orderRef) ? Number(item.orderRef) : item.orderRef;
92391
+ const oid = orderStatusOid(item.orderRef);
92293
92392
  const response = await readOrNull(() => fetchBrowserHyperliquidInfoPayload(
92294
92393
  input,
92295
92394
  { type: "orderStatus", user: wallet, oid },
@@ -92408,7 +92507,7 @@ var init_protective_evidence = __esm({
92408
92507
  readClientProtectiveOpenOrdersEvidence = async (context, dexes) => {
92409
92508
  const wallet = String(context.walletAddress ?? "").trim();
92410
92509
  if (!wallet) throw new Error("Missing Hyperliquid wallet address for open-orders evidence.");
92411
- const input = readInput(context);
92510
+ const input = evidenceReadInput(context);
92412
92511
  return Promise.all([...new Set(dexes.map((dex) => String(dex ?? "").trim()))].map(async (dex) => {
92413
92512
  const startedAtMonotonicMs = monotonicNowMs();
92414
92513
  const observedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -93126,6 +93225,189 @@ var init_execution_guard_contract = __esm({
93126
93225
  }
93127
93226
  });
93128
93227
 
93228
+ // lib/runtime/copy-trading-evidence.ts
93229
+ var ACCOUNT_MODE_CACHE_MS, dexList, normalizeRequest, openOrderRefs, EvidenceReadFailed, readClientCopyTradingAccountEvidence, accountEvidenceForUpload, readCopyOrderStatusEvidence, orderStatusEvidenceForAck;
93230
+ var init_copy_trading_evidence = __esm({
93231
+ "lib/runtime/copy-trading-evidence.ts"() {
93232
+ "use strict";
93233
+ init_define_VTX_EXO_POLICY();
93234
+ init_define_VTX_GROK_POLICY();
93235
+ init_define_VTX_PI_MODEL_POLICY();
93236
+ init_runtime_policy_generated2();
93237
+ init_hyperliquid_account_mode_contract();
93238
+ init_hyperliquid_client();
93239
+ init_monotonic_clock();
93240
+ init_protective_evidence();
93241
+ ACCOUNT_MODE_CACHE_MS = runtime_policy_generated_default2.exchange.hyperliquid.client_public_read_budget.account_mode_ttl_seconds * 1e3;
93242
+ dexList = (value) => {
93243
+ if (!Array.isArray(value) || value.some((dex) => typeof dex !== "string")) return null;
93244
+ return [...new Set(value.map((dex) => dex.trim()))];
93245
+ };
93246
+ normalizeRequest = (request) => {
93247
+ if (!request || typeof request !== "object") return null;
93248
+ const requestId = typeof request.request_id === "string" ? request.request_id.trim() : "";
93249
+ const walletAddress = typeof request.wallet_address === "string" ? request.wallet_address.trim() : "";
93250
+ const dexes = dexList(request.dexes);
93251
+ const openOrdersDexes = dexList(request.open_orders_dexes);
93252
+ const maxAgeSeconds = Number(request.max_age_seconds);
93253
+ if (!requestId || !walletAddress || !dexes || !openOrdersDexes || !Array.isArray(request.order_refs) || !Number.isFinite(maxAgeSeconds) || maxAgeSeconds <= 0) return null;
93254
+ const orderRefs = /* @__PURE__ */ new Map();
93255
+ for (const entry of request.order_refs) {
93256
+ const orderRef = typeof entry?.order_ref === "string" ? entry.order_ref.trim() : "";
93257
+ const dex = typeof entry?.dex === "string" ? entry.dex.trim() : null;
93258
+ if (dex == null || !isEvidenceOrderRef(orderRef)) return null;
93259
+ orderRefs.set(`${dex}|${orderRef.toLowerCase()}`, { orderRef, dex });
93260
+ }
93261
+ return {
93262
+ requestId,
93263
+ walletAddress,
93264
+ dexes,
93265
+ accountMode: request.account_mode === true,
93266
+ openOrdersDexes,
93267
+ orderRefs: [...orderRefs.values()],
93268
+ maxAgeMs: maxAgeSeconds * 1e3
93269
+ };
93270
+ };
93271
+ openOrderRefs = (response) => {
93272
+ if (!Array.isArray(response)) return null;
93273
+ const refs = /* @__PURE__ */ new Set();
93274
+ for (const order of response) {
93275
+ if (!order || typeof order !== "object") continue;
93276
+ const { oid, cloid } = order;
93277
+ if (oid != null && oid !== "") refs.add(String(oid).trim().toLowerCase());
93278
+ if (typeof cloid === "string" && cloid.trim()) refs.add(cloid.trim().toLowerCase());
93279
+ }
93280
+ return refs;
93281
+ };
93282
+ EvidenceReadFailed = class extends Error {
93283
+ };
93284
+ readClientCopyTradingAccountEvidence = async (context) => {
93285
+ const request = normalizeRequest(context.request);
93286
+ if (!request) return { ok: false, reason: "invalid_request" };
93287
+ const trustedWallet = String(context.trustedWalletAddress ?? "").trim();
93288
+ if (!trustedWallet || trustedWallet.toLowerCase() !== request.walletAddress.toLowerCase()) {
93289
+ return { ok: false, reason: "wallet_mismatch" };
93290
+ }
93291
+ if (context.signal?.aborted) return { ok: false, reason: "aborted" };
93292
+ const controller = new AbortController();
93293
+ const parentSignal = context.signal;
93294
+ const cancelReads = () => controller.abort(parentSignal?.reason);
93295
+ parentSignal?.addEventListener("abort", cancelReads, { once: true });
93296
+ const input = evidenceReadInput({ ...context, signal: controller.signal });
93297
+ const user = trustedWallet;
93298
+ let startedAtMonotonicMs = monotonicNowMs();
93299
+ const read = async (body, label2) => {
93300
+ try {
93301
+ const response = await fetchBrowserHyperliquidInfoPayload(input, body, label2);
93302
+ if (response == null) throw new EvidenceReadFailed(label2);
93303
+ return response;
93304
+ } catch (error48) {
93305
+ controller.abort();
93306
+ throw error48;
93307
+ }
93308
+ };
93309
+ const cacheAccountMode = ACCOUNT_MODE_CACHE_MS * 2 <= request.maxAgeMs;
93310
+ const readAccountMode = async (body, label2) => {
93311
+ const calledAtWallMs = Date.now();
93312
+ const calledAtMonotonicMs = monotonicNowMs();
93313
+ try {
93314
+ const { payload, fetchedAtMs } = await fetchBrowserHyperliquidInfoRead({ ...input, cacheAccountMode }, body, label2);
93315
+ if (Number.isFinite(fetchedAtMs) && fetchedAtMs < calledAtWallMs) {
93316
+ startedAtMonotonicMs = Math.min(startedAtMonotonicMs, calledAtMonotonicMs - (calledAtWallMs - fetchedAtMs));
93317
+ }
93318
+ return payload;
93319
+ } catch (error48) {
93320
+ controller.abort();
93321
+ throw error48;
93322
+ }
93323
+ };
93324
+ try {
93325
+ const clearinghouseStates = Promise.all(request.dexes.map(async (dex) => ({
93326
+ dex,
93327
+ response: await read({ type: "clearinghouseState", user, ...dexBody(dex) }, "hyperliquid.clearinghouseState")
93328
+ })));
93329
+ const accountMode = request.accountMode ? (async () => {
93330
+ const userAbstraction = await readAccountMode({ type: "userAbstraction", user }, "hyperliquid.userAbstraction");
93331
+ const mode2 = extractCanonicalHyperliquidAccountMode(userAbstraction);
93332
+ if (!mode2) throw new EvidenceReadFailed("hyperliquid.userAbstraction");
93333
+ const userDexAbstraction = mode2 === "default" || mode2 === "disabled" ? await readAccountMode({ type: "userDexAbstraction", user }, "hyperliquid.userDexAbstraction") : null;
93334
+ return { userAbstraction, userDexAbstraction };
93335
+ })() : Promise.resolve({ userAbstraction: null, userDexAbstraction: null });
93336
+ const openOrders = Promise.all(request.openOrdersDexes.map(async (dex) => {
93337
+ const response = await read({ type: "frontendOpenOrders", user, ...dexBody(dex) }, "hyperliquid.frontendOpenOrders");
93338
+ const refs = openOrderRefs(response);
93339
+ if (!refs) throw new EvidenceReadFailed("hyperliquid.frontendOpenOrders");
93340
+ return { dex, response, refs };
93341
+ }));
93342
+ const orderStatuses = openOrders.then((orders2) => {
93343
+ const openByDex = new Map(orders2.map((order) => [order.dex, order.refs]));
93344
+ return Promise.all(request.orderRefs.filter(({ orderRef, dex }) => !openByDex.get(dex)?.has(orderRef.toLowerCase())).map(async ({ orderRef, dex }) => ({
93345
+ order_ref: orderRef,
93346
+ dex,
93347
+ response: await read(
93348
+ { type: "orderStatus", user, oid: orderStatusOid(orderRef) },
93349
+ "hyperliquid.orderStatus"
93350
+ )
93351
+ })));
93352
+ });
93353
+ const [states, mode, orders, statuses] = await Promise.all([
93354
+ clearinghouseStates,
93355
+ accountMode,
93356
+ openOrders,
93357
+ orderStatuses
93358
+ ]);
93359
+ if (parentSignal?.aborted) return { ok: false, reason: "aborted" };
93360
+ if (monotonicAgeMs(startedAtMonotonicMs) > request.maxAgeMs) return { ok: false, reason: "stale" };
93361
+ return {
93362
+ ok: true,
93363
+ read: {
93364
+ evidence: {
93365
+ request_id: request.requestId,
93366
+ wallet_address: request.walletAddress,
93367
+ source: "live",
93368
+ clearinghouse_states: states,
93369
+ user_abstraction: mode.userAbstraction,
93370
+ user_dex_abstraction: mode.userDexAbstraction,
93371
+ open_orders: orders.map(({ dex, response }) => ({ dex, response })),
93372
+ order_statuses: statuses
93373
+ },
93374
+ startedAtMonotonicMs
93375
+ }
93376
+ };
93377
+ } catch {
93378
+ return { ok: false, reason: parentSignal?.aborted ? "aborted" : "read_failed" };
93379
+ } finally {
93380
+ parentSignal?.removeEventListener("abort", cancelReads);
93381
+ }
93382
+ };
93383
+ accountEvidenceForUpload = (read) => ({
93384
+ ...read.evidence,
93385
+ observed_age_ms: monotonicAgeMs(read.startedAtMonotonicMs)
93386
+ });
93387
+ readCopyOrderStatusEvidence = async (context, orderId) => {
93388
+ const user = String(context.walletAddress ?? "").trim();
93389
+ const orderRef = String(orderId).trim();
93390
+ if (!user || !isEvidenceOrderRef(orderRef) || context.signal?.aborted) return null;
93391
+ const startedAtMonotonicMs = monotonicNowMs();
93392
+ try {
93393
+ const response = await fetchBrowserHyperliquidInfoPayload(
93394
+ evidenceReadInput(context),
93395
+ { type: "orderStatus", user, oid: orderStatusOid(orderRef) },
93396
+ "hyperliquid.orderStatus"
93397
+ );
93398
+ return response == null ? null : { order_ref: orderRef, response, startedAtMonotonicMs };
93399
+ } catch {
93400
+ return null;
93401
+ }
93402
+ };
93403
+ orderStatusEvidenceForAck = (read) => ({
93404
+ order_ref: read.order_ref,
93405
+ response: read.response,
93406
+ observed_age_ms: monotonicAgeMs(read.startedAtMonotonicMs)
93407
+ });
93408
+ }
93409
+ });
93410
+
93129
93411
  // lib/runtime/protective-trigger-price.ts
93130
93412
  var toPositiveNumber, resolveRiskPct, buildTriggerPrice, resolveTrailingStopTightening;
93131
93413
  var init_protective_trigger_price = __esm({
@@ -93330,13 +93612,18 @@ function adjustCopiedTarget(target, longRemovedSince, shortRemovedSince) {
93330
93612
  if (target < -1e-12) return Math.min(0, target + Math.max(0, shortRemovedSince));
93331
93613
  return 0;
93332
93614
  }
93615
+ function copiedTargetBesideOwnPosition(target, copied, actual) {
93616
+ const own = actual - copied;
93617
+ if (Math.abs(own) <= 1e-12 || Math.abs(target) <= 1e-12 || own * target > 0) return target;
93618
+ return Math.min(Math.max(target, Math.min(0, copied)), Math.max(0, copied));
93619
+ }
93333
93620
  function removedByCap(copied, capped) {
93334
93621
  if (copied > 0) return [Math.max(0, copied - Math.max(0, capped)), 0];
93335
93622
  if (copied < 0) return [0, Math.max(0, Math.min(0, capped) - copied)];
93336
93623
  return [0, 0];
93337
93624
  }
93338
- function positionSpaceCopyTarget(reconciliation, recordedTarget, actualPosition) {
93339
- if (!reconciliation || reconciliation.target_space !== "copied") return recordedTarget;
93625
+ function copiedTargetNow(reconciliation, recordedTarget, actualPosition) {
93626
+ if (!reconciliation || reconciliation.target_space !== "copied") return null;
93340
93627
  const copiedServer = Number(reconciliation.copied_now ?? 0) || 0;
93341
93628
  const copiedNow = capCopiedToActual(copiedServer, actualPosition);
93342
93629
  const [deviceLongRemoved, deviceShortRemoved] = removedByCap(copiedServer, copiedNow);
@@ -93347,9 +93634,9 @@ function positionSpaceCopyTarget(reconciliation, recordedTarget, actualPosition)
93347
93634
  longRemovedNow - (Number(reconciliation.external_long_removed_before ?? 0) || 0),
93348
93635
  shortRemovedNow - (Number(reconciliation.external_short_removed_before ?? 0) || 0)
93349
93636
  );
93350
- return actualPosition + (targetNow - copiedNow);
93637
+ return { copiedNow, targetNow, kept: copiedTargetBesideOwnPosition(targetNow, copiedNow, actualPosition) };
93351
93638
  }
93352
- var clientProtectiveMutationAuthority, executionReadPriority, serverEntryLeverageAlreadyHeld, fetchClientRuntimeOpenOrders, _extractOrderResponseStates, createRuntimeId, _extractFilledSize, _extractOrderId, _toExecutionMetadata, _extractClientMutationId, _stableMutationIdentity, trailingStopMemory, protectiveGroupMemory, protectiveGroupReadFailures, windowHandoffCleanupAttempts, clientRuntimeProtectionStorage, resolveClientRuntimeProtectionStorage, setClientRuntimeProtectionStorage, trailingStopStorageKey, readTrackedTrailingStops, writeTrackedTrailingStops, rememberTrailingStop, protectiveGroupStorageKey, withClientProtectivePlanSetLock, readClientProtectiveGroups, writeClientProtectiveGroups, hasClientProtectiveGroupReadFailure, readFreshClientProtectiveGroups, stableProtectionSnapshot, exactClientProtectiveGroupSnapshot, exactClientProtectiveGroupSetSnapshot, storableClientProtectiveGroup, replaceExactClientProtectiveGroup, replaceExactClientProtectiveGroupSet, isClientRuntimeLeaseOwnershipError, hasClientRuntimeProtectionState, clearClientRuntimeVetoedProtectiveIntent, rethrowWindowHandoffAfterProtectiveReplacementVeto, canPersistClientProtectiveGroups, removeTrackedTrailingStop, replaceTrackedTrailingStop, replaceProtectiveLeg, replacementJournalEntryOrderId, buildProtectiveReplacementJournalGroup, isProtectiveReplacementJournalGroup, reserveProtectiveLegReplacement, ensureProtectiveReplacementJournalCompanion, buildVetoedProtectiveReplacementCleanup, assertExactProtectiveReplacementDispatchAuthority, transitionProtectiveReplacementAcknowledgement, transitionTerminalProtectiveReplacement, pendingProtectiveReplacementReport, isConfiguredProtectionRequested, protectiveAction, isExactClientPositionTpslPair, deviceOwnsClientProtectiveLegKind, isAdoptionNarrowedPositionTpslLeg, hasAmbiguousClientPositionTpslAuthority, protectiveStableShapeMatches, observedProtectiveGroupingMatches, protectiveLiveShapeMatches, protectiveTerminalShapeMatches, cancelClientProtectiveLeg, buildPendingProtectivePlan, persistPendingClientProtectiveGroup, storedClientProtectiveCover, attachClientProtectivePlan, resolveJournaledAttachmentContinuity, protectiveMemberRested, recoverJournaledClientProtectiveAttachments, readPendingEntryMutation, requireClientRuntimeConfigSeconds, replacePendingEntryRecovery, recoverPendingClientProtectiveGroups, recoverPendingProtectiveReplacements, liveProtectiveOrderShape, observedStandaloneProtectiveGroup, migrateTrackedTrailingStopsToStandalone, reconcileClientProtectiveGroups, cancelAllClientProtectiveGroups, tightenClientTrailingStops, throwIfAborted2, sleep2, isDefinitiveEntryRejection, resolveExchangeSizeDecimals, roundAssetSize, resolvePositionSize, resolveCurrentPositionSize, buildPositionSnapshot, signedRemainingExposureAfterConfirmedReduction, runtimeProtectionAuthority, runtimeProtectionOwners, resolveRuntimeProtectionOwner, drainServerProtectionForRuntime, drainServerProtectionIfOwned, verifyNoLiveClientProtectiveTriggers, clientExecutionMutations, CLIENT_EXECUTION_QUEUE_TIMEOUT_MESSAGE, withClientExecutionMutation, withClientProtectivePlanSetMutation, allocateServerExecutionCapacity, withClientProtectiveAdoptionMutation, executeClientRuntimeDecisionLocked, SERVER_AUDIT_RECORDED_ELSEWHERE, serverExecutionAuditOutcome, executeClientRuntimeDecision, waitForFlipCloseFreshness, maintainClientRuntimeTrailingStops, listPendingClientProtectiveSymbols, listStoredClientProtectiveSymbols, hasUnresolvedClientProtectiveIdentity, resolveClientProtectiveIdentitiesForAdoption, exportClientProtectiveGroupsForAdoption, adoptionGroupKey, applyClientProtectiveAdoptionOutcomes, hasStoredClientProtectiveGroupsForWallet, hasPendingClientProtectiveGroups, recoverManualClientProtectiveGroups, clientRuntimeDecisionSizesOrders, executeClientRuntimeDecisionUnlocked, executeClientCopyTradingIntent, executeClientCopyTradingOrderAction;
93639
+ var clientProtectiveMutationAuthority, executionReadPriority, serverEntryLeverageAlreadyHeld, fetchClientRuntimeOpenOrders, _extractOrderResponseStates, createRuntimeId, _extractFilledSize, _extractOrderId, _toExecutionMetadata, _extractClientMutationId, _stableMutationIdentity, trailingStopMemory, protectiveGroupMemory, protectiveGroupReadFailures, windowHandoffCleanupAttempts, clientRuntimeProtectionStorage, resolveClientRuntimeProtectionStorage, setClientRuntimeProtectionStorage, trailingStopStorageKey, readTrackedTrailingStops, writeTrackedTrailingStops, rememberTrailingStop, protectiveGroupStorageKey, withClientProtectivePlanSetLock, readClientProtectiveGroups, writeClientProtectiveGroups, hasClientProtectiveGroupReadFailure, readFreshClientProtectiveGroups, stableProtectionSnapshot, exactClientProtectiveGroupSnapshot, exactClientProtectiveGroupSetSnapshot, storableClientProtectiveGroup, replaceExactClientProtectiveGroup, replaceExactClientProtectiveGroupSet, isClientRuntimeLeaseOwnershipError, hasClientRuntimeProtectionState, clearClientRuntimeVetoedProtectiveIntent, rethrowWindowHandoffAfterProtectiveReplacementVeto, canPersistClientProtectiveGroups, removeTrackedTrailingStop, replaceTrackedTrailingStop, replaceProtectiveLeg, replacementJournalEntryOrderId, buildProtectiveReplacementJournalGroup, isProtectiveReplacementJournalGroup, reserveProtectiveLegReplacement, ensureProtectiveReplacementJournalCompanion, buildVetoedProtectiveReplacementCleanup, assertExactProtectiveReplacementDispatchAuthority, transitionProtectiveReplacementAcknowledgement, transitionTerminalProtectiveReplacement, pendingProtectiveReplacementReport, isConfiguredProtectionRequested, protectiveAction, isExactClientPositionTpslPair, deviceOwnsClientProtectiveLegKind, isAdoptionNarrowedPositionTpslLeg, hasAmbiguousClientPositionTpslAuthority, protectiveStableShapeMatches, observedProtectiveGroupingMatches, protectiveLiveShapeMatches, protectiveTerminalShapeMatches, cancelClientProtectiveLeg, buildPendingProtectivePlan, persistPendingClientProtectiveGroup, storedClientProtectiveCover, attachClientProtectivePlan, resolveJournaledAttachmentContinuity, protectiveMemberRested, recoverJournaledClientProtectiveAttachments, readPendingEntryMutation, requireClientRuntimeConfigSeconds, replacePendingEntryRecovery, recoverPendingClientProtectiveGroups, recoverPendingProtectiveReplacements, liveProtectiveOrderShape, observedStandaloneProtectiveGroup, migrateTrackedTrailingStopsToStandalone, reconcileClientProtectiveGroups, cancelAllClientProtectiveGroups, tightenClientTrailingStops, throwIfAborted2, sleep2, isDefinitiveEntryRejection, resolveExchangeSizeDecimals, roundAssetSize, resolvePositionSize, resolveCurrentPositionSize, buildPositionSnapshot, signedRemainingExposureAfterConfirmedReduction, runtimeProtectionAuthority, runtimeProtectionOwners, resolveRuntimeProtectionOwner, drainServerProtectionForRuntime, drainServerProtectionIfOwned, verifyNoLiveClientProtectiveTriggers, clientExecutionMutations, CLIENT_EXECUTION_QUEUE_TIMEOUT_MESSAGE, withClientExecutionMutation, withClientProtectivePlanSetMutation, allocateServerExecutionCapacity, withClientProtectiveAdoptionMutation, executeClientRuntimeDecisionLocked, SERVER_AUDIT_RECORDED_ELSEWHERE, serverExecutionAuditOutcome, executeClientRuntimeDecision, waitForFlipCloseFreshness, maintainClientRuntimeTrailingStops, listPendingClientProtectiveSymbols, listStoredClientProtectiveSymbols, hasUnresolvedClientProtectiveIdentity, resolveClientProtectiveIdentitiesForAdoption, exportClientProtectiveGroupsForAdoption, adoptionGroupKey, applyClientProtectiveAdoptionOutcomes, hasStoredClientProtectiveGroupsForWallet, hasPendingClientProtectiveGroups, recoverManualClientProtectiveGroups, clientRuntimeDecisionSizesOrders, executeClientRuntimeDecisionUnlocked, executeClientCopyTradingIntent, _copyCancelOrderId, executeClientCopyTradingOrderAction;
93353
93640
  var init_runtime_execution = __esm({
93354
93641
  "lib/runtime/runtime-execution.ts"() {
93355
93642
  "use strict";
@@ -93370,6 +93657,7 @@ var init_runtime_execution = __esm({
93370
93657
  init_hyperliquid_client();
93371
93658
  init_hyperliquid_market_symbol();
93372
93659
  init_network_debug();
93660
+ init_copy_trading_evidence();
93373
93661
  init_protective_trigger_price();
93374
93662
  init_runtime_redaction();
93375
93663
  init_protective_stop_replacement();
@@ -100348,6 +100636,7 @@ var init_runtime_execution = __esm({
100348
100636
  let minOrderNotional = 0;
100349
100637
  let executionReferencePrice = Number(intent.source_price);
100350
100638
  let dispatchedOrder = null;
100639
+ let ownPositionHold = {};
100351
100640
  if (reconciliation && typeof reconciliation === "object" && !Array.isArray(reconciliation)) {
100352
100641
  const record5 = reconciliation;
100353
100642
  const copiedNowServed = typeof record5.copied_now === "number" && Number.isFinite(record5.copied_now);
@@ -100375,7 +100664,11 @@ var init_runtime_execution = __esm({
100375
100664
  size: destinationSize,
100376
100665
  roundingMode: "nearest",
100377
100666
  includePrivateContext: desiredPosition != null && Number.isFinite(desiredPosition),
100378
- profileId: input.profileId
100667
+ profileId: input.profileId,
100668
+ // The device reads its own position and mark; the server never reads
100669
+ // a Client wallet.
100670
+ walletAddress: input.walletAddress,
100671
+ signal: input.signal
100379
100672
  });
100380
100673
  if (desiredPosition != null && Number.isFinite(desiredPosition)) {
100381
100674
  const preparedContextMaxAgeMs = Number(
@@ -100397,26 +100690,35 @@ var init_runtime_execution = __esm({
100397
100690
  if (!Number.isFinite(executionReferencePrice) || executionReferencePrice <= 0) {
100398
100691
  throw new Error("Copy Trading private-node execution mark was unavailable.");
100399
100692
  }
100400
- desiredPosition = positionSpaceCopyTarget(
100693
+ const copiedNow = copiedTargetNow(
100401
100694
  reconciliation,
100402
100695
  desiredPosition,
100403
100696
  actualPosition
100404
100697
  );
100698
+ if (copiedNow && Math.abs(copiedNow.targetNow - copiedNow.kept) > 1e-12) {
100699
+ ownPositionHold = {
100700
+ own_position_held_back_target: copiedNow.targetNow,
100701
+ own_position_kept_target: copiedNow.kept
100702
+ };
100703
+ }
100704
+ desiredPosition = copiedNow ? actualPosition + (copiedNow.kept - copiedNow.copiedNow) : desiredPosition;
100405
100705
  const liveDelta = desiredPosition - actualPosition;
100406
100706
  const tolerance = Math.max(1e-12, Math.abs(desiredPosition) * 1e-9);
100407
100707
  if (Math.abs(liveDelta) <= tolerance) {
100708
+ const heldBack = Object.keys(ownPositionHold).length > 0;
100408
100709
  return {
100409
100710
  status: "executed",
100410
100711
  orderId: null,
100411
- message: "Copy Trading destination position is already at target.",
100412
- skipReason: "already_at_target",
100712
+ message: heldBack ? "Copy Trading skipped a copy against your own opposite position." : "Copy Trading destination position is already at target.",
100713
+ skipReason: heldBack ? "own_position_opposite_side" : "already_at_target",
100413
100714
  destinationSize: 0,
100414
100715
  destinationNotional: 0,
100415
100716
  executionMetadata: {
100416
100717
  execution_reference_price: executionReferencePrice,
100417
100718
  desired_destination_position_after: desiredPosition,
100418
100719
  actual_destination_position: actualPosition,
100419
- no_order_required: true
100720
+ no_order_required: true,
100721
+ ...ownPositionHold
100420
100722
  }
100421
100723
  };
100422
100724
  }
@@ -100477,7 +100779,8 @@ var init_runtime_execution = __esm({
100477
100779
  quantized_size: 0,
100478
100780
  sz_decimals: sizePrecision.sizeDecimals,
100479
100781
  rounding_mode: sizePrecision.roundingMode,
100480
- execution_reference_price: referencePrice
100782
+ execution_reference_price: referencePrice,
100783
+ ...ownPositionHold
100481
100784
  }
100482
100785
  };
100483
100786
  }
@@ -100499,7 +100802,8 @@ var init_runtime_execution = __esm({
100499
100802
  rounding_mode: sizePrecision.roundingMode,
100500
100803
  execution_reference_price: referencePrice,
100501
100804
  minimum_usdc: minOrderNotional,
100502
- order_deferred: true
100805
+ order_deferred: true,
100806
+ ...ownPositionHold
100503
100807
  }
100504
100808
  };
100505
100809
  }
@@ -100511,6 +100815,7 @@ var init_runtime_execution = __esm({
100511
100815
  intent.sanitized_metadata?.client_order_id
100512
100816
  );
100513
100817
  dispatchedOrder = {
100818
+ ...ownPositionHold,
100514
100819
  quantized_size: destinationSize,
100515
100820
  ...desiredPosition != null && Number.isFinite(desiredPosition) && actualPosition != null && Number.isFinite(actualPosition) ? {
100516
100821
  desired_destination_position_after: desiredPosition,
@@ -100564,6 +100869,7 @@ var init_runtime_execution = __esm({
100564
100869
  // The server records the executed change in the copied-position
100565
100870
  // ledger from these values.
100566
100871
  ...filledSize != null ? { filled_size: filledSize } : {},
100872
+ ...ownPositionHold,
100567
100873
  ...desiredPosition != null && Number.isFinite(desiredPosition) && actualPosition != null && Number.isFinite(actualPosition) ? {
100568
100874
  desired_destination_position_after: desiredPosition,
100569
100875
  actual_destination_position: actualPosition
@@ -100584,6 +100890,13 @@ var init_runtime_execution = __esm({
100584
100890
  };
100585
100891
  }
100586
100892
  };
100893
+ _copyCancelOrderId = (action) => {
100894
+ const destinationOrderId = action.previous_destination_order_id ?? action.destination_order_id;
100895
+ const numericOrderId = Number(destinationOrderId);
100896
+ if (Number.isSafeInteger(numericOrderId) && numericOrderId > 0) return numericOrderId;
100897
+ const cloid = String(destinationOrderId || "").trim().toLowerCase();
100898
+ return /^0x[0-9a-f]{32}$/.test(cloid) ? cloid : null;
100899
+ };
100587
100900
  executeClientCopyTradingOrderAction = async (input) => {
100588
100901
  throwIfAborted2(input.signal);
100589
100902
  const action = input.action;
@@ -100614,12 +100927,18 @@ var init_runtime_execution = __esm({
100614
100927
  signal: input.signal,
100615
100928
  onExchangeOrderDispatched: () => input.onExchangeOrderDispatched?.("action")
100616
100929
  };
100930
+ const cancelledOrderStatusEvidence = async (orderId) => {
100931
+ if (orderId == null) return {};
100932
+ const evidence = await readCopyOrderStatusEvidence(
100933
+ { config: input.config ?? null, signal: input.signal, walletAddress: input.walletAddress },
100934
+ orderId
100935
+ );
100936
+ return evidence ? { orderStatusEvidence: evidence } : {};
100937
+ };
100617
100938
  try {
100618
100939
  if (action.action_type === "cancel") {
100619
- const destinationOrderId2 = action.previous_destination_order_id ?? action.destination_order_id;
100620
- const numericOrderId = Number(destinationOrderId2);
100621
- const orderId = Number.isSafeInteger(numericOrderId) && numericOrderId > 0 ? numericOrderId : String(destinationOrderId2 || "").trim().toLowerCase();
100622
- if (typeof orderId === "number" && orderId <= 0 || typeof orderId === "string" && !/^0x[0-9a-f]{32}$/.test(orderId)) {
100940
+ const orderId = _copyCancelOrderId(action);
100941
+ if (orderId == null) {
100623
100942
  throw new Error("Copy Trading cancel action is missing a valid destination order id.");
100624
100943
  }
100625
100944
  await executeClientCancelOrder({
@@ -100631,7 +100950,8 @@ var init_runtime_execution = __esm({
100631
100950
  destinationOrderId: String(orderId),
100632
100951
  destinationOrderState: null,
100633
100952
  orderMemberResults: null,
100634
- message: "Copy Trading order cancellation executed."
100953
+ message: "Copy Trading order cancellation executed.",
100954
+ ...await cancelledOrderStatusEvidence(orderId)
100635
100955
  };
100636
100956
  }
100637
100957
  const size = Number(action.destination_size);
@@ -100725,7 +101045,8 @@ var init_runtime_execution = __esm({
100725
101045
  destinationOrderId: action.previous_destination_order_id ?? action.destination_order_id ?? null,
100726
101046
  destinationOrderState: null,
100727
101047
  orderMemberResults: null,
100728
- message: "Copy Trading order was already terminal."
101048
+ message: "Copy Trading order was already terminal.",
101049
+ ...await cancelledOrderStatusEvidence(_copyCancelOrderId(action))
100729
101050
  };
100730
101051
  }
100731
101052
  return {
@@ -112863,8 +113184,11 @@ ${reviewOutputContract}`;
112863
113184
  startPosition: fill.start_position
112864
113185
  }))
112865
113186
  );
112866
- const perSymbolCap = 500;
112867
- const totalCap = 5e3;
113187
+ const perSymbolCap = Number(input.maxFillsPerSymbol);
113188
+ if (!Number.isInteger(perSymbolCap) || perSymbolCap < 1) {
113189
+ throw new Error("Missing required behavior memory max_fills_per_symbol configuration.");
113190
+ }
113191
+ const totalCap = perSymbolCap * Math.max(selectedSymbols.size, 1);
112868
113192
  const behaviorMemoryEnabled = input.behaviorMemoryEnabled ?? false;
112869
113193
  const rawPerSymbolCounts = /* @__PURE__ */ new Map();
112870
113194
  for (const fill of fillsDescending) {
@@ -114722,6 +115046,7 @@ ${behaviorJson}
114722
115046
  behaviorInstructions: promptBehaviorInstructions,
114723
115047
  lastTrades: asRecord(derivedContext.behavior_last_trades),
114724
115048
  behaviorMemoryEnabled,
115049
+ maxFillsPerSymbol: config2.behavior_memory_max_fills_per_symbol,
114725
115050
  decisionMemory: asRecord(derivedContext.behavior_decision_memory),
114726
115051
  cycleCutoffMs: behaviorMemoryCutoffMs,
114727
115052
  fillHistoryCoverage: behaviorFillCoverage
@@ -116097,7 +116422,7 @@ ${reviewOutputContract}`;
116097
116422
  });
116098
116423
 
116099
116424
  // lib/runtime/engine.ts
116100
- var localAnalysis, getExchangeFailureDiagnostics, getRuntimeFallbackAttempts, sentInvocationAttemptCount, boundRuntimeFallbackAttempts, isProviderFailureDiagnosticsCandidate, getEventBoundProviderLabel, getEventBoundProviderTraceId, getRecentProviderFailureDiagnostics, getClientRuntimeErrorProvenance, getRuntimeProviderSetupDiagnostics, buildProviderSetupErrorDiagnosticFields, buildClientRuntimeErrorProvenanceDiagnosticFields, buildRuntimeRequestErrorDiagnosticFields, getCycleErrorModelCalls, isReturnedModelCall, hasEventBoundProviderFailureEvidence, endsWithNeverSentAttempt, classifyRuntimeErrorStage, buildHyperliquidPublicReadDiagnosticFields, buildRuntimeErrorDiagnostics, positiveNumber, resolveRuntimeEngineOptions, withServerPositionEvents, CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX, getClientKillswitchBlockStorageKey, persistClientRuntimeKillswitchBlock, clearClientRuntimeKillswitchBlock, hashRuntimeDebugText2, createRuntimeUuid2, getRuntimeContractIdentityToken, getRuntimeStatusContractIdentityToken, getRuntimeContractBindingTokenFromCycleResult, getRuntimeContractBindingTupleToken, getRuntimeStatusContractBindingTupleToken, isTransientRuntimeConflictError, createRuntimeStartCancelledError, isRuntimeContractMismatchError, isClientExecutionModeMismatchError, isClientRuntimeSessionStoppedError, isClientRuntimeLeaseAuthError, isClientRuntimeReleasedError, deriveFailedStartCleanupOwnershipLossReason, isRuntimeAbortError, isExplicitClientExecutionMode, createStopAbortError, isRuntimeContractIdentityAdvancedAbort, CLIENT_RUNTIME_NO_DECISION_RECOVERY_REASON, sanitizeSettingsSnapshotForFallback, preflightClientRuntime, ClientExecutionEngine, createStoppedRuntimeSnapshot, ClientRuntimeRegistry, botEngine;
116425
+ var localAnalysis, getExchangeFailureDiagnostics, getRuntimeFallbackAttempts, sentInvocationAttemptCount, boundRuntimeFallbackAttempts, isProviderFailureDiagnosticsCandidate, getEventBoundProviderLabel, getEventBoundProviderTraceId, getRecentProviderFailureDiagnostics, getClientRuntimeErrorProvenance, getRuntimeProviderSetupDiagnostics, buildProviderSetupErrorDiagnosticFields, buildClientRuntimeErrorProvenanceDiagnosticFields, buildRuntimeRequestErrorDiagnosticFields, getCycleErrorModelCalls, isReturnedModelCall, hasEventBoundProviderFailureEvidence, endsWithNeverSentAttempt, classifyRuntimeErrorStage, buildHyperliquidPublicReadDiagnosticFields, buildRuntimeErrorDiagnostics, positiveNumber, resolveRuntimeEngineOptions, withServerPositionEvents, CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX, getClientKillswitchBlockStorageKey, isClientRuntimeKillswitchBlocked, persistClientRuntimeKillswitchBlock, clearClientRuntimeKillswitchBlock, hashRuntimeDebugText2, createRuntimeUuid2, getRuntimeContractIdentityToken, getRuntimeStatusContractIdentityToken, getRuntimeContractBindingTokenFromCycleResult, getRuntimeContractBindingTupleToken, getRuntimeStatusContractBindingTupleToken, isTransientRuntimeConflictError, createRuntimeStartCancelledError, isRuntimeContractMismatchError, isClientExecutionModeMismatchError, isClientRuntimeSessionStoppedError, isClientRuntimeLeaseAuthError, isClientRuntimeReleasedError, deriveFailedStartCleanupOwnershipLossReason, isRuntimeAbortError, isExplicitClientExecutionMode, createStopAbortError, isRuntimeContractIdentityAdvancedAbort, CLIENT_RUNTIME_NO_DECISION_RECOVERY_REASON, sanitizeSettingsSnapshotForFallback, preflightClientRuntime, ClientExecutionEngine, createStoppedRuntimeSnapshot, ClientRuntimeRegistry, botEngine;
116101
116426
  var init_engine = __esm({
116102
116427
  "lib/runtime/engine.ts"() {
116103
116428
  "use strict";
@@ -116136,6 +116461,7 @@ var init_engine = __esm({
116136
116461
  init_api2();
116137
116462
  init_history_evidence();
116138
116463
  init_portfolio_evidence();
116464
+ init_copy_trading_evidence();
116139
116465
  getExchangeFailureDiagnostics = (error48) => {
116140
116466
  if (error48 instanceof HyperliquidExchangeRejectionError) {
116141
116467
  return {
@@ -116545,6 +116871,13 @@ var init_engine = __esm({
116545
116871
  });
116546
116872
  CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX = "vtx_client_runtime_killswitch_block_v1:";
116547
116873
  getClientKillswitchBlockStorageKey = (profileId) => `${CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX}${profileId.trim()}`;
116874
+ isClientRuntimeKillswitchBlocked = (profileId) => {
116875
+ const storage3 = runtimeHostStorage();
116876
+ if (!storage3 || !profileId.trim()) {
116877
+ return false;
116878
+ }
116879
+ return storage3.getItem(getClientKillswitchBlockStorageKey(profileId)) !== null;
116880
+ };
116548
116881
  persistClientRuntimeKillswitchBlock = (profileId) => {
116549
116882
  const storage3 = runtimeHostStorage();
116550
116883
  if (!storage3 || !profileId.trim()) {
@@ -120357,7 +120690,7 @@ var init_engine = __esm({
120357
120690
  if (this._analysisRequestId === requestId) {
120358
120691
  this._analysisRequestId = null;
120359
120692
  this._analysisStartedAtMs = null;
120360
- if (this._expectedExecutionMode === "server" && this._state === "running") void this.sendHeartbeat();
120693
+ if (this._state === "running") void this.sendHeartbeat();
120361
120694
  }
120362
120695
  const silentEmptyAgentPoll = cycleOutcome === "skipped" && (cycleReason === "agent_instruction_poll_empty" || cycleReason === "ai_schedule_paused" || cycleReason === "ai_schedule_check") && !cycleStartEmitted;
120363
120696
  if (this._state === "running" && this._sessionId === sessionId) {
@@ -120820,9 +121153,11 @@ var init_engine = __esm({
120820
121153
  analysisRunId: heartbeatAnalysisRunId,
120821
121154
  isAnalyzing: heartbeatIsAnalyzing,
120822
121155
  isExecuting: heartbeatIsExecuting,
120823
- // Beats may arrive out of order: the server keeps a node bot's newest
120824
- // analyzing observation, so a cycle's end is never undone by its start.
120825
- ...this._expectedExecutionMode === "server" ? { analyzingObservedAtMs: heartbeatObservedAtMs } : {}
121156
+ // Beats may arrive out of order: the server keeps the owner's newest
121157
+ // analyzing observation (a node bot's status; a Client runtime's
121158
+ // handback to its home device), so a cycle's end is never undone by
121159
+ // its start.
121160
+ analyzingObservedAtMs: heartbeatObservedAtMs
120826
121161
  });
120827
121162
  if (Number(response.protective_actions_pending ?? 0) > 0) {
120828
121163
  notifyClientProtectiveActionsPending(heartbeatProfileId);
@@ -121366,22 +121701,66 @@ var init_engine = __esm({
121366
121701
  try {
121367
121702
  const persistedLease = getPersistedClientRuntimeServerLease(input.profileId);
121368
121703
  const runtimeLeaseToken = persistedLease?.runtimeSessionId === input.runtimeSessionId && persistedLease.deviceId === input.runtimeDeviceId && persistedLease.mode === "trader" ? persistedLease.runtimeLeaseToken : null;
121369
- const pollResponse = await pollCopyTradingRuntimeSource(Number(input.profileId), {
121704
+ const pollOptions = {
121370
121705
  runtimeLeaseToken: runtimeLeaseToken ?? void 0,
121371
121706
  schedulerInstanceId: this._instanceId,
121372
121707
  signal: input.signal
121373
- });
121374
- if (pollResponse.result.recorded_count > 0 || pollResponse.result.skipped_count > 0 || pollResponse.result.error_code) {
121375
- appendRuntimeDebugEvent({
121376
- label: "copy_trading_source_polled",
121377
- note: `observed=${pollResponse.result.observed_count} recorded=${pollResponse.result.recorded_count} skipped=${pollResponse.result.skipped_count} status=${pollResponse.result.latest_status || "none"} reason=${pollResponse.result.latest_skip_reason || pollResponse.result.error_code || "none"}`,
121378
- outcome: pollResponse.result.error_code ? "error" : "ok"
121379
- });
121380
- }
121381
- const copySourceUnavailable = pollResponse.result.error_code === "copy_trading_disabled" || pollResponse.result.error_code === "copy_trading_source_missing";
121708
+ };
121709
+ const logPoll = (response) => {
121710
+ if (response.result.recorded_count > 0 || response.result.skipped_count > 0 || response.result.error_code) {
121711
+ appendRuntimeDebugEvent({
121712
+ label: "copy_trading_source_polled",
121713
+ note: `observed=${response.result.observed_count} recorded=${response.result.recorded_count} skipped=${response.result.skipped_count} status=${response.result.latest_status || "none"} reason=${response.result.latest_skip_reason || response.result.error_code || "none"}`,
121714
+ outcome: response.result.error_code ? "error" : "ok"
121715
+ });
121716
+ }
121717
+ };
121718
+ let trustedWalletRead = null;
121719
+ const readTrustedWallet = () => {
121720
+ trustedWalletRead ??= getFreshPreferences(
121721
+ void 0,
121722
+ Number(input.profileId),
121723
+ input.signal,
121724
+ false,
121725
+ {
121726
+ runtimeLeaseToken: runtimeLeaseToken ?? void 0,
121727
+ schedulerInstanceId: this._instanceId
121728
+ }
121729
+ ).then((preferences) => String(
121730
+ preferences.preferences?.hyperliquid_wallet_address || ""
121731
+ ).trim() || null);
121732
+ return trustedWalletRead;
121733
+ };
121734
+ let pollResponse = await pollCopyTradingRuntimeSource(Number(input.profileId), pollOptions);
121735
+ logPoll(pollResponse);
121382
121736
  if (pollResponse.result.error_code === "self_copy_blocked") {
121383
121737
  return;
121384
121738
  }
121739
+ if (pollResponse.account_evidence_request) {
121740
+ if (this._windowHandoffRequested) {
121741
+ return;
121742
+ }
121743
+ const followUp = await this._sendClientCopyTradingAccountEvidence({
121744
+ profileId: input.profileId,
121745
+ request: pollResponse.account_evidence_request,
121746
+ // Unread preferences leave no trusted wallet: no evidence is read.
121747
+ trustedWalletAddress: await readTrustedWallet().catch((error48) => {
121748
+ if (input.signal.aborted) throw error48;
121749
+ return null;
121750
+ }),
121751
+ config: input.config,
121752
+ signal: input.signal,
121753
+ pollOptions
121754
+ });
121755
+ if (followUp) {
121756
+ pollResponse = followUp;
121757
+ logPoll(pollResponse);
121758
+ if (pollResponse.result.error_code === "self_copy_blocked") {
121759
+ return;
121760
+ }
121761
+ }
121762
+ }
121763
+ const copySourceUnavailable = pollResponse.result.error_code === "copy_trading_disabled" || pollResponse.result.error_code === "copy_trading_source_missing";
121385
121764
  const copyOrderActions = copySourceUnavailable ? [] : await getPendingClientCopyTradingOrderActions(Number(input.profileId), {
121386
121765
  runtimeLeaseToken: runtimeLeaseToken ?? void 0,
121387
121766
  schedulerInstanceId: this._instanceId,
@@ -121397,19 +121776,7 @@ var init_engine = __esm({
121397
121776
  ) : pendingCopyIntents;
121398
121777
  let expectedWalletAddress = null;
121399
121778
  if (copyOrderActions.length > 0 || copyIntents.length > 0) {
121400
- const referencePreferences = await getFreshPreferences(
121401
- void 0,
121402
- Number(input.profileId),
121403
- input.signal,
121404
- false,
121405
- {
121406
- runtimeLeaseToken: runtimeLeaseToken ?? void 0,
121407
- schedulerInstanceId: this._instanceId
121408
- }
121409
- );
121410
- expectedWalletAddress = String(
121411
- referencePreferences.preferences?.hyperliquid_wallet_address || ""
121412
- ).trim() || null;
121779
+ expectedWalletAddress = await readTrustedWallet();
121413
121780
  if (!expectedWalletAddress) {
121414
121781
  throw new Error(
121415
121782
  "runtime_wallet_assignment_mismatch: copy trading has no trusted wallet assignment"
@@ -121456,7 +121823,8 @@ var init_engine = __esm({
121456
121823
  order_id: actionResult.destinationOrderId,
121457
121824
  order_state: actionResult.destinationOrderState,
121458
121825
  order_member_results: actionResult.orderMemberResults,
121459
- error_message: actionResult.status === "executed" ? null : actionResult.message
121826
+ error_message: actionResult.status === "executed" ? null : actionResult.message,
121827
+ ...actionResult.orderStatusEvidence ? { order_status_evidence: orderStatusEvidenceForAck(actionResult.orderStatusEvidence) } : {}
121460
121828
  },
121461
121829
  {
121462
121830
  runtimeLeaseToken: runtimeLeaseToken ?? void 0,
@@ -121540,6 +121908,55 @@ var init_engine = __esm({
121540
121908
  });
121541
121909
  }
121542
121910
  }
121911
+ /**
121912
+ * Read the follower account evidence a copy poll asked for and send it on
121913
+ * one follow-up poll. Fails closed: when any read fails or the wallet is not
121914
+ * the trusted one, nothing is sent and the check-in continues on the first
121915
+ * poll (null). A report the server cannot use still answers the poll, with
121916
+ * its reason in account_evidence_status, which is logged here.
121917
+ */
121918
+ async _sendClientCopyTradingAccountEvidence(input) {
121919
+ const requestId = String(input.request.request_id ?? "").trim().slice(0, 80) || "none";
121920
+ const evidence = await readClientCopyTradingAccountEvidence({
121921
+ request: input.request,
121922
+ trustedWalletAddress: input.trustedWalletAddress,
121923
+ config: input.config,
121924
+ signal: input.signal
121925
+ });
121926
+ if (!evidence.ok) {
121927
+ appendRuntimeDebugEvent({
121928
+ label: "copy_trading_account_evidence_skipped",
121929
+ note: `profile_id=${input.profileId} request_id=${requestId} reason=${evidence.reason}`,
121930
+ outcome: "error"
121931
+ });
121932
+ return null;
121933
+ }
121934
+ try {
121935
+ const response = await pollCopyTradingRuntimeSource(Number(input.profileId), {
121936
+ ...input.pollOptions,
121937
+ accountEvidence: accountEvidenceForUpload(evidence.read)
121938
+ });
121939
+ const status = response.account_evidence_status ?? null;
121940
+ if (status !== "applied") {
121941
+ appendRuntimeDebugEvent({
121942
+ label: "copy_trading_account_evidence_rejected",
121943
+ note: `profile_id=${input.profileId} request_id=${requestId} reason=${String(status ?? "missing").slice(0, 80)}`,
121944
+ outcome: "error"
121945
+ });
121946
+ }
121947
+ return response;
121948
+ } catch (error48) {
121949
+ if (input.signal.aborted) {
121950
+ throw error48;
121951
+ }
121952
+ appendRuntimeDebugEvent({
121953
+ label: "copy_trading_account_evidence_rejected",
121954
+ note: `profile_id=${input.profileId} request_id=${requestId} error=${getSanitizedRuntimeErrorMessage(error48) || "unknown"}`,
121955
+ outcome: "error"
121956
+ });
121957
+ return null;
121958
+ }
121959
+ }
121543
121960
  _resetRuntimeState(options) {
121544
121961
  this._clearExecutionLoopTimer();
121545
121962
  this._clearClientKillswitchMonitor();
@@ -121952,6 +122369,99 @@ var init_reconcile = __esm({
121952
122369
  }
121953
122370
  });
121954
122371
 
122372
+ // lib/runtime/host/local-ai-preflight.ts
122373
+ var normalizeModelSource, isLocalModelSource2, getLocalAiBaseUrlFromPreferences, canReachLocalAiEndpoint;
122374
+ var init_local_ai_preflight = __esm({
122375
+ "lib/runtime/host/local-ai-preflight.ts"() {
122376
+ "use strict";
122377
+ init_define_VTX_EXO_POLICY();
122378
+ init_define_VTX_GROK_POLICY();
122379
+ init_define_VTX_PI_MODEL_POLICY();
122380
+ init_api2();
122381
+ init_local_ai();
122382
+ init_vault();
122383
+ normalizeModelSource = (value) => String(value ?? "").trim().toLowerCase();
122384
+ isLocalModelSource2 = (value) => {
122385
+ const normalized = normalizeModelSource(value);
122386
+ return normalized === "local" || normalized === "localai" || normalized === "local ai" || normalized === "local-ai" || normalized === "local_ai";
122387
+ };
122388
+ getLocalAiBaseUrlFromPreferences = (preferences) => {
122389
+ const record5 = preferences && typeof preferences === "object" && !Array.isArray(preferences) ? preferences : {};
122390
+ const direct = typeof record5.local_ai_base_url === "string" ? record5.local_ai_base_url.trim() : "";
122391
+ if (direct) {
122392
+ return direct;
122393
+ }
122394
+ const localAi = record5.local_ai && typeof record5.local_ai === "object" && !Array.isArray(record5.local_ai) ? record5.local_ai : null;
122395
+ const remembered = Array.isArray(localAi?.remembered_endpoints) ? localAi.remembered_endpoints : [];
122396
+ for (const endpoint of remembered) {
122397
+ if (!endpoint || typeof endpoint !== "object" || Array.isArray(endpoint)) {
122398
+ continue;
122399
+ }
122400
+ const baseUrl = typeof endpoint.baseUrl === "string" ? String(endpoint.baseUrl).trim() : "";
122401
+ if (baseUrl) {
122402
+ return baseUrl;
122403
+ }
122404
+ }
122405
+ return null;
122406
+ };
122407
+ canReachLocalAiEndpoint = async (preferences, profileId, timeoutMs, signal) => {
122408
+ const baseUrl = getLocalAiBaseUrlFromPreferences(preferences);
122409
+ if (!baseUrl) {
122410
+ return { ok: false, detail: "local_ai_endpoint_missing" };
122411
+ }
122412
+ let rawServerType = resolveLocalAiServerTypeInput(preferences);
122413
+ if (!rawServerType) {
122414
+ try {
122415
+ const secrets = await ClientVault.getSecrets(String(profileId));
122416
+ rawServerType = resolveLocalAiServerTypeInput(preferences, secrets?.localAi?.serverType);
122417
+ } catch {
122418
+ return { ok: false, detail: "local_ai_settings_unavailable" };
122419
+ }
122420
+ }
122421
+ const serverType = rawServerType ? normalizeLocalAiServerType(rawServerType) : "openai-compatible";
122422
+ if (!serverType) {
122423
+ return { ok: false, detail: "local_ai_reconnect_required" };
122424
+ }
122425
+ const endpoint = buildLocalAiModelsEndpointForServerType(baseUrl, serverType);
122426
+ if (!endpoint) {
122427
+ return { ok: false, detail: "local_ai_endpoint_missing" };
122428
+ }
122429
+ const headers = { Accept: "application/json" };
122430
+ try {
122431
+ const secret = await getLocalAiEndpointSecret(baseUrl, profileId, signal);
122432
+ const apiKey = typeof secret?.api_key === "string" ? secret.api_key.trim() : "";
122433
+ if (secret?.found && apiKey) {
122434
+ headers.Authorization = `Bearer ${apiKey}`;
122435
+ }
122436
+ } catch {
122437
+ }
122438
+ const controller = new AbortController();
122439
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
122440
+ const onAbort = () => controller.abort();
122441
+ signal?.addEventListener("abort", onAbort, { once: true });
122442
+ try {
122443
+ const response = await fetch(endpoint, {
122444
+ method: "GET",
122445
+ headers,
122446
+ signal: controller.signal
122447
+ });
122448
+ return {
122449
+ ok: response.ok,
122450
+ detail: response.ok ? "ok" : `status_${response.status}`
122451
+ };
122452
+ } catch (error48) {
122453
+ return {
122454
+ ok: false,
122455
+ detail: error48 instanceof Error && error48.name === "AbortError" ? "timeout" : "fetch_failed"
122456
+ };
122457
+ } finally {
122458
+ clearTimeout(timeout);
122459
+ signal?.removeEventListener("abort", onAbort);
122460
+ }
122461
+ };
122462
+ }
122463
+ });
122464
+
121955
122465
  // lib/agent-core/headless-runtime.ts
121956
122466
  import { randomUUID as randomUUID15 } from "node:crypto";
121957
122467
  import { setTimeout as sleep3 } from "node:timers/promises";
@@ -122195,6 +122705,11 @@ async function runHeadlessRuntime(options) {
122195
122705
  if (stored && stored.runtimeSessionId !== identity2.sessionId) return;
122196
122706
  await clearRuntimeState(options.statePath);
122197
122707
  };
122708
+ const readOwnStatus = async (signal = stopController.signal) => (await getClientRuntimeStatuses(
122709
+ [options.profileId],
122710
+ signal,
122711
+ { runtimeViewer: { deviceId: identity2.deviceId, sessionId: identity2.sessionId } }
122712
+ )).statuses?.[String(options.profileId)] ?? null;
122198
122713
  const stopRuntime = async (reason) => {
122199
122714
  if (engine.active) await engine.stop({ skipRemote: true, reason });
122200
122715
  try {
@@ -122210,6 +122725,8 @@ async function runHeadlessRuntime(options) {
122210
122725
  requestTimeoutMs: options.stopRequestTimeoutMs ?? STOP_REQUEST_TIMEOUT_MS
122211
122726
  });
122212
122727
  } catch (error48) {
122728
+ const backupRuns = await readOwnStatus(AbortSignal.timeout(options.stopRequestTimeoutMs ?? STOP_REQUEST_TIMEOUT_MS)).then((status) => status?.server_backup?.active === true, () => false);
122729
+ if (backupRuns) return;
122213
122730
  const detail = error48 instanceof Error ? error48.message : String(error48);
122214
122731
  throw new Error(`VTX could not stop this profile's runtime on the server (${detail}); it may still be set to run.`);
122215
122732
  }
@@ -122229,6 +122746,120 @@ async function runHeadlessRuntime(options) {
122229
122746
  }
122230
122747
  if (kind === "explicit") await clearOwnState().catch(() => void 0);
122231
122748
  };
122749
+ const readyToTakeBack = async (status) => {
122750
+ const profileId = String(options.profileId);
122751
+ const desiredMode = String(status.desired_runtime_mode || "").trim().toLowerCase();
122752
+ if (desiredMode && desiredMode !== identity2.mode) return false;
122753
+ if (identity2.mode === "trader" && isClientRuntimeKillswitchBlocked(profileId)) return false;
122754
+ try {
122755
+ const [config2, preferences] = await Promise.all([
122756
+ getLLMConfig(void 0, options.profileId, stopController.signal),
122757
+ getPreferences(void 0, options.profileId, stopController.signal)
122758
+ ]);
122759
+ if (config2.agent_headless_client_runtime_enabled !== true) return false;
122760
+ const prefs = preferences?.preferences;
122761
+ if (isLocalModelSource2(prefs?.preferred_model_source)) {
122762
+ return (await canReachLocalAiEndpoint(prefs, options.profileId, LOCAL_AI_PREFLIGHT_TIMEOUT_MS, stopController.signal)).ok;
122763
+ }
122764
+ return true;
122765
+ } catch {
122766
+ return false;
122767
+ }
122768
+ };
122769
+ const readWaitStatus = async () => {
122770
+ try {
122771
+ const response = await getClientRuntimeStatuses(
122772
+ [options.profileId],
122773
+ stopController.signal,
122774
+ { runtimeViewer: { deviceId: identity2.deviceId, sessionId: identity2.sessionId } }
122775
+ );
122776
+ const status = response.statuses?.[String(options.profileId)];
122777
+ if (status) return { status };
122778
+ const error48 = String(response.errors?.[String(options.profileId)] ?? "");
122779
+ return !error48 || /temporarily unavailable/iu.test(error48) ? "retry" : "ended";
122780
+ } catch (error48) {
122781
+ return classifyReconcileRequestError(error48) === "transient" ? "retry" : { refused: error48 };
122782
+ }
122783
+ };
122784
+ const waitForServerBackup = async () => {
122785
+ if (options.once || stopController.signal.aborted) return "not_backup";
122786
+ let status = null;
122787
+ for (let attempt = 0; ; attempt += 1) {
122788
+ const read = await readWaitStatus();
122789
+ if (read === "ended" || typeof read === "object" && "refused" in read) return "not_backup";
122790
+ status = read === "retry" ? null : read.status;
122791
+ if (status || attempt >= BACKUP_FIRST_READ_RETRY_MS.length || stopController.signal.aborted) break;
122792
+ try {
122793
+ await sleep3(BACKUP_FIRST_READ_RETRY_MS[attempt], void 0, { signal: stopController.signal });
122794
+ } catch {
122795
+ break;
122796
+ }
122797
+ }
122798
+ if (!status?.server_backup?.active) return "not_backup";
122799
+ const stored = await readRuntimeState(options.statePath).catch(() => null);
122800
+ const ownDevices = new Set([identity2.deviceId, stored?.deviceId].filter(Boolean).map(String));
122801
+ let offered = false;
122802
+ const stopped = new Promise((resolve14) => {
122803
+ if (stopController.signal.aborted) resolve14(false);
122804
+ else stopController.signal.addEventListener("abort", () => resolve14(false), { once: true });
122805
+ });
122806
+ const withdraw = async () => {
122807
+ if (!offered) return;
122808
+ await reportServerBackupReadiness(
122809
+ options.profileId,
122810
+ false,
122811
+ identity2.deviceId,
122812
+ AbortSignal.timeout(options.stopRequestTimeoutMs ?? STOP_REQUEST_TIMEOUT_MS)
122813
+ ).catch(() => void 0);
122814
+ };
122815
+ process.stderr.write("VTX CLI: Server Mode Backup runs this profile; waiting to take it back.\n");
122816
+ for (; ; ) {
122817
+ if (status) {
122818
+ const backup = status.server_backup;
122819
+ if (!backup?.active) {
122820
+ return String(status.execution_mode || "").trim().toLowerCase() === "client" ? "returned" : "not_backup";
122821
+ }
122822
+ if (backup.enabled && ownDevices.has(String(backup.return_device_id || "").trim())) {
122823
+ const ready = await Promise.race([readyToTakeBack(status), stopped]);
122824
+ if (!stopController.signal.aborted) {
122825
+ offered = true;
122826
+ await reportServerBackupReadiness(options.profileId, ready, identity2.deviceId, stopController.signal).catch(() => void 0);
122827
+ }
122828
+ }
122829
+ }
122830
+ if (options.shouldYieldForUpdate && await options.shouldYieldForUpdate()) {
122831
+ await withdraw();
122832
+ return "yielded_for_update";
122833
+ }
122834
+ try {
122835
+ await sleep3(options.serverBackupWaitMs ?? BACKUP_WAIT_TICK_MS, void 0, { signal: stopController.signal });
122836
+ } catch {
122837
+ await withdraw();
122838
+ return "stopped";
122839
+ }
122840
+ const read = await readWaitStatus();
122841
+ if (read === "ended") {
122842
+ await withdraw();
122843
+ return "not_backup";
122844
+ }
122845
+ if (typeof read === "object" && "refused" in read) {
122846
+ await withdraw();
122847
+ throw read.refused;
122848
+ }
122849
+ status = read === "retry" ? null : read.status;
122850
+ if (stopController.signal.aborted) {
122851
+ await withdraw();
122852
+ return "stopped";
122853
+ }
122854
+ }
122855
+ };
122856
+ const waitOutServerBackup = async () => {
122857
+ const waited = await waitForServerBackup();
122858
+ if (waited === "returned") return "resume";
122859
+ if (waited === "stopped") return result("stopped");
122860
+ if (waited === "yielded_for_update") return result("yielded_for_update");
122861
+ return null;
122862
+ };
122232
122863
  let handoffLease = resume?.handoffLease ?? null;
122233
122864
  const start = async (kind) => {
122234
122865
  attached = false;
@@ -122275,11 +122906,21 @@ async function runHeadlessRuntime(options) {
122275
122906
  await clearOwnState();
122276
122907
  throw error48;
122277
122908
  }
122278
- if (!stopController.signal.aborted) throw error48;
122279
- await stopRuntime("agent_cli:stop");
122280
- return result("stopped");
122909
+ if (!stopController.signal.aborted) {
122910
+ const waited = await waitOutServerBackup();
122911
+ if (waited === null && !stopController.signal.aborted) throw error48;
122912
+ if (waited !== null && waited !== "resume") return waited;
122913
+ if (waited === "resume") push({ kind: "resume", immediate: true });
122914
+ else {
122915
+ await stopRuntime("agent_cli:stop");
122916
+ return result("stopped");
122917
+ }
122918
+ } else {
122919
+ await stopRuntime("agent_cli:stop");
122920
+ return result("stopped");
122921
+ }
122281
122922
  }
122282
- stopProtection = firstAttached();
122923
+ if (attached) stopProtection = firstAttached();
122283
122924
  }
122284
122925
  let resumesWithoutCycle = 0;
122285
122926
  let lastResumeError = null;
@@ -122312,6 +122953,18 @@ async function runHeadlessRuntime(options) {
122312
122953
  if (event.kind === "engine_stopped") {
122313
122954
  if (stopController.signal.aborted || !engineEnded()) continue;
122314
122955
  if (snapshot.ownershipLossReason) {
122956
+ const waited = await waitOutServerBackup();
122957
+ if (waited === "resume") {
122958
+ resumesWithoutCycle = 0;
122959
+ lastResumeError = null;
122960
+ push({ kind: "resume", immediate: true });
122961
+ continue;
122962
+ }
122963
+ if (waited) return waited;
122964
+ if (stopController.signal.aborted) {
122965
+ await stopRuntime("agent_cli:stop");
122966
+ return result("stopped");
122967
+ }
122315
122968
  await clearOwnState();
122316
122969
  throw new Error(
122317
122970
  `Client runtime ownership moved (${snapshot.ownershipLossReason})${snapshot.lastError ? `: ${snapshot.lastError}` : ""}.`
@@ -122352,6 +123005,18 @@ async function runHeadlessRuntime(options) {
122352
123005
  await stopRuntime("agent_cli:stop");
122353
123006
  return result("stopped");
122354
123007
  }
123008
+ const waited = await waitOutServerBackup();
123009
+ if (waited !== null) {
123010
+ if (waited !== "resume") return waited;
123011
+ resumesWithoutCycle = 0;
123012
+ lastResumeError = null;
123013
+ push({ kind: "resume", immediate: true });
123014
+ continue;
123015
+ }
123016
+ if (stopController.signal.aborted) {
123017
+ await stopRuntime("agent_cli:stop");
123018
+ return result("stopped");
123019
+ }
122355
123020
  if (classifyReconcileRequestError(error48) !== "transient") throw error48;
122356
123021
  lastResumeError = error48;
122357
123022
  push({ kind: "resume", immediate: false });
@@ -122372,7 +123037,7 @@ async function runHeadlessRuntime(options) {
122372
123037
  }
122373
123038
  }
122374
123039
  }
122375
- var HeadlessRuntimeTakeoverRequiredError, HEADLESS_RUNTIME_AGENT_SCOPES, DEFAULT_MAX_CLAIM_WAITS, STOP_REQUEST_TIMEOUT_MS, PROTECTION_IDLE_RECHECK_MS, PROTECTION_RETRY_MS, MAX_RESUMES_WITHOUT_A_CYCLE, RESUME_BACKOFF_MS;
123040
+ var HeadlessRuntimeTakeoverRequiredError, HEADLESS_RUNTIME_AGENT_SCOPES, DEFAULT_MAX_CLAIM_WAITS, STOP_REQUEST_TIMEOUT_MS, PROTECTION_IDLE_RECHECK_MS, PROTECTION_RETRY_MS, MAX_RESUMES_WITHOUT_A_CYCLE, RESUME_BACKOFF_MS, BACKUP_WAIT_TICK_MS, LOCAL_AI_PREFLIGHT_TIMEOUT_MS, BACKUP_FIRST_READ_RETRY_MS;
122376
123041
  var init_headless_runtime = __esm({
122377
123042
  "lib/agent-core/headless-runtime.ts"() {
122378
123043
  "use strict";
@@ -122391,6 +123056,7 @@ var init_headless_runtime = __esm({
122391
123056
  init_engine();
122392
123057
  init_server_runtime_lease();
122393
123058
  init_reconcile();
123059
+ init_local_ai_preflight();
122394
123060
  HeadlessRuntimeTakeoverRequiredError = class extends Error {
122395
123061
  constructor(response) {
122396
123062
  const owner2 = objectOrNull2(response.owner);
@@ -122412,6 +123078,9 @@ var init_headless_runtime = __esm({
122412
123078
  PROTECTION_RETRY_MS = 15e3;
122413
123079
  MAX_RESUMES_WITHOUT_A_CYCLE = 5;
122414
123080
  RESUME_BACKOFF_MS = [1e3, 5e3, 15e3, 3e4, 6e4];
123081
+ BACKUP_WAIT_TICK_MS = runtime_policy_generated_default2.trading.engine.client_runtime.reconcile.tick_interval_seconds * 1e3;
123082
+ LOCAL_AI_PREFLIGHT_TIMEOUT_MS = runtime_policy_generated_default2.trading.engine.client_runtime.reconcile.local_ai_preflight_timeout_ms;
123083
+ BACKUP_FIRST_READ_RETRY_MS = [1e3, 5e3];
122415
123084
  }
122416
123085
  });
122417
123086