@vtxmacro/cli 2026.10.18 → 2026.10.20

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.18", 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.20", 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
 
@@ -961,6 +961,10 @@ var init_runtime_policy_generated = __esm({
961
961
  },
962
962
  defaults: {
963
963
  server_ai_max_slippage: 5
964
+ },
965
+ risk: {
966
+ max_order_notional: 5e3,
967
+ max_position_notional: 1e4
964
968
  }
965
969
  },
966
970
  agent_cli: {
@@ -1213,6 +1217,7 @@ var init_runtime_policy_generated = __esm({
1213
1217
  metadata_ttl_seconds: 300,
1214
1218
  user_fees_ttl_seconds: 300,
1215
1219
  account_mode_ttl_seconds: 30,
1220
+ ui_account_mode_ttl_seconds: 300,
1216
1221
  default_request_weight: 20,
1217
1222
  cache_max_entries: 512
1218
1223
  },
@@ -1292,6 +1297,9 @@ var init_runtime_policy_generated = __esm({
1292
1297
  websocket: {
1293
1298
  ping_interval_seconds: 20,
1294
1299
  account_open_timeout_seconds: 10
1300
+ },
1301
+ perp_dexs: {
1302
+ default_dex_label: "Hyperliquid"
1295
1303
  }
1296
1304
  },
1297
1305
  cache: {
@@ -1457,7 +1465,7 @@ var init_runtime_policy_generated = __esm({
1457
1465
  });
1458
1466
 
1459
1467
  // lib/constants.ts
1460
- var MS_PER_SECOND, SECONDS_PER_MINUTE, MINUTES_PER_HOUR, HOURS_PER_DAY, DAYS_PER_WEEK, MS_PER_MINUTE, SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, MINUTES_PER_DAY, MINUTES_PER_WEEK, MS_PER_HOUR, MS_PER_DAY, READ_STAMP_TIE_MS, READ_STAMP_STEP_BACK_MS, CLOCK_FIELD_DIGITS, BACKOFF_GROWTH_FACTOR, BYTES_PER_KIB, BYTES_PER_MIB, BITS_PER_BYTE, BYTE_MASK, OWNER_ONLY_FILE_MODE, OWNER_ONLY_DIRECTORY_MODE, GROUP_OTHER_PERMISSION_BITS, DECIMAL_RADIX, HEX_RADIX, BASE36_RADIX, BYTE_HEX_DIGITS, UINT32_HEX_DIGITS, RANDOM_FRACTION_PREFIX_LENGTH, PERCENT_SCALE, MIDPOINT_DIVISOR, SQUARE_EXPONENT, FNV1A_32_OFFSET_BASIS, FNV1A_32_PRIME, JSON_INDENT_SPACES, INT32_MIN, INT32_MAX, SET_TIMEOUT_MAX_DELAY_MS, POSITION_SIZE_EPSILON, CANDLE_TIMEFRAME_SECONDS, HTTP_STATUS, HTTP_STATUS_MIN, HTTP_STATUS_MAX, HTTP_CLIENT_ERROR_MIN, HTTP_SERVER_ERROR_MIN, AI_COST_ESTIMATE_PERIOD_DAYS, SECONDS_PER_AI_COST_ESTIMATE_PERIOD, DATE_FIELD_DIGITS, EXTERNAL_INFERENCE_LIMITS, NODE_ARGV_COMMAND_ARGS_START, EXIT_CODE_TEMPFAIL, SHA256_INITIAL_STATE, SHA256_ROUND_CONSTANTS, SHA256, UINT64_HIGH_WORD_DIVISOR, CANONICAL_BASE64URL, INFERENCE_ENVELOPE_CRYPTO, EXTERNAL_INFERENCE_SCHEMA_BOUNDS, JSON_RPC_ERROR_CODES, INFERENCE_MCP_SCHEMA_PROBE_MAX_DEPTH, INFERENCE_HOST_PROCESS_LOCK_RECORD_SCHEMA_VERSION, INFERENCE_HOST_RECLAIM_GUARD_CREATE_PASSES, LINUX_PROC_STAT_COMM_TERMINATOR_CHARS, INFERENCE_HOST_RANDOM_BYTES, INFERENCE_OAUTH_TOKEN_MAX_LENGTH, INFERENCE_CREDENTIAL_WINDOWS_NOT_FOUND_EXIT_CODE, MACOS_SECURITY_ITEM_NOT_FOUND_EXIT_CODE, INFERENCE_CREDENTIAL_LABEL_ACCOUNT_KEY_CHARS, INFERENCE_HOST_STABLE_OPERATION_ID_HASH_CHARS, INFERENCE_HOST_DRAIN_PRIORITY, INFERENCE_JOB_CLAIM_SCHEMA_VERSION, INFERENCE_HOST_WINDOWS_TASK_IDENTITY_MAX_CHARS, INFERENCE_HOST_OWNER_ONLY_EXECUTABLE_MODE, WINDOWS_TASKKILL_PROCESS_NOT_FOUND_EXIT_CODE, INFERENCE_HOST_CLI_MAX_SERVICE_POSITIONALS, INFERENCE_HOST_CLI_MAX_COMMAND_POSITIONALS, INFERENCE_HOST_DISPLAY_NAME_MAX_CHARS, INFERENCE_HOST_REVOCATION_CHECKPOINT_MAX_CHARS, INFERENCE_HOST_MODEL_ID_MAX_CHARS, CODEX_RECOVERY_RECEIPT_MAX_CHARS, CODEX_HOSTED_ATTEMPT_PATH_SEGMENTS, CODEX_GUARDIAN_PROCESS_TOKEN_BYTES, CODEX_RATE_LIMIT_EXHAUSTED_PERCENT, INFERENCE_HOST_PROXY_TOKEN_BYTES, GROK_TOOL_SERVER_TOKEN_BYTES, GROK_NATIVE_SESSION_GROUP_NAME_MAX_CHARS, GROK_POLICY_TRANSPORT_MAX_BYTES, EXO_POLICY_MAX_TOOL_ROUNDS, EXO_POLICY_MAX_MODELS, EXO_POLICY_MODEL_NAME_MAX_CHARS, EXO_RUNTIME_VERSION_COMMIT_CHARS, PI_QUALIFIED_MODEL_ID_MAX_CHARS, PI_STRUCTURED_OUTPUT_MAX_DEPTH, PI_STRUCTURED_OUTPUT_MAX_PROPERTIES, INFERENCE_HOST_API_KEY_MIN_CHARS, INFERENCE_HOST_API_KEY_MAX_BYTES, INFERENCE_HOST_API_KEY_IDENTITY_HEX_CHARS, DEEPSEEK_HARNESS_NODE_LTS_MAJOR, DEEPSEEK_HARNESS_NODE_LTS_MIN_MINOR, DEEPSEEK_HARNESS_NODE_CURRENT_MAJOR, PROMPT_FIXED_DIGITS, PROMPT_SIGNIFICANT_DIGITS, PROMPT_NUMBER_MAX_DIGITS, PROMPT_PRICE_INTEGER_THRESHOLD, PROMPT_MARGIN_UTILIZATION_DECIMALS, PROMPT_SYMBOL_MAX_CHARS, PROMPT_PARTIAL_UNIT_ROUND_UP_FRACTION, HALF_UP_ROUNDING_OFFSET, PROMPT_ENTRY_PRICE_MATCH_ABS_TOLERANCE, PROMPT_ENTRY_PRICE_MATCH_REL_TOLERANCE, DECISION_OUTPUT_EXAMPLE_TRADABILITY, INDICATOR_RSI_PERIOD, INDICATOR_ATR_PERIOD, INDICATOR_MACD_FAST_PERIOD, INDICATOR_MACD_SLOW_PERIOD, INDICATOR_MACD_SIGNAL_PERIOD, INDICATOR_BOLLINGER_PERIOD, INDICATOR_BOLLINGER_STD_DEV, INDICATOR_OSCILLATOR_MAX, EMA_SMOOTHING_NUMERATOR, PROMPT_EMA_PERIODS, JSON_UNICODE_ESCAPE_PREFIX_LENGTH, JSON_UNICODE_ESCAPE_HEX_DIGITS, JSON_CONTROL_CHARACTER_MAX, RUNTIME_DEBUG_SNIPPET_CHARS, RUNTIME_DEBUG_PROMPT_SNIPPET_CHARS, RUNTIME_DEBUG_TOKEN_PREFIX_CHARS, RUNTIME_DEBUG_USD_DECIMALS, REVIEW_FAILURE_DETAIL_MAX_CHARS, RUNTIME_LATENCY_SECONDS_DECIMALS, AI_SCHEDULE_CLOCK_PARTS, ESTIMATED_CHARS_PER_TOKEN, PROVIDER_ERROR_RAW_TEXT_MAX_CHARS, AI_CALL_COST_DECIMALS, PROVIDER_DIAGNOSTIC_LIMITS, AI_INVOCATION_CONTRACT_VERSION, AI_INVOCATION_TELEMETRY_LIMITS, PROVIDER_USAGE_DETAIL_LIMITS, HYPERLIQUID_EXCHANGE_SPECIFICATION, HYPERLIQUID_TPSL_BATCH_MIN_ORDERS, HYPERLIQUID_USER_FILLS_PROVIDER_PAGE_CAP, HYPERLIQUID_ROW_WEIGHTED_INFO_REQUESTS, HYPERLIQUID_INFO_ROWS_PER_EXTRA_WEIGHT, HYPERLIQUID_META_AND_ASSET_CTXS_PARTS, HYPERLIQUID_SIDE_PAIR_LENGTH, HYPERLIQUID_SIGNED_SIZE_MATCH_EXTRA_DECIMALS, HYPERLIQUID_OPEN_ORDERS_MAX_NESTING_DEPTH, ACCOUNT_PAYLOAD_MODE_SEARCH_MAX_DEPTH, HYPERLIQUID_ACCOUNT_ROUNDING_DECIMALS, HYPERLIQUID_UNREALIZED_PNL_ZERO_TOLERANCE, HYPERLIQUID_MAX_DEPLOYER_FEE_SCALE, HYPERLIQUID_DEPLOYER_FEE_SCALE_MULTIPLIER, HYPERLIQUID_GROWTH_MODE_FEE_FACTOR, HYPERLIQUID_ALIGNED_QUOTE_NON_DEPLOYER_FEE_FACTOR, HYPERLIQUID_CLOSE_SIZE_RELATIVE_TOLERANCE, HYPERLIQUID_POSITION_SIZE_MATCH_ABS_TOLERANCE, HYPERLIQUID_POSITION_SIZE_MATCH_RELATIVE_TOLERANCE, HYPERLIQUID_LOT_FLOOR_NOISE_DECIMALS, HYPERLIQUID_RECOVERY_BACKOFF_MAX_EXPONENT, HYPERLIQUID_RECOVERY_CONCURRENCY_GROWTH_FACTOR, UUID_BYTES, UUID_HEX_GROUP_ENDS, MSGPACK, CLIENT_RUNTIME_DEFAULT_RETRY_SECONDS, CLIENT_RUNTIME_PROVIDER_ATTEMPT_SUMMARY_MAX_CHARS, CLIENT_RUNTIME_HL_REQUEST_TYPE_MAX_CHARS, CLIENT_RUNTIME_DRAWDOWN_DEBUG_DECIMALS, CLIENT_PROTECTIVE_GROUP_VERSION, CLIENT_PROTECTIVE_TPSL_PAIR_LEGS, CLIENT_PROTECTIVE_FILL_MATCH_ABS_TOLERANCE, CLIENT_PROTECTIVE_FILL_MATCH_REL_TOLERANCE, CLIENT_CLOSE_FILL_EPSILON_ULPS, COPY_TRADING_SIZE_EPSILON, COPY_TRADING_RELATIVE_SIZE_TOLERANCE, COPY_TRADING_NOTIONAL_CAP_TOLERANCE_USD, CLIENT_ACCOUNT_PNL_NONZERO_MIN_USD, RUNTIME_PORTFOLIO_PERIOD_ENTRY_LENGTH, CLIENT_EXCHANGE_RECONCILIATION_MAX_DELAY_MS, RFC1918_172_BLOCK_SECOND_OCTET, AGENT_CLI_TAKEOVER_REQUIRED_EXIT_CODE, EXIT_CODE_INTERRUPTED, EXIT_CODE_SIGNAL_BASE, BYOK_PROVIDER_DISPLAY_ORDER_STEP, TOKENS_PER_MILLION, RENDER_DEBUG_ID_RANDOM_CHARS;
1468
+ var MS_PER_SECOND, SECONDS_PER_MINUTE, MINUTES_PER_HOUR, HOURS_PER_DAY, DAYS_PER_WEEK, MS_PER_MINUTE, SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, MINUTES_PER_DAY, MINUTES_PER_WEEK, MS_PER_HOUR, MS_PER_DAY, READ_STAMP_TIE_MS, READ_STAMP_STEP_BACK_MS, CLOCK_FIELD_DIGITS, BACKOFF_GROWTH_FACTOR, BYTES_PER_KIB, BYTES_PER_MIB, BITS_PER_BYTE, BYTE_MASK, OWNER_ONLY_FILE_MODE, OWNER_ONLY_DIRECTORY_MODE, GROUP_OTHER_PERMISSION_BITS, DECIMAL_RADIX, HEX_RADIX, BASE36_RADIX, BYTE_HEX_DIGITS, UINT32_HEX_DIGITS, RANDOM_FRACTION_PREFIX_LENGTH, PERCENT_SCALE, MIDPOINT_DIVISOR, SQUARE_EXPONENT, FNV1A_32_OFFSET_BASIS, FNV1A_32_PRIME, JSON_INDENT_SPACES, INT32_MIN, INT32_MAX, SET_TIMEOUT_MAX_DELAY_MS, POSITION_SIZE_EPSILON, CANDLE_TIMEFRAME_SECONDS, HTTP_STATUS, HTTP_STATUS_MIN, HTTP_STATUS_MAX, HTTP_CLIENT_ERROR_MIN, HTTP_SERVER_ERROR_MIN, USD_DISPLAY_DECIMALS, AI_COST_ESTIMATE_PERIOD_DAYS, SECONDS_PER_AI_COST_ESTIMATE_PERIOD, DATE_FIELD_DIGITS, EXTERNAL_INFERENCE_LIMITS, NODE_ARGV_COMMAND_ARGS_START, EXIT_CODE_TEMPFAIL, SHA256_INITIAL_STATE, SHA256_ROUND_CONSTANTS, SHA256, UINT64_HIGH_WORD_DIVISOR, CANONICAL_BASE64URL, INFERENCE_ENVELOPE_CRYPTO, EXTERNAL_INFERENCE_SCHEMA_BOUNDS, JSON_RPC_ERROR_CODES, INFERENCE_MCP_SCHEMA_PROBE_MAX_DEPTH, INFERENCE_HOST_PROCESS_LOCK_RECORD_SCHEMA_VERSION, INFERENCE_HOST_RECLAIM_GUARD_CREATE_PASSES, LINUX_PROC_STAT_COMM_TERMINATOR_CHARS, INFERENCE_HOST_RANDOM_BYTES, INFERENCE_OAUTH_TOKEN_MAX_LENGTH, INFERENCE_CREDENTIAL_WINDOWS_NOT_FOUND_EXIT_CODE, MACOS_SECURITY_ITEM_NOT_FOUND_EXIT_CODE, INFERENCE_CREDENTIAL_LABEL_ACCOUNT_KEY_CHARS, INFERENCE_HOST_STABLE_OPERATION_ID_HASH_CHARS, INFERENCE_HOST_DRAIN_PRIORITY, INFERENCE_JOB_CLAIM_SCHEMA_VERSION, INFERENCE_HOST_WINDOWS_TASK_IDENTITY_MAX_CHARS, INFERENCE_HOST_OWNER_ONLY_EXECUTABLE_MODE, WINDOWS_TASKKILL_PROCESS_NOT_FOUND_EXIT_CODE, INFERENCE_HOST_CLI_MAX_SERVICE_POSITIONALS, INFERENCE_HOST_CLI_MAX_COMMAND_POSITIONALS, INFERENCE_HOST_DISPLAY_NAME_MAX_CHARS, INFERENCE_HOST_REVOCATION_CHECKPOINT_MAX_CHARS, INFERENCE_HOST_MODEL_ID_MAX_CHARS, CODEX_RECOVERY_RECEIPT_MAX_CHARS, CODEX_HOSTED_ATTEMPT_PATH_SEGMENTS, CODEX_GUARDIAN_PROCESS_TOKEN_BYTES, CODEX_RATE_LIMIT_EXHAUSTED_PERCENT, INFERENCE_HOST_PROXY_TOKEN_BYTES, GROK_TOOL_SERVER_TOKEN_BYTES, GROK_NATIVE_SESSION_GROUP_NAME_MAX_CHARS, GROK_POLICY_TRANSPORT_MAX_BYTES, EXO_POLICY_MAX_TOOL_ROUNDS, EXO_POLICY_MAX_MODELS, EXO_POLICY_MODEL_NAME_MAX_CHARS, EXO_RUNTIME_VERSION_COMMIT_CHARS, PI_QUALIFIED_MODEL_ID_MAX_CHARS, PI_STRUCTURED_OUTPUT_MAX_DEPTH, PI_STRUCTURED_OUTPUT_MAX_PROPERTIES, INFERENCE_HOST_API_KEY_MIN_CHARS, INFERENCE_HOST_API_KEY_MAX_BYTES, INFERENCE_HOST_API_KEY_IDENTITY_HEX_CHARS, DEEPSEEK_HARNESS_NODE_LTS_MAJOR, DEEPSEEK_HARNESS_NODE_LTS_MIN_MINOR, DEEPSEEK_HARNESS_NODE_CURRENT_MAJOR, PROMPT_FIXED_DIGITS, PROMPT_SIGNIFICANT_DIGITS, PROMPT_NUMBER_MAX_DIGITS, PROMPT_PRICE_INTEGER_THRESHOLD, PROMPT_MARGIN_UTILIZATION_DECIMALS, PROMPT_SYMBOL_MAX_CHARS, PROMPT_PARTIAL_UNIT_ROUND_UP_FRACTION, HALF_UP_ROUNDING_OFFSET, PROMPT_ENTRY_PRICE_MATCH_ABS_TOLERANCE, PROMPT_ENTRY_PRICE_MATCH_REL_TOLERANCE, DECISION_OUTPUT_EXAMPLE_TRADABILITY, INDICATOR_RSI_PERIOD, INDICATOR_ATR_PERIOD, INDICATOR_MACD_FAST_PERIOD, INDICATOR_MACD_SLOW_PERIOD, INDICATOR_MACD_SIGNAL_PERIOD, INDICATOR_BOLLINGER_PERIOD, INDICATOR_BOLLINGER_STD_DEV, INDICATOR_OSCILLATOR_MAX, EMA_SMOOTHING_NUMERATOR, PROMPT_EMA_PERIODS, JSON_UNICODE_ESCAPE_PREFIX_LENGTH, JSON_UNICODE_ESCAPE_HEX_DIGITS, JSON_CONTROL_CHARACTER_MAX, RUNTIME_DEBUG_SNIPPET_CHARS, RUNTIME_DEBUG_PROMPT_SNIPPET_CHARS, RUNTIME_DEBUG_TOKEN_PREFIX_CHARS, RUNTIME_DEBUG_USD_DECIMALS, REVIEW_FAILURE_DETAIL_MAX_CHARS, RUNTIME_LATENCY_SECONDS_DECIMALS, AI_SCHEDULE_CLOCK_PARTS, ESTIMATED_CHARS_PER_TOKEN, PROVIDER_ERROR_RAW_TEXT_MAX_CHARS, AI_CALL_COST_DECIMALS, PROVIDER_DIAGNOSTIC_LIMITS, AI_INVOCATION_CONTRACT_VERSION, AI_INVOCATION_TELEMETRY_LIMITS, PROVIDER_USAGE_DETAIL_LIMITS, HYPERLIQUID_EXCHANGE_SPECIFICATION, HYPERLIQUID_TPSL_BATCH_MIN_ORDERS, HYPERLIQUID_USER_FILLS_PROVIDER_PAGE_CAP, HYPERLIQUID_ROW_WEIGHTED_INFO_REQUESTS, HYPERLIQUID_INFO_ROWS_PER_EXTRA_WEIGHT, HYPERLIQUID_META_AND_ASSET_CTXS_PARTS, HYPERLIQUID_SIDE_PAIR_LENGTH, HYPERLIQUID_SIGNED_SIZE_MATCH_EXTRA_DECIMALS, HYPERLIQUID_OPEN_ORDERS_MAX_NESTING_DEPTH, ACCOUNT_PAYLOAD_MODE_SEARCH_MAX_DEPTH, HYPERLIQUID_ACCOUNT_ROUNDING_DECIMALS, HYPERLIQUID_UNREALIZED_PNL_ZERO_TOLERANCE, HYPERLIQUID_MAX_DEPLOYER_FEE_SCALE, HYPERLIQUID_DEPLOYER_FEE_SCALE_MULTIPLIER, HYPERLIQUID_GROWTH_MODE_FEE_FACTOR, HYPERLIQUID_ALIGNED_QUOTE_NON_DEPLOYER_FEE_FACTOR, HYPERLIQUID_CLOSE_SIZE_RELATIVE_TOLERANCE, HYPERLIQUID_POSITION_SIZE_MATCH_ABS_TOLERANCE, HYPERLIQUID_POSITION_SIZE_MATCH_RELATIVE_TOLERANCE, HYPERLIQUID_LOT_FLOOR_NOISE_DECIMALS, HYPERLIQUID_RECOVERY_BACKOFF_MAX_EXPONENT, HYPERLIQUID_RECOVERY_CONCURRENCY_GROWTH_FACTOR, UUID_BYTES, UUID_HEX_GROUP_ENDS, MSGPACK, CLIENT_RUNTIME_DEFAULT_RETRY_SECONDS, CLIENT_RUNTIME_PROVIDER_ATTEMPT_SUMMARY_MAX_CHARS, CLIENT_RUNTIME_HL_REQUEST_TYPE_MAX_CHARS, CLIENT_RUNTIME_DRAWDOWN_DEBUG_DECIMALS, CLIENT_PROTECTIVE_GROUP_VERSION, CLIENT_PROTECTIVE_TPSL_PAIR_LEGS, CLIENT_PROTECTIVE_FILL_MATCH_ABS_TOLERANCE, CLIENT_PROTECTIVE_FILL_MATCH_REL_TOLERANCE, CLIENT_CLOSE_FILL_EPSILON_ULPS, COPY_TRADING_SIZE_EPSILON, COPY_TRADING_RELATIVE_SIZE_TOLERANCE, COPY_TRADING_NOTIONAL_CAP_TOLERANCE_USD, CLIENT_ACCOUNT_PNL_NONZERO_MIN_USD, RUNTIME_PORTFOLIO_PERIOD_ENTRY_LENGTH, CLIENT_EXCHANGE_RECONCILIATION_MAX_DELAY_MS, RFC1918_172_BLOCK_SECOND_OCTET, AGENT_CLI_TAKEOVER_REQUIRED_EXIT_CODE, EXIT_CODE_INTERRUPTED, EXIT_CODE_SIGNAL_BASE, BYOK_PROVIDER_DISPLAY_ORDER_STEP, TOKENS_PER_MILLION, RENDER_DEBUG_ID_RANDOM_CHARS;
1461
1469
  var init_constants = __esm({
1462
1470
  "lib/constants.ts"() {
1463
1471
  "use strict";
@@ -1550,6 +1558,7 @@ var init_constants = __esm({
1550
1558
  HTTP_STATUS_MAX = 599;
1551
1559
  HTTP_CLIENT_ERROR_MIN = 400;
1552
1560
  HTTP_SERVER_ERROR_MIN = 500;
1561
+ USD_DISPLAY_DECIMALS = 2;
1553
1562
  AI_COST_ESTIMATE_PERIOD_DAYS = 30;
1554
1563
  SECONDS_PER_AI_COST_ESTIMATE_PERIOD = SECONDS_PER_DAY * AI_COST_ESTIMATE_PERIOD_DAYS;
1555
1564
  DATE_FIELD_DIGITS = 2;
@@ -20766,6 +20775,10 @@ var init_runtime_policy_generated2 = __esm({
20766
20775
  },
20767
20776
  defaults: {
20768
20777
  server_ai_max_slippage: 5
20778
+ },
20779
+ risk: {
20780
+ max_order_notional: 5e3,
20781
+ max_position_notional: 1e4
20769
20782
  }
20770
20783
  },
20771
20784
  agent_cli: {
@@ -21018,6 +21031,7 @@ var init_runtime_policy_generated2 = __esm({
21018
21031
  metadata_ttl_seconds: 300,
21019
21032
  user_fees_ttl_seconds: 300,
21020
21033
  account_mode_ttl_seconds: 30,
21034
+ ui_account_mode_ttl_seconds: 300,
21021
21035
  default_request_weight: 20,
21022
21036
  cache_max_entries: 512
21023
21037
  },
@@ -21097,6 +21111,9 @@ var init_runtime_policy_generated2 = __esm({
21097
21111
  websocket: {
21098
21112
  ping_interval_seconds: 20,
21099
21113
  account_open_timeout_seconds: 10
21114
+ },
21115
+ perp_dexs: {
21116
+ default_dex_label: "Hyperliquid"
21100
21117
  }
21101
21118
  },
21102
21119
  cache: {
@@ -54314,7 +54331,7 @@ var init_hyperliquid_market_symbol = __esm({
54314
54331
  });
54315
54332
 
54316
54333
  // lib/runtime/bot-exchanges.ts
54317
- var exchangesByProfile, profileKey, dexList, recordBotExchanges, recordStatusExchanges;
54334
+ var exchangesByProfile, exchangesVersion, exchangeListeners, exchangesChanged, profileKey, dexList, recordBotExchanges, recordStatusExchanges;
54318
54335
  var init_bot_exchanges = __esm({
54319
54336
  "lib/runtime/bot-exchanges.ts"() {
54320
54337
  "use strict";
@@ -54323,6 +54340,12 @@ var init_bot_exchanges = __esm({
54323
54340
  init_define_VTX_PI_MODEL_POLICY();
54324
54341
  init_hyperliquid_market_symbol();
54325
54342
  exchangesByProfile = /* @__PURE__ */ new Map();
54343
+ exchangesVersion = 0;
54344
+ exchangeListeners = /* @__PURE__ */ new Set();
54345
+ exchangesChanged = () => {
54346
+ exchangesVersion += 1;
54347
+ exchangeListeners.forEach((listener) => listener());
54348
+ };
54326
54349
  profileKey = (profileId) => {
54327
54350
  const id2 = Number(profileId);
54328
54351
  return Number.isInteger(id2) && id2 > 0 ? id2 : null;
@@ -54333,11 +54356,14 @@ var init_bot_exchanges = __esm({
54333
54356
  if (id2 === null) return;
54334
54357
  const equity = dexList(equityVenues);
54335
54358
  const read = readVenues === void 0 ? equity : dexList(readVenues);
54359
+ const previous = exchangesByProfile.get(id2);
54336
54360
  if (!equity || !read) {
54337
- exchangesByProfile.delete(id2);
54361
+ if (exchangesByProfile.delete(id2)) exchangesChanged();
54338
54362
  return;
54339
54363
  }
54364
+ if (previous && previous.equity.join() === equity.join() && previous.read.join() === read.join()) return;
54340
54365
  exchangesByProfile.set(id2, { equity, read });
54366
+ exchangesChanged();
54341
54367
  };
54342
54368
  recordStatusExchanges = (status) => {
54343
54369
  const fields = status;
@@ -54773,7 +54799,7 @@ async function getLiveTicker(symbol2 = "PI_XBTUSD", exchange = "kraken", signal)
54773
54799
  }
54774
54800
  async function getExecutionAssetMetadata(exchange, symbol2, options) {
54775
54801
  const params = new URLSearchParams();
54776
- if (options?.includePrivateContext) params.set("include_private_context", "true");
54802
+ if (options?.forceCatalogRefresh) params.set("force_catalog_refresh", "true");
54777
54803
  if (options?.publicRequestPriority) params.set("public_request_priority", options.publicRequestPriority);
54778
54804
  const query = params.size > 0 ? `?${params.toString()}` : "";
54779
54805
  const url2 = `${getApiUrl()}/trading/execution-metadata/${encodeURIComponent(exchange)}/${encodeURIComponent(symbol2)}${query}`;
@@ -55253,8 +55279,225 @@ var init_hyperliquid_account_mode_contract = __esm({
55253
55279
  }
55254
55280
  });
55255
55281
 
55282
+ // lib/runtime/server-loop-account-value.ts
55283
+ var STABLE_SPOT_SYMBOLS, toNumber, firstTruthy, spotContainers, extractCanonicalSpotMetrics, stableOrPricedValueUsd, sumBalanceValueUsd, sumBalanceHoldUsd, approximatelyEqual, balancesMirrorUnifiedAccountValue, computeEffectiveAccountValue, requireThreshold, serverLoopAccountValue;
55284
+ var init_server_loop_account_value = __esm({
55285
+ "lib/runtime/server-loop-account-value.ts"() {
55286
+ "use strict";
55287
+ init_define_VTX_EXO_POLICY();
55288
+ init_define_VTX_GROK_POLICY();
55289
+ init_define_VTX_PI_MODEL_POLICY();
55290
+ init_hyperliquid_account_mode_contract();
55291
+ STABLE_SPOT_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USD", "USDT"]);
55292
+ toNumber = (value, fallback = 0) => {
55293
+ const numeric2 = Number(value);
55294
+ return Number.isFinite(numeric2) ? numeric2 : fallback;
55295
+ };
55296
+ firstTruthy = (values, fallback) => {
55297
+ for (const value of values) {
55298
+ if (value) return value;
55299
+ }
55300
+ return fallback;
55301
+ };
55302
+ spotContainers = (spotResponse) => {
55303
+ if (!spotResponse || typeof spotResponse !== "object" || Array.isArray(spotResponse)) return [];
55304
+ const response = spotResponse;
55305
+ const containers = [response];
55306
+ for (const key of ["spotState", "userState", "clearinghouseState", "state", "data"]) {
55307
+ const child = response[key];
55308
+ if (child && typeof child === "object" && !Array.isArray(child)) containers.push(child);
55309
+ }
55310
+ return containers;
55311
+ };
55312
+ extractCanonicalSpotMetrics = (spotResponse) => {
55313
+ const response = spotResponse && typeof spotResponse === "object" && !Array.isArray(spotResponse) ? spotResponse : {};
55314
+ const containers = spotContainers(response);
55315
+ let accountValue = 0;
55316
+ let totalMarginUsed = 0;
55317
+ let withdrawable = 0;
55318
+ for (const container of containers) {
55319
+ const marginSummary = container.marginSummary && typeof container.marginSummary === "object" && !Array.isArray(container.marginSummary) ? container.marginSummary : {};
55320
+ accountValue = Math.max(accountValue, toNumber(marginSummary.accountValue));
55321
+ totalMarginUsed = Math.max(totalMarginUsed, toNumber(marginSummary.totalMarginUsed));
55322
+ withdrawable = Math.max(withdrawable, toNumber(container.withdrawable));
55323
+ }
55324
+ if (accountValue <= 0) {
55325
+ for (const key of ["accountValue", "totalValue", "equity", "totalRawUsd", "usdValue", "usdcValue"]) {
55326
+ accountValue = Math.max(accountValue, toNumber(response[key]));
55327
+ }
55328
+ }
55329
+ const balances = [];
55330
+ const listKeys = ["balances", "tokenBalances", "spotBalances", "assets"];
55331
+ for (const container of containers) {
55332
+ for (const listKey of listKeys) {
55333
+ const bucket = container[listKey];
55334
+ if (!Array.isArray(bucket)) continue;
55335
+ let stableTotal = 0;
55336
+ let anyTotal = 0;
55337
+ for (const rawEntry of bucket) {
55338
+ if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) continue;
55339
+ const entry = rawEntry;
55340
+ const coin = String(firstTruthy([
55341
+ entry.coin,
55342
+ entry.token,
55343
+ entry.asset,
55344
+ entry.symbol
55345
+ ], "")).trim().toUpperCase();
55346
+ if (!coin) continue;
55347
+ const total = toNumber(firstTruthy([entry.total, entry.balance, entry.amount], "0"));
55348
+ const hold = toNumber(firstTruthy([entry.hold, entry.locked], "0"));
55349
+ const available = Math.max(
55350
+ 0,
55351
+ toNumber(firstTruthy([entry.available, entry.free, total - hold], "0"))
55352
+ );
55353
+ let valueUsd = toNumber(firstTruthy([entry.usdValue, entry.usdcValue], "0"));
55354
+ if (valueUsd <= 0 && STABLE_SPOT_SYMBOLS.has(coin)) {
55355
+ valueUsd = available > 0 ? available : total;
55356
+ }
55357
+ balances.push({ coin, total, hold, available, value_usd: valueUsd });
55358
+ const entryValue = valueUsd > 0 ? valueUsd : total;
55359
+ if (entryValue > 0) {
55360
+ anyTotal += entryValue;
55361
+ if (STABLE_SPOT_SYMBOLS.has(coin)) stableTotal += entryValue;
55362
+ }
55363
+ }
55364
+ if (accountValue <= 0) {
55365
+ if (stableTotal > 0) accountValue = stableTotal;
55366
+ else if (anyTotal > 0) accountValue = anyTotal;
55367
+ }
55368
+ }
55369
+ if (balances.length > 0) break;
55370
+ }
55371
+ return { accountValue, totalMarginUsed, withdrawable, balances };
55372
+ };
55373
+ stableOrPricedValueUsd = (balance) => {
55374
+ const valueUsd = toNumber(balance.value_usd);
55375
+ if (valueUsd <= 0 && STABLE_SPOT_SYMBOLS.has(String(balance.coin || "").trim().toUpperCase())) {
55376
+ return toNumber(balance.total);
55377
+ }
55378
+ return valueUsd;
55379
+ };
55380
+ sumBalanceValueUsd = (balances) => balances.reduce(
55381
+ (total, balance) => total + Math.max(stableOrPricedValueUsd(balance), 0),
55382
+ 0
55383
+ );
55384
+ sumBalanceHoldUsd = (balances) => balances.reduce((total, balance) => {
55385
+ const valueUsd = stableOrPricedValueUsd(balance);
55386
+ const amount = toNumber(balance.total);
55387
+ if (valueUsd <= 0 || amount <= 0) return total;
55388
+ return total + Math.max(0, valueUsd * (toNumber(balance.hold) / amount));
55389
+ }, 0);
55390
+ approximatelyEqual = (left, right, absoluteToleranceUsd, relativeTolerance) => {
55391
+ const reference = Math.max(Math.abs(left), Math.abs(right), 1);
55392
+ return Math.abs(left - right) <= Math.max(absoluteToleranceUsd, reference * relativeTolerance);
55393
+ };
55394
+ balancesMirrorUnifiedAccountValue = (input) => input.perpsEquity > 0 && input.spotEquity > 0 && input.balancesEquity > 0 && approximatelyEqual(
55395
+ input.perpsEquity,
55396
+ input.spotEquity,
55397
+ input.absoluteToleranceUsd,
55398
+ input.relativeTolerance
55399
+ ) && approximatelyEqual(
55400
+ input.spotEquity,
55401
+ input.balancesEquity,
55402
+ input.absoluteToleranceUsd,
55403
+ input.relativeTolerance
55404
+ );
55405
+ computeEffectiveAccountValue = (input) => {
55406
+ if (!input.unifiedLike) return input.perpsEquity;
55407
+ if (input.balancesEquity > 0) {
55408
+ if (input.mirrored) {
55409
+ return Math.max(input.perpsEquity, input.spotEquity, input.balancesEquity);
55410
+ }
55411
+ return Math.max(
55412
+ input.perpsEquity + input.balancesEquity,
55413
+ input.spotEquity,
55414
+ input.balancesEquity
55415
+ );
55416
+ }
55417
+ return Math.max(input.perpsEquity, input.spotEquity);
55418
+ };
55419
+ requireThreshold = (value, key) => {
55420
+ const numeric2 = typeof value === "number" ? value : Number.NaN;
55421
+ if (!Number.isFinite(numeric2) || numeric2 < 0) {
55422
+ throw new Error(`Missing required Hyperliquid account-state configuration: ${key}`);
55423
+ }
55424
+ return numeric2;
55425
+ };
55426
+ serverLoopAccountValue = (input) => {
55427
+ const { classification } = input;
55428
+ const spotDominatesMinTotalUsd = requireThreshold(
55429
+ input.spotDominatesMinTotalUsd,
55430
+ "client_runtime_hyperliquid_account_state.spot_dominates_min_total_usd"
55431
+ );
55432
+ const spotDominatesPerpsMultiplier = requireThreshold(
55433
+ input.spotDominatesPerpsMultiplier,
55434
+ "client_runtime_hyperliquid_account_state.spot_dominates_perps_multiplier"
55435
+ );
55436
+ const spotAvailableToTradeRatioThreshold = requireThreshold(
55437
+ classification.spotAvailableToTradeRatioThreshold,
55438
+ "client_runtime_hyperliquid_account_state.spot_available_to_trade_ratio_threshold"
55439
+ );
55440
+ const spotMeaningfulHoldUsd = requireThreshold(
55441
+ classification.spotMeaningfulHoldUsd,
55442
+ "client_runtime_hyperliquid_account_state.spot_meaningful_hold_usd"
55443
+ );
55444
+ const spotVeryStrongTotalUsd = requireThreshold(
55445
+ classification.spotVeryStrongTotalUsd,
55446
+ "client_runtime_hyperliquid_account_state.spot_very_strong_total_usd"
55447
+ );
55448
+ const spotVeryStrongPerpsEquityThresholdUsd = requireThreshold(
55449
+ classification.spotVeryStrongPerpsEquityThresholdUsd,
55450
+ "client_runtime_hyperliquid_account_state.spot_very_strong_perps_equity_threshold_usd"
55451
+ );
55452
+ const absoluteToleranceUsd = requireThreshold(
55453
+ input.mirroredAccountValueAbsoluteToleranceUsd,
55454
+ "client_runtime_hyperliquid_account_state.mirrored_account_value_absolute_tolerance_usd"
55455
+ );
55456
+ const relativeTolerance = requireThreshold(
55457
+ input.mirroredAccountValueRelativeTolerance,
55458
+ "client_runtime_hyperliquid_account_state.mirrored_account_value_relative_tolerance"
55459
+ );
55460
+ const perps = input.perpsResponse && typeof input.perpsResponse === "object" && !Array.isArray(input.perpsResponse) ? input.perpsResponse : {};
55461
+ const rawPerpsAccountValue = toNumber(perps.marginSummary?.accountValue);
55462
+ const perpsEquity = Math.max(rawPerpsAccountValue, 0);
55463
+ const spot = extractCanonicalSpotMetrics(input.spotResponse);
55464
+ const spotEquity = Math.max(spot.accountValue, 0);
55465
+ const balancesEquity = sumBalanceValueUsd(spot.balances);
55466
+ const accountMode = classification.exactAccountMode ?? input.accountMode;
55467
+ let unifiedLike = isUnifiedAccountMode(accountMode);
55468
+ const defaultMode = String(accountMode ?? "").trim() === "" || normalizeCanonicalHyperliquidAccountMode(accountMode) === "default";
55469
+ if (!unifiedLike && defaultMode) {
55470
+ const [availableBuy, availableSell] = classification.availableToTrade ?? [0, 0];
55471
+ const equityBase = rawPerpsAccountValue > 0 ? rawPerpsAccountValue : spotEquity;
55472
+ const spotRatio = equityBase > 0 ? spot.accountValue / equityBase : 0;
55473
+ const tradableWithSpotCollateral = classification.availableToTrade !== null && balancesEquity >= spotDominatesMinTotalUsd && Math.max(availableBuy, availableSell) > 0 && spotRatio >= spotAvailableToTradeRatioThreshold;
55474
+ const spotDominates = balancesEquity >= spotDominatesMinTotalUsd && (perpsEquity <= 0 || balancesEquity >= perpsEquity * spotDominatesPerpsMultiplier);
55475
+ const meaningfulHold = sumBalanceHoldUsd(spot.balances) >= spotMeaningfulHoldUsd;
55476
+ const veryStrongSpot = balancesEquity >= spotVeryStrongTotalUsd && perpsEquity <= spotVeryStrongPerpsEquityThresholdUsd;
55477
+ unifiedLike = tradableWithSpotCollateral || spot.balances.length > 0 && spotDominates && (meaningfulHold || veryStrongSpot);
55478
+ }
55479
+ return {
55480
+ accountValue: computeEffectiveAccountValue({
55481
+ perpsEquity,
55482
+ spotEquity,
55483
+ balancesEquity,
55484
+ unifiedLike,
55485
+ mirrored: balancesMirrorUnifiedAccountValue({
55486
+ perpsEquity,
55487
+ spotEquity,
55488
+ balancesEquity,
55489
+ absoluteToleranceUsd,
55490
+ relativeTolerance
55491
+ })
55492
+ }),
55493
+ valuedAsUnified: unifiedLike
55494
+ };
55495
+ };
55496
+ }
55497
+ });
55498
+
55256
55499
  // lib/runtime/hyperliquid-account-contract.ts
55257
- var toNumber, firstNumber, roundTo, canonicalAvailableMargin, STABLE_SPOT_SYMBOLS, spotBalanceValueUsd, normalizeSpotBalancesFromInfoResponse, sumBalanceHoldUsd, sumPositionUnrealizedPnl, resolveTotalUnrealizedPnl, approximatelyEqualAccountValues, buildAccountSummaryFromInfoResponses;
55500
+ var toNumber2, firstNumber, roundTo, canonicalAvailableMargin, spotBalanceValueUsd, normalizeSpotBalancesFromInfoResponse, sumBalanceHoldUsd2, sumPositionUnrealizedPnl, resolveTotalUnrealizedPnl, approximatelyEqualAccountValues, accountValueThresholds, serverLoopValuation, serverLoopValuationCountsSpot, buildAccountSummaryFromInfoResponses;
55258
55501
  var init_hyperliquid_account_contract = __esm({
55259
55502
  "lib/runtime/hyperliquid-account-contract.ts"() {
55260
55503
  "use strict";
@@ -55263,7 +55506,8 @@ var init_hyperliquid_account_contract = __esm({
55263
55506
  init_define_VTX_PI_MODEL_POLICY();
55264
55507
  init_hyperliquid_account_mode_contract();
55265
55508
  init_constants();
55266
- toNumber = (value, fallback = 0) => {
55509
+ init_server_loop_account_value();
55510
+ toNumber2 = (value, fallback = 0) => {
55267
55511
  const numeric2 = Number(value);
55268
55512
  return Number.isFinite(numeric2) ? numeric2 : fallback;
55269
55513
  };
@@ -55281,7 +55525,6 @@ var init_hyperliquid_account_contract = __esm({
55281
55525
  };
55282
55526
  roundTo = (value, digits = HYPERLIQUID_ACCOUNT_ROUNDING_DECIMALS) => Number(value.toFixed(digits));
55283
55527
  canonicalAvailableMargin = (accountValue, totalMarginUsed) => Math.max(0, accountValue - totalMarginUsed);
55284
- STABLE_SPOT_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USD", "USDT"]);
55285
55528
  spotBalanceValueUsd = (balance, coin, total) => {
55286
55529
  const explicit = firstNumber([balance?.value_usd, balance?.usdValue, balance?.usdcValue], Number.NaN);
55287
55530
  if (Number.isFinite(explicit)) {
@@ -55304,8 +55547,8 @@ var init_hyperliquid_account_contract = __esm({
55304
55547
  const balances = Array.isArray(firstWithBalances?.balances) ? firstWithBalances.balances : [];
55305
55548
  return balances.map((balance) => {
55306
55549
  const coin = String(balance?.coin ?? "").toUpperCase();
55307
- const total = toNumber(balance?.total, 0);
55308
- const hold = toNumber(balance?.hold, 0);
55550
+ const total = toNumber2(balance?.total, 0);
55551
+ const hold = toNumber2(balance?.hold, 0);
55309
55552
  const available = roundTo(Math.max(0, total - hold));
55310
55553
  const value_usd = spotBalanceValueUsd(balance, coin, total);
55311
55554
  return {
@@ -55317,10 +55560,10 @@ var init_hyperliquid_account_contract = __esm({
55317
55560
  };
55318
55561
  }).filter((balance) => balance.coin.length > 0);
55319
55562
  };
55320
- sumBalanceHoldUsd = (balances) => balances.reduce((acc, balance) => {
55321
- const hold = toNumber(balance.hold, 0);
55322
- const total = toNumber(balance.total, 0);
55323
- const valueUsd = toNumber(balance.value_usd, 0);
55563
+ sumBalanceHoldUsd2 = (balances) => balances.reduce((acc, balance) => {
55564
+ const hold = toNumber2(balance.hold, 0);
55565
+ const total = toNumber2(balance.total, 0);
55566
+ const valueUsd = toNumber2(balance.value_usd, 0);
55324
55567
  if (hold <= 0 || total <= 0 || valueUsd <= 0) {
55325
55568
  return acc;
55326
55569
  }
@@ -55329,12 +55572,12 @@ var init_hyperliquid_account_contract = __esm({
55329
55572
  sumPositionUnrealizedPnl = (perpsResponse) => {
55330
55573
  const assetPositions = Array.isArray(perpsResponse?.assetPositions) ? perpsResponse.assetPositions : [];
55331
55574
  return assetPositions.reduce((total, entry) => {
55332
- const unrealizedPnl = toNumber(entry?.position?.unrealizedPnl, 0);
55575
+ const unrealizedPnl = toNumber2(entry?.position?.unrealizedPnl, 0);
55333
55576
  return total + unrealizedPnl;
55334
55577
  }, 0);
55335
55578
  };
55336
55579
  resolveTotalUnrealizedPnl = (perpsResponse) => {
55337
- const topLevel = toNumber(perpsResponse?.totalUnrealizedPnl, 0);
55580
+ const topLevel = toNumber2(perpsResponse?.totalUnrealizedPnl, 0);
55338
55581
  const positionTotal = sumPositionUnrealizedPnl(perpsResponse);
55339
55582
  if (Math.abs(topLevel) < HYPERLIQUID_UNREALIZED_PNL_ZERO_TOLERANCE && Math.abs(positionTotal) >= HYPERLIQUID_UNREALIZED_PNL_ZERO_TOLERANCE) {
55340
55583
  return positionTotal;
@@ -55348,33 +55591,49 @@ var init_hyperliquid_account_contract = __esm({
55348
55591
  reference * relativeTolerance
55349
55592
  );
55350
55593
  };
55594
+ accountValueThresholds = (options) => ({
55595
+ spotDominatesMinTotalUsd: Number(options.spotDominatesMinTotalUsd ?? options.spot_dominates_min_total_usd),
55596
+ spotDominatesPerpsMultiplier: Number(options.spotDominatesPerpsMultiplier ?? options.spot_dominates_perps_multiplier),
55597
+ mirroredAccountValueAbsoluteToleranceUsd: Number(
55598
+ options.mirroredAccountValueAbsoluteToleranceUsd ?? options.mirrored_account_value_absolute_tolerance_usd
55599
+ ),
55600
+ mirroredAccountValueRelativeTolerance: Number(
55601
+ options.mirroredAccountValueRelativeTolerance ?? options.mirrored_account_value_relative_tolerance
55602
+ )
55603
+ });
55604
+ serverLoopValuation = (perpsResponse, spotResponse, options) => options.serverLoopClassification ? serverLoopAccountValue({
55605
+ perpsResponse,
55606
+ spotResponse,
55607
+ accountMode: extractAccountModeFromPayload(perpsResponse),
55608
+ classification: options.serverLoopClassification,
55609
+ ...accountValueThresholds(options)
55610
+ }) : null;
55611
+ serverLoopValuationCountsSpot = (perpsResponse, spotResponse, options) => serverLoopValuation(perpsResponse, spotResponse, options)?.valuedAsUnified === true;
55351
55612
  buildAccountSummaryFromInfoResponses = (perpsResponse, spotResponse, options = {}) => {
55352
55613
  const marginSummary = perpsResponse?.marginSummary ?? {};
55353
- const perpsAccountValue = toNumber(marginSummary?.accountValue, 0);
55354
- const total_margin_used = toNumber(marginSummary?.totalMarginUsed, 0);
55355
- const totalNtlPos = toNumber(marginSummary?.totalNtlPos, 0);
55356
- const withdrawable = toNumber(perpsResponse?.withdrawable, 0);
55614
+ const perpsAccountValue = toNumber2(marginSummary?.accountValue, 0);
55615
+ const total_margin_used = toNumber2(marginSummary?.totalMarginUsed, 0);
55616
+ const totalNtlPos = toNumber2(marginSummary?.totalNtlPos, 0);
55617
+ const withdrawable = toNumber2(perpsResponse?.withdrawable, 0);
55357
55618
  const maintenance_margin = firstNumber([
55358
55619
  perpsResponse?.crossMaintenanceMarginUsed,
55359
55620
  marginSummary?.crossMaintenanceMarginUsed,
55360
55621
  marginSummary?.totalMaintenanceMargin
55361
55622
  ], 0);
55362
55623
  const balances = normalizeSpotBalancesFromInfoResponse(spotResponse);
55363
- const spotPortfolioValue = balances.reduce((acc, balance) => acc + toNumber(balance.value_usd, 0), 0);
55364
- const balancesHoldUsd = sumBalanceHoldUsd(balances);
55624
+ const spotPortfolioValue = balances.reduce((acc, balance) => acc + toNumber2(balance.value_usd, 0), 0);
55625
+ const balancesHoldUsd = sumBalanceHoldUsd2(balances);
55365
55626
  const account_mode = extractAccountModeFromPayload(perpsResponse);
55366
55627
  const crossMarginSummary = perpsResponse?.crossMarginSummary && typeof perpsResponse.crossMarginSummary === "object" ? perpsResponse.crossMarginSummary : null;
55367
- const crossMarginAccountValue = crossMarginSummary ? toNumber(crossMarginSummary.accountValue, 0) : 0;
55628
+ const crossMarginAccountValue = crossMarginSummary ? toNumber2(crossMarginSummary.accountValue, 0) : 0;
55368
55629
  const normalizedMode = String(account_mode || "").trim().toLowerCase().replace(/[_\s-]/g, "");
55369
55630
  const isAmbiguousDefaultMode = normalizedMode.length === 0 || normalizedMode === "default";
55370
- const spotDominatesMinTotalUsd = Number(options.spotDominatesMinTotalUsd ?? options.spot_dominates_min_total_usd);
55371
- const spotDominatesPerpsMultiplier = Number(options.spotDominatesPerpsMultiplier ?? options.spot_dominates_perps_multiplier);
55372
- const mirroredAccountValueAbsoluteToleranceUsd = Number(
55373
- options.mirroredAccountValueAbsoluteToleranceUsd ?? options.mirrored_account_value_absolute_tolerance_usd
55374
- );
55375
- const mirroredAccountValueRelativeTolerance = Number(
55376
- options.mirroredAccountValueRelativeTolerance ?? options.mirrored_account_value_relative_tolerance
55377
- );
55631
+ const {
55632
+ spotDominatesMinTotalUsd,
55633
+ spotDominatesPerpsMultiplier,
55634
+ mirroredAccountValueAbsoluteToleranceUsd,
55635
+ mirroredAccountValueRelativeTolerance
55636
+ } = accountValueThresholds(options);
55378
55637
  const hasSpotDominanceThresholds = Number.isFinite(spotDominatesMinTotalUsd) && spotDominatesMinTotalUsd >= 0 && Number.isFinite(spotDominatesPerpsMultiplier) && spotDominatesPerpsMultiplier >= 0;
55379
55638
  const hasMirroredAccountValueTolerances = Number.isFinite(mirroredAccountValueAbsoluteToleranceUsd) && mirroredAccountValueAbsoluteToleranceUsd >= 0 && Number.isFinite(mirroredAccountValueRelativeTolerance) && mirroredAccountValueRelativeTolerance >= 0;
55380
55639
  const spotDominatesPerps = hasSpotDominanceThresholds && spotPortfolioValue >= spotDominatesMinTotalUsd && (perpsAccountValue <= 0 || spotPortfolioValue >= perpsAccountValue * spotDominatesPerpsMultiplier);
@@ -55385,7 +55644,8 @@ var init_hyperliquid_account_contract = __esm({
55385
55644
  mirroredAccountValueAbsoluteToleranceUsd,
55386
55645
  mirroredAccountValueRelativeTolerance
55387
55646
  );
55388
- const account_value = isUnifiedAccountMode(account_mode) && crossMarginSummary !== null && crossMarginAccountValue > 0 ? crossMarginAccountValue + spotPortfolioValue : ambiguousDefaultLooksUnified && !ambiguousDefaultSpotAlreadyIncludesPerps ? perpsAccountValue + spotPortfolioValue : Math.max(perpsAccountValue, spotPortfolioValue);
55647
+ const deviceAccountValue = isUnifiedAccountMode(account_mode) && crossMarginSummary !== null && crossMarginAccountValue > 0 ? crossMarginAccountValue + spotPortfolioValue : ambiguousDefaultLooksUnified && !ambiguousDefaultSpotAlreadyIncludesPerps ? perpsAccountValue + spotPortfolioValue : Math.max(perpsAccountValue, spotPortfolioValue);
55648
+ const account_value = serverLoopValuation(perpsResponse, spotResponse, options)?.accountValue ?? deviceAccountValue;
55389
55649
  return {
55390
55650
  account_value,
55391
55651
  total_margin_used,
@@ -55403,7 +55663,7 @@ var init_hyperliquid_account_contract = __esm({
55403
55663
  });
55404
55664
 
55405
55665
  // lib/runtime/order-identity.ts
55406
- var clientOrderIdForMutation, clientDecisionMutationId;
55666
+ var clientOrderIdForMutation, mutationIdForClientOrderId, clientDecisionMutationId;
55407
55667
  var init_order_identity = __esm({
55408
55668
  "lib/runtime/order-identity.ts"() {
55409
55669
  "use strict";
@@ -55412,6 +55672,12 @@ var init_order_identity = __esm({
55412
55672
  init_define_VTX_PI_MODEL_POLICY();
55413
55673
  init_constants();
55414
55674
  clientOrderIdForMutation = (mutationId) => `0x${String(mutationId).trim().toLowerCase().replaceAll("-", "")}`;
55675
+ mutationIdForClientOrderId = (clientOrderId) => {
55676
+ const cloid = String(clientOrderId).trim().toLowerCase();
55677
+ if (!/^0x[0-9a-f]{32}$/.test(cloid)) return null;
55678
+ const hex4 = cloid.slice("0x".length);
55679
+ return UUID_HEX_GROUP_ENDS.map((end, index) => hex4.slice(index === 0 ? 0 : UUID_HEX_GROUP_ENDS[index - 1], end)).join("-");
55680
+ };
55415
55681
  clientDecisionMutationId = async (input) => {
55416
55682
  const key = [
55417
55683
  "client-decision:v1",
@@ -55642,7 +55908,14 @@ var init_hyperliquid_public_read = __esm({
55642
55908
  const ticket = crypto.randomUUID();
55643
55909
  const deadline = Math.min(deadlineMs ?? Infinity, Date.now() + recoveryPolicy.recovery_queue_wait_seconds * MS_PER_SECOND);
55644
55910
  if (hostTransport) {
55645
- const permit = await hostTransport.admission.acquire({ requestType, weight, priority: priority.value, deadlineMs: deadline, signal });
55911
+ const permit = await hostTransport.admission.acquire({
55912
+ requestType,
55913
+ weight,
55914
+ priority: priority.value,
55915
+ currentPriority: () => priority.value,
55916
+ deadlineMs: deadline,
55917
+ signal
55918
+ });
55646
55919
  return { ...permit, endpoint: apiUrl, fleet: true };
55647
55920
  }
55648
55921
  let admitted = false;
@@ -55808,7 +56081,7 @@ var init_hyperliquid_public_read = __esm({
55808
56081
  };
55809
56082
  cacheTtlMs = (body, options) => {
55810
56083
  const requestType = String(body.type);
55811
- return (["meta", "spotMeta", "perpDexs"].includes(requestType) ? policy.metadata_ttl_seconds : requestType === "userFees" ? policy.user_fees_ttl_seconds : options.cacheAccountMode && ["userAbstraction", "userDexAbstraction"].includes(requestType) ? policy.account_mode_ttl_seconds : 0) * MS_PER_SECOND;
56084
+ return (["meta", "spotMeta", "perpDexs"].includes(requestType) ? policy.metadata_ttl_seconds : requestType === "userFees" ? policy.user_fees_ttl_seconds : options.cacheAccountMode && ["userAbstraction", "userDexAbstraction"].includes(requestType) ? options.cacheAccountMode === "display" ? policy.ui_account_mode_ttl_seconds : policy.account_mode_ttl_seconds : 0) * MS_PER_SECOND;
55812
56085
  };
55813
56086
  eligibleCache = (apiUrl, body, options) => {
55814
56087
  const ttl = cacheTtlMs(body, options);
@@ -57453,7 +57726,7 @@ function getNumber(value, name) {
57453
57726
  }
57454
57727
  assertArgument(false, "invalid numeric value", name || "value", value);
57455
57728
  }
57456
- function toNumber2(value) {
57729
+ function toNumber3(value) {
57457
57730
  return getNumber(toBigInt(value));
57458
57731
  }
57459
57732
  function toBeHex(_value, _width) {
@@ -59875,7 +60148,7 @@ var init_abstract_coder = __esm({
59875
60148
  return toBigInt(this.readBytes(WordSize));
59876
60149
  }
59877
60150
  readIndex() {
59878
- return toNumber2(this.readBytes(WordSize));
60151
+ return toNumber3(this.readBytes(WordSize));
59879
60152
  }
59880
60153
  };
59881
60154
  }
@@ -86312,7 +86585,7 @@ __export(ethers_exports, {
86312
86585
  toBeArray: () => toBeArray,
86313
86586
  toBeHex: () => toBeHex,
86314
86587
  toBigInt: () => toBigInt,
86315
- toNumber: () => toNumber2,
86588
+ toNumber: () => toNumber3,
86316
86589
  toQuantity: () => toQuantity,
86317
86590
  toTwos: () => toTwos,
86318
86591
  toUtf8Bytes: () => toUtf8Bytes,
@@ -86530,7 +86803,7 @@ __export(lib_exports, {
86530
86803
  toBeArray: () => toBeArray,
86531
86804
  toBeHex: () => toBeHex,
86532
86805
  toBigInt: () => toBigInt,
86533
- toNumber: () => toNumber2,
86806
+ toNumber: () => toNumber3,
86534
86807
  toQuantity: () => toQuantity,
86535
86808
  toTwos: () => toTwos,
86536
86809
  toUtf8Bytes: () => toUtf8Bytes,
@@ -87442,7 +87715,7 @@ var init_hyperliquid_signer = __esm({
87442
87715
  });
87443
87716
 
87444
87717
  // lib/runtime/hyperliquid-client.ts
87445
- 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, coerceMarketMaxLeverage, 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;
87718
+ 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, coerceMarketMaxLeverage, toFiniteNumber, OPEN_ORDER_NUMERIC_STRING, OPEN_ORDER_ID_STRING, parseCanonicalOpenOrderId, parseOpenOrderFiniteNumber, parseOpenOrderPositiveNumber, parseOpenOrderPresentationNumber, readOpenOrderField, firstFiniteNumber, parseFundingUsdcFromInfoPosition, isExchangeIsolatedOnly, resolveLeverageTarget, 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;
87446
87719
  var init_hyperliquid_client = __esm({
87447
87720
  "lib/runtime/hyperliquid-client.ts"() {
87448
87721
  "use strict";
@@ -87819,6 +88092,10 @@ var init_hyperliquid_client = __esm({
87819
88092
  return null;
87820
88093
  };
87821
88094
  isExchangeIsolatedOnly = (asset) => asset.only_isolated === true || ["nocross", "strictisolated"].includes(String(asset.margin_mode || "").trim().toLowerCase());
88095
+ resolveLeverageTarget = (asset, leverage, isCross) => ({
88096
+ leverage: Math.max(1, Math.min(asset.max_leverage, Math.trunc(leverage))),
88097
+ isCross: isExchangeIsolatedOnly(asset) ? false : isCross !== false
88098
+ });
87822
88099
  computeHip3AssetId = (perpDexIndex, indexInMeta) => HYPERLIQUID_EXCHANGE_SPECIFICATION.hip3_asset_id_base + Math.trunc(perpDexIndex) * HYPERLIQUID_EXCHANGE_SPECIFICATION.hip3_asset_id_dex_stride + Math.trunc(indexInMeta);
87823
88100
  getPerpDexIndexMap = (payload) => {
87824
88101
  if (!Array.isArray(payload)) {
@@ -87972,6 +88249,12 @@ var init_hyperliquid_client = __esm({
87972
88249
  if (!symbol2) {
87973
88250
  throw new Error("Missing Hyperliquid symbol.");
87974
88251
  }
88252
+ if (input.refreshCatalog) {
88253
+ return normalizeExecutionAssetMetadata(symbol2, await getExecutionAssetMetadata("hyperliquid", symbol2, {
88254
+ forceCatalogRefresh: true,
88255
+ ...input.publicRequestPriority === "trading_reduce" ? { publicRequestPriority: "trading_reduce" } : {}
88256
+ }));
88257
+ }
87975
88258
  if (Array.isArray(input.assets) && input.assets.length > 0) {
87976
88259
  const explicitAsset = findResolvedAsset(symbol2, input.assets);
87977
88260
  if (explicitAsset) {
@@ -88099,20 +88382,14 @@ var init_hyperliquid_client = __esm({
88099
88382
  if (!symbol2) {
88100
88383
  throw new Error("Missing Hyperliquid symbol.");
88101
88384
  }
88102
- const deviceReadsPrivateContext = Boolean(
88103
- input.includePrivateContext && String(input.walletAddress ?? "").trim()
88104
- );
88105
- const devicePrivateContext = deviceReadsPrivateContext ? readDevicePrivateExecutionContext({
88385
+ const devicePrivateContext = input.includePrivateContext ? readDevicePrivateExecutionContext({
88106
88386
  ...input,
88107
- walletAddress: String(input.walletAddress),
88387
+ // Refused before any request when the wallet is missing.
88388
+ walletAddress: requireWalletAddress(String(input.walletAddress ?? "")),
88108
88389
  symbol: symbol2
88109
88390
  }) : null;
88110
88391
  devicePrivateContext?.catch(() => void 0);
88111
- const metadata = input.includePrivateContext && !deviceReadsPrivateContext ? await getExecutionAssetMetadata("hyperliquid", symbol2, {
88112
- includePrivateContext: true,
88113
- ...input.publicRequestPriority === "trading_reduce" ? { publicRequestPriority: "trading_reduce" } : {},
88114
- profileId: Number.isFinite(Number(input.profileId)) ? Number(input.profileId) : void 0
88115
- }) : input.publicRequestPriority === "trading_reduce" ? await getExecutionAssetMetadata("hyperliquid", symbol2, { publicRequestPriority: "trading_reduce" }) : await getExecutionAssetMetadata("hyperliquid", symbol2);
88392
+ const metadata = input.publicRequestPriority === "trading_reduce" ? await getExecutionAssetMetadata("hyperliquid", symbol2, { publicRequestPriority: "trading_reduce" }) : await getExecutionAssetMetadata("hyperliquid", symbol2);
88116
88393
  const deviceContext = devicePrivateContext ? await devicePrivateContext : null;
88117
88394
  const executionContextReceivedAtMonotonicMs = globalThis.performance.now();
88118
88395
  const resolved = normalizeExecutionAssetMetadata(symbol2, metadata);
@@ -88152,11 +88429,6 @@ var init_hyperliquid_client = __esm({
88152
88429
  executionPositionSize: deviceContext.executionPositionSize,
88153
88430
  executionContextAtMs: deviceContext.executionContextAtMs,
88154
88431
  executionContextReceivedAtMonotonicMs
88155
- } : input.includePrivateContext ? {
88156
- executionMarkPrice: Number.isFinite(Number(metadata.execution_mark_price)) && Number(metadata.execution_mark_price) > 0 ? Number(metadata.execution_mark_price) : null,
88157
- executionPositionSize: Number.isFinite(Number(metadata.execution_position_size)) ? Number(metadata.execution_position_size) : null,
88158
- executionContextAtMs: Number.isFinite(Number(metadata.execution_context_at_ms)) && Number(metadata.execution_context_at_ms) > 0 ? Number(metadata.execution_context_at_ms) : null,
88159
- executionContextReceivedAtMonotonicMs
88160
88432
  } : {}
88161
88433
  };
88162
88434
  };
@@ -88731,8 +89003,7 @@ var init_hyperliquid_client = __esm({
88731
89003
  const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
88732
89004
  const nonce = input.nonce ?? await allocateActionNonce(input, apiUrl);
88733
89005
  const expiresAfter = input.expiresAfterSeconds == null ? null : nonce + input.expiresAfterSeconds * MS_PER_SECOND;
88734
- const leverage = Math.max(1, Math.min(asset.max_leverage, Math.trunc(input.leverage)));
88735
- const isCross = isExchangeIsolatedOnly(asset) ? false : input.isCross !== false;
89006
+ const { leverage, isCross } = resolveLeverageTarget(asset, input.leverage, input.isCross);
88736
89007
  const action = {
88737
89008
  type: "updateLeverage",
88738
89009
  asset: asset.asset_index,
@@ -90000,9 +90271,6 @@ async function pollCopyTradingRuntimeSource(profileId, options) {
90000
90271
  ...schedulerInstanceId ? { "x-client-runtime-instance": schedulerInstanceId } : {}
90001
90272
  }, profileId),
90002
90273
  body: JSON.stringify({
90003
- dry_run: Boolean(options?.dryRun),
90004
- force_refresh: Boolean(options?.forceRefresh),
90005
- ...options?.maxEvents ? { max_events: options.maxEvents } : {},
90006
90274
  ...options?.accountEvidence ? { account_evidence: options.accountEvidence } : {}
90007
90275
  }),
90008
90276
  credentials: "include",
@@ -93617,6 +93885,7 @@ var init_browser_trading = __esm({
93617
93885
  estimatedPrice: input.estimatedPrice,
93618
93886
  slippage: input.slippage,
93619
93887
  reduceOnly: true,
93888
+ assets: input.assets,
93620
93889
  onExchangeOrderDispatched: input.onExchangeOrderDispatched
93621
93890
  });
93622
93891
  };
@@ -93651,15 +93920,15 @@ var init_hyperliquid_active_asset_contract = __esm({
93651
93920
  };
93652
93921
  normalizePair = (raw) => {
93653
93922
  if (Array.isArray(raw) && raw.length >= HYPERLIQUID_SIDE_PAIR_LENGTH) {
93654
- return [toNumber(raw[0], 0), toNumber(raw[1], 0)];
93923
+ return [toNumber2(raw[0], 0), toNumber2(raw[1], 0)];
93655
93924
  }
93656
93925
  if (raw && typeof raw === "object") {
93657
- const buy = toNumber(raw.buy ?? raw.long ?? raw.b, 0);
93658
- const sell = toNumber(raw.sell ?? raw.short ?? raw.s, 0);
93926
+ const buy = toNumber2(raw.buy ?? raw.long ?? raw.b, 0);
93927
+ const sell = toNumber2(raw.sell ?? raw.short ?? raw.s, 0);
93659
93928
  return [buy, sell];
93660
93929
  }
93661
93930
  if (typeof raw === "string" || typeof raw === "number") {
93662
- const value = toNumber(raw, 0);
93931
+ const value = toNumber2(raw, 0);
93663
93932
  return [value, value];
93664
93933
  }
93665
93934
  return [0, 0];
@@ -93670,28 +93939,28 @@ var init_hyperliquid_active_asset_contract = __esm({
93670
93939
  const directSell = source.available_to_trade_sell;
93671
93940
  const hasDirectAvailable = directBuy !== void 0 || directSell !== void 0;
93672
93941
  const [pairBuy, pairSell] = normalizePair(source.availableToTrade);
93673
- const available_to_trade_buy = hasDirectAvailable ? toNumber(directBuy, pairBuy) : pairBuy;
93674
- const available_to_trade_sell = hasDirectAvailable ? toNumber(directSell, pairSell) : pairSell;
93942
+ const available_to_trade_buy = hasDirectAvailable ? toNumber2(directBuy, pairBuy) : pairBuy;
93943
+ const available_to_trade_sell = hasDirectAvailable ? toNumber2(directSell, pairSell) : pairSell;
93675
93944
  const directMaxBuy = source.max_trade_size_buy;
93676
93945
  const directMaxSell = source.max_trade_size_sell;
93677
93946
  const hasDirectMax = directMaxBuy !== void 0 || directMaxSell !== void 0;
93678
93947
  const [pairMaxBuy, pairMaxSell] = normalizePair(source.maxTradeSzs);
93679
- const max_trade_size_buy = hasDirectMax ? toNumber(directMaxBuy, pairMaxBuy) : pairMaxBuy;
93680
- const max_trade_size_sell = hasDirectMax ? toNumber(directMaxSell, pairMaxSell) : pairMaxSell;
93948
+ const max_trade_size_buy = hasDirectMax ? toNumber2(directMaxBuy, pairMaxBuy) : pairMaxBuy;
93949
+ const max_trade_size_sell = hasDirectMax ? toNumber2(directMaxSell, pairMaxSell) : pairMaxSell;
93681
93950
  return {
93682
93951
  symbol: String(source.coin || symbol2),
93683
93952
  available_to_trade_buy,
93684
93953
  available_to_trade_sell,
93685
93954
  max_trade_size_buy,
93686
93955
  max_trade_size_sell,
93687
- mark_price: toNumber(source.markPx ?? source.mark_price, 0)
93956
+ mark_price: toNumber2(source.markPx ?? source.mark_price, 0)
93688
93957
  };
93689
93958
  };
93690
93959
  }
93691
93960
  });
93692
93961
 
93693
93962
  // lib/runtime/server-prompt-rescue-account-contract.ts
93694
- var toNumber3, firstNumber2, firstTruthy, spotContainers, extractCanonicalSpotMetrics, sumBalanceValueUsd, approximatelyEqual, balancesMirrorUnifiedAccountValue, computeEffectiveAccountValue, equityFormula, buildServerPromptRescueAccountSummary;
93963
+ var firstNumber2, equityFormula, buildServerPromptRescueAccountSummary;
93695
93964
  var init_server_prompt_rescue_account_contract = __esm({
93696
93965
  "lib/runtime/server-prompt-rescue-account-contract.ts"() {
93697
93966
  "use strict";
@@ -93700,10 +93969,7 @@ var init_server_prompt_rescue_account_contract = __esm({
93700
93969
  init_define_VTX_PI_MODEL_POLICY();
93701
93970
  init_hyperliquid_account_mode_contract();
93702
93971
  init_hyperliquid_account_contract();
93703
- toNumber3 = (value, fallback = 0) => {
93704
- const numeric2 = Number(value);
93705
- return Number.isFinite(numeric2) ? numeric2 : fallback;
93706
- };
93972
+ init_server_loop_account_value();
93707
93973
  firstNumber2 = (values, fallback = 0) => {
93708
93974
  for (const value of values) {
93709
93975
  if (value == null || value === "") continue;
@@ -93712,119 +93978,6 @@ var init_server_prompt_rescue_account_contract = __esm({
93712
93978
  }
93713
93979
  return fallback;
93714
93980
  };
93715
- firstTruthy = (values, fallback) => {
93716
- for (const value of values) {
93717
- if (value) return value;
93718
- }
93719
- return fallback;
93720
- };
93721
- spotContainers = (spotResponse) => {
93722
- if (!spotResponse || typeof spotResponse !== "object" || Array.isArray(spotResponse)) return [];
93723
- const response = spotResponse;
93724
- const containers = [response];
93725
- for (const key of ["spotState", "userState", "clearinghouseState", "state", "data"]) {
93726
- const child = response[key];
93727
- if (child && typeof child === "object" && !Array.isArray(child)) containers.push(child);
93728
- }
93729
- return containers;
93730
- };
93731
- extractCanonicalSpotMetrics = (spotResponse) => {
93732
- const response = spotResponse && typeof spotResponse === "object" && !Array.isArray(spotResponse) ? spotResponse : {};
93733
- const containers = spotContainers(response);
93734
- let accountValue = 0;
93735
- let totalMarginUsed = 0;
93736
- let withdrawable = 0;
93737
- for (const container of containers) {
93738
- const marginSummary = container.marginSummary && typeof container.marginSummary === "object" && !Array.isArray(container.marginSummary) ? container.marginSummary : {};
93739
- accountValue = Math.max(accountValue, toNumber3(marginSummary.accountValue));
93740
- totalMarginUsed = Math.max(totalMarginUsed, toNumber3(marginSummary.totalMarginUsed));
93741
- withdrawable = Math.max(withdrawable, toNumber3(container.withdrawable));
93742
- }
93743
- if (accountValue <= 0) {
93744
- for (const key of ["accountValue", "totalValue", "equity", "totalRawUsd", "usdValue", "usdcValue"]) {
93745
- accountValue = Math.max(accountValue, toNumber3(response[key]));
93746
- }
93747
- }
93748
- const balances = [];
93749
- const listKeys = ["balances", "tokenBalances", "spotBalances", "assets"];
93750
- for (const container of containers) {
93751
- for (const listKey of listKeys) {
93752
- const bucket = container[listKey];
93753
- if (!Array.isArray(bucket)) continue;
93754
- let stableTotal = 0;
93755
- let anyTotal = 0;
93756
- for (const rawEntry of bucket) {
93757
- if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) continue;
93758
- const entry = rawEntry;
93759
- const coin = String(firstTruthy([
93760
- entry.coin,
93761
- entry.token,
93762
- entry.asset,
93763
- entry.symbol
93764
- ], "")).trim().toUpperCase();
93765
- if (!coin) continue;
93766
- const total = toNumber3(firstTruthy([entry.total, entry.balance, entry.amount], "0"));
93767
- const hold = toNumber3(firstTruthy([entry.hold, entry.locked], "0"));
93768
- const available = Math.max(
93769
- 0,
93770
- toNumber3(firstTruthy([entry.available, entry.free, total - hold], "0"))
93771
- );
93772
- let valueUsd = toNumber3(firstTruthy([entry.usdValue, entry.usdcValue], "0"));
93773
- if (valueUsd <= 0 && STABLE_SPOT_SYMBOLS.has(coin)) {
93774
- valueUsd = available > 0 ? available : total;
93775
- }
93776
- balances.push({ coin, total, hold, available, value_usd: valueUsd });
93777
- const entryValue = valueUsd > 0 ? valueUsd : total;
93778
- if (entryValue > 0) {
93779
- anyTotal += entryValue;
93780
- if (STABLE_SPOT_SYMBOLS.has(coin)) stableTotal += entryValue;
93781
- }
93782
- }
93783
- if (accountValue <= 0) {
93784
- if (stableTotal > 0) accountValue = stableTotal;
93785
- else if (anyTotal > 0) accountValue = anyTotal;
93786
- }
93787
- }
93788
- if (balances.length > 0) break;
93789
- }
93790
- return { accountValue, totalMarginUsed, withdrawable, balances };
93791
- };
93792
- sumBalanceValueUsd = (balances) => balances.reduce((total, balance) => {
93793
- let valueUsd = toNumber3(balance.value_usd);
93794
- if (valueUsd <= 0 && STABLE_SPOT_SYMBOLS.has(String(balance.coin || "").trim().toUpperCase())) {
93795
- valueUsd = toNumber3(balance.total);
93796
- }
93797
- return total + Math.max(valueUsd, 0);
93798
- }, 0);
93799
- approximatelyEqual = (left, right, absoluteToleranceUsd, relativeTolerance) => {
93800
- const reference = Math.max(Math.abs(left), Math.abs(right), 1);
93801
- return Math.abs(left - right) <= Math.max(absoluteToleranceUsd, reference * relativeTolerance);
93802
- };
93803
- balancesMirrorUnifiedAccountValue = (input) => input.perpsEquity > 0 && input.spotEquity > 0 && input.balancesEquity > 0 && approximatelyEqual(
93804
- input.perpsEquity,
93805
- input.spotEquity,
93806
- input.absoluteToleranceUsd,
93807
- input.relativeTolerance
93808
- ) && approximatelyEqual(
93809
- input.spotEquity,
93810
- input.balancesEquity,
93811
- input.absoluteToleranceUsd,
93812
- input.relativeTolerance
93813
- );
93814
- computeEffectiveAccountValue = (input) => {
93815
- if (!input.unifiedLike) return input.perpsEquity;
93816
- if (input.balancesEquity > 0) {
93817
- if (input.mirrored) {
93818
- return Math.max(input.perpsEquity, input.spotEquity, input.balancesEquity);
93819
- }
93820
- return Math.max(
93821
- input.perpsEquity + input.balancesEquity,
93822
- input.spotEquity,
93823
- input.balancesEquity
93824
- );
93825
- }
93826
- return Math.max(input.perpsEquity, input.spotEquity);
93827
- };
93828
93981
  equityFormula = (input) => {
93829
93982
  if (!input.unifiedLike) return "perps_account_value";
93830
93983
  if (input.balancesEquity > 0) {
@@ -93839,11 +93992,11 @@ var init_server_prompt_rescue_account_contract = __esm({
93839
93992
  const perps = perpsResponse && typeof perpsResponse === "object" && !Array.isArray(perpsResponse) ? perpsResponse : {};
93840
93993
  const marginSummary = perps.marginSummary && typeof perps.marginSummary === "object" && !Array.isArray(perps.marginSummary) ? perps.marginSummary : {};
93841
93994
  const crossMarginSummary = perps.crossMarginSummary && typeof perps.crossMarginSummary === "object" && !Array.isArray(perps.crossMarginSummary) ? perps.crossMarginSummary : {};
93842
- const rawPerpsAccountValue = toNumber3(marginSummary.accountValue);
93995
+ const rawPerpsAccountValue = toNumber(marginSummary.accountValue);
93843
93996
  const perpsAccountValue = Math.max(0, rawPerpsAccountValue);
93844
- const crossMarginAccountValue = toNumber3(crossMarginSummary.accountValue);
93845
- let totalMarginUsed = toNumber3(marginSummary.totalMarginUsed);
93846
- let withdrawable = toNumber3(perps.withdrawable);
93997
+ const crossMarginAccountValue = toNumber(crossMarginSummary.accountValue);
93998
+ let totalMarginUsed = toNumber(marginSummary.totalMarginUsed);
93999
+ let withdrawable = toNumber(perps.withdrawable);
93847
94000
  const spot = accountMode === "disabled" ? { accountValue: 0, totalMarginUsed: 0, withdrawable: 0, balances: [] } : extractCanonicalSpotMetrics(spotResponse);
93848
94001
  const balances = spot.balances;
93849
94002
  const balancesEquity = sumBalanceValueUsd(balances);
@@ -93875,7 +94028,7 @@ var init_server_prompt_rescue_account_contract = __esm({
93875
94028
  mirrored
93876
94029
  };
93877
94030
  const accountValue = computeEffectiveAccountValue(formulaInput);
93878
- const maintenanceMargin = toNumber3(perps.crossMaintenanceMarginUsed);
94031
+ const maintenanceMargin = toNumber(perps.crossMaintenanceMarginUsed);
93879
94032
  const availableMargin = canonicalAvailableMargin(accountValue, totalMarginUsed);
93880
94033
  let totalNotional = 0;
93881
94034
  let totalUnrealizedPnl = 0;
@@ -93883,10 +94036,10 @@ var init_server_prompt_rescue_account_contract = __esm({
93883
94036
  for (const entry of positions) {
93884
94037
  const position = entry && typeof entry === "object" && !Array.isArray(entry) ? entry.position : null;
93885
94038
  if (!position || typeof position !== "object" || Array.isArray(position)) continue;
93886
- const size = toNumber3(position.szi);
93887
- const unrealizedPnl = toNumber3(position.unrealizedPnl);
94039
+ const size = toNumber(position.szi);
94040
+ const unrealizedPnl = toNumber(position.unrealizedPnl);
93888
94041
  totalUnrealizedPnl += unrealizedPnl;
93889
- totalNotional += Math.abs(size * toNumber3(position.entryPx) + unrealizedPnl);
94042
+ totalNotional += Math.abs(size * toNumber(position.entryPx) + unrealizedPnl);
93890
94043
  }
93891
94044
  return {
93892
94045
  account_value: accountValue,
@@ -94033,7 +94186,7 @@ var init_hyperliquid_account_state_adapter = __esm({
94033
94186
  buildUserFillsStorageKey = (cacheKey) => {
94034
94187
  return `${USER_FILLS_CACHE_STORAGE_PREFIX}${cacheKey}`;
94035
94188
  };
94036
- buildAccountStateCacheKey = (apiUrl, walletAddress, symbol2, aggregatePerpDexs, scopeAccountSummaryToSelectedDex, dexNames, includeEffectiveTakerRate, includeExactAccountMode, includeActiveAssetData, feeSymbols) => {
94189
+ buildAccountStateCacheKey = (apiUrl, walletAddress, symbol2, aggregatePerpDexs, scopeAccountSummaryToSelectedDex, dexNames, includeEffectiveTakerRate, includeExactAccountMode, includeActiveAssetData, feeSymbols, serverLoopAccountValue2) => {
94037
94190
  return [
94038
94191
  apiUrl.replace(/\/$/, "").toLowerCase(),
94039
94192
  walletAddress.trim().toLowerCase(),
@@ -94043,6 +94196,8 @@ var init_hyperliquid_account_state_adapter = __esm({
94043
94196
  includeEffectiveTakerRate ? "with-effective-taker-rate" : "without-effective-taker-rate",
94044
94197
  includeExactAccountMode ? "with-exact-account-mode" : "without-exact-account-mode",
94045
94198
  includeActiveAssetData ? "with-active-asset" : "without-active-asset",
94199
+ // A device read's key is unchanged; a Server-loop valuation never shares it.
94200
+ ...serverLoopAccountValue2 ? ["server-loop-account-value"] : [],
94046
94201
  ...dexNames.map(normalizePerpDexName).sort(),
94047
94202
  "fee-symbols",
94048
94203
  ...feeSymbols
@@ -94633,7 +94788,8 @@ var init_hyperliquid_account_state_adapter = __esm({
94633
94788
  includeEffectiveTakerRate,
94634
94789
  includeExactAccountMode,
94635
94790
  includeActiveAssetData,
94636
- [...new Set((input.feeSymbols ?? [symbol2]).map(normalizeHyperliquidMarketSymbol).filter(Boolean))].sort()
94791
+ [...new Set((input.feeSymbols ?? [symbol2]).map(normalizeHyperliquidMarketSymbol).filter(Boolean))].sort(),
94792
+ input.serverLoopAccountValue === true
94637
94793
  );
94638
94794
  const now = Date.now();
94639
94795
  const cached2 = readBrowserAccountStateCache(cacheKey);
@@ -94701,17 +94857,19 @@ var init_hyperliquid_account_state_adapter = __esm({
94701
94857
  staleIf429MaxAgeMs
94702
94858
  }) => {
94703
94859
  const metadataBodies = input.includeEffectiveTakerRate === true ? ["", ...dexNames].map((dex) => ({ type: "meta", ...dex ? { dex } : {} })) : [];
94860
+ const accountModeCache = input.publicRequestPriority === "ui" ? "display" : true;
94704
94861
  const reservation = await reserveHyperliquidPublicReads(apiUrl, [
94705
94862
  { type: "clearinghouseState", user: walletAddress },
94706
94863
  ...dexNames.map((dex) => ({ type: "clearinghouseState", user: walletAddress, dex })),
94707
94864
  { type: "spotClearinghouseState", user: walletAddress },
94708
94865
  ...input.includeActiveAssetData === false ? [] : [{ type: "activeAssetData", user: walletAddress, coin: symbol2 }],
94709
94866
  ...input.includeEffectiveTakerRate === true ? [{ type: "userFees", user: walletAddress }, ...metadataBodies] : [],
94710
- ...input.includeExactAccountMode === true ? [
94867
+ // A Server-loop valuation may need the mode too; a reservation claims no weight.
94868
+ ...input.includeExactAccountMode === true || input.serverLoopAccountValue === true ? [
94711
94869
  { type: "userAbstraction", user: walletAddress },
94712
94870
  { type: "userDexAbstraction", user: walletAddress }
94713
94871
  ] : []
94714
- ], input.signal, { cacheAccountMode: true, cacheValidUntilMs: input.publicReadDeadlineMs });
94872
+ ], input.signal, { cacheAccountMode: accountModeCache, cacheValidUntilMs: input.publicReadDeadlineMs });
94715
94873
  const priorityScope = input.priorityScope ?? createHyperliquidPublicPriorityScope(input.publicRequestPriority);
94716
94874
  reservation.priorityScope = priorityScope;
94717
94875
  if (input.onPublicReadPendingChange) {
@@ -94741,8 +94899,8 @@ var init_hyperliquid_account_state_adapter = __esm({
94741
94899
  return { payload: null, fetchedAtMs: Date.now() };
94742
94900
  }).then((result) => ({ payload: result.payload, capturedAt: new Date(result.fetchedAtMs).toISOString() }))
94743
94901
  }))() : Promise.resolve(null);
94744
- const exactAccountModePromise = input.includeExactAccountMode === true ? (async () => {
94745
- const abstractionRead = await readHyperliquidPublicInfo(apiUrl, { type: "userAbstraction", user: walletAddress }, { signal: input.signal, reservation, cacheAccountMode: true, priorityScope });
94902
+ const readExactAccountMode = async () => {
94903
+ const abstractionRead = await readHyperliquidPublicInfo(apiUrl, { type: "userAbstraction", user: walletAddress }, { signal: input.signal, reservation, cacheAccountMode: accountModeCache, priorityScope });
94746
94904
  const userAbstraction = abstractionRead.payload;
94747
94905
  let capturedAtMs = abstractionRead.fetchedAtMs;
94748
94906
  const preliminaryMode = extractCanonicalHyperliquidAccountMode(userAbstraction);
@@ -94751,7 +94909,7 @@ var init_hyperliquid_account_state_adapter = __esm({
94751
94909
  }
94752
94910
  let userDexAbstraction;
94753
94911
  if (preliminaryMode === "default" || preliminaryMode === "disabled") {
94754
- const dexRead = await readHyperliquidPublicInfo(apiUrl, { type: "userDexAbstraction", user: walletAddress }, { signal: input.signal, reservation, cacheAccountMode: true, priorityScope });
94912
+ const dexRead = await readHyperliquidPublicInfo(apiUrl, { type: "userDexAbstraction", user: walletAddress }, { signal: input.signal, reservation, cacheAccountMode: accountModeCache, priorityScope });
94755
94913
  userDexAbstraction = dexRead.payload;
94756
94914
  capturedAtMs = Math.min(capturedAtMs, dexRead.fetchedAtMs);
94757
94915
  }
@@ -94762,7 +94920,8 @@ var init_hyperliquid_account_state_adapter = __esm({
94762
94920
  ),
94763
94921
  capturedAt: new Date(capturedAtMs).toISOString()
94764
94922
  };
94765
- })() : Promise.resolve(null);
94923
+ };
94924
+ const exactAccountModePromise = input.includeExactAccountMode === true ? readExactAccountMode() : Promise.resolve(null);
94766
94925
  await awaitAccountReads([userFeesPromise, exactAccountModePromise]);
94767
94926
  const metadataByDex = /* @__PURE__ */ new Map();
94768
94927
  if (input.includeEffectiveTakerRate === true) {
@@ -94871,12 +95030,31 @@ var init_hyperliquid_account_state_adapter = __esm({
94871
95030
  }
94872
95031
  const accountStateConfig = input.config.client_runtime_hyperliquid_account_state;
94873
95032
  const summaryPerpsResponse = exactAccountMode ? { ...accountSummaryPerpsResponse, accountMode: exactAccountMode.accountMode } : accountSummaryPerpsResponse;
94874
- const accountSummaryOptions = {
95033
+ const deviceSummaryOptions = {
94875
95034
  spotDominatesMinTotalUsd: accountStateConfig?.spot_dominates_min_total_usd,
94876
95035
  spotDominatesPerpsMultiplier: accountStateConfig?.spot_dominates_perps_multiplier,
94877
95036
  mirroredAccountValueAbsoluteToleranceUsd: accountStateConfig?.mirrored_account_value_absolute_tolerance_usd,
94878
95037
  mirroredAccountValueRelativeTolerance: accountStateConfig?.mirrored_account_value_relative_tolerance
94879
95038
  };
95039
+ let serverLoopClassification = input.serverLoopAccountValue === true ? {
95040
+ spotAvailableToTradeRatioThreshold: accountStateConfig?.spot_available_to_trade_ratio_threshold,
95041
+ spotMeaningfulHoldUsd: accountStateConfig?.spot_meaningful_hold_usd,
95042
+ spotVeryStrongTotalUsd: accountStateConfig?.spot_very_strong_total_usd,
95043
+ spotVeryStrongPerpsEquityThresholdUsd: accountStateConfig?.spot_very_strong_perps_equity_threshold_usd,
95044
+ // The Python loop probes BTC's activeAssetData. This read's own probe
95045
+ // answers for the same collateral only on the default Perps DEX.
95046
+ availableToTrade: activeAssetResult?.payload != null && !selectedDex ? ((probe) => [probe.available_to_trade_buy, probe.available_to_trade_sell])(
95047
+ normalizeActiveAssetData(activeAssetResult.payload, symbol2)
95048
+ ) : null
95049
+ } : null;
95050
+ if (serverLoopClassification && !exactAccountMode && input.scopeAccountSummaryToSelectedDex !== true && serverLoopValuationCountsSpot(accountSummaryPerpsResponse, spotResponse, { ...deviceSummaryOptions, serverLoopClassification })) {
95051
+ const [serverLoopExactAccountMode] = await awaitAccountReads([readExactAccountMode()]);
95052
+ serverLoopClassification = { ...serverLoopClassification, exactAccountMode: serverLoopExactAccountMode.accountMode };
95053
+ }
95054
+ const accountSummaryOptions = {
95055
+ ...deviceSummaryOptions,
95056
+ ...serverLoopClassification ? { serverLoopClassification } : {}
95057
+ };
94880
95058
  const walletSummary = exactAccountMode && input.scopeAccountSummaryToSelectedDex !== true ? buildServerPromptRescueAccountSummary(
94881
95059
  perpsResponse,
94882
95060
  spotResponse,
@@ -95890,7 +96068,7 @@ var init_client_exchange_mutations = __esm({
95890
96068
  });
95891
96069
 
95892
96070
  // lib/runtime/execution-guard-contract.ts
95893
- var unitsFromPosition, signedUnitsFromPosition, signedUnitsFromEntryPosition, classifyExecutionIntent, reductionFirstOrder, resolveExecutionTarget, decisionOrderSizeAsset, flipExecutionLegs, executedOrderPositionEvent;
96071
+ var unitsFromPosition, signedUnitsFromPosition, signedUnitsFromEntryPosition, classifyExecutionIntent, reductionFirstOrder, usdAmount, orderMetadataRetryReason, orderCeilingRefusal, resolveExecutionTarget, decisionOrderSizeAsset, flipExecutionLegs, executedOrderPositionEvent;
95894
96072
  var init_execution_guard_contract = __esm({
95895
96073
  "lib/runtime/execution-guard-contract.ts"() {
95896
96074
  "use strict";
@@ -96090,6 +96268,28 @@ var init_execution_guard_contract = __esm({
96090
96268
  const reduces = plans.map((plan) => classifyExecutionIntent(plan.decision, plan.units, plan.signedUnits).reduceOnly);
96091
96269
  return plans.map((_, index) => index).sort((left, right) => Number(reduces[right]) - Number(reduces[left]));
96092
96270
  };
96271
+ usdAmount = (value) => `$${value.toLocaleString("en-US", {
96272
+ minimumFractionDigits: USD_DISPLAY_DECIMALS,
96273
+ maximumFractionDigits: USD_DISPLAY_DECIMALS
96274
+ })}`;
96275
+ orderMetadataRetryReason = (rejection) => {
96276
+ const message = String(rejection ?? "").toLowerCase();
96277
+ if (message.includes("invalid size")) return "invalid_size";
96278
+ if (message.includes("reference price") && message.includes("95% away")) return "reference_price";
96279
+ return null;
96280
+ };
96281
+ orderCeilingRefusal = (input) => {
96282
+ const orderNotional = input.size * input.price;
96283
+ if (orderNotional > input.maxOrderNotional) {
96284
+ return `Order notional ${usdAmount(orderNotional)} exceeds limit ${usdAmount(input.maxOrderNotional)}`;
96285
+ }
96286
+ const resultingSize = input.side === "buy" ? input.currentPositionSize + input.size : input.currentPositionSize - input.size;
96287
+ const resultingNotional = Math.abs(resultingSize) * input.price;
96288
+ if (resultingNotional > input.maxPositionNotional) {
96289
+ return `Resulting position notional ${usdAmount(resultingNotional)} exceeds limit ${usdAmount(input.maxPositionNotional)}`;
96290
+ }
96291
+ return null;
96292
+ };
96093
96293
  resolveExecutionTarget = (classified, liveSignedUnits, livePositionDirection) => {
96094
96294
  const liveUnits = Number.isFinite(liveSignedUnits) ? Math.trunc(liveSignedUnits) : 0;
96095
96295
  const exactLiveDirection = livePositionDirection == null ? liveUnits > 0 ? 1 : liveUnits < 0 ? -1 : 0 : livePositionDirection;
@@ -96639,6 +96839,27 @@ var init_protective_leg_evidence = __esm({
96639
96839
  }
96640
96840
  });
96641
96841
 
96842
+ // lib/runtime/protective-entry-cover.ts
96843
+ var protectiveEntryCover, protectiveEntryLegSize;
96844
+ var init_protective_entry_cover = __esm({
96845
+ "lib/runtime/protective-entry-cover.ts"() {
96846
+ "use strict";
96847
+ init_define_VTX_EXO_POLICY();
96848
+ init_define_VTX_GROK_POLICY();
96849
+ init_define_VTX_PI_MODEL_POLICY();
96850
+ protectiveEntryCover = (input) => {
96851
+ const cover = { sl: 0, tp: 0 };
96852
+ for (const leg of input.storedLegs) {
96853
+ if (leg.isLong !== input.entryIsLong) continue;
96854
+ const rests = leg.orderId == null ? leg.canStillExist : input.liveOrderIds.has(String(leg.orderId));
96855
+ if (rests) cover[leg.kind] += leg.size;
96856
+ }
96857
+ return cover;
96858
+ };
96859
+ protectiveEntryLegSize = (input) => Math.min(input.filledSize, Math.max(0, input.liveExposure - input.cover));
96860
+ }
96861
+ });
96862
+
96642
96863
  // lib/runtime/runtime-execution.ts
96643
96864
  function capCopiedToActual(copied, actual) {
96644
96865
  if (Math.abs(copied) <= COPY_TRADING_SIZE_EPSILON) return 0;
@@ -96674,7 +96895,7 @@ function copiedTargetNow(reconciliation, recordedTarget, actualPosition) {
96674
96895
  );
96675
96896
  return { copiedNow, targetNow, kept: copiedTargetBesideOwnPosition(targetNow, copiedNow, actualPosition) };
96676
96897
  }
96677
- var clientProtectiveMutationAuthority, executionReadPriority, serverEntryLeverageAlreadyHeld, fetchClientRuntimeOpenOrders, _extractOrderResponseStates, createRuntimeId, _extractFilledSize, _extractOrderId, _toExecutionMetadata, _extractClientMutationId, _stableMutationIdentity, trailingStopMemory, protectiveGroupMemory, protectiveGroupReadFailures, windowHandoffCleanupAttempts, clientRuntimeProtectionStorage, resolveClientRuntimeProtectionStorage, setClientRuntimeProtectionStorage, trailingStopStorageKey, readTrackedTrailingStops, writeTrackedTrailingStops, rememberTrailingStop, protectiveGroupStorageKey, LOST_LEG_EVIDENCE_MAX_AGE_MS, EPISODE_END_FILL_LOOKBACK_MS, 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, executedProtectiveReport, 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, decisionLegOf, withExecutionAuditId, executeClientRuntimeDecision, waitForFlipCloseFreshness, maintainClientRuntimeTrailingStops, listPendingClientProtectiveSymbols, listStoredClientProtectiveSymbols, hasUnresolvedClientProtectiveIdentity, resolveClientProtectiveIdentitiesForAdoption, exportClientProtectiveGroupsForAdoption, adoptionGroupKey, applyClientProtectiveAdoptionOutcomes, hasStoredClientProtectiveGroupsForWallet, hasPendingClientProtectiveGroups, recoverManualClientProtectiveGroups, clientRuntimeDecisionSizesOrders, COMMITTED_EXECUTION_REPORTS, getCommittedExecutionReports, withCommittedExecutionReports, executeClientRuntimeDecisionUnlocked, executeClientCopyTradingIntent, _copyCancelOrderId, executeClientCopyTradingOrderAction;
96898
+ var clientProtectiveMutationAuthority, executionReadPriority, serverEntryLeverageAlreadyHeld, fetchClientRuntimeOpenOrders, _extractOrderResponseStates, createRuntimeId, _extractFilledSize, _extractOrderId, _toExecutionMetadata, _extractClientMutationId, _stableMutationIdentity, trailingStopMemory, protectiveGroupMemory, protectiveGroupReadFailures, windowHandoffCleanupAttempts, clientRuntimeProtectionStorage, resolveClientRuntimeProtectionStorage, setClientRuntimeProtectionStorage, trailingStopStorageKey, readTrackedTrailingStops, writeTrackedTrailingStops, rememberTrailingStop, protectiveGroupStorageKey, LOST_LEG_EVIDENCE_MAX_AGE_MS, EPISODE_END_FILL_LOOKBACK_MS, 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, executedProtectiveReport, isExactClientPositionTpslPair, deviceOwnsClientProtectiveLegKind, isAdoptionNarrowedPositionTpslLeg, hasAmbiguousClientPositionTpslAuthority, protectiveStableShapeMatches, observedProtectiveGroupingMatches, protectiveLiveShapeMatches, protectiveTerminalShapeMatches, cancelClientProtectiveLeg, buildPendingProtectivePlan, persistPendingClientProtectiveGroup, attachmentMemberNeverLanded, storedClientProtectiveCover, attachClientProtectivePlan, resolveJournaledAttachmentContinuity, protectiveMemberRested, ledgerOrderIdsByClientOrderId, journaledAttachmentNeverLanded, recoverJournaledClientProtectiveAttachments, readClientOrderMutation, readPendingEntryMutation, clientOrderNeverLandsAfterMs, requireClientRuntimeConfigSeconds, replacePendingEntryRecovery, recoverPendingClientProtectiveGroups, recoverPendingProtectiveReplacements, liveProtectiveOrderShape, observedStandaloneProtectiveGroup, migrateTrackedTrailingStopsToStandalone, reconcileClientProtectiveGroups, cancelAllClientProtectiveGroups, tightenClientTrailingStops, throwIfAborted2, sleep2, isDefinitiveEntryRejection, resolveExchangeSizeDecimals, roundAssetSize, resolvePositionSize, readServerOrderMarkPrice, serverOrderMetadataRetry, resolveCurrentPositionSize, buildPositionSnapshot, signedRemainingExposureAfterConfirmedReduction, runtimeProtectionAuthority, runtimeProtectionOwners, resolveRuntimeProtectionOwner, drainServerProtectionForRuntime, drainServerProtectionIfOwned, verifyNoLiveClientProtectiveTriggers, clientExecutionMutations, CLIENT_EXECUTION_QUEUE_TIMEOUT_MESSAGE, withClientExecutionMutation, withClientProtectivePlanSetMutation, allocateServerExecutionCapacity, withClientProtectiveAdoptionMutation, executeClientRuntimeDecisionLocked, unsentDecisionOrderReport, withCapacityTrim, SERVER_AUDIT_RECORDED_ELSEWHERE, serverExecutionAuditOutcome, decisionLegOf, withExecutionAuditId, executeClientRuntimeDecision, waitForFlipCloseFreshness, maintainClientRuntimeTrailingStops, listPendingClientProtectiveSymbols, listStoredClientProtectiveSymbols, hasUnresolvedClientProtectiveIdentity, resolveClientProtectiveIdentitiesForAdoption, exportClientProtectiveGroupsForAdoption, adoptionGroupKey, applyClientProtectiveAdoptionOutcomes, hasStoredClientProtectiveGroupsForWallet, hasPendingClientProtectiveGroups, recoverManualClientProtectiveGroups, clientRuntimeDecisionSizesOrders, COMMITTED_EXECUTION_REPORTS, COMMITTED_DECISION_ORDER, getCommittedExecutionReports, getCommittedDecisionOrder, withCommittedExecutionReports, executeClientRuntimeDecisionUnlocked, executeClientCopyTradingIntent, _copyCancelOrderId, executeClientCopyTradingOrderAction;
96678
96899
  var init_runtime_execution = __esm({
96679
96900
  "lib/runtime/runtime-execution.ts"() {
96680
96901
  "use strict";
@@ -96701,6 +96922,7 @@ var init_runtime_execution = __esm({
96701
96922
  init_runtime_redaction();
96702
96923
  init_protective_leg_evidence();
96703
96924
  init_protective_stop_replacement();
96925
+ init_protective_entry_cover();
96704
96926
  init_error_surface_contract();
96705
96927
  init_runtime_handoff();
96706
96928
  clientProtectiveMutationAuthority = (request) => request.mutationAuthority === "manual_session" ? {} : {
@@ -96725,7 +96947,13 @@ var init_runtime_execution = __esm({
96725
96947
  const wallet = String(context.walletAddress || "").trim();
96726
96948
  if (!symbol2 || !wallet || !Number.isInteger(context.leverage) || context.leverage <= 0 || !Number.isFinite(context.currentPositionSize) || context.currentPositionSize === 0) return false;
96727
96949
  let active;
96950
+ let target;
96728
96951
  try {
96952
+ target = resolveLeverageTarget(
96953
+ await resolveHyperliquidAsset({ symbol: symbol2, config: input.config ?? null, publicRequestPriority: "trading_reconcile" }),
96954
+ context.leverage,
96955
+ context.marginMode !== "isolated"
96956
+ );
96729
96957
  active = await fetchBrowserHyperliquidInfoPayload(
96730
96958
  { config: input.config ?? null, signal: input.signal, publicRequestPriority: "trading_reconcile" },
96731
96959
  { type: "activeAssetData", user: wallet, coin: symbol2 },
@@ -96736,7 +96964,7 @@ var init_runtime_execution = __esm({
96736
96964
  return false;
96737
96965
  }
96738
96966
  const leverage = active?.leverage;
96739
- return leverage?.value === context.leverage && leverage?.type === (context.marginMode === "isolated" ? "isolated" : "cross");
96967
+ return leverage?.value === target.leverage && leverage?.type === (target.isCross ? "cross" : "isolated");
96740
96968
  };
96741
96969
  fetchClientRuntimeOpenOrders = async (request, publicRequestPriority = "trading_reconcile") => {
96742
96970
  const normalizedSymbol = normalizeHyperliquidMarketSymbol(
@@ -97176,7 +97404,9 @@ var init_runtime_execution = __esm({
97176
97404
  const phase = journal.phase == null ? "awaiting_member_outcome" : journal.phase;
97177
97405
  const filledSize = Number(journal.filledSize);
97178
97406
  const averagePrice = Number(journal.averagePrice);
97179
- if (phase !== "awaiting_member_outcome" && phase !== "cancel_survivors" && phase !== "cancel_stale_members" || !/^[1-9]\d*$/.test(journalEntryOrderId) || !Number.isFinite(filledSize) || filledSize <= 0 || !Number.isFinite(averagePrice) || averagePrice <= 0 || !Array.isArray(journal.members) || journal.members.length < 1 || journal.members.length > CLIENT_PROTECTIVE_TPSL_PAIR_LEGS) {
97407
+ const invalidJournalTime = (value) => value != null && (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0);
97408
+ const journalMutationId = journal.mutationId == null ? void 0 : String(journal.mutationId).trim().toLowerCase();
97409
+ if (phase !== "awaiting_member_outcome" && phase !== "cancel_survivors" && phase !== "cancel_stale_members" || journalMutationId !== void 0 && !/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/.test(journalMutationId) || invalidJournalTime(journal.createdAtMs) || invalidJournalTime(journal.unknownOidFirstSeenAtMs) || invalidJournalTime(journal.unknownOidObservedAtMs) || !/^[1-9]\d*$/.test(journalEntryOrderId) || !Number.isFinite(filledSize) || filledSize <= 0 || !Number.isFinite(averagePrice) || averagePrice <= 0 || !Array.isArray(journal.members) || journal.members.length < 1 || journal.members.length > CLIENT_PROTECTIVE_TPSL_PAIR_LEGS) {
97180
97410
  protectiveGroupReadFailures.add(key);
97181
97411
  return [];
97182
97412
  }
@@ -97186,7 +97416,7 @@ var init_runtime_execution = __esm({
97186
97416
  const clientOrderId = String(member.clientOrderId ?? "").trim().toLowerCase();
97187
97417
  const triggerPrice = Number(member.triggerPrice);
97188
97418
  const size = Number(member.size);
97189
- if (member.kind !== "sl" && member.kind !== "tp" || !/^0x[0-9a-f]{32}$/.test(clientOrderId) || !Number.isFinite(triggerPrice) || triggerPrice <= 0 || !Number.isFinite(size) || size <= 0 || typeof member.isTrailing !== "boolean" || typeof member.positionTpsl !== "boolean") {
97419
+ if (member.kind !== "sl" && member.kind !== "tp" || !/^0x[0-9a-f]{32}$/.test(clientOrderId) || !Number.isFinite(triggerPrice) || triggerPrice <= 0 || !Number.isFinite(size) || size <= 0 || typeof member.isTrailing !== "boolean" || typeof member.positionTpsl !== "boolean" || invalidJournalTime(member.neverLandedAtMs)) {
97190
97420
  return [];
97191
97421
  }
97192
97422
  return [{
@@ -97195,7 +97425,8 @@ var init_runtime_execution = __esm({
97195
97425
  triggerPrice,
97196
97426
  size,
97197
97427
  isTrailing: member.isTrailing,
97198
- positionTpsl: member.positionTpsl
97428
+ positionTpsl: member.positionTpsl,
97429
+ ...typeof member.neverLandedAtMs === "number" ? { neverLandedAtMs: member.neverLandedAtMs } : {}
97199
97430
  }];
97200
97431
  });
97201
97432
  if (members.length !== journal.members.length || pendingEntry == null || legs.length > 0 && (members.length !== legs.length || members.some((member, index) => {
@@ -97210,6 +97441,10 @@ var init_runtime_execution = __esm({
97210
97441
  entryOrderId: journalEntryOrderId,
97211
97442
  filledSize,
97212
97443
  averagePrice,
97444
+ ...journalMutationId !== void 0 ? { mutationId: journalMutationId } : {},
97445
+ ...typeof journal.createdAtMs === "number" ? { createdAtMs: journal.createdAtMs } : {},
97446
+ ...typeof journal.unknownOidFirstSeenAtMs === "number" ? { unknownOidFirstSeenAtMs: journal.unknownOidFirstSeenAtMs } : {},
97447
+ ...typeof journal.unknownOidObservedAtMs === "number" ? { unknownOidObservedAtMs: journal.unknownOidObservedAtMs } : {},
97213
97448
  members
97214
97449
  };
97215
97450
  }
@@ -97970,21 +98205,27 @@ var init_runtime_execution = __esm({
97970
98205
  );
97971
98206
  return { group, cleanup, persistedGroupSet: persistenceFailed ? null : nextGroups };
97972
98207
  };
97973
- storedClientProtectiveCover = async (request, legs) => {
97974
- const cover = { sl: 0, tp: 0 };
97975
- if (legs.length === 0) return cover;
97976
- const symbol2 = request.executionContext.symbol.trim().toUpperCase();
97977
- const orders = await fetchClientRuntimeOpenOrders(request, "trading_reduce");
97978
- if (!Array.isArray(orders)) {
97979
- throw new Error("Malformed live protective-order snapshot.");
97980
- }
97981
- const liveOrderIds = new Set(orders.filter((order) => String(order.coin).trim().toUpperCase() === symbol2).map((order) => String(order.oid)));
97982
- for (const leg of legs) {
97983
- if (typeof leg.orderId === "string" || liveOrderIds.has(String(leg.orderId))) {
97984
- cover[leg.kind] += leg.size;
98208
+ attachmentMemberNeverLanded = (group, leg) => group.attachmentJournal?.members.some((member) => member.clientOrderId === leg.orderId && member.neverLandedAtMs != null) === true;
98209
+ storedClientProtectiveCover = async (request, entryIsLong, groups) => {
98210
+ const storedLegs = groups.filter((group) => group.isLong === entryIsLong).flatMap((group) => group.legs.map((leg) => ({
98211
+ isLong: group.isLong,
98212
+ kind: leg.kind,
98213
+ size: leg.size,
98214
+ orderId: typeof leg.orderId === "number" ? leg.orderId : null,
98215
+ canStillExist: !attachmentMemberNeverLanded(group, leg)
98216
+ })));
98217
+ const liveOrderIds = /* @__PURE__ */ new Set();
98218
+ if (storedLegs.length > 0) {
98219
+ const symbol2 = request.executionContext.symbol.trim().toUpperCase();
98220
+ const orders = await fetchClientRuntimeOpenOrders(request, "trading_reduce");
98221
+ if (!Array.isArray(orders)) {
98222
+ throw new Error("Malformed live protective-order snapshot.");
98223
+ }
98224
+ for (const order of orders) {
98225
+ if (String(order.coin).trim().toUpperCase() === symbol2) liveOrderIds.add(String(order.oid));
97985
98226
  }
97986
98227
  }
97987
- return cover;
98228
+ return protectiveEntryCover({ entryIsLong, storedLegs, liveOrderIds });
97988
98229
  };
97989
98230
  attachClientProtectivePlan = async (request, group, fill) => {
97990
98231
  const reports = [];
@@ -98082,10 +98323,7 @@ var init_runtime_execution = __esm({
98082
98323
  const liveExposure = Math.abs(livePositionSize);
98083
98324
  let storedCover;
98084
98325
  try {
98085
- storedCover = await storedClientProtectiveCover(
98086
- request,
98087
- existingGroups.flatMap((existing) => existing.legs)
98088
- );
98326
+ storedCover = await storedClientProtectiveCover(request, isLong, existingGroups);
98089
98327
  } catch (error48) {
98090
98328
  if (request.signal?.aborted) throw error48;
98091
98329
  reports.push({
@@ -98101,9 +98339,12 @@ var init_runtime_execution = __esm({
98101
98339
  return reports;
98102
98340
  }
98103
98341
  const allocatedCandidates = planned.flatMap((candidate) => {
98104
- const allocated = storedCover[candidate.kind];
98105
98342
  const size = roundAssetSize(
98106
- Math.min(fill.filledSize, Math.max(0, liveExposure - allocated)),
98343
+ protectiveEntryLegSize({
98344
+ filledSize: fill.filledSize,
98345
+ liveExposure,
98346
+ cover: storedCover[candidate.kind]
98347
+ }),
98107
98348
  request.executionContext.sizeDecimals
98108
98349
  );
98109
98350
  if (!Number.isFinite(size) || size <= 0) {
@@ -98211,6 +98452,9 @@ var init_runtime_execution = __esm({
98211
98452
  entryOrderId: fill.orderId,
98212
98453
  filledSize: fill.filledSize,
98213
98454
  averagePrice: fill.averagePrice,
98455
+ // One signed mutation carries every member (its first member's).
98456
+ mutationId: candidates[0].mutationId,
98457
+ createdAtMs: Date.now(),
98214
98458
  members: candidates.map((candidate) => ({
98215
98459
  kind: candidate.kind,
98216
98460
  clientOrderId: candidate.clientOrderId,
@@ -98723,6 +98967,82 @@ var init_runtime_execution = __esm({
98723
98967
  const endedAt = evidence.statusTimestampMs;
98724
98968
  return placedAt != null && endedAt != null && endedAt > placedAt;
98725
98969
  };
98970
+ ledgerOrderIdsByClientOrderId = (mutation) => {
98971
+ const orderIds = /* @__PURE__ */ new Map();
98972
+ const add = (clientOrderId, exchangeOrderId) => {
98973
+ const cloid = String(clientOrderId ?? "").trim().toLowerCase();
98974
+ const orderId = String(exchangeOrderId ?? "").trim();
98975
+ if (/^0x[0-9a-f]{32}$/.test(cloid) && /^[1-9]\d*$/.test(orderId) && Number.isSafeInteger(Number(orderId))) {
98976
+ orderIds.set(cloid, Number(orderId));
98977
+ }
98978
+ };
98979
+ add(mutation.client_order_id, mutation.exchange_order_id);
98980
+ for (const member of mutation.order_members ?? []) {
98981
+ add(member.client_order_id, member.exchange_order_id);
98982
+ }
98983
+ return orderIds;
98984
+ };
98985
+ journaledAttachmentNeverLanded = async (request, group) => {
98986
+ const journal = group.attachmentJournal;
98987
+ let ledgerOrderIds = /* @__PURE__ */ new Map();
98988
+ if (journal == null) return { group, proven: false, ledgerOrderIds };
98989
+ const observedAtMs = Date.now();
98990
+ const firstSeenAtMs = journal.unknownOidFirstSeenAtMs ?? observedAtMs;
98991
+ const waiting = (unknownOidObservedAtMs) => {
98992
+ if (journal.unknownOidFirstSeenAtMs != null && unknownOidObservedAtMs === void 0) {
98993
+ return { group, proven: false, ledgerOrderIds };
98994
+ }
98995
+ const recorded = {
98996
+ ...group,
98997
+ attachmentJournal: {
98998
+ ...journal,
98999
+ unknownOidFirstSeenAtMs: firstSeenAtMs,
99000
+ ...unknownOidObservedAtMs !== void 0 ? { unknownOidObservedAtMs } : {}
99001
+ }
99002
+ };
99003
+ if (!replaceExactClientProtectiveGroup(
99004
+ String(request.profileId).trim(),
99005
+ request.executionContext.symbol,
99006
+ group,
99007
+ recorded
99008
+ )) {
99009
+ throw new Error("Journaled attachment recovery state could not be saved durably.");
99010
+ }
99011
+ return { group: recorded, proven: false, ledgerOrderIds };
99012
+ };
99013
+ const mutationId = journal.mutationId ?? mutationIdForClientOrderId(journal.members[0]?.clientOrderId ?? "");
99014
+ let provableAtMs;
99015
+ if (mutationId == null) {
99016
+ provableAtMs = clientOrderNeverLandsAfterMs(request.config, { kind: "absent", ageStartMs: firstSeenAtMs });
99017
+ } else {
99018
+ const ledger = await readClientOrderMutation(
99019
+ request,
99020
+ mutationId,
99021
+ clientOrderIdForMutation(mutationId)
99022
+ );
99023
+ if (ledger.kind === "found") {
99024
+ ledgerOrderIds = ledgerOrderIdsByClientOrderId(ledger.mutation);
99025
+ if (String(ledger.mutation.exchange_order_id ?? "").trim().length > 0) {
99026
+ return { group, proven: false, ledgerOrderIds };
99027
+ }
99028
+ const expiresAfterMs = Number(ledger.mutation.exchange_expires_after_ms);
99029
+ if (!Number.isSafeInteger(expiresAfterMs) || expiresAfterMs <= 0) return waiting();
99030
+ provableAtMs = clientOrderNeverLandsAfterMs(request.config, { kind: "found", expiresAfterMs });
99031
+ } else if (ledger.kind === "absent") {
99032
+ provableAtMs = clientOrderNeverLandsAfterMs(request.config, {
99033
+ kind: "absent",
99034
+ ageStartMs: journal.createdAtMs ?? firstSeenAtMs
99035
+ });
99036
+ } else {
99037
+ return waiting();
99038
+ }
99039
+ }
99040
+ if (observedAtMs < provableAtMs) return waiting();
99041
+ if (journal.unknownOidObservedAtMs == null || journal.unknownOidObservedAtMs < provableAtMs) {
99042
+ return waiting(observedAtMs);
99043
+ }
99044
+ return { group, proven: true, ledgerOrderIds };
99045
+ };
98726
99046
  recoverJournaledClientProtectiveAttachments = async (request, journaledGroups) => {
98727
99047
  const reports = [];
98728
99048
  const profileId = String(request.profileId).trim();
@@ -98744,24 +99064,64 @@ var init_runtime_execution = __esm({
98744
99064
  }
98745
99065
  })));
98746
99066
  }
98747
- for (const group of journaledGroups) {
99067
+ const boundOrderIds = new Set(readClientProtectiveGroups(profileId, symbol2).flatMap((stored) => stored.legs.flatMap((leg) => typeof leg.orderId === "number" ? [String(leg.orderId)] : [])));
99068
+ for (const journaledGroup of journaledGroups) {
99069
+ let group = journaledGroup;
98748
99070
  const plan = group.pendingEntry;
98749
- const journal = group.attachmentJournal;
99071
+ let journal = group.attachmentJournal;
98750
99072
  if (plan == null || journal == null || group.legs.length === 0) continue;
98751
99073
  const inspected = [];
98752
99074
  let unresolved = false;
99075
+ let ledgerVerdict = null;
99076
+ const newlyNeverLanded = /* @__PURE__ */ new Set();
98753
99077
  for (const provisionalLeg of group.legs) {
99078
+ if (attachmentMemberNeverLanded(group, provisionalLeg)) {
99079
+ inspected.push({ leg: provisionalLeg, state: "terminal", rested: false, neverLanded: true });
99080
+ continue;
99081
+ }
98754
99082
  let openOrder = liveOrders.find((order) => String(order.oid) === String(provisionalLeg.orderId)) ?? null;
98755
99083
  let canonicalLeg = provisionalLeg;
98756
99084
  if (openOrder == null) {
98757
99085
  try {
98758
- const evidence = await fetchBrowserOrderStatusEvidence({
99086
+ let evidence = await fetchBrowserOrderStatusEvidence({
98759
99087
  publicRequestPriority: "trading_reconcile",
98760
99088
  config: request.config ?? null,
98761
99089
  walletAddress,
98762
99090
  signal: request.signal,
98763
99091
  orderId: provisionalLeg.orderId
98764
99092
  });
99093
+ if (typeof provisionalLeg.orderId === "string" && evidence.responseValid && evidence.responseStatus === "unknownOid") {
99094
+ if (ledgerVerdict == null) {
99095
+ ledgerVerdict = await journaledAttachmentNeverLanded(request, group);
99096
+ group = ledgerVerdict.group;
99097
+ journal = group.attachmentJournal ?? journal;
99098
+ }
99099
+ const ledgerOrderId = ledgerVerdict.ledgerOrderIds.get(provisionalLeg.orderId);
99100
+ if (ledgerOrderId != null) {
99101
+ evidence = await fetchBrowserOrderStatusEvidence({
99102
+ publicRequestPriority: "trading_reconcile",
99103
+ config: request.config ?? null,
99104
+ walletAddress,
99105
+ signal: request.signal,
99106
+ orderId: ledgerOrderId
99107
+ });
99108
+ if (!evidence.responseValid || !evidence.orderMatches) {
99109
+ throw new Error("Journaled protective order identity is unresolved.");
99110
+ }
99111
+ } else {
99112
+ const mayRestUnseen = liveOrders.some((order) => !boundOrderIds.has(String(order.oid)) && protectiveLiveShapeMatches({
99113
+ shape: liveProtectiveOrderShape(order),
99114
+ symbol: symbol2,
99115
+ isLong: group.isLong,
99116
+ leg: provisionalLeg
99117
+ }));
99118
+ if (ledgerVerdict.proven && !mayRestUnseen) {
99119
+ newlyNeverLanded.add(provisionalLeg.orderId);
99120
+ inspected.push({ leg: provisionalLeg, state: "terminal", rested: false, neverLanded: true });
99121
+ continue;
99122
+ }
99123
+ }
99124
+ }
98765
99125
  const resolvedOrderId = Number(evidence.orderId);
98766
99126
  if (!Number.isSafeInteger(resolvedOrderId) || resolvedOrderId <= 0) {
98767
99127
  throw new Error("Journaled protective order identity is unresolved.");
@@ -98829,6 +99189,28 @@ var init_runtime_execution = __esm({
98829
99189
  inspected.push({ leg: canonicalLeg, state: "open" });
98830
99190
  }
98831
99191
  if (unresolved || inspected.length !== group.legs.length) continue;
99192
+ if (newlyNeverLanded.size > 0) {
99193
+ const neverLandedAtMs = Date.now();
99194
+ const proven = {
99195
+ ...group,
99196
+ attachmentJournal: {
99197
+ ...journal,
99198
+ members: journal.members.map((member) => newlyNeverLanded.has(member.clientOrderId) ? { ...member, neverLandedAtMs } : member)
99199
+ }
99200
+ };
99201
+ if (!replaceExactClientProtectiveGroup(profileId, symbol2, group, proven)) {
99202
+ reports.push({
99203
+ order_id: journal.entryOrderId,
99204
+ symbol: symbol2,
99205
+ action: "PROTECTIVE_RECONCILIATION",
99206
+ status: "failed",
99207
+ execution_metadata: { reason_code: "protective_lifecycle_persistence_failed" }
99208
+ });
99209
+ continue;
99210
+ }
99211
+ group = proven;
99212
+ journal = proven.attachmentJournal ?? journal;
99213
+ }
98832
99214
  const hasFulfilled = inspected.some((entry) => entry.state === "fulfilled");
98833
99215
  const hasNonfulfilledTerminal = inspected.some((entry) => entry.state === "terminal");
98834
99216
  const openEntries = inspected.filter((entry) => entry.state === "open");
@@ -99073,6 +99455,47 @@ var init_runtime_execution = __esm({
99073
99455
  });
99074
99456
  continue;
99075
99457
  }
99458
+ if (inspected.every((entry) => entry.neverLanded === true)) {
99459
+ let livePositionSize = Number.NaN;
99460
+ let positionError = null;
99461
+ try {
99462
+ livePositionSize = Number((await fetchBrowserPositionSnapshot(
99463
+ request.config ?? {},
99464
+ walletAddress,
99465
+ symbol2,
99466
+ request.signal,
99467
+ "trading_reconcile"
99468
+ )).size);
99469
+ } catch (error48) {
99470
+ if (request.signal?.aborted) throw error48;
99471
+ positionError = error48;
99472
+ }
99473
+ if (!Number.isFinite(livePositionSize)) {
99474
+ reports.push({
99475
+ order_id: journal.entryOrderId,
99476
+ symbol: symbol2,
99477
+ action: "PROTECTIVE_RECONCILIATION",
99478
+ status: "failed",
99479
+ execution_metadata: {
99480
+ reason_code: "protective_attachment_continuity_unresolved",
99481
+ error: getSanitizedRuntimeErrorMessage(positionError) || "Unable to verify live position exposure."
99482
+ }
99483
+ });
99484
+ continue;
99485
+ }
99486
+ if (!(group.isLong ? livePositionSize > 0 : livePositionSize < 0)) {
99487
+ if (!replaceExactClientProtectiveGroup(profileId, symbol2, group, null)) {
99488
+ reports.push({
99489
+ order_id: journal.entryOrderId,
99490
+ symbol: symbol2,
99491
+ action: "PROTECTIVE_RECONCILIATION",
99492
+ status: "failed",
99493
+ execution_metadata: { reason_code: "protective_lifecycle_persistence_failed" }
99494
+ });
99495
+ }
99496
+ continue;
99497
+ }
99498
+ }
99076
99499
  let disposition;
99077
99500
  try {
99078
99501
  ({ disposition } = await resolveJournaledAttachmentContinuity(
@@ -99114,20 +99537,35 @@ var init_runtime_execution = __esm({
99114
99537
  }
99115
99538
  return reports;
99116
99539
  };
99117
- readPendingEntryMutation = async (request, plan) => {
99540
+ readClientOrderMutation = async (request, mutationId, clientOrderId) => {
99118
99541
  try {
99119
99542
  const mutation = await getClientRuntimeExchangeMutation(
99120
99543
  request.profileId,
99121
- plan.entryMutationId,
99544
+ mutationId,
99122
99545
  request.signal
99123
99546
  );
99124
99547
  if (mutation == null) return { kind: "absent" };
99125
- return mutation.operation_kind === "order" && String(mutation.client_order_id ?? "").trim().toLowerCase() === plan.entryClientOrderId ? { kind: "found", mutation } : { kind: "unavailable" };
99548
+ return mutation.operation_kind === "order" && String(mutation.client_order_id ?? "").trim().toLowerCase() === clientOrderId ? { kind: "found", mutation } : { kind: "unavailable" };
99126
99549
  } catch (error48) {
99127
99550
  if (request.signal?.aborted) throw error48;
99128
99551
  return { kind: "unavailable" };
99129
99552
  }
99130
99553
  };
99554
+ readPendingEntryMutation = (request, plan) => readClientOrderMutation(request, plan.entryMutationId, plan.entryClientOrderId);
99555
+ clientOrderNeverLandsAfterMs = (config2, ledger) => {
99556
+ const marginMs = requireClientRuntimeConfigSeconds(
99557
+ config2,
99558
+ "client_pending_entry_never_landed_margin_seconds"
99559
+ ) * MS_PER_SECOND;
99560
+ if (ledger.kind === "found") return ledger.expiresAfterMs + marginMs;
99561
+ const signedLifetimeSeconds = Number(
99562
+ config2?.client_runtime_exchange_mutation?.expires_after_seconds
99563
+ );
99564
+ if (!Number.isInteger(signedLifetimeSeconds) || signedLifetimeSeconds <= 0) {
99565
+ throw new Error("Missing required client runtime config: client_runtime_exchange_mutation.expires_after_seconds");
99566
+ }
99567
+ return ledger.ageStartMs + signedLifetimeSeconds * MS_PER_SECOND + marginMs;
99568
+ };
99131
99569
  requireClientRuntimeConfigSeconds = (config2, key) => {
99132
99570
  const value = Number(config2?.[key]);
99133
99571
  if (!Number.isFinite(value) || value < 0) {
@@ -99268,10 +99706,6 @@ var init_runtime_execution = __esm({
99268
99706
  });
99269
99707
  if (evidence.responseValid && evidence.responseStatus === "unknownOid") {
99270
99708
  const observedAtMs = Date.now();
99271
- const marginMs = requireClientRuntimeConfigSeconds(
99272
- request.config,
99273
- "client_pending_entry_never_landed_margin_seconds"
99274
- ) * MS_PER_SECOND;
99275
99709
  const firstSeenAtMs = plan.recovery?.unknownOidFirstSeenAtMs ?? observedAtMs;
99276
99710
  const recordFirstSeen = () => {
99277
99711
  if (plan.recovery?.unknownOidFirstSeenAtMs != null) return;
@@ -99286,16 +99720,12 @@ var init_runtime_execution = __esm({
99286
99720
  if (!Number.isSafeInteger(expiresAfterMs) || expiresAfterMs <= 0) {
99287
99721
  throw new Error("Pending entry is unknown to Hyperliquid and its signed expiry is unavailable.");
99288
99722
  }
99289
- provableAtMs = expiresAfterMs + marginMs;
99723
+ provableAtMs = clientOrderNeverLandsAfterMs(request.config, { kind: "found", expiresAfterMs });
99290
99724
  } else if (ledger.kind === "absent") {
99291
- const ageStartMs = plan.createdAtMs ?? firstSeenAtMs;
99292
- const signedLifetimeSeconds = Number(
99293
- request.config?.client_runtime_exchange_mutation?.expires_after_seconds
99294
- );
99295
- if (!Number.isInteger(signedLifetimeSeconds) || signedLifetimeSeconds <= 0) {
99296
- throw new Error("Missing required client runtime config: client_runtime_exchange_mutation.expires_after_seconds");
99297
- }
99298
- provableAtMs = ageStartMs + signedLifetimeSeconds * MS_PER_SECOND + marginMs;
99725
+ provableAtMs = clientOrderNeverLandsAfterMs(request.config, {
99726
+ kind: "absent",
99727
+ ageStartMs: plan.createdAtMs ?? firstSeenAtMs
99728
+ });
99299
99729
  } else {
99300
99730
  recordFirstSeen();
99301
99731
  throw new Error("Pending entry is unknown to Hyperliquid and the ledger cannot answer.");
@@ -100138,37 +100568,16 @@ var init_runtime_execution = __esm({
100138
100568
  }]
100139
100569
  });
100140
100570
  const observedAtMs = Date.now();
100141
- const marginMs = requireClientRuntimeConfigSeconds(
100142
- request.config,
100143
- "client_pending_entry_never_landed_margin_seconds"
100144
- ) * MS_PER_SECOND;
100145
- let ledgerKind;
100146
- let expiresAfterMs = Number.NaN;
100147
- try {
100148
- const mutation = await getClientRuntimeExchangeMutation(request.profileId, journal.mutationId, request.signal);
100149
- if (mutation == null) {
100150
- ledgerKind = "absent";
100151
- } else if (mutation.operation_kind === "order" && String(mutation.client_order_id ?? "").trim().toLowerCase() === String(leg.orderId)) {
100152
- ledgerKind = "found";
100153
- expiresAfterMs = Number(mutation.exchange_expires_after_ms);
100154
- } else {
100155
- ledgerKind = "unavailable";
100156
- }
100157
- } catch (error48) {
100158
- if (request.signal?.aborted) throw error48;
100159
- ledgerKind = "unavailable";
100160
- }
100571
+ const ledger = await readClientOrderMutation(request, journal.mutationId, String(leg.orderId));
100572
+ const expiresAfterMs = ledger.kind === "found" ? Number(ledger.mutation.exchange_expires_after_ms) : Number.NaN;
100161
100573
  let provableAtMs;
100162
- if (ledgerKind === "found" && Number.isSafeInteger(expiresAfterMs) && expiresAfterMs > 0) {
100163
- provableAtMs = expiresAfterMs + marginMs;
100164
- } else if (ledgerKind === "absent") {
100165
- const signedLifetimeSeconds = Number(
100166
- request.config?.client_runtime_exchange_mutation?.expires_after_seconds
100167
- );
100168
- if (!Number.isInteger(signedLifetimeSeconds) || signedLifetimeSeconds <= 0) {
100169
- throw new Error("Missing required client runtime config: client_runtime_exchange_mutation.expires_after_seconds");
100170
- }
100171
- provableAtMs = journal.createdAtMs + signedLifetimeSeconds * MS_PER_SECOND + marginMs;
100574
+ if (ledger.kind === "found" && Number.isSafeInteger(expiresAfterMs) && expiresAfterMs > 0) {
100575
+ provableAtMs = clientOrderNeverLandsAfterMs(request.config, { kind: "found", expiresAfterMs });
100576
+ } else if (ledger.kind === "absent") {
100577
+ provableAtMs = clientOrderNeverLandsAfterMs(request.config, {
100578
+ kind: "absent",
100579
+ ageStartMs: journal.createdAtMs
100580
+ });
100172
100581
  } else {
100173
100582
  return waiting("protective_stop_replacement_unresolved", "The stop re-place ledger cannot answer yet.");
100174
100583
  }
@@ -101643,7 +102052,64 @@ var init_runtime_execution = __esm({
101643
102052
  const parsed = Number(position?.size ?? 0);
101644
102053
  return Number.isFinite(parsed) ? parsed : 0;
101645
102054
  };
101646
- resolveCurrentPositionSize = async (input) => {
102055
+ readServerOrderMarkPrice = async (input) => {
102056
+ const symbol2 = normalizeHyperliquidMarketSymbol(input.executionContext.symbol);
102057
+ const active = await fetchBrowserHyperliquidInfoPayload(
102058
+ { config: input.config ?? null, signal: input.signal, publicRequestPriority: executionReadPriority(input) },
102059
+ { type: "activeAssetData", user: String(input.executionContext.walletAddress || "").trim(), coin: symbol2 },
102060
+ "hyperliquid.activeAssetData"
102061
+ );
102062
+ const markPrice = Number(active?.markPx);
102063
+ if (!Number.isFinite(markPrice) || !(markPrice > 0)) {
102064
+ throw new Error(`Missing Hyperliquid mark price for ${input.executionContext.symbol}.`);
102065
+ }
102066
+ return markPrice;
102067
+ };
102068
+ serverOrderMetadataRetry = async (input, rejection, leg, rejectedMutationId) => {
102069
+ const decisionSnapshotId = String(input.executionContext.decisionSnapshotId ?? "").trim();
102070
+ if (input.executionMode !== "server" || !decisionSnapshotId || !isDefinitiveEntryRejection(rejection, rejectedMutationId)) return null;
102071
+ const reason = orderMetadataRetryReason(rejection.message);
102072
+ if (reason === null) return null;
102073
+ throwIfAborted2(input.signal);
102074
+ try {
102075
+ const asset = await resolveHyperliquidAsset({
102076
+ symbol: input.executionContext.symbol,
102077
+ config: input.config ?? void 0,
102078
+ publicRequestPriority: executionReadPriority(input),
102079
+ refreshCatalog: true
102080
+ });
102081
+ if (!Number.isInteger(asset.sz_decimals) || asset.sz_decimals < 0) return null;
102082
+ const markPrice = reason === "reference_price" ? await readServerOrderMarkPrice(input) : null;
102083
+ appendRuntimeDebugEvent({
102084
+ label: "execution_order_metadata_retry",
102085
+ note: `symbol=${input.executionContext.symbol} leg=${leg} reason=${reason}`
102086
+ });
102087
+ return {
102088
+ mutationId: await clientDecisionMutationId({
102089
+ profileId: input.profileId,
102090
+ decisionSnapshotId,
102091
+ symbol: input.executionContext.symbol,
102092
+ leg,
102093
+ attempt: 1
102094
+ }),
102095
+ assets: [{
102096
+ symbol: input.executionContext.symbol,
102097
+ asset_id: asset.asset_index,
102098
+ asset_index: asset.asset_index,
102099
+ max_leverage: asset.max_leverage,
102100
+ sz_decimals: asset.sz_decimals,
102101
+ margin_mode: asset.margin_mode ?? null,
102102
+ only_isolated: asset.only_isolated === true
102103
+ }],
102104
+ sizeDecimals: asset.sz_decimals,
102105
+ markPrice
102106
+ };
102107
+ } catch {
102108
+ throwIfAborted2(input.signal);
102109
+ return null;
102110
+ }
102111
+ };
102112
+ resolveCurrentPositionSize = async (input, orderPrice = "decision") => {
101647
102113
  throwIfAborted2(input.signal);
101648
102114
  const snapshotPositionSize = Number.isFinite(input.executionContext.currentPositionSize) ? Number(input.executionContext.currentPositionSize) : 0;
101649
102115
  const decisionPrice = Number.isFinite(input.executionContext.lastPrice) ? Number(input.executionContext.lastPrice) : 0;
@@ -101655,7 +102121,7 @@ var init_runtime_execution = __esm({
101655
102121
  const decisionCapturedAtMs = Date.parse(String(input.executionContext.decisionSnapshotCapturedAt || ""));
101656
102122
  const maxAgeSeconds = Number(input.executionContext.executionFreshnessMaxAgeSeconds);
101657
102123
  const shouldRefreshExecutionSnapshot = Number.isFinite(decisionCapturedAtMs) && Number.isFinite(maxAgeSeconds) && maxAgeSeconds > 0 && (nowMs2 - decisionCapturedAtMs) / MS_PER_SECOND > maxAgeSeconds;
101658
- if (shouldRefreshExecutionSnapshot) {
102124
+ if (shouldRefreshExecutionSnapshot && orderPrice !== "fresh_mark") {
101659
102125
  try {
101660
102126
  const refreshed = await fetchBrowserAccountState2({
101661
102127
  publicRequestPriority: executionReadPriority(input),
@@ -101698,10 +102164,12 @@ var init_runtime_execution = __esm({
101698
102164
  symbol: input.executionContext.symbol,
101699
102165
  size: liveBrowserSnapshot.size
101700
102166
  });
102167
+ const liveMarkPrice = Number(liveBrowserSnapshot.markPrice);
102168
+ const executionPrice = orderPrice !== "fresh_mark" ? decisionPrice : parsedLiveSize !== 0 && Number.isFinite(liveMarkPrice) && liveMarkPrice > 0 ? liveMarkPrice : await readServerOrderMarkPrice(input);
101701
102169
  return {
101702
102170
  currentPositionSize: Number.isFinite(parsedLiveSize) ? parsedLiveSize : snapshotPositionSize,
101703
102171
  currentPositionEntryPrice: liveBrowserSnapshot.entryPrice,
101704
- executionPrice: decisionPrice,
102172
+ executionPrice,
101705
102173
  executionSnapshotId: createRuntimeId(),
101706
102174
  executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString()
101707
102175
  };
@@ -101902,9 +102370,30 @@ var init_runtime_execution = __esm({
101902
102370
  try {
101903
102371
  return await executeClientRuntimeDecisionUnlocked(input, progress);
101904
102372
  } catch (error48) {
101905
- throw withCommittedExecutionReports(error48, progress.committedReports);
102373
+ throw withCommittedExecutionReports(error48, progress.committedReports, progress.committedOrder ?? null);
102374
+ }
102375
+ });
102376
+ unsentDecisionOrderReport = (input, reasonCode, metadata = {}) => ({
102377
+ order_id: null,
102378
+ symbol: input.executionContext.symbol,
102379
+ action: String(input.decision).toUpperCase(),
102380
+ status: "blocked",
102381
+ execution_metadata: {
102382
+ reason_code: reasonCode,
102383
+ ...metadata,
102384
+ ...input.cycleId ? { cycle_id: input.cycleId } : {},
102385
+ ...input.executionContext.decisionSnapshotId ? { decision_snapshot_id: input.executionContext.decisionSnapshotId } : {}
101906
102386
  }
101907
102387
  });
102388
+ withCapacityTrim = (result, trim) => {
102389
+ const decisionOrders = result.executionReports.filter((report) => report.status === "executed" && (report.action === "BUY" || report.action === "SELL") && (result.intent !== "flip" || report.execution_metadata?.decision_leg === "entry"));
102390
+ const trimmed = decisionOrders[decisionOrders.length - 1];
102391
+ if (!trimmed) return result;
102392
+ return {
102393
+ ...result,
102394
+ executionReports: result.executionReports.map((report) => report === trimmed ? { ...report, execution_metadata: { ...report.execution_metadata, ...trim } } : report)
102395
+ };
102396
+ };
101908
102397
  SERVER_AUDIT_RECORDED_ELSEWHERE = /* @__PURE__ */ new Set([
101909
102398
  "suppressed_duplicate_decision",
101910
102399
  "same_intent_cooldown",
@@ -101918,7 +102407,7 @@ var init_runtime_execution = __esm({
101918
102407
  return ["executed", "executed"];
101919
102408
  }
101920
102409
  if (result.status === "skipped") {
101921
- if (result.reasonCode === "noop_already_at_target" || result.reasonCode === "stale_target_conflict") {
102410
+ if (result.reasonCode === "noop_already_at_target" || result.reasonCode === "stale_target_conflict" || result.reasonCode === "order_below_lot_size") {
101922
102411
  return ["noop", result.reasonCode];
101923
102412
  }
101924
102413
  if (result.reasonCode === "protective_reconciliation_unresolved") return ["blocked", result.reasonCode];
@@ -101938,6 +102427,7 @@ var init_runtime_execution = __esm({
101938
102427
  if (input.executionMode !== "server") return executeClientRuntimeDecisionLocked(input);
101939
102428
  const audit = input.serverExecutionAudit ?? { auditId: null };
101940
102429
  let entryDispatched = false;
102430
+ let exitDispatched = false;
101941
102431
  const recordAudit = async (auditId2, fields, signal = input.signal) => {
101942
102432
  try {
101943
102433
  const recorded = await recordServerHostExecutionAudit(
@@ -101974,13 +102464,15 @@ var init_runtime_execution = __esm({
101974
102464
  onExchangeOrderDispatched: (kind) => {
101975
102465
  input.onExchangeOrderDispatched?.(kind);
101976
102466
  if (kind === "entry") entryDispatched = true;
102467
+ if (kind === "exit") exitDispatched = true;
101977
102468
  }
101978
102469
  });
101979
102470
  } catch (error48) {
101980
102471
  const committedClose = getCommittedExecutionReports(error48).find((report) => report.status === "executed" && decisionLegOf(report) === "flip_close");
101981
102472
  if (audit.auditId !== null && (!input.signal?.aborted || committedClose) && (input.decision === "BUY" || input.decision === "SELL")) {
101982
102473
  const reason = String(error48?.reasonCode ?? "");
101983
- const [status2, reasonCode2] = reason === "outcome_unknown" || !reason && entryDispatched ? ["outcome_unknown", "outcome_unknown"] : ["error", reason === "exchange_rejected" ? "exchange_rejected" : "execution_error"];
102474
+ const orderMayHaveGoneOut = entryDispatched || exitDispatched && !committedClose;
102475
+ const [status2, reasonCode2] = reason === "outcome_unknown" || !reason && orderMayHaveGoneOut ? ["outcome_unknown", "outcome_unknown"] : ["error", reason === "exchange_rejected" ? "exchange_rejected" : "execution_error"];
101984
102476
  const side = input.decision === "BUY" ? "buy" : "sell";
101985
102477
  if (committedClose) {
101986
102478
  await recordAudit(audit.auditId, {
@@ -102038,7 +102530,7 @@ var init_runtime_execution = __esm({
102038
102530
  reasonCode: blockedByProtection ? "protective_reconciliation_unresolved" : "executed",
102039
102531
  orderId: flipClose.order_id == null ? null : String(flipClose.order_id)
102040
102532
  });
102041
- const [entryStatus, entryReason] = entryReport ? ["executed", "executed"] : blockedByProtection ? ["blocked", "protective_reconciliation_unresolved"] : result.reasonCode === "noop_already_at_target" ? ["noop", "noop_already_at_target"] : ["blocked", "local_safety_block"];
102533
+ const [entryStatus, entryReason] = entryReport ? ["executed", "executed"] : blockedByProtection ? ["blocked", "protective_reconciliation_unresolved"] : result.reasonCode === "noop_already_at_target" || result.reasonCode === "order_below_lot_size" ? ["noop", result.reasonCode] : ["blocked", "local_safety_block"];
102042
102534
  const entryAuditId = await recordAudit(null, {
102043
102535
  ...auditFields,
102044
102536
  status: entryStatus,
@@ -102457,12 +102949,18 @@ var init_runtime_execution = __esm({
102457
102949
  return !input.skipTrailingMaintenance && context.tpSlEnabled === true && context.stopLossEnabled !== false && context.stopLossType === "trailing" && positionSize !== 0;
102458
102950
  };
102459
102951
  COMMITTED_EXECUTION_REPORTS = /* @__PURE__ */ Symbol("committedExecutionReports");
102952
+ COMMITTED_DECISION_ORDER = /* @__PURE__ */ Symbol("committedDecisionOrder");
102460
102953
  getCommittedExecutionReports = (error48) => {
102461
102954
  if (!error48 || typeof error48 !== "object") return [];
102462
102955
  const reports = error48[COMMITTED_EXECUTION_REPORTS];
102463
102956
  return Array.isArray(reports) ? reports : [];
102464
102957
  };
102465
- withCommittedExecutionReports = (error48, reports) => {
102958
+ getCommittedDecisionOrder = (error48) => {
102959
+ if (!error48 || typeof error48 !== "object") return null;
102960
+ const order = error48[COMMITTED_DECISION_ORDER];
102961
+ return order && typeof order === "object" ? order : null;
102962
+ };
102963
+ withCommittedExecutionReports = (error48, reports, order = null) => {
102466
102964
  if (!reports || !reports.some((report) => report.status === "executed")) return error48;
102467
102965
  const carrier = error48 && typeof error48 === "object" ? error48 : new Error(String(error48 ?? "Unknown runtime execution error."), { cause: error48 });
102468
102966
  Object.defineProperty(carrier, COMMITTED_EXECUTION_REPORTS, {
@@ -102470,6 +102968,11 @@ var init_runtime_execution = __esm({
102470
102968
  enumerable: false,
102471
102969
  configurable: true
102472
102970
  });
102971
+ Object.defineProperty(carrier, COMMITTED_DECISION_ORDER, {
102972
+ value: order,
102973
+ enumerable: false,
102974
+ configurable: true
102975
+ });
102473
102976
  return carrier;
102474
102977
  };
102475
102978
  executeClientRuntimeDecisionUnlocked = async (unsizedInput, progress = { committedReports: null }) => {
@@ -102499,7 +103002,7 @@ var init_runtime_execution = __esm({
102499
103002
  };
102500
103003
  }
102501
103004
  if (unsizedInput.executionMode === "server" && !unsizedInput.serverCapacityChecked && (unsizedInput.decision === "BUY" || unsizedInput.decision === "SELL") && requestedUnits > 0) {
102502
- const skipped = (reasonCode, message) => ({
103005
+ const skipped = (reasonCode, constraintReasonCode) => ({
102503
103006
  status: "skipped",
102504
103007
  intent: "hold",
102505
103008
  side: null,
@@ -102507,8 +103010,13 @@ var init_runtime_execution = __esm({
102507
103010
  requestedUnits,
102508
103011
  targetSignedUnits: 0,
102509
103012
  executedSizeAsset: 0,
102510
- executionReports: [],
102511
- message,
103013
+ // The decision keeps its order; this record says it was not placed and
103014
+ // which limit refused it.
103015
+ executionReports: [unsentDecisionOrderReport(unsizedInput, reasonCode, {
103016
+ constraint_reason_code: constraintReasonCode,
103017
+ requested_units: requestedUnits
103018
+ })],
103019
+ message: `Skipped: runtime constraint ${constraintReasonCode}.`,
102512
103020
  reasonCode,
102513
103021
  executionSnapshotId: createRuntimeId(),
102514
103022
  executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -102526,13 +103034,19 @@ var init_runtime_execution = __esm({
102526
103034
  note: `symbol=${unsizedInput.executionContext.symbol} reason=${capacity.reason_code ?? "unknown"}`,
102527
103035
  outcome: "ok"
102528
103036
  });
102529
- return skipped("execution_capacity_refused", `Skipped: runtime constraint ${capacity.reason_code ?? "capacity"}.`);
103037
+ return skipped("execution_capacity_refused", capacity.reason_code ?? "capacity_reached");
102530
103038
  }
102531
- return executeClientRuntimeDecisionUnlocked({
103039
+ const acceptedUnits = Math.min(requestedUnits, Math.trunc(capacity.units));
103040
+ const result = await executeClientRuntimeDecisionUnlocked({
102532
103041
  ...unsizedInput,
102533
- units: Math.min(requestedUnits, Math.trunc(capacity.units)),
103042
+ units: acceptedUnits,
102534
103043
  serverCapacityChecked: true
102535
103044
  }, progress);
103045
+ return acceptedUnits < requestedUnits ? withCapacityTrim(result, {
103046
+ requested_units: requestedUnits,
103047
+ accepted_units: acceptedUnits,
103048
+ constraint_reason_code: capacity.reason_code ?? "units_capped"
103049
+ }) : result;
102536
103050
  }
102537
103051
  const input = {
102538
103052
  ...unsizedInput,
@@ -102624,13 +103138,15 @@ var init_runtime_execution = __esm({
102624
103138
  executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString()
102625
103139
  };
102626
103140
  }
103141
+ const serverOrder = input.executionMode === "server";
102627
103142
  const {
102628
103143
  currentPositionSize,
102629
103144
  currentPositionEntryPrice,
102630
- executionPrice,
103145
+ executionPrice: resolvedExecutionPrice,
102631
103146
  executionSnapshotId,
102632
103147
  executionSnapshotCapturedAt
102633
- } = await resolveCurrentPositionSize(input);
103148
+ } = await resolveCurrentPositionSize(input, serverOrder ? "fresh_mark" : "decision");
103149
+ let executionPrice = resolvedExecutionPrice;
102634
103150
  throwIfAborted2(input.signal);
102635
103151
  const currentPosition = buildPositionSnapshot(input.executionContext.symbol, currentPositionSize);
102636
103152
  const decisionSnapshotId = String(input.executionContext.decisionSnapshotId ?? "").trim();
@@ -102641,6 +103157,15 @@ var init_runtime_execution = __esm({
102641
103157
  leg,
102642
103158
  attempt: 0
102643
103159
  }) : Promise.resolve(void 0);
103160
+ const closeWithServerMetadataRetry = async (leg, mutationId, send) => {
103161
+ try {
103162
+ return await send(mutationId, executionPrice);
103163
+ } catch (rejection) {
103164
+ const retry = await serverOrderMetadataRetry(input, rejection, leg, mutationId);
103165
+ if (retry === null) throw rejection;
103166
+ return send(retry.mutationId, retry.markPrice ?? executionPrice, retry.assets);
103167
+ }
103168
+ };
102644
103169
  const liveSignedUnits = signedUnitsFromEntryPosition(
102645
103170
  currentPositionSize,
102646
103171
  currentPositionEntryPrice,
@@ -102691,7 +103216,12 @@ var init_runtime_execution = __esm({
102691
103216
  requestedUnits: classified.requestedUnits,
102692
103217
  targetSignedUnits: classified.targetSignedUnits,
102693
103218
  executedSizeAsset: 0,
102694
- executionReports: reconciliationReports,
103219
+ // A Server bot's skip is its execution audit row; a Client bot's is this record.
103220
+ executionReports: input.executionMode === "server" ? reconciliationReports : [...reconciliationReports, unsentDecisionOrderReport(
103221
+ input,
103222
+ staleTargetConflict ? "stale_target_conflict" : "noop_already_at_target",
103223
+ { intent: classified.intent }
103224
+ )],
102695
103225
  message: staleTargetConflict ? "Live state moved beyond the requested target; skipping stale decision" : "No-op: live position already matches target state",
102696
103226
  reasonCode: staleTargetConflict ? "stale_target_conflict" : "noop_already_at_target",
102697
103227
  executionSnapshotId,
@@ -102827,8 +103357,9 @@ var init_runtime_execution = __esm({
102827
103357
  if (classified.intent === "close") {
102828
103358
  throwIfAborted2(input.signal);
102829
103359
  const closeMutationId = await decisionLegMutationId("close");
102830
- const closeResponse = await executeClientClosePosition({
102831
- mutationId: closeMutationId,
103360
+ const closeResponse = await closeWithServerMetadataRetry("close", closeMutationId, (mutationId, estimatedPrice, assets) => executeClientClosePosition({
103361
+ mutationId,
103362
+ ...assets ? { assets } : {},
102832
103363
  profileId: input.profileId,
102833
103364
  runtimeSessionId: input.sessionId || "__missing_runtime_session__",
102834
103365
  runtimeLeaseToken: input.runtimeLeaseToken,
@@ -102838,20 +103369,42 @@ var init_runtime_execution = __esm({
102838
103369
  config: input.config ?? null,
102839
103370
  signal: input.signal,
102840
103371
  signingKey: input.signingKey,
102841
- onExchangeOrderDispatched: () => input.onExchangeOrderDispatched?.("action"),
103372
+ onExchangeOrderDispatched: () => input.onExchangeOrderDispatched?.("exit"),
102842
103373
  symbol: input.executionContext.symbol,
102843
103374
  position: currentPosition,
102844
- estimatedPrice: executionPrice,
103375
+ estimatedPrice,
102845
103376
  slippage: input.executionContext.maxSlippageFraction
102846
- });
103377
+ }));
102847
103378
  const confirmedClose = extractCanonicalHyperliquidFilledOrderAcknowledgement(
102848
103379
  closeResponse
102849
103380
  );
102850
103381
  const expectedCloseSize = Math.abs(currentPositionSize);
102851
103382
  const closeTolerance = Math.max(expectedCloseSize, 1) * Number.EPSILON * CLIENT_CLOSE_FILL_EPSILON_ULPS;
102852
103383
  const closeFillConfirmed = confirmedClose != null && Math.abs(confirmedClose.filledSize - expectedCloseSize) <= closeTolerance;
103384
+ const closeReport = {
103385
+ order_id: _extractOrderId(closeResponse),
103386
+ client_mutation_id: _extractClientMutationId(closeResponse),
103387
+ symbol: input.executionContext.symbol,
103388
+ action: classified.side.toUpperCase(),
103389
+ status: "executed",
103390
+ execution_metadata: _toExecutionMetadata(closeResponse)
103391
+ };
103392
+ const committedCloseReports = [...reconciliationReports, closeReport];
103393
+ progress.committedReports = committedCloseReports;
103394
+ const recordPostCloseReports = (reports) => {
103395
+ reconciliationReports.push(...reports);
103396
+ committedCloseReports.push(...reports);
103397
+ };
103398
+ progress.committedOrder = {
103399
+ intent: classified.intent,
103400
+ side: classified.side,
103401
+ reduceOnly: classified.reduceOnly,
103402
+ requestedUnits: classified.requestedUnits,
103403
+ targetSignedUnits: classified.targetSignedUnits,
103404
+ executedSizeAsset: confirmedClose?.filledSize ?? 0
103405
+ };
102853
103406
  if (closeFillConfirmed) {
102854
- reconciliationReports.push(...await cancelAllClientProtectiveGroups(
103407
+ recordPostCloseReports(await cancelAllClientProtectiveGroups(
102855
103408
  input,
102856
103409
  "position_closed"
102857
103410
  ));
@@ -102862,7 +103415,7 @@ var init_runtime_execution = __esm({
102862
103415
  []
102863
103416
  );
102864
103417
  } else if (hasTrackedProtection) {
102865
- reconciliationReports.push(...await reconcileClientProtectiveGroups(
103418
+ recordPostCloseReports(await reconcileClientProtectiveGroups(
102866
103419
  input,
102867
103420
  confirmedClose == null ? void 0 : signedRemainingExposureAfterConfirmedReduction(
102868
103421
  currentPositionSize,
@@ -102878,17 +103431,7 @@ var init_runtime_execution = __esm({
102878
103431
  requestedUnits: classified.requestedUnits,
102879
103432
  targetSignedUnits: classified.targetSignedUnits,
102880
103433
  executedSizeAsset: confirmedClose?.filledSize ?? 0,
102881
- executionReports: [
102882
- ...reconciliationReports,
102883
- {
102884
- order_id: _extractOrderId(closeResponse),
102885
- client_mutation_id: _extractClientMutationId(closeResponse),
102886
- symbol: input.executionContext.symbol,
102887
- action: classified.side.toUpperCase(),
102888
- status: "executed",
102889
- execution_metadata: _toExecutionMetadata(closeResponse)
102890
- }
102891
- ],
103434
+ executionReports: [...reconciliationReports, closeReport],
102892
103435
  message: closeFillConfirmed ? "Closed position" : "The close order did not confirm the full position size; retained trailing protection for any remaining exposure.",
102893
103436
  ...closeFillConfirmed ? {} : { reasonCode: "close_fill_unresolved" },
102894
103437
  executionSnapshotId,
@@ -102902,8 +103445,9 @@ var init_runtime_execution = __esm({
102902
103445
  if (targetResolution.closeOpposingPosition) {
102903
103446
  throwIfAborted2(input.signal);
102904
103447
  const flipCloseMutationId = await decisionLegMutationId("flip_close");
102905
- const closeResponse = await executeClientClosePosition({
102906
- mutationId: flipCloseMutationId,
103448
+ const closeResponse = await closeWithServerMetadataRetry("flip_close", flipCloseMutationId, (mutationId, estimatedPrice, assets) => executeClientClosePosition({
103449
+ mutationId,
103450
+ ...assets ? { assets } : {},
102907
103451
  profileId: input.profileId,
102908
103452
  runtimeSessionId: input.sessionId || "__missing_runtime_session__",
102909
103453
  runtimeLeaseToken: input.runtimeLeaseToken,
@@ -102913,12 +103457,12 @@ var init_runtime_execution = __esm({
102913
103457
  config: input.config ?? null,
102914
103458
  signal: input.signal,
102915
103459
  signingKey: input.signingKey,
102916
- onExchangeOrderDispatched: () => input.onExchangeOrderDispatched?.("action"),
103460
+ onExchangeOrderDispatched: () => input.onExchangeOrderDispatched?.("exit"),
102917
103461
  symbol: input.executionContext.symbol,
102918
103462
  position: currentPosition,
102919
- estimatedPrice: executionPrice,
103463
+ estimatedPrice,
102920
103464
  slippage: input.executionContext.maxSlippageFraction
102921
- });
103465
+ }));
102922
103466
  const confirmedFlipClose = extractCanonicalHyperliquidFilledOrderAcknowledgement(
102923
103467
  closeResponse
102924
103468
  );
@@ -103037,6 +103581,7 @@ var init_runtime_execution = __esm({
103037
103581
  isCross: input.executionContext.marginMode !== "isolated"
103038
103582
  });
103039
103583
  throwIfAborted2(input.signal);
103584
+ if (serverOrder) executionPrice = await readServerOrderMarkPrice(input);
103040
103585
  }
103041
103586
  const actualUnits = targetResolution.orderUnits;
103042
103587
  const intendedSizeAsset = decisionOrderSizeAsset({
@@ -103047,7 +103592,7 @@ var init_runtime_execution = __esm({
103047
103592
  entryPrice: currentPositionEntryPrice,
103048
103593
  livePositionSize: currentPositionSize
103049
103594
  });
103050
- const sizeAsset = Number.isFinite(intendedSizeAsset) && intendedSizeAsset > 0 ? quantizeHyperliquidOrderSizeValue(intendedSizeAsset, input.executionContext.sizeDecimals, "nearest") : 0;
103595
+ let sizeAsset = Number.isFinite(intendedSizeAsset) && intendedSizeAsset > 0 ? quantizeHyperliquidOrderSizeValue(intendedSizeAsset, input.executionContext.sizeDecimals, "nearest") : 0;
103051
103596
  appendRuntimeDebugEvent({
103052
103597
  label: "execution_size_computed",
103053
103598
  note: `symbol=${input.executionContext.symbol} actualUnits=${actualUnits} sizeAsset=${sizeAsset} price=${executionPrice}`
@@ -103055,7 +103600,7 @@ var init_runtime_execution = __esm({
103055
103600
  if (sizeAsset <= 0) {
103056
103601
  appendRuntimeDebugEvent({
103057
103602
  label: "execution_skipped_zero_size",
103058
- note: `reason=size_below_lot_precision actualUnits=${actualUnits} unitSize=${input.executionContext.unitSizeUsdc} intendedSize=${intendedSizeAsset} decimals=${input.executionContext.sizeDecimals}`,
103603
+ note: `reason=order_below_lot_size actualUnits=${actualUnits} unitSize=${input.executionContext.unitSizeUsdc} intendedSize=${intendedSizeAsset} decimals=${input.executionContext.sizeDecimals}`,
103059
103604
  outcome: "error"
103060
103605
  });
103061
103606
  return {
@@ -103067,13 +103612,27 @@ var init_runtime_execution = __esm({
103067
103612
  requestedUnits: classified.requestedUnits,
103068
103613
  targetSignedUnits: classified.targetSignedUnits,
103069
103614
  executedSizeAsset: 0,
103070
- executionReports,
103615
+ // Too small to place is not "already at target": it has its own reason,
103616
+ // on a Server bot's audit row and on a Client bot's record.
103617
+ executionReports: input.executionMode === "server" ? executionReports : [...executionReports, unsentDecisionOrderReport(input, "order_below_lot_size", { intent: classified.intent })],
103071
103618
  message: "Skipped: calculated size is zero",
103072
- reasonCode: "noop_already_at_target",
103619
+ reasonCode: "order_below_lot_size",
103073
103620
  executionSnapshotId,
103074
103621
  executionSnapshotCapturedAt
103075
103622
  };
103076
103623
  }
103624
+ if (input.executionMode === "server") {
103625
+ const ceilingRefusal = orderCeilingRefusal({
103626
+ side: classified.side,
103627
+ size: sizeAsset,
103628
+ price: executionPrice,
103629
+ // A flip's close has filled by now: its new position starts from flat.
103630
+ currentPositionSize: targetResolution.closeOpposingPosition ? 0 : currentPositionSize,
103631
+ maxOrderNotional: runtime_policy_generated_default2.trading.risk.max_order_notional,
103632
+ maxPositionNotional: runtime_policy_generated_default2.trading.risk.max_position_notional
103633
+ });
103634
+ if (ceilingRefusal !== null) throw new Error(`Order rejected by risk manager: ${ceilingRefusal}`);
103635
+ }
103077
103636
  const entryRequiresFlatAbsenceProof = Number.isFinite(currentPositionSize) && currentPositionSize === 0 || targetResolution.closeOpposingPosition;
103078
103637
  if (entryRequiresFlatAbsenceProof) {
103079
103638
  const finalProtectionObservation = await verifyNoLiveClientProtectiveTriggers(
@@ -103201,53 +103760,70 @@ var init_runtime_execution = __esm({
103201
103760
  let marketOrderResponse;
103202
103761
  let entryDispatchBoundaryPassed = false;
103203
103762
  let settledServerProtectedEntry = null;
103204
- try {
103205
- marketOrderResponse = await executeClientMarketOrder({
103206
- profileId: input.profileId,
103207
- runtimeSessionId: input.sessionId || "__missing_runtime_session__",
103208
- runtimeLeaseToken: input.runtimeLeaseToken,
103209
- runtimeDeviceId: input.runtimeDeviceId,
103210
- schedulerInstanceId: input.schedulerInstanceId,
103211
- walletAddress: input.executionContext.walletAddress,
103212
- config: input.config ?? null,
103213
- signal: input.signal,
103214
- signingKey: input.signingKey,
103215
- onExchangeOrderDispatched: () => {
103216
- if (persistedProtectiveGroupSet != null && pendingProtectiveCleanup != null && !replaceExactClientProtectiveGroupSet(
103217
- pendingProtectiveCleanup.profileId,
103218
- pendingProtectiveCleanup.symbol,
103219
- persistedProtectiveGroupSet,
103220
- persistedProtectiveGroupSet
103221
- )) {
103222
- throw createClientRuntimeWindowHandoffBeforePlanDispatchError(
103223
- pendingProtectiveCleanup
103224
- );
103225
- }
103226
- input.onExchangeOrderDispatched?.(
103227
- classified.intent === "open" || classified.intent === "add" || classified.intent === "flip" ? "entry" : "action"
103763
+ const entrySide = classified.side;
103764
+ let entryAssets;
103765
+ const sendEntry = () => executeClientMarketOrder({
103766
+ ...entryAssets ? { assets: entryAssets } : {},
103767
+ profileId: input.profileId,
103768
+ runtimeSessionId: input.sessionId || "__missing_runtime_session__",
103769
+ runtimeLeaseToken: input.runtimeLeaseToken,
103770
+ runtimeDeviceId: input.runtimeDeviceId,
103771
+ schedulerInstanceId: input.schedulerInstanceId,
103772
+ walletAddress: input.executionContext.walletAddress,
103773
+ config: input.config ?? null,
103774
+ signal: input.signal,
103775
+ signingKey: input.signingKey,
103776
+ onExchangeOrderDispatched: () => {
103777
+ if (persistedProtectiveGroupSet != null && pendingProtectiveCleanup != null && !replaceExactClientProtectiveGroupSet(
103778
+ pendingProtectiveCleanup.profileId,
103779
+ pendingProtectiveCleanup.symbol,
103780
+ persistedProtectiveGroupSet,
103781
+ persistedProtectiveGroupSet
103782
+ )) {
103783
+ throw createClientRuntimeWindowHandoffBeforePlanDispatchError(
103784
+ pendingProtectiveCleanup
103228
103785
  );
103229
- entryDispatchBoundaryPassed = true;
103786
+ }
103787
+ input.onExchangeOrderDispatched?.(
103788
+ classified.intent === "open" || classified.intent === "add" || classified.intent === "flip" ? "entry" : "exit"
103789
+ );
103790
+ entryDispatchBoundaryPassed = true;
103791
+ },
103792
+ symbol: input.executionContext.symbol,
103793
+ side: entrySide,
103794
+ size: sizeAsset,
103795
+ estimatedPrice: executionPrice,
103796
+ slippage: input.executionContext.maxSlippageFraction,
103797
+ reduceOnly: classified.reduceOnly,
103798
+ mutationId: entryMutationId,
103799
+ clientOrderId: entryClientOrderId,
103800
+ ...serverOwnedProtection ? {
103801
+ // The server attaches the configured Auto SL/TP to this entry.
103802
+ protection: {
103803
+ source: "runtime_config",
103804
+ requested_entry_size: sizeAsset,
103805
+ is_long: entrySide === "buy"
103230
103806
  },
103231
- symbol: input.executionContext.symbol,
103232
- side: classified.side,
103233
- size: sizeAsset,
103234
- estimatedPrice: executionPrice,
103235
- slippage: input.executionContext.maxSlippageFraction,
103236
- reduceOnly: classified.reduceOnly,
103237
- mutationId: entryMutationId,
103238
- clientOrderId: entryClientOrderId,
103239
- ...serverOwnedProtection ? {
103240
- // The server attaches the configured Auto SL/TP to this entry.
103241
- protection: {
103242
- source: "runtime_config",
103243
- requested_entry_size: sizeAsset,
103244
- is_long: classified.side === "buy"
103245
- },
103246
- onSettled: (mutation) => {
103247
- settledServerProtectedEntry = mutation;
103248
- }
103249
- } : {}
103250
- });
103807
+ onSettled: (mutation) => {
103808
+ settledServerProtectedEntry = mutation;
103809
+ }
103810
+ } : {}
103811
+ });
103812
+ try {
103813
+ try {
103814
+ marketOrderResponse = await sendEntry();
103815
+ } catch (rejection) {
103816
+ const retry = await serverOrderMetadataRetry(input, rejection, "entry", entryMutationId);
103817
+ const retrySize = retry === null ? 0 : quantizeHyperliquidOrderSizeValue(intendedSizeAsset, retry.sizeDecimals, "nearest");
103818
+ if (retry === null || !(retrySize > 0)) throw rejection;
103819
+ sizeAsset = retrySize;
103820
+ entryAssets = retry.assets;
103821
+ executionPrice = retry.markPrice ?? executionPrice;
103822
+ entryMutationId = retry.mutationId;
103823
+ entryClientOrderId = clientOrderIdForMutation(retry.mutationId);
103824
+ entryDispatchBoundaryPassed = false;
103825
+ marketOrderResponse = await sendEntry();
103826
+ }
103251
103827
  } catch (entryDispatchError) {
103252
103828
  const handoffVeto = isClientRuntimeWindowHandoffBeforePlanDispatch(entryDispatchError);
103253
103829
  const handoffBeforeDispatch = handoffVeto || !entryDispatchBoundaryPassed && input.shouldCancelBeforeExchangeOrderDispatch?.() === true;
@@ -103306,6 +103882,15 @@ var init_runtime_execution = __esm({
103306
103882
  status: "executed",
103307
103883
  execution_metadata: classified.intent === "flip" ? { ..._toExecutionMetadata(marketOrderResponse), decision_leg: "entry" } : { ..._toExecutionMetadata(marketOrderResponse), entry_began_flat: livePositionDirection === 0 }
103308
103884
  });
103885
+ progress.committedReports = executionReports;
103886
+ progress.committedOrder = {
103887
+ intent: classified.intent,
103888
+ side: classified.side,
103889
+ reduceOnly: classified.reduceOnly,
103890
+ requestedUnits: classified.requestedUnits,
103891
+ targetSignedUnits: classified.targetSignedUnits,
103892
+ executedSizeAsset: confirmedMarketFill == null ? 0 : confirmedMarketFill.filledSize
103893
+ };
103309
103894
  const appendPostEntryProtectionFailure = (error48) => {
103310
103895
  const projection = projectExecutionErrorContract({
103311
103896
  error: error48,
@@ -103471,10 +104056,11 @@ var init_runtime_execution = __esm({
103471
104056
  const kind = triggerInput.isTakeProfit ? "tp" : "sl";
103472
104057
  const alreadyProtected = (liveDirectionMatches ? (await storedClientProtectiveCover(
103473
104058
  input,
104059
+ isLong,
103474
104060
  readClientProtectiveGroups(
103475
104061
  String(input.profileId).trim(),
103476
104062
  input.executionContext.symbol
103477
- ).flatMap((group) => group.legs)
104063
+ )
103478
104064
  ))[kind] : 0) + activeLegs.filter((leg2) => leg2.kind === kind).reduce((total, leg2) => total + leg2.size, 0);
103479
104065
  const liveExposure = Math.abs(livePositionSize);
103480
104066
  const availableExposure = Math.max(0, liveExposure - alreadyProtected);
@@ -103869,7 +104455,6 @@ var init_runtime_execution = __esm({
103869
104455
  size: destinationSize,
103870
104456
  roundingMode: "nearest",
103871
104457
  includePrivateContext: desiredPosition != null && Number.isFinite(desiredPosition),
103872
- profileId: input.profileId,
103873
104458
  // The device reads its own position and mark; the server never reads
103874
104459
  // a Client wallet.
103875
104460
  walletAddress: input.walletAddress,
@@ -104643,6 +105228,7 @@ var init_provider_observability = __esm({
104643
105228
  }
104644
105229
  if (typeof raw.credential_ref === "string" && /^[a-f0-9]{64}$/.test(raw.credential_ref)) result.credential_ref = raw.credential_ref;
104645
105230
  if (raw.execution_mode === "client" || raw.execution_mode === "server") result.execution_mode = raw.execution_mode;
105231
+ if (raw.timeout_bound === "attempt_cap") result.timeout_bound = "attempt_cap";
104646
105232
  if (typeof raw.quota_project_ref === "string" && /^[a-f0-9]{64}$/.test(raw.quota_project_ref) && raw.quota_project_source === "provider_quota_subject") {
104647
105233
  result.quota_project_ref = raw.quota_project_ref;
104648
105234
  result.quota_project_source = "provider_quota_subject";
@@ -107468,7 +108054,7 @@ var init_client_runtime_status_store = __esm({
107468
108054
  });
107469
108055
 
107470
108056
  // lib/runtime/perp-dex-scope.ts
107471
- var perpDexScopeForSymbols, equityVenuesForSymbols, profileEquityVenues, positionsOnVenues;
108057
+ var perpDexScopeForSymbols, equityVenuesForSymbols, profileEquityVenues, profileExchanges, positionsOnVenues;
107472
108058
  var init_perp_dex_scope = __esm({
107473
108059
  "lib/runtime/perp-dex-scope.ts"() {
107474
108060
  "use strict";
@@ -107497,6 +108083,14 @@ var init_perp_dex_scope = __esm({
107497
108083
  profileEquityVenues = (tradingSymbols, defaultTradingSymbols) => equityVenuesForSymbols(
107498
108084
  Array.isArray(tradingSymbols) && tradingSymbols.length > 0 ? tradingSymbols : defaultTradingSymbols ?? []
107499
108085
  );
108086
+ profileExchanges = (exchanges, tradingSymbols, defaultTradingSymbols, configuredDexes) => {
108087
+ if (Array.isArray(exchanges) && exchanges.length > 0) {
108088
+ const configured2 = /* @__PURE__ */ new Set(["", ...(configuredDexes ?? []).map((dex) => String(dex).trim().toLowerCase())]);
108089
+ const names2 = exchanges.map((exchange) => typeof exchange === "string" ? exchange.trim().toLowerCase() : null);
108090
+ if (names2.every((name) => name !== null && configured2.has(name))) return [...new Set(names2)].sort();
108091
+ }
108092
+ return profileEquityVenues(tradingSymbols, defaultTradingSymbols);
108093
+ };
107500
108094
  positionsOnVenues = (positions, venues) => venues ? positions.filter((position) => normalizeHyperliquidMarketSymbol(position.symbol) && venues.includes(getHyperliquidMarketDex(position.symbol))) : [...positions];
107501
108095
  }
107502
108096
  });
@@ -107567,6 +108161,12 @@ var init_client_killswitch = __esm({
107567
108161
  const symbol2 = firstConfiguredSymbol(settings, input.config);
107568
108162
  const leverage = toPositiveFinite2(settings.leverage) ?? 1;
107569
108163
  const equityVenues = profileEquityVenues(settings.trading_symbols, input.config.default_trading_symbols);
108164
+ const closeVenues = profileExchanges(
108165
+ settings.exchanges,
108166
+ settings.trading_symbols,
108167
+ input.config.default_trading_symbols,
108168
+ input.config.client_runtime_hyperliquid_perp_dexs?.allowed_dexes
108169
+ );
107570
108170
  const accountState = await fetchBrowserAccountState2({
107571
108171
  publicRequestPriority: "trading_reduce",
107572
108172
  config: input.config,
@@ -107609,7 +108209,8 @@ var init_client_killswitch = __esm({
107609
108209
  accountState,
107610
108210
  walletAddress,
107611
108211
  symbol: symbol2,
107612
- equityVenues
108212
+ equityVenues,
108213
+ closeVenues
107613
108214
  };
107614
108215
  }
107615
108216
  if (!context.snapshot_trusted || context.status === "untrusted") {
@@ -107621,7 +108222,8 @@ var init_client_killswitch = __esm({
107621
108222
  accountState,
107622
108223
  walletAddress,
107623
108224
  symbol: symbol2,
107624
- equityVenues
108225
+ equityVenues,
108226
+ closeVenues
107625
108227
  };
107626
108228
  }
107627
108229
  const peakEquity = toPositiveFinite2(context.peak_equity);
@@ -107634,7 +108236,8 @@ var init_client_killswitch = __esm({
107634
108236
  accountState,
107635
108237
  walletAddress,
107636
108238
  symbol: symbol2,
107637
- equityVenues
108239
+ equityVenues,
108240
+ closeVenues
107638
108241
  };
107639
108242
  }
107640
108243
  const drawdownPercent = calculateClientKillswitchDrawdownPercent(
@@ -107650,7 +108253,8 @@ var init_client_killswitch = __esm({
107650
108253
  accountState,
107651
108254
  walletAddress,
107652
108255
  symbol: symbol2,
107653
- equityVenues
108256
+ equityVenues,
108257
+ closeVenues
107654
108258
  };
107655
108259
  };
107656
108260
  closeClientKillswitchPositions = async (input) => {
@@ -108136,6 +108740,7 @@ var init_ai_settings_helpers = __esm({
108136
108740
  init_define_VTX_EXO_POLICY();
108137
108741
  init_define_VTX_GROK_POLICY();
108138
108742
  init_define_VTX_PI_MODEL_POLICY();
108743
+ init_perp_dex_scope();
108139
108744
  sortAiSettings = (settings) => {
108140
108745
  if (!settings || typeof settings !== "object") return settings;
108141
108746
  const normalized = { ...settings };
@@ -109446,8 +110051,14 @@ var init_native_provider_budget = __esm({
109446
110051
  init_define_VTX_GROK_POLICY();
109447
110052
  init_define_VTX_PI_MODEL_POLICY();
109448
110053
  NativeModelTimeoutError = class extends Error {
109449
- constructor() {
110054
+ /**
110055
+ * attemptCapExpired: one Google egress attempt ran out its per-attempt cap
110056
+ * while the model's own budget had time left, which the Server loop reads
110057
+ * as an unreachable route (google_runtime_transport), not as a timeout.
110058
+ */
110059
+ constructor(attemptCapExpired = false) {
109450
110060
  super("Native model request timed out.");
110061
+ this.attemptCapExpired = attemptCapExpired;
109451
110062
  this.runtimeNativeFailureKind = "timeout";
109452
110063
  this.name = "NativeModelTimeoutError";
109453
110064
  }
@@ -109819,7 +110430,10 @@ var init_provider_client = __esm({
109819
110430
  }
109820
110431
  sanitizedError.runtimeProviderStatusCode = response?.status ?? null;
109821
110432
  sanitizedError.runtimeProviderRequestId = providerRequestId(response);
109822
- sanitizedError.runtimeProviderDiagnostics = marker?.providerDiagnostics ?? {};
110433
+ sanitizedError.runtimeProviderDiagnostics = {
110434
+ ...marker?.providerDiagnostics ?? {},
110435
+ ...error48 instanceof NativeModelTimeoutError && error48.attemptCapExpired ? { timeout_bound: "attempt_cap" } : {}
110436
+ };
109823
110437
  if (marker?.googleQuotaFailure) sanitizedError.runtimeGoogleQuotaFailure = true;
109824
110438
  sanitizedError.runtimeRequestInputTokens = marker?.requestInputTokens ?? null;
109825
110439
  if (marker) {
@@ -112095,7 +112709,8 @@ var init_provider_client = __esm({
112095
112709
  if (egress && (timeoutMs <= 0 || !googleEgressHasBudget(egress))) throw new NativeModelTimeoutError();
112096
112710
  signal?.addEventListener("abort", cancelAttempt, { once: true });
112097
112711
  if (signal?.aborted) cancelAttempt();
112098
- const attemptTimer = attemptController ? setTimeout(() => attemptController.abort(new NativeModelTimeoutError()), timeoutMs) : void 0;
112712
+ const capBound = Boolean(egress && egress.policy.attempt_timeout_seconds * MS_PER_SECOND < egress.deadline - Date.now());
112713
+ const attemptTimer = attemptController ? setTimeout(() => attemptController.abort(new NativeModelTimeoutError(capBound)), timeoutMs) : void 0;
112099
112714
  try {
112100
112715
  response = await callGoogle(
112101
112716
  remoteApiKey,
@@ -113940,6 +114555,7 @@ __export(local_analysis_exports, {
113940
114555
  ClientRuntimeAgentInstructionEmpty: () => ClientRuntimeAgentInstructionEmpty,
113941
114556
  ClientRuntimeAiSchedulePaused: () => ClientRuntimeAiSchedulePaused,
113942
114557
  ClientRuntimeAiScheduleStillActive: () => ClientRuntimeAiScheduleStillActive,
114558
+ SERVER_UNREADABLE_REPLY_HOLD_REASONING: () => SERVER_UNREADABLE_REPLY_HOLD_REASONING,
113943
114559
  ServerDispatchAccountStateStale: () => ServerDispatchAccountStateStale,
113944
114560
  aiOrderSlippageFraction: () => aiOrderSlippageFraction,
113945
114561
  buildLocalRuntimePromptArtifacts: () => buildLocalRuntimePromptArtifacts,
@@ -113960,7 +114576,7 @@ __export(local_analysis_exports, {
113960
114576
  runLocalRuntimeCycle: () => runLocalRuntimeCycle,
113961
114577
  summarizeReviewFailureExplanation: () => summarizeReviewFailureExplanation
113962
114578
  });
113963
- var CYCLE_TIMEOUT_FLOOR_MS, DECISION_SETTLEMENT_RESERVE_MAX_BUDGET_DIVISOR, MIN_AGENT_INSTRUCTION_RETRY_AFTER_MS, PROMPT_PARITY_ERROR_DETAIL_MAX_CHARS, EXTERNAL_INFERENCE_RUNTIME_POLL_INTERVAL_MS, REVIEW_PROVIDER_SERVER_ERROR_STATUSES, TRUNCATION_ELLIPSIS2, normalizeNativeValues, assertPromptModelController, resolveRuntimeReasoningControlsForModel, modelScopedKey, resolveNativeValuesForModel, observeRuntimeCycle, observeAccountState, aiOrderSlippageFraction, serverBehaviorStateArtifacts, ClientRuntimeAgentInstructionEmpty, isClientRuntimeAgentInstructionEmpty, ClientRuntimeAiSchedulePaused, ClientRuntimeAiScheduleStillActive, isClientRuntimeAiScheduleStillActive, ServerDispatchAccountStateStale, isServerDispatchAccountStateStale, isClientRuntimeAiSchedulePaused, acceptancePositionCaps, accountSnapshotCapturedAt, buildClaimedAgentRuntimeCycleResult, resolveRuntimeMarginModePreference, resolveRuntimeLeveragePreference, resolveBooleanSetting2, CLIENT_RUNTIME_LIVE_CONTEXT_UNAVAILABLE_ERRORS, BEHAVIOR_STATE_UNAVAILABLE_ERROR, CriticalBehaviorStateError, clampNumber, resolveExternalInferenceRuntimeTimeoutSeconds, toPositiveFinite3, compactSnippet, hashRuntimeDebugText, EFFECTIVE_INPUT_MANIFEST_SCHEMA_VERSION, PROMPT_ASSEMBLY_DEFINITION_VERSION, RUNTIME_SOURCE_DEFINITION_VERSION, DECISION_INPUT_DEFINITION_VERSION, CONTEXT_ENVELOPE_DEFINITION_VERSION, CLIENT_RUNTIME_SOURCE_VERSION, CLIENT_MAIN_PROMPT_RENDERER, SERVER_MAIN_PROMPT_RENDERER, CLIENT_REVIEW_PROMPT_RENDERER, SERVER_REVIEW_PROMPT_RENDERER, resolveEffectivePromptRuntimeProvenance, canonicalManifestValue, canonicalManifestJson, sha256ManifestHex, effectiveInputComponent, buildEffectiveInputManifest, derivePromptVisibleSections, decodeDecisionTracePayload, extractDecisionSymbolTrace, formatDecisionSymbolTrace, formatActionableDecisionSymbols, decisionRecordsBySymbol, normalizePromptSymbols, JSON_MODEL_OUTPUT_FENCE_PATTERN, STRICT_MODEL_OUTPUT_KEYS, currentModelOutputValidationErrors, currentModelOutputMatchesContract, projectCurrentModelDecisionContent, modelOutputValidationError, buildMissingDecisionHold, buildDecisionPlansFromResponse, buildReviewCandidatePlansFromResponse, forceUnavailableSymbolsToHold, extractTemplatePlaceholders, requireReviewPrimaryUserPromptTemplate, containsCompetingBehaviorStateMarkup, containsCompetingMainBehaviorStateMarkup, requireStrategyReviewTemplates, preflightStrategyReviewPromptContract, extractRuntimeReasoningSelection, isAbortError, isRuntimeTimeoutAbortReason, REVIEW_FAILURE_SENSITIVE_DB_TOKENS, REVIEW_FAILURE_SCHEMA_DISCLOSURE_TOKENS, REVIEW_FAILURE_SQL_STATEMENT_PATTERN, REVIEW_FAILURE_TRACEBACK_PATTERN, isSensitiveReviewFailureDetail, summarizeReviewFailureExplanation, buildReviewFailureHoldReason, createAbortError2, settleRuntimeCyclePromise, unwrapRuntimeCycleSettledResult, normalizeDecisionLabel, normalizeRuntimeSymbol, PromptContractFetchError, isLivePromptContextUnavailableError, buildFailClosedHoldResult, buildPromptConstructionFailureResult, buildLivePromptContextUnavailableFailureResult, pickFirstString, normalizeRuntimeStringList, requirePositiveRuntimeLimit, resolveRuntimeTradingScope, normalizeRuntimeProviderAlias, resolveCatalogModelEntry, createClientRuntimeProviderSetupError, createProviderSetupRejectionError, evaluateModelEligibility, extractReviewRuntimeReasoningSelection, isUsableRuntimeSettingsFallback, resolveRuntimeSettings, formatRuntimeDurationMs, normalizeRuntimeTimingNote, appendRuntimeTimingEvent, reportPromptParityTelemetry, resolveLocalRuntimeSecretRequirements, resolveLocalRuntimeSecretProvider, toEpochSeconds, REQUIRED_AI_INDICATOR_KEYS, sortTradingTimeframes, normalizePromptIdentityTimestamp, resolveCompletedCandleBoundary, normalizeAiIndicatorFlags, getPromptLookback, computeSma, computeEma, computeRsi, computeAtr, computeMacd, computeBollingerBands, getIndicatorValue, buildPromptCandlesComponent, CANDLE_CLOSE_TICKER_TIMEFRAME, candleCloseTicker, buildPromptCandlesPayload, formatUtcTimestampWithWeekday, formatUtcNowWithWeekday, formatPromptPrice, capacityUnitSize, computePromptUnitsUsedForPosition, buildPromptAccountStatusValue, buildPromptPositionsValue, sanitizePromptSymbol, fillTimeMs, fillSize, normalizeFillSide, normalizeFillOrderId, normalizeFillRiskOrderIdentity, fillStartPosition, fillSortValue, sortFillsAscending, sortFillsDescending, inferEntryFromStartPositionChain, inferEntryFromCurrentPositionSize, calculateCurrentPositionState, calculatePositionEntryTimes, countPositionAdds, latestPositionRiskIncreaseTimeMs, latestPositionRiskIncreaseEvidence, compactPromptRiskIncrease, roundPositiveDecimalHalfUp, compactPromptLastTrade, ENTRY_TRADE_FIELDS, PREVIOUS_DECISION_FIELDS, PREVIOUS_CAMPAIGN_FIELDS, hasExactKeys2, isNonnegativeInteger, isFiniteNumber, isExactEnumString, isNonemptyPromptText, isCampaignReasoningText, projectBackendDecisionMemoryItem, requireRenderedStrategyBehaviorState, canonicalFillSideForRiskEvidence, isValidRiskEvidenceFill, isValidCampaignBoundaryFill, normalizeFillHistoryCoverage, resolveFillHistoryCoverageForSymbol, buildPromptBehaviorStateArtifacts, buildPromptBehaviorStateValue, shouldCompareServerPromptParity, buildLocalRuntimePromptArtifacts, createRuntimeId2, asRecord, buildRuntimeConstraintRejectionMessage, hasDeviceProviderSecret, requireNonEmptyStringField, requirePositiveIntegerField, compareContractVersion, parsePromptContractTimestamp, assertPromptContractCompatibility, assertPromptContractTemporalBounds, sleepWithAbort, requireAgentPollRetryAfterMs, materializeClaimedClientRuntimeAgentInstruction, attachClientRuntimeErrorProvenance, isExternalRuntimeProviderResult, invokeClientExternalInference, assertPromptContractBindingTupleEqual, assertPromptContractScopeMatch, fetchBoundPromptContracts, formatTemplateWithNamedVariables, carryReturnedModelCalls, runLocalRuntimeCycle;
114579
+ var CYCLE_TIMEOUT_FLOOR_MS, DECISION_SETTLEMENT_RESERVE_MAX_BUDGET_DIVISOR, MIN_AGENT_INSTRUCTION_RETRY_AFTER_MS, PROMPT_PARITY_ERROR_DETAIL_MAX_CHARS, EXTERNAL_INFERENCE_RUNTIME_POLL_INTERVAL_MS, REVIEW_PROVIDER_SERVER_ERROR_STATUSES, TRUNCATION_ELLIPSIS2, normalizeNativeValues, assertPromptModelController, resolveRuntimeReasoningControlsForModel, modelScopedKey, resolveNativeValuesForModel, observeRuntimeCycle, observeAccountState, aiOrderSlippageFraction, serverBehaviorStateArtifacts, ClientRuntimeAgentInstructionEmpty, isClientRuntimeAgentInstructionEmpty, ClientRuntimeAiSchedulePaused, ClientRuntimeAiScheduleStillActive, isClientRuntimeAiScheduleStillActive, ServerDispatchAccountStateStale, isServerDispatchAccountStateStale, isClientRuntimeAiSchedulePaused, acceptancePositionCaps, accountSnapshotCapturedAt, buildClaimedAgentRuntimeCycleResult, resolveRuntimeMarginModePreference, resolveRuntimeLeveragePreference, resolveBooleanSetting2, CLIENT_RUNTIME_LIVE_CONTEXT_UNAVAILABLE_ERRORS, BEHAVIOR_STATE_UNAVAILABLE_ERROR, CriticalBehaviorStateError, clampNumber, resolveExternalInferenceRuntimeTimeoutSeconds, toPositiveFinite3, compactSnippet, hashRuntimeDebugText, EFFECTIVE_INPUT_MANIFEST_SCHEMA_VERSION, PROMPT_ASSEMBLY_DEFINITION_VERSION, RUNTIME_SOURCE_DEFINITION_VERSION, DECISION_INPUT_DEFINITION_VERSION, CONTEXT_ENVELOPE_DEFINITION_VERSION, CLIENT_RUNTIME_SOURCE_VERSION, CLIENT_MAIN_PROMPT_RENDERER, SERVER_MAIN_PROMPT_RENDERER, CLIENT_REVIEW_PROMPT_RENDERER, SERVER_REVIEW_PROMPT_RENDERER, resolveEffectivePromptRuntimeProvenance, canonicalManifestValue, canonicalManifestJson, sha256ManifestHex, effectiveInputComponent, buildEffectiveInputManifest, derivePromptVisibleSections, decodeDecisionTracePayload, extractDecisionSymbolTrace, formatDecisionSymbolTrace, formatActionableDecisionSymbols, decisionRecordsBySymbol, normalizePromptSymbols, JSON_MODEL_OUTPUT_FENCE_PATTERN, STRICT_MODEL_OUTPUT_KEYS, currentModelOutputValidationErrors, currentModelOutputMatchesContract, projectCurrentModelDecisionContent, modelOutputValidationError, SERVER_UNREADABLE_REPLY_HOLD_REASONING, buildMissingDecisionHold, buildDecisionPlansFromResponse, buildReviewCandidatePlansFromResponse, forceUnavailableSymbolsToHold, extractTemplatePlaceholders, requireReviewPrimaryUserPromptTemplate, containsCompetingBehaviorStateMarkup, containsCompetingMainBehaviorStateMarkup, requireStrategyReviewTemplates, preflightStrategyReviewPromptContract, extractRuntimeReasoningSelection, isAbortError, isRuntimeTimeoutAbortReason, REVIEW_FAILURE_SENSITIVE_DB_TOKENS, REVIEW_FAILURE_SCHEMA_DISCLOSURE_TOKENS, REVIEW_FAILURE_SQL_STATEMENT_PATTERN, REVIEW_FAILURE_TRACEBACK_PATTERN, isSensitiveReviewFailureDetail, summarizeReviewFailureExplanation, buildReviewFailureHoldReason, createAbortError2, settleRuntimeCyclePromise, unwrapRuntimeCycleSettledResult, normalizeDecisionLabel, normalizeRuntimeSymbol, PromptContractFetchError, isLivePromptContextUnavailableError, buildFailClosedHoldResult, buildPromptConstructionFailureResult, buildLivePromptContextUnavailableFailureResult, pickFirstString, normalizeRuntimeStringList, requirePositiveRuntimeLimit, resolveRuntimeTradingScope, normalizeRuntimeProviderAlias, resolveCatalogModelEntry, createClientRuntimeProviderSetupError, createProviderSetupRejectionError, evaluateModelEligibility, extractReviewRuntimeReasoningSelection, isUsableRuntimeSettingsFallback, resolveRuntimeSettings, formatRuntimeDurationMs, normalizeRuntimeTimingNote, appendRuntimeTimingEvent, reportPromptParityTelemetry, resolveLocalRuntimeSecretRequirements, resolveLocalRuntimeSecretProvider, toEpochSeconds, REQUIRED_AI_INDICATOR_KEYS, sortTradingTimeframes, normalizePromptIdentityTimestamp, resolveCompletedCandleBoundary, normalizeAiIndicatorFlags, getPromptLookback, computeSma, computeEma, computeRsi, computeAtr, computeMacd, computeBollingerBands, getIndicatorValue, buildPromptCandlesComponent, CANDLE_CLOSE_TICKER_TIMEFRAME, candleCloseTicker, buildPromptCandlesPayload, formatUtcTimestampWithWeekday, formatUtcNowWithWeekday, formatPromptPrice, capacityUnitSize, computePromptUnitsUsedForPosition, buildPromptAccountStatusValue, buildPromptPositionsValue, sanitizePromptSymbol, fillTimeMs, fillSize, normalizeFillSide, normalizeFillOrderId, normalizeFillRiskOrderIdentity, fillStartPosition, fillSortValue, sortFillsAscending, sortFillsDescending, inferEntryFromStartPositionChain, inferEntryFromCurrentPositionSize, calculateCurrentPositionState, calculatePositionEntryTimes, countPositionAdds, latestPositionRiskIncreaseTimeMs, latestPositionRiskIncreaseEvidence, compactPromptRiskIncrease, roundPositiveDecimalHalfUp, compactPromptLastTrade, ENTRY_TRADE_FIELDS, PREVIOUS_DECISION_FIELDS, PREVIOUS_CAMPAIGN_FIELDS, hasExactKeys2, isNonnegativeInteger, isFiniteNumber, isExactEnumString, isNonemptyPromptText, isCampaignReasoningText, projectBackendDecisionMemoryItem, requireRenderedStrategyBehaviorState, canonicalFillSideForRiskEvidence, isValidRiskEvidenceFill, isValidCampaignBoundaryFill, normalizeFillHistoryCoverage, resolveFillHistoryCoverageForSymbol, buildPromptBehaviorStateArtifacts, buildPromptBehaviorStateValue, shouldCompareServerPromptParity, buildLocalRuntimePromptArtifacts, createRuntimeId2, asRecord, buildRuntimeConstraintRejectionMessage, hasDeviceProviderSecret, requireNonEmptyStringField, requirePositiveIntegerField, compareContractVersion, parsePromptContractTimestamp, assertPromptContractCompatibility, assertPromptContractTemporalBounds, sleepWithAbort, requireAgentPollRetryAfterMs, materializeClaimedClientRuntimeAgentInstruction, attachClientRuntimeErrorProvenance, isExternalRuntimeProviderResult, invokeClientExternalInference, assertPromptContractBindingTupleEqual, assertPromptContractScopeMatch, fetchBoundPromptContracts, formatTemplateWithNamedVariables, carryReturnedModelCalls, runLocalRuntimeCycle;
113964
114580
  var init_local_analysis = __esm({
113965
114581
  "lib/runtime/local-analysis.ts"() {
113966
114582
  "use strict";
@@ -114178,6 +114794,8 @@ var init_local_analysis = __esm({
114178
114794
  perpDexScope: perpDexScopeForSymbols(symbols),
114179
114795
  feeSymbols: symbols,
114180
114796
  includeEffectiveTakerRate: true,
114797
+ // A Server bot's account is valued as the Python Server loop valued it.
114798
+ serverLoopAccountValue: runtimeInput.executionMode === "server",
114181
114799
  sessionId: String(runtimeInput.sessionId || "").trim(),
114182
114800
  signal
114183
114801
  });
@@ -114352,7 +114970,8 @@ var init_local_analysis = __esm({
114352
114970
  decision: "HOLD",
114353
114971
  units: 0,
114354
114972
  reasoning: `Skipped by client runtime constraints: ${accepted.reason_code}`,
114355
- executionContext
114973
+ executionContext,
114974
+ ...entry.decision === "BUY" || entry.decision === "SELL" ? { unsentOrder: { decision: entry.decision, units: entry.units, constraintReasonCode: accepted.reason_code } } : {}
114356
114975
  };
114357
114976
  }
114358
114977
  throw new Error(buildRuntimeConstraintRejectionMessage({
@@ -114925,6 +115544,7 @@ var init_local_analysis = __esm({
114925
115544
  }
114926
115545
  );
114927
115546
  };
115547
+ SERVER_UNREADABLE_REPLY_HOLD_REASONING = "Configured symbol was omitted from the model response. Defaulted to HOLD.";
114928
115548
  buildMissingDecisionHold = (symbol2, reasoning = `No valid model decision was returned for configured symbol ${symbol2}.`) => ({
114929
115549
  symbol: symbol2,
114930
115550
  decision: "HOLD",
@@ -117492,7 +118112,7 @@ ${behaviorJson}
117492
118112
  );
117493
118113
  }
117494
118114
  };
117495
- fetchBoundPromptContracts = async (profileId, payload, signal, walletAddress, getEquity, getTotalUnrealizedPnl, getAccountStateResolvedAtMs, getUserFills, waitForLiveAccountState, initialMetadata, getPositions, getPerpDexAccounts) => {
118115
+ fetchBoundPromptContracts = async (profileId, payload, signal, walletAddress, getEquity, getTotalUnrealizedPnl, getAccountStateResolvedAtMs, getUserFills, waitForLiveAccountState, initialMetadata, getPositions, getPerpDexAccounts, runsWithoutEquity = false) => {
117496
118116
  let attempt = 0;
117497
118117
  while (true) {
117498
118118
  if (waitForLiveAccountState) {
@@ -117542,7 +118162,7 @@ ${behaviorJson}
117542
118162
  const liveEquity = Number.isFinite(Number(liveEquityRaw)) ? Number(liveEquityRaw) : 0;
117543
118163
  const liveUnrealizedPnlRaw = getTotalUnrealizedPnl ? getTotalUnrealizedPnl() : null;
117544
118164
  const liveUnrealizedPnl = liveUnrealizedPnlRaw !== null && liveUnrealizedPnlRaw !== void 0 && Number.isFinite(Number(liveUnrealizedPnlRaw)) ? Number(liveUnrealizedPnlRaw) : null;
117545
- const parityIncluded = liveEquity > 0;
118165
+ const parityIncluded = liveEquity > 0 || runsWithoutEquity;
117546
118166
  const parityPreparedAtMs = Date.now();
117547
118167
  const accountStateResolvedAtMs = getAccountStateResolvedAtMs ? getAccountStateResolvedAtMs() : null;
117548
118168
  const accountStateAgeMs = typeof accountStateResolvedAtMs === "number" ? Math.max(0, parityPreparedAtMs - accountStateResolvedAtMs) : null;
@@ -118126,6 +118746,10 @@ ${behaviorJson}
118126
118746
  // A Server bot's cycle reads the account authoritatively, as the Python
118127
118747
  // Server loop does: never a cached or rate-limit-stale observation.
118128
118748
  forceRefresh: input.executionMode === "server",
118749
+ // And values it as that loop does: Perps equity alone unless the loop's
118750
+ // own tests count Spot (serverLoopAccountValue). A Client bot's cycle
118751
+ // keeps the device rule.
118752
+ serverLoopAccountValue: input.executionMode === "server",
118129
118753
  sessionId,
118130
118754
  signal: timeoutController.signal
118131
118755
  }).catch(async (error48) => {
@@ -118236,7 +118860,8 @@ ${behaviorJson}
118236
118860
  },
118237
118861
  initialPromptMetadata,
118238
118862
  () => latestPositions,
118239
- () => _latestPerpDexAccounts
118863
+ () => _latestPerpDexAccounts,
118864
+ input.executionMode === "server"
118240
118865
  ).then((contracts) => {
118241
118866
  appendRuntimeTimingEvent("prompt_contract_loaded", promptContractStartedAtMs);
118242
118867
  return contracts;
@@ -119268,18 +119893,31 @@ ${stringifyPromptJson(candlesPayload)}
119268
119893
  `provider=${provider} requested_model=${authoritativeModel} response_model=${providerResponse.model} llm_latency_s=${providerResponse.latency} snippet=${responseSnippet || "(empty)"}`
119269
119894
  );
119270
119895
  let primaryDecisionContent = providerResponse.content;
119896
+ let mainReplyUnreadable = false;
119271
119897
  if (!allPromptSymbolsUnavailable && !isExternalRuntimeProviderResult(providerResponse)) {
119272
119898
  const validationErrors = currentModelOutputValidationErrors(providerResponse.content, promptSymbols);
119273
- if (validationErrors.length > 0) {
119899
+ if (validationErrors.length > 0 && input.executionMode !== "server") {
119274
119900
  throw modelOutputValidationError("Main", providerResponse.invocations, validationErrors, promptSymbols);
119275
119901
  }
119276
- primaryDecisionContent = projectCurrentModelDecisionContent(providerResponse.content);
119902
+ if (validationErrors.length > 0) {
119903
+ mainReplyUnreadable = true;
119904
+ primaryDecisionContent = JSON.stringify(Object.fromEntries(promptSymbols.map((promptSymbol) => [promptSymbol, {
119905
+ decision: "HOLD",
119906
+ units: 0,
119907
+ tradability: null,
119908
+ reasoning: SERVER_UNREADABLE_REPLY_HOLD_REASONING
119909
+ }])));
119910
+ } else {
119911
+ primaryDecisionContent = projectCurrentModelDecisionContent(providerResponse.content);
119912
+ }
119277
119913
  }
119278
- const primaryParseOutcome = classifyDecisionParseOutcome(
119279
- providerResponse.content,
119280
- symbol2,
119281
- promptSymbols
119282
- );
119914
+ const primaryParseOutcome = mainReplyUnreadable ? {
119915
+ status: "failed",
119916
+ fallbackStrategy: null,
119917
+ // The loop records this one code for a reply its strict parser rejects.
119918
+ validationErrorCodes: ["model_output_schema_invalid"],
119919
+ discardedFields: []
119920
+ } : classifyDecisionParseOutcome(providerResponse.content, symbol2, promptSymbols);
119283
119921
  invocationAttempts = applyInvocationParseOutcome(
119284
119922
  providerResponse.invocations,
119285
119923
  {
@@ -119395,7 +120033,7 @@ ${stringifyPromptJson(candlesPayload)}
119395
120033
  return entry.decision === "BUY" || entry.decision === "SELL" ? total + Math.max(0, Math.trunc(entry.units)) : total;
119396
120034
  }, 0);
119397
120035
  const reviewMaxTrades = Math.max(0, maxTradesPerPrompt - unreviewedPrimaryUnits);
119398
- const shouldReview = !allPromptSymbolsUnavailable && reviewEnabled && reviewCandidatePlans.length > 0;
120036
+ const shouldReview = !allPromptSymbolsUnavailable && reviewEnabled && !mainReplyUnreadable && reviewCandidatePlans.length > 0;
119399
120037
  if (shouldReview) {
119400
120038
  let reviewModel = requireNonEmptyStringField(promptMetadata.review_model, "review_model");
119401
120039
  const requestedReviewModel = reviewModel;
@@ -119696,6 +120334,9 @@ ${reviewOutputContract}`;
119696
120334
  if (error48 instanceof CriticalBehaviorStateError || detail.includes(BEHAVIOR_STATE_UNAVAILABLE_ERROR) || detail.includes("Critical behavior context could not be constructed")) {
119697
120335
  throw new CriticalBehaviorStateError(error48);
119698
120336
  }
120337
+ if (input.executionMode === "server" && error48?.code === "settings_superseded") {
120338
+ throw error48;
120339
+ }
119699
120340
  invocationAttempts = mergeInvocationAttemptChains(
119700
120341
  invocationAttempts,
119701
120342
  Array.isArray(error48?.runtimeInvocationAttempts) ? error48.runtimeInvocationAttempts : []
@@ -119835,7 +120476,14 @@ ${reviewOutputContract}`;
119835
120476
  units: 0,
119836
120477
  tradability: entry.tradability,
119837
120478
  reasoning: `Skipped by client runtime constraints: ${planAcceptance.reason_code || "capacity_reached"}`,
119838
- executionContext: buildExecutionContextForSymbol(entry.symbol)
120479
+ executionContext: buildExecutionContextForSymbol(entry.symbol),
120480
+ ...entry.decision === "BUY" || entry.decision === "SELL" ? {
120481
+ unsentOrder: {
120482
+ decision: entry.decision,
120483
+ units: entry.units,
120484
+ constraintReasonCode: planAcceptance.reason_code || "capacity_reached"
120485
+ }
120486
+ } : {}
119839
120487
  };
119840
120488
  }
119841
120489
  throw new Error(buildRuntimeConstraintRejectionMessage({
@@ -120847,6 +121495,9 @@ var init_engine = __esm({
120847
121495
  this._lastErrorReportCalls = null;
120848
121496
  // The retry wait the API returned for this runtime's latest error report.
120849
121497
  this._reportedProviderRetryAfterSeconds = null;
121498
+ // Whether the server answered the last error report with the failure shown
121499
+ // on its decision's card.
121500
+ this._reportedOrderFailureOnDecisionCard = false;
120850
121501
  this._activeRuntimeContractIdentity = null;
120851
121502
  this._contractRebindInFlight = false;
120852
121503
  this._contractRebindExhausted = false;
@@ -121035,7 +121686,12 @@ var init_engine = __esm({
121035
121686
  await this._trailingMaintenancePromise;
121036
121687
  await this._pendingProtectionRecoveryPromise;
121037
121688
  await waitForBrowserExchangeMutationSettlement(profileId);
121038
- const stopCloseVenues = profileEquityVenues(paused.settings.trading_symbols, paused.config.default_trading_symbols);
121689
+ const stopCloseVenues = profileExchanges(
121690
+ paused.settings.exchanges,
121691
+ paused.settings.trading_symbols,
121692
+ paused.config.default_trading_symbols,
121693
+ paused.config.client_runtime_hyperliquid_perp_dexs?.allowed_dexes
121694
+ );
121039
121695
  const { positions } = await fetchBrowserAccountState2({
121040
121696
  publicRequestPriority: "trading_reduce",
121041
121697
  config: paused.config,
@@ -123229,6 +123885,7 @@ var init_engine = __esm({
123229
123885
  let cycleObservation = { stage: "setup" };
123230
123886
  let cycleOutcome = "unknown";
123231
123887
  let cycleReason = null;
123888
+ let cycleOrderFailure = null;
123232
123889
  let cycleFailureStage = null;
123233
123890
  let decisionSnapshotId = null;
123234
123891
  let observationClosed = false;
@@ -123815,6 +124472,7 @@ var init_engine = __esm({
123815
124472
  }
123816
124473
  const executionResults = [];
123817
124474
  const executionFailures = [];
124475
+ const executionFailureCauses = [];
123818
124476
  const executionLeaseToken = () => {
123819
124477
  const lease = getPersistedClientRuntimeServerLease(profileId);
123820
124478
  return lease?.runtimeSessionId === sessionId && lease.deviceId === deviceId && lease.mode === "trader" ? lease.runtimeLeaseToken : null;
@@ -123838,6 +124496,7 @@ var init_engine = __esm({
123838
124496
  }
123839
124497
  const runPlan = async (plan, planIndex) => {
123840
124498
  let planEntryOrderDispatched = false;
124499
+ let planExitOrderDispatched = false;
123841
124500
  const decisionWallet = String(
123842
124501
  plan.executionContext.walletAddress || ""
123843
124502
  ).trim().toLowerCase();
@@ -123930,100 +124589,171 @@ var init_engine = __esm({
123930
124589
  if (dispatchKind === "entry") {
123931
124590
  planEntryOrderDispatched = true;
123932
124591
  }
124592
+ if (dispatchKind === "exit") {
124593
+ planExitOrderDispatched = true;
124594
+ }
123933
124595
  this._executionFinalizationRequired = true;
123934
124596
  },
123935
124597
  shouldCancelBeforeExchangeOrderDispatch: () => this._windowHandoffRequested
123936
124598
  });
123937
124599
  } catch (executionError) {
124600
+ const committedReports = getCommittedExecutionReports(executionError);
124601
+ const committedOrder = getCommittedDecisionOrder(executionError);
124602
+ const plannedUnits = Number.isFinite(Number(plan.units)) ? Math.max(0, Math.trunc(Number(plan.units))) : 0;
123938
124603
  if (isClientRuntimeWindowHandoffBeforePlanDispatch(executionError)) {
123939
124604
  const handoffCleanup = getClientRuntimeWindowHandoffCleanup(executionError);
123940
- if (handoffCleanup) {
124605
+ if (handoffCleanup || committedReports.length > 0) {
123941
124606
  this._executionFinalizationRequired = true;
123942
124607
  return { control: "break", result: {
123943
- status: "skipped",
124608
+ status: committedReports.length > 0 ? "executed" : "skipped",
123944
124609
  intent: "hold",
123945
124610
  side: null,
123946
124611
  reduceOnly: false,
123947
- requestedUnits: Number.isFinite(Number(plan.units)) ? Math.max(0, Math.trunc(Number(plan.units))) : 0,
124612
+ requestedUnits: plannedUnits,
123948
124613
  targetSignedUnits: 0,
123949
124614
  executedSizeAsset: 0,
123950
- executionReports: [],
123951
- message: "Stopped before protective replacement dispatch; cleanup remains blocked.",
123952
- handoffCleanup,
124615
+ ...committedOrder ?? {},
124616
+ executionReports: committedReports,
124617
+ message: handoffCleanup ? "Stopped before protective replacement dispatch; cleanup remains blocked." : "Stopped after the order for ownership handoff.",
124618
+ ...handoffCleanup ? { handoffCleanup } : {},
123953
124619
  executionSnapshotId: `handoff-cleanup-${planIndex + 1}-${Date.now()}`,
123954
124620
  executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString()
123955
124621
  } };
123956
124622
  }
123957
124623
  return { control: "break" };
123958
124624
  }
123959
- const committedReports = getCommittedExecutionReports(executionError);
123960
124625
  const abortedAfterCommittedOrder = committedReports.length > 0 && (analysisAbortController.signal.aborted || isRuntimeAbortError(executionError));
123961
124626
  if (!abortedAfterCommittedOrder && (analysisAbortController.signal.aborted || isRuntimeAbortError(executionError)) || isRuntimeContractMismatchError(executionError) || isClientExecutionModeMismatchError(executionError) || isClientRuntimeSessionStoppedError(executionError) || isClientRuntimeLeaseAuthError(executionError) || isTransientRuntimeConflictError(executionError) && committedReports.length === 0) {
123962
124627
  throw executionError;
123963
124628
  }
123964
124629
  const sanitizedReason = getSanitizedRuntimeErrorMessage(executionError) || "Unknown runtime execution error.";
123965
- const typedExecutionError = executionError;
123966
- const projectedFailure = projectExecutionErrorContract({
123967
- error: executionError,
123968
- symbol: plan.executionContext.symbol,
123969
- reasonCode: typeof typedExecutionError?.reasonCode === "string" ? typedExecutionError.reasonCode : planEntryOrderDispatched ? "outcome_unknown" : "local_safety_block"
123970
- });
123971
- const failureDiagnostics = getExchangeFailureDiagnostics(executionError);
123972
- if (!abortedAfterCommittedOrder) {
123973
- executionFailures.push({
123974
- symbol: plan.executionContext.symbol,
123975
- projection: projectedFailure
124630
+ if (committedOrder !== null) {
124631
+ const stepFailure = projectExecutionErrorContract({
124632
+ error: executionError,
124633
+ symbol: plan.executionContext.symbol
123976
124634
  });
123977
- }
123978
- appendRuntimeDebugEvent({
123979
- label: "execution_plan_failed",
123980
- note: [
123981
- `cycle_id=${result.cycleId}`,
123982
- `decision_snapshot_id=${result.decisionSnapshotId}`,
123983
- `index=${planIndex + 1}/${executionPlans.length}`,
123984
- `symbol=${plan.executionContext.symbol}`,
123985
- `decision=${plan.decision}`,
123986
- `units=${plan.units}`,
123987
- `error=${sanitizedReason}`
123988
- ].join(" "),
123989
- outcome: "error"
123990
- });
123991
- const flipCloseCommitted = committedReports.some((report) => report.status === "executed" && report.execution_metadata?.decision_leg === "flip_close");
123992
- const planSide = String(plan.decision || "").toUpperCase() === "BUY" ? "buy" : String(plan.decision || "").toUpperCase() === "SELL" ? "sell" : null;
123993
- executionResult = {
123994
- status: committedReports.length > 0 ? "executed" : "skipped",
123995
- intent: flipCloseCommitted ? "flip" : "hold",
123996
- side: flipCloseCommitted ? planSide : null,
123997
- reduceOnly: false,
123998
- requestedUnits: Number.isFinite(Number(plan.units)) ? Math.max(0, Math.trunc(Number(plan.units))) : 0,
123999
- targetSignedUnits: 0,
124000
- executedSizeAsset: 0,
124001
- message: projectedFailure.message,
124002
- executionSnapshotId: `execution-error-${planIndex + 1}-${Date.now()}`,
124003
- executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString(),
124004
- executionReports: [...committedReports, {
124005
- order_id: null,
124635
+ appendRuntimeDebugEvent({
124636
+ label: "execution_plan_failed_after_order",
124637
+ note: [
124638
+ `cycle_id=${result.cycleId}`,
124639
+ `decision_snapshot_id=${result.decisionSnapshotId}`,
124640
+ `index=${planIndex + 1}/${executionPlans.length}`,
124641
+ `symbol=${plan.executionContext.symbol}`,
124642
+ `decision=${plan.decision}`,
124643
+ `error=${sanitizedReason}`
124644
+ ].join(" "),
124645
+ outcome: "error"
124646
+ });
124647
+ executionResult = {
124648
+ status: "executed",
124649
+ ...committedOrder,
124650
+ message: stepFailure.message,
124651
+ executionSnapshotId: `execution-error-${planIndex + 1}-${Date.now()}`,
124652
+ executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString(),
124653
+ executionReports: abortedAfterCommittedOrder ? committedReports : [...committedReports, {
124654
+ order_id: null,
124655
+ symbol: plan.executionContext.symbol,
124656
+ action: "PROTECTIVE_RECONCILIATION",
124657
+ status: "failed",
124658
+ execution_metadata: {
124659
+ reason_code: stepFailure.reason_code,
124660
+ execution_stage: stepFailure.execution_stage,
124661
+ dispatch_outcome: stepFailure.dispatch_outcome,
124662
+ operation_stage: committedOrder.intent === "close" ? "post_close_protection" : "post_entry_protection",
124663
+ error: stepFailure.message,
124664
+ cycle_id: result.cycleId,
124665
+ decision_snapshot_id: result.decisionSnapshotId
124666
+ }
124667
+ }]
124668
+ };
124669
+ if (abortedAfterCommittedOrder) {
124670
+ this._executionFinalizationRequired = true;
124671
+ return { control: "break", result: executionResult };
124672
+ }
124673
+ } else {
124674
+ const typedExecutionError = executionError;
124675
+ const planOrderMayHaveGoneOut = planEntryOrderDispatched || planExitOrderDispatched && committedReports.length === 0;
124676
+ const projectedFailure = projectExecutionErrorContract({
124677
+ error: executionError,
124006
124678
  symbol: plan.executionContext.symbol,
124007
- action: String(plan.decision || "UNKNOWN").toUpperCase(),
124008
- status: "failed",
124009
- execution_metadata: {
124010
- error: projectedFailure.message,
124011
- reason_code: projectedFailure.reason_code,
124012
- execution_stage: projectedFailure.execution_stage,
124013
- dispatch_outcome: projectedFailure.dispatch_outcome,
124014
- cycle_id: result.cycleId,
124015
- decision_snapshot_id: result.decisionSnapshotId,
124016
- ...flipCloseCommitted ? { decision_leg: "entry" } : {},
124017
- ...failureDiagnostics ?? {}
124018
- }
124019
- }]
124020
- };
124021
- if (abortedAfterCommittedOrder) {
124022
- this._executionFinalizationRequired = true;
124023
- return { control: "break", result: executionResult };
124679
+ reasonCode: typeof typedExecutionError?.reasonCode === "string" ? typedExecutionError.reasonCode : planOrderMayHaveGoneOut ? "outcome_unknown" : "local_safety_block"
124680
+ });
124681
+ const failureDiagnostics = getExchangeFailureDiagnostics(executionError);
124682
+ if (!abortedAfterCommittedOrder) {
124683
+ executionFailures.push({
124684
+ symbol: plan.executionContext.symbol,
124685
+ projection: projectedFailure
124686
+ });
124687
+ executionFailureCauses.push(executionError);
124688
+ }
124689
+ appendRuntimeDebugEvent({
124690
+ label: "execution_plan_failed",
124691
+ note: [
124692
+ `cycle_id=${result.cycleId}`,
124693
+ `decision_snapshot_id=${result.decisionSnapshotId}`,
124694
+ `index=${planIndex + 1}/${executionPlans.length}`,
124695
+ `symbol=${plan.executionContext.symbol}`,
124696
+ `decision=${plan.decision}`,
124697
+ `units=${plan.units}`,
124698
+ `error=${sanitizedReason}`
124699
+ ].join(" "),
124700
+ outcome: "error"
124701
+ });
124702
+ const flipCloseCommitted = committedReports.some((report) => report.status === "executed" && report.execution_metadata?.decision_leg === "flip_close");
124703
+ const planSide = String(plan.decision || "").toUpperCase() === "BUY" ? "buy" : String(plan.decision || "").toUpperCase() === "SELL" ? "sell" : null;
124704
+ executionResult = {
124705
+ status: committedReports.length > 0 ? "executed" : "skipped",
124706
+ intent: flipCloseCommitted ? "flip" : "hold",
124707
+ side: flipCloseCommitted ? planSide : null,
124708
+ reduceOnly: false,
124709
+ requestedUnits: plannedUnits,
124710
+ targetSignedUnits: 0,
124711
+ executedSizeAsset: 0,
124712
+ message: projectedFailure.message,
124713
+ executionSnapshotId: `execution-error-${planIndex + 1}-${Date.now()}`,
124714
+ executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString(),
124715
+ executionReports: [...committedReports, {
124716
+ order_id: null,
124717
+ symbol: plan.executionContext.symbol,
124718
+ action: String(plan.decision || "UNKNOWN").toUpperCase(),
124719
+ status: "failed",
124720
+ execution_metadata: {
124721
+ error: projectedFailure.message,
124722
+ reason_code: projectedFailure.reason_code,
124723
+ execution_stage: projectedFailure.execution_stage,
124724
+ dispatch_outcome: projectedFailure.dispatch_outcome,
124725
+ cycle_id: result.cycleId,
124726
+ decision_snapshot_id: result.decisionSnapshotId,
124727
+ ...flipCloseCommitted ? { decision_leg: "entry" } : {},
124728
+ ...failureDiagnostics ?? {}
124729
+ }
124730
+ }]
124731
+ };
124732
+ if (abortedAfterCommittedOrder) {
124733
+ this._executionFinalizationRequired = true;
124734
+ return { control: "break", result: executionResult };
124735
+ }
124024
124736
  }
124025
124737
  }
124026
124738
  }
124739
+ if (plan.unsentOrder) {
124740
+ executionResult = {
124741
+ ...executionResult,
124742
+ executionReports: [...executionResult.executionReports, {
124743
+ order_id: null,
124744
+ symbol: plan.executionContext.symbol,
124745
+ action: plan.unsentOrder.decision,
124746
+ status: "blocked",
124747
+ execution_metadata: {
124748
+ reason_code: "execution_capacity_refused",
124749
+ constraint_reason_code: plan.unsentOrder.constraintReasonCode,
124750
+ requested_units: plan.unsentOrder.units,
124751
+ cycle_id: result.cycleId,
124752
+ decision_snapshot_id: result.decisionSnapshotId
124753
+ }
124754
+ }]
124755
+ };
124756
+ }
124027
124757
  return { control: "continue", result: executionResult };
124028
124758
  };
124029
124759
  const recordPlanResult = (executionResult) => {
@@ -124226,16 +124956,23 @@ var init_engine = __esm({
124226
124956
  cycleReason = "execution_failed";
124227
124957
  cycleFailureStage = "execution";
124228
124958
  const primaryFailure = selectPrimaryExecutionFailure(executionFailures);
124229
- if (!primaryFailure) return;
124230
- await this.reportError(primaryFailure.projection.message, {
124231
- fatal: false,
124232
- model: result.model,
124233
- modelSource: result.model_source ?? result.provider,
124234
- executionSymbol: primaryFailure.symbol,
124235
- executionReasonCode: primaryFailure.projection.reason_code,
124236
- executionStage: primaryFailure.projection.execution_stage,
124237
- dispatchOutcome: primaryFailure.projection.dispatch_outcome
124238
- });
124959
+ const reportedFailures = this._expectedExecutionMode === "server" ? executionFailures.filter((_, index) => executionFailureCauses.indexOf(executionFailureCauses[index]) === index) : primaryFailure ? [primaryFailure] : [];
124960
+ this._lastError = null;
124961
+ for (const failure2 of reportedFailures) {
124962
+ await this.reportError(failure2.projection.message, {
124963
+ fatal: false,
124964
+ model: result.model,
124965
+ modelSource: result.model_source ?? result.provider,
124966
+ executionSymbol: failure2.symbol,
124967
+ executionReasonCode: failure2.projection.reason_code,
124968
+ executionStage: failure2.projection.execution_stage,
124969
+ dispatchOutcome: failure2.projection.dispatch_outcome,
124970
+ recordedOrderFailure: true
124971
+ });
124972
+ if (this._reportedOrderFailureOnDecisionCard) {
124973
+ cycleOrderFailure = failure2.projection.message;
124974
+ }
124975
+ }
124239
124976
  return;
124240
124977
  }
124241
124978
  }
@@ -124502,7 +125239,7 @@ var init_engine = __esm({
124502
125239
  requestId,
124503
125240
  outcome: cycleOutcome,
124504
125241
  reason: cycleReason,
124505
- error: cycleOutcome === "failed" ? this._lastError : null,
125242
+ error: cycleOutcome === "failed" ? this._lastError ?? cycleOrderFailure : null,
124506
125243
  decisionSubmitted,
124507
125244
  executionOccurred: executedExchangeOrderInCycle
124508
125245
  };
@@ -124695,6 +125432,7 @@ var init_engine = __esm({
124695
125432
  }
124696
125433
  async reportError(reason, options) {
124697
125434
  this._reportedProviderRetryAfterSeconds = null;
125435
+ this._reportedOrderFailureOnDecisionCard = false;
124698
125436
  if (this._isStopping) {
124699
125437
  this._lastError = null;
124700
125438
  return null;
@@ -124729,10 +125467,13 @@ var init_engine = __esm({
124729
125467
  });
124730
125468
  const projectedErrorWithoutWarning = String(projected.error_message || "").replace(/^\s*⚠️?\s*/u, "").trim();
124731
125469
  const persistedError = executionProjection?.message ?? (projectedErrorWithoutWarning === sanitizedReason ? sanitizedReason : projected.error_message);
124732
- this._lastError = persistedError;
125470
+ const awaitsDecisionCardAnswer = options?.recordedOrderFailure === true && !isFatal;
125471
+ if (!awaitsDecisionCardAnswer) {
125472
+ this._lastError = persistedError;
125473
+ }
124733
125474
  if (isFatal) {
124734
125475
  this._setState("error");
124735
- } else {
125476
+ } else if (!awaitsDecisionCardAnswer) {
124736
125477
  this._notifyListeners();
124737
125478
  }
124738
125479
  this.recordLocalBreadcrumb("runtime_error_detected", projected.error_message, {
@@ -124772,13 +125513,18 @@ var init_engine = __esm({
124772
125513
  requestTimeoutMs: this._settlementRequestTimeoutMs ?? void 0
124773
125514
  }
124774
125515
  );
125516
+ const shownOnDecisionCard = awaitsDecisionCardAnswer && response.shown_on_decision_card === true;
125517
+ this._reportedOrderFailureOnDecisionCard = shownOnDecisionCard;
125518
+ if (!shownOnDecisionCard) {
125519
+ this._lastError = persistedError;
125520
+ }
124775
125521
  const accepted = this._setRuntimeStatus(response.runtime, "error_report");
124776
125522
  const retryAfterSeconds = Number(response.provider_retry_after_seconds);
124777
125523
  this._reportedProviderRetryAfterSeconds = accepted && response.provider_retry_after_seconds != null && Number.isFinite(retryAfterSeconds) && retryAfterSeconds >= 0 ? retryAfterSeconds : null;
124778
- this._lastError = persistedError;
124779
125524
  this._notifyListeners();
124780
125525
  return accepted ? response.runtime ?? null : null;
124781
125526
  } catch (error48) {
125527
+ this._lastError = persistedError;
124782
125528
  if (isClientRuntimeReleasedError(error48)) {
124783
125529
  await this._handleRuntimeReleased("error_report", { deferUntilExecutionLoopSettles: true });
124784
125530
  return null;
@@ -125314,7 +126060,7 @@ var init_engine = __esm({
125314
126060
  positionCloseFailures: 0
125315
126061
  };
125316
126062
  if (context.close_positions) {
125317
- const stalePositions = positionsOnVenues(evaluation.accountState?.positions ?? [], evaluation.equityVenues);
126063
+ const stalePositions = positionsOnVenues(evaluation.accountState?.positions ?? [], evaluation.closeVenues);
125318
126064
  try {
125319
126065
  const signingKey = String(
125320
126066
  this._deviceSecrets?.hyperliquidSigningKey || ""
@@ -125343,8 +126089,8 @@ var init_engine = __esm({
125343
126089
  tickerPrice: 0,
125344
126090
  leverage: 1,
125345
126091
  aggregatePerpDexs: true,
125346
- // The exchanges the check read: positions elsewhere are not the bot's to close.
125347
- perpDexScope: evaluation.equityVenues?.filter(Boolean),
126092
+ // The bot's exchanges: positions elsewhere are not the bot's to close.
126093
+ perpDexScope: evaluation.closeVenues?.filter(Boolean),
125348
126094
  forceRefresh: true,
125349
126095
  sessionId: this._sessionId ?? void 0,
125350
126096
  signal: refreshController.signal
@@ -125368,7 +126114,7 @@ var init_engine = __esm({
125368
126114
  config: config2,
125369
126115
  signingKey,
125370
126116
  timeoutSeconds: closeTimeoutSeconds,
125371
- venues: evaluation.equityVenues
126117
+ venues: evaluation.closeVenues
125372
126118
  });
125373
126119
  } else {
125374
126120
  closeSummary = {