@vtxmacro/cli 2026.10.32 → 2026.10.33

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.32", 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.33", 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
 
@@ -1195,6 +1195,7 @@ var init_runtime_policy_generated = __esm({
1195
1195
  runtime: {
1196
1196
  assignment_page_default_limit: 20,
1197
1197
  client_candidate_owner_lease_grace_ms: 6e4,
1198
+ bot_switch_max_retries: 2,
1198
1199
  client_server_heartbeats_per_owner_lease: 2,
1199
1200
  client_server_heartbeat_min_ms: 5e3,
1200
1201
  client_server_heartbeat_max_ms: 3e4
@@ -21026,6 +21027,7 @@ var init_runtime_policy_generated2 = __esm({
21026
21027
  runtime: {
21027
21028
  assignment_page_default_limit: 20,
21028
21029
  client_candidate_owner_lease_grace_ms: 6e4,
21030
+ bot_switch_max_retries: 2,
21029
21031
  client_server_heartbeats_per_owner_lease: 2,
21030
21032
  client_server_heartbeat_min_ms: 5e3,
21031
21033
  client_server_heartbeat_max_ms: 3e4
@@ -57837,6 +57839,7 @@ async function getLLMConfig(cookie, profileId, signal) {
57837
57839
  method: "GET",
57838
57840
  headers,
57839
57841
  credentials: "include",
57842
+ cache: "no-store",
57840
57843
  signal: requestSignal
57841
57844
  });
57842
57845
  if (held && response.status === HTTP_STATUS.NOT_MODIFIED) return JSON.parse(held.text);
@@ -57961,6 +57964,17 @@ var init_account_summary = __esm({
57961
57964
  }
57962
57965
  });
57963
57966
 
57967
+ // lib/api/mobile-notifications.ts
57968
+ var init_mobile_notifications = __esm({
57969
+ "lib/api/mobile-notifications.ts"() {
57970
+ "use strict";
57971
+ init_define_VTX_EXO_POLICY();
57972
+ init_define_VTX_GROK_POLICY();
57973
+ init_define_VTX_PI_MODEL_POLICY();
57974
+ init_shared();
57975
+ }
57976
+ });
57977
+
57964
57978
  // lib/runtime/hyperliquid-account-mode-contract.ts
57965
57979
  function resolveExactHyperliquidAccountMode(userAbstraction, ...dexEvidence) {
57966
57980
  const mode = extractCanonicalHyperliquidAccountMode(userAbstraction);
@@ -59882,7 +59896,7 @@ var init_error_surface_contract = __esm({
59882
59896
  return `${pausePrefix}: Critical behavior context could not be constructed for this cycle. The cycle was skipped safely; VTX will retry at the next scheduled cycle.`;
59883
59897
  }
59884
59898
  if (classificationBasis.includes("critical behavior state is unavailable for this trading cycle")) {
59885
- return `${pausePrefix}: Your prompt on the AI page contains something VTX can't use, for example copied DATA FORMAT definitions in the System Prompt. Fix the prompt; VTX skipped this cycle and will retry at the next scheduled cycle.`;
59899
+ return `${pausePrefix}: Your prompt on the AI page contains something VTX can't use, for example a <behavior_state> line in the System Prompt that doesn't start with "- ". Fix the prompt; VTX skipped this cycle and will retry at the next scheduled cycle.`;
59886
59900
  }
59887
59901
  if (classificationBasis.includes(
59888
59902
  "client runtime decision persistence deadline exceeded after the ai run completed"
@@ -91657,7 +91671,12 @@ var init_hyperliquid_client = __esm({
91657
91671
  };
91658
91672
  fetchBrowserAccountState = async (input) => {
91659
91673
  const user = requireWalletAddress(input.walletAddress);
91660
- const payload = await postHyperliquidInfo(input, { type: "clearinghouseState", user }, "hyperliquid.clearinghouseState");
91674
+ const dex = String(input.dex ?? "").trim().toLowerCase();
91675
+ const payload = await postHyperliquidInfo(
91676
+ input,
91677
+ { type: "clearinghouseState", user, ...dex ? { dex } : {} },
91678
+ "hyperliquid.clearinghouseState"
91679
+ );
91661
91680
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
91662
91681
  throw new Error("Malformed Hyperliquid clearinghouseState response.");
91663
91682
  }
@@ -91675,8 +91694,10 @@ var init_hyperliquid_client = __esm({
91675
91694
  const positions = Array.isArray(state2.assetPositions) ? state2.assetPositions.map((entry) => {
91676
91695
  const assetPosition = entry;
91677
91696
  const position = assetPosition.position || {};
91697
+ const coin = String(position.coin || assetPosition.coin || "");
91678
91698
  return {
91679
- symbol: String(position.coin || assetPosition.coin || ""),
91699
+ // A HIP-3 DEX may name its coins without the DEX.
91700
+ symbol: dex && coin && !coin.includes(":") ? `${dex}:${coin}` : coin,
91680
91701
  size: toFiniteNumber(position.szi, 0),
91681
91702
  entry_price: position.entryPx == null ? null : toFiniteNumber(position.entryPx, 0),
91682
91703
  unrealized_pnl: position.unrealizedPnl == null ? null : toFiniteNumber(position.unrealizedPnl, 0),
@@ -91706,7 +91727,7 @@ var init_hyperliquid_client = __esm({
91706
91727
  };
91707
91728
  fetchBrowserPosition = async (input) => {
91708
91729
  const symbol2 = normalizeSymbol(input.symbol);
91709
- const accountState = await fetchBrowserAccountState(input);
91730
+ const accountState = await fetchBrowserAccountState({ ...input, dex: getHyperliquidMarketDex(symbol2) });
91710
91731
  return accountState.positions.find((position) => normalizeSymbol(position.symbol) === symbol2) ?? null;
91711
91732
  };
91712
91733
  buildHyperliquidOrderWire = async (input, tif, price, priceKind) => {
@@ -94716,6 +94737,7 @@ var init_api2 = __esm({
94716
94737
  init_updates();
94717
94738
  init_profile_emoji();
94718
94739
  init_account_summary();
94740
+ init_mobile_notifications();
94719
94741
  init_server_runtime_lease();
94720
94742
  clientRuntimeSecretHeaders = (profileId) => {
94721
94743
  const headers = getProfileHeaders({}, profileId);
@@ -94799,9 +94821,8 @@ var init_api2 = __esm({
94799
94821
  if ("invocations" in payload) {
94800
94822
  body.invocations = payload.invocations ?? [];
94801
94823
  }
94802
- if (payload.stopReason !== void 0) {
94803
- body.stop_reason = payload.stopReason ?? null;
94804
- }
94824
+ if (payload.stopReason !== void 0) body.stop_reason = payload.stopReason ?? null;
94825
+ if (payload.modeSwitch) body.mode_switch = true;
94805
94826
  if (payload.authoritativeIntent !== void 0) {
94806
94827
  body.authoritative_intent = payload.authoritativeIntent;
94807
94828
  }
@@ -98688,7 +98709,7 @@ var init_protective_evidence = __esm({
98688
98709
  });
98689
98710
 
98690
98711
  // lib/runtime/protective-actions.ts
98691
- var DECIMAL, CLOID, fail2, exactKeys, nonNegativeInteger, decimalString, POSITION_ORDER_SIZE, orderSizeString, canonicalTriggerOrder, canonicalProtectiveWireAction, assertProtectiveActionLocallySafe, authorityArgs2, errorCode2, foreignClaimExpiresAtMs, drainLocks, refusedUntil, drainClientProtectiveActions, drainOnce;
98712
+ var DECIMAL, PERCENT, CLOID, fail2, exactKeys, nonNegativeInteger, decimalString, POSITION_ORDER_SIZE, orderSizeString, canonicalTriggerOrder, canonicalProtectiveWireAction, assertProtectiveActionLocallySafe, authorityArgs2, errorCode2, foreignClaimExpiresAtMs, drainLocks, refusedUntil, drainClientProtectiveActions, drainOnce;
98692
98713
  var init_protective_actions = __esm({
98693
98714
  "lib/runtime/protective-actions.ts"() {
98694
98715
  "use strict";
@@ -98705,6 +98726,7 @@ var init_protective_actions = __esm({
98705
98726
  init_error_surface_contract();
98706
98727
  init_protective_evidence();
98707
98728
  DECIMAL = /^(?:0|[1-9]\d*)(?:\.\d+)?$/;
98729
+ PERCENT = /^(?:0|[1-9]\d*)(?:\.\d+)?%$/;
98708
98730
  CLOID = /^0x[0-9a-f]{32}$/;
98709
98731
  fail2 = (message) => {
98710
98732
  throw new RuntimeExecutionError(
@@ -98783,9 +98805,48 @@ var init_protective_actions = __esm({
98783
98805
  if (oid <= 0) fail2("cancel target is invalid.");
98784
98806
  return { type: "cancel", cancels: [{ a: nonNegativeInteger(cancel.a, "asset"), o: oid }] };
98785
98807
  }
98808
+ if (kind === "trailingStop") {
98809
+ const action = exactKeys(wire, ["type", "asset", "isBuy", "sz", "reduceOnly", "retracement", "activationPx"], "action");
98810
+ if (action.reduceOnly !== true) fail2("a trailing stop must be reduce-only.");
98811
+ if (typeof action.isBuy !== "boolean") fail2("trailing stop side is invalid.");
98812
+ if (action.activationPx !== null) fail2("a trailing stop is active at once.");
98813
+ const distance = action.retracement;
98814
+ let retracement;
98815
+ if (distance && typeof distance === "object" && "pct" in distance) {
98816
+ const pct = exactKeys(distance, ["pct"], "retracement").pct;
98817
+ const decimals = typeof pct === "string" && pct.includes(".") ? pct.slice(pct.indexOf(".") + 1, -1).length : 0;
98818
+ if (typeof pct !== "string" || !PERCENT.test(pct) || !(Number(pct.slice(0, -1)) > 0) || decimals > HYPERLIQUID_EXCHANGE_SPECIFICATION.trailing_retracement_pct_max_decimals) {
98819
+ fail2("trailing stop percent is invalid.");
98820
+ }
98821
+ retracement = { pct };
98822
+ } else {
98823
+ retracement = { px: decimalString(exactKeys(distance, ["px"], "retracement").px, "trailing stop distance") };
98824
+ }
98825
+ return {
98826
+ type: "trailingStop",
98827
+ asset: nonNegativeInteger(action.asset, "asset"),
98828
+ isBuy: action.isBuy,
98829
+ sz: decimalString(action.sz, "trailing stop size"),
98830
+ reduceOnly: true,
98831
+ retracement,
98832
+ activationPx: null
98833
+ };
98834
+ }
98786
98835
  return fail2("unsupported action type.");
98787
98836
  };
98788
98837
  assertProtectiveActionLocallySafe = (action, canonical, livePositionSize) => {
98838
+ if (canonical.type === "trailingStop" !== (action.operation_kind === "trailing_stop")) {
98839
+ fail2("operation kind does not match the action.");
98840
+ }
98841
+ if (canonical.type === "trailingStop") {
98842
+ if (action.action_kind !== "place" || action.client_order_ids.length > 0) fail2("trailing stop metadata does not match.");
98843
+ if (canonical.asset !== action.exchange_asset_id) fail2("asset does not match the symbol.");
98844
+ if (livePositionSize == null || !Number.isFinite(livePositionSize) || livePositionSize === 0) {
98845
+ fail2("the live position is flat or unknown.");
98846
+ }
98847
+ if (canonical.isBuy !== livePositionSize < 0) fail2("the trailing stop would not close the live position.");
98848
+ return;
98849
+ }
98789
98850
  const assets = canonical.type === "cancel" ? canonical.cancels.map((cancel) => cancel.a) : canonical.type === "modify" ? [canonical.order.a] : canonical.orders.map((order) => order.a);
98790
98851
  if (assets.some((asset) => asset !== action.exchange_asset_id)) fail2("asset does not match the symbol.");
98791
98852
  if (canonical.type === "cancel") {
@@ -99695,7 +99756,7 @@ var init_protective_trigger_price = __esm({
99695
99756
  });
99696
99757
 
99697
99758
  // lib/runtime/protective-stop-replacement.ts
99698
- var STOP_REPLACED, STOP_REPLACEMENT_EXHAUSTED, STOP_REPLACEMENT_REJECTED, STOP_REPLACEMENT_NOT_LANDED, STOP_CLEANUP_IN_FLIGHT, TERMINAL_WITHOUT_FILL, CANCELLED_BY_USER, POSITION_FLAT_AFTER_TERMINAL, CAPACITY_ALREADY_ALLOCATED, TRIGGER_INVALID, STOP_EXECUTION_REJECTED, STOP_TRIGGER_CROSSED, permanentStopRejectionStatuses, protectiveStopRejectionIsPermanent, POSITION_ENDED_ORDER_STATUSES, finiteOrNull, floorToLot, positiveSafeInteger, decimalOrNull, positionTolerance, chainFillChronology, protectivePositionEpisodeEnded, decideProtectiveStopReplacement;
99759
+ var STOP_REPLACED, STOP_REPLACEMENT_EXHAUSTED, STOP_REPLACEMENT_REJECTED, STOP_REPLACEMENT_NOT_LANDED, STOP_CLEANUP_IN_FLIGHT, TERMINAL_WITHOUT_FILL, CANCELLED_BY_USER, POSITION_FLAT_AFTER_TERMINAL, CAPACITY_ALREADY_ALLOCATED, TRIGGER_INVALID, STOP_EXECUTION_REJECTED, STOP_TRIGGER_CROSSED, permanentStopRejectionStatuses, protectiveStopRejectionIsPermanent, POSITION_ENDED_ORDER_STATUSES, finiteOrNull, floorToLot, positiveSafeInteger, decimalOrNull, positionTolerance, chainFillChronology, marketFillChain, noExposureOnSide, protectivePositionEpisodeEnded, decideProtectiveStopReplacement;
99699
99760
  var init_protective_stop_replacement = __esm({
99700
99761
  "lib/runtime/protective-stop-replacement.ts"() {
99701
99762
  "use strict";
@@ -99772,16 +99833,13 @@ var init_protective_stop_replacement = __esm({
99772
99833
  }
99773
99834
  return ordered;
99774
99835
  };
99775
- protectivePositionEpisodeEnded = (input) => {
99776
- if (!POSITION_ENDED_ORDER_STATUSES.has(String(input.orderStatus ?? ""))) return false;
99777
- const statusMs = positiveSafeInteger(input.statusTimestampMs);
99778
- if (statusMs == null || !Array.isArray(input.fills)) return false;
99779
- const market = normalizeHyperliquidMarketSymbol(input.symbol);
99780
- const sign = input.isLong ? 1 : -1;
99836
+ marketFillChain = (fills, symbol2) => {
99837
+ if (!Array.isArray(fills)) return null;
99838
+ const market = normalizeHyperliquidMarketSymbol(symbol2);
99781
99839
  const rows = [];
99782
99840
  const seen = /* @__PURE__ */ new Set();
99783
- for (const fill of input.fills) {
99784
- if (fill == null || typeof fill !== "object" || Array.isArray(fill)) return false;
99841
+ for (const fill of fills) {
99842
+ if (fill == null || typeof fill !== "object" || Array.isArray(fill)) return null;
99785
99843
  const record5 = fill;
99786
99844
  if (normalizeHyperliquidMarketSymbol(String(record5.coin ?? "")) !== market) continue;
99787
99845
  const tradeId = positiveSafeInteger(record5.tid);
@@ -99789,12 +99847,26 @@ var init_protective_stop_replacement = __esm({
99789
99847
  const size = decimalOrNull(record5.sz);
99790
99848
  const start = decimalOrNull(record5.startPosition);
99791
99849
  if (tradeId == null || seen.has(tradeId) || time3 == null || record5.side !== "B" && record5.side !== "A" || size == null || size <= 0 || start == null) {
99792
- return false;
99850
+ return null;
99793
99851
  }
99794
99852
  seen.add(tradeId);
99795
- rows.push({ time: time3, tradeId, start, end: start + (record5.side === "B" ? size : -size) });
99853
+ rows.push({
99854
+ time: time3,
99855
+ tradeId,
99856
+ start,
99857
+ end: start + (record5.side === "B" ? size : -size),
99858
+ orderId: String(record5.oid ?? "").trim()
99859
+ });
99796
99860
  }
99797
- const chained = chainFillChronology(rows);
99861
+ return chainFillChronology(rows);
99862
+ };
99863
+ noExposureOnSide = (position, isLong) => (isLong ? 1 : -1) * position <= positionTolerance(position, 0);
99864
+ protectivePositionEpisodeEnded = (input) => {
99865
+ if (!POSITION_ENDED_ORDER_STATUSES.has(String(input.orderStatus ?? ""))) return false;
99866
+ const statusMs = positiveSafeInteger(input.statusTimestampMs);
99867
+ if (statusMs == null) return false;
99868
+ const sign = input.isLong ? 1 : -1;
99869
+ const chained = marketFillChain(input.fills, input.symbol);
99798
99870
  if (chained == null) return false;
99799
99871
  const before = chained.filter((row) => row.time <= statusMs);
99800
99872
  const after = chained.filter((row) => row.time > statusMs);
@@ -99947,7 +100019,7 @@ var init_protective_entry_cover = __esm({
99947
100019
  });
99948
100020
 
99949
100021
  // lib/runtime/native-position-protection.ts
99950
- var nativeProtectionSettings, memberSetting, KINDS, formatTriggerOrNull, nativePositionTriggerPrice, nativeEntryRequest, HALF_UP_DIGIT, roundDecimalHalfUp, nativeTrailingRetracement, nativeAfterFillActions, classifyNativeOrderEnd, isOpenInDirection, nativePlacementGate, nativeStrayOrderDecision, FIRED_TRIGGER_CONDITION, TRAILING_ORDER_TYPE, closingSide, DECIMAL_PATTERN, decimalUnits2, fractionDigits, nativePlaceCover, positiveOrderId, nativeRearmDecision, nativeLostStopCrossed, readListedProtectiveRow, explainAbsentProtectiveOrder, readServerNativeProtectionState;
100022
+ var nativeProtectionSettings, memberSetting, KINDS, formatTriggerOrNull, nativePositionTriggerPrice, nativeEntryRequest, HALF_UP_DIGIT, roundDecimalHalfUp, nativeTrailingRetracement, nativeAfterFillActions, classifyNativeOrderEnd, isOpenInDirection, nativePlacementGate, nativeStrayOrderDecision, FIRED_TRIGGER_CONDITION, TRAILING_ORDER_TYPE, closingSide, DECIMAL_PATTERN, decimalUnits2, fractionDigits, nativePlaceCover, positiveOrderId, nativeRearmDecision, nativeLostStopCrossed, readListedProtectiveRow, explainAbsentProtectiveOrder, readServerNativeProtectionState, nativeFillOpenedPosition, nativePositionEndedSince, flatReadEndsPosition;
99951
100023
  var init_native_position_protection = __esm({
99952
100024
  "lib/runtime/native-position-protection.ts"() {
99953
100025
  "use strict";
@@ -100167,11 +100239,60 @@ var init_native_position_protection = __esm({
100167
100239
  if (typeof record5.enabled !== "boolean" || legacy == null || native == null) return null;
100168
100240
  return { enabled: record5.enabled, legacySymbols: new Set(legacy), nativeSymbols: new Set(native) };
100169
100241
  };
100242
+ nativeFillOpenedPosition = (input) => {
100243
+ if (!input.complete || !Array.isArray(input.fills)) return "unknown";
100244
+ const market = normalizeHyperliquidMarketSymbol(input.symbol);
100245
+ const moves = [];
100246
+ const decimal = (value) => {
100247
+ const text = typeof value === "number" && Number.isFinite(value) ? String(value) : typeof value === "string" ? value.trim() : "";
100248
+ return DECIMAL_PATTERN.test(text) ? Number(text) : null;
100249
+ };
100250
+ for (const fill of input.fills) {
100251
+ if (fill == null || typeof fill !== "object" || Array.isArray(fill)) continue;
100252
+ const record5 = fill;
100253
+ if (String(record5.oid ?? "").trim() !== input.orderId.trim()) continue;
100254
+ if (normalizeHyperliquidMarketSymbol(String(record5.coin ?? "")) !== market) continue;
100255
+ const start = decimal(record5.startPosition);
100256
+ const size = decimal(record5.sz);
100257
+ if (start == null || size == null || size <= 0 || record5.side !== "B" && record5.side !== "A") return "unknown";
100258
+ moves.push({ start, end: start + (record5.side === "B" ? size : -size) });
100259
+ }
100260
+ if (moves.length === 0) return "unknown";
100261
+ if (moves.some(({ start, end }) => noExposureOnSide(start, input.isLong) && !noExposureOnSide(end, input.isLong))) {
100262
+ return "opened";
100263
+ }
100264
+ if (moves.every(({ start }) => !noExposureOnSide(start, input.isLong))) return "joined";
100265
+ if (moves.every(({ end }) => noExposureOnSide(end, input.isLong))) return "other_side";
100266
+ return "unknown";
100267
+ };
100268
+ nativePositionEndedSince = (input) => {
100269
+ let answer = "unknown";
100270
+ const chain = input.complete ? marketFillChain(input.fills, input.symbol) : null;
100271
+ if (chain != null) {
100272
+ let last = -1;
100273
+ chain.forEach((row, index) => {
100274
+ if (row.orderId === input.orderId.trim()) last = index;
100275
+ });
100276
+ if (last >= 0) {
100277
+ answer = chain.slice(last).some((row) => noExposureOnSide(row.end, input.isLong)) ? "ended" : "open";
100278
+ }
100279
+ }
100280
+ if (answer === "unknown" && input.flatRead != null && flatReadEndsPosition(input.flatRead, input.isLong)) return "ended";
100281
+ return answer;
100282
+ };
100283
+ flatReadEndsPosition = (read, isLong) => {
100284
+ if (read.pageComplete !== true || read.newestFillMs === void 0) return false;
100285
+ const text = String(read.position ?? "").trim();
100286
+ if (!DECIMAL_PATTERN.test(text) || !Number.isSafeInteger(read.stateMs)) return false;
100287
+ if (!noExposureOnSide(Number(text), isLong)) return false;
100288
+ if (read.newestFillMs == null) return true;
100289
+ return Number.isSafeInteger(read.newestFillMs) && read.newestFillMs < read.stateMs;
100290
+ };
100170
100291
  }
100171
100292
  });
100172
100293
 
100173
100294
  // lib/runtime/native-protection-device.ts
100174
- var NATIVE_PROTECTION_RECORD_VERSION, nativeProtectionStorage, resolveStorage, setNativeProtectionStorage, recordKey, isMember, isRetracement, isLot, readNativeProtectionRecord, versioned, writeNativeProtectionRecord, NativeOrderNotSentError, withDispatchBoundary, attempt, notSentRestores, errorText, actionOf, isOpenInDirection2, coverRows, restingOrderIdAt, definitivelyRefused, TRAILING_LOT_FIRED, ownLotOrderIds, lotRetracement, lotReport, sendTrailingLot, planNativeFillLot, dropNativePendingLot, planNativePendingLot, planNativeOpen, recordEntryChildren, observeMembers, UNKNOWN_ORDER_RESPONSE, resolveUnknownOrderIds, settleNativeProtectionAfterFill, reconcileNativeProtection;
100295
+ var NATIVE_PROTECTION_RECORD_VERSION, nativeProtectionStorage, resolveStorage, setNativeProtectionStorage, recordKey, isMember, isRetracement, isLot, isStandbyAdd, readNativeProtectionRecord, versioned, writeNativeProtectionRecord, NO_FILLS, nativeFillsPageFromUserFills, fillsReader, flatReadOf, orderFillTimes, namedOrderId, NativeOrderNotSentError, withDispatchBoundary, attempt, notSentRestores, errorText, actionOf, isOpenInDirection2, coverRows, restingOrderIdAt, definitivelyRefused, TRAILING_LOT_FIRED, TRAILING_LOT_POSITION_ENDED, TRAILING_LOT_OTHER_SIDE, lotFillLeftPosition, lotOfAdd, ORDER_ID_PATTERN, lotFillOrderId, lotPositionSince, ownLotOrderIds, lotRetracement, lotReport, sendTrailingLot, planNativeFillLot, planNativeStandbyAdd, nameNativeStandbyAdd, dropNativeStandbyAdd, dropNativePendingLot, planNativePendingLot, planNativeOpen, recordEntryChildren, observeMembers, UNKNOWN_ORDER_RESPONSE, resolveUnknownOrderIds, plannedPair, resolveStandbyAdds, settleNativeProtectionAfterFill, reconcileNativeProtection;
100175
100296
  var init_native_protection_device = __esm({
100176
100297
  "lib/runtime/native-protection-device.ts"() {
100177
100298
  "use strict";
@@ -100179,6 +100300,8 @@ var init_native_protection_device = __esm({
100179
100300
  init_define_VTX_GROK_POLICY();
100180
100301
  init_define_VTX_PI_MODEL_POLICY();
100181
100302
  init_constants();
100303
+ init_hyperliquid_market_symbol();
100304
+ init_hyperliquid_order_status();
100182
100305
  init_order_identity();
100183
100306
  init_native_position_protection();
100184
100307
  NATIVE_PROTECTION_RECORD_VERSION = 1;
@@ -100199,7 +100322,7 @@ var init_native_protection_device = __esm({
100199
100322
  isMember = (value) => {
100200
100323
  if (!value || typeof value !== "object") return false;
100201
100324
  const member = value;
100202
- return (member.kind === "sl" || member.kind === "tp") && typeof member.clientOrderId === "string" && (member.orderId === null || typeof member.orderId === "number" && Number.isSafeInteger(member.orderId)) && typeof member.trigger === "string" && (member.placedAtMs === null || typeof member.placedAtMs === "number") && typeof member.sentAtMs === "number" && typeof member.replacedOnce === "boolean" && (member.pendingModify === void 0 || typeof member.pendingModify === "object" && member.pendingModify !== null && typeof member.pendingModify.clientOrderId === "string" && typeof member.pendingModify.trigger === "string" && typeof member.pendingModify.sentAtMs === "number");
100325
+ return (member.kind === "sl" || member.kind === "tp") && typeof member.clientOrderId === "string" && (member.orderId === null || typeof member.orderId === "number" && Number.isSafeInteger(member.orderId)) && typeof member.trigger === "string" && (member.placedAtMs === null || typeof member.placedAtMs === "number") && typeof member.sentAtMs === "number" && typeof member.replacedOnce === "boolean" && (member.plannedAfterMs === void 0 || typeof member.plannedAfterMs === "number") && (member.pendingModify === void 0 || typeof member.pendingModify === "object" && member.pendingModify !== null && typeof member.pendingModify.clientOrderId === "string" && typeof member.pendingModify.trigger === "string" && typeof member.pendingModify.sentAtMs === "number");
100203
100326
  };
100204
100327
  isRetracement = (value) => {
100205
100328
  if (!value || typeof value !== "object") return false;
@@ -100210,7 +100333,12 @@ var init_native_protection_device = __esm({
100210
100333
  isLot = (value) => {
100211
100334
  if (!value || typeof value !== "object") return false;
100212
100335
  const lot = value;
100213
- return (lot.mutationId === null || typeof lot.mutationId === "string") && typeof lot.fillKey === "string" && typeof lot.fillEventMs === "number" && typeof lot.size === "string" && isRetracement(lot.retracement) && (lot.orderId === null || typeof lot.orderId === "number" && Number.isSafeInteger(lot.orderId)) && (lot.placedAtMs === null || typeof lot.placedAtMs === "number") && typeof lot.sentAtMs === "number" && typeof lot.replacedOnce === "boolean" && (lot.userCancelledOrderId === void 0 || typeof lot.userCancelledOrderId === "number") && (lot.fillEventFromDevice === void 0 || typeof lot.fillEventFromDevice === "boolean") && (lot.retiredReason === void 0 || typeof lot.retiredReason === "string");
100336
+ return (lot.mutationId === null || typeof lot.mutationId === "string") && typeof lot.fillKey === "string" && (lot.fillOrderId === void 0 || typeof lot.fillOrderId === "string") && typeof lot.fillEventMs === "number" && typeof lot.size === "string" && isRetracement(lot.retracement) && (lot.orderId === null || typeof lot.orderId === "number" && Number.isSafeInteger(lot.orderId)) && (lot.placedAtMs === null || typeof lot.placedAtMs === "number") && typeof lot.sentAtMs === "number" && typeof lot.replacedOnce === "boolean" && (lot.userCancelledOrderId === void 0 || typeof lot.userCancelledOrderId === "number") && (lot.fillEventFromDevice === void 0 || typeof lot.fillEventFromDevice === "boolean") && (lot.retiredReason === void 0 || typeof lot.retiredReason === "string");
100337
+ };
100338
+ isStandbyAdd = (value) => {
100339
+ if (!value || typeof value !== "object") return false;
100340
+ const add = value;
100341
+ return typeof add.clientOrderId === "string" && (add.orderId === null || typeof add.orderId === "string") && typeof add.sentAtMs === "number";
100214
100342
  };
100215
100343
  readNativeProtectionRecord = (profileId, symbol2) => {
100216
100344
  const storage3 = resolveStorage();
@@ -100218,7 +100346,7 @@ var init_native_protection_device = __esm({
100218
100346
  const raw = storage3.getItem(recordKey(profileId, symbol2));
100219
100347
  if (raw == null) return null;
100220
100348
  const parsed = JSON.parse(raw);
100221
- if (parsed?.version !== NATIVE_PROTECTION_RECORD_VERSION && parsed?.version !== NATIVE_PROTECTION_RECORD_WITH_LOTS_VERSION || parsed.profileId !== profileId || parsed.symbol !== symbol2 || typeof parsed.walletAddress !== "string" || typeof parsed.isLong !== "boolean" || parsed.phase !== "entry_pending" && parsed.phase !== "active" || typeof parsed.entryMutationId !== "string" || typeof parsed.entryClientOrderId !== "string" || typeof parsed.createdAtMs !== "number" || !Array.isArray(parsed.members) || !parsed.members.every(isMember) || parsed.lots !== void 0 && (parsed.version !== NATIVE_PROTECTION_RECORD_WITH_LOTS_VERSION || !Array.isArray(parsed.lots) || !parsed.lots.every(isLot))) {
100349
+ if (parsed?.version !== NATIVE_PROTECTION_RECORD_VERSION && parsed?.version !== NATIVE_PROTECTION_RECORD_WITH_LOTS_VERSION || parsed.profileId !== profileId || parsed.symbol !== symbol2 || typeof parsed.walletAddress !== "string" || typeof parsed.isLong !== "boolean" || parsed.phase !== "entry_pending" && parsed.phase !== "active" || typeof parsed.entryMutationId !== "string" || typeof parsed.entryClientOrderId !== "string" || typeof parsed.createdAtMs !== "number" || !Array.isArray(parsed.members) || !parsed.members.every(isMember) || parsed.lots !== void 0 && (parsed.version !== NATIVE_PROTECTION_RECORD_WITH_LOTS_VERSION || !Array.isArray(parsed.lots) || !parsed.lots.every(isLot)) || parsed.standby !== void 0 && (!Array.isArray(parsed.standby) || !parsed.standby.every(isStandbyAdd)) || parsed.positionOrderId !== void 0 && typeof parsed.positionOrderId !== "string") {
100222
100350
  throw new Error("Stored native protection record is invalid.");
100223
100351
  }
100224
100352
  return parsed;
@@ -100238,6 +100366,63 @@ var init_native_protection_device = __esm({
100238
100366
  return false;
100239
100367
  }
100240
100368
  };
100369
+ NO_FILLS = { fills: [], complete: false, coversFromMs: null };
100370
+ nativeFillsPageFromUserFills = (rawFills, evidence) => {
100371
+ const live = evidence.source === "live";
100372
+ if (evidence.providerRowCount < evidence.providerPageCap) return { fills: [...rawFills], complete: live, coversFromMs: null };
100373
+ const oldest = evidence.oldestFillTimeMs;
100374
+ if (oldest == null) return NO_FILLS;
100375
+ return {
100376
+ fills: rawFills.filter((fill) => Number(fill?.time) > oldest),
100377
+ complete: live,
100378
+ coversFromMs: oldest + 1
100379
+ };
100380
+ };
100381
+ fillsReader = (io) => {
100382
+ let read = null;
100383
+ return () => {
100384
+ read ??= io.readFills().catch((error48) => {
100385
+ if (io.endsPass?.(error48)) throw error48;
100386
+ return NO_FILLS;
100387
+ });
100388
+ return read;
100389
+ };
100390
+ };
100391
+ flatReadOf = (position, page, symbol2) => {
100392
+ const stateMs = position.stateTimeMs;
100393
+ if (!page.complete || stateMs == null || !Number.isSafeInteger(stateMs)) return null;
100394
+ const market = normalizeHyperliquidMarketSymbol(symbol2);
100395
+ let newest = null;
100396
+ for (const fill of page.fills) {
100397
+ if (fill == null || typeof fill !== "object" || Array.isArray(fill)) continue;
100398
+ const row = fill;
100399
+ if (normalizeHyperliquidMarketSymbol(String(row.coin ?? "")) !== market) continue;
100400
+ const time3 = Number(row.time);
100401
+ if (!Number.isSafeInteger(time3)) return null;
100402
+ newest = newest == null ? time3 : Math.max(newest, time3);
100403
+ }
100404
+ return {
100405
+ position: String(position.size),
100406
+ stateMs,
100407
+ newestFillMs: newest,
100408
+ pageComplete: page.coversFromMs == null || page.coversFromMs < stateMs
100409
+ };
100410
+ };
100411
+ orderFillTimes = (page, orderId, symbol2) => {
100412
+ const market = normalizeHyperliquidMarketSymbol(symbol2);
100413
+ return page.fills.flatMap((fill) => {
100414
+ if (fill == null || typeof fill !== "object" || Array.isArray(fill)) return [];
100415
+ const row = fill;
100416
+ if (String(row.oid ?? "").trim() !== orderId.trim()) return [];
100417
+ if (normalizeHyperliquidMarketSymbol(String(row.coin ?? "")) !== market) return [];
100418
+ const time3 = Number(row.time);
100419
+ return [Number.isSafeInteger(time3) && time3 > 0 ? time3 : Number.NaN];
100420
+ });
100421
+ };
100422
+ namedOrderId = (evidence) => {
100423
+ const orderId = Number(evidence.orderId);
100424
+ return evidence.responseValid && evidence.orderMatches && Number.isSafeInteger(orderId) && orderId > 0 ? String(orderId) : null;
100425
+ };
100241
100426
  NativeOrderNotSentError = class extends Error {
100242
100427
  constructor(cause) {
100243
100428
  super(cause instanceof Error ? cause.message : "The exchange call failed before dispatch.");
@@ -100303,6 +100488,24 @@ var init_native_protection_device = __esm({
100303
100488
  return Array.isArray(statuses) && statuses.length > 0 && statuses.every((status) => Boolean(status && typeof status === "object" && "error" in status));
100304
100489
  };
100305
100490
  TRAILING_LOT_FIRED = "protective_trailing_lot_fired";
100491
+ TRAILING_LOT_POSITION_ENDED = "protective_trailing_lot_position_ended";
100492
+ TRAILING_LOT_OTHER_SIDE = "protective_trailing_lot_other_side";
100493
+ lotFillLeftPosition = (lot) => lot.retiredReason === TRAILING_LOT_FIRED || lot.retiredReason === TRAILING_LOT_POSITION_ENDED || lot.retiredReason === TRAILING_LOT_OTHER_SIDE;
100494
+ lotOfAdd = (lot, add) => lot.fillKey === add.clientOrderId || add.orderId != null && (lot.fillKey === add.orderId || lot.fillOrderId === add.orderId);
100495
+ ORDER_ID_PATTERN = /^\d+$/;
100496
+ lotFillOrderId = (lot) => lot.fillOrderId ?? (ORDER_ID_PATTERN.test(lot.fillKey) ? lot.fillKey : null);
100497
+ lotPositionSince = async (lot, record5, fills) => {
100498
+ const orderId = lotFillOrderId(lot);
100499
+ if (orderId == null) return "unknown";
100500
+ const page = await fills();
100501
+ return nativePositionEndedSince({
100502
+ fills: page.fills,
100503
+ complete: page.complete,
100504
+ orderId,
100505
+ isLong: record5.isLong,
100506
+ symbol: record5.symbol
100507
+ });
100508
+ };
100306
100509
  ownLotOrderIds = (record5) => (record5.lots ?? []).flatMap((lot) => lot.orderId == null ? [] : [lot.orderId]);
100307
100510
  lotRetracement = (settings, size, sizeDecimals) => {
100308
100511
  const stopLoss = settings.stopLoss;
@@ -100385,6 +100588,22 @@ var init_native_protection_device = __esm({
100385
100588
  else lots.push(planned);
100386
100589
  return { ...record5, lots };
100387
100590
  };
100591
+ planNativeStandbyAdd = (record5, input) => {
100592
+ if (!input.clientOrderId || (record5.standby ?? []).some((add) => add.clientOrderId === input.clientOrderId)) return record5;
100593
+ return {
100594
+ ...record5,
100595
+ standby: [...record5.standby ?? [], { clientOrderId: input.clientOrderId, orderId: null, sentAtMs: input.nowMs }]
100596
+ };
100597
+ };
100598
+ nameNativeStandbyAdd = (record5, clientOrderId, orderId) => (record5.standby ?? []).some((add) => add.clientOrderId === clientOrderId && add.orderId !== orderId) ? {
100599
+ ...record5,
100600
+ standby: (record5.standby ?? []).map((add) => add.clientOrderId === clientOrderId ? { ...add, orderId } : add)
100601
+ } : record5;
100602
+ dropNativeStandbyAdd = (record5, clientOrderId) => {
100603
+ const standby = (record5.standby ?? []).filter((add) => add.clientOrderId !== clientOrderId);
100604
+ const { standby: _dropped, ...rest } = record5;
100605
+ return standby.length > 0 ? { ...rest, standby } : rest;
100606
+ };
100388
100607
  dropNativePendingLot = (record5, key) => versioned({
100389
100608
  ...record5,
100390
100609
  lots: (record5.lots ?? []).filter((lot) => !(lot.fillKey === key && lot.mutationId == null && lot.size === ""))
@@ -100495,7 +100714,7 @@ var init_native_protection_device = __esm({
100495
100714
  }
100496
100715
  continue;
100497
100716
  }
100498
- if (member.orderId != null || member.retiredReason) {
100717
+ if (member.orderId != null || member.retiredReason || member.plannedAfterMs != null) {
100499
100718
  members.push(member);
100500
100719
  continue;
100501
100720
  }
@@ -100508,6 +100727,109 @@ var init_native_protection_device = __esm({
100508
100727
  }
100509
100728
  return { ...record5, members };
100510
100729
  };
100730
+ plannedPair = (settings, afterMs, io) => ["sl", "tp"].filter((kind) => (kind === "sl" ? settings.stopLoss : settings.takeProfit) != null).map((kind) => ({
100731
+ kind,
100732
+ clientOrderId: clientOrderIdForMutation(io.newMutationId()),
100733
+ orderId: null,
100734
+ trigger: "",
100735
+ placedAtMs: null,
100736
+ sentAtMs: io.nowMs(),
100737
+ replacedOnce: false,
100738
+ plannedAfterMs: afterMs
100739
+ }));
100740
+ resolveStandbyAdds = async (args) => {
100741
+ const { io } = args;
100742
+ let record5 = args.record;
100743
+ const standby = record5.standby ?? [];
100744
+ if (standby.length === 0) return { record: record5, addFillMs: null, undecided: false };
100745
+ const left = [];
100746
+ let addFillMs = null;
100747
+ for (const add of standby) {
100748
+ if (left.length > 0) {
100749
+ left.push(add);
100750
+ continue;
100751
+ }
100752
+ let orderId = add.orderId;
100753
+ let endedUnfilledAtMs = null;
100754
+ if (orderId == null) {
100755
+ const evidence = await io.readOrderStatus(add.clientOrderId);
100756
+ orderId = namedOrderId(evidence);
100757
+ if (orderId == null) {
100758
+ if (!(evidence.responseStatus === UNKNOWN_ORDER_RESPONSE && io.nowMs() > io.neverLandsAfterMs(add.sentAtMs))) {
100759
+ left.push(add);
100760
+ }
100761
+ continue;
100762
+ }
100763
+ if (classifyHyperliquidOrderStatus(evidence.orderStatus) === "terminal_unfilled") {
100764
+ endedUnfilledAtMs = evidence.orderTimestampMs ?? null;
100765
+ }
100766
+ }
100767
+ const page = await args.fills();
100768
+ const times = orderFillTimes(page, orderId, record5.symbol);
100769
+ const verdict = nativeFillOpenedPosition({
100770
+ fills: page.fills,
100771
+ complete: page.complete,
100772
+ orderId,
100773
+ isLong: record5.isLong,
100774
+ symbol: record5.symbol
100775
+ });
100776
+ const fillMs = times.length > 0 && times.every(Number.isFinite) ? Math.max(...times) : null;
100777
+ if (verdict === "other_side") {
100778
+ const lots = record5.lots ?? [];
100779
+ if (lots.some((lot) => lotOfAdd(lot, { clientOrderId: add.clientOrderId, orderId }))) {
100780
+ record5 = {
100781
+ ...record5,
100782
+ lots: lots.map((lot) => lotOfAdd(lot, { clientOrderId: add.clientOrderId, orderId }) && !lot.retiredReason ? { ...lot, retiredReason: TRAILING_LOT_OTHER_SIDE } : lot)
100783
+ };
100784
+ }
100785
+ continue;
100786
+ }
100787
+ if (verdict === "unknown" || fillMs == null) {
100788
+ const neverFilled = endedUnfilledAtMs != null && page.complete && times.length === 0 && (page.coversFromMs == null || page.coversFromMs <= endedUnfilledAtMs);
100789
+ if (neverFilled) continue;
100790
+ let pageAccountsForAdd = times.length > 0;
100791
+ if (!pageAccountsForAdd && page.coversFromMs != null) {
100792
+ const evidence = await io.readOrderStatus(orderId);
100793
+ const endedMs = evidence.statusTimestampMs;
100794
+ pageAccountsForAdd = evidence.responseValid && evidence.terminal && endedMs != null && endedMs < page.coversFromMs;
100795
+ }
100796
+ const positionEnded = nativePositionEndedSince({
100797
+ fills: page.fills,
100798
+ complete: page.complete,
100799
+ orderId,
100800
+ isLong: record5.isLong,
100801
+ symbol: record5.symbol,
100802
+ flatRead: pageAccountsForAdd ? flatReadOf(args.position, page, record5.symbol) : null
100803
+ }) === "ended";
100804
+ if (!positionEnded) left.push(add);
100805
+ continue;
100806
+ }
100807
+ const stateMs = args.position.stateTimeMs;
100808
+ if (stateMs == null || !(stateMs > fillMs)) {
100809
+ left.push(add);
100810
+ continue;
100811
+ }
100812
+ record5 = { ...record5, positionOrderId: orderId };
100813
+ addFillMs = fillMs;
100814
+ if (verdict === "opened") {
100815
+ const resting = record5.members.filter((member) => member.orderId != null && !member.retiredReason && args.page.some((order) => order.oid === member.orderId));
100816
+ const planned = plannedPair(args.settings, fillMs, io);
100817
+ record5 = {
100818
+ ...record5,
100819
+ members: [
100820
+ ...planned.map((member) => {
100821
+ const kept = resting.find((entry) => entry.kind === member.kind);
100822
+ return kept ? { ...kept, replacedOnce: false } : member;
100823
+ }),
100824
+ // A kind the settings no longer enable stays tracked while it rests.
100825
+ ...resting.filter((entry) => !planned.some((member) => member.kind === entry.kind))
100826
+ ]
100827
+ };
100828
+ }
100829
+ }
100830
+ const { standby: _decided, ...rest } = record5;
100831
+ return { record: left.length > 0 ? { ...rest, standby: left } : rest, addFillMs, undecided: left.length > 0 };
100832
+ };
100511
100833
  settleNativeProtectionAfterFill = async (input) => {
100512
100834
  const { io } = input;
100513
100835
  const reports = [];
@@ -100516,6 +100838,17 @@ var init_native_protection_device = __esm({
100516
100838
  const page = await io.readOpenOrders();
100517
100839
  const position = await io.readPosition();
100518
100840
  const symbol2 = record5.symbol;
100841
+ const fills = fillsReader(io);
100842
+ const settlingAdds = (record5.standby ?? []).length > 0;
100843
+ const boundary = await resolveStandbyAdds({ record: record5, settings: input.settings, io, fills, position, page });
100844
+ record5 = boundary.record;
100845
+ if (boundary.undecided) {
100846
+ return { record: record5, reports };
100847
+ }
100848
+ const entryOrderId = String(input.entryOrderId ?? "").trim();
100849
+ if (record5.positionOrderId == null && boundary.addFillMs == null && !settlingAdds && ORDER_ID_PATTERN.test(entryOrderId)) {
100850
+ record5 = { ...record5, positionOrderId: entryOrderId };
100851
+ }
100519
100852
  if (!isOpenInDirection2(position.size, record5.isLong)) {
100520
100853
  reports.push({
100521
100854
  order_id: input.entryOrderId,
@@ -100554,7 +100887,10 @@ var init_native_protection_device = __esm({
100554
100887
  });
100555
100888
  let eventMs = Math.max(
100556
100889
  0,
100557
- ...observations.map((entry) => entry.row?.timestamp ?? entry.member.placedAtMs ?? 0)
100890
+ ...observations.map((entry) => entry.row?.timestamp ?? entry.member.placedAtMs ?? 0),
100891
+ // An add's own fill, and the fill a planned pair answers: Hyperliquid's times.
100892
+ boundary.addFillMs ?? 0,
100893
+ ...record5.members.map((member) => member.plannedAfterMs ?? 0)
100558
100894
  );
100559
100895
  if (eventMs <= 0 && input.entryOrderId) {
100560
100896
  const entryStatus = await io.readOrderStatus(input.entryOrderId);
@@ -100634,7 +100970,7 @@ var init_native_protection_device = __esm({
100634
100970
  });
100635
100971
  continue;
100636
100972
  }
100637
- if (existing != null && existing.orderId == null && !unknownClientOrderIds.has(existing.clientOrderId)) {
100973
+ if (existing != null && existing.orderId == null && existing.plannedAfterMs == null && !unknownClientOrderIds.has(existing.clientOrderId)) {
100638
100974
  continue;
100639
100975
  }
100640
100976
  if (gate !== "place") {
@@ -100753,8 +101089,15 @@ var init_native_protection_device = __esm({
100753
101089
  const retracement = lotRetracement(input.settings, size, input.sizeDecimals);
100754
101090
  if (retracement) {
100755
101091
  const { fillEventFromDevice: _deviceTime, ...withoutDeviceTime } = journaledLot;
100756
- const planned = eventMs > 0 ? { ...withoutDeviceTime, size, retracement, fillEventMs: eventMs } : { ...journaledLot, size, retracement };
100757
- if (gate === "place") {
101092
+ let planned = eventMs > 0 ? { ...withoutDeviceTime, size, retracement, fillEventMs: eventMs } : { ...journaledLot, size, retracement };
101093
+ if (gate === "place" && lotFillOrderId(planned) == null) {
101094
+ const named = namedOrderId(await io.readOrderStatus(planned.fillKey));
101095
+ if (named != null) planned = { ...planned, fillOrderId: named };
101096
+ }
101097
+ const since = gate === "place" ? await lotPositionSince(planned, record5, fills) : "unknown";
101098
+ if (since === "ended") {
101099
+ lots[lotIndex] = { ...planned, retiredReason: TRAILING_LOT_POSITION_ENDED };
101100
+ } else if (since === "open") {
100758
101101
  const index = lotIndex;
100759
101102
  const sent = await sendTrailingLot({
100760
101103
  io,
@@ -100800,6 +101143,28 @@ var init_native_protection_device = __esm({
100800
101143
  const position = await io.readPosition();
100801
101144
  const symbol2 = record5.symbol;
100802
101145
  const stateMs = position.stateTimeMs ?? Number.NEGATIVE_INFINITY;
101146
+ const fills = fillsReader(io);
101147
+ const undecidedAdds = (record5.standby ?? []).length > 0;
101148
+ let membersPositionEnded = null;
101149
+ const membersEnded = () => {
101150
+ membersPositionEnded ??= (async () => {
101151
+ let anchor = record5.positionOrderId ?? null;
101152
+ if (anchor == null) {
101153
+ anchor = namedOrderId(await io.readOrderStatus(record5.entryClientOrderId));
101154
+ if (anchor != null) record5 = { ...record5, positionOrderId: anchor };
101155
+ }
101156
+ const fillsPage = await fills();
101157
+ return nativePositionEndedSince({
101158
+ fills: fillsPage.fills,
101159
+ complete: fillsPage.complete,
101160
+ orderId: anchor ?? "",
101161
+ isLong: record5.isLong,
101162
+ symbol: symbol2,
101163
+ flatRead: flatReadOf(position, fillsPage, symbol2)
101164
+ });
101165
+ })();
101166
+ return membersPositionEnded;
101167
+ };
100803
101168
  const observations = observeMembers(record5, page).map((entry) => ({
100804
101169
  ...entry,
100805
101170
  member: entry.row ? { ...entry.member, placedAtMs: entry.row.timestamp || entry.member.placedAtMs } : entry.member
@@ -100971,6 +101336,33 @@ var init_native_protection_device = __esm({
100971
101336
  members.push(member);
100972
101337
  continue;
100973
101338
  }
101339
+ if (member.plannedAfterMs != null) {
101340
+ if (!kindEnabled(member)) continue;
101341
+ const plannedGate = nativePlacementGate({
101342
+ eventMs: member.plannedAfterMs,
101343
+ position: position.size,
101344
+ positionStateMs: stateMs,
101345
+ isLong: record5.isLong
101346
+ });
101347
+ if (plannedGate === "not_required") continue;
101348
+ const plannedTrigger = currentTrigger(member);
101349
+ if (plannedGate === "need_reads" || plannedTrigger == null) {
101350
+ anyResting = true;
101351
+ members.push(member);
101352
+ continue;
101353
+ }
101354
+ const placed = await placeMember({
101355
+ member,
101356
+ trigger: plannedTrigger,
101357
+ replacedOnce: false,
101358
+ eventMs: member.plannedAfterMs,
101359
+ reasonCode: "protective_native_position_opened_by_add",
101360
+ observationIndex
101361
+ });
101362
+ members.push(placed);
101363
+ if (!placed.retiredReason) anyResting = true;
101364
+ continue;
101365
+ }
100974
101366
  if (member.orderId == null) {
100975
101367
  if (io.nowMs() <= io.neverLandsAfterMs(member.sentAtMs) || !unknownClientOrderIds.has(member.clientOrderId)) {
100976
101368
  anyResting = true;
@@ -101014,10 +101406,9 @@ var init_native_protection_device = __esm({
101014
101406
  });
101015
101407
  explained = end2 === "resting" || end2 === "pending" || end2 === "unknown" ? "status_read" : "ended_with_position";
101016
101408
  }
101017
- if (explained !== "ended_with_position") {
101018
- anyResting = true;
101019
- members.push(member);
101020
- }
101409
+ if (explained === "ended_with_position" && await membersEnded() === "ended") continue;
101410
+ anyResting = true;
101411
+ members.push(member);
101021
101412
  continue;
101022
101413
  }
101023
101414
  const evidence = await io.readOrderStatus(member.orderId);
@@ -101039,7 +101430,7 @@ var init_native_protection_device = __esm({
101039
101430
  });
101040
101431
  if (rearm === "retire" || !kindEnabled(member)) continue;
101041
101432
  const rearmTrigger = currentTrigger(member);
101042
- if (rearm === "need_reads" || rearmTrigger == null) {
101433
+ if (rearm === "need_reads" || rearmTrigger == null || undecidedAdds) {
101043
101434
  members.push(member);
101044
101435
  continue;
101045
101436
  }
@@ -101124,7 +101515,8 @@ var init_native_protection_device = __esm({
101124
101515
  for (const [index, prior] of priorLots.entries()) {
101125
101516
  let lot = prior;
101126
101517
  const restingRow = lot.orderId == null ? null : page.find((order) => order.oid === lot.orderId) ?? null;
101127
- if ((lot.retiredReason || lot.userCancelledOrderId != null) && !(restingRow && readListedProtectiveRow({ triggerCondition: restingRow.trigger_condition }) === "resting")) {
101518
+ const otherSideUnnamed = lot.retiredReason === TRAILING_LOT_OTHER_SIDE && lot.mutationId != null && lot.orderId == null;
101519
+ if ((lot.retiredReason || lot.userCancelledOrderId != null) && !otherSideUnnamed && !(restingRow && readListedProtectiveRow({ triggerCondition: restingRow.trigger_condition }) === "resting")) {
101128
101520
  lots.push(lot);
101129
101521
  continue;
101130
101522
  }
@@ -101133,7 +101525,8 @@ var init_native_protection_device = __esm({
101133
101525
  const entryStatus = await io.readOrderStatus(lot.fillKey);
101134
101526
  if (entryStatus.responseValid && entryStatus.orderMatches && entryStatus.statusTimestampMs != null) {
101135
101527
  const { fillEventFromDevice: _deviceTime, ...exchangeTimed } = lot;
101136
- lot = { ...exchangeTimed, fillEventMs: entryStatus.statusTimestampMs };
101528
+ const named = lotFillOrderId(lot) == null ? namedOrderId(entryStatus) : null;
101529
+ lot = { ...exchangeTimed, fillEventMs: entryStatus.statusTimestampMs, ...named != null ? { fillOrderId: named } : {} };
101137
101530
  } else if (entryStatus.responseStatus === UNKNOWN_ORDER_RESPONSE && io.nowMs() > io.neverLandsAfterMs(lot.sentAtMs)) {
101138
101531
  continue;
101139
101532
  } else {
@@ -101154,9 +101547,28 @@ var init_native_protection_device = __esm({
101154
101547
  lots.push(lot);
101155
101548
  continue;
101156
101549
  }
101550
+ if (lotFillOrderId(lot) == null) {
101551
+ const named = namedOrderId(await io.readOrderStatus(lot.fillKey));
101552
+ if (named != null) lot = { ...lot, fillOrderId: named };
101553
+ }
101554
+ if ((record5.standby ?? []).some((add) => lotOfAdd(lot, add))) {
101555
+ anyResting = true;
101556
+ lots.push(lot);
101557
+ continue;
101558
+ }
101559
+ const since = await lotPositionSince(lot, record5, fills);
101560
+ if (since === "ended") {
101561
+ lots.push({ ...lot, retiredReason: TRAILING_LOT_POSITION_ENDED });
101562
+ continue;
101563
+ }
101564
+ if (since !== "open") {
101565
+ anyResting = true;
101566
+ lots.push(lot);
101567
+ continue;
101568
+ }
101157
101569
  if (!lot.size) {
101158
101570
  const others = [...lots, ...priorLots.slice(index + 1)];
101159
- const covered = others.reduce((total, other) => other.size && other.retiredReason !== TRAILING_LOT_FIRED ? total + Number(other.size) : total, 0);
101571
+ const covered = others.reduce((total, other) => other.size && !lotFillLeftPosition(other) ? total + Number(other.size) : total, 0);
101160
101572
  const uncovered = Number((Math.abs(position.size) - covered).toFixed(input.sizeDecimals));
101161
101573
  if (!(uncovered > 0)) continue;
101162
101574
  lot = { ...lot, size: String(uncovered) };
@@ -101183,11 +101595,24 @@ var init_native_protection_device = __esm({
101183
101595
  const named = answer != null && (answer.status === "settled" && answer.outcome_code === "success" || answer.status === "reconciled" && answer.outcome_code === "exchange_effect_observed") && Number.isSafeInteger(orderId) && orderId > 0;
101184
101596
  if (named) {
101185
101597
  lot = { ...lot, orderId };
101598
+ } else if (lot.retiredReason && (answer?.status === "settled" && answer.outcome_code === "rejected" || answer?.status === "reconciled" && answer.outcome_code === "exchange_expired_unconfirmed" || answer?.status === "absent" && io.nowMs() > io.neverLandsAfterMs(lot.sentAtMs))) {
101599
+ lots.push({ ...lot, mutationId: null });
101600
+ continue;
101186
101601
  } else if (answer?.status === "settled" && answer.outcome_code === "rejected") {
101187
101602
  lots.push({ ...lot, retiredReason: "protective_place_rejected" });
101188
101603
  continue;
101189
101604
  } else if (answer?.status === "reconciled" && answer.outcome_code === "exchange_expired_unconfirmed" || answer?.status === "absent" && io.nowMs() > io.neverLandsAfterMs(lot.sentAtMs)) {
101190
101605
  if (!positionOpen) continue;
101606
+ const since = await lotPositionSince(lot, record5, fills);
101607
+ if (since === "ended") {
101608
+ lots.push({ ...lot, retiredReason: TRAILING_LOT_POSITION_ENDED });
101609
+ continue;
101610
+ }
101611
+ if (since !== "open") {
101612
+ anyResting = true;
101613
+ lots.push(lot);
101614
+ continue;
101615
+ }
101191
101616
  const sent2 = await sendTrailingLot({ io, symbol: symbol2, lot: { ...lot, mutationId: null }, journal: (next) => journalLot(index, next) });
101192
101617
  lots.push(sent2.lot);
101193
101618
  if (sent2.report) reports.push(sent2.report);
@@ -101203,7 +101628,7 @@ var init_native_protection_device = __esm({
101203
101628
  const row = lot === prior ? restingRow : page.find((order) => order.oid === lotOrderId) ?? null;
101204
101629
  if (row && readListedProtectiveRow({ triggerCondition: row.trigger_condition }) === "resting") {
101205
101630
  lot = { ...lot, placedAtMs: row.timestamp || lot.placedAtMs };
101206
- const stray = nativeStrayOrderDecision({
101631
+ const stray = lot.retiredReason === TRAILING_LOT_OTHER_SIDE ? "cancel" : nativeStrayOrderDecision({
101207
101632
  placedMs: lot.placedAtMs ?? Number.POSITIVE_INFINITY,
101208
101633
  position: position.size,
101209
101634
  positionStateMs: stateMs,
@@ -101282,6 +101707,15 @@ var init_native_protection_device = __esm({
101282
101707
  lots.push(lot);
101283
101708
  continue;
101284
101709
  }
101710
+ const lostSince = await lotPositionSince(lot, record5, fills);
101711
+ if (lostSince === "ended") {
101712
+ lots.push({ ...lot, retiredReason: TRAILING_LOT_POSITION_ENDED });
101713
+ continue;
101714
+ }
101715
+ if (lostSince !== "open") {
101716
+ lots.push(lot);
101717
+ continue;
101718
+ }
101285
101719
  const sent = await sendTrailingLot({
101286
101720
  io,
101287
101721
  symbol: symbol2,
@@ -101293,7 +101727,7 @@ var init_native_protection_device = __esm({
101293
101727
  if (sent.report) reports.push(sent.report);
101294
101728
  if (!sent.lot.retiredReason) anyResting = true;
101295
101729
  }
101296
- if (!positionOpen && !anyResting) {
101730
+ if (!positionOpen && !anyResting && !undecidedAdds) {
101297
101731
  return { record: null, reports };
101298
101732
  }
101299
101733
  const { lots: _priorLots, ...withoutLots } = record5;
@@ -105020,6 +105454,19 @@ var init_runtime_execution = __esm({
105020
105454
  if (mutation.operation_kind !== "trailing_stop") throw new Error("The ledger names another action for this trailing lot.");
105021
105455
  return { status: mutation.status, outcome_code: mutation.outcome_code, exchange_order_id: mutation.exchange_order_id };
105022
105456
  },
105457
+ // The device's own fills read (Client Mode: every Hyperliquid read comes
105458
+ // from the device), fresh, as the per-entry lane's episode rule reads it.
105459
+ readFills: async () => {
105460
+ const { rawFills, evidence } = await fetchBrowserUserFills({
105461
+ publicRequestPriority: "trading_reduce",
105462
+ config: request.config ?? {},
105463
+ walletAddress,
105464
+ symbols: [symbol2],
105465
+ forceRefresh: true,
105466
+ signal: request.signal
105467
+ });
105468
+ return nativeFillsPageFromUserFills(rawFills, evidence);
105469
+ },
105023
105470
  isDefinitiveRefusal: (error48) => error48 instanceof HyperliquidExchangeRejectionError || error48 instanceof NativeOrderNotSentError,
105024
105471
  neverLandsAfterMs: (sentAtMs) => clientOrderNeverLandsAfterMs(request.config, { kind: "absent", ageStartMs: sentAtMs }),
105025
105472
  newMutationId: () => createRuntimeId().toLowerCase(),
@@ -105053,17 +105500,29 @@ var init_runtime_execution = __esm({
105053
105500
  if (read.record.walletAddress !== wallet) return [nativeStorageReport(symbol2, "protective_wallet_mismatch")];
105054
105501
  try {
105055
105502
  const io = nativeProtectionIo(request, read.record.isLong);
105056
- if (read.record.phase === "entry_pending") {
105503
+ const standby = read.record.standby ?? [];
105504
+ if (read.record.phase === "entry_pending" || standby.length > 0) {
105057
105505
  const settled = await settleNativeProtectionAfterFill({
105058
105506
  record: read.record,
105059
105507
  settings: nativeSettingsOf(request.executionContext),
105060
105508
  sizeDecimals: request.executionContext.sizeDecimals,
105061
105509
  fillSize: "0",
105062
- entryOrderId: read.record.entryClientOrderId,
105510
+ entryOrderId: read.record.phase === "entry_pending" ? read.record.entryClientOrderId : standby[0].orderId ?? standby[0].clientOrderId,
105063
105511
  io
105064
105512
  });
105065
105513
  const reports2 = [...settled.reports];
105066
- if (!writeNativeProtectionRecord(profileId, symbol2, settled.record)) {
105514
+ let record5 = settled.record;
105515
+ if (record5 != null && record5.phase !== "entry_pending" && (record5.standby ?? []).length > 0) {
105516
+ const kept = await reconcileNativeProtection({
105517
+ record: record5,
105518
+ settings: nativeSettingsOf(request.executionContext),
105519
+ sizeDecimals: request.executionContext.sizeDecimals,
105520
+ io
105521
+ });
105522
+ reports2.push(...kept.reports);
105523
+ record5 = kept.record;
105524
+ }
105525
+ if (!writeNativeProtectionRecord(profileId, symbol2, record5)) {
105067
105526
  reports2.push(nativeStorageReport(symbol2, "protective_lifecycle_persistence_failed"));
105068
105527
  }
105069
105528
  return reports2;
@@ -108439,13 +108898,14 @@ var init_runtime_execution = __esm({
108439
108898
  entryMutationId ??= createRuntimeId().toLowerCase();
108440
108899
  entryClientOrderId = clientOrderIdForMutation(entryMutationId);
108441
108900
  nativePendingLotKey = entryClientOrderId;
108442
- nativeAddRecord = planNativePendingLot(existingNative.record, {
108901
+ const journaledAt = Date.now();
108902
+ nativeAddRecord = planNativeStandbyAdd(planNativePendingLot(existingNative.record, {
108443
108903
  settings: nativeSettingsOf(input.executionContext),
108444
108904
  sizeDecimals: input.executionContext.sizeDecimals,
108445
108905
  key: entryClientOrderId,
108446
108906
  sizeHint: sizeAsset,
108447
- nowMs: Date.now()
108448
- });
108907
+ nowMs: journaledAt
108908
+ }), { clientOrderId: entryClientOrderId, nowMs: journaledAt });
108449
108909
  if (nativeAddRecord !== existingNative.record && !writeNativeProtectionRecord(nativeProfileId, input.executionContext.symbol, nativeAddRecord)) {
108450
108910
  return nativeBlocked(
108451
108911
  "protective_lifecycle_persistence_failed",
@@ -108632,7 +109092,7 @@ var init_runtime_execution = __esm({
108632
109092
  writeNativeProtectionRecord(
108633
109093
  nativeProfileId,
108634
109094
  input.executionContext.symbol,
108635
- dropNativePendingLot(stored.record, nativePendingLotKey)
109095
+ dropNativeStandbyAdd(dropNativePendingLot(stored.record, nativePendingLotKey), nativePendingLotKey)
108636
109096
  );
108637
109097
  }
108638
109098
  }
@@ -108759,6 +109219,9 @@ var init_runtime_execution = __esm({
108759
109219
  let record5 = nativeOpen != null ? recordEntryChildren(nativeOpen.record, marketOrderResponse) : nativeAddRecord;
108760
109220
  let keepNativeJournal = false;
108761
109221
  if (confirmedMarketFill?.orderId) {
109222
+ if (nativeOpen == null && nativePendingLotKey != null) {
109223
+ record5 = nameNativeStandbyAdd(record5, nativePendingLotKey, String(confirmedMarketFill.orderId));
109224
+ }
108762
109225
  record5 = planNativeFillLot(record5, {
108763
109226
  settings: nativeSettingsOf(input.executionContext),
108764
109227
  sizeDecimals: input.executionContext.sizeDecimals,
@@ -113599,7 +114062,7 @@ var init_profile_model_cascade = __esm({
113599
114062
  });
113600
114063
 
113601
114064
  // lib/runtime/prompt-variable-validation-contract.ts
113602
- var ESCAPED_OPEN_BRACE, ESCAPED_CLOSE_BRACE, PROMPT_PLACEHOLDER_PATTERN, ESCAPED_BRACE_PAIR_PATTERN, readPromptTemplate, restoreEscapedBraces, countAtMost, countBelow, locatePlaceholders, isPromptVariableName, renderPromptTemplate, promptTemplatePlaceholderSpans, promptTemplatePlaceholders, promptTemplateVariables, NEWS_PROMPT_VARIABLES, REFERENCE_CANDLES_PROMPT_VARIABLE, ALLOWED_PROMPT_VARIABLES, OPTIONAL_BLANK_PROMPT_VARIABLES, coercePromptVariableValue, isMissingPromptVariableValue, validatePromptVariables;
114065
+ var ESCAPED_OPEN_BRACE, ESCAPED_CLOSE_BRACE, PROMPT_PLACEHOLDER_PATTERN, ESCAPED_BRACE_PAIR_PATTERN, readPromptTemplate, restoreEscapedBraces, countAtMost, countBelow, locatePlaceholders, isPromptVariableName, renderPromptTemplate, formatInstructionTemplate, promptTemplatePlaceholderSpans, promptTemplatePlaceholders, promptTemplateVariables, NEWS_PROMPT_VARIABLES, REFERENCE_CANDLES_PROMPT_VARIABLE, ALLOWED_PROMPT_VARIABLES, OPTIONAL_BLANK_PROMPT_VARIABLES, coercePromptVariableValue, isMissingPromptVariableValue, validatePromptVariables;
113603
114066
  var init_prompt_variable_validation_contract = __esm({
113604
114067
  "lib/runtime/prompt-variable-validation-contract.ts"() {
113605
114068
  "use strict";
@@ -113685,6 +114148,40 @@ var init_prompt_variable_validation_contract = __esm({
113685
114148
  rendered.push(prepared.slice(cursor));
113686
114149
  return restoreEscapedBraces(rendered.join(""));
113687
114150
  };
114151
+ formatInstructionTemplate = (template, values, label2 = "instruction template") => {
114152
+ const text = String(template || "");
114153
+ const rendered = [];
114154
+ let index = 0;
114155
+ while (index < text.length) {
114156
+ const char = text[index];
114157
+ const escapedPair = `${char}${char}`;
114158
+ if ((char === "{" || char === "}") && text.startsWith(escapedPair, index)) {
114159
+ rendered.push(char);
114160
+ index += escapedPair.length;
114161
+ continue;
114162
+ }
114163
+ if (char === "}") {
114164
+ throw new Error(`Invalid ${label2}: ${template}`);
114165
+ }
114166
+ if (char !== "{") {
114167
+ rendered.push(char);
114168
+ index += 1;
114169
+ continue;
114170
+ }
114171
+ const end = text.indexOf("}", index + 1);
114172
+ const field = end < 0 ? "" : text.slice(index + 1, end);
114173
+ const name = field.endsWith(":") ? field.slice(0, -1) : field;
114174
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
114175
+ throw new Error(`Invalid ${label2}: ${template}`);
114176
+ }
114177
+ if (!Object.prototype.hasOwnProperty.call(values, name)) {
114178
+ throw new Error(`Unexpected ${label2} placeholder: ${name}`);
114179
+ }
114180
+ rendered.push(String(values[name]));
114181
+ index = end + 1;
114182
+ }
114183
+ return rendered.join("");
114184
+ };
113688
114185
  promptTemplatePlaceholderSpans = (template) => {
113689
114186
  if (typeof template !== "string" || !template) {
113690
114187
  return [];
@@ -118420,7 +118917,7 @@ var init_provider_client = __esm({
118420
118917
  });
118421
118918
 
118422
118919
  // lib/runtime/prompt-contract.ts
118423
- var PROMPT_PLACEHOLDER_MAP, DATA_FORMAT_TAG_ALIASES, buildDecisionInstructionVariables, renderCandleIndicatorDefinitions, NEWS_COLUMN_DESCRIPTIONS, isNewsPromptTag, newsTagBlock, newsRowColumns, renderNewsLegendLine, behaviorStateHasObjectField, candleBlockPayload, candlesHaveLiveField, templateReferencesTag, templateTagOrder, renderDataFormatLegend, replaceEmbeddedDataFormatLegend, SIZE_AMOUNT_USDC_LABEL_PATTERN, labelSizeAmountInUsd, canonicalizePromptPlaceholders, normalizePromptWhitespace, formatInstructionTemplate, constructPromptSystemTemplate;
118920
+ var PROMPT_PLACEHOLDER_MAP, DATA_FORMAT_TAG_ALIASES, buildDecisionInstructionVariables, renderCandleIndicatorDefinitions, NEWS_COLUMN_DESCRIPTIONS, isNewsPromptTag, newsTagBlock, newsRowColumns, renderNewsLegendLine, behaviorStateHasObjectField, candleBlockPayload, candlesHaveLiveField, templateReferencesTag, templateTagOrder, renderDataFormatLegend, replaceEmbeddedDataFormatLegend, SIZE_AMOUNT_USDC_LABEL_PATTERN, labelSizeAmountInUsd, canonicalizePromptPlaceholders, normalizePromptWhitespace, constructPromptSystemTemplate;
118424
118921
  var init_prompt_contract = __esm({
118425
118922
  "lib/runtime/prompt-contract.ts"() {
118426
118923
  "use strict";
@@ -118837,28 +119334,6 @@ var init_prompt_contract = __esm({
118837
119334
  }
118838
119335
  return text.replace(/\r\n/g, "\n").replace(/[\t ]{2,}\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
118839
119336
  };
118840
- formatInstructionTemplate = (template, vars) => {
118841
- const escapedOpen = "__VTX_INSTR_OPEN_BRACE__";
118842
- const escapedClose = "__VTX_INSTR_CLOSE_BRACE__";
118843
- const prepared = String(template ?? "").replaceAll("{{", escapedOpen).replaceAll("}}", escapedClose);
118844
- const replacements = [];
118845
- const formatted = prepared.replace(/\{([a-zA-Z0-9_]+)\}/g, (_match, key) => {
118846
- if (!Object.prototype.hasOwnProperty.call(vars, key)) {
118847
- throw new Error(`Unexpected instruction template placeholder: ${key}`);
118848
- }
118849
- const marker = `__VTX_INSTR_VALUE_${replacements.length}__`;
118850
- replacements.push(String(vars[key]));
118851
- return marker;
118852
- });
118853
- if (/[{}]/.test(formatted)) {
118854
- throw new Error(`Invalid instruction template: ${template}`);
118855
- }
118856
- let rendered = formatted.replaceAll(escapedOpen, "{").replaceAll(escapedClose, "}");
118857
- replacements.forEach((value, index) => {
118858
- rendered = rendered.replaceAll(`__VTX_INSTR_VALUE_${index}__`, value);
118859
- });
118860
- return rendered;
118861
- };
118862
119337
  constructPromptSystemTemplate = (systemTemplate, options) => {
118863
119338
  const instructions = options.instructions ?? {};
118864
119339
  const symbols = (options.symbols ?? []).map((symbol2) => String(symbol2).trim()).filter(Boolean);
@@ -119730,7 +120205,7 @@ __export(local_analysis_exports, {
119730
120205
  runLocalRuntimeCycle: () => runLocalRuntimeCycle,
119731
120206
  summarizeReviewFailureExplanation: () => summarizeReviewFailureExplanation
119732
120207
  });
119733
- 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, BEHAVIOR_MEMORY_UNAVAILABLE_ERROR, BehaviorMemoryUnavailableError, 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, MANIFEST_COMPONENT_NAME, 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, AI_INDICATOR_KEYS_NEWER_THAN_SOME_SERVERS, sortTradingTimeframes, normalizePromptIdentityTimestamp, resolveCompletedCandleBoundary, normalizeAiIndicatorFlags, getPromptLookback, computeSma, computeEma, computeRsi, computeAtr, computeMacd, computeBollingerBands, getIndicatorValue, buildPromptCandlesComponent, buildPromptCandleTimeframeComponent, resolvePromptRelativeVolumeContext, promptRelativeVolumeBaseline, 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;
120208
+ 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, BEHAVIOR_MEMORY_UNAVAILABLE_ERROR, BehaviorMemoryUnavailableError, 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, MANIFEST_COMPONENT_NAME, 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, AI_INDICATOR_KEYS_NEWER_THAN_SOME_SERVERS, sortTradingTimeframes, normalizePromptIdentityTimestamp, resolveCompletedCandleBoundary, normalizeAiIndicatorFlags, getPromptLookback, computeSma, computeEma, computeRsi, computeAtr, computeMacd, computeBollingerBands, getIndicatorValue, buildPromptCandlesComponent, buildPromptCandleTimeframeComponent, resolvePromptRelativeVolumeContext, promptRelativeVolumeBaseline, 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, carryReturnedModelCalls, runLocalRuntimeCycle;
119734
120209
  var init_local_analysis = __esm({
119735
120210
  "lib/runtime/local-analysis.ts"() {
119736
120211
  "use strict";
@@ -120910,29 +121385,27 @@ var init_local_analysis = __esm({
120910
121385
  return assembledUserTemplate;
120911
121386
  };
120912
121387
  preflightStrategyReviewPromptContract = (metadata, symbols, maxTrades) => {
121388
+ const reviewSystemTemplate = String(metadata.review_system_template ?? "");
121389
+ const reviewUserTemplate = String(metadata.review_user_template ?? "");
121390
+ if (!reviewSystemTemplate.trim() || !reviewUserTemplate.trim() || extractTemplatePlaceholders(reviewSystemTemplate).length > 0) {
121391
+ throw new CriticalBehaviorStateError();
121392
+ }
121393
+ requireStrategyReviewTemplates(reviewSystemTemplate, reviewUserTemplate);
120913
121394
  try {
120914
- requireStrategyReviewTemplates(
120915
- requireNonEmptyStringField(metadata.review_system_template, "review_system_template"),
120916
- requireNonEmptyStringField(metadata.review_user_template, "review_user_template")
120917
- );
120918
121395
  const reviewInstructions = asRecord(metadata.review_instructions);
120919
121396
  const reviewSecurity = requireNonEmptyStringField(
120920
121397
  reviewInstructions.review_security,
120921
121398
  "review_instructions.review_security"
120922
121399
  );
120923
- const reviewOutputContract = formatTemplateWithNamedVariables(
121400
+ const reviewOutputContract = formatInstructionTemplate(
120924
121401
  requireNonEmptyStringField(
120925
121402
  reviewInstructions.review_json_format,
120926
121403
  "review_instructions.review_json_format"
120927
121404
  ),
120928
121405
  buildDecisionInstructionVariables(symbols, maxTrades)
120929
121406
  );
120930
- const reviewSystemTemplate = requireNonEmptyStringField(
120931
- metadata.review_system_template,
120932
- "review_system_template"
120933
- );
120934
- if (extractTemplatePlaceholders(reviewSystemTemplate).length > 0 || extractTemplatePlaceholders(reviewSecurity).length > 0) {
120935
- throw new CriticalBehaviorStateError();
121407
+ if (extractTemplatePlaceholders(reviewSecurity).length > 0) {
121408
+ throw new BehaviorMemoryUnavailableError();
120936
121409
  }
120937
121410
  const securedReviewSystem = reviewSystemTemplate.includes(reviewSecurity) ? reviewSystemTemplate : `${reviewSystemTemplate.trim()}
120938
121411
 
@@ -120941,13 +121414,13 @@ ${reviewSecurity}`;
120941
121414
 
120942
121415
  ${reviewOutputContract}`;
120943
121416
  if (containsCompetingBehaviorStateMarkup(renderedReviewSystem)) {
120944
- throw new CriticalBehaviorStateError();
121417
+ throw new BehaviorMemoryUnavailableError();
120945
121418
  }
120946
121419
  } catch (error48) {
120947
- if (error48 instanceof CriticalBehaviorStateError) {
121420
+ if (error48 instanceof BehaviorMemoryUnavailableError) {
120948
121421
  throw error48;
120949
121422
  }
120950
- throw new CriticalBehaviorStateError();
121423
+ throw new BehaviorMemoryUnavailableError(error48);
120951
121424
  }
120952
121425
  };
120953
121426
  extractRuntimeReasoningSelection = (settings, controlType, toggleBehavior = "disable_reasoning") => {
@@ -121932,33 +122405,11 @@ ${reviewOutputContract}`;
121932
122405
  ].join("\n");
121933
122406
  buildPromptPositionsValue = (input) => {
121934
122407
  const validateInstructionTemplate = (template, allowedKeys) => {
121935
- const escapedOpen = "__VTX_ESCAPED_OPEN__";
121936
- const escapedClose = "__VTX_ESCAPED_CLOSE__";
121937
- const normalizedTemplate = template.replace(/\{\{/g, escapedOpen).replace(/\}\}/g, escapedClose);
121938
- const formatted = normalizedTemplate.replace(/\{([a-z_]+)\}/g, (_match, key) => {
121939
- if (!allowedKeys.includes(key)) {
121940
- throw new Error(`Unexpected positions instruction placeholder: ${key}`);
121941
- }
121942
- return "";
121943
- });
121944
- if (/[{}]/.test(formatted)) {
121945
- throw new Error(`Invalid positions instruction template: ${template}`);
121946
- }
121947
- };
121948
- const formatInstructionTemplate2 = (template, values) => {
121949
- const escapedOpen = "__VTX_ESCAPED_OPEN__";
121950
- const escapedClose = "__VTX_ESCAPED_CLOSE__";
121951
- const normalizedTemplate = template.replace(/\{\{/g, escapedOpen).replace(/\}\}/g, escapedClose);
121952
- const formatted = normalizedTemplate.replace(/\{([a-z_]+)\}/g, (_match, key) => {
121953
- if (!Object.prototype.hasOwnProperty.call(values, key)) {
121954
- throw new Error(`Unexpected positions instruction placeholder: ${key}`);
121955
- }
121956
- return String(values[key]);
121957
- });
121958
- if (/[{}]/.test(formatted)) {
121959
- throw new Error(`Invalid positions instruction template: ${template}`);
121960
- }
121961
- return formatted.replaceAll(escapedOpen, "{").replaceAll(escapedClose, "}");
122408
+ formatInstructionTemplate(
122409
+ template,
122410
+ Object.fromEntries(allowedKeys.map((key) => [key, ""])),
122411
+ "positions instruction template"
122412
+ );
121962
122413
  };
121963
122414
  validateInstructionTemplate(input.positionsInstructions.close_reduce, []);
121964
122415
  validateInstructionTemplate(input.positionsInstructions.capacity_flat, []);
@@ -122053,9 +122504,9 @@ ${reviewOutputContract}`;
122053
122504
  if (remainingGlobal <= 0) {
122054
122505
  parts.push(`${input.positionsInstructions.capacity_full} `);
122055
122506
  } else if (input.maxTradesPerPrompt < input.maxTradesGlobal && remainingGlobal < input.maxTradesPerPrompt) {
122056
- parts.push(`${formatInstructionTemplate2(input.positionsInstructions.capacity_low, {
122507
+ parts.push(`${formatInstructionTemplate(input.positionsInstructions.capacity_low, {
122057
122508
  remaining: remainingGlobal
122058
- })} `);
122509
+ }, "positions instruction template")} `);
122059
122510
  }
122060
122511
  return parts.join("\n");
122061
122512
  };
@@ -122551,6 +123002,9 @@ ${reviewOutputContract}`;
122551
123002
  const matches2 = Array.from(
122552
123003
  userPrompt.matchAll(/<behavior_state>\s*([\s\S]*?)\s*<\/behavior_state>/g)
122553
123004
  );
123005
+ if (openingTags.length === 0 && closingTags.length === 0) {
123006
+ throw new BehaviorMemoryUnavailableError();
123007
+ }
122554
123008
  if (openingTags.length !== 1 || closingTags.length !== 1 || matches2.length !== 1) {
122555
123009
  throw new CriticalBehaviorStateError();
122556
123010
  }
@@ -123533,27 +123987,6 @@ ${behaviorJson}
123533
123987
  }
123534
123988
  }
123535
123989
  };
123536
- formatTemplateWithNamedVariables = (template, values) => {
123537
- const escapedOpen = "__VTX_FMT_OPEN__";
123538
- const escapedClose = "__VTX_FMT_CLOSE__";
123539
- const prepared = String(template || "").replaceAll("{{", escapedOpen).replaceAll("}}", escapedClose);
123540
- const validatedTemplate = prepared.replace(/\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g, (_match, key) => {
123541
- if (!Object.prototype.hasOwnProperty.call(values, key)) {
123542
- throw new Error(`Missing required review template variable: ${key}`);
123543
- }
123544
- return "";
123545
- });
123546
- if (/[{}]/.test(validatedTemplate)) {
123547
- throw new Error(`Invalid review template: ${template}`);
123548
- }
123549
- const formatted = prepared.replace(/\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g, (_match, key) => {
123550
- if (!Object.prototype.hasOwnProperty.call(values, key)) {
123551
- throw new Error(`Missing required review template variable: ${key}`);
123552
- }
123553
- return String(values[key]);
123554
- });
123555
- return formatted.replaceAll(escapedOpen, "{").replaceAll(escapedClose, "}");
123556
- };
123557
123990
  carryReturnedModelCalls = (error48, attempts) => {
123558
123991
  if (!attempts.length || !error48 || typeof error48 !== "object" && typeof error48 !== "function") return error48;
123559
123992
  error48.runtimeReturnedModelCalls = attempts;
@@ -125291,7 +125724,7 @@ ${stringifyPromptJson(candlesPayload)}
125291
125724
  reviewInstructions.review_security,
125292
125725
  "review_instructions.review_security"
125293
125726
  );
125294
- const reviewOutputContract = formatTemplateWithNamedVariables(
125727
+ const reviewOutputContract = formatInstructionTemplate(
125295
125728
  reviewOutputFormat,
125296
125729
  buildDecisionInstructionVariables(reviewSymbols, reviewMaxTrades)
125297
125730
  );
@@ -125314,12 +125747,18 @@ ${reviewOutputContract}`;
125314
125747
  configuredReviewUserTemplate
125315
125748
  ) : configuredReviewUserTemplate;
125316
125749
  const renderedPrimaryUserPrompt = stringifyPromptJson(userPrompt);
125317
- const reviewUserPrompt = formatTemplateWithNamedVariables(reviewUserTemplate, {
125318
- primary_model: selectedPrimaryModel,
125319
- primary_system_prompt: stringifyPromptJson(systemPrompt),
125320
- primary_user_prompt: renderedPrimaryUserPrompt,
125321
- primary_decision_json: primaryDecisionJson
125322
- });
125750
+ let reviewUserPrompt;
125751
+ try {
125752
+ reviewUserPrompt = formatInstructionTemplate(reviewUserTemplate, {
125753
+ primary_model: selectedPrimaryModel,
125754
+ primary_system_prompt: stringifyPromptJson(systemPrompt),
125755
+ primary_user_prompt: renderedPrimaryUserPrompt,
125756
+ primary_decision_json: primaryDecisionJson
125757
+ });
125758
+ } catch (error48) {
125759
+ if (input.mode === "trader") throw new CriticalBehaviorStateError(error48);
125760
+ throw error48;
125761
+ }
125323
125762
  if (input.mode === "trader" && (reviewUserPrompt.split(renderedPrimaryUserPrompt).length - 1 !== 1 || /<\/?behavior_state\b/.test(reviewUserPrompt) || containsCompetingBehaviorStateMarkup(reviewSystemPrompt))) {
125324
125763
  throw new CriticalBehaviorStateError();
125325
125764
  }
@@ -128111,6 +128550,7 @@ var init_engine = __esm({
128111
128550
  const runtime = await this.notifyRuntimeStop(this._profileId, {
128112
128551
  keepalive: options?.keepalive === true,
128113
128552
  reason: stopReason,
128553
+ modeSwitch: options?.modeSwitch === true,
128114
128554
  killswitchTrigger: options?.killswitchTrigger ?? null,
128115
128555
  authoritativeIntent: this._remoteStopPending === "authoritative-stop" && this._pendingAuthoritativeStopDetails?.authoritativeIntent === true
128116
128556
  });
@@ -128190,7 +128630,8 @@ var init_engine = __esm({
128190
128630
  reason: effectiveRemoteStopReason,
128191
128631
  killswitchTrigger: supersedingStop?.killswitchTrigger ?? options?.killswitchTrigger ?? null,
128192
128632
  acceptDeferredStopCompletion: !remoteStopWasAuthoritativeAtDispatch,
128193
- authoritativeIntent: supersedingStop?.authoritativeIntent === true
128633
+ authoritativeIntent: supersedingStop?.authoritativeIntent === true,
128634
+ modeSwitch: !supersedingStop && options?.modeSwitch === true
128194
128635
  });
128195
128636
  this._setRuntimeStatus(runtime, "stop");
128196
128637
  appendRuntimeDebugEvent({
@@ -131735,7 +132176,8 @@ var init_engine = __esm({
131735
132176
  lastRunAt: this._lastRunAt,
131736
132177
  stopReason: options?.reason ?? null,
131737
132178
  killswitchTrigger: options?.killswitchTrigger ?? null,
131738
- authoritativeIntent: options?.authoritativeIntent === true
132179
+ authoritativeIntent: options?.authoritativeIntent === true,
132180
+ modeSwitch: options?.modeSwitch === true
131739
132181
  },
131740
132182
  {
131741
132183
  ...options,