@vtxmacro/cli 2026.10.6 → 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 +2097 -659
- 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) => {
|
|
@@ -50092,7 +50126,7 @@ function getProfileHeaders(baseHeaders = {}, explicitProfileId) {
|
|
|
50092
50126
|
if (profileId) headers["x-profile-id"] = profileId.toString();
|
|
50093
50127
|
return headers;
|
|
50094
50128
|
}
|
|
50095
|
-
var configuredApiTransport, getApiUrl, apiFetch, sleep, inFlightClientGetRequests, recentClientGetResponses, clientGetRequestGenerations, initializedClientGetRequestKeys, CLIENT_GET_DEDUPE_TTL_MS,
|
|
50129
|
+
var configuredApiTransport, getApiUrl, apiFetch, sleep, inFlightClientGetRequests, recentClientGetResponses, clientGetRequestGenerations, initializedClientGetRequestKeys, CLIENT_GET_DEDUPE_TTL_MS, CLIENT_LLM_CONFIG_PRIME_TTL_MS, AUTH_BOOTSTRAP_GET_MAX_ATTEMPTS, AUTH_BOOTSTRAP_RETRY_JITTER_MS, canUseClientGetRequestCache, invalidateClientGetRequestCache, raceWithAbortSignal, shareClientGetRequest, clientGetRequestKey, clientPreferencesRequestKey, invalidateClientPreferencesCache, parseRetryAfterMs2, resolveAuthBootstrapRetryDelayMs, fetchAuthBootstrapGetWithRetry, annotateMarketDataRequestError, buildMarketDataFetchError, buildMarketDataNetworkError, buildMarketDataResponseBodyError, isTransientNetworkFetchError, createIdempotencyKey, getErrorMessage, getErrorPayloadOrEmpty, getErrorPayloadOrFallbackDetail, getErrorMessageFromResponse, throwUnauthorizedIfNeeded, activeProfileId, PROFILE_STORAGE_KEY;
|
|
50096
50130
|
var init_shared = __esm({
|
|
50097
50131
|
"lib/api/shared.ts"() {
|
|
50098
50132
|
"use strict";
|
|
@@ -50132,7 +50166,6 @@ var init_shared = __esm({
|
|
|
50132
50166
|
clientGetRequestGenerations = /* @__PURE__ */ new Map();
|
|
50133
50167
|
initializedClientGetRequestKeys = /* @__PURE__ */ new Set();
|
|
50134
50168
|
CLIENT_GET_DEDUPE_TTL_MS = 2e3;
|
|
50135
|
-
CLIENT_RUNTIME_STATUSES_DEDUPE_TTL_MS = 5e3;
|
|
50136
50169
|
CLIENT_LLM_CONFIG_PRIME_TTL_MS = 1e4;
|
|
50137
50170
|
AUTH_BOOTSTRAP_GET_MAX_ATTEMPTS = runtime_policy_generated_default2.ui.auth_bootstrap_retry.max_attempts;
|
|
50138
50171
|
AUTH_BOOTSTRAP_RETRY_JITTER_MS = runtime_policy_generated_default2.ui.auth_bootstrap_retry.jitter_milliseconds;
|
|
@@ -50233,7 +50266,7 @@ var init_shared = __esm({
|
|
|
50233
50266
|
runtimeRequestErrorKind: kind,
|
|
50234
50267
|
runtimeRequestTransientNetwork: kind === "network" && isTransientNetworkFetchError(error48)
|
|
50235
50268
|
});
|
|
50236
|
-
buildMarketDataFetchError = async (response,
|
|
50269
|
+
buildMarketDataFetchError = async (response, label2, path) => {
|
|
50237
50270
|
let responseText = "";
|
|
50238
50271
|
try {
|
|
50239
50272
|
responseText = (await response.clone().text()).trim();
|
|
@@ -50243,21 +50276,21 @@ var init_shared = __esm({
|
|
|
50243
50276
|
const statusText = response.statusText ? ` ${response.statusText}` : "";
|
|
50244
50277
|
const detail = responseText ? `: ${responseText.slice(0, 240)}` : "";
|
|
50245
50278
|
return annotateMarketDataRequestError(
|
|
50246
|
-
new Error(`Market data request failed: ${
|
|
50279
|
+
new Error(`Market data request failed: ${label2} unavailable (HTTP ${response.status}${statusText})${detail}`),
|
|
50247
50280
|
path,
|
|
50248
50281
|
response.status,
|
|
50249
50282
|
"http"
|
|
50250
50283
|
);
|
|
50251
50284
|
};
|
|
50252
|
-
buildMarketDataNetworkError = (error48,
|
|
50285
|
+
buildMarketDataNetworkError = (error48, label2, path) => {
|
|
50253
50286
|
const message = error48 instanceof Error ? error48.message : String(error48 || "unknown error");
|
|
50254
50287
|
return annotateMarketDataRequestError(Object.assign(
|
|
50255
|
-
new Error(`Market data request failed: ${
|
|
50288
|
+
new Error(`Market data request failed: ${label2} network error (${message})`),
|
|
50256
50289
|
{ cause: error48, name: error48 instanceof Error ? error48.name : "Error" }
|
|
50257
50290
|
), path, null, "network");
|
|
50258
50291
|
};
|
|
50259
|
-
buildMarketDataResponseBodyError = (error48,
|
|
50260
|
-
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})`),
|
|
50261
50294
|
{ cause: error48, name: error48 instanceof Error ? error48.name : "Error" }
|
|
50262
50295
|
), path, response.status, "response_body");
|
|
50263
50296
|
isTransientNetworkFetchError = (error48) => {
|
|
@@ -51172,10 +51205,10 @@ var init_network_debug = __esm({
|
|
|
51172
51205
|
};
|
|
51173
51206
|
getLatestRuntimeProviderFailureTelemetrySnapshot = (options = {}) => {
|
|
51174
51207
|
const maxAgeMs = Number.isFinite(Number(options.maxAgeMs)) ? Math.max(0, Number(options.maxAgeMs)) : 5 * 60 * 1e3;
|
|
51175
|
-
const
|
|
51208
|
+
const label2 = typeof options.label === "string" && options.label.trim() ? options.label.trim().toLowerCase() : null;
|
|
51176
51209
|
const traceId = typeof options.traceId === "string" && options.traceId.trim() ? options.traceId.trim() : null;
|
|
51177
51210
|
const now = Date.now();
|
|
51178
|
-
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));
|
|
51179
51212
|
const latest = candidates[0] ?? null;
|
|
51180
51213
|
if (!latest) {
|
|
51181
51214
|
return null;
|
|
@@ -52073,6 +52106,288 @@ var init_server_runtime_lease = __esm({
|
|
|
52073
52106
|
}
|
|
52074
52107
|
});
|
|
52075
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
|
+
|
|
52076
52391
|
// lib/runtime/order-identity.ts
|
|
52077
52392
|
var clientOrderIdForMutation, clientDecisionMutationId;
|
|
52078
52393
|
var init_order_identity = __esm({
|
|
@@ -52148,7 +52463,7 @@ var init_hyperliquid_order_status = __esm({
|
|
|
52148
52463
|
});
|
|
52149
52464
|
|
|
52150
52465
|
// lib/runtime/hyperliquid-public-read.ts
|
|
52151
|
-
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;
|
|
52152
52467
|
var init_hyperliquid_public_read = __esm({
|
|
52153
52468
|
"lib/runtime/hyperliquid-public-read.ts"() {
|
|
52154
52469
|
"use strict";
|
|
@@ -52172,6 +52487,7 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52172
52487
|
scope.value = priority;
|
|
52173
52488
|
scope.followers?.forEach((promote) => promote(priority));
|
|
52174
52489
|
};
|
|
52490
|
+
hostTransport = null;
|
|
52175
52491
|
abortError2 = (signal) => getSanitizedRuntimeAbortReason(signal, "Aborted");
|
|
52176
52492
|
checkAbort = (signal) => {
|
|
52177
52493
|
if (signal?.aborted) throw abortError2(signal);
|
|
@@ -52309,6 +52625,10 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52309
52625
|
const weight = weightOverride ?? weights[requestType] ?? policy.default_request_weight;
|
|
52310
52626
|
const ticket = crypto.randomUUID();
|
|
52311
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
|
+
}
|
|
52312
52632
|
let admitted = false;
|
|
52313
52633
|
try {
|
|
52314
52634
|
for (; ; ) {
|
|
@@ -52379,7 +52699,11 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52379
52699
|
});
|
|
52380
52700
|
}
|
|
52381
52701
|
};
|
|
52382
|
-
cooldown = async (apiUrl, retryAfter) => {
|
|
52702
|
+
cooldown = async (apiUrl, retryAfter, requestType) => {
|
|
52703
|
+
if (hostTransport) {
|
|
52704
|
+
await hostTransport.admission.record429(retryAfter, requestType);
|
|
52705
|
+
return;
|
|
52706
|
+
}
|
|
52383
52707
|
const key = `${PREFIX}${apiUrl}`;
|
|
52384
52708
|
await withBudgetLock(key, void 0, () => {
|
|
52385
52709
|
const now = Date.now();
|
|
@@ -52405,6 +52729,11 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52405
52729
|
};
|
|
52406
52730
|
finishHyperliquidRecoveryRequest = async (permit, outcome) => {
|
|
52407
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
|
+
}
|
|
52408
52737
|
const key = `${PREFIX}${permit.endpoint}`;
|
|
52409
52738
|
await withBudgetLock(key, void 0, () => {
|
|
52410
52739
|
const budget = loadBudget(key);
|
|
@@ -52441,6 +52770,15 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52441
52770
|
}
|
|
52442
52771
|
if (!permit && budget.recovery) throw recoveryWaitError(requestType);
|
|
52443
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
|
+
};
|
|
52444
52782
|
cacheTtlMs = (body, options) => {
|
|
52445
52783
|
const requestType = String(body.type);
|
|
52446
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;
|
|
@@ -52470,7 +52808,7 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52470
52808
|
return admit(endpoint.replace(/\/$/, ""), "exchange", signal, weight, void 0, createHyperliquidPublicPriorityScope(priority));
|
|
52471
52809
|
};
|
|
52472
52810
|
recordHyperliquidExchangeResponse = async (endpoint, response, permit) => {
|
|
52473
|
-
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");
|
|
52474
52812
|
await finishHyperliquidRecoveryRequest(permit, response.status < 400 ? "success" : "failure");
|
|
52475
52813
|
};
|
|
52476
52814
|
readHyperliquidPublicInfo = async (endpoint, body, options) => {
|
|
@@ -52504,6 +52842,7 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52504
52842
|
let settled;
|
|
52505
52843
|
let acquiring = false;
|
|
52506
52844
|
let observedRateLimit;
|
|
52845
|
+
let privateRouteUsed = false;
|
|
52507
52846
|
let pendingPhase = null;
|
|
52508
52847
|
const setPendingPhase = (next) => {
|
|
52509
52848
|
if (next === pendingPhase) return;
|
|
@@ -52548,14 +52887,18 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52548
52887
|
}), priority });
|
|
52549
52888
|
}
|
|
52550
52889
|
if (options.reservation?.closed) throw new DOMException("Hyperliquid account read was cancelled.", "AbortError");
|
|
52551
|
-
|
|
52552
|
-
|
|
52553
|
-
|
|
52554
|
-
|
|
52555
|
-
|
|
52556
|
-
|
|
52557
|
-
|
|
52558
|
-
|
|
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
|
+
}
|
|
52559
52902
|
outcome = "failure";
|
|
52560
52903
|
let transportAborted;
|
|
52561
52904
|
let response;
|
|
@@ -52568,16 +52911,16 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52568
52911
|
});
|
|
52569
52912
|
const transport = (async () => {
|
|
52570
52913
|
setPendingPhase("transport");
|
|
52571
|
-
const received = await fetch(`${apiUrl}/info`, {
|
|
52914
|
+
const received = await fetch(`${privateRoute?.url.replace(/\/$/, "") ?? apiUrl}/info`, {
|
|
52572
52915
|
method: "POST",
|
|
52573
|
-
headers: { "Content-Type": "application/json" },
|
|
52916
|
+
headers: { ...privateRoute?.headers, "Content-Type": "application/json" },
|
|
52574
52917
|
body: JSON.stringify(body),
|
|
52575
52918
|
signal
|
|
52576
52919
|
});
|
|
52577
52920
|
checkAbort(signal);
|
|
52578
52921
|
if (received.status === 429) {
|
|
52579
52922
|
observedRateLimit = new HyperliquidPublicReadError("public_rate_limited", "Hyperliquid public API returned HTTP 429.", requestType, 429);
|
|
52580
|
-
await cooldown(apiUrl, received.headers.get("Retry-After"));
|
|
52923
|
+
if (!privateRoute) await cooldown(apiUrl, received.headers.get("Retry-After"), requestType);
|
|
52581
52924
|
throw observedRateLimit;
|
|
52582
52925
|
}
|
|
52583
52926
|
let receivedText;
|
|
@@ -52624,6 +52967,13 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52624
52967
|
outcome = "cancelled";
|
|
52625
52968
|
throw abortError2(options.signal);
|
|
52626
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
|
+
}
|
|
52627
52977
|
if (acquiring && signal.aborted && signal.reason?.name === "TimeoutError") throw recoveryWaitError(requestType);
|
|
52628
52978
|
if (error48 instanceof HyperliquidPublicReadError) throw error48;
|
|
52629
52979
|
if (error48 instanceof TypeError) throw new HyperliquidPublicReadError("public_network_error", "Hyperliquid public request network failure.", requestType);
|
|
@@ -52647,6 +52997,32 @@ var init_hyperliquid_public_read = __esm({
|
|
|
52647
52997
|
}
|
|
52648
52998
|
});
|
|
52649
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
|
+
|
|
52650
53026
|
// lib/runtime/hyperliquid-market-symbol.ts
|
|
52651
53027
|
var configuredCaseSensitiveSymbols, isHyperliquidSpotSymbol, normalizeCaseSensitiveSymbols, configureHyperliquidMarketSymbolCasing, canonicalBaseSymbol, normalizeHyperliquidMarketSymbol, getHyperliquidMarketDex;
|
|
52652
53028
|
var init_hyperliquid_market_symbol = __esm({
|
|
@@ -54092,7 +54468,7 @@ function getNumber(value, name) {
|
|
|
54092
54468
|
}
|
|
54093
54469
|
assertArgument(false, "invalid numeric value", name || "value", value);
|
|
54094
54470
|
}
|
|
54095
|
-
function
|
|
54471
|
+
function toNumber2(value) {
|
|
54096
54472
|
return getNumber(toBigInt(value));
|
|
54097
54473
|
}
|
|
54098
54474
|
function toBeHex(_value, _width) {
|
|
@@ -56514,7 +56890,7 @@ var init_abstract_coder = __esm({
|
|
|
56514
56890
|
return toBigInt(this.readBytes(WordSize));
|
|
56515
56891
|
}
|
|
56516
56892
|
readIndex() {
|
|
56517
|
-
return
|
|
56893
|
+
return toNumber2(this.readBytes(WordSize));
|
|
56518
56894
|
}
|
|
56519
56895
|
};
|
|
56520
56896
|
}
|
|
@@ -63802,8 +64178,8 @@ function split2(name, nf, ef) {
|
|
|
63802
64178
|
if (!name) return [];
|
|
63803
64179
|
init();
|
|
63804
64180
|
let offset = 0;
|
|
63805
|
-
return name.split(STOP_CH).map((
|
|
63806
|
-
let input = explode_cp(
|
|
64181
|
+
return name.split(STOP_CH).map((label2) => {
|
|
64182
|
+
let input = explode_cp(label2);
|
|
63807
64183
|
let info = {
|
|
63808
64184
|
input,
|
|
63809
64185
|
offset
|
|
@@ -69478,8 +69854,8 @@ var init_contract = __esm({
|
|
|
69478
69854
|
}
|
|
69479
69855
|
const { subs } = getInternal(this);
|
|
69480
69856
|
let total = 0;
|
|
69481
|
-
for (const { listeners:
|
|
69482
|
-
total +=
|
|
69857
|
+
for (const { listeners: listeners3 } of subs.values()) {
|
|
69858
|
+
total += listeners3.length;
|
|
69483
69859
|
}
|
|
69484
69860
|
return total;
|
|
69485
69861
|
}
|
|
@@ -69497,8 +69873,8 @@ var init_contract = __esm({
|
|
|
69497
69873
|
}
|
|
69498
69874
|
const { subs } = getInternal(this);
|
|
69499
69875
|
let result = [];
|
|
69500
|
-
for (const { listeners:
|
|
69501
|
-
result = result.concat(
|
|
69876
|
+
for (const { listeners: listeners3 } of subs.values()) {
|
|
69877
|
+
result = result.concat(listeners3.map(({ listener }) => listener));
|
|
69502
69878
|
}
|
|
69503
69879
|
return result;
|
|
69504
69880
|
}
|
|
@@ -72335,8 +72711,8 @@ var init_abstract_provider = __esm({
|
|
|
72335
72711
|
return sub.listeners.length;
|
|
72336
72712
|
}
|
|
72337
72713
|
let total = 0;
|
|
72338
|
-
for (const { listeners:
|
|
72339
|
-
total +=
|
|
72714
|
+
for (const { listeners: listeners3 } of this.#subs.values()) {
|
|
72715
|
+
total += listeners3.length;
|
|
72340
72716
|
}
|
|
72341
72717
|
return total;
|
|
72342
72718
|
}
|
|
@@ -72349,8 +72725,8 @@ var init_abstract_provider = __esm({
|
|
|
72349
72725
|
return sub.listeners.map(({ listener }) => listener);
|
|
72350
72726
|
}
|
|
72351
72727
|
let result = [];
|
|
72352
|
-
for (const { listeners:
|
|
72353
|
-
result = result.concat(
|
|
72728
|
+
for (const { listeners: listeners3 } of this.#subs.values()) {
|
|
72729
|
+
result = result.concat(listeners3.map(({ listener }) => listener));
|
|
72354
72730
|
}
|
|
72355
72731
|
return result;
|
|
72356
72732
|
}
|
|
@@ -82951,7 +83327,7 @@ __export(ethers_exports, {
|
|
|
82951
83327
|
toBeArray: () => toBeArray,
|
|
82952
83328
|
toBeHex: () => toBeHex,
|
|
82953
83329
|
toBigInt: () => toBigInt,
|
|
82954
|
-
toNumber: () =>
|
|
83330
|
+
toNumber: () => toNumber2,
|
|
82955
83331
|
toQuantity: () => toQuantity,
|
|
82956
83332
|
toTwos: () => toTwos,
|
|
82957
83333
|
toUtf8Bytes: () => toUtf8Bytes,
|
|
@@ -83169,7 +83545,7 @@ __export(lib_exports, {
|
|
|
83169
83545
|
toBeArray: () => toBeArray,
|
|
83170
83546
|
toBeHex: () => toBeHex,
|
|
83171
83547
|
toBigInt: () => toBigInt,
|
|
83172
|
-
toNumber: () =>
|
|
83548
|
+
toNumber: () => toNumber2,
|
|
83173
83549
|
toQuantity: () => toQuantity,
|
|
83174
83550
|
toTwos: () => toTwos,
|
|
83175
83551
|
toUtf8Bytes: () => toUtf8Bytes,
|
|
@@ -83872,9 +84248,9 @@ var init_hyperliquid_signer = __esm({
|
|
|
83872
84248
|
{ name: "connectionId", type: "bytes32" }
|
|
83873
84249
|
]
|
|
83874
84250
|
};
|
|
83875
|
-
assertUint64 = (value,
|
|
84251
|
+
assertUint64 = (value, label2) => {
|
|
83876
84252
|
if (!Number.isInteger(value) || value < 0) {
|
|
83877
|
-
throw new Error(`${
|
|
84253
|
+
throw new Error(`${label2} must be a non-negative integer.`);
|
|
83878
84254
|
}
|
|
83879
84255
|
};
|
|
83880
84256
|
concatBytes3 = (...parts) => {
|
|
@@ -83899,10 +84275,10 @@ var init_hyperliquid_signer = __esm({
|
|
|
83899
84275
|
}
|
|
83900
84276
|
return bytes3;
|
|
83901
84277
|
};
|
|
83902
|
-
hexToBytes2 = (value,
|
|
84278
|
+
hexToBytes2 = (value, label2) => {
|
|
83903
84279
|
const normalized = value.trim().replace(/^0x/i, "");
|
|
83904
84280
|
if (!normalized || normalized.length % 2 !== 0 || /[^0-9a-f]/i.test(normalized)) {
|
|
83905
|
-
throw new Error(`Invalid ${
|
|
84281
|
+
throw new Error(`Invalid ${label2}.`);
|
|
83906
84282
|
}
|
|
83907
84283
|
const bytes3 = new Uint8Array(normalized.length / 2);
|
|
83908
84284
|
for (let index = 0; index < normalized.length; index += 2) {
|
|
@@ -84131,19 +84507,21 @@ var init_hyperliquid_signer = __esm({
|
|
|
84131
84507
|
});
|
|
84132
84508
|
|
|
84133
84509
|
// lib/runtime/hyperliquid-client.ts
|
|
84134
|
-
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;
|
|
84135
84511
|
var init_hyperliquid_client = __esm({
|
|
84136
84512
|
"lib/runtime/hyperliquid-client.ts"() {
|
|
84137
84513
|
"use strict";
|
|
84138
84514
|
init_define_VTX_EXO_POLICY();
|
|
84139
84515
|
init_define_VTX_GROK_POLICY();
|
|
84140
84516
|
init_define_VTX_PI_MODEL_POLICY();
|
|
84517
|
+
init_hyperliquid_account_contract();
|
|
84141
84518
|
init_order_identity();
|
|
84142
84519
|
init_hyperliquid_order_status();
|
|
84143
84520
|
init_runtime_policy_generated2();
|
|
84144
84521
|
init_hyperliquid_public_read();
|
|
84145
84522
|
init_api2();
|
|
84146
84523
|
init_abort();
|
|
84524
|
+
init_hyperliquid_exchange_rejections();
|
|
84147
84525
|
init_hyperliquid_market_symbol();
|
|
84148
84526
|
init_network_debug();
|
|
84149
84527
|
init_runtime_redaction();
|
|
@@ -84238,6 +84616,14 @@ var init_hyperliquid_client = __esm({
|
|
|
84238
84616
|
coordinator.write?.(lastGeneratedNonce);
|
|
84239
84617
|
return lastGeneratedNonce;
|
|
84240
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
|
+
};
|
|
84241
84627
|
generateHyperliquidNonce = async (coordinator) => {
|
|
84242
84628
|
const resolvedCoordinator = coordinator ?? browserNonceCoordinator();
|
|
84243
84629
|
if (resolvedCoordinator.withLock) {
|
|
@@ -84363,12 +84749,12 @@ var init_hyperliquid_client = __esm({
|
|
|
84363
84749
|
throw new Error("Missing client runtime Hyperliquid API URL.");
|
|
84364
84750
|
};
|
|
84365
84751
|
inferIsTestnet = (apiUrl) => apiUrl.toLowerCase().includes("testnet");
|
|
84366
|
-
postHyperliquidInfoRead = async (input, body,
|
|
84752
|
+
postHyperliquidInfoRead = async (input, body, label2, includeBodyText = false) => {
|
|
84367
84753
|
const apiUrl = inferApiUrl(input);
|
|
84368
84754
|
const requestUrl = `${apiUrl.replace(/\/$/, "")}/info`;
|
|
84369
84755
|
const trace = startRuntimeNetworkDebugTrace({
|
|
84370
84756
|
kind: "exchange",
|
|
84371
|
-
label,
|
|
84757
|
+
label: label2,
|
|
84372
84758
|
method: "POST",
|
|
84373
84759
|
url: requestUrl
|
|
84374
84760
|
});
|
|
@@ -84386,10 +84772,10 @@ var init_hyperliquid_client = __esm({
|
|
|
84386
84772
|
throw sanitizedError;
|
|
84387
84773
|
}
|
|
84388
84774
|
};
|
|
84389
|
-
postHyperliquidInfo = async (input, body,
|
|
84390
|
-
fetchBrowserHyperliquidInfoPayload = (input, body,
|
|
84391
|
-
fetchBrowserHyperliquidInfoText = async (input, body,
|
|
84392
|
-
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);
|
|
84393
84779
|
if (typeof bodyText !== "string") throw new Error("Hyperliquid returned no response text.");
|
|
84394
84780
|
return bodyText;
|
|
84395
84781
|
};
|
|
@@ -84559,14 +84945,14 @@ var init_hyperliquid_client = __esm({
|
|
|
84559
84945
|
}
|
|
84560
84946
|
return normalized;
|
|
84561
84947
|
};
|
|
84562
|
-
assertPositiveInteger = (value,
|
|
84948
|
+
assertPositiveInteger = (value, label2) => {
|
|
84563
84949
|
if (!Number.isInteger(value) || value <= 0) {
|
|
84564
|
-
throw new Error(`${
|
|
84950
|
+
throw new Error(`${label2} must be a positive integer.`);
|
|
84565
84951
|
}
|
|
84566
84952
|
};
|
|
84567
|
-
assertPositiveNumber = (value,
|
|
84953
|
+
assertPositiveNumber = (value, label2) => {
|
|
84568
84954
|
if (!Number.isFinite(value) || value <= 0) {
|
|
84569
|
-
throw new Error(`${
|
|
84955
|
+
throw new Error(`${label2} must be a positive number.`);
|
|
84570
84956
|
}
|
|
84571
84957
|
};
|
|
84572
84958
|
normalizeOrderSide = (value) => {
|
|
@@ -84703,6 +85089,17 @@ var init_hyperliquid_client = __esm({
|
|
|
84703
85089
|
const units = decimalUnits(value, decimals, roundingMode);
|
|
84704
85090
|
return units / 10 ** decimals;
|
|
84705
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
|
+
};
|
|
84706
85103
|
finitePositive = (value) => {
|
|
84707
85104
|
const parsed = Number(value);
|
|
84708
85105
|
return typeof value !== "boolean" && value !== null && value !== "" && Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
@@ -85211,7 +85608,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85211
85608
|
accountSummary: {
|
|
85212
85609
|
account_value: accountValue,
|
|
85213
85610
|
total_margin_used: totalMarginUsed,
|
|
85214
|
-
available_margin:
|
|
85611
|
+
available_margin: canonicalAvailableMargin(accountValue, totalMarginUsed),
|
|
85215
85612
|
withdrawable,
|
|
85216
85613
|
cross_margin_ratio: accountValue > 0 ? maintenanceMargin / accountValue : 0,
|
|
85217
85614
|
maintenance_margin: maintenanceMargin,
|
|
@@ -85232,7 +85629,8 @@ var init_hyperliquid_client = __esm({
|
|
|
85232
85629
|
buildHyperliquidOrderWire = async (input, tif, price, priceKind) => {
|
|
85233
85630
|
const { asset_index: assetIndex, sz_decimals: sizeDecimals } = await resolveHyperliquidAsset(input);
|
|
85234
85631
|
const side = normalizeOrderSide(input.side);
|
|
85235
|
-
|
|
85632
|
+
assertPositiveNumber(input.size, "Hyperliquid order size");
|
|
85633
|
+
const roundedSize = quantizeHyperliquidOrderSizeValue(input.size, sizeDecimals, "nearest");
|
|
85236
85634
|
assertPositiveNumber(roundedSize, "Hyperliquid order size");
|
|
85237
85635
|
const priceWire = formatHyperliquidOrderPriceWire(price, sizeDecimals, side, priceKind);
|
|
85238
85636
|
const sizeWire = formatSizeWire(roundedSize, sizeDecimals);
|
|
@@ -85260,7 +85658,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85260
85658
|
assertPositiveNumber(input.limitPrice, "Hyperliquid trigger limit price");
|
|
85261
85659
|
const { asset_index: assetIndex, sz_decimals: sizeDecimals } = await resolveHyperliquidAsset(input);
|
|
85262
85660
|
const side = normalizeOrderSide(input.side);
|
|
85263
|
-
const roundedSize =
|
|
85661
|
+
const roundedSize = quantizeHyperliquidOrderSizeValue(input.size, sizeDecimals, "nearest");
|
|
85264
85662
|
assertPositiveNumber(roundedSize, "Hyperliquid trigger order size");
|
|
85265
85663
|
const triggerPriceWire = formatHyperliquidTriggerPriceWire(input.triggerPrice, sizeDecimals);
|
|
85266
85664
|
const limitPriceWire = input.limitPrice === input.triggerPrice ? triggerPriceWire : formatHyperliquidOrderPriceWire(input.limitPrice, sizeDecimals, side, "limit");
|
|
@@ -85296,7 +85694,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85296
85694
|
signHyperliquidPayload = async (input, action) => {
|
|
85297
85695
|
const apiUrl = inferApiUrl(input);
|
|
85298
85696
|
const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
|
|
85299
|
-
const nonce = input.nonce ?? await
|
|
85697
|
+
const nonce = input.nonce ?? await allocateActionNonce(input, apiUrl);
|
|
85300
85698
|
const expiresAfter = input.expiresAfterSeconds == null ? null : nonce + input.expiresAfterSeconds * 1e3;
|
|
85301
85699
|
const signed2 = await signHyperliquidAction2({
|
|
85302
85700
|
privateKey: input.signingKey,
|
|
@@ -85320,7 +85718,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85320
85718
|
}
|
|
85321
85719
|
const apiUrl = inferApiUrl(input);
|
|
85322
85720
|
const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
|
|
85323
|
-
const nonce = await
|
|
85721
|
+
const nonce = await allocateActionNonce(input, apiUrl);
|
|
85324
85722
|
const expiresAfter = nonce + input.expiresAfterSeconds * 1e3;
|
|
85325
85723
|
const signed2 = await signHyperliquidAction2({
|
|
85326
85724
|
privateKey: input.signingKey,
|
|
@@ -85348,7 +85746,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85348
85746
|
const apiUrl = inferApiUrl(input);
|
|
85349
85747
|
const assetIndex = await resolveHyperliquidAssetIndex(input);
|
|
85350
85748
|
const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
|
|
85351
|
-
const nonce = input.nonce ?? await
|
|
85749
|
+
const nonce = input.nonce ?? await allocateActionNonce(input, apiUrl);
|
|
85352
85750
|
const expiresAfter = input.expiresAfterSeconds == null ? null : nonce + input.expiresAfterSeconds * 1e3;
|
|
85353
85751
|
const action = clientOrderId != null ? {
|
|
85354
85752
|
type: "cancelByCloid",
|
|
@@ -85378,7 +85776,7 @@ var init_hyperliquid_client = __esm({
|
|
|
85378
85776
|
const apiUrl = inferApiUrl(input);
|
|
85379
85777
|
const asset = await resolveHyperliquidAsset(input);
|
|
85380
85778
|
const { signHyperliquidAction: signHyperliquidAction2 } = await Promise.resolve().then(() => (init_hyperliquid_signer(), hyperliquid_signer_exports));
|
|
85381
|
-
const nonce = input.nonce ?? await
|
|
85779
|
+
const nonce = input.nonce ?? await allocateActionNonce(input, apiUrl);
|
|
85382
85780
|
const expiresAfter = input.expiresAfterSeconds == null ? null : nonce + input.expiresAfterSeconds * 1e3;
|
|
85383
85781
|
const leverage = Math.max(1, Math.min(asset.max_leverage, Math.trunc(input.leverage)));
|
|
85384
85782
|
const isCross = isExchangeIsolatedOnly(asset) ? false : input.isCross !== false;
|
|
@@ -86205,7 +86603,7 @@ var init_hyperliquid_client = __esm({
|
|
|
86205
86603
|
try {
|
|
86206
86604
|
recoveryPermit = await admitHyperliquidExchangeRequest(apiUrl, input.payload.action, input.signal, input.publicRequestPriority);
|
|
86207
86605
|
assertFreshPreparedExecutionContext(input.preparedContext);
|
|
86208
|
-
|
|
86606
|
+
await validateHyperliquidRecoveryDispatch(apiUrl, recoveryPermit, "exchange");
|
|
86209
86607
|
} catch (preparedContextError) {
|
|
86210
86608
|
await settleDurableMutation("rejected");
|
|
86211
86609
|
if (isAbortLikeError(preparedContextError) || preparedContextError instanceof HyperliquidPublicReadError) throw preparedContextError;
|
|
@@ -86296,6 +86694,7 @@ var init_hyperliquid_client = __esm({
|
|
|
86296
86694
|
}
|
|
86297
86695
|
const exchangeError = extractHyperliquidExchangeError(payload);
|
|
86298
86696
|
if (exchangeError) {
|
|
86697
|
+
emitHyperliquidExchangeRejection(String(exchangeError.message ?? ""));
|
|
86299
86698
|
await settleDurableMutation(
|
|
86300
86699
|
exchangeError.partial ? "transport_ambiguous" : "rejected",
|
|
86301
86700
|
null,
|
|
@@ -86914,7 +87313,8 @@ async function postClientRuntime(path, profileId, body, options) {
|
|
|
86914
87313
|
const payload = await response.json();
|
|
86915
87314
|
persistRuntimeLeaseFromPayload(payload);
|
|
86916
87315
|
persistRuntimeLeaseStatusMetadata(numericProfileId, payload);
|
|
86917
|
-
|
|
87316
|
+
const stopStatus = payload?.status;
|
|
87317
|
+
if (path === "/runtime/session/stop" && stopStatus !== "preserved" && stopStatus !== "not_owner") {
|
|
86918
87318
|
clearPersistedClientRuntimeServerLease(numericProfileId);
|
|
86919
87319
|
}
|
|
86920
87320
|
trace.completeSuccess(response.status);
|
|
@@ -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,
|
|
@@ -87845,41 +88323,6 @@ async function fetchClientRuntimeKillswitchContext(profileId, payload, options)
|
|
|
87845
88323
|
options
|
|
87846
88324
|
);
|
|
87847
88325
|
}
|
|
87848
|
-
async function getClientRuntimeStatuses(profileIds, signal, options) {
|
|
87849
|
-
const normalizedProfileIds = [...new Set(profileIds)].sort((left, right) => left - right);
|
|
87850
|
-
const params = new URLSearchParams();
|
|
87851
|
-
for (const profileId of normalizedProfileIds) {
|
|
87852
|
-
params.append("profile_id", String(profileId));
|
|
87853
|
-
}
|
|
87854
|
-
const viewer = resolveClientRuntimeStatusViewerHeaders(options?.runtimeViewer);
|
|
87855
|
-
const requestKey = `client-runtime-statuses:${normalizedProfileIds.join(",")}${viewer.requestKey}`;
|
|
87856
|
-
return shareClientGetRequest(requestKey, async () => {
|
|
87857
|
-
const headers = { ...viewer.headers };
|
|
87858
|
-
const response = await apiFetch(
|
|
87859
|
-
`${getApiUrl()}/trading/ai/runtime/statuses?${params.toString()}`,
|
|
87860
|
-
{
|
|
87861
|
-
method: "GET",
|
|
87862
|
-
credentials: "include",
|
|
87863
|
-
cache: "no-store",
|
|
87864
|
-
headers,
|
|
87865
|
-
// Without the browser's shared request a caller's abort ends the request too.
|
|
87866
|
-
signal: typeof window === "undefined" ? signal : void 0
|
|
87867
|
-
}
|
|
87868
|
-
);
|
|
87869
|
-
if (!response.ok) {
|
|
87870
|
-
const error48 = await createRuntimeRequestError(response, "Failed to fetch client runtime statuses");
|
|
87871
|
-
throw error48;
|
|
87872
|
-
}
|
|
87873
|
-
return response.json();
|
|
87874
|
-
}, {
|
|
87875
|
-
signal,
|
|
87876
|
-
shareAbortScoped: true,
|
|
87877
|
-
// A host-named read decides whether that host claims: it must see an
|
|
87878
|
-
// intent change made a moment ago, so it shares only an in-flight read
|
|
87879
|
-
// and never reuses a finished one.
|
|
87880
|
-
ttlMs: viewer.requestKey ? 0 : CLIENT_RUNTIME_STATUSES_DEDUPE_TTL_MS
|
|
87881
|
-
});
|
|
87882
|
-
}
|
|
87883
88326
|
var clientRuntimeSecretHeaders, preferencesWriteQueue, getCopyTradingRuntimeLeaseToken, getCopyTradingSchedulerInstanceId, resolveClientRuntimeStatusViewerHeaders, CLIENT_SUPPORTED_PROMPT_CONTRACT_VERSION, CLIENT_PROTECTION_CAPABILITY_VERSION, completedDeferredClientRuntimeStops, rememberCompletedDeferredClientRuntimeStop, consumeCompletedDeferredClientRuntimeStop, toNumericProfileId, buildClientRuntimeBody, shouldAttachRuntimeIdempotencyKey, attachRuntimeLeaseHeader, attachRuntimeSchedulerInstanceHeader, resolveRuntimeLeaseToken, resolveSchedulerBoundRuntimeLeaseToken, persistRuntimeLeaseFromPayload, persistRuntimeLeaseStatusMetadata, shouldClearPersistedRuntimeLeaseOnError, createRuntimeRequestError, parseClientRuntimeRequestContext, recordRuntimeAuthFailureBreadcrumb, classifyRuntimeRequestError, annotateRuntimeRequestError, parseRuntimeRetryAfterMs, isRetryableClientRuntimeStatus, shouldRetryClientRuntimeHttpStatus, isRuntimeIdempotencyInProgressError, isRetryableRuntimeConflictError, resolveClientRuntimeRetryDelayMs, reconcilePendingClientExchangeMutation, CLIENT_RUNTIME_CLAIM_EXCHANGE_MUTATION_WAIT_CODES, CLIENT_EXCHANGE_AUTHORITY_DEVICE_KEY, CLIENT_EXCHANGE_AUTHORITY_SESSION_KEY, getOrCreateClientExchangeAuthorityIdentity, resolveClientExchangeMutationAuthority, clientExchangeMutationAuthorityBody, isPendingClientExchangeMutationError, isMissingActiveClientExchangeMutationError, clientExchangeMutationReconciliationTimers, MAX_CLIENT_EXCHANGE_RECONCILIATION_DELAY_MS, CLIENT_EXCHANGE_RECONCILIATION_CLOCK_SKEW_MS, ClientExchangeMutationRebuildRequiredError, isTerminalClientExchangeMutation, clientExchangeMutationReconciliationKey, clearScheduledClientExchangeMutationReconciliation, snapshotClientExchangeMutationReconciliationAuthority, completeClientExchangeMutationReconciliation, protectiveBoundClientExchangeMutations, rememberProtectiveBoundClientExchangeMutation, isProtectiveBoundClientExchangeMutation, postClientExchangeMutationReconciliation, scheduleClientExchangeMutationReconciliation;
|
|
87884
88327
|
var init_api2 = __esm({
|
|
87885
88328
|
"lib/api.ts"() {
|
|
@@ -87990,6 +88433,9 @@ var init_api2 = __esm({
|
|
|
87990
88433
|
if (payload.authoritativeIntent !== void 0) {
|
|
87991
88434
|
body.authoritative_intent = payload.authoritativeIntent;
|
|
87992
88435
|
}
|
|
88436
|
+
if (payload.requireCurrentOwner !== void 0) {
|
|
88437
|
+
body.require_current_owner = payload.requireCurrentOwner;
|
|
88438
|
+
}
|
|
87993
88439
|
if (payload.analysisRunId !== void 0) {
|
|
87994
88440
|
body.analysis_run_id = payload.analysisRunId ?? null;
|
|
87995
88441
|
}
|
|
@@ -88291,14 +88737,14 @@ var init_api2 = __esm({
|
|
|
88291
88737
|
]);
|
|
88292
88738
|
CLIENT_EXCHANGE_AUTHORITY_DEVICE_KEY = "vtx_client_exchange_authority_device_v1";
|
|
88293
88739
|
CLIENT_EXCHANGE_AUTHORITY_SESSION_KEY = "vtx_client_exchange_authority_session_v1";
|
|
88294
|
-
getOrCreateClientExchangeAuthorityIdentity = (storage3, key,
|
|
88740
|
+
getOrCreateClientExchangeAuthorityIdentity = (storage3, key, label2) => {
|
|
88295
88741
|
const existing = String(storage3.getItem(key) || "").trim().toLowerCase();
|
|
88296
88742
|
if (/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/.test(existing)) {
|
|
88297
88743
|
return existing;
|
|
88298
88744
|
}
|
|
88299
88745
|
const generated = globalThis.crypto?.randomUUID?.().toLowerCase();
|
|
88300
88746
|
if (!generated || !/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/.test(generated)) {
|
|
88301
|
-
throw new Error(`Secure ${
|
|
88747
|
+
throw new Error(`Secure ${label2} generation is unavailable.`);
|
|
88302
88748
|
}
|
|
88303
88749
|
storage3.setItem(key, generated);
|
|
88304
88750
|
return generated;
|
|
@@ -88517,7 +88963,7 @@ var init_api2 = __esm({
|
|
|
88517
88963
|
});
|
|
88518
88964
|
|
|
88519
88965
|
// lib/runtime/hyperliquid-signer-binding.ts
|
|
88520
|
-
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;
|
|
88521
88967
|
var init_hyperliquid_signer_binding = __esm({
|
|
88522
88968
|
"lib/runtime/hyperliquid-signer-binding.ts"() {
|
|
88523
88969
|
"use strict";
|
|
@@ -88525,6 +88971,7 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88525
88971
|
init_define_VTX_GROK_POLICY();
|
|
88526
88972
|
init_define_VTX_PI_MODEL_POLICY();
|
|
88527
88973
|
init_hyperliquid_client();
|
|
88974
|
+
init_hyperliquid_exchange_rejections();
|
|
88528
88975
|
init_error_surface_contract();
|
|
88529
88976
|
DeviceSigningKeyError = class extends RuntimeExecutionError {
|
|
88530
88977
|
constructor(message, reasonCode, deviceSigningKeyFailure) {
|
|
@@ -88540,10 +88987,10 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88540
88987
|
const failure2 = error48?.deviceSigningKeyFailure;
|
|
88541
88988
|
return typeof failure2 === "string" && DEVICE_SIGNING_KEY_FAILURES.has(failure2) ? failure2 : null;
|
|
88542
88989
|
};
|
|
88543
|
-
normalizeAddress = (value,
|
|
88990
|
+
normalizeAddress = (value, label2) => {
|
|
88544
88991
|
const normalized = String(value || "").trim().toLowerCase();
|
|
88545
88992
|
if (!/^0x[0-9a-f]{40}$/.test(normalized)) {
|
|
88546
|
-
throw new Error(`Invalid Hyperliquid ${
|
|
88993
|
+
throw new Error(`Invalid Hyperliquid ${label2}.`);
|
|
88547
88994
|
}
|
|
88548
88995
|
return normalized;
|
|
88549
88996
|
};
|
|
@@ -88561,6 +89008,22 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88561
89008
|
}
|
|
88562
89009
|
return null;
|
|
88563
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
|
+
});
|
|
88564
89027
|
assertBrowserHyperliquidSignerWalletBinding = async (input) => {
|
|
88565
89028
|
let walletAddress;
|
|
88566
89029
|
try {
|
|
@@ -88586,6 +89049,24 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88586
89049
|
"device_signing_key_invalid"
|
|
88587
89050
|
);
|
|
88588
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
|
+
};
|
|
88589
89070
|
let roleResponse;
|
|
88590
89071
|
try {
|
|
88591
89072
|
roleResponse = await fetchBrowserUserRole({
|
|
@@ -88603,11 +89084,11 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88603
89084
|
}
|
|
88604
89085
|
const signerRole = String(roleResponse.role || "").trim().toLowerCase();
|
|
88605
89086
|
if (signerRole === "user" && signerAddress === walletAddress) {
|
|
88606
|
-
return {
|
|
89087
|
+
return remember({
|
|
88607
89088
|
signerAddress,
|
|
88608
89089
|
walletAddress,
|
|
88609
89090
|
signerRole: "user"
|
|
88610
|
-
};
|
|
89091
|
+
});
|
|
88611
89092
|
}
|
|
88612
89093
|
if (signerRole === "agent") {
|
|
88613
89094
|
const masterWallet = extractRoleAddress(
|
|
@@ -88615,11 +89096,11 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
88615
89096
|
["user"]
|
|
88616
89097
|
);
|
|
88617
89098
|
if (masterWallet === walletAddress) {
|
|
88618
|
-
return {
|
|
89099
|
+
return remember({
|
|
88619
89100
|
signerAddress,
|
|
88620
89101
|
walletAddress,
|
|
88621
89102
|
signerRole: "agent"
|
|
88622
|
-
};
|
|
89103
|
+
});
|
|
88623
89104
|
}
|
|
88624
89105
|
}
|
|
88625
89106
|
throw new DeviceSigningKeyError(
|
|
@@ -89575,9 +90056,9 @@ var init_browser_trading = __esm({
|
|
|
89575
90056
|
}
|
|
89576
90057
|
return profileId;
|
|
89577
90058
|
};
|
|
89578
|
-
requirePositiveNumber = (value,
|
|
90059
|
+
requirePositiveNumber = (value, label2) => {
|
|
89579
90060
|
if (!Number.isFinite(value) || value <= 0) {
|
|
89580
|
-
throw new Error(`${
|
|
90061
|
+
throw new Error(`${label2} must be a positive number.`);
|
|
89581
90062
|
}
|
|
89582
90063
|
};
|
|
89583
90064
|
assertFreshPreparedContext = (preparedContext) => {
|
|
@@ -90050,287 +90531,6 @@ var init_browser_trading = __esm({
|
|
|
90050
90531
|
}
|
|
90051
90532
|
});
|
|
90052
90533
|
|
|
90053
|
-
// lib/runtime/hyperliquid-account-mode-contract.ts
|
|
90054
|
-
function resolveExactHyperliquidAccountMode(userAbstraction, ...dexEvidence) {
|
|
90055
|
-
const mode = extractCanonicalHyperliquidAccountMode(userAbstraction);
|
|
90056
|
-
if (!mode) {
|
|
90057
|
-
throw new Error("Exact Hyperliquid userAbstraction response is invalid.");
|
|
90058
|
-
}
|
|
90059
|
-
if (mode !== "default" && mode !== "disabled") return mode;
|
|
90060
|
-
if (dexEvidence.length < 1) {
|
|
90061
|
-
throw new Error("Exact Hyperliquid userDexAbstraction response is unavailable.");
|
|
90062
|
-
}
|
|
90063
|
-
return parseExactDexAbstractionEnabled(dexEvidence[0]) ? "dexAbstraction" : mode;
|
|
90064
|
-
}
|
|
90065
|
-
var UNIFIED_MODE_ALIASES, CANONICAL_ACCOUNT_MODE_ALIASES, EXACT_MODE_KEYS, EXACT_MODE_BOOLEAN_KEYS, isExactTruthyFlag, normalizeCanonicalHyperliquidAccountMode, extractCanonicalHyperliquidAccountMode, parseExactDexAbstractionEnabled, normalizeAccountMode, extractAccountModeFromPayload, extractAccountModeCandidateFromPayload, isUnifiedAccountMode;
|
|
90066
|
-
var init_hyperliquid_account_mode_contract = __esm({
|
|
90067
|
-
"lib/runtime/hyperliquid-account-mode-contract.ts"() {
|
|
90068
|
-
"use strict";
|
|
90069
|
-
init_define_VTX_EXO_POLICY();
|
|
90070
|
-
init_define_VTX_GROK_POLICY();
|
|
90071
|
-
init_define_VTX_PI_MODEL_POLICY();
|
|
90072
|
-
UNIFIED_MODE_ALIASES = /* @__PURE__ */ new Set([
|
|
90073
|
-
"unifiedaccount",
|
|
90074
|
-
"dexabstraction",
|
|
90075
|
-
"portfoliomargin",
|
|
90076
|
-
"unified",
|
|
90077
|
-
"pm"
|
|
90078
|
-
]);
|
|
90079
|
-
CANONICAL_ACCOUNT_MODE_ALIASES = /* @__PURE__ */ new Map([
|
|
90080
|
-
["default", "default"],
|
|
90081
|
-
["standard", "default"],
|
|
90082
|
-
["classic", "default"],
|
|
90083
|
-
["disabled", "disabled"],
|
|
90084
|
-
["unifiedaccount", "unifiedAccount"],
|
|
90085
|
-
["unified", "unifiedAccount"],
|
|
90086
|
-
["portfoliomargin", "portfolioMargin"],
|
|
90087
|
-
["pm", "portfolioMargin"],
|
|
90088
|
-
["dexabstraction", "dexAbstraction"]
|
|
90089
|
-
]);
|
|
90090
|
-
EXACT_MODE_KEYS = [
|
|
90091
|
-
"accountMode",
|
|
90092
|
-
"account_mode",
|
|
90093
|
-
"accountType",
|
|
90094
|
-
"account_type",
|
|
90095
|
-
"accountUnificationMode",
|
|
90096
|
-
"account_unification_mode",
|
|
90097
|
-
"abstractionMode",
|
|
90098
|
-
"abstraction_mode",
|
|
90099
|
-
"abstraction",
|
|
90100
|
-
"abstractionState",
|
|
90101
|
-
"dexAbstractionState",
|
|
90102
|
-
"marginMode",
|
|
90103
|
-
"state",
|
|
90104
|
-
"mode",
|
|
90105
|
-
"value"
|
|
90106
|
-
];
|
|
90107
|
-
EXACT_MODE_BOOLEAN_KEYS = [
|
|
90108
|
-
["unifiedAccount", ["isUnifiedAccount", "unifiedAccount", "isUnified", "unified", "is_unified_account"]],
|
|
90109
|
-
["portfolioMargin", ["isPortfolioMargin", "portfolioMargin", "isPm", "pm", "is_portfolio_margin"]],
|
|
90110
|
-
["dexAbstraction", ["isDexAbstraction", "dexAbstraction", "dexAbstractionEnabled", "is_dex_abstraction"]],
|
|
90111
|
-
["default", ["isClassic", "classic", "isStandard", "standard"]]
|
|
90112
|
-
];
|
|
90113
|
-
isExactTruthyFlag = (value) => value === true || value === 1 || typeof value === "string" && value.trim().toLowerCase() === "true";
|
|
90114
|
-
normalizeCanonicalHyperliquidAccountMode = (value) => {
|
|
90115
|
-
if (typeof value !== "string") return null;
|
|
90116
|
-
const key = value.trim().replace(/[_\s-]/g, "").toLowerCase();
|
|
90117
|
-
return CANONICAL_ACCOUNT_MODE_ALIASES.get(key) ?? null;
|
|
90118
|
-
};
|
|
90119
|
-
extractCanonicalHyperliquidAccountMode = (payload, depth = 0) => {
|
|
90120
|
-
if (depth > 6) return null;
|
|
90121
|
-
const direct = normalizeCanonicalHyperliquidAccountMode(payload);
|
|
90122
|
-
if (direct) return direct;
|
|
90123
|
-
if (Array.isArray(payload)) {
|
|
90124
|
-
for (const item of payload) {
|
|
90125
|
-
const mode = extractCanonicalHyperliquidAccountMode(item, depth + 1);
|
|
90126
|
-
if (mode) return mode;
|
|
90127
|
-
}
|
|
90128
|
-
return null;
|
|
90129
|
-
}
|
|
90130
|
-
if (!payload || typeof payload !== "object") return null;
|
|
90131
|
-
const source = payload;
|
|
90132
|
-
for (const key of EXACT_MODE_KEYS) {
|
|
90133
|
-
if (!(key in source)) continue;
|
|
90134
|
-
const mode = normalizeCanonicalHyperliquidAccountMode(source[key]);
|
|
90135
|
-
if (mode) return mode;
|
|
90136
|
-
}
|
|
90137
|
-
for (const [mode, keys] of EXACT_MODE_BOOLEAN_KEYS) {
|
|
90138
|
-
for (const key of keys) {
|
|
90139
|
-
if (isExactTruthyFlag(source[key])) return mode;
|
|
90140
|
-
}
|
|
90141
|
-
}
|
|
90142
|
-
for (const value of Object.values(source)) {
|
|
90143
|
-
const mode = extractCanonicalHyperliquidAccountMode(value, depth + 1);
|
|
90144
|
-
if (mode) return mode;
|
|
90145
|
-
}
|
|
90146
|
-
return null;
|
|
90147
|
-
};
|
|
90148
|
-
parseExactDexAbstractionEnabled = (payload) => {
|
|
90149
|
-
if (payload == null || payload === false) return false;
|
|
90150
|
-
if (payload === true) return true;
|
|
90151
|
-
if (typeof payload === "string") {
|
|
90152
|
-
const normalized = payload.trim().toLowerCase();
|
|
90153
|
-
if (normalized === "true") return true;
|
|
90154
|
-
if (normalized === "false") return false;
|
|
90155
|
-
}
|
|
90156
|
-
if (typeof payload === "number" && Number.isFinite(payload)) {
|
|
90157
|
-
if (payload === 1) return true;
|
|
90158
|
-
if (payload === 0) return false;
|
|
90159
|
-
}
|
|
90160
|
-
throw new Error("Exact Hyperliquid userDexAbstraction response is invalid.");
|
|
90161
|
-
};
|
|
90162
|
-
normalizeAccountMode = (mode) => String(mode ?? "").trim().toLowerCase().replace(/[_\s-]/g, "");
|
|
90163
|
-
extractAccountModeFromPayload = (payload) => {
|
|
90164
|
-
const candidate = extractAccountModeCandidateFromPayload(payload);
|
|
90165
|
-
if (candidate && candidate.trim().length > 0) {
|
|
90166
|
-
return candidate;
|
|
90167
|
-
}
|
|
90168
|
-
return "default";
|
|
90169
|
-
};
|
|
90170
|
-
extractAccountModeCandidateFromPayload = (payload) => {
|
|
90171
|
-
if (!payload || typeof payload !== "object") {
|
|
90172
|
-
return null;
|
|
90173
|
-
}
|
|
90174
|
-
const source = payload;
|
|
90175
|
-
if ("accountMode" in source) {
|
|
90176
|
-
return String(source.accountMode ?? "");
|
|
90177
|
-
}
|
|
90178
|
-
if ("account_mode" in source) {
|
|
90179
|
-
return String(source.account_mode ?? "");
|
|
90180
|
-
}
|
|
90181
|
-
return null;
|
|
90182
|
-
};
|
|
90183
|
-
isUnifiedAccountMode = (mode) => UNIFIED_MODE_ALIASES.has(normalizeAccountMode(mode));
|
|
90184
|
-
}
|
|
90185
|
-
});
|
|
90186
|
-
|
|
90187
|
-
// lib/runtime/hyperliquid-account-contract.ts
|
|
90188
|
-
var toNumber2, firstNumber, roundTo, STABLE_SPOT_SYMBOLS, spotBalanceValueUsd, normalizeSpotBalancesFromInfoResponse, sumBalanceHoldUsd, sumPositionUnrealizedPnl, resolveTotalUnrealizedPnl, approximatelyEqualAccountValues, buildAccountSummaryFromInfoResponses;
|
|
90189
|
-
var init_hyperliquid_account_contract = __esm({
|
|
90190
|
-
"lib/runtime/hyperliquid-account-contract.ts"() {
|
|
90191
|
-
"use strict";
|
|
90192
|
-
init_define_VTX_EXO_POLICY();
|
|
90193
|
-
init_define_VTX_GROK_POLICY();
|
|
90194
|
-
init_define_VTX_PI_MODEL_POLICY();
|
|
90195
|
-
init_hyperliquid_account_mode_contract();
|
|
90196
|
-
toNumber2 = (value, fallback = 0) => {
|
|
90197
|
-
const numeric2 = Number(value);
|
|
90198
|
-
return Number.isFinite(numeric2) ? numeric2 : fallback;
|
|
90199
|
-
};
|
|
90200
|
-
firstNumber = (values, fallback = 0) => {
|
|
90201
|
-
for (const value of values) {
|
|
90202
|
-
if (value == null || typeof value === "string" && value.trim() === "") {
|
|
90203
|
-
continue;
|
|
90204
|
-
}
|
|
90205
|
-
const numeric2 = Number(value);
|
|
90206
|
-
if (Number.isFinite(numeric2)) {
|
|
90207
|
-
return numeric2;
|
|
90208
|
-
}
|
|
90209
|
-
}
|
|
90210
|
-
return fallback;
|
|
90211
|
-
};
|
|
90212
|
-
roundTo = (value, digits = 12) => Number(value.toFixed(digits));
|
|
90213
|
-
STABLE_SPOT_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USD", "USDT"]);
|
|
90214
|
-
spotBalanceValueUsd = (balance, coin, total) => {
|
|
90215
|
-
const explicit = firstNumber([balance?.value_usd, balance?.usdValue, balance?.usdcValue], Number.NaN);
|
|
90216
|
-
if (Number.isFinite(explicit)) {
|
|
90217
|
-
return explicit;
|
|
90218
|
-
}
|
|
90219
|
-
return STABLE_SPOT_SYMBOLS.has(coin) ? total : 0;
|
|
90220
|
-
};
|
|
90221
|
-
normalizeSpotBalancesFromInfoResponse = (spotResponse) => {
|
|
90222
|
-
const containers = [];
|
|
90223
|
-
if (spotResponse && typeof spotResponse === "object") {
|
|
90224
|
-
containers.push(spotResponse);
|
|
90225
|
-
const keys = ["spotState", "userState", "clearinghouseState", "state", "data"];
|
|
90226
|
-
for (const key of keys) {
|
|
90227
|
-
if (spotResponse[key] && typeof spotResponse[key] === "object") {
|
|
90228
|
-
containers.push(spotResponse[key]);
|
|
90229
|
-
}
|
|
90230
|
-
}
|
|
90231
|
-
}
|
|
90232
|
-
const firstWithBalances = containers.find((container) => Array.isArray(container?.balances));
|
|
90233
|
-
const balances = Array.isArray(firstWithBalances?.balances) ? firstWithBalances.balances : [];
|
|
90234
|
-
return balances.map((balance) => {
|
|
90235
|
-
const coin = String(balance?.coin ?? "").toUpperCase();
|
|
90236
|
-
const total = toNumber2(balance?.total, 0);
|
|
90237
|
-
const hold = toNumber2(balance?.hold, 0);
|
|
90238
|
-
const available = roundTo(Math.max(0, total - hold));
|
|
90239
|
-
const value_usd = spotBalanceValueUsd(balance, coin, total);
|
|
90240
|
-
return {
|
|
90241
|
-
coin,
|
|
90242
|
-
total,
|
|
90243
|
-
hold,
|
|
90244
|
-
available,
|
|
90245
|
-
value_usd
|
|
90246
|
-
};
|
|
90247
|
-
}).filter((balance) => balance.coin.length > 0);
|
|
90248
|
-
};
|
|
90249
|
-
sumBalanceHoldUsd = (balances) => balances.reduce((acc, balance) => {
|
|
90250
|
-
const hold = toNumber2(balance.hold, 0);
|
|
90251
|
-
const total = toNumber2(balance.total, 0);
|
|
90252
|
-
const valueUsd = toNumber2(balance.value_usd, 0);
|
|
90253
|
-
if (hold <= 0 || total <= 0 || valueUsd <= 0) {
|
|
90254
|
-
return acc;
|
|
90255
|
-
}
|
|
90256
|
-
return acc + Math.max(0, valueUsd * (hold / total));
|
|
90257
|
-
}, 0);
|
|
90258
|
-
sumPositionUnrealizedPnl = (perpsResponse) => {
|
|
90259
|
-
const assetPositions = Array.isArray(perpsResponse?.assetPositions) ? perpsResponse.assetPositions : [];
|
|
90260
|
-
return assetPositions.reduce((total, entry) => {
|
|
90261
|
-
const unrealizedPnl = toNumber2(entry?.position?.unrealizedPnl, 0);
|
|
90262
|
-
return total + unrealizedPnl;
|
|
90263
|
-
}, 0);
|
|
90264
|
-
};
|
|
90265
|
-
resolveTotalUnrealizedPnl = (perpsResponse) => {
|
|
90266
|
-
const topLevel = toNumber2(perpsResponse?.totalUnrealizedPnl, 0);
|
|
90267
|
-
const positionTotal = sumPositionUnrealizedPnl(perpsResponse);
|
|
90268
|
-
if (Math.abs(topLevel) < 1e-12 && Math.abs(positionTotal) >= 1e-12) {
|
|
90269
|
-
return positionTotal;
|
|
90270
|
-
}
|
|
90271
|
-
return topLevel;
|
|
90272
|
-
};
|
|
90273
|
-
approximatelyEqualAccountValues = (left, right, absoluteToleranceUsd, relativeTolerance) => {
|
|
90274
|
-
const reference = Math.max(Math.abs(left), Math.abs(right), 1);
|
|
90275
|
-
return Math.abs(left - right) <= Math.max(
|
|
90276
|
-
absoluteToleranceUsd,
|
|
90277
|
-
reference * relativeTolerance
|
|
90278
|
-
);
|
|
90279
|
-
};
|
|
90280
|
-
buildAccountSummaryFromInfoResponses = (perpsResponse, spotResponse, options = {}) => {
|
|
90281
|
-
const marginSummary = perpsResponse?.marginSummary ?? {};
|
|
90282
|
-
const perpsAccountValue = toNumber2(marginSummary?.accountValue, 0);
|
|
90283
|
-
const total_margin_used = toNumber2(marginSummary?.totalMarginUsed, 0);
|
|
90284
|
-
const totalNtlPos = toNumber2(marginSummary?.totalNtlPos, 0);
|
|
90285
|
-
const withdrawable = toNumber2(perpsResponse?.withdrawable, 0);
|
|
90286
|
-
const maintenance_margin = firstNumber([
|
|
90287
|
-
perpsResponse?.crossMaintenanceMarginUsed,
|
|
90288
|
-
marginSummary?.crossMaintenanceMarginUsed,
|
|
90289
|
-
marginSummary?.totalMaintenanceMargin
|
|
90290
|
-
], 0);
|
|
90291
|
-
const balances = normalizeSpotBalancesFromInfoResponse(spotResponse);
|
|
90292
|
-
const spotPortfolioValue = balances.reduce((acc, balance) => acc + toNumber2(balance.value_usd, 0), 0);
|
|
90293
|
-
const balancesHoldUsd = sumBalanceHoldUsd(balances);
|
|
90294
|
-
const account_mode = extractAccountModeFromPayload(perpsResponse);
|
|
90295
|
-
const crossMarginSummary = perpsResponse?.crossMarginSummary && typeof perpsResponse.crossMarginSummary === "object" ? perpsResponse.crossMarginSummary : null;
|
|
90296
|
-
const crossMarginAccountValue = crossMarginSummary ? toNumber2(crossMarginSummary.accountValue, 0) : 0;
|
|
90297
|
-
const normalizedMode = String(account_mode || "").trim().toLowerCase().replace(/[_\s-]/g, "");
|
|
90298
|
-
const isAmbiguousDefaultMode = normalizedMode.length === 0 || normalizedMode === "default";
|
|
90299
|
-
const spotDominatesMinTotalUsd = Number(options.spotDominatesMinTotalUsd ?? options.spot_dominates_min_total_usd);
|
|
90300
|
-
const spotDominatesPerpsMultiplier = Number(options.spotDominatesPerpsMultiplier ?? options.spot_dominates_perps_multiplier);
|
|
90301
|
-
const mirroredAccountValueAbsoluteToleranceUsd = Number(
|
|
90302
|
-
options.mirroredAccountValueAbsoluteToleranceUsd ?? options.mirrored_account_value_absolute_tolerance_usd
|
|
90303
|
-
);
|
|
90304
|
-
const mirroredAccountValueRelativeTolerance = Number(
|
|
90305
|
-
options.mirroredAccountValueRelativeTolerance ?? options.mirrored_account_value_relative_tolerance
|
|
90306
|
-
);
|
|
90307
|
-
const hasSpotDominanceThresholds = Number.isFinite(spotDominatesMinTotalUsd) && spotDominatesMinTotalUsd >= 0 && Number.isFinite(spotDominatesPerpsMultiplier) && spotDominatesPerpsMultiplier >= 0;
|
|
90308
|
-
const hasMirroredAccountValueTolerances = Number.isFinite(mirroredAccountValueAbsoluteToleranceUsd) && mirroredAccountValueAbsoluteToleranceUsd >= 0 && Number.isFinite(mirroredAccountValueRelativeTolerance) && mirroredAccountValueRelativeTolerance >= 0;
|
|
90309
|
-
const spotDominatesPerps = hasSpotDominanceThresholds && spotPortfolioValue >= spotDominatesMinTotalUsd && (perpsAccountValue <= 0 || spotPortfolioValue >= perpsAccountValue * spotDominatesPerpsMultiplier);
|
|
90310
|
-
const ambiguousDefaultLooksUnified = isAmbiguousDefaultMode && spotDominatesPerps;
|
|
90311
|
-
const ambiguousDefaultSpotAlreadyIncludesPerps = ambiguousDefaultLooksUnified && perpsAccountValue > 0 && balancesHoldUsd > 0 && hasMirroredAccountValueTolerances && approximatelyEqualAccountValues(
|
|
90312
|
-
balancesHoldUsd,
|
|
90313
|
-
perpsAccountValue,
|
|
90314
|
-
mirroredAccountValueAbsoluteToleranceUsd,
|
|
90315
|
-
mirroredAccountValueRelativeTolerance
|
|
90316
|
-
);
|
|
90317
|
-
const account_value = isUnifiedAccountMode(account_mode) && crossMarginSummary !== null && crossMarginAccountValue > 0 ? crossMarginAccountValue + spotPortfolioValue : ambiguousDefaultLooksUnified && !ambiguousDefaultSpotAlreadyIncludesPerps ? perpsAccountValue + spotPortfolioValue : Math.max(perpsAccountValue, spotPortfolioValue);
|
|
90318
|
-
return {
|
|
90319
|
-
account_value,
|
|
90320
|
-
total_margin_used,
|
|
90321
|
-
available_margin: roundTo(Math.max(0, account_value - total_margin_used)),
|
|
90322
|
-
withdrawable,
|
|
90323
|
-
cross_margin_ratio: account_value > 0 ? maintenance_margin / account_value : 0,
|
|
90324
|
-
maintenance_margin,
|
|
90325
|
-
cross_account_leverage: account_value > 0 ? totalNtlPos / account_value : 0,
|
|
90326
|
-
total_unrealized_pnl: resolveTotalUnrealizedPnl(perpsResponse),
|
|
90327
|
-
account_mode,
|
|
90328
|
-
balances
|
|
90329
|
-
};
|
|
90330
|
-
};
|
|
90331
|
-
}
|
|
90332
|
-
});
|
|
90333
|
-
|
|
90334
90534
|
// lib/runtime/hyperliquid-active-asset-contract.ts
|
|
90335
90535
|
var unwrapActiveAssetPayload, normalizePair, normalizeActiveAssetData;
|
|
90336
90536
|
var init_hyperliquid_active_asset_contract = __esm({
|
|
@@ -90358,15 +90558,15 @@ var init_hyperliquid_active_asset_contract = __esm({
|
|
|
90358
90558
|
};
|
|
90359
90559
|
normalizePair = (raw) => {
|
|
90360
90560
|
if (Array.isArray(raw) && raw.length >= 2) {
|
|
90361
|
-
return [
|
|
90561
|
+
return [toNumber(raw[0], 0), toNumber(raw[1], 0)];
|
|
90362
90562
|
}
|
|
90363
90563
|
if (raw && typeof raw === "object") {
|
|
90364
|
-
const buy =
|
|
90365
|
-
const sell =
|
|
90564
|
+
const buy = toNumber(raw.buy ?? raw.long ?? raw.b, 0);
|
|
90565
|
+
const sell = toNumber(raw.sell ?? raw.short ?? raw.s, 0);
|
|
90366
90566
|
return [buy, sell];
|
|
90367
90567
|
}
|
|
90368
90568
|
if (typeof raw === "string" || typeof raw === "number") {
|
|
90369
|
-
const value =
|
|
90569
|
+
const value = toNumber(raw, 0);
|
|
90370
90570
|
return [value, value];
|
|
90371
90571
|
}
|
|
90372
90572
|
return [0, 0];
|
|
@@ -90377,21 +90577,21 @@ var init_hyperliquid_active_asset_contract = __esm({
|
|
|
90377
90577
|
const directSell = source.available_to_trade_sell;
|
|
90378
90578
|
const hasDirectAvailable = directBuy !== void 0 || directSell !== void 0;
|
|
90379
90579
|
const [pairBuy, pairSell] = normalizePair(source.availableToTrade);
|
|
90380
|
-
const available_to_trade_buy = hasDirectAvailable ?
|
|
90381
|
-
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;
|
|
90382
90582
|
const directMaxBuy = source.max_trade_size_buy;
|
|
90383
90583
|
const directMaxSell = source.max_trade_size_sell;
|
|
90384
90584
|
const hasDirectMax = directMaxBuy !== void 0 || directMaxSell !== void 0;
|
|
90385
90585
|
const [pairMaxBuy, pairMaxSell] = normalizePair(source.maxTradeSzs);
|
|
90386
|
-
const max_trade_size_buy = hasDirectMax ?
|
|
90387
|
-
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;
|
|
90388
90588
|
return {
|
|
90389
90589
|
symbol: String(source.coin || symbol2),
|
|
90390
90590
|
available_to_trade_buy,
|
|
90391
90591
|
available_to_trade_sell,
|
|
90392
90592
|
max_trade_size_buy,
|
|
90393
90593
|
max_trade_size_sell,
|
|
90394
|
-
mark_price:
|
|
90594
|
+
mark_price: toNumber(source.markPx ?? source.mark_price, 0)
|
|
90395
90595
|
};
|
|
90396
90596
|
};
|
|
90397
90597
|
}
|
|
@@ -90583,12 +90783,7 @@ var init_server_prompt_rescue_account_contract = __esm({
|
|
|
90583
90783
|
};
|
|
90584
90784
|
const accountValue = computeEffectiveAccountValue(formulaInput);
|
|
90585
90785
|
const maintenanceMargin = toNumber3(perps.crossMaintenanceMarginUsed);
|
|
90586
|
-
const
|
|
90587
|
-
const availableMargin = maintenanceMargin > 0 ? Math.max(
|
|
90588
|
-
calculatedAvailable,
|
|
90589
|
-
Math.max(0, accountValue - 4 * maintenanceMargin),
|
|
90590
|
-
withdrawable
|
|
90591
|
-
) : Math.max(calculatedAvailable, withdrawable);
|
|
90786
|
+
const availableMargin = canonicalAvailableMargin(accountValue, totalMarginUsed);
|
|
90592
90787
|
let totalNotional = 0;
|
|
90593
90788
|
let totalUnrealizedPnl = 0;
|
|
90594
90789
|
const positions = Array.isArray(perps.assetPositions) ? perps.assetPositions : [];
|
|
@@ -91046,18 +91241,18 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91046
91241
|
}
|
|
91047
91242
|
return parsed;
|
|
91048
91243
|
};
|
|
91049
|
-
requirePromptClearinghouseState = (response,
|
|
91244
|
+
requirePromptClearinghouseState = (response, label2) => {
|
|
91050
91245
|
if (!response || typeof response !== "object" || Array.isArray(response)) {
|
|
91051
|
-
throw new Error(`Malformed ${
|
|
91246
|
+
throw new Error(`Malformed ${label2} clearinghouseState response for client runtime prompt context.`);
|
|
91052
91247
|
}
|
|
91053
91248
|
const marginSummary = response.marginSummary;
|
|
91054
91249
|
if (!marginSummary || typeof marginSummary !== "object" || Array.isArray(marginSummary)) {
|
|
91055
|
-
throw new Error(`${
|
|
91250
|
+
throw new Error(`${label2} clearinghouseState is missing marginSummary for client runtime prompt context.`);
|
|
91056
91251
|
}
|
|
91057
|
-
requireFinitePromptMetric(marginSummary.accountValue, `${
|
|
91058
|
-
requireFinitePromptMetric(marginSummary.totalMarginUsed, `${
|
|
91059
|
-
requireFinitePromptMetric(marginSummary.totalNtlPos, `${
|
|
91060
|
-
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`);
|
|
91061
91256
|
const maintenanceCandidates = [
|
|
91062
91257
|
response.crossMaintenanceMarginUsed,
|
|
91063
91258
|
marginSummary.crossMaintenanceMarginUsed,
|
|
@@ -91066,33 +91261,33 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91066
91261
|
const maintenance = maintenanceCandidates.find(
|
|
91067
91262
|
(value) => value != null && !(typeof value === "string" && value.trim() === "")
|
|
91068
91263
|
);
|
|
91069
|
-
requireFinitePromptMetric(maintenance, `${
|
|
91264
|
+
requireFinitePromptMetric(maintenance, `${label2}.maintenanceMargin`);
|
|
91070
91265
|
if (!Array.isArray(response.assetPositions)) {
|
|
91071
|
-
throw new Error(`${
|
|
91266
|
+
throw new Error(`${label2} clearinghouseState is missing assetPositions for client runtime prompt context.`);
|
|
91072
91267
|
}
|
|
91073
91268
|
response.assetPositions.forEach((entry, index) => {
|
|
91074
91269
|
const position = entry?.position;
|
|
91075
91270
|
if (!position || typeof position !== "object" || Array.isArray(position)) {
|
|
91076
|
-
throw new Error(`${
|
|
91271
|
+
throw new Error(`${label2}.assetPositions[${index}] is malformed for client runtime prompt context.`);
|
|
91077
91272
|
}
|
|
91078
91273
|
if (!String(entry?.coin || position.coin || "").trim()) {
|
|
91079
|
-
throw new Error(`${
|
|
91274
|
+
throw new Error(`${label2}.assetPositions[${index}] is missing its symbol for client runtime prompt context.`);
|
|
91080
91275
|
}
|
|
91081
91276
|
const size = requireFinitePromptMetric(
|
|
91082
91277
|
position.szi,
|
|
91083
|
-
`${
|
|
91278
|
+
`${label2}.assetPositions[${index}].position.szi`
|
|
91084
91279
|
);
|
|
91085
91280
|
if (size !== 0) {
|
|
91086
91281
|
const entryPrice = requireFinitePromptMetric(
|
|
91087
91282
|
position.entryPx,
|
|
91088
|
-
`${
|
|
91283
|
+
`${label2}.assetPositions[${index}].position.entryPx`
|
|
91089
91284
|
);
|
|
91090
91285
|
if (entryPrice <= 0) {
|
|
91091
|
-
throw new Error(`${
|
|
91286
|
+
throw new Error(`${label2}.assetPositions[${index}] has a nonpositive entry price for client runtime prompt context.`);
|
|
91092
91287
|
}
|
|
91093
91288
|
requireFinitePromptMetric(
|
|
91094
91289
|
position.unrealizedPnl,
|
|
91095
|
-
`${
|
|
91290
|
+
`${label2}.assetPositions[${index}].position.unrealizedPnl`
|
|
91096
91291
|
);
|
|
91097
91292
|
}
|
|
91098
91293
|
});
|
|
@@ -91116,9 +91311,12 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91116
91311
|
perpDexConfig.allowed_dexes.map(normalizePerpDexName).filter((value) => value.length > 0)
|
|
91117
91312
|
));
|
|
91118
91313
|
};
|
|
91119
|
-
listPerpDexsForAccountState = (config2, selectedDex, aggregatePerpDexs) => {
|
|
91314
|
+
listPerpDexsForAccountState = (config2, selectedDex, aggregatePerpDexs, perpDexScope) => {
|
|
91120
91315
|
if (aggregatePerpDexs) {
|
|
91121
|
-
|
|
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));
|
|
91122
91320
|
}
|
|
91123
91321
|
return selectedDex ? [selectedDex] : [];
|
|
91124
91322
|
};
|
|
@@ -91326,7 +91524,7 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91326
91524
|
const includeEffectiveTakerRate = input.includeEffectiveTakerRate === true;
|
|
91327
91525
|
const includeExactAccountMode = input.includeExactAccountMode === true;
|
|
91328
91526
|
const includeActiveAssetData = input.includeActiveAssetData !== false;
|
|
91329
|
-
const dexNames = listPerpDexsForAccountState(input.config, dex, aggregatePerpDexs);
|
|
91527
|
+
const dexNames = listPerpDexsForAccountState(input.config, dex, aggregatePerpDexs, input.perpDexScope);
|
|
91330
91528
|
if (scopeAccountSummaryToSelectedDex && dex && !dexNames.includes(dex)) {
|
|
91331
91529
|
dexNames.push(dex);
|
|
91332
91530
|
}
|
|
@@ -91624,8 +91822,7 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
91624
91822
|
])
|
|
91625
91823
|
}, {}, "disabled", accountSummaryOptions);
|
|
91626
91824
|
const accountValue = Number(payload.marginSummary.accountValue);
|
|
91627
|
-
const
|
|
91628
|
-
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);
|
|
91629
91826
|
return {
|
|
91630
91827
|
dex,
|
|
91631
91828
|
account_value: accountValue,
|
|
@@ -91930,7 +92127,7 @@ var init_protective_evidence = __esm({
|
|
|
91930
92127
|
const perDex = /* @__PURE__ */ new Map();
|
|
91931
92128
|
const scope = `${String(input.apiUrl ?? "")}|${wallet.toLowerCase()}`;
|
|
91932
92129
|
const shareable = batch.every((item) => item.kind !== "fills" && item.shareable);
|
|
91933
|
-
const dexRead = (key, body,
|
|
92130
|
+
const dexRead = (key, body, label2) => {
|
|
91934
92131
|
let read = perDex.get(key);
|
|
91935
92132
|
if (read) return read;
|
|
91936
92133
|
const sharedKey = `${scope}|${key}`;
|
|
@@ -91940,7 +92137,7 @@ var init_protective_evidence = __esm({
|
|
|
91940
92137
|
startedAtMonotonicMs = Math.min(startedAtMonotonicMs, shared.startedAtMonotonicMs);
|
|
91941
92138
|
read = shared.read;
|
|
91942
92139
|
} else {
|
|
91943
|
-
read = readOrNull(() => fetchBrowserHyperliquidInfoPayload(input, body,
|
|
92140
|
+
read = readOrNull(() => fetchBrowserHyperliquidInfoPayload(input, body, label2));
|
|
91944
92141
|
const entry = { startedAtMonotonicMs: now, read };
|
|
91945
92142
|
sharedAccountReads.set(sharedKey, entry);
|
|
91946
92143
|
void read.then((value) => {
|
|
@@ -92117,19 +92314,19 @@ var init_protective_actions = __esm({
|
|
|
92117
92314
|
"local_safety_block"
|
|
92118
92315
|
);
|
|
92119
92316
|
};
|
|
92120
|
-
exactKeys = (value, keys,
|
|
92121
|
-
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.`);
|
|
92122
92319
|
const record5 = value;
|
|
92123
92320
|
const present = Object.keys(record5).sort();
|
|
92124
|
-
if (present.join(",") !== [...keys].sort().join(",")) fail2(`${
|
|
92321
|
+
if (present.join(",") !== [...keys].sort().join(",")) fail2(`${label2} has unexpected fields.`);
|
|
92125
92322
|
return record5;
|
|
92126
92323
|
};
|
|
92127
|
-
nonNegativeInteger = (value,
|
|
92128
|
-
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.`);
|
|
92129
92326
|
return value;
|
|
92130
92327
|
};
|
|
92131
|
-
decimalString = (value,
|
|
92132
|
-
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.`);
|
|
92133
92330
|
return value;
|
|
92134
92331
|
};
|
|
92135
92332
|
canonicalTriggerOrder = (value) => {
|
|
@@ -92439,6 +92636,119 @@ var init_protective_actions = __esm({
|
|
|
92439
92636
|
}
|
|
92440
92637
|
});
|
|
92441
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
|
+
|
|
92442
92752
|
// lib/runtime/execution-guard-contract.ts
|
|
92443
92753
|
var unitsFromPosition, signedUnitsFromPosition, signedUnitsFromEntryPosition, classifyExecutionIntent, resolveExecutionTarget;
|
|
92444
92754
|
var init_execution_guard_contract = __esm({
|
|
@@ -92724,7 +93034,7 @@ var init_protective_trigger_price = __esm({
|
|
|
92724
93034
|
});
|
|
92725
93035
|
|
|
92726
93036
|
// lib/runtime/runtime-execution.ts
|
|
92727
|
-
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;
|
|
92728
93038
|
var init_runtime_execution = __esm({
|
|
92729
93039
|
"lib/runtime/runtime-execution.ts"() {
|
|
92730
93040
|
"use strict";
|
|
@@ -92732,8 +93042,11 @@ var init_runtime_execution = __esm({
|
|
|
92732
93042
|
init_define_VTX_GROK_POLICY();
|
|
92733
93043
|
init_define_VTX_PI_MODEL_POLICY();
|
|
92734
93044
|
init_order_identity();
|
|
93045
|
+
init_runtime_policy_generated2();
|
|
93046
|
+
init_bounded_lock();
|
|
92735
93047
|
init_client_runtime_ownership_errors();
|
|
92736
93048
|
init_api2();
|
|
93049
|
+
init_client_exchange_mutations();
|
|
92737
93050
|
init_hyperliquid_order_status();
|
|
92738
93051
|
init_protective_actions();
|
|
92739
93052
|
init_browser_trading();
|
|
@@ -92761,6 +93074,26 @@ var init_runtime_execution = __esm({
|
|
|
92761
93074
|
);
|
|
92762
93075
|
return classified.reduceOnly ? "trading_reduce" : "trading_execute";
|
|
92763
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
|
+
};
|
|
92764
93097
|
fetchClientRuntimeOpenOrders = async (request, publicRequestPriority = "trading_reconcile") => {
|
|
92765
93098
|
const normalizedSymbol = normalizeHyperliquidMarketSymbol(
|
|
92766
93099
|
request.executionContext.symbol
|
|
@@ -92975,6 +93308,12 @@ var init_runtime_execution = __esm({
|
|
|
92975
93308
|
]);
|
|
92976
93309
|
};
|
|
92977
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
|
+
);
|
|
92978
93317
|
readClientProtectiveGroups = (profileId, symbol2) => {
|
|
92979
93318
|
const key = protectiveGroupStorageKey(profileId, symbol2);
|
|
92980
93319
|
const inMemory = protectiveGroupMemory.get(key);
|
|
@@ -93068,12 +93407,41 @@ var init_runtime_execution = __esm({
|
|
|
93068
93407
|
const pending3 = pendingRecord;
|
|
93069
93408
|
const stopLoss = pending3.stopLoss;
|
|
93070
93409
|
const takeProfit = pending3.takeProfit;
|
|
93071
|
-
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)) {
|
|
93072
93411
|
protectiveGroupReadFailures.add(key);
|
|
93073
93412
|
return [];
|
|
93074
93413
|
}
|
|
93075
93414
|
const sl = stopLoss;
|
|
93076
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
|
+
}
|
|
93077
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) {
|
|
93078
93446
|
protectiveGroupReadFailures.add(key);
|
|
93079
93447
|
return [];
|
|
@@ -93083,6 +93451,7 @@ var init_runtime_execution = __esm({
|
|
|
93083
93451
|
entryClientOrderId: pending3.entryClientOrderId,
|
|
93084
93452
|
entrySide: pending3.entrySide,
|
|
93085
93453
|
requestedSize: Number(pending3.requestedSize),
|
|
93454
|
+
...typeof pending3.createdAtMs === "number" ? { createdAtMs: pending3.createdAtMs } : {},
|
|
93086
93455
|
stopLoss: {
|
|
93087
93456
|
enabled: sl.enabled,
|
|
93088
93457
|
mode: sl.mode,
|
|
@@ -93093,7 +93462,8 @@ var init_runtime_execution = __esm({
|
|
|
93093
93462
|
enabled: tp.enabled,
|
|
93094
93463
|
mode: tp.mode,
|
|
93095
93464
|
value: Number(tp.value)
|
|
93096
|
-
}
|
|
93465
|
+
},
|
|
93466
|
+
...recovery ? { recovery } : {}
|
|
93097
93467
|
};
|
|
93098
93468
|
}
|
|
93099
93469
|
const attachmentRecord = record5.attachmentJournal;
|
|
@@ -93837,6 +94207,7 @@ var init_runtime_execution = __esm({
|
|
|
93837
94207
|
};
|
|
93838
94208
|
buildPendingProtectivePlan = (settings, input) => ({
|
|
93839
94209
|
...input,
|
|
94210
|
+
createdAtMs: Date.now(),
|
|
93840
94211
|
stopLoss: {
|
|
93841
94212
|
enabled: settings.stopLossEnabled !== false,
|
|
93842
94213
|
mode: settings.stopLossMode === "usdc" ? "usdc" : "percent",
|
|
@@ -94462,7 +94833,7 @@ var init_runtime_execution = __esm({
|
|
|
94462
94833
|
}
|
|
94463
94834
|
return reports;
|
|
94464
94835
|
};
|
|
94465
|
-
resolveJournaledAttachmentContinuity = async (request, group) => {
|
|
94836
|
+
resolveJournaledAttachmentContinuity = async (request, group, options = {}) => {
|
|
94466
94837
|
const journal = group.attachmentJournal;
|
|
94467
94838
|
const plan = group.pendingEntry;
|
|
94468
94839
|
if (journal == null || plan == null) {
|
|
@@ -94559,7 +94930,7 @@ var init_runtime_execution = __esm({
|
|
|
94559
94930
|
throw new Error("Journaled protective entry chronology is unresolved.");
|
|
94560
94931
|
}
|
|
94561
94932
|
const firstEntry = canonicalRows[firstEntryIndex];
|
|
94562
|
-
if (expectedSign * firstEntry.startPosition < -positionTolerance(firstEntry.startPosition, 0)) {
|
|
94933
|
+
if (options.allowOppositeStart !== true && expectedSign * firstEntry.startPosition < -positionTolerance(firstEntry.startPosition, 0)) {
|
|
94563
94934
|
throw new Error("Journaled protective entry start position is directionally unresolved.");
|
|
94564
94935
|
}
|
|
94565
94936
|
let expectedExposureEstablished = false;
|
|
@@ -94961,20 +95332,117 @@ var init_runtime_execution = __esm({
|
|
|
94961
95332
|
}
|
|
94962
95333
|
return reports;
|
|
94963
95334
|
};
|
|
94964
|
-
|
|
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) => {
|
|
94965
95366
|
const reports = [];
|
|
94966
95367
|
const profileId = String(request.profileId).trim();
|
|
94967
95368
|
const symbol2 = request.executionContext.symbol;
|
|
94968
|
-
|
|
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;
|
|
94969
95383
|
const plan = group.pendingEntry;
|
|
94970
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
|
+
};
|
|
94971
95439
|
try {
|
|
94972
95440
|
if (group.attachmentJournal != null) {
|
|
94973
|
-
const { disposition } = await resolveJournaledAttachmentContinuity(
|
|
95441
|
+
const { disposition: disposition2 } = await resolveJournaledAttachmentContinuity(
|
|
94974
95442
|
request,
|
|
94975
95443
|
group
|
|
94976
95444
|
);
|
|
94977
|
-
if (
|
|
95445
|
+
if (disposition2 !== "matching") {
|
|
94978
95446
|
if (!replaceExactClientProtectiveGroup(profileId, symbol2, group, null)) {
|
|
94979
95447
|
reports.push({
|
|
94980
95448
|
order_id: group.attachmentJournal.entryOrderId,
|
|
@@ -94997,6 +95465,13 @@ var init_runtime_execution = __esm({
|
|
|
94997
95465
|
attachment2.handoffCleanup
|
|
94998
95466
|
);
|
|
94999
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");
|
|
95000
95475
|
continue;
|
|
95001
95476
|
}
|
|
95002
95477
|
const evidence = await fetchBrowserOrderStatusEvidence({
|
|
@@ -95006,12 +95481,102 @@ var init_runtime_execution = __esm({
|
|
|
95006
95481
|
signal: request.signal,
|
|
95007
95482
|
orderId: plan.entryClientOrderId
|
|
95008
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
|
+
}
|
|
95009
95553
|
const expectedSide = plan.entrySide === "buy" ? ["b", "buy"] : ["a", "sell"];
|
|
95010
|
-
const
|
|
95011
|
-
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
|
+
}
|
|
95012
95576
|
if (!shapeMatches || !evidence.terminal) {
|
|
95013
95577
|
throw new Error("Pending entry status or shape is unresolved.");
|
|
95014
95578
|
}
|
|
95579
|
+
if (evidence.fulfilled === true) entryFilled = true;
|
|
95015
95580
|
const { rawFills, evidence: fillEvidence } = await fetchBrowserUserFills({
|
|
95016
95581
|
publicRequestPriority: "trading_reconcile",
|
|
95017
95582
|
config: request.config ?? {},
|
|
@@ -95052,14 +95617,37 @@ var init_runtime_execution = __esm({
|
|
|
95052
95617
|
filledNotional += canonicalSize * canonicalPrice;
|
|
95053
95618
|
}
|
|
95054
95619
|
if (matchingFills.length === 0 && evidence.fulfilled === false) {
|
|
95055
|
-
|
|
95056
|
-
throw new Error("Non-filled pending entry could not be cleared durably.");
|
|
95057
|
-
}
|
|
95620
|
+
retire("pending_protective_entry_unfilled");
|
|
95058
95621
|
continue;
|
|
95059
95622
|
}
|
|
95060
|
-
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) {
|
|
95061
95624
|
throw new Error("Exact pending entry fills are unavailable.");
|
|
95062
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
|
+
}
|
|
95063
95651
|
const attachment = await attachClientProtectivePlan(request, group, {
|
|
95064
95652
|
orderId: String(evidence.orderId),
|
|
95065
95653
|
filledSize,
|
|
@@ -95071,21 +95659,12 @@ var init_runtime_execution = __esm({
|
|
|
95071
95659
|
attachment.handoffCleanup
|
|
95072
95660
|
);
|
|
95073
95661
|
}
|
|
95662
|
+
recordIfStillPending();
|
|
95074
95663
|
} catch (error48) {
|
|
95075
95664
|
if (isClientRuntimeWindowHandoffBeforePlanDispatch(error48) || isClientRuntimeLeaseOwnershipError(error48)) {
|
|
95076
95665
|
throw error48;
|
|
95077
95666
|
}
|
|
95078
|
-
|
|
95079
|
-
order_id: plan.entryClientOrderId,
|
|
95080
|
-
client_mutation_id: plan.entryMutationId,
|
|
95081
|
-
symbol: symbol2,
|
|
95082
|
-
action: "PROTECTIVE_RECONCILIATION",
|
|
95083
|
-
status: "failed",
|
|
95084
|
-
execution_metadata: {
|
|
95085
|
-
reason_code: "pending_protective_entry_unresolved",
|
|
95086
|
-
error: getSanitizedRuntimeErrorMessage(error48) || "Pending entry protection is unresolved."
|
|
95087
|
-
}
|
|
95088
|
-
});
|
|
95667
|
+
recordUnresolved(getSanitizedRuntimeErrorMessage(error48) || "Pending entry protection is unresolved.");
|
|
95089
95668
|
}
|
|
95090
95669
|
}
|
|
95091
95670
|
if (hasClientProtectiveGroupReadFailure(profileId, symbol2)) {
|
|
@@ -95649,11 +96228,10 @@ var init_runtime_execution = __esm({
|
|
|
95649
96228
|
...await recoverJournaledClientProtectiveAttachments(
|
|
95650
96229
|
request,
|
|
95651
96230
|
readClientProtectiveGroups(profileId, symbol2).filter((group) => group.pendingEntry != null && group.legs.length > 0)
|
|
95652
|
-
),
|
|
95653
|
-
...await recoverPendingClientProtectiveGroups(
|
|
95654
|
-
request,
|
|
95655
|
-
readClientProtectiveGroups(profileId, symbol2).filter((group) => group.pendingEntry != null && group.legs.length === 0)
|
|
95656
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.
|
|
95657
96235
|
];
|
|
95658
96236
|
const reconciliationGroupSet = readFreshClientProtectiveGroups(profileId, symbol2);
|
|
95659
96237
|
if (hasClientProtectiveGroupReadFailure(profileId, symbol2)) {
|
|
@@ -96708,6 +97286,18 @@ var init_runtime_execution = __esm({
|
|
|
96708
97286
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
96709
97287
|
});
|
|
96710
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
|
+
};
|
|
96711
97301
|
roundAssetSize = (size, decimals) => {
|
|
96712
97302
|
if (!Number.isFinite(size)) {
|
|
96713
97303
|
return 0;
|
|
@@ -96825,6 +97415,7 @@ var init_runtime_execution = __esm({
|
|
|
96825
97415
|
return pending3;
|
|
96826
97416
|
};
|
|
96827
97417
|
drainServerProtectionForRuntime = async (request, initialActions) => {
|
|
97418
|
+
if (request.executionMode === "server") return;
|
|
96828
97419
|
try {
|
|
96829
97420
|
await drainClientProtectiveActions({
|
|
96830
97421
|
profileId: request.profileId,
|
|
@@ -96909,9 +97500,178 @@ var init_runtime_execution = __esm({
|
|
|
96909
97500
|
if (clientExecutionMutations.get(key) === pending3) clientExecutionMutations.delete(key);
|
|
96910
97501
|
}
|
|
96911
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
|
+
};
|
|
96912
97520
|
withClientProtectiveAdoptionMutation = (profileId, work, signal) => withClientExecutionMutation({ profileId: String(profileId).trim(), signal }, work);
|
|
96913
|
-
|
|
96914
|
-
|
|
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 () => {
|
|
96915
97675
|
const context = request.executionContext;
|
|
96916
97676
|
const capturedAt = Date.parse(context.decisionSnapshotCapturedAt ?? "");
|
|
96917
97677
|
const maxAge = Number(context.executionFreshnessMaxAgeSeconds) * 1e3;
|
|
@@ -96920,15 +97680,11 @@ var init_runtime_execution = __esm({
|
|
|
96920
97680
|
const groups = readFreshClientProtectiveGroups(String(request.profileId).trim(), context.symbol);
|
|
96921
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 [];
|
|
96922
97682
|
if (!groups.some((group) => group.legs.some((leg) => leg.isTrailing && typeof leg.orderId === "number"))) return [];
|
|
96923
|
-
const
|
|
96924
|
-
symbol: context.symbol,
|
|
96925
|
-
config: request.config,
|
|
96926
|
-
publicRequestPriority: "trading_reduce"
|
|
96927
|
-
});
|
|
97683
|
+
const assetSizeDecimals = await resolveExchangeSizeDecimals(context.symbol, request.config ?? void 0, "trading_reduce");
|
|
96928
97684
|
const isLong = context.currentPositionSize > 0;
|
|
96929
97685
|
const improves = groups.some((group) => group.isLong === isLong && group.legs.some((leg) => {
|
|
96930
97686
|
if (!leg.isTrailing || typeof leg.orderId !== "number") return false;
|
|
96931
|
-
const size = roundAssetSize(Math.min(leg.size, Math.abs(context.currentPositionSize)),
|
|
97687
|
+
const size = roundAssetSize(Math.min(leg.size, Math.abs(context.currentPositionSize)), assetSizeDecimals);
|
|
96932
97688
|
if (!(size > 0)) return false;
|
|
96933
97689
|
return resolveTrailingStopTightening({
|
|
96934
97690
|
currentPrice: context.lastPrice,
|
|
@@ -96943,12 +97699,16 @@ var init_runtime_execution = __esm({
|
|
|
96943
97699
|
}));
|
|
96944
97700
|
if (!improves) return [];
|
|
96945
97701
|
await request.beforeTrailingMaintenance?.(request.signal);
|
|
96946
|
-
const guardedRequest = {
|
|
96947
|
-
|
|
96948
|
-
|
|
96949
|
-
|
|
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
|
+
};
|
|
96950
97710
|
return tightenClientTrailingStops({ request: guardedRequest, currentPositionSize: context.currentPositionSize, currentPrice: context.lastPrice });
|
|
96951
|
-
});
|
|
97711
|
+
}, request.signal));
|
|
96952
97712
|
listPendingClientProtectiveSymbols = (profileId) => {
|
|
96953
97713
|
const storage3 = resolveClientRuntimeProtectionStorage();
|
|
96954
97714
|
if (!storage3) return [];
|
|
@@ -97002,11 +97762,7 @@ var init_runtime_execution = __esm({
|
|
|
97002
97762
|
if (!hasUnresolvedClientProtectiveIdentity(groups)) continue;
|
|
97003
97763
|
let symbolReports = [];
|
|
97004
97764
|
try {
|
|
97005
|
-
const
|
|
97006
|
-
symbol: symbol2,
|
|
97007
|
-
config: input.config,
|
|
97008
|
-
publicRequestPriority: "trading_reconcile"
|
|
97009
|
-
});
|
|
97765
|
+
const sizeDecimals = await resolveExchangeSizeDecimals(symbol2, input.config, "trading_reconcile");
|
|
97010
97766
|
const core = {
|
|
97011
97767
|
profileId,
|
|
97012
97768
|
config: input.config,
|
|
@@ -97218,7 +97974,8 @@ var init_runtime_execution = __esm({
|
|
|
97218
97974
|
const results = [];
|
|
97219
97975
|
for (const symbol2 of listPendingClientProtectiveSymbols(profileId)) {
|
|
97220
97976
|
throwIfAborted2(input.signal);
|
|
97221
|
-
const
|
|
97977
|
+
const retired = [];
|
|
97978
|
+
const reports = await withClientExecutionMutation({ profileId, signal: input.signal }, () => withClientProtectivePlanSetLock(profileId, symbol2, async () => {
|
|
97222
97979
|
const groups = readFreshClientProtectiveGroups(profileId, symbol2);
|
|
97223
97980
|
if (hasClientProtectiveGroupReadFailure(profileId, symbol2)) {
|
|
97224
97981
|
return [{
|
|
@@ -97231,14 +97988,7 @@ var init_runtime_execution = __esm({
|
|
|
97231
97988
|
}
|
|
97232
97989
|
const ownGroups = groups.filter((group) => group.pendingEntry != null && group.walletAddress === walletAddress.toLowerCase());
|
|
97233
97990
|
if (ownGroups.length === 0) return [];
|
|
97234
|
-
const
|
|
97235
|
-
symbol: symbol2,
|
|
97236
|
-
config: input.config,
|
|
97237
|
-
publicRequestPriority: "trading_reconcile"
|
|
97238
|
-
});
|
|
97239
|
-
if (!Number.isInteger(sizeDecimals) || sizeDecimals < 0) {
|
|
97240
|
-
throw new Error(`Hyperliquid size precision is unavailable for ${symbol2}.`);
|
|
97241
|
-
}
|
|
97991
|
+
const sizeDecimals = await resolveExchangeSizeDecimals(symbol2, input.config, "trading_reconcile");
|
|
97242
97992
|
const request = {
|
|
97243
97993
|
mutationAuthority: "manual_session",
|
|
97244
97994
|
profileId,
|
|
@@ -97254,21 +98004,100 @@ var init_runtime_execution = __esm({
|
|
|
97254
98004
|
),
|
|
97255
98005
|
...await recoverPendingClientProtectiveGroups(
|
|
97256
98006
|
request,
|
|
97257
|
-
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
|
|
97258
98010
|
)
|
|
97259
98011
|
];
|
|
97260
|
-
});
|
|
97261
|
-
results.push({ symbol: symbol2, reports });
|
|
98012
|
+
}, input.signal));
|
|
98013
|
+
results.push({ symbol: symbol2, reports, ...retired.length > 0 ? { retired } : {} });
|
|
97262
98014
|
}
|
|
97263
98015
|
return results;
|
|
97264
98016
|
};
|
|
97265
|
-
|
|
97266
|
-
|
|
97267
|
-
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));
|
|
97268
98030
|
appendRuntimeDebugEvent({
|
|
97269
98031
|
label: "execution_start",
|
|
97270
|
-
note: `decision=${
|
|
98032
|
+
note: `decision=${unsizedInput.decision} units=${requestedUnits} symbol=${unsizedInput.executionContext.symbol}`
|
|
97271
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);
|
|
97272
98101
|
const decisionSnapshotPositionSize = Number.isFinite(input.executionContext.currentPositionSize) ? Number(input.executionContext.currentPositionSize) : 0;
|
|
97273
98102
|
const decisionSnapshotSignedUnits = signedUnitsFromEntryPosition(
|
|
97274
98103
|
decisionSnapshotPositionSize,
|
|
@@ -97481,7 +98310,52 @@ var init_runtime_execution = __esm({
|
|
|
97481
98310
|
executionSnapshotCapturedAt
|
|
97482
98311
|
};
|
|
97483
98312
|
}
|
|
97484
|
-
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)) {
|
|
97485
98359
|
throwIfAborted2(input.signal);
|
|
97486
98360
|
await executeClientLeverageUpdate({
|
|
97487
98361
|
profileId: input.profileId,
|
|
@@ -97694,9 +98568,7 @@ var init_runtime_execution = __esm({
|
|
|
97694
98568
|
input.executionContext.symbol,
|
|
97695
98569
|
[]
|
|
97696
98570
|
);
|
|
97697
|
-
|
|
97698
|
-
await sleep2(Math.round(input.executionContext.closePositionDelaySeconds * 1e3), input.signal);
|
|
97699
|
-
}
|
|
98571
|
+
await waitForFlipCloseFreshness(input);
|
|
97700
98572
|
throwIfAborted2(input.signal);
|
|
97701
98573
|
await executeClientLeverageUpdate({
|
|
97702
98574
|
profileId: input.profileId,
|
|
@@ -97715,10 +98587,8 @@ var init_runtime_execution = __esm({
|
|
|
97715
98587
|
throwIfAborted2(input.signal);
|
|
97716
98588
|
}
|
|
97717
98589
|
const actualUnits = targetResolution.orderUnits;
|
|
97718
|
-
const
|
|
97719
|
-
|
|
97720
|
-
input.executionContext.sizeDecimals
|
|
97721
|
-
);
|
|
98590
|
+
const intendedSizeAsset = input.executionContext.unitSizeUsdc * actualUnits / executionPrice;
|
|
98591
|
+
const sizeAsset = Number.isFinite(intendedSizeAsset) && intendedSizeAsset > 0 ? quantizeHyperliquidOrderSizeValue(intendedSizeAsset, input.executionContext.sizeDecimals, "nearest") : 0;
|
|
97722
98592
|
appendRuntimeDebugEvent({
|
|
97723
98593
|
label: "execution_size_computed",
|
|
97724
98594
|
note: `symbol=${input.executionContext.symbol} actualUnits=${actualUnits} sizeAsset=${sizeAsset} price=${executionPrice}`
|
|
@@ -97726,7 +98596,7 @@ var init_runtime_execution = __esm({
|
|
|
97726
98596
|
if (sizeAsset <= 0) {
|
|
97727
98597
|
appendRuntimeDebugEvent({
|
|
97728
98598
|
label: "execution_skipped_zero_size",
|
|
97729
|
-
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}`,
|
|
97730
98600
|
outcome: "error"
|
|
97731
98601
|
});
|
|
97732
98602
|
return {
|
|
@@ -97922,6 +98792,9 @@ var init_runtime_execution = __esm({
|
|
|
97922
98792
|
const handoffBeforeDispatch = handoffVeto || !entryDispatchBoundaryPassed && input.shouldCancelBeforeExchangeOrderDispatch?.() === true;
|
|
97923
98793
|
const hasCommittedReports = executionReports.some((report) => report.status === "executed" && String(report.order_id || "").trim().length > 0);
|
|
97924
98794
|
let vetoedProtectionCleanupFailed = false;
|
|
98795
|
+
if (pendingProtectiveGroup != null && entryDispatchBoundaryPassed && pendingProtectiveCleanup != null && isDefinitiveEntryRejection(entryDispatchError, entryMutationId)) {
|
|
98796
|
+
clearClientRuntimeVetoedProtectiveIntent(pendingProtectiveCleanup);
|
|
98797
|
+
}
|
|
97925
98798
|
if (pendingProtectiveGroup != null && !entryDispatchBoundaryPassed) {
|
|
97926
98799
|
if (pendingProtectiveCleanup == null || !clearClientRuntimeVetoedProtectiveIntent(pendingProtectiveCleanup)) {
|
|
97927
98800
|
vetoedProtectionCleanupFailed = true;
|
|
@@ -98875,7 +99748,7 @@ var init_runtime_execution = __esm({
|
|
|
98875
99748
|
});
|
|
98876
99749
|
|
|
98877
99750
|
// lib/runtime/protective-adoption-status.ts
|
|
98878
|
-
var deferrals,
|
|
99751
|
+
var deferrals, listeners2, notify, recordClientProtectiveAdoptionDeferral, clearClientProtectiveAdoptionDeferral;
|
|
98879
99752
|
var init_protective_adoption_status = __esm({
|
|
98880
99753
|
"lib/runtime/protective-adoption-status.ts"() {
|
|
98881
99754
|
"use strict";
|
|
@@ -98883,9 +99756,9 @@ var init_protective_adoption_status = __esm({
|
|
|
98883
99756
|
init_define_VTX_GROK_POLICY();
|
|
98884
99757
|
init_define_VTX_PI_MODEL_POLICY();
|
|
98885
99758
|
deferrals = /* @__PURE__ */ new Map();
|
|
98886
|
-
|
|
99759
|
+
listeners2 = /* @__PURE__ */ new Set();
|
|
98887
99760
|
notify = () => {
|
|
98888
|
-
|
|
99761
|
+
listeners2.forEach((listener) => listener());
|
|
98889
99762
|
};
|
|
98890
99763
|
recordClientProtectiveAdoptionDeferral = (profileId, symbols) => {
|
|
98891
99764
|
deferrals.set(String(profileId).trim(), { deferredAtMs: Date.now(), symbols: [...symbols] });
|
|
@@ -104055,7 +104928,7 @@ var init_inference_observability = __esm({
|
|
|
104055
104928
|
});
|
|
104056
104929
|
|
|
104057
104930
|
// lib/runtime/provider-client.ts
|
|
104058
|
-
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;
|
|
104059
104932
|
var init_provider_client = __esm({
|
|
104060
104933
|
"lib/runtime/provider-client.ts"() {
|
|
104061
104934
|
"use strict";
|
|
@@ -106770,8 +107643,10 @@ var init_provider_client = __esm({
|
|
|
106770
107643
|
toolCalls: response.toolCalls
|
|
106771
107644
|
};
|
|
106772
107645
|
};
|
|
107646
|
+
runtimeProviderInvoker = null;
|
|
106773
107647
|
invokeRuntimeProvider = async (input) => {
|
|
106774
107648
|
if (input.signal?.aborted) throw input.signal.reason ?? new DOMException("Cancelled", "AbortError");
|
|
107649
|
+
if (runtimeProviderInvoker) return runtimeProviderInvoker(input);
|
|
106775
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;
|
|
106776
107651
|
if (policy2) {
|
|
106777
107652
|
const timeoutMs = Math.min(input.timeoutMs ?? policy2.deadline_seconds * 1e3, policy2.deadline_seconds * 1e3);
|
|
@@ -107762,7 +108637,7 @@ var init_reasoning_controls = __esm({
|
|
|
107762
108637
|
return buildNoneReasoningControls();
|
|
107763
108638
|
}
|
|
107764
108639
|
seen.add(key);
|
|
107765
|
-
const
|
|
108640
|
+
const label2 = typeof record5.label === "string" && record5.label.trim() ? record5.label.trim() : void 0;
|
|
107766
108641
|
const nested = normalizeReasoningControls({
|
|
107767
108642
|
...Object.fromEntries(Object.entries(record5).filter(([itemKey]) => !["key", "label"].includes(itemKey))),
|
|
107768
108643
|
schema_version: 1
|
|
@@ -107772,7 +108647,7 @@ var init_reasoning_controls = __esm({
|
|
|
107772
108647
|
}
|
|
107773
108648
|
nestedControls.push({
|
|
107774
108649
|
key,
|
|
107775
|
-
...
|
|
108650
|
+
...label2 ? { label: label2 } : {},
|
|
107776
108651
|
...nested
|
|
107777
108652
|
});
|
|
107778
108653
|
}
|
|
@@ -107937,24 +108812,170 @@ var init_model_controller_provenance = __esm({
|
|
|
107937
108812
|
}
|
|
107938
108813
|
});
|
|
107939
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
|
+
|
|
107940
108953
|
// lib/runtime/local-analysis.ts
|
|
107941
108954
|
var local_analysis_exports = {};
|
|
107942
108955
|
__export(local_analysis_exports, {
|
|
107943
108956
|
ClientRuntimeAgentInstructionEmpty: () => ClientRuntimeAgentInstructionEmpty,
|
|
108957
|
+
ClientRuntimeAiSchedulePaused: () => ClientRuntimeAiSchedulePaused,
|
|
108958
|
+
ClientRuntimeAiScheduleStillActive: () => ClientRuntimeAiScheduleStillActive,
|
|
108959
|
+
ServerDispatchAccountStateStale: () => ServerDispatchAccountStateStale,
|
|
108960
|
+
aiOrderSlippageFraction: () => aiOrderSlippageFraction,
|
|
107944
108961
|
buildLocalRuntimePromptArtifacts: () => buildLocalRuntimePromptArtifacts,
|
|
107945
108962
|
buildPromptBehaviorStateArtifacts: () => buildPromptBehaviorStateArtifacts,
|
|
107946
108963
|
buildPromptBehaviorStateValue: () => buildPromptBehaviorStateValue,
|
|
107947
108964
|
derivePromptVisibleSections: () => derivePromptVisibleSections,
|
|
107948
108965
|
isClientRuntimeAgentInstructionEmpty: () => isClientRuntimeAgentInstructionEmpty,
|
|
108966
|
+
isClientRuntimeAiSchedulePaused: () => isClientRuntimeAiSchedulePaused,
|
|
108967
|
+
isClientRuntimeAiScheduleStillActive: () => isClientRuntimeAiScheduleStillActive,
|
|
108968
|
+
isServerDispatchAccountStateStale: () => isServerDispatchAccountStateStale,
|
|
107949
108969
|
resolveEffectivePromptRuntimeProvenance: () => resolveEffectivePromptRuntimeProvenance,
|
|
107950
108970
|
resolveExternalInferenceRuntimeTimeoutSeconds: () => resolveExternalInferenceRuntimeTimeoutSeconds,
|
|
107951
108971
|
resolveLocalRuntimeSecretProvider: () => resolveLocalRuntimeSecretProvider,
|
|
107952
108972
|
resolveLocalRuntimeSecretRequirements: () => resolveLocalRuntimeSecretRequirements,
|
|
107953
108973
|
resolveNativeValuesForModel: () => resolveNativeValuesForModel,
|
|
107954
108974
|
runLocalRuntimeCycle: () => runLocalRuntimeCycle,
|
|
108975
|
+
serverPerpDexScope: () => serverPerpDexScope,
|
|
107955
108976
|
summarizeReviewFailureExplanation: () => summarizeReviewFailureExplanation
|
|
107956
108977
|
});
|
|
107957
|
-
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;
|
|
107958
108979
|
var init_local_analysis = __esm({
|
|
107959
108980
|
"lib/runtime/local-analysis.ts"() {
|
|
107960
108981
|
"use strict";
|
|
@@ -107994,6 +109015,7 @@ var init_local_analysis = __esm({
|
|
|
107994
109015
|
init_hyperliquid_market_symbol();
|
|
107995
109016
|
init_external_inference_contract();
|
|
107996
109017
|
init_model_controller_provenance();
|
|
109018
|
+
init_ai_schedule();
|
|
107997
109019
|
normalizeNativeValues = (value) => {
|
|
107998
109020
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
107999
109021
|
const entries = {};
|
|
@@ -108062,6 +109084,29 @@ var init_local_analysis = __esm({
|
|
|
108062
109084
|
}
|
|
108063
109085
|
});
|
|
108064
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
|
+
};
|
|
108065
109110
|
ClientRuntimeAgentInstructionEmpty = class extends Error {
|
|
108066
109111
|
constructor(retryAfterMs) {
|
|
108067
109112
|
super("No Agent instruction is currently queued for this Client runtime.");
|
|
@@ -108070,6 +109115,31 @@ var init_local_analysis = __esm({
|
|
|
108070
109115
|
}
|
|
108071
109116
|
};
|
|
108072
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;
|
|
108073
109143
|
buildClaimedAgentRuntimeCycleResult = async (input) => {
|
|
108074
109144
|
const { config: config2, settings, instruction, runtimeInput, signal } = input;
|
|
108075
109145
|
const binding = runtimeInput.runtimeContractBinding;
|
|
@@ -108106,6 +109176,7 @@ var init_local_analysis = __esm({
|
|
|
108106
109176
|
tickerPrice: 0,
|
|
108107
109177
|
leverage,
|
|
108108
109178
|
aggregatePerpDexs: true,
|
|
109179
|
+
perpDexScope: serverPerpDexScope(symbols, runtimeInput.executionMode),
|
|
108109
109180
|
feeSymbols: symbols,
|
|
108110
109181
|
includeEffectiveTakerRate: true,
|
|
108111
109182
|
sessionId: String(runtimeInput.sessionId || "").trim(),
|
|
@@ -108200,11 +109271,11 @@ var init_local_analysis = __esm({
|
|
|
108200
109271
|
walletAddress,
|
|
108201
109272
|
lastPrice: price,
|
|
108202
109273
|
unitSizeUsdc: tradeSize,
|
|
108203
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
108204
109274
|
leverage,
|
|
108205
109275
|
marginMode,
|
|
108206
109276
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
108207
|
-
|
|
109277
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
109278
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, runtimeInput.executionMode),
|
|
108208
109279
|
...buildRuntimeSlTpExecutionSettings(settings, config2)
|
|
108209
109280
|
};
|
|
108210
109281
|
};
|
|
@@ -109554,14 +110625,14 @@ ${reviewOutputContract}`;
|
|
|
109554
110625
|
const normalized = String(value || "").replace(/\s+/g, " ").trim();
|
|
109555
110626
|
return normalized.length > 0 ? normalized : null;
|
|
109556
110627
|
};
|
|
109557
|
-
appendRuntimeTimingEvent = (
|
|
110628
|
+
appendRuntimeTimingEvent = (label2, startedAtMs, note, outcome) => {
|
|
109558
110629
|
const parts = [`duration=${formatRuntimeDurationMs(Date.now() - startedAtMs)}`];
|
|
109559
110630
|
const normalizedNote = normalizeRuntimeTimingNote(note);
|
|
109560
110631
|
if (normalizedNote) {
|
|
109561
110632
|
parts.push(normalizedNote);
|
|
109562
110633
|
}
|
|
109563
110634
|
appendRuntimeDebugEvent({
|
|
109564
|
-
label,
|
|
110635
|
+
label: label2,
|
|
109565
110636
|
note: parts.join(" "),
|
|
109566
110637
|
outcome
|
|
109567
110638
|
});
|
|
@@ -111040,17 +112111,17 @@ ${behaviorJson}
|
|
|
111040
112111
|
}
|
|
111041
112112
|
return hasValue(secrets.providerKeys[provider]) || hasSlotValue(secrets.providerKeySlots?.[provider]);
|
|
111042
112113
|
};
|
|
111043
|
-
requireNonEmptyStringField = (value,
|
|
112114
|
+
requireNonEmptyStringField = (value, label2) => {
|
|
111044
112115
|
const normalized = String(value ?? "").trim();
|
|
111045
112116
|
if (!normalized) {
|
|
111046
|
-
throw new Error(`Missing required prompt contract field: ${
|
|
112117
|
+
throw new Error(`Missing required prompt contract field: ${label2}`);
|
|
111047
112118
|
}
|
|
111048
112119
|
return normalized;
|
|
111049
112120
|
};
|
|
111050
|
-
requirePositiveIntegerField = (value,
|
|
112121
|
+
requirePositiveIntegerField = (value, label2) => {
|
|
111051
112122
|
const parsed = Number(value);
|
|
111052
112123
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
111053
|
-
throw new Error(`Missing required positive prompt contract field: ${
|
|
112124
|
+
throw new Error(`Missing required positive prompt contract field: ${label2}`);
|
|
111054
112125
|
}
|
|
111055
112126
|
return Math.trunc(parsed);
|
|
111056
112127
|
};
|
|
@@ -111800,6 +112871,25 @@ ${behaviorJson}
|
|
|
111800
112871
|
}
|
|
111801
112872
|
const config2 = configResult.value;
|
|
111802
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
|
+
}
|
|
111803
112893
|
input = {
|
|
111804
112894
|
...input,
|
|
111805
112895
|
secrets: await ClientVault.refreshProviderSecretsForVersion(
|
|
@@ -111977,11 +113067,11 @@ ${behaviorJson}
|
|
|
111977
113067
|
walletAddress: String(settings.hyperliquid_wallet_address || "").trim() || void 0,
|
|
111978
113068
|
lastPrice: 0,
|
|
111979
113069
|
unitSizeUsdc: clampNumber(promptKnobs2.trade_size, config2.default_ai_trade_amount),
|
|
111980
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
111981
113070
|
leverage: clampNumber(promptKnobs2.leverage, config2.default_leverage),
|
|
111982
113071
|
marginMode: resolveRuntimeMarginModePreference(settings, config2),
|
|
111983
113072
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
111984
|
-
|
|
113073
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113074
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
111985
113075
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
111986
113076
|
executionFreshnessMaxAgeSeconds: requirePositiveIntegerField(
|
|
111987
113077
|
promptKnobs2.execution_decision_max_age_seconds,
|
|
@@ -112002,6 +113092,8 @@ ${behaviorJson}
|
|
|
112002
113092
|
let _latestPerpDexAccounts = null;
|
|
112003
113093
|
let latestPositions = [];
|
|
112004
113094
|
let _accountStateResolvedAtMs = null;
|
|
113095
|
+
let _accountStateFetchedAtMs = null;
|
|
113096
|
+
let _accountStateSource = null;
|
|
112005
113097
|
const getLatestAccountEquity = () => _latestAccountEquity;
|
|
112006
113098
|
const getLatestTotalUnrealizedPnl = () => _latestTotalUnrealizedPnl;
|
|
112007
113099
|
const getAccountStateResolvedAtMs = () => _accountStateResolvedAtMs;
|
|
@@ -112015,8 +113107,12 @@ ${behaviorJson}
|
|
|
112015
113107
|
tickerPrice: 0,
|
|
112016
113108
|
leverage: resolveRuntimeLeveragePreference(settings, config2),
|
|
112017
113109
|
aggregatePerpDexs: true,
|
|
113110
|
+
perpDexScope: serverPerpDexScope(symbols, input.executionMode),
|
|
112018
113111
|
feeSymbols: symbols,
|
|
112019
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",
|
|
112020
113116
|
sessionId,
|
|
112021
113117
|
signal: timeoutController.signal
|
|
112022
113118
|
}).then((state2) => {
|
|
@@ -112024,6 +113120,8 @@ ${behaviorJson}
|
|
|
112024
113120
|
latestPositions = state2.positions;
|
|
112025
113121
|
const resolvedEquity = Number(state2.accountSummary?.account_value) || 0;
|
|
112026
113122
|
_accountStateResolvedAtMs = Date.now();
|
|
113123
|
+
_accountStateFetchedAtMs = state2.evidence?.fetchedAtMs ?? _accountStateResolvedAtMs;
|
|
113124
|
+
_accountStateSource = state2.evidence?.source ?? null;
|
|
112027
113125
|
if (resolvedEquity > 0) {
|
|
112028
113126
|
_latestAccountEquity = resolvedEquity;
|
|
112029
113127
|
_latestPerpDexAccounts = state2.accountSummary?.perp_dex_accounts ?? null;
|
|
@@ -112050,7 +113148,8 @@ ${behaviorJson}
|
|
|
112050
113148
|
});
|
|
112051
113149
|
const browserAccountStatePromise = settleRuntimeCyclePromise(browserAccountStateTask);
|
|
112052
113150
|
const browserUserFillsStartedAtMs = Date.now();
|
|
112053
|
-
const
|
|
113151
|
+
const serverOwnsBehaviorState = input.executionMode === "server";
|
|
113152
|
+
const browserUserFillsTask = serverOwnsBehaviorState ? Promise.resolve(null) : fetchBrowserUserFills({
|
|
112054
113153
|
publicRequestPriority: "trading_analysis",
|
|
112055
113154
|
config: config2,
|
|
112056
113155
|
walletAddress,
|
|
@@ -112085,7 +113184,7 @@ ${behaviorJson}
|
|
|
112085
113184
|
getLatestAccountEquity,
|
|
112086
113185
|
getLatestTotalUnrealizedPnl,
|
|
112087
113186
|
getAccountStateResolvedAtMs,
|
|
112088
|
-
async () => {
|
|
113187
|
+
serverOwnsBehaviorState ? void 0 : async () => {
|
|
112089
113188
|
const result = unwrapRuntimeCycleSettledResult(await browserUserFillsPromise);
|
|
112090
113189
|
return { fills: result.rawFills, evidence: result.evidence };
|
|
112091
113190
|
},
|
|
@@ -112113,12 +113212,14 @@ ${behaviorJson}
|
|
|
112113
113212
|
sortedTimeframes.map(async (marketTimeframe) => [
|
|
112114
113213
|
marketTimeframe,
|
|
112115
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.
|
|
112116
113217
|
Math.max(getPromptLookback(
|
|
112117
113218
|
lookbackSettings,
|
|
112118
113219
|
marketTimeframe,
|
|
112119
113220
|
effectiveDefaultLookbacks,
|
|
112120
113221
|
config2.max_analysis_lookback
|
|
112121
|
-
), 250),
|
|
113222
|
+
), Number(config2.indicator_candle_count) || 250),
|
|
112122
113223
|
"hyperliquid",
|
|
112123
113224
|
marketSymbol,
|
|
112124
113225
|
marketTimeframe,
|
|
@@ -112215,11 +113316,11 @@ ${behaviorJson}
|
|
|
112215
113316
|
walletAddress: String(settings.hyperliquid_wallet_address || "").trim() || void 0,
|
|
112216
113317
|
lastPrice: toPositiveFinite3(ticker.price) ?? 0,
|
|
112217
113318
|
unitSizeUsdc: clampNumber(rejectedPromptKnobs.trade_size, config2.default_ai_trade_amount),
|
|
112218
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
112219
113319
|
leverage: clampNumber(rejectedPromptKnobs.leverage, config2.default_leverage),
|
|
112220
113320
|
marginMode: resolveRuntimeMarginModePreference(settings, config2),
|
|
112221
113321
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
112222
|
-
|
|
113322
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113323
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
112223
113324
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
112224
113325
|
executionFreshnessMaxAgeSeconds: requirePositiveIntegerField(
|
|
112225
113326
|
rejectedPromptKnobs.execution_decision_max_age_seconds,
|
|
@@ -112244,8 +113345,8 @@ ${behaviorJson}
|
|
|
112244
113345
|
positions
|
|
112245
113346
|
) ?? browserAccountState.accountSummary.total_unrealized_pnl
|
|
112246
113347
|
};
|
|
112247
|
-
tradeHistory = browserUserFills
|
|
112248
|
-
if (input.mode === "trader" && browserUserFills
|
|
113348
|
+
tradeHistory = browserUserFills?.tradeHistory ?? [];
|
|
113349
|
+
if (input.mode === "trader" && !serverOwnsBehaviorState && browserUserFills?.evidence?.source !== "live") {
|
|
112249
113350
|
throw new CriticalBehaviorStateError();
|
|
112250
113351
|
}
|
|
112251
113352
|
const metadataSymbol = requireNonEmptyStringField(promptMetadata.symbol, "symbol");
|
|
@@ -112540,11 +113641,11 @@ ${behaviorJson}
|
|
|
112540
113641
|
if (input.mode === "trader" && !behaviorMemoryEnabled) {
|
|
112541
113642
|
throw new CriticalBehaviorStateError();
|
|
112542
113643
|
}
|
|
112543
|
-
const browserFillEvidence = browserUserFills
|
|
113644
|
+
const browserFillEvidence = browserUserFills?.evidence;
|
|
112544
113645
|
const behaviorFillCoverage = browserFillEvidence?.source === "live" && browserFillEvidence.exactTerminalFillEvidenceComplete === true ? "complete" : "capped";
|
|
112545
113646
|
let behaviorStateArtifacts;
|
|
112546
113647
|
try {
|
|
112547
|
-
behaviorStateArtifacts = buildPromptBehaviorStateArtifacts({
|
|
113648
|
+
behaviorStateArtifacts = serverOwnsBehaviorState ? serverBehaviorStateArtifacts(derivedContext) : buildPromptBehaviorStateArtifacts({
|
|
112548
113649
|
fills: tradeHistory,
|
|
112549
113650
|
positions,
|
|
112550
113651
|
symbols: promptSymbols,
|
|
@@ -112632,11 +113733,11 @@ ${stringifyPromptJson(candlesPayload)}
|
|
|
112632
113733
|
walletAddress: walletAddress || void 0,
|
|
112633
113734
|
lastPrice: 0,
|
|
112634
113735
|
unitSizeUsdc: metadataTradeSize,
|
|
112635
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
112636
113736
|
leverage: metadataLeverage,
|
|
112637
113737
|
marginMode: resolveRuntimeMarginModePreference(settings, config2),
|
|
112638
113738
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
112639
|
-
|
|
113739
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113740
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
112640
113741
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
112641
113742
|
executionFreshnessMaxAgeSeconds
|
|
112642
113743
|
}
|
|
@@ -112758,11 +113859,11 @@ ${stringifyPromptJson(candlesPayload)}
|
|
|
112758
113859
|
walletAddress: String(settings.hyperliquid_wallet_address || "").trim() || void 0,
|
|
112759
113860
|
lastPrice: executionPrice,
|
|
112760
113861
|
unitSizeUsdc: metadataTradeSize,
|
|
112761
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
112762
113862
|
leverage: metadataLeverage,
|
|
112763
113863
|
marginMode: resolveRuntimeMarginModePreference(settings, config2),
|
|
112764
113864
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
112765
|
-
|
|
113865
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113866
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
112766
113867
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
112767
113868
|
executionFreshnessMaxAgeSeconds
|
|
112768
113869
|
}
|
|
@@ -112788,11 +113889,11 @@ ${stringifyPromptJson(candlesPayload)}
|
|
|
112788
113889
|
walletAddress: String(settings.hyperliquid_wallet_address || "").trim() || void 0,
|
|
112789
113890
|
lastPrice: planPrice,
|
|
112790
113891
|
unitSizeUsdc: metadataTradeSize,
|
|
112791
|
-
sizeDecimals: Number(config2.default_size_decimals),
|
|
112792
113892
|
leverage: metadataLeverage,
|
|
112793
113893
|
marginMode,
|
|
112794
113894
|
closePositionDelaySeconds: Number(config2.client_runtime_close_position_delay_seconds),
|
|
112795
|
-
|
|
113895
|
+
closePositionFreshnessPollMs: Number(config2.close_position_freshness_poll_milliseconds),
|
|
113896
|
+
maxSlippageFraction: aiOrderSlippageFraction(config2, input.executionMode),
|
|
112796
113897
|
...buildRuntimeSlTpExecutionSettings(settings, config2),
|
|
112797
113898
|
executionFreshnessMaxAgeSeconds
|
|
112798
113899
|
};
|
|
@@ -112945,6 +114046,17 @@ ${stringifyPromptJson(candlesPayload)}
|
|
|
112945
114046
|
note: `lane=main seconds=${requestTimeoutSeconds}`
|
|
112946
114047
|
});
|
|
112947
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
|
+
}
|
|
112948
114060
|
const providerStartedAtMs = Date.now();
|
|
112949
114061
|
observeRuntimeCycle(input, { stage: "model", reason_code: null });
|
|
112950
114062
|
let selectedPrimaryModel = authoritativeModel;
|
|
@@ -113855,7 +114967,7 @@ ${reviewOutputContract}`;
|
|
|
113855
114967
|
executionPlans: acceptedExecutionPlans
|
|
113856
114968
|
});
|
|
113857
114969
|
} catch (error48) {
|
|
113858
|
-
if (isClientRuntimeAgentInstructionEmpty(error48)) {
|
|
114970
|
+
if (isClientRuntimeAgentInstructionEmpty(error48) || isClientRuntimeAiSchedulePaused(error48) || isClientRuntimeAiScheduleStillActive(error48)) {
|
|
113859
114971
|
throw error48;
|
|
113860
114972
|
}
|
|
113861
114973
|
if (error48 instanceof PromptContractFetchError && error48.metadata) {
|
|
@@ -113886,8 +114998,8 @@ ${reviewOutputContract}`;
|
|
|
113886
114998
|
const detail = error48 instanceof Error ? error48.message : String(error48);
|
|
113887
114999
|
appendRuntimeTimingEvent("analysis_cycle_failed", cycleStartedAtMs, detail, "error");
|
|
113888
115000
|
if (isAbortError(error48)) {
|
|
113889
|
-
const
|
|
113890
|
-
if (isRuntimeTimeoutAbortReason(
|
|
115001
|
+
const abortReason2 = timeoutController.signal.reason;
|
|
115002
|
+
if (isRuntimeTimeoutAbortReason(abortReason2)) {
|
|
113891
115003
|
const timeoutError = Object.assign(
|
|
113892
115004
|
new Error("Client runtime analysis timed out before the provider returned a result.", { cause: error48 }),
|
|
113893
115005
|
error48,
|
|
@@ -113895,8 +115007,8 @@ ${reviewOutputContract}`;
|
|
|
113895
115007
|
);
|
|
113896
115008
|
throw cycleErrorProvenance ? attachClientRuntimeErrorProvenance(timeoutError, cycleErrorProvenance) : timeoutError;
|
|
113897
115009
|
}
|
|
113898
|
-
if (
|
|
113899
|
-
throw cycleErrorProvenance ? attachClientRuntimeErrorProvenance(
|
|
115010
|
+
if (abortReason2 instanceof Error) {
|
|
115011
|
+
throw cycleErrorProvenance ? attachClientRuntimeErrorProvenance(abortReason2, cycleErrorProvenance) : abortReason2;
|
|
113900
115012
|
}
|
|
113901
115013
|
throw cycleErrorProvenance ? attachClientRuntimeErrorProvenance(error48, cycleErrorProvenance) : error48;
|
|
113902
115014
|
}
|
|
@@ -113912,7 +115024,7 @@ ${reviewOutputContract}`;
|
|
|
113912
115024
|
});
|
|
113913
115025
|
|
|
113914
115026
|
// lib/runtime/engine.ts
|
|
113915
|
-
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;
|
|
113916
115028
|
var init_engine = __esm({
|
|
113917
115029
|
"lib/runtime/engine.ts"() {
|
|
113918
115030
|
"use strict";
|
|
@@ -114293,6 +115405,28 @@ var init_engine = __esm({
|
|
|
114293
115405
|
}
|
|
114294
115406
|
return options;
|
|
114295
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
|
+
});
|
|
114296
115430
|
CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX = "vtx_client_runtime_killswitch_block_v1:";
|
|
114297
115431
|
getClientKillswitchBlockStorageKey = (profileId) => `${CLIENT_KILLSWITCH_BLOCK_STORAGE_PREFIX}${profileId.trim()}`;
|
|
114298
115432
|
persistClientRuntimeKillswitchBlock = (profileId) => {
|
|
@@ -114526,6 +115660,20 @@ var init_engine = __esm({
|
|
|
114526
115660
|
this._startupPendingAnalysis = false;
|
|
114527
115661
|
// True while the previous cycle ended in Agent-instruction polling.
|
|
114528
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;
|
|
114529
115677
|
// Cycle whose Agent-instruction claim is currently held open by the server.
|
|
114530
115678
|
// That idle wait is not analysis, so busy flags exclude it.
|
|
114531
115679
|
this._agentInstructionClaimWaitRequestId = null;
|
|
@@ -114549,6 +115697,8 @@ var init_engine = __esm({
|
|
|
114549
115697
|
this._primaryAnalysisDisabled = false;
|
|
114550
115698
|
this._loopEarlyReturnRetryDelayMs = 5e3;
|
|
114551
115699
|
this._executionModeMismatchConsecutiveCount = 0;
|
|
115700
|
+
this._expectedExecutionMode = "client";
|
|
115701
|
+
this._settleUnreportedModelCalls = null;
|
|
114552
115702
|
this._activeRuntimeContractIdentity = null;
|
|
114553
115703
|
this._contractRebindInFlight = false;
|
|
114554
115704
|
this._contractRebindExhausted = false;
|
|
@@ -114716,6 +115866,57 @@ var init_engine = __esm({
|
|
|
114716
115866
|
}
|
|
114717
115867
|
return pending3.length === 0;
|
|
114718
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
|
+
}
|
|
114719
115920
|
async _assertFreshClientWalletAssignment(profileId, expectedWalletAddress, signal, stage) {
|
|
114720
115921
|
const expectedWallet = String(expectedWalletAddress || "").trim().toLowerCase();
|
|
114721
115922
|
if (!expectedWallet) {
|
|
@@ -114755,7 +115956,9 @@ var init_engine = __esm({
|
|
|
114755
115956
|
const status = await getAiTradingStatus(void 0, Number(this._profileId), {
|
|
114756
115957
|
runtimeViewer: this._runtimeStatusViewer()
|
|
114757
115958
|
});
|
|
114758
|
-
|
|
115959
|
+
const statusMode = status?.execution_mode;
|
|
115960
|
+
const expectedMode = this._expectedExecutionMode === "server" ? String(statusMode ?? "").trim().toLowerCase() === "server" : isExplicitClientExecutionMode(statusMode);
|
|
115961
|
+
if (!expectedMode) {
|
|
114759
115962
|
this._executionModeMismatchConsecutiveCount += 1;
|
|
114760
115963
|
return this._executionModeMismatchConsecutiveCount >= 2;
|
|
114761
115964
|
}
|
|
@@ -115297,6 +116500,7 @@ var init_engine = __esm({
|
|
|
115297
116500
|
}
|
|
115298
116501
|
_armExecutionLoopTimer(options) {
|
|
115299
116502
|
this._clearExecutionLoopTimer();
|
|
116503
|
+
if (options?.reason !== "ai_schedule_window_end") this._aiScheduleCheckPending = false;
|
|
115300
116504
|
if (this._state !== "running" || this._loopIntervalMs == null) {
|
|
115301
116505
|
return;
|
|
115302
116506
|
}
|
|
@@ -115318,7 +116522,7 @@ var init_engine = __esm({
|
|
|
115318
116522
|
const timerReason = options?.reason || "scheduled";
|
|
115319
116523
|
const armedAtMs = Date.now();
|
|
115320
116524
|
const expectedFireAtMs = armedAtMs + delayMs;
|
|
115321
|
-
const quietAgentPollTimer = timerReason === "agent_instruction_poll";
|
|
116525
|
+
const quietAgentPollTimer = timerReason === "agent_instruction_poll" || timerReason === "ai_schedule_paused";
|
|
115322
116526
|
if (!quietAgentPollTimer) this._emitLoopBoundaryTelemetry("client_timer_armed", `reason=${options?.reason || "scheduled"} delay_ms=${delayMs}`, {
|
|
115323
116527
|
reason: timerReason,
|
|
115324
116528
|
delay_ms: delayMs,
|
|
@@ -115327,7 +116531,13 @@ var init_engine = __esm({
|
|
|
115327
116531
|
timer_expected_fire_at_ms: expectedFireAtMs,
|
|
115328
116532
|
// Terminal cycle evidence already records its next schedule. Retain the
|
|
115329
116533
|
// initial/repaired schedule too, even if its first cycle never starts.
|
|
115330
|
-
...[
|
|
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: {
|
|
115331
116541
|
version: 1,
|
|
115332
116542
|
runtime_source: "client",
|
|
115333
116543
|
mode: this._mode,
|
|
@@ -115570,6 +116780,24 @@ var init_engine = __esm({
|
|
|
115570
116780
|
return this._instanceId;
|
|
115571
116781
|
}
|
|
115572
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
|
+
}
|
|
115573
116801
|
get active() {
|
|
115574
116802
|
return this._startPromise !== null || this._isStopping || this._state === "running" || this._state === "stale" || this._state === "offline";
|
|
115575
116803
|
}
|
|
@@ -115596,12 +116824,20 @@ var init_engine = __esm({
|
|
|
115596
116824
|
await this.relinquishControl("window");
|
|
115597
116825
|
}
|
|
115598
116826
|
async _attachInternal(profileId, grant, options, startController) {
|
|
116827
|
+
this._aiSchedulePaused = false;
|
|
116828
|
+
this._aiScheduleWindowActive = false;
|
|
116829
|
+
this._aiScheduleWindowEndsAtMs = null;
|
|
115599
116830
|
const lease = grant.lease;
|
|
115600
116831
|
const grantSessionId = String(lease.runtime_session_id || "").trim();
|
|
115601
116832
|
const grantDeviceId = String(lease.device_id || "").trim();
|
|
115602
116833
|
if (String(lease.profile_id) !== String(profileId) || !grantSessionId || !grantDeviceId) {
|
|
115603
116834
|
throw new Error("The runtime grant does not belong to this profile.");
|
|
115604
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;
|
|
115605
116841
|
const leaseSchedulerInstanceId = String(lease.scheduler_instance_id ?? "").trim();
|
|
115606
116842
|
if (leaseSchedulerInstanceId !== this._instanceId && !(leaseSchedulerInstanceId === "" && options.unboundSchedulerLease === true)) {
|
|
115607
116843
|
throw createRuntimeStartCancelledError("scheduler_instance_binding_missing", {
|
|
@@ -115621,7 +116857,8 @@ var init_engine = __esm({
|
|
|
115621
116857
|
this._sessionId = grantSessionId;
|
|
115622
116858
|
this._deviceId = grantDeviceId;
|
|
115623
116859
|
this._mode = lease.mode === "assistant" ? "assistant" : "trader";
|
|
115624
|
-
|
|
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();
|
|
115625
116862
|
this._lastAnalysisStartedAtMs = null;
|
|
115626
116863
|
this._lastError = null;
|
|
115627
116864
|
this._lastStopReason = null;
|
|
@@ -115747,7 +116984,10 @@ var init_engine = __esm({
|
|
|
115747
116984
|
return;
|
|
115748
116985
|
}
|
|
115749
116986
|
this._assertStartAttemptActive(startController, "before_execution_loop");
|
|
115750
|
-
if (waitsForAssignedStartPhase) {
|
|
116987
|
+
if (waitsForAssignedStartPhase && this._expectedExecutionMode === "server" && this._mode === "trader") {
|
|
116988
|
+
this._aiScheduleCheckPending = true;
|
|
116989
|
+
void this._runExecutionLoop();
|
|
116990
|
+
} else if (waitsForAssignedStartPhase) {
|
|
115751
116991
|
this._armExecutionLoopTimer({ alignToNextRun: true, reason: "assigned_start_phase" });
|
|
115752
116992
|
} else {
|
|
115753
116993
|
this._armExecutionLoopTimer({ alignToNextRun: true });
|
|
@@ -116403,10 +117643,13 @@ var init_engine = __esm({
|
|
|
116403
117643
|
}
|
|
116404
117644
|
await this.relinquishControl(reason);
|
|
116405
117645
|
}
|
|
116406
|
-
async triggerNow() {
|
|
117646
|
+
async triggerNow(options) {
|
|
116407
117647
|
if (this._state !== "running") {
|
|
116408
117648
|
throw new Error("AI runtime is not running on this client.");
|
|
116409
117649
|
}
|
|
117650
|
+
if ((options?.ignoreAiSchedule ?? true) && (!this._executionLoopPromise || this._aiSchedulePaused || this._checkOnlyCycleInFlight)) {
|
|
117651
|
+
this._manualRunRequested = true;
|
|
117652
|
+
}
|
|
116410
117653
|
await this._runExecutionLoop();
|
|
116411
117654
|
}
|
|
116412
117655
|
_abortTrailingMaintenanceBeforeDispatch() {
|
|
@@ -116517,6 +117760,19 @@ var init_engine = __esm({
|
|
|
116517
117760
|
this._pendingProtectionRecoveryDispatched = true;
|
|
116518
117761
|
}
|
|
116519
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
|
+
}
|
|
116520
117776
|
if (results.length) {
|
|
116521
117777
|
appendRuntimeDebugEvent({
|
|
116522
117778
|
label: "pending_protection_recovery",
|
|
@@ -116779,10 +118035,22 @@ var init_engine = __esm({
|
|
|
116779
118035
|
const analysisAbortController = new AbortController();
|
|
116780
118036
|
this._analysisAbortController = analysisAbortController;
|
|
116781
118037
|
let decisionSubmitted = false;
|
|
118038
|
+
let cycleModelCalls = [];
|
|
118039
|
+
let cycleModelCallsReported = false;
|
|
116782
118040
|
let executedExchangeOrderInCycle = false;
|
|
116783
118041
|
let pendingExternalInferenceBindings = [];
|
|
116784
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;
|
|
116785
118052
|
const agentPollContinuation = this._agentInstructionPollActive;
|
|
118053
|
+
const aiSchedulePauseContinuation = this._aiSchedulePaused || aiScheduleCheckOnly;
|
|
116786
118054
|
let cycleStartEmitted = false;
|
|
116787
118055
|
let cycleErrorProvenance = null;
|
|
116788
118056
|
let cycleWorkStarted = false;
|
|
@@ -116857,15 +118125,35 @@ var init_engine = __esm({
|
|
|
116857
118125
|
this._notifyListeners();
|
|
116858
118126
|
void this.sendHeartbeat();
|
|
116859
118127
|
};
|
|
116860
|
-
if (!agentPollContinuation) emitCycleStarted();
|
|
118128
|
+
if (!agentPollContinuation && !aiSchedulePauseContinuation) emitCycleStarted();
|
|
116861
118129
|
try {
|
|
116862
|
-
|
|
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
|
+
}
|
|
116863
118150
|
if (analysisAbortController.signal.aborted || this._isStopping || this._analysisRequestId !== requestId) {
|
|
116864
118151
|
throw new DOMException("The operation was aborted.", "AbortError");
|
|
116865
118152
|
}
|
|
116866
118153
|
if (savedSecrets) {
|
|
116867
118154
|
deviceSecrets = {
|
|
116868
118155
|
...deviceSecrets,
|
|
118156
|
+
...serverSigningKey ? { hyperliquidSigningKey: serverSigningKey } : {},
|
|
116869
118157
|
providerKeys: savedSecrets.providerKeys ?? {},
|
|
116870
118158
|
providerKeySlots: savedSecrets.providerKeySlots,
|
|
116871
118159
|
providerBaseUrls: savedSecrets.providerBaseUrls,
|
|
@@ -116912,6 +118200,18 @@ var init_engine = __esm({
|
|
|
116912
118200
|
}
|
|
116913
118201
|
},
|
|
116914
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,
|
|
116915
118215
|
onPreparedExecutionContexts: async ({ config: config2, executionContexts }) => {
|
|
116916
118216
|
if (runtimeMode !== "trader") return;
|
|
116917
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;
|
|
@@ -116940,10 +118240,74 @@ var init_engine = __esm({
|
|
|
116940
118240
|
},
|
|
116941
118241
|
signal: analysisAbortController.signal
|
|
116942
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
|
+
});
|
|
116943
118250
|
let result;
|
|
116944
118251
|
try {
|
|
116945
|
-
result = await
|
|
118252
|
+
result = await runCycleWithDispatchFreshness(deviceSecrets);
|
|
116946
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
|
+
}
|
|
116947
118311
|
if (localAnalysis.isClientRuntimeAgentInstructionEmpty(error48)) {
|
|
116948
118312
|
cycleOutcome = "skipped";
|
|
116949
118313
|
cycleReason = "agent_instruction_poll_empty";
|
|
@@ -116981,7 +118345,7 @@ var init_engine = __esm({
|
|
|
116981
118345
|
throw error48;
|
|
116982
118346
|
}
|
|
116983
118347
|
try {
|
|
116984
|
-
result = await
|
|
118348
|
+
result = await runCycleWithDispatchFreshness(refresh.secrets);
|
|
116985
118349
|
} catch (retryError) {
|
|
116986
118350
|
const retryProviderSetup = getRuntimeProviderSetupDiagnostics(retryError);
|
|
116987
118351
|
if (retryProviderSetup) {
|
|
@@ -117017,6 +118381,7 @@ var init_engine = __esm({
|
|
|
117017
118381
|
}
|
|
117018
118382
|
markCycleWorkStarted();
|
|
117019
118383
|
decisionSnapshotId = result.decisionSnapshotId;
|
|
118384
|
+
cycleModelCalls = Array.isArray(result.invocations) ? result.invocations : [];
|
|
117020
118385
|
if (result.runtimeError) cycleFailureStage = cycleObservation.stage;
|
|
117021
118386
|
observeCycle({ stage: "decision" });
|
|
117022
118387
|
cycleErrorProvenance = {
|
|
@@ -117173,7 +118538,10 @@ var init_engine = __esm({
|
|
|
117173
118538
|
promptTokens: result.prompt_tokens,
|
|
117174
118539
|
completionTokens: result.completion_tokens,
|
|
117175
118540
|
totalTokens: result.total_tokens,
|
|
117176
|
-
|
|
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,
|
|
117177
118545
|
clientExchangeSnapshot: result.clientExchangeSnapshot ?? null,
|
|
117178
118546
|
invocations: result.invocations,
|
|
117179
118547
|
externalInferenceBindings: result.externalInferenceBindings ?? [],
|
|
@@ -117186,6 +118554,7 @@ var init_engine = __esm({
|
|
|
117186
118554
|
reconciliationTimeoutMs: result.decisionReconciliationTimeoutMs
|
|
117187
118555
|
});
|
|
117188
118556
|
decisionSubmitted = true;
|
|
118557
|
+
cycleModelCallsReported = true;
|
|
117189
118558
|
} catch (decisionError) {
|
|
117190
118559
|
if (isRuntimeContractMismatchError(decisionError)) {
|
|
117191
118560
|
await this._discardCycleOnContractMismatch("decision", decisionError);
|
|
@@ -117258,11 +118627,28 @@ var init_engine = __esm({
|
|
|
117258
118627
|
}
|
|
117259
118628
|
const executionResults = [];
|
|
117260
118629
|
const executionFailures = [];
|
|
117261
|
-
|
|
117262
|
-
|
|
117263
|
-
|
|
117264
|
-
|
|
117265
|
-
|
|
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) => {
|
|
117266
118652
|
let planEntryOrderDispatched = false;
|
|
117267
118653
|
const decisionWallet = String(
|
|
117268
118654
|
plan.executionContext.walletAddress || ""
|
|
@@ -117284,7 +118670,7 @@ var init_engine = __esm({
|
|
|
117284
118670
|
actionablePlan ? "decision execution" : trailingHoldCanMutate ? "trailing stop maintenance" : "protective order reconciliation"
|
|
117285
118671
|
);
|
|
117286
118672
|
if (shouldAbortForContractInvalidation("post_execution_preferences_refresh")) {
|
|
117287
|
-
return;
|
|
118673
|
+
return { control: "return" };
|
|
117288
118674
|
}
|
|
117289
118675
|
}
|
|
117290
118676
|
appendRuntimeDebugEvent({
|
|
@@ -117336,17 +118722,16 @@ var init_engine = __esm({
|
|
|
117336
118722
|
executionResult = await executeClientRuntimeDecision({
|
|
117337
118723
|
profileId,
|
|
117338
118724
|
sessionId,
|
|
117339
|
-
runtimeLeaseToken: (
|
|
117340
|
-
const lease = getPersistedClientRuntimeServerLease(profileId);
|
|
117341
|
-
return lease?.runtimeSessionId === sessionId && lease.deviceId === deviceId && lease.mode === "trader" ? lease.runtimeLeaseToken : null;
|
|
117342
|
-
})(),
|
|
118725
|
+
runtimeLeaseToken: executionLeaseToken(),
|
|
117343
118726
|
runtimeDeviceId: deviceId,
|
|
117344
118727
|
schedulerInstanceId: this._instanceId,
|
|
117345
118728
|
cycleId: result.cycleId,
|
|
118729
|
+
serverCapacityAllocation: serverCapacityByPlan.get(planIndex),
|
|
117346
118730
|
signingKey: this._deviceSecrets?.hyperliquidSigningKey ?? null,
|
|
117347
118731
|
config: config2,
|
|
117348
118732
|
decision: plan.decision,
|
|
117349
118733
|
units: plan.units,
|
|
118734
|
+
executionMode: this._expectedExecutionMode,
|
|
117350
118735
|
executionContext: plan.executionContext,
|
|
117351
118736
|
skipTrailingMaintenance: this._trailingObservations.some((request) => request.executionContext.decisionSnapshotId === plan.executionContext.decisionSnapshotId),
|
|
117352
118737
|
signal: analysisAbortController.signal,
|
|
@@ -117365,7 +118750,8 @@ var init_engine = __esm({
|
|
|
117365
118750
|
if (isClientRuntimeWindowHandoffBeforePlanDispatch(executionError)) {
|
|
117366
118751
|
const handoffCleanup = getClientRuntimeWindowHandoffCleanup(executionError);
|
|
117367
118752
|
if (handoffCleanup) {
|
|
117368
|
-
|
|
118753
|
+
this._executionFinalizationRequired = true;
|
|
118754
|
+
return { control: "break", result: {
|
|
117369
118755
|
status: "skipped",
|
|
117370
118756
|
intent: "hold",
|
|
117371
118757
|
side: null,
|
|
@@ -117378,10 +118764,9 @@ var init_engine = __esm({
|
|
|
117378
118764
|
handoffCleanup,
|
|
117379
118765
|
executionSnapshotId: `handoff-cleanup-${planIndex + 1}-${Date.now()}`,
|
|
117380
118766
|
executionSnapshotCapturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
117381
|
-
}
|
|
117382
|
-
this._executionFinalizationRequired = true;
|
|
118767
|
+
} };
|
|
117383
118768
|
}
|
|
117384
|
-
break;
|
|
118769
|
+
return { control: "break" };
|
|
117385
118770
|
}
|
|
117386
118771
|
if (analysisAbortController.signal.aborted || isRuntimeAbortError(executionError) || isRuntimeContractMismatchError(executionError) || isClientExecutionModeMismatchError(executionError) || isClientRuntimeSessionStoppedError(executionError) || isClientRuntimeLeaseAuthError(executionError) || isTransientRuntimeConflictError(executionError)) {
|
|
117387
118772
|
throw executionError;
|
|
@@ -117440,6 +118825,9 @@ var init_engine = __esm({
|
|
|
117440
118825
|
};
|
|
117441
118826
|
}
|
|
117442
118827
|
}
|
|
118828
|
+
return { control: "continue", result: executionResult };
|
|
118829
|
+
};
|
|
118830
|
+
const recordPlanResult = (executionResult) => {
|
|
117443
118831
|
executionResults.push(executionResult);
|
|
117444
118832
|
if (executionResult.handoffCleanup) {
|
|
117445
118833
|
this._executionFinalizationRequired = true;
|
|
@@ -117448,11 +118836,26 @@ var init_engine = __esm({
|
|
|
117448
118836
|
executedExchangeOrderInCycle = true;
|
|
117449
118837
|
this._executionFinalizationRequired = true;
|
|
117450
118838
|
}
|
|
117451
|
-
|
|
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()) {
|
|
117452
118855
|
return;
|
|
117453
118856
|
}
|
|
117454
118857
|
}
|
|
117455
|
-
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 : []);
|
|
117456
118859
|
const executedOrderReports = executionReports.filter((report) => report.status === "executed" && String(report.order_id || "").trim().length > 0);
|
|
117457
118860
|
const handoffCleanups = executionResults.flatMap((executionResult) => executionResult.handoffCleanup ? [executionResult.handoffCleanup] : []);
|
|
117458
118861
|
if (this._windowHandoffRequested && executedOrderReports.length === 0) {
|
|
@@ -117638,6 +119041,8 @@ var init_engine = __esm({
|
|
|
117638
119041
|
this._notifyListeners();
|
|
117639
119042
|
}
|
|
117640
119043
|
} catch (error48) {
|
|
119044
|
+
const errorModelCalls = error48?.runtimeInvocationAttempts;
|
|
119045
|
+
if (Array.isArray(errorModelCalls) && errorModelCalls.length > 0) cycleModelCalls = errorModelCalls;
|
|
117641
119046
|
const cycleElapsedSeconds = Math.max(0, (performance.now() - runStartedMonotonicMs) / 1e3);
|
|
117642
119047
|
cycleOutcome = "failed";
|
|
117643
119048
|
cycleReason = cycleObservation.reason_code ?? "runtime_failed";
|
|
@@ -117743,12 +119148,19 @@ var init_engine = __esm({
|
|
|
117743
119148
|
model: cycleErrorProvenance?.model ?? null,
|
|
117744
119149
|
modelSource: cycleErrorProvenance?.modelSource ?? null
|
|
117745
119150
|
});
|
|
119151
|
+
if (reportedRuntime !== null && Array.isArray(errorModelCalls) && errorModelCalls.length > 0) {
|
|
119152
|
+
cycleModelCallsReported = true;
|
|
119153
|
+
}
|
|
117746
119154
|
if (reportedRuntime?.runtime_recovery_blocked_source === "terminal_failure") {
|
|
117747
119155
|
this._scheduleRecoverableSuspendAfterExecutionLoop({
|
|
117748
119156
|
reason: "runtime_terminal_failure"
|
|
117749
119157
|
});
|
|
117750
119158
|
return;
|
|
117751
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
|
+
}
|
|
117752
119164
|
if (hasEventBoundProviderFailureEvidence(error48)) {
|
|
117753
119165
|
this.scheduleProviderFailureDiagnosticsTelemetry({
|
|
117754
119166
|
profileId,
|
|
@@ -117762,6 +119174,18 @@ var init_engine = __esm({
|
|
|
117762
119174
|
});
|
|
117763
119175
|
}
|
|
117764
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
|
+
}
|
|
117765
119189
|
if (!decisionSubmitted && pendingExternalInferenceBindings.length > 0) {
|
|
117766
119190
|
await Promise.allSettled(
|
|
117767
119191
|
pendingExternalInferenceBindings.map((binding) => cancelClientRuntimeInferenceJob(profileId, binding.job_id, {
|
|
@@ -117788,8 +119212,9 @@ var init_engine = __esm({
|
|
|
117788
119212
|
if (this._analysisRequestId === requestId) {
|
|
117789
119213
|
this._analysisRequestId = null;
|
|
117790
119214
|
this._analysisStartedAtMs = null;
|
|
119215
|
+
if (this._expectedExecutionMode === "server" && this._state === "running") void this.sendHeartbeat();
|
|
117791
119216
|
}
|
|
117792
|
-
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;
|
|
117793
119218
|
if (this._state === "running" && this._sessionId === sessionId) {
|
|
117794
119219
|
this._agentInstructionPollActive = agentPollDelayMs !== null;
|
|
117795
119220
|
}
|
|
@@ -117807,7 +119232,7 @@ var init_engine = __esm({
|
|
|
117807
119232
|
});
|
|
117808
119233
|
}
|
|
117809
119234
|
this._notifyListeners();
|
|
117810
|
-
if (this._periodicSchedule && agentPollDelayMs === null && !this._primaryAnalysisDisabled) {
|
|
119235
|
+
if (this._periodicSchedule && agentPollDelayMs === null && aiSchedulePauseMs === null && !this._primaryAnalysisDisabled) {
|
|
117811
119236
|
this._advanceNextRunAnchor();
|
|
117812
119237
|
}
|
|
117813
119238
|
if (!silentEmptyAgentPoll) this._emitLoopBoundaryTelemetry("client_timer_rearmed", "reason=cycle_finally", {
|
|
@@ -117816,11 +119241,18 @@ var init_engine = __esm({
|
|
|
117816
119241
|
primary_analysis_disabled: this._primaryAnalysisDisabled,
|
|
117817
119242
|
agent_poll_retry_ms: agentPollDelayMs
|
|
117818
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;
|
|
117819
119251
|
this._armExecutionLoopTimer({
|
|
117820
119252
|
alignToNextRun: agentPollDelayMs === null,
|
|
117821
|
-
delayOverrideMs: agentPollDelayMs,
|
|
117822
|
-
reason: agentPollDelayMs !== null ? "agent_instruction_poll" : this._primaryAnalysisDisabled ? "main_model_disabled_copy_poll" : "cycle_finally",
|
|
117823
|
-
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
|
|
117824
119256
|
});
|
|
117825
119257
|
}
|
|
117826
119258
|
if (cycleOutcome === "unknown" && (analysisAbortController.signal.aborted || this._isStopping || this._state === "stopped")) {
|
|
@@ -118220,6 +119652,7 @@ var init_engine = __esm({
|
|
|
118220
119652
|
const heartbeatAnalysisRunId = this._primaryAnalysisDisabled || !this._isAnalysisInFlight() ? null : this._analysisRequestId;
|
|
118221
119653
|
const heartbeatIsAnalyzing = !this._primaryAnalysisDisabled && (this._isAnalysisInFlight() || this._startupPendingAnalysis && options?.confirmGrant !== true || this._isExecuting);
|
|
118222
119654
|
const heartbeatIsExecuting = this._isExecuting;
|
|
119655
|
+
const heartbeatObservedAtMs = Date.now();
|
|
118223
119656
|
const priorHeartbeatFailures = this._heartbeatFailures;
|
|
118224
119657
|
try {
|
|
118225
119658
|
const response = await sendClientRuntimeHeartbeat(heartbeatProfileId, {
|
|
@@ -118234,7 +119667,10 @@ var init_engine = __esm({
|
|
|
118234
119667
|
schedulerPhase: heartbeatSchedulerPhase,
|
|
118235
119668
|
analysisRunId: heartbeatAnalysisRunId,
|
|
118236
119669
|
isAnalyzing: heartbeatIsAnalyzing,
|
|
118237
|
-
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 } : {}
|
|
118238
119674
|
});
|
|
118239
119675
|
if (Number(response.protective_actions_pending ?? 0) > 0) {
|
|
118240
119676
|
notifyClientProtectiveActionsPending(heartbeatProfileId);
|
|
@@ -118418,8 +119854,18 @@ var init_engine = __esm({
|
|
|
118418
119854
|
);
|
|
118419
119855
|
this._killswitchAbortController = null;
|
|
118420
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
|
+
}
|
|
118421
119867
|
async _startClientKillswitchMonitor(startController) {
|
|
118422
|
-
if (this._mode !== "trader" || !this._profileId) {
|
|
119868
|
+
if (this._mode !== "trader" || !this._profileId || !this._ownsKillswitch()) {
|
|
118423
119869
|
return;
|
|
118424
119870
|
}
|
|
118425
119871
|
const configPromise = this.getExecutionConfig(this._profileId);
|
|
@@ -118446,7 +119892,7 @@ var init_engine = __esm({
|
|
|
118446
119892
|
);
|
|
118447
119893
|
}
|
|
118448
119894
|
async _runClientKillswitchCheck() {
|
|
118449
|
-
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) {
|
|
118450
119896
|
return;
|
|
118451
119897
|
}
|
|
118452
119898
|
const profileId = this._profileId;
|
|
@@ -118762,6 +120208,9 @@ var init_engine = __esm({
|
|
|
118762
120208
|
return config2;
|
|
118763
120209
|
}
|
|
118764
120210
|
async _processClientCopyTrading(input) {
|
|
120211
|
+
if (this._expectedExecutionMode === "server") {
|
|
120212
|
+
return;
|
|
120213
|
+
}
|
|
118765
120214
|
try {
|
|
118766
120215
|
const persistedLease = getPersistedClientRuntimeServerLease(input.profileId);
|
|
118767
120216
|
const runtimeLeaseToken = persistedLease?.runtimeSessionId === input.runtimeSessionId && persistedLease.deviceId === input.runtimeDeviceId && persistedLease.mode === "trader" ? persistedLease.runtimeLeaseToken : null;
|
|
@@ -119232,8 +120681,8 @@ var init_engine = __esm({
|
|
|
119232
120681
|
if (!normalized) return false;
|
|
119233
120682
|
return this._getEngine(normalized, false)?.updateLoopInterval(options) ?? false;
|
|
119234
120683
|
}
|
|
119235
|
-
async triggerNow() {
|
|
119236
|
-
await this._getSelectedEngine()?.triggerNow();
|
|
120684
|
+
async triggerNow(options) {
|
|
120685
|
+
await this._getSelectedEngine()?.triggerNow(options);
|
|
119237
120686
|
}
|
|
119238
120687
|
async triggerProfileNow(profileId) {
|
|
119239
120688
|
const normalized = this._normalizeProfileId(profileId);
|
|
@@ -119517,7 +120966,8 @@ function startServerProtectionSweeper(options, identity2) {
|
|
|
119517
120966
|
authority: {
|
|
119518
120967
|
runtimeSessionId: identity2.sessionId,
|
|
119519
120968
|
runtimeLeaseToken: lease.runtimeLeaseToken,
|
|
119520
|
-
runtimeDeviceId: identity2.deviceId
|
|
120969
|
+
runtimeDeviceId: identity2.deviceId,
|
|
120970
|
+
schedulerInstanceId: identity2.schedulerInstanceId
|
|
119521
120971
|
}
|
|
119522
120972
|
}) : Date.now() + PROTECTION_IDLE_RECHECK_MS;
|
|
119523
120973
|
} while (again && !controller.signal.aborted);
|
|
@@ -119593,36 +121043,24 @@ async function runHeadlessRuntime(options) {
|
|
|
119593
121043
|
if (stored && stored.runtimeSessionId !== identity2.sessionId) return;
|
|
119594
121044
|
await clearRuntimeState(options.statePath);
|
|
119595
121045
|
};
|
|
119596
|
-
const runtimeOwner = async () => {
|
|
119597
|
-
try {
|
|
119598
|
-
const { statuses } = await getClientRuntimeStatuses([options.profileId], AbortSignal.timeout(options.ownerReadTimeoutMs ?? OWNER_READ_TIMEOUT_MS));
|
|
119599
|
-
const status = statuses[String(options.profileId)];
|
|
119600
|
-
if (status) {
|
|
119601
|
-
const ownerSession = String(status.runtime_session_id ?? "").trim();
|
|
119602
|
-
const ownerDevice = String(status.runtime_device_id ?? "").trim();
|
|
119603
|
-
return !ownerSession || ownerSession === identity2.sessionId && ownerDevice === identity2.deviceId ? "mine" : "other";
|
|
119604
|
-
}
|
|
119605
|
-
} catch {
|
|
119606
|
-
}
|
|
119607
|
-
return engine.snapshot.ownershipLossReason ? "other" : "unknown";
|
|
119608
|
-
};
|
|
119609
121046
|
const stopRuntime = async (reason) => {
|
|
119610
121047
|
if (engine.active) await engine.stop({ skipRemote: true, reason });
|
|
119611
|
-
|
|
119612
|
-
|
|
119613
|
-
|
|
119614
|
-
|
|
119615
|
-
|
|
119616
|
-
|
|
119617
|
-
|
|
121048
|
+
try {
|
|
121049
|
+
await stopClientRuntimeSession(options.profileId, {
|
|
121050
|
+
sessionId: identity2.sessionId,
|
|
121051
|
+
deviceId: identity2.deviceId,
|
|
121052
|
+
mode: identity2.mode,
|
|
121053
|
+
stopReason: reason,
|
|
121054
|
+
authoritativeIntent: true,
|
|
121055
|
+
requireCurrentOwner: true
|
|
121056
|
+
}, {
|
|
121057
|
+
omitRuntimeLeaseToken: true,
|
|
121058
|
+
requestTimeoutMs: options.stopRequestTimeoutMs ?? STOP_REQUEST_TIMEOUT_MS
|
|
121059
|
+
});
|
|
121060
|
+
} catch (error48) {
|
|
121061
|
+
const detail = error48 instanceof Error ? error48.message : String(error48);
|
|
121062
|
+
throw new Error(`VTX could not stop this profile's runtime on the server (${detail}); it may still be set to run.`);
|
|
119618
121063
|
}
|
|
119619
|
-
await stopClientRuntimeSession(options.profileId, {
|
|
119620
|
-
sessionId: identity2.sessionId,
|
|
119621
|
-
deviceId: identity2.deviceId,
|
|
119622
|
-
mode: identity2.mode,
|
|
119623
|
-
stopReason: reason,
|
|
119624
|
-
authoritativeIntent: true
|
|
119625
|
-
}, { omitRuntimeLeaseToken: true });
|
|
119626
121064
|
await clearOwnState();
|
|
119627
121065
|
};
|
|
119628
121066
|
const releaseFailedStart = async (kind) => {
|
|
@@ -119661,9 +121099,9 @@ async function runHeadlessRuntime(options) {
|
|
|
119661
121099
|
return true;
|
|
119662
121100
|
};
|
|
119663
121101
|
const firstAttached = () => {
|
|
119664
|
-
const stopSweep = startServerProtectionSweeper(options, identity2);
|
|
121102
|
+
const stopSweep = startServerProtectionSweeper(options, { ...identity2, schedulerInstanceId: engine.schedulerInstanceId });
|
|
119665
121103
|
if (options.once && engine.state === "running" && !engine.snapshot.isAnalyzing) {
|
|
119666
|
-
void engine.triggerNow().catch(() => void 0);
|
|
121104
|
+
void engine.triggerNow({ ignoreAiSchedule: false }).catch(() => void 0);
|
|
119667
121105
|
}
|
|
119668
121106
|
return stopSweep;
|
|
119669
121107
|
};
|
|
@@ -119782,7 +121220,7 @@ async function runHeadlessRuntime(options) {
|
|
|
119782
121220
|
}
|
|
119783
121221
|
}
|
|
119784
121222
|
}
|
|
119785
|
-
var HeadlessRuntimeTakeoverRequiredError, HEADLESS_RUNTIME_AGENT_SCOPES, DEFAULT_MAX_CLAIM_WAITS,
|
|
121223
|
+
var HeadlessRuntimeTakeoverRequiredError, HEADLESS_RUNTIME_AGENT_SCOPES, DEFAULT_MAX_CLAIM_WAITS, STOP_REQUEST_TIMEOUT_MS, PROTECTION_IDLE_RECHECK_MS, PROTECTION_RETRY_MS, MAX_RESUMES_WITHOUT_A_CYCLE, RESUME_BACKOFF_MS;
|
|
119786
121224
|
var init_headless_runtime = __esm({
|
|
119787
121225
|
"lib/agent-core/headless-runtime.ts"() {
|
|
119788
121226
|
"use strict";
|
|
@@ -119817,7 +121255,7 @@ var init_headless_runtime = __esm({
|
|
|
119817
121255
|
};
|
|
119818
121256
|
HEADLESS_RUNTIME_AGENT_SCOPES = ["read", "bot:control", "trading:execute", "secrets:hydrate"];
|
|
119819
121257
|
DEFAULT_MAX_CLAIM_WAITS = 10;
|
|
119820
|
-
|
|
121258
|
+
STOP_REQUEST_TIMEOUT_MS = 1e4;
|
|
119821
121259
|
PROTECTION_IDLE_RECHECK_MS = runtime_policy_generated_default2.trading.engine.client_runtime.protective_actions.idle_recheck_seconds * 1e3;
|
|
119822
121260
|
PROTECTION_RETRY_MS = 15e3;
|
|
119823
121261
|
MAX_RESUMES_WITHOUT_A_CYCLE = 5;
|