@vtxmacro/cli 2026.8.51 → 2026.8.53
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/README.md +42 -18
- package/bin/vtx.js +1780 -185
- package/package.json +1 -1
package/bin/vtx.js
CHANGED
|
@@ -5,11 +5,20 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __esm = (fn, res) => function __init() {
|
|
9
|
-
|
|
8
|
+
var __esm = (fn, res, err) => function __init() {
|
|
9
|
+
if (err) throw err[0];
|
|
10
|
+
try {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw err = [e], e;
|
|
14
|
+
}
|
|
10
15
|
};
|
|
11
16
|
var __commonJS = (cb, mod2) => function __require() {
|
|
12
|
-
|
|
17
|
+
try {
|
|
18
|
+
return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
throw mod2 = 0, e;
|
|
21
|
+
}
|
|
13
22
|
};
|
|
14
23
|
var __export = (target, all) => {
|
|
15
24
|
for (var name in all)
|
|
@@ -38,7 +47,7 @@ var init_agent_cli_release = __esm({
|
|
|
38
47
|
"agent-cli-release.json"() {
|
|
39
48
|
agent_cli_release_default = {
|
|
40
49
|
package_name: "@vtxmacro/cli",
|
|
41
|
-
package_version: "2026.8.
|
|
50
|
+
package_version: "2026.8.53",
|
|
42
51
|
codex_package_name: "@openai/codex",
|
|
43
52
|
codex_version: "0.147.0",
|
|
44
53
|
copilot_sdk_package_name: "@github/copilot-sdk",
|
|
@@ -16535,6 +16544,25 @@ async function syncInferenceDirectory(path, platform = process.platform) {
|
|
|
16535
16544
|
await handle.close();
|
|
16536
16545
|
}
|
|
16537
16546
|
}
|
|
16547
|
+
async function replaceAtomicInferencePrivateFile(temporaryPath, destinationPath, options = {}) {
|
|
16548
|
+
const platform = options.platform ?? process.platform;
|
|
16549
|
+
const renameFile = options.renameFile ?? rename;
|
|
16550
|
+
const sleep4 = options.sleep ?? ((milliseconds) => new Promise((resolve6) => setTimeout(resolve6, milliseconds)));
|
|
16551
|
+
const maxAttempts = Math.max(1, options.maxAttempts ?? 40);
|
|
16552
|
+
const retryDelayMs = Math.max(0, options.retryDelayMs ?? 25);
|
|
16553
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
16554
|
+
try {
|
|
16555
|
+
await renameFile(temporaryPath, destinationPath);
|
|
16556
|
+
return;
|
|
16557
|
+
} catch (error48) {
|
|
16558
|
+
const code = String(error48.code ?? "");
|
|
16559
|
+
if (platform !== "win32" || !WINDOWS_PRIVATE_FILE_REPLACE_ERROR_CODES.has(code) || attempt === maxAttempts - 1) {
|
|
16560
|
+
throw error48;
|
|
16561
|
+
}
|
|
16562
|
+
await sleep4(retryDelayMs);
|
|
16563
|
+
}
|
|
16564
|
+
}
|
|
16565
|
+
}
|
|
16538
16566
|
async function writeAtomicInferencePrivateFile(path, contents, dependencies = {}) {
|
|
16539
16567
|
const platform = dependencies.platform ?? process.platform;
|
|
16540
16568
|
const runner = dependencies.runner ?? runWindowsPrivateAcl;
|
|
@@ -16571,7 +16599,13 @@ async function writeAtomicInferencePrivateFile(path, contents, dependencies = {}
|
|
|
16571
16599
|
}
|
|
16572
16600
|
try {
|
|
16573
16601
|
invalidateWindowsAclCache(path);
|
|
16574
|
-
await
|
|
16602
|
+
await replaceAtomicInferencePrivateFile(temporary, path, {
|
|
16603
|
+
platform,
|
|
16604
|
+
renameFile: dependencies.renameFile,
|
|
16605
|
+
sleep: dependencies.sleep,
|
|
16606
|
+
maxAttempts: dependencies.replaceMaxAttempts,
|
|
16607
|
+
retryDelayMs: dependencies.replaceRetryDelayMs
|
|
16608
|
+
});
|
|
16575
16609
|
if (platform === "win32" && hardenedIdentity) {
|
|
16576
16610
|
await rebindHardenedWindowsAclAfterRename(
|
|
16577
16611
|
temporary,
|
|
@@ -16838,7 +16872,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
|
|
|
16838
16872
|
}
|
|
16839
16873
|
};
|
|
16840
16874
|
}
|
|
16841
|
-
var 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, defaultCurrentProcessIdentity, processLockObservationCache, inferenceProcessIdentitiesMatch, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity, inferenceHostCredentialContextPath, inferenceHostCredentialContextTransitionPath, credentialContextForConfig;
|
|
16875
|
+
var 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, defaultCurrentProcessIdentity, processLockObservationCache, inferenceProcessIdentitiesMatch, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity, inferenceHostCredentialContextPath, inferenceHostCredentialContextTransitionPath, credentialContextForConfig, WINDOWS_PRIVATE_FILE_REPLACE_ERROR_CODES;
|
|
16842
16876
|
var init_config = __esm({
|
|
16843
16877
|
"lib/inference-host/config.ts"() {
|
|
16844
16878
|
"use strict";
|
|
@@ -17413,6 +17447,13 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
17413
17447
|
credential_store_mode: config2.credentialStoreMode,
|
|
17414
17448
|
credential_file_path: config2.credentialStoreMode === "file" ? resolve(config2.credentialFilePath) : null
|
|
17415
17449
|
});
|
|
17450
|
+
WINDOWS_PRIVATE_FILE_REPLACE_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
17451
|
+
"EACCES",
|
|
17452
|
+
"EBUSY",
|
|
17453
|
+
"EEXIST",
|
|
17454
|
+
"ENOTEMPTY",
|
|
17455
|
+
"EPERM"
|
|
17456
|
+
]);
|
|
17416
17457
|
}
|
|
17417
17458
|
});
|
|
17418
17459
|
|
|
@@ -19654,32 +19695,60 @@ var init_agent_client = __esm({
|
|
|
19654
19695
|
});
|
|
19655
19696
|
|
|
19656
19697
|
// lib/inference-host/agent-state.ts
|
|
19657
|
-
async function
|
|
19698
|
+
async function readInferenceAgentRuntimeState(statePath) {
|
|
19658
19699
|
const raw = await readInferencePrivateFile(
|
|
19659
|
-
|
|
19660
|
-
"
|
|
19700
|
+
inferenceAgentRuntimeStatePath(statePath),
|
|
19701
|
+
"Inference Agent runtime recovery state"
|
|
19661
19702
|
);
|
|
19662
19703
|
if (raw === null) return null;
|
|
19663
19704
|
try {
|
|
19664
|
-
return
|
|
19705
|
+
return assertInferenceAgentRuntimeState(JSON.parse(raw));
|
|
19665
19706
|
} catch (error48) {
|
|
19666
19707
|
if (error48 instanceof SyntaxError) {
|
|
19667
|
-
throw new Error("
|
|
19708
|
+
throw new Error("Inference Agent runtime recovery state is not valid JSON.");
|
|
19668
19709
|
}
|
|
19669
19710
|
throw error48;
|
|
19670
19711
|
}
|
|
19671
19712
|
}
|
|
19672
|
-
async function
|
|
19713
|
+
async function writeInferenceAgentRuntimeState(statePath, value) {
|
|
19673
19714
|
await writeAtomicInferencePrivateFile(
|
|
19674
|
-
|
|
19675
|
-
`${JSON.stringify(
|
|
19715
|
+
inferenceAgentRuntimeStatePath(statePath),
|
|
19716
|
+
`${JSON.stringify(assertInferenceAgentRuntimeState(value), null, 2)}
|
|
19676
19717
|
`
|
|
19677
19718
|
);
|
|
19678
19719
|
}
|
|
19679
|
-
async function
|
|
19720
|
+
async function clearInferenceAgentRuntimeState(statePath) {
|
|
19680
19721
|
await clearInferencePrivateFile(
|
|
19681
|
-
|
|
19682
|
-
"
|
|
19722
|
+
inferenceAgentRuntimeStatePath(statePath),
|
|
19723
|
+
"Inference Agent runtime recovery state"
|
|
19724
|
+
);
|
|
19725
|
+
}
|
|
19726
|
+
async function readInferenceForegroundAgentControlState(statePath) {
|
|
19727
|
+
const raw = await readInferencePrivateFile(
|
|
19728
|
+
foregroundAgentControlStatePath(statePath),
|
|
19729
|
+
"Foreground Agent control recovery state"
|
|
19730
|
+
);
|
|
19731
|
+
if (raw === null) return null;
|
|
19732
|
+
try {
|
|
19733
|
+
return assertForegroundAgentControlState(JSON.parse(raw));
|
|
19734
|
+
} catch (error48) {
|
|
19735
|
+
if (error48 instanceof SyntaxError) {
|
|
19736
|
+
throw new Error("Foreground Agent control recovery state is not valid JSON.");
|
|
19737
|
+
}
|
|
19738
|
+
throw error48;
|
|
19739
|
+
}
|
|
19740
|
+
}
|
|
19741
|
+
async function writeInferenceForegroundAgentControlState(statePath, value) {
|
|
19742
|
+
await writeAtomicInferencePrivateFile(
|
|
19743
|
+
foregroundAgentControlStatePath(statePath),
|
|
19744
|
+
`${JSON.stringify(assertForegroundAgentControlState(value), null, 2)}
|
|
19745
|
+
`
|
|
19746
|
+
);
|
|
19747
|
+
}
|
|
19748
|
+
async function clearInferenceForegroundAgentControlState(statePath) {
|
|
19749
|
+
await clearInferencePrivateFile(
|
|
19750
|
+
foregroundAgentControlStatePath(statePath),
|
|
19751
|
+
"Foreground Agent control recovery state"
|
|
19683
19752
|
);
|
|
19684
19753
|
}
|
|
19685
19754
|
async function readInferenceAgentAttemptState(statePath) {
|
|
@@ -19738,7 +19807,7 @@ async function clearInferenceAgentNextState(statePath) {
|
|
|
19738
19807
|
"Agent-driven inference next recovery state"
|
|
19739
19808
|
);
|
|
19740
19809
|
}
|
|
19741
|
-
var inferenceAgentAttemptStatePath, inferenceAgentNextStatePath,
|
|
19810
|
+
var inferenceAgentAttemptStatePath, inferenceAgentNextStatePath, inferenceAgentRuntimeStatePath, isIsoTimestamp, assertPlainObject, hasExactKeys, assertInferenceAgentRuntimeState, readCodexAgentRuntimeState, clearCodexAgentRuntimeState, foregroundAgentControlStatePath, assertRuntimeAssignment, assertForegroundAgentControlState, assertNextState, assertAttemptState;
|
|
19742
19811
|
var init_agent_state = __esm({
|
|
19743
19812
|
"lib/inference-host/agent-state.ts"() {
|
|
19744
19813
|
"use strict";
|
|
@@ -19746,18 +19815,20 @@ var init_agent_state = __esm({
|
|
|
19746
19815
|
init_external_inference_contract();
|
|
19747
19816
|
inferenceAgentAttemptStatePath = (statePath) => `${statePath}.agent-attempt.json`;
|
|
19748
19817
|
inferenceAgentNextStatePath = (statePath) => `${statePath}.agent-next.json`;
|
|
19749
|
-
|
|
19818
|
+
inferenceAgentRuntimeStatePath = (statePath) => `${statePath}.codex-agent-runtime.json`;
|
|
19750
19819
|
isIsoTimestamp = (value) => typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
19751
19820
|
assertPlainObject = (value, message) => {
|
|
19752
19821
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(message);
|
|
19753
19822
|
return value;
|
|
19754
19823
|
};
|
|
19755
19824
|
hasExactKeys = (record2, keys) => Object.keys(record2).sort().join("\0") === [...keys].sort().join("\0");
|
|
19756
|
-
|
|
19757
|
-
const message = "
|
|
19825
|
+
assertInferenceAgentRuntimeState = (value) => {
|
|
19826
|
+
const message = "Inference Agent runtime recovery state is invalid.";
|
|
19758
19827
|
const state = assertPlainObject(value, message);
|
|
19828
|
+
const generic = state.schema_version === "vtx_inference_agent_runtime_v3";
|
|
19759
19829
|
if (!hasExactKeys(state, [
|
|
19760
19830
|
"schema_version",
|
|
19831
|
+
...generic ? ["adapter_id"] : [],
|
|
19761
19832
|
"host_id",
|
|
19762
19833
|
"assignment",
|
|
19763
19834
|
"thread",
|
|
@@ -19766,9 +19837,13 @@ var init_agent_state = __esm({
|
|
|
19766
19837
|
"updated_at"
|
|
19767
19838
|
])) throw new Error(message);
|
|
19768
19839
|
const assignment = assertPlainObject(state.assignment, message);
|
|
19769
|
-
if (![
|
|
19840
|
+
if (![
|
|
19841
|
+
"vtx_codex_agent_runtime_v1",
|
|
19842
|
+
"vtx_codex_agent_runtime_v2",
|
|
19843
|
+
"vtx_inference_agent_runtime_v3"
|
|
19844
|
+
].includes(
|
|
19770
19845
|
String(state.schema_version)
|
|
19771
|
-
) || typeof state.host_id !== "string" || !state.host_id || !isIsoTimestamp(state.next_wake_at) || !isIsoTimestamp(state.updated_at) || !hasExactKeys(
|
|
19846
|
+
) || generic && (typeof state.adapter_id !== "string" || !/^[a-z0-9][a-z0-9._-]{0,63}$/u.test(state.adapter_id)) || typeof state.host_id !== "string" || !state.host_id || !isIsoTimestamp(state.next_wake_at) || !isIsoTimestamp(state.updated_at) || !hasExactKeys(
|
|
19772
19847
|
assignment,
|
|
19773
19848
|
[
|
|
19774
19849
|
"assignment_id",
|
|
@@ -19782,10 +19857,10 @@ var init_agent_state = __esm({
|
|
|
19782
19857
|
"minimum_wake_seconds",
|
|
19783
19858
|
"maximum_wake_seconds",
|
|
19784
19859
|
"lease_expires_at",
|
|
19785
|
-
...state.schema_version
|
|
19860
|
+
...state.schema_version !== "vtx_codex_agent_runtime_v1" ? ["data_contract"] : []
|
|
19786
19861
|
]
|
|
19787
19862
|
) || typeof assignment.assignment_id !== "string" || !assignment.assignment_id || !Number.isSafeInteger(assignment.assignment_generation) || Number(assignment.assignment_generation) < 1 || typeof assignment.model_id !== "string" || !assignment.model_id || typeof assignment.reasoning_effort !== "string" || !assignment.reasoning_effort || !["trader", "assistant"].includes(String(assignment.bot_mode)) || !["server", "client"].includes(String(assignment.execution_mode)) || !Array.isArray(assignment.allowed_symbols) || assignment.allowed_symbols.some((symbol2) => typeof symbol2 !== "string" || !symbol2) || !assignment.output_schema || typeof assignment.output_schema !== "object" || Array.isArray(assignment.output_schema) || !Number.isSafeInteger(assignment.minimum_wake_seconds) || Number(assignment.minimum_wake_seconds) < 1 || !Number.isSafeInteger(assignment.maximum_wake_seconds) || Number(assignment.maximum_wake_seconds) < Number(assignment.minimum_wake_seconds) || !isIsoTimestamp(assignment.lease_expires_at)) throw new Error(message);
|
|
19788
|
-
if (state.schema_version
|
|
19863
|
+
if (state.schema_version !== "vtx_codex_agent_runtime_v1") {
|
|
19789
19864
|
if (!Array.isArray(assignment.data_contract) || assignment.data_contract.length === 0) {
|
|
19790
19865
|
throw new Error(message);
|
|
19791
19866
|
}
|
|
@@ -19824,6 +19899,76 @@ var init_agent_state = __esm({
|
|
|
19824
19899
|
}
|
|
19825
19900
|
return state;
|
|
19826
19901
|
};
|
|
19902
|
+
readCodexAgentRuntimeState = readInferenceAgentRuntimeState;
|
|
19903
|
+
clearCodexAgentRuntimeState = clearInferenceAgentRuntimeState;
|
|
19904
|
+
foregroundAgentControlStatePath = (statePath) => `${statePath}.foreground-agent-control.json`;
|
|
19905
|
+
assertRuntimeAssignment = (value, message) => {
|
|
19906
|
+
const assignment = assertPlainObject(value, message);
|
|
19907
|
+
if (!hasExactKeys(assignment, [
|
|
19908
|
+
"assignment_id",
|
|
19909
|
+
"assignment_generation",
|
|
19910
|
+
"model_id",
|
|
19911
|
+
"reasoning_effort",
|
|
19912
|
+
"bot_mode",
|
|
19913
|
+
"execution_mode",
|
|
19914
|
+
"allowed_symbols",
|
|
19915
|
+
"output_schema",
|
|
19916
|
+
"data_contract",
|
|
19917
|
+
"minimum_wake_seconds",
|
|
19918
|
+
"maximum_wake_seconds",
|
|
19919
|
+
"lease_expires_at"
|
|
19920
|
+
]) || typeof assignment.assignment_id !== "string" || !assignment.assignment_id || !Number.isSafeInteger(assignment.assignment_generation) || Number(assignment.assignment_generation) < 1 || typeof assignment.model_id !== "string" || !assignment.model_id || typeof assignment.reasoning_effort !== "string" || !assignment.reasoning_effort || !["trader", "assistant"].includes(String(assignment.bot_mode)) || !["server", "client"].includes(String(assignment.execution_mode)) || !Array.isArray(assignment.allowed_symbols) || assignment.allowed_symbols.some((symbol2) => typeof symbol2 !== "string" || !symbol2) || !assignment.output_schema || typeof assignment.output_schema !== "object" || Array.isArray(assignment.output_schema) || !Array.isArray(assignment.data_contract) || assignment.data_contract.length === 0 || !Number.isSafeInteger(assignment.minimum_wake_seconds) || Number(assignment.minimum_wake_seconds) < 1 || !Number.isSafeInteger(assignment.maximum_wake_seconds) || Number(assignment.maximum_wake_seconds) < Number(assignment.minimum_wake_seconds) || !isIsoTimestamp(assignment.lease_expires_at)) throw new Error(message);
|
|
19921
|
+
const ids = assignment.data_contract.map((value2) => {
|
|
19922
|
+
const descriptor = assertPlainObject(value2, message);
|
|
19923
|
+
if (!hasExactKeys(descriptor, [
|
|
19924
|
+
"id",
|
|
19925
|
+
"title",
|
|
19926
|
+
"description",
|
|
19927
|
+
"input_schema",
|
|
19928
|
+
"input_schema_sha256"
|
|
19929
|
+
]) || typeof descriptor.id !== "string" || !descriptor.id || typeof descriptor.title !== "string" || !descriptor.title || typeof descriptor.description !== "string" || !descriptor.description || !descriptor.input_schema || typeof descriptor.input_schema !== "object" || Array.isArray(descriptor.input_schema) || typeof descriptor.input_schema_sha256 !== "string" || !/^[0-9a-f]{64}$/u.test(descriptor.input_schema_sha256)) throw new Error(message);
|
|
19930
|
+
return descriptor.id;
|
|
19931
|
+
});
|
|
19932
|
+
if (new Set(ids).size !== ids.length) throw new Error(message);
|
|
19933
|
+
return assignment;
|
|
19934
|
+
};
|
|
19935
|
+
assertForegroundAgentControlState = (value) => {
|
|
19936
|
+
const message = "Foreground Agent control recovery state is invalid.";
|
|
19937
|
+
const state = assertPlainObject(value, message);
|
|
19938
|
+
if (!hasExactKeys(state, [
|
|
19939
|
+
"schema_version",
|
|
19940
|
+
"host_id",
|
|
19941
|
+
"assignment",
|
|
19942
|
+
"pending_next",
|
|
19943
|
+
"pending_decision",
|
|
19944
|
+
"next_wake_at",
|
|
19945
|
+
"updated_at"
|
|
19946
|
+
]) || state.schema_version !== "vtx_foreground_agent_control_v1" || typeof state.host_id !== "string" || !state.host_id || state.next_wake_at !== null && !isIsoTimestamp(state.next_wake_at) || !isIsoTimestamp(state.updated_at)) throw new Error(message);
|
|
19947
|
+
if (state.assignment !== null) assertRuntimeAssignment(state.assignment, message);
|
|
19948
|
+
if (state.pending_next !== null) {
|
|
19949
|
+
const pending = assertPlainObject(state.pending_next, message);
|
|
19950
|
+
if (!hasExactKeys(pending, ["operation_id", "requested_at"]) || typeof pending.operation_id !== "string" || !pending.operation_id || !isIsoTimestamp(pending.requested_at)) throw new Error(message);
|
|
19951
|
+
}
|
|
19952
|
+
if (state.pending_decision !== null) {
|
|
19953
|
+
if (state.assignment === null) throw new Error(message);
|
|
19954
|
+
const pending = assertPlainObject(state.pending_decision, message);
|
|
19955
|
+
if (!hasExactKeys(pending, [
|
|
19956
|
+
"request",
|
|
19957
|
+
"first_transmit_at",
|
|
19958
|
+
"last_status_check_at"
|
|
19959
|
+
])) throw new Error(message);
|
|
19960
|
+
const request = assertPlainObject(pending.request, message);
|
|
19961
|
+
if (!hasExactKeys(request, [
|
|
19962
|
+
"assignment_id",
|
|
19963
|
+
"assignment_generation",
|
|
19964
|
+
"operation_id",
|
|
19965
|
+
"candidate",
|
|
19966
|
+
"observed_at",
|
|
19967
|
+
"provenance"
|
|
19968
|
+
]) || request.assignment_id !== state.assignment.assignment_id || request.assignment_generation !== state.assignment.assignment_generation || typeof request.operation_id !== "string" || !request.operation_id || !request.candidate || typeof request.candidate !== "object" || Array.isArray(request.candidate) || !isIsoTimestamp(request.observed_at) || !request.provenance || typeof request.provenance !== "object" || Array.isArray(request.provenance) || pending.first_transmit_at !== null && !isIsoTimestamp(pending.first_transmit_at) || pending.last_status_check_at !== null && !isIsoTimestamp(pending.last_status_check_at)) throw new Error(message);
|
|
19969
|
+
}
|
|
19970
|
+
return state;
|
|
19971
|
+
};
|
|
19827
19972
|
assertNextState = (value) => {
|
|
19828
19973
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
19829
19974
|
throw new Error("Agent-driven inference next recovery state is invalid.");
|
|
@@ -23978,15 +24123,17 @@ $items = @(Get-CimInstance Win32_Process | Where-Object { $_.Name -in @('node.ex
|
|
|
23978
24123
|
});
|
|
23979
24124
|
|
|
23980
24125
|
// lib/inference-host/copilot-adapter.ts
|
|
24126
|
+
import { randomUUID } from "node:crypto";
|
|
23981
24127
|
import { mkdtemp as mkdtemp2, rm as rm4 } from "node:fs/promises";
|
|
23982
24128
|
import { createRequire as createRequire2 } from "node:module";
|
|
23983
24129
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
23984
24130
|
import { join as join5 } from "node:path";
|
|
23985
24131
|
import {
|
|
23986
24132
|
CopilotClient,
|
|
23987
|
-
RuntimeConnection
|
|
24133
|
+
RuntimeConnection,
|
|
24134
|
+
defineTool
|
|
23988
24135
|
} from "@github/copilot-sdk";
|
|
23989
|
-
var COPILOT_SDK_VERSION, MAX_RESULT_BYTES, resolveRuntimePackage, copilotRuntimePackageCandidates, resolvePinnedCopilotCliPath, createPrivateWorkspace, cleanCopilotEnvironment, defaultClient, modelCapabilities, requiredUsageInteger, optionalUsageInteger, CopilotSubscriptionAdapter;
|
|
24136
|
+
var COPILOT_SDK_VERSION, MAX_RESULT_BYTES, resolveRuntimePackage, copilotRuntimePackageCandidates, resolvePinnedCopilotCliPath, createPrivateWorkspace, cleanCopilotEnvironment, defaultClient, modelCapabilities, requiredUsageInteger, optionalUsageInteger, copilotAgentToolDefinitions, CopilotSubscriptionAdapter;
|
|
23990
24137
|
var init_copilot_adapter = __esm({
|
|
23991
24138
|
"lib/inference-host/copilot-adapter.ts"() {
|
|
23992
24139
|
"use strict";
|
|
@@ -24082,9 +24229,66 @@ var init_copilot_adapter = __esm({
|
|
|
24082
24229
|
}
|
|
24083
24230
|
return Number(value);
|
|
24084
24231
|
};
|
|
24232
|
+
copilotAgentToolDefinitions = (input, evidence) => {
|
|
24233
|
+
const execute = async (tool, argumentsValue) => {
|
|
24234
|
+
const argumentsRecord = argumentsValue && typeof argumentsValue === "object" && !Array.isArray(argumentsValue) ? argumentsValue : {};
|
|
24235
|
+
const callId = randomUUID();
|
|
24236
|
+
const result2 = await input.executeTool({
|
|
24237
|
+
callId,
|
|
24238
|
+
tool,
|
|
24239
|
+
arguments: argumentsRecord
|
|
24240
|
+
});
|
|
24241
|
+
evidence.push({ callId, tool, arguments: argumentsRecord, success: result2.success });
|
|
24242
|
+
return result2.success ? result2.value : { error: result2.value };
|
|
24243
|
+
};
|
|
24244
|
+
return [
|
|
24245
|
+
defineTool("vtx_get_data", {
|
|
24246
|
+
description: "Request assignment-scoped VTX data using one exact canonical capability schema.",
|
|
24247
|
+
parameters: {
|
|
24248
|
+
oneOf: input.dataContract.map((descriptor) => ({
|
|
24249
|
+
type: "object",
|
|
24250
|
+
additionalProperties: false,
|
|
24251
|
+
required: ["capability", "arguments"],
|
|
24252
|
+
description: descriptor.description,
|
|
24253
|
+
properties: {
|
|
24254
|
+
capability: { type: "string", const: descriptor.id, title: descriptor.title },
|
|
24255
|
+
arguments: descriptor.input_schema
|
|
24256
|
+
}
|
|
24257
|
+
}))
|
|
24258
|
+
},
|
|
24259
|
+
skipPermission: true,
|
|
24260
|
+
handler: async (args) => await execute("vtx_get_data", args)
|
|
24261
|
+
}),
|
|
24262
|
+
defineTool("vtx_submit_decision", {
|
|
24263
|
+
description: "Submit one VTX structured trading decision candidate.",
|
|
24264
|
+
parameters: {
|
|
24265
|
+
type: "object",
|
|
24266
|
+
additionalProperties: false,
|
|
24267
|
+
required: ["candidate"],
|
|
24268
|
+
properties: { candidate: input.decisionSchema }
|
|
24269
|
+
},
|
|
24270
|
+
skipPermission: true,
|
|
24271
|
+
handler: async (args) => await execute("vtx_submit_decision", args)
|
|
24272
|
+
}),
|
|
24273
|
+
defineTool("vtx_decision_status", {
|
|
24274
|
+
description: "Resolve the durable status of a previously attempted decision operation.",
|
|
24275
|
+
parameters: {
|
|
24276
|
+
type: "object",
|
|
24277
|
+
additionalProperties: false,
|
|
24278
|
+
required: ["operation_id"],
|
|
24279
|
+
properties: { operation_id: { type: "string", minLength: 1 } }
|
|
24280
|
+
},
|
|
24281
|
+
skipPermission: true,
|
|
24282
|
+
handler: async (args) => await execute("vtx_decision_status", args)
|
|
24283
|
+
})
|
|
24284
|
+
];
|
|
24285
|
+
};
|
|
24085
24286
|
CopilotSubscriptionAdapter = class {
|
|
24086
24287
|
constructor(dependencies = {}) {
|
|
24087
24288
|
this.inFlight = /* @__PURE__ */ new Map();
|
|
24289
|
+
this.agentConnection = null;
|
|
24290
|
+
this.agentWorkspaceCleanups = /* @__PURE__ */ new Map();
|
|
24291
|
+
this.closing = false;
|
|
24088
24292
|
this.dependencies = dependencies;
|
|
24089
24293
|
}
|
|
24090
24294
|
async preflight(signal) {
|
|
@@ -24296,6 +24500,224 @@ ${input.outputSchemaJson}`
|
|
|
24296
24500
|
await workspace.cleanup();
|
|
24297
24501
|
}
|
|
24298
24502
|
}
|
|
24503
|
+
async runTurn(input) {
|
|
24504
|
+
if (this.closing) {
|
|
24505
|
+
throw new CodexAppServerError({
|
|
24506
|
+
message: "Copilot Agent adapter is closing.",
|
|
24507
|
+
category: "transport",
|
|
24508
|
+
code: "transport_closed",
|
|
24509
|
+
retryable: true
|
|
24510
|
+
});
|
|
24511
|
+
}
|
|
24512
|
+
input.signal?.throwIfAborted();
|
|
24513
|
+
if (Date.now() >= input.deadlineAtMs || input.dataContract.length === 0) {
|
|
24514
|
+
throw new CodexAppServerError({
|
|
24515
|
+
message: "Copilot Agent turn input is invalid or expired.",
|
|
24516
|
+
category: Date.now() >= input.deadlineAtMs ? "timeout" : "schema",
|
|
24517
|
+
code: Date.now() >= input.deadlineAtMs ? "deadline_exceeded" : "invalid_agent_turn_input",
|
|
24518
|
+
retryable: false
|
|
24519
|
+
});
|
|
24520
|
+
}
|
|
24521
|
+
const startedAt = (this.dependencies.now ?? Date.now)();
|
|
24522
|
+
const ownedWorkspace = input.durableThread ? null : await (this.dependencies.createAgentWorkspace ?? this.dependencies.createWorkspace ?? createPrivateWorkspace)();
|
|
24523
|
+
const workspacePath = input.durableThread?.threadPath ?? ownedWorkspace.path;
|
|
24524
|
+
if (ownedWorkspace) this.agentWorkspaceCleanups.set(workspacePath, ownedWorkspace.cleanup);
|
|
24525
|
+
const client = (this.dependencies.createClient ?? defaultClient)(workspacePath);
|
|
24526
|
+
let session = null;
|
|
24527
|
+
let durableCheckpointed = input.durableThread !== null;
|
|
24528
|
+
let dispatchEntered = false;
|
|
24529
|
+
const toolEvidence = [];
|
|
24530
|
+
try {
|
|
24531
|
+
await client.start();
|
|
24532
|
+
const tools = copilotAgentToolDefinitions(input, toolEvidence);
|
|
24533
|
+
const sessionConfig = {
|
|
24534
|
+
clientName: "@vtxmacro/cli durable Copilot Agent host",
|
|
24535
|
+
model: input.requestedModel,
|
|
24536
|
+
...input.requestedReasoningEffort === "none" ? {} : { reasoningEffort: input.requestedReasoningEffort },
|
|
24537
|
+
systemMessage: {
|
|
24538
|
+
mode: "replace",
|
|
24539
|
+
content: `${input.systemPrompt}
|
|
24540
|
+
|
|
24541
|
+
Return only one JSON value matching this JSON Schema exactly:
|
|
24542
|
+
${JSON.stringify(input.outputSchema)}`
|
|
24543
|
+
},
|
|
24544
|
+
tools,
|
|
24545
|
+
availableTools: tools.map((tool) => tool.name),
|
|
24546
|
+
enableConfigDiscovery: false,
|
|
24547
|
+
streaming: true,
|
|
24548
|
+
workingDirectory: workspacePath,
|
|
24549
|
+
infiniteSessions: { enabled: true }
|
|
24550
|
+
};
|
|
24551
|
+
session = input.durableThread ? await client.resumeSession(input.durableThread.threadId, sessionConfig) : await client.createSession(sessionConfig);
|
|
24552
|
+
this.agentConnection = {
|
|
24553
|
+
client,
|
|
24554
|
+
session,
|
|
24555
|
+
workspacePath,
|
|
24556
|
+
cleanup: ownedWorkspace?.cleanup ?? null
|
|
24557
|
+
};
|
|
24558
|
+
const thread = {
|
|
24559
|
+
threadId: session.sessionId,
|
|
24560
|
+
threadPath: workspacePath,
|
|
24561
|
+
effectiveModel: input.requestedModel,
|
|
24562
|
+
effectiveReasoningEffort: input.requestedReasoningEffort
|
|
24563
|
+
};
|
|
24564
|
+
if (input.onThreadReady) {
|
|
24565
|
+
await input.onThreadReady(thread);
|
|
24566
|
+
durableCheckpointed = true;
|
|
24567
|
+
}
|
|
24568
|
+
const usageEvents = [];
|
|
24569
|
+
session.on((event) => {
|
|
24570
|
+
if (event.type === "assistant.usage" && !event.agentId) usageEvents.push(event);
|
|
24571
|
+
});
|
|
24572
|
+
const onAbort = () => {
|
|
24573
|
+
void session?.abort().catch(() => void 0);
|
|
24574
|
+
};
|
|
24575
|
+
input.signal?.addEventListener("abort", onAbort, { once: true });
|
|
24576
|
+
dispatchEntered = true;
|
|
24577
|
+
let response;
|
|
24578
|
+
try {
|
|
24579
|
+
response = await session.sendAndWait(
|
|
24580
|
+
{ prompt: input.userPrompt },
|
|
24581
|
+
Math.max(1, input.deadlineAtMs - Date.now())
|
|
24582
|
+
);
|
|
24583
|
+
} finally {
|
|
24584
|
+
input.signal?.removeEventListener("abort", onAbort);
|
|
24585
|
+
}
|
|
24586
|
+
if (!response?.data.content || Buffer.byteLength(response.data.content, "utf8") > MAX_RESULT_BYTES) {
|
|
24587
|
+
throw new Error("copilot_agent_invalid_result");
|
|
24588
|
+
}
|
|
24589
|
+
const observedModels = /* @__PURE__ */ new Set();
|
|
24590
|
+
const observedEfforts = /* @__PURE__ */ new Set();
|
|
24591
|
+
let inputTokens = 0;
|
|
24592
|
+
let cachedInputTokens = 0;
|
|
24593
|
+
let outputTokens = 0;
|
|
24594
|
+
let reasoningOutputTokens = 0;
|
|
24595
|
+
let cacheWriteInputTokens = 0;
|
|
24596
|
+
let cacheWriteSupported = false;
|
|
24597
|
+
let timeToFirstTokenMs = null;
|
|
24598
|
+
let providerCallId = null;
|
|
24599
|
+
for (const event of usageEvents) {
|
|
24600
|
+
if (event.type !== "assistant.usage") continue;
|
|
24601
|
+
observedModels.add(event.data.model);
|
|
24602
|
+
if (event.data.reasoningEffort) observedEfforts.add(event.data.reasoningEffort);
|
|
24603
|
+
inputTokens += requiredUsageInteger(event.data.inputTokens, "input_tokens");
|
|
24604
|
+
cachedInputTokens += optionalUsageInteger(event.data.cacheReadTokens, "cache_read_tokens");
|
|
24605
|
+
outputTokens += requiredUsageInteger(event.data.outputTokens, "output_tokens");
|
|
24606
|
+
reasoningOutputTokens += optionalUsageInteger(event.data.reasoningTokens, "reasoning_tokens");
|
|
24607
|
+
if (event.data.cacheWriteTokens !== void 0) {
|
|
24608
|
+
cacheWriteSupported = true;
|
|
24609
|
+
cacheWriteInputTokens += optionalUsageInteger(event.data.cacheWriteTokens, "cache_write_tokens");
|
|
24610
|
+
}
|
|
24611
|
+
if (timeToFirstTokenMs === null && Number.isSafeInteger(event.data.timeToFirstTokenMs)) {
|
|
24612
|
+
timeToFirstTokenMs = Number(event.data.timeToFirstTokenMs);
|
|
24613
|
+
}
|
|
24614
|
+
providerCallId = event.data.providerCallId ?? event.data.apiCallId ?? providerCallId;
|
|
24615
|
+
}
|
|
24616
|
+
if (usageEvents.length === 0) throw new Error("copilot_agent_usage_receipt_missing");
|
|
24617
|
+
if (response.data.model) observedModels.add(response.data.model);
|
|
24618
|
+
if (observedModels.size !== 1 || !observedModels.has(input.requestedModel)) {
|
|
24619
|
+
throw new Error("copilot_agent_effective_model_mismatch");
|
|
24620
|
+
}
|
|
24621
|
+
const effectiveEffort = input.requestedReasoningEffort === "none" ? observedEfforts.size === 0 ? "none" : observedEfforts.size === 1 ? [...observedEfforts][0] : null : observedEfforts.size === 1 ? [...observedEfforts][0] : null;
|
|
24622
|
+
if (effectiveEffort !== input.requestedReasoningEffort) {
|
|
24623
|
+
throw new Error("copilot_agent_effective_effort_mismatch");
|
|
24624
|
+
}
|
|
24625
|
+
const usage = {
|
|
24626
|
+
inputTokens,
|
|
24627
|
+
cachedInputTokens: Math.min(cachedInputTokens, inputTokens),
|
|
24628
|
+
outputTokens,
|
|
24629
|
+
reasoningOutputTokens: Math.min(reasoningOutputTokens, outputTokens),
|
|
24630
|
+
totalTokens: inputTokens + outputTokens,
|
|
24631
|
+
cacheWriteInputTokens: cacheWriteSupported ? cacheWriteInputTokens : null,
|
|
24632
|
+
cacheWriteSupported
|
|
24633
|
+
};
|
|
24634
|
+
return {
|
|
24635
|
+
thread,
|
|
24636
|
+
turn: {
|
|
24637
|
+
text: response.data.content,
|
|
24638
|
+
reasoningContent: response.data.reasoningText ?? null,
|
|
24639
|
+
reasoningSummary: null,
|
|
24640
|
+
requestedModel: input.requestedModel,
|
|
24641
|
+
effectiveModel: input.requestedModel,
|
|
24642
|
+
requestedReasoningEffort: input.requestedReasoningEffort,
|
|
24643
|
+
effectiveReasoningEffort: effectiveEffort,
|
|
24644
|
+
adapterRequestId: providerCallId ?? response.data.requestId ?? response.data.messageId,
|
|
24645
|
+
adapterResponseId: response.data.serviceRequestId ?? response.data.messageId,
|
|
24646
|
+
usage,
|
|
24647
|
+
latencyMs: Math.max(0, (this.dependencies.now ?? Date.now)() - startedAt),
|
|
24648
|
+
timeToFirstTokenMs,
|
|
24649
|
+
terminalStatus: "completed",
|
|
24650
|
+
toolCalls: toolEvidence,
|
|
24651
|
+
webSearches: []
|
|
24652
|
+
}
|
|
24653
|
+
};
|
|
24654
|
+
} catch (error48) {
|
|
24655
|
+
if (error48 instanceof CodexAppServerError) throw error48;
|
|
24656
|
+
const cancelled = input.signal?.aborted === true;
|
|
24657
|
+
const deadline = Date.now() >= input.deadlineAtMs;
|
|
24658
|
+
if (dispatchEntered) await session?.abort().catch(() => void 0);
|
|
24659
|
+
if (session && !durableCheckpointed) {
|
|
24660
|
+
const abandonedSession = session;
|
|
24661
|
+
session = null;
|
|
24662
|
+
if (this.agentConnection?.session === abandonedSession) this.agentConnection = null;
|
|
24663
|
+
await abandonedSession.disconnect().catch(() => void 0);
|
|
24664
|
+
await client.deleteSession(abandonedSession.sessionId).catch(() => void 0);
|
|
24665
|
+
const cleanup = this.agentWorkspaceCleanups.get(workspacePath);
|
|
24666
|
+
if (cleanup) {
|
|
24667
|
+
await cleanup().catch(() => void 0);
|
|
24668
|
+
this.agentWorkspaceCleanups.delete(workspacePath);
|
|
24669
|
+
}
|
|
24670
|
+
}
|
|
24671
|
+
throw new CodexAppServerError({
|
|
24672
|
+
message: cancelled ? "Copilot Agent turn was cancelled." : deadline ? "Copilot Agent turn exceeded its deadline." : error48 instanceof Error ? error48.message : "Copilot Agent adapter failed.",
|
|
24673
|
+
category: cancelled ? "cancelled" : deadline ? "timeout" : "adapter",
|
|
24674
|
+
code: cancelled ? "cancelled" : deadline ? "deadline_exceeded" : "copilot_agent_adapter_failure",
|
|
24675
|
+
retryable: false,
|
|
24676
|
+
dispatchOutcome: dispatchEntered ? "confirmed_dispatched" : "not_dispatched",
|
|
24677
|
+
cause: error48
|
|
24678
|
+
});
|
|
24679
|
+
} finally {
|
|
24680
|
+
await session?.disconnect().catch(() => void 0);
|
|
24681
|
+
await client.stop().catch(async () => {
|
|
24682
|
+
await client.forceStop();
|
|
24683
|
+
});
|
|
24684
|
+
if (this.agentConnection?.session === session) this.agentConnection = null;
|
|
24685
|
+
}
|
|
24686
|
+
}
|
|
24687
|
+
async releaseThread(thread) {
|
|
24688
|
+
const active = this.agentConnection;
|
|
24689
|
+
if (active?.session.sessionId === thread.threadId) {
|
|
24690
|
+
await active.session.disconnect().catch(() => void 0);
|
|
24691
|
+
await active.client.stop().catch(async () => {
|
|
24692
|
+
await active.client.forceStop();
|
|
24693
|
+
});
|
|
24694
|
+
this.agentConnection = null;
|
|
24695
|
+
}
|
|
24696
|
+
const client = (this.dependencies.createClient ?? defaultClient)(thread.threadPath);
|
|
24697
|
+
await client.start();
|
|
24698
|
+
try {
|
|
24699
|
+
await client.deleteSession(thread.threadId);
|
|
24700
|
+
} finally {
|
|
24701
|
+
await client.stop().catch(async () => {
|
|
24702
|
+
await client.forceStop();
|
|
24703
|
+
});
|
|
24704
|
+
}
|
|
24705
|
+
const cleanup = this.agentWorkspaceCleanups.get(thread.threadPath);
|
|
24706
|
+
if (cleanup) {
|
|
24707
|
+
await cleanup();
|
|
24708
|
+
this.agentWorkspaceCleanups.delete(thread.threadPath);
|
|
24709
|
+
}
|
|
24710
|
+
}
|
|
24711
|
+
async close() {
|
|
24712
|
+
this.closing = true;
|
|
24713
|
+
const active = this.agentConnection;
|
|
24714
|
+
this.agentConnection = null;
|
|
24715
|
+
if (!active) return;
|
|
24716
|
+
await active.session.disconnect().catch(() => void 0);
|
|
24717
|
+
await active.client.stop().catch(async () => {
|
|
24718
|
+
await active.client.forceStop();
|
|
24719
|
+
});
|
|
24720
|
+
}
|
|
24299
24721
|
};
|
|
24300
24722
|
}
|
|
24301
24723
|
});
|
|
@@ -30873,7 +31295,7 @@ var require_ajv = __commonJS({
|
|
|
30873
31295
|
});
|
|
30874
31296
|
|
|
30875
31297
|
// lib/inference-host/runner.ts
|
|
30876
|
-
import { createHash as createHash6, randomUUID } from "node:crypto";
|
|
31298
|
+
import { createHash as createHash6, randomUUID as randomUUID2 } from "node:crypto";
|
|
30877
31299
|
function createDefaultInferenceHostRunnerDependencies(options) {
|
|
30878
31300
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
30879
31301
|
return {
|
|
@@ -30908,7 +31330,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
|
|
|
30908
31330
|
envelopePublicKey: options.envelopePublicKey
|
|
30909
31331
|
};
|
|
30910
31332
|
}
|
|
30911
|
-
var import_ajv, RUNTIME_RECEIPT_SCHEMA_VERSION, ATTEMPT_RECEIPT_SCHEMA_VERSION, DEFAULT_ADVERTISEMENT_TTL_MS, DEFAULT_ADVERTISEMENT_REFRESH_LEAD_MS, DEFAULT_HOST_HEARTBEAT_MS, DEFAULT_PROVIDER_RATE_LIMIT_REFRESH_MS, DEFAULT_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, MIN_SLEEP_MS, MIN_HOST_HEARTBEAT_GAP_DIAGNOSTIC_MS, HOST_HEARTBEAT_GAP_DIAGNOSTIC_FACTOR, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, MAX_ATTEMPT_START_RETRY_DELAY_MS, UNBOUNDED_AVAILABLE_SLOTS, buildInferenceAdvertisedModels, summarizeInferenceHostRuntimeRecovery, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, settlesWithin, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, providerWeeklyQuotaFromRateLimits, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, membershipFailureDisposition, safeFailureCode, attemptStartRetryFallbackMs, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner,
|
|
31333
|
+
var import_ajv, RUNTIME_RECEIPT_SCHEMA_VERSION, ATTEMPT_RECEIPT_SCHEMA_VERSION, DEFAULT_ADVERTISEMENT_TTL_MS, DEFAULT_ADVERTISEMENT_REFRESH_LEAD_MS, DEFAULT_HOST_HEARTBEAT_MS, DEFAULT_PROVIDER_RATE_LIMIT_REFRESH_MS, DEFAULT_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, MIN_SLEEP_MS, MIN_HOST_HEARTBEAT_GAP_DIAGNOSTIC_MS, HOST_HEARTBEAT_GAP_DIAGNOSTIC_FACTOR, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, MAX_ATTEMPT_START_RETRY_DELAY_MS, UNBOUNDED_AVAILABLE_SLOTS, buildInferenceAdvertisedModels, summarizeInferenceHostRuntimeRecovery, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, settlesWithin, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, providerWeeklyQuotaFromRateLimits, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, membershipFailureDisposition, safeFailureCode, attemptStartRetryFallbackMs, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner, createInferenceAgentControlClient, INFERENCE_AGENT_SYSTEM_PROMPT, INFERENCE_AGENT_WAKE_SCHEMA, parseInferenceAgentWake, InferenceAgentRuntime;
|
|
30912
31334
|
var init_runner = __esm({
|
|
30913
31335
|
"lib/inference-host/runner.ts"() {
|
|
30914
31336
|
"use strict";
|
|
@@ -31292,7 +31714,7 @@ var init_runner = __esm({
|
|
|
31292
31714
|
adapterId,
|
|
31293
31715
|
options.structuredOutput ?? adapterId === "codex",
|
|
31294
31716
|
options.sameAttemptRecovery ?? adapterId === "codex",
|
|
31295
|
-
options.agentRuntime
|
|
31717
|
+
options.agentRuntime ? ["provider", "agent"] : ["provider"]
|
|
31296
31718
|
),
|
|
31297
31719
|
maxConcurrency: options.maxConcurrency === null || options.maxConcurrency === void 0 ? null : finitePositiveOption(options.maxConcurrency, 1, "Maximum concurrency"),
|
|
31298
31720
|
advertisementTtlMs,
|
|
@@ -31747,10 +32169,11 @@ var init_runner = __esm({
|
|
|
31747
32169
|
const agentRuntimeSettings = settings.agentRuntime;
|
|
31748
32170
|
agentLoop = (async () => {
|
|
31749
32171
|
while (!agentAbort.signal.aborted) {
|
|
31750
|
-
const agentRuntime = new
|
|
32172
|
+
const agentRuntime = new InferenceAgentRuntime({
|
|
32173
|
+
adapterId: settings.adapterId,
|
|
31751
32174
|
hostId: localState.host_id,
|
|
31752
32175
|
statePath: agentRuntimeSettings.statePath,
|
|
31753
|
-
controlClient:
|
|
32176
|
+
controlClient: createInferenceAgentControlClient(mcp),
|
|
31754
32177
|
adapter: agentRuntimeSettings.adapter
|
|
31755
32178
|
});
|
|
31756
32179
|
try {
|
|
@@ -33088,7 +33511,7 @@ var init_runner = __esm({
|
|
|
33088
33511
|
}
|
|
33089
33512
|
}
|
|
33090
33513
|
};
|
|
33091
|
-
|
|
33514
|
+
createInferenceAgentControlClient = (mcp) => ({
|
|
33092
33515
|
nextAssignment: async (request, options) => {
|
|
33093
33516
|
const result2 = await mcp.callTool("inference.agent.assignment.next", {
|
|
33094
33517
|
...request,
|
|
@@ -33131,9 +33554,9 @@ var init_runner = __esm({
|
|
|
33131
33554
|
await mcp.callTool("inference.agent.assignment.release", request, options);
|
|
33132
33555
|
}
|
|
33133
33556
|
});
|
|
33134
|
-
|
|
33557
|
+
INFERENCE_AGENT_SYSTEM_PROMPT = `You autonomously control one running VTX bot.
|
|
33135
33558
|
VTX supplies no trading prompt or prepared market context. At your own cadence, request zero, some, or all assignment-scoped data with vtx_get_data and independently use web search when useful. Submit trading instructions only through vtx_submit_decision, using the assignment's exact decision schema. VTX remains responsible for validating and executing the same structured decision used by normal Server and Client modes. You have no shell, filesystem-write, app, plugin, browser-control, or subagent authority.`;
|
|
33136
|
-
|
|
33559
|
+
INFERENCE_AGENT_WAKE_SCHEMA = {
|
|
33137
33560
|
type: "object",
|
|
33138
33561
|
additionalProperties: false,
|
|
33139
33562
|
required: ["next_wake_seconds", "summary"],
|
|
@@ -33142,29 +33565,29 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33142
33565
|
summary: { type: "string", minLength: 1, maxLength: 2e3 }
|
|
33143
33566
|
}
|
|
33144
33567
|
};
|
|
33145
|
-
|
|
33568
|
+
parseInferenceAgentWake = (text, assignment) => {
|
|
33146
33569
|
let value;
|
|
33147
33570
|
try {
|
|
33148
33571
|
value = JSON.parse(text);
|
|
33149
33572
|
} catch {
|
|
33150
33573
|
throw new InferenceHostRunnerError(
|
|
33151
33574
|
"invalid_agent_wake",
|
|
33152
|
-
"
|
|
33575
|
+
"Inference Agent returned invalid wake JSON."
|
|
33153
33576
|
);
|
|
33154
33577
|
}
|
|
33155
33578
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
33156
|
-
throw new InferenceHostRunnerError("invalid_agent_wake", "
|
|
33579
|
+
throw new InferenceHostRunnerError("invalid_agent_wake", "Inference Agent wake is invalid.");
|
|
33157
33580
|
}
|
|
33158
33581
|
const seconds = value.next_wake_seconds;
|
|
33159
33582
|
if (!Number.isSafeInteger(seconds) || Number(seconds) < 1) {
|
|
33160
|
-
throw new InferenceHostRunnerError("invalid_agent_wake", "
|
|
33583
|
+
throw new InferenceHostRunnerError("invalid_agent_wake", "Inference Agent wake is invalid.");
|
|
33161
33584
|
}
|
|
33162
33585
|
return Math.max(
|
|
33163
33586
|
assignment.minimum_wake_seconds,
|
|
33164
33587
|
Math.min(assignment.maximum_wake_seconds, Number(seconds))
|
|
33165
33588
|
);
|
|
33166
33589
|
};
|
|
33167
|
-
|
|
33590
|
+
InferenceAgentRuntime = class {
|
|
33168
33591
|
constructor(options) {
|
|
33169
33592
|
this.options = options;
|
|
33170
33593
|
this.stopped = false;
|
|
@@ -33198,29 +33621,55 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33198
33621
|
}
|
|
33199
33622
|
async runOnce(signal) {
|
|
33200
33623
|
const nowIso = () => new Date(this.now()).toISOString();
|
|
33201
|
-
const recoveredState = await
|
|
33624
|
+
const recoveredState = await readInferenceAgentRuntimeState(this.options.statePath);
|
|
33202
33625
|
if (recoveredState && recoveredState.host_id !== this.options.hostId) {
|
|
33203
33626
|
throw new InferenceHostRunnerError(
|
|
33204
33627
|
"agent_recovery_scope_mismatch",
|
|
33205
|
-
"
|
|
33628
|
+
"Inference Agent recovery state belongs to another host."
|
|
33206
33629
|
);
|
|
33207
33630
|
}
|
|
33208
33631
|
let state;
|
|
33209
33632
|
if (recoveredState?.schema_version === "vtx_codex_agent_runtime_v1") {
|
|
33633
|
+
if (this.options.adapterId !== "codex") {
|
|
33634
|
+
throw new InferenceHostRunnerError(
|
|
33635
|
+
"agent_recovery_adapter_mismatch",
|
|
33636
|
+
"Legacy Codex Agent recovery state cannot be opened by another adapter."
|
|
33637
|
+
);
|
|
33638
|
+
}
|
|
33210
33639
|
state = await this.upgradeLegacyRuntimeState(recoveredState, signal);
|
|
33211
33640
|
if (!state) return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33641
|
+
} else if (recoveredState?.schema_version === "vtx_codex_agent_runtime_v2") {
|
|
33642
|
+
if (this.options.adapterId !== "codex") {
|
|
33643
|
+
throw new InferenceHostRunnerError(
|
|
33644
|
+
"agent_recovery_adapter_mismatch",
|
|
33645
|
+
"Legacy Codex Agent recovery state cannot be opened by another adapter."
|
|
33646
|
+
);
|
|
33647
|
+
}
|
|
33648
|
+
state = {
|
|
33649
|
+
...recoveredState,
|
|
33650
|
+
schema_version: "vtx_inference_agent_runtime_v3",
|
|
33651
|
+
adapter_id: "codex"
|
|
33652
|
+
};
|
|
33653
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33212
33654
|
} else {
|
|
33213
33655
|
state = recoveredState ?? null;
|
|
33656
|
+
if (state && state.adapter_id !== this.options.adapterId) {
|
|
33657
|
+
throw new InferenceHostRunnerError(
|
|
33658
|
+
"agent_recovery_adapter_mismatch",
|
|
33659
|
+
"Inference Agent recovery state belongs to another adapter."
|
|
33660
|
+
);
|
|
33661
|
+
}
|
|
33214
33662
|
}
|
|
33215
33663
|
if (!state) {
|
|
33216
33664
|
const assignment2 = await this.options.controlClient.nextAssignment({
|
|
33217
|
-
operation_id:
|
|
33665
|
+
operation_id: randomUUID2(),
|
|
33218
33666
|
host_id: this.options.hostId,
|
|
33219
33667
|
requested_at: nowIso()
|
|
33220
33668
|
}, { signal });
|
|
33221
33669
|
if (!assignment2) return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33222
33670
|
state = {
|
|
33223
|
-
schema_version: "
|
|
33671
|
+
schema_version: "vtx_inference_agent_runtime_v3",
|
|
33672
|
+
adapter_id: this.options.adapterId,
|
|
33224
33673
|
host_id: this.options.hostId,
|
|
33225
33674
|
assignment: assignment2,
|
|
33226
33675
|
thread: null,
|
|
@@ -33228,7 +33677,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33228
33677
|
pending_decision: null,
|
|
33229
33678
|
updated_at: nowIso()
|
|
33230
33679
|
};
|
|
33231
|
-
await
|
|
33680
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33232
33681
|
} else {
|
|
33233
33682
|
const persistedWakeAtMs = Date.parse(state.next_wake_at);
|
|
33234
33683
|
if (persistedWakeAtMs > this.now()) {
|
|
@@ -33236,8 +33685,8 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33236
33685
|
if (wakeOutcome !== "ready") {
|
|
33237
33686
|
return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33238
33687
|
}
|
|
33239
|
-
const rereadState = await
|
|
33240
|
-
if (rereadState?.schema_version !== "
|
|
33688
|
+
const rereadState = await readInferenceAgentRuntimeState(this.options.statePath);
|
|
33689
|
+
if (rereadState?.schema_version !== "vtx_inference_agent_runtime_v3" || rereadState.adapter_id !== this.options.adapterId) {
|
|
33241
33690
|
return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33242
33691
|
}
|
|
33243
33692
|
state = rereadState;
|
|
@@ -33246,7 +33695,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33246
33695
|
state = await this.resolvePendingDecision(state, signal);
|
|
33247
33696
|
let assignment = state.assignment;
|
|
33248
33697
|
const preTurnHeartbeat = await this.options.controlClient.heartbeat({
|
|
33249
|
-
operation_id:
|
|
33698
|
+
operation_id: randomUUID2(),
|
|
33250
33699
|
host_id: this.options.hostId,
|
|
33251
33700
|
assignment_id: assignment.assignment_id,
|
|
33252
33701
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33261,7 +33710,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33261
33710
|
lease_expires_at: preTurnHeartbeat.lease_expires_at
|
|
33262
33711
|
};
|
|
33263
33712
|
state = { ...state, assignment, updated_at: nowIso() };
|
|
33264
|
-
await
|
|
33713
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33265
33714
|
const turnAbort = new AbortController();
|
|
33266
33715
|
const relayAbort = () => turnAbort.abort();
|
|
33267
33716
|
signal?.addEventListener("abort", relayAbort, { once: true });
|
|
@@ -33271,7 +33720,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33271
33720
|
const heartbeatTask = (async () => {
|
|
33272
33721
|
while (!heartbeatStopped && !turnAbort.signal.aborted) {
|
|
33273
33722
|
const heartbeat = await this.options.controlClient.heartbeat({
|
|
33274
|
-
operation_id:
|
|
33723
|
+
operation_id: randomUUID2(),
|
|
33275
33724
|
host_id: this.options.hostId,
|
|
33276
33725
|
assignment_id: assignment.assignment_id,
|
|
33277
33726
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33295,7 +33744,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33295
33744
|
const deadlineAtMs = this.now() + (this.options.turnTimeoutMs ?? 10 * 6e4);
|
|
33296
33745
|
const result2 = await this.options.adapter.runTurn({
|
|
33297
33746
|
durableThread: state.thread,
|
|
33298
|
-
systemPrompt:
|
|
33747
|
+
systemPrompt: INFERENCE_AGENT_SYSTEM_PROMPT,
|
|
33299
33748
|
userPrompt: JSON.stringify({
|
|
33300
33749
|
assignment_id: assignment.assignment_id,
|
|
33301
33750
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33309,7 +33758,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33309
33758
|
maximum: assignment.maximum_wake_seconds
|
|
33310
33759
|
}
|
|
33311
33760
|
}),
|
|
33312
|
-
outputSchema:
|
|
33761
|
+
outputSchema: INFERENCE_AGENT_WAKE_SCHEMA,
|
|
33313
33762
|
dataContract: assignment.data_contract,
|
|
33314
33763
|
decisionSchema: assignment.output_schema,
|
|
33315
33764
|
requestedModel: assignment.model_id,
|
|
@@ -33318,7 +33767,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33318
33767
|
signal: turnAbort.signal,
|
|
33319
33768
|
onThreadReady: async (thread) => {
|
|
33320
33769
|
state = { ...state, thread, updated_at: nowIso() };
|
|
33321
|
-
await
|
|
33770
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33322
33771
|
},
|
|
33323
33772
|
executeTool: async (call) => {
|
|
33324
33773
|
if (call.tool === "vtx_get_data") {
|
|
@@ -33328,7 +33777,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33328
33777
|
return { success: false, value: { error: "invalid_data_request" } };
|
|
33329
33778
|
}
|
|
33330
33779
|
const value = await this.options.controlClient.dataCall({
|
|
33331
|
-
operation_id:
|
|
33780
|
+
operation_id: randomUUID2(),
|
|
33332
33781
|
host_id: this.options.hostId,
|
|
33333
33782
|
assignment_id: assignment.assignment_id,
|
|
33334
33783
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33352,12 +33801,12 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33352
33801
|
return { success: false, value: { error: "decision_outcome_unresolved" } };
|
|
33353
33802
|
}
|
|
33354
33803
|
const pending = {
|
|
33355
|
-
operation_id:
|
|
33804
|
+
operation_id: randomUUID2(),
|
|
33356
33805
|
candidate,
|
|
33357
33806
|
observed_at: nowIso(),
|
|
33358
33807
|
provenance: {
|
|
33359
|
-
source: "
|
|
33360
|
-
|
|
33808
|
+
source: "external_agent",
|
|
33809
|
+
agent_run_id: liveThread.threadId,
|
|
33361
33810
|
requested_model: assignment.model_id,
|
|
33362
33811
|
effective_model: liveThread.effectiveModel,
|
|
33363
33812
|
requested_reasoning_effort: assignment.reasoning_effort,
|
|
@@ -33367,13 +33816,13 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33367
33816
|
last_status_check_at: null
|
|
33368
33817
|
};
|
|
33369
33818
|
state = { ...state, pending_decision: pending, updated_at: nowIso() };
|
|
33370
|
-
await
|
|
33819
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33371
33820
|
state = {
|
|
33372
33821
|
...state,
|
|
33373
33822
|
pending_decision: { ...pending, first_transmit_at: nowIso() },
|
|
33374
33823
|
updated_at: nowIso()
|
|
33375
33824
|
};
|
|
33376
|
-
await
|
|
33825
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33377
33826
|
let submitStatus;
|
|
33378
33827
|
try {
|
|
33379
33828
|
submitStatus = await this.options.controlClient.submitDecision({
|
|
@@ -33390,7 +33839,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33390
33839
|
}
|
|
33391
33840
|
if (submitStatus.status === "applied" || submitStatus.status === "not_applied") {
|
|
33392
33841
|
state = { ...state, pending_decision: null, updated_at: nowIso() };
|
|
33393
|
-
await
|
|
33842
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33394
33843
|
}
|
|
33395
33844
|
return {
|
|
33396
33845
|
success: submitStatus.status === "applied",
|
|
@@ -33414,7 +33863,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33414
33863
|
pending_decision: null,
|
|
33415
33864
|
updated_at: nowIso()
|
|
33416
33865
|
};
|
|
33417
|
-
await
|
|
33866
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33418
33867
|
}
|
|
33419
33868
|
return {
|
|
33420
33869
|
success: status.status === "applied" || status.status === "not_applied",
|
|
@@ -33422,11 +33871,11 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33422
33871
|
};
|
|
33423
33872
|
}
|
|
33424
33873
|
});
|
|
33425
|
-
const wakeSeconds =
|
|
33874
|
+
const wakeSeconds = parseInferenceAgentWake(result2.turn.text, assignment);
|
|
33426
33875
|
const nextWakeAtMs = this.now() + wakeSeconds * 1e3;
|
|
33427
33876
|
const scheduledWakeAt = new Date(nextWakeAtMs).toISOString();
|
|
33428
33877
|
const wakeHeartbeat = await this.options.controlClient.heartbeat({
|
|
33429
|
-
operation_id:
|
|
33878
|
+
operation_id: randomUUID2(),
|
|
33430
33879
|
host_id: this.options.hostId,
|
|
33431
33880
|
assignment_id: assignment.assignment_id,
|
|
33432
33881
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33436,7 +33885,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33436
33885
|
if (wakeHeartbeat.directive === "cancel") {
|
|
33437
33886
|
if (state.pending_decision) return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33438
33887
|
await this.options.adapter.releaseThread(result2.thread).catch(() => void 0);
|
|
33439
|
-
await
|
|
33888
|
+
await clearInferenceAgentRuntimeState(this.options.statePath);
|
|
33440
33889
|
return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33441
33890
|
}
|
|
33442
33891
|
latestLeaseExpiry = wakeHeartbeat.lease_expires_at;
|
|
@@ -33447,7 +33896,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33447
33896
|
next_wake_at: scheduledWakeAt,
|
|
33448
33897
|
updated_at: nowIso()
|
|
33449
33898
|
};
|
|
33450
|
-
await
|
|
33899
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33451
33900
|
return nextWakeAtMs;
|
|
33452
33901
|
} catch (error48) {
|
|
33453
33902
|
if (!cancelled) throw error48;
|
|
@@ -33466,7 +33915,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33466
33915
|
if (state.thread) {
|
|
33467
33916
|
await this.options.adapter.releaseThread(state.thread).catch(() => void 0);
|
|
33468
33917
|
}
|
|
33469
|
-
await
|
|
33918
|
+
await clearInferenceAgentRuntimeState(this.options.statePath);
|
|
33470
33919
|
return null;
|
|
33471
33920
|
}
|
|
33472
33921
|
async resolveLegacyPendingDecision(state, signal) {
|
|
@@ -33478,7 +33927,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33478
33927
|
pending_decision: { ...pending, last_status_check_at: checkedAt },
|
|
33479
33928
|
updated_at: checkedAt
|
|
33480
33929
|
};
|
|
33481
|
-
await
|
|
33930
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, checking);
|
|
33482
33931
|
const status = await this.options.controlClient.decisionStatus({
|
|
33483
33932
|
host_id: this.options.hostId,
|
|
33484
33933
|
assignment_id: state.assignment.assignment_id,
|
|
@@ -33491,7 +33940,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33491
33940
|
pending_decision: null,
|
|
33492
33941
|
updated_at: new Date(this.now()).toISOString()
|
|
33493
33942
|
};
|
|
33494
|
-
await
|
|
33943
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, resolved);
|
|
33495
33944
|
return resolved;
|
|
33496
33945
|
}
|
|
33497
33946
|
async resolvePendingDecision(state, signal) {
|
|
@@ -33503,7 +33952,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33503
33952
|
pending_decision: { ...pending, last_status_check_at: checkedAt },
|
|
33504
33953
|
updated_at: checkedAt
|
|
33505
33954
|
};
|
|
33506
|
-
await
|
|
33955
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, checking);
|
|
33507
33956
|
const status = await this.options.controlClient.decisionStatus({
|
|
33508
33957
|
host_id: this.options.hostId,
|
|
33509
33958
|
assignment_id: state.assignment.assignment_id,
|
|
@@ -33516,7 +33965,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33516
33965
|
pending_decision: null,
|
|
33517
33966
|
updated_at: new Date(this.now()).toISOString()
|
|
33518
33967
|
};
|
|
33519
|
-
await
|
|
33968
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, resolved);
|
|
33520
33969
|
return resolved;
|
|
33521
33970
|
}
|
|
33522
33971
|
async handleCancelledAssignment(state, signal) {
|
|
@@ -33532,7 +33981,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33532
33981
|
if (current.thread) {
|
|
33533
33982
|
await this.options.adapter.releaseThread(current.thread).catch(() => void 0);
|
|
33534
33983
|
}
|
|
33535
|
-
await
|
|
33984
|
+
await clearInferenceAgentRuntimeState(this.options.statePath);
|
|
33536
33985
|
}
|
|
33537
33986
|
async waitUntilWake(nextWakeAtMs, signal) {
|
|
33538
33987
|
const heartbeatIntervalMs = this.options.heartbeatIntervalMs ?? 3e3;
|
|
@@ -33540,11 +33989,11 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33540
33989
|
await this.sleep(Math.min(heartbeatIntervalMs, nextWakeAtMs - this.now()), signal);
|
|
33541
33990
|
if (this.stopped || signal?.aborted) return "stopped";
|
|
33542
33991
|
if (this.now() >= nextWakeAtMs) return "ready";
|
|
33543
|
-
const state = await
|
|
33544
|
-
if (state?.schema_version !== "
|
|
33992
|
+
const state = await readInferenceAgentRuntimeState(this.options.statePath);
|
|
33993
|
+
if (state?.schema_version !== "vtx_inference_agent_runtime_v3" || state.adapter_id !== this.options.adapterId) return "cancelled";
|
|
33545
33994
|
const requestedAt = new Date(this.now()).toISOString();
|
|
33546
33995
|
const heartbeat = await this.options.controlClient.heartbeat({
|
|
33547
|
-
operation_id:
|
|
33996
|
+
operation_id: randomUUID2(),
|
|
33548
33997
|
host_id: this.options.hostId,
|
|
33549
33998
|
assignment_id: state.assignment.assignment_id,
|
|
33550
33999
|
assignment_generation: state.assignment.assignment_generation,
|
|
@@ -33554,7 +34003,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33554
34003
|
await this.handleCancelledAssignment(state, signal);
|
|
33555
34004
|
return "cancelled";
|
|
33556
34005
|
}
|
|
33557
|
-
await
|
|
34006
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, {
|
|
33558
34007
|
...state,
|
|
33559
34008
|
assignment: {
|
|
33560
34009
|
...state.assignment,
|
|
@@ -33566,8 +34015,24 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33566
34015
|
return this.stopped || signal?.aborted ? "stopped" : "ready";
|
|
33567
34016
|
}
|
|
33568
34017
|
async releaseForHostStop() {
|
|
33569
|
-
|
|
33570
|
-
if (!
|
|
34018
|
+
const recovered = await readInferenceAgentRuntimeState(this.options.statePath);
|
|
34019
|
+
if (!recovered) return;
|
|
34020
|
+
let state;
|
|
34021
|
+
if (recovered.schema_version === "vtx_codex_agent_runtime_v1") {
|
|
34022
|
+
if (this.options.adapterId !== "codex") return;
|
|
34023
|
+
state = recovered;
|
|
34024
|
+
} else if (recovered.schema_version === "vtx_codex_agent_runtime_v2") {
|
|
34025
|
+
if (this.options.adapterId !== "codex") return;
|
|
34026
|
+
state = {
|
|
34027
|
+
...recovered,
|
|
34028
|
+
schema_version: "vtx_inference_agent_runtime_v3",
|
|
34029
|
+
adapter_id: "codex"
|
|
34030
|
+
};
|
|
34031
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
34032
|
+
} else {
|
|
34033
|
+
if (recovered.adapter_id !== this.options.adapterId) return;
|
|
34034
|
+
state = recovered;
|
|
34035
|
+
}
|
|
33571
34036
|
try {
|
|
33572
34037
|
state = state.schema_version === "vtx_codex_agent_runtime_v1" ? await this.resolveLegacyPendingDecision(state) : await this.resolvePendingDecision(state);
|
|
33573
34038
|
} catch {
|
|
@@ -33575,7 +34040,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33575
34040
|
}
|
|
33576
34041
|
if (state.pending_decision) return;
|
|
33577
34042
|
await this.options.controlClient.releaseAssignment({
|
|
33578
|
-
operation_id:
|
|
34043
|
+
operation_id: randomUUID2(),
|
|
33579
34044
|
host_id: this.options.hostId,
|
|
33580
34045
|
assignment_id: state.assignment.assignment_id,
|
|
33581
34046
|
assignment_generation: state.assignment.assignment_generation,
|
|
@@ -33583,7 +34048,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33583
34048
|
requested_at: new Date(this.now()).toISOString()
|
|
33584
34049
|
}, {});
|
|
33585
34050
|
if (state.thread) await this.options.adapter.releaseThread(state.thread);
|
|
33586
|
-
await
|
|
34051
|
+
await clearInferenceAgentRuntimeState(this.options.statePath);
|
|
33587
34052
|
}
|
|
33588
34053
|
};
|
|
33589
34054
|
}
|
|
@@ -33591,7 +34056,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33591
34056
|
|
|
33592
34057
|
// lib/inference-host/service.ts
|
|
33593
34058
|
import { spawn as spawn6 } from "node:child_process";
|
|
33594
|
-
import { randomUUID as
|
|
34059
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
33595
34060
|
import { createWriteStream, readFileSync } from "node:fs";
|
|
33596
34061
|
import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as rm5, writeFile as writeFile2 } from "node:fs/promises";
|
|
33597
34062
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -34116,7 +34581,7 @@ WantedBy=default.target
|
|
|
34116
34581
|
const previousRuntimeUpdatedAt = previousRuntime?.manifest_generation === manifest.generation ? Date.parse(previousRuntime.updated_at) : Number.NaN;
|
|
34117
34582
|
const restoredManifest = preserveGeneration ? manifest : assertManifest({
|
|
34118
34583
|
...manifest,
|
|
34119
|
-
generation:
|
|
34584
|
+
generation: randomUUID3(),
|
|
34120
34585
|
installed_at: this.now().toISOString()
|
|
34121
34586
|
});
|
|
34122
34587
|
await writeAtomicInferencePrivateFile(
|
|
@@ -34402,7 +34867,7 @@ ${cleanup.stderr}`)) {
|
|
|
34402
34867
|
].sort((left, right) => left.instance_name.localeCompare(right.instance_name));
|
|
34403
34868
|
const manifest = assertManifest({
|
|
34404
34869
|
schema_version: "vtx_inference_service_v3",
|
|
34405
|
-
generation:
|
|
34870
|
+
generation: randomUUID3(),
|
|
34406
34871
|
installed_at: this.now().toISOString(),
|
|
34407
34872
|
executable: this.executable,
|
|
34408
34873
|
script: this.script,
|
|
@@ -34616,7 +35081,7 @@ ${result2.stderr}`)) {
|
|
|
34616
35081
|
if (remaining.length === 0) return await this.uninstallUnlocked();
|
|
34617
35082
|
return await this.replaceManifestUnlocked({
|
|
34618
35083
|
...manifest,
|
|
34619
|
-
generation:
|
|
35084
|
+
generation: randomUUID3(),
|
|
34620
35085
|
installed_at: this.now().toISOString(),
|
|
34621
35086
|
workers: remaining
|
|
34622
35087
|
}, await readInferenceHostServiceDesired(this.desiredPath()));
|
|
@@ -35006,7 +35471,7 @@ __export(cli_exports, {
|
|
|
35006
35471
|
registerInferenceHostServiceControlInput: () => registerInferenceHostServiceControlInput,
|
|
35007
35472
|
runInferenceHostCli: () => runInferenceHostCli
|
|
35008
35473
|
});
|
|
35009
|
-
import { createHash as createHash7, randomUUID as
|
|
35474
|
+
import { createHash as createHash7, randomUUID as randomUUID4 } from "node:crypto";
|
|
35010
35475
|
import { spawn as spawn7 } from "node:child_process";
|
|
35011
35476
|
import { lstat as lstat4, realpath as realpath4, rm as rm6 } from "node:fs/promises";
|
|
35012
35477
|
import { hostname as osHostname } from "node:os";
|
|
@@ -35070,6 +35535,42 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35070
35535
|
async () => await agentFail(config2, parsed, dependencies, warnings)
|
|
35071
35536
|
);
|
|
35072
35537
|
}
|
|
35538
|
+
if (parsed.command === "agent-assignment-next") {
|
|
35539
|
+
return await withAgentCommandLock(
|
|
35540
|
+
config2,
|
|
35541
|
+
async () => await foregroundAssignmentNext(config2, parsed, dependencies, warnings)
|
|
35542
|
+
);
|
|
35543
|
+
}
|
|
35544
|
+
if (parsed.command === "agent-assignment-heartbeat") {
|
|
35545
|
+
return await withAgentCommandLock(
|
|
35546
|
+
config2,
|
|
35547
|
+
async () => await foregroundAssignmentHeartbeat(config2, parsed, dependencies, warnings)
|
|
35548
|
+
);
|
|
35549
|
+
}
|
|
35550
|
+
if (parsed.command === "agent-data-call") {
|
|
35551
|
+
return await withAgentCommandLock(
|
|
35552
|
+
config2,
|
|
35553
|
+
async () => await foregroundDataCall(config2, parsed, dependencies, warnings)
|
|
35554
|
+
);
|
|
35555
|
+
}
|
|
35556
|
+
if (parsed.command === "agent-decision-submit") {
|
|
35557
|
+
return await withAgentCommandLock(
|
|
35558
|
+
config2,
|
|
35559
|
+
async () => await foregroundDecisionSubmit(config2, parsed, dependencies, warnings)
|
|
35560
|
+
);
|
|
35561
|
+
}
|
|
35562
|
+
if (parsed.command === "agent-decision-status") {
|
|
35563
|
+
return await withAgentCommandLock(
|
|
35564
|
+
config2,
|
|
35565
|
+
async () => await foregroundDecisionStatus(config2, parsed, dependencies, warnings)
|
|
35566
|
+
);
|
|
35567
|
+
}
|
|
35568
|
+
if (parsed.command === "agent-assignment-release") {
|
|
35569
|
+
return await withAgentCommandLock(
|
|
35570
|
+
config2,
|
|
35571
|
+
async () => await foregroundAssignmentRelease(config2, parsed, dependencies, warnings)
|
|
35572
|
+
);
|
|
35573
|
+
}
|
|
35073
35574
|
if (parsed.command === "service") {
|
|
35074
35575
|
const mutationActions = /* @__PURE__ */ new Set(["install", "start", "stop", "recover", "uninstall"]);
|
|
35075
35576
|
if (!parsed.serviceAction || !mutationActions.has(parsed.serviceAction)) {
|
|
@@ -35100,7 +35601,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35100
35601
|
return await cleanupLogin(config2, parsed, dependencies, warnings, true);
|
|
35101
35602
|
}
|
|
35102
35603
|
throw new Error(
|
|
35103
|
-
"Usage: vtx inference-host <login|codex-login|run|agent-connect|agent-run|agent-next|agent-complete|agent-fail|service|status|doctor|logout|codex-logout|revoke> [--json]"
|
|
35604
|
+
"Usage: vtx inference-host <login|codex-login|run|agent-connect|agent-run|agent-next|agent-complete|agent-fail|agent-assignment-next|agent-assignment-heartbeat|agent-data-call|agent-decision-submit|agent-decision-status|agent-assignment-release|service|status|doctor|logout|codex-logout|revoke> [--json]"
|
|
35104
35605
|
);
|
|
35105
35606
|
} catch (error48) {
|
|
35106
35607
|
return {
|
|
@@ -35111,7 +35612,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35111
35612
|
};
|
|
35112
35613
|
}
|
|
35113
35614
|
}
|
|
35114
|
-
var INFERENCE_HOST_CLI_VERSION, runtimeReceiptPath, codexRecoveryPath, codexGuardianReceiptRoot, revocationCheckpointPath, foregroundHostLockPath, credentialLifecycleLockPath, serviceRecoveryCommandLockPath, AGENT_HEARTBEAT_INTERVAL_MS, AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS, retryableAgentHeartbeatError, assertRevocationCheckpoint, readRevocationCheckpoint, writeRevocationCheckpoint, clearRevocationCheckpoint, render, INFERENCE_HOST_HELP, parseHostConcurrency, parseInferenceHostArgs, resolveDurableServiceDisplayName, defaultOpenBrowser, registerInferenceHostServiceControlInput, defaultRegisterLifecycleSignalHandlers, lifecycleCancellation, configuredCredentialStore, restoreInferenceHostCredentialContext, recoverInferenceHostCredentialContextTransition, accountKeyForState, assertCredentialMatchesState2, revocationCheckpointForCredential, assertRevocationCheckpointMatchesLocalIdentity, fileExistsPrivately, inspectCodexAuthentication, clearLocalRuntimeArtifacts, assertDurableServiceUninstalled, assertLocalRuntimeArtifactsMayBeDiscarded, defaultRunForeground, preparePortableDurableAdapter, defaultRunPortableDurableAdapter, login, codexLogin, codexLogout, localStatus, doctor, cleanupLogin, runHost, defaultReadStdin, parseAgentStdin, agentOperationId, agentSession, agentConnect, agentRun, agentNext, agentComplete, agentFail, withAgentCommandLock, recoveryBackupPath, serviceRecoveryTransactionPath, readServiceRecoveryTransaction, assertResumableCodexRecoveryEvidence, recoverInstalledCodexService, serviceCommand, hasExplicitCredentialStoreConfiguration, credentialEnvironmentForIdentity, commandRequiresRetainedCredentialStore, commandUsesInstalledServiceCredentials, resolveInferenceHostCommandConfig;
|
|
35615
|
+
var INFERENCE_HOST_CLI_VERSION, runtimeReceiptPath, codexRecoveryPath, codexGuardianReceiptRoot, revocationCheckpointPath, foregroundHostLockPath, credentialLifecycleLockPath, serviceRecoveryCommandLockPath, AGENT_HEARTBEAT_INTERVAL_MS, AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS, retryableAgentHeartbeatError, assertRevocationCheckpoint, readRevocationCheckpoint, writeRevocationCheckpoint, clearRevocationCheckpoint, render, INFERENCE_HOST_HELP, parseHostConcurrency, parseInferenceHostArgs, resolveDurableServiceDisplayName, defaultOpenBrowser, registerInferenceHostServiceControlInput, defaultRegisterLifecycleSignalHandlers, lifecycleCancellation, configuredCredentialStore, restoreInferenceHostCredentialContext, recoverInferenceHostCredentialContextTransition, accountKeyForState, assertCredentialMatchesState2, revocationCheckpointForCredential, assertRevocationCheckpointMatchesLocalIdentity, fileExistsPrivately, inspectCodexAuthentication, clearLocalRuntimeArtifacts, assertDurableServiceUninstalled, assertLocalRuntimeArtifactsMayBeDiscarded, defaultRunForeground, preparePortableDurableAdapter, defaultRunPortableDurableAdapter, login, codexLogin, codexLogout, localStatus, doctor, cleanupLogin, runHost, defaultReadStdin, parseAgentStdin, parseOptionalAgentStdin, agentOperationId, agentSession, agentConnect, foregroundAgentControlState, requireForegroundAgentState, assignmentFromClaim, foregroundAssignmentNext, foregroundAssignmentHeartbeat, foregroundDataCall, foregroundDecisionStatusRequest, foregroundAssignmentLeaseEnded, handleForegroundCancelledAssignment, foregroundDecisionStatus, foregroundDecisionSubmit, foregroundAssignmentRelease, agentRun, agentNext, agentComplete, agentFail, withAgentCommandLock, recoveryBackupPath, serviceRecoveryTransactionPath, readServiceRecoveryTransaction, assertResumableCodexRecoveryEvidence, recoverInstalledCodexService, serviceCommand, hasExplicitCredentialStoreConfiguration, credentialEnvironmentForIdentity, commandRequiresRetainedCredentialStore, commandUsesInstalledServiceCredentials, resolveInferenceHostCommandConfig;
|
|
35115
35616
|
var init_cli = __esm({
|
|
35116
35617
|
"lib/inference-host/cli.ts"() {
|
|
35117
35618
|
"use strict";
|
|
@@ -35211,6 +35712,12 @@ Commands:
|
|
|
35211
35712
|
agent-next Claim the next exact VTX inference request
|
|
35212
35713
|
agent-complete Submit one completed agent result from stdin
|
|
35213
35714
|
agent-fail Submit one truthful agent failure from stdin
|
|
35715
|
+
agent-assignment-next Claim the assigned Main bot for Agent control
|
|
35716
|
+
agent-assignment-heartbeat Renew the current Agent assignment
|
|
35717
|
+
agent-data-call Request allowed assignment-scoped VTX data
|
|
35718
|
+
agent-decision-submit Submit the normal structured trading decision
|
|
35719
|
+
agent-decision-status Resolve an uncertain Agent decision submission
|
|
35720
|
+
agent-assignment-release Release the current Agent assignment
|
|
35214
35721
|
service Install and control the durable background host
|
|
35215
35722
|
status Inspect local host and credential state
|
|
35216
35723
|
doctor Verify credentials, provider runtime, and private state
|
|
@@ -35525,6 +36032,7 @@ Durable service:
|
|
|
35525
36032
|
);
|
|
35526
36033
|
await clearInferenceAgentAttemptState(config2.statePath);
|
|
35527
36034
|
await clearInferenceAgentNextState(config2.statePath);
|
|
36035
|
+
await clearInferenceForegroundAgentControlState(config2.statePath);
|
|
35528
36036
|
await clearCodexAgentRuntimeState(config2.statePath);
|
|
35529
36037
|
await clearInferenceHostLocalState(config2.statePath);
|
|
35530
36038
|
};
|
|
@@ -35552,10 +36060,11 @@ Durable service:
|
|
|
35552
36060
|
const revocationCheckpointPresent = await readRevocationCheckpoint(config2) !== null;
|
|
35553
36061
|
const agentAttemptPresent = await readInferenceAgentAttemptState(config2.statePath) !== null;
|
|
35554
36062
|
const agentNextRecoveryPresent = await readInferenceAgentNextState(config2.statePath) !== null;
|
|
36063
|
+
const foregroundAgentControlPresent = await readInferenceForegroundAgentControlState(config2.statePath) !== null;
|
|
35555
36064
|
const codexAgentRuntimePresent = await readCodexAgentRuntimeState(config2.statePath) !== null;
|
|
35556
|
-
if (pendingAttempts > 0 || codexRecoveryPresent || serviceRecoveryPresent || revocationCheckpointPresent || agentAttemptPresent || agentNextRecoveryPresent || codexAgentRuntimePresent) {
|
|
36065
|
+
if (pendingAttempts > 0 || codexRecoveryPresent || serviceRecoveryPresent || revocationCheckpointPresent || agentAttemptPresent || agentNextRecoveryPresent || foregroundAgentControlPresent || codexAgentRuntimePresent) {
|
|
35557
36066
|
throw new Error(
|
|
35558
|
-
"Inference host logout refused because attempt recovery is still pending (Codex,
|
|
36067
|
+
"Inference host logout refused because attempt recovery is still pending (Codex, Provider, Agent-control, or revocation recovery). Reconcile or release the exact active operation before retrying logout, or resume revoke."
|
|
35559
36068
|
);
|
|
35560
36069
|
}
|
|
35561
36070
|
};
|
|
@@ -35628,6 +36137,12 @@ Durable service:
|
|
|
35628
36137
|
return { adapter, preflight: await adapter.preflight(signal) };
|
|
35629
36138
|
};
|
|
35630
36139
|
defaultRunPortableDurableAdapter = async (options) => {
|
|
36140
|
+
const agentAdapter = options.adapter;
|
|
36141
|
+
if (typeof agentAdapter.runTurn !== "function" || typeof agentAdapter.releaseThread !== "function" || typeof agentAdapter.close !== "function") {
|
|
36142
|
+
throw new Error(
|
|
36143
|
+
`${options.preflight.adapterId} does not implement the durable Agent-control contract.`
|
|
36144
|
+
);
|
|
36145
|
+
}
|
|
35631
36146
|
const dependencies = createDefaultInferenceHostRunnerDependencies({
|
|
35632
36147
|
apiUrl: options.config.apiUrl,
|
|
35633
36148
|
statePath: options.config.statePath,
|
|
@@ -35663,6 +36178,10 @@ Durable service:
|
|
|
35663
36178
|
maxConcurrency: options.maxConcurrency,
|
|
35664
36179
|
once: options.once,
|
|
35665
36180
|
emitDiagnosticEvent: options.emitDiagnosticEvent,
|
|
36181
|
+
agentRuntime: {
|
|
36182
|
+
statePath: options.config.statePath,
|
|
36183
|
+
adapter: agentAdapter
|
|
36184
|
+
},
|
|
35666
36185
|
signal: options.signal
|
|
35667
36186
|
}).run();
|
|
35668
36187
|
};
|
|
@@ -35696,7 +36215,7 @@ Durable service:
|
|
|
35696
36215
|
await writeInferenceHostCredentialContextTransition(config2, previousCredentialContext);
|
|
35697
36216
|
await writeInferenceHostCredentialContext(config2);
|
|
35698
36217
|
const keyPair = generateExternalInferenceEnvelopeKeyPair();
|
|
35699
|
-
const hostId =
|
|
36218
|
+
const hostId = randomUUID4();
|
|
35700
36219
|
const beginLogin = dependencies.beginLogin ?? beginInferenceOAuthLogin;
|
|
35701
36220
|
const loginStore = {
|
|
35702
36221
|
kind: store.kind,
|
|
@@ -36376,7 +36895,27 @@ Waiting for approval...
|
|
|
36376
36895
|
}
|
|
36377
36896
|
return record2;
|
|
36378
36897
|
};
|
|
36379
|
-
|
|
36898
|
+
parseOptionalAgentStdin = async (dependencies, allowedKeys) => {
|
|
36899
|
+
if (!dependencies.readStdin && process.stdin.isTTY) return {};
|
|
36900
|
+
const raw = await (dependencies.readStdin ?? defaultReadStdin)();
|
|
36901
|
+
if (!raw.trim()) return {};
|
|
36902
|
+
let value;
|
|
36903
|
+
try {
|
|
36904
|
+
value = JSON.parse(raw);
|
|
36905
|
+
} catch {
|
|
36906
|
+
throw new Error("Agent-driven inference stdin must be one JSON object.");
|
|
36907
|
+
}
|
|
36908
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
36909
|
+
throw new Error("Agent-driven inference stdin must be one JSON object.");
|
|
36910
|
+
}
|
|
36911
|
+
const record2 = value;
|
|
36912
|
+
const unexpected = Object.keys(record2).filter((key) => !allowedKeys.includes(key));
|
|
36913
|
+
if (unexpected.length > 0) {
|
|
36914
|
+
throw new Error(`Unsupported agent-driven inference fields: ${unexpected.join(", ")}.`);
|
|
36915
|
+
}
|
|
36916
|
+
return record2;
|
|
36917
|
+
};
|
|
36918
|
+
agentOperationId = (kind) => `${kind}-${randomUUID4()}`;
|
|
36380
36919
|
agentSession = async (config2, dependencies, warnings, signal) => {
|
|
36381
36920
|
if (await readRevocationCheckpoint(config2)) {
|
|
36382
36921
|
throw new Error("Inference host revocation recovery must finish first.");
|
|
@@ -36420,11 +36959,419 @@ Waiting for approval...
|
|
|
36420
36959
|
reasoning_effort: result2.reasoning_effort,
|
|
36421
36960
|
lanes: ["main", "review", "screener"],
|
|
36422
36961
|
response_modes: ["provider_response", "decision_candidate"],
|
|
36962
|
+
control_modes: ["provider", "agent"],
|
|
36423
36963
|
execution_modes: ["client", "server"],
|
|
36424
36964
|
next_command: "vtx inference-host agent-next --wait-seconds 50 --json",
|
|
36965
|
+
agent_next_command: "vtx inference-host agent-assignment-next --wait-seconds 50 --json",
|
|
36425
36966
|
keeper_command: "vtx inference-host agent-run"
|
|
36426
36967
|
}, parsed.json),
|
|
36427
36968
|
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
36969
|
+
` : ""
|
|
36970
|
+
};
|
|
36971
|
+
};
|
|
36972
|
+
foregroundAgentControlState = (hostId, updatedAt) => ({
|
|
36973
|
+
schema_version: "vtx_foreground_agent_control_v1",
|
|
36974
|
+
host_id: hostId,
|
|
36975
|
+
assignment: null,
|
|
36976
|
+
pending_next: null,
|
|
36977
|
+
pending_decision: null,
|
|
36978
|
+
next_wake_at: null,
|
|
36979
|
+
updated_at: updatedAt
|
|
36980
|
+
});
|
|
36981
|
+
requireForegroundAgentState = async (config2, hostId) => {
|
|
36982
|
+
const state = await readInferenceForegroundAgentControlState(config2.statePath);
|
|
36983
|
+
if (!state?.assignment) {
|
|
36984
|
+
throw new Error("No active foreground Agent assignment. Run agent-assignment-next first.");
|
|
36985
|
+
}
|
|
36986
|
+
if (state.host_id !== hostId) {
|
|
36987
|
+
throw new Error("Foreground Agent assignment belongs to another inference host.");
|
|
36988
|
+
}
|
|
36989
|
+
return state;
|
|
36990
|
+
};
|
|
36991
|
+
assignmentFromClaim = (result2) => ({
|
|
36992
|
+
assignment_id: result2.assignment_id,
|
|
36993
|
+
assignment_generation: result2.assignment_generation,
|
|
36994
|
+
model_id: result2.model_id,
|
|
36995
|
+
reasoning_effort: result2.reasoning_effort,
|
|
36996
|
+
bot_mode: result2.bot_mode,
|
|
36997
|
+
execution_mode: result2.execution_mode,
|
|
36998
|
+
allowed_symbols: result2.allowed_symbols,
|
|
36999
|
+
data_contract: result2.data_contract,
|
|
37000
|
+
output_schema: result2.output_schema,
|
|
37001
|
+
minimum_wake_seconds: result2.minimum_wake_seconds,
|
|
37002
|
+
maximum_wake_seconds: result2.maximum_wake_seconds,
|
|
37003
|
+
lease_expires_at: result2.lease_expires_at
|
|
37004
|
+
});
|
|
37005
|
+
foregroundAssignmentNext = async (config2, parsed, dependencies, warnings) => {
|
|
37006
|
+
const session = await agentSession(config2, dependencies, warnings);
|
|
37007
|
+
const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
|
|
37008
|
+
const sleep4 = dependencies.sleep ?? (async (milliseconds) => {
|
|
37009
|
+
await new Promise((resolve6) => setTimeout(resolve6, milliseconds));
|
|
37010
|
+
});
|
|
37011
|
+
const stopAt = now().getTime() + parsed.waitSeconds * 1e3;
|
|
37012
|
+
let state = await readInferenceForegroundAgentControlState(config2.statePath) ?? foregroundAgentControlState(session.localState.host_id, now().toISOString());
|
|
37013
|
+
if (state.host_id !== session.localState.host_id) {
|
|
37014
|
+
throw new Error("Foreground Agent recovery state belongs to another inference host.");
|
|
37015
|
+
}
|
|
37016
|
+
if (state.pending_decision) {
|
|
37017
|
+
throw new Error("Resolve the pending Agent decision before claiming another assignment.");
|
|
37018
|
+
}
|
|
37019
|
+
while (true) {
|
|
37020
|
+
if (!state.pending_next) {
|
|
37021
|
+
const requestedAt = now().toISOString();
|
|
37022
|
+
state = {
|
|
37023
|
+
...state,
|
|
37024
|
+
pending_next: {
|
|
37025
|
+
operation_id: agentOperationId("agent-assignment-next"),
|
|
37026
|
+
requested_at: requestedAt
|
|
37027
|
+
},
|
|
37028
|
+
updated_at: requestedAt
|
|
37029
|
+
};
|
|
37030
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37031
|
+
}
|
|
37032
|
+
const pending = state.pending_next;
|
|
37033
|
+
let result2;
|
|
37034
|
+
try {
|
|
37035
|
+
result2 = await session.client.callTool("inference.agent.assignment.next", {
|
|
37036
|
+
operation_id: pending.operation_id,
|
|
37037
|
+
host_id: session.localState.host_id,
|
|
37038
|
+
requested_at: pending.requested_at,
|
|
37039
|
+
contract_version: "agent_assignment_v2",
|
|
37040
|
+
...state.assignment ? {
|
|
37041
|
+
assignment_id: state.assignment.assignment_id,
|
|
37042
|
+
assignment_generation: state.assignment.assignment_generation
|
|
37043
|
+
} : {}
|
|
37044
|
+
});
|
|
37045
|
+
} catch (error48) {
|
|
37046
|
+
if (error48 && typeof error48 === "object" && error48.definitivelyNotApplied === true) {
|
|
37047
|
+
state = { ...state, pending_next: null, updated_at: now().toISOString() };
|
|
37048
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37049
|
+
}
|
|
37050
|
+
throw error48;
|
|
37051
|
+
}
|
|
37052
|
+
if (result2.claim_state === "claimed") {
|
|
37053
|
+
const assignment = assignmentFromClaim(result2);
|
|
37054
|
+
state = {
|
|
37055
|
+
...state,
|
|
37056
|
+
assignment,
|
|
37057
|
+
pending_next: null,
|
|
37058
|
+
next_wake_at: null,
|
|
37059
|
+
updated_at: now().toISOString()
|
|
37060
|
+
};
|
|
37061
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37062
|
+
return {
|
|
37063
|
+
exitCode: 0,
|
|
37064
|
+
stdout: render({
|
|
37065
|
+
...result2,
|
|
37066
|
+
instructions: "VTX supplied no trading prompt or prepared context. Choose your own cadence; use agent-data-call zero or more times, submit the exact output_schema through agent-decision-submit, then record the next wake with agent-assignment-heartbeat. Keep agent-run open for liveness.",
|
|
37067
|
+
data_command: "vtx inference-host agent-data-call --json",
|
|
37068
|
+
decision_command: "vtx inference-host agent-decision-submit --json",
|
|
37069
|
+
decision_input: {
|
|
37070
|
+
candidate: "<object matching output_schema>",
|
|
37071
|
+
provenance: {
|
|
37072
|
+
source: "external_agent",
|
|
37073
|
+
agent_run_id: "<stable harness run id>",
|
|
37074
|
+
requested_model: result2.model_id,
|
|
37075
|
+
effective_model: "<actual model used>",
|
|
37076
|
+
requested_reasoning_effort: result2.reasoning_effort,
|
|
37077
|
+
effective_reasoning_effort: "<actual reasoning effort used>"
|
|
37078
|
+
}
|
|
37079
|
+
},
|
|
37080
|
+
heartbeat_command: "vtx inference-host agent-assignment-heartbeat --json",
|
|
37081
|
+
release_command: "vtx inference-host agent-assignment-release --json"
|
|
37082
|
+
}, parsed.json),
|
|
37083
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
37084
|
+
` : ""
|
|
37085
|
+
};
|
|
37086
|
+
}
|
|
37087
|
+
state = { ...state, pending_next: null, updated_at: now().toISOString() };
|
|
37088
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37089
|
+
const remaining = stopAt - now().getTime();
|
|
37090
|
+
if (remaining <= 0 || parsed.waitSeconds === 0) {
|
|
37091
|
+
return {
|
|
37092
|
+
exitCode: 0,
|
|
37093
|
+
stdout: render(result2, parsed.json),
|
|
37094
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
37095
|
+
` : ""
|
|
37096
|
+
};
|
|
37097
|
+
}
|
|
37098
|
+
await sleep4(Math.min(remaining, Math.max(50, result2.retry_after_ms)));
|
|
37099
|
+
}
|
|
37100
|
+
};
|
|
37101
|
+
foregroundAssignmentHeartbeat = async (config2, parsed, dependencies, warnings) => {
|
|
37102
|
+
const session = await agentSession(config2, dependencies, warnings);
|
|
37103
|
+
const state = await requireForegroundAgentState(
|
|
37104
|
+
config2,
|
|
37105
|
+
session.localState.host_id
|
|
37106
|
+
);
|
|
37107
|
+
const input = await parseOptionalAgentStdin(dependencies, ["next_wake_at"]);
|
|
37108
|
+
const nextWakeAt = input.next_wake_at;
|
|
37109
|
+
if (nextWakeAt !== void 0 && (typeof nextWakeAt !== "string" || !Number.isFinite(Date.parse(nextWakeAt)))) {
|
|
37110
|
+
throw new Error("next_wake_at must be an ISO timestamp.");
|
|
37111
|
+
}
|
|
37112
|
+
const requestedAt = (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
|
|
37113
|
+
const result2 = await session.client.callTool("inference.agent.assignment.heartbeat", {
|
|
37114
|
+
operation_id: agentOperationId("agent-assignment-heartbeat"),
|
|
37115
|
+
host_id: session.localState.host_id,
|
|
37116
|
+
assignment_id: state.assignment.assignment_id,
|
|
37117
|
+
assignment_generation: state.assignment.assignment_generation,
|
|
37118
|
+
requested_at: requestedAt,
|
|
37119
|
+
...nextWakeAt === void 0 ? {} : { next_wake_at: nextWakeAt }
|
|
37120
|
+
});
|
|
37121
|
+
if (result2.directive === "cancel") {
|
|
37122
|
+
await handleForegroundCancelledAssignment(config2, session, state, requestedAt);
|
|
37123
|
+
} else {
|
|
37124
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, {
|
|
37125
|
+
...state,
|
|
37126
|
+
assignment: { ...state.assignment, lease_expires_at: result2.lease_expires_at },
|
|
37127
|
+
next_wake_at: result2.next_wake_at ?? state.next_wake_at,
|
|
37128
|
+
updated_at: requestedAt
|
|
37129
|
+
});
|
|
37130
|
+
}
|
|
37131
|
+
return {
|
|
37132
|
+
exitCode: 0,
|
|
37133
|
+
stdout: render(result2, parsed.json),
|
|
37134
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
37135
|
+
` : ""
|
|
37136
|
+
};
|
|
37137
|
+
};
|
|
37138
|
+
foregroundDataCall = async (config2, parsed, dependencies, warnings) => {
|
|
37139
|
+
const session = await agentSession(config2, dependencies, warnings);
|
|
37140
|
+
const state = await requireForegroundAgentState(config2, session.localState.host_id);
|
|
37141
|
+
const input = await parseAgentStdin(dependencies, ["capability", "arguments"]);
|
|
37142
|
+
const capability = typeof input.capability === "string" ? input.capability.trim() : "";
|
|
37143
|
+
if (!capability || !state.assignment.data_contract.some((item) => item.id === capability)) {
|
|
37144
|
+
throw new Error("Agent data capability is not allowed by the current assignment.");
|
|
37145
|
+
}
|
|
37146
|
+
if (!input.arguments || typeof input.arguments !== "object" || Array.isArray(input.arguments)) {
|
|
37147
|
+
throw new Error("Agent data arguments must be one JSON object.");
|
|
37148
|
+
}
|
|
37149
|
+
const result2 = await session.client.callTool("inference.agent.data.call", {
|
|
37150
|
+
operation_id: agentOperationId("agent-data-call"),
|
|
37151
|
+
host_id: session.localState.host_id,
|
|
37152
|
+
assignment_id: state.assignment.assignment_id,
|
|
37153
|
+
assignment_generation: state.assignment.assignment_generation,
|
|
37154
|
+
capability,
|
|
37155
|
+
arguments: input.arguments,
|
|
37156
|
+
requested_at: (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString()
|
|
37157
|
+
});
|
|
37158
|
+
return {
|
|
37159
|
+
exitCode: 0,
|
|
37160
|
+
stdout: render(result2, parsed.json),
|
|
37161
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
37162
|
+
` : ""
|
|
37163
|
+
};
|
|
37164
|
+
};
|
|
37165
|
+
foregroundDecisionStatusRequest = (hostId, state) => ({
|
|
37166
|
+
operation_id: state.pending_decision.request.operation_id,
|
|
37167
|
+
host_id: hostId,
|
|
37168
|
+
assignment_id: state.assignment.assignment_id,
|
|
37169
|
+
assignment_generation: state.assignment.assignment_generation
|
|
37170
|
+
});
|
|
37171
|
+
foregroundAssignmentLeaseEnded = (state, now) => Boolean(state.assignment) && Date.parse(state.assignment.lease_expires_at) <= now.getTime();
|
|
37172
|
+
handleForegroundCancelledAssignment = async (config2, session, state, requestedAt, signal) => {
|
|
37173
|
+
if (!state.pending_decision) {
|
|
37174
|
+
await clearInferenceForegroundAgentControlState(config2.statePath);
|
|
37175
|
+
return;
|
|
37176
|
+
}
|
|
37177
|
+
const cancelledState = {
|
|
37178
|
+
...state,
|
|
37179
|
+
assignment: {
|
|
37180
|
+
...state.assignment,
|
|
37181
|
+
lease_expires_at: requestedAt
|
|
37182
|
+
},
|
|
37183
|
+
pending_decision: {
|
|
37184
|
+
...state.pending_decision,
|
|
37185
|
+
last_status_check_at: requestedAt
|
|
37186
|
+
},
|
|
37187
|
+
next_wake_at: null,
|
|
37188
|
+
updated_at: requestedAt
|
|
37189
|
+
};
|
|
37190
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, cancelledState);
|
|
37191
|
+
try {
|
|
37192
|
+
await session.client.callTool(
|
|
37193
|
+
"inference.agent.decision.status",
|
|
37194
|
+
foregroundDecisionStatusRequest(session.localState.host_id, cancelledState),
|
|
37195
|
+
{ signal }
|
|
37196
|
+
);
|
|
37197
|
+
} catch {
|
|
37198
|
+
return;
|
|
37199
|
+
}
|
|
37200
|
+
await clearInferenceForegroundAgentControlState(config2.statePath);
|
|
37201
|
+
};
|
|
37202
|
+
foregroundDecisionStatus = async (config2, parsed, dependencies, warnings) => {
|
|
37203
|
+
const session = await agentSession(config2, dependencies, warnings);
|
|
37204
|
+
let state = await requireForegroundAgentState(config2, session.localState.host_id);
|
|
37205
|
+
if (!state.pending_decision) {
|
|
37206
|
+
throw new Error("No uncertain foreground Agent decision requires status recovery.");
|
|
37207
|
+
}
|
|
37208
|
+
const checkedAt = (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
|
|
37209
|
+
state = {
|
|
37210
|
+
...state,
|
|
37211
|
+
pending_decision: { ...state.pending_decision, last_status_check_at: checkedAt },
|
|
37212
|
+
updated_at: checkedAt
|
|
37213
|
+
};
|
|
37214
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37215
|
+
const result2 = await session.client.callTool(
|
|
37216
|
+
"inference.agent.decision.status",
|
|
37217
|
+
foregroundDecisionStatusRequest(session.localState.host_id, state)
|
|
37218
|
+
);
|
|
37219
|
+
const assignmentLeaseEnded = foregroundAssignmentLeaseEnded(state, new Date(checkedAt));
|
|
37220
|
+
if (result2.found || assignmentLeaseEnded) {
|
|
37221
|
+
if (assignmentLeaseEnded) {
|
|
37222
|
+
await clearInferenceForegroundAgentControlState(config2.statePath);
|
|
37223
|
+
} else {
|
|
37224
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, {
|
|
37225
|
+
...state,
|
|
37226
|
+
pending_decision: null,
|
|
37227
|
+
updated_at: checkedAt
|
|
37228
|
+
});
|
|
37229
|
+
}
|
|
37230
|
+
}
|
|
37231
|
+
return {
|
|
37232
|
+
exitCode: 0,
|
|
37233
|
+
stdout: render(result2, parsed.json),
|
|
37234
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
37235
|
+
` : ""
|
|
37236
|
+
};
|
|
37237
|
+
};
|
|
37238
|
+
foregroundDecisionSubmit = async (config2, parsed, dependencies, warnings) => {
|
|
37239
|
+
const session = await agentSession(config2, dependencies, warnings);
|
|
37240
|
+
const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
|
|
37241
|
+
let state = await requireForegroundAgentState(config2, session.localState.host_id);
|
|
37242
|
+
if (!state.pending_decision) {
|
|
37243
|
+
const input = await parseAgentStdin(dependencies, ["candidate", "provenance"]);
|
|
37244
|
+
if (!input.candidate || typeof input.candidate !== "object" || Array.isArray(input.candidate)) {
|
|
37245
|
+
throw new Error("Agent decision candidate must be one JSON object.");
|
|
37246
|
+
}
|
|
37247
|
+
if (!input.provenance || typeof input.provenance !== "object" || Array.isArray(input.provenance)) {
|
|
37248
|
+
throw new Error("Agent decision provenance must be one JSON object.");
|
|
37249
|
+
}
|
|
37250
|
+
const observedAt = now().toISOString();
|
|
37251
|
+
state = {
|
|
37252
|
+
...state,
|
|
37253
|
+
pending_decision: {
|
|
37254
|
+
request: {
|
|
37255
|
+
assignment_id: state.assignment.assignment_id,
|
|
37256
|
+
assignment_generation: state.assignment.assignment_generation,
|
|
37257
|
+
operation_id: agentOperationId("agent-decision-submit"),
|
|
37258
|
+
candidate: input.candidate,
|
|
37259
|
+
observed_at: observedAt,
|
|
37260
|
+
provenance: input.provenance
|
|
37261
|
+
},
|
|
37262
|
+
first_transmit_at: null,
|
|
37263
|
+
last_status_check_at: null
|
|
37264
|
+
},
|
|
37265
|
+
updated_at: observedAt
|
|
37266
|
+
};
|
|
37267
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37268
|
+
} else {
|
|
37269
|
+
const checkedAt = now().toISOString();
|
|
37270
|
+
state = {
|
|
37271
|
+
...state,
|
|
37272
|
+
pending_decision: { ...state.pending_decision, last_status_check_at: checkedAt },
|
|
37273
|
+
updated_at: checkedAt
|
|
37274
|
+
};
|
|
37275
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37276
|
+
const status = await session.client.callTool(
|
|
37277
|
+
"inference.agent.decision.status",
|
|
37278
|
+
foregroundDecisionStatusRequest(session.localState.host_id, state)
|
|
37279
|
+
);
|
|
37280
|
+
if (status.found) {
|
|
37281
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, {
|
|
37282
|
+
...state,
|
|
37283
|
+
pending_decision: null,
|
|
37284
|
+
updated_at: checkedAt
|
|
37285
|
+
});
|
|
37286
|
+
return {
|
|
37287
|
+
exitCode: 0,
|
|
37288
|
+
stdout: render({ ...status, recovered: true }, parsed.json),
|
|
37289
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
37290
|
+
` : ""
|
|
37291
|
+
};
|
|
37292
|
+
}
|
|
37293
|
+
}
|
|
37294
|
+
const transmittedAt = now().toISOString();
|
|
37295
|
+
state = {
|
|
37296
|
+
...state,
|
|
37297
|
+
pending_decision: {
|
|
37298
|
+
...state.pending_decision,
|
|
37299
|
+
first_transmit_at: state.pending_decision.first_transmit_at ?? transmittedAt
|
|
37300
|
+
},
|
|
37301
|
+
updated_at: transmittedAt
|
|
37302
|
+
};
|
|
37303
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37304
|
+
try {
|
|
37305
|
+
const result2 = await session.client.callTool(
|
|
37306
|
+
"inference.agent.decision.submit",
|
|
37307
|
+
state.pending_decision.request
|
|
37308
|
+
);
|
|
37309
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, {
|
|
37310
|
+
...state,
|
|
37311
|
+
pending_decision: null,
|
|
37312
|
+
updated_at: now().toISOString()
|
|
37313
|
+
});
|
|
37314
|
+
return {
|
|
37315
|
+
exitCode: 0,
|
|
37316
|
+
stdout: render(result2, parsed.json),
|
|
37317
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
37318
|
+
` : ""
|
|
37319
|
+
};
|
|
37320
|
+
} catch (error48) {
|
|
37321
|
+
const checkedAt = now().toISOString();
|
|
37322
|
+
state = {
|
|
37323
|
+
...state,
|
|
37324
|
+
pending_decision: { ...state.pending_decision, last_status_check_at: checkedAt },
|
|
37325
|
+
updated_at: checkedAt
|
|
37326
|
+
};
|
|
37327
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, state);
|
|
37328
|
+
try {
|
|
37329
|
+
const status = await session.client.callTool(
|
|
37330
|
+
"inference.agent.decision.status",
|
|
37331
|
+
foregroundDecisionStatusRequest(session.localState.host_id, state)
|
|
37332
|
+
);
|
|
37333
|
+
if (status.found) {
|
|
37334
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, {
|
|
37335
|
+
...state,
|
|
37336
|
+
pending_decision: null,
|
|
37337
|
+
updated_at: checkedAt
|
|
37338
|
+
});
|
|
37339
|
+
return {
|
|
37340
|
+
exitCode: 0,
|
|
37341
|
+
stdout: render({ ...status, recovered: true }, parsed.json),
|
|
37342
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
37343
|
+
` : ""
|
|
37344
|
+
};
|
|
37345
|
+
}
|
|
37346
|
+
} catch {
|
|
37347
|
+
}
|
|
37348
|
+
throw error48;
|
|
37349
|
+
}
|
|
37350
|
+
};
|
|
37351
|
+
foregroundAssignmentRelease = async (config2, parsed, dependencies, warnings) => {
|
|
37352
|
+
const session = await agentSession(config2, dependencies, warnings);
|
|
37353
|
+
const state = await requireForegroundAgentState(config2, session.localState.host_id);
|
|
37354
|
+
if (state.pending_decision) {
|
|
37355
|
+
throw new Error("Resolve the pending Agent decision before releasing its assignment.");
|
|
37356
|
+
}
|
|
37357
|
+
const input = await parseOptionalAgentStdin(dependencies, ["reason_code"]);
|
|
37358
|
+
const reasonCode = input.reason_code === void 0 ? "agent_released" : input.reason_code;
|
|
37359
|
+
if (typeof reasonCode !== "string" || !/^[a-z0-9][a-z0-9._-]{0,95}$/u.test(reasonCode)) {
|
|
37360
|
+
throw new Error("reason_code must be a safe lowercase code.");
|
|
37361
|
+
}
|
|
37362
|
+
const result2 = await session.client.callTool("inference.agent.assignment.release", {
|
|
37363
|
+
operation_id: agentOperationId("agent-assignment-release"),
|
|
37364
|
+
host_id: session.localState.host_id,
|
|
37365
|
+
assignment_id: state.assignment.assignment_id,
|
|
37366
|
+
assignment_generation: state.assignment.assignment_generation,
|
|
37367
|
+
reason_code: reasonCode,
|
|
37368
|
+
requested_at: (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString()
|
|
37369
|
+
});
|
|
37370
|
+
await clearInferenceForegroundAgentControlState(config2.statePath);
|
|
37371
|
+
return {
|
|
37372
|
+
exitCode: 0,
|
|
37373
|
+
stdout: render(result2, parsed.json),
|
|
37374
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
36428
37375
|
` : ""
|
|
36429
37376
|
};
|
|
36430
37377
|
};
|
|
@@ -36432,6 +37379,7 @@ Waiting for approval...
|
|
|
36432
37379
|
const cancellation = lifecycleCancellation(dependencies);
|
|
36433
37380
|
let keeperLock = null;
|
|
36434
37381
|
let heartbeatCount = 0;
|
|
37382
|
+
let assignmentHeartbeatCount = 0;
|
|
36435
37383
|
try {
|
|
36436
37384
|
keeperLock = await acquireInferenceHostProcessLock(foregroundHostLockPath(config2));
|
|
36437
37385
|
const store = configuredCredentialStore(config2, dependencies, (message) => {
|
|
@@ -36465,6 +37413,7 @@ Waiting for approval...
|
|
|
36465
37413
|
}
|
|
36466
37414
|
if (commandLock) {
|
|
36467
37415
|
let heartbeatSuppressed = false;
|
|
37416
|
+
let assignmentHeartbeatComplete = true;
|
|
36468
37417
|
try {
|
|
36469
37418
|
const active = await readInferenceAgentAttemptState(config2.statePath);
|
|
36470
37419
|
const pendingNext = await readInferenceAgentNextState(config2.statePath);
|
|
@@ -36524,10 +37473,65 @@ Waiting for approval...
|
|
|
36524
37473
|
}
|
|
36525
37474
|
}
|
|
36526
37475
|
}
|
|
37476
|
+
const control = await readInferenceForegroundAgentControlState(config2.statePath);
|
|
37477
|
+
if (control && control.host_id !== session.localState.host_id) {
|
|
37478
|
+
throw new Error("Foreground Agent control state belongs to another inference host.");
|
|
37479
|
+
}
|
|
37480
|
+
if (control?.assignment) {
|
|
37481
|
+
assignmentHeartbeatComplete = false;
|
|
37482
|
+
try {
|
|
37483
|
+
const requestedAt = (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
|
|
37484
|
+
const result2 = await session.client.callTool(
|
|
37485
|
+
"inference.agent.assignment.heartbeat",
|
|
37486
|
+
{
|
|
37487
|
+
operation_id: agentOperationId("agent-assignment-heartbeat"),
|
|
37488
|
+
host_id: session.localState.host_id,
|
|
37489
|
+
assignment_id: control.assignment.assignment_id,
|
|
37490
|
+
assignment_generation: control.assignment.assignment_generation,
|
|
37491
|
+
requested_at: requestedAt
|
|
37492
|
+
},
|
|
37493
|
+
{ signal: cancellation.signal }
|
|
37494
|
+
);
|
|
37495
|
+
assignmentHeartbeatComplete = true;
|
|
37496
|
+
assignmentHeartbeatCount += 1;
|
|
37497
|
+
if (result2.directive === "cancel") {
|
|
37498
|
+
await handleForegroundCancelledAssignment(
|
|
37499
|
+
config2,
|
|
37500
|
+
session,
|
|
37501
|
+
control,
|
|
37502
|
+
requestedAt,
|
|
37503
|
+
cancellation.signal
|
|
37504
|
+
);
|
|
37505
|
+
} else {
|
|
37506
|
+
await writeInferenceForegroundAgentControlState(config2.statePath, {
|
|
37507
|
+
...control,
|
|
37508
|
+
assignment: {
|
|
37509
|
+
...control.assignment,
|
|
37510
|
+
lease_expires_at: result2.lease_expires_at
|
|
37511
|
+
},
|
|
37512
|
+
updated_at: requestedAt
|
|
37513
|
+
});
|
|
37514
|
+
}
|
|
37515
|
+
} catch (error48) {
|
|
37516
|
+
if (cancellation.signal.aborted) break;
|
|
37517
|
+
if (!retryableAgentHeartbeatError(error48)) throw error48;
|
|
37518
|
+
consecutiveHeartbeatFailures += 1;
|
|
37519
|
+
retryDelayMs = Math.min(
|
|
37520
|
+
AGENT_HEARTBEAT_INTERVAL_MS * 2 ** Math.max(0, consecutiveHeartbeatFailures - 1),
|
|
37521
|
+
AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS
|
|
37522
|
+
);
|
|
37523
|
+
emitStderr(parsed.json ? `${JSON.stringify({
|
|
37524
|
+
status: "assignment_heartbeat_retry",
|
|
37525
|
+
retry_after_ms: retryDelayMs
|
|
37526
|
+
})}
|
|
37527
|
+
` : `Foreground Agent assignment heartbeat was temporarily unavailable; retrying in ${retryDelayMs}ms.
|
|
37528
|
+
`);
|
|
37529
|
+
}
|
|
37530
|
+
}
|
|
36527
37531
|
} finally {
|
|
36528
37532
|
await commandLock.release();
|
|
36529
37533
|
}
|
|
36530
|
-
if (parsed.once && (heartbeatCount > 0 || heartbeatSuppressed)) break;
|
|
37534
|
+
if (parsed.once && (heartbeatCount > 0 || heartbeatSuppressed) && assignmentHeartbeatComplete) break;
|
|
36531
37535
|
}
|
|
36532
37536
|
if (parsed.once && !commandLock) break;
|
|
36533
37537
|
await (dependencies.sleep ?? (async (milliseconds) => {
|
|
@@ -36536,7 +37540,11 @@ Waiting for approval...
|
|
|
36536
37540
|
}
|
|
36537
37541
|
return {
|
|
36538
37542
|
exitCode: 0,
|
|
36539
|
-
stdout: render({
|
|
37543
|
+
stdout: render({
|
|
37544
|
+
status: "stopped",
|
|
37545
|
+
heartbeats: heartbeatCount,
|
|
37546
|
+
assignment_heartbeats: assignmentHeartbeatCount
|
|
37547
|
+
}, parsed.json),
|
|
36540
37548
|
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
36541
37549
|
` : ""
|
|
36542
37550
|
};
|
|
@@ -36924,7 +37932,7 @@ Waiting for approval...
|
|
|
36924
37932
|
if (recoveryRaw === null && existingTransaction?.phase !== "reconciled") {
|
|
36925
37933
|
throw new Error("Codex recovery evidence changed before service recovery began.");
|
|
36926
37934
|
}
|
|
36927
|
-
const transactionId = existingTransaction?.transaction_id ??
|
|
37935
|
+
const transactionId = existingTransaction?.transaction_id ?? randomUUID4();
|
|
36928
37936
|
const backupPath = existingTransaction?.recovery_backup_path ?? recoveryBackupPath(config2, transactionId);
|
|
36929
37937
|
if (!existingTransaction) {
|
|
36930
37938
|
await writeAtomicInferencePrivateFile(backupPath, recoveryRaw);
|
|
@@ -37445,7 +38453,7 @@ var init_types = __esm({
|
|
|
37445
38453
|
});
|
|
37446
38454
|
|
|
37447
38455
|
// lib/agent-core/client.ts
|
|
37448
|
-
import { randomUUID as
|
|
38456
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
37449
38457
|
function normalizeApiUrl(value) {
|
|
37450
38458
|
const parsed = String(value || "").trim();
|
|
37451
38459
|
if (!parsed) {
|
|
@@ -37707,7 +38715,7 @@ var init_client = __esm({
|
|
|
37707
38715
|
return this.request("/trading/ai/runtime/decision", {
|
|
37708
38716
|
method: "POST",
|
|
37709
38717
|
profileId,
|
|
37710
|
-
idempotencyKey:
|
|
38718
|
+
idempotencyKey: randomUUID5(),
|
|
37711
38719
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
37712
38720
|
body: payload
|
|
37713
38721
|
});
|
|
@@ -37716,7 +38724,7 @@ var init_client = __esm({
|
|
|
37716
38724
|
return this.request("/trading/ai/runtime/trade-sync", {
|
|
37717
38725
|
method: "POST",
|
|
37718
38726
|
profileId,
|
|
37719
|
-
idempotencyKey:
|
|
38727
|
+
idempotencyKey: randomUUID5(),
|
|
37720
38728
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
37721
38729
|
body: payload
|
|
37722
38730
|
});
|
|
@@ -37725,7 +38733,7 @@ var init_client = __esm({
|
|
|
37725
38733
|
return this.request("/trading/ai/runtime/error", {
|
|
37726
38734
|
method: "POST",
|
|
37727
38735
|
profileId,
|
|
37728
|
-
idempotencyKey:
|
|
38736
|
+
idempotencyKey: randomUUID5(),
|
|
37729
38737
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
37730
38738
|
body: payload
|
|
37731
38739
|
});
|
|
@@ -37737,7 +38745,7 @@ var init_client = __esm({
|
|
|
37737
38745
|
return this.request("/trading/market-order", {
|
|
37738
38746
|
method: "POST",
|
|
37739
38747
|
profileId,
|
|
37740
|
-
idempotencyKey:
|
|
38748
|
+
idempotencyKey: randomUUID5(),
|
|
37741
38749
|
body: payload
|
|
37742
38750
|
});
|
|
37743
38751
|
}
|
|
@@ -37745,7 +38753,7 @@ var init_client = __esm({
|
|
|
37745
38753
|
return this.request("/trading/limit-order", {
|
|
37746
38754
|
method: "POST",
|
|
37747
38755
|
profileId,
|
|
37748
|
-
idempotencyKey:
|
|
38756
|
+
idempotencyKey: randomUUID5(),
|
|
37749
38757
|
body: payload
|
|
37750
38758
|
});
|
|
37751
38759
|
}
|
|
@@ -37753,7 +38761,7 @@ var init_client = __esm({
|
|
|
37753
38761
|
return this.request("/trading/cancel-order", {
|
|
37754
38762
|
method: "POST",
|
|
37755
38763
|
profileId,
|
|
37756
|
-
idempotencyKey:
|
|
38764
|
+
idempotencyKey: randomUUID5(),
|
|
37757
38765
|
body: payload
|
|
37758
38766
|
});
|
|
37759
38767
|
}
|
|
@@ -37772,7 +38780,7 @@ var init_client = __esm({
|
|
|
37772
38780
|
return this.request("/trading/ai/start", {
|
|
37773
38781
|
method: "POST",
|
|
37774
38782
|
profileId,
|
|
37775
|
-
idempotencyKey:
|
|
38783
|
+
idempotencyKey: randomUUID5(),
|
|
37776
38784
|
body: payload
|
|
37777
38785
|
});
|
|
37778
38786
|
}
|
|
@@ -37780,7 +38788,7 @@ var init_client = __esm({
|
|
|
37780
38788
|
return this.request("/trading/ai/stop", {
|
|
37781
38789
|
method: "POST",
|
|
37782
38790
|
profileId,
|
|
37783
|
-
idempotencyKey:
|
|
38791
|
+
idempotencyKey: randomUUID5(),
|
|
37784
38792
|
body: {}
|
|
37785
38793
|
});
|
|
37786
38794
|
}
|
|
@@ -37788,7 +38796,7 @@ var init_client = __esm({
|
|
|
37788
38796
|
return this.request("/trading/ai/assistant/start", {
|
|
37789
38797
|
method: "POST",
|
|
37790
38798
|
profileId,
|
|
37791
|
-
idempotencyKey:
|
|
38799
|
+
idempotencyKey: randomUUID5(),
|
|
37792
38800
|
body: {}
|
|
37793
38801
|
});
|
|
37794
38802
|
}
|
|
@@ -37796,7 +38804,7 @@ var init_client = __esm({
|
|
|
37796
38804
|
return this.request("/trading/ai/assistant/stop", {
|
|
37797
38805
|
method: "POST",
|
|
37798
38806
|
profileId,
|
|
37799
|
-
idempotencyKey:
|
|
38807
|
+
idempotencyKey: randomUUID5(),
|
|
37800
38808
|
body: {}
|
|
37801
38809
|
});
|
|
37802
38810
|
}
|
|
@@ -37804,7 +38812,7 @@ var init_client = __esm({
|
|
|
37804
38812
|
return this.request("/trading/ai/runtime/session/start", {
|
|
37805
38813
|
method: "POST",
|
|
37806
38814
|
profileId,
|
|
37807
|
-
idempotencyKey:
|
|
38815
|
+
idempotencyKey: randomUUID5(),
|
|
37808
38816
|
body: payload
|
|
37809
38817
|
});
|
|
37810
38818
|
}
|
|
@@ -37815,7 +38823,7 @@ var init_client = __esm({
|
|
|
37815
38823
|
return this.request("/trading/ai/runtime/session/stop", {
|
|
37816
38824
|
method: "POST",
|
|
37817
38825
|
profileId,
|
|
37818
|
-
idempotencyKey:
|
|
38826
|
+
idempotencyKey: randomUUID5(),
|
|
37819
38827
|
body: payload
|
|
37820
38828
|
});
|
|
37821
38829
|
}
|
|
@@ -37832,7 +38840,7 @@ var init_client = __esm({
|
|
|
37832
38840
|
}).request("/trading/ai/runtime/session/stop", {
|
|
37833
38841
|
method: "POST",
|
|
37834
38842
|
profileId,
|
|
37835
|
-
idempotencyKey:
|
|
38843
|
+
idempotencyKey: randomUUID5(),
|
|
37836
38844
|
body: payload
|
|
37837
38845
|
});
|
|
37838
38846
|
}
|
|
@@ -37849,7 +38857,7 @@ import {
|
|
|
37849
38857
|
unlinkSync,
|
|
37850
38858
|
writeFileSync
|
|
37851
38859
|
} from "node:fs";
|
|
37852
|
-
import { randomUUID as
|
|
38860
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
37853
38861
|
import { dirname as dirname6 } from "node:path";
|
|
37854
38862
|
var parseStoredValues, FileBackedProtectionStorage, clientRuntimeProtectionStatePath;
|
|
37855
38863
|
var init_protection_storage = __esm({
|
|
@@ -37906,7 +38914,7 @@ var init_protection_storage = __esm({
|
|
|
37906
38914
|
mkdirSync(dirname6(this.path), { recursive: true, mode: 448 });
|
|
37907
38915
|
const serialized = `${JSON.stringify(values)}
|
|
37908
38916
|
`;
|
|
37909
|
-
const temporaryPath = `${this.path}.${process.pid}.${
|
|
38917
|
+
const temporaryPath = `${this.path}.${process.pid}.${randomUUID6()}.tmp`;
|
|
37910
38918
|
try {
|
|
37911
38919
|
writeFileSync(temporaryPath, serialized, {
|
|
37912
38920
|
encoding: "utf8",
|
|
@@ -37933,7 +38941,7 @@ var init_protection_storage = __esm({
|
|
|
37933
38941
|
});
|
|
37934
38942
|
|
|
37935
38943
|
// lib/agent-core/headless-runtime.ts
|
|
37936
|
-
import { randomUUID as
|
|
38944
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
37937
38945
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
37938
38946
|
function objectOrNull2(value) {
|
|
37939
38947
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -38031,8 +39039,8 @@ async function runAndReportLocalWorkCycle(options, state, leaseToken, context) {
|
|
|
38031
39039
|
return Boolean(result2.decision || tradeSync || result2.afterDecision);
|
|
38032
39040
|
}
|
|
38033
39041
|
async function startHeadlessRuntime(options) {
|
|
38034
|
-
const runtimeSessionId =
|
|
38035
|
-
const deviceId = String(options.deviceId || "").trim() ||
|
|
39042
|
+
const runtimeSessionId = randomUUID7();
|
|
39043
|
+
const deviceId = String(options.deviceId || "").trim() || randomUUID7();
|
|
38036
39044
|
const startResponse = await options.client.startRuntime(options.profileId, {
|
|
38037
39045
|
session_id: runtimeSessionId,
|
|
38038
39046
|
device_id: deviceId,
|
|
@@ -38220,7 +39228,18 @@ var init_sort_utils = __esm({
|
|
|
38220
39228
|
});
|
|
38221
39229
|
|
|
38222
39230
|
// lib/runtime/hyperliquid-account-mode-contract.ts
|
|
38223
|
-
|
|
39231
|
+
function resolveExactHyperliquidAccountMode(userAbstraction, ...dexEvidence) {
|
|
39232
|
+
const mode = extractCanonicalHyperliquidAccountMode(userAbstraction);
|
|
39233
|
+
if (!mode) {
|
|
39234
|
+
throw new Error("Exact Hyperliquid userAbstraction response is invalid.");
|
|
39235
|
+
}
|
|
39236
|
+
if (mode !== "default" && mode !== "disabled") return mode;
|
|
39237
|
+
if (dexEvidence.length < 1) {
|
|
39238
|
+
throw new Error("Exact Hyperliquid userDexAbstraction response is unavailable.");
|
|
39239
|
+
}
|
|
39240
|
+
return parseExactDexAbstractionEnabled(dexEvidence[0]) ? "dexAbstraction" : mode;
|
|
39241
|
+
}
|
|
39242
|
+
var UNIFIED_MODE_ALIASES, CANONICAL_ACCOUNT_MODE_ALIASES, EXACT_MODE_KEYS, EXACT_MODE_BOOLEAN_KEYS, isExactTruthyFlag, normalizeCanonicalHyperliquidAccountMode, extractCanonicalHyperliquidAccountMode, parseExactDexAbstractionEnabled, normalizeAccountMode, extractAccountModeFromPayload, extractAccountModeCandidateFromPayload, isUnifiedAccountMode;
|
|
38224
39243
|
var init_hyperliquid_account_mode_contract = __esm({
|
|
38225
39244
|
"lib/runtime/hyperliquid-account-mode-contract.ts"() {
|
|
38226
39245
|
"use strict";
|
|
@@ -38231,6 +39250,89 @@ var init_hyperliquid_account_mode_contract = __esm({
|
|
|
38231
39250
|
"unified",
|
|
38232
39251
|
"pm"
|
|
38233
39252
|
]);
|
|
39253
|
+
CANONICAL_ACCOUNT_MODE_ALIASES = /* @__PURE__ */ new Map([
|
|
39254
|
+
["default", "default"],
|
|
39255
|
+
["standard", "default"],
|
|
39256
|
+
["classic", "default"],
|
|
39257
|
+
["disabled", "disabled"],
|
|
39258
|
+
["unifiedaccount", "unifiedAccount"],
|
|
39259
|
+
["unified", "unifiedAccount"],
|
|
39260
|
+
["portfoliomargin", "portfolioMargin"],
|
|
39261
|
+
["pm", "portfolioMargin"],
|
|
39262
|
+
["dexabstraction", "dexAbstraction"]
|
|
39263
|
+
]);
|
|
39264
|
+
EXACT_MODE_KEYS = [
|
|
39265
|
+
"accountMode",
|
|
39266
|
+
"account_mode",
|
|
39267
|
+
"accountType",
|
|
39268
|
+
"account_type",
|
|
39269
|
+
"accountUnificationMode",
|
|
39270
|
+
"account_unification_mode",
|
|
39271
|
+
"abstractionMode",
|
|
39272
|
+
"abstraction_mode",
|
|
39273
|
+
"abstraction",
|
|
39274
|
+
"abstractionState",
|
|
39275
|
+
"dexAbstractionState",
|
|
39276
|
+
"marginMode",
|
|
39277
|
+
"state",
|
|
39278
|
+
"mode",
|
|
39279
|
+
"value"
|
|
39280
|
+
];
|
|
39281
|
+
EXACT_MODE_BOOLEAN_KEYS = [
|
|
39282
|
+
["unifiedAccount", ["isUnifiedAccount", "unifiedAccount", "isUnified", "unified", "is_unified_account"]],
|
|
39283
|
+
["portfolioMargin", ["isPortfolioMargin", "portfolioMargin", "isPm", "pm", "is_portfolio_margin"]],
|
|
39284
|
+
["dexAbstraction", ["isDexAbstraction", "dexAbstraction", "dexAbstractionEnabled", "is_dex_abstraction"]],
|
|
39285
|
+
["default", ["isClassic", "classic", "isStandard", "standard"]]
|
|
39286
|
+
];
|
|
39287
|
+
isExactTruthyFlag = (value) => value === true || value === 1 || typeof value === "string" && value.trim().toLowerCase() === "true";
|
|
39288
|
+
normalizeCanonicalHyperliquidAccountMode = (value) => {
|
|
39289
|
+
if (typeof value !== "string") return null;
|
|
39290
|
+
const key = value.trim().replace(/[_\s-]/g, "").toLowerCase();
|
|
39291
|
+
return CANONICAL_ACCOUNT_MODE_ALIASES.get(key) ?? null;
|
|
39292
|
+
};
|
|
39293
|
+
extractCanonicalHyperliquidAccountMode = (payload, depth = 0) => {
|
|
39294
|
+
if (depth > 6) return null;
|
|
39295
|
+
const direct = normalizeCanonicalHyperliquidAccountMode(payload);
|
|
39296
|
+
if (direct) return direct;
|
|
39297
|
+
if (Array.isArray(payload)) {
|
|
39298
|
+
for (const item of payload) {
|
|
39299
|
+
const mode = extractCanonicalHyperliquidAccountMode(item, depth + 1);
|
|
39300
|
+
if (mode) return mode;
|
|
39301
|
+
}
|
|
39302
|
+
return null;
|
|
39303
|
+
}
|
|
39304
|
+
if (!payload || typeof payload !== "object") return null;
|
|
39305
|
+
const source = payload;
|
|
39306
|
+
for (const key of EXACT_MODE_KEYS) {
|
|
39307
|
+
if (!(key in source)) continue;
|
|
39308
|
+
const mode = normalizeCanonicalHyperliquidAccountMode(source[key]);
|
|
39309
|
+
if (mode) return mode;
|
|
39310
|
+
}
|
|
39311
|
+
for (const [mode, keys] of EXACT_MODE_BOOLEAN_KEYS) {
|
|
39312
|
+
for (const key of keys) {
|
|
39313
|
+
if (isExactTruthyFlag(source[key])) return mode;
|
|
39314
|
+
}
|
|
39315
|
+
}
|
|
39316
|
+
for (const value of Object.values(source)) {
|
|
39317
|
+
const mode = extractCanonicalHyperliquidAccountMode(value, depth + 1);
|
|
39318
|
+
if (mode) return mode;
|
|
39319
|
+
}
|
|
39320
|
+
return null;
|
|
39321
|
+
};
|
|
39322
|
+
parseExactDexAbstractionEnabled = (payload) => {
|
|
39323
|
+
if (payload == null || payload === false) return false;
|
|
39324
|
+
if (payload === true) return true;
|
|
39325
|
+
if (typeof payload === "string") {
|
|
39326
|
+
const normalized = payload.trim().toLowerCase();
|
|
39327
|
+
if (normalized === "true") return true;
|
|
39328
|
+
if (normalized === "false") return false;
|
|
39329
|
+
}
|
|
39330
|
+
if (typeof payload === "number" && Number.isFinite(payload)) {
|
|
39331
|
+
if (payload === 1) return true;
|
|
39332
|
+
if (payload === 0) return false;
|
|
39333
|
+
}
|
|
39334
|
+
throw new Error("Exact Hyperliquid userDexAbstraction response is invalid.");
|
|
39335
|
+
};
|
|
38234
39336
|
normalizeAccountMode = (mode) => String(mode ?? "").trim().toLowerCase().replace(/[_\s-]/g, "");
|
|
38235
39337
|
extractAccountModeFromPayload = (payload) => {
|
|
38236
39338
|
const candidate = extractAccountModeCandidateFromPayload(payload);
|
|
@@ -38455,6 +39557,229 @@ var init_hyperliquid_active_asset_contract = __esm({
|
|
|
38455
39557
|
}
|
|
38456
39558
|
});
|
|
38457
39559
|
|
|
39560
|
+
// lib/runtime/server-prompt-rescue-account-contract.ts
|
|
39561
|
+
var STABLE_SYMBOLS, toNumber2, firstNumber2, firstTruthy, spotContainers, extractCanonicalSpotMetrics, sumBalanceValueUsd, approximatelyEqual, balancesMirrorUnifiedAccountValue, computeEffectiveAccountValue, equityFormula, buildServerPromptRescueAccountSummary;
|
|
39562
|
+
var init_server_prompt_rescue_account_contract = __esm({
|
|
39563
|
+
"lib/runtime/server-prompt-rescue-account-contract.ts"() {
|
|
39564
|
+
"use strict";
|
|
39565
|
+
init_hyperliquid_account_mode_contract();
|
|
39566
|
+
STABLE_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USD", "USDT"]);
|
|
39567
|
+
toNumber2 = (value, fallback = 0) => {
|
|
39568
|
+
const numeric = Number(value);
|
|
39569
|
+
return Number.isFinite(numeric) ? numeric : fallback;
|
|
39570
|
+
};
|
|
39571
|
+
firstNumber2 = (values, fallback = 0) => {
|
|
39572
|
+
for (const value of values) {
|
|
39573
|
+
if (value == null || value === "") continue;
|
|
39574
|
+
const numeric = Number(value);
|
|
39575
|
+
if (Number.isFinite(numeric)) return numeric;
|
|
39576
|
+
}
|
|
39577
|
+
return fallback;
|
|
39578
|
+
};
|
|
39579
|
+
firstTruthy = (values, fallback) => {
|
|
39580
|
+
for (const value of values) {
|
|
39581
|
+
if (value) return value;
|
|
39582
|
+
}
|
|
39583
|
+
return fallback;
|
|
39584
|
+
};
|
|
39585
|
+
spotContainers = (spotResponse) => {
|
|
39586
|
+
if (!spotResponse || typeof spotResponse !== "object" || Array.isArray(spotResponse)) return [];
|
|
39587
|
+
const response = spotResponse;
|
|
39588
|
+
const containers = [response];
|
|
39589
|
+
for (const key of ["spotState", "userState", "clearinghouseState", "state", "data"]) {
|
|
39590
|
+
const child = response[key];
|
|
39591
|
+
if (child && typeof child === "object" && !Array.isArray(child)) containers.push(child);
|
|
39592
|
+
}
|
|
39593
|
+
return containers;
|
|
39594
|
+
};
|
|
39595
|
+
extractCanonicalSpotMetrics = (spotResponse) => {
|
|
39596
|
+
const response = spotResponse && typeof spotResponse === "object" && !Array.isArray(spotResponse) ? spotResponse : {};
|
|
39597
|
+
const containers = spotContainers(response);
|
|
39598
|
+
let accountValue = 0;
|
|
39599
|
+
let totalMarginUsed = 0;
|
|
39600
|
+
let withdrawable = 0;
|
|
39601
|
+
for (const container of containers) {
|
|
39602
|
+
const marginSummary = container.marginSummary && typeof container.marginSummary === "object" && !Array.isArray(container.marginSummary) ? container.marginSummary : {};
|
|
39603
|
+
accountValue = Math.max(accountValue, toNumber2(marginSummary.accountValue));
|
|
39604
|
+
totalMarginUsed = Math.max(totalMarginUsed, toNumber2(marginSummary.totalMarginUsed));
|
|
39605
|
+
withdrawable = Math.max(withdrawable, toNumber2(container.withdrawable));
|
|
39606
|
+
}
|
|
39607
|
+
if (accountValue <= 0) {
|
|
39608
|
+
for (const key of ["accountValue", "totalValue", "equity", "totalRawUsd", "usdValue", "usdcValue"]) {
|
|
39609
|
+
accountValue = Math.max(accountValue, toNumber2(response[key]));
|
|
39610
|
+
}
|
|
39611
|
+
}
|
|
39612
|
+
const balances = [];
|
|
39613
|
+
const listKeys = ["balances", "tokenBalances", "spotBalances", "assets"];
|
|
39614
|
+
for (const container of containers) {
|
|
39615
|
+
for (const listKey of listKeys) {
|
|
39616
|
+
const bucket = container[listKey];
|
|
39617
|
+
if (!Array.isArray(bucket)) continue;
|
|
39618
|
+
let stableTotal = 0;
|
|
39619
|
+
let anyTotal = 0;
|
|
39620
|
+
for (const rawEntry of bucket) {
|
|
39621
|
+
if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) continue;
|
|
39622
|
+
const entry = rawEntry;
|
|
39623
|
+
const coin = String(firstTruthy([
|
|
39624
|
+
entry.coin,
|
|
39625
|
+
entry.token,
|
|
39626
|
+
entry.asset,
|
|
39627
|
+
entry.symbol
|
|
39628
|
+
], "")).trim().toUpperCase();
|
|
39629
|
+
if (!coin) continue;
|
|
39630
|
+
const total = toNumber2(firstTruthy([entry.total, entry.balance, entry.amount], "0"));
|
|
39631
|
+
const hold = toNumber2(firstTruthy([entry.hold, entry.locked], "0"));
|
|
39632
|
+
const available = Math.max(
|
|
39633
|
+
0,
|
|
39634
|
+
toNumber2(firstTruthy([entry.available, entry.free, total - hold], "0"))
|
|
39635
|
+
);
|
|
39636
|
+
let valueUsd = toNumber2(firstTruthy([entry.usdValue, entry.usdcValue], "0"));
|
|
39637
|
+
if (valueUsd <= 0 && STABLE_SYMBOLS.has(coin)) {
|
|
39638
|
+
valueUsd = available > 0 ? available : total;
|
|
39639
|
+
}
|
|
39640
|
+
balances.push({ coin, total, hold, available, value_usd: valueUsd });
|
|
39641
|
+
const entryValue = valueUsd > 0 ? valueUsd : total;
|
|
39642
|
+
if (entryValue > 0) {
|
|
39643
|
+
anyTotal += entryValue;
|
|
39644
|
+
if (STABLE_SYMBOLS.has(coin)) stableTotal += entryValue;
|
|
39645
|
+
}
|
|
39646
|
+
}
|
|
39647
|
+
if (accountValue <= 0) {
|
|
39648
|
+
if (stableTotal > 0) accountValue = stableTotal;
|
|
39649
|
+
else if (anyTotal > 0) accountValue = anyTotal;
|
|
39650
|
+
}
|
|
39651
|
+
}
|
|
39652
|
+
if (balances.length > 0) break;
|
|
39653
|
+
}
|
|
39654
|
+
return { accountValue, totalMarginUsed, withdrawable, balances };
|
|
39655
|
+
};
|
|
39656
|
+
sumBalanceValueUsd = (balances) => balances.reduce((total, balance) => {
|
|
39657
|
+
let valueUsd = toNumber2(balance.value_usd);
|
|
39658
|
+
if (valueUsd <= 0 && STABLE_SYMBOLS.has(String(balance.coin || "").trim().toUpperCase())) {
|
|
39659
|
+
valueUsd = toNumber2(balance.total);
|
|
39660
|
+
}
|
|
39661
|
+
return total + Math.max(valueUsd, 0);
|
|
39662
|
+
}, 0);
|
|
39663
|
+
approximatelyEqual = (left, right, absoluteToleranceUsd, relativeTolerance) => {
|
|
39664
|
+
const reference = Math.max(Math.abs(left), Math.abs(right), 1);
|
|
39665
|
+
return Math.abs(left - right) <= Math.max(absoluteToleranceUsd, reference * relativeTolerance);
|
|
39666
|
+
};
|
|
39667
|
+
balancesMirrorUnifiedAccountValue = (input) => input.perpsEquity > 0 && input.spotEquity > 0 && input.balancesEquity > 0 && approximatelyEqual(
|
|
39668
|
+
input.perpsEquity,
|
|
39669
|
+
input.spotEquity,
|
|
39670
|
+
input.absoluteToleranceUsd,
|
|
39671
|
+
input.relativeTolerance
|
|
39672
|
+
) && approximatelyEqual(
|
|
39673
|
+
input.spotEquity,
|
|
39674
|
+
input.balancesEquity,
|
|
39675
|
+
input.absoluteToleranceUsd,
|
|
39676
|
+
input.relativeTolerance
|
|
39677
|
+
);
|
|
39678
|
+
computeEffectiveAccountValue = (input) => {
|
|
39679
|
+
if (!input.unifiedLike) return input.perpsEquity;
|
|
39680
|
+
if (input.balancesEquity > 0) {
|
|
39681
|
+
if (input.mirrored) {
|
|
39682
|
+
return Math.max(input.perpsEquity, input.spotEquity, input.balancesEquity);
|
|
39683
|
+
}
|
|
39684
|
+
return Math.max(
|
|
39685
|
+
input.perpsEquity + input.balancesEquity,
|
|
39686
|
+
input.spotEquity,
|
|
39687
|
+
input.balancesEquity
|
|
39688
|
+
);
|
|
39689
|
+
}
|
|
39690
|
+
return Math.max(input.perpsEquity, input.spotEquity);
|
|
39691
|
+
};
|
|
39692
|
+
equityFormula = (input) => {
|
|
39693
|
+
if (!input.unifiedLike) return "perps_account_value";
|
|
39694
|
+
if (input.balancesEquity > 0) {
|
|
39695
|
+
if (input.mirrored) return "unified_mirrored_balances_equity";
|
|
39696
|
+
if (input.perpsEquity + input.balancesEquity >= Math.max(input.spotEquity, input.balancesEquity)) return "unified_perps_plus_balances";
|
|
39697
|
+
if (input.spotEquity >= input.balancesEquity) return "unified_spot_account_value";
|
|
39698
|
+
return "unified_balances_equity";
|
|
39699
|
+
}
|
|
39700
|
+
return input.perpsEquity >= input.spotEquity ? "unified_perps_account_value" : "unified_spot_account_value";
|
|
39701
|
+
};
|
|
39702
|
+
buildServerPromptRescueAccountSummary = (perpsResponse, spotResponse, accountMode, options = {}) => {
|
|
39703
|
+
const perps = perpsResponse && typeof perpsResponse === "object" && !Array.isArray(perpsResponse) ? perpsResponse : {};
|
|
39704
|
+
const marginSummary = perps.marginSummary && typeof perps.marginSummary === "object" && !Array.isArray(perps.marginSummary) ? perps.marginSummary : {};
|
|
39705
|
+
const crossMarginSummary = perps.crossMarginSummary && typeof perps.crossMarginSummary === "object" && !Array.isArray(perps.crossMarginSummary) ? perps.crossMarginSummary : {};
|
|
39706
|
+
const rawPerpsAccountValue = toNumber2(marginSummary.accountValue);
|
|
39707
|
+
const perpsAccountValue = Math.max(0, rawPerpsAccountValue);
|
|
39708
|
+
const crossMarginAccountValue = toNumber2(crossMarginSummary.accountValue);
|
|
39709
|
+
let totalMarginUsed = toNumber2(marginSummary.totalMarginUsed);
|
|
39710
|
+
let withdrawable = toNumber2(perps.withdrawable);
|
|
39711
|
+
const spot = accountMode === "disabled" ? { accountValue: 0, totalMarginUsed: 0, withdrawable: 0, balances: [] } : extractCanonicalSpotMetrics(spotResponse);
|
|
39712
|
+
const balances = spot.balances;
|
|
39713
|
+
const balancesEquity = sumBalanceValueUsd(balances);
|
|
39714
|
+
const unifiedLike = isUnifiedAccountMode(accountMode);
|
|
39715
|
+
if (unifiedLike) {
|
|
39716
|
+
totalMarginUsed = Math.max(totalMarginUsed, spot.totalMarginUsed);
|
|
39717
|
+
withdrawable = Math.max(withdrawable, spot.withdrawable);
|
|
39718
|
+
}
|
|
39719
|
+
const absoluteToleranceUsd = firstNumber2([
|
|
39720
|
+
options.mirroredAccountValueAbsoluteToleranceUsd,
|
|
39721
|
+
options.mirrored_account_value_absolute_tolerance_usd
|
|
39722
|
+
]);
|
|
39723
|
+
const relativeTolerance = firstNumber2([
|
|
39724
|
+
options.mirroredAccountValueRelativeTolerance,
|
|
39725
|
+
options.mirrored_account_value_relative_tolerance
|
|
39726
|
+
]);
|
|
39727
|
+
const mirrored = balancesMirrorUnifiedAccountValue({
|
|
39728
|
+
perpsEquity: perpsAccountValue,
|
|
39729
|
+
spotEquity: Math.max(spot.accountValue, 0),
|
|
39730
|
+
balancesEquity,
|
|
39731
|
+
absoluteToleranceUsd,
|
|
39732
|
+
relativeTolerance
|
|
39733
|
+
});
|
|
39734
|
+
const formulaInput = {
|
|
39735
|
+
perpsEquity: perpsAccountValue,
|
|
39736
|
+
spotEquity: Math.max(spot.accountValue, 0),
|
|
39737
|
+
balancesEquity,
|
|
39738
|
+
unifiedLike,
|
|
39739
|
+
mirrored
|
|
39740
|
+
};
|
|
39741
|
+
const accountValue = computeEffectiveAccountValue(formulaInput);
|
|
39742
|
+
const maintenanceMargin = toNumber2(perps.crossMaintenanceMarginUsed);
|
|
39743
|
+
const calculatedAvailable = accountValue - totalMarginUsed;
|
|
39744
|
+
const availableMargin = maintenanceMargin > 0 ? Math.max(
|
|
39745
|
+
calculatedAvailable,
|
|
39746
|
+
Math.max(0, accountValue - 4 * maintenanceMargin),
|
|
39747
|
+
withdrawable
|
|
39748
|
+
) : Math.max(calculatedAvailable, withdrawable);
|
|
39749
|
+
let totalNotional = 0;
|
|
39750
|
+
let totalUnrealizedPnl = 0;
|
|
39751
|
+
const positions = Array.isArray(perps.assetPositions) ? perps.assetPositions : [];
|
|
39752
|
+
for (const entry of positions) {
|
|
39753
|
+
const position = entry && typeof entry === "object" && !Array.isArray(entry) ? entry.position : null;
|
|
39754
|
+
if (!position || typeof position !== "object" || Array.isArray(position)) continue;
|
|
39755
|
+
const size = toNumber2(position.szi);
|
|
39756
|
+
const unrealizedPnl = toNumber2(position.unrealizedPnl);
|
|
39757
|
+
totalUnrealizedPnl += unrealizedPnl;
|
|
39758
|
+
totalNotional += Math.abs(size * toNumber2(position.entryPx) + unrealizedPnl);
|
|
39759
|
+
}
|
|
39760
|
+
return {
|
|
39761
|
+
account_value: accountValue,
|
|
39762
|
+
total_margin_used: totalMarginUsed,
|
|
39763
|
+
available_margin: availableMargin,
|
|
39764
|
+
withdrawable,
|
|
39765
|
+
cross_margin_ratio: accountValue > 0 ? maintenanceMargin / accountValue : 0,
|
|
39766
|
+
maintenance_margin: maintenanceMargin,
|
|
39767
|
+
cross_account_leverage: accountValue > 0 ? totalNotional / accountValue : 0,
|
|
39768
|
+
total_unrealized_pnl: totalUnrealizedPnl,
|
|
39769
|
+
account_mode: accountMode,
|
|
39770
|
+
mode_source: "canonical",
|
|
39771
|
+
balances,
|
|
39772
|
+
raw_account_value: rawPerpsAccountValue,
|
|
39773
|
+
cross_margin_account_value: crossMarginAccountValue,
|
|
39774
|
+
spot_account_value: spot.accountValue,
|
|
39775
|
+
balances_equity: balancesEquity,
|
|
39776
|
+
equity_formula: equityFormula(formulaInput),
|
|
39777
|
+
balance_trust_classification: "trusted_canonical"
|
|
39778
|
+
};
|
|
39779
|
+
};
|
|
39780
|
+
}
|
|
39781
|
+
});
|
|
39782
|
+
|
|
38458
39783
|
// lib/runtime/abort.ts
|
|
38459
39784
|
var ABORT_MESSAGE_TOKENS, readAbortLikeMessage, isAbortLikeError;
|
|
38460
39785
|
var init_abort = __esm({
|
|
@@ -39021,6 +40346,8 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39021
40346
|
init_sort_utils();
|
|
39022
40347
|
init_hyperliquid_account_contract();
|
|
39023
40348
|
init_hyperliquid_active_asset_contract();
|
|
40349
|
+
init_hyperliquid_account_mode_contract();
|
|
40350
|
+
init_server_prompt_rescue_account_contract();
|
|
39024
40351
|
init_hyperliquid_market_symbol();
|
|
39025
40352
|
init_network_debug();
|
|
39026
40353
|
unsupportedUserActiveAssetCache = /* @__PURE__ */ new Set();
|
|
@@ -39136,13 +40463,15 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39136
40463
|
buildUserFillsStorageKey = (cacheKey) => {
|
|
39137
40464
|
return `${USER_FILLS_CACHE_STORAGE_PREFIX}${cacheKey}`;
|
|
39138
40465
|
};
|
|
39139
|
-
buildAccountStateCacheKey = (apiUrl, walletAddress, symbol2, aggregatePerpDexs, dexNames, includeEffectiveTakerRate) => {
|
|
40466
|
+
buildAccountStateCacheKey = (apiUrl, walletAddress, symbol2, aggregatePerpDexs, dexNames, includeEffectiveTakerRate, includeExactAccountMode, includeActiveAssetData) => {
|
|
39140
40467
|
return [
|
|
39141
40468
|
apiUrl.replace(/\/$/, "").toLowerCase(),
|
|
39142
40469
|
walletAddress.trim().toLowerCase(),
|
|
39143
40470
|
normalizeHyperliquidMarketSymbol(symbol2),
|
|
39144
40471
|
aggregatePerpDexs ? "aggregate" : "selected",
|
|
39145
40472
|
includeEffectiveTakerRate ? "with-effective-taker-rate" : "without-effective-taker-rate",
|
|
40473
|
+
includeExactAccountMode ? "with-exact-account-mode" : "without-exact-account-mode",
|
|
40474
|
+
includeActiveAssetData ? "with-active-asset" : "without-active-asset",
|
|
39146
40475
|
...dexNames.map(normalizePerpDexName).sort()
|
|
39147
40476
|
].join("::");
|
|
39148
40477
|
};
|
|
@@ -39352,7 +40681,8 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39352
40681
|
accountSummary: { ...result2.accountSummary },
|
|
39353
40682
|
availableToTrade: { ...result2.availableToTrade },
|
|
39354
40683
|
positions: result2.positions.map((position) => ({ ...position })),
|
|
39355
|
-
...result2.takerRate == null ? {} : { takerRate: result2.takerRate }
|
|
40684
|
+
...result2.takerRate == null ? {} : { takerRate: result2.takerRate },
|
|
40685
|
+
...result2.promptRescueEvidence == null ? {} : { promptRescueEvidence: { ...result2.promptRescueEvidence } }
|
|
39356
40686
|
});
|
|
39357
40687
|
readBrowserAccountStateCache = (cacheKey) => {
|
|
39358
40688
|
const memoryEntry = browserAccountStateCache.get(cacheKey);
|
|
@@ -39382,7 +40712,8 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39382
40712
|
accountSummary: { ...result2.accountSummary || {} },
|
|
39383
40713
|
availableToTrade: { ...result2.availableToTrade || {} },
|
|
39384
40714
|
positions: Array.isArray(result2.positions) ? result2.positions.filter((position) => position !== null && typeof position === "object" && !Array.isArray(position)).map((position) => ({ ...position })) : [],
|
|
39385
|
-
...result2.takerRate == null ? {} : { takerRate: Number(result2.takerRate) }
|
|
40715
|
+
...result2.takerRate == null ? {} : { takerRate: Number(result2.takerRate) },
|
|
40716
|
+
...result2.promptRescueEvidence == null ? {} : { promptRescueEvidence: { ...result2.promptRescueEvidence } }
|
|
39386
40717
|
}
|
|
39387
40718
|
};
|
|
39388
40719
|
if (entry.result.takerRate != null && (!Number.isFinite(entry.result.takerRate) || entry.result.takerRate < 0 || entry.result.takerRate >= 1)) {
|
|
@@ -39810,6 +41141,8 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39810
41141
|
const activeAssetRequestTypes = getBrowserActiveAssetTypeCandidates(apiUrl, walletAddress, symbol2);
|
|
39811
41142
|
const aggregatePerpDexs = input.aggregatePerpDexs !== false;
|
|
39812
41143
|
const includeEffectiveTakerRate = input.includeEffectiveTakerRate === true;
|
|
41144
|
+
const includeExactAccountMode = input.includeExactAccountMode === true;
|
|
41145
|
+
const includeActiveAssetData = input.includeActiveAssetData !== false;
|
|
39813
41146
|
const dexNames = listPerpDexsForAccountState(input.config, dex, aggregatePerpDexs);
|
|
39814
41147
|
const cacheKey = buildAccountStateCacheKey(
|
|
39815
41148
|
apiUrl,
|
|
@@ -39817,7 +41150,9 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39817
41150
|
symbol2,
|
|
39818
41151
|
aggregatePerpDexs,
|
|
39819
41152
|
dexNames,
|
|
39820
|
-
includeEffectiveTakerRate
|
|
41153
|
+
includeEffectiveTakerRate,
|
|
41154
|
+
includeExactAccountMode,
|
|
41155
|
+
includeActiveAssetData
|
|
39821
41156
|
);
|
|
39822
41157
|
const now = Date.now();
|
|
39823
41158
|
const cached2 = readBrowserAccountStateCache(cacheKey);
|
|
@@ -39828,7 +41163,8 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39828
41163
|
"clearinghouseState",
|
|
39829
41164
|
"spotClearinghouseState",
|
|
39830
41165
|
...includeEffectiveTakerRate ? ["userFees"] : [],
|
|
39831
|
-
...
|
|
41166
|
+
...includeExactAccountMode ? ["userAbstraction", "userDexAbstraction"] : [],
|
|
41167
|
+
...includeActiveAssetData ? activeAssetRequestTypes : []
|
|
39832
41168
|
], now)) {
|
|
39833
41169
|
return cloneBrowserAccountStateResult(cached2.result);
|
|
39834
41170
|
}
|
|
@@ -39906,20 +41242,29 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39906
41242
|
return prefixHip3PositionCoins(response, dexName);
|
|
39907
41243
|
})
|
|
39908
41244
|
);
|
|
39909
|
-
return
|
|
41245
|
+
return {
|
|
41246
|
+
payload: aggregateClearinghouseResponses([defaultResponse, ...dexResponses]),
|
|
41247
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41248
|
+
};
|
|
39910
41249
|
})();
|
|
39911
|
-
const spotPromise =
|
|
39912
|
-
|
|
39913
|
-
{
|
|
39914
|
-
|
|
39915
|
-
|
|
39916
|
-
|
|
39917
|
-
|
|
39918
|
-
|
|
41250
|
+
const spotPromise = (async () => {
|
|
41251
|
+
let payload;
|
|
41252
|
+
try {
|
|
41253
|
+
payload = await fetchHyperliquidInfoPayload(
|
|
41254
|
+
apiUrl,
|
|
41255
|
+
{ type: "spotClearinghouseState", user: walletAddress },
|
|
41256
|
+
input.signal
|
|
41257
|
+
);
|
|
41258
|
+
} catch (error48) {
|
|
41259
|
+
recordInfoRateLimitCooldownFromError(apiUrl, error48, staleIf429MaxAgeMs);
|
|
41260
|
+
if (input.forceRefresh || input.includeEffectiveTakerRate === true) {
|
|
41261
|
+
throw error48;
|
|
41262
|
+
}
|
|
41263
|
+
payload = {};
|
|
39919
41264
|
}
|
|
39920
|
-
return {};
|
|
39921
|
-
});
|
|
39922
|
-
const activeAssetPromise = (async () => {
|
|
41265
|
+
return { payload, capturedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
41266
|
+
})();
|
|
41267
|
+
const activeAssetPromise = input.includeActiveAssetData === false ? Promise.resolve(null) : (async () => {
|
|
39923
41268
|
let lastError = null;
|
|
39924
41269
|
for (const typeName of activeAssetRequestTypes) {
|
|
39925
41270
|
try {
|
|
@@ -39939,17 +41284,50 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39939
41284
|
}
|
|
39940
41285
|
throw lastError instanceof Error ? lastError : new Error("Failed to fetch browser active asset data.");
|
|
39941
41286
|
})();
|
|
39942
|
-
const userFeesPromise = input.includeEffectiveTakerRate === true ?
|
|
39943
|
-
|
|
39944
|
-
|
|
39945
|
-
|
|
39946
|
-
|
|
39947
|
-
|
|
41287
|
+
const userFeesPromise = input.includeEffectiveTakerRate === true ? (async () => ({
|
|
41288
|
+
payload: await fetchHyperliquidInfoPayload(
|
|
41289
|
+
apiUrl,
|
|
41290
|
+
{ type: "userFees", user: walletAddress },
|
|
41291
|
+
input.signal
|
|
41292
|
+
),
|
|
41293
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41294
|
+
}))() : Promise.resolve(null);
|
|
41295
|
+
const exactAccountModePromise = input.includeExactAccountMode === true ? (async () => {
|
|
41296
|
+
const userAbstraction = await fetchHyperliquidInfoPayload(
|
|
41297
|
+
apiUrl,
|
|
41298
|
+
{ type: "userAbstraction", user: walletAddress },
|
|
41299
|
+
input.signal
|
|
41300
|
+
);
|
|
41301
|
+
const preliminaryMode = extractCanonicalHyperliquidAccountMode(userAbstraction);
|
|
41302
|
+
if (!preliminaryMode) {
|
|
41303
|
+
throw new Error("Exact Hyperliquid userAbstraction response is invalid.");
|
|
41304
|
+
}
|
|
41305
|
+
let userDexAbstraction;
|
|
41306
|
+
if (preliminaryMode === "default" || preliminaryMode === "disabled") {
|
|
41307
|
+
userDexAbstraction = await fetchHyperliquidInfoPayload(
|
|
41308
|
+
apiUrl,
|
|
41309
|
+
{ type: "userDexAbstraction", user: walletAddress },
|
|
41310
|
+
input.signal
|
|
41311
|
+
);
|
|
41312
|
+
}
|
|
41313
|
+
return {
|
|
41314
|
+
accountMode: resolveExactHyperliquidAccountMode(
|
|
41315
|
+
userAbstraction,
|
|
41316
|
+
userDexAbstraction
|
|
41317
|
+
),
|
|
41318
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41319
|
+
};
|
|
41320
|
+
})() : Promise.resolve(null);
|
|
41321
|
+
const [perpsResult, spotResult, activeAssetResult, userFeesResult, exactAccountMode] = await Promise.all([
|
|
39948
41322
|
perpsPromise,
|
|
39949
41323
|
spotPromise,
|
|
39950
41324
|
activeAssetPromise,
|
|
39951
|
-
userFeesPromise
|
|
41325
|
+
userFeesPromise,
|
|
41326
|
+
exactAccountModePromise
|
|
39952
41327
|
]);
|
|
41328
|
+
const perpsResponse = perpsResult.payload;
|
|
41329
|
+
const spotResponse = spotResult.payload;
|
|
41330
|
+
const userFeesResponse = userFeesResult?.payload ?? null;
|
|
39953
41331
|
if (input.includeEffectiveTakerRate === true) {
|
|
39954
41332
|
requirePromptSpotState(spotResponse);
|
|
39955
41333
|
}
|
|
@@ -39969,20 +41347,32 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
39969
41347
|
takerRate = parsedUserCrossRate;
|
|
39970
41348
|
}
|
|
39971
41349
|
const accountStateConfig = input.config.client_runtime_hyperliquid_account_state;
|
|
39972
|
-
const
|
|
41350
|
+
const summaryPerpsResponse = exactAccountMode ? { ...perpsResponse, accountMode: exactAccountMode.accountMode } : perpsResponse;
|
|
41351
|
+
const accountSummaryOptions = {
|
|
39973
41352
|
spotDominatesMinTotalUsd: accountStateConfig?.spot_dominates_min_total_usd,
|
|
39974
41353
|
spotDominatesPerpsMultiplier: accountStateConfig?.spot_dominates_perps_multiplier,
|
|
39975
41354
|
mirroredAccountValueAbsoluteToleranceUsd: accountStateConfig?.mirrored_account_value_absolute_tolerance_usd,
|
|
39976
41355
|
mirroredAccountValueRelativeTolerance: accountStateConfig?.mirrored_account_value_relative_tolerance
|
|
39977
|
-
}
|
|
41356
|
+
};
|
|
41357
|
+
const normalizedSummary = exactAccountMode ? buildServerPromptRescueAccountSummary(
|
|
41358
|
+
perpsResponse,
|
|
41359
|
+
spotResponse,
|
|
41360
|
+
exactAccountMode.accountMode,
|
|
41361
|
+
accountSummaryOptions
|
|
41362
|
+
) : buildAccountSummaryFromInfoResponses(
|
|
41363
|
+
summaryPerpsResponse,
|
|
41364
|
+
spotResponse,
|
|
41365
|
+
accountSummaryOptions
|
|
41366
|
+
);
|
|
39978
41367
|
const accountSummary = {
|
|
39979
41368
|
...normalizedSummary,
|
|
41369
|
+
...exactAccountMode == null ? {} : { account_mode: exactAccountMode.accountMode, mode_source: "canonical" },
|
|
39980
41370
|
address: walletAddress,
|
|
39981
41371
|
dex: "all",
|
|
39982
41372
|
market_type: "perp"
|
|
39983
41373
|
};
|
|
39984
|
-
const activeAssetPayload = activeAssetResult
|
|
39985
|
-
const activeAssetType = activeAssetResult
|
|
41374
|
+
const activeAssetPayload = activeAssetResult?.payload ?? null;
|
|
41375
|
+
const activeAssetType = activeAssetResult?.type ?? "promptAccountState";
|
|
39986
41376
|
const normalizedActiveAsset = normalizeActiveAssetData(activeAssetPayload, symbol2);
|
|
39987
41377
|
const markPrice = toPositiveFinite(normalizedActiveAsset.mark_price, toPositiveFinite(input.tickerPrice));
|
|
39988
41378
|
const fallbackLeverage = toPositiveFinite(input.leverage, 1);
|
|
@@ -40000,7 +41390,17 @@ var init_hyperliquid_account_state_adapter = __esm({
|
|
|
40000
41390
|
accountSummary,
|
|
40001
41391
|
availableToTrade,
|
|
40002
41392
|
positions: parseInfoPositions(perpsResponse),
|
|
40003
|
-
...takerRate == null ? {} : { takerRate }
|
|
41393
|
+
...takerRate == null ? {} : { takerRate },
|
|
41394
|
+
...exactAccountMode == null || userFeesResult == null ? {} : {
|
|
41395
|
+
promptRescueEvidence: {
|
|
41396
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41397
|
+
perpsCapturedAt: perpsResult.capturedAt,
|
|
41398
|
+
spotCapturedAt: spotResult.capturedAt,
|
|
41399
|
+
feesCapturedAt: userFeesResult.capturedAt,
|
|
41400
|
+
accountModeCapturedAt: exactAccountMode.capturedAt,
|
|
41401
|
+
accountModeSource: "canonical"
|
|
41402
|
+
}
|
|
41403
|
+
}
|
|
40004
41404
|
};
|
|
40005
41405
|
};
|
|
40006
41406
|
fetchBrowserUserFills = async (input) => {
|
|
@@ -51158,6 +52558,145 @@ var init_runtime_handoff = __esm({
|
|
|
51158
52558
|
}
|
|
51159
52559
|
});
|
|
51160
52560
|
|
|
52561
|
+
// lib/runtime/status-contract.ts
|
|
52562
|
+
var init_status_contract = __esm({
|
|
52563
|
+
"lib/runtime/status-contract.ts"() {
|
|
52564
|
+
"use strict";
|
|
52565
|
+
}
|
|
52566
|
+
});
|
|
52567
|
+
|
|
52568
|
+
// lib/runtime/error-surface-contract.ts
|
|
52569
|
+
var SENSITIVE_DB_TOKENS, SCHEMA_DISCLOSURE_TOKENS, SQL_STATEMENT_PATTERN, TRACEBACK_PATTERN, DB_SESSION_STATE_PATTERNS, isSensitiveRuntimeErrorDetail, EXECUTION_ERROR_DEFAULTS, isExecutionErrorReasonCode, RuntimeExecutionError, projectExecutionErrorContract;
|
|
52570
|
+
var init_error_surface_contract = __esm({
|
|
52571
|
+
"lib/runtime/error-surface-contract.ts"() {
|
|
52572
|
+
"use strict";
|
|
52573
|
+
init_status_contract();
|
|
52574
|
+
init_runtime_redaction();
|
|
52575
|
+
SENSITIVE_DB_TOKENS = [
|
|
52576
|
+
"sqlalchemy",
|
|
52577
|
+
"asyncpg",
|
|
52578
|
+
"psycopg",
|
|
52579
|
+
"dbapi",
|
|
52580
|
+
"programmingerror",
|
|
52581
|
+
"undefinedcolumnerror",
|
|
52582
|
+
"integrityerror",
|
|
52583
|
+
"statementerror",
|
|
52584
|
+
"queuepool",
|
|
52585
|
+
"postgresql",
|
|
52586
|
+
"sqlite"
|
|
52587
|
+
];
|
|
52588
|
+
SCHEMA_DISCLOSURE_TOKENS = [
|
|
52589
|
+
" column ",
|
|
52590
|
+
" table ",
|
|
52591
|
+
" schema ",
|
|
52592
|
+
" relation ",
|
|
52593
|
+
" constraint "
|
|
52594
|
+
];
|
|
52595
|
+
SQL_STATEMENT_PATTERN = /\b(select|insert|update|delete)\b[\s\S]{0,300}\bfrom\b/i;
|
|
52596
|
+
TRACEBACK_PATTERN = /traceback \(most recent call last\):/i;
|
|
52597
|
+
DB_SESSION_STATE_PATTERNS = [
|
|
52598
|
+
/\bthis session is in ['"]?\w+['"]? state\b/i,
|
|
52599
|
+
/\bno further sql can be emitted within this transaction\b/i,
|
|
52600
|
+
/\bcan(?:not|'t) reconnect until (?:the )?invalid transaction is rolled back\b/i,
|
|
52601
|
+
/\bthis session(?:'s)? transaction has been rolled back due to a previous exception\b/i,
|
|
52602
|
+
/\bthis transaction is (?:closed|inactive)\b/i,
|
|
52603
|
+
/\bthis session is provisioning a new connection; concurrent operations are not permitted\b/i,
|
|
52604
|
+
/\bthis session has been permanently closed\b/i,
|
|
52605
|
+
/\binvalid savepoint transaction\b/i
|
|
52606
|
+
];
|
|
52607
|
+
isSensitiveRuntimeErrorDetail = (error48) => {
|
|
52608
|
+
const message = String(error48 || "").trim();
|
|
52609
|
+
if (!message) {
|
|
52610
|
+
return false;
|
|
52611
|
+
}
|
|
52612
|
+
const lowered = message.toLowerCase();
|
|
52613
|
+
if (TRACEBACK_PATTERN.test(lowered) || lowered.includes("[sql:")) {
|
|
52614
|
+
return true;
|
|
52615
|
+
}
|
|
52616
|
+
if (SENSITIVE_DB_TOKENS.some((token) => lowered.includes(token))) {
|
|
52617
|
+
return true;
|
|
52618
|
+
}
|
|
52619
|
+
if (DB_SESSION_STATE_PATTERNS.some((pattern) => pattern.test(message))) {
|
|
52620
|
+
return true;
|
|
52621
|
+
}
|
|
52622
|
+
return SQL_STATEMENT_PATTERN.test(lowered) && SCHEMA_DISCLOSURE_TOKENS.some((token) => ` ${lowered} `.includes(token));
|
|
52623
|
+
};
|
|
52624
|
+
EXECUTION_ERROR_DEFAULTS = {
|
|
52625
|
+
private_node_stale: ["preflight", "not_dispatched"],
|
|
52626
|
+
signer_validation_unavailable: ["preflight", "not_dispatched"],
|
|
52627
|
+
wallet_not_authorized: ["preflight", "not_dispatched"],
|
|
52628
|
+
credentials_missing: ["preflight", "not_dispatched"],
|
|
52629
|
+
local_safety_block: ["preflight", "not_dispatched"],
|
|
52630
|
+
redis_unavailable: ["coordination", "not_dispatched"],
|
|
52631
|
+
exchange_rejected: ["exchange_response", "confirmed_dispatched"],
|
|
52632
|
+
outcome_unknown: ["transport", "outcome_unknown"],
|
|
52633
|
+
internal_execution_error: ["execution", "unknown"]
|
|
52634
|
+
};
|
|
52635
|
+
isExecutionErrorReasonCode = (value) => Object.prototype.hasOwnProperty.call(EXECUTION_ERROR_DEFAULTS, value);
|
|
52636
|
+
RuntimeExecutionError = class extends Error {
|
|
52637
|
+
constructor(message, reasonCode) {
|
|
52638
|
+
super(message);
|
|
52639
|
+
this.name = "RuntimeExecutionError";
|
|
52640
|
+
this.reasonCode = reasonCode;
|
|
52641
|
+
this.executionStage = EXECUTION_ERROR_DEFAULTS[reasonCode][0];
|
|
52642
|
+
this.dispatchOutcome = EXECUTION_ERROR_DEFAULTS[reasonCode][1];
|
|
52643
|
+
}
|
|
52644
|
+
};
|
|
52645
|
+
projectExecutionErrorContract = (input) => {
|
|
52646
|
+
const {
|
|
52647
|
+
error: error48,
|
|
52648
|
+
symbol: symbol2 = null,
|
|
52649
|
+
reasonCode = null
|
|
52650
|
+
} = input;
|
|
52651
|
+
const typed = error48;
|
|
52652
|
+
const rawReason = String(reasonCode || typed?.reasonCode || "internal_execution_error").trim().toLowerCase();
|
|
52653
|
+
const resolvedReason = isExecutionErrorReasonCode(rawReason) ? rawReason : "internal_execution_error";
|
|
52654
|
+
const defaults = EXECUTION_ERROR_DEFAULTS[resolvedReason];
|
|
52655
|
+
const resolvedStage = defaults[0];
|
|
52656
|
+
const resolvedDispatch = defaults[1];
|
|
52657
|
+
const normalizedSymbol = String(symbol2 || "").trim();
|
|
52658
|
+
const orderLabel = normalizedSymbol ? `${normalizedSymbol} order` : "order";
|
|
52659
|
+
const rawMessage = sanitizeRuntimeDiagnosticValue(
|
|
52660
|
+
error48 instanceof Error ? error48.message : String(error48 || "").trim()
|
|
52661
|
+
);
|
|
52662
|
+
let message;
|
|
52663
|
+
if (resolvedReason === "private_node_stale") {
|
|
52664
|
+
message = `\u26A0\uFE0F The ${orderLabel} was not sent: Hyperliquid private account data was too stale to validate the signing key.`;
|
|
52665
|
+
} else if (resolvedReason === "signer_validation_unavailable") {
|
|
52666
|
+
message = `\u26A0\uFE0F The ${orderLabel} was not sent: Hyperliquid's private account service could not validate the signing key.`;
|
|
52667
|
+
} else if (resolvedReason === "wallet_not_authorized") {
|
|
52668
|
+
message = `\u26A0\uFE0F The ${orderLabel} was not sent: the signing key is not authorized for the configured wallet.`;
|
|
52669
|
+
} else if (resolvedReason === "credentials_missing") {
|
|
52670
|
+
message = `\u26A0\uFE0F The ${orderLabel} was not sent: a wallet address and authorized signing key are required for trading.`;
|
|
52671
|
+
} else if (resolvedReason === "local_safety_block") {
|
|
52672
|
+
const detail = isSensitiveRuntimeErrorDetail(rawMessage) ? "Local preflight validation failed." : rawMessage || "Local preflight validation failed.";
|
|
52673
|
+
const canonicalDetail = detail.replace(/^⚠️?\s*The (?:.+ )?order was not sent before exchange dispatch:\s*/i, "").trim() || "Local preflight validation failed.";
|
|
52674
|
+
message = `\u26A0\uFE0F The ${orderLabel} was not sent before exchange dispatch: ${canonicalDetail}`;
|
|
52675
|
+
} else if (resolvedReason === "redis_unavailable") {
|
|
52676
|
+
message = `\u26A0\uFE0F The ${orderLabel} was not sent because execution coordination was unavailable.`;
|
|
52677
|
+
} else if (resolvedReason === "exchange_rejected") {
|
|
52678
|
+
let detail = isSensitiveRuntimeErrorDetail(rawMessage) ? "The exchange did not provide safe rejection details." : rawMessage || "The exchange did not provide safe rejection details.";
|
|
52679
|
+
detail = detail.replace(/^⚠️?\s*Hyperliquid rejected the (?:.+ )?order:\s*/i, "").trim();
|
|
52680
|
+
detail = detail.replace(/^(?:Hyperliquid rejected order:|Order execution failed:|order execution failed:)\s*/, "");
|
|
52681
|
+
detail = detail.replace(/\s+asset=\d+\b\.?/g, "").trim() || "The exchange did not provide safe rejection details.";
|
|
52682
|
+
message = `\u26A0\uFE0F Hyperliquid rejected the ${orderLabel}: ${detail}`;
|
|
52683
|
+
} else if (resolvedReason === "outcome_unknown") {
|
|
52684
|
+
message = `\u26A0\uFE0F VTX could not confirm whether the ${orderLabel} was applied. Check open orders and the current position before retrying.`;
|
|
52685
|
+
} else {
|
|
52686
|
+
const detail = isSensitiveRuntimeErrorDetail(rawMessage) ? "VTX could not complete the exchange operation." : rawMessage || "VTX could not complete the exchange operation.";
|
|
52687
|
+
const canonicalDetail = detail.replace(/^⚠️?\s*VTX could not complete the (?:.+ )?order:\s*/i, "").trim() || "VTX could not complete the exchange operation.";
|
|
52688
|
+
message = `\u26A0\uFE0F VTX could not complete the ${orderLabel}: ${canonicalDetail}`;
|
|
52689
|
+
}
|
|
52690
|
+
return {
|
|
52691
|
+
reason_code: resolvedReason,
|
|
52692
|
+
execution_stage: resolvedStage,
|
|
52693
|
+
dispatch_outcome: resolvedDispatch,
|
|
52694
|
+
message
|
|
52695
|
+
};
|
|
52696
|
+
};
|
|
52697
|
+
}
|
|
52698
|
+
});
|
|
52699
|
+
|
|
51161
52700
|
// lib/runtime/hyperliquid-client.ts
|
|
51162
52701
|
var HyperliquidExchangeRejectionError, durableMutationAuthorityArgs, assertFreshPreparedExecutionContext, HYPERLIQUID_TERMINAL_ORDER_STATUSES, normalizeSymbol, HYPERLIQUID_NONCE_STORAGE_KEY, HYPERLIQUID_NONCE_LOCK_NAME, lastGeneratedNonce, readBrowserStoredHyperliquidNonce, writeBrowserStoredHyperliquidNonce, browserNonceCoordinator, allocateHyperliquidNonce, generateHyperliquidNonce, roundToSigFigs, normalizeDecimalString, toPlainDecimalString, roundDirectionalDecimalString, formatHyperliquidPerpPriceWire, formatHyperliquidTriggerPriceWire, countSignificantDigits, countDecimalPlaces, validateHyperliquidPerpPriceWire, validateHyperliquidSizeWire, formatSizeWire, inferApiUrl, inferIsTestnet, postHyperliquidInfo, toFiniteNumber, OPEN_ORDER_NUMERIC_STRING, OPEN_ORDER_ID_STRING, parseCanonicalOpenOrderId, parseOpenOrderFiniteNumber, parseOpenOrderPositiveNumber, parseOpenOrderPresentationNumber, readOpenOrderField, firstFiniteNumber2, parseFundingUsdcFromInfoPosition2, isExchangeIsolatedOnly, computeHip3AssetId, getPerpDexIndexMap, buildAssetInfosFromMetaResponse, requireWalletAddress2, assertPositiveInteger, assertPositiveNumber, normalizeOrderSide, normalizeHyperliquidClientOrderId, resolveAssets, findResolvedAsset, normalizeExecutionAssetMetadata, resolveHyperliquidAsset, resolveHyperliquidAssetIndex, fetchBrowserAvailableAssets, fetchBrowserAllMids, fetchBrowserSymbolMidPrice, fetchBrowserOpenOrders, parseCanonicalHyperliquidOrderStatusEvidence, fetchBrowserOrderStatusEvidence, fetchBrowserUserRole, fetchBrowserAccountState2, fetchBrowserPosition, buildHyperliquidOrderWire, buildHyperliquidTriggerOrderWire, signHyperliquidPayload, buildHyperliquidCancelPayload, buildHyperliquidUpdateLeveragePayload, buildHyperliquidMarketOrderPayload, buildHyperliquidTriggerOrderPayload, buildHyperliquidOrderBatchPayload, buildHyperliquidModifyOrderPayload, extractHyperliquidExchangeError, isDefinitiveHyperliquidExchangeResponse, extractDefinitiveHyperliquidOrderId, CANONICAL_POSITIVE_DECIMAL_PATTERN, extractCanonicalHyperliquidOrderStateAcknowledgement, extractCanonicalHyperliquidOrderStateAcknowledgements, extractCanonicalHyperliquidFilledOrderAcknowledgement, extractDefinitiveHyperliquidOrderMemberResults, buildHyperliquidOrderDiagnostics, loadClientExecutionReferenceEvidence, sha256Hex, extractSignedPayloadClientOrderId, extractSignedPayloadMutationCorrelation, assertDurableMutationMatchesSignedAction, submitHyperliquidExchangePayload;
|
|
51163
52702
|
var init_hyperliquid_client = __esm({
|
|
@@ -51171,9 +52710,10 @@ var init_hyperliquid_client = __esm({
|
|
|
51171
52710
|
init_runtime_redaction();
|
|
51172
52711
|
init_exchange_mutation_fence();
|
|
51173
52712
|
init_runtime_handoff();
|
|
51174
|
-
|
|
52713
|
+
init_error_surface_contract();
|
|
52714
|
+
HyperliquidExchangeRejectionError = class extends RuntimeExecutionError {
|
|
51175
52715
|
constructor(message, orderDiagnostics, clientMutationId = null) {
|
|
51176
|
-
super(message);
|
|
52716
|
+
super(message, "exchange_rejected");
|
|
51177
52717
|
this.name = "HyperliquidExchangeRejectionError";
|
|
51178
52718
|
this.orderDiagnostics = orderDiagnostics;
|
|
51179
52719
|
this.clientMutationId = clientMutationId;
|
|
@@ -52871,8 +54411,9 @@ var init_hyperliquid_client = __esm({
|
|
|
52871
54411
|
...durableMutationAuthorityArgs(durableMutation)
|
|
52872
54412
|
);
|
|
52873
54413
|
if (beginResult.dispatch_authorized !== true) {
|
|
52874
|
-
throw new
|
|
52875
|
-
"This exchange mutation was already recorded and will not be dispatched again. Durable reconciliation is required before retrying."
|
|
54414
|
+
throw new RuntimeExecutionError(
|
|
54415
|
+
"This exchange mutation was already recorded and will not be dispatched again. Durable reconciliation is required before retrying.",
|
|
54416
|
+
"local_safety_block"
|
|
52876
54417
|
);
|
|
52877
54418
|
}
|
|
52878
54419
|
}
|
|
@@ -52895,8 +54436,9 @@ var init_hyperliquid_client = __esm({
|
|
|
52895
54436
|
...durableMutationAuthorityArgs(durableMutation)
|
|
52896
54437
|
);
|
|
52897
54438
|
} catch {
|
|
52898
|
-
throw new
|
|
52899
|
-
"Exchange submission may have completed; durable reconciliation is pending."
|
|
54439
|
+
throw new RuntimeExecutionError(
|
|
54440
|
+
"Exchange submission may have completed; durable reconciliation is pending.",
|
|
54441
|
+
"outcome_unknown"
|
|
52900
54442
|
);
|
|
52901
54443
|
}
|
|
52902
54444
|
};
|
|
@@ -52980,7 +54522,10 @@ var init_hyperliquid_client = __esm({
|
|
|
52980
54522
|
assertFreshPreparedExecutionContext(input.preparedContext);
|
|
52981
54523
|
} catch (preparedContextError) {
|
|
52982
54524
|
await settleDurableMutation("rejected");
|
|
52983
|
-
throw
|
|
54525
|
+
throw new RuntimeExecutionError(
|
|
54526
|
+
preparedContextError instanceof Error ? preparedContextError.message : "Prepared exchange context expired before dispatch.",
|
|
54527
|
+
"local_safety_block"
|
|
54528
|
+
);
|
|
52984
54529
|
}
|
|
52985
54530
|
if (input.signal?.aborted) {
|
|
52986
54531
|
await settleDurableMutation("rejected");
|
|
@@ -53012,8 +54557,9 @@ var init_hyperliquid_client = __esm({
|
|
|
53012
54557
|
const payload = await response.json().catch(() => ({}));
|
|
53013
54558
|
if (!response.ok) {
|
|
53014
54559
|
await settleDurableMutation("transport_ambiguous");
|
|
53015
|
-
throw new
|
|
53016
|
-
"Exchange submission may have completed; durable reconciliation is pending."
|
|
54560
|
+
throw new RuntimeExecutionError(
|
|
54561
|
+
"Exchange submission may have completed; durable reconciliation is pending.",
|
|
54562
|
+
"outcome_unknown"
|
|
53017
54563
|
);
|
|
53018
54564
|
}
|
|
53019
54565
|
const exchangeError = extractHyperliquidExchangeError(payload);
|
|
@@ -53022,8 +54568,9 @@ var init_hyperliquid_client = __esm({
|
|
|
53022
54568
|
exchangeError.partial ? "transport_ambiguous" : "rejected"
|
|
53023
54569
|
);
|
|
53024
54570
|
if (exchangeError.partial) {
|
|
53025
|
-
throw new
|
|
53026
|
-
"Hyperliquid returned a partially applied exchange response; durable reconciliation is pending."
|
|
54571
|
+
throw new RuntimeExecutionError(
|
|
54572
|
+
"Hyperliquid returned a partially applied exchange response; durable reconciliation is pending.",
|
|
54573
|
+
"outcome_unknown"
|
|
53027
54574
|
);
|
|
53028
54575
|
}
|
|
53029
54576
|
throw new HyperliquidExchangeRejectionError(
|
|
@@ -53037,8 +54584,9 @@ var init_hyperliquid_client = __esm({
|
|
|
53037
54584
|
input.payload.action
|
|
53038
54585
|
)) {
|
|
53039
54586
|
await settleDurableMutation("transport_ambiguous");
|
|
53040
|
-
throw new
|
|
53041
|
-
"Hyperliquid returned an incomplete exchange response; durable reconciliation is pending."
|
|
54587
|
+
throw new RuntimeExecutionError(
|
|
54588
|
+
"Hyperliquid returned an incomplete exchange response; durable reconciliation is pending.",
|
|
54589
|
+
"outcome_unknown"
|
|
53042
54590
|
);
|
|
53043
54591
|
}
|
|
53044
54592
|
const exactExchangeOrderId = durableMutation?.operationKind === "order" ? extractDefinitiveHyperliquidOrderId(payload, input.payload.action) : null;
|
|
@@ -53060,12 +54608,14 @@ var init_hyperliquid_client = __esm({
|
|
|
53060
54608
|
try {
|
|
53061
54609
|
await settleDurableMutation("transport_ambiguous");
|
|
53062
54610
|
} catch {
|
|
53063
|
-
throw new
|
|
53064
|
-
"Exchange submission may have completed; durable reconciliation is pending."
|
|
54611
|
+
throw new RuntimeExecutionError(
|
|
54612
|
+
"Exchange submission may have completed; durable reconciliation is pending.",
|
|
54613
|
+
"outcome_unknown"
|
|
53065
54614
|
);
|
|
53066
54615
|
}
|
|
53067
|
-
throw new
|
|
53068
|
-
"Exchange submission may have completed; durable reconciliation is pending."
|
|
54616
|
+
throw new RuntimeExecutionError(
|
|
54617
|
+
"Exchange submission may have completed; durable reconciliation is pending.",
|
|
54618
|
+
"outcome_unknown"
|
|
53069
54619
|
);
|
|
53070
54620
|
}
|
|
53071
54621
|
throw error48;
|
|
@@ -53087,6 +54637,7 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
53087
54637
|
"use strict";
|
|
53088
54638
|
init_lib2();
|
|
53089
54639
|
init_hyperliquid_client();
|
|
54640
|
+
init_error_surface_contract();
|
|
53090
54641
|
normalizeAddress = (value, label) => {
|
|
53091
54642
|
const normalized = String(value || "").trim().toLowerCase();
|
|
53092
54643
|
if (!/^0x[0-9a-f]{40}$/.test(normalized)) {
|
|
@@ -53109,7 +54660,15 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
53109
54660
|
return null;
|
|
53110
54661
|
};
|
|
53111
54662
|
assertBrowserHyperliquidSignerWalletBinding = async (input) => {
|
|
53112
|
-
|
|
54663
|
+
let walletAddress;
|
|
54664
|
+
try {
|
|
54665
|
+
walletAddress = normalizeAddress(input.walletAddress, "wallet address");
|
|
54666
|
+
} catch {
|
|
54667
|
+
throw new RuntimeExecutionError(
|
|
54668
|
+
"A valid Hyperliquid wallet address is required for trading.",
|
|
54669
|
+
"credentials_missing"
|
|
54670
|
+
);
|
|
54671
|
+
}
|
|
53113
54672
|
let signerAddress;
|
|
53114
54673
|
try {
|
|
53115
54674
|
signerAddress = normalizeAddress(
|
|
@@ -53117,13 +54676,25 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
53117
54676
|
"signer address"
|
|
53118
54677
|
);
|
|
53119
54678
|
} catch {
|
|
53120
|
-
throw new
|
|
54679
|
+
throw new RuntimeExecutionError(
|
|
54680
|
+
"Invalid Hyperliquid signing key.",
|
|
54681
|
+
"credentials_missing"
|
|
54682
|
+
);
|
|
54683
|
+
}
|
|
54684
|
+
let roleResponse;
|
|
54685
|
+
try {
|
|
54686
|
+
roleResponse = await fetchBrowserUserRole({
|
|
54687
|
+
config: input.config ?? null,
|
|
54688
|
+
walletAddress: signerAddress,
|
|
54689
|
+
signal: input.signal
|
|
54690
|
+
});
|
|
54691
|
+
} catch (error48) {
|
|
54692
|
+
if (input.signal?.aborted) throw error48;
|
|
54693
|
+
throw new RuntimeExecutionError(
|
|
54694
|
+
"Hyperliquid's private account service could not validate the signing key.",
|
|
54695
|
+
"signer_validation_unavailable"
|
|
54696
|
+
);
|
|
53121
54697
|
}
|
|
53122
|
-
const roleResponse = await fetchBrowserUserRole({
|
|
53123
|
-
config: input.config ?? null,
|
|
53124
|
-
walletAddress: signerAddress,
|
|
53125
|
-
signal: input.signal
|
|
53126
|
-
});
|
|
53127
54698
|
const signerRole = String(roleResponse.role || "").trim().toLowerCase();
|
|
53128
54699
|
if (signerRole === "user" && signerAddress === walletAddress) {
|
|
53129
54700
|
return {
|
|
@@ -53145,8 +54716,9 @@ var init_hyperliquid_signer_binding = __esm({
|
|
|
53145
54716
|
};
|
|
53146
54717
|
}
|
|
53147
54718
|
}
|
|
53148
|
-
throw new
|
|
53149
|
-
"The device Hyperliquid signing key is not authorized for this profile wallet. Stop the runtime and reconnect the wallet."
|
|
54719
|
+
throw new RuntimeExecutionError(
|
|
54720
|
+
"The device Hyperliquid signing key is not authorized for this profile wallet. Stop the runtime and reconnect the wallet.",
|
|
54721
|
+
"wallet_not_authorized"
|
|
53150
54722
|
);
|
|
53151
54723
|
};
|
|
53152
54724
|
}
|
|
@@ -53881,6 +55453,7 @@ var init_browser_trading = __esm({
|
|
|
53881
55453
|
"use strict";
|
|
53882
55454
|
init_hyperliquid_client();
|
|
53883
55455
|
init_hyperliquid_signer_binding();
|
|
55456
|
+
init_error_surface_contract();
|
|
53884
55457
|
init_vault();
|
|
53885
55458
|
resolveProfileId = (value) => {
|
|
53886
55459
|
const profileId = String(value).trim();
|
|
@@ -53966,7 +55539,10 @@ var init_browser_trading = __esm({
|
|
|
53966
55539
|
}
|
|
53967
55540
|
}
|
|
53968
55541
|
if (!signingKey) {
|
|
53969
|
-
throw new
|
|
55542
|
+
throw new RuntimeExecutionError(
|
|
55543
|
+
"Missing required device-local Hyperliquid signing key for this profile. Configure it in System for this device.",
|
|
55544
|
+
"credentials_missing"
|
|
55545
|
+
);
|
|
53970
55546
|
}
|
|
53971
55547
|
return signingKey;
|
|
53972
55548
|
};
|
|
@@ -53975,7 +55551,10 @@ var init_browser_trading = __esm({
|
|
|
53975
55551
|
const signingKey = explicit || await loadSigningKey(resolveProfileId(input.profileId));
|
|
53976
55552
|
const walletAddress = String(input.walletAddress || "").trim();
|
|
53977
55553
|
if (!walletAddress) {
|
|
53978
|
-
throw new
|
|
55554
|
+
throw new RuntimeExecutionError(
|
|
55555
|
+
"Missing wallet address for client Hyperliquid signing.",
|
|
55556
|
+
"credentials_missing"
|
|
55557
|
+
);
|
|
53979
55558
|
}
|
|
53980
55559
|
await assertBrowserHyperliquidSignerWalletBinding({
|
|
53981
55560
|
signingKey,
|
|
@@ -54484,6 +56063,7 @@ var init_runtime_execution = __esm({
|
|
|
54484
56063
|
init_hyperliquid_market_symbol();
|
|
54485
56064
|
init_network_debug();
|
|
54486
56065
|
init_runtime_redaction();
|
|
56066
|
+
init_error_surface_contract();
|
|
54487
56067
|
init_runtime_handoff();
|
|
54488
56068
|
fetchClientRuntimeOpenOrders = async (request) => {
|
|
54489
56069
|
const normalizedSymbol = normalizeHyperliquidMarketSymbol(
|
|
@@ -55961,6 +57541,7 @@ var init_runtime_execution = __esm({
|
|
|
55961
57541
|
}
|
|
55962
57542
|
}
|
|
55963
57543
|
for (const candidate of candidates) {
|
|
57544
|
+
const rejectionProjection = error48 instanceof HyperliquidExchangeRejectionError ? projectExecutionErrorContract({ error: error48, symbol: symbol2 }) : null;
|
|
55964
57545
|
reports.push({
|
|
55965
57546
|
order_id: null,
|
|
55966
57547
|
client_mutation_id: error48 instanceof HyperliquidExchangeRejectionError ? error48.clientMutationId ?? candidate.mutationId : candidate.mutationId,
|
|
@@ -55968,10 +57549,12 @@ var init_runtime_execution = __esm({
|
|
|
55968
57549
|
action: candidate.kind === "sl" ? "AUTO_SL" : "AUTO_TP",
|
|
55969
57550
|
status: error48 instanceof HyperliquidExchangeRejectionError ? "failed" : "blocked",
|
|
55970
57551
|
execution_metadata: {
|
|
55971
|
-
reason_code: error48 instanceof HyperliquidExchangeRejectionError ?
|
|
55972
|
-
error: getSanitizedRuntimeErrorMessage(error48)
|
|
57552
|
+
reason_code: error48 instanceof HyperliquidExchangeRejectionError ? rejectionProjection?.reason_code : "protective_trigger_ack_unresolved",
|
|
57553
|
+
error: rejectionProjection?.message ?? getSanitizedRuntimeErrorMessage(error48) ?? "Protective trigger submission is unresolved.",
|
|
55973
57554
|
...error48 instanceof HyperliquidExchangeRejectionError ? {
|
|
55974
|
-
execution_stage:
|
|
57555
|
+
execution_stage: rejectionProjection?.execution_stage,
|
|
57556
|
+
dispatch_outcome: rejectionProjection?.dispatch_outcome,
|
|
57557
|
+
operation_stage: "protective_trigger_order",
|
|
55975
57558
|
entry_order_id: fill.orderId,
|
|
55976
57559
|
order_diagnostics: error48.orderDiagnostics
|
|
55977
57560
|
} : {}
|
|
@@ -59030,15 +60613,21 @@ var init_runtime_execution = __esm({
|
|
|
59030
60613
|
execution_metadata: _toExecutionMetadata(marketOrderResponse)
|
|
59031
60614
|
});
|
|
59032
60615
|
const appendPostEntryProtectionFailure = (error48) => {
|
|
59033
|
-
const
|
|
60616
|
+
const projection = projectExecutionErrorContract({
|
|
60617
|
+
error: error48,
|
|
60618
|
+
symbol: input.executionContext.symbol
|
|
60619
|
+
});
|
|
60620
|
+
const message = projection.message;
|
|
59034
60621
|
executionReports.push({
|
|
59035
60622
|
order_id: null,
|
|
59036
60623
|
symbol: input.executionContext.symbol,
|
|
59037
60624
|
action: "PROTECTIVE_RECONCILIATION",
|
|
59038
60625
|
status: "failed",
|
|
59039
60626
|
execution_metadata: {
|
|
59040
|
-
reason_code:
|
|
59041
|
-
execution_stage:
|
|
60627
|
+
reason_code: projection.reason_code,
|
|
60628
|
+
execution_stage: projection.execution_stage,
|
|
60629
|
+
dispatch_outcome: projection.dispatch_outcome,
|
|
60630
|
+
operation_stage: "post_entry_protection",
|
|
59042
60631
|
entry_order_id: _extractOrderId(marketOrderResponse),
|
|
59043
60632
|
error: message
|
|
59044
60633
|
}
|
|
@@ -59443,7 +61032,11 @@ var init_runtime_execution = __esm({
|
|
|
59443
61032
|
);
|
|
59444
61033
|
}
|
|
59445
61034
|
} catch (triggerError) {
|
|
59446
|
-
const
|
|
61035
|
+
const projection = projectExecutionErrorContract({
|
|
61036
|
+
error: triggerError,
|
|
61037
|
+
symbol: input.executionContext.symbol
|
|
61038
|
+
});
|
|
61039
|
+
const message = projection.message;
|
|
59447
61040
|
const rejection = triggerError instanceof HyperliquidExchangeRejectionError ? triggerError : null;
|
|
59448
61041
|
executionReports.push({
|
|
59449
61042
|
order_id: null,
|
|
@@ -59454,8 +61047,10 @@ var init_runtime_execution = __esm({
|
|
|
59454
61047
|
execution_metadata: {
|
|
59455
61048
|
trigger_price: triggerInput.triggerPrice,
|
|
59456
61049
|
is_take_profit: triggerInput.isTakeProfit,
|
|
59457
|
-
reason_code:
|
|
59458
|
-
execution_stage:
|
|
61050
|
+
reason_code: projection.reason_code,
|
|
61051
|
+
execution_stage: projection.execution_stage,
|
|
61052
|
+
dispatch_outcome: projection.dispatch_outcome,
|
|
61053
|
+
operation_stage: "protective_trigger_order",
|
|
59459
61054
|
entry_order_id: _extractOrderId(marketOrderResponse),
|
|
59460
61055
|
error: message,
|
|
59461
61056
|
...rejection ? { order_diagnostics: rejection.orderDiagnostics } : {}
|
|
@@ -59997,7 +61592,7 @@ var headless_local_worker_exports = {};
|
|
|
59997
61592
|
__export(headless_local_worker_exports, {
|
|
59998
61593
|
createHeadlessLocalWorker: () => createHeadlessLocalWorker
|
|
59999
61594
|
});
|
|
60000
|
-
import { randomUUID as
|
|
61595
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
60001
61596
|
function objectOrNull3(value) {
|
|
60002
61597
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
60003
61598
|
}
|
|
@@ -60414,7 +62009,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
60414
62009
|
const statusMatch = errorText.match(/\b([45]\d{2})\b/);
|
|
60415
62010
|
const statusCode = statusMatch ? Number(statusMatch[1]) : null;
|
|
60416
62011
|
const failedInvocation = normalizeAiInvocationTelemetry({
|
|
60417
|
-
client_invocation_id:
|
|
62012
|
+
client_invocation_id: randomUUID8(),
|
|
60418
62013
|
use_case: "trader",
|
|
60419
62014
|
role: "primary",
|
|
60420
62015
|
attempt_index: 0,
|
|
@@ -60470,7 +62065,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
60470
62065
|
billable_cached_input_tokens: normalizedUsage.cached_input_tokens
|
|
60471
62066
|
};
|
|
60472
62067
|
const invocation = normalizeAiInvocationTelemetry({
|
|
60473
|
-
client_invocation_id:
|
|
62068
|
+
client_invocation_id: randomUUID8(),
|
|
60474
62069
|
use_case: "trader",
|
|
60475
62070
|
role: "primary",
|
|
60476
62071
|
attempt_index: 0,
|
|
@@ -60689,7 +62284,7 @@ var vtx_exports = {};
|
|
|
60689
62284
|
__export(vtx_exports, {
|
|
60690
62285
|
runVtxCli: () => runVtxCli
|
|
60691
62286
|
});
|
|
60692
|
-
import { randomUUID as
|
|
62287
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
60693
62288
|
import { spawn as spawn8 } from "node:child_process";
|
|
60694
62289
|
function render2(value, json2) {
|
|
60695
62290
|
if (json2) {
|
|
@@ -61103,8 +62698,8 @@ async function runVtxCli(argv2, env = process.env) {
|
|
|
61103
62698
|
});
|
|
61104
62699
|
return { exitCode: 0, stdout: render2(redactCliOutput(response2), json2), stderr: "" };
|
|
61105
62700
|
}
|
|
61106
|
-
const runtimeSessionId =
|
|
61107
|
-
const deviceId = config2.runtimeDeviceId ??
|
|
62701
|
+
const runtimeSessionId = randomUUID9();
|
|
62702
|
+
const deviceId = config2.runtimeDeviceId ?? randomUUID9();
|
|
61108
62703
|
const response = await client.startRuntime(profileId, {
|
|
61109
62704
|
session_id: runtimeSessionId,
|
|
61110
62705
|
device_id: deviceId,
|