@vtxmacro/cli 2026.8.53 → 2026.8.54
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 +44 -16
- package/bin/vtx.js +1395 -125
- package/package.json +52 -4
package/bin/vtx.js
CHANGED
|
@@ -47,13 +47,67 @@ 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.54",
|
|
51
51
|
codex_package_name: "@openai/codex",
|
|
52
52
|
codex_version: "0.147.0",
|
|
53
53
|
copilot_sdk_package_name: "@github/copilot-sdk",
|
|
54
54
|
copilot_sdk_version: "1.0.0-beta.8",
|
|
55
55
|
copilot_cli_package_name: "@github/copilot",
|
|
56
56
|
copilot_cli_version: "1.0.80",
|
|
57
|
+
deepseek_harness_version: "0.1.1-rc.2",
|
|
58
|
+
deepseek_harness_packages: [
|
|
59
|
+
"@deepseek-ai/dsh-agent",
|
|
60
|
+
"@deepseek-ai/dsh-agent-instructions",
|
|
61
|
+
"@deepseek-ai/dsh-agent-loop",
|
|
62
|
+
"@deepseek-ai/dsh-agent-spine-demo",
|
|
63
|
+
"@deepseek-ai/dsh-anonymous-user-id",
|
|
64
|
+
"@deepseek-ai/dsh-atomic-write",
|
|
65
|
+
"@deepseek-ai/dsh-attachment",
|
|
66
|
+
"@deepseek-ai/dsh-brand",
|
|
67
|
+
"@deepseek-ai/dsh-code-runtime",
|
|
68
|
+
"@deepseek-ai/dsh-credentials",
|
|
69
|
+
"@deepseek-ai/dsh-fs",
|
|
70
|
+
"@deepseek-ai/dsh-goal",
|
|
71
|
+
"@deepseek-ai/dsh-goal-round-driver",
|
|
72
|
+
"@deepseek-ai/dsh-home-paths",
|
|
73
|
+
"@deepseek-ai/dsh-invariants",
|
|
74
|
+
"@deepseek-ai/dsh-jobs",
|
|
75
|
+
"@deepseek-ai/dsh-jobs-local",
|
|
76
|
+
"@deepseek-ai/dsh-launch-environment",
|
|
77
|
+
"@deepseek-ai/dsh-llm",
|
|
78
|
+
"@deepseek-ai/dsh-llm-deepseek",
|
|
79
|
+
"@deepseek-ai/dsh-llm-retry",
|
|
80
|
+
"@deepseek-ai/dsh-output-retention",
|
|
81
|
+
"@deepseek-ai/dsh-sandbox",
|
|
82
|
+
"@deepseek-ai/dsh-sandbox-policy",
|
|
83
|
+
"@deepseek-ai/dsh-scope",
|
|
84
|
+
"@deepseek-ai/dsh-session",
|
|
85
|
+
"@deepseek-ai/dsh-session-checkpoint-policy",
|
|
86
|
+
"@deepseek-ai/dsh-session-persistence",
|
|
87
|
+
"@deepseek-ai/dsh-session-persistence-jsonl",
|
|
88
|
+
"@deepseek-ai/dsh-session-projection",
|
|
89
|
+
"@deepseek-ai/dsh-session-title",
|
|
90
|
+
"@deepseek-ai/dsh-settings",
|
|
91
|
+
"@deepseek-ai/dsh-shell",
|
|
92
|
+
"@deepseek-ai/dsh-shell-env",
|
|
93
|
+
"@deepseek-ai/dsh-skill",
|
|
94
|
+
"@deepseek-ai/dsh-skill-filesystem",
|
|
95
|
+
"@deepseek-ai/dsh-subprocess",
|
|
96
|
+
"@deepseek-ai/dsh-system-prompt",
|
|
97
|
+
"@deepseek-ai/dsh-timeout",
|
|
98
|
+
"@deepseek-ai/dsh-tool-bash",
|
|
99
|
+
"@deepseek-ai/dsh-tool-goal",
|
|
100
|
+
"@deepseek-ai/dsh-tool-jobs",
|
|
101
|
+
"@deepseek-ai/dsh-tool-skill",
|
|
102
|
+
"@deepseek-ai/dsh-tools",
|
|
103
|
+
"@deepseek-ai/dsh-typert-protocol",
|
|
104
|
+
"@deepseek-ai/dsh-user-approval"
|
|
105
|
+
],
|
|
106
|
+
deepseek_cordis_package_name: "@deepseek-ai/cordis",
|
|
107
|
+
deepseek_cordis_version: "4.0.1",
|
|
108
|
+
deepseek_support_packages: {
|
|
109
|
+
"@deepseek-ai/cordis-plugin-timer": "1.1.3"
|
|
110
|
+
},
|
|
57
111
|
platforms: {
|
|
58
112
|
"linux-x64": {
|
|
59
113
|
package_name: "@openai/codex-linux-x64",
|
|
@@ -19695,6 +19749,34 @@ var init_agent_client = __esm({
|
|
|
19695
19749
|
});
|
|
19696
19750
|
|
|
19697
19751
|
// lib/inference-host/agent-state.ts
|
|
19752
|
+
async function readInferenceAgentFailureFence(statePath) {
|
|
19753
|
+
const raw = await readInferencePrivateFile(
|
|
19754
|
+
inferenceAgentFailureFencePath(statePath),
|
|
19755
|
+
"Inference Agent failure fence"
|
|
19756
|
+
);
|
|
19757
|
+
if (raw === null) return null;
|
|
19758
|
+
try {
|
|
19759
|
+
return assertInferenceAgentFailureFence(JSON.parse(raw));
|
|
19760
|
+
} catch (error48) {
|
|
19761
|
+
if (error48 instanceof SyntaxError) {
|
|
19762
|
+
throw new Error("Inference Agent failure fence is not valid JSON.");
|
|
19763
|
+
}
|
|
19764
|
+
throw error48;
|
|
19765
|
+
}
|
|
19766
|
+
}
|
|
19767
|
+
async function writeInferenceAgentFailureFence(statePath, value) {
|
|
19768
|
+
await writeAtomicInferencePrivateFile(
|
|
19769
|
+
inferenceAgentFailureFencePath(statePath),
|
|
19770
|
+
`${JSON.stringify(assertInferenceAgentFailureFence(value), null, 2)}
|
|
19771
|
+
`
|
|
19772
|
+
);
|
|
19773
|
+
}
|
|
19774
|
+
async function clearInferenceAgentFailureFence(statePath) {
|
|
19775
|
+
await clearInferencePrivateFile(
|
|
19776
|
+
inferenceAgentFailureFencePath(statePath),
|
|
19777
|
+
"Inference Agent failure fence"
|
|
19778
|
+
);
|
|
19779
|
+
}
|
|
19698
19780
|
async function readInferenceAgentRuntimeState(statePath) {
|
|
19699
19781
|
const raw = await readInferencePrivateFile(
|
|
19700
19782
|
inferenceAgentRuntimeStatePath(statePath),
|
|
@@ -19807,7 +19889,7 @@ async function clearInferenceAgentNextState(statePath) {
|
|
|
19807
19889
|
"Agent-driven inference next recovery state"
|
|
19808
19890
|
);
|
|
19809
19891
|
}
|
|
19810
|
-
var inferenceAgentAttemptStatePath, inferenceAgentNextStatePath, inferenceAgentRuntimeStatePath, isIsoTimestamp, assertPlainObject, hasExactKeys, assertInferenceAgentRuntimeState, readCodexAgentRuntimeState, clearCodexAgentRuntimeState, foregroundAgentControlStatePath, assertRuntimeAssignment, assertForegroundAgentControlState, assertNextState, assertAttemptState;
|
|
19892
|
+
var inferenceAgentAttemptStatePath, inferenceAgentNextStatePath, inferenceAgentRuntimeStatePath, inferenceAgentFailureFencePath, isIsoTimestamp, assertPlainObject, hasExactKeys, assertInferenceAgentFailureFence, assertInferenceAgentRuntimeState, readCodexAgentRuntimeState, clearCodexAgentRuntimeState, foregroundAgentControlStatePath, assertRuntimeAssignment, assertForegroundAgentControlState, assertNextState, assertAttemptState;
|
|
19811
19893
|
var init_agent_state = __esm({
|
|
19812
19894
|
"lib/inference-host/agent-state.ts"() {
|
|
19813
19895
|
"use strict";
|
|
@@ -19816,12 +19898,31 @@ var init_agent_state = __esm({
|
|
|
19816
19898
|
inferenceAgentAttemptStatePath = (statePath) => `${statePath}.agent-attempt.json`;
|
|
19817
19899
|
inferenceAgentNextStatePath = (statePath) => `${statePath}.agent-next.json`;
|
|
19818
19900
|
inferenceAgentRuntimeStatePath = (statePath) => `${statePath}.codex-agent-runtime.json`;
|
|
19901
|
+
inferenceAgentFailureFencePath = (statePath) => `${statePath}.agent-failure-fence.json`;
|
|
19819
19902
|
isIsoTimestamp = (value) => typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
19820
19903
|
assertPlainObject = (value, message) => {
|
|
19821
19904
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(message);
|
|
19822
19905
|
return value;
|
|
19823
19906
|
};
|
|
19824
19907
|
hasExactKeys = (record2, keys) => Object.keys(record2).sort().join("\0") === [...keys].sort().join("\0");
|
|
19908
|
+
assertInferenceAgentFailureFence = (value) => {
|
|
19909
|
+
const message = "Inference Agent failure fence is invalid.";
|
|
19910
|
+
const fence = assertPlainObject(value, message);
|
|
19911
|
+
if (!hasExactKeys(fence, [
|
|
19912
|
+
"schema_version",
|
|
19913
|
+
"adapter_id",
|
|
19914
|
+
"host_id",
|
|
19915
|
+
"assignment_id",
|
|
19916
|
+
"failure_category",
|
|
19917
|
+
"failure_code",
|
|
19918
|
+
"dispatch_outcome",
|
|
19919
|
+
"retry_at",
|
|
19920
|
+
"created_at"
|
|
19921
|
+
]) || fence.schema_version !== "vtx_inference_agent_failure_fence_v1" || typeof fence.adapter_id !== "string" || !/^[a-z0-9][a-z0-9._-]{0,63}$/u.test(fence.adapter_id) || typeof fence.host_id !== "string" || !fence.host_id || fence.assignment_id !== null && (typeof fence.assignment_id !== "string" || !fence.assignment_id) || typeof fence.failure_category !== "string" || !/^[a-z0-9][a-z0-9._-]{0,159}$/u.test(fence.failure_category) || typeof fence.failure_code !== "string" || !/^[a-z0-9][a-z0-9._-]{0,159}$/u.test(fence.failure_code) || !["not_dispatched", "confirmed_dispatched", "outcome_unknown"].includes(
|
|
19922
|
+
String(fence.dispatch_outcome)
|
|
19923
|
+
) || fence.retry_at !== null && !isIsoTimestamp(fence.retry_at) || !isIsoTimestamp(fence.created_at)) throw new Error(message);
|
|
19924
|
+
return fence;
|
|
19925
|
+
};
|
|
19825
19926
|
assertInferenceAgentRuntimeState = (value) => {
|
|
19826
19927
|
const message = "Inference Agent runtime recovery state is invalid.";
|
|
19827
19928
|
const state = assertPlainObject(value, message);
|
|
@@ -24722,6 +24823,995 @@ ${JSON.stringify(input.outputSchema)}`
|
|
|
24722
24823
|
}
|
|
24723
24824
|
});
|
|
24724
24825
|
|
|
24826
|
+
// lib/inference-host/deepseek-transport-proxy.ts
|
|
24827
|
+
import { createServer as createServer2 } from "node:http";
|
|
24828
|
+
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
24829
|
+
var MAX_REQUEST_BYTES, DeepSeekTransportProxy;
|
|
24830
|
+
var init_deepseek_transport_proxy = __esm({
|
|
24831
|
+
"lib/inference-host/deepseek-transport-proxy.ts"() {
|
|
24832
|
+
"use strict";
|
|
24833
|
+
MAX_REQUEST_BYTES = 8 * 1024 * 1024;
|
|
24834
|
+
DeepSeekTransportProxy = class {
|
|
24835
|
+
constructor(apiKey, expectedModel, expectedEffort, upstreamBaseUrl = "https://api.deepseek.com", fetchImpl = fetch) {
|
|
24836
|
+
this.apiKey = apiKey;
|
|
24837
|
+
this.expectedModel = expectedModel;
|
|
24838
|
+
this.expectedEffort = expectedEffort;
|
|
24839
|
+
this.upstreamBaseUrl = upstreamBaseUrl;
|
|
24840
|
+
this.fetchImpl = fetchImpl;
|
|
24841
|
+
this.server = null;
|
|
24842
|
+
this.urlValue = null;
|
|
24843
|
+
this.receiptsValue = [];
|
|
24844
|
+
this.controllers = /* @__PURE__ */ new Set();
|
|
24845
|
+
this.token = randomBytes4(24).toString("hex");
|
|
24846
|
+
this.upstreamRequestStartedValue = false;
|
|
24847
|
+
this.providerResponseObservedValue = false;
|
|
24848
|
+
this.unansweredUpstreamRequestsValue = 0;
|
|
24849
|
+
}
|
|
24850
|
+
get baseUrl() {
|
|
24851
|
+
if (!this.urlValue) throw new Error("deepseek_transport_proxy_not_started");
|
|
24852
|
+
return `${this.urlValue}/${this.token}`;
|
|
24853
|
+
}
|
|
24854
|
+
get receipts() {
|
|
24855
|
+
return [...this.receiptsValue];
|
|
24856
|
+
}
|
|
24857
|
+
get providerResponseObserved() {
|
|
24858
|
+
return this.providerResponseObservedValue;
|
|
24859
|
+
}
|
|
24860
|
+
get upstreamRequestStarted() {
|
|
24861
|
+
return this.upstreamRequestStartedValue;
|
|
24862
|
+
}
|
|
24863
|
+
get unansweredUpstreamRequest() {
|
|
24864
|
+
return this.unansweredUpstreamRequestsValue > 0;
|
|
24865
|
+
}
|
|
24866
|
+
async start() {
|
|
24867
|
+
if (this.server) return;
|
|
24868
|
+
this.server = createServer2(async (request, response) => {
|
|
24869
|
+
try {
|
|
24870
|
+
const prefix = `/${this.token}`;
|
|
24871
|
+
const requestUrl = request.url ?? "";
|
|
24872
|
+
if (request.method !== "POST" || requestUrl !== `${prefix}/chat/completions`) {
|
|
24873
|
+
response.writeHead(404).end();
|
|
24874
|
+
return;
|
|
24875
|
+
}
|
|
24876
|
+
const chunks = [];
|
|
24877
|
+
let requestBytes = 0;
|
|
24878
|
+
for await (const chunk of request) {
|
|
24879
|
+
const buffer = Buffer.from(chunk);
|
|
24880
|
+
requestBytes += buffer.byteLength;
|
|
24881
|
+
if (requestBytes > MAX_REQUEST_BYTES) throw new Error("deepseek_proxy_request_too_large");
|
|
24882
|
+
chunks.push(buffer);
|
|
24883
|
+
}
|
|
24884
|
+
const body = Buffer.concat(chunks);
|
|
24885
|
+
let requestedModel = "";
|
|
24886
|
+
let requestedEffort = "off";
|
|
24887
|
+
const payload = JSON.parse(body.toString("utf8"));
|
|
24888
|
+
requestedModel = String(payload.model ?? "");
|
|
24889
|
+
const thinking = payload.thinking;
|
|
24890
|
+
requestedEffort = thinking?.type === "disabled" ? "off" : String(payload.reasoning_effort ?? "");
|
|
24891
|
+
if (requestedModel !== this.expectedModel || requestedEffort !== this.expectedEffort) throw new Error("deepseek_outbound_model_or_effort_mismatch");
|
|
24892
|
+
const controller = new AbortController();
|
|
24893
|
+
this.controllers.add(controller);
|
|
24894
|
+
try {
|
|
24895
|
+
this.upstreamRequestStartedValue = true;
|
|
24896
|
+
this.unansweredUpstreamRequestsValue += 1;
|
|
24897
|
+
const upstream = await this.fetchImpl(
|
|
24898
|
+
`${this.upstreamBaseUrl}/chat/completions`,
|
|
24899
|
+
{
|
|
24900
|
+
method: request.method,
|
|
24901
|
+
headers: {
|
|
24902
|
+
"authorization": `Bearer ${this.apiKey}`,
|
|
24903
|
+
"content-type": String(request.headers["content-type"] ?? "application/json"),
|
|
24904
|
+
"accept": String(request.headers.accept ?? "application/json"),
|
|
24905
|
+
"user-agent": String(request.headers["user-agent"] ?? "@vtxmacro/cli")
|
|
24906
|
+
},
|
|
24907
|
+
body,
|
|
24908
|
+
signal: controller.signal
|
|
24909
|
+
}
|
|
24910
|
+
);
|
|
24911
|
+
this.unansweredUpstreamRequestsValue -= 1;
|
|
24912
|
+
this.providerResponseObservedValue = true;
|
|
24913
|
+
const headers = {};
|
|
24914
|
+
upstream.headers.forEach((value, name) => {
|
|
24915
|
+
if (!["connection", "transfer-encoding", "content-length"].includes(name)) {
|
|
24916
|
+
headers[name] = value;
|
|
24917
|
+
}
|
|
24918
|
+
});
|
|
24919
|
+
response.writeHead(upstream.status, headers);
|
|
24920
|
+
if (!upstream.body) {
|
|
24921
|
+
response.end();
|
|
24922
|
+
return;
|
|
24923
|
+
}
|
|
24924
|
+
if (!upstream.ok) {
|
|
24925
|
+
const errorReader = upstream.body.getReader();
|
|
24926
|
+
while (true) {
|
|
24927
|
+
const part = await errorReader.read();
|
|
24928
|
+
if (part.done) break;
|
|
24929
|
+
response.write(Buffer.from(part.value));
|
|
24930
|
+
}
|
|
24931
|
+
response.end();
|
|
24932
|
+
return;
|
|
24933
|
+
}
|
|
24934
|
+
const reader = upstream.body.getReader();
|
|
24935
|
+
const decoder2 = new TextDecoder();
|
|
24936
|
+
let pending = "";
|
|
24937
|
+
let observedId = "";
|
|
24938
|
+
let terminalObserved = false;
|
|
24939
|
+
const forwardLine = (line) => {
|
|
24940
|
+
if (!line.startsWith("data:")) {
|
|
24941
|
+
response.write(`${line}
|
|
24942
|
+
`);
|
|
24943
|
+
return;
|
|
24944
|
+
}
|
|
24945
|
+
const value = line.slice(5).trim();
|
|
24946
|
+
if (!value) {
|
|
24947
|
+
response.write(`${line}
|
|
24948
|
+
`);
|
|
24949
|
+
return;
|
|
24950
|
+
}
|
|
24951
|
+
if (value === "[DONE]") {
|
|
24952
|
+
if (terminalObserved || !observedId) {
|
|
24953
|
+
throw new Error("deepseek_provider_receipt_missing_or_mismatched");
|
|
24954
|
+
}
|
|
24955
|
+
terminalObserved = true;
|
|
24956
|
+
this.receiptsValue.push({
|
|
24957
|
+
id: observedId,
|
|
24958
|
+
model: this.expectedModel,
|
|
24959
|
+
requestedModel,
|
|
24960
|
+
requestedReasoningEffort: requestedEffort
|
|
24961
|
+
});
|
|
24962
|
+
response.write(`${line}
|
|
24963
|
+
`);
|
|
24964
|
+
return;
|
|
24965
|
+
}
|
|
24966
|
+
const event = JSON.parse(value);
|
|
24967
|
+
const eventId = typeof event.id === "string" ? event.id.trim() : "";
|
|
24968
|
+
const eventModel = typeof event.model === "string" ? event.model.trim() : "";
|
|
24969
|
+
if (!eventId || eventModel !== this.expectedModel || observedId && eventId !== observedId) throw new Error("deepseek_provider_receipt_missing_or_mismatched");
|
|
24970
|
+
observedId = eventId;
|
|
24971
|
+
response.write(`${line}
|
|
24972
|
+
`);
|
|
24973
|
+
};
|
|
24974
|
+
while (true) {
|
|
24975
|
+
const part = await reader.read();
|
|
24976
|
+
if (part.done) break;
|
|
24977
|
+
pending += decoder2.decode(part.value, { stream: true });
|
|
24978
|
+
const lines = pending.split(/\r?\n/u);
|
|
24979
|
+
pending = lines.pop() ?? "";
|
|
24980
|
+
for (const line of lines) forwardLine(line);
|
|
24981
|
+
}
|
|
24982
|
+
pending += decoder2.decode();
|
|
24983
|
+
if (pending) forwardLine(pending);
|
|
24984
|
+
if (!terminalObserved) {
|
|
24985
|
+
throw new Error("deepseek_provider_receipt_missing_or_mismatched");
|
|
24986
|
+
}
|
|
24987
|
+
response.end();
|
|
24988
|
+
} finally {
|
|
24989
|
+
this.controllers.delete(controller);
|
|
24990
|
+
}
|
|
24991
|
+
} catch {
|
|
24992
|
+
if (!response.headersSent) response.writeHead(502);
|
|
24993
|
+
response.end();
|
|
24994
|
+
}
|
|
24995
|
+
});
|
|
24996
|
+
await new Promise((resolve6, reject) => {
|
|
24997
|
+
this.server.once("error", reject);
|
|
24998
|
+
this.server.listen(0, "127.0.0.1", () => resolve6());
|
|
24999
|
+
});
|
|
25000
|
+
const address = this.server.address();
|
|
25001
|
+
if (!address || typeof address === "string") throw new Error("deepseek_proxy_bind_failed");
|
|
25002
|
+
this.urlValue = `http://127.0.0.1:${address.port}`;
|
|
25003
|
+
}
|
|
25004
|
+
async close() {
|
|
25005
|
+
for (const controller of this.controllers) controller.abort();
|
|
25006
|
+
const server = this.server;
|
|
25007
|
+
this.server = null;
|
|
25008
|
+
this.urlValue = null;
|
|
25009
|
+
if (!server) return;
|
|
25010
|
+
await new Promise((resolve6) => server.close(() => resolve6()));
|
|
25011
|
+
}
|
|
25012
|
+
};
|
|
25013
|
+
}
|
|
25014
|
+
});
|
|
25015
|
+
|
|
25016
|
+
// lib/inference-host/deepseek-harness-adapter.ts
|
|
25017
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
25018
|
+
import { mkdtemp as mkdtemp3, realpath as realpath4, rm as rm5 } from "node:fs/promises";
|
|
25019
|
+
import { tmpdir as tmpdir4 } from "node:os";
|
|
25020
|
+
import { basename, dirname as dirname4, join as join6 } from "node:path";
|
|
25021
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
25022
|
+
import * as AgentSpine from "@deepseek-ai/dsh-agent-spine-demo";
|
|
25023
|
+
import {
|
|
25024
|
+
createUserMessage,
|
|
25025
|
+
LlmError
|
|
25026
|
+
} from "@deepseek-ai/dsh-llm";
|
|
25027
|
+
import {
|
|
25028
|
+
DeepSeekAdapter,
|
|
25029
|
+
resolveAdapterOptions
|
|
25030
|
+
} from "@deepseek-ai/dsh-llm-deepseek";
|
|
25031
|
+
import * as LlmDeepSeek from "@deepseek-ai/dsh-llm-deepseek";
|
|
25032
|
+
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
25033
|
+
import * as SessionCheckpointPolicy from "@deepseek-ai/dsh-session-checkpoint-policy";
|
|
25034
|
+
import { JsonlSessionPersistence } from "@deepseek-ai/dsh-session-persistence-jsonl";
|
|
25035
|
+
var DEEPSEEK_HARNESS_VERSION, MAX_RESULT_BYTES2, DEEPSEEK_MODELS, DEEPSEEK_API_BASE_URL, isSupportedNodeVersion, effortForHarness, supportedEfforts, toVtxUsage, sumUsage, textFromBlocks, validateText, createDeadlineBoundary, nonDispatchedError, proxyDispatchOutcome, mapDeepSeekFailure, createPrivateWorkspace2, directAdapter, normalizeJsonValue, DeepSeekHarnessAdapter;
|
|
25036
|
+
var init_deepseek_harness_adapter = __esm({
|
|
25037
|
+
"lib/inference-host/deepseek-harness-adapter.ts"() {
|
|
25038
|
+
"use strict";
|
|
25039
|
+
init_codex_app_server();
|
|
25040
|
+
init_deepseek_transport_proxy();
|
|
25041
|
+
DEEPSEEK_HARNESS_VERSION = "0.1.1-rc.2";
|
|
25042
|
+
MAX_RESULT_BYTES2 = 3e5;
|
|
25043
|
+
DEEPSEEK_MODELS = ["deepseek-v4-flash", "deepseek-v4-pro"];
|
|
25044
|
+
DEEPSEEK_API_BASE_URL = "https://api.deepseek.com";
|
|
25045
|
+
isSupportedNodeVersion = (version3) => {
|
|
25046
|
+
const [major, minor] = version3.replace(/^v/u, "").split(".").map(Number);
|
|
25047
|
+
return major === 22 && minor >= 19 || major >= 24;
|
|
25048
|
+
};
|
|
25049
|
+
effortForHarness = (effort) => {
|
|
25050
|
+
if (effort === "none") return "off";
|
|
25051
|
+
if (effort === "low" || effort === "high" || effort === "max") return effort;
|
|
25052
|
+
throw new Error(`deepseek_reasoning_effort_unsupported:${effort}`);
|
|
25053
|
+
};
|
|
25054
|
+
supportedEfforts = (model) => model === "deepseek-v4-pro" ? ["none", "high", "max"] : ["none", "low", "high", "max"];
|
|
25055
|
+
toVtxUsage = (usage) => {
|
|
25056
|
+
const cacheRead = usage.cacheReadTokens ?? 0;
|
|
25057
|
+
const cacheWrite = usage.cacheWriteTokens ?? 0;
|
|
25058
|
+
const inclusiveInput = usage.inputTokens + cacheRead + cacheWrite;
|
|
25059
|
+
return {
|
|
25060
|
+
inputTokens: inclusiveInput,
|
|
25061
|
+
cachedInputTokens: cacheRead,
|
|
25062
|
+
outputTokens: usage.outputTokens,
|
|
25063
|
+
reasoningOutputTokens: Math.min(usage.reasoningTokens ?? 0, usage.outputTokens),
|
|
25064
|
+
totalTokens: inclusiveInput + usage.outputTokens,
|
|
25065
|
+
cacheWriteInputTokens: usage.cacheWriteTokens ?? null,
|
|
25066
|
+
cacheWriteSupported: usage.cacheWriteTokens !== void 0
|
|
25067
|
+
};
|
|
25068
|
+
};
|
|
25069
|
+
sumUsage = (values) => toVtxUsage({
|
|
25070
|
+
inputTokens: values.reduce((sum, value) => sum + value.inputTokens, 0),
|
|
25071
|
+
outputTokens: values.reduce((sum, value) => sum + value.outputTokens, 0),
|
|
25072
|
+
cacheReadTokens: values.reduce((sum, value) => sum + (value.cacheReadTokens ?? 0), 0),
|
|
25073
|
+
cacheWriteTokens: values.some((value) => value.cacheWriteTokens !== void 0) ? values.reduce((sum, value) => sum + (value.cacheWriteTokens ?? 0), 0) : void 0,
|
|
25074
|
+
reasoningTokens: values.reduce((sum, value) => sum + (value.reasoningTokens ?? 0), 0)
|
|
25075
|
+
});
|
|
25076
|
+
textFromBlocks = (blocks, type) => blocks.flatMap((block) => block.type === type ? [block.text] : []).join("");
|
|
25077
|
+
validateText = (text, code) => {
|
|
25078
|
+
if (!text.trim() || Buffer.byteLength(text, "utf8") > MAX_RESULT_BYTES2) throw new Error(code);
|
|
25079
|
+
return text;
|
|
25080
|
+
};
|
|
25081
|
+
createDeadlineBoundary = (source, deadlineAtMs) => {
|
|
25082
|
+
const controller = new AbortController();
|
|
25083
|
+
const relayAbort = () => controller.abort(source?.reason);
|
|
25084
|
+
source?.addEventListener("abort", relayAbort, { once: true });
|
|
25085
|
+
if (source?.aborted) controller.abort(source.reason);
|
|
25086
|
+
const timeout = setTimeout(
|
|
25087
|
+
() => controller.abort(new Error("deadline_exceeded")),
|
|
25088
|
+
Math.max(1, deadlineAtMs - Date.now())
|
|
25089
|
+
);
|
|
25090
|
+
timeout.unref();
|
|
25091
|
+
return {
|
|
25092
|
+
signal: controller.signal,
|
|
25093
|
+
cleanup: () => {
|
|
25094
|
+
clearTimeout(timeout);
|
|
25095
|
+
source?.removeEventListener("abort", relayAbort);
|
|
25096
|
+
}
|
|
25097
|
+
};
|
|
25098
|
+
};
|
|
25099
|
+
nonDispatchedError = (message, category, code, retryable = false) => new CodexAppServerError({
|
|
25100
|
+
message,
|
|
25101
|
+
category,
|
|
25102
|
+
code,
|
|
25103
|
+
retryable,
|
|
25104
|
+
dispatchOutcome: "not_dispatched"
|
|
25105
|
+
});
|
|
25106
|
+
proxyDispatchOutcome = (proxy) => {
|
|
25107
|
+
if (proxy.unansweredUpstreamRequest) return "outcome_unknown";
|
|
25108
|
+
if (proxy.providerResponseObserved) return "confirmed_dispatched";
|
|
25109
|
+
return proxy.upstreamRequestStarted ? "outcome_unknown" : "not_dispatched";
|
|
25110
|
+
};
|
|
25111
|
+
mapDeepSeekFailure = (options) => {
|
|
25112
|
+
if (options.error instanceof CodexAppServerError) return options.error;
|
|
25113
|
+
if (options.cancelled || options.deadline) {
|
|
25114
|
+
return new CodexAppServerError({
|
|
25115
|
+
message: options.cancelled ? "DeepSeek Harness request was cancelled." : "DeepSeek Harness request exceeded its deadline.",
|
|
25116
|
+
category: options.cancelled ? "cancelled" : "timeout",
|
|
25117
|
+
code: options.cancelled ? "cancelled" : "deadline_exceeded",
|
|
25118
|
+
retryable: false,
|
|
25119
|
+
dispatchOutcome: options.dispatchOutcome,
|
|
25120
|
+
cause: options.error
|
|
25121
|
+
});
|
|
25122
|
+
}
|
|
25123
|
+
if (options.error instanceof LlmError) {
|
|
25124
|
+
const failure = options.error.failure;
|
|
25125
|
+
const auth = ["AUTH", "INVALID_CREDENTIAL", "MISSING_CREDENTIAL"].includes(failure.code);
|
|
25126
|
+
const quota = failure.code === "QUOTA" || failure.status === 402;
|
|
25127
|
+
const rateLimit = failure.code === "RATE_LIMIT";
|
|
25128
|
+
const clientError = failure.status !== void 0 && failure.status >= 400 && failure.status < 500;
|
|
25129
|
+
const model = !auth && !quota && !rateLimit && clientError || [
|
|
25130
|
+
"CONTEXT_WINDOW_EXCEEDED",
|
|
25131
|
+
"INVALID_REQUEST",
|
|
25132
|
+
"UNSUPPORTED_CONTENT",
|
|
25133
|
+
"UNSUPPORTED_REASONING_EFFORT"
|
|
25134
|
+
].includes(failure.code);
|
|
25135
|
+
const transport = [
|
|
25136
|
+
"EMPTY_RESPONSE",
|
|
25137
|
+
"MALFORMED_RESPONSE",
|
|
25138
|
+
"SERVER",
|
|
25139
|
+
"STREAM_CLOSED",
|
|
25140
|
+
"TIMEOUT",
|
|
25141
|
+
"TRANSPORT"
|
|
25142
|
+
].includes(failure.code) || failure.code.startsWith("HTTP_") && !clientError;
|
|
25143
|
+
const code = auth ? "deepseek_auth_failed" : quota ? "quota_exceeded" : rateLimit ? "provider_rate_limited" : model ? `deepseek_${failure.code.toLowerCase()}` : transport ? `deepseek_${failure.code.toLowerCase()}` : "deepseek_harness_adapter_failure";
|
|
25144
|
+
return new CodexAppServerError({
|
|
25145
|
+
message: failure.message,
|
|
25146
|
+
category: auth ? "auth" : model || quota || rateLimit ? "model" : transport ? "transport" : "adapter",
|
|
25147
|
+
code,
|
|
25148
|
+
retryable: transport && !quota,
|
|
25149
|
+
dispatchOutcome: options.dispatchOutcome,
|
|
25150
|
+
httpStatusCode: failure.status ?? null,
|
|
25151
|
+
retryAtMs: failure.providerRetryAfterMs === void 0 ? null : Date.now() + failure.providerRetryAfterMs,
|
|
25152
|
+
cause: options.error
|
|
25153
|
+
});
|
|
25154
|
+
}
|
|
25155
|
+
return new CodexAppServerError({
|
|
25156
|
+
message: options.error instanceof Error ? options.error.message : "DeepSeek Harness adapter failed.",
|
|
25157
|
+
category: "adapter",
|
|
25158
|
+
code: "deepseek_harness_adapter_failure",
|
|
25159
|
+
retryable: false,
|
|
25160
|
+
dispatchOutcome: options.dispatchOutcome,
|
|
25161
|
+
cause: options.error
|
|
25162
|
+
});
|
|
25163
|
+
};
|
|
25164
|
+
createPrivateWorkspace2 = async () => {
|
|
25165
|
+
const path = await mkdtemp3(join6(tmpdir4(), "vtx-deepseek-harness-"));
|
|
25166
|
+
return { path, cleanup: async () => {
|
|
25167
|
+
await rm5(path, { recursive: true, force: true });
|
|
25168
|
+
} };
|
|
25169
|
+
};
|
|
25170
|
+
directAdapter = (proxy, model, effort) => {
|
|
25171
|
+
const connection = resolveAdapterOptions({
|
|
25172
|
+
apiKeyEnv: "VTX_DSH_LOOPBACK_TOKEN",
|
|
25173
|
+
baseURL: proxy.baseUrl,
|
|
25174
|
+
reasoningEffort: effort,
|
|
25175
|
+
thinking: "enabled",
|
|
25176
|
+
models: [{ id: model }],
|
|
25177
|
+
retryPolicy: { mode: "normal", maxRetries: 0 }
|
|
25178
|
+
});
|
|
25179
|
+
return new DeepSeekAdapter({
|
|
25180
|
+
options: () => connection,
|
|
25181
|
+
resolveApiKey: async () => "vtx-loopback-only",
|
|
25182
|
+
resolveUserId: () => "vtx-macro"
|
|
25183
|
+
});
|
|
25184
|
+
};
|
|
25185
|
+
normalizeJsonValue = (value) => JSON.parse(JSON.stringify(value));
|
|
25186
|
+
DeepSeekHarnessAdapter = class {
|
|
25187
|
+
constructor(dependencies) {
|
|
25188
|
+
this.agentWorkspaces = /* @__PURE__ */ new Map();
|
|
25189
|
+
this.closing = false;
|
|
25190
|
+
this.dependencies = dependencies;
|
|
25191
|
+
}
|
|
25192
|
+
async preflight(signal) {
|
|
25193
|
+
if (!isSupportedNodeVersion(this.dependencies.nodeVersion ?? process.version)) {
|
|
25194
|
+
throw new CodexAppServerError({
|
|
25195
|
+
message: "DeepSeek Harness requires Node 22.19 or newer in the Node 22 line, or Node 24+.",
|
|
25196
|
+
category: "adapter",
|
|
25197
|
+
code: "deepseek_harness_node_version_unsupported",
|
|
25198
|
+
retryable: false
|
|
25199
|
+
});
|
|
25200
|
+
}
|
|
25201
|
+
const credential = await this.dependencies.credentialStore.read(signal);
|
|
25202
|
+
if (!credential) {
|
|
25203
|
+
throw new CodexAppServerError({
|
|
25204
|
+
message: "Import a DeepSeek API key with vtx inference-host deepseek-login first.",
|
|
25205
|
+
category: "auth",
|
|
25206
|
+
code: "deepseek_harness_credential_required",
|
|
25207
|
+
retryable: false
|
|
25208
|
+
});
|
|
25209
|
+
}
|
|
25210
|
+
const response = await (this.dependencies.fetch ?? fetch)(
|
|
25211
|
+
`${this.dependencies.apiBaseUrl ?? DEEPSEEK_API_BASE_URL}/models`,
|
|
25212
|
+
{ headers: { authorization: `Bearer ${credential.apiKey}` }, signal }
|
|
25213
|
+
);
|
|
25214
|
+
if (!response.ok) {
|
|
25215
|
+
throw new CodexAppServerError({
|
|
25216
|
+
message: `DeepSeek model catalog request failed with HTTP ${response.status}.`,
|
|
25217
|
+
category: response.status === 401 || response.status === 403 ? "auth" : "transport",
|
|
25218
|
+
code: "deepseek_harness_model_catalog_failed",
|
|
25219
|
+
retryable: false
|
|
25220
|
+
});
|
|
25221
|
+
}
|
|
25222
|
+
const payload = await response.json();
|
|
25223
|
+
const live = new Set((payload.data ?? []).map((item) => String(item.id ?? "")));
|
|
25224
|
+
const models = DEEPSEEK_MODELS.filter((model) => live.has(model));
|
|
25225
|
+
if (models.length === 0) {
|
|
25226
|
+
throw new CodexAppServerError({
|
|
25227
|
+
message: "DeepSeek returned no VTX-supported Harness models.",
|
|
25228
|
+
category: "model",
|
|
25229
|
+
code: "deepseek_harness_model_catalog_empty",
|
|
25230
|
+
retryable: false
|
|
25231
|
+
});
|
|
25232
|
+
}
|
|
25233
|
+
return {
|
|
25234
|
+
adapterId: "deepseek-harness",
|
|
25235
|
+
runtimeVersion: DEEPSEEK_HARNESS_VERSION,
|
|
25236
|
+
authenticatedAccountIdentity: null,
|
|
25237
|
+
authenticatedAccountEmail: null,
|
|
25238
|
+
authenticatedAccountPlan: null,
|
|
25239
|
+
modelCapabilities: models.map((model, index) => ({
|
|
25240
|
+
id: model,
|
|
25241
|
+
model,
|
|
25242
|
+
displayName: model === "deepseek-v4-flash" ? "DeepSeek V4 Flash" : "DeepSeek V4 Pro",
|
|
25243
|
+
hidden: false,
|
|
25244
|
+
supportedReasoningEfforts: [...supportedEfforts(model)],
|
|
25245
|
+
defaultReasoningEffort: "high",
|
|
25246
|
+
isDefault: index === 0
|
|
25247
|
+
})),
|
|
25248
|
+
rateLimits: null,
|
|
25249
|
+
sameAttemptRecovery: false
|
|
25250
|
+
};
|
|
25251
|
+
}
|
|
25252
|
+
async runAttempt(input) {
|
|
25253
|
+
const startedAt = (this.dependencies.now ?? Date.now)();
|
|
25254
|
+
if (Date.now() >= input.deadlineAtMs) {
|
|
25255
|
+
throw nonDispatchedError(
|
|
25256
|
+
"DeepSeek Harness attempt exceeded its deadline.",
|
|
25257
|
+
"timeout",
|
|
25258
|
+
"deadline_exceeded"
|
|
25259
|
+
);
|
|
25260
|
+
}
|
|
25261
|
+
if (!DEEPSEEK_MODELS.includes(input.requestedModel)) {
|
|
25262
|
+
throw nonDispatchedError(
|
|
25263
|
+
"The requested DeepSeek Harness model is unsupported.",
|
|
25264
|
+
"model",
|
|
25265
|
+
"deepseek_model_unsupported"
|
|
25266
|
+
);
|
|
25267
|
+
}
|
|
25268
|
+
if (!supportedEfforts(input.requestedModel).includes(input.requestedReasoningEffort)) {
|
|
25269
|
+
throw nonDispatchedError(
|
|
25270
|
+
"The requested DeepSeek Harness reasoning effort is unsupported.",
|
|
25271
|
+
"model",
|
|
25272
|
+
"deepseek_reasoning_effort_unsupported"
|
|
25273
|
+
);
|
|
25274
|
+
}
|
|
25275
|
+
const effort = effortForHarness(input.requestedReasoningEffort);
|
|
25276
|
+
const boundary = createDeadlineBoundary(input.signal, input.deadlineAtMs);
|
|
25277
|
+
let credential;
|
|
25278
|
+
try {
|
|
25279
|
+
credential = await this.dependencies.credentialStore.read(boundary.signal);
|
|
25280
|
+
if (!credential) {
|
|
25281
|
+
throw nonDispatchedError(
|
|
25282
|
+
"Import a DeepSeek API key with vtx inference-host deepseek-login first.",
|
|
25283
|
+
"auth",
|
|
25284
|
+
"deepseek_harness_credential_required"
|
|
25285
|
+
);
|
|
25286
|
+
}
|
|
25287
|
+
} catch (error48) {
|
|
25288
|
+
const cancelled = input.signal?.aborted === true;
|
|
25289
|
+
const deadline = !cancelled && boundary.signal.aborted;
|
|
25290
|
+
boundary.cleanup();
|
|
25291
|
+
if (error48 instanceof CodexAppServerError) throw error48;
|
|
25292
|
+
throw nonDispatchedError(
|
|
25293
|
+
cancelled ? "DeepSeek Harness attempt was cancelled." : deadline ? "DeepSeek Harness attempt exceeded its deadline." : "DeepSeek Harness could not read its local credential.",
|
|
25294
|
+
cancelled ? "cancelled" : deadline ? "timeout" : "auth",
|
|
25295
|
+
cancelled ? "cancelled" : deadline ? "deadline_exceeded" : "deepseek_harness_credential_read_failed"
|
|
25296
|
+
);
|
|
25297
|
+
}
|
|
25298
|
+
const proxy = new DeepSeekTransportProxy(
|
|
25299
|
+
credential.apiKey,
|
|
25300
|
+
input.requestedModel,
|
|
25301
|
+
effort,
|
|
25302
|
+
this.dependencies.apiBaseUrl ?? DEEPSEEK_API_BASE_URL,
|
|
25303
|
+
this.dependencies.fetch ?? fetch
|
|
25304
|
+
);
|
|
25305
|
+
try {
|
|
25306
|
+
boundary.signal.throwIfAborted();
|
|
25307
|
+
await proxy.start();
|
|
25308
|
+
const adapter = directAdapter(proxy, input.requestedModel, effort);
|
|
25309
|
+
const blocks = [];
|
|
25310
|
+
let usage = null;
|
|
25311
|
+
let finish = null;
|
|
25312
|
+
for await (const chunk of adapter.stream({
|
|
25313
|
+
provider: "deepseek-official",
|
|
25314
|
+
model: input.requestedModel,
|
|
25315
|
+
reasoningEffort: effort,
|
|
25316
|
+
system: `${input.systemPrompt}
|
|
25317
|
+
|
|
25318
|
+
Return only one JSON value matching this JSON Schema exactly:
|
|
25319
|
+
${input.outputSchemaJson}`,
|
|
25320
|
+
messages: [createUserMessage({
|
|
25321
|
+
content: [{ type: "text", text: input.userPrompt }],
|
|
25322
|
+
source: { kind: "user" }
|
|
25323
|
+
})],
|
|
25324
|
+
tools: [],
|
|
25325
|
+
signal: boundary.signal
|
|
25326
|
+
})) {
|
|
25327
|
+
if (chunk.type === "block-end") blocks.push(chunk.block);
|
|
25328
|
+
if (chunk.type === "usage") usage = chunk.usage;
|
|
25329
|
+
if (chunk.type === "finish") finish = chunk;
|
|
25330
|
+
}
|
|
25331
|
+
const receipts = proxy.receipts;
|
|
25332
|
+
if (receipts.length !== 1 || !usage || finish?.type !== "finish" || finish.reason.kind !== "stop") {
|
|
25333
|
+
throw new Error("deepseek_harness_terminal_receipt_invalid");
|
|
25334
|
+
}
|
|
25335
|
+
const text = validateText(textFromBlocks(blocks, "text"), "deepseek_harness_result_invalid");
|
|
25336
|
+
return {
|
|
25337
|
+
text,
|
|
25338
|
+
reasoningContent: textFromBlocks(blocks, "reasoning") || null,
|
|
25339
|
+
reasoningSummary: null,
|
|
25340
|
+
requestedModel: input.requestedModel,
|
|
25341
|
+
effectiveModel: receipts[0].model,
|
|
25342
|
+
requestedReasoningEffort: input.requestedReasoningEffort,
|
|
25343
|
+
effectiveReasoningEffort: input.requestedReasoningEffort,
|
|
25344
|
+
adapterRequestId: receipts[0].id,
|
|
25345
|
+
adapterResponseId: receipts[0].id,
|
|
25346
|
+
usage: toVtxUsage(usage),
|
|
25347
|
+
latencyMs: Math.max(0, (this.dependencies.now ?? Date.now)() - startedAt),
|
|
25348
|
+
timeToFirstTokenMs: null,
|
|
25349
|
+
terminalStatus: "completed"
|
|
25350
|
+
};
|
|
25351
|
+
} catch (error48) {
|
|
25352
|
+
const cancelled = input.signal?.aborted === true;
|
|
25353
|
+
const deadline = !cancelled && boundary.signal.aborted;
|
|
25354
|
+
throw mapDeepSeekFailure({
|
|
25355
|
+
error: error48,
|
|
25356
|
+
cancelled,
|
|
25357
|
+
deadline,
|
|
25358
|
+
dispatchOutcome: proxyDispatchOutcome(proxy)
|
|
25359
|
+
});
|
|
25360
|
+
} finally {
|
|
25361
|
+
boundary.cleanup();
|
|
25362
|
+
await proxy.close();
|
|
25363
|
+
}
|
|
25364
|
+
}
|
|
25365
|
+
async runTurn(input) {
|
|
25366
|
+
if (this.closing) {
|
|
25367
|
+
throw nonDispatchedError(
|
|
25368
|
+
"DeepSeek Harness Agent adapter is closing.",
|
|
25369
|
+
"transport",
|
|
25370
|
+
"transport_closed",
|
|
25371
|
+
true
|
|
25372
|
+
);
|
|
25373
|
+
}
|
|
25374
|
+
if (Date.now() >= input.deadlineAtMs) {
|
|
25375
|
+
throw nonDispatchedError(
|
|
25376
|
+
"DeepSeek Harness Agent turn exceeded its deadline.",
|
|
25377
|
+
"timeout",
|
|
25378
|
+
"deadline_exceeded"
|
|
25379
|
+
);
|
|
25380
|
+
}
|
|
25381
|
+
if (!DEEPSEEK_MODELS.includes(input.requestedModel)) {
|
|
25382
|
+
throw nonDispatchedError(
|
|
25383
|
+
"The requested DeepSeek Harness model is unsupported.",
|
|
25384
|
+
"model",
|
|
25385
|
+
"deepseek_model_unsupported"
|
|
25386
|
+
);
|
|
25387
|
+
}
|
|
25388
|
+
if (input.dataContract.length === 0 || !supportedEfforts(input.requestedModel).includes(input.requestedReasoningEffort)) {
|
|
25389
|
+
throw nonDispatchedError(
|
|
25390
|
+
"DeepSeek Harness Agent turn input is invalid.",
|
|
25391
|
+
"schema",
|
|
25392
|
+
"invalid_agent_turn_input"
|
|
25393
|
+
);
|
|
25394
|
+
}
|
|
25395
|
+
const startedAt = (this.dependencies.now ?? Date.now)();
|
|
25396
|
+
const effort = effortForHarness(input.requestedReasoningEffort);
|
|
25397
|
+
const boundary = createDeadlineBoundary(input.signal, input.deadlineAtMs);
|
|
25398
|
+
let credential;
|
|
25399
|
+
try {
|
|
25400
|
+
credential = await this.dependencies.credentialStore.read(boundary.signal);
|
|
25401
|
+
if (!credential) {
|
|
25402
|
+
throw nonDispatchedError(
|
|
25403
|
+
"Import a DeepSeek API key with vtx inference-host deepseek-login first.",
|
|
25404
|
+
"auth",
|
|
25405
|
+
"deepseek_harness_credential_required"
|
|
25406
|
+
);
|
|
25407
|
+
}
|
|
25408
|
+
} catch (error48) {
|
|
25409
|
+
const cancelled = input.signal?.aborted === true;
|
|
25410
|
+
const deadline = !cancelled && boundary.signal.aborted;
|
|
25411
|
+
boundary.cleanup();
|
|
25412
|
+
if (error48 instanceof CodexAppServerError) throw error48;
|
|
25413
|
+
throw nonDispatchedError(
|
|
25414
|
+
cancelled ? "DeepSeek Harness Agent turn was cancelled." : deadline ? "DeepSeek Harness Agent turn exceeded its deadline." : "DeepSeek Harness could not read its local credential.",
|
|
25415
|
+
cancelled ? "cancelled" : deadline ? "timeout" : "auth",
|
|
25416
|
+
cancelled ? "cancelled" : deadline ? "deadline_exceeded" : "deepseek_harness_credential_read_failed"
|
|
25417
|
+
);
|
|
25418
|
+
}
|
|
25419
|
+
const owned = input.durableThread ? null : await (this.dependencies.createWorkspace ?? createPrivateWorkspace2)();
|
|
25420
|
+
const rootPath = input.durableThread?.threadPath ?? owned.path;
|
|
25421
|
+
if (owned) this.agentWorkspaces.set(rootPath, owned.cleanup);
|
|
25422
|
+
const proxy = new DeepSeekTransportProxy(
|
|
25423
|
+
credential.apiKey,
|
|
25424
|
+
input.requestedModel,
|
|
25425
|
+
effort,
|
|
25426
|
+
this.dependencies.apiBaseUrl ?? DEEPSEEK_API_BASE_URL,
|
|
25427
|
+
this.dependencies.fetch ?? fetch
|
|
25428
|
+
);
|
|
25429
|
+
const ctx = new Context();
|
|
25430
|
+
const loopbackEnvName = `VTX_DSH_LOOPBACK_TOKEN_${randomUUID2().replaceAll("-", "").toUpperCase()}`;
|
|
25431
|
+
process.env[loopbackEnvName] = "vtx-loopback-only";
|
|
25432
|
+
let durableCheckpointed = input.durableThread !== null;
|
|
25433
|
+
let cleanupUnpublishedWorkspace = false;
|
|
25434
|
+
let removeAgentAbortListener = () => void 0;
|
|
25435
|
+
let cancelAgentTurn = () => void 0;
|
|
25436
|
+
let releaseAgentDispatch = () => void 0;
|
|
25437
|
+
let permitAgentDispatch = false;
|
|
25438
|
+
try {
|
|
25439
|
+
await proxy.start();
|
|
25440
|
+
await ctx.plugin(AgentSpine, {
|
|
25441
|
+
agents: [],
|
|
25442
|
+
maxParallelToolCalls: 1,
|
|
25443
|
+
includeHarnessIdentity: false,
|
|
25444
|
+
includeRuntimeContext: false,
|
|
25445
|
+
persona: `${input.systemPrompt}
|
|
25446
|
+
|
|
25447
|
+
Return only one JSON value matching this JSON Schema exactly:
|
|
25448
|
+
${JSON.stringify(input.outputSchema)}`,
|
|
25449
|
+
tools: { mode: "native" },
|
|
25450
|
+
workspaceContext: false,
|
|
25451
|
+
skills: { enabled: false },
|
|
25452
|
+
toolBash: false,
|
|
25453
|
+
toolJobs: false,
|
|
25454
|
+
goals: false
|
|
25455
|
+
});
|
|
25456
|
+
await ctx.plugin(JsonlSessionPersistence, { root: rootPath, compression: "none" });
|
|
25457
|
+
await ctx.plugin(SessionCheckpointPolicy);
|
|
25458
|
+
await ctx.plugin(LlmDeepSeek, {
|
|
25459
|
+
apiKeyEnv: loopbackEnvName,
|
|
25460
|
+
baseURL: proxy.baseUrl,
|
|
25461
|
+
reasoningEffort: effort,
|
|
25462
|
+
thinking: "enabled",
|
|
25463
|
+
models: [{ id: input.requestedModel }],
|
|
25464
|
+
retryPolicy: { mode: "normal", maxRetries: 0 }
|
|
25465
|
+
});
|
|
25466
|
+
const evidence = [];
|
|
25467
|
+
const setup = (agentCtx) => {
|
|
25468
|
+
const definitions = [
|
|
25469
|
+
{
|
|
25470
|
+
name: "vtx_get_data",
|
|
25471
|
+
description: "Request assignment-scoped VTX data.",
|
|
25472
|
+
parameters: { oneOf: input.dataContract.map((entry) => ({
|
|
25473
|
+
type: "object",
|
|
25474
|
+
additionalProperties: false,
|
|
25475
|
+
required: ["capability", "arguments"],
|
|
25476
|
+
properties: { capability: { const: entry.id }, arguments: entry.input_schema }
|
|
25477
|
+
})) }
|
|
25478
|
+
},
|
|
25479
|
+
{
|
|
25480
|
+
name: "vtx_submit_decision",
|
|
25481
|
+
description: "Submit one VTX structured trading decision candidate.",
|
|
25482
|
+
parameters: { type: "object", additionalProperties: false, required: ["candidate"], properties: { candidate: input.decisionSchema } }
|
|
25483
|
+
},
|
|
25484
|
+
{
|
|
25485
|
+
name: "vtx_decision_status",
|
|
25486
|
+
description: "Resolve the durable status of a decision operation.",
|
|
25487
|
+
parameters: { type: "object", additionalProperties: false, required: ["operation_id"], properties: { operation_id: { type: "string", minLength: 1 } } }
|
|
25488
|
+
}
|
|
25489
|
+
];
|
|
25490
|
+
for (const definition of definitions) {
|
|
25491
|
+
agentCtx.tools.register({
|
|
25492
|
+
...definition,
|
|
25493
|
+
output: {
|
|
25494
|
+
schema: {},
|
|
25495
|
+
render: (_arguments, value) => [{ type: "text", text: JSON.stringify(value) }]
|
|
25496
|
+
},
|
|
25497
|
+
execute: async (argumentsValue) => {
|
|
25498
|
+
const argumentsRecord = argumentsValue && typeof argumentsValue === "object" && !Array.isArray(argumentsValue) ? argumentsValue : {};
|
|
25499
|
+
const callId = randomUUID2();
|
|
25500
|
+
const result2 = await input.executeTool({ callId, tool: definition.name, arguments: argumentsRecord });
|
|
25501
|
+
evidence.push({ callId, tool: definition.name, arguments: argumentsRecord, success: result2.success });
|
|
25502
|
+
return normalizeJsonValue(result2.success ? result2.value : { error: result2.value });
|
|
25503
|
+
}
|
|
25504
|
+
});
|
|
25505
|
+
}
|
|
25506
|
+
};
|
|
25507
|
+
const sessionId = input.durableThread ? SessionId(input.durableThread.threadId) : SessionId(`vtx-${randomUUID2()}`);
|
|
25508
|
+
const handle = input.durableThread ? await ctx.agents.resume({
|
|
25509
|
+
resumeSessionId: sessionId,
|
|
25510
|
+
agentOptions: { provider: "deepseek-official", model: input.requestedModel, reasoningEffort: effort },
|
|
25511
|
+
signal: boundary.signal,
|
|
25512
|
+
setup
|
|
25513
|
+
}) : await ctx.agents.create({
|
|
25514
|
+
sessionId,
|
|
25515
|
+
meta: { cwd: rootPath },
|
|
25516
|
+
agentOptions: { provider: "deepseek-official", model: input.requestedModel, reasoningEffort: effort },
|
|
25517
|
+
signal: boundary.signal,
|
|
25518
|
+
setup
|
|
25519
|
+
});
|
|
25520
|
+
const onAbort = () => handle.agent.cancel({ kind: "user" });
|
|
25521
|
+
cancelAgentTurn = onAbort;
|
|
25522
|
+
boundary.signal.addEventListener("abort", onAbort, { once: true });
|
|
25523
|
+
removeAgentAbortListener = () => boundary.signal.removeEventListener("abort", onAbort);
|
|
25524
|
+
if (boundary.signal.aborted) onAbort();
|
|
25525
|
+
boundary.signal.throwIfAborted();
|
|
25526
|
+
let checkpointReached = false;
|
|
25527
|
+
let resolveCheckpoint;
|
|
25528
|
+
const checkpoint = new Promise((resolve6) => {
|
|
25529
|
+
resolveCheckpoint = resolve6;
|
|
25530
|
+
});
|
|
25531
|
+
const dispatchGate = new Promise((resolve6) => {
|
|
25532
|
+
releaseAgentDispatch = resolve6;
|
|
25533
|
+
});
|
|
25534
|
+
ctx.on("llm/stream", (options, next) => {
|
|
25535
|
+
if (String(options.sessionId ?? "") !== String(sessionId)) return next();
|
|
25536
|
+
return (async function* () {
|
|
25537
|
+
await ctx.sessions.flush(handle.agent.session);
|
|
25538
|
+
checkpointReached = true;
|
|
25539
|
+
resolveCheckpoint();
|
|
25540
|
+
await dispatchGate;
|
|
25541
|
+
boundary.signal.throwIfAborted();
|
|
25542
|
+
if (!permitAgentDispatch) throw new Error("deepseek_agent_publication_not_committed");
|
|
25543
|
+
yield* next();
|
|
25544
|
+
})();
|
|
25545
|
+
});
|
|
25546
|
+
const thread = {
|
|
25547
|
+
threadId: String(sessionId),
|
|
25548
|
+
threadPath: rootPath,
|
|
25549
|
+
effectiveModel: input.requestedModel,
|
|
25550
|
+
effectiveReasoningEffort: input.requestedReasoningEffort
|
|
25551
|
+
};
|
|
25552
|
+
const startSeq = handle.agent.session.seq;
|
|
25553
|
+
handle.agent.followup(createUserMessage({
|
|
25554
|
+
content: [{ type: "text", text: input.userPrompt }],
|
|
25555
|
+
source: { kind: "user" }
|
|
25556
|
+
}));
|
|
25557
|
+
const idle = handle.agent.whenIdle();
|
|
25558
|
+
await Promise.race([
|
|
25559
|
+
checkpoint,
|
|
25560
|
+
idle.then(() => {
|
|
25561
|
+
if (!checkpointReached) throw new Error("deepseek_agent_checkpoint_not_reached");
|
|
25562
|
+
})
|
|
25563
|
+
]);
|
|
25564
|
+
boundary.signal.throwIfAborted();
|
|
25565
|
+
if (input.onThreadReady) {
|
|
25566
|
+
await input.onThreadReady(thread);
|
|
25567
|
+
durableCheckpointed = true;
|
|
25568
|
+
}
|
|
25569
|
+
boundary.signal.throwIfAborted();
|
|
25570
|
+
permitAgentDispatch = true;
|
|
25571
|
+
releaseAgentDispatch();
|
|
25572
|
+
releaseAgentDispatch = () => void 0;
|
|
25573
|
+
await idle;
|
|
25574
|
+
const events = handle.agent.session.events.slice(startSeq);
|
|
25575
|
+
const assistantEvents = events.filter((event) => event.type === "assistant/message");
|
|
25576
|
+
const turnEnd = [...events].reverse().find((event) => event.type === "turn/end");
|
|
25577
|
+
if (!turnEnd || turnEnd.type !== "turn/end" || turnEnd.data.reason.kind !== "completed") {
|
|
25578
|
+
if (turnEnd?.type === "turn/end" && turnEnd.data.reason.kind === "error") {
|
|
25579
|
+
const failure = turnEnd.data.reason.error;
|
|
25580
|
+
throw new LlmError(failure.message, failure.code, {
|
|
25581
|
+
...failure.status === void 0 ? {} : { status: failure.status },
|
|
25582
|
+
...failure.providerRetryAfterMs === void 0 ? {} : { providerRetryAfterMs: failure.providerRetryAfterMs }
|
|
25583
|
+
});
|
|
25584
|
+
}
|
|
25585
|
+
const reason = turnEnd?.type === "turn/end" ? turnEnd.data.reason : { kind: "missing" };
|
|
25586
|
+
throw new Error(`deepseek_harness_agent_turn_incomplete:${JSON.stringify(reason)}`);
|
|
25587
|
+
}
|
|
25588
|
+
const last = assistantEvents.at(-1);
|
|
25589
|
+
if (!last || last.type !== "assistant/message" || last.data.interrupted) {
|
|
25590
|
+
throw new Error("deepseek_harness_agent_result_missing");
|
|
25591
|
+
}
|
|
25592
|
+
const usages = assistantEvents.flatMap((event) => event.type === "assistant/message" && event.data.usage ? [event.data.usage] : []);
|
|
25593
|
+
if (usages.length === 0 || proxy.receipts.length !== usages.length) {
|
|
25594
|
+
throw new Error("deepseek_harness_agent_receipt_missing");
|
|
25595
|
+
}
|
|
25596
|
+
const text = validateText(textFromBlocks(last.data.message.content, "text"), "deepseek_harness_agent_result_invalid");
|
|
25597
|
+
const receipts = proxy.receipts;
|
|
25598
|
+
await handle.dispose();
|
|
25599
|
+
return {
|
|
25600
|
+
thread,
|
|
25601
|
+
turn: {
|
|
25602
|
+
text,
|
|
25603
|
+
reasoningContent: textFromBlocks(last.data.message.content, "reasoning") || null,
|
|
25604
|
+
reasoningSummary: null,
|
|
25605
|
+
requestedModel: input.requestedModel,
|
|
25606
|
+
effectiveModel: receipts.at(-1).model,
|
|
25607
|
+
requestedReasoningEffort: input.requestedReasoningEffort,
|
|
25608
|
+
effectiveReasoningEffort: input.requestedReasoningEffort,
|
|
25609
|
+
adapterRequestId: receipts[0].id,
|
|
25610
|
+
adapterResponseId: receipts.at(-1).id,
|
|
25611
|
+
usage: sumUsage(usages),
|
|
25612
|
+
latencyMs: Math.max(0, (this.dependencies.now ?? Date.now)() - startedAt),
|
|
25613
|
+
timeToFirstTokenMs: null,
|
|
25614
|
+
terminalStatus: "completed",
|
|
25615
|
+
toolCalls: evidence,
|
|
25616
|
+
webSearches: []
|
|
25617
|
+
}
|
|
25618
|
+
};
|
|
25619
|
+
} catch (error48) {
|
|
25620
|
+
cancelAgentTurn();
|
|
25621
|
+
releaseAgentDispatch();
|
|
25622
|
+
releaseAgentDispatch = () => void 0;
|
|
25623
|
+
if (!durableCheckpointed && owned) {
|
|
25624
|
+
cleanupUnpublishedWorkspace = true;
|
|
25625
|
+
}
|
|
25626
|
+
throw mapDeepSeekFailure({
|
|
25627
|
+
error: error48,
|
|
25628
|
+
cancelled: input.signal?.aborted === true,
|
|
25629
|
+
deadline: input.signal?.aborted !== true && boundary.signal.aborted,
|
|
25630
|
+
dispatchOutcome: proxyDispatchOutcome(proxy)
|
|
25631
|
+
});
|
|
25632
|
+
} finally {
|
|
25633
|
+
removeAgentAbortListener();
|
|
25634
|
+
boundary.cleanup();
|
|
25635
|
+
await ctx.fiber.dispose().catch(() => void 0);
|
|
25636
|
+
await proxy.close();
|
|
25637
|
+
if (cleanupUnpublishedWorkspace && owned) {
|
|
25638
|
+
await owned.cleanup().catch(() => void 0);
|
|
25639
|
+
this.agentWorkspaces.delete(rootPath);
|
|
25640
|
+
}
|
|
25641
|
+
delete process.env[loopbackEnvName];
|
|
25642
|
+
}
|
|
25643
|
+
}
|
|
25644
|
+
async releaseThread(thread) {
|
|
25645
|
+
const cleanup = this.agentWorkspaces.get(thread.threadPath);
|
|
25646
|
+
if (cleanup) {
|
|
25647
|
+
await cleanup();
|
|
25648
|
+
this.agentWorkspaces.delete(thread.threadPath);
|
|
25649
|
+
return;
|
|
25650
|
+
}
|
|
25651
|
+
const resolved = await realpath4(thread.threadPath);
|
|
25652
|
+
const temporaryRoot = await realpath4(tmpdir4());
|
|
25653
|
+
if (dirname4(resolved) !== temporaryRoot || !basename(resolved).startsWith("vtx-deepseek-harness-")) throw new Error("deepseek_harness_thread_path_not_owned");
|
|
25654
|
+
await rm5(resolved, { recursive: true, force: true });
|
|
25655
|
+
}
|
|
25656
|
+
async close() {
|
|
25657
|
+
this.closing = true;
|
|
25658
|
+
}
|
|
25659
|
+
};
|
|
25660
|
+
}
|
|
25661
|
+
});
|
|
25662
|
+
|
|
25663
|
+
// lib/inference-host/deepseek-credential-store.ts
|
|
25664
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
25665
|
+
var DEEPSEEK_CREDENTIAL_NAMESPACE, MAX_API_KEY_BYTES, validateApiKey, credentialIdentity, parseCredential, serializeCredential, platformCommands, createDeepSeekHarnessCredentialStore;
|
|
25666
|
+
var init_deepseek_credential_store = __esm({
|
|
25667
|
+
"lib/inference-host/deepseek-credential-store.ts"() {
|
|
25668
|
+
"use strict";
|
|
25669
|
+
init_config();
|
|
25670
|
+
init_credential_store();
|
|
25671
|
+
DEEPSEEK_CREDENTIAL_NAMESPACE = "vtxmacro-deepseek-harness";
|
|
25672
|
+
MAX_API_KEY_BYTES = 512;
|
|
25673
|
+
validateApiKey = (raw) => {
|
|
25674
|
+
const apiKey = raw.trim();
|
|
25675
|
+
if (apiKey.length < 16 || Buffer.byteLength(apiKey, "utf8") > MAX_API_KEY_BYTES || /[\s\u0000-\u001f\u007f]/u.test(apiKey)) {
|
|
25676
|
+
throw new Error("DeepSeek API key is invalid. Provide one private key through stdin.");
|
|
25677
|
+
}
|
|
25678
|
+
return apiKey;
|
|
25679
|
+
};
|
|
25680
|
+
credentialIdentity = (apiKey) => `deepseek-key-${createHash5("sha256").update(apiKey).digest("hex").slice(0, 24)}`;
|
|
25681
|
+
parseCredential = (raw) => {
|
|
25682
|
+
let value;
|
|
25683
|
+
try {
|
|
25684
|
+
value = JSON.parse(raw);
|
|
25685
|
+
} catch {
|
|
25686
|
+
throw new Error("Stored DeepSeek Harness credential is invalid JSON.");
|
|
25687
|
+
}
|
|
25688
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
25689
|
+
throw new Error("Stored DeepSeek Harness credential is invalid.");
|
|
25690
|
+
}
|
|
25691
|
+
const record2 = value;
|
|
25692
|
+
const apiKey = validateApiKey(String(record2.api_key ?? ""));
|
|
25693
|
+
const identity = credentialIdentity(apiKey);
|
|
25694
|
+
if (record2.schema_version !== 1 || record2.adapter !== "deepseek-harness" || record2.identity !== identity || Object.keys(record2).sort().join(",") !== "adapter,api_key,identity,schema_version") {
|
|
25695
|
+
throw new Error("Stored DeepSeek Harness credential failed validation.");
|
|
25696
|
+
}
|
|
25697
|
+
return { apiKey, identity };
|
|
25698
|
+
};
|
|
25699
|
+
serializeCredential = (apiKey) => {
|
|
25700
|
+
const validated = validateApiKey(apiKey);
|
|
25701
|
+
return `${JSON.stringify({
|
|
25702
|
+
schema_version: 1,
|
|
25703
|
+
adapter: "deepseek-harness",
|
|
25704
|
+
api_key: validated,
|
|
25705
|
+
identity: credentialIdentity(validated)
|
|
25706
|
+
})}
|
|
25707
|
+
`;
|
|
25708
|
+
};
|
|
25709
|
+
platformCommands = (env, platform) => {
|
|
25710
|
+
if (platform === "win32") return windowsInferenceCredentialCommands;
|
|
25711
|
+
if (platform === "linux" && String(env.WSL_INTEROP || "").trim()) {
|
|
25712
|
+
return windowsInferenceCredentialCommands;
|
|
25713
|
+
}
|
|
25714
|
+
if (platform === "linux") return linuxSecretServiceInferenceCredentialCommands;
|
|
25715
|
+
if (platform === "darwin") return macosKeychainInferenceCredentialCommands;
|
|
25716
|
+
return null;
|
|
25717
|
+
};
|
|
25718
|
+
createDeepSeekHarnessCredentialStore = (config2, dependencies = {}) => {
|
|
25719
|
+
const accountKey = `deepseek-harness:${config2.instanceName}`;
|
|
25720
|
+
const path = `${config2.statePath}.deepseek-harness-secret.json`;
|
|
25721
|
+
const env = dependencies.env ?? process.env;
|
|
25722
|
+
const platform = dependencies.platform ?? process.platform;
|
|
25723
|
+
const commands = dependencies.commands === void 0 ? platformCommands(env, platform) : dependencies.commands;
|
|
25724
|
+
const runner = dependencies.commandRunner ?? runCredentialCommand;
|
|
25725
|
+
if (config2.credentialStoreMode === "os") {
|
|
25726
|
+
if (!commands) {
|
|
25727
|
+
throw new Error("OS credential storage is unavailable for the DeepSeek API key.");
|
|
25728
|
+
}
|
|
25729
|
+
return {
|
|
25730
|
+
read: async (signal) => {
|
|
25731
|
+
const command = commands.lookup(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey);
|
|
25732
|
+
const result2 = await runner(command, { stdin: null, signal });
|
|
25733
|
+
if ((command.notFoundExitCodes ?? []).includes(result2.exitCode)) return null;
|
|
25734
|
+
if (result2.exitCode !== 0) throw new Error("DeepSeek OS credential lookup failed.");
|
|
25735
|
+
return parseCredential(result2.stdout);
|
|
25736
|
+
},
|
|
25737
|
+
write: async (apiKey, signal) => {
|
|
25738
|
+
const serialized = serializeCredential(apiKey);
|
|
25739
|
+
const priorLookup = commands.lookup(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey);
|
|
25740
|
+
const priorResult = await runner(priorLookup, { stdin: null, signal });
|
|
25741
|
+
const prior = (priorLookup.notFoundExitCodes ?? []).includes(priorResult.exitCode) ? null : priorResult.exitCode === 0 ? parseCredential(priorResult.stdout) : void 0;
|
|
25742
|
+
if (prior === void 0) throw new Error("DeepSeek OS credential lookup failed before write.");
|
|
25743
|
+
const command = commands.store(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey);
|
|
25744
|
+
if (command.args.some((value) => value.includes(validateApiKey(apiKey)))) {
|
|
25745
|
+
throw new Error("DeepSeek API key must never be passed in command arguments.");
|
|
25746
|
+
}
|
|
25747
|
+
try {
|
|
25748
|
+
const result2 = await runner(command, { stdin: serialized, signal });
|
|
25749
|
+
if (result2.exitCode !== 0) throw new Error("DeepSeek OS credential write failed.");
|
|
25750
|
+
const retainedCommand = commands.lookup(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey);
|
|
25751
|
+
const retained = await runner(retainedCommand, { stdin: null, signal });
|
|
25752
|
+
if (retained.exitCode !== 0) {
|
|
25753
|
+
throw new Error("DeepSeek OS credential write could not be verified.");
|
|
25754
|
+
}
|
|
25755
|
+
const expected = parseCredential(serialized);
|
|
25756
|
+
const observed = parseCredential(retained.stdout);
|
|
25757
|
+
if (observed.identity !== expected.identity || observed.apiKey !== expected.apiKey) {
|
|
25758
|
+
throw new Error("DeepSeek OS credential write could not be verified.");
|
|
25759
|
+
}
|
|
25760
|
+
return observed;
|
|
25761
|
+
} catch (error48) {
|
|
25762
|
+
const rollback = prior ? commands.store(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey) : commands.remove(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey);
|
|
25763
|
+
const rollbackResult = await runner(rollback, {
|
|
25764
|
+
stdin: prior ? serializeCredential(prior.apiKey) : null
|
|
25765
|
+
});
|
|
25766
|
+
if (rollbackResult.exitCode !== 0 && !(rollback.notFoundExitCodes ?? []).includes(rollbackResult.exitCode)) {
|
|
25767
|
+
throw new Error("DeepSeek OS credential write failed and rollback failed.", {
|
|
25768
|
+
cause: error48
|
|
25769
|
+
});
|
|
25770
|
+
}
|
|
25771
|
+
const verifyCommand = commands.lookup(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey);
|
|
25772
|
+
const verified = await runner(verifyCommand, { stdin: null });
|
|
25773
|
+
const absent = (verifyCommand.notFoundExitCodes ?? []).includes(verified.exitCode);
|
|
25774
|
+
const restored = prior && verified.exitCode === 0 ? parseCredential(verified.stdout) : null;
|
|
25775
|
+
if (prior === null && !absent || prior !== null && (!restored || restored.identity !== prior.identity || restored.apiKey !== prior.apiKey)) {
|
|
25776
|
+
throw new Error("DeepSeek OS credential write failed and rollback could not be verified.", {
|
|
25777
|
+
cause: error48
|
|
25778
|
+
});
|
|
25779
|
+
}
|
|
25780
|
+
throw error48;
|
|
25781
|
+
}
|
|
25782
|
+
},
|
|
25783
|
+
remove: async (signal) => {
|
|
25784
|
+
const command = commands.remove(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey);
|
|
25785
|
+
const result2 = await runner(command, { stdin: null, signal });
|
|
25786
|
+
if (result2.exitCode !== 0 && !(command.notFoundExitCodes ?? []).includes(result2.exitCode)) throw new Error("DeepSeek OS credential removal failed.");
|
|
25787
|
+
const retainedCommand = commands.lookup(DEEPSEEK_CREDENTIAL_NAMESPACE, accountKey);
|
|
25788
|
+
const retained = await runner(retainedCommand, { stdin: null });
|
|
25789
|
+
if (!(retainedCommand.notFoundExitCodes ?? []).includes(retained.exitCode)) {
|
|
25790
|
+
throw new Error("DeepSeek OS credential removal could not be verified.");
|
|
25791
|
+
}
|
|
25792
|
+
}
|
|
25793
|
+
};
|
|
25794
|
+
}
|
|
25795
|
+
return {
|
|
25796
|
+
read: async () => {
|
|
25797
|
+
const raw = await readInferencePrivateFile(path, "DeepSeek Harness credential file");
|
|
25798
|
+
return raw === null ? null : parseCredential(raw);
|
|
25799
|
+
},
|
|
25800
|
+
write: async (apiKey) => {
|
|
25801
|
+
const serialized = serializeCredential(apiKey);
|
|
25802
|
+
await writeAtomicInferencePrivateFile(path, serialized);
|
|
25803
|
+
const retained = await readInferencePrivateFile(path, "DeepSeek Harness credential file");
|
|
25804
|
+
if (retained !== serialized) throw new Error("DeepSeek credential write could not be verified.");
|
|
25805
|
+
return parseCredential(serialized);
|
|
25806
|
+
},
|
|
25807
|
+
remove: async () => {
|
|
25808
|
+
await clearInferencePrivateFile(path, "DeepSeek Harness credential file");
|
|
25809
|
+
}
|
|
25810
|
+
};
|
|
25811
|
+
};
|
|
25812
|
+
}
|
|
25813
|
+
});
|
|
25814
|
+
|
|
24725
25815
|
// lib/inference-host/durable-adapter.ts
|
|
24726
25816
|
var DURABLE_INFERENCE_ADAPTER_IDS, isDurableInferenceAdapterId, durableAdapterDisplayName;
|
|
24727
25817
|
var init_durable_adapter = __esm({
|
|
@@ -24729,12 +25819,14 @@ var init_durable_adapter = __esm({
|
|
|
24729
25819
|
"use strict";
|
|
24730
25820
|
DURABLE_INFERENCE_ADAPTER_IDS = [
|
|
24731
25821
|
"codex",
|
|
24732
|
-
"copilot"
|
|
25822
|
+
"copilot",
|
|
25823
|
+
"deepseek-harness"
|
|
24733
25824
|
];
|
|
24734
25825
|
isDurableInferenceAdapterId = (value) => DURABLE_INFERENCE_ADAPTER_IDS.includes(value);
|
|
24735
25826
|
durableAdapterDisplayName = (adapter) => ({
|
|
24736
25827
|
codex: "Codex",
|
|
24737
|
-
copilot: "GitHub Copilot"
|
|
25828
|
+
copilot: "GitHub Copilot",
|
|
25829
|
+
"deepseek-harness": "DeepSeek Harness"
|
|
24738
25830
|
})[adapter];
|
|
24739
25831
|
}
|
|
24740
25832
|
});
|
|
@@ -24743,13 +25835,13 @@ var init_durable_adapter = __esm({
|
|
|
24743
25835
|
import {
|
|
24744
25836
|
createCipheriv,
|
|
24745
25837
|
createDecipheriv,
|
|
24746
|
-
createHash as
|
|
25838
|
+
createHash as createHash6,
|
|
24747
25839
|
createPrivateKey,
|
|
24748
25840
|
createPublicKey,
|
|
24749
25841
|
diffieHellman,
|
|
24750
25842
|
generateKeyPairSync,
|
|
24751
25843
|
hkdfSync,
|
|
24752
|
-
randomBytes as
|
|
25844
|
+
randomBytes as randomBytes5
|
|
24753
25845
|
} from "node:crypto";
|
|
24754
25846
|
var ENVELOPE_SUITE, JOB_KEY_PAYLOAD_SCHEMA_VERSION, WRAP_HKDF_INFO, PAYLOAD_HKDF_INFO, X25519_PKCS8_PREFIX, X25519_SPKI_PREFIX, ExternalInferenceEnvelopeError, canonicalize, canonicalEnvelopeAadBytes, externalInferenceSha256, decodeCanonicalBase64Url, rawPrivateKey, rawPublicKey, rawPublicBytes, aesGcmDecrypt, aesGcmEncrypt, assertIdentity, validatePlaintext, generateExternalInferenceEnvelopeKeyPair, externalInferenceEnvelopePublicKey, deriveKey, deriveExternalInferencePayloadKey, unwrapExternalInferenceJobKey, decryptExternalInferenceJobInput, decryptExternalInferenceClaim, sealExternalInferenceCandidate;
|
|
24755
25847
|
var init_crypto = __esm({
|
|
@@ -24782,7 +25874,7 @@ var init_crypto = __esm({
|
|
|
24782
25874
|
const aad = envelopeAadSchema.parse(input);
|
|
24783
25875
|
return Buffer.from(JSON.stringify(canonicalize(aad)), "utf8");
|
|
24784
25876
|
};
|
|
24785
|
-
externalInferenceSha256 = (value) =>
|
|
25877
|
+
externalInferenceSha256 = (value) => createHash6("sha256").update(value).digest("hex");
|
|
24786
25878
|
decodeCanonicalBase64Url = (value, fieldName, expectedBytes) => {
|
|
24787
25879
|
if (!/^[A-Za-z0-9_-]+$/u.test(value)) {
|
|
24788
25880
|
throw new ExternalInferenceEnvelopeError("invalid_encoding", `${fieldName} is invalid.`);
|
|
@@ -24881,7 +25973,7 @@ var init_crypto = __esm({
|
|
|
24881
25973
|
return Buffer.from(hkdfSync(
|
|
24882
25974
|
"sha256",
|
|
24883
25975
|
root,
|
|
24884
|
-
|
|
25976
|
+
createHash6("sha256").update(aadBytes).digest(),
|
|
24885
25977
|
info,
|
|
24886
25978
|
32
|
|
24887
25979
|
));
|
|
@@ -25023,7 +26115,7 @@ var init_crypto = __esm({
|
|
|
25023
26115
|
"External inference candidate must not be empty."
|
|
25024
26116
|
);
|
|
25025
26117
|
}
|
|
25026
|
-
const nonce = options.nonce ? Buffer.from(options.nonce) :
|
|
26118
|
+
const nonce = options.nonce ? Buffer.from(options.nonce) : randomBytes5(12);
|
|
25027
26119
|
if (nonce.length !== 12) {
|
|
25028
26120
|
throw new ExternalInferenceEnvelopeError(
|
|
25029
26121
|
"invalid_nonce",
|
|
@@ -31295,7 +32387,7 @@ var require_ajv = __commonJS({
|
|
|
31295
32387
|
});
|
|
31296
32388
|
|
|
31297
32389
|
// lib/inference-host/runner.ts
|
|
31298
|
-
import { createHash as
|
|
32390
|
+
import { createHash as createHash7, randomUUID as randomUUID3 } from "node:crypto";
|
|
31299
32391
|
function createDefaultInferenceHostRunnerDependencies(options) {
|
|
31300
32392
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
31301
32393
|
return {
|
|
@@ -31330,7 +32422,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
|
|
|
31330
32422
|
envelopePublicKey: options.envelopePublicKey
|
|
31331
32423
|
};
|
|
31332
32424
|
}
|
|
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;
|
|
32425
|
+
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, DEFAULT_AGENT_RATE_LIMIT_COOLDOWN_MS, DEFAULT_AGENT_QUOTA_COOLDOWN_MS, DEFAULT_AGENT_TRANSIENT_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;
|
|
31334
32426
|
var init_runner = __esm({
|
|
31335
32427
|
"lib/inference-host/runner.ts"() {
|
|
31336
32428
|
"use strict";
|
|
@@ -31356,6 +32448,9 @@ var init_runner = __esm({
|
|
|
31356
32448
|
MIN_HOST_HEARTBEAT_GAP_DIAGNOSTIC_MS = 1e4;
|
|
31357
32449
|
HOST_HEARTBEAT_GAP_DIAGNOSTIC_FACTOR = 3;
|
|
31358
32450
|
DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
32451
|
+
DEFAULT_AGENT_RATE_LIMIT_COOLDOWN_MS = 6e4;
|
|
32452
|
+
DEFAULT_AGENT_QUOTA_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
32453
|
+
DEFAULT_AGENT_TRANSIENT_COOLDOWN_MS = 5e3;
|
|
31359
32454
|
MIN_CLAIM_START_WINDOW_MS = 5e3;
|
|
31360
32455
|
MAX_ATTEMPT_START_RETRY_DELAY_MS = 15e3;
|
|
31361
32456
|
UNBOUNDED_AVAILABLE_SLOTS = Number.MAX_SAFE_INTEGER;
|
|
@@ -31622,7 +32717,7 @@ var init_runner = __esm({
|
|
|
31622
32717
|
attempts
|
|
31623
32718
|
};
|
|
31624
32719
|
};
|
|
31625
|
-
sha256 = (value) =>
|
|
32720
|
+
sha256 = (value) => createHash7("sha256").update(value, "utf8").digest("hex");
|
|
31626
32721
|
stableOperationId = (kind, parts) => `${kind}_${sha256(JSON.stringify(parts)).slice(0, 48)}`;
|
|
31627
32722
|
buildAttemptStartRequest = (claim, attemptId, startedAt) => attemptStartRequestSchema.parse({
|
|
31628
32723
|
schema_version: "external_inference_attempt_start_v1",
|
|
@@ -31895,7 +32990,7 @@ var init_runner = __esm({
|
|
|
31895
32990
|
membershipFailureDisposition = (failure) => {
|
|
31896
32991
|
if (failure.dispatchOutcome === "outcome_unknown") return "quarantine_ambiguous";
|
|
31897
32992
|
if (failure.category === "auth" || ["auth_expired", "managed_chatgpt_auth_required", "invalid_account_metadata"].includes(failure.code)) return "cascade_disable";
|
|
31898
|
-
if (failure.category === "quota" || ["quota_exceeded", "codex_rate_limited"].includes(failure.code)) return "cascade_cooldown";
|
|
32993
|
+
if (failure.category === "quota" || ["quota_exceeded", "codex_rate_limited", "provider_rate_limited"].includes(failure.code)) return "cascade_cooldown";
|
|
31899
32994
|
if (failure.retryable && (["adapter", "network", "transport"].includes(failure.category) || failure.code === "rpc_timeout")) return "retry_same_host";
|
|
31900
32995
|
if (["model_unavailable", "reasoning_effort_unavailable"].includes(failure.code)) return "cascade_cooldown";
|
|
31901
32996
|
if ([
|
|
@@ -32169,6 +33264,43 @@ var init_runner = __esm({
|
|
|
32169
33264
|
const agentRuntimeSettings = settings.agentRuntime;
|
|
32170
33265
|
agentLoop = (async () => {
|
|
32171
33266
|
while (!agentAbort.signal.aborted) {
|
|
33267
|
+
const existingFence = await readInferenceAgentFailureFence(
|
|
33268
|
+
agentRuntimeSettings.statePath
|
|
33269
|
+
);
|
|
33270
|
+
if (existingFence) {
|
|
33271
|
+
if (existingFence.adapter_id !== settings.adapterId || existingFence.host_id !== localState.host_id) {
|
|
33272
|
+
throw new InferenceHostRecoveryRequiredError(
|
|
33273
|
+
"Inference Agent failure fence belongs to another host or adapter."
|
|
33274
|
+
);
|
|
33275
|
+
}
|
|
33276
|
+
if (existingFence.retry_at === null) {
|
|
33277
|
+
emitDiagnostic("agent_runtime_quarantined", {
|
|
33278
|
+
assignment_id: existingFence.assignment_id,
|
|
33279
|
+
failure_category: existingFence.failure_category,
|
|
33280
|
+
failure_code: existingFence.failure_code,
|
|
33281
|
+
dispatch_outcome: existingFence.dispatch_outcome
|
|
33282
|
+
});
|
|
33283
|
+
return;
|
|
33284
|
+
}
|
|
33285
|
+
const retryAtMs = Date.parse(existingFence.retry_at);
|
|
33286
|
+
if (retryAtMs > now()) {
|
|
33287
|
+
emitDiagnostic("agent_runtime_cooldown", {
|
|
33288
|
+
assignment_id: existingFence.assignment_id,
|
|
33289
|
+
failure_category: existingFence.failure_category,
|
|
33290
|
+
failure_code: existingFence.failure_code,
|
|
33291
|
+
dispatch_outcome: existingFence.dispatch_outcome,
|
|
33292
|
+
cooldown_until: existingFence.retry_at
|
|
33293
|
+
});
|
|
33294
|
+
if (this.options.once) return;
|
|
33295
|
+
try {
|
|
33296
|
+
await sleep4(Math.max(MIN_SLEEP_MS, retryAtMs - now()), agentAbort.signal);
|
|
33297
|
+
} catch {
|
|
33298
|
+
return;
|
|
33299
|
+
}
|
|
33300
|
+
continue;
|
|
33301
|
+
}
|
|
33302
|
+
await clearInferenceAgentFailureFence(agentRuntimeSettings.statePath);
|
|
33303
|
+
}
|
|
32172
33304
|
const agentRuntime = new InferenceAgentRuntime({
|
|
32173
33305
|
adapterId: settings.adapterId,
|
|
32174
33306
|
hostId: localState.host_id,
|
|
@@ -32189,6 +33321,51 @@ var init_runner = __esm({
|
|
|
32189
33321
|
requestDrain("authority_lost");
|
|
32190
33322
|
return;
|
|
32191
33323
|
}
|
|
33324
|
+
if (error48 instanceof CodexAppServerError) {
|
|
33325
|
+
const failure = classifyFailure(error48);
|
|
33326
|
+
const providerLimited = failure.category === "auth" || failure.category === "quota" || ["quota_exceeded", "codex_rate_limited", "provider_rate_limited"].includes(failure.code);
|
|
33327
|
+
const deepSeekTransient = settings.adapterId === "deepseek-harness" && failure.retryable;
|
|
33328
|
+
if (failure.dispatchOutcome === "outcome_unknown" || providerLimited || deepSeekTransient) {
|
|
33329
|
+
const runtimeState = await readInferenceAgentRuntimeState(
|
|
33330
|
+
agentRuntimeSettings.statePath
|
|
33331
|
+
);
|
|
33332
|
+
const retryAtMs = failure.dispatchOutcome === "outcome_unknown" || failure.category === "auth" && settings.adapterId === "deepseek-harness" ? null : error48.retryAtMs !== null && error48.retryAtMs > now() ? error48.retryAtMs : now() + (failure.category === "quota" || failure.code === "quota_exceeded" ? DEFAULT_AGENT_QUOTA_COOLDOWN_MS : failure.category === "auth" ? DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS : failure.code === "provider_rate_limited" || failure.code === "codex_rate_limited" ? DEFAULT_AGENT_RATE_LIMIT_COOLDOWN_MS : DEFAULT_AGENT_TRANSIENT_COOLDOWN_MS);
|
|
33333
|
+
await writeInferenceAgentFailureFence(agentRuntimeSettings.statePath, {
|
|
33334
|
+
schema_version: "vtx_inference_agent_failure_fence_v1",
|
|
33335
|
+
adapter_id: settings.adapterId,
|
|
33336
|
+
host_id: localState.host_id,
|
|
33337
|
+
assignment_id: runtimeState?.schema_version === "vtx_inference_agent_runtime_v3" ? runtimeState.assignment.assignment_id : null,
|
|
33338
|
+
failure_category: safeFailureCode(failure.category, "adapter"),
|
|
33339
|
+
failure_code: safeFailureCode(failure.code, "adapter_failure"),
|
|
33340
|
+
dispatch_outcome: failure.dispatchOutcome,
|
|
33341
|
+
retry_at: retryAtMs === null ? null : isoAt(retryAtMs),
|
|
33342
|
+
created_at: isoAt(now())
|
|
33343
|
+
});
|
|
33344
|
+
if (failure.dispatchOutcome !== "outcome_unknown") {
|
|
33345
|
+
try {
|
|
33346
|
+
await agentRuntime.releaseAfterProviderFailure(failure.code);
|
|
33347
|
+
} catch {
|
|
33348
|
+
}
|
|
33349
|
+
}
|
|
33350
|
+
emitDiagnostic(
|
|
33351
|
+
retryAtMs === null ? "agent_runtime_quarantined" : "agent_runtime_cooldown",
|
|
33352
|
+
{
|
|
33353
|
+
assignment_id: runtimeState?.schema_version === "vtx_inference_agent_runtime_v3" ? runtimeState.assignment.assignment_id : null,
|
|
33354
|
+
failure_category: failure.category,
|
|
33355
|
+
failure_code: failure.code,
|
|
33356
|
+
dispatch_outcome: failure.dispatchOutcome,
|
|
33357
|
+
cooldown_until: retryAtMs === null ? null : isoAt(retryAtMs)
|
|
33358
|
+
}
|
|
33359
|
+
);
|
|
33360
|
+
if (this.options.once || retryAtMs === null) return;
|
|
33361
|
+
try {
|
|
33362
|
+
await sleep4(Math.max(MIN_SLEEP_MS, retryAtMs - now()), agentAbort.signal);
|
|
33363
|
+
} catch {
|
|
33364
|
+
return;
|
|
33365
|
+
}
|
|
33366
|
+
continue;
|
|
33367
|
+
}
|
|
33368
|
+
}
|
|
32192
33369
|
emitDiagnostic("agent_runtime_retry", {
|
|
32193
33370
|
error_code: error48 && typeof error48 === "object" && "code" in error48 ? String(error48.code) : "agent_runtime_error"
|
|
32194
33371
|
});
|
|
@@ -32201,7 +33378,13 @@ var init_runner = __esm({
|
|
|
32201
33378
|
}
|
|
32202
33379
|
}
|
|
32203
33380
|
})();
|
|
32204
|
-
void agentLoop.catch(() =>
|
|
33381
|
+
void agentLoop.catch((error48) => {
|
|
33382
|
+
if (agentAbort.signal.aborted) return;
|
|
33383
|
+
emitDiagnostic("agent_runtime_fence_failed", {
|
|
33384
|
+
error_code: error48 && typeof error48 === "object" && "code" in error48 ? String(error48.code) : "agent_runtime_fence_failed"
|
|
33385
|
+
});
|
|
33386
|
+
requestDrain("agent_recovery_failed");
|
|
33387
|
+
});
|
|
32205
33388
|
}
|
|
32206
33389
|
const existingReceipt = await this.dependencies.receiptStore.read();
|
|
32207
33390
|
const identityMatches = existingReceipt && existingReceipt.host_id === localState.host_id && existingReceipt.host_generation === localState.host_generation && existingReceipt.key_generation === localState.key_generation;
|
|
@@ -33379,10 +34562,10 @@ var init_runner = __esm({
|
|
|
33379
34562
|
if (error48 instanceof InferenceHostRunnerError && error48.code === "terminal_outcome_unconfirmed") {
|
|
33380
34563
|
throw error48;
|
|
33381
34564
|
}
|
|
33382
|
-
if (error48 instanceof CodexAppServerError && error48.retryAtMs !== null && ["quota_exceeded", "codex_rate_limited"].includes(error48.code)) {
|
|
34565
|
+
if (error48 instanceof CodexAppServerError && error48.retryAtMs !== null && ["quota_exceeded", "codex_rate_limited", "provider_rate_limited"].includes(error48.code)) {
|
|
33383
34566
|
options.onProviderCooldown?.({
|
|
33384
34567
|
retryAtMs: error48.retryAtMs,
|
|
33385
|
-
reason: error48.code === "quota_exceeded" ? "quota_exceeded" : "codex_rate_limited",
|
|
34568
|
+
reason: error48.code === "quota_exceeded" ? "quota_exceeded" : error48.code === "provider_rate_limited" ? "provider_rate_limited" : "codex_rate_limited",
|
|
33386
34569
|
rateLimits: error48.rateLimits
|
|
33387
34570
|
});
|
|
33388
34571
|
}
|
|
@@ -33597,6 +34780,9 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33597
34780
|
stop() {
|
|
33598
34781
|
this.stopped = true;
|
|
33599
34782
|
}
|
|
34783
|
+
async releaseAfterProviderFailure(reasonCode) {
|
|
34784
|
+
await this.releaseForHostStop(safeFailureCode(reasonCode, "provider_failure"));
|
|
34785
|
+
}
|
|
33600
34786
|
async run(signal) {
|
|
33601
34787
|
let exitedNormally = false;
|
|
33602
34788
|
try {
|
|
@@ -33613,10 +34799,14 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33613
34799
|
}
|
|
33614
34800
|
}
|
|
33615
34801
|
async runSingle(signal) {
|
|
34802
|
+
let exitedNormally = false;
|
|
33616
34803
|
try {
|
|
33617
34804
|
await this.runOnce(signal);
|
|
34805
|
+
exitedNormally = true;
|
|
33618
34806
|
} finally {
|
|
33619
|
-
|
|
34807
|
+
if (exitedNormally || this.stopped || signal?.aborted) {
|
|
34808
|
+
await this.releaseForHostStop();
|
|
34809
|
+
}
|
|
33620
34810
|
}
|
|
33621
34811
|
}
|
|
33622
34812
|
async runOnce(signal) {
|
|
@@ -33662,7 +34852,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33662
34852
|
}
|
|
33663
34853
|
if (!state) {
|
|
33664
34854
|
const assignment2 = await this.options.controlClient.nextAssignment({
|
|
33665
|
-
operation_id:
|
|
34855
|
+
operation_id: randomUUID3(),
|
|
33666
34856
|
host_id: this.options.hostId,
|
|
33667
34857
|
requested_at: nowIso()
|
|
33668
34858
|
}, { signal });
|
|
@@ -33695,7 +34885,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33695
34885
|
state = await this.resolvePendingDecision(state, signal);
|
|
33696
34886
|
let assignment = state.assignment;
|
|
33697
34887
|
const preTurnHeartbeat = await this.options.controlClient.heartbeat({
|
|
33698
|
-
operation_id:
|
|
34888
|
+
operation_id: randomUUID3(),
|
|
33699
34889
|
host_id: this.options.hostId,
|
|
33700
34890
|
assignment_id: assignment.assignment_id,
|
|
33701
34891
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33720,7 +34910,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33720
34910
|
const heartbeatTask = (async () => {
|
|
33721
34911
|
while (!heartbeatStopped && !turnAbort.signal.aborted) {
|
|
33722
34912
|
const heartbeat = await this.options.controlClient.heartbeat({
|
|
33723
|
-
operation_id:
|
|
34913
|
+
operation_id: randomUUID3(),
|
|
33724
34914
|
host_id: this.options.hostId,
|
|
33725
34915
|
assignment_id: assignment.assignment_id,
|
|
33726
34916
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33777,7 +34967,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33777
34967
|
return { success: false, value: { error: "invalid_data_request" } };
|
|
33778
34968
|
}
|
|
33779
34969
|
const value = await this.options.controlClient.dataCall({
|
|
33780
|
-
operation_id:
|
|
34970
|
+
operation_id: randomUUID3(),
|
|
33781
34971
|
host_id: this.options.hostId,
|
|
33782
34972
|
assignment_id: assignment.assignment_id,
|
|
33783
34973
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33801,7 +34991,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33801
34991
|
return { success: false, value: { error: "decision_outcome_unresolved" } };
|
|
33802
34992
|
}
|
|
33803
34993
|
const pending = {
|
|
33804
|
-
operation_id:
|
|
34994
|
+
operation_id: randomUUID3(),
|
|
33805
34995
|
candidate,
|
|
33806
34996
|
observed_at: nowIso(),
|
|
33807
34997
|
provenance: {
|
|
@@ -33875,7 +35065,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33875
35065
|
const nextWakeAtMs = this.now() + wakeSeconds * 1e3;
|
|
33876
35066
|
const scheduledWakeAt = new Date(nextWakeAtMs).toISOString();
|
|
33877
35067
|
const wakeHeartbeat = await this.options.controlClient.heartbeat({
|
|
33878
|
-
operation_id:
|
|
35068
|
+
operation_id: randomUUID3(),
|
|
33879
35069
|
host_id: this.options.hostId,
|
|
33880
35070
|
assignment_id: assignment.assignment_id,
|
|
33881
35071
|
assignment_generation: assignment.assignment_generation,
|
|
@@ -33993,7 +35183,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
33993
35183
|
if (state?.schema_version !== "vtx_inference_agent_runtime_v3" || state.adapter_id !== this.options.adapterId) return "cancelled";
|
|
33994
35184
|
const requestedAt = new Date(this.now()).toISOString();
|
|
33995
35185
|
const heartbeat = await this.options.controlClient.heartbeat({
|
|
33996
|
-
operation_id:
|
|
35186
|
+
operation_id: randomUUID3(),
|
|
33997
35187
|
host_id: this.options.hostId,
|
|
33998
35188
|
assignment_id: state.assignment.assignment_id,
|
|
33999
35189
|
assignment_generation: state.assignment.assignment_generation,
|
|
@@ -34014,7 +35204,7 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
34014
35204
|
}
|
|
34015
35205
|
return this.stopped || signal?.aborted ? "stopped" : "ready";
|
|
34016
35206
|
}
|
|
34017
|
-
async releaseForHostStop() {
|
|
35207
|
+
async releaseForHostStop(reasonCode = "host_stopped") {
|
|
34018
35208
|
const recovered = await readInferenceAgentRuntimeState(this.options.statePath);
|
|
34019
35209
|
if (!recovered) return;
|
|
34020
35210
|
let state;
|
|
@@ -34040,11 +35230,11 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
34040
35230
|
}
|
|
34041
35231
|
if (state.pending_decision) return;
|
|
34042
35232
|
await this.options.controlClient.releaseAssignment({
|
|
34043
|
-
operation_id:
|
|
35233
|
+
operation_id: randomUUID3(),
|
|
34044
35234
|
host_id: this.options.hostId,
|
|
34045
35235
|
assignment_id: state.assignment.assignment_id,
|
|
34046
35236
|
assignment_generation: state.assignment.assignment_generation,
|
|
34047
|
-
reason_code:
|
|
35237
|
+
reason_code: reasonCode,
|
|
34048
35238
|
requested_at: new Date(this.now()).toISOString()
|
|
34049
35239
|
}, {});
|
|
34050
35240
|
if (state.thread) await this.options.adapter.releaseThread(state.thread);
|
|
@@ -34056,11 +35246,11 @@ VTX supplies no trading prompt or prepared market context. At your own cadence,
|
|
|
34056
35246
|
|
|
34057
35247
|
// lib/inference-host/service.ts
|
|
34058
35248
|
import { spawn as spawn6 } from "node:child_process";
|
|
34059
|
-
import { randomUUID as
|
|
35249
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
34060
35250
|
import { createWriteStream, readFileSync } from "node:fs";
|
|
34061
|
-
import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as
|
|
35251
|
+
import { access as access3, chmod as chmod3, mkdir as mkdir3, readFile as readFile5, rm as rm6, writeFile as writeFile2 } from "node:fs/promises";
|
|
34062
35252
|
import { homedir as homedir2 } from "node:os";
|
|
34063
|
-
import { dirname as
|
|
35253
|
+
import { dirname as dirname5, join as join7, resolve as resolve4 } from "node:path";
|
|
34064
35254
|
var SERVICE_NAME, SYSTEMD_UNIT, LAUNCHD_LABEL, SERVICE_COOPERATIVE_STOP_SECONDS, INFERENCE_HOST_SERVICE_DRAIN_COMMAND, inferenceHostServiceChildEnvironment, isWindowsSubsystemForLinux, inferenceHostServiceManifestPath, inferenceHostServiceDesiredPath, inferenceHostServiceLogPath, inferenceHostServiceRuntimePath, xmlEscape, plistEscape, systemdQuote, defaultRunCommand, managerName, assertRuntimeEnvironment, withoutConcurrencyLimit, assertServicePath, manifestGeneration, assertWorker, assertManifest, assertServiceRuntimeState, assertDesiredState, readInferenceHostServiceManifest, readManifestAcrossAtomicReplacement, readInferenceHostServiceRuntime, readRuntimeAcrossAtomicReplacement, readInferenceHostServiceDesired, readDesiredAcrossAtomicReplacement, writeDesired, runtimeEnvironment, serviceArguments, windowsOwnedCommandLine, vbScriptString, windowsServiceLauncher, windowsTaskXml, systemdUnit, launchAgentPlist, sameWorker, sameServiceDefinition, sameWorkerSet, InferenceHostServiceManager, appendServiceLog, spawnInferenceHostServiceChild, runInferenceHostServiceSupervisor;
|
|
34065
35255
|
var init_service = __esm({
|
|
34066
35256
|
"lib/inference-host/service.ts"() {
|
|
@@ -34529,8 +35719,8 @@ WantedBy=default.target
|
|
|
34529
35719
|
}
|
|
34530
35720
|
definitionPath() {
|
|
34531
35721
|
if (this.platform === "win32") return `${this.config.supervisorStatePath}.service-task.xml`;
|
|
34532
|
-
if (this.platform === "darwin") return
|
|
34533
|
-
return
|
|
35722
|
+
if (this.platform === "darwin") return join7(this.home, "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
35723
|
+
return join7(this.home, ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
34534
35724
|
}
|
|
34535
35725
|
windowsLauncherPath() {
|
|
34536
35726
|
return `${this.config.supervisorStatePath}.service-launcher.vbs`;
|
|
@@ -34581,7 +35771,7 @@ WantedBy=default.target
|
|
|
34581
35771
|
const previousRuntimeUpdatedAt = previousRuntime?.manifest_generation === manifest.generation ? Date.parse(previousRuntime.updated_at) : Number.NaN;
|
|
34582
35772
|
const restoredManifest = preserveGeneration ? manifest : assertManifest({
|
|
34583
35773
|
...manifest,
|
|
34584
|
-
generation:
|
|
35774
|
+
generation: randomUUID4(),
|
|
34585
35775
|
installed_at: this.now().toISOString()
|
|
34586
35776
|
});
|
|
34587
35777
|
await writeAtomicInferencePrivateFile(
|
|
@@ -34663,7 +35853,7 @@ ${result2.stderr}`)) {
|
|
|
34663
35853
|
await writeAtomicInferencePrivateFile(this.manifestPath(), `${JSON.stringify(manifest, null, 2)}
|
|
34664
35854
|
`);
|
|
34665
35855
|
await writeDesired(this.desiredPath(), desiredRunning, this.now());
|
|
34666
|
-
await mkdir3(
|
|
35856
|
+
await mkdir3(dirname5(this.definitionPath()), { recursive: true, mode: 448 });
|
|
34667
35857
|
if (this.platform === "win32") {
|
|
34668
35858
|
await writeAtomicInferencePrivateFile(
|
|
34669
35859
|
this.windowsLauncherPath(),
|
|
@@ -34712,13 +35902,13 @@ ${cleanup.stderr}`)) {
|
|
|
34712
35902
|
);
|
|
34713
35903
|
}
|
|
34714
35904
|
}
|
|
34715
|
-
await
|
|
35905
|
+
await rm6(this.definitionPath(), { force: true }).catch(() => void 0);
|
|
34716
35906
|
if (this.platform === "win32") {
|
|
34717
|
-
await
|
|
35907
|
+
await rm6(this.windowsLauncherPath(), { force: true }).catch(() => void 0);
|
|
34718
35908
|
}
|
|
34719
|
-
await
|
|
34720
|
-
await
|
|
34721
|
-
await
|
|
35909
|
+
await rm6(this.manifestPath(), { force: true }).catch(() => void 0);
|
|
35910
|
+
await rm6(this.desiredPath(), { force: true }).catch(() => void 0);
|
|
35911
|
+
await rm6(this.runtimePath(), { force: true }).catch(() => void 0);
|
|
34722
35912
|
if (this.platform === "linux") {
|
|
34723
35913
|
await this.runCommand("systemctl", ["--user", "daemon-reload"]).catch(() => void 0);
|
|
34724
35914
|
}
|
|
@@ -34867,7 +36057,7 @@ ${cleanup.stderr}`)) {
|
|
|
34867
36057
|
].sort((left, right) => left.instance_name.localeCompare(right.instance_name));
|
|
34868
36058
|
const manifest = assertManifest({
|
|
34869
36059
|
schema_version: "vtx_inference_service_v3",
|
|
34870
|
-
generation:
|
|
36060
|
+
generation: randomUUID4(),
|
|
34871
36061
|
installed_at: this.now().toISOString(),
|
|
34872
36062
|
executable: this.executable,
|
|
34873
36063
|
script: this.script,
|
|
@@ -35081,7 +36271,7 @@ ${result2.stderr}`)) {
|
|
|
35081
36271
|
if (remaining.length === 0) return await this.uninstallUnlocked();
|
|
35082
36272
|
return await this.replaceManifestUnlocked({
|
|
35083
36273
|
...manifest,
|
|
35084
|
-
generation:
|
|
36274
|
+
generation: randomUUID4(),
|
|
35085
36275
|
installed_at: this.now().toISOString(),
|
|
35086
36276
|
workers: remaining
|
|
35087
36277
|
}, await readInferenceHostServiceDesired(this.desiredPath()));
|
|
@@ -35104,12 +36294,12 @@ ${result2.stderr}`)) {
|
|
|
35104
36294
|
${result2.stderr}`)) {
|
|
35105
36295
|
throw new Error(`Background service uninstall failed: ${result2.stderr.trim()}`);
|
|
35106
36296
|
}
|
|
35107
|
-
await
|
|
35108
|
-
if (this.platform === "win32") await
|
|
36297
|
+
await rm6(this.definitionPath(), { force: true });
|
|
36298
|
+
if (this.platform === "win32") await rm6(this.windowsLauncherPath(), { force: true });
|
|
35109
36299
|
if (this.platform === "linux") await this.runCommand("systemctl", ["--user", "daemon-reload"]);
|
|
35110
|
-
await
|
|
35111
|
-
await
|
|
35112
|
-
await
|
|
36300
|
+
await rm6(this.manifestPath(), { force: true });
|
|
36301
|
+
await rm6(this.desiredPath(), { force: true });
|
|
36302
|
+
await rm6(this.runtimePath(), { force: true });
|
|
35113
36303
|
return {
|
|
35114
36304
|
installed: false,
|
|
35115
36305
|
desired_running: false,
|
|
@@ -35123,7 +36313,7 @@ ${result2.stderr}`)) {
|
|
|
35123
36313
|
}
|
|
35124
36314
|
};
|
|
35125
36315
|
appendServiceLog = async (path, event, fields = {}) => {
|
|
35126
|
-
await mkdir3(
|
|
36316
|
+
await mkdir3(dirname5(path), { recursive: true, mode: 448 });
|
|
35127
36317
|
const stream = createWriteStream(path, { flags: "a", mode: 384 });
|
|
35128
36318
|
await new Promise((resolvePromise, reject) => {
|
|
35129
36319
|
stream.once("error", reject);
|
|
@@ -35471,11 +36661,11 @@ __export(cli_exports, {
|
|
|
35471
36661
|
registerInferenceHostServiceControlInput: () => registerInferenceHostServiceControlInput,
|
|
35472
36662
|
runInferenceHostCli: () => runInferenceHostCli
|
|
35473
36663
|
});
|
|
35474
|
-
import { createHash as
|
|
36664
|
+
import { createHash as createHash8, randomUUID as randomUUID5 } from "node:crypto";
|
|
35475
36665
|
import { spawn as spawn7 } from "node:child_process";
|
|
35476
|
-
import { lstat as lstat4, realpath as
|
|
36666
|
+
import { lstat as lstat4, realpath as realpath5, rm as rm7 } from "node:fs/promises";
|
|
35477
36667
|
import { hostname as osHostname } from "node:os";
|
|
35478
|
-
import { join as
|
|
36668
|
+
import { join as join8, resolve as resolve5 } from "node:path";
|
|
35479
36669
|
async function runInferenceHostCli(argv2, env = process.env, dependencies = {}) {
|
|
35480
36670
|
const warnings = [];
|
|
35481
36671
|
try {
|
|
@@ -35505,6 +36695,9 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35505
36695
|
if (parsed.command === "codex-login") {
|
|
35506
36696
|
return await codexLogin(config2, parsed, env, dependencies);
|
|
35507
36697
|
}
|
|
36698
|
+
if (parsed.command === "deepseek-login") {
|
|
36699
|
+
return await deepSeekLogin(config2, parsed, dependencies);
|
|
36700
|
+
}
|
|
35508
36701
|
if (parsed.command === "run") {
|
|
35509
36702
|
return await runHost(config2, parsed, env, dependencies, warnings);
|
|
35510
36703
|
}
|
|
@@ -35597,11 +36790,14 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35597
36790
|
if (parsed.command === "codex-logout") {
|
|
35598
36791
|
return await codexLogout(config2, parsed, env, dependencies);
|
|
35599
36792
|
}
|
|
36793
|
+
if (parsed.command === "deepseek-logout") {
|
|
36794
|
+
return await deepSeekLogout(config2, parsed, dependencies);
|
|
36795
|
+
}
|
|
35600
36796
|
if (parsed.command === "revoke") {
|
|
35601
36797
|
return await cleanupLogin(config2, parsed, dependencies, warnings, true);
|
|
35602
36798
|
}
|
|
35603
36799
|
throw new Error(
|
|
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]"
|
|
36800
|
+
"Usage: vtx inference-host <login|codex-login|deepseek-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|deepseek-logout|revoke> [--json]"
|
|
35605
36801
|
);
|
|
35606
36802
|
} catch (error48) {
|
|
35607
36803
|
return {
|
|
@@ -35612,7 +36808,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
35612
36808
|
};
|
|
35613
36809
|
}
|
|
35614
36810
|
}
|
|
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;
|
|
36811
|
+
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, deepSeekCredentialStore, deepSeekLogin, deepSeekLogout, 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;
|
|
35616
36812
|
var init_cli = __esm({
|
|
35617
36813
|
"lib/inference-host/cli.ts"() {
|
|
35618
36814
|
"use strict";
|
|
@@ -35623,6 +36819,8 @@ var init_cli = __esm({
|
|
|
35623
36819
|
init_codex_adapter();
|
|
35624
36820
|
init_codex_recovery_process();
|
|
35625
36821
|
init_copilot_adapter();
|
|
36822
|
+
init_deepseek_harness_adapter();
|
|
36823
|
+
init_deepseek_credential_store();
|
|
35626
36824
|
init_durable_adapter();
|
|
35627
36825
|
init_codex_app_server();
|
|
35628
36826
|
init_codex_binary();
|
|
@@ -35706,6 +36904,7 @@ var init_cli = __esm({
|
|
|
35706
36904
|
Commands:
|
|
35707
36905
|
login Authorize the isolated VTX insights:inference grant
|
|
35708
36906
|
codex-login Sign the automated Codex host into a ChatGPT subscription
|
|
36907
|
+
deepseek-login Import a DeepSeek API key privately from stdin
|
|
35709
36908
|
run Run a supported durable inference adapter in the foreground
|
|
35710
36909
|
agent-connect Advertise a model from a compatible agent harness
|
|
35711
36910
|
agent-run Keep an agent-driven host online in the foreground
|
|
@@ -35724,11 +36923,12 @@ Commands:
|
|
|
35724
36923
|
logout Remove local VTX host state without revoking the grant
|
|
35725
36924
|
revoke Revoke the VTX grant and remove local host state
|
|
35726
36925
|
codex-logout Remove the automated host's dedicated Codex login
|
|
36926
|
+
deepseek-logout Remove the locally stored DeepSeek API key
|
|
35727
36927
|
|
|
35728
36928
|
Common options:
|
|
35729
36929
|
--json Emit machine-readable JSON
|
|
35730
36930
|
--instance NAME Target an isolated local subscription instance (default: default)
|
|
35731
|
-
--adapter ID Durable adapter: codex or
|
|
36931
|
+
--adapter ID Durable adapter: codex, copilot, or deepseek-harness
|
|
35732
36932
|
--max-concurrency N Optional positive-integer local slot limit (default: unlimited)
|
|
35733
36933
|
--help, -h Show this help
|
|
35734
36934
|
|
|
@@ -35744,6 +36944,8 @@ Durable service:
|
|
|
35744
36944
|
vtx inference-host codex-login --instance codex-2
|
|
35745
36945
|
vtx inference-host service install --instance codex-2
|
|
35746
36946
|
vtx inference-host service install --adapter copilot --instance copilot-1
|
|
36947
|
+
vtx inference-host deepseek-login --instance deepseek-1 < /private/path/deepseek.key
|
|
36948
|
+
vtx inference-host service install --adapter deepseek-harness --instance deepseek-1
|
|
35747
36949
|
vtx inference-host service uninstall --instance codex-2
|
|
35748
36950
|
vtx inference-host service recover --instance codex-1 --force-recovery
|
|
35749
36951
|
vtx inference-host service <start|stop|status|logs|recover|uninstall>
|
|
@@ -35850,7 +37052,7 @@ Durable service:
|
|
|
35850
37052
|
if (command === "agent-connect" && !displayNameExplicit) {
|
|
35851
37053
|
displayName = "Agent-driven inference host";
|
|
35852
37054
|
} else if (adapter && isDurableInferenceAdapterId(adapter) && !displayNameExplicit) {
|
|
35853
|
-
displayName = `${durableAdapterDisplayName(adapter)}
|
|
37055
|
+
displayName = `${durableAdapterDisplayName(adapter)} host`;
|
|
35854
37056
|
}
|
|
35855
37057
|
return {
|
|
35856
37058
|
command,
|
|
@@ -36007,10 +37209,10 @@ Durable service:
|
|
|
36007
37209
|
return raw !== null;
|
|
36008
37210
|
};
|
|
36009
37211
|
inspectCodexAuthentication = async (config2) => {
|
|
36010
|
-
const path =
|
|
37212
|
+
const path = join8(config2.codexHomePath, "auth.json");
|
|
36011
37213
|
try {
|
|
36012
37214
|
const before = await lstat4(path);
|
|
36013
|
-
const canonical = await
|
|
37215
|
+
const canonical = await realpath5(path);
|
|
36014
37216
|
const isPrivate = before.isFile() && !before.isSymbolicLink() && canonical === resolve5(path) && before.size <= 8 * 1024 * 1024 && (process.platform === "win32" || (before.mode & 63) === 0 && (typeof process.getuid !== "function" || before.uid === process.getuid()));
|
|
36015
37217
|
return { present: true, private: isPrivate };
|
|
36016
37218
|
} catch (error48) {
|
|
@@ -36025,7 +37227,7 @@ Durable service:
|
|
|
36025
37227
|
runtimeReceiptPath(config2),
|
|
36026
37228
|
"Inference host runtime receipt file"
|
|
36027
37229
|
);
|
|
36028
|
-
await
|
|
37230
|
+
await rm7(codexGuardianReceiptRoot(config2), { recursive: true, force: true });
|
|
36029
37231
|
await clearInferencePrivateFile(
|
|
36030
37232
|
codexRecoveryPath(config2),
|
|
36031
37233
|
"Codex attempt recovery file"
|
|
@@ -36034,6 +37236,7 @@ Durable service:
|
|
|
36034
37236
|
await clearInferenceAgentNextState(config2.statePath);
|
|
36035
37237
|
await clearInferenceForegroundAgentControlState(config2.statePath);
|
|
36036
37238
|
await clearCodexAgentRuntimeState(config2.statePath);
|
|
37239
|
+
await clearInferenceAgentFailureFence(config2.statePath);
|
|
36037
37240
|
await clearInferenceHostLocalState(config2.statePath);
|
|
36038
37241
|
};
|
|
36039
37242
|
assertDurableServiceUninstalled = async (config2) => {
|
|
@@ -36062,7 +37265,8 @@ Durable service:
|
|
|
36062
37265
|
const agentNextRecoveryPresent = await readInferenceAgentNextState(config2.statePath) !== null;
|
|
36063
37266
|
const foregroundAgentControlPresent = await readInferenceForegroundAgentControlState(config2.statePath) !== null;
|
|
36064
37267
|
const codexAgentRuntimePresent = await readCodexAgentRuntimeState(config2.statePath) !== null;
|
|
36065
|
-
|
|
37268
|
+
const agentFailureFencePresent = await readInferenceAgentFailureFence(config2.statePath) !== null;
|
|
37269
|
+
if (pendingAttempts > 0 || codexRecoveryPresent || serviceRecoveryPresent || revocationCheckpointPresent || agentAttemptPresent || agentNextRecoveryPresent || foregroundAgentControlPresent || codexAgentRuntimePresent || agentFailureFencePresent) {
|
|
36066
37270
|
throw new Error(
|
|
36067
37271
|
"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."
|
|
36068
37272
|
);
|
|
@@ -36132,8 +37336,10 @@ Durable service:
|
|
|
36132
37336
|
signal: options.signal
|
|
36133
37337
|
}).run();
|
|
36134
37338
|
};
|
|
36135
|
-
preparePortableDurableAdapter = async (adapterId, signal) => {
|
|
36136
|
-
const adapter = new CopilotSubscriptionAdapter()
|
|
37339
|
+
preparePortableDurableAdapter = async (adapterId, config2, signal) => {
|
|
37340
|
+
const adapter = adapterId === "copilot" ? new CopilotSubscriptionAdapter() : new DeepSeekHarnessAdapter({
|
|
37341
|
+
credentialStore: createDeepSeekHarnessCredentialStore(config2)
|
|
37342
|
+
});
|
|
36137
37343
|
return { adapter, preflight: await adapter.preflight(signal) };
|
|
36138
37344
|
};
|
|
36139
37345
|
defaultRunPortableDurableAdapter = async (options) => {
|
|
@@ -36215,7 +37421,7 @@ Durable service:
|
|
|
36215
37421
|
await writeInferenceHostCredentialContextTransition(config2, previousCredentialContext);
|
|
36216
37422
|
await writeInferenceHostCredentialContext(config2);
|
|
36217
37423
|
const keyPair = generateExternalInferenceEnvelopeKeyPair();
|
|
36218
|
-
const hostId =
|
|
37424
|
+
const hostId = randomUUID5();
|
|
36219
37425
|
const beginLogin = dependencies.beginLogin ?? beginInferenceOAuthLogin;
|
|
36220
37426
|
const loginStore = {
|
|
36221
37427
|
kind: store.kind,
|
|
@@ -36413,6 +37619,53 @@ Waiting for approval...
|
|
|
36413
37619
|
cancellation.unregister();
|
|
36414
37620
|
}
|
|
36415
37621
|
};
|
|
37622
|
+
deepSeekCredentialStore = (config2, dependencies) => dependencies.createDeepSeekCredentialStore?.(config2) ?? createDeepSeekHarnessCredentialStore(config2);
|
|
37623
|
+
deepSeekLogin = async (config2, parsed, dependencies) => {
|
|
37624
|
+
await assertDurableServiceUninstalled(config2);
|
|
37625
|
+
if (!dependencies.readStdin && process.stdin.isTTY) {
|
|
37626
|
+
throw new Error("DeepSeek API key must be supplied through stdin, never as an argument.");
|
|
37627
|
+
}
|
|
37628
|
+
const cancellation = lifecycleCancellation(dependencies);
|
|
37629
|
+
let lock2 = null;
|
|
37630
|
+
try {
|
|
37631
|
+
lock2 = await acquireInferenceHostProcessLock(config2.processLockPath);
|
|
37632
|
+
const raw = await (dependencies.readStdin ?? defaultReadStdin)();
|
|
37633
|
+
const credential = await deepSeekCredentialStore(config2, dependencies).write(
|
|
37634
|
+
raw,
|
|
37635
|
+
cancellation.signal
|
|
37636
|
+
);
|
|
37637
|
+
const failureFence = await readInferenceAgentFailureFence(config2.statePath);
|
|
37638
|
+
if (failureFence?.adapter_id === "deepseek-harness" && failureFence.failure_category === "auth") {
|
|
37639
|
+
await clearInferenceAgentFailureFence(config2.statePath);
|
|
37640
|
+
}
|
|
37641
|
+
return {
|
|
37642
|
+
exitCode: 0,
|
|
37643
|
+
stdout: render({
|
|
37644
|
+
status: "deepseek_api_key_imported",
|
|
37645
|
+
identity: credential.identity,
|
|
37646
|
+
credential_store: config2.credentialStoreMode
|
|
37647
|
+
}, parsed.json),
|
|
37648
|
+
stderr: ""
|
|
37649
|
+
};
|
|
37650
|
+
} finally {
|
|
37651
|
+
await lock2?.release();
|
|
37652
|
+
cancellation.unregister();
|
|
37653
|
+
}
|
|
37654
|
+
};
|
|
37655
|
+
deepSeekLogout = async (config2, parsed, dependencies) => {
|
|
37656
|
+
await assertDurableServiceUninstalled(config2);
|
|
37657
|
+
const lock2 = await acquireInferenceHostProcessLock(config2.processLockPath);
|
|
37658
|
+
try {
|
|
37659
|
+
await deepSeekCredentialStore(config2, dependencies).remove();
|
|
37660
|
+
return {
|
|
37661
|
+
exitCode: 0,
|
|
37662
|
+
stdout: render({ status: "deepseek_api_key_removed" }, parsed.json),
|
|
37663
|
+
stderr: ""
|
|
37664
|
+
};
|
|
37665
|
+
} finally {
|
|
37666
|
+
await lock2.release();
|
|
37667
|
+
}
|
|
37668
|
+
};
|
|
36416
37669
|
localStatus = async (config2, parsed, dependencies, warnings) => {
|
|
36417
37670
|
const codexAuthentication = await inspectCodexAuthentication(config2);
|
|
36418
37671
|
const state = await readInferenceHostLocalState(config2.statePath);
|
|
@@ -36457,6 +37710,7 @@ Waiting for approval...
|
|
|
36457
37710
|
);
|
|
36458
37711
|
const agentAttempt = await readInferenceAgentAttemptState(config2.statePath);
|
|
36459
37712
|
const agentNextRecoveryPresent = await readInferenceAgentNextState(config2.statePath) !== null;
|
|
37713
|
+
const agentFailureFence = await readInferenceAgentFailureFence(config2.statePath);
|
|
36460
37714
|
return {
|
|
36461
37715
|
exitCode: 0,
|
|
36462
37716
|
stdout: render({
|
|
@@ -36482,6 +37736,13 @@ Waiting for approval...
|
|
|
36482
37736
|
deadline_at: agentAttempt.deadline_at
|
|
36483
37737
|
} : null,
|
|
36484
37738
|
agent_next_recovery_present: agentNextRecoveryPresent,
|
|
37739
|
+
agent_failure_fence: agentFailureFence ? {
|
|
37740
|
+
adapter: agentFailureFence.adapter_id,
|
|
37741
|
+
failure_category: agentFailureFence.failure_category,
|
|
37742
|
+
failure_code: agentFailureFence.failure_code,
|
|
37743
|
+
dispatch_outcome: agentFailureFence.dispatch_outcome,
|
|
37744
|
+
retry_at: agentFailureFence.retry_at
|
|
37745
|
+
} : null,
|
|
36485
37746
|
codex_recovery_present: recoveryPresent,
|
|
36486
37747
|
service_recovery_present: serviceRecoveryPresent,
|
|
36487
37748
|
codex_auth: codexAuthentication,
|
|
@@ -36500,6 +37761,12 @@ Waiting for approval...
|
|
|
36500
37761
|
ok: state !== null,
|
|
36501
37762
|
detail: state ? "valid" : "missing"
|
|
36502
37763
|
});
|
|
37764
|
+
const agentFailureFence = await readInferenceAgentFailureFence(config2.statePath);
|
|
37765
|
+
checks.push({
|
|
37766
|
+
name: "agent_runtime_fence",
|
|
37767
|
+
ok: agentFailureFence === null,
|
|
37768
|
+
detail: agentFailureFence === null ? "clear" : `${agentFailureFence.failure_code}:${agentFailureFence.dispatch_outcome}`
|
|
37769
|
+
});
|
|
36503
37770
|
checks.push({
|
|
36504
37771
|
name: "revocation_recovery",
|
|
36505
37772
|
ok: revocationCheckpoint === null,
|
|
@@ -36538,7 +37805,8 @@ Waiting for approval...
|
|
|
36538
37805
|
} else if (adapterId !== "codex") {
|
|
36539
37806
|
try {
|
|
36540
37807
|
const prepared = await (dependencies.prepareDurableAdapter ?? preparePortableDurableAdapter)(
|
|
36541
|
-
adapterId
|
|
37808
|
+
adapterId,
|
|
37809
|
+
config2
|
|
36542
37810
|
);
|
|
36543
37811
|
checks.push({
|
|
36544
37812
|
name: "provider_runtime",
|
|
@@ -36796,6 +38064,7 @@ Waiting for approval...
|
|
|
36796
38064
|
if (adapterId !== "codex") {
|
|
36797
38065
|
const prepared = await (dependencies.prepareDurableAdapter ?? preparePortableDurableAdapter)(
|
|
36798
38066
|
adapterId,
|
|
38067
|
+
config2,
|
|
36799
38068
|
cancellation.signal
|
|
36800
38069
|
);
|
|
36801
38070
|
const summary = await (dependencies.runPortableDurableAdapter ?? defaultRunPortableDurableAdapter)({
|
|
@@ -36915,7 +38184,7 @@ Waiting for approval...
|
|
|
36915
38184
|
}
|
|
36916
38185
|
return record2;
|
|
36917
38186
|
};
|
|
36918
|
-
agentOperationId = (kind) => `${kind}-${
|
|
38187
|
+
agentOperationId = (kind) => `${kind}-${randomUUID5()}`;
|
|
36919
38188
|
agentSession = async (config2, dependencies, warnings, signal) => {
|
|
36920
38189
|
if (await readRevocationCheckpoint(config2)) {
|
|
36921
38190
|
throw new Error("Inference host revocation recovery must finish first.");
|
|
@@ -37932,7 +39201,7 @@ Waiting for approval...
|
|
|
37932
39201
|
if (recoveryRaw === null && existingTransaction?.phase !== "reconciled") {
|
|
37933
39202
|
throw new Error("Codex recovery evidence changed before service recovery began.");
|
|
37934
39203
|
}
|
|
37935
|
-
const transactionId = existingTransaction?.transaction_id ??
|
|
39204
|
+
const transactionId = existingTransaction?.transaction_id ?? randomUUID5();
|
|
37936
39205
|
const backupPath = existingTransaction?.recovery_backup_path ?? recoveryBackupPath(config2, transactionId);
|
|
37937
39206
|
if (!existingTransaction) {
|
|
37938
39207
|
await writeAtomicInferencePrivateFile(backupPath, recoveryRaw);
|
|
@@ -37941,7 +39210,7 @@ Waiting for approval...
|
|
|
37941
39210
|
backupPath,
|
|
37942
39211
|
"Codex service recovery backup"
|
|
37943
39212
|
);
|
|
37944
|
-
const backupSha256 = backupRaw === null ? null :
|
|
39213
|
+
const backupSha256 = backupRaw === null ? null : createHash8("sha256").update(backupRaw).digest("hex");
|
|
37945
39214
|
if (backupSha256 === null || existingTransaction && backupSha256 !== existingTransaction.recovery_backup_sha256) {
|
|
37946
39215
|
throw new Error("Codex service recovery backup is missing or changed.");
|
|
37947
39216
|
}
|
|
@@ -37952,7 +39221,7 @@ Waiting for approval...
|
|
|
37952
39221
|
existingTransaction?.cleanup_confirmed_attempt_ids ?? [],
|
|
37953
39222
|
existingTransaction?.phase ?? "prepared"
|
|
37954
39223
|
);
|
|
37955
|
-
const recoverySha256 = recoveryRaw === null ? null :
|
|
39224
|
+
const recoverySha256 = recoveryRaw === null ? null : createHash8("sha256").update(recoveryRaw).digest("hex");
|
|
37956
39225
|
const unresolvedAttemptIds = Object.keys(backupAttempts).filter((attemptId) => !existingTransaction?.cleanup_confirmed_attempt_ids.includes(attemptId) && !initialAttempts[attemptId]?.cleanupConfirmed);
|
|
37957
39226
|
const binary = unresolvedAttemptIds.length > 0 ? await (dependencies.resolveBinary ?? resolvePinnedCodexBinary)(env) : null;
|
|
37958
39227
|
let activeTransaction = existingTransaction;
|
|
@@ -37991,7 +39260,7 @@ Waiting for approval...
|
|
|
37991
39260
|
codexRecoveryPath(config2),
|
|
37992
39261
|
"Codex attempt recovery file"
|
|
37993
39262
|
);
|
|
37994
|
-
if (currentRaw === null || recoverySha256 === null ||
|
|
39263
|
+
if (currentRaw === null || recoverySha256 === null || createHash8("sha256").update(currentRaw).digest("hex") !== recoverySha256) {
|
|
37995
39264
|
throw new Error("Codex recovery evidence changed while the service was stopping.");
|
|
37996
39265
|
}
|
|
37997
39266
|
const proof = await (dependencies.proveCodexQuiescence ?? proveCodexSameBootQuiescence)({
|
|
@@ -38080,7 +39349,7 @@ Waiting for approval...
|
|
|
38080
39349
|
serviceRecoveryTransactionPath(config2),
|
|
38081
39350
|
"Inference-host service recovery transaction"
|
|
38082
39351
|
);
|
|
38083
|
-
await
|
|
39352
|
+
await rm7(backupPath, { force: true });
|
|
38084
39353
|
}
|
|
38085
39354
|
}
|
|
38086
39355
|
} finally {
|
|
@@ -38161,7 +39430,8 @@ Waiting for approval...
|
|
|
38161
39430
|
const displayName = resolveDurableServiceDisplayName(parsed, dependencies);
|
|
38162
39431
|
if (adapter !== "codex") {
|
|
38163
39432
|
const prepared = await (dependencies.prepareDurableAdapter ?? preparePortableDurableAdapter)(
|
|
38164
|
-
adapter
|
|
39433
|
+
adapter,
|
|
39434
|
+
config2
|
|
38165
39435
|
);
|
|
38166
39436
|
try {
|
|
38167
39437
|
const status2 = await manager.install({
|
|
@@ -38348,11 +39618,11 @@ Waiting for approval...
|
|
|
38348
39618
|
});
|
|
38349
39619
|
|
|
38350
39620
|
// lib/agent-core/config.ts
|
|
38351
|
-
import { mkdir as mkdir5, readFile as readFile6, rm as
|
|
38352
|
-
import { dirname as
|
|
39621
|
+
import { mkdir as mkdir5, readFile as readFile6, rm as rm8, writeFile as writeFile3 } from "node:fs/promises";
|
|
39622
|
+
import { dirname as dirname6, join as join9 } from "node:path";
|
|
38353
39623
|
import { homedir as homedir3 } from "node:os";
|
|
38354
39624
|
function defaultBaseDir() {
|
|
38355
|
-
return
|
|
39625
|
+
return join9(homedir3(), ".vtx");
|
|
38356
39626
|
}
|
|
38357
39627
|
function resolveAgentCliConfig(env = process.env) {
|
|
38358
39628
|
const baseDir = String(env.VTX_HOME || "").trim() || defaultBaseDir();
|
|
@@ -38360,8 +39630,8 @@ function resolveAgentCliConfig(env = process.env) {
|
|
|
38360
39630
|
const parsedProfile = rawProfile ? Number(rawProfile) : NaN;
|
|
38361
39631
|
return {
|
|
38362
39632
|
apiUrl: String(env.VTX_API_URL || "http://localhost:8000").replace(/\/+$/, ""),
|
|
38363
|
-
tokenPath: String(env.VTX_TOKEN_PATH || "").trim() ||
|
|
38364
|
-
statePath: String(env.VTX_RUNTIME_STATE_PATH || "").trim() ||
|
|
39633
|
+
tokenPath: String(env.VTX_TOKEN_PATH || "").trim() || join9(baseDir, "token.json"),
|
|
39634
|
+
statePath: String(env.VTX_RUNTIME_STATE_PATH || "").trim() || join9(baseDir, "runtime-state.json"),
|
|
38365
39635
|
runtimeDeviceId: String(env.VTX_RUNTIME_DEVICE_ID || "").trim() || null,
|
|
38366
39636
|
activeProfileId: Number.isFinite(parsedProfile) && parsedProfile > 0 ? parsedProfile : null,
|
|
38367
39637
|
outputJson: String(env.VTX_OUTPUT || "").trim().toLowerCase() === "json"
|
|
@@ -38387,12 +39657,12 @@ async function readStoredAgentAuth(path) {
|
|
|
38387
39657
|
}
|
|
38388
39658
|
}
|
|
38389
39659
|
async function writeStoredAgentAuth(path, auth) {
|
|
38390
|
-
await mkdir5(
|
|
39660
|
+
await mkdir5(dirname6(path), { recursive: true });
|
|
38391
39661
|
await writeFile3(path, `${JSON.stringify(auth, null, 2)}
|
|
38392
39662
|
`, { encoding: "utf8", mode: 384 });
|
|
38393
39663
|
}
|
|
38394
39664
|
async function clearStoredAgentAuth(path) {
|
|
38395
|
-
await
|
|
39665
|
+
await rm8(path, { force: true });
|
|
38396
39666
|
}
|
|
38397
39667
|
async function readRuntimeState(path) {
|
|
38398
39668
|
try {
|
|
@@ -38422,12 +39692,12 @@ async function readRuntimeState(path) {
|
|
|
38422
39692
|
}
|
|
38423
39693
|
}
|
|
38424
39694
|
async function writeRuntimeState(path, state) {
|
|
38425
|
-
await mkdir5(
|
|
39695
|
+
await mkdir5(dirname6(path), { recursive: true });
|
|
38426
39696
|
await writeFile3(path, `${JSON.stringify(state, null, 2)}
|
|
38427
39697
|
`, { encoding: "utf8", mode: 384 });
|
|
38428
39698
|
}
|
|
38429
39699
|
async function clearRuntimeState(path) {
|
|
38430
|
-
await
|
|
39700
|
+
await rm8(path, { force: true });
|
|
38431
39701
|
}
|
|
38432
39702
|
var init_config2 = __esm({
|
|
38433
39703
|
"lib/agent-core/config.ts"() {
|
|
@@ -38453,7 +39723,7 @@ var init_types = __esm({
|
|
|
38453
39723
|
});
|
|
38454
39724
|
|
|
38455
39725
|
// lib/agent-core/client.ts
|
|
38456
|
-
import { randomUUID as
|
|
39726
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
38457
39727
|
function normalizeApiUrl(value) {
|
|
38458
39728
|
const parsed = String(value || "").trim();
|
|
38459
39729
|
if (!parsed) {
|
|
@@ -38715,7 +39985,7 @@ var init_client = __esm({
|
|
|
38715
39985
|
return this.request("/trading/ai/runtime/decision", {
|
|
38716
39986
|
method: "POST",
|
|
38717
39987
|
profileId,
|
|
38718
|
-
idempotencyKey:
|
|
39988
|
+
idempotencyKey: randomUUID6(),
|
|
38719
39989
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
38720
39990
|
body: payload
|
|
38721
39991
|
});
|
|
@@ -38724,7 +39994,7 @@ var init_client = __esm({
|
|
|
38724
39994
|
return this.request("/trading/ai/runtime/trade-sync", {
|
|
38725
39995
|
method: "POST",
|
|
38726
39996
|
profileId,
|
|
38727
|
-
idempotencyKey:
|
|
39997
|
+
idempotencyKey: randomUUID6(),
|
|
38728
39998
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
38729
39999
|
body: payload
|
|
38730
40000
|
});
|
|
@@ -38733,7 +40003,7 @@ var init_client = __esm({
|
|
|
38733
40003
|
return this.request("/trading/ai/runtime/error", {
|
|
38734
40004
|
method: "POST",
|
|
38735
40005
|
profileId,
|
|
38736
|
-
idempotencyKey:
|
|
40006
|
+
idempotencyKey: randomUUID6(),
|
|
38737
40007
|
headers: { "x-client-runtime-lease": leaseToken },
|
|
38738
40008
|
body: payload
|
|
38739
40009
|
});
|
|
@@ -38745,7 +40015,7 @@ var init_client = __esm({
|
|
|
38745
40015
|
return this.request("/trading/market-order", {
|
|
38746
40016
|
method: "POST",
|
|
38747
40017
|
profileId,
|
|
38748
|
-
idempotencyKey:
|
|
40018
|
+
idempotencyKey: randomUUID6(),
|
|
38749
40019
|
body: payload
|
|
38750
40020
|
});
|
|
38751
40021
|
}
|
|
@@ -38753,7 +40023,7 @@ var init_client = __esm({
|
|
|
38753
40023
|
return this.request("/trading/limit-order", {
|
|
38754
40024
|
method: "POST",
|
|
38755
40025
|
profileId,
|
|
38756
|
-
idempotencyKey:
|
|
40026
|
+
idempotencyKey: randomUUID6(),
|
|
38757
40027
|
body: payload
|
|
38758
40028
|
});
|
|
38759
40029
|
}
|
|
@@ -38761,7 +40031,7 @@ var init_client = __esm({
|
|
|
38761
40031
|
return this.request("/trading/cancel-order", {
|
|
38762
40032
|
method: "POST",
|
|
38763
40033
|
profileId,
|
|
38764
|
-
idempotencyKey:
|
|
40034
|
+
idempotencyKey: randomUUID6(),
|
|
38765
40035
|
body: payload
|
|
38766
40036
|
});
|
|
38767
40037
|
}
|
|
@@ -38780,7 +40050,7 @@ var init_client = __esm({
|
|
|
38780
40050
|
return this.request("/trading/ai/start", {
|
|
38781
40051
|
method: "POST",
|
|
38782
40052
|
profileId,
|
|
38783
|
-
idempotencyKey:
|
|
40053
|
+
idempotencyKey: randomUUID6(),
|
|
38784
40054
|
body: payload
|
|
38785
40055
|
});
|
|
38786
40056
|
}
|
|
@@ -38788,7 +40058,7 @@ var init_client = __esm({
|
|
|
38788
40058
|
return this.request("/trading/ai/stop", {
|
|
38789
40059
|
method: "POST",
|
|
38790
40060
|
profileId,
|
|
38791
|
-
idempotencyKey:
|
|
40061
|
+
idempotencyKey: randomUUID6(),
|
|
38792
40062
|
body: {}
|
|
38793
40063
|
});
|
|
38794
40064
|
}
|
|
@@ -38796,7 +40066,7 @@ var init_client = __esm({
|
|
|
38796
40066
|
return this.request("/trading/ai/assistant/start", {
|
|
38797
40067
|
method: "POST",
|
|
38798
40068
|
profileId,
|
|
38799
|
-
idempotencyKey:
|
|
40069
|
+
idempotencyKey: randomUUID6(),
|
|
38800
40070
|
body: {}
|
|
38801
40071
|
});
|
|
38802
40072
|
}
|
|
@@ -38804,7 +40074,7 @@ var init_client = __esm({
|
|
|
38804
40074
|
return this.request("/trading/ai/assistant/stop", {
|
|
38805
40075
|
method: "POST",
|
|
38806
40076
|
profileId,
|
|
38807
|
-
idempotencyKey:
|
|
40077
|
+
idempotencyKey: randomUUID6(),
|
|
38808
40078
|
body: {}
|
|
38809
40079
|
});
|
|
38810
40080
|
}
|
|
@@ -38812,7 +40082,7 @@ var init_client = __esm({
|
|
|
38812
40082
|
return this.request("/trading/ai/runtime/session/start", {
|
|
38813
40083
|
method: "POST",
|
|
38814
40084
|
profileId,
|
|
38815
|
-
idempotencyKey:
|
|
40085
|
+
idempotencyKey: randomUUID6(),
|
|
38816
40086
|
body: payload
|
|
38817
40087
|
});
|
|
38818
40088
|
}
|
|
@@ -38823,7 +40093,7 @@ var init_client = __esm({
|
|
|
38823
40093
|
return this.request("/trading/ai/runtime/session/stop", {
|
|
38824
40094
|
method: "POST",
|
|
38825
40095
|
profileId,
|
|
38826
|
-
idempotencyKey:
|
|
40096
|
+
idempotencyKey: randomUUID6(),
|
|
38827
40097
|
body: payload
|
|
38828
40098
|
});
|
|
38829
40099
|
}
|
|
@@ -38840,7 +40110,7 @@ var init_client = __esm({
|
|
|
38840
40110
|
}).request("/trading/ai/runtime/session/stop", {
|
|
38841
40111
|
method: "POST",
|
|
38842
40112
|
profileId,
|
|
38843
|
-
idempotencyKey:
|
|
40113
|
+
idempotencyKey: randomUUID6(),
|
|
38844
40114
|
body: payload
|
|
38845
40115
|
});
|
|
38846
40116
|
}
|
|
@@ -38857,8 +40127,8 @@ import {
|
|
|
38857
40127
|
unlinkSync,
|
|
38858
40128
|
writeFileSync
|
|
38859
40129
|
} from "node:fs";
|
|
38860
|
-
import { randomUUID as
|
|
38861
|
-
import { dirname as
|
|
40130
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
40131
|
+
import { dirname as dirname7 } from "node:path";
|
|
38862
40132
|
var parseStoredValues, FileBackedProtectionStorage, clientRuntimeProtectionStatePath;
|
|
38863
40133
|
var init_protection_storage = __esm({
|
|
38864
40134
|
"lib/agent-core/protection-storage.ts"() {
|
|
@@ -38911,10 +40181,10 @@ var init_protection_storage = __esm({
|
|
|
38911
40181
|
}
|
|
38912
40182
|
}
|
|
38913
40183
|
writeValues(values) {
|
|
38914
|
-
mkdirSync(
|
|
40184
|
+
mkdirSync(dirname7(this.path), { recursive: true, mode: 448 });
|
|
38915
40185
|
const serialized = `${JSON.stringify(values)}
|
|
38916
40186
|
`;
|
|
38917
|
-
const temporaryPath = `${this.path}.${process.pid}.${
|
|
40187
|
+
const temporaryPath = `${this.path}.${process.pid}.${randomUUID7()}.tmp`;
|
|
38918
40188
|
try {
|
|
38919
40189
|
writeFileSync(temporaryPath, serialized, {
|
|
38920
40190
|
encoding: "utf8",
|
|
@@ -38941,7 +40211,7 @@ var init_protection_storage = __esm({
|
|
|
38941
40211
|
});
|
|
38942
40212
|
|
|
38943
40213
|
// lib/agent-core/headless-runtime.ts
|
|
38944
|
-
import { randomUUID as
|
|
40214
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
38945
40215
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
38946
40216
|
function objectOrNull2(value) {
|
|
38947
40217
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -39039,8 +40309,8 @@ async function runAndReportLocalWorkCycle(options, state, leaseToken, context) {
|
|
|
39039
40309
|
return Boolean(result2.decision || tradeSync || result2.afterDecision);
|
|
39040
40310
|
}
|
|
39041
40311
|
async function startHeadlessRuntime(options) {
|
|
39042
|
-
const runtimeSessionId =
|
|
39043
|
-
const deviceId = String(options.deviceId || "").trim() ||
|
|
40312
|
+
const runtimeSessionId = randomUUID8();
|
|
40313
|
+
const deviceId = String(options.deviceId || "").trim() || randomUUID8();
|
|
39044
40314
|
const startResponse = await options.client.startRuntime(options.profileId, {
|
|
39045
40315
|
session_id: runtimeSessionId,
|
|
39046
40316
|
device_id: deviceId,
|
|
@@ -43725,8 +44995,8 @@ var init_rlp_encode = __esm({
|
|
|
43725
44995
|
});
|
|
43726
44996
|
|
|
43727
44997
|
// node_modules/ethers/lib.esm/utils/uuid.js
|
|
43728
|
-
function uuidV4(
|
|
43729
|
-
const bytes3 = getBytes(
|
|
44998
|
+
function uuidV4(randomBytes9) {
|
|
44999
|
+
const bytes3 = getBytes(randomBytes9, "randomBytes");
|
|
43730
45000
|
bytes3[6] = bytes3[6] & 15 | 64;
|
|
43731
45001
|
bytes3[8] = bytes3[8] & 63 | 128;
|
|
43732
45002
|
const value = hexlify(bytes3);
|
|
@@ -43760,7 +45030,7 @@ var init_utils = __esm({
|
|
|
43760
45030
|
});
|
|
43761
45031
|
|
|
43762
45032
|
// node_modules/ethers/lib.esm/crypto/crypto.js
|
|
43763
|
-
import { createHash as
|
|
45033
|
+
import { createHash as createHash9, createHmac, pbkdf2Sync, randomBytes as randomBytes6 } from "crypto";
|
|
43764
45034
|
var init_crypto2 = __esm({
|
|
43765
45035
|
"node_modules/ethers/lib.esm/crypto/crypto.js"() {
|
|
43766
45036
|
}
|
|
@@ -44414,7 +45684,7 @@ var init_pbkdf2 = __esm({
|
|
|
44414
45684
|
});
|
|
44415
45685
|
|
|
44416
45686
|
// node_modules/ethers/lib.esm/crypto/random.js
|
|
44417
|
-
function
|
|
45687
|
+
function randomBytes7(length) {
|
|
44418
45688
|
return __randomBytes(length);
|
|
44419
45689
|
}
|
|
44420
45690
|
var locked5, _randomBytes, __randomBytes;
|
|
@@ -44423,20 +45693,20 @@ var init_random = __esm({
|
|
|
44423
45693
|
init_crypto2();
|
|
44424
45694
|
locked5 = false;
|
|
44425
45695
|
_randomBytes = function(length) {
|
|
44426
|
-
return new Uint8Array(
|
|
45696
|
+
return new Uint8Array(randomBytes6(length));
|
|
44427
45697
|
};
|
|
44428
45698
|
__randomBytes = _randomBytes;
|
|
44429
|
-
|
|
44430
|
-
|
|
45699
|
+
randomBytes7._ = _randomBytes;
|
|
45700
|
+
randomBytes7.lock = function() {
|
|
44431
45701
|
locked5 = true;
|
|
44432
45702
|
};
|
|
44433
|
-
|
|
45703
|
+
randomBytes7.register = function(func) {
|
|
44434
45704
|
if (locked5) {
|
|
44435
45705
|
throw new Error("randomBytes is locked");
|
|
44436
45706
|
}
|
|
44437
45707
|
__randomBytes = func;
|
|
44438
45708
|
};
|
|
44439
|
-
Object.freeze(
|
|
45709
|
+
Object.freeze(randomBytes7);
|
|
44440
45710
|
}
|
|
44441
45711
|
});
|
|
44442
45712
|
|
|
@@ -44974,10 +46244,10 @@ var init_sha22 = __esm({
|
|
|
44974
46244
|
init_crypto2();
|
|
44975
46245
|
init_utils();
|
|
44976
46246
|
_sha256 = function(data) {
|
|
44977
|
-
return
|
|
46247
|
+
return createHash9("sha256").update(data).digest();
|
|
44978
46248
|
};
|
|
44979
46249
|
_sha512 = function(data) {
|
|
44980
|
-
return
|
|
46250
|
+
return createHash9("sha512").update(data).digest();
|
|
44981
46251
|
};
|
|
44982
46252
|
__sha256 = _sha256;
|
|
44983
46253
|
__sha512 = _sha512;
|
|
@@ -45084,7 +46354,7 @@ function wrapConstructor2(hashCons) {
|
|
|
45084
46354
|
hashC.create = () => hashCons();
|
|
45085
46355
|
return hashC;
|
|
45086
46356
|
}
|
|
45087
|
-
function
|
|
46357
|
+
function randomBytes8(bytesLength = 32) {
|
|
45088
46358
|
if (crypto2 && typeof crypto2.getRandomValues === "function") {
|
|
45089
46359
|
return crypto2.getRandomValues(new Uint8Array(bytesLength));
|
|
45090
46360
|
}
|
|
@@ -46623,7 +47893,7 @@ function weierstrass(curveDef) {
|
|
|
46623
47893
|
function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
|
|
46624
47894
|
if (["recovered", "canonical"].some((k) => k in opts))
|
|
46625
47895
|
throw new Error("sign() legacy options not supported");
|
|
46626
|
-
const { hash: hash4, randomBytes:
|
|
47896
|
+
const { hash: hash4, randomBytes: randomBytes9 } = CURVE;
|
|
46627
47897
|
let { lowS, prehash, extraEntropy: ent } = opts;
|
|
46628
47898
|
if (lowS == null)
|
|
46629
47899
|
lowS = true;
|
|
@@ -46634,7 +47904,7 @@ function weierstrass(curveDef) {
|
|
|
46634
47904
|
const d = normPrivateKeyToScalar(privateKey);
|
|
46635
47905
|
const seedArgs = [int2octets(d), int2octets(h1int)];
|
|
46636
47906
|
if (ent != null) {
|
|
46637
|
-
const e = ent === true ?
|
|
47907
|
+
const e = ent === true ? randomBytes9(Fp2.BYTES) : ent;
|
|
46638
47908
|
seedArgs.push(ensureBytes("extraEntropy", e));
|
|
46639
47909
|
}
|
|
46640
47910
|
const seed = concatBytes2(...seedArgs);
|
|
@@ -46871,7 +48141,7 @@ function getHash(hash4) {
|
|
|
46871
48141
|
return {
|
|
46872
48142
|
hash: hash4,
|
|
46873
48143
|
hmac: (key, ...msgs) => hmac2(hash4, key, concatBytes(...msgs)),
|
|
46874
|
-
randomBytes:
|
|
48144
|
+
randomBytes: randomBytes8
|
|
46875
48145
|
};
|
|
46876
48146
|
}
|
|
46877
48147
|
function createCurve(curveDef, defHash) {
|
|
@@ -50845,7 +52115,7 @@ async function decryptKeystoreJson(json2, _password, progress) {
|
|
|
50845
52115
|
return getAccount(data, key);
|
|
50846
52116
|
}
|
|
50847
52117
|
function getEncryptKdfParams(options) {
|
|
50848
|
-
const salt = options.salt != null ? getBytes(options.salt, "options.salt") :
|
|
52118
|
+
const salt = options.salt != null ? getBytes(options.salt, "options.salt") : randomBytes7(32);
|
|
50849
52119
|
let N2 = 1 << 17, r = 8, p = 1;
|
|
50850
52120
|
if (options.scrypt) {
|
|
50851
52121
|
if (options.scrypt.N) {
|
|
@@ -50865,9 +52135,9 @@ function getEncryptKdfParams(options) {
|
|
|
50865
52135
|
}
|
|
50866
52136
|
function _encryptKeystore(key, kdf, account, options) {
|
|
50867
52137
|
const privateKey = getBytes(account.privateKey, "privateKey");
|
|
50868
|
-
const iv = options.iv != null ? getBytes(options.iv, "options.iv") :
|
|
52138
|
+
const iv = options.iv != null ? getBytes(options.iv, "options.iv") : randomBytes7(16);
|
|
50869
52139
|
assertArgument(iv.length === 16, "invalid options.iv length", "options.iv", options.iv);
|
|
50870
|
-
const uuidRandom = options.uuid != null ? getBytes(options.uuid, "options.uuid") :
|
|
52140
|
+
const uuidRandom = options.uuid != null ? getBytes(options.uuid, "options.uuid") : randomBytes7(16);
|
|
50871
52141
|
assertArgument(uuidRandom.length === 16, "invalid options.uuid length", "options.uuid", options.iv);
|
|
50872
52142
|
const derivedKey = key.slice(0, 16);
|
|
50873
52143
|
const macPrefix = key.slice(16, 32);
|
|
@@ -50901,7 +52171,7 @@ function _encryptKeystore(key, kdf, account, options) {
|
|
|
50901
52171
|
const locale = account.mnemonic.locale || "en";
|
|
50902
52172
|
const mnemonicKey = key.slice(32, 64);
|
|
50903
52173
|
const entropy = getBytes(account.mnemonic.entropy, "account.mnemonic.entropy");
|
|
50904
|
-
const mnemonicIv =
|
|
52174
|
+
const mnemonicIv = randomBytes7(16);
|
|
50905
52175
|
const mnemonicAesCtr = new CTR(mnemonicKey, mnemonicIv);
|
|
50906
52176
|
const mnemonicCiphertext = getBytes(mnemonicAesCtr.encrypt(entropy));
|
|
50907
52177
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -51239,7 +52509,7 @@ var init_hdwallet = __esm({
|
|
|
51239
52509
|
if (wordlist2 == null) {
|
|
51240
52510
|
wordlist2 = LangEn.wordlist();
|
|
51241
52511
|
}
|
|
51242
|
-
const mnemonic = Mnemonic.fromEntropy(
|
|
52512
|
+
const mnemonic = Mnemonic.fromEntropy(randomBytes7(16), password, wordlist2);
|
|
51243
52513
|
return _HDNodeWallet.#fromSeed(mnemonic.computeSeed(), mnemonic).derivePath(path);
|
|
51244
52514
|
}
|
|
51245
52515
|
/**
|
|
@@ -61592,7 +62862,7 @@ var headless_local_worker_exports = {};
|
|
|
61592
62862
|
__export(headless_local_worker_exports, {
|
|
61593
62863
|
createHeadlessLocalWorker: () => createHeadlessLocalWorker
|
|
61594
62864
|
});
|
|
61595
|
-
import { randomUUID as
|
|
62865
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
61596
62866
|
function objectOrNull3(value) {
|
|
61597
62867
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
61598
62868
|
}
|
|
@@ -62009,7 +63279,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
62009
63279
|
const statusMatch = errorText.match(/\b([45]\d{2})\b/);
|
|
62010
63280
|
const statusCode = statusMatch ? Number(statusMatch[1]) : null;
|
|
62011
63281
|
const failedInvocation = normalizeAiInvocationTelemetry({
|
|
62012
|
-
client_invocation_id:
|
|
63282
|
+
client_invocation_id: randomUUID9(),
|
|
62013
63283
|
use_case: "trader",
|
|
62014
63284
|
role: "primary",
|
|
62015
63285
|
attempt_index: 0,
|
|
@@ -62065,7 +63335,7 @@ function createHeadlessLocalWorker(options) {
|
|
|
62065
63335
|
billable_cached_input_tokens: normalizedUsage.cached_input_tokens
|
|
62066
63336
|
};
|
|
62067
63337
|
const invocation = normalizeAiInvocationTelemetry({
|
|
62068
|
-
client_invocation_id:
|
|
63338
|
+
client_invocation_id: randomUUID9(),
|
|
62069
63339
|
use_case: "trader",
|
|
62070
63340
|
role: "primary",
|
|
62071
63341
|
attempt_index: 0,
|
|
@@ -62284,7 +63554,7 @@ var vtx_exports = {};
|
|
|
62284
63554
|
__export(vtx_exports, {
|
|
62285
63555
|
runVtxCli: () => runVtxCli
|
|
62286
63556
|
});
|
|
62287
|
-
import { randomUUID as
|
|
63557
|
+
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
62288
63558
|
import { spawn as spawn8 } from "node:child_process";
|
|
62289
63559
|
function render2(value, json2) {
|
|
62290
63560
|
if (json2) {
|
|
@@ -62698,8 +63968,8 @@ async function runVtxCli(argv2, env = process.env) {
|
|
|
62698
63968
|
});
|
|
62699
63969
|
return { exitCode: 0, stdout: render2(redactCliOutput(response2), json2), stderr: "" };
|
|
62700
63970
|
}
|
|
62701
|
-
const runtimeSessionId =
|
|
62702
|
-
const deviceId = config2.runtimeDeviceId ??
|
|
63971
|
+
const runtimeSessionId = randomUUID10();
|
|
63972
|
+
const deviceId = config2.runtimeDeviceId ?? randomUUID10();
|
|
62703
63973
|
const response = await client.startRuntime(profileId, {
|
|
62704
63974
|
session_id: runtimeSessionId,
|
|
62705
63975
|
device_id: deviceId,
|