@vtxmacro/cli 2026.8.11 → 2026.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -3
- package/bin/vtx.js +667 -100
- package/package.json +1 -1
package/bin/vtx.js
CHANGED
|
@@ -38,7 +38,7 @@ var init_agent_cli_release = __esm({
|
|
|
38
38
|
"agent-cli-release.json"() {
|
|
39
39
|
agent_cli_release_default = {
|
|
40
40
|
package_name: "@vtxmacro/cli",
|
|
41
|
-
package_version: "2026.8.
|
|
41
|
+
package_version: "2026.8.13",
|
|
42
42
|
codex_package_name: "@openai/codex",
|
|
43
43
|
codex_version: "0.147.0",
|
|
44
44
|
platforms: {
|
|
@@ -14375,7 +14375,7 @@ var init_zod = __esm({
|
|
|
14375
14375
|
});
|
|
14376
14376
|
|
|
14377
14377
|
// lib/external-inference-contract.ts
|
|
14378
|
-
var EXTERNAL_INFERENCE_CONTRACT_VERSION, EXTERNAL_INFERENCE_CONTROLLER_SCHEMA_VERSION, EXTERNAL_INFERENCE_ADVERTISEMENT_SCHEMA_VERSION, EXTERNAL_INFERENCE_ENVELOPE_SCHEMA_VERSION, EXTERNAL_INFERENCE_JOB_INPUT_SCHEMA_VERSION, EXTERNAL_INFERENCE_USAGE_SCHEMA_VERSION, EXTERNAL_INFERENCE_INPUT_HASH_DOMAIN, MAX_EXTERNAL_INFERENCE_STATUS_HOSTS, MAX_GENERATION, MAX_SAFE_INTEGER, MAX_PROMPT_BYTES, MAX_IMMUTABLE_JOB_INPUT_BYTES, MAX_CANDIDATE_PLAINTEXT_BYTES, MAX_CIPHERTEXT_CHARS, SHA256_INITIAL_STATE, SHA256_ROUND_CONSTANTS, rotateRight, sha256BytesHex, sha256Utf8Hex, computeImmutableJobInputSha256, identifierSchema, operationIdentifierSchema, sha256HexSchema, generationSchema, zeroBasedGenerationSchema, nonNegativeSafeIntegerSchema, positiveSafeIntegerSchema, sqlIntegerTokenCountSchema, timestampSchema, safeCodeSchema, externalInferenceAdapterIdSchema, reasoningEffortSchema, modelNameSchema, displayNameSchema, protocolVersionSchema, base64UrlAlphabet, isCanonicalBase64Url, base64Url32BytesSchema, base64UrlNonceSchema, base64UrlCiphertextSchema, claimHandleSchema, boundedJsonTextSchema, boundedPromptTextSchema, laneSchema, botModeSchema, executionModeSchema, responseModeSchema, dispatchOutcomeSchema, responseOutcomeSchema, nativeModelControllerSchema, externalAgentModelControllerSchema, externalAgentUnboundControllerSchema, liveModelControllerSchema, snapshotModelControllerSchema, modelIdentityMappingSchema, advertisedModelSchema, hostAdvertisementSchema, envelopeAadSchema, validateEnvelopeAad, commonEnvelopeShape, sealedKeyWrapEnvelopeSchema, sealedInputEnvelopeSchema, sealedCandidateEnvelopeSchema, sealedEnvelopeSchema, screenerCandidateRuntimeBindingSchema, screenerClientLeaseBindingSchema, screenerRuntimeBindingSchema, serverRuntimeBindingSchema, clientRuntimeBindingSchema, runtimeBindingSchema, immutableJobInputSchema, canonicalizeJsonValue, serializeImmutableJobInput, reportedTokenUsageSchema, unavailableTokenUsageSchema, tokenUsageSchema, agentConnectRequestSchema, agentNextRequestSchema, emptyAgentNextResultSchema, claimedAgentNextResultSchema, agentNextResultSchema, agentCompleteRequestSchema, agentFailRequestSchema, requestedModelSelectionSchema, completedModelProvenanceSchema, attemptModelProvenanceSchema, hostHeartbeatRequestSchema, jobClaimRequestSchema, emptyJobClaimSchema, claimedJobSchema, jobClaimResultSchema, attemptStartRequestSchema, jobHeartbeatRequestSchema, continueHeartbeatDirectiveSchema, cancelHeartbeatDirectiveSchema, jobHeartbeatResultSchema, adapterOutcomeEvidenceSchema, completionBaseShape, validateCompletion, providerResponseCompletionSchema, decisionCandidateCompletionSchema, jobCompleteRequestSchema, jobFailRequestSchema, jobCancelRequestSchema, jobCancellationReceiptSchema, jobDeliveryRequestSchema, deliveryBaseShape, validateDeliveryCandidate, providerResponseDeliverySchema, decisionCandidateDeliverySchema, jobDeliveryResultSchema, jobConsumptionRequestSchema, jobConsumptionReceiptSchema, jobStateSchema, jobStatusReadSchema, hostStatusReadSchema, controllerBindingStatusReadSchema, queueStatusReadSchema, outcomeStatusReadSchema, externalInferenceStatusReadSchema, nativeResearchEvidenceSourceSchema, externalAgentResearchEvidenceSourceSchema, researchEvidenceSourceSchema, reportedResearchTokenUsageSchema, unavailableResearchTokenUsageSchema, researchTokenUsageSchema, externalInferenceProductLineageBaseShape, traderExternalInferenceProductLineageSchema, decisionChatExternalInferenceProductLineageSchema, screenerExternalInferenceProductLineageSchema, externalInferenceProductLineageSchema, normalProductLinkageSchema, evidenceMaterializationMarkerSchema, deliveredExternalAgentSourceIdentitySchema, deliveredRequestEvidenceSchema, researchEvidenceBaseShape, researchEvidenceBaseSchema, validateExactUtf8, validateResearchEvidence, providerResponseResearchEvidenceSchema, decisionCandidateResearchEvidenceSchema, researchEvidenceSchema;
|
|
14378
|
+
var EXTERNAL_INFERENCE_CONTRACT_VERSION, EXTERNAL_INFERENCE_CONTROLLER_SCHEMA_VERSION, EXTERNAL_INFERENCE_ADVERTISEMENT_SCHEMA_VERSION, EXTERNAL_INFERENCE_ENVELOPE_SCHEMA_VERSION, EXTERNAL_INFERENCE_JOB_INPUT_SCHEMA_VERSION, EXTERNAL_INFERENCE_USAGE_SCHEMA_VERSION, EXTERNAL_INFERENCE_INPUT_HASH_DOMAIN, MAX_EXTERNAL_INFERENCE_STATUS_HOSTS, MAX_GENERATION, MAX_SAFE_INTEGER, MAX_PROMPT_BYTES, MAX_IMMUTABLE_JOB_INPUT_BYTES, MAX_CANDIDATE_PLAINTEXT_BYTES, MAX_CIPHERTEXT_CHARS, SHA256_INITIAL_STATE, SHA256_ROUND_CONSTANTS, rotateRight, sha256BytesHex, sha256Utf8Hex, computeImmutableJobInputSha256, identifierSchema, operationIdentifierSchema, sha256HexSchema, generationSchema, zeroBasedGenerationSchema, nonNegativeSafeIntegerSchema, positiveSafeIntegerSchema, sqlIntegerTokenCountSchema, timestampSchema, safeCodeSchema, externalInferenceAdapterIdSchema, reasoningEffortSchema, modelNameSchema, displayNameSchema, authenticatedAccountEmailSchema, protocolVersionSchema, base64UrlAlphabet, isCanonicalBase64Url, base64Url32BytesSchema, base64UrlNonceSchema, base64UrlCiphertextSchema, claimHandleSchema, boundedJsonTextSchema, boundedPromptTextSchema, laneSchema, botModeSchema, executionModeSchema, responseModeSchema, dispatchOutcomeSchema, responseOutcomeSchema, nativeModelControllerSchema, externalAgentModelControllerSchema, externalAgentUnboundControllerSchema, liveModelControllerSchema, snapshotModelControllerSchema, modelIdentityMappingSchema, advertisedModelSchema, hostAdvertisementSchema, envelopeAadSchema, validateEnvelopeAad, commonEnvelopeShape, sealedKeyWrapEnvelopeSchema, sealedInputEnvelopeSchema, sealedCandidateEnvelopeSchema, sealedEnvelopeSchema, screenerCandidateRuntimeBindingSchema, screenerClientLeaseBindingSchema, screenerRuntimeBindingSchema, serverRuntimeBindingSchema, clientRuntimeBindingSchema, runtimeBindingSchema, immutableJobInputSchema, canonicalizeJsonValue, serializeImmutableJobInput, reportedTokenUsageSchema, unavailableTokenUsageSchema, tokenUsageSchema, agentConnectRequestSchema, agentNextRequestSchema, agentHeartbeatRequestSchema, emptyAgentNextResultSchema, claimedAgentNextResultSchema, agentNextResultSchema, agentCompleteRequestSchema, agentFailRequestSchema, requestedModelSelectionSchema, completedModelProvenanceSchema, attemptModelProvenanceSchema, hostHeartbeatRequestSchema, jobClaimRequestSchema, emptyJobClaimSchema, claimedJobSchema, jobClaimResultSchema, attemptStartRequestSchema, jobHeartbeatRequestSchema, continueHeartbeatDirectiveSchema, cancelHeartbeatDirectiveSchema, jobHeartbeatResultSchema, adapterOutcomeEvidenceSchema, completionBaseShape, validateCompletion, providerResponseCompletionSchema, decisionCandidateCompletionSchema, jobCompleteRequestSchema, jobFailRequestSchema, jobCancelRequestSchema, jobCancellationReceiptSchema, jobDeliveryRequestSchema, deliveryBaseShape, validateDeliveryCandidate, providerResponseDeliverySchema, decisionCandidateDeliverySchema, jobDeliveryResultSchema, jobConsumptionRequestSchema, jobConsumptionReceiptSchema, jobStateSchema, jobStatusReadSchema, hostStatusReadSchema, controllerBindingStatusReadSchema, queueStatusReadSchema, outcomeStatusReadSchema, externalInferenceStatusReadSchema, nativeResearchEvidenceSourceSchema, externalAgentResearchEvidenceSourceSchema, researchEvidenceSourceSchema, reportedResearchTokenUsageSchema, unavailableResearchTokenUsageSchema, researchTokenUsageSchema, externalInferenceProductLineageBaseShape, traderExternalInferenceProductLineageSchema, decisionChatExternalInferenceProductLineageSchema, screenerExternalInferenceProductLineageSchema, externalInferenceProductLineageSchema, normalProductLinkageSchema, evidenceMaterializationMarkerSchema, deliveredExternalAgentSourceIdentitySchema, deliveredRequestEvidenceSchema, researchEvidenceBaseShape, researchEvidenceBaseSchema, validateExactUtf8, validateResearchEvidence, providerResponseResearchEvidenceSchema, decisionCandidateResearchEvidenceSchema, researchEvidenceSchema;
|
|
14379
14379
|
var init_external_inference_contract = __esm({
|
|
14380
14380
|
"lib/external-inference-contract.ts"() {
|
|
14381
14381
|
"use strict";
|
|
@@ -14580,6 +14580,7 @@ var init_external_inference_contract = __esm({
|
|
|
14580
14580
|
reasoningEffortSchema = external_exports.string().min(1).max(32).regex(/^[a-z][a-z0-9_-]{0,31}$/);
|
|
14581
14581
|
modelNameSchema = external_exports.string().min(1).max(256);
|
|
14582
14582
|
displayNameSchema = external_exports.string().min(1).max(128);
|
|
14583
|
+
authenticatedAccountEmailSchema = external_exports.string().max(320).email();
|
|
14583
14584
|
protocolVersionSchema = external_exports.string().min(1).max(64);
|
|
14584
14585
|
base64UrlAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
14585
14586
|
isCanonicalBase64Url = (value, exactBytes) => {
|
|
@@ -14713,6 +14714,8 @@ var init_external_inference_contract = __esm({
|
|
|
14713
14714
|
key_generation: generationSchema,
|
|
14714
14715
|
adapter: externalInferenceAdapterIdSchema,
|
|
14715
14716
|
display_name: displayNameSchema,
|
|
14717
|
+
authenticated_account_email: authenticatedAccountEmailSchema.nullable().optional(),
|
|
14718
|
+
authenticated_account_plan: safeCodeSchema.nullable().optional(),
|
|
14716
14719
|
protocol_version: protocolVersionSchema,
|
|
14717
14720
|
envelope_public_key: base64Url32BytesSchema,
|
|
14718
14721
|
health: external_exports.enum(["healthy", "degraded", "draining"]),
|
|
@@ -15051,6 +15054,12 @@ var init_external_inference_contract = __esm({
|
|
|
15051
15054
|
host_id: identifierSchema,
|
|
15052
15055
|
requested_at: timestampSchema
|
|
15053
15056
|
});
|
|
15057
|
+
agentHeartbeatRequestSchema = external_exports.strictObject({
|
|
15058
|
+
operation_id: operationIdentifierSchema,
|
|
15059
|
+
host_id: identifierSchema,
|
|
15060
|
+
attempt_id: identifierSchema.nullable().optional(),
|
|
15061
|
+
requested_at: timestampSchema
|
|
15062
|
+
});
|
|
15054
15063
|
emptyAgentNextResultSchema = external_exports.strictObject({
|
|
15055
15064
|
claim_state: external_exports.literal("empty"),
|
|
15056
15065
|
retry_after_ms: nonNegativeSafeIntegerSchema
|
|
@@ -15570,6 +15579,8 @@ var init_external_inference_contract = __esm({
|
|
|
15570
15579
|
hostStatusReadSchema = external_exports.strictObject({
|
|
15571
15580
|
host_id: identifierSchema,
|
|
15572
15581
|
display_name: displayNameSchema,
|
|
15582
|
+
authenticated_account_email: authenticatedAccountEmailSchema.nullable().optional(),
|
|
15583
|
+
authenticated_account_plan: safeCodeSchema.nullable().optional(),
|
|
15573
15584
|
adapter: externalInferenceAdapterIdSchema,
|
|
15574
15585
|
status: external_exports.enum(["online", "degraded", "offline", "draining", "revoked"]),
|
|
15575
15586
|
host_generation: generationSchema,
|
|
@@ -16647,6 +16658,10 @@ var init_credential_store = __esm({
|
|
|
16647
16658
|
}
|
|
16648
16659
|
const result2 = await this.runner(command, { stdin: serialized, ...options });
|
|
16649
16660
|
if (result2.exitCode !== 0) throw new Error("OS credential write failed.");
|
|
16661
|
+
const retained = await this.read(accountKey, options);
|
|
16662
|
+
if (!retained || JSON.stringify(retained) !== JSON.stringify(validated)) {
|
|
16663
|
+
throw new Error("OS credential write could not be verified.");
|
|
16664
|
+
}
|
|
16650
16665
|
}
|
|
16651
16666
|
async remove(accountKey, options = {}) {
|
|
16652
16667
|
const command = this.commands.remove(INFERENCE_CREDENTIAL_NAMESPACE, accountKey);
|
|
@@ -16864,7 +16879,7 @@ public static class VtxInferenceCredential {
|
|
|
16864
16879
|
}`;
|
|
16865
16880
|
powershellCredentialCommand = (operation, namespace, accountKey) => {
|
|
16866
16881
|
const target = JSON.stringify(`${namespace}:${accountKey}`);
|
|
16867
|
-
const body = operation === "read" ? `try { [Console]::Out.Write([VtxInferenceCredential]::Read(${target})) } catch [System.ComponentModel.Win32Exception] { if ($_.Exception.NativeErrorCode -eq 1168) { exit 4 }; exit 1 }` : operation === "write" ? `[VtxInferenceCredential]::Write(${target}, [Console]::In.ReadToEnd())` : `try { [VtxInferenceCredential]::Delete(${target}) } catch [System.ComponentModel.Win32Exception] { if ($_.Exception.NativeErrorCode -eq 1168) { exit 4 }; exit 1 }`;
|
|
16882
|
+
const body = operation === "read" ? `try { [Console]::Out.Write([VtxInferenceCredential]::Read(${target})) } catch [System.ComponentModel.Win32Exception] { if ($_.Exception.NativeErrorCode -eq 1168) { exit 4 }; exit 1 }` : operation === "write" ? `try { [VtxInferenceCredential]::Write(${target}, [Console]::In.ReadToEnd()); exit 0 } catch { exit 1 }` : `try { [VtxInferenceCredential]::Delete(${target}) } catch [System.ComponentModel.Win32Exception] { if ($_.Exception.NativeErrorCode -eq 1168) { exit 4 }; exit 1 }`;
|
|
16868
16883
|
const script = `Add-Type -TypeDefinition @'
|
|
16869
16884
|
${windowsCredentialInterop}
|
|
16870
16885
|
'@
|
|
@@ -16979,7 +16994,7 @@ ${body}`;
|
|
|
16979
16994
|
});
|
|
16980
16995
|
|
|
16981
16996
|
// lib/inference-host/mcp-client.ts
|
|
16982
|
-
var EXTERNAL_INFERENCE_MCP_PROTOCOL_VERSION, EXTERNAL_INFERENCE_AUTOMATED_HOST_TOOLS, EXTERNAL_INFERENCE_OPERATIONAL_TOOLS, ExternalInferenceMcpError, DEFAULT_REQUEST_TIMEOUT_MS, identifierSchema2, safeCodeSchema2, hostMutationResultSchema, attemptStartResultSchema, agentConnectResultSchema, jobCompletionResultSchema, jobFailureResultSchema, toolContracts, discoveryResultSchema, toolListResultSchema, inlineStructuredContentSchema, protocolMeta, parseJsonDocument, parseSseDocuments, parseResponseDocuments, exactOperationalInventory, exactJson, invalidBoundResult, verifyToolResult, ExternalInferenceMcpClient;
|
|
16997
|
+
var EXTERNAL_INFERENCE_MCP_PROTOCOL_VERSION, EXTERNAL_INFERENCE_AUTOMATED_HOST_TOOLS, EXTERNAL_INFERENCE_OPERATIONAL_TOOLS, ExternalInferenceMcpError, DEFAULT_REQUEST_TIMEOUT_MS, MAX_RETRY_AFTER_MS, parseRetryAfterMs, identifierSchema2, safeCodeSchema2, hostMutationResultSchema, attemptStartResultSchema, agentConnectResultSchema, agentHeartbeatResultSchema, jobCompletionResultSchema, jobFailureResultSchema, toolContracts, discoveryResultSchema, toolListResultSchema, inlineStructuredContentSchema, protocolMeta, parseJsonDocument, parseSseDocuments, parseResponseDocuments, exactOperationalInventory, exactJson, invalidBoundResult, verifyToolResult, ExternalInferenceMcpClient;
|
|
16983
16998
|
var init_mcp_client = __esm({
|
|
16984
16999
|
"lib/inference-host/mcp-client.ts"() {
|
|
16985
17000
|
"use strict";
|
|
@@ -16999,6 +17014,7 @@ var init_mcp_client = __esm({
|
|
|
16999
17014
|
EXTERNAL_INFERENCE_OPERATIONAL_TOOLS = [
|
|
17000
17015
|
...EXTERNAL_INFERENCE_AUTOMATED_HOST_TOOLS,
|
|
17001
17016
|
"inference.agent.connect",
|
|
17017
|
+
"inference.agent.heartbeat",
|
|
17002
17018
|
"inference.agent.next",
|
|
17003
17019
|
"inference.agent.complete",
|
|
17004
17020
|
"inference.agent.fail"
|
|
@@ -17009,9 +17025,29 @@ var init_mcp_client = __esm({
|
|
|
17009
17025
|
this.name = "ExternalInferenceMcpError";
|
|
17010
17026
|
this.code = code;
|
|
17011
17027
|
this.definitivelyNotApplied = options.definitivelyNotApplied ?? false;
|
|
17028
|
+
this.httpStatusCode = options.httpStatusCode ?? null;
|
|
17029
|
+
this.retryAfterMs = options.retryAfterMs ?? null;
|
|
17030
|
+
this.retryable = options.retryable ?? [
|
|
17031
|
+
"network_error",
|
|
17032
|
+
"transport_rejected",
|
|
17033
|
+
"server_rejected",
|
|
17034
|
+
"rate_limited",
|
|
17035
|
+
"invalid_response",
|
|
17036
|
+
"request_timeout",
|
|
17037
|
+
"authentication_timeout"
|
|
17038
|
+
].includes(code);
|
|
17012
17039
|
}
|
|
17013
17040
|
};
|
|
17014
17041
|
DEFAULT_REQUEST_TIMEOUT_MS = 15e3;
|
|
17042
|
+
MAX_RETRY_AFTER_MS = 24 * 60 * 60 * 1e3;
|
|
17043
|
+
parseRetryAfterMs = (response, observedAtMs = Date.now()) => {
|
|
17044
|
+
const value = response.headers.get("retry-after")?.trim();
|
|
17045
|
+
if (!value) return null;
|
|
17046
|
+
const seconds = Number(value);
|
|
17047
|
+
const milliseconds = Number.isFinite(seconds) && seconds >= 0 ? Math.ceil(seconds * 1e3) : Math.max(0, Date.parse(value) - observedAtMs);
|
|
17048
|
+
if (!Number.isSafeInteger(milliseconds)) return null;
|
|
17049
|
+
return Math.min(milliseconds, MAX_RETRY_AFTER_MS);
|
|
17050
|
+
};
|
|
17015
17051
|
identifierSchema2 = external_exports.string().min(1).max(128);
|
|
17016
17052
|
safeCodeSchema2 = external_exports.string().min(1).max(96);
|
|
17017
17053
|
hostMutationResultSchema = external_exports.strictObject({
|
|
@@ -17030,6 +17066,20 @@ var init_mcp_client = __esm({
|
|
|
17030
17066
|
reasoning_effort: safeCodeSchema2,
|
|
17031
17067
|
replayed: external_exports.boolean()
|
|
17032
17068
|
});
|
|
17069
|
+
agentHeartbeatResultSchema = external_exports.strictObject({
|
|
17070
|
+
host: hostStatusReadSchema,
|
|
17071
|
+
active_attempts: external_exports.number().int().min(0).max(1),
|
|
17072
|
+
available_slots: external_exports.number().int().min(0).max(1),
|
|
17073
|
+
replayed: external_exports.boolean()
|
|
17074
|
+
}).superRefine((value, context) => {
|
|
17075
|
+
if (value.active_attempts + value.available_slots !== 1) {
|
|
17076
|
+
context.addIssue({
|
|
17077
|
+
code: "custom",
|
|
17078
|
+
message: "Agent heartbeat capacity must describe exactly one slot.",
|
|
17079
|
+
path: ["available_slots"]
|
|
17080
|
+
});
|
|
17081
|
+
}
|
|
17082
|
+
});
|
|
17033
17083
|
jobCompletionResultSchema = external_exports.strictObject({
|
|
17034
17084
|
job_id: identifierSchema2,
|
|
17035
17085
|
attempt_id: identifierSchema2,
|
|
@@ -17099,6 +17149,10 @@ var init_mcp_client = __esm({
|
|
|
17099
17149
|
arguments: agentConnectRequestSchema,
|
|
17100
17150
|
result: agentConnectResultSchema
|
|
17101
17151
|
},
|
|
17152
|
+
"inference.agent.heartbeat": {
|
|
17153
|
+
arguments: agentHeartbeatRequestSchema,
|
|
17154
|
+
result: agentHeartbeatResultSchema
|
|
17155
|
+
},
|
|
17102
17156
|
"inference.agent.next": {
|
|
17103
17157
|
arguments: agentNextRequestSchema,
|
|
17104
17158
|
result: agentNextResultSchema
|
|
@@ -17213,11 +17267,11 @@ var init_mcp_client = __esm({
|
|
|
17213
17267
|
if (!host) return invalidBoundResult(name);
|
|
17214
17268
|
if (host.host_id !== request.host_id || host.host_generation !== request.host_generation || host.advertisement_generation !== request.advertisement_generation || host.key_generation !== request.key_generation || request.adapter !== void 0 && host.adapter !== request.adapter) invalidBoundResult(name);
|
|
17215
17269
|
if (name !== "inference.host.heartbeat") {
|
|
17216
|
-
if (host.display_name !== request.display_name || !exactJson(host.models, request.models) || host.status === "revoked") invalidBoundResult(name);
|
|
17270
|
+
if (host.display_name !== request.display_name || (host.authenticated_account_email ?? null) !== (request.authenticated_account_email ?? null) || (host.authenticated_account_plan ?? null) !== (request.authenticated_account_plan ?? null) || !exactJson(host.models, request.models) || host.status === "revoked") invalidBoundResult(name);
|
|
17217
17271
|
return;
|
|
17218
17272
|
}
|
|
17219
17273
|
const expectedStatus = request.status === "healthy" ? "online" : request.status;
|
|
17220
|
-
if (host.status !== expectedStatus) invalidBoundResult(name);
|
|
17274
|
+
if (host.status !== expectedStatus && !(request.status === "healthy" && host.status === "offline")) invalidBoundResult(name);
|
|
17221
17275
|
return;
|
|
17222
17276
|
}
|
|
17223
17277
|
if (name === "inference.agent.connect") {
|
|
@@ -17225,6 +17279,12 @@ var init_mcp_client = __esm({
|
|
|
17225
17279
|
if (!host || host.host_id !== request.host_id || host.adapter !== request.adapter || result2.model_id !== request.model_id || result2.reasoning_effort !== request.reasoning_effort) invalidBoundResult(name);
|
|
17226
17280
|
return;
|
|
17227
17281
|
}
|
|
17282
|
+
if (name === "inference.agent.heartbeat") {
|
|
17283
|
+
const host = result2.host;
|
|
17284
|
+
const expectedActive = request.attempt_id == null ? 0 : 1;
|
|
17285
|
+
if (!host || host.host_id !== request.host_id || host.status !== "online" || result2.active_attempts !== expectedActive || result2.available_slots !== 1 - expectedActive) invalidBoundResult(name);
|
|
17286
|
+
return;
|
|
17287
|
+
}
|
|
17228
17288
|
if (name === "inference.agent.next") {
|
|
17229
17289
|
if (result2.claim_state === "claimed" && !result2.job_id) invalidBoundResult(name);
|
|
17230
17290
|
return;
|
|
@@ -17343,7 +17403,7 @@ var init_mcp_client = __esm({
|
|
|
17343
17403
|
}).passthrough().parse(rawResult);
|
|
17344
17404
|
if (callResult.isError === true) {
|
|
17345
17405
|
const errorText = (callResult.content ?? []).filter((block) => block.type === "text").map((block) => block.text ?? "").join("\n");
|
|
17346
|
-
const definitivelyNotApplied = (name === "inference.host.register" || name === "inference.host.advertise") && errorText.includes("Advertisement is already expired.") || name === "inference.agent.next" && (errorText.includes("Advertisement time is outside the allowed clock skew.") || errorText.includes("Advertisement is already expired.") || errorText.includes("Heartbeat time is outside the allowed clock skew."));
|
|
17406
|
+
const definitivelyNotApplied = (name === "inference.host.register" || name === "inference.host.advertise") && errorText.includes("Advertisement is already expired.") || (name === "inference.agent.next" || name === "inference.agent.heartbeat") && (errorText.includes("Advertisement time is outside the allowed clock skew.") || errorText.includes("Advertisement is already expired.") || errorText.includes("Heartbeat time is outside the allowed clock skew."));
|
|
17347
17407
|
throw new ExternalInferenceMcpError(
|
|
17348
17408
|
"tool_rejected",
|
|
17349
17409
|
`Insights MCP rejected ${name}.`,
|
|
@@ -17423,9 +17483,14 @@ var init_mcp_client = __esm({
|
|
|
17423
17483
|
);
|
|
17424
17484
|
}
|
|
17425
17485
|
if (!response.ok) {
|
|
17486
|
+
const httpStatusCode = response.status;
|
|
17487
|
+
const retryAfterMs = parseRetryAfterMs(response);
|
|
17488
|
+
await response.body?.cancel().catch(() => void 0);
|
|
17489
|
+
const retryable = httpStatusCode === 408 || httpStatusCode === 425 || httpStatusCode === 429 || httpStatusCode >= 500;
|
|
17426
17490
|
throw new ExternalInferenceMcpError(
|
|
17427
|
-
|
|
17428
|
-
`Insights MCP request failed with HTTP ${
|
|
17491
|
+
httpStatusCode === 401 ? "authentication_rejected" : httpStatusCode === 429 ? "rate_limited" : httpStatusCode >= 500 ? "server_rejected" : retryable ? "transport_rejected" : "http_rejected",
|
|
17492
|
+
`Insights MCP request failed with HTTP ${httpStatusCode}.`,
|
|
17493
|
+
{ httpStatusCode, retryAfterMs, retryable }
|
|
17429
17494
|
);
|
|
17430
17495
|
}
|
|
17431
17496
|
let documents;
|
|
@@ -18021,13 +18086,13 @@ async function beginInferenceOAuthLogin(options) {
|
|
|
18021
18086
|
);
|
|
18022
18087
|
}
|
|
18023
18088
|
const fetchImpl = options.fetchImpl || fetch;
|
|
18024
|
-
const callbackPath = `/
|
|
18089
|
+
const callbackPath = `/vtx-inference-authorized/${randomBytes2(16).toString("hex")}`;
|
|
18025
18090
|
let handler = null;
|
|
18026
18091
|
const server = createServer((request, response) => {
|
|
18027
18092
|
response.setHeader("Cache-Control", "no-store");
|
|
18028
18093
|
response.setHeader("Pragma", "no-cache");
|
|
18029
18094
|
response.setHeader("Referrer-Policy", "no-referrer");
|
|
18030
|
-
response.setHeader("Content-Type", "text/
|
|
18095
|
+
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
18031
18096
|
const writeResponse = (status, body) => {
|
|
18032
18097
|
response.statusCode = status;
|
|
18033
18098
|
response.end(body);
|
|
@@ -18131,9 +18196,12 @@ async function beginInferenceOAuthLogin(options) {
|
|
|
18131
18196
|
cause: error48
|
|
18132
18197
|
});
|
|
18133
18198
|
}
|
|
18134
|
-
throw error48;
|
|
18199
|
+
throw new InferenceOAuthCredentialStoreError({ cause: error48 });
|
|
18135
18200
|
}
|
|
18136
|
-
writeResponse(
|
|
18201
|
+
writeResponse(
|
|
18202
|
+
200,
|
|
18203
|
+
'<!doctype html><html><head><meta charset="utf-8"><title>VTX authorization complete</title></head><body><main><h1>VTX authorization complete</h1><p>The VTX CLI received your approval. You can close this tab and return to the terminal.</p></main></body></html>'
|
|
18204
|
+
);
|
|
18137
18205
|
await closeServer(server);
|
|
18138
18206
|
resolve5({
|
|
18139
18207
|
accessToken: tokens.accessToken,
|
|
@@ -18142,9 +18210,12 @@ async function beginInferenceOAuthLogin(options) {
|
|
|
18142
18210
|
accountKey
|
|
18143
18211
|
});
|
|
18144
18212
|
} catch (error48) {
|
|
18145
|
-
writeResponse(
|
|
18213
|
+
writeResponse(
|
|
18214
|
+
400,
|
|
18215
|
+
'<!doctype html><html><head><meta charset="utf-8"><title>VTX authorization failed</title></head><body><main><h1>VTX authorization failed</h1><p>Return to the VTX CLI for the actionable error.</p></main></body></html>'
|
|
18216
|
+
);
|
|
18146
18217
|
await closeServer(server);
|
|
18147
|
-
reject(error48 instanceof InferenceOAuthRequestError ? error48 : new Error("Inference OAuth authorization failed."));
|
|
18218
|
+
reject(error48 instanceof InferenceOAuthRequestError || error48 instanceof InferenceOAuthCredentialStoreError ? error48 : new Error("Inference OAuth authorization failed."));
|
|
18148
18219
|
}
|
|
18149
18220
|
};
|
|
18150
18221
|
});
|
|
@@ -18194,7 +18265,7 @@ async function beginInferenceOAuthLogin(options) {
|
|
|
18194
18265
|
throw error48;
|
|
18195
18266
|
}
|
|
18196
18267
|
}
|
|
18197
|
-
var INFERENCE_SCOPE, CALLBACK_HOST, TOKEN_PREFIX, DEFAULT_OAUTH_REQUEST_TIMEOUT_MS, InferenceOAuthRequestError;
|
|
18268
|
+
var INFERENCE_SCOPE, CALLBACK_HOST, TOKEN_PREFIX, DEFAULT_OAUTH_REQUEST_TIMEOUT_MS, InferenceOAuthRequestError, InferenceOAuthCredentialStoreError;
|
|
18198
18269
|
var init_oauth = __esm({
|
|
18199
18270
|
"lib/inference-host/oauth.ts"() {
|
|
18200
18271
|
"use strict";
|
|
@@ -18210,6 +18281,15 @@ var init_oauth = __esm({
|
|
|
18210
18281
|
this.code = code;
|
|
18211
18282
|
}
|
|
18212
18283
|
};
|
|
18284
|
+
InferenceOAuthCredentialStoreError = class extends Error {
|
|
18285
|
+
constructor(options = {}) {
|
|
18286
|
+
super(
|
|
18287
|
+
"VTX authorization succeeded, but the credential store did not retain the grant. VTX revoked the new remote grant. Set VTX_INFERENCE_HOST_CREDENTIAL_STORE=file and run vtx inference-host login again to use the secure private-file fallback.",
|
|
18288
|
+
{ cause: options.cause }
|
|
18289
|
+
);
|
|
18290
|
+
this.name = "InferenceOAuthCredentialStoreError";
|
|
18291
|
+
}
|
|
18292
|
+
};
|
|
18213
18293
|
}
|
|
18214
18294
|
});
|
|
18215
18295
|
|
|
@@ -18457,7 +18537,25 @@ async function loginCodexSubscription(options) {
|
|
|
18457
18537
|
async function preflightCodexSubscription(options) {
|
|
18458
18538
|
const session = await CodexAppServerSession.start(options);
|
|
18459
18539
|
try {
|
|
18460
|
-
await session.
|
|
18540
|
+
const account = await session.readAccountSnapshot(
|
|
18541
|
+
options.deadlineAtMs,
|
|
18542
|
+
options.signal,
|
|
18543
|
+
true
|
|
18544
|
+
);
|
|
18545
|
+
if (!account.requiresOpenaiAuth || account.authenticatedChatGptAccount === null) {
|
|
18546
|
+
throw new CodexAppServerError({
|
|
18547
|
+
message: "Codex managed ChatGPT authentication is required.",
|
|
18548
|
+
category: "auth",
|
|
18549
|
+
code: "managed_chatgpt_auth_required",
|
|
18550
|
+
retryable: false
|
|
18551
|
+
});
|
|
18552
|
+
}
|
|
18553
|
+
const rateLimits = await session.readAccountRateLimits(options.deadlineAtMs, options.signal);
|
|
18554
|
+
return {
|
|
18555
|
+
authenticated_account_email: account.authenticatedChatGptAccount.email,
|
|
18556
|
+
authenticated_account_plan: account.authenticatedChatGptAccount.planType,
|
|
18557
|
+
rate_limits: rateLimits
|
|
18558
|
+
};
|
|
18461
18559
|
} finally {
|
|
18462
18560
|
await session.close();
|
|
18463
18561
|
}
|
|
@@ -18470,11 +18568,28 @@ async function logoutCodexSubscription(options) {
|
|
|
18470
18568
|
await session.close();
|
|
18471
18569
|
}
|
|
18472
18570
|
}
|
|
18473
|
-
var CODEX_INFERENCE_PERMISSION_PROFILE, CodexAppServerError, objectOrNull, finiteToken, tokenUsageFromBreakdown, usageFromNotification, forbiddenMethod, forbiddenTerminalItem, classifyCodexTurnFailure, scrubbedCodexEnvironment, killWindowsProcessTree, appServerArgs, GUARDIAN_SCRIPT, writeCodexGuardianSpawnIntent, parseGuardianReceipt, readCodexGuardianReceipt, waitForCodexGuardianState, defaultSpawn, CodexAppServerSession;
|
|
18571
|
+
var CODEX_INFERENCE_PERMISSION_PROFILE, CODEX_ACCOUNT_PLAN_TYPES, CodexAppServerError, objectOrNull, finiteToken, tokenUsageFromBreakdown, usageFromNotification, validPlanType, nonnegativeSafeIntegerOrNull, nonnegativeFiniteNumberOrNull, parseRateLimitWindow, RATE_LIMIT_REACHED_TYPES, DEFAULT_CODEX_QUOTA_COOLDOWN_MS, MAX_CODEX_QUOTA_COOLDOWN_MS, CODEX_TRANSIENT_RATE_LIMIT_COOLDOWN_MS, parseRateLimitSnapshot, codexRateLimitRetryAtMs, codexAccountRateLimitReached, forbiddenMethod, forbiddenTerminalItem, classifyCodexTurnFailure, scrubbedCodexEnvironment, killWindowsProcessTree, appServerArgs, GUARDIAN_SCRIPT, writeCodexGuardianSpawnIntent, parseGuardianReceipt, readCodexGuardianReceipt, waitForCodexGuardianState, defaultSpawn, CodexAppServerSession;
|
|
18474
18572
|
var init_codex_app_server = __esm({
|
|
18475
18573
|
"lib/inference-host/codex-app-server.ts"() {
|
|
18476
18574
|
"use strict";
|
|
18477
18575
|
CODEX_INFERENCE_PERMISSION_PROFILE = "vtx_inference_readonly";
|
|
18576
|
+
CODEX_ACCOUNT_PLAN_TYPES = [
|
|
18577
|
+
"free",
|
|
18578
|
+
"go",
|
|
18579
|
+
"plus",
|
|
18580
|
+
"pro",
|
|
18581
|
+
"prolite",
|
|
18582
|
+
"team",
|
|
18583
|
+
"self_serve_business_prolite",
|
|
18584
|
+
"self_serve_business_usage_based",
|
|
18585
|
+
"business",
|
|
18586
|
+
"ent26",
|
|
18587
|
+
"enterprise_cbp_automation",
|
|
18588
|
+
"enterprise_cbp_usage_based",
|
|
18589
|
+
"enterprise",
|
|
18590
|
+
"edu",
|
|
18591
|
+
"unknown"
|
|
18592
|
+
];
|
|
18478
18593
|
CodexAppServerError = class extends Error {
|
|
18479
18594
|
constructor(options) {
|
|
18480
18595
|
super(options.message, { cause: options.cause });
|
|
@@ -18483,6 +18598,9 @@ var init_codex_app_server = __esm({
|
|
|
18483
18598
|
this.code = options.code;
|
|
18484
18599
|
this.retryable = options.retryable;
|
|
18485
18600
|
this.dispatchOutcome = options.dispatchOutcome ?? "not_dispatched";
|
|
18601
|
+
this.httpStatusCode = options.httpStatusCode ?? null;
|
|
18602
|
+
this.retryAtMs = options.retryAtMs ?? null;
|
|
18603
|
+
this.usage = options.usage ?? null;
|
|
18486
18604
|
}
|
|
18487
18605
|
};
|
|
18488
18606
|
objectOrNull = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -18523,6 +18641,72 @@ var init_codex_app_server = __esm({
|
|
|
18523
18641
|
}
|
|
18524
18642
|
return null;
|
|
18525
18643
|
};
|
|
18644
|
+
validPlanType = (value) => typeof value === "string" && CODEX_ACCOUNT_PLAN_TYPES.includes(value);
|
|
18645
|
+
nonnegativeSafeIntegerOrNull = (value) => Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : null;
|
|
18646
|
+
nonnegativeFiniteNumberOrNull = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
18647
|
+
parseRateLimitWindow = (value) => {
|
|
18648
|
+
if (value === null) return null;
|
|
18649
|
+
const candidate = objectOrNull(value);
|
|
18650
|
+
if (!candidate) throw new Error("invalid rate-limit window");
|
|
18651
|
+
const usedPercent = nonnegativeFiniteNumberOrNull(candidate.usedPercent);
|
|
18652
|
+
const windowDurationMins = candidate.windowDurationMins == null ? null : nonnegativeSafeIntegerOrNull(candidate.windowDurationMins);
|
|
18653
|
+
const resetsAt = candidate.resetsAt == null ? null : nonnegativeSafeIntegerOrNull(candidate.resetsAt);
|
|
18654
|
+
if (usedPercent === null || windowDurationMins === null && candidate.windowDurationMins != null || resetsAt === null && candidate.resetsAt != null) {
|
|
18655
|
+
throw new Error("invalid rate-limit window");
|
|
18656
|
+
}
|
|
18657
|
+
return { usedPercent, windowDurationMins, resetsAt };
|
|
18658
|
+
};
|
|
18659
|
+
RATE_LIMIT_REACHED_TYPES = [
|
|
18660
|
+
"rate_limit_reached",
|
|
18661
|
+
"workspace_owner_credits_depleted",
|
|
18662
|
+
"workspace_member_credits_depleted",
|
|
18663
|
+
"workspace_owner_usage_limit_reached",
|
|
18664
|
+
"workspace_member_usage_limit_reached"
|
|
18665
|
+
];
|
|
18666
|
+
DEFAULT_CODEX_QUOTA_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
18667
|
+
MAX_CODEX_QUOTA_COOLDOWN_MS = 8 * 24 * 60 * 60 * 1e3;
|
|
18668
|
+
CODEX_TRANSIENT_RATE_LIMIT_COOLDOWN_MS = 30 * 1e3;
|
|
18669
|
+
parseRateLimitSnapshot = (value) => {
|
|
18670
|
+
const candidate = objectOrNull(value);
|
|
18671
|
+
if (!candidate) throw new Error("invalid rate-limit snapshot");
|
|
18672
|
+
const limitId = candidate.limitId === null || candidate.limitId === void 0 ? null : typeof candidate.limitId === "string" && candidate.limitId.trim() ? candidate.limitId.trim() : void 0;
|
|
18673
|
+
const limitName = candidate.limitName === null || candidate.limitName === void 0 ? null : typeof candidate.limitName === "string" && candidate.limitName.trim() ? candidate.limitName.trim() : void 0;
|
|
18674
|
+
const planType = candidate.planType === null || candidate.planType === void 0 ? null : validPlanType(candidate.planType) ? candidate.planType : void 0;
|
|
18675
|
+
const reached = candidate.rateLimitReachedType === null || candidate.rateLimitReachedType === void 0 ? null : typeof candidate.rateLimitReachedType === "string" && RATE_LIMIT_REACHED_TYPES.includes(candidate.rateLimitReachedType) ? candidate.rateLimitReachedType : void 0;
|
|
18676
|
+
const spendControlReached = candidate.spendControlReached === null || candidate.spendControlReached === void 0 ? null : typeof candidate.spendControlReached === "boolean" ? candidate.spendControlReached : void 0;
|
|
18677
|
+
if (limitId === void 0 || limitName === void 0 || planType === void 0 || reached === void 0 || spendControlReached === void 0) throw new Error("invalid rate-limit snapshot");
|
|
18678
|
+
return {
|
|
18679
|
+
limitId,
|
|
18680
|
+
limitName,
|
|
18681
|
+
planType,
|
|
18682
|
+
primary: parseRateLimitWindow(candidate.primary ?? null),
|
|
18683
|
+
secondary: parseRateLimitWindow(candidate.secondary ?? null),
|
|
18684
|
+
rateLimitReachedType: reached,
|
|
18685
|
+
spendControlReached
|
|
18686
|
+
};
|
|
18687
|
+
};
|
|
18688
|
+
codexRateLimitRetryAtMs = (accountRateLimits) => {
|
|
18689
|
+
const snapshots = [accountRateLimits.rateLimits];
|
|
18690
|
+
const exhaustedResets = [];
|
|
18691
|
+
const reachedResets = [];
|
|
18692
|
+
for (const snapshot of snapshots) {
|
|
18693
|
+
const windows = [snapshot.primary, snapshot.secondary].filter(
|
|
18694
|
+
(window2) => window2 !== null
|
|
18695
|
+
);
|
|
18696
|
+
for (const window2 of windows) {
|
|
18697
|
+
if (window2.resetsAt === null) continue;
|
|
18698
|
+
const resetAtMs = window2.resetsAt * 1e3;
|
|
18699
|
+
if (!Number.isSafeInteger(resetAtMs)) continue;
|
|
18700
|
+
if (window2.usedPercent >= 100) exhaustedResets.push(resetAtMs);
|
|
18701
|
+
if (snapshot.rateLimitReachedType !== null || snapshot.spendControlReached === true) {
|
|
18702
|
+
reachedResets.push(resetAtMs);
|
|
18703
|
+
}
|
|
18704
|
+
}
|
|
18705
|
+
}
|
|
18706
|
+
const candidates = exhaustedResets.length > 0 ? exhaustedResets : reachedResets.length > 0 ? reachedResets : [];
|
|
18707
|
+
return candidates.length > 0 ? Math.max(...candidates) : null;
|
|
18708
|
+
};
|
|
18709
|
+
codexAccountRateLimitReached = (accountRateLimits) => [accountRateLimits.rateLimits].some((snapshot) => snapshot.rateLimitReachedType !== null || snapshot.spendControlReached === true || snapshot.primary?.usedPercent !== void 0 && snapshot.primary.usedPercent >= 100 || snapshot.secondary?.usedPercent !== void 0 && snapshot.secondary.usedPercent >= 100);
|
|
18526
18710
|
forbiddenMethod = (method) => method.startsWith("mcpServer/") || method.startsWith("serverRequest/") || method.startsWith("item/mcpToolCall") || method.startsWith("item/commandExecution") || method.startsWith("item/fileChange") || method.startsWith("item/dynamicToolCall") || method.startsWith("item/collabAgentToolCall");
|
|
18527
18711
|
forbiddenTerminalItem = (item) => ![
|
|
18528
18712
|
"userMessage",
|
|
@@ -18531,13 +18715,13 @@ var init_codex_app_server = __esm({
|
|
|
18531
18715
|
].includes(String(item.type || ""));
|
|
18532
18716
|
classifyCodexTurnFailure = (codexErrorInfo, terminalStatus) => {
|
|
18533
18717
|
if (terminalStatus === "interrupted") {
|
|
18534
|
-
return { code: "cancelled", category: "cancelled", retryable: false };
|
|
18718
|
+
return { code: "cancelled", category: "cancelled", retryable: false, httpStatusCode: null };
|
|
18535
18719
|
}
|
|
18536
18720
|
if (codexErrorInfo === "usageLimitExceeded") {
|
|
18537
|
-
return { code: "quota_exceeded", category: "model", retryable: false };
|
|
18721
|
+
return { code: "quota_exceeded", category: "model", retryable: false, httpStatusCode: null };
|
|
18538
18722
|
}
|
|
18539
18723
|
if (codexErrorInfo === "unauthorized") {
|
|
18540
|
-
return { code: "auth_expired", category: "auth", retryable: false };
|
|
18724
|
+
return { code: "auth_expired", category: "auth", retryable: false, httpStatusCode: null };
|
|
18541
18725
|
}
|
|
18542
18726
|
const stableStringCodes = {
|
|
18543
18727
|
badRequest: "codex_bad_request",
|
|
@@ -18554,22 +18738,40 @@ var init_codex_app_server = __esm({
|
|
|
18554
18738
|
return {
|
|
18555
18739
|
code,
|
|
18556
18740
|
category: "adapter",
|
|
18557
|
-
retryable: code === "codex_internal_error" || code === "codex_server_overloaded"
|
|
18741
|
+
retryable: code === "codex_internal_error" || code === "codex_server_overloaded",
|
|
18742
|
+
httpStatusCode: null
|
|
18558
18743
|
};
|
|
18559
18744
|
}
|
|
18560
18745
|
const structured = objectOrNull(codexErrorInfo);
|
|
18561
18746
|
if (structured) {
|
|
18562
|
-
|
|
18563
|
-
|
|
18564
|
-
|
|
18565
|
-
|
|
18566
|
-
|
|
18567
|
-
|
|
18568
|
-
|
|
18569
|
-
|
|
18747
|
+
const variants = [
|
|
18748
|
+
["httpConnectionFailed", "codex_http_connection_failed"],
|
|
18749
|
+
["responseStreamConnectionFailed", "codex_response_stream_connection_failed"],
|
|
18750
|
+
["responseStreamDisconnected", "codex_response_stream_disconnected"],
|
|
18751
|
+
["responseTooManyFailedAttempts", "codex_provider_retry_exhausted"]
|
|
18752
|
+
];
|
|
18753
|
+
for (const [variant, code] of variants) {
|
|
18754
|
+
if (!(variant in structured)) continue;
|
|
18755
|
+
const details = objectOrNull(structured[variant]);
|
|
18756
|
+
const rawStatus = details?.httpStatusCode;
|
|
18757
|
+
const httpStatusCode = Number.isSafeInteger(rawStatus) && Number(rawStatus) >= 100 && Number(rawStatus) <= 599 ? Number(rawStatus) : null;
|
|
18758
|
+
if (httpStatusCode === 429) {
|
|
18759
|
+
return {
|
|
18760
|
+
code: "codex_rate_limited",
|
|
18761
|
+
category: "adapter",
|
|
18762
|
+
retryable: true,
|
|
18763
|
+
httpStatusCode
|
|
18764
|
+
};
|
|
18765
|
+
}
|
|
18766
|
+
return {
|
|
18767
|
+
code,
|
|
18768
|
+
category: "adapter",
|
|
18769
|
+
retryable: httpStatusCode === null ? variant !== "responseTooManyFailedAttempts" : httpStatusCode === 408 || httpStatusCode === 425 || httpStatusCode >= 500,
|
|
18770
|
+
httpStatusCode
|
|
18771
|
+
};
|
|
18570
18772
|
}
|
|
18571
18773
|
}
|
|
18572
|
-
return { code: "turn_failed", category: "adapter", retryable: false };
|
|
18774
|
+
return { code: "turn_failed", category: "adapter", retryable: false, httpStatusCode: null };
|
|
18573
18775
|
};
|
|
18574
18776
|
scrubbedCodexEnvironment = (codexHome) => {
|
|
18575
18777
|
if (process.platform === "win32") {
|
|
@@ -19049,13 +19251,80 @@ child.once('close', async () => {
|
|
|
19049
19251
|
this.fatalListeners.add(listener);
|
|
19050
19252
|
return () => this.fatalListeners.delete(listener);
|
|
19051
19253
|
}
|
|
19052
|
-
async
|
|
19254
|
+
async readAccountSnapshot(deadlineAtMs, signal, refreshToken = false) {
|
|
19053
19255
|
const result2 = await this.request("account/read", { refreshToken }, {
|
|
19054
19256
|
timeoutMs: Math.max(1, deadlineAtMs - Date.now()),
|
|
19055
19257
|
signal
|
|
19056
19258
|
});
|
|
19057
19259
|
const account = objectOrNull(result2.account);
|
|
19058
|
-
|
|
19260
|
+
if (typeof result2.requiresOpenaiAuth !== "boolean") {
|
|
19261
|
+
throw new CodexAppServerError({
|
|
19262
|
+
message: "Codex returned invalid account metadata.",
|
|
19263
|
+
category: "auth",
|
|
19264
|
+
code: "invalid_account_metadata",
|
|
19265
|
+
retryable: false
|
|
19266
|
+
});
|
|
19267
|
+
}
|
|
19268
|
+
if (account?.type === "chatgpt") {
|
|
19269
|
+
const email3 = account.email === null ? null : typeof account.email === "string" && account.email.trim() ? account.email.trim() : void 0;
|
|
19270
|
+
if (email3 === void 0 || !validPlanType(account.planType)) {
|
|
19271
|
+
throw new CodexAppServerError({
|
|
19272
|
+
message: "Codex returned invalid managed ChatGPT account metadata.",
|
|
19273
|
+
category: "auth",
|
|
19274
|
+
code: "invalid_account_metadata",
|
|
19275
|
+
retryable: false
|
|
19276
|
+
});
|
|
19277
|
+
}
|
|
19278
|
+
return {
|
|
19279
|
+
requiresOpenaiAuth: result2.requiresOpenaiAuth,
|
|
19280
|
+
authenticatedChatGptAccount: { email: email3, planType: account.planType }
|
|
19281
|
+
};
|
|
19282
|
+
}
|
|
19283
|
+
if (account !== null && account?.type !== "apiKey" && account?.type !== "amazonBedrock") {
|
|
19284
|
+
throw new CodexAppServerError({
|
|
19285
|
+
message: "Codex returned an unsupported account type.",
|
|
19286
|
+
category: "auth",
|
|
19287
|
+
code: "invalid_account_metadata",
|
|
19288
|
+
retryable: false
|
|
19289
|
+
});
|
|
19290
|
+
}
|
|
19291
|
+
return {
|
|
19292
|
+
requiresOpenaiAuth: result2.requiresOpenaiAuth,
|
|
19293
|
+
authenticatedChatGptAccount: null
|
|
19294
|
+
};
|
|
19295
|
+
}
|
|
19296
|
+
async hasManagedChatGptAuth(deadlineAtMs, signal, refreshToken = false) {
|
|
19297
|
+
const snapshot = await this.readAccountSnapshot(deadlineAtMs, signal, refreshToken);
|
|
19298
|
+
return snapshot.authenticatedChatGptAccount !== null && snapshot.requiresOpenaiAuth;
|
|
19299
|
+
}
|
|
19300
|
+
async readAccountRateLimits(deadlineAtMs, signal) {
|
|
19301
|
+
const result2 = await this.request("account/rateLimits/read", void 0, {
|
|
19302
|
+
timeoutMs: Math.max(1, deadlineAtMs - Date.now()),
|
|
19303
|
+
signal
|
|
19304
|
+
});
|
|
19305
|
+
try {
|
|
19306
|
+
const rateLimits = parseRateLimitSnapshot(result2.rateLimits);
|
|
19307
|
+
const rawByLimitId = result2.rateLimitsByLimitId;
|
|
19308
|
+
let rateLimitsByLimitId = null;
|
|
19309
|
+
if (rawByLimitId !== null && rawByLimitId !== void 0) {
|
|
19310
|
+
const byLimitId = objectOrNull(rawByLimitId);
|
|
19311
|
+
if (!byLimitId) throw new Error("invalid rate-limit bucket map");
|
|
19312
|
+
rateLimitsByLimitId = {};
|
|
19313
|
+
for (const [limitId, snapshot] of Object.entries(byLimitId)) {
|
|
19314
|
+
if (!limitId.trim()) throw new Error("invalid rate-limit bucket identity");
|
|
19315
|
+
rateLimitsByLimitId[limitId] = parseRateLimitSnapshot(snapshot);
|
|
19316
|
+
}
|
|
19317
|
+
}
|
|
19318
|
+
return { rateLimits, rateLimitsByLimitId };
|
|
19319
|
+
} catch (error48) {
|
|
19320
|
+
throw new CodexAppServerError({
|
|
19321
|
+
message: "Codex returned invalid account rate-limit metadata.",
|
|
19322
|
+
category: "adapter",
|
|
19323
|
+
code: "invalid_rate_limit_metadata",
|
|
19324
|
+
retryable: false,
|
|
19325
|
+
cause: error48
|
|
19326
|
+
});
|
|
19327
|
+
}
|
|
19059
19328
|
}
|
|
19060
19329
|
async requireManagedChatGptAuth(deadlineAtMs, signal, refreshToken = false) {
|
|
19061
19330
|
if (!await this.hasManagedChatGptAuth(deadlineAtMs, signal, refreshToken)) {
|
|
@@ -19592,13 +19861,54 @@ child.once('close', async () => {
|
|
|
19592
19861
|
}
|
|
19593
19862
|
if (terminal.status !== "completed") {
|
|
19594
19863
|
const turnError = objectOrNull(terminal.error);
|
|
19595
|
-
|
|
19864
|
+
let failure = classifyCodexTurnFailure(
|
|
19865
|
+
turnError?.codexErrorInfo,
|
|
19866
|
+
String(terminal.status)
|
|
19867
|
+
);
|
|
19868
|
+
const observedUsage = threadUsage ?? rawResponseUsage;
|
|
19869
|
+
let retryAtMs = null;
|
|
19870
|
+
if (failure.code === "quota_exceeded" || failure.httpStatusCode === 429) {
|
|
19871
|
+
const observedAtMs = Date.now();
|
|
19872
|
+
let accountLimitReached = failure.code === "quota_exceeded";
|
|
19873
|
+
try {
|
|
19874
|
+
const metadataDeadlineAtMs = Math.min(
|
|
19875
|
+
request.deadlineAtMs,
|
|
19876
|
+
observedAtMs + 5e3
|
|
19877
|
+
);
|
|
19878
|
+
if (metadataDeadlineAtMs <= observedAtMs) throw new Error("rate-limit deadline elapsed");
|
|
19879
|
+
const rateLimits = await this.readAccountRateLimits(metadataDeadlineAtMs, request.signal);
|
|
19880
|
+
accountLimitReached = accountLimitReached || codexAccountRateLimitReached(rateLimits);
|
|
19881
|
+
retryAtMs = codexRateLimitRetryAtMs(rateLimits);
|
|
19882
|
+
} catch {
|
|
19883
|
+
}
|
|
19884
|
+
if (accountLimitReached) {
|
|
19885
|
+
failure = {
|
|
19886
|
+
...failure,
|
|
19887
|
+
code: "quota_exceeded",
|
|
19888
|
+
category: "model",
|
|
19889
|
+
retryable: false
|
|
19890
|
+
};
|
|
19891
|
+
if (retryAtMs === null || retryAtMs <= observedAtMs) {
|
|
19892
|
+
retryAtMs = observedAtMs + DEFAULT_CODEX_QUOTA_COOLDOWN_MS;
|
|
19893
|
+
} else {
|
|
19894
|
+
retryAtMs = Math.min(
|
|
19895
|
+
retryAtMs,
|
|
19896
|
+
observedAtMs + MAX_CODEX_QUOTA_COOLDOWN_MS
|
|
19897
|
+
);
|
|
19898
|
+
}
|
|
19899
|
+
} else {
|
|
19900
|
+
retryAtMs = observedAtMs + CODEX_TRANSIENT_RATE_LIMIT_COOLDOWN_MS;
|
|
19901
|
+
}
|
|
19902
|
+
}
|
|
19596
19903
|
throw new CodexAppServerError({
|
|
19597
19904
|
message: "Codex turn did not complete successfully.",
|
|
19598
19905
|
category: failure.category,
|
|
19599
19906
|
code: failure.code,
|
|
19600
19907
|
retryable: failure.retryable,
|
|
19601
|
-
dispatchOutcome: "confirmed_dispatched"
|
|
19908
|
+
dispatchOutcome: "confirmed_dispatched",
|
|
19909
|
+
httpStatusCode: failure.httpStatusCode,
|
|
19910
|
+
retryAtMs,
|
|
19911
|
+
usage: observedUsage
|
|
19602
19912
|
});
|
|
19603
19913
|
}
|
|
19604
19914
|
const items = Array.isArray(terminal.items) ? terminal.items.map(objectOrNull) : [];
|
|
@@ -19958,7 +20268,10 @@ var init_codex_adapter = __esm({
|
|
|
19958
20268
|
category: external_exports.enum(["auth", "model", "schema", "timeout", "cancelled", "transport", "adapter"]),
|
|
19959
20269
|
code: external_exports.string().min(1).max(96),
|
|
19960
20270
|
retryable: external_exports.boolean(),
|
|
19961
|
-
dispatchOutcome: external_exports.enum(["not_dispatched", "confirmed_dispatched", "outcome_unknown"])
|
|
20271
|
+
dispatchOutcome: external_exports.enum(["not_dispatched", "confirmed_dispatched", "outcome_unknown"]),
|
|
20272
|
+
httpStatusCode: external_exports.number().int().min(100).max(599).nullable().optional(),
|
|
20273
|
+
retryAtMs: external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).nullable().optional(),
|
|
20274
|
+
usage: tokenUsageReceiptSchema.nullable().optional()
|
|
19962
20275
|
})
|
|
19963
20276
|
})
|
|
19964
20277
|
]);
|
|
@@ -20479,7 +20792,10 @@ var init_codex_adapter = __esm({
|
|
|
20479
20792
|
category: recovered.category,
|
|
20480
20793
|
code: recovered.code,
|
|
20481
20794
|
retryable: recovered.retryable,
|
|
20482
|
-
dispatchOutcome: recovered.dispatchOutcome
|
|
20795
|
+
dispatchOutcome: recovered.dispatchOutcome,
|
|
20796
|
+
httpStatusCode: recovered.httpStatusCode,
|
|
20797
|
+
retryAtMs: recovered.retryAtMs,
|
|
20798
|
+
usage: recovered.usage
|
|
20483
20799
|
});
|
|
20484
20800
|
}
|
|
20485
20801
|
throw new CodexAppServerError({
|
|
@@ -20618,7 +20934,10 @@ var init_codex_adapter = __esm({
|
|
|
20618
20934
|
category: error48.category,
|
|
20619
20935
|
code: error48.code,
|
|
20620
20936
|
retryable: error48.retryable,
|
|
20621
|
-
dispatchOutcome
|
|
20937
|
+
dispatchOutcome,
|
|
20938
|
+
httpStatusCode: error48.httpStatusCode,
|
|
20939
|
+
retryAtMs: error48.retryAtMs,
|
|
20940
|
+
usage: error48.usage
|
|
20622
20941
|
}
|
|
20623
20942
|
}
|
|
20624
20943
|
};
|
|
@@ -20631,6 +20950,9 @@ var init_codex_adapter = __esm({
|
|
|
20631
20950
|
code: error48.code,
|
|
20632
20951
|
retryable: error48.retryable,
|
|
20633
20952
|
dispatchOutcome,
|
|
20953
|
+
httpStatusCode: error48.httpStatusCode,
|
|
20954
|
+
retryAtMs: error48.retryAtMs,
|
|
20955
|
+
usage: error48.usage,
|
|
20634
20956
|
cause: error48
|
|
20635
20957
|
});
|
|
20636
20958
|
}
|
|
@@ -27310,7 +27632,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
|
|
|
27310
27632
|
envelopePublicKey: options.envelopePublicKey
|
|
27311
27633
|
};
|
|
27312
27634
|
}
|
|
27313
|
-
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_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, DEFAULT_MAX_CONCURRENCY, MIN_SLEEP_MS, CODEX_INFERENCE_ADVERTISED_MODEL, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, safeFailureCode, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedUsage, InferenceHostRunner;
|
|
27635
|
+
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_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, DEFAULT_MAX_CONCURRENCY, MIN_SLEEP_MS, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, CODEX_INFERENCE_ADVERTISED_MODEL, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, safeFailureCode, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner;
|
|
27314
27636
|
var init_runner = __esm({
|
|
27315
27637
|
"lib/inference-host/runner.ts"() {
|
|
27316
27638
|
"use strict";
|
|
@@ -27333,6 +27655,7 @@ var init_runner = __esm({
|
|
|
27333
27655
|
DEFAULT_REMOTE_RETRY_LIMIT = 3;
|
|
27334
27656
|
DEFAULT_MAX_CONCURRENCY = 1;
|
|
27335
27657
|
MIN_SLEEP_MS = 10;
|
|
27658
|
+
DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
27336
27659
|
CODEX_INFERENCE_ADVERTISED_MODEL = Object.freeze({
|
|
27337
27660
|
model_id: INITIAL_CODEX_INFERENCE_MODEL,
|
|
27338
27661
|
label: "Codex GPT-5.6 Sol",
|
|
@@ -27622,19 +27945,14 @@ var init_runner = __esm({
|
|
|
27622
27945
|
};
|
|
27623
27946
|
retryableRemoteError = (error48) => {
|
|
27624
27947
|
if (error48 instanceof ExternalInferenceMcpError) {
|
|
27625
|
-
return
|
|
27626
|
-
"network_error",
|
|
27627
|
-
"transport_rejected",
|
|
27628
|
-
"invalid_response",
|
|
27629
|
-
"request_timeout",
|
|
27630
|
-
"authentication_timeout"
|
|
27631
|
-
].includes(error48.code);
|
|
27948
|
+
return error48.retryable;
|
|
27632
27949
|
}
|
|
27633
27950
|
if (error48 && typeof error48 === "object" && "retryable" in error48) {
|
|
27634
27951
|
return error48.retryable === true;
|
|
27635
27952
|
}
|
|
27636
27953
|
return false;
|
|
27637
27954
|
};
|
|
27955
|
+
remoteRetryAfterMs = (error48, fallbackMs) => error48 instanceof ExternalInferenceMcpError && error48.retryAfterMs !== null && Number.isSafeInteger(error48.retryAfterMs) && error48.retryAfterMs >= 0 ? Math.max(fallbackMs, error48.retryAfterMs) : fallbackMs;
|
|
27638
27956
|
controlPlaneFatal = (error48) => {
|
|
27639
27957
|
const code = error48 && typeof error48 === "object" && "code" in error48 ? String(error48.code) : "";
|
|
27640
27958
|
return [
|
|
@@ -27757,11 +28075,12 @@ var init_runner = __esm({
|
|
|
27757
28075
|
};
|
|
27758
28076
|
assertAdvertisementResult = (advertisement, result2) => {
|
|
27759
28077
|
const host = result2.host;
|
|
27760
|
-
if (host.host_id !== advertisement.host_id || host.host_generation !== advertisement.host_generation || host.advertisement_generation !== advertisement.advertisement_generation || host.key_generation !== advertisement.key_generation || host.display_name !== advertisement.display_name || host.adapter !== advertisement.adapter || host.status === "revoked" || !exactJson2(host.models, advertisement.models)) runnerIdentityMismatch("Host advertisement");
|
|
28078
|
+
if (host.host_id !== advertisement.host_id || host.host_generation !== advertisement.host_generation || host.advertisement_generation !== advertisement.advertisement_generation || host.key_generation !== advertisement.key_generation || host.display_name !== advertisement.display_name || (host.authenticated_account_email ?? null) !== (advertisement.authenticated_account_email ?? null) || (host.authenticated_account_plan ?? null) !== (advertisement.authenticated_account_plan ?? null) || host.adapter !== advertisement.adapter || host.status === "revoked" || !exactJson2(host.models, advertisement.models)) runnerIdentityMismatch("Host advertisement");
|
|
27761
28079
|
};
|
|
27762
|
-
assertHostHeartbeatResult = (request, result2) => {
|
|
28080
|
+
assertHostHeartbeatResult = (request, result2, allowOfflineProjection = false) => {
|
|
27763
28081
|
const expectedStatus = request.status === "healthy" ? "online" : request.status;
|
|
27764
|
-
|
|
28082
|
+
const expectedTemporaryOffline = allowOfflineProjection && request.status === "healthy" && result2.host.status === "offline";
|
|
28083
|
+
if (result2.host.host_id !== request.host_id || result2.host.host_generation !== request.host_generation || result2.host.advertisement_generation !== request.advertisement_generation || result2.host.key_generation !== request.key_generation || result2.host.adapter !== "codex" || result2.host.status !== expectedStatus && !expectedTemporaryOffline) runnerIdentityMismatch("Host heartbeat");
|
|
27765
28084
|
};
|
|
27766
28085
|
assertClaimResult = (request, result2) => {
|
|
27767
28086
|
if (result2.claim_request_id !== request.claim_request_id) {
|
|
@@ -27797,7 +28116,13 @@ var init_runner = __esm({
|
|
|
27797
28116
|
};
|
|
27798
28117
|
}
|
|
27799
28118
|
if (error48 instanceof ExternalInferenceMcpError) {
|
|
27800
|
-
const category2 = error48.code.startsWith("authentication") ? "auth" : [
|
|
28119
|
+
const category2 = error48.code.startsWith("authentication") ? "auth" : [
|
|
28120
|
+
"network_error",
|
|
28121
|
+
"transport_rejected",
|
|
28122
|
+
"server_rejected",
|
|
28123
|
+
"rate_limited",
|
|
28124
|
+
"request_timeout"
|
|
28125
|
+
].includes(error48.code) ? "network" : "transport";
|
|
27801
28126
|
return {
|
|
27802
28127
|
category: category2,
|
|
27803
28128
|
code: safeFailureCode(error48.code, "transport_failure"),
|
|
@@ -27823,24 +28148,27 @@ var init_runner = __esm({
|
|
|
27823
28148
|
return [
|
|
27824
28149
|
"network_error",
|
|
27825
28150
|
"transport_rejected",
|
|
28151
|
+
"server_rejected",
|
|
28152
|
+
"rate_limited",
|
|
27826
28153
|
"invalid_response",
|
|
27827
28154
|
"identity_mismatch",
|
|
27828
28155
|
"request_timeout",
|
|
27829
28156
|
"authentication_timeout"
|
|
27830
28157
|
].includes(code);
|
|
27831
28158
|
};
|
|
27832
|
-
|
|
28159
|
+
reportedTokenUsage = (usage) => ({
|
|
27833
28160
|
schema_version: EXTERNAL_INFERENCE_USAGE_SCHEMA_VERSION,
|
|
27834
28161
|
availability: "reported",
|
|
27835
28162
|
source: "codex_app_server",
|
|
27836
|
-
input_tokens:
|
|
27837
|
-
cached_input_tokens:
|
|
27838
|
-
output_tokens:
|
|
27839
|
-
reasoning_output_tokens:
|
|
27840
|
-
total_tokens:
|
|
27841
|
-
cache_write_input_tokens:
|
|
27842
|
-
cache_write_support:
|
|
27843
|
-
});
|
|
28163
|
+
input_tokens: usage.inputTokens,
|
|
28164
|
+
cached_input_tokens: usage.cachedInputTokens,
|
|
28165
|
+
output_tokens: usage.outputTokens,
|
|
28166
|
+
reasoning_output_tokens: usage.reasoningOutputTokens,
|
|
28167
|
+
total_tokens: usage.totalTokens,
|
|
28168
|
+
cache_write_input_tokens: usage.cacheWriteInputTokens,
|
|
28169
|
+
cache_write_support: usage.cacheWriteSupported ? "reported" : "unsupported"
|
|
28170
|
+
});
|
|
28171
|
+
reportedUsage = (result2) => reportedTokenUsage(result2.usage);
|
|
27844
28172
|
InferenceHostRunner = class {
|
|
27845
28173
|
constructor(dependencies, options) {
|
|
27846
28174
|
this.receiptWriteChain = Promise.resolve();
|
|
@@ -28003,24 +28331,24 @@ var init_runner = __esm({
|
|
|
28003
28331
|
} catch (error48) {
|
|
28004
28332
|
lastError = error48;
|
|
28005
28333
|
if (!retryableRemoteError(error48) || attempt === settings.remoteRetryLimit) throw error48;
|
|
28006
|
-
const
|
|
28007
|
-
|
|
28008
|
-
1e3
|
|
28009
|
-
boundary.deadlineAtMs === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, boundary.deadlineAtMs - now())
|
|
28334
|
+
const requestedRetryDelay = remoteRetryAfterMs(
|
|
28335
|
+
error48,
|
|
28336
|
+
Math.min(250 * attempt, 1e3)
|
|
28010
28337
|
);
|
|
28011
|
-
|
|
28338
|
+
const remaining = boundary.deadlineAtMs === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, boundary.deadlineAtMs - now());
|
|
28339
|
+
if (requestedRetryDelay < 1 || requestedRetryDelay >= remaining) {
|
|
28012
28340
|
throw new ExternalInferenceMcpError(
|
|
28013
28341
|
"request_timeout",
|
|
28014
28342
|
"Insights MCP retry deadline elapsed.",
|
|
28015
28343
|
{ cause: error48 }
|
|
28016
28344
|
);
|
|
28017
28345
|
}
|
|
28018
|
-
await sleep4(
|
|
28346
|
+
await sleep4(requestedRetryDelay, boundary.signal);
|
|
28019
28347
|
}
|
|
28020
28348
|
}
|
|
28021
28349
|
throw lastError;
|
|
28022
28350
|
};
|
|
28023
|
-
const publishAdvertisement = async (health, forceAdvance) => {
|
|
28351
|
+
const publishAdvertisement = async (health, forceAdvance, retryRemote = true) => {
|
|
28024
28352
|
let advertisement = receipt.pending_advertisement;
|
|
28025
28353
|
if (!advertisement) {
|
|
28026
28354
|
const generation = receipt.registered && forceAdvance ? receipt.advertisement_generation + 1 : receipt.advertisement_generation;
|
|
@@ -28041,6 +28369,8 @@ var init_runner = __esm({
|
|
|
28041
28369
|
key_generation: localState.key_generation,
|
|
28042
28370
|
adapter: "codex",
|
|
28043
28371
|
display_name: this.options.displayName.trim(),
|
|
28372
|
+
authenticated_account_email: this.options.authenticatedAccountEmail ?? null,
|
|
28373
|
+
authenticated_account_plan: this.options.authenticatedAccountPlan ?? null,
|
|
28044
28374
|
protocol_version: this.options.protocolVersion,
|
|
28045
28375
|
envelope_public_key: envelopePublicKey,
|
|
28046
28376
|
health,
|
|
@@ -28063,15 +28393,12 @@ var init_runner = __esm({
|
|
|
28063
28393
|
const tool = receipt.registered ? "inference.host.advertise" : "inference.host.register";
|
|
28064
28394
|
let result2;
|
|
28065
28395
|
try {
|
|
28066
|
-
|
|
28396
|
+
const advertiseOperation = () => mcp.callTool(
|
|
28067
28397
|
tool,
|
|
28068
28398
|
advertisement,
|
|
28069
28399
|
{ signal: this.options.signal }
|
|
28070
|
-
)
|
|
28071
|
-
|
|
28072
|
-
advertisement,
|
|
28073
|
-
{ signal: this.options.signal }
|
|
28074
|
-
), { signal: this.options.signal });
|
|
28400
|
+
);
|
|
28401
|
+
result2 = retryRemote ? await retryExact(advertiseOperation, { signal: this.options.signal }) : await advertiseOperation();
|
|
28075
28402
|
} catch (error48) {
|
|
28076
28403
|
const definitivelyNotApplied = error48 instanceof ExternalInferenceMcpError ? error48.definitivelyNotApplied : Boolean(error48 && typeof error48 === "object" && error48.definitivelyNotApplied === true);
|
|
28077
28404
|
const expectedGeneration = receipt.registered ? receipt.advertisement_generation + 1 : receipt.advertisement_generation;
|
|
@@ -28082,7 +28409,7 @@ var init_runner = __esm({
|
|
|
28082
28409
|
updated_at: isoAt(now())
|
|
28083
28410
|
};
|
|
28084
28411
|
await this.persistReceipt(receipt, now);
|
|
28085
|
-
return await publishAdvertisement(health, forceAdvance);
|
|
28412
|
+
return await publishAdvertisement(health, forceAdvance, retryRemote);
|
|
28086
28413
|
}
|
|
28087
28414
|
throw error48;
|
|
28088
28415
|
}
|
|
@@ -28104,7 +28431,7 @@ var init_runner = __esm({
|
|
|
28104
28431
|
}
|
|
28105
28432
|
const hostHeartbeat = async (status, requestOptions = {
|
|
28106
28433
|
signal: this.options.signal
|
|
28107
|
-
}) => {
|
|
28434
|
+
}, retryRemote = true, allowOfflineProjection = false) => {
|
|
28108
28435
|
const sequence = receipt.host_heartbeat_sequence + 1;
|
|
28109
28436
|
const request = {
|
|
28110
28437
|
schema_version: "external_inference_host_heartbeat_v1",
|
|
@@ -28130,9 +28457,9 @@ var init_runner = __esm({
|
|
|
28130
28457
|
request,
|
|
28131
28458
|
requestOptions
|
|
28132
28459
|
);
|
|
28133
|
-
const result2 = status === "draining" ? await heartbeatOperation() : await retryExact(heartbeatOperation, requestOptions);
|
|
28134
|
-
assertHostHeartbeatResult(request, result2);
|
|
28135
|
-
if (
|
|
28460
|
+
const result2 = status === "draining" || !retryRemote ? await heartbeatOperation() : await retryExact(heartbeatOperation, requestOptions);
|
|
28461
|
+
assertHostHeartbeatResult(request, result2, allowOfflineProjection);
|
|
28462
|
+
if (result2.host.status === "revoked" || result2.host.status === "offline" && !allowOfflineProjection) {
|
|
28136
28463
|
const error48 = new InferenceHostRunnerError(
|
|
28137
28464
|
result2.host.status === "revoked" ? "host_revoked" : "host_offline",
|
|
28138
28465
|
"The external inference host is no longer active."
|
|
@@ -28142,7 +28469,9 @@ var init_runner = __esm({
|
|
|
28142
28469
|
};
|
|
28143
28470
|
await hostHeartbeat("healthy");
|
|
28144
28471
|
let nextHostHeartbeatAt = now() + settings.hostHeartbeatMs;
|
|
28145
|
-
let
|
|
28472
|
+
let nextAdvertisementAttemptAt = 0;
|
|
28473
|
+
let providerRetryAtMs = this.options.codexRateLimits && codexAccountRateLimitReached(this.options.codexRateLimits) ? codexRateLimitRetryAtMs(this.options.codexRateLimits) ?? now() + DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS : null;
|
|
28474
|
+
let nextClaimAt = Math.max(now(), providerRetryAtMs ?? 0);
|
|
28146
28475
|
let onceClaimed = false;
|
|
28147
28476
|
const launchClaim = (claim, recovery) => {
|
|
28148
28477
|
if (!recovery) {
|
|
@@ -28180,6 +28509,11 @@ var init_runner = __esm({
|
|
|
28180
28509
|
attemptHeartbeatMs: settings.attemptHeartbeatMs,
|
|
28181
28510
|
sleep: sleep4,
|
|
28182
28511
|
now,
|
|
28512
|
+
onProviderCooldown: (retryAtMs) => {
|
|
28513
|
+
if (!Number.isSafeInteger(retryAtMs) || retryAtMs <= now()) return;
|
|
28514
|
+
providerRetryAtMs = Math.max(providerRetryAtMs ?? 0, retryAtMs);
|
|
28515
|
+
nextClaimAt = Math.max(nextClaimAt, providerRetryAtMs);
|
|
28516
|
+
},
|
|
28183
28517
|
resumeReceipt: recovery
|
|
28184
28518
|
}).then((outcome) => {
|
|
28185
28519
|
if (outcome === "completed") completed += 1;
|
|
@@ -28239,22 +28573,46 @@ var init_runner = __esm({
|
|
|
28239
28573
|
while (!drainRequested) {
|
|
28240
28574
|
const currentTime = now();
|
|
28241
28575
|
const expiresAt = receipt.advertisement_expires_at ? Date.parse(receipt.advertisement_expires_at) : 0;
|
|
28242
|
-
if (expiresAt - currentTime <= settings.advertisementRefreshLeadMs) {
|
|
28576
|
+
if (currentTime >= nextAdvertisementAttemptAt && expiresAt - currentTime <= settings.advertisementRefreshLeadMs) {
|
|
28243
28577
|
try {
|
|
28244
|
-
await publishAdvertisement("healthy", true);
|
|
28578
|
+
await publishAdvertisement("healthy", true, false);
|
|
28579
|
+
nextAdvertisementAttemptAt = 0;
|
|
28245
28580
|
} catch (error48) {
|
|
28246
|
-
|
|
28247
|
-
|
|
28581
|
+
if (controlPlaneFatal(error48)) {
|
|
28582
|
+
requestDrain("authority_lost");
|
|
28583
|
+
break;
|
|
28584
|
+
}
|
|
28585
|
+
if (!retryableRemoteError(error48)) {
|
|
28586
|
+
requestDrain("advertisement_failed");
|
|
28587
|
+
break;
|
|
28588
|
+
}
|
|
28589
|
+
nextAdvertisementAttemptAt = now() + remoteRetryAfterMs(error48, 1e3);
|
|
28590
|
+
nextClaimAt = Math.max(nextClaimAt, nextAdvertisementAttemptAt);
|
|
28248
28591
|
}
|
|
28249
28592
|
}
|
|
28250
28593
|
if (currentTime >= nextHostHeartbeatAt) {
|
|
28251
28594
|
try {
|
|
28252
|
-
|
|
28595
|
+
const refreshPendingAcrossExpiry = receipt.pending_advertisement !== null && expiresAt <= currentTime && nextAdvertisementAttemptAt > currentTime;
|
|
28596
|
+
await hostHeartbeat(
|
|
28597
|
+
"healthy",
|
|
28598
|
+
{ signal: this.options.signal },
|
|
28599
|
+
false,
|
|
28600
|
+
refreshPendingAcrossExpiry
|
|
28601
|
+
);
|
|
28253
28602
|
} catch (error48) {
|
|
28254
|
-
|
|
28255
|
-
|
|
28603
|
+
if (controlPlaneFatal(error48)) {
|
|
28604
|
+
requestDrain("authority_lost");
|
|
28605
|
+
break;
|
|
28606
|
+
}
|
|
28607
|
+
if (!retryableRemoteError(error48)) {
|
|
28608
|
+
requestDrain("host_heartbeat_failed");
|
|
28609
|
+
break;
|
|
28610
|
+
}
|
|
28611
|
+
nextHostHeartbeatAt = now() + remoteRetryAfterMs(error48, settings.hostHeartbeatMs);
|
|
28612
|
+
}
|
|
28613
|
+
if (!drainRequested && currentTime >= nextHostHeartbeatAt) {
|
|
28614
|
+
nextHostHeartbeatAt = now() + settings.hostHeartbeatMs;
|
|
28256
28615
|
}
|
|
28257
|
-
nextHostHeartbeatAt = now() + settings.hostHeartbeatMs;
|
|
28258
28616
|
}
|
|
28259
28617
|
while (recoveryQueue.length > 0 && active.size < settings.maxConcurrency) {
|
|
28260
28618
|
const recovery = recoveryQueue.shift();
|
|
@@ -28285,15 +28643,19 @@ var init_runner = __esm({
|
|
|
28285
28643
|
await this.persistReceipt(receipt, now);
|
|
28286
28644
|
let claim;
|
|
28287
28645
|
try {
|
|
28288
|
-
claim = await
|
|
28646
|
+
claim = await mcp.callTool(
|
|
28289
28647
|
"inference.job.claim",
|
|
28290
28648
|
request,
|
|
28291
28649
|
{ signal: this.options.signal }
|
|
28292
|
-
)
|
|
28650
|
+
);
|
|
28293
28651
|
assertClaimResult(request, claim);
|
|
28294
28652
|
} catch (error48) {
|
|
28295
|
-
if (!this.options.signal?.aborted) {
|
|
28296
|
-
requestDrain(
|
|
28653
|
+
if (!this.options.signal?.aborted && controlPlaneFatal(error48)) {
|
|
28654
|
+
requestDrain("authority_lost");
|
|
28655
|
+
} else if (!this.options.signal?.aborted && retryableRemoteError(error48)) {
|
|
28656
|
+
nextClaimAt = now() + remoteRetryAfterMs(error48, 1e3);
|
|
28657
|
+
} else if (!this.options.signal?.aborted) {
|
|
28658
|
+
requestDrain("claim_failed");
|
|
28297
28659
|
}
|
|
28298
28660
|
break;
|
|
28299
28661
|
}
|
|
@@ -28306,10 +28668,12 @@ var init_runner = __esm({
|
|
|
28306
28668
|
if (this.options.once) requestDrain("once_complete");
|
|
28307
28669
|
}
|
|
28308
28670
|
if (drainRequested) break;
|
|
28309
|
-
const
|
|
28310
|
-
|
|
28311
|
-
|
|
28312
|
-
|
|
28671
|
+
const advertisementDueAt = nextAdvertisementAttemptAt > now() ? nextAdvertisementAttemptAt : receipt.advertisement_expires_at ? Date.parse(receipt.advertisement_expires_at) - settings.advertisementRefreshLeadMs : now() + MIN_SLEEP_MS;
|
|
28672
|
+
const wakeAt = Math.min(
|
|
28673
|
+
nextClaimAt,
|
|
28674
|
+
nextHostHeartbeatAt,
|
|
28675
|
+
Math.max(now() + MIN_SLEEP_MS, advertisementDueAt)
|
|
28676
|
+
);
|
|
28313
28677
|
await Promise.race([
|
|
28314
28678
|
sleep4(Math.max(MIN_SLEEP_MS, wakeAt - now())),
|
|
28315
28679
|
drainSignal,
|
|
@@ -28653,6 +29017,9 @@ var init_runner = __esm({
|
|
|
28653
29017
|
if (error48 instanceof InferenceHostRunnerError && error48.code === "terminal_outcome_unconfirmed") {
|
|
28654
29018
|
throw error48;
|
|
28655
29019
|
}
|
|
29020
|
+
if (error48 instanceof CodexAppServerError && error48.retryAtMs !== null && ["quota_exceeded", "codex_rate_limited"].includes(error48.code)) {
|
|
29021
|
+
options.onProviderCooldown?.(error48.retryAtMs);
|
|
29022
|
+
}
|
|
28656
29023
|
const classified = classifyFailure(heartbeatFailure ?? error48, adapterResult);
|
|
28657
29024
|
const heartbeatAmbiguous = ambiguousHeartbeatTransport(heartbeatFailure);
|
|
28658
29025
|
const failure = heartbeatAmbiguous ? {
|
|
@@ -28703,7 +29070,7 @@ var init_runner = __esm({
|
|
|
28703
29070
|
adapter_request_id: canReportEffective ? adapterResult?.adapterRequestId ?? null : null,
|
|
28704
29071
|
adapter_response_id: canReportEffective ? adapterResult?.adapterResponseId ?? null : null
|
|
28705
29072
|
},
|
|
28706
|
-
usage: adapterResult ? reportedUsage(adapterResult) : null,
|
|
29073
|
+
usage: adapterResult ? reportedUsage(adapterResult) : error48 instanceof CodexAppServerError && error48.usage ? reportedTokenUsage(error48.usage) : null,
|
|
28707
29074
|
failure_category: failure.category,
|
|
28708
29075
|
failure_code: failure.code,
|
|
28709
29076
|
retryable: failure.retryable,
|
|
@@ -28777,6 +29144,9 @@ import { join as join5, resolve as resolve4 } from "node:path";
|
|
|
28777
29144
|
async function runInferenceHostCli(argv2, env = process.env, dependencies = {}) {
|
|
28778
29145
|
const warnings = [];
|
|
28779
29146
|
try {
|
|
29147
|
+
if (argv2.includes("--help") || argv2.includes("-h") || argv2[1] === "help") {
|
|
29148
|
+
return { exitCode: 0, stdout: INFERENCE_HOST_HELP, stderr: "" };
|
|
29149
|
+
}
|
|
28780
29150
|
const parsed = parseInferenceHostArgs(argv2, env);
|
|
28781
29151
|
const config2 = resolveInferenceHostConfig(env);
|
|
28782
29152
|
if (parsed.command === "login") {
|
|
@@ -28794,6 +29164,9 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
28794
29164
|
async () => await agentConnect(config2, parsed, dependencies, warnings)
|
|
28795
29165
|
);
|
|
28796
29166
|
}
|
|
29167
|
+
if (parsed.command === "agent-run") {
|
|
29168
|
+
return await agentRun(config2, parsed, dependencies, warnings);
|
|
29169
|
+
}
|
|
28797
29170
|
if (parsed.command === "agent-next") {
|
|
28798
29171
|
return await withAgentCommandLock(
|
|
28799
29172
|
config2,
|
|
@@ -28828,7 +29201,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
28828
29201
|
return await cleanupLogin(config2, parsed, dependencies, warnings, true);
|
|
28829
29202
|
}
|
|
28830
29203
|
throw new Error(
|
|
28831
|
-
"Usage: vtx inference-host <login|codex-login|run|agent-connect|agent-next|agent-complete|agent-fail|status|doctor|logout|codex-logout|revoke> [--json]"
|
|
29204
|
+
"Usage: vtx inference-host <login|codex-login|run|agent-connect|agent-run|agent-next|agent-complete|agent-fail|status|doctor|logout|codex-logout|revoke> [--json]"
|
|
28832
29205
|
);
|
|
28833
29206
|
} catch (error48) {
|
|
28834
29207
|
return {
|
|
@@ -28839,7 +29212,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
28839
29212
|
};
|
|
28840
29213
|
}
|
|
28841
29214
|
}
|
|
28842
|
-
var INFERENCE_HOST_CLI_VERSION, runtimeReceiptPath, codexRecoveryPath, codexGuardianReceiptRoot, revocationCheckpointPath, assertRevocationCheckpoint, readRevocationCheckpoint, writeRevocationCheckpoint, clearRevocationCheckpoint, render, parsePositiveInteger, parseInferenceHostArgs, defaultOpenBrowser, defaultRegisterLifecycleSignalHandlers, lifecycleCancellation, configuredCredentialStore, accountKeyForState, assertCredentialMatchesState2, revocationCheckpointForCredential, assertRevocationCheckpointMatchesLocalIdentity, fileExistsPrivately, inspectCodexAuthentication, clearLocalRuntimeArtifacts, assertLocalRuntimeArtifactsMayBeDiscarded, defaultRunForeground, login, codexLogin, codexLogout, localStatus, doctor, cleanupLogin, runHost, defaultReadStdin, parseAgentStdin, agentOperationId, agentSession, agentConnect, agentNext, agentComplete, agentFail, withAgentCommandLock;
|
|
29215
|
+
var INFERENCE_HOST_CLI_VERSION, runtimeReceiptPath, codexRecoveryPath, codexGuardianReceiptRoot, revocationCheckpointPath, foregroundHostLockPath, AGENT_HEARTBEAT_INTERVAL_MS, AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS, retryableAgentHeartbeatError, assertRevocationCheckpoint, readRevocationCheckpoint, writeRevocationCheckpoint, clearRevocationCheckpoint, render, INFERENCE_HOST_HELP, parsePositiveInteger, parseInferenceHostArgs, defaultOpenBrowser, defaultRegisterLifecycleSignalHandlers, lifecycleCancellation, configuredCredentialStore, accountKeyForState, assertCredentialMatchesState2, revocationCheckpointForCredential, assertRevocationCheckpointMatchesLocalIdentity, fileExistsPrivately, inspectCodexAuthentication, clearLocalRuntimeArtifacts, assertLocalRuntimeArtifactsMayBeDiscarded, defaultRunForeground, login, codexLogin, codexLogout, localStatus, doctor, cleanupLogin, runHost, defaultReadStdin, parseAgentStdin, agentOperationId, agentSession, agentConnect, agentRun, agentNext, agentComplete, agentFail, withAgentCommandLock;
|
|
28843
29216
|
var init_cli = __esm({
|
|
28844
29217
|
"lib/inference-host/cli.ts"() {
|
|
28845
29218
|
"use strict";
|
|
@@ -28855,11 +29228,20 @@ var init_cli = __esm({
|
|
|
28855
29228
|
init_crypto();
|
|
28856
29229
|
init_oauth();
|
|
28857
29230
|
init_runner();
|
|
29231
|
+
init_mcp_client();
|
|
28858
29232
|
INFERENCE_HOST_CLI_VERSION = agent_cli_release_default.package_version;
|
|
28859
29233
|
runtimeReceiptPath = (config2) => `${config2.statePath}.runtime.json`;
|
|
28860
29234
|
codexRecoveryPath = (config2) => `${config2.statePath}.codex-recovery.json`;
|
|
28861
29235
|
codexGuardianReceiptRoot = (config2) => `${config2.statePath}.codex-processes`;
|
|
28862
29236
|
revocationCheckpointPath = (config2) => `${config2.statePath}.revoke.json`;
|
|
29237
|
+
foregroundHostLockPath = (config2) => `${config2.processLockPath}.foreground`;
|
|
29238
|
+
AGENT_HEARTBEAT_INTERVAL_MS = 3e3;
|
|
29239
|
+
AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS = 9e3;
|
|
29240
|
+
retryableAgentHeartbeatError = (error48) => {
|
|
29241
|
+
if (!(error48 instanceof ExternalInferenceMcpError)) return false;
|
|
29242
|
+
if (error48.code === "network_error" || error48.code === "request_timeout") return true;
|
|
29243
|
+
return error48.code === "transport_rejected" && /HTTP (?:408|425|429|5\d\d)\b/u.test(error48.message);
|
|
29244
|
+
};
|
|
28863
29245
|
assertRevocationCheckpoint = (value) => {
|
|
28864
29246
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
28865
29247
|
throw new Error("Inference host revocation checkpoint is invalid.");
|
|
@@ -28912,6 +29294,31 @@ var init_cli = __esm({
|
|
|
28912
29294
|
render = (value, json2) => json2 ? `${JSON.stringify(value, null, 2)}
|
|
28913
29295
|
` : typeof value === "string" ? `${value}
|
|
28914
29296
|
` : `${JSON.stringify(value, null, 2)}
|
|
29297
|
+
`;
|
|
29298
|
+
INFERENCE_HOST_HELP = `Usage: vtx inference-host <command> [options]
|
|
29299
|
+
|
|
29300
|
+
Commands:
|
|
29301
|
+
login Authorize the isolated VTX insights:inference grant
|
|
29302
|
+
codex-login Sign the automated Codex host into a ChatGPT subscription
|
|
29303
|
+
run Run the automated Codex inference host in the foreground
|
|
29304
|
+
agent-connect Advertise a model from a compatible agent harness
|
|
29305
|
+
agent-run Keep an agent-driven host online in the foreground
|
|
29306
|
+
agent-next Claim the next exact VTX inference request
|
|
29307
|
+
agent-complete Submit one completed agent result from stdin
|
|
29308
|
+
agent-fail Submit one truthful agent failure from stdin
|
|
29309
|
+
status Inspect local host and credential state
|
|
29310
|
+
doctor Verify credentials, Codex, and private runtime state
|
|
29311
|
+
logout Remove local VTX host state without revoking the grant
|
|
29312
|
+
revoke Revoke the VTX grant and remove local host state
|
|
29313
|
+
codex-logout Remove the automated host's dedicated Codex login
|
|
29314
|
+
|
|
29315
|
+
Common options:
|
|
29316
|
+
--json Emit machine-readable JSON
|
|
29317
|
+
--help, -h Show this help
|
|
29318
|
+
|
|
29319
|
+
If the OS credential store cannot retain the VTX grant, set
|
|
29320
|
+
VTX_INFERENCE_HOST_CREDENTIAL_STORE=file before login to use the supported
|
|
29321
|
+
private-file fallback. See https://vtxmacro.com/insights#subscription-inference.
|
|
28915
29322
|
`;
|
|
28916
29323
|
parsePositiveInteger = (raw, label) => {
|
|
28917
29324
|
const value = Number(raw);
|
|
@@ -29151,6 +29558,9 @@ var init_cli = __esm({
|
|
|
29151
29558
|
acquireProcessLock: async () => borrowedProcessLock
|
|
29152
29559
|
}, {
|
|
29153
29560
|
displayName: options.displayName,
|
|
29561
|
+
authenticatedAccountEmail: options.authenticatedAccountEmail,
|
|
29562
|
+
authenticatedAccountPlan: options.authenticatedAccountPlan,
|
|
29563
|
+
codexRateLimits: options.codexRateLimits,
|
|
29154
29564
|
protocolVersion: EXTERNAL_INFERENCE_CONTRACT_VERSION,
|
|
29155
29565
|
adapterRuntimeVersion: INFERENCE_HOST_CLI_VERSION,
|
|
29156
29566
|
maxConcurrency: options.maxConcurrency,
|
|
@@ -29489,7 +29899,18 @@ Waiting for approval...
|
|
|
29489
29899
|
};
|
|
29490
29900
|
cleanupLogin = async (config2, parsed, dependencies, warnings, revoke) => {
|
|
29491
29901
|
const lock2 = await acquireInferenceHostProcessLock(config2.processLockPath);
|
|
29902
|
+
let keeperLock = null;
|
|
29492
29903
|
try {
|
|
29904
|
+
try {
|
|
29905
|
+
keeperLock = await acquireInferenceHostProcessLock(foregroundHostLockPath(config2));
|
|
29906
|
+
} catch (error48) {
|
|
29907
|
+
if (error48 instanceof Error && error48.message.includes("Another inference host process already owns")) {
|
|
29908
|
+
throw new Error(
|
|
29909
|
+
"Stop vtx inference-host agent-run before logging out or revoking this host."
|
|
29910
|
+
);
|
|
29911
|
+
}
|
|
29912
|
+
throw error48;
|
|
29913
|
+
}
|
|
29493
29914
|
if (!revoke) {
|
|
29494
29915
|
await assertLocalRuntimeArtifactsMayBeDiscarded(config2);
|
|
29495
29916
|
}
|
|
@@ -29592,13 +30013,16 @@ Waiting for approval...
|
|
|
29592
30013
|
` : ""
|
|
29593
30014
|
};
|
|
29594
30015
|
} finally {
|
|
30016
|
+
await keeperLock?.release();
|
|
29595
30017
|
await lock2.release();
|
|
29596
30018
|
}
|
|
29597
30019
|
};
|
|
29598
30020
|
runHost = async (config2, parsed, env, dependencies, warnings) => {
|
|
29599
30021
|
const cancellation = lifecycleCancellation(dependencies);
|
|
30022
|
+
let foregroundLock = null;
|
|
29600
30023
|
let processLock = null;
|
|
29601
30024
|
try {
|
|
30025
|
+
foregroundLock = await acquireInferenceHostProcessLock(foregroundHostLockPath(config2));
|
|
29602
30026
|
processLock = await acquireInferenceHostProcessLock(config2.processLockPath);
|
|
29603
30027
|
cancellation.signal.throwIfAborted();
|
|
29604
30028
|
if (await readRevocationCheckpoint(config2)) {
|
|
@@ -29620,7 +30044,7 @@ Waiting for approval...
|
|
|
29620
30044
|
cancellation.signal.throwIfAborted();
|
|
29621
30045
|
const hostResources = await (dependencies.createHostResources ?? createIsolatedCodexHostResources)(config2.codexHomePath);
|
|
29622
30046
|
try {
|
|
29623
|
-
await (dependencies.preflightCodex ?? preflightCodexSubscription)({
|
|
30047
|
+
const preflight = await (dependencies.preflightCodex ?? preflightCodexSubscription)({
|
|
29624
30048
|
binary: verifiedBinary,
|
|
29625
30049
|
codexHome: config2.codexHomePath,
|
|
29626
30050
|
deadlineAtMs: Date.now() + 3e4,
|
|
@@ -29632,6 +30056,9 @@ Waiting for approval...
|
|
|
29632
30056
|
verifiedBinary,
|
|
29633
30057
|
hostResources,
|
|
29634
30058
|
displayName: parsed.displayName,
|
|
30059
|
+
authenticatedAccountEmail: preflight?.authenticated_account_email ?? null,
|
|
30060
|
+
authenticatedAccountPlan: preflight?.authenticated_account_plan ?? null,
|
|
30061
|
+
codexRateLimits: preflight?.rate_limits ?? null,
|
|
29635
30062
|
maxConcurrency: parsed.maxConcurrency,
|
|
29636
30063
|
once: parsed.once,
|
|
29637
30064
|
env,
|
|
@@ -29649,6 +30076,7 @@ Waiting for approval...
|
|
|
29649
30076
|
}
|
|
29650
30077
|
} finally {
|
|
29651
30078
|
await processLock?.release();
|
|
30079
|
+
await foregroundLock?.release();
|
|
29652
30080
|
cancellation.unregister();
|
|
29653
30081
|
}
|
|
29654
30082
|
};
|
|
@@ -29728,12 +30156,130 @@ Waiting for approval...
|
|
|
29728
30156
|
lanes: ["main", "review", "screener"],
|
|
29729
30157
|
response_modes: ["provider_response", "decision_candidate"],
|
|
29730
30158
|
execution_modes: ["client", "server"],
|
|
29731
|
-
next_command: "vtx inference-host agent-next --wait-seconds 50 --json"
|
|
30159
|
+
next_command: "vtx inference-host agent-next --wait-seconds 50 --json",
|
|
30160
|
+
keeper_command: "vtx inference-host agent-run"
|
|
29732
30161
|
}, parsed.json),
|
|
29733
30162
|
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
29734
30163
|
` : ""
|
|
29735
30164
|
};
|
|
29736
30165
|
};
|
|
30166
|
+
agentRun = async (config2, parsed, dependencies, warnings) => {
|
|
30167
|
+
const cancellation = lifecycleCancellation(dependencies);
|
|
30168
|
+
let keeperLock = null;
|
|
30169
|
+
let heartbeatCount = 0;
|
|
30170
|
+
try {
|
|
30171
|
+
keeperLock = await acquireInferenceHostProcessLock(foregroundHostLockPath(config2));
|
|
30172
|
+
const store = configuredCredentialStore(config2, dependencies, (message) => {
|
|
30173
|
+
warnings.push(message);
|
|
30174
|
+
});
|
|
30175
|
+
const session = await (dependencies.createAgentSession ?? createInferenceAgentMcpSession)({
|
|
30176
|
+
config: config2,
|
|
30177
|
+
credentialStore: store,
|
|
30178
|
+
clientVersion: INFERENCE_HOST_CLI_VERSION,
|
|
30179
|
+
signal: cancellation.signal
|
|
30180
|
+
});
|
|
30181
|
+
const emitStdout = dependencies.emitStdout ?? ((text) => {
|
|
30182
|
+
process.stdout.write(text);
|
|
30183
|
+
});
|
|
30184
|
+
const emitStderr = dependencies.emitStderr ?? ((text) => {
|
|
30185
|
+
process.stderr.write(text);
|
|
30186
|
+
});
|
|
30187
|
+
let consecutiveHeartbeatFailures = 0;
|
|
30188
|
+
let retryDelayMs = AGENT_HEARTBEAT_INTERVAL_MS;
|
|
30189
|
+
let pendingHeartbeatRequest = null;
|
|
30190
|
+
emitStdout(parsed.json ? `${JSON.stringify({ status: "running", host_id: session.localState.host_id })}
|
|
30191
|
+
` : "Agent-driven inference host keeper is running.\n");
|
|
30192
|
+
while (!cancellation.signal.aborted) {
|
|
30193
|
+
let commandLock = null;
|
|
30194
|
+
try {
|
|
30195
|
+
commandLock = await acquireInferenceHostProcessLock(config2.processLockPath);
|
|
30196
|
+
} catch (error48) {
|
|
30197
|
+
if (!(error48 instanceof Error) || !error48.message.includes("Another inference host process already owns")) {
|
|
30198
|
+
throw error48;
|
|
30199
|
+
}
|
|
30200
|
+
}
|
|
30201
|
+
if (commandLock) {
|
|
30202
|
+
let heartbeatSuppressed = false;
|
|
30203
|
+
try {
|
|
30204
|
+
const active = await readInferenceAgentAttemptState(config2.statePath);
|
|
30205
|
+
const pendingNext = await readInferenceAgentNextState(config2.statePath);
|
|
30206
|
+
heartbeatSuppressed = Boolean(pendingNext && !active);
|
|
30207
|
+
if (heartbeatSuppressed) pendingHeartbeatRequest = null;
|
|
30208
|
+
if (!heartbeatSuppressed) {
|
|
30209
|
+
if (active && active.host_id !== session.localState.host_id) {
|
|
30210
|
+
throw new Error("Active agent-driven attempt belongs to another inference host.");
|
|
30211
|
+
}
|
|
30212
|
+
const activeAttemptId = active?.attempt_id ?? null;
|
|
30213
|
+
if (pendingHeartbeatRequest?.attempt_id !== activeAttemptId) {
|
|
30214
|
+
pendingHeartbeatRequest = null;
|
|
30215
|
+
}
|
|
30216
|
+
const heartbeatRequest = pendingHeartbeatRequest ?? {
|
|
30217
|
+
operation_id: agentOperationId("agent-heartbeat"),
|
|
30218
|
+
host_id: session.localState.host_id,
|
|
30219
|
+
attempt_id: activeAttemptId,
|
|
30220
|
+
requested_at: (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString()
|
|
30221
|
+
};
|
|
30222
|
+
try {
|
|
30223
|
+
await session.client.callTool(
|
|
30224
|
+
"inference.agent.heartbeat",
|
|
30225
|
+
heartbeatRequest,
|
|
30226
|
+
{ signal: cancellation.signal }
|
|
30227
|
+
);
|
|
30228
|
+
heartbeatCount += 1;
|
|
30229
|
+
pendingHeartbeatRequest = null;
|
|
30230
|
+
consecutiveHeartbeatFailures = 0;
|
|
30231
|
+
retryDelayMs = AGENT_HEARTBEAT_INTERVAL_MS;
|
|
30232
|
+
} catch (error48) {
|
|
30233
|
+
if (cancellation.signal.aborted) break;
|
|
30234
|
+
if (error48 instanceof ExternalInferenceMcpError && error48.definitivelyNotApplied) {
|
|
30235
|
+
pendingHeartbeatRequest = null;
|
|
30236
|
+
consecutiveHeartbeatFailures = 0;
|
|
30237
|
+
retryDelayMs = AGENT_HEARTBEAT_INTERVAL_MS;
|
|
30238
|
+
emitStderr(parsed.json ? `${JSON.stringify({
|
|
30239
|
+
status: "heartbeat_retry",
|
|
30240
|
+
retry_after_ms: retryDelayMs
|
|
30241
|
+
})}
|
|
30242
|
+
` : `Agent-driven inference heartbeat was not applied; retrying in ${retryDelayMs}ms.
|
|
30243
|
+
`);
|
|
30244
|
+
} else {
|
|
30245
|
+
if (!retryableAgentHeartbeatError(error48)) throw error48;
|
|
30246
|
+
pendingHeartbeatRequest = heartbeatRequest;
|
|
30247
|
+
consecutiveHeartbeatFailures += 1;
|
|
30248
|
+
retryDelayMs = Math.min(
|
|
30249
|
+
AGENT_HEARTBEAT_INTERVAL_MS * 2 ** Math.max(0, consecutiveHeartbeatFailures - 1),
|
|
30250
|
+
AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS
|
|
30251
|
+
);
|
|
30252
|
+
const message = `Agent-driven inference heartbeat was temporarily unavailable; retrying in ${retryDelayMs}ms.
|
|
30253
|
+
`;
|
|
30254
|
+
emitStderr(parsed.json ? `${JSON.stringify({
|
|
30255
|
+
status: "heartbeat_retry",
|
|
30256
|
+
retry_after_ms: retryDelayMs
|
|
30257
|
+
})}
|
|
30258
|
+
` : message);
|
|
30259
|
+
}
|
|
30260
|
+
}
|
|
30261
|
+
}
|
|
30262
|
+
} finally {
|
|
30263
|
+
await commandLock.release();
|
|
30264
|
+
}
|
|
30265
|
+
if (parsed.once && (heartbeatCount > 0 || heartbeatSuppressed)) break;
|
|
30266
|
+
}
|
|
30267
|
+
if (parsed.once && !commandLock) break;
|
|
30268
|
+
await (dependencies.sleep ?? (async (milliseconds) => {
|
|
30269
|
+
await new Promise((resolve5) => setTimeout(resolve5, milliseconds));
|
|
30270
|
+
}))(retryDelayMs);
|
|
30271
|
+
}
|
|
30272
|
+
return {
|
|
30273
|
+
exitCode: 0,
|
|
30274
|
+
stdout: render({ status: "stopped", heartbeats: heartbeatCount }, parsed.json),
|
|
30275
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
30276
|
+
` : ""
|
|
30277
|
+
};
|
|
30278
|
+
} finally {
|
|
30279
|
+
await keeperLock?.release();
|
|
30280
|
+
cancellation.unregister();
|
|
30281
|
+
}
|
|
30282
|
+
};
|
|
29737
30283
|
agentNext = async (config2, parsed, dependencies, warnings) => {
|
|
29738
30284
|
const active = await readInferenceAgentAttemptState(config2.statePath);
|
|
29739
30285
|
const recoveredNext = await readInferenceAgentNextState(config2.statePath);
|
|
@@ -48127,6 +48673,9 @@ Waiting for approval...
|
|
|
48127
48673
|
}
|
|
48128
48674
|
async function runVtxCli(argv2, env = process.env) {
|
|
48129
48675
|
try {
|
|
48676
|
+
if (argv2.length === 0 || argv2.includes("--help") || argv2.includes("-h") || argv2[0] === "help") {
|
|
48677
|
+
return { exitCode: 0, stdout: VTX_CLI_HELP, stderr: "" };
|
|
48678
|
+
}
|
|
48130
48679
|
const parsed = parseFlags(argv2);
|
|
48131
48680
|
const [group, command, ...args] = parsed.rest;
|
|
48132
48681
|
const config2 = resolveAgentCliConfig(env);
|
|
@@ -48374,7 +48923,7 @@ async function runVtxCli(argv2, env = process.env) {
|
|
|
48374
48923
|
` };
|
|
48375
48924
|
}
|
|
48376
48925
|
}
|
|
48377
|
-
var WRITABLE_SECRET_FIELDS, delay;
|
|
48926
|
+
var VTX_CLI_HELP, WRITABLE_SECRET_FIELDS, delay;
|
|
48378
48927
|
var init_vtx = __esm({
|
|
48379
48928
|
"lib/agent-cli/vtx.ts"() {
|
|
48380
48929
|
"use strict";
|
|
@@ -48383,6 +48932,24 @@ var init_vtx = __esm({
|
|
|
48383
48932
|
init_headless_runtime();
|
|
48384
48933
|
init_types();
|
|
48385
48934
|
init_hyperliquid_market_symbol();
|
|
48935
|
+
VTX_CLI_HELP = `Usage: vtx [--json] [--profile <id>] <command>
|
|
48936
|
+
|
|
48937
|
+
Common commands:
|
|
48938
|
+
auth login Authorize the normal VTX CLI
|
|
48939
|
+
auth whoami Show the current VTX CLI identity
|
|
48940
|
+
profiles list List accessible profiles
|
|
48941
|
+
bots status Read the selected profile's Trader state
|
|
48942
|
+
bots start Start the normal VTX Trader
|
|
48943
|
+
bots stop Stop the normal VTX Trader
|
|
48944
|
+
runtime events Read recent runtime events and errors
|
|
48945
|
+
inference-host --help Set up an automated or agent-driven inference host
|
|
48946
|
+
|
|
48947
|
+
Global options:
|
|
48948
|
+
--json Emit machine-readable JSON
|
|
48949
|
+
--profile <id> Select one VTX profile
|
|
48950
|
+
--version, -v Show the installed CLI version
|
|
48951
|
+
--help, -h Show this help
|
|
48952
|
+
`;
|
|
48386
48953
|
WRITABLE_SECRET_FIELDS = /* @__PURE__ */ new Set([
|
|
48387
48954
|
"hyperliquid_signing_key",
|
|
48388
48955
|
"local_ai_api_key",
|