@vtxmacro/cli 2026.10.7 → 2026.10.8
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-mcp.js +44 -13
- package/bin/vtx-service-bootstrap.js +44 -13
- package/bin/vtx-service-launcher.js +13 -8
- package/bin/vtx.js +2071 -590
- package/package.json +1 -1
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.
|
|
116
|
+
agent_cli_release_default = { package_name: "@vtxmacro/cli", package_version: "2026.10.8", 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
|
|
|
@@ -213,6 +213,9 @@ var init_runtime_policy_generated = __esm({
|
|
|
213
213
|
evidence_max_items: 32,
|
|
214
214
|
evidence_shared_read_seconds: 10
|
|
215
215
|
},
|
|
216
|
+
protective_plan_set_lock: {
|
|
217
|
+
wait_seconds: 120
|
|
218
|
+
},
|
|
216
219
|
history_evidence: {
|
|
217
220
|
device_rounds_per_beat: 6,
|
|
218
221
|
device_retry_seconds: 60
|
|
@@ -1623,7 +1626,7 @@ async function writeAtomicInferencePrivateFile(path, contents, dependencies = {}
|
|
|
1623
1626
|
throw error48;
|
|
1624
1627
|
}
|
|
1625
1628
|
}
|
|
1626
|
-
async function readInferencePrivateFile(path,
|
|
1629
|
+
async function readInferencePrivateFile(path, label2, dependencies = {}) {
|
|
1627
1630
|
const platform = dependencies.platform ?? process.platform;
|
|
1628
1631
|
const runner = dependencies.runner ?? runWindowsPrivateAcl;
|
|
1629
1632
|
const defaultRoot = dependencies.defaultRoot ?? resolve(homedir2(), ".vtx", "inference-host");
|
|
@@ -1635,7 +1638,7 @@ async function readInferencePrivateFile(path, label, dependencies = {}) {
|
|
|
1635
1638
|
throw error48;
|
|
1636
1639
|
}
|
|
1637
1640
|
if (before.isSymbolicLink() || !before.isFile()) {
|
|
1638
|
-
throw new Error(`${
|
|
1641
|
+
throw new Error(`${label2} is unsafe.`);
|
|
1639
1642
|
}
|
|
1640
1643
|
await secureExistingWindowsPath(
|
|
1641
1644
|
dirname2(path),
|
|
@@ -1649,21 +1652,21 @@ async function readInferencePrivateFile(path, label, dependencies = {}) {
|
|
|
1649
1652
|
try {
|
|
1650
1653
|
const opened = await handle.stat();
|
|
1651
1654
|
if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino || opened.size > MAX_INFERENCE_PRIVATE_FILE_BYTES || typeof process.getuid === "function" && opened.uid !== process.getuid()) {
|
|
1652
|
-
throw new Error(`${
|
|
1655
|
+
throw new Error(`${label2} changed while it was opened.`);
|
|
1653
1656
|
}
|
|
1654
1657
|
if (platform !== "win32" && (opened.mode & 63) !== 0) {
|
|
1655
|
-
throw new Error(`${
|
|
1658
|
+
throw new Error(`${label2} must have mode 0600.`);
|
|
1656
1659
|
}
|
|
1657
1660
|
return await handle.readFile("utf8");
|
|
1658
1661
|
} finally {
|
|
1659
1662
|
await handle.close();
|
|
1660
1663
|
}
|
|
1661
1664
|
}
|
|
1662
|
-
async function clearInferencePrivateFile(path,
|
|
1665
|
+
async function clearInferencePrivateFile(path, label2) {
|
|
1663
1666
|
try {
|
|
1664
1667
|
const metadata = await lstat(path);
|
|
1665
1668
|
if (metadata.isSymbolicLink() || !metadata.isFile()) {
|
|
1666
|
-
throw new Error(`${
|
|
1669
|
+
throw new Error(`${label2} is unsafe.`);
|
|
1667
1670
|
}
|
|
1668
1671
|
await secureExistingWindowsPath(dirname2(path), "directory");
|
|
1669
1672
|
await secureExistingWindowsPath(path, "file");
|
|
@@ -1785,7 +1788,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
|
|
|
1785
1788
|
}
|
|
1786
1789
|
};
|
|
1787
1790
|
}
|
|
1788
|
-
var loadInferenceReceiptDurabilityTimeoutMs, loadInferenceAgentDataRequestTimeoutMs, loadInferenceAgentCommandLockPolicy, InferenceHostProcessLockBusyError, INFERENCE_CREDENTIAL_NAMESPACE, MAX_INFERENCE_PRIVATE_FILE_BYTES, WINDOWS_PRIVATE_ACL_BROKER_SCRIPT, WINDOWS_IDENTITY_COMMAND_TIMEOUT_MS, WINDOWS_PRIVATE_ACL_BROKER_STARTUP_TIMEOUT_MS, SMALL_IDENTITY_COMMAND_TIMEOUT_MS, windowsPowerShellEnvironment, windowsPrivateAclBrokerInvocation, WindowsPrivateAclBroker, defaultWindowsPrivateAclBroker, runWindowsPrivateAcl, windowsAclCache, windowsAclIdentity, aclCacheKey, secureWindowsPrivatePath, invalidateWindowsAclCache, rebindHardenedWindowsAclAfterRename, rebindHardenedWindowsDirectoryAfterOwnedMutation, isDefaultWindowsPrivatePath, secureExistingWindowsPath, linuxProcessIdentity, windowsProcessIdentityInvocation, windowsBootIdentityInvocation, windowsProcessIdentity, darwinProcessIdentity, runSmallIdentityCommand, cachedSystemBootIdentity, readInferenceSystemBootIdentity, defaultProcessIdentity, cachedCurrentProcessIdentity, defaultCurrentProcessIdentity, readInferenceHostProcessLockStatus, processLockObservationCache, inferenceProcessIdentitiesMatch, resolveInferenceHostApiUrl, inferenceHostSupervisorServiceManifestPath, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity, inferenceHostCredentialContextPath, inferenceHostCredentialContextTransitionPath, credentialContextForConfig, WINDOWS_PRIVATE_FILE_REPLACE_ERROR_CODES, PROCESS_LOCK_PUBLICATION_GRACE_MS, PROCESS_LOCK_MAX_RECORD_BYTES, PROCESS_LOCK_GUARD_ELECTION_LEASE_MS, PROCESS_LOCK_GUARD_ELECTION_STALE_MS, PROCESS_LOCK_GUARD_ELECTION_ATTEMPTS, PROCESS_LOCK_GUARD_ELECTION_BACKOFF_MS, PROCESS_LOCK_LABEL, PROCESS_LOCK_GUARD_LABEL, sameProcessLockFile, openExclusiveProcessLockFile, inspectProcessLockFile, removeVerifiedStaleProcessLockFile, removeStaleProcessLockReclaimGuard, acquireProcessLockReclaimGuard;
|
|
1791
|
+
var loadInferenceReceiptDurabilityTimeoutMs, loadInferenceAgentDataRequestTimeoutMs, loadInferenceAgentCommandLockPolicy, InferenceHostProcessLockBusyError, INFERENCE_CREDENTIAL_NAMESPACE, MAX_INFERENCE_PRIVATE_FILE_BYTES, WINDOWS_PRIVATE_ACL_MODES, WINDOWS_PRIVATE_ACL_BROKER_SCRIPT, WINDOWS_IDENTITY_COMMAND_TIMEOUT_MS, WINDOWS_PRIVATE_ACL_BROKER_STARTUP_TIMEOUT_MS, SMALL_IDENTITY_COMMAND_TIMEOUT_MS, windowsPowerShellEnvironment, windowsPrivateAclBrokerInvocation, WindowsPrivateAclBroker, defaultWindowsPrivateAclBroker, runWindowsPrivateAcl, windowsAclCache, windowsAclIdentity, aclCacheKey, secureWindowsPrivatePath, invalidateWindowsAclCache, rebindHardenedWindowsAclAfterRename, rebindHardenedWindowsDirectoryAfterOwnedMutation, isWindowsPrivateAclVerificationFailure, isDefaultWindowsPrivatePath, secureExistingWindowsPath, linuxProcessIdentity, windowsProcessIdentityInvocation, windowsBootIdentityInvocation, windowsProcessIdentity, darwinProcessIdentity, runSmallIdentityCommand, cachedSystemBootIdentity, readInferenceSystemBootIdentity, defaultProcessIdentity, cachedCurrentProcessIdentity, defaultCurrentProcessIdentity, readInferenceHostProcessLockStatus, processLockObservationCache, inferenceProcessIdentitiesMatch, resolveInferenceHostApiUrl, inferenceHostSupervisorServiceManifestPath, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity, inferenceHostCredentialContextPath, inferenceHostCredentialContextTransitionPath, credentialContextForConfig, WINDOWS_PRIVATE_FILE_REPLACE_ERROR_CODES, PROCESS_LOCK_PUBLICATION_GRACE_MS, PROCESS_LOCK_MAX_RECORD_BYTES, PROCESS_LOCK_GUARD_ELECTION_LEASE_MS, PROCESS_LOCK_GUARD_ELECTION_STALE_MS, PROCESS_LOCK_GUARD_ELECTION_ATTEMPTS, PROCESS_LOCK_GUARD_ELECTION_BACKOFF_MS, PROCESS_LOCK_LABEL, PROCESS_LOCK_GUARD_LABEL, sameProcessLockFile, openExclusiveProcessLockFile, inspectProcessLockFile, removeVerifiedStaleProcessLockFile, removeStaleProcessLockReclaimGuard, acquireProcessLockReclaimGuard;
|
|
1789
1792
|
var init_config2 = __esm({
|
|
1790
1793
|
"lib/inference-host/config.ts"() {
|
|
1791
1794
|
"use strict";
|
|
@@ -1847,6 +1850,7 @@ var init_config2 = __esm({
|
|
|
1847
1850
|
};
|
|
1848
1851
|
INFERENCE_CREDENTIAL_NAMESPACE = "vtxmacro-insights-inference";
|
|
1849
1852
|
MAX_INFERENCE_PRIVATE_FILE_BYTES = 16 * 1024 * 1024;
|
|
1853
|
+
WINDOWS_PRIVATE_ACL_MODES = ["harden", "verify", "verify-owner", "verify-private"];
|
|
1850
1854
|
WINDOWS_PRIVATE_ACL_BROKER_SCRIPT = `$ErrorActionPreference='Stop'
|
|
1851
1855
|
$ProgressPreference='SilentlyContinue'
|
|
1852
1856
|
while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
@@ -1863,7 +1867,7 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
1863
1867
|
$kind=[string]$request.kind
|
|
1864
1868
|
$mode=[string]$request.mode
|
|
1865
1869
|
if($kind -ne 'directory' -and $kind -ne 'file') { throw 'invalid path kind' }
|
|
1866
|
-
if($mode -ne 'harden' -and $mode -ne 'verify' -and $mode -ne 'verify-owner') { throw 'invalid ACL mode' }
|
|
1870
|
+
if($mode -ne 'harden' -and $mode -ne 'verify' -and $mode -ne 'verify-owner' -and $mode -ne 'verify-private') { throw 'invalid ACL mode' }
|
|
1867
1871
|
$path=[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String([string]$request.path_b64))
|
|
1868
1872
|
if([string]::IsNullOrWhiteSpace($path) -or $path.Length -gt 32767 -or $path.Contains([char]0)) { throw 'invalid path' }
|
|
1869
1873
|
$failureStage='path_lookup'
|
|
@@ -1912,11 +1916,12 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
1912
1916
|
$owner=(New-Object Security.Principal.NTAccount($actual.Owner)).Translate([Security.Principal.SecurityIdentifier]).Value
|
|
1913
1917
|
if($owner -ne $current.Value -and ($owner -ne $admins.Value -or -not $currentIsAdmin)) { throw 'private ACL owner is invalid' }
|
|
1914
1918
|
if($mode -ne 'verify-owner') {
|
|
1915
|
-
|
|
1919
|
+
$inheritedAllowed=$mode -eq 'verify-private'
|
|
1920
|
+
if(-not $inheritedAllowed -and -not $actual.AreAccessRulesProtected) { throw 'private ACL inheritance is invalid' }
|
|
1916
1921
|
$userFull=$false
|
|
1917
1922
|
foreach($rule in $actual.Access) {
|
|
1918
1923
|
$sid=$rule.IdentityReference.Translate([Security.Principal.SecurityIdentifier]).Value
|
|
1919
|
-
if($rule.IsInherited -or $allowed -notcontains $sid -or $rule.AccessControlType -ne [Security.AccessControl.AccessControlType]::Allow) {
|
|
1924
|
+
if(($rule.IsInherited -and -not $inheritedAllowed) -or $allowed -notcontains $sid -or $rule.AccessControlType -ne [Security.AccessControl.AccessControlType]::Allow) {
|
|
1920
1925
|
throw 'private ACL contains an unauthorized access rule'
|
|
1921
1926
|
}
|
|
1922
1927
|
if($sid -eq $current.Value -and (($rule.FileSystemRights -band [Security.AccessControl.FileSystemRights]::FullControl) -eq [Security.AccessControl.FileSystemRights]::FullControl)) { $userFull=$true }
|
|
@@ -2052,9 +2057,9 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
2052
2057
|
error48.code = "ENOENT";
|
|
2053
2058
|
pending3.reject(error48);
|
|
2054
2059
|
} else {
|
|
2055
|
-
pending3.reject(new Error(
|
|
2060
|
+
pending3.reject(Object.assign(new Error(
|
|
2056
2061
|
`Windows private ACL ${pending3.mode} failed (${response.error_code}).`
|
|
2057
|
-
));
|
|
2062
|
+
), { aclStage: response.error_code }));
|
|
2058
2063
|
}
|
|
2059
2064
|
this.scheduleIdleShutdown();
|
|
2060
2065
|
}
|
|
@@ -2159,7 +2164,7 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
2159
2164
|
};
|
|
2160
2165
|
invalidateWindowsAclCache = (path) => {
|
|
2161
2166
|
for (const kind of ["file", "directory"]) {
|
|
2162
|
-
for (const mode of
|
|
2167
|
+
for (const mode of WINDOWS_PRIVATE_ACL_MODES) {
|
|
2163
2168
|
windowsAclCache.delete(aclCacheKey(path, kind, mode));
|
|
2164
2169
|
}
|
|
2165
2170
|
}
|
|
@@ -2178,7 +2183,7 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
2178
2183
|
}
|
|
2179
2184
|
invalidateWindowsAclCache(source);
|
|
2180
2185
|
invalidateWindowsAclCache(destination);
|
|
2181
|
-
for (const mode of
|
|
2186
|
+
for (const mode of WINDOWS_PRIVATE_ACL_MODES) {
|
|
2182
2187
|
windowsAclCache.set(aclCacheKey(destination, kind, mode), published);
|
|
2183
2188
|
}
|
|
2184
2189
|
};
|
|
@@ -2189,10 +2194,11 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
2189
2194
|
throw new Error("Windows private directory identity changed during atomic publication.");
|
|
2190
2195
|
}
|
|
2191
2196
|
invalidateWindowsAclCache(path);
|
|
2192
|
-
for (const mode of
|
|
2197
|
+
for (const mode of WINDOWS_PRIVATE_ACL_MODES) {
|
|
2193
2198
|
windowsAclCache.set(aclCacheKey(path, "directory", mode), current);
|
|
2194
2199
|
}
|
|
2195
2200
|
};
|
|
2201
|
+
isWindowsPrivateAclVerificationFailure = (error48) => error48?.aclStage === "acl_verification";
|
|
2196
2202
|
isDefaultWindowsPrivatePath = (path, root = resolve(homedir2(), ".vtx", "inference-host")) => {
|
|
2197
2203
|
const child = relative(root, resolve(path));
|
|
2198
2204
|
return child === "" || !child.startsWith("..") && !child.includes(":");
|
|
@@ -2421,11 +2427,11 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
2421
2427
|
inferenceHostSupervisorServiceManifestPath = (env) => `${join2(inferenceBaseDir(env), "state.json")}.service.json`;
|
|
2422
2428
|
DEFAULT_INFERENCE_HOST_INSTANCE = "default";
|
|
2423
2429
|
SAFE_INFERENCE_HOST_INSTANCE = /^[a-z0-9](?:[a-z0-9-]{0,46}[a-z0-9])?$/u;
|
|
2424
|
-
requireNamedInstancePath = (instanceName, instanceDir, rawPath,
|
|
2430
|
+
requireNamedInstancePath = (instanceName, instanceDir, rawPath, label2) => {
|
|
2425
2431
|
if (!rawPath || instanceName === DEFAULT_INFERENCE_HOST_INSTANCE) return rawPath;
|
|
2426
2432
|
const relativePath = relative(resolve(instanceDir), resolve(rawPath));
|
|
2427
2433
|
if (relativePath === ".." || relativePath.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute2(relativePath)) {
|
|
2428
|
-
throw new Error(`${
|
|
2434
|
+
throw new Error(`${label2} for a named instance must stay inside its isolated instance directory.`);
|
|
2429
2435
|
}
|
|
2430
2436
|
return rawPath;
|
|
2431
2437
|
};
|
|
@@ -2480,7 +2486,7 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
2480
2486
|
throw error48;
|
|
2481
2487
|
}
|
|
2482
2488
|
};
|
|
2483
|
-
inspectProcessLockFile = async (path,
|
|
2489
|
+
inspectProcessLockFile = async (path, label2, probes) => {
|
|
2484
2490
|
let before;
|
|
2485
2491
|
try {
|
|
2486
2492
|
before = await lstat(path);
|
|
@@ -2489,7 +2495,7 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
2489
2495
|
throw error48;
|
|
2490
2496
|
}
|
|
2491
2497
|
if (before.isSymbolicLink() || !before.isFile() || process.platform !== "win32" && (before.mode & 63) !== 0 || typeof process.getuid === "function" && before.uid !== process.getuid()) {
|
|
2492
|
-
throw new Error(`${
|
|
2498
|
+
throw new Error(`${label2} is unsafe.`);
|
|
2493
2499
|
}
|
|
2494
2500
|
let handle;
|
|
2495
2501
|
try {
|
|
@@ -2736,7 +2742,7 @@ __export(updater_exports, {
|
|
|
2736
2742
|
});
|
|
2737
2743
|
import { spawn as spawn2 } from "node:child_process";
|
|
2738
2744
|
import { createHash, randomUUID } from "node:crypto";
|
|
2739
|
-
import { access, appendFile, chmod, lstat as lstat2,
|
|
2745
|
+
import { access, appendFile, chmod, lstat as lstat2, readFile as readFile3, readdir as readdir3, realpath as realpath2, rename as rename2, rm as rm3 } from "node:fs/promises";
|
|
2740
2746
|
import { constants as osConstants, homedir as homedir3 } from "node:os";
|
|
2741
2747
|
import { dirname as dirname3, isAbsolute as isAbsolute3, join as join3, relative as relative2, resolve as resolve2, win32 as windowsPath2 } from "node:path";
|
|
2742
2748
|
var CLI_PACKAGE_NAME, OFFICIAL_NPM_REGISTRY, CLI_UPDATE_COMMAND, parseCliReleaseVersion, compareCliReleaseVersions, isPathWithin, defaultRunCliCommand, runCliReleaseNpmCommand, fetchLatestCliRelease, verifyCliReleaseIntegrity, verifyInstalledCliRelease, cleanupInterruptedReleaseStaging, ensureUpdaterPrivateDirectory, stageCliRelease, stageCliReleaseWithin, readCliReleaseRejection, writeCliReleaseRejection, CLI_BACKGROUND_STAGE_ARGUMENT, READY_MESSAGE_TYPE, CHILD_ENV, READY_PROTOCOL_ENV, EMPTY_STATE, resolveCliUpdatePaths, cliAutoUpdateDisabled, resolveRegistry, validSelection, readState, writeState, appendCliUpdateLog, isSkippedInvocation, isVersionQuery, policyApiUrl, fetchMinimumSupportedVersion, classifyCliInstall, refusal, inferenceHostServiceManifestPaths, prune, stageAndSelect, planCliEntryUpdate, spawnBackgroundStage, runCliBackgroundStage, installStopTracker, runReleaseProcess, reportCliEntryReady, markConfirmed, ROLLBACK_SKIPPED, rollBack, finishRollBack, INTERRUPTED_EXIT_CODE, superviseRuntime, releaseEntryScript, runCliEntry, RUNTIME_RESTART_FOR_UPDATE_EXIT_CODE, RUNTIME_SUPERVISED_ENV, RUNTIME_RESUME_ENV, RUNTIME_SUPERVISOR_PID_ENV, RUNTIME_RESUME_FILE_ENV, runtimeResumeFile, parseRuntimeResumeRecord, readRuntimeResume, writeRuntimeResume, clearRuntimeResume, isSupervisableRuntimeCommand, isRuntimeResume, runtimeRestartEligible, pollRuntimeRelease, createRuntimeRestartCheck;
|
|
@@ -2872,7 +2878,32 @@ var init_updater = __esm({
|
|
|
2872
2878
|
};
|
|
2873
2879
|
ensureUpdaterPrivateDirectory = async (path, root, dependencies = {}) => {
|
|
2874
2880
|
const platform = dependencies.platform ?? process.platform;
|
|
2875
|
-
if (platform
|
|
2881
|
+
if (platform === "win32") {
|
|
2882
|
+
const existing = await lstat2(path).catch((error48) => {
|
|
2883
|
+
if (error48.code === "ENOENT") return null;
|
|
2884
|
+
throw error48;
|
|
2885
|
+
});
|
|
2886
|
+
if (!existing) {
|
|
2887
|
+
await ensureInferencePrivateDirectory(path, { ...dependencies, defaultRoot: root });
|
|
2888
|
+
return;
|
|
2889
|
+
}
|
|
2890
|
+
if (existing.isSymbolicLink() || !existing.isDirectory()) {
|
|
2891
|
+
throw new Error("Inference host state directory is unsafe.");
|
|
2892
|
+
}
|
|
2893
|
+
const runner = dependencies.runner ?? runWindowsPrivateAcl;
|
|
2894
|
+
try {
|
|
2895
|
+
await secureWindowsPrivatePath(path, "directory", "verify-private", platform, runner);
|
|
2896
|
+
} catch (error48) {
|
|
2897
|
+
if (!isWindowsPrivateAclVerificationFailure(error48)) throw error48;
|
|
2898
|
+
if ((await readdir3(path)).length > 0) {
|
|
2899
|
+
const recovery = /\.service-releases$/u.test(path) ? "run 'vtx inference-host service uninstall' then 'install'" : "delete this directory; it is recreated private";
|
|
2900
|
+
throw new Error(`updater_dir_not_private: ${recovery} (${path})`, { cause: error48 });
|
|
2901
|
+
}
|
|
2902
|
+
await secureWindowsPrivatePath(path, "directory", "harden", platform, runner);
|
|
2903
|
+
}
|
|
2904
|
+
return;
|
|
2905
|
+
}
|
|
2906
|
+
if (resolve2(path) === resolve2(root) || isPathWithin(root, path)) {
|
|
2876
2907
|
const existing = await lstat2(path).catch(() => null);
|
|
2877
2908
|
if (existing && existing.isDirectory() && !existing.isSymbolicLink() && (existing.mode & 63) !== 0 && (typeof process.getuid !== "function" || existing.uid === process.getuid())) {
|
|
2878
2909
|
await chmod(path, 448);
|
|
@@ -2929,8 +2960,8 @@ var init_updater = __esm({
|
|
|
2929
2960
|
} catch (error48) {
|
|
2930
2961
|
if (error48.code !== "ENOENT") throw error48;
|
|
2931
2962
|
}
|
|
2932
|
-
await
|
|
2933
|
-
await
|
|
2963
|
+
await ensureUpdaterPrivateDirectory(stagingPath, input.privateRoot, { platform });
|
|
2964
|
+
await ensureUpdaterPrivateDirectory(downloadPath, input.privateRoot, { platform });
|
|
2934
2965
|
try {
|
|
2935
2966
|
const packed = await runCliReleaseNpmCommand(executable, [
|
|
2936
2967
|
"pack",
|
|
@@ -20407,25 +20438,25 @@ var init_external_inference_contract = __esm({
|
|
|
20407
20438
|
// lib/inference-host/credential-store.ts
|
|
20408
20439
|
import { createHash as createHash2 } from "node:crypto";
|
|
20409
20440
|
import { spawn as spawn3 } from "node:child_process";
|
|
20410
|
-
function canonicalUrl(raw,
|
|
20441
|
+
function canonicalUrl(raw, label2) {
|
|
20411
20442
|
let parsed;
|
|
20412
20443
|
try {
|
|
20413
20444
|
parsed = new URL(raw);
|
|
20414
20445
|
} catch {
|
|
20415
|
-
throw new Error(`${
|
|
20446
|
+
throw new Error(`${label2} is invalid.`);
|
|
20416
20447
|
}
|
|
20417
20448
|
if (parsed.username || parsed.password || parsed.search || parsed.hash || !parsed.hostname || !["http:", "https:"].includes(parsed.protocol)) {
|
|
20418
|
-
throw new Error(`${
|
|
20449
|
+
throw new Error(`${label2} is invalid.`);
|
|
20419
20450
|
}
|
|
20420
20451
|
const isLoopback = ["localhost", "127.0.0.1", "[::1]"].includes(parsed.hostname);
|
|
20421
20452
|
if (parsed.protocol !== "https:" && !isLoopback) {
|
|
20422
|
-
throw new Error(`${
|
|
20453
|
+
throw new Error(`${label2} must use HTTPS outside loopback.`);
|
|
20423
20454
|
}
|
|
20424
20455
|
return parsed.toString().replace(/\/$/u, "");
|
|
20425
20456
|
}
|
|
20426
|
-
function isoTimestamp(value,
|
|
20457
|
+
function isoTimestamp(value, label2) {
|
|
20427
20458
|
if (typeof value !== "string" || !value || !Number.isFinite(Date.parse(value))) {
|
|
20428
|
-
throw new Error(`${
|
|
20459
|
+
throw new Error(`${label2} is invalid.`);
|
|
20429
20460
|
}
|
|
20430
20461
|
return value;
|
|
20431
20462
|
}
|
|
@@ -21396,33 +21427,33 @@ var init_crypto = __esm({
|
|
|
21396
21427
|
// lib/inference-host/oauth.ts
|
|
21397
21428
|
import { createHash as createHash4, randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
|
|
21398
21429
|
import { createServer } from "node:http";
|
|
21399
|
-
function requireObject(value,
|
|
21430
|
+
function requireObject(value, label2) {
|
|
21400
21431
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
21401
|
-
throw new Error(`${
|
|
21432
|
+
throw new Error(`${label2} is invalid.`);
|
|
21402
21433
|
}
|
|
21403
21434
|
return value;
|
|
21404
21435
|
}
|
|
21405
|
-
function exactUrl(raw,
|
|
21406
|
-
if (typeof raw !== "string" || !raw) throw new Error(`${
|
|
21436
|
+
function exactUrl(raw, label2) {
|
|
21437
|
+
if (typeof raw !== "string" || !raw) throw new Error(`${label2} is unavailable.`);
|
|
21407
21438
|
let parsed;
|
|
21408
21439
|
try {
|
|
21409
21440
|
parsed = new URL(raw);
|
|
21410
21441
|
} catch {
|
|
21411
|
-
throw new Error(`${
|
|
21442
|
+
throw new Error(`${label2} is invalid.`);
|
|
21412
21443
|
}
|
|
21413
21444
|
if (parsed.username || parsed.password || parsed.search || parsed.hash || !parsed.hostname) {
|
|
21414
|
-
throw new Error(`${
|
|
21445
|
+
throw new Error(`${label2} is invalid.`);
|
|
21415
21446
|
}
|
|
21416
21447
|
const loopback = ["localhost", "127.0.0.1", "[::1]"].includes(parsed.hostname);
|
|
21417
21448
|
if (parsed.protocol !== "https:" && !(parsed.protocol === "http:" && loopback)) {
|
|
21418
|
-
throw new Error(`${
|
|
21449
|
+
throw new Error(`${label2} must use HTTPS outside loopback.`);
|
|
21419
21450
|
}
|
|
21420
21451
|
return parsed.toString();
|
|
21421
21452
|
}
|
|
21422
|
-
function requireSameOrigin(endpoint, issuer,
|
|
21423
|
-
const parsed = new URL(exactUrl(endpoint,
|
|
21453
|
+
function requireSameOrigin(endpoint, issuer, label2) {
|
|
21454
|
+
const parsed = new URL(exactUrl(endpoint, label2));
|
|
21424
21455
|
if (parsed.origin !== new URL(issuer).origin) {
|
|
21425
|
-
throw new Error(`${
|
|
21456
|
+
throw new Error(`${label2} has an unexpected origin.`);
|
|
21426
21457
|
}
|
|
21427
21458
|
return parsed.toString();
|
|
21428
21459
|
}
|
|
@@ -22158,6 +22189,9 @@ var init_runtime_policy_generated2 = __esm({
|
|
|
22158
22189
|
evidence_max_items: 32,
|
|
22159
22190
|
evidence_shared_read_seconds: 10
|
|
22160
22191
|
},
|
|
22192
|
+
protective_plan_set_lock: {
|
|
22193
|
+
wait_seconds: 120
|
|
22194
|
+
},
|
|
22161
22195
|
history_evidence: {
|
|
22162
22196
|
device_rounds_per_beat: 6,
|
|
22163
22197
|
device_retry_seconds: 60
|
|
@@ -33244,10 +33278,10 @@ var init_runner = __esm({
|
|
|
33244
33278
|
if (known && (!window2 || window2.windowDurationMins !== known.windowDurationMins)) return false;
|
|
33245
33279
|
return window2 === null || window2.resetsAt !== null && window2.resetsAt * 1e3 > nowMs2 && (window2.usedPercent < 100 || codexCreditsAvailable(rateLimits.rateLimits));
|
|
33246
33280
|
});
|
|
33247
|
-
finitePositiveOption = (value, fallback,
|
|
33281
|
+
finitePositiveOption = (value, fallback, label2) => {
|
|
33248
33282
|
const result = value ?? fallback;
|
|
33249
33283
|
if (!Number.isSafeInteger(result) || result < 1) {
|
|
33250
|
-
throw new InferenceHostRunnerError("invalid_configuration", `${
|
|
33284
|
+
throw new InferenceHostRunnerError("invalid_configuration", `${label2} must be a positive integer.`);
|
|
33251
33285
|
}
|
|
33252
33286
|
return result;
|
|
33253
33287
|
};
|
|
@@ -46377,10 +46411,10 @@ Durable service:
|
|
|
46377
46411
|
vtx inference-host service recover --instance codex-1 --force-recovery
|
|
46378
46412
|
vtx inference-host service <start|stop|status|logs|recover|uninstall>
|
|
46379
46413
|
`;
|
|
46380
|
-
parseHostConcurrency = (raw,
|
|
46414
|
+
parseHostConcurrency = (raw, label2) => {
|
|
46381
46415
|
const value = Number(raw);
|
|
46382
46416
|
if (!Number.isSafeInteger(value) || value < 1) {
|
|
46383
|
-
throw new Error(`${
|
|
46417
|
+
throw new Error(`${label2} must be a positive safe integer.`);
|
|
46384
46418
|
}
|
|
46385
46419
|
return value;
|
|
46386
46420
|
};
|
|
@@ -46688,8 +46722,8 @@ Durable service:
|
|
|
46688
46722
|
throw new Error("Inference host revocation checkpoint does not match credential recovery.");
|
|
46689
46723
|
}
|
|
46690
46724
|
};
|
|
46691
|
-
fileExistsPrivately = async (path,
|
|
46692
|
-
const raw = await readInferencePrivateFile(path,
|
|
46725
|
+
fileExistsPrivately = async (path, label2) => {
|
|
46726
|
+
const raw = await readInferencePrivateFile(path, label2);
|
|
46693
46727
|
return raw !== null;
|
|
46694
46728
|
};
|
|
46695
46729
|
inspectCodexAuthentication = async (config2) => {
|
|
@@ -50232,7 +50266,7 @@ var init_shared = __esm({
|
|
|
50232
50266
|
runtimeRequestErrorKind: kind,
|
|
50233
50267
|
runtimeRequestTransientNetwork: kind === "network" && isTransientNetworkFetchError(error48)
|
|
50234
50268
|
});
|
|
50235
|
-
buildMarketDataFetchError = async (response,
|
|
50269
|
+
buildMarketDataFetchError = async (response, label2, path) => {
|
|
50236
50270
|
let responseText = "";
|
|
50237
50271
|
try {
|
|
50238
50272
|
responseText = (await response.clone().text()).trim();
|
|
@@ -50242,21 +50276,21 @@ var init_shared = __esm({
|
|
|
50242
50276
|
const statusText = response.statusText ? ` ${response.statusText}` : "";
|
|
50243
50277
|
const detail = responseText ? `: ${responseText.slice(0, 240)}` : "";
|
|
50244
50278
|
return annotateMarketDataRequestError(
|
|
50245
|
-
new Error(`Market data request failed: ${
|
|
50279
|
+
new Error(`Market data request failed: ${label2} unavailable (HTTP ${response.status}${statusText})${detail}`),
|
|
50246
50280
|
path,
|
|
50247
50281
|
response.status,
|
|
50248
50282
|
"http"
|
|
50249
50283
|
);
|
|
50250
50284
|
};
|
|
50251
|
-
buildMarketDataNetworkError = (error48,
|
|
50285
|
+
buildMarketDataNetworkError = (error48, label2, path) => {
|
|
50252
50286
|
const message = error48 instanceof Error ? error48.message : String(error48 || "unknown error");
|
|
50253
50287
|
return annotateMarketDataRequestError(Object.assign(
|
|
50254
|
-
new Error(`Market data request failed: ${
|
|
50288
|
+
new Error(`Market data request failed: ${label2} network error (${message})`),
|
|
50255
50289
|
{ cause: error48, name: error48 instanceof Error ? error48.name : "Error" }
|
|
50256
50290
|
), path, null, "network");
|
|
50257
50291
|
};
|
|
50258
|
-
buildMarketDataResponseBodyError = (error48,
|
|
50259
|
-
new Error(`Market data request failed: ${
|
|
50292
|
+
buildMarketDataResponseBodyError = (error48, label2, response, path) => annotateMarketDataRequestError(Object.assign(
|
|
50293
|
+
new Error(`Market data request failed: ${label2} response body could not be read (HTTP ${response.status})`),
|
|
50260
50294
|
{ cause: error48, name: error48 instanceof Error ? error48.name : "Error" }
|
|
50261
50295
|
), path, response.status, "response_body");
|
|
50262
50296
|
isTransientNetworkFetchError = (error48) => {
|
|
@@ -51171,10 +51205,10 @@ var init_network_debug = __esm({
|
|
|
51171
51205
|
};
|
|
51172
51206
|
getLatestRuntimeProviderFailureTelemetrySnapshot = (options = {}) => {
|
|
51173
51207
|
const maxAgeMs = Number.isFinite(Number(options.maxAgeMs)) ? Math.max(0, Number(options.maxAgeMs)) : 5 * 60 * 1e3;
|
|
51174
|
-
const
|
|
51208
|
+
const label2 = typeof options.label === "string" && options.label.trim() ? options.label.trim().toLowerCase() : null;
|
|
51175
51209
|
const traceId = typeof options.traceId === "string" && options.traceId.trim() ? options.traceId.trim() : null;
|
|
51176
51210
|
const now = Date.now();
|
|
51177
|
-
const candidates = getRuntimeProviderFailureDebugEntries().filter((entry) => entry.kind === "provider" && entry.outcome === "error").filter((entry) => !traceId || entry.id === traceId).filter((entry) => !
|
|
51211
|
+
const candidates = getRuntimeProviderFailureDebugEntries().filter((entry) => entry.kind === "provider" && entry.outcome === "error").filter((entry) => !traceId || entry.id === traceId).filter((entry) => !label2 || entry.label.toLowerCase() === label2).filter((entry) => Math.abs(now - (entry.completedAt ?? entry.startedAt)) <= maxAgeMs).sort((a, b2) => (b2.completedAt ?? b2.startedAt) - (a.completedAt ?? a.startedAt));
|
|
51178
51212
|
const latest = candidates[0] ?? null;
|
|
51179
51213
|
if (!latest) {
|
|
51180
51214
|
return null;
|
|
@@ -52072,6 +52106,288 @@ var init_server_runtime_lease = __esm({
|
|
|
52072
52106
|
}
|
|
52073
52107
|
});
|
|
52074
52108
|
|
|
52109
|
+
// lib/runtime/hyperliquid-account-mode-contract.ts
|
|
52110
|
+
function resolveExactHyperliquidAccountMode(userAbstraction, ...dexEvidence) {
|
|
52111
|
+
const mode = extractCanonicalHyperliquidAccountMode(userAbstraction);
|
|
52112
|
+
if (!mode) {
|
|
52113
|
+
throw new Error("Exact Hyperliquid userAbstraction response is invalid.");
|
|
52114
|
+
}
|
|
52115
|
+
if (mode !== "default" && mode !== "disabled") return mode;
|
|
52116
|
+
if (dexEvidence.length < 1) {
|
|
52117
|
+
throw new Error("Exact Hyperliquid userDexAbstraction response is unavailable.");
|
|
52118
|
+
}
|
|
52119
|
+
return parseExactDexAbstractionEnabled(dexEvidence[0]) ? "dexAbstraction" : mode;
|
|
52120
|
+
}
|
|
52121
|
+
var UNIFIED_MODE_ALIASES, CANONICAL_ACCOUNT_MODE_ALIASES, EXACT_MODE_KEYS, EXACT_MODE_BOOLEAN_KEYS, isExactTruthyFlag, normalizeCanonicalHyperliquidAccountMode, extractCanonicalHyperliquidAccountMode, parseExactDexAbstractionEnabled, normalizeAccountMode, extractAccountModeFromPayload, extractAccountModeCandidateFromPayload, isUnifiedAccountMode;
|
|
52122
|
+
var init_hyperliquid_account_mode_contract = __esm({
|
|
52123
|
+
"lib/runtime/hyperliquid-account-mode-contract.ts"() {
|
|
52124
|
+
"use strict";
|
|
52125
|
+
init_define_VTX_EXO_POLICY();
|
|
52126
|
+
init_define_VTX_GROK_POLICY();
|
|
52127
|
+
init_define_VTX_PI_MODEL_POLICY();
|
|
52128
|
+
UNIFIED_MODE_ALIASES = /* @__PURE__ */ new Set([
|
|
52129
|
+
"unifiedaccount",
|
|
52130
|
+
"dexabstraction",
|
|
52131
|
+
"portfoliomargin",
|
|
52132
|
+
"unified",
|
|
52133
|
+
"pm"
|
|
52134
|
+
]);
|
|
52135
|
+
CANONICAL_ACCOUNT_MODE_ALIASES = /* @__PURE__ */ new Map([
|
|
52136
|
+
["default", "default"],
|
|
52137
|
+
["standard", "default"],
|
|
52138
|
+
["classic", "default"],
|
|
52139
|
+
["disabled", "disabled"],
|
|
52140
|
+
["unifiedaccount", "unifiedAccount"],
|
|
52141
|
+
["unified", "unifiedAccount"],
|
|
52142
|
+
["portfoliomargin", "portfolioMargin"],
|
|
52143
|
+
["pm", "portfolioMargin"],
|
|
52144
|
+
["dexabstraction", "dexAbstraction"]
|
|
52145
|
+
]);
|
|
52146
|
+
EXACT_MODE_KEYS = [
|
|
52147
|
+
"accountMode",
|
|
52148
|
+
"account_mode",
|
|
52149
|
+
"accountType",
|
|
52150
|
+
"account_type",
|
|
52151
|
+
"accountUnificationMode",
|
|
52152
|
+
"account_unification_mode",
|
|
52153
|
+
"abstractionMode",
|
|
52154
|
+
"abstraction_mode",
|
|
52155
|
+
"abstraction",
|
|
52156
|
+
"abstractionState",
|
|
52157
|
+
"dexAbstractionState",
|
|
52158
|
+
"marginMode",
|
|
52159
|
+
"state",
|
|
52160
|
+
"mode",
|
|
52161
|
+
"value"
|
|
52162
|
+
];
|
|
52163
|
+
EXACT_MODE_BOOLEAN_KEYS = [
|
|
52164
|
+
["unifiedAccount", ["isUnifiedAccount", "unifiedAccount", "isUnified", "unified", "is_unified_account"]],
|
|
52165
|
+
["portfolioMargin", ["isPortfolioMargin", "portfolioMargin", "isPm", "pm", "is_portfolio_margin"]],
|
|
52166
|
+
["dexAbstraction", ["isDexAbstraction", "dexAbstraction", "dexAbstractionEnabled", "is_dex_abstraction"]],
|
|
52167
|
+
["default", ["isClassic", "classic", "isStandard", "standard"]]
|
|
52168
|
+
];
|
|
52169
|
+
isExactTruthyFlag = (value) => value === true || value === 1 || typeof value === "string" && value.trim().toLowerCase() === "true";
|
|
52170
|
+
normalizeCanonicalHyperliquidAccountMode = (value) => {
|
|
52171
|
+
if (typeof value !== "string") return null;
|
|
52172
|
+
const key = value.trim().replace(/[_\s-]/g, "").toLowerCase();
|
|
52173
|
+
return CANONICAL_ACCOUNT_MODE_ALIASES.get(key) ?? null;
|
|
52174
|
+
};
|
|
52175
|
+
extractCanonicalHyperliquidAccountMode = (payload, depth = 0) => {
|
|
52176
|
+
if (depth > 6) return null;
|
|
52177
|
+
const direct = normalizeCanonicalHyperliquidAccountMode(payload);
|
|
52178
|
+
if (direct) return direct;
|
|
52179
|
+
if (Array.isArray(payload)) {
|
|
52180
|
+
for (const item of payload) {
|
|
52181
|
+
const mode = extractCanonicalHyperliquidAccountMode(item, depth + 1);
|
|
52182
|
+
if (mode) return mode;
|
|
52183
|
+
}
|
|
52184
|
+
return null;
|
|
52185
|
+
}
|
|
52186
|
+
if (!payload || typeof payload !== "object") return null;
|
|
52187
|
+
const source = payload;
|
|
52188
|
+
for (const key of EXACT_MODE_KEYS) {
|
|
52189
|
+
if (!(key in source)) continue;
|
|
52190
|
+
const mode = normalizeCanonicalHyperliquidAccountMode(source[key]);
|
|
52191
|
+
if (mode) return mode;
|
|
52192
|
+
}
|
|
52193
|
+
for (const [mode, keys] of EXACT_MODE_BOOLEAN_KEYS) {
|
|
52194
|
+
for (const key of keys) {
|
|
52195
|
+
if (isExactTruthyFlag(source[key])) return mode;
|
|
52196
|
+
}
|
|
52197
|
+
}
|
|
52198
|
+
for (const value of Object.values(source)) {
|
|
52199
|
+
const mode = extractCanonicalHyperliquidAccountMode(value, depth + 1);
|
|
52200
|
+
if (mode) return mode;
|
|
52201
|
+
}
|
|
52202
|
+
return null;
|
|
52203
|
+
};
|
|
52204
|
+
parseExactDexAbstractionEnabled = (payload) => {
|
|
52205
|
+
if (payload == null || payload === false) return false;
|
|
52206
|
+
if (payload === true) return true;
|
|
52207
|
+
if (typeof payload === "string") {
|
|
52208
|
+
const normalized = payload.trim().toLowerCase();
|
|
52209
|
+
if (normalized === "true") return true;
|
|
52210
|
+
if (normalized === "false") return false;
|
|
52211
|
+
}
|
|
52212
|
+
if (typeof payload === "number" && Number.isFinite(payload)) {
|
|
52213
|
+
if (payload === 1) return true;
|
|
52214
|
+
if (payload === 0) return false;
|
|
52215
|
+
}
|
|
52216
|
+
throw new Error("Exact Hyperliquid userDexAbstraction response is invalid.");
|
|
52217
|
+
};
|
|
52218
|
+
normalizeAccountMode = (mode) => String(mode ?? "").trim().toLowerCase().replace(/[_\s-]/g, "");
|
|
52219
|
+
extractAccountModeFromPayload = (payload) => {
|
|
52220
|
+
const candidate = extractAccountModeCandidateFromPayload(payload);
|
|
52221
|
+
if (candidate && candidate.trim().length > 0) {
|
|
52222
|
+
return candidate;
|
|
52223
|
+
}
|
|
52224
|
+
return "default";
|
|
52225
|
+
};
|
|
52226
|
+
extractAccountModeCandidateFromPayload = (payload) => {
|
|
52227
|
+
if (!payload || typeof payload !== "object") {
|
|
52228
|
+
return null;
|
|
52229
|
+
}
|
|
52230
|
+
const source = payload;
|
|
52231
|
+
if ("accountMode" in source) {
|
|
52232
|
+
return String(source.accountMode ?? "");
|
|
52233
|
+
}
|
|
52234
|
+
if ("account_mode" in source) {
|
|
52235
|
+
return String(source.account_mode ?? "");
|
|
52236
|
+
}
|
|
52237
|
+
return null;
|
|
52238
|
+
};
|
|
52239
|
+
isUnifiedAccountMode = (mode) => UNIFIED_MODE_ALIASES.has(normalizeAccountMode(mode));
|
|
52240
|
+
}
|
|
52241
|
+
});
|
|
52242
|
+
|
|
52243
|
+
// lib/runtime/hyperliquid-account-contract.ts
|
|
52244
|
+
var toNumber, firstNumber, roundTo, canonicalAvailableMargin, STABLE_SPOT_SYMBOLS, spotBalanceValueUsd, normalizeSpotBalancesFromInfoResponse, sumBalanceHoldUsd, sumPositionUnrealizedPnl, resolveTotalUnrealizedPnl, approximatelyEqualAccountValues, buildAccountSummaryFromInfoResponses;
|
|
52245
|
+
var init_hyperliquid_account_contract = __esm({
|
|
52246
|
+
"lib/runtime/hyperliquid-account-contract.ts"() {
|
|
52247
|
+
"use strict";
|
|
52248
|
+
init_define_VTX_EXO_POLICY();
|
|
52249
|
+
init_define_VTX_GROK_POLICY();
|
|
52250
|
+
init_define_VTX_PI_MODEL_POLICY();
|
|
52251
|
+
init_hyperliquid_account_mode_contract();
|
|
52252
|
+
toNumber = (value, fallback = 0) => {
|
|
52253
|
+
const numeric2 = Number(value);
|
|
52254
|
+
return Number.isFinite(numeric2) ? numeric2 : fallback;
|
|
52255
|
+
};
|
|
52256
|
+
firstNumber = (values, fallback = 0) => {
|
|
52257
|
+
for (const value of values) {
|
|
52258
|
+
if (value == null || typeof value === "string" && value.trim() === "") {
|
|
52259
|
+
continue;
|
|
52260
|
+
}
|
|
52261
|
+
const numeric2 = Number(value);
|
|
52262
|
+
if (Number.isFinite(numeric2)) {
|
|
52263
|
+
return numeric2;
|
|
52264
|
+
}
|
|
52265
|
+
}
|
|
52266
|
+
return fallback;
|
|
52267
|
+
};
|
|
52268
|
+
roundTo = (value, digits = 12) => Number(value.toFixed(digits));
|
|
52269
|
+
canonicalAvailableMargin = (accountValue, totalMarginUsed) => Math.max(0, accountValue - totalMarginUsed);
|
|
52270
|
+
STABLE_SPOT_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USD", "USDT"]);
|
|
52271
|
+
spotBalanceValueUsd = (balance, coin, total) => {
|
|
52272
|
+
const explicit = firstNumber([balance?.value_usd, balance?.usdValue, balance?.usdcValue], Number.NaN);
|
|
52273
|
+
if (Number.isFinite(explicit)) {
|
|
52274
|
+
return explicit;
|
|
52275
|
+
}
|
|
52276
|
+
return STABLE_SPOT_SYMBOLS.has(coin) ? total : 0;
|
|
52277
|
+
};
|
|
52278
|
+
normalizeSpotBalancesFromInfoResponse = (spotResponse) => {
|
|
52279
|
+
const containers = [];
|
|
52280
|
+
if (spotResponse && typeof spotResponse === "object") {
|
|
52281
|
+
containers.push(spotResponse);
|
|
52282
|
+
const keys = ["spotState", "userState", "clearinghouseState", "state", "data"];
|
|
52283
|
+
for (const key of keys) {
|
|
52284
|
+
if (spotResponse[key] && typeof spotResponse[key] === "object") {
|
|
52285
|
+
containers.push(spotResponse[key]);
|
|
52286
|
+
}
|
|
52287
|
+
}
|
|
52288
|
+
}
|
|
52289
|
+
const firstWithBalances = containers.find((container) => Array.isArray(container?.balances));
|
|
52290
|
+
const balances = Array.isArray(firstWithBalances?.balances) ? firstWithBalances.balances : [];
|
|
52291
|
+
return balances.map((balance) => {
|
|
52292
|
+
const coin = String(balance?.coin ?? "").toUpperCase();
|
|
52293
|
+
const total = toNumber(balance?.total, 0);
|
|
52294
|
+
const hold = toNumber(balance?.hold, 0);
|
|
52295
|
+
const available = roundTo(Math.max(0, total - hold));
|
|
52296
|
+
const value_usd = spotBalanceValueUsd(balance, coin, total);
|
|
52297
|
+
return {
|
|
52298
|
+
coin,
|
|
52299
|
+
total,
|
|
52300
|
+
hold,
|
|
52301
|
+
available,
|
|
52302
|
+
value_usd
|
|
52303
|
+
};
|
|
52304
|
+
}).filter((balance) => balance.coin.length > 0);
|
|
52305
|
+
};
|
|
52306
|
+
sumBalanceHoldUsd = (balances) => balances.reduce((acc, balance) => {
|
|
52307
|
+
const hold = toNumber(balance.hold, 0);
|
|
52308
|
+
const total = toNumber(balance.total, 0);
|
|
52309
|
+
const valueUsd = toNumber(balance.value_usd, 0);
|
|
52310
|
+
if (hold <= 0 || total <= 0 || valueUsd <= 0) {
|
|
52311
|
+
return acc;
|
|
52312
|
+
}
|
|
52313
|
+
return acc + Math.max(0, valueUsd * (hold / total));
|
|
52314
|
+
}, 0);
|
|
52315
|
+
sumPositionUnrealizedPnl = (perpsResponse) => {
|
|
52316
|
+
const assetPositions = Array.isArray(perpsResponse?.assetPositions) ? perpsResponse.assetPositions : [];
|
|
52317
|
+
return assetPositions.reduce((total, entry) => {
|
|
52318
|
+
const unrealizedPnl = toNumber(entry?.position?.unrealizedPnl, 0);
|
|
52319
|
+
return total + unrealizedPnl;
|
|
52320
|
+
}, 0);
|
|
52321
|
+
};
|
|
52322
|
+
resolveTotalUnrealizedPnl = (perpsResponse) => {
|
|
52323
|
+
const topLevel = toNumber(perpsResponse?.totalUnrealizedPnl, 0);
|
|
52324
|
+
const positionTotal = sumPositionUnrealizedPnl(perpsResponse);
|
|
52325
|
+
if (Math.abs(topLevel) < 1e-12 && Math.abs(positionTotal) >= 1e-12) {
|
|
52326
|
+
return positionTotal;
|
|
52327
|
+
}
|
|
52328
|
+
return topLevel;
|
|
52329
|
+
};
|
|
52330
|
+
approximatelyEqualAccountValues = (left, right, absoluteToleranceUsd, relativeTolerance) => {
|
|
52331
|
+
const reference = Math.max(Math.abs(left), Math.abs(right), 1);
|
|
52332
|
+
return Math.abs(left - right) <= Math.max(
|
|
52333
|
+
absoluteToleranceUsd,
|
|
52334
|
+
reference * relativeTolerance
|
|
52335
|
+
);
|
|
52336
|
+
};
|
|
52337
|
+
buildAccountSummaryFromInfoResponses = (perpsResponse, spotResponse, options = {}) => {
|
|
52338
|
+
const marginSummary = perpsResponse?.marginSummary ?? {};
|
|
52339
|
+
const perpsAccountValue = toNumber(marginSummary?.accountValue, 0);
|
|
52340
|
+
const total_margin_used = toNumber(marginSummary?.totalMarginUsed, 0);
|
|
52341
|
+
const totalNtlPos = toNumber(marginSummary?.totalNtlPos, 0);
|
|
52342
|
+
const withdrawable = toNumber(perpsResponse?.withdrawable, 0);
|
|
52343
|
+
const maintenance_margin = firstNumber([
|
|
52344
|
+
perpsResponse?.crossMaintenanceMarginUsed,
|
|
52345
|
+
marginSummary?.crossMaintenanceMarginUsed,
|
|
52346
|
+
marginSummary?.totalMaintenanceMargin
|
|
52347
|
+
], 0);
|
|
52348
|
+
const balances = normalizeSpotBalancesFromInfoResponse(spotResponse);
|
|
52349
|
+
const spotPortfolioValue = balances.reduce((acc, balance) => acc + toNumber(balance.value_usd, 0), 0);
|
|
52350
|
+
const balancesHoldUsd = sumBalanceHoldUsd(balances);
|
|
52351
|
+
const account_mode = extractAccountModeFromPayload(perpsResponse);
|
|
52352
|
+
const crossMarginSummary = perpsResponse?.crossMarginSummary && typeof perpsResponse.crossMarginSummary === "object" ? perpsResponse.crossMarginSummary : null;
|
|
52353
|
+
const crossMarginAccountValue = crossMarginSummary ? toNumber(crossMarginSummary.accountValue, 0) : 0;
|
|
52354
|
+
const normalizedMode = String(account_mode || "").trim().toLowerCase().replace(/[_\s-]/g, "");
|
|
52355
|
+
const isAmbiguousDefaultMode = normalizedMode.length === 0 || normalizedMode === "default";
|
|
52356
|
+
const spotDominatesMinTotalUsd = Number(options.spotDominatesMinTotalUsd ?? options.spot_dominates_min_total_usd);
|
|
52357
|
+
const spotDominatesPerpsMultiplier = Number(options.spotDominatesPerpsMultiplier ?? options.spot_dominates_perps_multiplier);
|
|
52358
|
+
const mirroredAccountValueAbsoluteToleranceUsd = Number(
|
|
52359
|
+
options.mirroredAccountValueAbsoluteToleranceUsd ?? options.mirrored_account_value_absolute_tolerance_usd
|
|
52360
|
+
);
|
|
52361
|
+
const mirroredAccountValueRelativeTolerance = Number(
|
|
52362
|
+
options.mirroredAccountValueRelativeTolerance ?? options.mirrored_account_value_relative_tolerance
|
|
52363
|
+
);
|
|
52364
|
+
const hasSpotDominanceThresholds = Number.isFinite(spotDominatesMinTotalUsd) && spotDominatesMinTotalUsd >= 0 && Number.isFinite(spotDominatesPerpsMultiplier) && spotDominatesPerpsMultiplier >= 0;
|
|
52365
|
+
const hasMirroredAccountValueTolerances = Number.isFinite(mirroredAccountValueAbsoluteToleranceUsd) && mirroredAccountValueAbsoluteToleranceUsd >= 0 && Number.isFinite(mirroredAccountValueRelativeTolerance) && mirroredAccountValueRelativeTolerance >= 0;
|
|
52366
|
+
const spotDominatesPerps = hasSpotDominanceThresholds && spotPortfolioValue >= spotDominatesMinTotalUsd && (perpsAccountValue <= 0 || spotPortfolioValue >= perpsAccountValue * spotDominatesPerpsMultiplier);
|
|
52367
|
+
const ambiguousDefaultLooksUnified = isAmbiguousDefaultMode && spotDominatesPerps;
|
|
52368
|
+
const ambiguousDefaultSpotAlreadyIncludesPerps = ambiguousDefaultLooksUnified && perpsAccountValue > 0 && balancesHoldUsd > 0 && hasMirroredAccountValueTolerances && approximatelyEqualAccountValues(
|
|
52369
|
+
balancesHoldUsd,
|
|
52370
|
+
perpsAccountValue,
|
|
52371
|
+
mirroredAccountValueAbsoluteToleranceUsd,
|
|
52372
|
+
mirroredAccountValueRelativeTolerance
|
|
52373
|
+
);
|
|
52374
|
+
const account_value = isUnifiedAccountMode(account_mode) && crossMarginSummary !== null && crossMarginAccountValue > 0 ? crossMarginAccountValue + spotPortfolioValue : ambiguousDefaultLooksUnified && !ambiguousDefaultSpotAlreadyIncludesPerps ? perpsAccountValue + spotPortfolioValue : Math.max(perpsAccountValue, spotPortfolioValue);
|
|
52375
|
+
return {
|
|
52376
|
+
account_value,
|
|
52377
|
+
total_margin_used,
|
|
52378
|
+
available_margin: roundTo(canonicalAvailableMargin(account_value, total_margin_used)),
|
|
52379
|
+
withdrawable,
|
|
52380
|
+
cross_margin_ratio: account_value > 0 ? maintenance_margin / account_value : 0,
|
|
52381
|
+
maintenance_margin,
|
|
52382
|
+
cross_account_leverage: account_value > 0 ? totalNtlPos / account_value : 0,
|
|
52383
|
+
total_unrealized_pnl: resolveTotalUnrealizedPnl(perpsResponse),
|
|
52384
|
+
account_mode,
|
|
52385
|
+
balances
|
|
52386
|
+
};
|
|
52387
|
+
};
|
|
52388
|
+
}
|
|
52389
|
+
});
|
|
52390
|
+
|
|
52075
52391
|
// lib/runtime/order-identity.ts
|
|
52076
52392
|
var clientOrderIdForMutation, clientDecisionMutationId;
|
|
52077
52393
|
var init_order_identity = __esm({
|
|
@@ -52147,7 +52463,7 @@ var init_hyperliquid_order_status = __esm({
|
|
|
52147
52463
|
});
|
|
52148
52464
|
|
|
52149
52465
|
// lib/runtime/hyperliquid-public-read.ts
|
|
52150
|
-
var policy, weights, recoveryPolicy, budgets, unpersistedBudgets, cache, pending2, PREFIX, priorityRank, createHyperliquidPublicPriorityScope, promoteHyperliquidPublicPriority, abortError2, checkAbort, wait, waitUnlessPromoted, storage, loadBudget, saveBudget, withBudgetLock, HyperliquidPublicReadError, getHyperliquidPublicReadBudget, cooldownError, recoveryWaitError, nonTradingWeightCap, nonTradingWaitMs, fallbackDelayMs, admit, cooldown, finishHyperliquidRecoveryRequest, assertHyperliquidRecoveryDispatch, cacheTtlMs, eligibleCache, reserveHyperliquidPublicReads, releaseHyperliquidPublicReadReservation, admitHyperliquidExchangeRequest, recordHyperliquidExchangeResponse, readHyperliquidPublicInfo;
|
|
52466
|
+
var policy, weights, recoveryPolicy, budgets, unpersistedBudgets, cache, pending2, PREFIX, priorityRank, createHyperliquidPublicPriorityScope, promoteHyperliquidPublicPriority, hostTransport, abortError2, checkAbort, wait, waitUnlessPromoted, storage, loadBudget, saveBudget, withBudgetLock, HyperliquidPublicReadError, getHyperliquidPublicReadBudget, cooldownError, recoveryWaitError, nonTradingWeightCap, nonTradingWaitMs, fallbackDelayMs, admit, cooldown, finishHyperliquidRecoveryRequest, assertHyperliquidRecoveryDispatch, validateHyperliquidRecoveryDispatch, cacheTtlMs, eligibleCache, reserveHyperliquidPublicReads, releaseHyperliquidPublicReadReservation, admitHyperliquidExchangeRequest, recordHyperliquidExchangeResponse, readHyperliquidPublicInfo;
|
|
52151
52467
|
var init_hyperliquid_public_read = __esm({
|
|
52152
52468
|
"lib/runtime/hyperliquid-public-read.ts"() {
|
|
52153
52469
|
"use strict";
|
|
@@ -52171,6 +52487,7 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52171
52487
|
scope.value = priority;
|
|
52172
52488
|
scope.followers?.forEach((promote) => promote(priority));
|
|
52173
52489
|
};
|
|
52490
|
+
hostTransport = null;
|
|
52174
52491
|
abortError2 = (signal) => getSanitizedRuntimeAbortReason(signal, "Aborted");
|
|
52175
52492
|
checkAbort = (signal) => {
|
|
52176
52493
|
if (signal?.aborted) throw abortError2(signal);
|
|
@@ -52308,6 +52625,10 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52308
52625
|
const weight = weightOverride ?? weights[requestType] ?? policy.default_request_weight;
|
|
52309
52626
|
const ticket = crypto.randomUUID();
|
|
52310
52627
|
const deadline = Math.min(deadlineMs ?? Infinity, Date.now() + recoveryPolicy.recovery_queue_wait_seconds * 1e3);
|
|
52628
|
+
if (hostTransport) {
|
|
52629
|
+
const permit = await hostTransport.admission.acquire({ requestType, weight, priority: priority.value, deadlineMs: deadline, signal });
|
|
52630
|
+
return { ...permit, endpoint: apiUrl, fleet: true };
|
|
52631
|
+
}
|
|
52311
52632
|
let admitted = false;
|
|
52312
52633
|
try {
|
|
52313
52634
|
for (; ; ) {
|
|
@@ -52378,7 +52699,11 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52378
52699
|
});
|
|
52379
52700
|
}
|
|
52380
52701
|
};
|
|
52381
|
-
cooldown = async (apiUrl, retryAfter) => {
|
|
52702
|
+
cooldown = async (apiUrl, retryAfter, requestType) => {
|
|
52703
|
+
if (hostTransport) {
|
|
52704
|
+
await hostTransport.admission.record429(retryAfter, requestType);
|
|
52705
|
+
return;
|
|
52706
|
+
}
|
|
52382
52707
|
const key = `${PREFIX}${apiUrl}`;
|
|
52383
52708
|
await withBudgetLock(key, void 0, () => {
|
|
52384
52709
|
const now = Date.now();
|
|
@@ -52404,6 +52729,11 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52404
52729
|
};
|
|
52405
52730
|
finishHyperliquidRecoveryRequest = async (permit, outcome) => {
|
|
52406
52731
|
if (!permit) return;
|
|
52732
|
+
if (permit.fleet) {
|
|
52733
|
+
if (!hostTransport) throw new Error("A fleet Hyperliquid permit needs the host transport that issued it.");
|
|
52734
|
+
await hostTransport.admission.finish(permit, outcome);
|
|
52735
|
+
return;
|
|
52736
|
+
}
|
|
52407
52737
|
const key = `${PREFIX}${permit.endpoint}`;
|
|
52408
52738
|
await withBudgetLock(key, void 0, () => {
|
|
52409
52739
|
const budget = loadBudget(key);
|
|
@@ -52440,6 +52770,15 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52440
52770
|
}
|
|
52441
52771
|
if (!permit && budget.recovery) throw recoveryWaitError(requestType);
|
|
52442
52772
|
};
|
|
52773
|
+
validateHyperliquidRecoveryDispatch = async (endpoint, permit, requestType) => {
|
|
52774
|
+
if (permit?.fleet) {
|
|
52775
|
+
if (!hostTransport) throw recoveryWaitError(requestType);
|
|
52776
|
+
await hostTransport.admission.validate(permit, requestType);
|
|
52777
|
+
return;
|
|
52778
|
+
}
|
|
52779
|
+
if (hostTransport) throw recoveryWaitError(requestType);
|
|
52780
|
+
assertHyperliquidRecoveryDispatch(endpoint, permit, requestType);
|
|
52781
|
+
};
|
|
52443
52782
|
cacheTtlMs = (body, options) => {
|
|
52444
52783
|
const requestType = String(body.type);
|
|
52445
52784
|
return (["meta", "spotMeta", "perpDexs"].includes(requestType) ? policy.metadata_ttl_seconds : requestType === "userFees" ? policy.user_fees_ttl_seconds : options.cacheAccountMode && ["userAbstraction", "userDexAbstraction"].includes(requestType) ? policy.account_mode_ttl_seconds : 0) * 1e3;
|
|
@@ -52469,7 +52808,7 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52469
52808
|
return admit(endpoint.replace(/\/$/, ""), "exchange", signal, weight, void 0, createHyperliquidPublicPriorityScope(priority));
|
|
52470
52809
|
};
|
|
52471
52810
|
recordHyperliquidExchangeResponse = async (endpoint, response, permit) => {
|
|
52472
|
-
if (response.status === 429) await cooldown(endpoint.replace(/\/$/, ""), response.headers.get("Retry-After"));
|
|
52811
|
+
if (response.status === 429) await cooldown(endpoint.replace(/\/$/, ""), response.headers.get("Retry-After"), "exchange");
|
|
52473
52812
|
await finishHyperliquidRecoveryRequest(permit, response.status < 400 ? "success" : "failure");
|
|
52474
52813
|
};
|
|
52475
52814
|
readHyperliquidPublicInfo = async (endpoint, body, options) => {
|
|
@@ -52503,6 +52842,7 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52503
52842
|
let settled;
|
|
52504
52843
|
let acquiring = false;
|
|
52505
52844
|
let observedRateLimit;
|
|
52845
|
+
let privateRouteUsed = false;
|
|
52506
52846
|
let pendingPhase = null;
|
|
52507
52847
|
const setPendingPhase = (next) => {
|
|
52508
52848
|
if (next === pendingPhase) return;
|
|
@@ -52547,14 +52887,18 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52547
52887
|
}), priority });
|
|
52548
52888
|
}
|
|
52549
52889
|
if (options.reservation?.closed) throw new DOMException("Hyperliquid account read was cancelled.", "AbortError");
|
|
52550
|
-
|
|
52551
|
-
|
|
52552
|
-
|
|
52553
|
-
|
|
52554
|
-
|
|
52555
|
-
|
|
52556
|
-
|
|
52557
|
-
|
|
52890
|
+
const privateRoute = await hostTransport?.routeInfo?.(body, priority.value, deadline) ?? null;
|
|
52891
|
+
privateRouteUsed = privateRoute !== null;
|
|
52892
|
+
if (!privateRoute) {
|
|
52893
|
+
acquiring = true;
|
|
52894
|
+
setPendingPhase("admission");
|
|
52895
|
+
permit = await admit(apiUrl, requestType, signal, void 0, deadline, priority);
|
|
52896
|
+
acquiring = false;
|
|
52897
|
+
armDeadline(Math.min(deadline, permit?.expiresAt ?? Infinity));
|
|
52898
|
+
checkAbort(signal);
|
|
52899
|
+
if (options.reservation?.closed) throw new DOMException("Hyperliquid account read was cancelled.", "AbortError");
|
|
52900
|
+
await validateHyperliquidRecoveryDispatch(apiUrl, permit, requestType);
|
|
52901
|
+
}
|
|
52558
52902
|
outcome = "failure";
|
|
52559
52903
|
let transportAborted;
|
|
52560
52904
|
let response;
|
|
@@ -52567,16 +52911,16 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52567
52911
|
});
|
|
52568
52912
|
const transport = (async () => {
|
|
52569
52913
|
setPendingPhase("transport");
|
|
52570
|
-
const received = await fetch(`${apiUrl}/info`, {
|
|
52914
|
+
const received = await fetch(`${privateRoute?.url.replace(/\/$/, "") ?? apiUrl}/info`, {
|
|
52571
52915
|
method: "POST",
|
|
52572
|
-
headers: { "Content-Type": "application/json" },
|
|
52916
|
+
headers: { ...privateRoute?.headers, "Content-Type": "application/json" },
|
|
52573
52917
|
body: JSON.stringify(body),
|
|
52574
52918
|
signal
|
|
52575
52919
|
});
|
|
52576
52920
|
checkAbort(signal);
|
|
52577
52921
|
if (received.status === 429) {
|
|
52578
52922
|
observedRateLimit = new HyperliquidPublicReadError("public_rate_limited", "Hyperliquid public API returned HTTP 429.", requestType, 429);
|
|
52579
|
-
await cooldown(apiUrl, received.headers.get("Retry-After"));
|
|
52923
|
+
if (!privateRoute) await cooldown(apiUrl, received.headers.get("Retry-After"), requestType);
|
|
52580
52924
|
throw observedRateLimit;
|
|
52581
52925
|
}
|
|
52582
52926
|
let receivedText;
|
|
@@ -52623,6 +52967,13 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52623
52967
|
outcome = "cancelled";
|
|
52624
52968
|
throw abortError2(options.signal);
|
|
52625
52969
|
}
|
|
52970
|
+
const failedStatus = error48?.status;
|
|
52971
|
+
if (outcome === "failure" && privateRouteUsed && !(typeof failedStatus === "number" && failedStatus < 500)) {
|
|
52972
|
+
try {
|
|
52973
|
+
hostTransport?.onPrivateInfoFailure?.(body);
|
|
52974
|
+
} catch {
|
|
52975
|
+
}
|
|
52976
|
+
}
|
|
52626
52977
|
if (acquiring && signal.aborted && signal.reason?.name === "TimeoutError") throw recoveryWaitError(requestType);
|
|
52627
52978
|
if (error48 instanceof HyperliquidPublicReadError) throw error48;
|
|
52628
52979
|
if (error48 instanceof TypeError) throw new HyperliquidPublicReadError("public_network_error", "Hyperliquid public request network failure.", requestType);
|
|
@@ -52646,6 +52997,32 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52646
52997
|
}
|
|
52647
52998
|
});
|
|
52648
52999
|
|
|
53000
|
+
// lib/runtime/hyperliquid-exchange-rejections.ts
|
|
53001
|
+
var listeners, onHyperliquidExchangeRejection, emitHyperliquidExchangeRejection;
|
|
53002
|
+
var init_hyperliquid_exchange_rejections = __esm({
|
|
53003
|
+
"lib/runtime/hyperliquid-exchange-rejections.ts"() {
|
|
53004
|
+
"use strict";
|
|
53005
|
+
init_define_VTX_EXO_POLICY();
|
|
53006
|
+
init_define_VTX_GROK_POLICY();
|
|
53007
|
+
init_define_VTX_PI_MODEL_POLICY();
|
|
53008
|
+
listeners = /* @__PURE__ */ new Set();
|
|
53009
|
+
onHyperliquidExchangeRejection = (listener) => {
|
|
53010
|
+
listeners.add(listener);
|
|
53011
|
+
return () => {
|
|
53012
|
+
listeners.delete(listener);
|
|
53013
|
+
};
|
|
53014
|
+
};
|
|
53015
|
+
emitHyperliquidExchangeRejection = (message) => {
|
|
53016
|
+
for (const listener of listeners) {
|
|
53017
|
+
try {
|
|
53018
|
+
listener(message);
|
|
53019
|
+
} catch {
|
|
53020
|
+
}
|
|
53021
|
+
}
|
|
53022
|
+
};
|
|
53023
|
+
}
|
|
53024
|
+
});
|
|
53025
|
+
|
|
52649
53026
|
// lib/runtime/hyperliquid-market-symbol.ts
|
|
52650
53027
|
var configuredCaseSensitiveSymbols, isHyperliquidSpotSymbol, normalizeCaseSensitiveSymbols, configureHyperliquidMarketSymbolCasing, canonicalBaseSymbol, normalizeHyperliquidMarketSymbol, getHyperliquidMarketDex;
|
|
52651
53028
|
var init_hyperliquid_market_symbol = __esm({
|
|
@@ -54091,7 +54468,7 @@ function getNumber(value, name) {
|
|
|
54091
54468
|
}
|
|
54092
54469
|
assertArgument(false, "invalid numeric value", name || "value", value);
|
|
54093
54470
|
}
|
|
54094
|
-
function
|
|
54471
|
+
function toNumber2(value) {
|
|
54095
54472
|
return getNumber(toBigInt(value));
|
|
54096
54473
|
}
|
|
54097
54474
|
function toBeHex(_value, _width) {
|
|
@@ -56513,7 +56890,7 @@ var init_abstract_coder = __esm({
|
|
|
56513
56890
|
return toBigInt(this.readBytes(WordSize));
|
|
56514
56891
|
}
|
|
56515
56892
|
readIndex() {
|
|
56516
|
-
return
|
|
56893
|
+
return toNumber2(this.readBytes(WordSize));
|
|
56517
56894
|
}
|
|
56518
56895
|
};
|
|
56519
56896
|
}
|
|
@@ -63801,8 +64178,8 @@ function split2(name, nf, ef) {
|
|
|
63801
64178
|
if (!name) return [];
|
|
63802
64179
|
init();
|
|
63803
64180
|
let offset = 0;
|
|
63804
|
-
return name.split(STOP_CH).map((
|
|
63805
|
-
let input = explode_cp(
|
|
64181
|
+
return name.split(STOP_CH).map((label2) => {
|
|
64182
|
+
let input = explode_cp(label2);
|
|
63806
64183
|
let info = {
|
|
63807
64184
|
input,
|
|
63808
64185
|
offset
|
|
@@ -69477,8 +69854,8 @@ var init_contract = __esm({
|
|
|
69477
69854
|
}
|
|
69478
69855
|
const { subs } = getInternal(this);
|
|
69479
69856
|
let total = 0;
|
|
69480
|
-
for (const { listeners:
|
|
69481
|
-
total +=
|
|
69857
|
+
for (const { listeners: listeners3 } of subs.values()) {
|
|
69858
|
+
total += listeners3.length;
|
|
69482
69859
|
}
|
|
69483
69860
|
return total;
|
|
69484
69861
|
}
|
|
@@ -69496,8 +69873,8 @@ var init_contract = __esm({
|
|
|
69496
69873
|
}
|
|
69497
69874
|
const { subs } = getInternal(this);
|
|
69498
69875
|
let result = [];
|
|
69499
|
-
for (const { listeners:
|
|
69500
|
-
result = result.concat(
|
|
69876
|
+
for (const { listeners: listeners3 } of subs.values()) {
|
|
69877
|
+
result = result.concat(listeners3.map(({ listener }) => listener));
|
|
69501
69878
|
}
|
|
69502
69879
|
return result;
|
|
69503
69880
|
}
|
|
@@ -72334,8 +72711,8 @@ var init_abstract_provider = __esm({
|
|
|
72334
72711
|
return sub.listeners.length;
|
|
72335
72712
|
}
|
|
72336
72713
|
let total = 0;
|
|
72337
|
-
for (const { listeners:
|
|
72338
|
-
total +=
|
|
72714
|
+
for (const { listeners: listeners3 } of this.#subs.values()) {
|
|
72715
|
+
total += listeners3.length;
|
|
72339
72716
|
}
|
|
72340
72717
|
return total;
|
|
72341
72718
|
}
|
|
@@ -72348,8 +72725,8 @@ var init_abstract_provider = __esm({
|
|
|
72348
72725
|
return sub.listeners.map(({ listener }) => listener);
|
|
72349
72726
|
}
|
|
72350
72727
|
let result = [];
|
|
72351
|
-
for (const { listeners:
|
|
72352
|
-
result = result.concat(
|
|
72728
|
+
for (const { listeners: listeners3 } of this.#subs.values()) {
|
|
72729
|
+
result = result.concat(listeners3.map(({ listener }) => listener));
|
|
72353
72730
|
}
|
|
72354
72731
|
return result;
|
|
72355
72732
|
}
|
|
@@ -82950,7 +83327,7 @@ __export(ethers_exports, {
|
|
|
82950
83327
|
toBeArray: () => toBeArray,
|
|
82951
83328
|
toBeHex: () => toBeHex,
|
|
82952
83329
|
toBigInt: () => toBigInt,
|
|
82953
|
-
toNumber: () =>
|
|
83330
|
+
toNumber: () => toNumber2,
|
|
82954
83331
|
toQuantity: () => toQuantity,
|
|
82955
83332
|
toTwos: () => toTwos,
|
|
82956
83333
|
toUtf8Bytes: () => toUtf8Bytes,
|
|
@@ -83168,7 +83545,7 @@ __export(lib_exports, {
|
|
|
83168
83545
|
toBeArray: () => toBeArray,
|
|
83169
83546
|
toBeHex: () => toBeHex,
|
|
83170
83547
|
toBigInt: () => toBigInt,
|
|
83171
|
-
toNumber: () =>
|
|
83548
|
+
toNumber: () => toNumber2,
|
|
83172
83549
|
toQuantity: () => toQuantity,
|
|
83173
83550
|
toTwos: () => toTwos,
|
|
83174
83551
|
toUtf8Bytes: () => toUtf8Bytes,
|
|
@@ -83871,9 +84248,9 @@ var init_hyperliquid_signer = __esm({
|
|
|
83871
84248
|
{ name: "connectionId", type: "bytes32" }
|
|
83872
84249
|
]
|
|
83873
84250
|
};
|
|
83874
|
-
assertUint64 = (value,
|
|
84251
|
+
assertUint64 = (value, label2) => {
|
|
83875
84252
|
if (!Number.isInteger(value) || value < 0) {
|
|
83876
|
-
throw new Error(`${
|
|
84253
|
+
throw new Error(`${label2} must be a non-negative integer.`);
|
|
83877
84254
|
}
|
|
83878
84255
|
};
|
|
83879
84256
|
concatBytes3 = (...parts) => {
|
|
@@ -83898,10 +84275,10 @@ var init_hyperliquid_signer = __esm({
|
|
|
83898
84275
|
}
|
|
83899
84276
|
return bytes3;
|
|
83900
84277
|
};
|
|
83901
|
-
hexToBytes2 = (value,
|
|
84278
|
+
hexToBytes2 = (value, label2) => {
|
|
83902
84279
|
const normalized = value.trim().replace(/^0x/i, "");
|
|
83903
84280
|
if (!normalized || normalized.length % 2 !== 0 || /[^0-9a-f]/i.test(normalized)) {
|
|
83904
|
-
throw new Error(`Invalid ${
|
|
84281
|
+
throw new Error(`Invalid ${label2}.`);
|
|
83905
84282
|
}
|
|
83906
84283
|
const bytes3 = new Uint8Array(normalized.length / 2);
|
|
83907
84284
|
for (let index = 0; index < normalized.length; index += 2) {
|
|
@@ -84130,19 +84507,21 @@ var init_hyperliquid_signer = __esm({
|
|
|
84130
84507
|
});
|
|
84131
84508
|
|
|
84132
84509
|
// lib/runtime/hyperliquid-client.ts
|
|
84133
|
-
var HyperliquidExchangeRejectionError, durableMutationAuthorityArgs, assertFreshPreparedExecutionContext, normalizeSymbol, HYPERLIQUID_NONCE_STORAGE_KEY, HYPERLIQUID_NONCE_LOCK_NAME, lastGeneratedNonce, readBrowserStoredHyperliquidNonce, writeBrowserStoredHyperliquidNonce, browserNonceCoordinator, allocateHyperliquidNonce, generateHyperliquidNonce, normalizeDecimalString, HYPERLIQUID_PRICE_SIGNIFICANT_FIGURES, HYPERLIQUID_INTEGER_PRICE_MINIMUM, shortestDecimalParts, formatHyperliquidPerpPriceGrid, formatHyperliquidTriggerPriceWire, hyperliquidOrderPriceRounding, formatHyperliquidOrderPriceWire, countSignificantDigits, countDecimalPlaces, validateHyperliquidPerpPriceWire, validateHyperliquidSizeWire, formatSizeWire, inferApiUrl, inferIsTestnet, postHyperliquidInfoRead, postHyperliquidInfo, fetchBrowserHyperliquidInfoPayload, fetchBrowserHyperliquidInfoText, toFiniteNumber, OPEN_ORDER_NUMERIC_STRING, OPEN_ORDER_ID_STRING, parseCanonicalOpenOrderId, parseOpenOrderFiniteNumber, parseOpenOrderPositiveNumber, parseOpenOrderPresentationNumber, readOpenOrderField, firstFiniteNumber, parseFundingUsdcFromInfoPosition, isExchangeIsolatedOnly, computeHip3AssetId, getPerpDexIndexMap, buildAssetInfosFromMetaResponse, requireWalletAddress, assertPositiveInteger, assertPositiveNumber, normalizeOrderSide, normalizeHyperliquidClientOrderId, resolveAssets, findResolvedAsset, normalizeExecutionAssetMetadata, resolveHyperliquidAsset, resolveHyperliquidAssetIndex, decimalUnits, quantizeHyperliquidOrderSizeValue, finitePositive, readDevicePrivateExecutionContext, quantizeHyperliquidOrderSize, fetchBrowserAvailableAssets, fetchBrowserAllMids, fetchBrowserSymbolMidPrice, fetchBrowserOpenOrders, parseCanonicalHyperliquidOrderStatusEvidence, fetchBrowserOrderStatusEvidence, fetchBrowserUserRole, fetchBrowserAccountState, fetchBrowserPosition, buildHyperliquidOrderWire, buildHyperliquidTriggerOrderWire, signHyperliquidPayload, signHyperliquidPreparedAction, buildHyperliquidCancelPayload, buildHyperliquidUpdateLeveragePayload, buildHyperliquidMarketOrderPayload, buildHyperliquidLimitOrderPayload, buildHyperliquidTriggerOrderPayload, buildHyperliquidOrderBatchPayload, buildHyperliquidModifyOrderPayload, extractHyperliquidExchangeError, resolveHyperliquidTriggerAcknowledgements, isDefinitiveHyperliquidExchangeResponse, extractDefinitiveHyperliquidOrderId, CANONICAL_POSITIVE_DECIMAL_PATTERN, extractCanonicalHyperliquidOrderStateAcknowledgement, extractCanonicalHyperliquidOrderStateAcknowledgements, extractCanonicalHyperliquidFilledOrderAcknowledgement, extractDefinitiveHyperliquidOrderMemberResults, buildHyperliquidOrderDiagnostics, loadClientExecutionReferenceEvidence, sha256Hex, extractSignedPayloadClientOrderId, extractSignedPayloadMutationCorrelation, assertDurableMutationMatchesSignedAction, exchangeRejectionReason, exchangeActionPriority, submitHyperliquidExchangePayload;
|
|
84510
|
+
var HyperliquidExchangeRejectionError, durableMutationAuthorityArgs, assertFreshPreparedExecutionContext, normalizeSymbol, HYPERLIQUID_NONCE_STORAGE_KEY, HYPERLIQUID_NONCE_LOCK_NAME, lastGeneratedNonce, readBrowserStoredHyperliquidNonce, writeBrowserStoredHyperliquidNonce, browserNonceCoordinator, allocateHyperliquidNonce, hostNonceAllocator, allocateActionNonce, generateHyperliquidNonce, normalizeDecimalString, HYPERLIQUID_PRICE_SIGNIFICANT_FIGURES, HYPERLIQUID_INTEGER_PRICE_MINIMUM, shortestDecimalParts, formatHyperliquidPerpPriceGrid, formatHyperliquidTriggerPriceWire, hyperliquidOrderPriceRounding, formatHyperliquidOrderPriceWire, countSignificantDigits, countDecimalPlaces, validateHyperliquidPerpPriceWire, validateHyperliquidSizeWire, formatSizeWire, inferApiUrl, inferIsTestnet, postHyperliquidInfoRead, postHyperliquidInfo, fetchBrowserHyperliquidInfoPayload, fetchBrowserHyperliquidInfoText, toFiniteNumber, OPEN_ORDER_NUMERIC_STRING, OPEN_ORDER_ID_STRING, parseCanonicalOpenOrderId, parseOpenOrderFiniteNumber, parseOpenOrderPositiveNumber, parseOpenOrderPresentationNumber, readOpenOrderField, firstFiniteNumber, parseFundingUsdcFromInfoPosition, isExchangeIsolatedOnly, computeHip3AssetId, getPerpDexIndexMap, buildAssetInfosFromMetaResponse, requireWalletAddress, assertPositiveInteger, assertPositiveNumber, normalizeOrderSide, normalizeHyperliquidClientOrderId, resolveAssets, findResolvedAsset, normalizeExecutionAssetMetadata, resolveHyperliquidAsset, resolveHyperliquidAssetIndex, decimalUnits, quantizeHyperliquidOrderSizeValue, hyperliquidSignedSizeMatchesRequestedSize, finitePositive, readDevicePrivateExecutionContext, quantizeHyperliquidOrderSize, fetchBrowserAvailableAssets, fetchBrowserAllMids, fetchBrowserSymbolMidPrice, fetchBrowserOpenOrders, parseCanonicalHyperliquidOrderStatusEvidence, fetchBrowserOrderStatusEvidence, fetchBrowserUserRole, fetchBrowserAccountState, fetchBrowserPosition, buildHyperliquidOrderWire, buildHyperliquidTriggerOrderWire, signHyperliquidPayload, signHyperliquidPreparedAction, buildHyperliquidCancelPayload, buildHyperliquidUpdateLeveragePayload, buildHyperliquidMarketOrderPayload, buildHyperliquidLimitOrderPayload, buildHyperliquidTriggerOrderPayload, buildHyperliquidOrderBatchPayload, buildHyperliquidModifyOrderPayload, extractHyperliquidExchangeError, resolveHyperliquidTriggerAcknowledgements, isDefinitiveHyperliquidExchangeResponse, extractDefinitiveHyperliquidOrderId, CANONICAL_POSITIVE_DECIMAL_PATTERN, extractCanonicalHyperliquidOrderStateAcknowledgement, extractCanonicalHyperliquidOrderStateAcknowledgements, extractCanonicalHyperliquidFilledOrderAcknowledgement, extractDefinitiveHyperliquidOrderMemberResults, buildHyperliquidOrderDiagnostics, loadClientExecutionReferenceEvidence, sha256Hex, extractSignedPayloadClientOrderId, extractSignedPayloadMutationCorrelation, assertDurableMutationMatchesSignedAction, exchangeRejectionReason, exchangeActionPriority, submitHyperliquidExchangePayload;
|
|
84134
84511
|
var init_hyperliquid_client = __esm({
|
|
84135
84512
|
"lib/runtime/hyperliquid-client.ts"() {
|
|
84136
84513
|
"use strict";
|
|
84137
84514
|
init_define_VTX_EXO_POLICY();
|
|
84138
84515
|
init_define_VTX_GROK_POLICY();
|
|
84139
84516
|
init_define_VTX_PI_MODEL_POLICY();
|
|
84517
|
+
init_hyperliquid_account_contract();
|
|
84140
84518
|
init_order_identity();
|
|
84141
84519
|
init_hyperliquid_order_status();
|
|
84142
84520
|
init_runtime_policy_generated2();
|
|
84143
84521
|
init_hyperliquid_public_read();
|
|
84144
84522
|
init_api2();
|
|
84145
84523
|
init_abort();
|
|
84524
|
+
init_hyperliquid_exchange_rejections();
|
|
84146
84525
|
init_hyperliquid_market_symbol();
|
|
84147
84526
|
init_network_debug();
|
|
84148
84527
|
init_runtime_redaction();
|
|
@@ -84237,6 +84616,14 @@ var init_hyperliquid_client = __esm({
|
|
|
84237
84616
|
coordinator.write?.(lastGeneratedNonce);
|
|
84238
84617
|
return lastGeneratedNonce;
|
|
84239
84618
|
};
|
|
84619
|
+
hostNonceAllocator = null;
|
|
84620
|
+
allocateActionNonce = async (input, apiUrl) => {
|
|
84621
|
+
if (hostNonceAllocator) {
|
|
84622
|
+
if (!input.signingKey) throw new Error("A fleet-allocated Hyperliquid nonce needs the action's signing key.");
|
|
84623
|
+
return hostNonceAllocator({ signingKey: input.signingKey, apiUrl });
|
|
84624
|
+
}
|
|
84625
|
+
return generateHyperliquidNonce(input.nonceCoordinator);
|
|
84626
|
+
};
|
|
84240
84627
|
generateHyperliquidNonce = async (coordinator) => {
|
|
84241
84628
|
const resolvedCoordinator = coordinator ?? browserNonceCoordinator();
|
|
84242
84629
|
if (resolvedCoordinator.withLock) {
|
|
@@ -84362,12 +84749,12 @@ var init_hyperliquid_client = __esm({
|
|
|
84362
84749
|
throw new Error("Missing client runtime Hyperliquid API URL.");
|
|
84363
84750
|
};
|
|
84364
84751
|
inferIsTestnet = (apiUrl) => apiUrl.toLowerCase().includes("testnet");
|
|
84365
|
-
postHyperliquidInfoRead = async (input, body,
|
|
84752
|
+
postHyperliquidInfoRead = async (input, body, label2, includeBodyText = false) => {
|
|
84366
84753
|
const apiUrl = inferApiUrl(input);
|
|
84367
84754
|
const requestUrl = `${apiUrl.replace(/\/$/, "")}/info`;
|
|
84368
84755
|
const trace = startRuntimeNetworkDebugTrace({
|
|
84369
84756
|
kind: "exchange",
|
|
84370
|
-
label,
|
|
84757
|
+
label: label2,
|
|
84371
84758
|
method: "POST",
|
|
84372
84759
|
url: requestUrl
|
|
84373
84760
|
});
|
|
@@ -84385,10 +84772,10 @@ var init_hyperliquid_client = __esm({
|
|
|
84385
84772
|
throw sanitizedError;
|
|
84386
84773
|
}
|
|
84387
84774
|
};
|
|
84388
|
-
postHyperliquidInfo = async (input, body,
|
|
84389
|
-
fetchBrowserHyperliquidInfoPayload = (input, body,
|
|
84390
|
-
fetchBrowserHyperliquidInfoText = async (input, body,
|
|
84391
|
-
const { bodyText } = await postHyperliquidInfoRead(input, body,
|
|
84775
|
+
postHyperliquidInfo = async (input, body, label2) => (await postHyperliquidInfoRead(input, body, label2)).payload;
|
|
84776
|
+
fetchBrowserHyperliquidInfoPayload = (input, body, label2) => postHyperliquidInfo(input, body, label2);
|
|
84777
|
+
fetchBrowserHyperliquidInfoText = async (input, body, label2) => {
|
|
84778
|
+
const { bodyText } = await postHyperliquidInfoRead(input, body, label2, true);
|
|
84392
84779
|
if (typeof bodyText !== "string") throw new Error("Hyperliquid returned no response text.");
|
|
84393
84780
|
return bodyText;
|
|
84394
84781
|
};
|
|
@@ -84558,14 +84945,14 @@ var init_hyperliquid_client = __esm({
|
|
|
84558
84945
|
}
|
|
84559
84946
|
return normalized;
|
|
84560
84947
|
};
|
|
84561
|
-
assertPositiveInteger = (value,
|
|
84948
|
+
assertPositiveInteger = (value, label2) => {
|
|
84562
84949
|
if (!Number.isInteger(value) || value <= 0) {
|
|
84563
|
-
throw new Error(`${
|
|
84950
|
+
throw new Error(`${label2} must be a positive integer.`);
|
|
84564
84951
|
}
|
|
84565
84952
|
};
|
|
84566
|
-
assertPositiveNumber = (value,
|
|
84953
|
+
assertPositiveNumber = (value, label2) => {
|
|
84567
84954
|
if (!Number.isFinite(value) || value <= 0) {
|
|
84568
|
-
throw new Error(`${
|
|
84955
|
+
throw new Error(`${label2} must be a positive number.`);
|
|
84569
84956
|
}
|
|
84570
84957
|
};
|
|
84571
84958
|
normalizeOrderSide = (value) => {
|
|
@@ -84702,6 +85089,17 @@ var init_hyperliquid_client = __esm({
|
|
|
84702
85089
|
const units = decimalUnits(value, decimals, roundingMode);
|
|
84703
85090
|
return units / 10 ** decimals;
|
|
84704
85091
|
};
|
|
85092
|
+
hyperliquidSignedSizeMatchesRequestedSize = (requestedSize, sizeDecimals, signedSize) => {
|
|
85093
|
+
if (!Number.isFinite(requestedSize) || requestedSize <= 0 || !Number.isFinite(signedSize) || signedSize <= 0 || !Number.isInteger(sizeDecimals) || sizeDecimals < 0) {
|
|
85094
|
+
return false;
|
|
85095
|
+
}
|
|
85096
|
+
const tolerance = 10 ** -(sizeDecimals + 4);
|
|
85097
|
+
const candidates = [
|
|
85098
|
+
quantizeHyperliquidOrderSizeValue(requestedSize, sizeDecimals, "nearest"),
|
|
85099
|
+
Number(requestedSize.toFixed(sizeDecimals))
|
|
85100
|
+
];
|
|
85101
|
+
return candidates.some((candidate) => candidate > 0 && Math.abs(candidate - signedSize) <= tolerance);
|
|
85102
|
+
};
|
|
84705
85103
|
finitePositive = (value) => {
|
|
84706
85104
|
const parsed = Number(value);
|
|
84707
85105
|
return typeof value !== "boolean" && value !== null && value !== "" && Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
@@ -85210,7 +85608,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85210
85608
|
accountSummary: {
|
|
85211
85609
|
account_value: accountValue,
|
|
85212
85610
|
total_margin_used: totalMarginUsed,
|
|
85213
|
-
available_margin:
|
|
85611
|
+
available_margin: canonicalAvailableMargin(accountValue, totalMarginUsed),
|
|
85214
85612
|
withdrawable,
|
|
85215
85613
|
cross_margin_ratio: accountValue > 0 ? maintenanceMargin / accountValue : 0,
|
|
85216
85614
|
maintenance_margin: maintenanceMargin,
|
|
@@ -85231,7 +85629,8 @@ var init_hyperliquid_client = __esm({
|
|
|
85231
85629
|
buildHyperliquidOrderWire = async (input, tif, price, priceKind) => {
|
|
85232
85630
|
const { asset_index: assetIndex, sz_decimals: sizeDecimals } = await resolveHyperliquidAsset(input);
|
|
85233
85631
|
const side = normalizeOrderSide(input.side);
|
|
85234
|
-
|
|
85632
|
+
assertPositiveNumber(input.size, "Hyperliquid order size");
|
|
85633
|
+
const roundedSize = quantizeHyperliquidOrderSizeValue(input.size, sizeDecimals, "nearest");
|
|
85235
85634
|
assertPositiveNumber(roundedSize, "Hyperliquid order size");
|
|
85236
85635
|
const priceWire = formatHyperliquidOrderPriceWire(price, sizeDecimals, side, priceKind);
|
|
85237
85636
|
const sizeWire = formatSizeWire(roundedSize, sizeDecimals);
|
|
@@ -85259,7 +85658,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85259
85658
|
assertPositiveNumber(input.limitPrice, "Hyperliquid trigger limit price");
|
|
85260
85659
|
const { asset_index: assetIndex, sz_decimals: sizeDecimals } = await resolveHyperliquidAsset(input);
|
|
85261
85660
|
const side = normalizeOrderSide(input.side);
|
|
85262
|
-
const roundedSize =
|
|
85661
|
+
const roundedSize = quantizeHyperliquidOrderSizeValue(input.size, sizeDecimals, "nearest");
|
|
85263
85662
|
assertPositiveNumber(roundedSize, "Hyperliquid trigger order size");
|
|
85264
85663
|
const triggerPriceWire = formatHyperliquidTriggerPriceWire(input.triggerPrice, sizeDecimals);
|
|
85265
85664
|
const limitPriceWire = input.limitPrice === input.triggerPrice ? triggerPriceWire : formatHyperliquidOrderPriceWire(input.limitPrice, sizeDecimals, side, "limit");
|
|
@@ -85295,7 +85694,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85295
85694
|
signHyperliquidPayload = async (input, action) => {
|
|
85296
85695
|
const apiUrl = inferApiUrl(input);
|
|
85297
85696
|
const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
|
|
85298
|
-
const nonce = input.nonce ?? await
|
|
85697
|
+
const nonce = input.nonce ?? await allocateActionNonce(input, apiUrl);
|
|
85299
85698
|
const expiresAfter = input.expiresAfterSeconds == null ? null : nonce + input.expiresAfterSeconds * 1e3;
|
|
85300
85699
|
const signed2 = await signHyperliquidAction2({
|
|
85301
85700
|
privateKey: input.signingKey,
|
|
@@ -85319,7 +85718,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85319
85718
|
}
|
|
85320
85719
|
const apiUrl = inferApiUrl(input);
|
|
85321
85720
|
const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
|
|
85322
|
-
const nonce = await
|
|
85721
|
+
const nonce = await allocateActionNonce(input, apiUrl);
|
|
85323
85722
|
const expiresAfter = nonce + input.expiresAfterSeconds * 1e3;
|
|
85324
85723
|
const signed2 = await signHyperliquidAction2({
|
|
85325
85724
|
privateKey: input.signingKey,
|
|
@@ -85347,7 +85746,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85347
85746
|
const apiUrl = inferApiUrl(input);
|
|
85348
85747
|
const assetIndex = await resolveHyperliquidAssetIndex(input);
|
|
85349
85748
|
const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
|
|
85350
|
-
const nonce = input.nonce ?? await
|
|
85749
|
+
const nonce = input.nonce ?? await allocateActionNonce(input, apiUrl);
|
|
85351
85750
|
const expiresAfter = input.expiresAfterSeconds == null ? null : nonce + input.expiresAfterSeconds * 1e3;
|
|
85352
85751
|
const action = clientOrderId != null ? {
|
|
85353
85752
|
type: "cancelByCloid",
|
|
@@ -85377,7 +85776,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85377
85776
|
const apiUrl = inferApiUrl(input);
|
|
85378
85777
|
const asset = await resolveHyperliquidAsset(input);
|
|
85379
85778
|
const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
|
|
85380
|
-
const nonce = input.nonce ?? await
|
|
85779
|
+
const nonce = input.nonce ?? await allocateActionNonce(input, apiUrl);
|
|
85381
85780
|
const expiresAfter = input.expiresAfterSeconds == null ? null : nonce + input.expiresAfterSeconds * 1e3;
|
|
85382
85781
|
const leverage = Math.max(1, Math.min(asset.max_leverage, Math.trunc(input.leverage)));
|
|
85383
85782
|
const isCross = isExchangeIsolatedOnly(asset) ? false : input.isCross !== false;
|
|
@@ -86204,7 +86603,7 @@ var init_hyperliquid_client = __esm({
|
|
|
86204
86603
|
try {
|
|
86205
86604
|
recoveryPermit = await admitHyperliquidExchangeRequest(apiUrl, input.payload.action, input.signal, input.publicRequestPriority);
|
|
86206
86605
|
assertFreshPreparedExecutionContext(input.preparedContext);
|
|
86207
|
-
|
|
86606
|
+
await validateHyperliquidRecoveryDispatch(apiUrl, recoveryPermit, "exchange");
|
|
86208
86607
|
} catch (preparedContextError) {
|
|
86209
86608
|
await settleDurableMutation("rejected");
|
|
86210
86609
|
if (isAbortLikeError(preparedContextError) || preparedContextError instanceof HyperliquidPublicReadError) throw preparedContextError;
|
|
@@ -86295,6 +86694,7 @@ var init_hyperliquid_client = __esm({
|
|
|
86295
86694
|
}
|
|
86296
86695
|
const exchangeError = extractHyperliquidExchangeError(payload);
|
|
86297
86696
|
if (exchangeError) {
|
|
86697
|
+
emitHyperliquidExchangeRejection(String(exchangeError.message ?? ""));
|
|
86298
86698
|
await settleDurableMutation(
|
|
86299
86699
|
exchangeError.partial ? "transport_ambiguous" : "rejected",
|
|
86300
86700
|
null,
|
|
@@ -87268,6 +87668,81 @@ async function adoptClientProtectiveLegs(profileId, payload, requiredRuntimeSess
|
|
|
87268
87668
|
{ ...authority.requestOptions, signal: payload.signal }
|
|
87269
87669
|
);
|
|
87270
87670
|
}
|
|
87671
|
+
async function claimServerHostExecution(profileId, payload, signal, requiredRuntimeSessionId, explicitRuntimeLeaseToken, explicitRuntimeDeviceId, explicitSchedulerInstanceId) {
|
|
87672
|
+
const authority = resolveClientExchangeMutationAuthority(
|
|
87673
|
+
profileId,
|
|
87674
|
+
requiredRuntimeSessionId,
|
|
87675
|
+
explicitRuntimeLeaseToken,
|
|
87676
|
+
explicitRuntimeDeviceId,
|
|
87677
|
+
explicitSchedulerInstanceId
|
|
87678
|
+
);
|
|
87679
|
+
return postClientRuntime(
|
|
87680
|
+
"/runtime/execution-claim",
|
|
87681
|
+
authority.numericProfileId,
|
|
87682
|
+
JSON.stringify({
|
|
87683
|
+
...clientExchangeMutationAuthorityBody(authority),
|
|
87684
|
+
cycle_id: payload.cycleId ?? null,
|
|
87685
|
+
symbol: payload.symbol,
|
|
87686
|
+
intent: payload.intent,
|
|
87687
|
+
side: payload.side,
|
|
87688
|
+
requested_units: payload.requestedUnits,
|
|
87689
|
+
reduce_only: payload.reduceOnly,
|
|
87690
|
+
margin_mode: payload.marginMode ?? null,
|
|
87691
|
+
last_price: payload.lastPrice
|
|
87692
|
+
}),
|
|
87693
|
+
{ ...authority.requestOptions, signal }
|
|
87694
|
+
);
|
|
87695
|
+
}
|
|
87696
|
+
async function recordServerHostExecutionAudit(profileId, payload, signal, requiredRuntimeSessionId, explicitRuntimeLeaseToken, explicitRuntimeDeviceId, explicitSchedulerInstanceId) {
|
|
87697
|
+
const authority = resolveClientExchangeMutationAuthority(
|
|
87698
|
+
profileId,
|
|
87699
|
+
requiredRuntimeSessionId,
|
|
87700
|
+
explicitRuntimeLeaseToken,
|
|
87701
|
+
explicitRuntimeDeviceId,
|
|
87702
|
+
explicitSchedulerInstanceId
|
|
87703
|
+
);
|
|
87704
|
+
return postClientRuntime(
|
|
87705
|
+
"/runtime/execution-audit",
|
|
87706
|
+
authority.numericProfileId,
|
|
87707
|
+
JSON.stringify({
|
|
87708
|
+
...clientExchangeMutationAuthorityBody(authority),
|
|
87709
|
+
audit_id: payload.auditId,
|
|
87710
|
+
cycle_id: payload.cycleId ?? null,
|
|
87711
|
+
symbol: payload.symbol,
|
|
87712
|
+
intent: payload.intent,
|
|
87713
|
+
side: payload.side,
|
|
87714
|
+
requested_units: payload.requestedUnits,
|
|
87715
|
+
reduce_only: payload.reduceOnly,
|
|
87716
|
+
last_price: payload.lastPrice,
|
|
87717
|
+
status: payload.status,
|
|
87718
|
+
reason_code: payload.reasonCode,
|
|
87719
|
+
order_id: payload.orderId ?? null
|
|
87720
|
+
}),
|
|
87721
|
+
{ ...authority.requestOptions, signal }
|
|
87722
|
+
);
|
|
87723
|
+
}
|
|
87724
|
+
async function checkServerHostExecutionCapacity(profileId, plans, signal, requiredRuntimeSessionId, explicitRuntimeLeaseToken, explicitRuntimeDeviceId, explicitSchedulerInstanceId) {
|
|
87725
|
+
const authority = resolveClientExchangeMutationAuthority(
|
|
87726
|
+
profileId,
|
|
87727
|
+
requiredRuntimeSessionId,
|
|
87728
|
+
explicitRuntimeLeaseToken,
|
|
87729
|
+
explicitRuntimeDeviceId,
|
|
87730
|
+
explicitSchedulerInstanceId
|
|
87731
|
+
);
|
|
87732
|
+
const answer = await postClientRuntime(
|
|
87733
|
+
"/runtime/execution-capacity",
|
|
87734
|
+
authority.numericProfileId,
|
|
87735
|
+
JSON.stringify({
|
|
87736
|
+
...clientExchangeMutationAuthorityBody(authority),
|
|
87737
|
+
plans
|
|
87738
|
+
}),
|
|
87739
|
+
{ ...authority.requestOptions, signal }
|
|
87740
|
+
);
|
|
87741
|
+
if (!Array.isArray(answer.results) || answer.results.length !== plans.length) {
|
|
87742
|
+
throw new Error("Server execution capacity answered a different number of plans.");
|
|
87743
|
+
}
|
|
87744
|
+
return answer.results;
|
|
87745
|
+
}
|
|
87271
87746
|
async function reportClientRuntimeExchangeAttemptTransition(profileId, mutationId, payload, signal, requiredRuntimeSessionId, explicitRuntimeLeaseToken, explicitRuntimeDeviceId, explicitSchedulerInstanceId) {
|
|
87272
87747
|
const authority = resolveClientExchangeMutationAuthority(
|
|
87273
87748
|
profileId,
|
|
@@ -87396,6 +87871,9 @@ async function sendClientRuntimeHeartbeat(profileId, payload, options) {
|
|
|
87396
87871
|
if (payload.isExecuting !== void 0) {
|
|
87397
87872
|
extras.is_executing = payload.isExecuting;
|
|
87398
87873
|
}
|
|
87874
|
+
if (payload.analyzingObservedAtMs !== void 0) {
|
|
87875
|
+
extras.analyzing_observed_at_ms = payload.analyzingObservedAtMs;
|
|
87876
|
+
}
|
|
87399
87877
|
return postClientRuntime(
|
|
87400
87878
|
"/runtime/heartbeat",
|
|
87401
87879
|
profileId,
|
|
@@ -88259,14 +88737,14 @@ var init_api2 = __esm({
|
|
|
88259
88737
|
]);
|
|
88260
88738
|
CLIENT_EXCHANGE_AUTHORITY_DEVICE_KEY = "vtx_client_exchange_authority_device_v1";
|
|
88261
88739
|
CLIENT_EXCHANGE_AUTHORITY_SESSION_KEY = "vtx_client_exchange_authority_session_v1";
|
|
88262
|
-
getOrCreateClientExchangeAuthorityIdentity = (storage3, key,
|
|
88740
|
+
getOrCreateClientExchangeAuthorityIdentity = (storage3, key, label2) => {
|
|
88263
88741
|
const existing = String(storage3.getItem(key) || "").trim().toLowerCase();
|
|
88264
88742
|
if (/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/.test(existing)) {
|
|
88265
88743
|
return existing;
|
|
88266
88744
|
}
|
|
88267
88745
|
const generated = globalThis.crypto?.randomUUID?.().toLowerCase();
|
|
88268
88746
|
if (!generated || !/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/.test(generated)) {
|
|
88269
|
-
throw new Error(`Secure ${
|
|
88747
|
+
throw new Error(`Secure ${label2} generation is unavailable.`);
|
|
88270
88748
|
}
|
|
88271
88749
|
storage3.setItem(key, generated);
|
|
88272
88750
|
return generated;
|
|
@@ -88485,7 +88963,7 @@ var init_api2 = __esm({
|
|
|
88485
88963
|
});
|
|
88486
88964
|
|
|
88487
88965
|
// lib/runtime/hyperliquid-signer-binding.ts
|
|
88488
|
-
var DeviceSigningKeyError, DEVICE_SIGNING_KEY_FAILURES, getDeviceSigningKeyFailure, normalizeAddress, extractRoleAddress, assertBrowserHyperliquidSignerWalletBinding;
|
|
88966
|
+
var DeviceSigningKeyError, DEVICE_SIGNING_KEY_FAILURES, getDeviceSigningKeyFailure, normalizeAddress, extractRoleAddress, signerBindingCache, validatedSignerBindings, SIGNER_NOT_FOUND, invalidateHyperliquidSignerBindingAfterRejection, assertBrowserHyperliquidSignerWalletBinding;
|
|
88489
88967
|
var init_hyperliquid_signer_binding = __esm({
|
|
88490
88968
|
"lib/runtime/hyperliquid-signer-binding.ts"() {
|
|
88491
88969
|
"use strict";
|
|
@@ -88493,6 +88971,7 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88493
88971
|
init_define_VTX_GROK_POLICY();
|
|
88494
88972
|
init_define_VTX_PI_MODEL_POLICY();
|
|
88495
88973
|
init_hyperliquid_client();
|
|
88974
|
+
init_hyperliquid_exchange_rejections();
|
|
88496
88975
|
init_error_surface_contract();
|
|
88497
88976
|
DeviceSigningKeyError = class extends RuntimeExecutionError {
|
|
88498
88977
|
constructor(message, reasonCode, deviceSigningKeyFailure) {
|
|
@@ -88508,10 +88987,10 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88508
88987
|
const failure2 = error48?.deviceSigningKeyFailure;
|
|
88509
88988
|
return typeof failure2 === "string" && DEVICE_SIGNING_KEY_FAILURES.has(failure2) ? failure2 : null;
|
|
88510
88989
|
};
|
|
88511
|
-
normalizeAddress = (value,
|
|
88990
|
+
normalizeAddress = (value, label2) => {
|
|
88512
88991
|
const normalized = String(value || "").trim().toLowerCase();
|
|
88513
88992
|
if (!/^0x[0-9a-f]{40}$/.test(normalized)) {
|
|
88514
|
-
throw new Error(`Invalid Hyperliquid ${
|
|
88993
|
+
throw new Error(`Invalid Hyperliquid ${label2}.`);
|
|
88515
88994
|
}
|
|
88516
88995
|
return normalized;
|
|
88517
88996
|
};
|
|
@@ -88529,6 +89008,22 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88529
89008
|
}
|
|
88530
89009
|
return null;
|
|
88531
89010
|
};
|
|
89011
|
+
signerBindingCache = null;
|
|
89012
|
+
validatedSignerBindings = /* @__PURE__ */ new Map();
|
|
89013
|
+
SIGNER_NOT_FOUND = /^(?:L1 error:\s*)?User or API Wallet\s+(0x[0-9a-fA-F]{40})\s+does not exist\.?$/i;
|
|
89014
|
+
invalidateHyperliquidSignerBindingAfterRejection = async (message) => {
|
|
89015
|
+
const match = SIGNER_NOT_FOUND.exec(String(message ?? "").trim());
|
|
89016
|
+
if (!match || !signerBindingCache) return;
|
|
89017
|
+
const signerAddress = match[1].toLowerCase();
|
|
89018
|
+
for (const [key, entry] of [...validatedSignerBindings.entries()]) {
|
|
89019
|
+
if (entry.binding.signerAddress !== signerAddress) continue;
|
|
89020
|
+
validatedSignerBindings.delete(key);
|
|
89021
|
+
await signerBindingCache.invalidate(entry.binding.walletAddress, signerAddress).catch(() => void 0);
|
|
89022
|
+
}
|
|
89023
|
+
};
|
|
89024
|
+
onHyperliquidExchangeRejection((message) => {
|
|
89025
|
+
void invalidateHyperliquidSignerBindingAfterRejection(message);
|
|
89026
|
+
});
|
|
88532
89027
|
assertBrowserHyperliquidSignerWalletBinding = async (input) => {
|
|
88533
89028
|
let walletAddress;
|
|
88534
89029
|
try {
|
|
@@ -88554,6 +89049,24 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88554
89049
|
"device_signing_key_invalid"
|
|
88555
89050
|
);
|
|
88556
89051
|
}
|
|
89052
|
+
const cacheKey = `${walletAddress}:${signerAddress}`;
|
|
89053
|
+
let generation = null;
|
|
89054
|
+
if (signerBindingCache) {
|
|
89055
|
+
try {
|
|
89056
|
+
generation = await signerBindingCache.generation(walletAddress, signerAddress);
|
|
89057
|
+
} catch {
|
|
89058
|
+
throw new RuntimeExecutionError(
|
|
89059
|
+
"VTX could not verify the cached signing-key authorization because its coordination state was temporarily unavailable. The signing key was not rejected.",
|
|
89060
|
+
"signer_validation_unavailable"
|
|
89061
|
+
);
|
|
89062
|
+
}
|
|
89063
|
+
const cached2 = validatedSignerBindings.get(cacheKey);
|
|
89064
|
+
if (cached2 && cached2.generation === generation) return cached2.binding;
|
|
89065
|
+
}
|
|
89066
|
+
const remember = (binding) => {
|
|
89067
|
+
if (signerBindingCache && generation !== null) validatedSignerBindings.set(cacheKey, { generation, binding });
|
|
89068
|
+
return binding;
|
|
89069
|
+
};
|
|
88557
89070
|
let roleResponse;
|
|
88558
89071
|
try {
|
|
88559
89072
|
roleResponse = await fetchBrowserUserRole({
|
|
@@ -88571,11 +89084,11 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88571
89084
|
}
|
|
88572
89085
|
const signerRole = String(roleResponse.role || "").trim().toLowerCase();
|
|
88573
89086
|
if (signerRole === "user" && signerAddress === walletAddress) {
|
|
88574
|
-
return {
|
|
89087
|
+
return remember({
|
|
88575
89088
|
signerAddress,
|
|
88576
89089
|
walletAddress,
|
|
88577
89090
|
signerRole: "user"
|
|
88578
|
-
};
|
|
89091
|
+
});
|
|
88579
89092
|
}
|
|
88580
89093
|
if (signerRole === "agent") {
|
|
88581
89094
|
const masterWallet = extractRoleAddress(
|
|
@@ -88583,11 +89096,11 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88583
89096
|
["user"]
|
|
88584
89097
|
);
|
|
88585
89098
|
if (masterWallet === walletAddress) {
|
|
88586
|
-
return {
|
|
89099
|
+
return remember({
|
|
88587
89100
|
signerAddress,
|
|
88588
89101
|
walletAddress,
|
|
88589
89102
|
signerRole: "agent"
|
|
88590
|
-
};
|
|
89103
|
+
});
|
|
88591
89104
|
}
|
|
88592
89105
|
}
|
|
88593
89106
|
throw new DeviceSigningKeyError(
|
|
@@ -89543,9 +90056,9 @@ var init_browser_trading = __esm({
|
|
|
89543
90056
|
}
|
|
89544
90057
|
return profileId;
|
|
89545
90058
|
};
|
|
89546
|
-
requirePositiveNumber = (value,
|
|
90059
|
+
requirePositiveNumber = (value, label2) => {
|
|
89547
90060
|
if (!Number.isFinite(value) || value <= 0) {
|
|
89548
|
-
throw new Error(`${
|
|
90061
|
+
throw new Error(`${label2} must be a positive number.`);
|
|
89549
90062
|
}
|
|
89550
90063
|
};
|
|
89551
90064
|
assertFreshPreparedContext = (preparedContext) => {
|
|
@@ -90018,287 +90531,6 @@ var init_browser_trading = __esm({
|
|
|
90018
90531
|
}
|
|
90019
90532
|
});
|
|
90020
90533
|
|
|
90021
|
-
// lib/runtime/hyperliquid-account-mode-contract.ts
|
|
90022
|
-
function resolveExactHyperliquidAccountMode(userAbstraction, ...dexEvidence) {
|
|
90023
|
-
const mode = extractCanonicalHyperliquidAccountMode(userAbstraction);
|
|
90024
|
-
if (!mode) {
|
|
90025
|
-
throw new Error("Exact Hyperliquid userAbstraction response is invalid.");
|
|
90026
|
-
}
|
|
90027
|
-
if (mode !== "default" && mode !== "disabled") return mode;
|
|
90028
|
-
if (dexEvidence.length < 1) {
|
|
90029
|
-
throw new Error("Exact Hyperliquid userDexAbstraction response is unavailable.");
|
|
90030
|
-
}
|
|
90031
|
-
return parseExactDexAbstractionEnabled(dexEvidence[0]) ? "dexAbstraction" : mode;
|
|
90032
|
-
}
|
|
90033
|
-
var UNIFIED_MODE_ALIASES, CANONICAL_ACCOUNT_MODE_ALIASES, EXACT_MODE_KEYS, EXACT_MODE_BOOLEAN_KEYS, isExactTruthyFlag, normalizeCanonicalHyperliquidAccountMode, extractCanonicalHyperliquidAccountMode, parseExactDexAbstractionEnabled, normalizeAccountMode, extractAccountModeFromPayload, extractAccountModeCandidateFromPayload, isUnifiedAccountMode;
|
|
90034
|
-
var init_hyperliquid_account_mode_contract = __esm({
|
|
90035
|
-
"lib/runtime/hyperliquid-account-mode-contract.ts"() {
|
|
90036
|
-
"use strict";
|
|
90037
|
-
init_define_VTX_EXO_POLICY();
|
|
90038
|
-
init_define_VTX_GROK_POLICY();
|
|
90039
|
-
init_define_VTX_PI_MODEL_POLICY();
|
|
90040
|
-
UNIFIED_MODE_ALIASES = /* @__PURE__ */ new Set([
|
|
90041
|
-
"unifiedaccount",
|
|
90042
|
-
"dexabstraction",
|
|
90043
|
-
"portfoliomargin",
|
|
90044
|
-
"unified",
|
|
90045
|
-
"pm"
|
|
90046
|
-
]);
|
|
90047
|
-
CANONICAL_ACCOUNT_MODE_ALIASES = /* @__PURE__ */ new Map([
|
|
90048
|
-
["default", "default"],
|
|
90049
|
-
["standard", "default"],
|
|
90050
|
-
["classic", "default"],
|
|
90051
|
-
["disabled", "disabled"],
|
|
90052
|
-
["unifiedaccount", "unifiedAccount"],
|
|
90053
|
-
["unified", "unifiedAccount"],
|
|
90054
|
-
["portfoliomargin", "portfolioMargin"],
|
|
90055
|
-
["pm", "portfolioMargin"],
|
|
90056
|
-
["dexabstraction", "dexAbstraction"]
|
|
90057
|
-
]);
|
|
90058
|
-
EXACT_MODE_KEYS = [
|
|
90059
|
-
"accountMode",
|
|
90060
|
-
"account_mode",
|
|
90061
|
-
"accountType",
|
|
90062
|
-
"account_type",
|
|
90063
|
-
"accountUnificationMode",
|
|
90064
|
-
"account_unification_mode",
|
|
90065
|
-
"abstractionMode",
|
|
90066
|
-
"abstraction_mode",
|
|
90067
|
-
"abstraction",
|
|
90068
|
-
"abstractionState",
|
|
90069
|
-
"dexAbstractionState",
|
|
90070
|
-
"marginMode",
|
|
90071
|
-
"state",
|
|
90072
|
-
"mode",
|
|
90073
|
-
"value"
|
|
90074
|
-
];
|
|
90075
|
-
EXACT_MODE_BOOLEAN_KEYS = [
|
|
90076
|
-
["unifiedAccount", ["isUnifiedAccount", "unifiedAccount", "isUnified", "unified", "is_unified_account"]],
|
|
90077
|
-
["portfolioMargin", ["isPortfolioMargin", "portfolioMargin", "isPm", "pm", "is_portfolio_margin"]],
|
|
90078
|
-
["dexAbstraction", ["isDexAbstraction", "dexAbstraction", "dexAbstractionEnabled", "is_dex_abstraction"]],
|
|
90079
|
-
["default", ["isClassic", "classic", "isStandard", "standard"]]
|
|
90080
|
-
];
|
|
90081
|
-
isExactTruthyFlag = (value) => value === true || value === 1 || typeof value === "string" && value.trim().toLowerCase() === "true";
|
|
90082
|
-
normalizeCanonicalHyperliquidAccountMode = (value) => {
|
|
90083
|
-
if (typeof value !== "string") return null;
|
|
90084
|
-
const key = value.trim().replace(/[_\s-]/g, "").toLowerCase();
|
|
90085
|
-
return CANONICAL_ACCOUNT_MODE_ALIASES.get(key) ?? null;
|
|
90086
|
-
};
|
|
90087
|
-
extractCanonicalHyperliquidAccountMode = (payload, depth = 0) => {
|
|
90088
|
-
if (depth > 6) return null;
|
|
90089
|
-
const direct = normalizeCanonicalHyperliquidAccountMode(payload);
|
|
90090
|
-
if (direct) return direct;
|
|
90091
|
-
if (Array.isArray(payload)) {
|
|
90092
|
-
for (const item of payload) {
|
|
90093
|
-
const mode = extractCanonicalHyperliquidAccountMode(item, depth + 1);
|
|
90094
|
-
if (mode) return mode;
|
|
90095
|
-
}
|
|
90096
|
-
return null;
|
|
90097
|
-
}
|
|
90098
|
-
if (!payload || typeof payload !== "object") return null;
|
|
90099
|
-
const source = payload;
|
|
90100
|
-
for (const key of EXACT_MODE_KEYS) {
|
|
90101
|
-
if (!(key in source)) continue;
|
|
90102
|
-
const mode = normalizeCanonicalHyperliquidAccountMode(source[key]);
|
|
90103
|
-
if (mode) return mode;
|
|
90104
|
-
}
|
|
90105
|
-
for (const [mode, keys] of EXACT_MODE_BOOLEAN_KEYS) {
|
|
90106
|
-
for (const key of keys) {
|
|
90107
|
-
if (isExactTruthyFlag(source[key])) return mode;
|
|
90108
|
-
}
|
|
90109
|
-
}
|
|
90110
|
-
for (const value of Object.values(source)) {
|
|
90111
|
-
const mode = extractCanonicalHyperliquidAccountMode(value, depth + 1);
|
|
90112
|
-
if (mode) return mode;
|
|
90113
|
-
}
|
|
90114
|
-
return null;
|
|
90115
|
-
};
|
|
90116
|
-
parseExactDexAbstractionEnabled = (payload) => {
|
|
90117
|
-
if (payload == null || payload === false) return false;
|
|
90118
|
-
if (payload === true) return true;
|
|
90119
|
-
if (typeof payload === "string") {
|
|
90120
|
-
const normalized = payload.trim().toLowerCase();
|
|
90121
|
-
if (normalized === "true") return true;
|
|
90122
|
-
if (normalized === "false") return false;
|
|
90123
|
-
}
|
|
90124
|
-
if (typeof payload === "number" && Number.isFinite(payload)) {
|
|
90125
|
-
if (payload === 1) return true;
|
|
90126
|
-
if (payload === 0) return false;
|
|
90127
|
-
}
|
|
90128
|
-
throw new Error("Exact Hyperliquid userDexAbstraction response is invalid.");
|
|
90129
|
-
};
|
|
90130
|
-
normalizeAccountMode = (mode) => String(mode ?? "").trim().toLowerCase().replace(/[_\s-]/g, "");
|
|
90131
|
-
extractAccountModeFromPayload = (payload) => {
|
|
90132
|
-
const candidate = extractAccountModeCandidateFromPayload(payload);
|
|
90133
|
-
if (candidate && candidate.trim().length > 0) {
|
|
90134
|
-
return candidate;
|
|
90135
|
-
}
|
|
90136
|
-
return "default";
|
|
90137
|
-
};
|
|
90138
|
-
extractAccountModeCandidateFromPayload = (payload) => {
|
|
90139
|
-
if (!payload || typeof payload !== "object") {
|
|
90140
|
-
return null;
|
|
90141
|
-
}
|
|
90142
|
-
const source = payload;
|
|
90143
|
-
if ("accountMode" in source) {
|
|
90144
|
-
return String(source.accountMode ?? "");
|
|
90145
|
-
}
|
|
90146
|
-
if ("account_mode" in source) {
|
|
90147
|
-
return String(source.account_mode ?? "");
|
|
90148
|
-
}
|
|
90149
|
-
return null;
|
|
90150
|
-
};
|
|
90151
|
-
isUnifiedAccountMode = (mode) => UNIFIED_MODE_ALIASES.has(normalizeAccountMode(mode));
|
|
90152
|
-
}
|
|
90153
|
-
});
|
|
90154
|
-
|
|
90155
|
-
// lib/runtime/hyperliquid-account-contract.ts
|
|
90156
|
-
var toNumber2, firstNumber, roundTo, STABLE_SPOT_SYMBOLS, spotBalanceValueUsd, normalizeSpotBalancesFromInfoResponse, sumBalanceHoldUsd, sumPositionUnrealizedPnl, resolveTotalUnrealizedPnl, approximatelyEqualAccountValues, buildAccountSummaryFromInfoResponses;
|
|
90157
|
-
var init_hyperliquid_account_contract = __esm({
|
|
90158
|
-
"lib/runtime/hyperliquid-account-contract.ts"() {
|
|
90159
|
-
"use strict";
|
|
90160
|
-
init_define_VTX_EXO_POLICY();
|
|
90161
|
-
init_define_VTX_GROK_POLICY();
|
|
90162
|
-
init_define_VTX_PI_MODEL_POLICY();
|
|
90163
|
-
init_hyperliquid_account_mode_contract();
|
|
90164
|
-
toNumber2 = (value, fallback = 0) => {
|
|
90165
|
-
const numeric2 = Number(value);
|
|
90166
|
-
return Number.isFinite(numeric2) ? numeric2 : fallback;
|
|
90167
|
-
};
|
|
90168
|
-
firstNumber = (values, fallback = 0) => {
|
|
90169
|
-
for (const value of values) {
|
|
90170
|
-
if (value == null || typeof value === "string" && value.trim() === "") {
|
|
90171
|
-
continue;
|
|
90172
|
-
}
|
|
90173
|
-
const numeric2 = Number(value);
|
|
90174
|
-
if (Number.isFinite(numeric2)) {
|
|
90175
|
-
return numeric2;
|
|
90176
|
-
}
|
|
90177
|
-
}
|
|
90178
|
-
return fallback;
|
|
90179
|
-
};
|
|
90180
|
-
roundTo = (value, digits = 12) => Number(value.toFixed(digits));
|
|
90181
|
-
STABLE_SPOT_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USD", "USDT"]);
|
|
90182
|
-
spotBalanceValueUsd = (balance, coin, total) => {
|
|
90183
|
-
const explicit = firstNumber([balance?.value_usd, balance?.usdValue, balance?.usdcValue], Number.NaN);
|
|
90184
|
-
if (Number.isFinite(explicit)) {
|
|
90185
|
-
return explicit;
|
|
90186
|
-
}
|
|
90187
|
-
return STABLE_SPOT_SYMBOLS.has(coin) ? total : 0;
|
|
90188
|
-
};
|
|
90189
|
-
normalizeSpotBalancesFromInfoResponse = (spotResponse) => {
|
|
90190
|
-
const containers = [];
|
|
90191
|
-
if (spotResponse && typeof spotResponse === "object") {
|
|
90192
|
-
containers.push(spotResponse);
|
|
90193
|
-
const keys = ["spotState", "userState", "clearinghouseState", "state", "data"];
|
|
90194
|
-
for (const key of keys) {
|
|
90195
|
-
if (spotResponse[key] && typeof spotResponse[key] === "object") {
|
|
90196
|
-
containers.push(spotResponse[key]);
|
|
90197
|
-
}
|
|
90198
|
-
}
|
|
90199
|
-
}
|
|
90200
|
-
const firstWithBalances = containers.find((container) => Array.isArray(container?.balances));
|
|
90201
|
-
const balances = Array.isArray(firstWithBalances?.balances) ? firstWithBalances.balances : [];
|
|
90202
|
-
return balances.map((balance) => {
|
|
90203
|
-
const coin = String(balance?.coin ?? "").toUpperCase();
|
|
90204
|
-
const total = toNumber2(balance?.total, 0);
|
|
90205
|
-
const hold = toNumber2(balance?.hold, 0);
|
|
90206
|
-
const available = roundTo(Math.max(0, total - hold));
|
|
90207
|
-
const value_usd = spotBalanceValueUsd(balance, coin, total);
|
|
90208
|
-
return {
|
|
90209
|
-
coin,
|
|
90210
|
-
total,
|
|
90211
|
-
hold,
|
|
90212
|
-
available,
|
|
90213
|
-
value_usd
|
|
90214
|
-
};
|
|
90215
|
-
}).filter((balance) => balance.coin.length > 0);
|
|
90216
|
-
};
|
|
90217
|
-
sumBalanceHoldUsd = (balances) => balances.reduce((acc, balance) => {
|
|
90218
|
-
const hold = toNumber2(balance.hold, 0);
|
|
90219
|
-
const total = toNumber2(balance.total, 0);
|
|
90220
|
-
const valueUsd = toNumber2(balance.value_usd, 0);
|
|
90221
|
-
if (hold <= 0 || total <= 0 || valueUsd <= 0) {
|
|
90222
|
-
return acc;
|
|
90223
|
-
}
|
|
90224
|
-
return acc + Math.max(0, valueUsd * (hold / total));
|
|
90225
|
-
}, 0);
|
|
90226
|
-
sumPositionUnrealizedPnl = (perpsResponse) => {
|
|
90227
|
-
const assetPositions = Array.isArray(perpsResponse?.assetPositions) ? perpsResponse.assetPositions : [];
|
|
90228
|
-
return assetPositions.reduce((total, entry) => {
|
|
90229
|
-
const unrealizedPnl = toNumber2(entry?.position?.unrealizedPnl, 0);
|
|
90230
|
-
return total + unrealizedPnl;
|
|
90231
|
-
}, 0);
|
|
90232
|
-
};
|
|
90233
|
-
resolveTotalUnrealizedPnl = (perpsResponse) => {
|
|
90234
|
-
const topLevel = toNumber2(perpsResponse?.totalUnrealizedPnl, 0);
|
|
90235
|
-
const positionTotal = sumPositionUnrealizedPnl(perpsResponse);
|
|
90236
|
-
if (Math.abs(topLevel) < 1e-12 && Math.abs(positionTotal) >= 1e-12) {
|
|
90237
|
-
return positionTotal;
|
|
90238
|
-
}
|
|
90239
|
-
return topLevel;
|
|
90240
|
-
};
|
|
90241
|
-
approximatelyEqualAccountValues = (left, right, absoluteToleranceUsd, relativeTolerance) => {
|
|
90242
|
-
const reference = Math.max(Math.abs(left), Math.abs(right), 1);
|
|
90243
|
-
return Math.abs(left - right) <= Math.max(
|
|
90244
|
-
absoluteToleranceUsd,
|
|
90245
|
-
reference * relativeTolerance
|
|
90246
|
-
);
|
|
90247
|
-
};
|
|
90248
|
-
buildAccountSummaryFromInfoResponses = (perpsResponse, spotResponse, options = {}) => {
|
|
90249
|
-
const marginSummary = perpsResponse?.marginSummary ?? {};
|
|
90250
|
-
const perpsAccountValue = toNumber2(marginSummary?.accountValue, 0);
|
|
90251
|
-
const total_margin_used = toNumber2(marginSummary?.totalMarginUsed, 0);
|
|
90252
|
-
const totalNtlPos = toNumber2(marginSummary?.totalNtlPos, 0);
|
|
90253
|
-
const withdrawable = toNumber2(perpsResponse?.withdrawable, 0);
|
|
90254
|
-
const maintenance_margin = firstNumber([
|
|
90255
|
-
perpsResponse?.crossMaintenanceMarginUsed,
|
|
90256
|
-
marginSummary?.crossMaintenanceMarginUsed,
|
|
90257
|
-
marginSummary?.totalMaintenanceMargin
|
|
90258
|
-
], 0);
|
|
90259
|
-
const balances = normalizeSpotBalancesFromInfoResponse(spotResponse);
|
|
90260
|
-
const spotPortfolioValue = balances.reduce((acc, balance) => acc + toNumber2(balance.value_usd, 0), 0);
|
|
90261
|
-
const balancesHoldUsd = sumBalanceHoldUsd(balances);
|
|
90262
|
-
const account_mode = extractAccountModeFromPayload(perpsResponse);
|
|
90263
|
-
const crossMarginSummary = perpsResponse?.crossMarginSummary && typeof perpsResponse.crossMarginSummary === "object" ? perpsResponse.crossMarginSummary : null;
|
|
90264
|
-
const crossMarginAccountValue = crossMarginSummary ? toNumber2(crossMarginSummary.accountValue, 0) : 0;
|
|
90265
|
-
const normalizedMode = String(account_mode || "").trim().toLowerCase().replace(/[_\s-]/g, "");
|
|
90266
|
-
const isAmbiguousDefaultMode = normalizedMode.length === 0 || normalizedMode === "default";
|
|
90267
|
-
const spotDominatesMinTotalUsd = Number(options.spotDominatesMinTotalUsd ?? options.spot_dominates_min_total_usd);
|
|
90268
|
-
const spotDominatesPerpsMultiplier = Number(options.spotDominatesPerpsMultiplier ?? options.spot_dominates_perps_multiplier);
|
|
90269
|
-
const mirroredAccountValueAbsoluteToleranceUsd = Number(
|
|
90270
|
-
options.mirroredAccountValueAbsoluteToleranceUsd ?? options.mirrored_account_value_absolute_tolerance_usd
|
|
90271
|
-
);
|
|
90272
|
-
const mirroredAccountValueRelativeTolerance = Number(
|
|
90273
|
-
options.mirroredAccountValueRelativeTolerance ?? options.mirrored_account_value_relative_tolerance
|
|
90274
|
-
);
|
|
90275
|
-
const hasSpotDominanceThresholds = Number.isFinite(spotDominatesMinTotalUsd) && spotDominatesMinTotalUsd >= 0 && Number.isFinite(spotDominatesPerpsMultiplier) && spotDominatesPerpsMultiplier >= 0;
|
|
90276
|
-
const hasMirroredAccountValueTolerances = Number.isFinite(mirroredAccountValueAbsoluteToleranceUsd) && mirroredAccountValueAbsoluteToleranceUsd >= 0 && Number.isFinite(mirroredAccountValueRelativeTolerance) && mirroredAccountValueRelativeTolerance >= 0;
|
|
90277
|
-
const spotDominatesPerps = hasSpotDominanceThresholds && spotPortfolioValue >= spotDominatesMinTotalUsd && (perpsAccountValue <= 0 || spotPortfolioValue >= perpsAccountValue * spotDominatesPerpsMultiplier);
|
|
90278
|
-
const ambiguousDefaultLooksUnified = isAmbiguousDefaultMode && spotDominatesPerps;
|
|
90279
|
-
const ambiguousDefaultSpotAlreadyIncludesPerps = ambiguousDefaultLooksUnified && perpsAccountValue > 0 && balancesHoldUsd > 0 && hasMirroredAccountValueTolerances && approximatelyEqualAccountValues(
|
|
90280
|
-
balancesHoldUsd,
|
|
90281
|
-
perpsAccountValue,
|
|
90282
|
-
mirroredAccountValueAbsoluteToleranceUsd,
|
|
90283
|
-
mirroredAccountValueRelativeTolerance
|
|
90284
|
-
);
|
|
90285
|
-
const account_value = isUnifiedAccountMode(account_mode) && crossMarginSummary !== null && crossMarginAccountValue > 0 ? crossMarginAccountValue + spotPortfolioValue : ambiguousDefaultLooksUnified && !ambiguousDefaultSpotAlreadyIncludesPerps ? perpsAccountValue + spotPortfolioValue : Math.max(perpsAccountValue, spotPortfolioValue);
|
|
90286
|
-
return {
|
|
90287
|
-
account_value,
|
|
90288
|
-
total_margin_used,
|
|
90289
|
-
available_margin: roundTo(Math.max(0, account_value - total_margin_used)),
|
|
90290
|
-
withdrawable,
|
|
90291
|
-
cross_margin_ratio: account_value > 0 ? maintenance_margin / account_value : 0,
|
|
90292
|
-
maintenance_margin,
|
|
90293
|
-
cross_account_leverage: account_value > 0 ? totalNtlPos / account_value : 0,
|
|
90294
|
-
total_unrealized_pnl: resolveTotalUnrealizedPnl(perpsResponse),
|
|
90295
|
-
account_mode,
|
|
90296
|
-
balances
|
|
90297
|
-
};
|
|
90298
|
-
};
|
|
90299
|
-
}
|
|
90300
|
-
});
|
|
90301
|
-
|
|
90302
90534
|
// lib/runtime/hyperliquid-active-asset-contract.ts
|
|
90303
90535
|
var unwrapActiveAssetPayload, normalizePair, normalizeActiveAssetData;
|
|
90304
90536
|
var init_hyperliquid_active_asset_contract = __esm({
|
|
@@ -90326,15 +90558,15 @@ var init_hyperliquid_active_asset_contract = __esm({
|
|
|
90326
90558
|
};
|
|
90327
90559
|
normalizePair = (raw) => {
|
|
90328
90560
|
if (Array.isArray(raw) && raw.length >= 2) {
|
|
90329
|
-
return [
|
|
90561
|
+
return [toNumber(raw[0], 0), toNumber(raw[1], 0)];
|
|
90330
90562
|
}
|
|
90331
90563
|
if (raw && typeof raw === "object") {
|
|
90332
|
-
const buy =
|
|
90333
|
-
const sell =
|
|
90564
|
+
const buy = toNumber(raw.buy ?? raw.long ?? raw.b, 0);
|
|
90565
|
+
const sell = toNumber(raw.sell ?? raw.short ?? raw.s, 0);
|
|
90334
90566
|
return [buy, sell];
|
|
90335
90567
|
}
|
|
90336
90568
|
if (typeof raw === "string" || typeof raw === "number") {
|
|
90337
|
-
const value =
|
|
90569
|
+
const value = toNumber(raw, 0);
|
|
90338
90570
|
return [value, value];
|
|
90339
90571
|
}
|
|
90340
90572
|
return [0, 0];
|
|
@@ -90345,21 +90577,21 @@ var init_hyperliquid_active_asset_contract = __esm({
|
|
|
90345
90577
|
const directSell = source.available_to_trade_sell;
|
|
90346
90578
|
const hasDirectAvailable = directBuy !== void 0 || directSell !== void 0;
|
|
90347
90579
|
const [pairBuy, pairSell] = normalizePair(source.availableToTrade);
|
|
90348
|
-
const available_to_trade_buy = hasDirectAvailable ?
|
|
90349
|
-
const available_to_trade_sell = hasDirectAvailable ?
|
|
90580
|
+
const available_to_trade_buy = hasDirectAvailable ? toNumber(directBuy, pairBuy) : pairBuy;
|
|
90581
|
+
const available_to_trade_sell = hasDirectAvailable ? toNumber(directSell, pairSell) : pairSell;
|
|
90350
90582
|
const directMaxBuy = source.max_trade_size_buy;
|
|
90351
90583
|
const directMaxSell = source.max_trade_size_sell;
|
|
90352
90584
|
const hasDirectMax = directMaxBuy !== void 0 || directMaxSell !== void 0;
|
|
90353
90585
|
const [pairMaxBuy, pairMaxSell] = normalizePair(source.maxTradeSzs);
|
|
90354
|
-
const max_trade_size_buy = hasDirectMax ?
|
|
90355
|
-
const max_trade_size_sell = hasDirectMax ?
|
|
90586
|
+
const max_trade_size_buy = hasDirectMax ? toNumber(directMaxBuy, pairMaxBuy) : pairMaxBuy;
|
|
90587
|
+
const max_trade_size_sell = hasDirectMax ? toNumber(directMaxSell, pairMaxSell) : pairMaxSell;
|
|
90356
90588
|
return {
|
|
90357
90589
|
symbol: String(source.coin || symbol2),
|
|
90358
90590
|
available_to_trade_buy,
|
|
90359
90591
|
available_to_trade_sell,
|
|
90360
90592
|
max_trade_size_buy,
|
|
90361
90593
|
max_trade_size_sell,
|
|
90362
|
-
mark_price:
|
|
90594
|
+
mark_price: toNumber(source.markPx ?? source.mark_price, 0)
|
|
90363
90595
|
};
|
|
90364
90596
|
};
|
|
90365
90597
|
}
|
|
@@ -90551,12 +90783,7 @@ var init_server_prompt_rescue_account_contract = __esm({
|
|
|
90551
90783
|
};
|
|
90552
90784
|
const accountValue = computeEffectiveAccountValue(formulaInput);
|
|
90553
90785
|
const maintenanceMargin = toNumber3(perps.crossMaintenanceMarginUsed);
|
|
90554
|
-
const
|
|
90555
|
-
const availableMargin = maintenanceMargin > 0 ? Math.max(
|
|
90556
|
-
calculatedAvailable,
|
|
90557
|
-
Math.max(0, accountValue - 4 * maintenanceMargin),
|
|
90558
|
-
withdrawable
|
|
90559
|
-
) : Math.max(calculatedAvailable, withdrawable);
|
|
90786
|
+
const availableMargin = canonicalAvailableMargin(accountValue, totalMarginUsed);
|
|
90560
90787
|
let totalNotional = 0;
|
|
90561
90788
|
let totalUnrealizedPnl = 0;
|
|
90562
90789
|
const positions = Array.isArray(perps.assetPositions) ? perps.assetPositions : [];
|
|
@@ -91014,18 +91241,18 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91014
91241
|
}
|
|
91015
91242
|
return parsed;
|
|
91016
91243
|
};
|
|
91017
|
-
requirePromptClearinghouseState = (response,
|
|
91244
|
+
requirePromptClearinghouseState = (response, label2) => {
|
|
91018
91245
|
if (!response || typeof response !== "object" || Array.isArray(response)) {
|
|
91019
|
-
throw new Error(`Malformed ${
|
|
91246
|
+
throw new Error(`Malformed ${label2} clearinghouseState response for client runtime prompt context.`);
|
|
91020
91247
|
}
|
|
91021
91248
|
const marginSummary = response.marginSummary;
|
|
91022
91249
|
if (!marginSummary || typeof marginSummary !== "object" || Array.isArray(marginSummary)) {
|
|
91023
|
-
throw new Error(`${
|
|
91250
|
+
throw new Error(`${label2} clearinghouseState is missing marginSummary for client runtime prompt context.`);
|
|
91024
91251
|
}
|
|
91025
|
-
requireFinitePromptMetric(marginSummary.accountValue, `${
|
|
91026
|
-
requireFinitePromptMetric(marginSummary.totalMarginUsed, `${
|
|
91027
|
-
requireFinitePromptMetric(marginSummary.totalNtlPos, `${
|
|
91028
|
-
requireFinitePromptMetric(response.withdrawable, `${
|
|
91252
|
+
requireFinitePromptMetric(marginSummary.accountValue, `${label2}.marginSummary.accountValue`);
|
|
91253
|
+
requireFinitePromptMetric(marginSummary.totalMarginUsed, `${label2}.marginSummary.totalMarginUsed`);
|
|
91254
|
+
requireFinitePromptMetric(marginSummary.totalNtlPos, `${label2}.marginSummary.totalNtlPos`);
|
|
91255
|
+
requireFinitePromptMetric(response.withdrawable, `${label2}.withdrawable`);
|
|
91029
91256
|
const maintenanceCandidates = [
|
|
91030
91257
|
response.crossMaintenanceMarginUsed,
|
|
91031
91258
|
marginSummary.crossMaintenanceMarginUsed,
|
|
@@ -91034,33 +91261,33 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91034
91261
|
const maintenance = maintenanceCandidates.find(
|
|
91035
91262
|
(value) => value != null && !(typeof value === "string" && value.trim() === "")
|
|
91036
91263
|
);
|
|
91037
|
-
requireFinitePromptMetric(maintenance, `${
|
|
91264
|
+
requireFinitePromptMetric(maintenance, `${label2}.maintenanceMargin`);
|
|
91038
91265
|
if (!Array.isArray(response.assetPositions)) {
|
|
91039
|
-
throw new Error(`${
|
|
91266
|
+
throw new Error(`${label2} clearinghouseState is missing assetPositions for client runtime prompt context.`);
|
|
91040
91267
|
}
|
|
91041
91268
|
response.assetPositions.forEach((entry, index) => {
|
|
91042
91269
|
const position = entry?.position;
|
|
91043
91270
|
if (!position || typeof position !== "object" || Array.isArray(position)) {
|
|
91044
|
-
throw new Error(`${
|
|
91271
|
+
throw new Error(`${label2}.assetPositions[${index}] is malformed for client runtime prompt context.`);
|
|
91045
91272
|
}
|
|
91046
91273
|
if (!String(entry?.coin || position.coin || "").trim()) {
|
|
91047
|
-
throw new Error(`${
|
|
91274
|
+
throw new Error(`${label2}.assetPositions[${index}] is missing its symbol for client runtime prompt context.`);
|
|
91048
91275
|
}
|
|
91049
91276
|
const size = requireFinitePromptMetric(
|
|
91050
91277
|
position.szi,
|
|
91051
|
-
`${
|
|
91278
|
+
`${label2}.assetPositions[${index}].position.szi`
|
|
91052
91279
|
);
|
|
91053
91280
|
if (size !== 0) {
|
|
91054
91281
|
const entryPrice = requireFinitePromptMetric(
|
|
91055
91282
|
position.entryPx,
|
|
91056
|
-
`${
|
|
91283
|
+
`${label2}.assetPositions[${index}].position.entryPx`
|
|
91057
91284
|
);
|
|
91058
91285
|
if (entryPrice <= 0) {
|
|
91059
|
-
throw new Error(`${
|
|
91286
|
+
throw new Error(`${label2}.assetPositions[${index}] has a nonpositive entry price for client runtime prompt context.`);
|
|
91060
91287
|
}
|
|
91061
91288
|
requireFinitePromptMetric(
|
|
91062
91289
|
position.unrealizedPnl,
|
|
91063
|
-
`${
|
|
91290
|
+
`${label2}.assetPositions[${index}].position.unrealizedPnl`
|
|
91064
91291
|
);
|
|
91065
91292
|
}
|
|
91066
91293
|
});
|
|
@@ -91084,9 +91311,12 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91084
91311
|
perpDexConfig.allowed_dexes.map(normalizePerpDexName).filter((value) => value.length > 0)
|
|
91085
91312
|
));
|
|
91086
91313
|
};
|
|
91087
|
-
listPerpDexsForAccountState = (config2, selectedDex, aggregatePerpDexs) => {
|
|
91314
|
+
listPerpDexsForAccountState = (config2, selectedDex, aggregatePerpDexs, perpDexScope) => {
|
|
91088
91315
|
if (aggregatePerpDexs) {
|
|
91089
|
-
|
|
91316
|
+
const configured = listConfiguredPerpDexs(config2);
|
|
91317
|
+
if (!perpDexScope) return configured;
|
|
91318
|
+
const scope = new Set(perpDexScope.map(normalizePerpDexName));
|
|
91319
|
+
return configured.filter((dex) => scope.has(dex));
|
|
91090
91320
|
}
|
|
91091
91321
|
return selectedDex ? [selectedDex] : [];
|
|
91092
91322
|
};
|
|
@@ -91294,7 +91524,7 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91294
91524
|
const includeEffectiveTakerRate = input.includeEffectiveTakerRate === true;
|
|
91295
91525
|
const includeExactAccountMode = input.includeExactAccountMode === true;
|
|
91296
91526
|
const includeActiveAssetData = input.includeActiveAssetData !== false;
|
|
91297
|
-
const dexNames = listPerpDexsForAccountState(input.config, dex, aggregatePerpDexs);
|
|
91527
|
+
const dexNames = listPerpDexsForAccountState(input.config, dex, aggregatePerpDexs, input.perpDexScope);
|
|
91298
91528
|
if (scopeAccountSummaryToSelectedDex && dex && !dexNames.includes(dex)) {
|
|
91299
91529
|
dexNames.push(dex);
|
|
91300
91530
|
}
|
|
@@ -91592,8 +91822,7 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91592
91822
|
])
|
|
91593
91823
|
}, {}, "disabled", accountSummaryOptions);
|
|
91594
91824
|
const accountValue = Number(payload.marginSummary.accountValue);
|
|
91595
|
-
const
|
|
91596
|
-
const availableMargin = summary.maintenance_margin > 0 ? Math.max(calculatedAvailable, Math.max(0, accountValue - 4 * summary.maintenance_margin), summary.withdrawable) : Math.max(calculatedAvailable, summary.withdrawable);
|
|
91825
|
+
const availableMargin = canonicalAvailableMargin(accountValue, summary.total_margin_used);
|
|
91597
91826
|
return {
|
|
91598
91827
|
dex,
|
|
91599
91828
|
account_value: accountValue,
|
|
@@ -91898,7 +92127,7 @@ var init_protective_evidence = __esm({
|
|
|
91898
92127
|
const perDex = /* @__PURE__ */ new Map();
|
|
91899
92128
|
const scope = `${String(input.apiUrl ?? "")}|${wallet.toLowerCase()}`;
|
|
91900
92129
|
const shareable = batch.every((item) => item.kind !== "fills" && item.shareable);
|
|
91901
|
-
const dexRead = (key, body,
|
|
92130
|
+
const dexRead = (key, body, label2) => {
|
|
91902
92131
|
let read = perDex.get(key);
|
|
91903
92132
|
if (read) return read;
|
|
91904
92133
|
const sharedKey = `${scope}|${key}`;
|
|
@@ -91908,7 +92137,7 @@ var init_protective_evidence = __esm({
|
|
|
91908
92137
|
startedAtMonotonicMs = Math.min(startedAtMonotonicMs, shared.startedAtMonotonicMs);
|
|
91909
92138
|
read = shared.read;
|
|
91910
92139
|
} else {
|
|
91911
|
-
read = readOrNull(() => fetchBrowserHyperliquidInfoPayload(input, body,
|
|
92140
|
+
read = readOrNull(() => fetchBrowserHyperliquidInfoPayload(input, body, label2));
|
|
91912
92141
|
const entry = { startedAtMonotonicMs: now, read };
|
|
91913
92142
|
sharedAccountReads.set(sharedKey, entry);
|
|
91914
92143
|
void read.then((value) => {
|
|
@@ -92085,19 +92314,19 @@ var init_protective_actions = __esm({
|
|
|
92085
92314
|
"local_safety_block"
|
|
92086
92315
|
);
|
|
92087
92316
|
};
|
|
92088
|
-
exactKeys = (value, keys,
|
|
92089
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) fail2(`${
|
|
92317
|
+
exactKeys = (value, keys, label2) => {
|
|
92318
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) fail2(`${label2} is not an object.`);
|
|
92090
92319
|
const record5 = value;
|
|
92091
92320
|
const present = Object.keys(record5).sort();
|
|
92092
|
-
if (present.join(",") !== [...keys].sort().join(",")) fail2(`${
|
|
92321
|
+
if (present.join(",") !== [...keys].sort().join(",")) fail2(`${label2} has unexpected fields.`);
|
|
92093
92322
|
return record5;
|
|
92094
92323
|
};
|
|
92095
|
-
nonNegativeInteger = (value,
|
|
92096
|
-
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) fail2(`${
|
|
92324
|
+
nonNegativeInteger = (value, label2) => {
|
|
92325
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) fail2(`${label2} is invalid.`);
|
|
92097
92326
|
return value;
|
|
92098
92327
|
};
|
|
92099
|
-
decimalString = (value,
|
|
92100
|
-
if (typeof value !== "string" || !DECIMAL.test(value) || Number(value) <= 0) fail2(`${
|
|
92328
|
+
decimalString = (value, label2) => {
|
|
92329
|
+
if (typeof value !== "string" || !DECIMAL.test(value) || Number(value) <= 0) fail2(`${label2} is invalid.`);
|
|
92101
92330
|
return value;
|
|
92102
92331
|
};
|
|
92103
92332
|
canonicalTriggerOrder = (value) => {
|
|
@@ -92407,6 +92636,119 @@ var init_protective_actions = __esm({
|
|
|
92407
92636
|
}
|
|
92408
92637
|
});
|
|
92409
92638
|
|
|
92639
|
+
// lib/runtime/bounded-lock.ts
|
|
92640
|
+
var webLocks, inProcessTails, abortReason, waitBounded, withInProcessLock, withBoundedExclusiveLock;
|
|
92641
|
+
var init_bounded_lock = __esm({
|
|
92642
|
+
"lib/runtime/bounded-lock.ts"() {
|
|
92643
|
+
"use strict";
|
|
92644
|
+
init_define_VTX_EXO_POLICY();
|
|
92645
|
+
init_define_VTX_GROK_POLICY();
|
|
92646
|
+
init_define_VTX_PI_MODEL_POLICY();
|
|
92647
|
+
webLocks = () => {
|
|
92648
|
+
const locks = typeof navigator === "undefined" ? void 0 : navigator.locks;
|
|
92649
|
+
return locks && typeof locks.request === "function" ? locks : null;
|
|
92650
|
+
};
|
|
92651
|
+
inProcessTails = /* @__PURE__ */ new Map();
|
|
92652
|
+
abortReason = (signal) => signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted.", "AbortError");
|
|
92653
|
+
waitBounded = (gate, waitMs, signal) => new Promise((resolve14, reject) => {
|
|
92654
|
+
if (signal?.aborted) {
|
|
92655
|
+
reject(abortReason(signal));
|
|
92656
|
+
return;
|
|
92657
|
+
}
|
|
92658
|
+
const finish = () => {
|
|
92659
|
+
clearTimeout(timer);
|
|
92660
|
+
signal?.removeEventListener("abort", onAbort);
|
|
92661
|
+
};
|
|
92662
|
+
const onAbort = () => {
|
|
92663
|
+
finish();
|
|
92664
|
+
reject(abortReason(signal));
|
|
92665
|
+
};
|
|
92666
|
+
const timer = setTimeout(() => {
|
|
92667
|
+
finish();
|
|
92668
|
+
resolve14();
|
|
92669
|
+
}, waitMs);
|
|
92670
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
92671
|
+
void gate.then(() => {
|
|
92672
|
+
finish();
|
|
92673
|
+
resolve14();
|
|
92674
|
+
});
|
|
92675
|
+
});
|
|
92676
|
+
withInProcessLock = async (name, waitMs, work, signal) => {
|
|
92677
|
+
const previous = inProcessTails.get(name) ?? Promise.resolve();
|
|
92678
|
+
let release;
|
|
92679
|
+
const released = new Promise((resolve14) => {
|
|
92680
|
+
release = resolve14;
|
|
92681
|
+
});
|
|
92682
|
+
const tail = previous.then(() => released);
|
|
92683
|
+
inProcessTails.set(name, tail);
|
|
92684
|
+
try {
|
|
92685
|
+
await waitBounded(previous, waitMs, signal);
|
|
92686
|
+
return await work();
|
|
92687
|
+
} finally {
|
|
92688
|
+
release();
|
|
92689
|
+
if (inProcessTails.get(name) === tail) inProcessTails.delete(name);
|
|
92690
|
+
}
|
|
92691
|
+
};
|
|
92692
|
+
withBoundedExclusiveLock = async (name, waitMs, work, signal) => {
|
|
92693
|
+
if (!Number.isFinite(waitMs) || waitMs <= 0) {
|
|
92694
|
+
throw new Error(`Invalid lock wait bound for ${name}.`);
|
|
92695
|
+
}
|
|
92696
|
+
const locks = webLocks();
|
|
92697
|
+
if (locks == null) return withInProcessLock(name, waitMs, work, signal);
|
|
92698
|
+
const waitTimeout = new AbortController();
|
|
92699
|
+
const timer = setTimeout(() => waitTimeout.abort(), waitMs);
|
|
92700
|
+
const relayAbort = () => waitTimeout.abort();
|
|
92701
|
+
signal?.addEventListener("abort", relayAbort, { once: true });
|
|
92702
|
+
let acquired = false;
|
|
92703
|
+
try {
|
|
92704
|
+
return await locks.request(name, { signal: waitTimeout.signal }, async () => {
|
|
92705
|
+
acquired = true;
|
|
92706
|
+
clearTimeout(timer);
|
|
92707
|
+
signal?.removeEventListener("abort", relayAbort);
|
|
92708
|
+
return work();
|
|
92709
|
+
});
|
|
92710
|
+
} catch (error48) {
|
|
92711
|
+
if (acquired) throw error48;
|
|
92712
|
+
if (signal?.aborted) throw abortReason(signal);
|
|
92713
|
+
if (!waitTimeout.signal.aborted) throw error48;
|
|
92714
|
+
return work();
|
|
92715
|
+
} finally {
|
|
92716
|
+
clearTimeout(timer);
|
|
92717
|
+
signal?.removeEventListener("abort", relayAbort);
|
|
92718
|
+
}
|
|
92719
|
+
};
|
|
92720
|
+
}
|
|
92721
|
+
});
|
|
92722
|
+
|
|
92723
|
+
// lib/api/client-exchange-mutations.ts
|
|
92724
|
+
async function getClientRuntimeExchangeMutation(profileId, mutationId, signal) {
|
|
92725
|
+
const numericProfileId = Number(profileId);
|
|
92726
|
+
const response = await apiFetch(
|
|
92727
|
+
`${getApiUrl()}/trading/ai/runtime/exchange-mutations/${encodeURIComponent(String(mutationId).trim().toLowerCase())}`,
|
|
92728
|
+
{
|
|
92729
|
+
method: "GET",
|
|
92730
|
+
credentials: "include",
|
|
92731
|
+
cache: "no-store",
|
|
92732
|
+
headers: getProfileHeaders({}, Number.isSafeInteger(numericProfileId) ? numericProfileId : void 0),
|
|
92733
|
+
signal
|
|
92734
|
+
}
|
|
92735
|
+
);
|
|
92736
|
+
if (response.status === 404) return null;
|
|
92737
|
+
if (!response.ok) {
|
|
92738
|
+
throw new Error(await getErrorMessageFromResponse(response, "Failed to read the exchange mutation"));
|
|
92739
|
+
}
|
|
92740
|
+
return response.json();
|
|
92741
|
+
}
|
|
92742
|
+
var init_client_exchange_mutations = __esm({
|
|
92743
|
+
"lib/api/client-exchange-mutations.ts"() {
|
|
92744
|
+
"use strict";
|
|
92745
|
+
init_define_VTX_EXO_POLICY();
|
|
92746
|
+
init_define_VTX_GROK_POLICY();
|
|
92747
|
+
init_define_VTX_PI_MODEL_POLICY();
|
|
92748
|
+
init_shared();
|
|
92749
|
+
}
|
|
92750
|
+
});
|
|
92751
|
+
|
|
92410
92752
|
// lib/runtime/execution-guard-contract.ts
|
|
92411
92753
|
var unitsFromPosition, signedUnitsFromPosition, signedUnitsFromEntryPosition, classifyExecutionIntent, resolveExecutionTarget;
|
|
92412
92754
|
var init_execution_guard_contract = __esm({
|
|
@@ -92692,7 +93034,7 @@ var init_protective_trigger_price = __esm({
|
|
|
92692
93034
|
});
|
|
92693
93035
|
|
|
92694
93036
|
// lib/runtime/runtime-execution.ts
|
|
92695
|
-
var clientProtectiveMutationAuthority, executionReadPriority, fetchClientRuntimeOpenOrders, _extractOrderResponseStates, createRuntimeId, _extractOrderId, _toExecutionMetadata, _extractClientMutationId, _stableMutationIdentity, trailingStopMemory, protectiveGroupMemory, protectiveGroupReadFailures, windowHandoffCleanupAttempts, clientRuntimeProtectionStorage, resolveClientRuntimeProtectionStorage, setClientRuntimeProtectionStorage, trailingStopStorageKey, readTrackedTrailingStops, writeTrackedTrailingStops, rememberTrailingStop, protectiveGroupStorageKey, readClientProtectiveGroups, writeClientProtectiveGroups, hasClientProtectiveGroupReadFailure, readFreshClientProtectiveGroups, stableProtectionSnapshot, exactClientProtectiveGroupSnapshot, exactClientProtectiveGroupSetSnapshot, replaceExactClientProtectiveGroup, replaceExactClientProtectiveGroupSet, isClientRuntimeLeaseOwnershipError, hasClientRuntimeProtectionState, clearClientRuntimeVetoedProtectiveIntent, rethrowWindowHandoffAfterProtectiveReplacementVeto, canPersistClientProtectiveGroups, removeTrackedTrailingStop, replaceTrackedTrailingStop, replaceProtectiveLeg, replacementJournalEntryOrderId, buildProtectiveReplacementJournalGroup, isProtectiveReplacementJournalGroup, reserveProtectiveLegReplacement, ensureProtectiveReplacementJournalCompanion, buildVetoedProtectiveReplacementCleanup, assertExactProtectiveReplacementDispatchAuthority, transitionProtectiveReplacementAcknowledgement, transitionTerminalProtectiveReplacement, pendingProtectiveReplacementReport, isConfiguredProtectionRequested, protectiveAction, isExactClientPositionTpslPair, deviceOwnsClientProtectiveLegKind, isAdoptionNarrowedPositionTpslLeg, hasAmbiguousClientPositionTpslAuthority, protectiveStableShapeMatches, protectiveLiveShapeMatches, protectiveTerminalShapeMatches, cancelClientProtectiveLeg, buildPendingProtectivePlan, persistPendingClientProtectiveGroup, attachClientProtectivePlan, resolveJournaledAttachmentContinuity, recoverJournaledClientProtectiveAttachments, recoverPendingClientProtectiveGroups, recoverPendingProtectiveReplacements, reconcileClientProtectiveGroups, cancelAllClientProtectiveGroups, tightenClientTrailingStops, throwIfAborted2, sleep2, roundAssetSize, resolvePositionSize, resolveCurrentPositionSize, buildPositionSnapshot, signedRemainingExposureAfterConfirmedReduction, runtimeProtectionAuthority, runtimeProtectionOwners, resolveRuntimeProtectionOwner, drainServerProtectionForRuntime, drainServerProtectionIfOwned, verifyNoLiveClientProtectiveTriggers, clientExecutionMutations, withClientExecutionMutation, withClientProtectiveAdoptionMutation, executeClientRuntimeDecision, maintainClientRuntimeTrailingStops, listPendingClientProtectiveSymbols, listStoredClientProtectiveSymbols, hasUnresolvedClientProtectiveIdentity, resolveClientProtectiveIdentitiesForAdoption, exportClientProtectiveGroupsForAdoption, adoptionGroupKey, applyClientProtectiveAdoptionOutcomes, hasStoredClientProtectiveGroupsForWallet, hasPendingClientProtectiveGroups, recoverManualClientProtectiveGroups, executeClientRuntimeDecisionUnlocked, executeClientCopyTradingIntent, executeClientCopyTradingOrderAction;
|
|
93037
|
+
var clientProtectiveMutationAuthority, executionReadPriority, serverEntryLeverageAlreadyHeld, fetchClientRuntimeOpenOrders, _extractOrderResponseStates, createRuntimeId, _extractOrderId, _toExecutionMetadata, _extractClientMutationId, _stableMutationIdentity, trailingStopMemory, protectiveGroupMemory, protectiveGroupReadFailures, windowHandoffCleanupAttempts, clientRuntimeProtectionStorage, resolveClientRuntimeProtectionStorage, setClientRuntimeProtectionStorage, trailingStopStorageKey, readTrackedTrailingStops, writeTrackedTrailingStops, rememberTrailingStop, protectiveGroupStorageKey, withClientProtectivePlanSetLock, readClientProtectiveGroups, writeClientProtectiveGroups, hasClientProtectiveGroupReadFailure, readFreshClientProtectiveGroups, stableProtectionSnapshot, exactClientProtectiveGroupSnapshot, exactClientProtectiveGroupSetSnapshot, replaceExactClientProtectiveGroup, replaceExactClientProtectiveGroupSet, isClientRuntimeLeaseOwnershipError, hasClientRuntimeProtectionState, clearClientRuntimeVetoedProtectiveIntent, rethrowWindowHandoffAfterProtectiveReplacementVeto, canPersistClientProtectiveGroups, removeTrackedTrailingStop, replaceTrackedTrailingStop, replaceProtectiveLeg, replacementJournalEntryOrderId, buildProtectiveReplacementJournalGroup, isProtectiveReplacementJournalGroup, reserveProtectiveLegReplacement, ensureProtectiveReplacementJournalCompanion, buildVetoedProtectiveReplacementCleanup, assertExactProtectiveReplacementDispatchAuthority, transitionProtectiveReplacementAcknowledgement, transitionTerminalProtectiveReplacement, pendingProtectiveReplacementReport, isConfiguredProtectionRequested, protectiveAction, isExactClientPositionTpslPair, deviceOwnsClientProtectiveLegKind, isAdoptionNarrowedPositionTpslLeg, hasAmbiguousClientPositionTpslAuthority, protectiveStableShapeMatches, protectiveLiveShapeMatches, protectiveTerminalShapeMatches, cancelClientProtectiveLeg, buildPendingProtectivePlan, persistPendingClientProtectiveGroup, attachClientProtectivePlan, resolveJournaledAttachmentContinuity, recoverJournaledClientProtectiveAttachments, readPendingEntryMutation, requireClientRuntimeConfigSeconds, replacePendingEntryRecovery, recoverPendingClientProtectiveGroups, recoverPendingProtectiveReplacements, reconcileClientProtectiveGroups, cancelAllClientProtectiveGroups, tightenClientTrailingStops, throwIfAborted2, sleep2, isDefinitiveEntryRejection, resolveExchangeSizeDecimals, roundAssetSize, resolvePositionSize, resolveCurrentPositionSize, buildPositionSnapshot, signedRemainingExposureAfterConfirmedReduction, runtimeProtectionAuthority, runtimeProtectionOwners, resolveRuntimeProtectionOwner, drainServerProtectionForRuntime, drainServerProtectionIfOwned, verifyNoLiveClientProtectiveTriggers, clientExecutionMutations, withClientExecutionMutation, allocateServerExecutionCapacity, withClientProtectiveAdoptionMutation, executeClientRuntimeDecisionLocked, SERVER_AUDIT_RECORDED_ELSEWHERE, serverExecutionAuditOutcome, executeClientRuntimeDecision, waitForFlipCloseFreshness, maintainClientRuntimeTrailingStops, listPendingClientProtectiveSymbols, listStoredClientProtectiveSymbols, hasUnresolvedClientProtectiveIdentity, resolveClientProtectiveIdentitiesForAdoption, exportClientProtectiveGroupsForAdoption, adoptionGroupKey, applyClientProtectiveAdoptionOutcomes, hasStoredClientProtectiveGroupsForWallet, hasPendingClientProtectiveGroups, recoverManualClientProtectiveGroups, clientRuntimeDecisionSizesOrders, executeClientRuntimeDecisionUnlocked, executeClientCopyTradingIntent, executeClientCopyTradingOrderAction;
|
|
92696
93038
|
var init_runtime_execution = __esm({
|
|
92697
93039
|
"lib/runtime/runtime-execution.ts"() {
|
|
92698
93040
|
"use strict";
|
|
@@ -92700,8 +93042,11 @@ var init_runtime_execution = __esm({
|
|
|
92700
93042
|
init_define_VTX_GROK_POLICY();
|
|
92701
93043
|
init_define_VTX_PI_MODEL_POLICY();
|
|
92702
93044
|
init_order_identity();
|
|
93045
|
+
init_runtime_policy_generated2();
|
|
93046
|
+
init_bounded_lock();
|
|
92703
93047
|
init_client_runtime_ownership_errors();
|
|
92704
93048
|
init_api2();
|
|
93049
|
+
init_client_exchange_mutations();
|
|
92705
93050
|
init_hyperliquid_order_status();
|
|
92706
93051
|
init_protective_actions();
|
|
92707
93052
|
init_browser_trading();
|
|
@@ -92729,6 +93074,26 @@ var init_runtime_execution = __esm({
|
|
|
92729
93074
|
);
|
|
92730
93075
|
return classified.reduceOnly ? "trading_reduce" : "trading_execute";
|
|
92731
93076
|
};
|
|
93077
|
+
serverEntryLeverageAlreadyHeld = async (input) => {
|
|
93078
|
+
if (input.executionMode !== "server") return false;
|
|
93079
|
+
const context = input.executionContext;
|
|
93080
|
+
const symbol2 = normalizeHyperliquidMarketSymbol(context.symbol);
|
|
93081
|
+
const wallet = String(context.walletAddress || "").trim();
|
|
93082
|
+
if (!symbol2 || !wallet || !Number.isInteger(context.leverage) || context.leverage <= 0 || !Number.isFinite(context.currentPositionSize) || context.currentPositionSize === 0) return false;
|
|
93083
|
+
let active;
|
|
93084
|
+
try {
|
|
93085
|
+
active = await fetchBrowserHyperliquidInfoPayload(
|
|
93086
|
+
{ config: input.config ?? null, signal: input.signal, publicRequestPriority: "trading_reconcile" },
|
|
93087
|
+
{ type: "activeAssetData", user: wallet, coin: symbol2 },
|
|
93088
|
+
"hyperliquid.activeAssetData"
|
|
93089
|
+
);
|
|
93090
|
+
} catch {
|
|
93091
|
+
throwIfAborted2(input.signal);
|
|
93092
|
+
return false;
|
|
93093
|
+
}
|
|
93094
|
+
const leverage = active?.leverage;
|
|
93095
|
+
return leverage?.value === context.leverage && leverage?.type === (context.marginMode === "isolated" ? "isolated" : "cross");
|
|
93096
|
+
};
|
|
92732
93097
|
fetchClientRuntimeOpenOrders = async (request, publicRequestPriority = "trading_reconcile") => {
|
|
92733
93098
|
const normalizedSymbol = normalizeHyperliquidMarketSymbol(
|
|
92734
93099
|
request.executionContext.symbol
|
|
@@ -92943,6 +93308,12 @@ var init_runtime_execution = __esm({
|
|
|
92943
93308
|
]);
|
|
92944
93309
|
};
|
|
92945
93310
|
protectiveGroupStorageKey = (profileId, symbol2) => `vtx:auto-protective-group:${profileId}:${symbol2}`;
|
|
93311
|
+
withClientProtectivePlanSetLock = (profileId, symbol2, work, signal) => withBoundedExclusiveLock(
|
|
93312
|
+
`vtx:protective-plan-set:${protectiveGroupStorageKey(String(profileId).trim(), String(symbol2).trim())}`,
|
|
93313
|
+
runtime_policy_generated_default2.trading.engine.client_runtime.protective_plan_set_lock.wait_seconds * 1e3,
|
|
93314
|
+
work,
|
|
93315
|
+
signal
|
|
93316
|
+
);
|
|
92946
93317
|
readClientProtectiveGroups = (profileId, symbol2) => {
|
|
92947
93318
|
const key = protectiveGroupStorageKey(profileId, symbol2);
|
|
92948
93319
|
const inMemory = protectiveGroupMemory.get(key);
|
|
@@ -93036,12 +93407,41 @@ var init_runtime_execution = __esm({
|
|
|
93036
93407
|
const pending3 = pendingRecord;
|
|
93037
93408
|
const stopLoss = pending3.stopLoss;
|
|
93038
93409
|
const takeProfit = pending3.takeProfit;
|
|
93039
|
-
if (typeof pending3.entryMutationId !== "string" || !/^[0-9a-f-]{36}$/.test(pending3.entryMutationId) || typeof pending3.entryClientOrderId !== "string" || !/^0x[0-9a-f]{32}$/.test(pending3.entryClientOrderId) || pending3.entrySide !== "buy" && pending3.entrySide !== "sell" || !Number.isFinite(Number(pending3.requestedSize)) || Number(pending3.requestedSize) <= 0 || stopLoss == null || typeof stopLoss !== "object" || Array.isArray(stopLoss) || takeProfit == null || typeof takeProfit !== "object" || Array.isArray(takeProfit)) {
|
|
93410
|
+
if (typeof pending3.entryMutationId !== "string" || !/^[0-9a-f-]{36}$/.test(pending3.entryMutationId) || typeof pending3.entryClientOrderId !== "string" || !/^0x[0-9a-f]{32}$/.test(pending3.entryClientOrderId) || pending3.entrySide !== "buy" && pending3.entrySide !== "sell" || !Number.isFinite(Number(pending3.requestedSize)) || Number(pending3.requestedSize) <= 0 || pending3.createdAtMs != null && (typeof pending3.createdAtMs !== "number" || !Number.isSafeInteger(pending3.createdAtMs) || pending3.createdAtMs <= 0) || stopLoss == null || typeof stopLoss !== "object" || Array.isArray(stopLoss) || takeProfit == null || typeof takeProfit !== "object" || Array.isArray(takeProfit)) {
|
|
93040
93411
|
protectiveGroupReadFailures.add(key);
|
|
93041
93412
|
return [];
|
|
93042
93413
|
}
|
|
93043
93414
|
const sl = stopLoss;
|
|
93044
93415
|
const tp = takeProfit;
|
|
93416
|
+
let recovery;
|
|
93417
|
+
if (pending3.recovery != null) {
|
|
93418
|
+
const recoveryRecord = pending3.recovery;
|
|
93419
|
+
if (typeof recoveryRecord !== "object" || Array.isArray(recoveryRecord)) {
|
|
93420
|
+
protectiveGroupReadFailures.add(key);
|
|
93421
|
+
return [];
|
|
93422
|
+
}
|
|
93423
|
+
const {
|
|
93424
|
+
unknownOidObservedAtMs,
|
|
93425
|
+
unknownOidFirstSeenAtMs,
|
|
93426
|
+
attempts,
|
|
93427
|
+
nextAttemptAtMs,
|
|
93428
|
+
staleReported,
|
|
93429
|
+
entryFilled
|
|
93430
|
+
} = recoveryRecord;
|
|
93431
|
+
const invalidCount = (value, minimum) => value != null && (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum);
|
|
93432
|
+
if (invalidCount(unknownOidObservedAtMs, 1) || invalidCount(unknownOidFirstSeenAtMs, 1) || invalidCount(attempts, 0) || invalidCount(nextAttemptAtMs, 0) || staleReported != null && typeof staleReported !== "boolean" || entryFilled != null && typeof entryFilled !== "boolean") {
|
|
93433
|
+
protectiveGroupReadFailures.add(key);
|
|
93434
|
+
return [];
|
|
93435
|
+
}
|
|
93436
|
+
recovery = {
|
|
93437
|
+
...typeof unknownOidObservedAtMs === "number" ? { unknownOidObservedAtMs } : {},
|
|
93438
|
+
...typeof unknownOidFirstSeenAtMs === "number" ? { unknownOidFirstSeenAtMs } : {},
|
|
93439
|
+
...typeof attempts === "number" ? { attempts } : {},
|
|
93440
|
+
...typeof nextAttemptAtMs === "number" ? { nextAttemptAtMs } : {},
|
|
93441
|
+
...typeof staleReported === "boolean" ? { staleReported } : {},
|
|
93442
|
+
...typeof entryFilled === "boolean" ? { entryFilled } : {}
|
|
93443
|
+
};
|
|
93444
|
+
}
|
|
93045
93445
|
if (typeof sl.enabled !== "boolean" || sl.mode !== "percent" && sl.mode !== "usdc" || !Number.isFinite(Number(sl.value)) || Number(sl.value) < 0 || typeof sl.isTrailing !== "boolean" || typeof tp.enabled !== "boolean" || tp.mode !== "percent" && tp.mode !== "usdc" || !Number.isFinite(Number(tp.value)) || Number(tp.value) < 0) {
|
|
93046
93446
|
protectiveGroupReadFailures.add(key);
|
|
93047
93447
|
return [];
|
|
@@ -93051,6 +93451,7 @@ var init_runtime_execution = __esm({
|
|
|
93051
93451
|
entryClientOrderId: pending3.entryClientOrderId,
|
|
93052
93452
|
entrySide: pending3.entrySide,
|
|
93053
93453
|
requestedSize: Number(pending3.requestedSize),
|
|
93454
|
+
...typeof pending3.createdAtMs === "number" ? { createdAtMs: pending3.createdAtMs } : {},
|
|
93054
93455
|
stopLoss: {
|
|
93055
93456
|
enabled: sl.enabled,
|
|
93056
93457
|
mode: sl.mode,
|
|
@@ -93061,7 +93462,8 @@ var init_runtime_execution = __esm({
|
|
|
93061
93462
|
enabled: tp.enabled,
|
|
93062
93463
|
mode: tp.mode,
|
|
93063
93464
|
value: Number(tp.value)
|
|
93064
|
-
}
|
|
93465
|
+
},
|
|
93466
|
+
...recovery ? { recovery } : {}
|
|
93065
93467
|
};
|
|
93066
93468
|
}
|
|
93067
93469
|
const attachmentRecord = record5.attachmentJournal;
|
|
@@ -93805,6 +94207,7 @@ var init_runtime_execution = __esm({
|
|
|
93805
94207
|
};
|
|
93806
94208
|
buildPendingProtectivePlan = (settings, input) => ({
|
|
93807
94209
|
...input,
|
|
94210
|
+
createdAtMs: Date.now(),
|
|
93808
94211
|
stopLoss: {
|
|
93809
94212
|
enabled: settings.stopLossEnabled !== false,
|
|
93810
94213
|
mode: settings.stopLossMode === "usdc" ? "usdc" : "percent",
|
|
@@ -94430,7 +94833,7 @@ var init_runtime_execution = __esm({
|
|
|
94430
94833
|
}
|
|
94431
94834
|
return reports;
|
|
94432
94835
|
};
|
|
94433
|
-
resolveJournaledAttachmentContinuity = async (request, group) => {
|
|
94836
|
+
resolveJournaledAttachmentContinuity = async (request, group, options = {}) => {
|
|
94434
94837
|
const journal = group.attachmentJournal;
|
|
94435
94838
|
const plan = group.pendingEntry;
|
|
94436
94839
|
if (journal == null || plan == null) {
|
|
@@ -94527,7 +94930,7 @@ var init_runtime_execution = __esm({
|
|
|
94527
94930
|
throw new Error("Journaled protective entry chronology is unresolved.");
|
|
94528
94931
|
}
|
|
94529
94932
|
const firstEntry = canonicalRows[firstEntryIndex];
|
|
94530
|
-
if (expectedSign * firstEntry.startPosition < -positionTolerance(firstEntry.startPosition, 0)) {
|
|
94933
|
+
if (options.allowOppositeStart !== true && expectedSign * firstEntry.startPosition < -positionTolerance(firstEntry.startPosition, 0)) {
|
|
94531
94934
|
throw new Error("Journaled protective entry start position is directionally unresolved.");
|
|
94532
94935
|
}
|
|
94533
94936
|
let expectedExposureEstablished = false;
|
|
@@ -94929,20 +95332,117 @@ var init_runtime_execution = __esm({
|
|
|
94929
95332
|
}
|
|
94930
95333
|
return reports;
|
|
94931
95334
|
};
|
|
94932
|
-
|
|
95335
|
+
readPendingEntryMutation = async (request, plan) => {
|
|
95336
|
+
try {
|
|
95337
|
+
const mutation = await getClientRuntimeExchangeMutation(
|
|
95338
|
+
request.profileId,
|
|
95339
|
+
plan.entryMutationId,
|
|
95340
|
+
request.signal
|
|
95341
|
+
);
|
|
95342
|
+
if (mutation == null) return { kind: "absent" };
|
|
95343
|
+
return mutation.operation_kind === "order" && String(mutation.client_order_id ?? "").trim().toLowerCase() === plan.entryClientOrderId ? { kind: "found", mutation } : { kind: "unavailable" };
|
|
95344
|
+
} catch (error48) {
|
|
95345
|
+
if (request.signal?.aborted) throw error48;
|
|
95346
|
+
return { kind: "unavailable" };
|
|
95347
|
+
}
|
|
95348
|
+
};
|
|
95349
|
+
requireClientRuntimeConfigSeconds = (config2, key) => {
|
|
95350
|
+
const value = Number(config2?.[key]);
|
|
95351
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
95352
|
+
throw new Error(`Missing required client runtime config: ${String(key)}`);
|
|
95353
|
+
}
|
|
95354
|
+
return value;
|
|
95355
|
+
};
|
|
95356
|
+
replacePendingEntryRecovery = (profileId, symbol2, group, recovery) => {
|
|
95357
|
+
const plan = group.pendingEntry;
|
|
95358
|
+
if (plan == null) throw new Error("Pending entry plan is unavailable.");
|
|
95359
|
+
const updated = { ...group, pendingEntry: { ...plan, recovery } };
|
|
95360
|
+
if (!replaceExactClientProtectiveGroup(profileId, symbol2, group, updated)) {
|
|
95361
|
+
throw new Error("Pending entry recovery state could not be saved durably.");
|
|
95362
|
+
}
|
|
95363
|
+
return updated;
|
|
95364
|
+
};
|
|
95365
|
+
recoverPendingClientProtectiveGroups = async (request, pendingGroups, retirements = [], reportsStale = false) => {
|
|
94933
95366
|
const reports = [];
|
|
94934
95367
|
const profileId = String(request.profileId).trim();
|
|
94935
95368
|
const symbol2 = request.executionContext.symbol;
|
|
94936
|
-
|
|
95369
|
+
const retryInitialMs = requireClientRuntimeConfigSeconds(
|
|
95370
|
+
request.config,
|
|
95371
|
+
"client_pending_entry_retry_initial_seconds"
|
|
95372
|
+
) * 1e3;
|
|
95373
|
+
const retryMaxMs = Math.max(retryInitialMs, requireClientRuntimeConfigSeconds(
|
|
95374
|
+
request.config,
|
|
95375
|
+
"client_pending_entry_retry_max_seconds"
|
|
95376
|
+
) * 1e3);
|
|
95377
|
+
const staleAfterAttempts = Math.max(1, Math.trunc(requireClientRuntimeConfigSeconds(
|
|
95378
|
+
request.config,
|
|
95379
|
+
"client_pending_entry_stale_after_attempts"
|
|
95380
|
+
)));
|
|
95381
|
+
for (const storedGroup of pendingGroups) {
|
|
95382
|
+
let group = storedGroup;
|
|
94937
95383
|
const plan = group.pendingEntry;
|
|
94938
95384
|
if (plan == null) continue;
|
|
95385
|
+
const waitMs = (plan.recovery?.nextAttemptAtMs ?? 0) - Date.now();
|
|
95386
|
+
if (waitMs > 0 && waitMs <= retryMaxMs) continue;
|
|
95387
|
+
let entryFilled = plan.recovery?.entryFilled === true || group.attachmentJournal != null;
|
|
95388
|
+
const recordUnresolved = (errorMessage) => {
|
|
95389
|
+
const currentRecovery = group.pendingEntry?.recovery ?? plan.recovery;
|
|
95390
|
+
const attempts = (currentRecovery?.attempts ?? 0) + 1;
|
|
95391
|
+
const reachedCap = attempts >= staleAfterAttempts;
|
|
95392
|
+
const reportStale = reachedCap && reportsStale && currentRecovery?.staleReported !== true;
|
|
95393
|
+
try {
|
|
95394
|
+
group = replacePendingEntryRecovery(profileId, symbol2, group, {
|
|
95395
|
+
...currentRecovery,
|
|
95396
|
+
attempts,
|
|
95397
|
+
nextAttemptAtMs: entryFilled ? Date.now() : Date.now() + Math.min(retryMaxMs, retryInitialMs * 2 ** Math.min(30, attempts - 1)),
|
|
95398
|
+
...entryFilled ? { entryFilled: true } : {},
|
|
95399
|
+
...reportStale || currentRecovery?.staleReported === true ? { staleReported: true } : {}
|
|
95400
|
+
});
|
|
95401
|
+
} catch {
|
|
95402
|
+
reports.push({
|
|
95403
|
+
order_id: plan.entryClientOrderId,
|
|
95404
|
+
client_mutation_id: plan.entryMutationId,
|
|
95405
|
+
symbol: symbol2,
|
|
95406
|
+
action: "PROTECTIVE_RECONCILIATION",
|
|
95407
|
+
status: "failed",
|
|
95408
|
+
execution_metadata: { reason_code: "protective_lifecycle_persistence_failed" }
|
|
95409
|
+
});
|
|
95410
|
+
}
|
|
95411
|
+
if (errorMessage == null && !reportStale) return;
|
|
95412
|
+
if (reachedCap && !reportStale) return;
|
|
95413
|
+
reports.push({
|
|
95414
|
+
order_id: plan.entryClientOrderId,
|
|
95415
|
+
client_mutation_id: plan.entryMutationId,
|
|
95416
|
+
symbol: symbol2,
|
|
95417
|
+
action: "PROTECTIVE_RECONCILIATION",
|
|
95418
|
+
status: "failed",
|
|
95419
|
+
execution_metadata: {
|
|
95420
|
+
reason_code: reportStale ? "pending_protective_entry_stale" : "pending_protective_entry_unresolved",
|
|
95421
|
+
attempts,
|
|
95422
|
+
...errorMessage ? { error: errorMessage } : {}
|
|
95423
|
+
}
|
|
95424
|
+
});
|
|
95425
|
+
};
|
|
95426
|
+
const recordIfStillPending = () => {
|
|
95427
|
+
const stored = readFreshClientProtectiveGroups(profileId, symbol2);
|
|
95428
|
+
const snapshot = exactClientProtectiveGroupSnapshot(group);
|
|
95429
|
+
if (stored.some((candidate) => exactClientProtectiveGroupSnapshot(candidate) === snapshot)) {
|
|
95430
|
+
recordUnresolved(null);
|
|
95431
|
+
}
|
|
95432
|
+
};
|
|
95433
|
+
const retire = (reasonCode) => {
|
|
95434
|
+
if (!replaceExactClientProtectiveGroup(profileId, symbol2, group, null)) {
|
|
95435
|
+
throw new Error("Pending entry plan could not be retired durably.");
|
|
95436
|
+
}
|
|
95437
|
+
retirements.push({ entryOrderId: plan.entryClientOrderId, reasonCode });
|
|
95438
|
+
};
|
|
94939
95439
|
try {
|
|
94940
95440
|
if (group.attachmentJournal != null) {
|
|
94941
|
-
const { disposition } = await resolveJournaledAttachmentContinuity(
|
|
95441
|
+
const { disposition: disposition2 } = await resolveJournaledAttachmentContinuity(
|
|
94942
95442
|
request,
|
|
94943
95443
|
group
|
|
94944
95444
|
);
|
|
94945
|
-
if (
|
|
95445
|
+
if (disposition2 !== "matching") {
|
|
94946
95446
|
if (!replaceExactClientProtectiveGroup(profileId, symbol2, group, null)) {
|
|
94947
95447
|
reports.push({
|
|
94948
95448
|
order_id: group.attachmentJournal.entryOrderId,
|
|
@@ -94965,6 +95465,13 @@ var init_runtime_execution = __esm({
|
|
|
94965
95465
|
attachment2.handoffCleanup
|
|
94966
95466
|
);
|
|
94967
95467
|
}
|
|
95468
|
+
recordIfStillPending();
|
|
95469
|
+
continue;
|
|
95470
|
+
}
|
|
95471
|
+
const ledger = await readPendingEntryMutation(request, plan);
|
|
95472
|
+
const mutation = ledger.kind === "found" ? ledger.mutation : null;
|
|
95473
|
+
if (mutation != null && (mutation.status === "settled" || mutation.status === "reconciled") && mutation.outcome_code === "rejected") {
|
|
95474
|
+
retire("pending_protective_entry_rejected");
|
|
94968
95475
|
continue;
|
|
94969
95476
|
}
|
|
94970
95477
|
const evidence = await fetchBrowserOrderStatusEvidence({
|
|
@@ -94974,12 +95481,102 @@ var init_runtime_execution = __esm({
|
|
|
94974
95481
|
signal: request.signal,
|
|
94975
95482
|
orderId: plan.entryClientOrderId
|
|
94976
95483
|
});
|
|
95484
|
+
if (evidence.responseValid && evidence.responseStatus === "unknownOid") {
|
|
95485
|
+
const observedAtMs = Date.now();
|
|
95486
|
+
const marginMs = requireClientRuntimeConfigSeconds(
|
|
95487
|
+
request.config,
|
|
95488
|
+
"client_pending_entry_never_landed_margin_seconds"
|
|
95489
|
+
) * 1e3;
|
|
95490
|
+
const firstSeenAtMs = plan.recovery?.unknownOidFirstSeenAtMs ?? observedAtMs;
|
|
95491
|
+
const recordFirstSeen = () => {
|
|
95492
|
+
if (plan.recovery?.unknownOidFirstSeenAtMs != null) return;
|
|
95493
|
+
group = replacePendingEntryRecovery(profileId, symbol2, group, {
|
|
95494
|
+
...group.pendingEntry?.recovery ?? plan.recovery,
|
|
95495
|
+
unknownOidFirstSeenAtMs: firstSeenAtMs
|
|
95496
|
+
});
|
|
95497
|
+
};
|
|
95498
|
+
let provableAtMs;
|
|
95499
|
+
if (ledger.kind === "found") {
|
|
95500
|
+
const expiresAfterMs = Number(ledger.mutation.exchange_expires_after_ms);
|
|
95501
|
+
if (!Number.isSafeInteger(expiresAfterMs) || expiresAfterMs <= 0) {
|
|
95502
|
+
throw new Error("Pending entry is unknown to Hyperliquid and its signed expiry is unavailable.");
|
|
95503
|
+
}
|
|
95504
|
+
provableAtMs = expiresAfterMs + marginMs;
|
|
95505
|
+
} else if (ledger.kind === "absent") {
|
|
95506
|
+
const ageStartMs = plan.createdAtMs ?? firstSeenAtMs;
|
|
95507
|
+
const signedLifetimeSeconds = Number(
|
|
95508
|
+
request.config?.client_runtime_exchange_mutation?.expires_after_seconds
|
|
95509
|
+
);
|
|
95510
|
+
if (!Number.isInteger(signedLifetimeSeconds) || signedLifetimeSeconds <= 0) {
|
|
95511
|
+
throw new Error("Missing required client runtime config: client_runtime_exchange_mutation.expires_after_seconds");
|
|
95512
|
+
}
|
|
95513
|
+
provableAtMs = ageStartMs + signedLifetimeSeconds * 1e3 + marginMs;
|
|
95514
|
+
} else {
|
|
95515
|
+
recordFirstSeen();
|
|
95516
|
+
throw new Error("Pending entry is unknown to Hyperliquid and the ledger cannot answer.");
|
|
95517
|
+
}
|
|
95518
|
+
if (observedAtMs < provableAtMs) {
|
|
95519
|
+
recordFirstSeen();
|
|
95520
|
+
throw new Error("Pending entry is unknown to Hyperliquid while its signed action can still land.");
|
|
95521
|
+
}
|
|
95522
|
+
const confirmedAtMs = plan.recovery?.unknownOidObservedAtMs;
|
|
95523
|
+
if (confirmedAtMs == null || confirmedAtMs < provableAtMs) {
|
|
95524
|
+
group = replacePendingEntryRecovery(profileId, symbol2, group, {
|
|
95525
|
+
...group.pendingEntry?.recovery ?? plan.recovery,
|
|
95526
|
+
unknownOidFirstSeenAtMs: firstSeenAtMs,
|
|
95527
|
+
unknownOidObservedAtMs: observedAtMs
|
|
95528
|
+
});
|
|
95529
|
+
throw new Error("Pending entry is unknown to Hyperliquid; a second read confirms it never landed.");
|
|
95530
|
+
}
|
|
95531
|
+
const { rawFills: unknownEntryFills, evidence: unknownEntryFillEvidence } = await fetchBrowserUserFills({
|
|
95532
|
+
publicRequestPriority: "trading_reconcile",
|
|
95533
|
+
config: request.config ?? {},
|
|
95534
|
+
walletAddress: String(request.executionContext.walletAddress || "").trim(),
|
|
95535
|
+
symbols: [symbol2],
|
|
95536
|
+
forceRefresh: true,
|
|
95537
|
+
signal: request.signal
|
|
95538
|
+
});
|
|
95539
|
+
if (unknownEntryFillEvidence?.exactTerminalFillEvidenceComplete !== true) {
|
|
95540
|
+
throw new Error(
|
|
95541
|
+
`Never-landed pending entry fills are incomplete (${unknownEntryFillEvidence?.source ?? "unknown"}; provider_rows=${unknownEntryFillEvidence?.providerRowCount ?? "unknown"}).`
|
|
95542
|
+
);
|
|
95543
|
+
}
|
|
95544
|
+
if (unknownEntryFills.some((fill) => String(fill.cloid ?? "").trim().toLowerCase() === plan.entryClientOrderId)) {
|
|
95545
|
+
throw new Error("Pending entry is unknown to Hyperliquid but has fills for its CLOID.");
|
|
95546
|
+
}
|
|
95547
|
+
if (ledger.kind === "absent" && (await readPendingEntryMutation(request, plan)).kind !== "absent") {
|
|
95548
|
+
throw new Error("Pending entry reached the ledger while its retirement was being proven.");
|
|
95549
|
+
}
|
|
95550
|
+
retire("pending_protective_entry_never_landed");
|
|
95551
|
+
continue;
|
|
95552
|
+
}
|
|
94977
95553
|
const expectedSide = plan.entrySide === "buy" ? ["b", "buy"] : ["a", "sell"];
|
|
94978
|
-
const
|
|
94979
|
-
const
|
|
95554
|
+
const signedSize = evidence.originalSize;
|
|
95555
|
+
const sizeTolerance = Math.max(1e-10, (signedSize ?? 0) * 1e-8);
|
|
95556
|
+
const shapeMatches = evidence.responseValid && evidence.orderMatches && String(evidence.coin ?? "").trim().toUpperCase() === symbol2.trim().toUpperCase() && expectedSide.includes(String(evidence.side ?? "").trim().toLowerCase()) && evidence.reduceOnly === false && evidence.isTrigger === false && evidence.isPositionTpsl === false && signedSize != null && hyperliquidSignedSizeMatchesRequestedSize(
|
|
95557
|
+
plan.requestedSize,
|
|
95558
|
+
request.executionContext.sizeDecimals,
|
|
95559
|
+
signedSize
|
|
95560
|
+
);
|
|
95561
|
+
if (!shapeMatches && evidence.responseValid && evidence.orderMatches && evidence.terminal) {
|
|
95562
|
+
retire("pending_protective_entry_shape_mismatch");
|
|
95563
|
+
reports.push({
|
|
95564
|
+
order_id: plan.entryClientOrderId,
|
|
95565
|
+
client_mutation_id: plan.entryMutationId,
|
|
95566
|
+
symbol: symbol2,
|
|
95567
|
+
action: "PROTECTIVE_RECONCILIATION",
|
|
95568
|
+
status: "failed",
|
|
95569
|
+
execution_metadata: {
|
|
95570
|
+
reason_code: "pending_protective_entry_shape_mismatch",
|
|
95571
|
+
order_status: evidence.orderStatus
|
|
95572
|
+
}
|
|
95573
|
+
});
|
|
95574
|
+
continue;
|
|
95575
|
+
}
|
|
94980
95576
|
if (!shapeMatches || !evidence.terminal) {
|
|
94981
95577
|
throw new Error("Pending entry status or shape is unresolved.");
|
|
94982
95578
|
}
|
|
95579
|
+
if (evidence.fulfilled === true) entryFilled = true;
|
|
94983
95580
|
const { rawFills, evidence: fillEvidence } = await fetchBrowserUserFills({
|
|
94984
95581
|
publicRequestPriority: "trading_reconcile",
|
|
94985
95582
|
config: request.config ?? {},
|
|
@@ -95020,14 +95617,37 @@ var init_runtime_execution = __esm({
|
|
|
95020
95617
|
filledNotional += canonicalSize * canonicalPrice;
|
|
95021
95618
|
}
|
|
95022
95619
|
if (matchingFills.length === 0 && evidence.fulfilled === false) {
|
|
95023
|
-
|
|
95024
|
-
throw new Error("Non-filled pending entry could not be cleared durably.");
|
|
95025
|
-
}
|
|
95620
|
+
retire("pending_protective_entry_unfilled");
|
|
95026
95621
|
continue;
|
|
95027
95622
|
}
|
|
95028
|
-
if (!fillRowsValid || !Number.isFinite(filledSize) || filledSize <= 0 || filledSize >
|
|
95623
|
+
if (!fillRowsValid || !Number.isFinite(filledSize) || filledSize <= 0 || filledSize > (signedSize ?? 0) + sizeTolerance || !Number.isFinite(filledNotional) || filledNotional <= 0) {
|
|
95029
95624
|
throw new Error("Exact pending entry fills are unavailable.");
|
|
95030
95625
|
}
|
|
95626
|
+
const { disposition } = await resolveJournaledAttachmentContinuity(request, {
|
|
95627
|
+
...group,
|
|
95628
|
+
attachmentJournal: {
|
|
95629
|
+
phase: "awaiting_member_outcome",
|
|
95630
|
+
entryOrderId: confirmedEntryOrderId,
|
|
95631
|
+
filledSize,
|
|
95632
|
+
averagePrice: filledNotional / filledSize,
|
|
95633
|
+
members: []
|
|
95634
|
+
}
|
|
95635
|
+
}, { allowOppositeStart: true });
|
|
95636
|
+
if (disposition === "interrupted") {
|
|
95637
|
+
retire("protective_attachment_continuity_interrupted");
|
|
95638
|
+
reports.push({
|
|
95639
|
+
order_id: plan.entryClientOrderId,
|
|
95640
|
+
client_mutation_id: plan.entryMutationId,
|
|
95641
|
+
symbol: symbol2,
|
|
95642
|
+
action: "PROTECTIVE_RECONCILIATION",
|
|
95643
|
+
status: "failed",
|
|
95644
|
+
execution_metadata: {
|
|
95645
|
+
reason_code: "protective_attachment_continuity_interrupted",
|
|
95646
|
+
entry_order_id: plan.entryClientOrderId
|
|
95647
|
+
}
|
|
95648
|
+
});
|
|
95649
|
+
continue;
|
|
95650
|
+
}
|
|
95031
95651
|
const attachment = await attachClientProtectivePlan(request, group, {
|
|
95032
95652
|
orderId: String(evidence.orderId),
|
|
95033
95653
|
filledSize,
|
|
@@ -95039,21 +95659,12 @@ var init_runtime_execution = __esm({
|
|
|
95039
95659
|
attachment.handoffCleanup
|
|
95040
95660
|
);
|
|
95041
95661
|
}
|
|
95662
|
+
recordIfStillPending();
|
|
95042
95663
|
} catch (error48) {
|
|
95043
95664
|
if (isClientRuntimeWindowHandoffBeforePlanDispatch(error48) || isClientRuntimeLeaseOwnershipError(error48)) {
|
|
95044
95665
|
throw error48;
|
|
95045
95666
|
}
|
|
95046
|
-
|
|
95047
|
-
order_id: plan.entryClientOrderId,
|
|
95048
|
-
client_mutation_id: plan.entryMutationId,
|
|
95049
|
-
symbol: symbol2,
|
|
95050
|
-
action: "PROTECTIVE_RECONCILIATION",
|
|
95051
|
-
status: "failed",
|
|
95052
|
-
execution_metadata: {
|
|
95053
|
-
reason_code: "pending_protective_entry_unresolved",
|
|
95054
|
-
error: getSanitizedRuntimeErrorMessage(error48) || "Pending entry protection is unresolved."
|
|
95055
|
-
}
|
|
95056
|
-
});
|
|
95667
|
+
recordUnresolved(getSanitizedRuntimeErrorMessage(error48) || "Pending entry protection is unresolved.");
|
|
95057
95668
|
}
|
|
95058
95669
|
}
|
|
95059
95670
|
if (hasClientProtectiveGroupReadFailure(profileId, symbol2)) {
|
|
@@ -95617,11 +96228,10 @@ var init_runtime_execution = __esm({
|
|
|
95617
96228
|
...await recoverJournaledClientProtectiveAttachments(
|
|
95618
96229
|
request,
|
|
95619
96230
|
readClientProtectiveGroups(profileId, symbol2).filter((group) => group.pendingEntry != null && group.legs.length > 0)
|
|
95620
|
-
),
|
|
95621
|
-
...await recoverPendingClientProtectiveGroups(
|
|
95622
|
-
request,
|
|
95623
|
-
readClientProtectiveGroups(profileId, symbol2).filter((group) => group.pendingEntry != null && group.legs.length === 0)
|
|
95624
96231
|
)
|
|
96232
|
+
// Pending entries (no legs yet) are polled by one owner, the runtime's
|
|
96233
|
+
// pending-protection sweep (or the app host without a runtime), never
|
|
96234
|
+
// again by each decision.
|
|
95625
96235
|
];
|
|
95626
96236
|
const reconciliationGroupSet = readFreshClientProtectiveGroups(profileId, symbol2);
|
|
95627
96237
|
if (hasClientProtectiveGroupReadFailure(profileId, symbol2)) {
|
|
@@ -96676,6 +97286,18 @@ var init_runtime_execution = __esm({
|
|
|
96676
97286
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
96677
97287
|
});
|
|
96678
97288
|
};
|
|
97289
|
+
isDefinitiveEntryRejection = (error48, entryMutationId) => error48 instanceof HyperliquidExchangeRejectionError && Boolean(entryMutationId) && String(error48.clientMutationId ?? "").trim().toLowerCase() === String(entryMutationId).trim().toLowerCase();
|
|
97290
|
+
resolveExchangeSizeDecimals = async (symbol2, config2, publicRequestPriority) => {
|
|
97291
|
+
const { sz_decimals: sizeDecimals } = await resolveHyperliquidAsset({
|
|
97292
|
+
symbol: symbol2,
|
|
97293
|
+
config: config2,
|
|
97294
|
+
publicRequestPriority
|
|
97295
|
+
});
|
|
97296
|
+
if (!Number.isInteger(sizeDecimals) || sizeDecimals < 0) {
|
|
97297
|
+
throw new Error(`Hyperliquid size precision is unavailable for ${symbol2}.`);
|
|
97298
|
+
}
|
|
97299
|
+
return sizeDecimals;
|
|
97300
|
+
};
|
|
96679
97301
|
roundAssetSize = (size, decimals) => {
|
|
96680
97302
|
if (!Number.isFinite(size)) {
|
|
96681
97303
|
return 0;
|
|
@@ -96793,6 +97415,7 @@ var init_runtime_execution = __esm({
|
|
|
96793
97415
|
return pending3;
|
|
96794
97416
|
};
|
|
96795
97417
|
drainServerProtectionForRuntime = async (request, initialActions) => {
|
|
97418
|
+
if (request.executionMode === "server") return;
|
|
96796
97419
|
try {
|
|
96797
97420
|
await drainClientProtectiveActions({
|
|
96798
97421
|
profileId: request.profileId,
|
|
@@ -96877,9 +97500,178 @@ var init_runtime_execution = __esm({
|
|
|
96877
97500
|
if (clientExecutionMutations.get(key) === pending3) clientExecutionMutations.delete(key);
|
|
96878
97501
|
}
|
|
96879
97502
|
};
|
|
97503
|
+
allocateServerExecutionCapacity = async (authority, plans) => {
|
|
97504
|
+
if (plans.length === 0) return [];
|
|
97505
|
+
try {
|
|
97506
|
+
return await checkServerHostExecutionCapacity(
|
|
97507
|
+
authority.profileId,
|
|
97508
|
+
plans,
|
|
97509
|
+
authority.signal,
|
|
97510
|
+
authority.sessionId,
|
|
97511
|
+
authority.runtimeLeaseToken,
|
|
97512
|
+
authority.runtimeDeviceId,
|
|
97513
|
+
authority.schedulerInstanceId
|
|
97514
|
+
);
|
|
97515
|
+
} catch {
|
|
97516
|
+
throwIfAborted2(authority.signal);
|
|
97517
|
+
return plans.map(() => "unavailable");
|
|
97518
|
+
}
|
|
97519
|
+
};
|
|
96880
97520
|
withClientProtectiveAdoptionMutation = (profileId, work, signal) => withClientExecutionMutation({ profileId: String(profileId).trim(), signal }, work);
|
|
96881
|
-
|
|
96882
|
-
|
|
97521
|
+
executeClientRuntimeDecisionLocked = (input) => withClientExecutionMutation(input, () => withClientProtectivePlanSetLock(
|
|
97522
|
+
input.profileId,
|
|
97523
|
+
input.executionContext.symbol,
|
|
97524
|
+
() => executeClientRuntimeDecisionUnlocked(input),
|
|
97525
|
+
input.signal
|
|
97526
|
+
));
|
|
97527
|
+
SERVER_AUDIT_RECORDED_ELSEWHERE = /* @__PURE__ */ new Set([
|
|
97528
|
+
"suppressed_duplicate_decision",
|
|
97529
|
+
"same_intent_cooldown",
|
|
97530
|
+
"redis_unavailable",
|
|
97531
|
+
"execution_capacity_refused",
|
|
97532
|
+
"execution_capacity_unavailable"
|
|
97533
|
+
]);
|
|
97534
|
+
serverExecutionAuditOutcome = (result) => {
|
|
97535
|
+
if (result.status === "executed") {
|
|
97536
|
+
if (result.reasonCode === "close_fill_unresolved") return ["executed", "close_fill_unresolved"];
|
|
97537
|
+
if (result.reasonCode === "flip_close_fill_unresolved") return ["blocked", "flip_close_fill_unresolved"];
|
|
97538
|
+
if (result.reasonCode === "protective_reconciliation_unresolved") return ["blocked", "protective_reconciliation_unresolved"];
|
|
97539
|
+
return ["executed", "executed"];
|
|
97540
|
+
}
|
|
97541
|
+
if (result.status === "skipped") {
|
|
97542
|
+
if (result.reasonCode === "noop_already_at_target" || result.reasonCode === "stale_target_conflict") {
|
|
97543
|
+
return ["noop", result.reasonCode];
|
|
97544
|
+
}
|
|
97545
|
+
if (result.reasonCode === "protective_reconciliation_unresolved") return ["blocked", result.reasonCode];
|
|
97546
|
+
return ["blocked", "local_safety_block"];
|
|
97547
|
+
}
|
|
97548
|
+
const failure2 = result.executionReports.find((report) => report.status === "failed");
|
|
97549
|
+
const failureReason = String(failure2?.execution_metadata?.reason_code ?? "");
|
|
97550
|
+
if (failureReason === "outcome_unknown") return ["outcome_unknown", "outcome_unknown"];
|
|
97551
|
+
return ["error", failureReason === "exchange_rejected" ? "exchange_rejected" : "execution_error"];
|
|
97552
|
+
};
|
|
97553
|
+
executeClientRuntimeDecision = async (input) => {
|
|
97554
|
+
if (input.executionMode !== "server") return executeClientRuntimeDecisionLocked(input);
|
|
97555
|
+
const audit = input.serverExecutionAudit ?? { auditId: null };
|
|
97556
|
+
let entryDispatched = false;
|
|
97557
|
+
let result;
|
|
97558
|
+
try {
|
|
97559
|
+
result = await executeClientRuntimeDecisionLocked({
|
|
97560
|
+
...input,
|
|
97561
|
+
serverExecutionAudit: audit,
|
|
97562
|
+
onExchangeOrderDispatched: (kind) => {
|
|
97563
|
+
input.onExchangeOrderDispatched?.(kind);
|
|
97564
|
+
if (kind === "entry") entryDispatched = true;
|
|
97565
|
+
}
|
|
97566
|
+
});
|
|
97567
|
+
} catch (error48) {
|
|
97568
|
+
if (audit.auditId !== null && !input.signal?.aborted && (input.decision === "BUY" || input.decision === "SELL")) {
|
|
97569
|
+
const reason = String(error48?.reasonCode ?? "");
|
|
97570
|
+
const [status2, reasonCode2] = reason === "outcome_unknown" || !reason && entryDispatched ? ["outcome_unknown", "outcome_unknown"] : ["error", reason === "exchange_rejected" ? "exchange_rejected" : "execution_error"];
|
|
97571
|
+
try {
|
|
97572
|
+
await recordServerHostExecutionAudit(
|
|
97573
|
+
input.profileId,
|
|
97574
|
+
{
|
|
97575
|
+
auditId: audit.auditId,
|
|
97576
|
+
cycleId: input.cycleId ?? null,
|
|
97577
|
+
symbol: input.executionContext.symbol,
|
|
97578
|
+
intent: "open",
|
|
97579
|
+
side: input.decision === "BUY" ? "buy" : "sell",
|
|
97580
|
+
requestedUnits: Math.max(0, Math.trunc(input.units)),
|
|
97581
|
+
reduceOnly: false,
|
|
97582
|
+
lastPrice: input.executionContext.lastPrice,
|
|
97583
|
+
status: status2,
|
|
97584
|
+
reasonCode: reasonCode2,
|
|
97585
|
+
orderId: null
|
|
97586
|
+
},
|
|
97587
|
+
input.signal,
|
|
97588
|
+
input.sessionId,
|
|
97589
|
+
input.runtimeLeaseToken,
|
|
97590
|
+
input.runtimeDeviceId,
|
|
97591
|
+
input.schedulerInstanceId
|
|
97592
|
+
);
|
|
97593
|
+
} catch (auditError) {
|
|
97594
|
+
appendRuntimeDebugEvent({
|
|
97595
|
+
label: "server_execution_audit_failed",
|
|
97596
|
+
note: getSanitizedRuntimeErrorMessage(auditError) || "unknown",
|
|
97597
|
+
outcome: "error"
|
|
97598
|
+
});
|
|
97599
|
+
}
|
|
97600
|
+
}
|
|
97601
|
+
throw error48;
|
|
97602
|
+
}
|
|
97603
|
+
if (result.intent === "hold" || !(input.decision === "BUY" || input.decision === "SELL") || SERVER_AUDIT_RECORDED_ELSEWHERE.has(String(result.reasonCode ?? ""))) {
|
|
97604
|
+
return result;
|
|
97605
|
+
}
|
|
97606
|
+
const [status, reasonCode] = serverExecutionAuditOutcome(result);
|
|
97607
|
+
const orderId = result.executionReports.find((report) => report.status === "executed" && report.order_id)?.order_id ?? null;
|
|
97608
|
+
try {
|
|
97609
|
+
const recorded = await recordServerHostExecutionAudit(
|
|
97610
|
+
input.profileId,
|
|
97611
|
+
{
|
|
97612
|
+
auditId: audit.auditId,
|
|
97613
|
+
cycleId: input.cycleId ?? null,
|
|
97614
|
+
symbol: input.executionContext.symbol,
|
|
97615
|
+
intent: result.intent,
|
|
97616
|
+
side: result.side ?? null,
|
|
97617
|
+
requestedUnits: Math.max(0, Math.trunc(result.requestedUnits)),
|
|
97618
|
+
reduceOnly: result.reduceOnly,
|
|
97619
|
+
lastPrice: input.executionContext.lastPrice,
|
|
97620
|
+
status,
|
|
97621
|
+
reasonCode,
|
|
97622
|
+
orderId: orderId === null ? null : String(orderId)
|
|
97623
|
+
},
|
|
97624
|
+
input.signal,
|
|
97625
|
+
input.sessionId,
|
|
97626
|
+
input.runtimeLeaseToken,
|
|
97627
|
+
input.runtimeDeviceId,
|
|
97628
|
+
input.schedulerInstanceId
|
|
97629
|
+
);
|
|
97630
|
+
audit.auditId = recorded.audit_id;
|
|
97631
|
+
} catch (error48) {
|
|
97632
|
+
appendRuntimeDebugEvent({
|
|
97633
|
+
label: "server_execution_audit_failed",
|
|
97634
|
+
note: getSanitizedRuntimeErrorMessage(error48) || "unknown",
|
|
97635
|
+
outcome: "error"
|
|
97636
|
+
});
|
|
97637
|
+
}
|
|
97638
|
+
if (audit.auditId === null) return result;
|
|
97639
|
+
const auditId = audit.auditId;
|
|
97640
|
+
return {
|
|
97641
|
+
...result,
|
|
97642
|
+
executionReports: result.executionReports.map((report) => report.status === "executed" && ["BUY", "SELL", "FLIP_OPEN"].includes(String(report.action).toUpperCase()) ? { ...report, execution_metadata: { ...report.execution_metadata, execution_audit_id: auditId } } : report)
|
|
97643
|
+
};
|
|
97644
|
+
};
|
|
97645
|
+
waitForFlipCloseFreshness = async (input) => {
|
|
97646
|
+
const delayMs = Math.round(input.executionContext.closePositionDelaySeconds * 1e3);
|
|
97647
|
+
if (!(delayMs > 0)) return;
|
|
97648
|
+
const pollMs = Number(input.executionContext.closePositionFreshnessPollMs);
|
|
97649
|
+
const walletAddress = String(input.executionContext.walletAddress || "").trim();
|
|
97650
|
+
if (input.executionMode !== "server" || !(pollMs > 0) || !walletAddress) {
|
|
97651
|
+
await sleep2(delayMs, input.signal);
|
|
97652
|
+
return;
|
|
97653
|
+
}
|
|
97654
|
+
const deadline = Date.now() + delayMs;
|
|
97655
|
+
for (; ; ) {
|
|
97656
|
+
throwIfAborted2(input.signal);
|
|
97657
|
+
try {
|
|
97658
|
+
const snapshot = await fetchBrowserPositionSnapshot(
|
|
97659
|
+
input.config ?? {},
|
|
97660
|
+
walletAddress,
|
|
97661
|
+
input.executionContext.symbol,
|
|
97662
|
+
input.signal,
|
|
97663
|
+
executionReadPriority(input)
|
|
97664
|
+
);
|
|
97665
|
+
if (Number(snapshot.size) === 0) return;
|
|
97666
|
+
} catch {
|
|
97667
|
+
throwIfAborted2(input.signal);
|
|
97668
|
+
}
|
|
97669
|
+
const remaining = deadline - Date.now();
|
|
97670
|
+
if (remaining <= 0) return;
|
|
97671
|
+
await sleep2(Math.min(pollMs, remaining), input.signal);
|
|
97672
|
+
}
|
|
97673
|
+
};
|
|
97674
|
+
maintainClientRuntimeTrailingStops = (request) => withClientExecutionMutation(request, () => withClientProtectivePlanSetLock(request.profileId, request.executionContext.symbol, async () => {
|
|
96883
97675
|
const context = request.executionContext;
|
|
96884
97676
|
const capturedAt = Date.parse(context.decisionSnapshotCapturedAt ?? "");
|
|
96885
97677
|
const maxAge = Number(context.executionFreshnessMaxAgeSeconds) * 1e3;
|
|
@@ -96888,15 +97680,11 @@ var init_runtime_execution = __esm({
|
|
|
96888
97680
|
const groups = readFreshClientProtectiveGroups(String(request.profileId).trim(), context.symbol);
|
|
96889
97681
|
if (hasClientProtectiveGroupReadFailure(String(request.profileId).trim(), context.symbol) || groups.some((group) => group.walletAddress !== String(context.walletAddress ?? "").trim().toLowerCase() || group.pendingEntry || group.attachmentJournal || group.cleanupRequired || group.legs.some((leg) => leg.replacement))) return [];
|
|
96890
97682
|
if (!groups.some((group) => group.legs.some((leg) => leg.isTrailing && typeof leg.orderId === "number"))) return [];
|
|
96891
|
-
const
|
|
96892
|
-
symbol: context.symbol,
|
|
96893
|
-
config: request.config,
|
|
96894
|
-
publicRequestPriority: "trading_reduce"
|
|
96895
|
-
});
|
|
97683
|
+
const assetSizeDecimals = await resolveExchangeSizeDecimals(context.symbol, request.config ?? void 0, "trading_reduce");
|
|
96896
97684
|
const isLong = context.currentPositionSize > 0;
|
|
96897
97685
|
const improves = groups.some((group) => group.isLong === isLong && group.legs.some((leg) => {
|
|
96898
97686
|
if (!leg.isTrailing || typeof leg.orderId !== "number") return false;
|
|
96899
|
-
const size = roundAssetSize(Math.min(leg.size, Math.abs(context.currentPositionSize)),
|
|
97687
|
+
const size = roundAssetSize(Math.min(leg.size, Math.abs(context.currentPositionSize)), assetSizeDecimals);
|
|
96900
97688
|
if (!(size > 0)) return false;
|
|
96901
97689
|
return resolveTrailingStopTightening({
|
|
96902
97690
|
currentPrice: context.lastPrice,
|
|
@@ -96911,12 +97699,16 @@ var init_runtime_execution = __esm({
|
|
|
96911
97699
|
}));
|
|
96912
97700
|
if (!improves) return [];
|
|
96913
97701
|
await request.beforeTrailingMaintenance?.(request.signal);
|
|
96914
|
-
const guardedRequest = {
|
|
96915
|
-
|
|
96916
|
-
|
|
96917
|
-
|
|
97702
|
+
const guardedRequest = {
|
|
97703
|
+
...request,
|
|
97704
|
+
executionContext: { ...context, sizeDecimals: assetSizeDecimals },
|
|
97705
|
+
onExchangeOrderDispatched: (kind) => {
|
|
97706
|
+
if (Date.now() - capturedAt > maxAge) throw new Error("Trailing observation expired before exchange dispatch.");
|
|
97707
|
+
request.onExchangeOrderDispatched?.(kind);
|
|
97708
|
+
}
|
|
97709
|
+
};
|
|
96918
97710
|
return tightenClientTrailingStops({ request: guardedRequest, currentPositionSize: context.currentPositionSize, currentPrice: context.lastPrice });
|
|
96919
|
-
});
|
|
97711
|
+
}, request.signal));
|
|
96920
97712
|
listPendingClientProtectiveSymbols = (profileId) => {
|
|
96921
97713
|
const storage3 = resolveClientRuntimeProtectionStorage();
|
|
96922
97714
|
if (!storage3) return [];
|
|
@@ -96970,11 +97762,7 @@ var init_runtime_execution = __esm({
|
|
|
96970
97762
|
if (!hasUnresolvedClientProtectiveIdentity(groups)) continue;
|
|
96971
97763
|
let symbolReports = [];
|
|
96972
97764
|
try {
|
|
96973
|
-
const
|
|
96974
|
-
symbol: symbol2,
|
|
96975
|
-
config: input.config,
|
|
96976
|
-
publicRequestPriority: "trading_reconcile"
|
|
96977
|
-
});
|
|
97765
|
+
const sizeDecimals = await resolveExchangeSizeDecimals(symbol2, input.config, "trading_reconcile");
|
|
96978
97766
|
const core = {
|
|
96979
97767
|
profileId,
|
|
96980
97768
|
config: input.config,
|
|
@@ -97186,7 +97974,8 @@ var init_runtime_execution = __esm({
|
|
|
97186
97974
|
const results = [];
|
|
97187
97975
|
for (const symbol2 of listPendingClientProtectiveSymbols(profileId)) {
|
|
97188
97976
|
throwIfAborted2(input.signal);
|
|
97189
|
-
const
|
|
97977
|
+
const retired = [];
|
|
97978
|
+
const reports = await withClientExecutionMutation({ profileId, signal: input.signal }, () => withClientProtectivePlanSetLock(profileId, symbol2, async () => {
|
|
97190
97979
|
const groups = readFreshClientProtectiveGroups(profileId, symbol2);
|
|
97191
97980
|
if (hasClientProtectiveGroupReadFailure(profileId, symbol2)) {
|
|
97192
97981
|
return [{
|
|
@@ -97199,14 +97988,7 @@ var init_runtime_execution = __esm({
|
|
|
97199
97988
|
}
|
|
97200
97989
|
const ownGroups = groups.filter((group) => group.pendingEntry != null && group.walletAddress === walletAddress.toLowerCase());
|
|
97201
97990
|
if (ownGroups.length === 0) return [];
|
|
97202
|
-
const
|
|
97203
|
-
symbol: symbol2,
|
|
97204
|
-
config: input.config,
|
|
97205
|
-
publicRequestPriority: "trading_reconcile"
|
|
97206
|
-
});
|
|
97207
|
-
if (!Number.isInteger(sizeDecimals) || sizeDecimals < 0) {
|
|
97208
|
-
throw new Error(`Hyperliquid size precision is unavailable for ${symbol2}.`);
|
|
97209
|
-
}
|
|
97991
|
+
const sizeDecimals = await resolveExchangeSizeDecimals(symbol2, input.config, "trading_reconcile");
|
|
97210
97992
|
const request = {
|
|
97211
97993
|
mutationAuthority: "manual_session",
|
|
97212
97994
|
profileId,
|
|
@@ -97222,21 +98004,100 @@ var init_runtime_execution = __esm({
|
|
|
97222
98004
|
),
|
|
97223
98005
|
...await recoverPendingClientProtectiveGroups(
|
|
97224
98006
|
request,
|
|
97225
|
-
readClientProtectiveGroups(profileId, symbol2).filter((group) => group.pendingEntry != null && group.legs.length === 0 && group.walletAddress === walletAddress.toLowerCase())
|
|
98007
|
+
readClientProtectiveGroups(profileId, symbol2).filter((group) => group.pendingEntry != null && group.legs.length === 0 && group.walletAddress === walletAddress.toLowerCase()),
|
|
98008
|
+
retired,
|
|
98009
|
+
input.reportsStale !== false
|
|
97226
98010
|
)
|
|
97227
98011
|
];
|
|
97228
|
-
});
|
|
97229
|
-
results.push({ symbol: symbol2, reports });
|
|
98012
|
+
}, input.signal));
|
|
98013
|
+
results.push({ symbol: symbol2, reports, ...retired.length > 0 ? { retired } : {} });
|
|
97230
98014
|
}
|
|
97231
98015
|
return results;
|
|
97232
98016
|
};
|
|
97233
|
-
|
|
97234
|
-
|
|
97235
|
-
const
|
|
98017
|
+
clientRuntimeDecisionSizesOrders = (input) => {
|
|
98018
|
+
const context = input.executionContext;
|
|
98019
|
+
const profileId = String(input.profileId).trim();
|
|
98020
|
+
if (input.decision !== "HOLD" && Math.max(0, Math.trunc(input.units)) > 0) return true;
|
|
98021
|
+
if (readClientProtectiveGroups(profileId, context.symbol).some((group) => group.legs.length > 0 || group.attachmentJournal != null) || hasClientProtectiveGroupReadFailure(profileId, context.symbol)) {
|
|
98022
|
+
return true;
|
|
98023
|
+
}
|
|
98024
|
+
const positionSize = Number.isFinite(context.currentPositionSize) ? Number(context.currentPositionSize) : 0;
|
|
98025
|
+
return !input.skipTrailingMaintenance && context.tpSlEnabled === true && context.stopLossEnabled !== false && context.stopLossType === "trailing" && positionSize !== 0;
|
|
98026
|
+
};
|
|
98027
|
+
executeClientRuntimeDecisionUnlocked = async (unsizedInput) => {
|
|
98028
|
+
throwIfAborted2(unsizedInput.signal);
|
|
98029
|
+
const requestedUnits = Math.max(0, Math.trunc(unsizedInput.units));
|
|
97236
98030
|
appendRuntimeDebugEvent({
|
|
97237
98031
|
label: "execution_start",
|
|
97238
|
-
note: `decision=${
|
|
98032
|
+
note: `decision=${unsizedInput.decision} units=${requestedUnits} symbol=${unsizedInput.executionContext.symbol}`
|
|
97239
98033
|
});
|
|
98034
|
+
if (!clientRuntimeDecisionSizesOrders(unsizedInput)) {
|
|
98035
|
+
return {
|
|
98036
|
+
status: "skipped",
|
|
98037
|
+
intent: "hold",
|
|
98038
|
+
side: null,
|
|
98039
|
+
reduceOnly: false,
|
|
98040
|
+
requestedUnits,
|
|
98041
|
+
targetSignedUnits: signedUnitsFromEntryPosition(
|
|
98042
|
+
Number.isFinite(unsizedInput.executionContext.currentPositionSize) ? Number(unsizedInput.executionContext.currentPositionSize) : 0,
|
|
98043
|
+
unsizedInput.executionContext.currentPositionEntryPrice,
|
|
98044
|
+
unsizedInput.executionContext.unitSizeUsdc
|
|
98045
|
+
),
|
|
98046
|
+
executedSizeAsset: 0,
|
|
98047
|
+
executionReports: [],
|
|
98048
|
+
message: unsizedInput.decision === "HOLD" ? "Hold (No Action)" : "Unsupported decision",
|
|
98049
|
+
executionSnapshotId: createRuntimeId(),
|
|
98050
|
+
executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
98051
|
+
};
|
|
98052
|
+
}
|
|
98053
|
+
if (unsizedInput.executionMode === "server" && !unsizedInput.serverCapacityChecked && (unsizedInput.decision === "BUY" || unsizedInput.decision === "SELL") && requestedUnits > 0) {
|
|
98054
|
+
const skipped = (reasonCode, message) => ({
|
|
98055
|
+
status: "skipped",
|
|
98056
|
+
intent: "hold",
|
|
98057
|
+
side: null,
|
|
98058
|
+
reduceOnly: false,
|
|
98059
|
+
requestedUnits,
|
|
98060
|
+
targetSignedUnits: 0,
|
|
98061
|
+
executedSizeAsset: 0,
|
|
98062
|
+
executionReports: [],
|
|
98063
|
+
message,
|
|
98064
|
+
reasonCode,
|
|
98065
|
+
executionSnapshotId: createRuntimeId(),
|
|
98066
|
+
executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
98067
|
+
});
|
|
98068
|
+
const capacity = unsizedInput.serverCapacityAllocation ?? (await allocateServerExecutionCapacity(unsizedInput, [
|
|
98069
|
+
{ symbol: unsizedInput.executionContext.symbol, decision: unsizedInput.decision, units: requestedUnits }
|
|
98070
|
+
]))[0];
|
|
98071
|
+
if (capacity === "unavailable") {
|
|
98072
|
+
throwIfAborted2(unsizedInput.signal);
|
|
98073
|
+
return skipped("execution_capacity_unavailable", "Execution skipped: Failed to fetch positions before limit check.");
|
|
98074
|
+
}
|
|
98075
|
+
if (!capacity.accepted || !(capacity.units > 0)) {
|
|
98076
|
+
appendRuntimeDebugEvent({
|
|
98077
|
+
label: "execution_capacity_refused",
|
|
98078
|
+
note: `symbol=${unsizedInput.executionContext.symbol} reason=${capacity.reason_code ?? "unknown"}`,
|
|
98079
|
+
outcome: "ok"
|
|
98080
|
+
});
|
|
98081
|
+
return skipped("execution_capacity_refused", `Skipped: runtime constraint ${capacity.reason_code ?? "capacity"}.`);
|
|
98082
|
+
}
|
|
98083
|
+
return executeClientRuntimeDecisionUnlocked({
|
|
98084
|
+
...unsizedInput,
|
|
98085
|
+
units: Math.min(requestedUnits, Math.trunc(capacity.units)),
|
|
98086
|
+
serverCapacityChecked: true
|
|
98087
|
+
});
|
|
98088
|
+
}
|
|
98089
|
+
const input = {
|
|
98090
|
+
...unsizedInput,
|
|
98091
|
+
executionContext: {
|
|
98092
|
+
...unsizedInput.executionContext,
|
|
98093
|
+
sizeDecimals: await resolveExchangeSizeDecimals(
|
|
98094
|
+
unsizedInput.executionContext.symbol,
|
|
98095
|
+
unsizedInput.config ?? void 0,
|
|
98096
|
+
unsizedInput.decision === "HOLD" || requestedUnits <= 0 ? "trading_reconcile" : executionReadPriority(unsizedInput)
|
|
98097
|
+
)
|
|
98098
|
+
}
|
|
98099
|
+
};
|
|
98100
|
+
throwIfAborted2(input.signal);
|
|
97240
98101
|
const decisionSnapshotPositionSize = Number.isFinite(input.executionContext.currentPositionSize) ? Number(input.executionContext.currentPositionSize) : 0;
|
|
97241
98102
|
const decisionSnapshotSignedUnits = signedUnitsFromEntryPosition(
|
|
97242
98103
|
decisionSnapshotPositionSize,
|
|
@@ -97449,7 +98310,52 @@ var init_runtime_execution = __esm({
|
|
|
97449
98310
|
executionSnapshotCapturedAt
|
|
97450
98311
|
};
|
|
97451
98312
|
}
|
|
97452
|
-
if (
|
|
98313
|
+
if (input.executionMode === "server") {
|
|
98314
|
+
throwIfAborted2(input.signal);
|
|
98315
|
+
const claim = await claimServerHostExecution(
|
|
98316
|
+
input.profileId,
|
|
98317
|
+
{
|
|
98318
|
+
cycleId: input.cycleId ?? null,
|
|
98319
|
+
symbol: input.executionContext.symbol,
|
|
98320
|
+
intent: classified.intent,
|
|
98321
|
+
side: classified.side,
|
|
98322
|
+
requestedUnits: Math.max(0, Math.trunc(classified.requestedUnits)),
|
|
98323
|
+
reduceOnly: classified.reduceOnly,
|
|
98324
|
+
marginMode: input.executionContext.marginMode === "auto" ? null : input.executionContext.marginMode,
|
|
98325
|
+
lastPrice: input.executionContext.lastPrice
|
|
98326
|
+
},
|
|
98327
|
+
input.signal,
|
|
98328
|
+
input.sessionId,
|
|
98329
|
+
input.runtimeLeaseToken,
|
|
98330
|
+
input.runtimeDeviceId,
|
|
98331
|
+
input.schedulerInstanceId
|
|
98332
|
+
);
|
|
98333
|
+
if (input.serverExecutionAudit && typeof claim.audit_id === "number") {
|
|
98334
|
+
input.serverExecutionAudit.auditId = claim.audit_id;
|
|
98335
|
+
}
|
|
98336
|
+
if (!claim.allowed) {
|
|
98337
|
+
appendRuntimeDebugEvent({
|
|
98338
|
+
label: "execution_guard_suppressed",
|
|
98339
|
+
note: `symbol=${input.executionContext.symbol} intent=${classified.intent} reason=${claim.reason_code}`,
|
|
98340
|
+
outcome: "ok"
|
|
98341
|
+
});
|
|
98342
|
+
return {
|
|
98343
|
+
status: "skipped",
|
|
98344
|
+
intent: classified.intent,
|
|
98345
|
+
side: classified.side,
|
|
98346
|
+
reduceOnly: classified.reduceOnly,
|
|
98347
|
+
requestedUnits: classified.requestedUnits,
|
|
98348
|
+
targetSignedUnits: classified.targetSignedUnits,
|
|
98349
|
+
executedSizeAsset: 0,
|
|
98350
|
+
executionReports: reconciliationReports,
|
|
98351
|
+
message: "The execution guard suppressed a duplicate or repeated decision.",
|
|
98352
|
+
reasonCode: claim.reason_code,
|
|
98353
|
+
executionSnapshotId,
|
|
98354
|
+
executionSnapshotCapturedAt
|
|
98355
|
+
};
|
|
98356
|
+
}
|
|
98357
|
+
}
|
|
98358
|
+
if (!targetResolution.closeOpposingPosition && classified.reduceOnly !== true && !await serverEntryLeverageAlreadyHeld(input)) {
|
|
97453
98359
|
throwIfAborted2(input.signal);
|
|
97454
98360
|
await executeClientLeverageUpdate({
|
|
97455
98361
|
profileId: input.profileId,
|
|
@@ -97662,9 +98568,7 @@ var init_runtime_execution = __esm({
|
|
|
97662
98568
|
input.executionContext.symbol,
|
|
97663
98569
|
[]
|
|
97664
98570
|
);
|
|
97665
|
-
|
|
97666
|
-
await sleep2(Math.round(input.executionContext.closePositionDelaySeconds * 1e3), input.signal);
|
|
97667
|
-
}
|
|
98571
|
+
await waitForFlipCloseFreshness(input);
|
|
97668
98572
|
throwIfAborted2(input.signal);
|
|
97669
98573
|
await executeClientLeverageUpdate({
|
|
97670
98574
|
profileId: input.profileId,
|
|
@@ -97683,10 +98587,8 @@ var init_runtime_execution = __esm({
|
|
|
97683
98587
|
throwIfAborted2(input.signal);
|
|
97684
98588
|
}
|
|
97685
98589
|
const actualUnits = targetResolution.orderUnits;
|
|
97686
|
-
const
|
|
97687
|
-
|
|
97688
|
-
input.executionContext.sizeDecimals
|
|
97689
|
-
);
|
|
98590
|
+
const intendedSizeAsset = input.executionContext.unitSizeUsdc * actualUnits / executionPrice;
|
|
98591
|
+
const sizeAsset = Number.isFinite(intendedSizeAsset) && intendedSizeAsset > 0 ? quantizeHyperliquidOrderSizeValue(intendedSizeAsset, input.executionContext.sizeDecimals, "nearest") : 0;
|
|
97690
98592
|
appendRuntimeDebugEvent({
|
|
97691
98593
|
label: "execution_size_computed",
|
|
97692
98594
|
note: `symbol=${input.executionContext.symbol} actualUnits=${actualUnits} sizeAsset=${sizeAsset} price=${executionPrice}`
|
|
@@ -97694,7 +98596,7 @@ var init_runtime_execution = __esm({
|
|
|
97694
98596
|
if (sizeAsset <= 0) {
|
|
97695
98597
|
appendRuntimeDebugEvent({
|
|
97696
98598
|
label: "execution_skipped_zero_size",
|
|
97697
|
-
note: `actualUnits=${actualUnits} unitSize=${input.executionContext.unitSizeUsdc} decimals=${input.executionContext.sizeDecimals}`,
|
|
98599
|
+
note: `reason=size_below_lot_precision actualUnits=${actualUnits} unitSize=${input.executionContext.unitSizeUsdc} intendedSize=${intendedSizeAsset} decimals=${input.executionContext.sizeDecimals}`,
|
|
97698
98600
|
outcome: "error"
|
|
97699
98601
|
});
|
|
97700
98602
|
return {
|
|
@@ -97890,6 +98792,9 @@ var init_runtime_execution = __esm({
|
|
|
97890
98792
|
const handoffBeforeDispatch = handoffVeto || !entryDispatchBoundaryPassed && input.shouldCancelBeforeExchangeOrderDispatch?.() === true;
|
|
97891
98793
|
const hasCommittedReports = executionReports.some((report) => report.status === "executed" && String(report.order_id || "").trim().length > 0);
|
|
97892
98794
|
let vetoedProtectionCleanupFailed = false;
|
|
98795
|
+
if (pendingProtectiveGroup != null && entryDispatchBoundaryPassed && pendingProtectiveCleanup != null && isDefinitiveEntryRejection(entryDispatchError, entryMutationId)) {
|
|
98796
|
+
clearClientRuntimeVetoedProtectiveIntent(pendingProtectiveCleanup);
|
|
98797
|
+
}
|
|
97893
98798
|
if (pendingProtectiveGroup != null && !entryDispatchBoundaryPassed) {
|
|
97894
98799
|
if (pendingProtectiveCleanup == null || !clearClientRuntimeVetoedProtectiveIntent(pendingProtectiveCleanup)) {
|
|
97895
98800
|
vetoedProtectionCleanupFailed = true;
|
|
@@ -98843,7 +99748,7 @@ var init_runtime_execution = __esm({
|
|
|
98843
99748
|
});
|
|
98844
99749
|
|
|
98845
99750
|
// lib/runtime/protective-adoption-status.ts
|
|
98846
|
-
var deferrals,
|
|
99751
|
+
var deferrals, listeners2, notify, recordClientProtectiveAdoptionDeferral, clearClientProtectiveAdoptionDeferral;
|
|
98847
99752
|
var init_protective_adoption_status = __esm({
|
|
98848
99753
|
"lib/runtime/protective-adoption-status.ts"() {
|
|
98849
99754
|
"use strict";
|
|
@@ -98851,9 +99756,9 @@ var init_protective_adoption_status = __esm({
|
|
|
98851
99756
|
init_define_VTX_GROK_POLICY();
|
|
98852
99757
|
init_define_VTX_PI_MODEL_POLICY();
|
|
98853
99758
|
deferrals = /* @__PURE__ */ new Map();
|
|
98854
|
-
|
|
99759
|
+
listeners2 = /* @__PURE__ */ new Set();
|
|
98855
99760
|
notify = () => {
|
|
98856
|
-
|
|
99761
|
+
listeners2.forEach((listener) => listener());
|
|
98857
99762
|
};
|
|
98858
99763
|
recordClientProtectiveAdoptionDeferral = (profileId, symbols) => {
|
|
98859
99764
|
deferrals.set(String(profileId).trim(), { deferredAtMs: Date.now(), symbols: [...symbols] });
|
|
@@ -104023,7 +104928,7 @@ var init_inference_observability = __esm({
|
|
|
104023
104928
|
});
|
|
104024
104929
|
|
|
104025
104930
|
// lib/runtime/provider-client.ts
|
|
104026
|
-
var mapOpenAiCompatibleNativeRequestPath, isRetryableProviderFailureForFallback, extractRuntimeProviderFailureStatusCode, isModelSpecificProviderFailure, isKeySpecificOrTransientProviderFailure, providerDispatchClockMs, beginProviderDispatch, providerDispatchLatencyMs, attachProviderDispatchFailure, attachProviderFailureTrace, toRuntimeExecutionMode, buildNoneReasoningPayload, normalizeLevelValue, buildRuntimeReasoningPayload, resolveProviderReasoningParameters, requestedReasoningParameters, usesReasoningCompletionTokens, shouldRequestReasoningTrace, normalizeProviderToken, runtimeProviderForByokProvider, findByokProviderForRuntime, findNativeRequestParametersForModel, modelHasNativeRequestApiSurface, setDottedRequestValue, normalizeProviderMaxTokens, applyRuntimeRequestContract, normalizeProvider2, requireProviderEndpoint, estimateTokenCount, normalizeUsageCount, buildOpenAiUsagePayload, buildAnthropicUsagePayload, buildGoogleUsagePayload, normalizeProviderUsageMetrics, providerResponseSignals, fetchProvider, readProviderPayload, emitRuntimeDelta, readProviderTextStream, extractOpenAiCompatibleDeltaText, readOpenAiCompatibleTextStream, rawProviderTextForDebug, extractProviderErrorDetail, buildCanonicalProviderFailureMessage, toProviderNetworkDebugError, REASONING_ONLY_CONTENT_TYPES, extractOpenAiContentPartText, extractOpenAiReasoningPartText, extractOpenAiMessageContent, extractOpenAiMessageReasoningContent, extractOpenAiCompatibleText, normalizeRuntimeChatHistory, calculateProviderCost, callOpenAiCompatible, extractOpenAiResponsesText, extractOpenAiResponsesReasoning, callOpenAiResponses, extractAnthropicMessageText, extractAnthropicReasoningContent, callAnthropic, isVertexExpressKey, googlePublicModelIdRegexes, shouldUseGooglePublicEndpointForModel, normalizeGoogleModelId, shouldRetryGoogleVertexRequestPublicly, GOOGLE_VERTEX_PUBLIC_RETRY_NOTE, buildGoogleRequest, isGoogleReasoningPart, extractGoogleMessageText, extractGoogleReasoningContent, extractGoogleSafetyMetadata, GOOGLE_BLOCKED_FINISH_REASONS, googleProviderBlockReason, callGoogle, resolveRuntimeProvider, defaultInvocationContext, defaultProviderTransport, invocationFailureCode, buildBrowserInvocation, resolveProviderSecretKey, resolveNativeProviderCredentialSlots, resolveProviderSecretKeySlots, requireOpenAiCompatibleRuntimeBaseUrl, runtimeSubscriptionPlan, runtimeKeySlotSupportsModel, invokeRuntimeProviderAttempt, invokeRuntimeProvider;
|
|
104931
|
+
var mapOpenAiCompatibleNativeRequestPath, isRetryableProviderFailureForFallback, extractRuntimeProviderFailureStatusCode, isModelSpecificProviderFailure, isKeySpecificOrTransientProviderFailure, providerDispatchClockMs, beginProviderDispatch, providerDispatchLatencyMs, attachProviderDispatchFailure, attachProviderFailureTrace, toRuntimeExecutionMode, buildNoneReasoningPayload, normalizeLevelValue, buildRuntimeReasoningPayload, resolveProviderReasoningParameters, requestedReasoningParameters, usesReasoningCompletionTokens, shouldRequestReasoningTrace, normalizeProviderToken, runtimeProviderForByokProvider, findByokProviderForRuntime, findNativeRequestParametersForModel, modelHasNativeRequestApiSurface, setDottedRequestValue, normalizeProviderMaxTokens, applyRuntimeRequestContract, normalizeProvider2, requireProviderEndpoint, estimateTokenCount, normalizeUsageCount, buildOpenAiUsagePayload, buildAnthropicUsagePayload, buildGoogleUsagePayload, normalizeProviderUsageMetrics, providerResponseSignals, fetchProvider, readProviderPayload, emitRuntimeDelta, readProviderTextStream, extractOpenAiCompatibleDeltaText, readOpenAiCompatibleTextStream, rawProviderTextForDebug, extractProviderErrorDetail, buildCanonicalProviderFailureMessage, toProviderNetworkDebugError, REASONING_ONLY_CONTENT_TYPES, extractOpenAiContentPartText, extractOpenAiReasoningPartText, extractOpenAiMessageContent, extractOpenAiMessageReasoningContent, extractOpenAiCompatibleText, normalizeRuntimeChatHistory, calculateProviderCost, callOpenAiCompatible, extractOpenAiResponsesText, extractOpenAiResponsesReasoning, callOpenAiResponses, extractAnthropicMessageText, extractAnthropicReasoningContent, callAnthropic, isVertexExpressKey, googlePublicModelIdRegexes, shouldUseGooglePublicEndpointForModel, normalizeGoogleModelId, shouldRetryGoogleVertexRequestPublicly, GOOGLE_VERTEX_PUBLIC_RETRY_NOTE, buildGoogleRequest, isGoogleReasoningPart, extractGoogleMessageText, extractGoogleReasoningContent, extractGoogleSafetyMetadata, GOOGLE_BLOCKED_FINISH_REASONS, googleProviderBlockReason, callGoogle, resolveRuntimeProvider, defaultInvocationContext, defaultProviderTransport, invocationFailureCode, buildBrowserInvocation, resolveProviderSecretKey, resolveNativeProviderCredentialSlots, resolveProviderSecretKeySlots, requireOpenAiCompatibleRuntimeBaseUrl, runtimeSubscriptionPlan, runtimeKeySlotSupportsModel, invokeRuntimeProviderAttempt, runtimeProviderInvoker, invokeRuntimeProvider;
|
|
104027
104932
|
var init_provider_client = __esm({
|
|
104028
104933
|
"lib/runtime/provider-client.ts"() {
|
|
104029
104934
|
"use strict";
|
|
@@ -106738,8 +107643,10 @@ var init_provider_client = __esm({
|
|
|
106738
107643
|
toolCalls: response.toolCalls
|
|
106739
107644
|
};
|
|
106740
107645
|
};
|
|
107646
|
+
runtimeProviderInvoker = null;
|
|
106741
107647
|
invokeRuntimeProvider = async (input) => {
|
|
106742
107648
|
if (input.signal?.aborted) throw input.signal.reason ?? new DOMException("Cancelled", "AbortError");
|
|
107649
|
+
if (runtimeProviderInvoker) return runtimeProviderInvoker(input);
|
|
106743
107650
|
const policy2 = input.provider === "google" && Number(input.profileId) > 0 && !input.tools?.length && !input.onDelta && shouldUseGooglePublicEndpointForModel(input.config, input.model) ? googleEgressPolicyForModel(input.config.google_egress, input.model) : void 0;
|
|
106744
107651
|
if (policy2) {
|
|
106745
107652
|
const timeoutMs = Math.min(input.timeoutMs ?? policy2.deadline_seconds * 1e3, policy2.deadline_seconds * 1e3);
|
|
@@ -107730,7 +108637,7 @@ var init_reasoning_controls = __esm({
|
|
|
107730
108637
|
return buildNoneReasoningControls();
|
|
107731
108638
|
}
|
|
107732
108639
|
seen.add(key);
|
|
107733
|
-
const
|
|
108640
|
+
const label2 = typeof record5.label === "string" && record5.label.trim() ? record5.label.trim() : void 0;
|
|
107734
108641
|
const nested = normalizeReasoningControls({
|
|
107735
108642
|
...Object.fromEntries(Object.entries(record5).filter(([itemKey]) => !["key", "label"].includes(itemKey))),
|
|
107736
108643
|
schema_version: 1
|
|
@@ -107740,7 +108647,7 @@ var init_reasoning_controls = __esm({
|
|
|
107740
108647
|
}
|
|
107741
108648
|
nestedControls.push({
|
|
107742
108649
|
key,
|
|
107743
|
-
...
|
|
108650
|
+
...label2 ? { label: label2 } : {},
|
|
107744
108651
|
...nested
|
|
107745
108652
|
});
|
|
107746
108653
|
}
|
|
@@ -107905,24 +108812,170 @@ var init_model_controller_provenance = __esm({
|
|
|
107905
108812
|
}
|
|
107906
108813
|
});
|
|
107907
108814
|
|
|
108815
|
+
// lib/runtime/ai-schedule.ts
|
|
108816
|
+
function evaluateAiSchedule(schedule, defaults, nowMs2) {
|
|
108817
|
+
if (!isAiScheduleEnabled(schedule)) {
|
|
108818
|
+
return { shouldRun: true, nextChangeAtMs: null, message: "Schedule Disabled (Running 24/7)" };
|
|
108819
|
+
}
|
|
108820
|
+
try {
|
|
108821
|
+
const timeZone = schedule.timezone ?? defaults?.timezone;
|
|
108822
|
+
if (typeof timeZone !== "string" || !timeZone.trim()) throw new Error("Invalid schedule timezone");
|
|
108823
|
+
const nowWall = wallAt(timeZone, nowMs2);
|
|
108824
|
+
const windows = schedule.windows ?? defaults?.windows;
|
|
108825
|
+
if (!truthy(windows)) return { shouldRun: false, nextChangeAtMs: null, message: "No windows configured" };
|
|
108826
|
+
if (!Array.isArray(windows)) throw new Error("Invalid schedule windows");
|
|
108827
|
+
const nowDay = Math.floor(nowWall / DAY_MS) * DAY_MS;
|
|
108828
|
+
const candidates = [];
|
|
108829
|
+
for (let dayOffset = -6; dayOffset < 8; dayOffset += 1) {
|
|
108830
|
+
const dateMs = nowDay + dayOffset * DAY_MS;
|
|
108831
|
+
const weekday = (new Date(dateMs).getUTCDay() + 6) % 7;
|
|
108832
|
+
for (const window2 of windows) {
|
|
108833
|
+
if (!window2 || typeof window2 !== "object" || Array.isArray(window2)) {
|
|
108834
|
+
throw new Error("Invalid schedule window");
|
|
108835
|
+
}
|
|
108836
|
+
const startDay = dayNumber(window2.start_day);
|
|
108837
|
+
if (startDay === null || startDay !== weekday) continue;
|
|
108838
|
+
const start = parseClock(window2.start_time);
|
|
108839
|
+
const end = parseClock(window2.end_time);
|
|
108840
|
+
const endDay = dayNumber(window2.end_day);
|
|
108841
|
+
if (!start || !end || endDay === null) continue;
|
|
108842
|
+
const startWall = dateMs + (start[0] * 60 + start[1]) * MINUTE_MS;
|
|
108843
|
+
const daysDiff = ((endDay - startDay) % 7 + 7) % 7;
|
|
108844
|
+
const shifted = startWall + Math.round(daysDiff * DAY_MS);
|
|
108845
|
+
const endWall = Math.floor(shifted / DAY_MS) * DAY_MS + (end[0] * 60 + end[1]) * MINUTE_MS + shifted % MINUTE_MS;
|
|
108846
|
+
if (endWall <= startWall) continue;
|
|
108847
|
+
candidates.push([startWall, endWall]);
|
|
108848
|
+
}
|
|
108849
|
+
}
|
|
108850
|
+
candidates.sort((left, right) => left[0] - right[0]);
|
|
108851
|
+
const active = candidates.find(([start, end]) => start <= nowWall && nowWall < end);
|
|
108852
|
+
if (active) {
|
|
108853
|
+
const endsAt = instantOfWall(timeZone, active[1]);
|
|
108854
|
+
return { shouldRun: true, nextChangeAtMs: endsAt, message: `Active until ${label(timeZone, endsAt, active[1])}` };
|
|
108855
|
+
}
|
|
108856
|
+
const next = candidates.find(([start]) => start > nowWall);
|
|
108857
|
+
if (next) {
|
|
108858
|
+
const startsAt = instantOfWall(timeZone, next[0]);
|
|
108859
|
+
return { shouldRun: false, nextChangeAtMs: startsAt, message: `Paused until ${label(timeZone, startsAt, next[0])}` };
|
|
108860
|
+
}
|
|
108861
|
+
return { shouldRun: false, nextChangeAtMs: null, message: "No future schedule found" };
|
|
108862
|
+
} catch {
|
|
108863
|
+
return { shouldRun: true, nextChangeAtMs: null, message: "Schedule Error (Defaulting to Active)" };
|
|
108864
|
+
}
|
|
108865
|
+
}
|
|
108866
|
+
var MINUTE_MS, DAY_MS, truthy, isAiScheduleEnabled, formatters, formatterFor, wallAt, offsetAt, instantOfWall, digitValue, clockPart, dayNumber, parseClock, label;
|
|
108867
|
+
var init_ai_schedule = __esm({
|
|
108868
|
+
"lib/runtime/ai-schedule.ts"() {
|
|
108869
|
+
"use strict";
|
|
108870
|
+
init_define_VTX_EXO_POLICY();
|
|
108871
|
+
init_define_VTX_GROK_POLICY();
|
|
108872
|
+
init_define_VTX_PI_MODEL_POLICY();
|
|
108873
|
+
MINUTE_MS = 6e4;
|
|
108874
|
+
DAY_MS = 864e5;
|
|
108875
|
+
truthy = (value) => {
|
|
108876
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
108877
|
+
if (value && typeof value === "object") return Object.keys(value).length > 0;
|
|
108878
|
+
return Boolean(value);
|
|
108879
|
+
};
|
|
108880
|
+
isAiScheduleEnabled = (schedule) => Boolean(schedule) && typeof schedule === "object" && truthy(schedule.enabled);
|
|
108881
|
+
formatters = /* @__PURE__ */ new Map();
|
|
108882
|
+
formatterFor = (timeZone) => {
|
|
108883
|
+
let formatter = formatters.get(timeZone);
|
|
108884
|
+
if (!formatter) {
|
|
108885
|
+
formatter = new Intl.DateTimeFormat("en-US", {
|
|
108886
|
+
timeZone,
|
|
108887
|
+
hourCycle: "h23",
|
|
108888
|
+
year: "numeric",
|
|
108889
|
+
month: "numeric",
|
|
108890
|
+
day: "numeric",
|
|
108891
|
+
hour: "numeric",
|
|
108892
|
+
minute: "numeric",
|
|
108893
|
+
second: "numeric"
|
|
108894
|
+
});
|
|
108895
|
+
const resolved = formatter.resolvedOptions().timeZone;
|
|
108896
|
+
if (resolved !== timeZone && resolved.toLowerCase() === timeZone.toLowerCase() || timeZone === timeZone.toLowerCase()) {
|
|
108897
|
+
throw new RangeError(`Invalid time zone: ${timeZone}`);
|
|
108898
|
+
}
|
|
108899
|
+
formatters.set(timeZone, formatter);
|
|
108900
|
+
}
|
|
108901
|
+
return formatter;
|
|
108902
|
+
};
|
|
108903
|
+
wallAt = (timeZone, instantMs) => {
|
|
108904
|
+
const parts = {};
|
|
108905
|
+
for (const part of formatterFor(timeZone).formatToParts(new Date(instantMs))) {
|
|
108906
|
+
if (part.type !== "literal") parts[part.type] = Number(part.value);
|
|
108907
|
+
}
|
|
108908
|
+
const wholeSecond = Math.floor(instantMs / 1e3) * 1e3;
|
|
108909
|
+
return Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second) + (instantMs - wholeSecond);
|
|
108910
|
+
};
|
|
108911
|
+
offsetAt = (timeZone, instantMs) => wallAt(timeZone, instantMs) - instantMs;
|
|
108912
|
+
instantOfWall = (timeZone, wallMs) => {
|
|
108913
|
+
const before = offsetAt(timeZone, wallMs - DAY_MS);
|
|
108914
|
+
if (offsetAt(timeZone, wallMs - before) === before) return wallMs - before;
|
|
108915
|
+
const after = offsetAt(timeZone, wallMs + DAY_MS);
|
|
108916
|
+
if (offsetAt(timeZone, wallMs - after) === after) return wallMs - after;
|
|
108917
|
+
return wallMs - before;
|
|
108918
|
+
};
|
|
108919
|
+
digitValue = (char) => {
|
|
108920
|
+
let start = char.codePointAt(0);
|
|
108921
|
+
while (start > 0 && new RegExp("\\p{Nd}", "u").test(String.fromCodePoint(start - 1))) start -= 1;
|
|
108922
|
+
return (char.codePointAt(0) - start) % 10;
|
|
108923
|
+
};
|
|
108924
|
+
clockPart = (text) => {
|
|
108925
|
+
const match = new RegExp("^\\s*([+-]?)(\\p{Nd}+(?:_\\p{Nd}+)*)\\s*$", "u").exec(text);
|
|
108926
|
+
if (!match) return null;
|
|
108927
|
+
const value = [...match[2].replace(/_/g, "")].reduce((total, char) => total * 10 + digitValue(char), 0);
|
|
108928
|
+
return match[1] === "-" ? -value : value;
|
|
108929
|
+
};
|
|
108930
|
+
dayNumber = (value) => {
|
|
108931
|
+
if (typeof value === "boolean") return Number(value);
|
|
108932
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
108933
|
+
};
|
|
108934
|
+
parseClock = (value) => {
|
|
108935
|
+
if (typeof value !== "string") return null;
|
|
108936
|
+
const parts = value.split(":");
|
|
108937
|
+
if (parts.length !== 2) return null;
|
|
108938
|
+
const hour = clockPart(parts[0]);
|
|
108939
|
+
const minute = clockPart(parts[1]);
|
|
108940
|
+
if (hour === null || minute === null || hour < 0 || hour > 23 || minute < 0 || minute > 59) return null;
|
|
108941
|
+
return [hour, minute];
|
|
108942
|
+
};
|
|
108943
|
+
label = (timeZone, instantMs, wallMs) => {
|
|
108944
|
+
const wall = new Date(wallMs);
|
|
108945
|
+
const day = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][wall.getUTCDay()];
|
|
108946
|
+
const clock = `${String(wall.getUTCHours()).padStart(2, "0")}:${String(wall.getUTCMinutes()).padStart(2, "0")}`;
|
|
108947
|
+
const zone = new Intl.DateTimeFormat("en-US", { timeZone, timeZoneName: "short" }).formatToParts(new Date(instantMs)).find((part) => part.type === "timeZoneName")?.value || timeZone;
|
|
108948
|
+
return `${day} ${clock} ${zone}`;
|
|
108949
|
+
};
|
|
108950
|
+
}
|
|
108951
|
+
});
|
|
108952
|
+
|
|
107908
108953
|
// lib/runtime/local-analysis.ts
|
|
107909
108954
|
var local_analysis_exports = {};
|
|
107910
108955
|
__export(local_analysis_exports, {
|
|
107911
108956
|
ClientRuntimeAgentInstructionEmpty: () => ClientRuntimeAgentInstructionEmpty,
|
|
108957
|
+
ClientRuntimeAiSchedulePaused: () => ClientRuntimeAiSchedulePaused,
|
|
108958
|
+
ClientRuntimeAiScheduleStillActive: () => ClientRuntimeAiScheduleStillActive,
|
|
108959
|
+
ServerDispatchAccountStateStale: () => ServerDispatchAccountStateStale,
|
|
108960
|
+
aiOrderSlippageFraction: () => aiOrderSlippageFraction,
|
|
107912
108961
|
buildLocalRuntimePromptArtifacts: () => buildLocalRuntimePromptArtifacts,
|
|
107913
108962
|
buildPromptBehaviorStateArtifacts: () => buildPromptBehaviorStateArtifacts,
|
|
107914
108963
|
buildPromptBehaviorStateValue: () => buildPromptBehaviorStateValue,
|
|
107915
108964
|
derivePromptVisibleSections: () => derivePromptVisibleSections,
|
|
107916
108965
|
isClientRuntimeAgentInstructionEmpty: () => isClientRuntimeAgentInstructionEmpty,
|
|
108966
|
+
isClientRuntimeAiSchedulePaused: () => isClientRuntimeAiSchedulePaused,
|
|
108967
|
+
isClientRuntimeAiScheduleStillActive: () => isClientRuntimeAiScheduleStillActive,
|
|
108968
|
+
isServerDispatchAccountStateStale: () => isServerDispatchAccountStateStale,
|
|
107917
108969
|
resolveEffectivePromptRuntimeProvenance: () => resolveEffectivePromptRuntimeProvenance,
|
|
107918
108970
|
resolveExternalInferenceRuntimeTimeoutSeconds: () => resolveExternalInferenceRuntimeTimeoutSeconds,
|
|
107919
108971
|
resolveLocalRuntimeSecretProvider: () => resolveLocalRuntimeSecretProvider,
|
|
107920
108972
|
resolveLocalRuntimeSecretRequirements: () => resolveLocalRuntimeSecretRequirements,
|
|
107921
108973
|
resolveNativeValuesForModel: () => resolveNativeValuesForModel,
|
|
107922
108974
|
runLocalRuntimeCycle: () => runLocalRuntimeCycle,
|
|
108975
|
+
serverPerpDexScope: () => serverPerpDexScope,
|
|
107923
108976
|
summarizeReviewFailureExplanation: () => summarizeReviewFailureExplanation
|
|
107924
108977
|
});
|
|
107925
|
-
var normalizeNativeValues, assertPromptModelController, resolveRuntimeReasoningControlsForModel, modelScopedKey, resolveNativeValuesForModel, observeRuntimeCycle, observeAccountState, ClientRuntimeAgentInstructionEmpty, isClientRuntimeAgentInstructionEmpty, buildClaimedAgentRuntimeCycleResult, resolveRuntimeMarginModePreference, resolveRuntimeLeveragePreference, resolveBooleanSetting2, CLIENT_RUNTIME_LIVE_CONTEXT_UNAVAILABLE_ERRORS, BEHAVIOR_STATE_UNAVAILABLE_ERROR, CriticalBehaviorStateError, clampNumber, resolveExternalInferenceRuntimeTimeoutSeconds, toPositiveFinite3, compactSnippet, hashRuntimeDebugText, EFFECTIVE_INPUT_MANIFEST_SCHEMA_VERSION, PROMPT_ASSEMBLY_DEFINITION_VERSION, RUNTIME_SOURCE_DEFINITION_VERSION, DECISION_INPUT_DEFINITION_VERSION, CONTEXT_ENVELOPE_DEFINITION_VERSION, CLIENT_RUNTIME_SOURCE_VERSION, CLIENT_MAIN_PROMPT_RENDERER, SERVER_MAIN_PROMPT_RENDERER, CLIENT_REVIEW_PROMPT_RENDERER, SERVER_REVIEW_PROMPT_RENDERER, resolveEffectivePromptRuntimeProvenance, canonicalManifestValue, canonicalManifestJson, sha256ManifestHex, effectiveInputComponent, buildEffectiveInputManifest, derivePromptVisibleSections, decodeDecisionTracePayload, extractDecisionSymbolTrace, formatDecisionSymbolTrace, formatActionableDecisionSymbols, normalizePromptSymbols, JSON_MODEL_OUTPUT_FENCE_PATTERN, STRICT_MODEL_OUTPUT_KEYS, currentModelOutputValidationErrors, currentModelOutputMatchesContract, projectCurrentModelDecisionContent, modelOutputValidationError, buildMissingDecisionHold, buildDecisionPlansFromResponse, buildReviewCandidatePlansFromResponse, forceUnavailableSymbolsToHold, extractTemplatePlaceholders, requireReviewPrimaryUserPromptTemplate, containsCompetingBehaviorStateMarkup, containsCompetingMainBehaviorStateMarkup, requireStrategyReviewTemplates, preflightStrategyReviewPromptContract, extractRuntimeReasoningSelection, isAbortError, isRuntimeTimeoutAbortReason, REVIEW_FAILURE_SENSITIVE_DB_TOKENS, REVIEW_FAILURE_SCHEMA_DISCLOSURE_TOKENS, REVIEW_FAILURE_SQL_STATEMENT_PATTERN, REVIEW_FAILURE_TRACEBACK_PATTERN, isSensitiveReviewFailureDetail, summarizeReviewFailureExplanation, buildReviewFailureHoldReason, createAbortError2, settleRuntimeCyclePromise, unwrapRuntimeCycleSettledResult, normalizeDecisionLabel, normalizeRuntimeSymbol, PromptContractFetchError, isLivePromptContextUnavailableError, buildFailClosedHoldResult, buildPromptConstructionFailureResult, buildLivePromptContextUnavailableFailureResult, pickFirstString, normalizeRuntimeStringList, requirePositiveRuntimeLimit, resolveRuntimeTradingScope, normalizeRuntimeProviderAlias, resolveCatalogModelEntry, createClientRuntimeProviderSetupError, createProviderSetupRejectionError, evaluateModelEligibility, extractReviewRuntimeReasoningSelection, isUsableRuntimeSettingsFallback, resolveRuntimeSettings, formatRuntimeDurationMs, normalizeRuntimeTimingNote, appendRuntimeTimingEvent, reportPromptParityTelemetry, resolveLocalRuntimeSecretRequirements, resolveLocalRuntimeSecretProvider, toEpochSeconds, REQUIRED_AI_INDICATOR_KEYS, TIMEFRAME_ORDER, sortTradingTimeframes, normalizePromptIdentityTimestamp, resolveCompletedCandleBoundary, normalizeAiIndicatorFlags, getPromptLookback, computeSma, computeEma, computeRsi, computeAtr, computeMacd, computeBollingerBands, getIndicatorValue, buildPromptCandlesComponent, buildPromptCandlesPayload, formatUtcTimestampWithWeekday, formatUtcNowWithWeekday, formatPromptPrice, 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, runLocalRuntimeCycle;
|
|
108978
|
+
var normalizeNativeValues, assertPromptModelController, resolveRuntimeReasoningControlsForModel, modelScopedKey, resolveNativeValuesForModel, observeRuntimeCycle, observeAccountState, aiOrderSlippageFraction, serverPerpDexScope, serverBehaviorStateArtifacts, ClientRuntimeAgentInstructionEmpty, isClientRuntimeAgentInstructionEmpty, ClientRuntimeAiSchedulePaused, ClientRuntimeAiScheduleStillActive, isClientRuntimeAiScheduleStillActive, ServerDispatchAccountStateStale, isServerDispatchAccountStateStale, isClientRuntimeAiSchedulePaused, buildClaimedAgentRuntimeCycleResult, resolveRuntimeMarginModePreference, resolveRuntimeLeveragePreference, resolveBooleanSetting2, CLIENT_RUNTIME_LIVE_CONTEXT_UNAVAILABLE_ERRORS, BEHAVIOR_STATE_UNAVAILABLE_ERROR, CriticalBehaviorStateError, clampNumber, resolveExternalInferenceRuntimeTimeoutSeconds, toPositiveFinite3, compactSnippet, hashRuntimeDebugText, EFFECTIVE_INPUT_MANIFEST_SCHEMA_VERSION, PROMPT_ASSEMBLY_DEFINITION_VERSION, RUNTIME_SOURCE_DEFINITION_VERSION, DECISION_INPUT_DEFINITION_VERSION, CONTEXT_ENVELOPE_DEFINITION_VERSION, CLIENT_RUNTIME_SOURCE_VERSION, CLIENT_MAIN_PROMPT_RENDERER, SERVER_MAIN_PROMPT_RENDERER, CLIENT_REVIEW_PROMPT_RENDERER, SERVER_REVIEW_PROMPT_RENDERER, resolveEffectivePromptRuntimeProvenance, canonicalManifestValue, canonicalManifestJson, sha256ManifestHex, effectiveInputComponent, buildEffectiveInputManifest, derivePromptVisibleSections, decodeDecisionTracePayload, extractDecisionSymbolTrace, formatDecisionSymbolTrace, formatActionableDecisionSymbols, normalizePromptSymbols, JSON_MODEL_OUTPUT_FENCE_PATTERN, STRICT_MODEL_OUTPUT_KEYS, currentModelOutputValidationErrors, currentModelOutputMatchesContract, projectCurrentModelDecisionContent, modelOutputValidationError, buildMissingDecisionHold, buildDecisionPlansFromResponse, buildReviewCandidatePlansFromResponse, forceUnavailableSymbolsToHold, extractTemplatePlaceholders, requireReviewPrimaryUserPromptTemplate, containsCompetingBehaviorStateMarkup, containsCompetingMainBehaviorStateMarkup, requireStrategyReviewTemplates, preflightStrategyReviewPromptContract, extractRuntimeReasoningSelection, isAbortError, isRuntimeTimeoutAbortReason, REVIEW_FAILURE_SENSITIVE_DB_TOKENS, REVIEW_FAILURE_SCHEMA_DISCLOSURE_TOKENS, REVIEW_FAILURE_SQL_STATEMENT_PATTERN, REVIEW_FAILURE_TRACEBACK_PATTERN, isSensitiveReviewFailureDetail, summarizeReviewFailureExplanation, buildReviewFailureHoldReason, createAbortError2, settleRuntimeCyclePromise, unwrapRuntimeCycleSettledResult, normalizeDecisionLabel, normalizeRuntimeSymbol, PromptContractFetchError, isLivePromptContextUnavailableError, buildFailClosedHoldResult, buildPromptConstructionFailureResult, buildLivePromptContextUnavailableFailureResult, pickFirstString, normalizeRuntimeStringList, requirePositiveRuntimeLimit, resolveRuntimeTradingScope, normalizeRuntimeProviderAlias, resolveCatalogModelEntry, createClientRuntimeProviderSetupError, createProviderSetupRejectionError, evaluateModelEligibility, extractReviewRuntimeReasoningSelection, isUsableRuntimeSettingsFallback, resolveRuntimeSettings, formatRuntimeDurationMs, normalizeRuntimeTimingNote, appendRuntimeTimingEvent, reportPromptParityTelemetry, resolveLocalRuntimeSecretRequirements, resolveLocalRuntimeSecretProvider, toEpochSeconds, REQUIRED_AI_INDICATOR_KEYS, TIMEFRAME_ORDER, sortTradingTimeframes, normalizePromptIdentityTimestamp, resolveCompletedCandleBoundary, normalizeAiIndicatorFlags, getPromptLookback, computeSma, computeEma, computeRsi, computeAtr, computeMacd, computeBollingerBands, getIndicatorValue, buildPromptCandlesComponent, buildPromptCandlesPayload, formatUtcTimestampWithWeekday, formatUtcNowWithWeekday, formatPromptPrice, 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, runLocalRuntimeCycle;
|
|
107926
108979
|
var init_local_analysis = __esm({
|
|
107927
108980
|
"lib/runtime/local-analysis.ts"() {
|
|
107928
108981
|
"use strict";
|
|
@@ -107962,6 +109015,7 @@ var init_local_analysis = __esm({
|
|
|
107962
109015
|
init_hyperliquid_market_symbol();
|
|
107963
109016
|
init_external_inference_contract();
|
|
107964
109017
|
init_model_controller_provenance();
|
|
109018
|
+
init_ai_schedule();
|
|
107965
109019
|
normalizeNativeValues = (value) => {
|
|
107966
109020
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
107967
109021
|
const entries = {};
|
|
@@ -108030,6 +109084,29 @@ var init_local_analysis = __esm({
|
|
|
108030
109084
|
}
|
|
108031
109085
|
});
|
|
108032
109086
|
};
|
|
109087
|
+
aiOrderSlippageFraction = (config2, executionMode) => executionMode === "server" ? Number(config2.server_ai_max_slippage) / 100 : clampNumber(void 0, config2.default_max_slippage) / 100;
|
|
109088
|
+
serverPerpDexScope = (symbols, executionMode) => {
|
|
109089
|
+
if (executionMode !== "server") return void 0;
|
|
109090
|
+
const dexes = /* @__PURE__ */ new Set();
|
|
109091
|
+
for (const raw of symbols) {
|
|
109092
|
+
if (!String(raw ?? "").trim()) continue;
|
|
109093
|
+
if (!normalizeHyperliquidMarketSymbol(raw)) return void 0;
|
|
109094
|
+
dexes.add(getHyperliquidMarketDex(raw));
|
|
109095
|
+
}
|
|
109096
|
+
return dexes.size > 0 ? [...dexes].filter(Boolean) : void 0;
|
|
109097
|
+
};
|
|
109098
|
+
serverBehaviorStateArtifacts = (derived) => {
|
|
109099
|
+
const rendered = derived.behavior_state;
|
|
109100
|
+
if (derived.behavior_state_owner !== "server" || typeof rendered !== "string" || !rendered.trim()) {
|
|
109101
|
+
throw new Error("The server did not build this Server bot's behavior state.");
|
|
109102
|
+
}
|
|
109103
|
+
const preMemory = derived.behavior_state_pre_memory;
|
|
109104
|
+
return {
|
|
109105
|
+
rendered,
|
|
109106
|
+
preMemoryRendered: typeof preMemory === "string" && preMemory.trim() ? preMemory : rendered,
|
|
109107
|
+
policyState: asRecord(derived.behavior_policy_state)
|
|
109108
|
+
};
|
|
109109
|
+
};
|
|
108033
109110
|
ClientRuntimeAgentInstructionEmpty = class extends Error {
|
|
108034
109111
|
constructor(retryAfterMs) {
|
|
108035
109112
|
super("No Agent instruction is currently queued for this Client runtime.");
|
|
@@ -108038,6 +109115,31 @@ var init_local_analysis = __esm({
|
|
|
108038
109115
|
}
|
|
108039
109116
|
};
|
|
108040
109117
|
isClientRuntimeAgentInstructionEmpty = (value) => value instanceof ClientRuntimeAgentInstructionEmpty;
|
|
109118
|
+
ClientRuntimeAiSchedulePaused = class extends Error {
|
|
109119
|
+
constructor(input) {
|
|
109120
|
+
super(input.message);
|
|
109121
|
+
this.name = "ClientRuntimeAiSchedulePaused";
|
|
109122
|
+
this.nextChangeAtMs = input.nextChangeAtMs;
|
|
109123
|
+
this.closeOnStop = input.closeOnStop;
|
|
109124
|
+
this.settings = input.settings;
|
|
109125
|
+
this.config = input.config;
|
|
109126
|
+
}
|
|
109127
|
+
};
|
|
109128
|
+
ClientRuntimeAiScheduleStillActive = class extends Error {
|
|
109129
|
+
constructor() {
|
|
109130
|
+
super("The AI schedule still lets this bot run.");
|
|
109131
|
+
this.name = "ClientRuntimeAiScheduleStillActive";
|
|
109132
|
+
}
|
|
109133
|
+
};
|
|
109134
|
+
isClientRuntimeAiScheduleStillActive = (value) => value instanceof ClientRuntimeAiScheduleStillActive;
|
|
109135
|
+
ServerDispatchAccountStateStale = class extends Error {
|
|
109136
|
+
constructor() {
|
|
109137
|
+
super("Server account context could not be rebuilt inside the dispatch freshness window");
|
|
109138
|
+
this.name = "ServerDispatchAccountStateStale";
|
|
109139
|
+
}
|
|
109140
|
+
};
|
|
109141
|
+
isServerDispatchAccountStateStale = (value) => value instanceof Error && value.name === "ServerDispatchAccountStateStale";
|
|
109142
|
+
isClientRuntimeAiSchedulePaused = (value) => value instanceof ClientRuntimeAiSchedulePaused;
|
|
108041
109143
|
buildClaimedAgentRuntimeCycleResult = async (input) => {
|
|
108042
109144
|
const { config: config2, settings, instruction, runtimeInput, signal } = input;
|
|
108043
109145
|
const binding = runtimeInput.runtimeContractBinding;
|
|
@@ -108074,6 +109176,7 @@ var init_local_analysis = __esm({
|
|
|
108074
109176
|
tickerPrice: 0,
|
|
108075
109177
|
leverage,
|
|
108076
109178
|
aggregatePerpDexs: true,
|
|
109179
|
+
perpDexScope: serverPerpDexScope(symbols, runtimeInput.executionMode),
|
|
108077
109180
|
feeSymbols: symbols,
|
|
108078
109181
|
includeEffectiveTakerRate: true,
|
|
108079
109182
|
sessionId: String(runtimeInput.sessionId || "").trim(),
|
|
@@ -108168,11 +109271,11 @@ var init_local_analysis = __esm({
|
|
|
108168
109271
|
walletAddress,
|
|
108169
109272
|
lastPrice: price,
|
|
108170
109273
|
unitSizeUsdc: tradeSize,
|
|
108171
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
108172
109274
|
leverage,
|
|
108173
109275
|
marginMode,
|
|
108174
109276
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
108175
|
-
|
|
109277
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
109278
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, runtimeInput.executionMode),
|
|
108176
109279
|
...buildRuntimeSlTpExecutionSettings(settings, config2)
|
|
108177
109280
|
};
|
|
108178
109281
|
};
|
|
@@ -109522,14 +110625,14 @@ ${reviewOutputContract}`;
|
|
|
109522
110625
|
const normalized = String(value || "").replace(/\s+/g, " ").trim();
|
|
109523
110626
|
return normalized.length > 0 ? normalized : null;
|
|
109524
110627
|
};
|
|
109525
|
-
appendRuntimeTimingEvent = (
|
|
110628
|
+
appendRuntimeTimingEvent = (label2, startedAtMs, note, outcome) => {
|
|
109526
110629
|
const parts = [`duration=${formatRuntimeDurationMs(Date.now() - startedAtMs)}`];
|
|
109527
110630
|
const normalizedNote = normalizeRuntimeTimingNote(note);
|
|
109528
110631
|
if (normalizedNote) {
|
|
109529
110632
|
parts.push(normalizedNote);
|
|
109530
110633
|
}
|
|
109531
110634
|
appendRuntimeDebugEvent({
|
|
109532
|
-
label,
|
|
110635
|
+
label: label2,
|
|
109533
110636
|
note: parts.join(" "),
|
|
109534
110637
|
outcome
|
|
109535
110638
|
});
|
|
@@ -111008,17 +112111,17 @@ ${behaviorJson}
|
|
|
111008
112111
|
}
|
|
111009
112112
|
return hasValue(secrets.providerKeys[provider]) || hasSlotValue(secrets.providerKeySlots?.[provider]);
|
|
111010
112113
|
};
|
|
111011
|
-
requireNonEmptyStringField = (value,
|
|
112114
|
+
requireNonEmptyStringField = (value, label2) => {
|
|
111012
112115
|
const normalized = String(value ?? "").trim();
|
|
111013
112116
|
if (!normalized) {
|
|
111014
|
-
throw new Error(`Missing required prompt contract field: ${
|
|
112117
|
+
throw new Error(`Missing required prompt contract field: ${label2}`);
|
|
111015
112118
|
}
|
|
111016
112119
|
return normalized;
|
|
111017
112120
|
};
|
|
111018
|
-
requirePositiveIntegerField = (value,
|
|
112121
|
+
requirePositiveIntegerField = (value, label2) => {
|
|
111019
112122
|
const parsed = Number(value);
|
|
111020
112123
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
111021
|
-
throw new Error(`Missing required positive prompt contract field: ${
|
|
112124
|
+
throw new Error(`Missing required positive prompt contract field: ${label2}`);
|
|
111022
112125
|
}
|
|
111023
112126
|
return Math.trunc(parsed);
|
|
111024
112127
|
};
|
|
@@ -111768,6 +112871,25 @@ ${behaviorJson}
|
|
|
111768
112871
|
}
|
|
111769
112872
|
const config2 = configResult.value;
|
|
111770
112873
|
const runtimeSettings = runtimeSettingsResult.value;
|
|
112874
|
+
const aiSchedule = runtimeSettings.settings.ai_schedule ?? config2.default_ai_schedule;
|
|
112875
|
+
if (!input.ignoreAiSchedule) {
|
|
112876
|
+
if (isAiScheduleEnabled(aiSchedule)) {
|
|
112877
|
+
const scheduleState = evaluateAiSchedule(aiSchedule, config2.default_ai_schedule, Date.now());
|
|
112878
|
+
if (!scheduleState.shouldRun) {
|
|
112879
|
+
throw new ClientRuntimeAiSchedulePaused({
|
|
112880
|
+
message: scheduleState.message,
|
|
112881
|
+
nextChangeAtMs: scheduleState.nextChangeAtMs,
|
|
112882
|
+
closeOnStop: isAiScheduleEnabled({ enabled: aiSchedule?.close_on_stop }),
|
|
112883
|
+
settings: runtimeSettings.settings,
|
|
112884
|
+
config: config2
|
|
112885
|
+
});
|
|
112886
|
+
}
|
|
112887
|
+
input.onAiScheduleWindowActive?.(scheduleState.nextChangeAtMs);
|
|
112888
|
+
} else {
|
|
112889
|
+
input.onAiScheduleOff?.();
|
|
112890
|
+
}
|
|
112891
|
+
if (input.aiScheduleCheckOnly) throw new ClientRuntimeAiScheduleStillActive();
|
|
112892
|
+
}
|
|
111771
112893
|
input = {
|
|
111772
112894
|
...input,
|
|
111773
112895
|
secrets: await ClientVault.refreshProviderSecretsForVersion(
|
|
@@ -111945,11 +113067,11 @@ ${behaviorJson}
|
|
|
111945
113067
|
walletAddress: String(settings.hyperliquid_wallet_address || "").trim() || void 0,
|
|
111946
113068
|
lastPrice: 0,
|
|
111947
113069
|
unitSizeUsdc: clampNumber(promptKnobs2.trade_size, config2.default_ai_trade_amount),
|
|
111948
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
111949
113070
|
leverage: clampNumber(promptKnobs2.leverage, config2.default_leverage),
|
|
111950
113071
|
marginMode: resolveRuntimeMarginModePreference(settings, config2),
|
|
111951
113072
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
111952
|
-
|
|
113073
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113074
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
111953
113075
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
111954
113076
|
executionFreshnessMaxAgeSeconds: requirePositiveIntegerField(
|
|
111955
113077
|
promptKnobs2.execution_decision_max_age_seconds,
|
|
@@ -111970,6 +113092,8 @@ ${behaviorJson}
|
|
|
111970
113092
|
let _latestPerpDexAccounts = null;
|
|
111971
113093
|
let latestPositions = [];
|
|
111972
113094
|
let _accountStateResolvedAtMs = null;
|
|
113095
|
+
let _accountStateFetchedAtMs = null;
|
|
113096
|
+
let _accountStateSource = null;
|
|
111973
113097
|
const getLatestAccountEquity = () => _latestAccountEquity;
|
|
111974
113098
|
const getLatestTotalUnrealizedPnl = () => _latestTotalUnrealizedPnl;
|
|
111975
113099
|
const getAccountStateResolvedAtMs = () => _accountStateResolvedAtMs;
|
|
@@ -111983,8 +113107,12 @@ ${behaviorJson}
|
|
|
111983
113107
|
tickerPrice: 0,
|
|
111984
113108
|
leverage: resolveRuntimeLeveragePreference(settings, config2),
|
|
111985
113109
|
aggregatePerpDexs: true,
|
|
113110
|
+
perpDexScope: serverPerpDexScope(symbols, input.executionMode),
|
|
111986
113111
|
feeSymbols: symbols,
|
|
111987
113112
|
includeEffectiveTakerRate: true,
|
|
113113
|
+
// A Server bot's cycle reads the account authoritatively, as the Python
|
|
113114
|
+
// Server loop does: never a cached or rate-limit-stale observation.
|
|
113115
|
+
forceRefresh: input.executionMode === "server",
|
|
111988
113116
|
sessionId,
|
|
111989
113117
|
signal: timeoutController.signal
|
|
111990
113118
|
}).then((state2) => {
|
|
@@ -111992,6 +113120,8 @@ ${behaviorJson}
|
|
|
111992
113120
|
latestPositions = state2.positions;
|
|
111993
113121
|
const resolvedEquity = Number(state2.accountSummary?.account_value) || 0;
|
|
111994
113122
|
_accountStateResolvedAtMs = Date.now();
|
|
113123
|
+
_accountStateFetchedAtMs = state2.evidence?.fetchedAtMs ?? _accountStateResolvedAtMs;
|
|
113124
|
+
_accountStateSource = state2.evidence?.source ?? null;
|
|
111995
113125
|
if (resolvedEquity > 0) {
|
|
111996
113126
|
_latestAccountEquity = resolvedEquity;
|
|
111997
113127
|
_latestPerpDexAccounts = state2.accountSummary?.perp_dex_accounts ?? null;
|
|
@@ -112018,7 +113148,8 @@ ${behaviorJson}
|
|
|
112018
113148
|
});
|
|
112019
113149
|
const browserAccountStatePromise = settleRuntimeCyclePromise(browserAccountStateTask);
|
|
112020
113150
|
const browserUserFillsStartedAtMs = Date.now();
|
|
112021
|
-
const
|
|
113151
|
+
const serverOwnsBehaviorState = input.executionMode === "server";
|
|
113152
|
+
const browserUserFillsTask = serverOwnsBehaviorState ? Promise.resolve(null) : fetchBrowserUserFills({
|
|
112022
113153
|
publicRequestPriority: "trading_analysis",
|
|
112023
113154
|
config: config2,
|
|
112024
113155
|
walletAddress,
|
|
@@ -112053,7 +113184,7 @@ ${behaviorJson}
|
|
|
112053
113184
|
getLatestAccountEquity,
|
|
112054
113185
|
getLatestTotalUnrealizedPnl,
|
|
112055
113186
|
getAccountStateResolvedAtMs,
|
|
112056
|
-
async () => {
|
|
113187
|
+
serverOwnsBehaviorState ? void 0 : async () => {
|
|
112057
113188
|
const result = unwrapRuntimeCycleSettledResult(await browserUserFillsPromise);
|
|
112058
113189
|
return { fills: result.rawFills, evidence: result.evidence };
|
|
112059
113190
|
},
|
|
@@ -112081,12 +113212,14 @@ ${behaviorJson}
|
|
|
112081
113212
|
sortedTimeframes.map(async (marketTimeframe) => [
|
|
112082
113213
|
marketTimeframe,
|
|
112083
113214
|
await getRecentCandles(
|
|
113215
|
+
// Indicators warm up on the same history as the Server loop's
|
|
113216
|
+
// (indicator_history.py); the prompt shows its lookback of it.
|
|
112084
113217
|
Math.max(getPromptLookback(
|
|
112085
113218
|
lookbackSettings,
|
|
112086
113219
|
marketTimeframe,
|
|
112087
113220
|
effectiveDefaultLookbacks,
|
|
112088
113221
|
config2.max_analysis_lookback
|
|
112089
|
-
), 250),
|
|
113222
|
+
), Number(config2.indicator_candle_count) || 250),
|
|
112090
113223
|
"hyperliquid",
|
|
112091
113224
|
marketSymbol,
|
|
112092
113225
|
marketTimeframe,
|
|
@@ -112183,11 +113316,11 @@ ${behaviorJson}
|
|
|
112183
113316
|
walletAddress: String(settings.hyperliquid_wallet_address || "").trim() || void 0,
|
|
112184
113317
|
lastPrice: toPositiveFinite3(ticker.price) ?? 0,
|
|
112185
113318
|
unitSizeUsdc: clampNumber(rejectedPromptKnobs.trade_size, config2.default_ai_trade_amount),
|
|
112186
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
112187
113319
|
leverage: clampNumber(rejectedPromptKnobs.leverage, config2.default_leverage),
|
|
112188
113320
|
marginMode: resolveRuntimeMarginModePreference(settings, config2),
|
|
112189
113321
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
112190
|
-
|
|
113322
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113323
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
112191
113324
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
112192
113325
|
executionFreshnessMaxAgeSeconds: requirePositiveIntegerField(
|
|
112193
113326
|
rejectedPromptKnobs.execution_decision_max_age_seconds,
|
|
@@ -112212,8 +113345,8 @@ ${behaviorJson}
|
|
|
112212
113345
|
positions
|
|
112213
113346
|
) ?? browserAccountState.accountSummary.total_unrealized_pnl
|
|
112214
113347
|
};
|
|
112215
|
-
tradeHistory = browserUserFills
|
|
112216
|
-
if (input.mode === "trader" && browserUserFills
|
|
113348
|
+
tradeHistory = browserUserFills?.tradeHistory ?? [];
|
|
113349
|
+
if (input.mode === "trader" && !serverOwnsBehaviorState && browserUserFills?.evidence?.source !== "live") {
|
|
112217
113350
|
throw new CriticalBehaviorStateError();
|
|
112218
113351
|
}
|
|
112219
113352
|
const metadataSymbol = requireNonEmptyStringField(promptMetadata.symbol, "symbol");
|
|
@@ -112508,11 +113641,11 @@ ${behaviorJson}
|
|
|
112508
113641
|
if (input.mode === "trader" && !behaviorMemoryEnabled) {
|
|
112509
113642
|
throw new CriticalBehaviorStateError();
|
|
112510
113643
|
}
|
|
112511
|
-
const browserFillEvidence = browserUserFills
|
|
113644
|
+
const browserFillEvidence = browserUserFills?.evidence;
|
|
112512
113645
|
const behaviorFillCoverage = browserFillEvidence?.source === "live" && browserFillEvidence.exactTerminalFillEvidenceComplete === true ? "complete" : "capped";
|
|
112513
113646
|
let behaviorStateArtifacts;
|
|
112514
113647
|
try {
|
|
112515
|
-
behaviorStateArtifacts = buildPromptBehaviorStateArtifacts({
|
|
113648
|
+
behaviorStateArtifacts = serverOwnsBehaviorState ? serverBehaviorStateArtifacts(derivedContext) : buildPromptBehaviorStateArtifacts({
|
|
112516
113649
|
fills: tradeHistory,
|
|
112517
113650
|
positions,
|
|
112518
113651
|
symbols: promptSymbols,
|
|
@@ -112600,11 +113733,11 @@ ${stringifyPromptJson(candlesPayload)}
|
|
|
112600
113733
|
walletAddress: walletAddress || void 0,
|
|
112601
113734
|
lastPrice: 0,
|
|
112602
113735
|
unitSizeUsdc: metadataTradeSize,
|
|
112603
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
112604
113736
|
leverage: metadataLeverage,
|
|
112605
113737
|
marginMode: resolveRuntimeMarginModePreference(settings, config2),
|
|
112606
113738
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
112607
|
-
|
|
113739
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113740
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
112608
113741
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
112609
113742
|
executionFreshnessMaxAgeSeconds
|
|
112610
113743
|
}
|
|
@@ -112726,11 +113859,11 @@ ${stringifyPromptJson(candlesPayload)}
|
|
|
112726
113859
|
walletAddress: String(settings.hyperliquid_wallet_address || "").trim() || void 0,
|
|
112727
113860
|
lastPrice: executionPrice,
|
|
112728
113861
|
unitSizeUsdc: metadataTradeSize,
|
|
112729
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
112730
113862
|
leverage: metadataLeverage,
|
|
112731
113863
|
marginMode: resolveRuntimeMarginModePreference(settings, config2),
|
|
112732
113864
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
112733
|
-
|
|
113865
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113866
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
112734
113867
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
112735
113868
|
executionFreshnessMaxAgeSeconds
|
|
112736
113869
|
}
|
|
@@ -112756,11 +113889,11 @@ ${stringifyPromptJson(candlesPayload)}
|
|
|
112756
113889
|
walletAddress: String(settings.hyperliquid_wallet_address || "").trim() || void 0,
|
|
112757
113890
|
lastPrice: planPrice,
|
|
112758
113891
|
unitSizeUsdc: metadataTradeSize,
|
|
112759
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
112760
113892
|
leverage: metadataLeverage,
|
|
112761
113893
|
marginMode,
|
|
112762
113894
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
112763
|
-
|
|
113895
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113896
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
112764
113897
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
112765
113898
|
executionFreshnessMaxAgeSeconds
|
|
112766
113899
|
};
|
|
@@ -112913,6 +114046,17 @@ ${stringifyPromptJson(candlesPayload)}
|
|
|
112913
114046
|
note: `lane=main seconds=${requestTimeoutSeconds}`
|
|
112914
114047
|
});
|
|
112915
114048
|
}
|
|
114049
|
+
const dispatchAccountStateAgeMs = _accountStateFetchedAtMs === null ? null : Date.now() - _accountStateFetchedAtMs;
|
|
114050
|
+
appendRuntimeDebugEvent({
|
|
114051
|
+
label: "account_state_dispatch_age",
|
|
114052
|
+
note: `account_state_age_ms=${dispatchAccountStateAgeMs ?? "unresolved"} source=${_accountStateSource ?? "unknown"}`
|
|
114053
|
+
});
|
|
114054
|
+
if (input.executionMode === "server" && !allPromptSymbolsUnavailable && (dispatchAccountStateAgeMs === null || dispatchAccountStateAgeMs > requirePositiveIntegerField(
|
|
114055
|
+
config2.server_dispatch_account_state_max_age_milliseconds,
|
|
114056
|
+
"server_dispatch_account_state_max_age_milliseconds"
|
|
114057
|
+
))) {
|
|
114058
|
+
throw new ServerDispatchAccountStateStale();
|
|
114059
|
+
}
|
|
112916
114060
|
const providerStartedAtMs = Date.now();
|
|
112917
114061
|
observeRuntimeCycle(input, { stage: "model", reason_code: null });
|
|
112918
114062
|
let selectedPrimaryModel = authoritativeModel;
|
|
@@ -113823,7 +114967,7 @@ ${reviewOutputContract}`;
|
|
|
113823
114967
|
executionPlans: acceptedExecutionPlans
|
|
113824
114968
|
});
|
|
113825
114969
|
} catch (error48) {
|
|
113826
|
-
if (isClientRuntimeAgentInstructionEmpty(error48)) {
|
|
114970
|
+
if (isClientRuntimeAgentInstructionEmpty(error48) || isClientRuntimeAiSchedulePaused(error48) || isClientRuntimeAiScheduleStillActive(error48)) {
|
|
113827
114971
|
throw error48;
|
|
113828
114972
|
}
|
|
113829
114973
|
if (error48 instanceof PromptContractFetchError && error48.metadata) {
|
|
@@ -113854,8 +114998,8 @@ ${reviewOutputContract}`;
|
|
|
113854
114998
|
const detail = error48 instanceof Error ? error48.message : String(error48);
|
|
113855
114999
|
appendRuntimeTimingEvent("analysis_cycle_failed", cycleStartedAtMs, detail, "error");
|
|
113856
115000
|
if (isAbortError(error48)) {
|
|
113857
|
-
const
|
|
113858
|
-
if (isRuntimeTimeoutAbortReason(
|
|
115001
|
+
const abortReason2 = timeoutController.signal.reason;
|
|
115002
|
+
if (isRuntimeTimeoutAbortReason(abortReason2)) {
|
|
113859
115003
|
const timeoutError = Object.assign(
|
|
113860
115004
|
new Error("Client runtime analysis timed out before the provider returned a result.", { cause: error48 }),
|
|
113861
115005
|
error48,
|
|
@@ -113863,8 +115007,8 @@ ${reviewOutputContract}`;
|
|
|
113863
115007
|
);
|
|
113864
115008
|
throw cycleErrorProvenance ? attachClientRuntimeErrorProvenance(timeoutError, cycleErrorProvenance) : timeoutError;
|
|
113865
115009
|
}
|
|
113866
|
-
if (
|
|
113867
|
-
throw cycleErrorProvenance ? attachClientRuntimeErrorProvenance(
|
|
115010
|
+
if (abortReason2 instanceof Error) {
|
|
115011
|
+
throw cycleErrorProvenance ? attachClientRuntimeErrorProvenance(abortReason2, cycleErrorProvenance) : abortReason2;
|
|
113868
115012
|
}
|
|
113869
115013
|
throw cycleErrorProvenance ? attachClientRuntimeErrorProvenance(error48, cycleErrorProvenance) : error48;
|
|
113870
115014
|
}
|
|
@@ -113880,7 +115024,7 @@ ${reviewOutputContract}`;
|
|
|
113880
115024
|
});
|
|
113881
115025
|
|
|
113882
115026
|
// lib/runtime/engine.ts
|
|
113883
|
-
var localAnalysis, getExchangeFailureDiagnostics, getRuntimeFallbackAttempts, isProviderFailureDiagnosticsCandidate, getEventBoundProviderLabel, getEventBoundProviderTraceId, getRecentProviderFailureDiagnostics, getClientRuntimeErrorProvenance, getRuntimeProviderSetupDiagnostics, buildProviderSetupErrorDiagnosticFields, buildClientRuntimeErrorProvenanceDiagnosticFields, buildRuntimeRequestErrorDiagnosticFields, hasEventBoundProviderFailureEvidence, classifyRuntimeErrorStage, buildHyperliquidPublicReadDiagnosticFields, buildRuntimeErrorDiagnostics, positiveNumber, resolveRuntimeEngineOptions, CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX, getClientKillswitchBlockStorageKey, persistClientRuntimeKillswitchBlock, clearClientRuntimeKillswitchBlock, hashRuntimeDebugText2, createRuntimeUuid2, getRuntimeContractIdentityToken, getRuntimeStatusContractIdentityToken, getRuntimeContractBindingTokenFromCycleResult, getRuntimeContractBindingTupleToken, getRuntimeStatusContractBindingTupleToken, isTransientRuntimeConflictError, createRuntimeStartCancelledError, isRuntimeContractMismatchError, isClientExecutionModeMismatchError, isClientRuntimeSessionStoppedError, isClientRuntimeLeaseAuthError, isClientRuntimeReleasedError, deriveFailedStartCleanupOwnershipLossReason, isRuntimeAbortError, isExplicitClientExecutionMode, createStopAbortError, isRuntimeContractIdentityAdvancedAbort, CLIENT_RUNTIME_NO_DECISION_RECOVERY_REASON, sanitizeSettingsSnapshotForFallback, preflightClientRuntime, ClientExecutionEngine, createStoppedRuntimeSnapshot, ClientRuntimeRegistry, botEngine;
|
|
115027
|
+
var localAnalysis, getExchangeFailureDiagnostics, getRuntimeFallbackAttempts, isProviderFailureDiagnosticsCandidate, getEventBoundProviderLabel, getEventBoundProviderTraceId, getRecentProviderFailureDiagnostics, getClientRuntimeErrorProvenance, getRuntimeProviderSetupDiagnostics, buildProviderSetupErrorDiagnosticFields, buildClientRuntimeErrorProvenanceDiagnosticFields, buildRuntimeRequestErrorDiagnosticFields, hasEventBoundProviderFailureEvidence, classifyRuntimeErrorStage, buildHyperliquidPublicReadDiagnosticFields, buildRuntimeErrorDiagnostics, positiveNumber, resolveRuntimeEngineOptions, withServerPositionEvents, CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX, getClientKillswitchBlockStorageKey, persistClientRuntimeKillswitchBlock, clearClientRuntimeKillswitchBlock, hashRuntimeDebugText2, createRuntimeUuid2, getRuntimeContractIdentityToken, getRuntimeStatusContractIdentityToken, getRuntimeContractBindingTokenFromCycleResult, getRuntimeContractBindingTupleToken, getRuntimeStatusContractBindingTupleToken, isTransientRuntimeConflictError, createRuntimeStartCancelledError, isRuntimeContractMismatchError, isClientExecutionModeMismatchError, isClientRuntimeSessionStoppedError, isClientRuntimeLeaseAuthError, isClientRuntimeReleasedError, deriveFailedStartCleanupOwnershipLossReason, isRuntimeAbortError, isExplicitClientExecutionMode, createStopAbortError, isRuntimeContractIdentityAdvancedAbort, CLIENT_RUNTIME_NO_DECISION_RECOVERY_REASON, sanitizeSettingsSnapshotForFallback, preflightClientRuntime, ClientExecutionEngine, createStoppedRuntimeSnapshot, ClientRuntimeRegistry, botEngine;
|
|
113884
115028
|
var init_engine = __esm({
|
|
113885
115029
|
"lib/runtime/engine.ts"() {
|
|
113886
115030
|
"use strict";
|
|
@@ -114261,6 +115405,28 @@ var init_engine = __esm({
|
|
|
114261
115405
|
}
|
|
114262
115406
|
return options;
|
|
114263
115407
|
};
|
|
115408
|
+
withServerPositionEvents = (result) => result.executionReports.map((report) => {
|
|
115409
|
+
const action = String(report.action ?? "").toUpperCase();
|
|
115410
|
+
if (report.status !== "executed" || !["BUY", "SELL", "FLIP_OPEN"].includes(action)) return report;
|
|
115411
|
+
const bySide = (side) => side === "BUY" ? "LONG" : "SHORT";
|
|
115412
|
+
let event = null;
|
|
115413
|
+
let direction = null;
|
|
115414
|
+
if (result.intent === "open" || result.intent === "add") {
|
|
115415
|
+
event = result.intent;
|
|
115416
|
+
direction = bySide(action);
|
|
115417
|
+
} else if (result.intent === "reduce") {
|
|
115418
|
+
event = "reduce";
|
|
115419
|
+
direction = action === "BUY" ? "SHORT" : "LONG";
|
|
115420
|
+
} else if (result.intent === "close" || result.intent === "flip" && action !== "FLIP_OPEN") {
|
|
115421
|
+
event = "close";
|
|
115422
|
+
direction = action === "SELL" ? "LONG" : "SHORT";
|
|
115423
|
+
} else if (result.intent === "flip" && (result.side === "buy" || result.side === "sell")) {
|
|
115424
|
+
event = "open";
|
|
115425
|
+
direction = result.side === "buy" ? "LONG" : "SHORT";
|
|
115426
|
+
}
|
|
115427
|
+
if (!event || !direction) return report;
|
|
115428
|
+
return { ...report, execution_metadata: { ...report.execution_metadata, position_event: event, position_direction: direction } };
|
|
115429
|
+
});
|
|
114264
115430
|
CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX = "vtx_client_runtime_killswitch_block_v1:";
|
|
114265
115431
|
getClientKillswitchBlockStorageKey = (profileId) => `${CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX}${profileId.trim()}`;
|
|
114266
115432
|
persistClientRuntimeKillswitchBlock = (profileId) => {
|
|
@@ -114494,6 +115660,20 @@ var init_engine = __esm({
|
|
|
114494
115660
|
this._startupPendingAnalysis = false;
|
|
114495
115661
|
// True while the previous cycle ended in Agent-instruction polling.
|
|
114496
115662
|
this._agentInstructionPollActive = false;
|
|
115663
|
+
// The AI schedule (lib/runtime/ai-schedule.ts): paused outside its windows,
|
|
115664
|
+
// and whether a window let a cycle run since (its end then may close
|
|
115665
|
+
// positions, as the Python Server loop's _was_scheduled_running).
|
|
115666
|
+
this._aiSchedulePaused = false;
|
|
115667
|
+
this._aiScheduleWindowActive = false;
|
|
115668
|
+
// When the window that let the last cycle run ends: the engine checks again
|
|
115669
|
+
// then, so a pause (and Close on Stop) starts at the window's end.
|
|
115670
|
+
this._aiScheduleWindowEndsAtMs = null;
|
|
115671
|
+
// Run Now's next cycle runs whatever the schedule says (triggerNow).
|
|
115672
|
+
this._manualRunRequested = false;
|
|
115673
|
+
// The cycle in flight only checks the AI schedule (a window-end or resume check).
|
|
115674
|
+
this._checkOnlyCycleInFlight = false;
|
|
115675
|
+
// The armed timer is a window-end wake: its cycle only applies the schedule.
|
|
115676
|
+
this._aiScheduleCheckPending = false;
|
|
114497
115677
|
// Cycle whose Agent-instruction claim is currently held open by the server.
|
|
114498
115678
|
// That idle wait is not analysis, so busy flags exclude it.
|
|
114499
115679
|
this._agentInstructionClaimWaitRequestId = null;
|
|
@@ -114517,6 +115697,8 @@ var init_engine = __esm({
|
|
|
114517
115697
|
this._primaryAnalysisDisabled = false;
|
|
114518
115698
|
this._loopEarlyReturnRetryDelayMs = 5e3;
|
|
114519
115699
|
this._executionModeMismatchConsecutiveCount = 0;
|
|
115700
|
+
this._expectedExecutionMode = "client";
|
|
115701
|
+
this._settleUnreportedModelCalls = null;
|
|
114520
115702
|
this._activeRuntimeContractIdentity = null;
|
|
114521
115703
|
this._contractRebindInFlight = false;
|
|
114522
115704
|
this._contractRebindExhausted = false;
|
|
@@ -114684,6 +115866,57 @@ var init_engine = __esm({
|
|
|
114684
115866
|
}
|
|
114685
115867
|
return pending3.length === 0;
|
|
114686
115868
|
}
|
|
115869
|
+
/**
|
|
115870
|
+
* Close on Stop: a Trader's schedule window ended with the option on, so
|
|
115871
|
+
* its open positions close, as the Python Server loop's
|
|
115872
|
+
* _handle_schedule_stop does. A failure is reported as a runtime error and
|
|
115873
|
+
* the bot stays paused.
|
|
115874
|
+
*/
|
|
115875
|
+
async _closePositionsAtScheduleEnd(profileId, paused, cancelled) {
|
|
115876
|
+
try {
|
|
115877
|
+
if (cancelled()) return;
|
|
115878
|
+
const walletAddress = String(paused.settings.hyperliquid_wallet_address || "").trim();
|
|
115879
|
+
const signingKey = String(this._deviceSecrets?.hyperliquidSigningKey || "").trim();
|
|
115880
|
+
if (!walletAddress || !signingKey) {
|
|
115881
|
+
throw new Error("the wallet or its signing key is unavailable");
|
|
115882
|
+
}
|
|
115883
|
+
const timeoutSeconds = Number(paused.config.client_runtime_killswitch_close_timeout_seconds);
|
|
115884
|
+
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
115885
|
+
throw new Error("Invalid Client Mode position close timeout configuration.");
|
|
115886
|
+
}
|
|
115887
|
+
await this._trailingMaintenancePromise;
|
|
115888
|
+
await this._pendingProtectionRecoveryPromise;
|
|
115889
|
+
await waitForBrowserExchangeMutationSettlement(profileId);
|
|
115890
|
+
const { positions } = await fetchBrowserAccountState2({
|
|
115891
|
+
publicRequestPriority: "trading_reduce",
|
|
115892
|
+
config: paused.config,
|
|
115893
|
+
walletAddress,
|
|
115894
|
+
symbol: firstConfiguredSymbol(paused.settings, paused.config),
|
|
115895
|
+
tickerPrice: 0,
|
|
115896
|
+
leverage: 1,
|
|
115897
|
+
aggregatePerpDexs: true,
|
|
115898
|
+
forceRefresh: true,
|
|
115899
|
+
sessionId: this._sessionId ?? void 0
|
|
115900
|
+
});
|
|
115901
|
+
if (cancelled()) return;
|
|
115902
|
+
await this._assertFreshClientWalletAssignment(profileId, walletAddress, void 0, "scheduled close on stop");
|
|
115903
|
+
if (cancelled()) return;
|
|
115904
|
+
const summary = await closeClientKillswitchPositions({
|
|
115905
|
+
profileId,
|
|
115906
|
+
walletAddress,
|
|
115907
|
+
positions,
|
|
115908
|
+
config: paused.config,
|
|
115909
|
+
signingKey,
|
|
115910
|
+
timeoutSeconds
|
|
115911
|
+
});
|
|
115912
|
+
if (summary.positionCloseFailures > 0) {
|
|
115913
|
+
throw new Error(`${summary.positionCloseFailures} position(s) could not be closed`);
|
|
115914
|
+
}
|
|
115915
|
+
} catch (error48) {
|
|
115916
|
+
const detail = error48 instanceof Error ? error48.message : String(error48);
|
|
115917
|
+
await this.reportError(`\u26A0\uFE0F Scheduled close-on-stop failed: ${detail}`, { fatal: false });
|
|
115918
|
+
}
|
|
115919
|
+
}
|
|
114687
115920
|
async _assertFreshClientWalletAssignment(profileId, expectedWalletAddress, signal, stage) {
|
|
114688
115921
|
const expectedWallet = String(expectedWalletAddress || "").trim().toLowerCase();
|
|
114689
115922
|
if (!expectedWallet) {
|
|
@@ -114723,7 +115956,9 @@ var init_engine = __esm({
|
|
|
114723
115956
|
const status = await getAiTradingStatus(void 0, Number(this._profileId), {
|
|
114724
115957
|
runtimeViewer: this._runtimeStatusViewer()
|
|
114725
115958
|
});
|
|
114726
|
-
|
|
115959
|
+
const statusMode = status?.execution_mode;
|
|
115960
|
+
const expectedMode = this._expectedExecutionMode === "server" ? String(statusMode ?? "").trim().toLowerCase() === "server" : isExplicitClientExecutionMode(statusMode);
|
|
115961
|
+
if (!expectedMode) {
|
|
114727
115962
|
this._executionModeMismatchConsecutiveCount += 1;
|
|
114728
115963
|
return this._executionModeMismatchConsecutiveCount >= 2;
|
|
114729
115964
|
}
|
|
@@ -115265,6 +116500,7 @@ var init_engine = __esm({
|
|
|
115265
116500
|
}
|
|
115266
116501
|
_armExecutionLoopTimer(options) {
|
|
115267
116502
|
this._clearExecutionLoopTimer();
|
|
116503
|
+
if (options?.reason !== "ai_schedule_window_end") this._aiScheduleCheckPending = false;
|
|
115268
116504
|
if (this._state !== "running" || this._loopIntervalMs == null) {
|
|
115269
116505
|
return;
|
|
115270
116506
|
}
|
|
@@ -115286,7 +116522,7 @@ var init_engine = __esm({
|
|
|
115286
116522
|
const timerReason = options?.reason || "scheduled";
|
|
115287
116523
|
const armedAtMs = Date.now();
|
|
115288
116524
|
const expectedFireAtMs = armedAtMs + delayMs;
|
|
115289
|
-
const quietAgentPollTimer = timerReason === "agent_instruction_poll";
|
|
116525
|
+
const quietAgentPollTimer = timerReason === "agent_instruction_poll" || timerReason === "ai_schedule_paused";
|
|
115290
116526
|
if (!quietAgentPollTimer) this._emitLoopBoundaryTelemetry("client_timer_armed", `reason=${options?.reason || "scheduled"} delay_ms=${delayMs}`, {
|
|
115291
116527
|
reason: timerReason,
|
|
115292
116528
|
delay_ms: delayMs,
|
|
@@ -115295,7 +116531,13 @@ var init_engine = __esm({
|
|
|
115295
116531
|
timer_expected_fire_at_ms: expectedFireAtMs,
|
|
115296
116532
|
// Terminal cycle evidence already records its next schedule. Retain the
|
|
115297
116533
|
// initial/repaired schedule too, even if its first cycle never starts.
|
|
115298
|
-
...[
|
|
116534
|
+
...[
|
|
116535
|
+
"cycle_finally",
|
|
116536
|
+
"main_model_disabled_copy_poll",
|
|
116537
|
+
"agent_instruction_poll",
|
|
116538
|
+
"ai_schedule_paused",
|
|
116539
|
+
"ai_schedule_window_end"
|
|
116540
|
+
].includes(timerReason) ? {} : { cycle_evidence: {
|
|
115299
116541
|
version: 1,
|
|
115300
116542
|
runtime_source: "client",
|
|
115301
116543
|
mode: this._mode,
|
|
@@ -115538,6 +116780,24 @@ var init_engine = __esm({
|
|
|
115538
116780
|
return this._instanceId;
|
|
115539
116781
|
}
|
|
115540
116782
|
/** Whether this engine runs, starts, or stops a runtime (never claim it again). */
|
|
116783
|
+
/**
|
|
116784
|
+
* Resolves once no cycle is in flight, or after the timeout: a Node runtime
|
|
116785
|
+
* host draining for a restart lets the current cycle finish, as a Python
|
|
116786
|
+
* Server worker drains its in-flight work. Whether it settled in time.
|
|
116787
|
+
*/
|
|
116788
|
+
async waitForCycleToSettle(timeoutMs) {
|
|
116789
|
+
const loop = this._executionLoopPromise;
|
|
116790
|
+
if (!loop) return true;
|
|
116791
|
+
let timer;
|
|
116792
|
+
const settled = await Promise.race([
|
|
116793
|
+
loop.then(() => true, () => true),
|
|
116794
|
+
new Promise((resolve14) => {
|
|
116795
|
+
timer = setTimeout(() => resolve14(false), timeoutMs);
|
|
116796
|
+
})
|
|
116797
|
+
]);
|
|
116798
|
+
clearTimeout(timer);
|
|
116799
|
+
return settled;
|
|
116800
|
+
}
|
|
115541
116801
|
get active() {
|
|
115542
116802
|
return this._startPromise !== null || this._isStopping || this._state === "running" || this._state === "stale" || this._state === "offline";
|
|
115543
116803
|
}
|
|
@@ -115564,12 +116824,20 @@ var init_engine = __esm({
|
|
|
115564
116824
|
await this.relinquishControl("window");
|
|
115565
116825
|
}
|
|
115566
116826
|
async _attachInternal(profileId, grant, options, startController) {
|
|
116827
|
+
this._aiSchedulePaused = false;
|
|
116828
|
+
this._aiScheduleWindowActive = false;
|
|
116829
|
+
this._aiScheduleWindowEndsAtMs = null;
|
|
115567
116830
|
const lease = grant.lease;
|
|
115568
116831
|
const grantSessionId = String(lease.runtime_session_id || "").trim();
|
|
115569
116832
|
const grantDeviceId = String(lease.device_id || "").trim();
|
|
115570
116833
|
if (String(lease.profile_id) !== String(profileId) || !grantSessionId || !grantDeviceId) {
|
|
115571
116834
|
throw new Error("The runtime grant does not belong to this profile.");
|
|
115572
116835
|
}
|
|
116836
|
+
this._expectedExecutionMode = options.executionMode === "server" ? "server" : "client";
|
|
116837
|
+
this._manualRunRequested = false;
|
|
116838
|
+
this._aiScheduleCheckPending = false;
|
|
116839
|
+
this._checkOnlyCycleInFlight = false;
|
|
116840
|
+
this._settleUnreportedModelCalls = options.settleUnreportedModelCalls ?? null;
|
|
115573
116841
|
const leaseSchedulerInstanceId = String(lease.scheduler_instance_id ?? "").trim();
|
|
115574
116842
|
if (leaseSchedulerInstanceId !== this._instanceId && !(leaseSchedulerInstanceId === "" && options.unboundSchedulerLease === true)) {
|
|
115575
116843
|
throw createRuntimeStartCancelledError("scheduler_instance_binding_missing", {
|
|
@@ -115589,7 +116857,8 @@ var init_engine = __esm({
|
|
|
115589
116857
|
this._sessionId = grantSessionId;
|
|
115590
116858
|
this._deviceId = grantDeviceId;
|
|
115591
116859
|
this._mode = lease.mode === "assistant" ? "assistant" : "trader";
|
|
115592
|
-
|
|
116860
|
+
const grantedLastRunAt = String(grant.runtime?.last_runtime_run_at ?? "").trim();
|
|
116861
|
+
this._lastRunAt = this._expectedExecutionMode === "server" ? Number.isFinite(Date.parse(grantedLastRunAt)) ? new Date(Date.parse(grantedLastRunAt)).toISOString() : null : (/* @__PURE__ */ new Date()).toISOString();
|
|
115593
116862
|
this._lastAnalysisStartedAtMs = null;
|
|
115594
116863
|
this._lastError = null;
|
|
115595
116864
|
this._lastStopReason = null;
|
|
@@ -115715,7 +116984,10 @@ var init_engine = __esm({
|
|
|
115715
116984
|
return;
|
|
115716
116985
|
}
|
|
115717
116986
|
this._assertStartAttemptActive(startController, "before_execution_loop");
|
|
115718
|
-
if (waitsForAssignedStartPhase) {
|
|
116987
|
+
if (waitsForAssignedStartPhase && this._expectedExecutionMode === "server" && this._mode === "trader") {
|
|
116988
|
+
this._aiScheduleCheckPending = true;
|
|
116989
|
+
void this._runExecutionLoop();
|
|
116990
|
+
} else if (waitsForAssignedStartPhase) {
|
|
115719
116991
|
this._armExecutionLoopTimer({ alignToNextRun: true, reason: "assigned_start_phase" });
|
|
115720
116992
|
} else {
|
|
115721
116993
|
this._armExecutionLoopTimer({ alignToNextRun: true });
|
|
@@ -116371,10 +117643,13 @@ var init_engine = __esm({
|
|
|
116371
117643
|
}
|
|
116372
117644
|
await this.relinquishControl(reason);
|
|
116373
117645
|
}
|
|
116374
|
-
async triggerNow() {
|
|
117646
|
+
async triggerNow(options) {
|
|
116375
117647
|
if (this._state !== "running") {
|
|
116376
117648
|
throw new Error("AI runtime is not running on this client.");
|
|
116377
117649
|
}
|
|
117650
|
+
if ((options?.ignoreAiSchedule ?? true) && (!this._executionLoopPromise || this._aiSchedulePaused || this._checkOnlyCycleInFlight)) {
|
|
117651
|
+
this._manualRunRequested = true;
|
|
117652
|
+
}
|
|
116378
117653
|
await this._runExecutionLoop();
|
|
116379
117654
|
}
|
|
116380
117655
|
_abortTrailingMaintenanceBeforeDispatch() {
|
|
@@ -116485,6 +117760,19 @@ var init_engine = __esm({
|
|
|
116485
117760
|
this._pendingProtectionRecoveryDispatched = true;
|
|
116486
117761
|
}
|
|
116487
117762
|
});
|
|
117763
|
+
const retired = results.flatMap(({ retired: symbolRetired }) => symbolRetired ?? []);
|
|
117764
|
+
const stale = results.flatMap(({ symbol: symbol2, reports }) => reports.filter((report) => report.execution_metadata?.reason_code === "pending_protective_entry_stale").map(() => symbol2));
|
|
117765
|
+
if (retired.length > 0 || stale.length > 0) {
|
|
117766
|
+
const retiredByReason = retired.reduce((counts, { reasonCode }) => ({
|
|
117767
|
+
...counts,
|
|
117768
|
+
[reasonCode]: (counts[reasonCode] ?? 0) + 1
|
|
117769
|
+
}), {});
|
|
117770
|
+
this.reportLifecycleTelemetry(
|
|
117771
|
+
"client_pending_protection_recovery",
|
|
117772
|
+
`retired=${retired.length} stale=${stale.length}`,
|
|
117773
|
+
{ profileId, payload: { retired_by_reason: retiredByReason, stale_symbols: stale } }
|
|
117774
|
+
);
|
|
117775
|
+
}
|
|
116488
117776
|
if (results.length) {
|
|
116489
117777
|
appendRuntimeDebugEvent({
|
|
116490
117778
|
label: "pending_protection_recovery",
|
|
@@ -116747,10 +118035,22 @@ var init_engine = __esm({
|
|
|
116747
118035
|
const analysisAbortController = new AbortController();
|
|
116748
118036
|
this._analysisAbortController = analysisAbortController;
|
|
116749
118037
|
let decisionSubmitted = false;
|
|
118038
|
+
let cycleModelCalls = [];
|
|
118039
|
+
let cycleModelCallsReported = false;
|
|
116750
118040
|
let executedExchangeOrderInCycle = false;
|
|
116751
118041
|
let pendingExternalInferenceBindings = [];
|
|
116752
118042
|
let agentPollDelayMs = null;
|
|
118043
|
+
let aiSchedulePauseMs = null;
|
|
118044
|
+
let aiSchedulePauseHasNext = false;
|
|
118045
|
+
let providerRetryDelayMs = null;
|
|
118046
|
+
const ignoreAiSchedule = this._manualRunRequested;
|
|
118047
|
+
this._manualRunRequested = false;
|
|
118048
|
+
const pausedBeforeSlot = this._aiSchedulePaused && this._nextRunAtMs != null && Date.now() < this._nextRunAtMs;
|
|
118049
|
+
const aiScheduleCheckOnly = (this._aiScheduleCheckPending || pausedBeforeSlot) && !ignoreAiSchedule;
|
|
118050
|
+
this._aiScheduleCheckPending = false;
|
|
118051
|
+
this._checkOnlyCycleInFlight = aiScheduleCheckOnly;
|
|
116753
118052
|
const agentPollContinuation = this._agentInstructionPollActive;
|
|
118053
|
+
const aiSchedulePauseContinuation = this._aiSchedulePaused || aiScheduleCheckOnly;
|
|
116754
118054
|
let cycleStartEmitted = false;
|
|
116755
118055
|
let cycleErrorProvenance = null;
|
|
116756
118056
|
let cycleWorkStarted = false;
|
|
@@ -116825,15 +118125,35 @@ var init_engine = __esm({
|
|
|
116825
118125
|
this._notifyListeners();
|
|
116826
118126
|
void this.sendHeartbeat();
|
|
116827
118127
|
};
|
|
116828
|
-
if (!agentPollContinuation) emitCycleStarted();
|
|
118128
|
+
if (!agentPollContinuation && !aiSchedulePauseContinuation) emitCycleStarted();
|
|
116829
118129
|
try {
|
|
116830
|
-
|
|
118130
|
+
let savedSecrets = await ClientVault.getSecrets(profileId);
|
|
118131
|
+
let serverSigningKey = null;
|
|
118132
|
+
if (this._expectedExecutionMode === "server") {
|
|
118133
|
+
try {
|
|
118134
|
+
const fresh = await ClientVault.hydrateFromServer(profileId, {
|
|
118135
|
+
includeAllProviderKeys: true,
|
|
118136
|
+
requireProviderSecret: false
|
|
118137
|
+
});
|
|
118138
|
+
if (fresh) {
|
|
118139
|
+
savedSecrets = fresh;
|
|
118140
|
+
serverSigningKey = String(fresh.hyperliquidSigningKey ?? "").trim() || null;
|
|
118141
|
+
}
|
|
118142
|
+
} catch (error48) {
|
|
118143
|
+
appendRuntimeDebugEvent({
|
|
118144
|
+
label: "server_secrets_refresh_failed",
|
|
118145
|
+
note: getSanitizedRuntimeErrorMessage(error48) || "unknown",
|
|
118146
|
+
outcome: "error"
|
|
118147
|
+
});
|
|
118148
|
+
}
|
|
118149
|
+
}
|
|
116831
118150
|
if (analysisAbortController.signal.aborted || this._isStopping || this._analysisRequestId !== requestId) {
|
|
116832
118151
|
throw new DOMException("The operation was aborted.", "AbortError");
|
|
116833
118152
|
}
|
|
116834
118153
|
if (savedSecrets) {
|
|
116835
118154
|
deviceSecrets = {
|
|
116836
118155
|
...deviceSecrets,
|
|
118156
|
+
...serverSigningKey ? { hyperliquidSigningKey: serverSigningKey } : {},
|
|
116837
118157
|
providerKeys: savedSecrets.providerKeys ?? {},
|
|
116838
118158
|
providerKeySlots: savedSecrets.providerKeySlots,
|
|
116839
118159
|
providerBaseUrls: savedSecrets.providerBaseUrls,
|
|
@@ -116880,6 +118200,18 @@ var init_engine = __esm({
|
|
|
116880
118200
|
}
|
|
116881
118201
|
},
|
|
116882
118202
|
onCycleObservation: observeCycle,
|
|
118203
|
+
onAiScheduleWindowActive: (windowEndsAtMs) => {
|
|
118204
|
+
this._aiSchedulePaused = false;
|
|
118205
|
+
this._aiScheduleWindowActive = true;
|
|
118206
|
+
this._aiScheduleWindowEndsAtMs = windowEndsAtMs;
|
|
118207
|
+
},
|
|
118208
|
+
onAiScheduleOff: () => {
|
|
118209
|
+
this._aiSchedulePaused = false;
|
|
118210
|
+
this._aiScheduleWindowEndsAtMs = null;
|
|
118211
|
+
},
|
|
118212
|
+
ignoreAiSchedule,
|
|
118213
|
+
aiScheduleCheckOnly,
|
|
118214
|
+
executionMode: this._expectedExecutionMode,
|
|
116883
118215
|
onPreparedExecutionContexts: async ({ config: config2, executionContexts }) => {
|
|
116884
118216
|
if (runtimeMode !== "trader") return;
|
|
116885
118217
|
const cancelled = () => this._state !== "running" || this._isStopping || this._windowHandoffRequested || this._killswitchLatched || this._profileId !== profileId || this._sessionId !== sessionId || this._deviceId !== deviceId || (getRuntimeContractBindingTupleToken(this._activeRuntimeContractIdentity) ?? getRuntimeStatusContractBindingTupleToken(this._runtimeStatus)) !== loopContractBindingToken;
|
|
@@ -116908,10 +118240,74 @@ var init_engine = __esm({
|
|
|
116908
118240
|
},
|
|
116909
118241
|
signal: analysisAbortController.signal
|
|
116910
118242
|
});
|
|
118243
|
+
const runCycleWithDispatchFreshness = (secrets) => this._expectedExecutionMode !== "server" ? runCycle(secrets) : runCycle(secrets).catch((error48) => {
|
|
118244
|
+
if (!localAnalysis.isServerDispatchAccountStateStale(error48) || analysisAbortController.signal.aborted || this._isStopping || this._analysisRequestId !== requestId) {
|
|
118245
|
+
throw error48;
|
|
118246
|
+
}
|
|
118247
|
+
appendRuntimeDebugEvent({ label: "server_dispatch_context_rebuilt", note: "attempt=2", outcome: "ok" });
|
|
118248
|
+
return runCycle(secrets);
|
|
118249
|
+
});
|
|
116911
118250
|
let result;
|
|
116912
118251
|
try {
|
|
116913
|
-
result = await
|
|
118252
|
+
result = await runCycleWithDispatchFreshness(deviceSecrets);
|
|
116914
118253
|
} catch (error48) {
|
|
118254
|
+
if (localAnalysis.isClientRuntimeAiScheduleStillActive(error48)) {
|
|
118255
|
+
cycleOutcome = "skipped";
|
|
118256
|
+
cycleReason = "ai_schedule_check";
|
|
118257
|
+
this._lastRunAt = previousLastRunAt;
|
|
118258
|
+
this._nextRunAtMs = previousNextRunAtMs;
|
|
118259
|
+
this._lastError = null;
|
|
118260
|
+
this._notifyListeners();
|
|
118261
|
+
return;
|
|
118262
|
+
}
|
|
118263
|
+
if (localAnalysis.isClientRuntimeAiSchedulePaused(error48)) {
|
|
118264
|
+
cycleOutcome = "skipped";
|
|
118265
|
+
cycleReason = "ai_schedule_paused";
|
|
118266
|
+
this._lastRunAt = previousLastRunAt;
|
|
118267
|
+
this._lastError = null;
|
|
118268
|
+
const windowEnded = this._aiScheduleWindowActive;
|
|
118269
|
+
this._aiScheduleWindowActive = false;
|
|
118270
|
+
this._aiScheduleWindowEndsAtMs = null;
|
|
118271
|
+
this._aiSchedulePaused = true;
|
|
118272
|
+
const nowMs2 = Date.now();
|
|
118273
|
+
const windowOpensAtMs = error48.nextChangeAtMs != null ? this._periodicNextSlot(error48.nextChangeAtMs, true) ?? error48.nextChangeAtMs : null;
|
|
118274
|
+
aiSchedulePauseHasNext = windowOpensAtMs != null;
|
|
118275
|
+
aiSchedulePauseMs = windowOpensAtMs != null ? Math.max(1e3, Math.min(windowOpensAtMs - nowMs2, 36e5)) : 6e4;
|
|
118276
|
+
if (runtimeMode === "trader" && this._loopIntervalMs != null) {
|
|
118277
|
+
aiSchedulePauseMs = Math.min(aiSchedulePauseMs, Math.max(1e3, this._loopIntervalMs));
|
|
118278
|
+
}
|
|
118279
|
+
this._nextRunAtMs = windowOpensAtMs;
|
|
118280
|
+
if (!aiSchedulePauseContinuation) {
|
|
118281
|
+
this._emitLoopBoundaryTelemetry("client_ai_schedule_paused", `request_id=${requestId}`, {
|
|
118282
|
+
request_id: requestId,
|
|
118283
|
+
status: error48.message,
|
|
118284
|
+
next_change_ms: error48.nextChangeAtMs
|
|
118285
|
+
});
|
|
118286
|
+
}
|
|
118287
|
+
const cancelled = () => this._state !== "running" || this._isStopping || this._windowHandoffRequested || this._killswitchLatched || analysisAbortController.signal.aborted || this._profileId !== profileId || this._sessionId !== sessionId || this._deviceId !== deviceId;
|
|
118288
|
+
if (windowEnded && runtimeMode === "trader" && error48.closeOnStop) {
|
|
118289
|
+
await this._closePositionsAtScheduleEnd(profileId, error48, cancelled);
|
|
118290
|
+
}
|
|
118291
|
+
if (runtimeMode === "trader" && !cancelled()) {
|
|
118292
|
+
try {
|
|
118293
|
+
await this._processClientCopyTrading({
|
|
118294
|
+
profileId,
|
|
118295
|
+
runtimeSessionId: sessionId,
|
|
118296
|
+
runtimeDeviceId: deviceId,
|
|
118297
|
+
config: await this.getExecutionConfig(profileId),
|
|
118298
|
+
signal: analysisAbortController.signal
|
|
118299
|
+
});
|
|
118300
|
+
} catch (copyTradingError) {
|
|
118301
|
+
appendRuntimeDebugEvent({
|
|
118302
|
+
label: "ai_schedule_paused_copy_poll_failed",
|
|
118303
|
+
note: getSanitizedRuntimeErrorMessage(copyTradingError) || "Copy Trading poll failed.",
|
|
118304
|
+
outcome: "error"
|
|
118305
|
+
});
|
|
118306
|
+
}
|
|
118307
|
+
}
|
|
118308
|
+
this._notifyListeners();
|
|
118309
|
+
return;
|
|
118310
|
+
}
|
|
116915
118311
|
if (localAnalysis.isClientRuntimeAgentInstructionEmpty(error48)) {
|
|
116916
118312
|
cycleOutcome = "skipped";
|
|
116917
118313
|
cycleReason = "agent_instruction_poll_empty";
|
|
@@ -116949,7 +118345,7 @@ var init_engine = __esm({
|
|
|
116949
118345
|
throw error48;
|
|
116950
118346
|
}
|
|
116951
118347
|
try {
|
|
116952
|
-
result = await
|
|
118348
|
+
result = await runCycleWithDispatchFreshness(refresh.secrets);
|
|
116953
118349
|
} catch (retryError) {
|
|
116954
118350
|
const retryProviderSetup = getRuntimeProviderSetupDiagnostics(retryError);
|
|
116955
118351
|
if (retryProviderSetup) {
|
|
@@ -116985,6 +118381,7 @@ var init_engine = __esm({
|
|
|
116985
118381
|
}
|
|
116986
118382
|
markCycleWorkStarted();
|
|
116987
118383
|
decisionSnapshotId = result.decisionSnapshotId;
|
|
118384
|
+
cycleModelCalls = Array.isArray(result.invocations) ? result.invocations : [];
|
|
116988
118385
|
if (result.runtimeError) cycleFailureStage = cycleObservation.stage;
|
|
116989
118386
|
observeCycle({ stage: "decision" });
|
|
116990
118387
|
cycleErrorProvenance = {
|
|
@@ -117141,7 +118538,10 @@ var init_engine = __esm({
|
|
|
117141
118538
|
promptTokens: result.prompt_tokens,
|
|
117142
118539
|
completionTokens: result.completion_tokens,
|
|
117143
118540
|
totalTokens: result.total_tokens,
|
|
117144
|
-
|
|
118541
|
+
// A Server bot's row records what started its cycle, as the
|
|
118542
|
+
// Python Server loop's does (a Client row never has, and the key
|
|
118543
|
+
// is part of a row's Insights settings epoch).
|
|
118544
|
+
settingsSnapshot: this._expectedExecutionMode === "server" ? { ...result.settingsSnapshot, analysis_trigger_origin: ignoreAiSchedule ? "manual" : "scheduled" } : result.settingsSnapshot,
|
|
117145
118545
|
clientExchangeSnapshot: result.clientExchangeSnapshot ?? null,
|
|
117146
118546
|
invocations: result.invocations,
|
|
117147
118547
|
externalInferenceBindings: result.externalInferenceBindings ?? [],
|
|
@@ -117154,6 +118554,7 @@ var init_engine = __esm({
|
|
|
117154
118554
|
reconciliationTimeoutMs: result.decisionReconciliationTimeoutMs
|
|
117155
118555
|
});
|
|
117156
118556
|
decisionSubmitted = true;
|
|
118557
|
+
cycleModelCallsReported = true;
|
|
117157
118558
|
} catch (decisionError) {
|
|
117158
118559
|
if (isRuntimeContractMismatchError(decisionError)) {
|
|
117159
118560
|
await this._discardCycleOnContractMismatch("decision", decisionError);
|
|
@@ -117226,11 +118627,28 @@ var init_engine = __esm({
|
|
|
117226
118627
|
}
|
|
117227
118628
|
const executionResults = [];
|
|
117228
118629
|
const executionFailures = [];
|
|
117229
|
-
|
|
117230
|
-
|
|
117231
|
-
|
|
117232
|
-
|
|
117233
|
-
|
|
118630
|
+
const executionLeaseToken = () => {
|
|
118631
|
+
const lease = getPersistedClientRuntimeServerLease(profileId);
|
|
118632
|
+
return lease?.runtimeSessionId === sessionId && lease.deviceId === deviceId && lease.mode === "trader" ? lease.runtimeLeaseToken : null;
|
|
118633
|
+
};
|
|
118634
|
+
const serverCapacityByPlan = /* @__PURE__ */ new Map();
|
|
118635
|
+
if (this._expectedExecutionMode === "server") {
|
|
118636
|
+
const capacityPlans = executionPlans.map((plan, planIndex) => ({ plan, planIndex, decision: String(plan.decision || "").toUpperCase() })).filter(({ plan, decision }) => !plan.executionBlock && (decision === "BUY" || decision === "SELL") && Math.trunc(Number(plan.units)) > 0);
|
|
118637
|
+
const allocations = capacityPlans.length === 0 ? [] : await allocateServerExecutionCapacity({
|
|
118638
|
+
profileId,
|
|
118639
|
+
sessionId,
|
|
118640
|
+
runtimeLeaseToken: executionLeaseToken(),
|
|
118641
|
+
runtimeDeviceId: deviceId,
|
|
118642
|
+
schedulerInstanceId: this._instanceId,
|
|
118643
|
+
signal: analysisAbortController.signal
|
|
118644
|
+
}, capacityPlans.map(({ plan, decision }) => ({
|
|
118645
|
+
symbol: plan.executionContext.symbol,
|
|
118646
|
+
decision,
|
|
118647
|
+
units: Math.trunc(Number(plan.units))
|
|
118648
|
+
})));
|
|
118649
|
+
capacityPlans.forEach(({ planIndex }, index) => serverCapacityByPlan.set(planIndex, allocations[index]));
|
|
118650
|
+
}
|
|
118651
|
+
const runPlan = async (plan, planIndex) => {
|
|
117234
118652
|
let planEntryOrderDispatched = false;
|
|
117235
118653
|
const decisionWallet = String(
|
|
117236
118654
|
plan.executionContext.walletAddress || ""
|
|
@@ -117252,7 +118670,7 @@ var init_engine = __esm({
|
|
|
117252
118670
|
actionablePlan ? "decision execution" : trailingHoldCanMutate ? "trailing stop maintenance" : "protective order reconciliation"
|
|
117253
118671
|
);
|
|
117254
118672
|
if (shouldAbortForContractInvalidation("post_execution_preferences_refresh")) {
|
|
117255
|
-
return;
|
|
118673
|
+
return { control: "return" };
|
|
117256
118674
|
}
|
|
117257
118675
|
}
|
|
117258
118676
|
appendRuntimeDebugEvent({
|
|
@@ -117304,17 +118722,16 @@ var init_engine = __esm({
|
|
|
117304
118722
|
executionResult = await executeClientRuntimeDecision({
|
|
117305
118723
|
profileId,
|
|
117306
118724
|
sessionId,
|
|
117307
|
-
runtimeLeaseToken: (
|
|
117308
|
-
const lease = getPersistedClientRuntimeServerLease(profileId);
|
|
117309
|
-
return lease?.runtimeSessionId === sessionId && lease.deviceId === deviceId && lease.mode === "trader" ? lease.runtimeLeaseToken : null;
|
|
117310
|
-
})(),
|
|
118725
|
+
runtimeLeaseToken: executionLeaseToken(),
|
|
117311
118726
|
runtimeDeviceId: deviceId,
|
|
117312
118727
|
schedulerInstanceId: this._instanceId,
|
|
117313
118728
|
cycleId: result.cycleId,
|
|
118729
|
+
serverCapacityAllocation: serverCapacityByPlan.get(planIndex),
|
|
117314
118730
|
signingKey: this._deviceSecrets?.hyperliquidSigningKey ?? null,
|
|
117315
118731
|
config: config2,
|
|
117316
118732
|
decision: plan.decision,
|
|
117317
118733
|
units: plan.units,
|
|
118734
|
+
executionMode: this._expectedExecutionMode,
|
|
117318
118735
|
executionContext: plan.executionContext,
|
|
117319
118736
|
skipTrailingMaintenance: this._trailingObservations.some((request) => request.executionContext.decisionSnapshotId === plan.executionContext.decisionSnapshotId),
|
|
117320
118737
|
signal: analysisAbortController.signal,
|
|
@@ -117333,7 +118750,8 @@ var init_engine = __esm({
|
|
|
117333
118750
|
if (isClientRuntimeWindowHandoffBeforePlanDispatch(executionError)) {
|
|
117334
118751
|
const handoffCleanup = getClientRuntimeWindowHandoffCleanup(executionError);
|
|
117335
118752
|
if (handoffCleanup) {
|
|
117336
|
-
|
|
118753
|
+
this._executionFinalizationRequired = true;
|
|
118754
|
+
return { control: "break", result: {
|
|
117337
118755
|
status: "skipped",
|
|
117338
118756
|
intent: "hold",
|
|
117339
118757
|
side: null,
|
|
@@ -117346,10 +118764,9 @@ var init_engine = __esm({
|
|
|
117346
118764
|
handoffCleanup,
|
|
117347
118765
|
executionSnapshotId: `handoff-cleanup-${planIndex + 1}-${Date.now()}`,
|
|
117348
118766
|
executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
117349
|
-
}
|
|
117350
|
-
this._executionFinalizationRequired = true;
|
|
118767
|
+
} };
|
|
117351
118768
|
}
|
|
117352
|
-
break;
|
|
118769
|
+
return { control: "break" };
|
|
117353
118770
|
}
|
|
117354
118771
|
if (analysisAbortController.signal.aborted || isRuntimeAbortError(executionError) || isRuntimeContractMismatchError(executionError) || isClientExecutionModeMismatchError(executionError) || isClientRuntimeSessionStoppedError(executionError) || isClientRuntimeLeaseAuthError(executionError) || isTransientRuntimeConflictError(executionError)) {
|
|
117355
118772
|
throw executionError;
|
|
@@ -117408,6 +118825,9 @@ var init_engine = __esm({
|
|
|
117408
118825
|
};
|
|
117409
118826
|
}
|
|
117410
118827
|
}
|
|
118828
|
+
return { control: "continue", result: executionResult };
|
|
118829
|
+
};
|
|
118830
|
+
const recordPlanResult = (executionResult) => {
|
|
117411
118831
|
executionResults.push(executionResult);
|
|
117412
118832
|
if (executionResult.handoffCleanup) {
|
|
117413
118833
|
this._executionFinalizationRequired = true;
|
|
@@ -117416,11 +118836,26 @@ var init_engine = __esm({
|
|
|
117416
118836
|
executedExchangeOrderInCycle = true;
|
|
117417
118837
|
this._executionFinalizationRequired = true;
|
|
117418
118838
|
}
|
|
117419
|
-
|
|
118839
|
+
};
|
|
118840
|
+
const cycleSupersededWithoutExecution = () => !this._executionFinalizationRequired && (analysisAbortController.signal.aborted || this._isStopping || this._analysisRequestId !== requestId);
|
|
118841
|
+
for (let planIndex = 0; planIndex < executionPlans.length; planIndex += 1) {
|
|
118842
|
+
if (planIndex > 0 && this._windowHandoffRequested) {
|
|
118843
|
+
break;
|
|
118844
|
+
}
|
|
118845
|
+
const outcome = await runPlan(executionPlans[planIndex], planIndex);
|
|
118846
|
+
if (outcome.control === "return") {
|
|
118847
|
+
return;
|
|
118848
|
+
}
|
|
118849
|
+
if (outcome.control === "break") {
|
|
118850
|
+
if (outcome.result) executionResults.push(outcome.result);
|
|
118851
|
+
break;
|
|
118852
|
+
}
|
|
118853
|
+
recordPlanResult(outcome.result);
|
|
118854
|
+
if (cycleSupersededWithoutExecution()) {
|
|
117420
118855
|
return;
|
|
117421
118856
|
}
|
|
117422
118857
|
}
|
|
117423
|
-
const executionReports = executionResults.flatMap((executionResult) => Array.isArray(executionResult.executionReports) ? executionResult.executionReports : []);
|
|
118858
|
+
const executionReports = executionResults.flatMap((executionResult) => Array.isArray(executionResult.executionReports) ? this._expectedExecutionMode === "server" ? withServerPositionEvents(executionResult) : executionResult.executionReports : []);
|
|
117424
118859
|
const executedOrderReports = executionReports.filter((report) => report.status === "executed" && String(report.order_id || "").trim().length > 0);
|
|
117425
118860
|
const handoffCleanups = executionResults.flatMap((executionResult) => executionResult.handoffCleanup ? [executionResult.handoffCleanup] : []);
|
|
117426
118861
|
if (this._windowHandoffRequested && executedOrderReports.length === 0) {
|
|
@@ -117606,6 +119041,8 @@ var init_engine = __esm({
|
|
|
117606
119041
|
this._notifyListeners();
|
|
117607
119042
|
}
|
|
117608
119043
|
} catch (error48) {
|
|
119044
|
+
const errorModelCalls = error48?.runtimeInvocationAttempts;
|
|
119045
|
+
if (Array.isArray(errorModelCalls) && errorModelCalls.length > 0) cycleModelCalls = errorModelCalls;
|
|
117609
119046
|
const cycleElapsedSeconds = Math.max(0, (performance.now() - runStartedMonotonicMs) / 1e3);
|
|
117610
119047
|
cycleOutcome = "failed";
|
|
117611
119048
|
cycleReason = cycleObservation.reason_code ?? "runtime_failed";
|
|
@@ -117711,12 +119148,19 @@ var init_engine = __esm({
|
|
|
117711
119148
|
model: cycleErrorProvenance?.model ?? null,
|
|
117712
119149
|
modelSource: cycleErrorProvenance?.modelSource ?? null
|
|
117713
119150
|
});
|
|
119151
|
+
if (reportedRuntime !== null && Array.isArray(errorModelCalls) && errorModelCalls.length > 0) {
|
|
119152
|
+
cycleModelCallsReported = true;
|
|
119153
|
+
}
|
|
117714
119154
|
if (reportedRuntime?.runtime_recovery_blocked_source === "terminal_failure") {
|
|
117715
119155
|
this._scheduleRecoverableSuspendAfterExecutionLoop({
|
|
117716
119156
|
reason: "runtime_terminal_failure"
|
|
117717
119157
|
});
|
|
117718
119158
|
return;
|
|
117719
119159
|
}
|
|
119160
|
+
if (hasEventBoundProviderFailureEvidence(error48) && this._expectedExecutionMode === "server") {
|
|
119161
|
+
const backoffSeconds = Number((await this.getExecutionConfig(profileId).catch(() => null))?.provider_failure_backoff_seconds);
|
|
119162
|
+
if (Number.isFinite(backoffSeconds) && backoffSeconds > 0) providerRetryDelayMs = backoffSeconds * 1e3;
|
|
119163
|
+
}
|
|
117720
119164
|
if (hasEventBoundProviderFailureEvidence(error48)) {
|
|
117721
119165
|
this.scheduleProviderFailureDiagnosticsTelemetry({
|
|
117722
119166
|
profileId,
|
|
@@ -117730,6 +119174,18 @@ var init_engine = __esm({
|
|
|
117730
119174
|
});
|
|
117731
119175
|
}
|
|
117732
119176
|
} finally {
|
|
119177
|
+
this._checkOnlyCycleInFlight = false;
|
|
119178
|
+
if (!cycleModelCallsReported && cycleModelCalls.length > 0 && this._settleUnreportedModelCalls) {
|
|
119179
|
+
try {
|
|
119180
|
+
await this._settleUnreportedModelCalls(cycleModelCalls);
|
|
119181
|
+
} catch (error48) {
|
|
119182
|
+
appendRuntimeDebugEvent({
|
|
119183
|
+
label: "unreported_model_calls_settle_failed",
|
|
119184
|
+
note: getSanitizedRuntimeErrorMessage(error48) || "unknown",
|
|
119185
|
+
outcome: "error"
|
|
119186
|
+
});
|
|
119187
|
+
}
|
|
119188
|
+
}
|
|
117733
119189
|
if (!decisionSubmitted && pendingExternalInferenceBindings.length > 0) {
|
|
117734
119190
|
await Promise.allSettled(
|
|
117735
119191
|
pendingExternalInferenceBindings.map((binding) => cancelClientRuntimeInferenceJob(profileId, binding.job_id, {
|
|
@@ -117756,8 +119212,9 @@ var init_engine = __esm({
|
|
|
117756
119212
|
if (this._analysisRequestId === requestId) {
|
|
117757
119213
|
this._analysisRequestId = null;
|
|
117758
119214
|
this._analysisStartedAtMs = null;
|
|
119215
|
+
if (this._expectedExecutionMode === "server" && this._state === "running") void this.sendHeartbeat();
|
|
117759
119216
|
}
|
|
117760
|
-
const silentEmptyAgentPoll = cycleOutcome === "skipped" && cycleReason === "agent_instruction_poll_empty" && !cycleStartEmitted;
|
|
119217
|
+
const silentEmptyAgentPoll = cycleOutcome === "skipped" && (cycleReason === "agent_instruction_poll_empty" || cycleReason === "ai_schedule_paused" || cycleReason === "ai_schedule_check") && !cycleStartEmitted;
|
|
117761
119218
|
if (this._state === "running" && this._sessionId === sessionId) {
|
|
117762
119219
|
this._agentInstructionPollActive = agentPollDelayMs !== null;
|
|
117763
119220
|
}
|
|
@@ -117775,7 +119232,7 @@ var init_engine = __esm({
|
|
|
117775
119232
|
});
|
|
117776
119233
|
}
|
|
117777
119234
|
this._notifyListeners();
|
|
117778
|
-
if (this._periodicSchedule && agentPollDelayMs === null && !this._primaryAnalysisDisabled) {
|
|
119235
|
+
if (this._periodicSchedule && agentPollDelayMs === null && aiSchedulePauseMs === null && !this._primaryAnalysisDisabled) {
|
|
117779
119236
|
this._advanceNextRunAnchor();
|
|
117780
119237
|
}
|
|
117781
119238
|
if (!silentEmptyAgentPoll) this._emitLoopBoundaryTelemetry("client_timer_rearmed", "reason=cycle_finally", {
|
|
@@ -117784,11 +119241,18 @@ var init_engine = __esm({
|
|
|
117784
119241
|
primary_analysis_disabled: this._primaryAnalysisDisabled,
|
|
117785
119242
|
agent_poll_retry_ms: agentPollDelayMs
|
|
117786
119243
|
});
|
|
119244
|
+
const providerRetryWake = providerRetryDelayMs !== null && aiSchedulePauseMs === null && agentPollDelayMs === null && (this._nextRunAtMs == null || this._nextRunAtMs > Date.now() + providerRetryDelayMs) ? providerRetryDelayMs : null;
|
|
119245
|
+
if (providerRetryWake !== null) this._nextRunAtMs = Date.now() + providerRetryWake;
|
|
119246
|
+
const windowEndsAtMs = this._aiScheduleWindowEndsAtMs;
|
|
119247
|
+
const nextWorkAtMs = this._primaryAnalysisDisabled && this._loopIntervalMs != null ? Date.now() + this._loopIntervalMs : this._nextRunAtMs;
|
|
119248
|
+
const windowEndWake = aiSchedulePauseMs === null && agentPollDelayMs === null && providerRetryWake === null && windowEndsAtMs != null && windowEndsAtMs > Date.now() && (nextWorkAtMs == null || windowEndsAtMs < nextWorkAtMs) ? windowEndsAtMs - Date.now() : null;
|
|
119249
|
+
this._aiScheduleCheckPending = windowEndWake !== null;
|
|
119250
|
+
const manualRunWake = this._manualRunRequested ? 0 : null;
|
|
117787
119251
|
this._armExecutionLoopTimer({
|
|
117788
119252
|
alignToNextRun: agentPollDelayMs === null,
|
|
117789
|
-
delayOverrideMs: agentPollDelayMs,
|
|
117790
|
-
reason: agentPollDelayMs !== null ? "agent_instruction_poll" : this._primaryAnalysisDisabled ? "main_model_disabled_copy_poll" : "cycle_finally",
|
|
117791
|
-
suppressNextRunProjection: agentPollDelayMs === null && this._primaryAnalysisDisabled
|
|
119253
|
+
delayOverrideMs: manualRunWake ?? aiSchedulePauseMs ?? agentPollDelayMs ?? providerRetryWake ?? windowEndWake,
|
|
119254
|
+
reason: manualRunWake !== null ? "manual_run_requested" : aiSchedulePauseMs !== null ? "ai_schedule_paused" : agentPollDelayMs !== null ? "agent_instruction_poll" : providerRetryWake !== null ? "provider_failure_retry" : windowEndWake !== null ? "ai_schedule_window_end" : this._primaryAnalysisDisabled ? "main_model_disabled_copy_poll" : "cycle_finally",
|
|
119255
|
+
suppressNextRunProjection: aiSchedulePauseMs !== null && !aiSchedulePauseHasNext || agentPollDelayMs === null && aiSchedulePauseMs === null && this._primaryAnalysisDisabled
|
|
117792
119256
|
});
|
|
117793
119257
|
}
|
|
117794
119258
|
if (cycleOutcome === "unknown" && (analysisAbortController.signal.aborted || this._isStopping || this._state === "stopped")) {
|
|
@@ -118188,6 +119652,7 @@ var init_engine = __esm({
|
|
|
118188
119652
|
const heartbeatAnalysisRunId = this._primaryAnalysisDisabled || !this._isAnalysisInFlight() ? null : this._analysisRequestId;
|
|
118189
119653
|
const heartbeatIsAnalyzing = !this._primaryAnalysisDisabled && (this._isAnalysisInFlight() || this._startupPendingAnalysis && options?.confirmGrant !== true || this._isExecuting);
|
|
118190
119654
|
const heartbeatIsExecuting = this._isExecuting;
|
|
119655
|
+
const heartbeatObservedAtMs = Date.now();
|
|
118191
119656
|
const priorHeartbeatFailures = this._heartbeatFailures;
|
|
118192
119657
|
try {
|
|
118193
119658
|
const response = await sendClientRuntimeHeartbeat(heartbeatProfileId, {
|
|
@@ -118202,7 +119667,10 @@ var init_engine = __esm({
|
|
|
118202
119667
|
schedulerPhase: heartbeatSchedulerPhase,
|
|
118203
119668
|
analysisRunId: heartbeatAnalysisRunId,
|
|
118204
119669
|
isAnalyzing: heartbeatIsAnalyzing,
|
|
118205
|
-
isExecuting: heartbeatIsExecuting
|
|
119670
|
+
isExecuting: heartbeatIsExecuting,
|
|
119671
|
+
// Beats may arrive out of order: the server keeps a node bot's newest
|
|
119672
|
+
// analyzing observation, so a cycle's end is never undone by its start.
|
|
119673
|
+
...this._expectedExecutionMode === "server" ? { analyzingObservedAtMs: heartbeatObservedAtMs } : {}
|
|
118206
119674
|
});
|
|
118207
119675
|
if (Number(response.protective_actions_pending ?? 0) > 0) {
|
|
118208
119676
|
notifyClientProtectiveActionsPending(heartbeatProfileId);
|
|
@@ -118386,8 +119854,18 @@ var init_engine = __esm({
|
|
|
118386
119854
|
);
|
|
118387
119855
|
this._killswitchAbortController = null;
|
|
118388
119856
|
}
|
|
119857
|
+
/**
|
|
119858
|
+
* A Server Mode bot (the Node runtime host, executionMode 'server') has one
|
|
119859
|
+
* killswitch, the Python worker's risk monitor: it reads the bot's account,
|
|
119860
|
+
* stops the bot through its runtime contract and closes its positions even
|
|
119861
|
+
* while this process is down, so the runtime evaluates none here and reads
|
|
119862
|
+
* no account for it.
|
|
119863
|
+
*/
|
|
119864
|
+
_ownsKillswitch() {
|
|
119865
|
+
return this._expectedExecutionMode !== "server";
|
|
119866
|
+
}
|
|
118389
119867
|
async _startClientKillswitchMonitor(startController) {
|
|
118390
|
-
if (this._mode !== "trader" || !this._profileId) {
|
|
119868
|
+
if (this._mode !== "trader" || !this._profileId || !this._ownsKillswitch()) {
|
|
118391
119869
|
return;
|
|
118392
119870
|
}
|
|
118393
119871
|
const configPromise = this.getExecutionConfig(this._profileId);
|
|
@@ -118414,7 +119892,7 @@ var init_engine = __esm({
|
|
|
118414
119892
|
);
|
|
118415
119893
|
}
|
|
118416
119894
|
async _runClientKillswitchCheck() {
|
|
118417
|
-
if (this._state !== "running" || this._mode !== "trader" || this._killswitchLatched || this._killswitchCheckInFlight || !this._profileId || !this._sessionId || !this._deviceId) {
|
|
119895
|
+
if (!this._ownsKillswitch() || this._state !== "running" || this._mode !== "trader" || this._killswitchLatched || this._killswitchCheckInFlight || !this._profileId || !this._sessionId || !this._deviceId) {
|
|
118418
119896
|
return;
|
|
118419
119897
|
}
|
|
118420
119898
|
const profileId = this._profileId;
|
|
@@ -118730,6 +120208,9 @@ var init_engine = __esm({
|
|
|
118730
120208
|
return config2;
|
|
118731
120209
|
}
|
|
118732
120210
|
async _processClientCopyTrading(input) {
|
|
120211
|
+
if (this._expectedExecutionMode === "server") {
|
|
120212
|
+
return;
|
|
120213
|
+
}
|
|
118733
120214
|
try {
|
|
118734
120215
|
const persistedLease = getPersistedClientRuntimeServerLease(input.profileId);
|
|
118735
120216
|
const runtimeLeaseToken = persistedLease?.runtimeSessionId === input.runtimeSessionId && persistedLease.deviceId === input.runtimeDeviceId && persistedLease.mode === "trader" ? persistedLease.runtimeLeaseToken : null;
|
|
@@ -119200,8 +120681,8 @@ var init_engine = __esm({
|
|
|
119200
120681
|
if (!normalized) return false;
|
|
119201
120682
|
return this._getEngine(normalized, false)?.updateLoopInterval(options) ?? false;
|
|
119202
120683
|
}
|
|
119203
|
-
async triggerNow() {
|
|
119204
|
-
await this._getSelectedEngine()?.triggerNow();
|
|
120684
|
+
async triggerNow(options) {
|
|
120685
|
+
await this._getSelectedEngine()?.triggerNow(options);
|
|
119205
120686
|
}
|
|
119206
120687
|
async triggerProfileNow(profileId) {
|
|
119207
120688
|
const normalized = this._normalizeProfileId(profileId);
|
|
@@ -119620,7 +121101,7 @@ async function runHeadlessRuntime(options) {
|
|
|
119620
121101
|
const firstAttached = () => {
|
|
119621
121102
|
const stopSweep = startServerProtectionSweeper(options, { ...identity2, schedulerInstanceId: engine.schedulerInstanceId });
|
|
119622
121103
|
if (options.once && engine.state === "running" && !engine.snapshot.isAnalyzing) {
|
|
119623
|
-
void engine.triggerNow().catch(() => void 0);
|
|
121104
|
+
void engine.triggerNow({ ignoreAiSchedule: false }).catch(() => void 0);
|
|
119624
121105
|
}
|
|
119625
121106
|
return stopSweep;
|
|
119626
121107
|
};
|