@vtxmacro/cli 2026.8.52 → 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 +1080 -113
- package/package.json +1 -1
package/bin/vtx.js
CHANGED
|
@@ -47,7 +47,7 @@ var init_agent_cli_release = __esm({
|
|
|
47
47
|
"agent-cli-release.json"() {
|
|
48
48
|
agent_cli_release_default = {
|
|
49
49
|
package_name: "@vtxmacro/cli",
|
|
50
|
-
package_version: "2026.8.
|
|
50
|
+
package_version: "2026.8.53",
|
|
51
51
|
codex_package_name: "@openai/codex",
|
|
52
52
|
codex_version: "0.147.0",
|
|
53
53
|
copilot_sdk_package_name: "@github/copilot-sdk",
|
|
@@ -19695,32 +19695,60 @@ var init_agent_client = __esm({
|
|
|
19695
19695
|
});
|
|
19696
19696
|
|
|
19697
19697
|
// lib/inference-host/agent-state.ts
|
|
19698
|
-
async function
|
|
19698
|
+
async function readInferenceAgentRuntimeState(statePath) {
|
|
19699
19699
|
const raw = await readInferencePrivateFile(
|
|
19700
|
-
|
|
19701
|
-
"
|
|
19700
|
+
inferenceAgentRuntimeStatePath(statePath),
|
|
19701
|
+
"Inference Agent runtime recovery state"
|
|
19702
19702
|
);
|
|
19703
19703
|
if (raw === null) return null;
|
|
19704
19704
|
try {
|
|
19705
|
-
return
|
|
19705
|
+
return assertInferenceAgentRuntimeState(JSON.parse(raw));
|
|
19706
19706
|
} catch (error48) {
|
|
19707
19707
|
if (error48 instanceof SyntaxError) {
|
|
19708
|
-
throw new Error("
|
|
19708
|
+
throw new Error("Inference Agent runtime recovery state is not valid JSON.");
|
|
19709
19709
|
}
|
|
19710
19710
|
throw error48;
|
|
19711
19711
|
}
|
|
19712
19712
|
}
|
|
19713
|
-
async function
|
|
19713
|
+
async function writeInferenceAgentRuntimeState(statePath, value) {
|
|
19714
19714
|
await writeAtomicInferencePrivateFile(
|
|
19715
|
-
|
|
19716
|
-
`${JSON.stringify(
|
|
19715
|
+
inferenceAgentRuntimeStatePath(statePath),
|
|
19716
|
+
`${JSON.stringify(assertInferenceAgentRuntimeState(value), null, 2)}
|
|
19717
19717
|
`
|
|
19718
19718
|
);
|
|
19719
19719
|
}
|
|
19720
|
-
async function
|
|
19720
|
+
async function clearInferenceAgentRuntimeState(statePath) {
|
|
19721
19721
|
await clearInferencePrivateFile(
|
|
19722
|
-
|
|
19723
|
-
"
|
|
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"
|
|
19724
19752
|
);
|
|
19725
19753
|
}
|
|
19726
19754
|
async function readInferenceAgentAttemptState(statePath) {
|
|
@@ -19779,7 +19807,7 @@ async function clearInferenceAgentNextState(statePath) {
|
|
|
19779
19807
|
"Agent-driven inference next recovery state"
|
|
19780
19808
|
);
|
|
19781
19809
|
}
|
|
19782
|
-
var inferenceAgentAttemptStatePath, inferenceAgentNextStatePath,
|
|
19810
|
+
var inferenceAgentAttemptStatePath, inferenceAgentNextStatePath, inferenceAgentRuntimeStatePath, isIsoTimestamp, assertPlainObject, hasExactKeys, assertInferenceAgentRuntimeState, readCodexAgentRuntimeState, clearCodexAgentRuntimeState, foregroundAgentControlStatePath, assertRuntimeAssignment, assertForegroundAgentControlState, assertNextState, assertAttemptState;
|
|
19783
19811
|
var init_agent_state = __esm({
|
|
19784
19812
|
"lib/inference-host/agent-state.ts"() {
|
|
19785
19813
|
"use strict";
|
|
@@ -19787,18 +19815,20 @@ var init_agent_state = __esm({
|
|
|
19787
19815
|
init_external_inference_contract();
|
|
19788
19816
|
inferenceAgentAttemptStatePath = (statePath) => `${statePath}.agent-attempt.json`;
|
|
19789
19817
|
inferenceAgentNextStatePath = (statePath) => `${statePath}.agent-next.json`;
|
|
19790
|
-
|
|
19818
|
+
inferenceAgentRuntimeStatePath = (statePath) => `${statePath}.codex-agent-runtime.json`;
|
|
19791
19819
|
isIsoTimestamp = (value) => typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
19792
19820
|
assertPlainObject = (value, message) => {
|
|
19793
19821
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(message);
|
|
19794
19822
|
return value;
|
|
19795
19823
|
};
|
|
19796
19824
|
hasExactKeys = (record2, keys) => Object.keys(record2).sort().join("\0") === [...keys].sort().join("\0");
|
|
19797
|
-
|
|
19798
|
-
const message = "
|
|
19825
|
+
assertInferenceAgentRuntimeState = (value) => {
|
|
19826
|
+
const message = "Inference Agent runtime recovery state is invalid.";
|
|
19799
19827
|
const state = assertPlainObject(value, message);
|
|
19828
|
+
const generic = state.schema_version === "vtx_inference_agent_runtime_v3";
|
|
19800
19829
|
if (!hasExactKeys(state, [
|
|
19801
19830
|
"schema_version",
|
|
19831
|
+
...generic ? ["adapter_id"] : [],
|
|
19802
19832
|
"host_id",
|
|
19803
19833
|
"assignment",
|
|
19804
19834
|
"thread",
|
|
@@ -19807,9 +19837,13 @@ var init_agent_state = __esm({
|
|
|
19807
19837
|
"updated_at"
|
|
19808
19838
|
])) throw new Error(message);
|
|
19809
19839
|
const assignment = assertPlainObject(state.assignment, message);
|
|
19810
|
-
if (![
|
|
19840
|
+
if (![
|
|
19841
|
+
"vtx_codex_agent_runtime_v1",
|
|
19842
|
+
"vtx_codex_agent_runtime_v2",
|
|
19843
|
+
"vtx_inference_agent_runtime_v3"
|
|
19844
|
+
].includes(
|
|
19811
19845
|
String(state.schema_version)
|
|
19812
|
-
) || 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(
|
|
19813
19847
|
assignment,
|
|
19814
19848
|
[
|
|
19815
19849
|
"assignment_id",
|
|
@@ -19823,10 +19857,10 @@ var init_agent_state = __esm({
|
|
|
19823
19857
|
"minimum_wake_seconds",
|
|
19824
19858
|
"maximum_wake_seconds",
|
|
19825
19859
|
"lease_expires_at",
|
|
19826
|
-
...state.schema_version
|
|
19860
|
+
...state.schema_version !== "vtx_codex_agent_runtime_v1" ? ["data_contract"] : []
|
|
19827
19861
|
]
|
|
19828
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);
|
|
19829
|
-
if (state.schema_version
|
|
19863
|
+
if (state.schema_version !== "vtx_codex_agent_runtime_v1") {
|
|
19830
19864
|
if (!Array.isArray(assignment.data_contract) || assignment.data_contract.length === 0) {
|
|
19831
19865
|
throw new Error(message);
|
|
19832
19866
|
}
|
|
@@ -19865,6 +19899,76 @@ var init_agent_state = __esm({
|
|
|
19865
19899
|
}
|
|
19866
19900
|
return state;
|
|
19867
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
|
+
};
|
|
19868
19972
|
assertNextState = (value) => {
|
|
19869
19973
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
19870
19974
|
throw new Error("Agent-driven inference next recovery state is invalid.");
|
|
@@ -24019,15 +24123,17 @@ $items = @(Get-CimInstance Win32_Process | Where-Object { $_.Name -in @('node.ex
|
|
|
24019
24123
|
});
|
|
24020
24124
|
|
|
24021
24125
|
// lib/inference-host/copilot-adapter.ts
|
|
24126
|
+
import { randomUUID } from "node:crypto";
|
|
24022
24127
|
import { mkdtemp as mkdtemp2, rm as rm4 } from "node:fs/promises";
|
|
24023
24128
|
import { createRequire as createRequire2 } from "node:module";
|
|
24024
24129
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
24025
24130
|
import { join as join5 } from "node:path";
|
|
24026
24131
|
import {
|
|
24027
24132
|
CopilotClient,
|
|
24028
|
-
RuntimeConnection
|
|
24133
|
+
RuntimeConnection,
|
|
24134
|
+
defineTool
|
|
24029
24135
|
} from "@github/copilot-sdk";
|
|
24030
|
-
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;
|
|
24031
24137
|
var init_copilot_adapter = __esm({
|
|
24032
24138
|
"lib/inference-host/copilot-adapter.ts"() {
|
|
24033
24139
|
"use strict";
|
|
@@ -24123,9 +24229,66 @@ var init_copilot_adapter = __esm({
|
|
|
24123
24229
|
}
|
|
24124
24230
|
return Number(value);
|
|
24125
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
|
+
};
|
|
24126
24286
|
CopilotSubscriptionAdapter = class {
|
|
24127
24287
|
constructor(dependencies = {}) {
|
|
24128
24288
|
this.inFlight = /* @__PURE__ */ new Map();
|
|
24289
|
+
this.agentConnection = null;
|
|
24290
|
+
this.agentWorkspaceCleanups = /* @__PURE__ */ new Map();
|
|
24291
|
+
this.closing = false;
|
|
24129
24292
|
this.dependencies = dependencies;
|
|
24130
24293
|
}
|
|
24131
24294
|
async preflight(signal) {
|
|
@@ -24337,6 +24500,224 @@ ${input.outputSchemaJson}`
|
|
|
24337
24500
|
await workspace.cleanup();
|
|
24338
24501
|
}
|
|
24339
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
|
+
}
|
|
24340
24721
|
};
|
|
24341
24722
|
}
|
|
24342
24723
|
});
|
|
@@ -30914,7 +31295,7 @@ var require_ajv = __commonJS({
|
|
|
30914
31295
|
});
|
|
30915
31296
|
|
|
30916
31297
|
// lib/inference-host/runner.ts
|
|
30917
|
-
import { createHash as createHash6, randomUUID } from "node:crypto";
|
|
31298
|
+
import { createHash as createHash6, randomUUID as randomUUID2 } from "node:crypto";
|
|
30918
31299
|
function createDefaultInferenceHostRunnerDependencies(options) {
|
|
30919
31300
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
30920
31301
|
return {
|
|
@@ -30949,7 +31330,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
|
|
|
30949
31330
|
envelopePublicKey: options.envelopePublicKey
|
|
30950
31331
|
};
|
|
30951
31332
|
}
|
|
30952
|
-
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;
|
|
30953
31334
|
var init_runner = __esm({
|
|
30954
31335
|
"lib/inference-host/runner.ts"() {
|
|
30955
31336
|
"use strict";
|
|
@@ -31333,7 +31714,7 @@ var init_runner = __esm({
|
|
|
31333
31714
|
adapterId,
|
|
31334
31715
|
options.structuredOutput ?? adapterId === "codex",
|
|
31335
31716
|
options.sameAttemptRecovery ?? adapterId === "codex",
|
|
31336
|
-
options.agentRuntime
|
|
31717
|
+
options.agentRuntime ? ["provider", "agent"] : ["provider"]
|
|
31337
31718
|
),
|
|
31338
31719
|
maxConcurrency: options.maxConcurrency === null || options.maxConcurrency === void 0 ? null : finitePositiveOption(options.maxConcurrency, 1, "Maximum concurrency"),
|
|
31339
31720
|
advertisementTtlMs,
|
|
@@ -31788,10 +32169,11 @@ var init_runner = __esm({
|
|
|
31788
32169
|
const agentRuntimeSettings = settings.agentRuntime;
|
|
31789
32170
|
agentLoop = (async () => {
|
|
31790
32171
|
while (!agentAbort.signal.aborted) {
|
|
31791
|
-
const agentRuntime = new
|
|
32172
|
+
const agentRuntime = new InferenceAgentRuntime({
|
|
32173
|
+
adapterId: settings.adapterId,
|
|
31792
32174
|
hostId: localState.host_id,
|
|
31793
32175
|
statePath: agentRuntimeSettings.statePath,
|
|
31794
|
-
controlClient:
|
|
32176
|
+
controlClient: createInferenceAgentControlClient(mcp),
|
|
31795
32177
|
adapter: agentRuntimeSettings.adapter
|
|
31796
32178
|
});
|
|
31797
32179
|
try {
|
|
@@ -33129,7 +33511,7 @@ var init_runner = __esm({
|
|
|
33129
33511
|
}
|
|
33130
33512
|
}
|
|
33131
33513
|
};
|
|
33132
|
-
|
|
33514
|
+
createInferenceAgentControlClient = (mcp) => ({
|
|
33133
33515
|
nextAssignment: async (request, options) => {
|
|
33134
33516
|
const result2 = await mcp.callTool("inference.agent.assignment.next", {
|
|
33135
33517
|
...request,
|
|
@@ -33172,9 +33554,9 @@ var init_runner = __esm({
|
|
|
33172
33554
|
await mcp.callTool("inference.agent.assignment.release", request, options);
|
|
33173
33555
|
}
|
|
33174
33556
|
});
|
|
33175
|
-
|
|
33557
|
+
INFERENCE_AGENT_SYSTEM_PROMPT = `You autonomously control one running VTX bot.
|
|
33176
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.`;
|
|
33177
|
-
|
|
33559
|
+
INFERENCE_AGENT_WAKE_SCHEMA = {
|
|
33178
33560
|
type: "object",
|
|
33179
33561
|
additionalProperties: false,
|
|
33180
33562
|
required: ["next_wake_seconds", "summary"],
|
|
@@ -33183,29 +33565,29 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33183
33565
|
summary: { type: "string", minLength: 1, maxLength: 2e3 }
|
|
33184
33566
|
}
|
|
33185
33567
|
};
|
|
33186
|
-
|
|
33568
|
+
parseInferenceAgentWake = (text, assignment) => {
|
|
33187
33569
|
let value;
|
|
33188
33570
|
try {
|
|
33189
33571
|
value = JSON.parse(text);
|
|
33190
33572
|
} catch {
|
|
33191
33573
|
throw new InferenceHostRunnerError(
|
|
33192
33574
|
"invalid_agent_wake",
|
|
33193
|
-
"
|
|
33575
|
+
"Inference Agent returned invalid wake JSON."
|
|
33194
33576
|
);
|
|
33195
33577
|
}
|
|
33196
33578
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
33197
|
-
throw new InferenceHostRunnerError("invalid_agent_wake", "
|
|
33579
|
+
throw new InferenceHostRunnerError("invalid_agent_wake", "Inference Agent wake is invalid.");
|
|
33198
33580
|
}
|
|
33199
33581
|
const seconds = value.next_wake_seconds;
|
|
33200
33582
|
if (!Number.isSafeInteger(seconds) || Number(seconds) < 1) {
|
|
33201
|
-
throw new InferenceHostRunnerError("invalid_agent_wake", "
|
|
33583
|
+
throw new InferenceHostRunnerError("invalid_agent_wake", "Inference Agent wake is invalid.");
|
|
33202
33584
|
}
|
|
33203
33585
|
return Math.max(
|
|
33204
33586
|
assignment.minimum_wake_seconds,
|
|
33205
33587
|
Math.min(assignment.maximum_wake_seconds, Number(seconds))
|
|
33206
33588
|
);
|
|
33207
33589
|
};
|
|
33208
|
-
|
|
33590
|
+
InferenceAgentRuntime = class {
|
|
33209
33591
|
constructor(options) {
|
|
33210
33592
|
this.options = options;
|
|
33211
33593
|
this.stopped = false;
|
|
@@ -33239,29 +33621,55 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33239
33621
|
}
|
|
33240
33622
|
async runOnce(signal) {
|
|
33241
33623
|
const nowIso = () => new Date(this.now()).toISOString();
|
|
33242
|
-
const recoveredState = await
|
|
33624
|
+
const recoveredState = await readInferenceAgentRuntimeState(this.options.statePath);
|
|
33243
33625
|
if (recoveredState && recoveredState.host_id !== this.options.hostId) {
|
|
33244
33626
|
throw new InferenceHostRunnerError(
|
|
33245
33627
|
"agent_recovery_scope_mismatch",
|
|
33246
|
-
"
|
|
33628
|
+
"Inference Agent recovery state belongs to another host."
|
|
33247
33629
|
);
|
|
33248
33630
|
}
|
|
33249
33631
|
let state;
|
|
33250
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
|
+
}
|
|
33251
33639
|
state = await this.upgradeLegacyRuntimeState(recoveredState, signal);
|
|
33252
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);
|
|
33253
33654
|
} else {
|
|
33254
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
|
+
}
|
|
33255
33662
|
}
|
|
33256
33663
|
if (!state) {
|
|
33257
33664
|
const assignment2 = await this.options.controlClient.nextAssignment({
|
|
33258
|
-
operation_id:
|
|
33665
|
+
operation_id: randomUUID2(),
|
|
33259
33666
|
host_id: this.options.hostId,
|
|
33260
33667
|
requested_at: nowIso()
|
|
33261
33668
|
}, { signal });
|
|
33262
33669
|
if (!assignment2) return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33263
33670
|
state = {
|
|
33264
|
-
schema_version: "
|
|
33671
|
+
schema_version: "vtx_inference_agent_runtime_v3",
|
|
33672
|
+
adapter_id: this.options.adapterId,
|
|
33265
33673
|
host_id: this.options.hostId,
|
|
33266
33674
|
assignment: assignment2,
|
|
33267
33675
|
thread: null,
|
|
@@ -33269,7 +33677,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33269
33677
|
pending_decision: null,
|
|
33270
33678
|
updated_at: nowIso()
|
|
33271
33679
|
};
|
|
33272
|
-
await
|
|
33680
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33273
33681
|
} else {
|
|
33274
33682
|
const persistedWakeAtMs = Date.parse(state.next_wake_at);
|
|
33275
33683
|
if (persistedWakeAtMs > this.now()) {
|
|
@@ -33277,8 +33685,8 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33277
33685
|
if (wakeOutcome !== "ready") {
|
|
33278
33686
|
return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33279
33687
|
}
|
|
33280
|
-
const rereadState = await
|
|
33281
|
-
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) {
|
|
33282
33690
|
return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33283
33691
|
}
|
|
33284
33692
|
state = rereadState;
|
|
@@ -33287,7 +33695,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33287
33695
|
state = await this.resolvePendingDecision(state, signal);
|
|
33288
33696
|
let assignment = state.assignment;
|
|
33289
33697
|
const preTurnHeartbeat = await this.options.controlClient.heartbeat({
|
|
33290
|
-
operation_id:
|
|
33698
|
+
operation_id: randomUUID2(),
|
|
33291
33699
|
host_id: this.options.hostId,
|
|
33292
33700
|
assignment_id: assignment.assignment_id,
|
|
33293
33701
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33302,7 +33710,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33302
33710
|
lease_expires_at: preTurnHeartbeat.lease_expires_at
|
|
33303
33711
|
};
|
|
33304
33712
|
state = { ...state, assignment, updated_at: nowIso() };
|
|
33305
|
-
await
|
|
33713
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33306
33714
|
const turnAbort = new AbortController();
|
|
33307
33715
|
const relayAbort = () => turnAbort.abort();
|
|
33308
33716
|
signal?.addEventListener("abort", relayAbort, { once: true });
|
|
@@ -33312,7 +33720,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33312
33720
|
const heartbeatTask = (async () => {
|
|
33313
33721
|
while (!heartbeatStopped && !turnAbort.signal.aborted) {
|
|
33314
33722
|
const heartbeat = await this.options.controlClient.heartbeat({
|
|
33315
|
-
operation_id:
|
|
33723
|
+
operation_id: randomUUID2(),
|
|
33316
33724
|
host_id: this.options.hostId,
|
|
33317
33725
|
assignment_id: assignment.assignment_id,
|
|
33318
33726
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33336,7 +33744,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33336
33744
|
const deadlineAtMs = this.now() + (this.options.turnTimeoutMs ?? 10 * 6e4);
|
|
33337
33745
|
const result2 = await this.options.adapter.runTurn({
|
|
33338
33746
|
durableThread: state.thread,
|
|
33339
|
-
systemPrompt:
|
|
33747
|
+
systemPrompt: INFERENCE_AGENT_SYSTEM_PROMPT,
|
|
33340
33748
|
userPrompt: JSON.stringify({
|
|
33341
33749
|
assignment_id: assignment.assignment_id,
|
|
33342
33750
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33350,7 +33758,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33350
33758
|
maximum: assignment.maximum_wake_seconds
|
|
33351
33759
|
}
|
|
33352
33760
|
}),
|
|
33353
|
-
outputSchema:
|
|
33761
|
+
outputSchema: INFERENCE_AGENT_WAKE_SCHEMA,
|
|
33354
33762
|
dataContract: assignment.data_contract,
|
|
33355
33763
|
decisionSchema: assignment.output_schema,
|
|
33356
33764
|
requestedModel: assignment.model_id,
|
|
@@ -33359,7 +33767,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33359
33767
|
signal: turnAbort.signal,
|
|
33360
33768
|
onThreadReady: async (thread) => {
|
|
33361
33769
|
state = { ...state, thread, updated_at: nowIso() };
|
|
33362
|
-
await
|
|
33770
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33363
33771
|
},
|
|
33364
33772
|
executeTool: async (call) => {
|
|
33365
33773
|
if (call.tool === "vtx_get_data") {
|
|
@@ -33369,7 +33777,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33369
33777
|
return { success: false, value: { error: "invalid_data_request" } };
|
|
33370
33778
|
}
|
|
33371
33779
|
const value = await this.options.controlClient.dataCall({
|
|
33372
|
-
operation_id:
|
|
33780
|
+
operation_id: randomUUID2(),
|
|
33373
33781
|
host_id: this.options.hostId,
|
|
33374
33782
|
assignment_id: assignment.assignment_id,
|
|
33375
33783
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33393,12 +33801,12 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33393
33801
|
return { success: false, value: { error: "decision_outcome_unresolved" } };
|
|
33394
33802
|
}
|
|
33395
33803
|
const pending = {
|
|
33396
|
-
operation_id:
|
|
33804
|
+
operation_id: randomUUID2(),
|
|
33397
33805
|
candidate,
|
|
33398
33806
|
observed_at: nowIso(),
|
|
33399
33807
|
provenance: {
|
|
33400
|
-
source: "
|
|
33401
|
-
|
|
33808
|
+
source: "external_agent",
|
|
33809
|
+
agent_run_id: liveThread.threadId,
|
|
33402
33810
|
requested_model: assignment.model_id,
|
|
33403
33811
|
effective_model: liveThread.effectiveModel,
|
|
33404
33812
|
requested_reasoning_effort: assignment.reasoning_effort,
|
|
@@ -33408,13 +33816,13 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33408
33816
|
last_status_check_at: null
|
|
33409
33817
|
};
|
|
33410
33818
|
state = { ...state, pending_decision: pending, updated_at: nowIso() };
|
|
33411
|
-
await
|
|
33819
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33412
33820
|
state = {
|
|
33413
33821
|
...state,
|
|
33414
33822
|
pending_decision: { ...pending, first_transmit_at: nowIso() },
|
|
33415
33823
|
updated_at: nowIso()
|
|
33416
33824
|
};
|
|
33417
|
-
await
|
|
33825
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33418
33826
|
let submitStatus;
|
|
33419
33827
|
try {
|
|
33420
33828
|
submitStatus = await this.options.controlClient.submitDecision({
|
|
@@ -33431,7 +33839,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33431
33839
|
}
|
|
33432
33840
|
if (submitStatus.status === "applied" || submitStatus.status === "not_applied") {
|
|
33433
33841
|
state = { ...state, pending_decision: null, updated_at: nowIso() };
|
|
33434
|
-
await
|
|
33842
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33435
33843
|
}
|
|
33436
33844
|
return {
|
|
33437
33845
|
success: submitStatus.status === "applied",
|
|
@@ -33455,7 +33863,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33455
33863
|
pending_decision: null,
|
|
33456
33864
|
updated_at: nowIso()
|
|
33457
33865
|
};
|
|
33458
|
-
await
|
|
33866
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33459
33867
|
}
|
|
33460
33868
|
return {
|
|
33461
33869
|
success: status.status === "applied" || status.status === "not_applied",
|
|
@@ -33463,11 +33871,11 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33463
33871
|
};
|
|
33464
33872
|
}
|
|
33465
33873
|
});
|
|
33466
|
-
const wakeSeconds =
|
|
33874
|
+
const wakeSeconds = parseInferenceAgentWake(result2.turn.text, assignment);
|
|
33467
33875
|
const nextWakeAtMs = this.now() + wakeSeconds * 1e3;
|
|
33468
33876
|
const scheduledWakeAt = new Date(nextWakeAtMs).toISOString();
|
|
33469
33877
|
const wakeHeartbeat = await this.options.controlClient.heartbeat({
|
|
33470
|
-
operation_id:
|
|
33878
|
+
operation_id: randomUUID2(),
|
|
33471
33879
|
host_id: this.options.hostId,
|
|
33472
33880
|
assignment_id: assignment.assignment_id,
|
|
33473
33881
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33477,7 +33885,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33477
33885
|
if (wakeHeartbeat.directive === "cancel") {
|
|
33478
33886
|
if (state.pending_decision) return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33479
33887
|
await this.options.adapter.releaseThread(result2.thread).catch(() => void 0);
|
|
33480
|
-
await
|
|
33888
|
+
await clearInferenceAgentRuntimeState(this.options.statePath);
|
|
33481
33889
|
return this.now() + (this.options.idlePollMs ?? 5e3);
|
|
33482
33890
|
}
|
|
33483
33891
|
latestLeaseExpiry = wakeHeartbeat.lease_expires_at;
|
|
@@ -33488,7 +33896,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33488
33896
|
next_wake_at: scheduledWakeAt,
|
|
33489
33897
|
updated_at: nowIso()
|
|
33490
33898
|
};
|
|
33491
|
-
await
|
|
33899
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, state);
|
|
33492
33900
|
return nextWakeAtMs;
|
|
33493
33901
|
} catch (error48) {
|
|
33494
33902
|
if (!cancelled) throw error48;
|
|
@@ -33507,7 +33915,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33507
33915
|
if (state.thread) {
|
|
33508
33916
|
await this.options.adapter.releaseThread(state.thread).catch(() => void 0);
|
|
33509
33917
|
}
|
|
33510
|
-
await
|
|
33918
|
+
await clearInferenceAgentRuntimeState(this.options.statePath);
|
|
33511
33919
|
return null;
|
|
33512
33920
|
}
|
|
33513
33921
|
async resolveLegacyPendingDecision(state, signal) {
|
|
@@ -33519,7 +33927,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33519
33927
|
pending_decision: { ...pending, last_status_check_at: checkedAt },
|
|
33520
33928
|
updated_at: checkedAt
|
|
33521
33929
|
};
|
|
33522
|
-
await
|
|
33930
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, checking);
|
|
33523
33931
|
const status = await this.options.controlClient.decisionStatus({
|
|
33524
33932
|
host_id: this.options.hostId,
|
|
33525
33933
|
assignment_id: state.assignment.assignment_id,
|
|
@@ -33532,7 +33940,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33532
33940
|
pending_decision: null,
|
|
33533
33941
|
updated_at: new Date(this.now()).toISOString()
|
|
33534
33942
|
};
|
|
33535
|
-
await
|
|
33943
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, resolved);
|
|
33536
33944
|
return resolved;
|
|
33537
33945
|
}
|
|
33538
33946
|
async resolvePendingDecision(state, signal) {
|
|
@@ -33544,7 +33952,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33544
33952
|
pending_decision: { ...pending, last_status_check_at: checkedAt },
|
|
33545
33953
|
updated_at: checkedAt
|
|
33546
33954
|
};
|
|
33547
|
-
await
|
|
33955
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, checking);
|
|
33548
33956
|
const status = await this.options.controlClient.decisionStatus({
|
|
33549
33957
|
host_id: this.options.hostId,
|
|
33550
33958
|
assignment_id: state.assignment.assignment_id,
|
|
@@ -33557,7 +33965,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33557
33965
|
pending_decision: null,
|
|
33558
33966
|
updated_at: new Date(this.now()).toISOString()
|
|
33559
33967
|
};
|
|
33560
|
-
await
|
|
33968
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, resolved);
|
|
33561
33969
|
return resolved;
|
|
33562
33970
|
}
|
|
33563
33971
|
async handleCancelledAssignment(state, signal) {
|
|
@@ -33573,7 +33981,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33573
33981
|
if (current.thread) {
|
|
33574
33982
|
await this.options.adapter.releaseThread(current.thread).catch(() => void 0);
|
|
33575
33983
|
}
|
|
33576
|
-
await
|
|
33984
|
+
await clearInferenceAgentRuntimeState(this.options.statePath);
|
|
33577
33985
|
}
|
|
33578
33986
|
async waitUntilWake(nextWakeAtMs, signal) {
|
|
33579
33987
|
const heartbeatIntervalMs = this.options.heartbeatIntervalMs ?? 3e3;
|
|
@@ -33581,11 +33989,11 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33581
33989
|
await this.sleep(Math.min(heartbeatIntervalMs, nextWakeAtMs - this.now()), signal);
|
|
33582
33990
|
if (this.stopped || signal?.aborted) return "stopped";
|
|
33583
33991
|
if (this.now() >= nextWakeAtMs) return "ready";
|
|
33584
|
-
const state = await
|
|
33585
|
-
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";
|
|
33586
33994
|
const requestedAt = new Date(this.now()).toISOString();
|
|
33587
33995
|
const heartbeat = await this.options.controlClient.heartbeat({
|
|
33588
|
-
operation_id:
|
|
33996
|
+
operation_id: randomUUID2(),
|
|
33589
33997
|
host_id: this.options.hostId,
|
|
33590
33998
|
assignment_id: state.assignment.assignment_id,
|
|
33591
33999
|
assignment_generation: state.assignment.assignment_generation,
|
|
@@ -33595,7 +34003,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33595
34003
|
await this.handleCancelledAssignment(state, signal);
|
|
33596
34004
|
return "cancelled";
|
|
33597
34005
|
}
|
|
33598
|
-
await
|
|
34006
|
+
await writeInferenceAgentRuntimeState(this.options.statePath, {
|
|
33599
34007
|
...state,
|
|
33600
34008
|
assignment: {
|
|
33601
34009
|
...state.assignment,
|
|
@@ -33607,8 +34015,24 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33607
34015
|
return this.stopped || signal?.aborted ? "stopped" : "ready";
|
|
33608
34016
|
}
|
|
33609
34017
|
async releaseForHostStop() {
|
|
33610
|
-
|
|
33611
|
-
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
|
+
}
|
|
33612
34036
|
try {
|
|
33613
34037
|
state = state.schema_version === "vtx_codex_agent_runtime_v1" ? await this.resolveLegacyPendingDecision(state) : await this.resolvePendingDecision(state);
|
|
33614
34038
|
} catch {
|
|
@@ -33616,7 +34040,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33616
34040
|
}
|
|
33617
34041
|
if (state.pending_decision) return;
|
|
33618
34042
|
await this.options.controlClient.releaseAssignment({
|
|
33619
|
-
operation_id:
|
|
34043
|
+
operation_id: randomUUID2(),
|
|
33620
34044
|
host_id: this.options.hostId,
|
|
33621
34045
|
assignment_id: state.assignment.assignment_id,
|
|
33622
34046
|
assignment_generation: state.assignment.assignment_generation,
|
|
@@ -33624,7 +34048,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33624
34048
|
requested_at: new Date(this.now()).toISOString()
|
|
33625
34049
|
}, {});
|
|
33626
34050
|
if (state.thread) await this.options.adapter.releaseThread(state.thread);
|
|
33627
|
-
await
|
|
34051
|
+
await clearInferenceAgentRuntimeState(this.options.statePath);
|
|
33628
34052
|
}
|
|
33629
34053
|
};
|
|
33630
34054
|
}
|
|
@@ -33632,7 +34056,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33632
34056
|
|
|
33633
34057
|
// lib/inference-host/service.ts
|
|
33634
34058
|
import { spawn as spawn6 } from "node:child_process";
|
|
33635
|
-
import { randomUUID as
|
|
34059
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
33636
34060
|
import { createWriteStream, readFileSync } from "node:fs";
|
|
33637
34061
|
import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as rm5, writeFile as writeFile2 } from "node:fs/promises";
|
|
33638
34062
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -34157,7 +34581,7 @@ WantedBy=default.target
|
|
|
34157
34581
|
const previousRuntimeUpdatedAt = previousRuntime?.manifest_generation === manifest.generation ? Date.parse(previousRuntime.updated_at) : Number.NaN;
|
|
34158
34582
|
const restoredManifest = preserveGeneration ? manifest : assertManifest({
|
|
34159
34583
|
...manifest,
|
|
34160
|
-
generation:
|
|
34584
|
+
generation: randomUUID3(),
|
|
34161
34585
|
installed_at: this.now().toISOString()
|
|
34162
34586
|
});
|
|
34163
34587
|
await writeAtomicInferencePrivateFile(
|
|
@@ -34443,7 +34867,7 @@ ${cleanup.stderr}`)) {
|
|
|
34443
34867
|
].sort((left, right) => left.instance_name.localeCompare(right.instance_name));
|
|
34444
34868
|
const manifest = assertManifest({
|
|
34445
34869
|
schema_version: "vtx_inference_service_v3",
|
|
34446
|
-
generation:
|
|
34870
|
+
generation: randomUUID3(),
|
|
34447
34871
|
installed_at: this.now().toISOString(),
|
|
34448
34872
|
executable: this.executable,
|
|
34449
34873
|
script: this.script,
|
|
@@ -34657,7 +35081,7 @@ ${result2.stderr}`)) {
|
|
|
34657
35081
|
if (remaining.length === 0) return await this.uninstallUnlocked();
|
|
34658
35082
|
return await this.replaceManifestUnlocked({
|
|
34659
35083
|
...manifest,
|
|
34660
|
-
generation:
|
|
35084
|
+
generation: randomUUID3(),
|
|
34661
35085
|
installed_at: this.now().toISOString(),
|
|
34662
35086
|
workers: remaining
|
|
34663
35087
|
}, await readInferenceHostServiceDesired(this.desiredPath()));
|
|
@@ -35047,7 +35471,7 @@ __export(cli_exports, {
|
|
|
35047
35471
|
registerInferenceHostServiceControlInput: () => registerInferenceHostServiceControlInput,
|
|
35048
35472
|
runInferenceHostCli: () => runInferenceHostCli
|
|
35049
35473
|
});
|
|
35050
|
-
import { createHash as createHash7, randomUUID as
|
|
35474
|
+
import { createHash as createHash7, randomUUID as randomUUID4 } from "node:crypto";
|
|
35051
35475
|
import { spawn as spawn7 } from "node:child_process";
|
|
35052
35476
|
import { lstat as lstat4, realpath as realpath4, rm as rm6 } from "node:fs/promises";
|
|
35053
35477
|
import { hostname as osHostname } from "node:os";
|
|
@@ -35111,6 +35535,42 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35111
35535
|
async () => await agentFail(config2, parsed, dependencies, warnings)
|
|
35112
35536
|
);
|
|
35113
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
|
+
}
|
|
35114
35574
|
if (parsed.command === "service") {
|
|
35115
35575
|
const mutationActions = /* @__PURE__ */ new Set(["install", "start", "stop", "recover", "uninstall"]);
|
|
35116
35576
|
if (!parsed.serviceAction || !mutationActions.has(parsed.serviceAction)) {
|
|
@@ -35141,7 +35601,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35141
35601
|
return await cleanupLogin(config2, parsed, dependencies, warnings, true);
|
|
35142
35602
|
}
|
|
35143
35603
|
throw new Error(
|
|
35144
|
-
"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]"
|
|
35145
35605
|
);
|
|
35146
35606
|
} catch (error48) {
|
|
35147
35607
|
return {
|
|
@@ -35152,7 +35612,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35152
35612
|
};
|
|
35153
35613
|
}
|
|
35154
35614
|
}
|
|
35155
|
-
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;
|
|
35156
35616
|
var init_cli = __esm({
|
|
35157
35617
|
"lib/inference-host/cli.ts"() {
|
|
35158
35618
|
"use strict";
|
|
@@ -35252,6 +35712,12 @@ Commands:
|
|
|
35252
35712
|
agent-next Claim the next exact VTX inference request
|
|
35253
35713
|
agent-complete Submit one completed agent result from stdin
|
|
35254
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
|
|
35255
35721
|
service Install and control the durable background host
|
|
35256
35722
|
status Inspect local host and credential state
|
|
35257
35723
|
doctor Verify credentials, provider runtime, and private state
|
|
@@ -35566,6 +36032,7 @@ Durable service:
|
|
|
35566
36032
|
);
|
|
35567
36033
|
await clearInferenceAgentAttemptState(config2.statePath);
|
|
35568
36034
|
await clearInferenceAgentNextState(config2.statePath);
|
|
36035
|
+
await clearInferenceForegroundAgentControlState(config2.statePath);
|
|
35569
36036
|
await clearCodexAgentRuntimeState(config2.statePath);
|
|
35570
36037
|
await clearInferenceHostLocalState(config2.statePath);
|
|
35571
36038
|
};
|
|
@@ -35593,10 +36060,11 @@ Durable service:
|
|
|
35593
36060
|
const revocationCheckpointPresent = await readRevocationCheckpoint(config2) !== null;
|
|
35594
36061
|
const agentAttemptPresent = await readInferenceAgentAttemptState(config2.statePath) !== null;
|
|
35595
36062
|
const agentNextRecoveryPresent = await readInferenceAgentNextState(config2.statePath) !== null;
|
|
36063
|
+
const foregroundAgentControlPresent = await readInferenceForegroundAgentControlState(config2.statePath) !== null;
|
|
35596
36064
|
const codexAgentRuntimePresent = await readCodexAgentRuntimeState(config2.statePath) !== null;
|
|
35597
|
-
if (pendingAttempts > 0 || codexRecoveryPresent || serviceRecoveryPresent || revocationCheckpointPresent || agentAttemptPresent || agentNextRecoveryPresent || codexAgentRuntimePresent) {
|
|
36065
|
+
if (pendingAttempts > 0 || codexRecoveryPresent || serviceRecoveryPresent || revocationCheckpointPresent || agentAttemptPresent || agentNextRecoveryPresent || foregroundAgentControlPresent || codexAgentRuntimePresent) {
|
|
35598
36066
|
throw new Error(
|
|
35599
|
-
"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."
|
|
35600
36068
|
);
|
|
35601
36069
|
}
|
|
35602
36070
|
};
|
|
@@ -35669,6 +36137,12 @@ Durable service:
|
|
|
35669
36137
|
return { adapter, preflight: await adapter.preflight(signal) };
|
|
35670
36138
|
};
|
|
35671
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
|
+
}
|
|
35672
36146
|
const dependencies = createDefaultInferenceHostRunnerDependencies({
|
|
35673
36147
|
apiUrl: options.config.apiUrl,
|
|
35674
36148
|
statePath: options.config.statePath,
|
|
@@ -35704,6 +36178,10 @@ Durable service:
|
|
|
35704
36178
|
maxConcurrency: options.maxConcurrency,
|
|
35705
36179
|
once: options.once,
|
|
35706
36180
|
emitDiagnosticEvent: options.emitDiagnosticEvent,
|
|
36181
|
+
agentRuntime: {
|
|
36182
|
+
statePath: options.config.statePath,
|
|
36183
|
+
adapter: agentAdapter
|
|
36184
|
+
},
|
|
35707
36185
|
signal: options.signal
|
|
35708
36186
|
}).run();
|
|
35709
36187
|
};
|
|
@@ -35737,7 +36215,7 @@ Durable service:
|
|
|
35737
36215
|
await writeInferenceHostCredentialContextTransition(config2, previousCredentialContext);
|
|
35738
36216
|
await writeInferenceHostCredentialContext(config2);
|
|
35739
36217
|
const keyPair = generateExternalInferenceEnvelopeKeyPair();
|
|
35740
|
-
const hostId =
|
|
36218
|
+
const hostId = randomUUID4();
|
|
35741
36219
|
const beginLogin = dependencies.beginLogin ?? beginInferenceOAuthLogin;
|
|
35742
36220
|
const loginStore = {
|
|
35743
36221
|
kind: store.kind,
|
|
@@ -36417,7 +36895,27 @@ Waiting for approval...
|
|
|
36417
36895
|
}
|
|
36418
36896
|
return record2;
|
|
36419
36897
|
};
|
|
36420
|
-
|
|
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()}`;
|
|
36421
36919
|
agentSession = async (config2, dependencies, warnings, signal) => {
|
|
36422
36920
|
if (await readRevocationCheckpoint(config2)) {
|
|
36423
36921
|
throw new Error("Inference host revocation recovery must finish first.");
|
|
@@ -36461,11 +36959,419 @@ Waiting for approval...
|
|
|
36461
36959
|
reasoning_effort: result2.reasoning_effort,
|
|
36462
36960
|
lanes: ["main", "review", "screener"],
|
|
36463
36961
|
response_modes: ["provider_response", "decision_candidate"],
|
|
36962
|
+
control_modes: ["provider", "agent"],
|
|
36464
36963
|
execution_modes: ["client", "server"],
|
|
36465
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",
|
|
36466
36966
|
keeper_command: "vtx inference-host agent-run"
|
|
36467
36967
|
}, parsed.json),
|
|
36468
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")}
|
|
36469
37375
|
` : ""
|
|
36470
37376
|
};
|
|
36471
37377
|
};
|
|
@@ -36473,6 +37379,7 @@ Waiting for approval...
|
|
|
36473
37379
|
const cancellation = lifecycleCancellation(dependencies);
|
|
36474
37380
|
let keeperLock = null;
|
|
36475
37381
|
let heartbeatCount = 0;
|
|
37382
|
+
let assignmentHeartbeatCount = 0;
|
|
36476
37383
|
try {
|
|
36477
37384
|
keeperLock = await acquireInferenceHostProcessLock(foregroundHostLockPath(config2));
|
|
36478
37385
|
const store = configuredCredentialStore(config2, dependencies, (message) => {
|
|
@@ -36506,6 +37413,7 @@ Waiting for approval...
|
|
|
36506
37413
|
}
|
|
36507
37414
|
if (commandLock) {
|
|
36508
37415
|
let heartbeatSuppressed = false;
|
|
37416
|
+
let assignmentHeartbeatComplete = true;
|
|
36509
37417
|
try {
|
|
36510
37418
|
const active = await readInferenceAgentAttemptState(config2.statePath);
|
|
36511
37419
|
const pendingNext = await readInferenceAgentNextState(config2.statePath);
|
|
@@ -36565,10 +37473,65 @@ Waiting for approval...
|
|
|
36565
37473
|
}
|
|
36566
37474
|
}
|
|
36567
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
|
+
}
|
|
36568
37531
|
} finally {
|
|
36569
37532
|
await commandLock.release();
|
|
36570
37533
|
}
|
|
36571
|
-
if (parsed.once && (heartbeatCount > 0 || heartbeatSuppressed)) break;
|
|
37534
|
+
if (parsed.once && (heartbeatCount > 0 || heartbeatSuppressed) && assignmentHeartbeatComplete) break;
|
|
36572
37535
|
}
|
|
36573
37536
|
if (parsed.once && !commandLock) break;
|
|
36574
37537
|
await (dependencies.sleep ?? (async (milliseconds) => {
|
|
@@ -36577,7 +37540,11 @@ Waiting for approval...
|
|
|
36577
37540
|
}
|
|
36578
37541
|
return {
|
|
36579
37542
|
exitCode: 0,
|
|
36580
|
-
stdout: render({
|
|
37543
|
+
stdout: render({
|
|
37544
|
+
status: "stopped",
|
|
37545
|
+
heartbeats: heartbeatCount,
|
|
37546
|
+
assignment_heartbeats: assignmentHeartbeatCount
|
|
37547
|
+
}, parsed.json),
|
|
36581
37548
|
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
36582
37549
|
` : ""
|
|
36583
37550
|
};
|
|
@@ -36965,7 +37932,7 @@ Waiting for approval...
|
|
|
36965
37932
|
if (recoveryRaw === null && existingTransaction?.phase !== "reconciled") {
|
|
36966
37933
|
throw new Error("Codex recovery evidence changed before service recovery began.");
|
|
36967
37934
|
}
|
|
36968
|
-
const transactionId = existingTransaction?.transaction_id ??
|
|
37935
|
+
const transactionId = existingTransaction?.transaction_id ?? randomUUID4();
|
|
36969
37936
|
const backupPath = existingTransaction?.recovery_backup_path ?? recoveryBackupPath(config2, transactionId);
|
|
36970
37937
|
if (!existingTransaction) {
|
|
36971
37938
|
await writeAtomicInferencePrivateFile(backupPath, recoveryRaw);
|
|
@@ -37486,7 +38453,7 @@ var init_types = __esm({
|
|
|
37486
38453
|
});
|
|
37487
38454
|
|
|
37488
38455
|
// lib/agent-core/client.ts
|
|
37489
|
-
import { randomUUID as
|
|
38456
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
37490
38457
|
function normalizeApiUrl(value) {
|
|
37491
38458
|
const parsed = String(value || "").trim();
|
|
37492
38459
|
if (!parsed) {
|
|
@@ -37748,7 +38715,7 @@ var init_client = __esm({
|
|
|
37748
38715
|
return this.request("/trading/ai/runtime/decision", {
|
|
37749
38716
|
method: "POST",
|
|
37750
38717
|
profileId,
|
|
37751
|
-
idempotencyKey:
|
|
38718
|
+
idempotencyKey: randomUUID5(),
|
|
37752
38719
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
37753
38720
|
body: payload
|
|
37754
38721
|
});
|
|
@@ -37757,7 +38724,7 @@ var init_client = __esm({
|
|
|
37757
38724
|
return this.request("/trading/ai/runtime/trade-sync", {
|
|
37758
38725
|
method: "POST",
|
|
37759
38726
|
profileId,
|
|
37760
|
-
idempotencyKey:
|
|
38727
|
+
idempotencyKey: randomUUID5(),
|
|
37761
38728
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
37762
38729
|
body: payload
|
|
37763
38730
|
});
|
|
@@ -37766,7 +38733,7 @@ var init_client = __esm({
|
|
|
37766
38733
|
return this.request("/trading/ai/runtime/error", {
|
|
37767
38734
|
method: "POST",
|
|
37768
38735
|
profileId,
|
|
37769
|
-
idempotencyKey:
|
|
38736
|
+
idempotencyKey: randomUUID5(),
|
|
37770
38737
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
37771
38738
|
body: payload
|
|
37772
38739
|
});
|
|
@@ -37778,7 +38745,7 @@ var init_client = __esm({
|
|
|
37778
38745
|
return this.request("/trading/market-order", {
|
|
37779
38746
|
method: "POST",
|
|
37780
38747
|
profileId,
|
|
37781
|
-
idempotencyKey:
|
|
38748
|
+
idempotencyKey: randomUUID5(),
|
|
37782
38749
|
body: payload
|
|
37783
38750
|
});
|
|
37784
38751
|
}
|
|
@@ -37786,7 +38753,7 @@ var init_client = __esm({
|
|
|
37786
38753
|
return this.request("/trading/limit-order", {
|
|
37787
38754
|
method: "POST",
|
|
37788
38755
|
profileId,
|
|
37789
|
-
idempotencyKey:
|
|
38756
|
+
idempotencyKey: randomUUID5(),
|
|
37790
38757
|
body: payload
|
|
37791
38758
|
});
|
|
37792
38759
|
}
|
|
@@ -37794,7 +38761,7 @@ var init_client = __esm({
|
|
|
37794
38761
|
return this.request("/trading/cancel-order", {
|
|
37795
38762
|
method: "POST",
|
|
37796
38763
|
profileId,
|
|
37797
|
-
idempotencyKey:
|
|
38764
|
+
idempotencyKey: randomUUID5(),
|
|
37798
38765
|
body: payload
|
|
37799
38766
|
});
|
|
37800
38767
|
}
|
|
@@ -37813,7 +38780,7 @@ var init_client = __esm({
|
|
|
37813
38780
|
return this.request("/trading/ai/start", {
|
|
37814
38781
|
method: "POST",
|
|
37815
38782
|
profileId,
|
|
37816
|
-
idempotencyKey:
|
|
38783
|
+
idempotencyKey: randomUUID5(),
|
|
37817
38784
|
body: payload
|
|
37818
38785
|
});
|
|
37819
38786
|
}
|
|
@@ -37821,7 +38788,7 @@ var init_client = __esm({
|
|
|
37821
38788
|
return this.request("/trading/ai/stop", {
|
|
37822
38789
|
method: "POST",
|
|
37823
38790
|
profileId,
|
|
37824
|
-
idempotencyKey:
|
|
38791
|
+
idempotencyKey: randomUUID5(),
|
|
37825
38792
|
body: {}
|
|
37826
38793
|
});
|
|
37827
38794
|
}
|
|
@@ -37829,7 +38796,7 @@ var init_client = __esm({
|
|
|
37829
38796
|
return this.request("/trading/ai/assistant/start", {
|
|
37830
38797
|
method: "POST",
|
|
37831
38798
|
profileId,
|
|
37832
|
-
idempotencyKey:
|
|
38799
|
+
idempotencyKey: randomUUID5(),
|
|
37833
38800
|
body: {}
|
|
37834
38801
|
});
|
|
37835
38802
|
}
|
|
@@ -37837,7 +38804,7 @@ var init_client = __esm({
|
|
|
37837
38804
|
return this.request("/trading/ai/assistant/stop", {
|
|
37838
38805
|
method: "POST",
|
|
37839
38806
|
profileId,
|
|
37840
|
-
idempotencyKey:
|
|
38807
|
+
idempotencyKey: randomUUID5(),
|
|
37841
38808
|
body: {}
|
|
37842
38809
|
});
|
|
37843
38810
|
}
|
|
@@ -37845,7 +38812,7 @@ var init_client = __esm({
|
|
|
37845
38812
|
return this.request("/trading/ai/runtime/session/start", {
|
|
37846
38813
|
method: "POST",
|
|
37847
38814
|
profileId,
|
|
37848
|
-
idempotencyKey:
|
|
38815
|
+
idempotencyKey: randomUUID5(),
|
|
37849
38816
|
body: payload
|
|
37850
38817
|
});
|
|
37851
38818
|
}
|
|
@@ -37856,7 +38823,7 @@ var init_client = __esm({
|
|
|
37856
38823
|
return this.request("/trading/ai/runtime/session/stop", {
|
|
37857
38824
|
method: "POST",
|
|
37858
38825
|
profileId,
|
|
37859
|
-
idempotencyKey:
|
|
38826
|
+
idempotencyKey: randomUUID5(),
|
|
37860
38827
|
body: payload
|
|
37861
38828
|
});
|
|
37862
38829
|
}
|
|
@@ -37873,7 +38840,7 @@ var init_client = __esm({
|
|
|
37873
38840
|
}).request("/trading/ai/runtime/session/stop", {
|
|
37874
38841
|
method: "POST",
|
|
37875
38842
|
profileId,
|
|
37876
|
-
idempotencyKey:
|
|
38843
|
+
idempotencyKey: randomUUID5(),
|
|
37877
38844
|
body: payload
|
|
37878
38845
|
});
|
|
37879
38846
|
}
|
|
@@ -37890,7 +38857,7 @@ import {
|
|
|
37890
38857
|
unlinkSync,
|
|
37891
38858
|
writeFileSync
|
|
37892
38859
|
} from "node:fs";
|
|
37893
|
-
import { randomUUID as
|
|
38860
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
37894
38861
|
import { dirname as dirname6 } from "node:path";
|
|
37895
38862
|
var parseStoredValues, FileBackedProtectionStorage, clientRuntimeProtectionStatePath;
|
|
37896
38863
|
var init_protection_storage = __esm({
|
|
@@ -37947,7 +38914,7 @@ var init_protection_storage = __esm({
|
|
|
37947
38914
|
mkdirSync(dirname6(this.path), { recursive: true, mode: 448 });
|
|
37948
38915
|
const serialized = `${JSON.stringify(values)}
|
|
37949
38916
|
`;
|
|
37950
|
-
const temporaryPath = `${this.path}.${process.pid}.${
|
|
38917
|
+
const temporaryPath = `${this.path}.${process.pid}.${randomUUID6()}.tmp`;
|
|
37951
38918
|
try {
|
|
37952
38919
|
writeFileSync(temporaryPath, serialized, {
|
|
37953
38920
|
encoding: "utf8",
|
|
@@ -37974,7 +38941,7 @@ var init_protection_storage = __esm({
|
|
|
37974
38941
|
});
|
|
37975
38942
|
|
|
37976
38943
|
// lib/agent-core/headless-runtime.ts
|
|
37977
|
-
import { randomUUID as
|
|
38944
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
37978
38945
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
37979
38946
|
function objectOrNull2(value) {
|
|
37980
38947
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -38072,8 +39039,8 @@ async function runAndReportLocalWorkCycle(options, state, leaseToken, context) {
|
|
|
38072
39039
|
return Boolean(result2.decision || tradeSync || result2.afterDecision);
|
|
38073
39040
|
}
|
|
38074
39041
|
async function startHeadlessRuntime(options) {
|
|
38075
|
-
const runtimeSessionId =
|
|
38076
|
-
const deviceId = String(options.deviceId || "").trim() ||
|
|
39042
|
+
const runtimeSessionId = randomUUID7();
|
|
39043
|
+
const deviceId = String(options.deviceId || "").trim() || randomUUID7();
|
|
38077
39044
|
const startResponse = await options.client.startRuntime(options.profileId, {
|
|
38078
39045
|
session_id: runtimeSessionId,
|
|
38079
39046
|
device_id: deviceId,
|
|
@@ -60625,7 +61592,7 @@ var headless_local_worker_exports = {};
|
|
|
60625
61592
|
__export(headless_local_worker_exports, {
|
|
60626
61593
|
createHeadlessLocalWorker: () => createHeadlessLocalWorker
|
|
60627
61594
|
});
|
|
60628
|
-
import { randomUUID as
|
|
61595
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
60629
61596
|
function objectOrNull3(value) {
|
|
60630
61597
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
60631
61598
|
}
|
|
@@ -61042,7 +62009,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
61042
62009
|
const statusMatch = errorText.match(/\b([45]\d{2})\b/);
|
|
61043
62010
|
const statusCode = statusMatch ? Number(statusMatch[1]) : null;
|
|
61044
62011
|
const failedInvocation = normalizeAiInvocationTelemetry({
|
|
61045
|
-
client_invocation_id:
|
|
62012
|
+
client_invocation_id: randomUUID8(),
|
|
61046
62013
|
use_case: "trader",
|
|
61047
62014
|
role: "primary",
|
|
61048
62015
|
attempt_index: 0,
|
|
@@ -61098,7 +62065,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
61098
62065
|
billable_cached_input_tokens: normalizedUsage.cached_input_tokens
|
|
61099
62066
|
};
|
|
61100
62067
|
const invocation = normalizeAiInvocationTelemetry({
|
|
61101
|
-
client_invocation_id:
|
|
62068
|
+
client_invocation_id: randomUUID8(),
|
|
61102
62069
|
use_case: "trader",
|
|
61103
62070
|
role: "primary",
|
|
61104
62071
|
attempt_index: 0,
|
|
@@ -61317,7 +62284,7 @@ var vtx_exports = {};
|
|
|
61317
62284
|
__export(vtx_exports, {
|
|
61318
62285
|
runVtxCli: () => runVtxCli
|
|
61319
62286
|
});
|
|
61320
|
-
import { randomUUID as
|
|
62287
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
61321
62288
|
import { spawn as spawn8 } from "node:child_process";
|
|
61322
62289
|
function render2(value, json2) {
|
|
61323
62290
|
if (json2) {
|
|
@@ -61731,8 +62698,8 @@ async function runVtxCli(argv2, env = process.env) {
|
|
|
61731
62698
|
});
|
|
61732
62699
|
return { exitCode: 0, stdout: render2(redactCliOutput(response2), json2), stderr: "" };
|
|
61733
62700
|
}
|
|
61734
|
-
const runtimeSessionId =
|
|
61735
|
-
const deviceId = config2.runtimeDeviceId ??
|
|
62701
|
+
const runtimeSessionId = randomUUID9();
|
|
62702
|
+
const deviceId = config2.runtimeDeviceId ?? randomUUID9();
|
|
61736
62703
|
const response = await client.startRuntime(profileId, {
|
|
61737
62704
|
session_id: runtimeSessionId,
|
|
61738
62705
|
device_id: deviceId,
|