@vtxmacro/cli 2026.8.44 → 2026.8.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/vtx.js +373 -26
- 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.45",
|
|
42
42
|
codex_package_name: "@openai/codex",
|
|
43
43
|
codex_version: "0.147.0",
|
|
44
44
|
copilot_sdk_package_name: "@github/copilot-sdk",
|
|
@@ -14379,7 +14379,7 @@ var init_zod = __esm({
|
|
|
14379
14379
|
});
|
|
14380
14380
|
|
|
14381
14381
|
// lib/external-inference-contract.ts
|
|
14382
|
-
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, LEGACY_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, orderedFallbackHostIdsSchema, externalInferenceFallbackHostIdsSchema, 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, providerWeeklyQuotaReadSchema, 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, externalInferenceVolumeWindowReadSchema, externalInferenceFailureCountReadSchema, externalInferenceHostDiagnosticsReadSchema, externalInferenceProfileActivityReadSchema, externalInferenceStatusReadSchema, nativeResearchEvidenceSourceSchema, externalAgentResearchEvidenceSourceSchema, researchEvidenceSourceSchema, reportedResearchTokenUsageSchema, unavailableResearchTokenUsageSchema, researchTokenUsageSchema, externalInferenceProductLineageBaseShape, traderExternalInferenceProductLineageSchema, decisionChatExternalInferenceProductLineageSchema, screenerExternalInferenceProductLineageSchema, externalInferenceProductLineageSchema, normalProductLinkageSchema, evidenceMaterializationMarkerSchema, deliveredExternalAgentSourceIdentitySchema, deliveredRequestEvidenceSchema, researchEvidenceBaseShape, researchEvidenceBaseSchema, validateExactUtf8, validateResearchEvidence, providerResponseResearchEvidenceSchema, decisionCandidateResearchEvidenceSchema, researchEvidenceSchema;
|
|
14382
|
+
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, LEGACY_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, processExitCodeSchema, externalInferenceAdapterIdSchema, reasoningEffortSchema, modelNameSchema, displayNameSchema, authenticatedAccountEmailSchema, protocolVersionSchema, base64UrlAlphabet, isCanonicalBase64Url, base64Url32BytesSchema, base64UrlNonceSchema, base64UrlCiphertextSchema, claimHandleSchema, boundedJsonTextSchema, boundedPromptTextSchema, laneSchema, botModeSchema, executionModeSchema, responseModeSchema, dispatchOutcomeSchema, responseOutcomeSchema, nativeModelControllerSchema, externalAgentModelControllerSchema, externalAgentUnboundControllerSchema, orderedFallbackHostIdsSchema, externalInferenceFallbackHostIdsSchema, 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, providerWeeklyQuotaReadSchema, hostHeartbeatRequestSchema, jobClaimRequestSchema, emptyJobClaimSchema, claimedJobSchema, jobClaimResultSchema, attemptStartRequestSchema, jobHeartbeatRequestSchema, continueHeartbeatDirectiveSchema, cancelHeartbeatDirectiveSchema, jobHeartbeatResultSchema, adapterOutcomeEvidenceSchema, completionBaseShape, validateCompletion, providerResponseCompletionSchema, decisionCandidateCompletionSchema, jobCompleteRequestSchema, codexProcessExitDiagnosticsSchema, jobFailRequestSchema, jobCancelRequestSchema, jobCancellationReceiptSchema, jobDeliveryRequestSchema, deliveryBaseShape, validateDeliveryCandidate, providerResponseDeliverySchema, decisionCandidateDeliverySchema, jobDeliveryResultSchema, jobConsumptionRequestSchema, jobConsumptionReceiptSchema, jobStateSchema, jobStatusReadSchema, hostStatusReadSchema, controllerBindingStatusReadSchema, queueStatusReadSchema, outcomeStatusReadSchema, externalInferenceVolumeWindowReadSchema, externalInferenceFailureCountReadSchema, externalInferenceHostDiagnosticsReadSchema, externalInferenceProfileActivityReadSchema, externalInferenceStatusReadSchema, nativeResearchEvidenceSourceSchema, externalAgentResearchEvidenceSourceSchema, researchEvidenceSourceSchema, reportedResearchTokenUsageSchema, unavailableResearchTokenUsageSchema, researchTokenUsageSchema, externalInferenceProductLineageBaseShape, traderExternalInferenceProductLineageSchema, decisionChatExternalInferenceProductLineageSchema, screenerExternalInferenceProductLineageSchema, externalInferenceProductLineageSchema, normalProductLinkageSchema, evidenceMaterializationMarkerSchema, deliveredExternalAgentSourceIdentitySchema, deliveredRequestEvidenceSchema, researchEvidenceBaseShape, researchEvidenceBaseSchema, validateExactUtf8, validateResearchEvidence, providerResponseResearchEvidenceSchema, decisionCandidateResearchEvidenceSchema, researchEvidenceSchema;
|
|
14383
14383
|
var init_external_inference_contract = __esm({
|
|
14384
14384
|
"lib/external-inference-contract.ts"() {
|
|
14385
14385
|
"use strict";
|
|
@@ -14582,6 +14582,7 @@ var init_external_inference_contract = __esm({
|
|
|
14582
14582
|
sqlIntegerTokenCountSchema = external_exports.number().int().min(0).max(2147483647);
|
|
14583
14583
|
timestampSchema = external_exports.iso.datetime({ offset: true });
|
|
14584
14584
|
safeCodeSchema = external_exports.string().min(1).max(96).regex(/^[a-z0-9][a-z0-9._-]{0,95}$/);
|
|
14585
|
+
processExitCodeSchema = external_exports.number().int().min(-(2 ** 31)).max(2 ** 31 - 1);
|
|
14585
14586
|
externalInferenceAdapterIdSchema = external_exports.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9._-]{0,63}$/);
|
|
14586
14587
|
reasoningEffortSchema = external_exports.string().min(1).max(32).regex(/^[a-z][a-z0-9_-]{0,31}$/);
|
|
14587
14588
|
modelNameSchema = external_exports.string().min(1).max(256);
|
|
@@ -15435,6 +15436,55 @@ var init_external_inference_contract = __esm({
|
|
|
15435
15436
|
providerResponseCompletionSchema,
|
|
15436
15437
|
decisionCandidateCompletionSchema
|
|
15437
15438
|
]);
|
|
15439
|
+
codexProcessExitDiagnosticsSchema = external_exports.strictObject({
|
|
15440
|
+
schema_version: external_exports.literal("external_inference_process_exit_v1"),
|
|
15441
|
+
runtime: external_exports.literal("codex_app_server"),
|
|
15442
|
+
source: external_exports.enum(["child_receipt", "direct_process", "guardian_process"]),
|
|
15443
|
+
session_generation: generationSchema,
|
|
15444
|
+
expected_shutdown: external_exports.boolean(),
|
|
15445
|
+
exit_class: external_exports.enum(["zero", "nonzero", "signal", "unknown"]),
|
|
15446
|
+
exit_code: processExitCodeSchema.nullable(),
|
|
15447
|
+
signal: safeCodeSchema.nullable(),
|
|
15448
|
+
uptime_ms: nonNegativeSafeIntegerSchema,
|
|
15449
|
+
pending_request_count: nonNegativeSafeIntegerSchema.nullable(),
|
|
15450
|
+
active_thread_count: nonNegativeSafeIntegerSchema.nullable(),
|
|
15451
|
+
stderr_nonempty: external_exports.boolean().nullable(),
|
|
15452
|
+
stderr_bytes_observed: external_exports.number().int().min(0).max(65536).nullable(),
|
|
15453
|
+
stderr_truncated: external_exports.boolean().nullable(),
|
|
15454
|
+
stderr_class: external_exports.enum([
|
|
15455
|
+
"unknown",
|
|
15456
|
+
"none",
|
|
15457
|
+
"out_of_memory",
|
|
15458
|
+
"runtime_fatal",
|
|
15459
|
+
"memory_fault",
|
|
15460
|
+
"pipe_or_connection",
|
|
15461
|
+
"unclassified"
|
|
15462
|
+
])
|
|
15463
|
+
}).superRefine((value, context) => {
|
|
15464
|
+
const expectedExitClass = value.signal !== null ? "signal" : value.exit_code === null ? "unknown" : value.exit_code === 0 ? "zero" : "nonzero";
|
|
15465
|
+
if (value.exit_class !== expectedExitClass) {
|
|
15466
|
+
context.addIssue({ code: "custom", message: "process exit class does not match code and signal", path: ["exit_class"] });
|
|
15467
|
+
}
|
|
15468
|
+
if (value.signal !== null && value.exit_code !== null) {
|
|
15469
|
+
context.addIssue({ code: "custom", message: "signal exits cannot also report an exit code", path: ["exit_code"] });
|
|
15470
|
+
}
|
|
15471
|
+
if (value.stderr_class === "unknown") {
|
|
15472
|
+
if (value.stderr_nonempty !== null || value.stderr_bytes_observed !== null || value.stderr_truncated !== null) {
|
|
15473
|
+
context.addIssue({ code: "custom", message: "unknown stderr diagnostics must not infer observations", path: ["stderr_class"] });
|
|
15474
|
+
}
|
|
15475
|
+
} else if (value.stderr_nonempty === null || value.stderr_bytes_observed === null || value.stderr_truncated === null) {
|
|
15476
|
+
context.addIssue({ code: "custom", message: "observed stderr diagnostics must be complete", path: ["stderr_class"] });
|
|
15477
|
+
} else if (!value.stderr_nonempty) {
|
|
15478
|
+
if (value.stderr_bytes_observed !== 0 || value.stderr_truncated || value.stderr_class !== "none") {
|
|
15479
|
+
context.addIssue({ code: "custom", message: "empty stderr diagnostics are inconsistent", path: ["stderr_nonempty"] });
|
|
15480
|
+
}
|
|
15481
|
+
} else if (value.stderr_bytes_observed === 0 || value.stderr_class === "none") {
|
|
15482
|
+
context.addIssue({ code: "custom", message: "non-empty stderr diagnostics are inconsistent", path: ["stderr_nonempty"] });
|
|
15483
|
+
}
|
|
15484
|
+
if (value.stderr_truncated && value.stderr_bytes_observed !== 65536) {
|
|
15485
|
+
context.addIssue({ code: "custom", message: "truncated stderr diagnostics must report the observation cap", path: ["stderr_truncated"] });
|
|
15486
|
+
}
|
|
15487
|
+
});
|
|
15438
15488
|
jobFailRequestSchema = external_exports.strictObject({
|
|
15439
15489
|
schema_version: external_exports.literal("external_inference_job_fail_v1"),
|
|
15440
15490
|
contract_version: external_exports.literal(EXTERNAL_INFERENCE_CONTRACT_VERSION),
|
|
@@ -15457,6 +15507,7 @@ var init_external_inference_contract = __esm({
|
|
|
15457
15507
|
failure_category: safeCodeSchema,
|
|
15458
15508
|
failure_code: safeCodeSchema,
|
|
15459
15509
|
retryable: external_exports.boolean(),
|
|
15510
|
+
process_exit: codexProcessExitDiagnosticsSchema.nullable().optional(),
|
|
15460
15511
|
membership_disposition: external_exports.enum([
|
|
15461
15512
|
"retry_same_host",
|
|
15462
15513
|
"cascade_cooldown",
|
|
@@ -15473,6 +15524,13 @@ var init_external_inference_contract = __esm({
|
|
|
15473
15524
|
if (value.attempt_status !== expectedStatus) {
|
|
15474
15525
|
context.addIssue({ code: "custom", message: "attempt_status must match dispatch outcome", path: ["attempt_status"] });
|
|
15475
15526
|
}
|
|
15527
|
+
if (value.process_exit != null && (value.failure_category !== "transport" || value.failure_code !== "codex_process_closed" || value.process_exit.expected_shutdown)) {
|
|
15528
|
+
context.addIssue({
|
|
15529
|
+
code: "custom",
|
|
15530
|
+
message: "process exit diagnostics require an unexpected Codex process-close failure",
|
|
15531
|
+
path: ["process_exit"]
|
|
15532
|
+
});
|
|
15533
|
+
}
|
|
15476
15534
|
if (value.outcome.dispatch_outcome === "outcome_unknown" && value.membership_disposition !== void 0 && value.membership_disposition !== "quarantine_ambiguous") {
|
|
15477
15535
|
context.addIssue({ code: "custom", message: "outcome-unknown failures must be quarantined", path: ["membership_disposition"] });
|
|
15478
15536
|
}
|
|
@@ -19593,6 +19651,7 @@ var init_codex_app_server = __esm({
|
|
|
19593
19651
|
this.retryAtMs = options.retryAtMs ?? null;
|
|
19594
19652
|
this.usage = options.usage ?? null;
|
|
19595
19653
|
this.rateLimits = options.rateLimits ?? null;
|
|
19654
|
+
this.processExit = options.processExit ?? null;
|
|
19596
19655
|
}
|
|
19597
19656
|
};
|
|
19598
19657
|
objectOrNull = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -19897,7 +19956,7 @@ var init_codex_app_server = __esm({
|
|
|
19897
19956
|
};
|
|
19898
19957
|
GUARDIAN_SCRIPT = String.raw`
|
|
19899
19958
|
import { spawn } from 'node:child_process';
|
|
19900
|
-
import { chmod, open, rename, rm, writeFile } from 'node:fs/promises';
|
|
19959
|
+
import { chmod, open, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
19901
19960
|
import { dirname } from 'node:path';
|
|
19902
19961
|
const input = JSON.parse(Buffer.from(process.argv[1], 'base64url').toString('utf8'));
|
|
19903
19962
|
// The guardian owns the process boundary for every attempt. Apply a private
|
|
@@ -19927,7 +19986,7 @@ const replaceReceipt = async (temporary) => {
|
|
|
19927
19986
|
};
|
|
19928
19987
|
let receiptWriteSequence = 0;
|
|
19929
19988
|
let receiptWriteChain = Promise.resolve();
|
|
19930
|
-
const writeReceipt = (state, childPid) => {
|
|
19989
|
+
const writeReceipt = (state, childPid, termination = null) => {
|
|
19931
19990
|
const write = async () => {
|
|
19932
19991
|
const body = JSON.stringify({
|
|
19933
19992
|
schema_version: 'vtx_codex_guardian_v1',
|
|
@@ -19936,6 +19995,7 @@ const writeReceipt = (state, childPid) => {
|
|
|
19936
19995
|
guardian_pid: process.pid,
|
|
19937
19996
|
child_pid: childPid ?? null,
|
|
19938
19997
|
boot_identity: input.bootIdentity,
|
|
19998
|
+
termination,
|
|
19939
19999
|
updated_at: new Date().toISOString(),
|
|
19940
20000
|
}) + '\n';
|
|
19941
20001
|
receiptWriteSequence += 1;
|
|
@@ -19960,8 +20020,11 @@ const writeReceipt = (state, childPid) => {
|
|
|
19960
20020
|
};
|
|
19961
20021
|
let child = null;
|
|
19962
20022
|
let shuttingDown = false;
|
|
20023
|
+
let shutdownRequested = false;
|
|
20024
|
+
let childStartedAt = null;
|
|
19963
20025
|
let forceTimer = null;
|
|
19964
|
-
const
|
|
20026
|
+
const stopChild = (expected) => {
|
|
20027
|
+
if (expected) shutdownRequested = true;
|
|
19965
20028
|
if (shuttingDown) return;
|
|
19966
20029
|
shuttingDown = true;
|
|
19967
20030
|
if (!child) return;
|
|
@@ -19971,6 +20034,19 @@ const shutdown = () => {
|
|
|
19971
20034
|
}, input.shutdownGraceMs);
|
|
19972
20035
|
forceTimer.unref();
|
|
19973
20036
|
};
|
|
20037
|
+
let shutdownStarted = false;
|
|
20038
|
+
const shutdown = async () => {
|
|
20039
|
+
if (shutdownStarted) return;
|
|
20040
|
+
shutdownStarted = true;
|
|
20041
|
+
let expected = false;
|
|
20042
|
+
try {
|
|
20043
|
+
expected = (await readFile(input.shutdownIntentPath, 'utf8')) === input.processToken;
|
|
20044
|
+
await rm(input.shutdownIntentPath, { force: true });
|
|
20045
|
+
} catch {
|
|
20046
|
+
expected = false;
|
|
20047
|
+
}
|
|
20048
|
+
stopChild(expected);
|
|
20049
|
+
};
|
|
19974
20050
|
process.stdin.once('end', shutdown);
|
|
19975
20051
|
process.stdin.once('close', shutdown);
|
|
19976
20052
|
process.stdout.on('error', () => undefined);
|
|
@@ -19986,6 +20062,7 @@ child = spawn(input.binary, input.args, {
|
|
|
19986
20062
|
windowsHide: true,
|
|
19987
20063
|
detached: false,
|
|
19988
20064
|
});
|
|
20065
|
+
childStartedAt = Date.now();
|
|
19989
20066
|
child.stdin.on('error', () => undefined);
|
|
19990
20067
|
process.stdin.pipe(child.stdin, { end: false });
|
|
19991
20068
|
child.stdout.pipe(process.stdout);
|
|
@@ -19994,18 +20071,33 @@ child.once('spawn', async () => {
|
|
|
19994
20071
|
try {
|
|
19995
20072
|
await writeReceipt('running', child.pid ?? null);
|
|
19996
20073
|
} catch {
|
|
19997
|
-
|
|
20074
|
+
stopChild(false);
|
|
19998
20075
|
}
|
|
19999
20076
|
});
|
|
20000
|
-
child.once('error',
|
|
20001
|
-
child.once('close', async () => {
|
|
20077
|
+
child.once('error', () => stopChild(false));
|
|
20078
|
+
child.once('close', async (code, signal) => {
|
|
20002
20079
|
if (forceTimer) clearTimeout(forceTimer);
|
|
20003
20080
|
// A pending promise alone does not keep Node's event loop alive after the
|
|
20004
20081
|
// child and parent stdin have both closed. Hold one local handle until the
|
|
20005
20082
|
// serialized terminal tombstone is durably replaced.
|
|
20006
20083
|
const receiptKeepAlive = setInterval(() => undefined, 1_000);
|
|
20007
20084
|
try {
|
|
20008
|
-
|
|
20085
|
+
const normalizedSignal = typeof signal === 'string' && /^SIG[A-Z0-9]{1,28}$/.test(signal)
|
|
20086
|
+
? signal.toLowerCase()
|
|
20087
|
+
: null;
|
|
20088
|
+
const normalizedCode = normalizedSignal === null && Number.isInteger(code)
|
|
20089
|
+
&& code >= -(2 ** 31) && code <= (2 ** 31) - 1
|
|
20090
|
+
? code
|
|
20091
|
+
: null;
|
|
20092
|
+
await writeReceipt('terminated', child.pid ?? null, {
|
|
20093
|
+
exit_code: normalizedCode,
|
|
20094
|
+
signal: normalizedSignal,
|
|
20095
|
+
expected: shutdownRequested,
|
|
20096
|
+
uptime_ms: Math.min(
|
|
20097
|
+
Math.max(0, Date.now() - (childStartedAt ?? Date.now())),
|
|
20098
|
+
Number.MAX_SAFE_INTEGER,
|
|
20099
|
+
),
|
|
20100
|
+
});
|
|
20009
20101
|
} finally {
|
|
20010
20102
|
clearInterval(receiptKeepAlive);
|
|
20011
20103
|
process.exit(0);
|
|
@@ -20057,6 +20149,7 @@ child.once('close', async () => {
|
|
|
20057
20149
|
guardian_pid: null,
|
|
20058
20150
|
child_pid: null,
|
|
20059
20151
|
boot_identity: guardian.bootIdentity ?? null,
|
|
20152
|
+
termination: null,
|
|
20060
20153
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
20061
20154
|
})}
|
|
20062
20155
|
`;
|
|
@@ -20081,12 +20174,15 @@ child.once('close', async () => {
|
|
|
20081
20174
|
};
|
|
20082
20175
|
parseGuardianReceipt = (raw) => {
|
|
20083
20176
|
const value = JSON.parse(raw);
|
|
20084
|
-
|
|
20177
|
+
const rawTermination = value.termination;
|
|
20178
|
+
const termination = rawTermination === null || rawTermination === void 0 ? null : objectOrNull(rawTermination);
|
|
20179
|
+
if (value.schema_version !== "vtx_codex_guardian_v1" || typeof value.process_token !== "string" || !/^[0-9a-f]{64}$/u.test(value.process_token) || !["spawn_intent", "starting", "running", "terminated"].includes(String(value.state)) || value.guardian_pid !== null && !Number.isSafeInteger(value.guardian_pid) || value.state === "spawn_intent" && value.guardian_pid !== null || value.state !== "spawn_intent" && !Number.isSafeInteger(value.guardian_pid) || value.child_pid !== null && !Number.isSafeInteger(value.child_pid) || value.boot_identity !== null && value.boot_identity !== void 0 && typeof value.boot_identity !== "string" || typeof value.updated_at !== "string" || !Number.isFinite(Date.parse(value.updated_at)) || rawTermination !== null && rawTermination !== void 0 && termination === null || termination !== null && (value.state !== "terminated" || termination.exit_code !== null && (!Number.isInteger(termination.exit_code) || Number(termination.exit_code) < -(2 ** 31) || Number(termination.exit_code) > 2 ** 31 - 1) || termination.signal !== null && (typeof termination.signal !== "string" || !/^sig[a-z0-9]{1,28}$/u.test(termination.signal)) || termination.signal !== null && termination.exit_code !== null || typeof termination.expected !== "boolean" || !Number.isSafeInteger(termination.uptime_ms) || Number(termination.uptime_ms) < 0)) {
|
|
20085
20180
|
throw new Error("Codex guardian receipt is invalid.");
|
|
20086
20181
|
}
|
|
20087
20182
|
return {
|
|
20088
20183
|
...value,
|
|
20089
|
-
boot_identity: typeof value.boot_identity === "string" ? value.boot_identity : null
|
|
20184
|
+
boot_identity: typeof value.boot_identity === "string" ? value.boot_identity : null,
|
|
20185
|
+
termination
|
|
20090
20186
|
};
|
|
20091
20187
|
};
|
|
20092
20188
|
readCodexGuardianReceipt = async (path) => {
|
|
@@ -20130,6 +20226,7 @@ child.once('close', async () => {
|
|
|
20130
20226
|
args,
|
|
20131
20227
|
processToken: options.guardian.processToken,
|
|
20132
20228
|
receiptPath: options.guardian.receiptPath,
|
|
20229
|
+
shutdownIntentPath: `${options.guardian.receiptPath}.shutdown-intent`,
|
|
20133
20230
|
shutdownGraceMs: Math.max(25, options.guardian.shutdownGraceMs ?? 2e3),
|
|
20134
20231
|
bootIdentity: options.guardian.bootIdentity
|
|
20135
20232
|
}), "utf8").toString("base64url");
|
|
@@ -20151,13 +20248,33 @@ child.once('close', async () => {
|
|
|
20151
20248
|
this.nextRequestId = 1;
|
|
20152
20249
|
this.fatalError = null;
|
|
20153
20250
|
this.closed = false;
|
|
20251
|
+
this.processCloseObserved = false;
|
|
20252
|
+
this.shutdownRequested = false;
|
|
20253
|
+
this.stderrBytesObserved = 0;
|
|
20254
|
+
this.stderrNonempty = false;
|
|
20255
|
+
this.stderrTruncated = false;
|
|
20256
|
+
this.stderrTail = "";
|
|
20257
|
+
this.stderrClass = "none";
|
|
20154
20258
|
this.process = options.process;
|
|
20155
20259
|
this.codexHome = options.codexHome;
|
|
20156
|
-
this.
|
|
20260
|
+
this.sessionGeneration = options.sessionGeneration;
|
|
20261
|
+
this.startedAtMs = Date.now();
|
|
20262
|
+
this.guardian = options.guardian;
|
|
20263
|
+
this.onProcessExit = options.onProcessExit;
|
|
20264
|
+
this.process.stderr.on("data", (chunk) => this.observeStderr(chunk));
|
|
20157
20265
|
const lines = createInterface({ input: this.process.stdout, crlfDelay: Infinity });
|
|
20158
20266
|
lines.on("line", (line) => this.handleLine(line));
|
|
20159
|
-
this.process.once("error", () =>
|
|
20160
|
-
|
|
20267
|
+
this.process.once("error", () => {
|
|
20268
|
+
});
|
|
20269
|
+
this.process.once("close", (code, signal) => {
|
|
20270
|
+
void this.handleProcessClose(code, signal);
|
|
20271
|
+
});
|
|
20272
|
+
}
|
|
20273
|
+
static {
|
|
20274
|
+
this.STDERR_OBSERVATION_CAP_BYTES = 65536;
|
|
20275
|
+
}
|
|
20276
|
+
static {
|
|
20277
|
+
this.STDERR_CLASSIFICATION_TAIL_CHARS = 1024;
|
|
20161
20278
|
}
|
|
20162
20279
|
static async start(options) {
|
|
20163
20280
|
const spawnProcess = options.spawnProcess ?? defaultSpawn;
|
|
@@ -20218,7 +20335,13 @@ child.once('close', async () => {
|
|
|
20218
20335
|
});
|
|
20219
20336
|
}
|
|
20220
20337
|
}
|
|
20221
|
-
const session = new _CodexAppServerSession({
|
|
20338
|
+
const session = new _CodexAppServerSession({
|
|
20339
|
+
process: child,
|
|
20340
|
+
codexHome: options.codexHome,
|
|
20341
|
+
sessionGeneration: options.sessionGeneration ?? 1,
|
|
20342
|
+
guardian: guardian ?? null,
|
|
20343
|
+
onProcessExit: options.onProcessExit ?? null
|
|
20344
|
+
});
|
|
20222
20345
|
try {
|
|
20223
20346
|
const initialized = await session.request("initialize", {
|
|
20224
20347
|
clientInfo: {
|
|
@@ -20333,13 +20456,14 @@ child.once('close', async () => {
|
|
|
20333
20456
|
}
|
|
20334
20457
|
for (const listener of this.notificationListeners) listener({ method, params });
|
|
20335
20458
|
}
|
|
20336
|
-
failTransport(code) {
|
|
20459
|
+
failTransport(code, processExit = null) {
|
|
20337
20460
|
if (this.fatalError) return;
|
|
20338
20461
|
this.fatalError = new CodexAppServerError({
|
|
20339
20462
|
message: "Codex app-server transport became unavailable.",
|
|
20340
20463
|
category: "transport",
|
|
20341
20464
|
code,
|
|
20342
|
-
retryable: true
|
|
20465
|
+
retryable: true,
|
|
20466
|
+
processExit
|
|
20343
20467
|
});
|
|
20344
20468
|
for (const pending of this.pending.values()) {
|
|
20345
20469
|
if (pending.timer) clearTimeout(pending.timer);
|
|
@@ -20440,6 +20564,77 @@ child.once('close', async () => {
|
|
|
20440
20564
|
this.fatalListeners.add(listener);
|
|
20441
20565
|
return () => this.fatalListeners.delete(listener);
|
|
20442
20566
|
}
|
|
20567
|
+
observeStderr(chunk) {
|
|
20568
|
+
const bytes3 = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
20569
|
+
if (bytes3.length === 0) return;
|
|
20570
|
+
this.stderrNonempty = true;
|
|
20571
|
+
const remaining = Math.max(
|
|
20572
|
+
0,
|
|
20573
|
+
_CodexAppServerSession.STDERR_OBSERVATION_CAP_BYTES - this.stderrBytesObserved
|
|
20574
|
+
);
|
|
20575
|
+
if (remaining === 0) {
|
|
20576
|
+
this.stderrTruncated = true;
|
|
20577
|
+
return;
|
|
20578
|
+
}
|
|
20579
|
+
const observed = bytes3.subarray(0, remaining);
|
|
20580
|
+
this.stderrBytesObserved += observed.length;
|
|
20581
|
+
if (bytes3.length > remaining) this.stderrTruncated = true;
|
|
20582
|
+
this.stderrTail = `${this.stderrTail}${observed.toString("utf8")}`.slice(-_CodexAppServerSession.STDERR_CLASSIFICATION_TAIL_CHARS).toLowerCase();
|
|
20583
|
+
const classified = /heap out of memory|allocation failed|out of memory/u.test(this.stderrTail) ? "out_of_memory" : /fatal runtime error|fatal error|\bpanic(?:ked)?\b/u.test(this.stderrTail) ? "runtime_fatal" : /access violation|segmentation fault|\bsegfault\b/u.test(this.stderrTail) ? "memory_fault" : /broken pipe|econnreset|connection reset/u.test(this.stderrTail) ? "pipe_or_connection" : null;
|
|
20584
|
+
if (classified) this.stderrClass = classified;
|
|
20585
|
+
else if (this.stderrClass === "none") this.stderrClass = "unclassified";
|
|
20586
|
+
}
|
|
20587
|
+
async handleProcessClose(rawCode, rawSignal) {
|
|
20588
|
+
this.processCloseObserved = true;
|
|
20589
|
+
let termination = null;
|
|
20590
|
+
if (this.guardian) {
|
|
20591
|
+
try {
|
|
20592
|
+
const receipt = await readCodexGuardianReceipt(this.guardian.receiptPath);
|
|
20593
|
+
if (receipt?.process_token === this.guardian.processToken && receipt.state === "terminated") {
|
|
20594
|
+
termination = receipt.termination;
|
|
20595
|
+
}
|
|
20596
|
+
} catch {
|
|
20597
|
+
}
|
|
20598
|
+
}
|
|
20599
|
+
const diagnostics = this.processExitDiagnostics(rawCode, rawSignal, termination);
|
|
20600
|
+
if (this.guardian) {
|
|
20601
|
+
await rm2(`${this.guardian.receiptPath}.shutdown-intent`, { force: true }).catch(() => void 0);
|
|
20602
|
+
}
|
|
20603
|
+
try {
|
|
20604
|
+
this.onProcessExit?.(diagnostics);
|
|
20605
|
+
} catch {
|
|
20606
|
+
}
|
|
20607
|
+
this.failTransport("codex_process_closed", diagnostics);
|
|
20608
|
+
}
|
|
20609
|
+
processExitDiagnostics(rawCode, rawSignal, termination) {
|
|
20610
|
+
const source = termination ? "child_receipt" : this.guardian ? "guardian_process" : "direct_process";
|
|
20611
|
+
const reportedCode = termination?.exit_code ?? rawCode;
|
|
20612
|
+
const reportedSignal = termination?.signal ?? rawSignal;
|
|
20613
|
+
const signal = typeof reportedSignal === "string" && /^(?:SIG[A-Z0-9]{1,28}|sig[a-z0-9]{1,28})$/u.test(reportedSignal) ? reportedSignal.toLowerCase() : null;
|
|
20614
|
+
const exitCode = signal === null && typeof reportedCode === "number" && Number.isInteger(reportedCode) && reportedCode >= -(2 ** 31) && reportedCode <= 2 ** 31 - 1 ? reportedCode : null;
|
|
20615
|
+
const diagnostics = {
|
|
20616
|
+
schema_version: "external_inference_process_exit_v1",
|
|
20617
|
+
runtime: "codex_app_server",
|
|
20618
|
+
source,
|
|
20619
|
+
session_generation: this.sessionGeneration,
|
|
20620
|
+
expected_shutdown: termination?.expected ?? this.shutdownRequested,
|
|
20621
|
+
exit_class: signal !== null ? "signal" : exitCode === null ? "unknown" : exitCode === 0 ? "zero" : "nonzero",
|
|
20622
|
+
exit_code: exitCode,
|
|
20623
|
+
signal,
|
|
20624
|
+
uptime_ms: termination?.uptime_ms ?? Math.min(
|
|
20625
|
+
Math.max(0, Date.now() - this.startedAtMs),
|
|
20626
|
+
Number.MAX_SAFE_INTEGER
|
|
20627
|
+
),
|
|
20628
|
+
pending_request_count: this.pending.size,
|
|
20629
|
+
active_thread_count: this.threads.size,
|
|
20630
|
+
stderr_nonempty: this.stderrNonempty,
|
|
20631
|
+
stderr_bytes_observed: this.stderrBytesObserved,
|
|
20632
|
+
stderr_truncated: this.stderrTruncated,
|
|
20633
|
+
stderr_class: this.stderrNonempty ? this.stderrClass : "none"
|
|
20634
|
+
};
|
|
20635
|
+
this.stderrTail = "";
|
|
20636
|
+
return diagnostics;
|
|
20637
|
+
}
|
|
20443
20638
|
isUsable() {
|
|
20444
20639
|
return !this.closed && this.fatalError === null && this.process.exitCode === null;
|
|
20445
20640
|
}
|
|
@@ -20864,6 +21059,7 @@ child.once('close', async () => {
|
|
|
20864
21059
|
code: error48.code,
|
|
20865
21060
|
retryable: error48.retryable,
|
|
20866
21061
|
dispatchOutcome: requestWritten ? "outcome_unknown" : "not_dispatched",
|
|
21062
|
+
processExit: error48.processExit,
|
|
20867
21063
|
cause: error48
|
|
20868
21064
|
}));
|
|
20869
21065
|
});
|
|
@@ -21067,6 +21263,7 @@ child.once('close', async () => {
|
|
|
21067
21263
|
code: error48.code,
|
|
21068
21264
|
retryable: error48.retryable,
|
|
21069
21265
|
dispatchOutcome: "outcome_unknown",
|
|
21266
|
+
processExit: error48.processExit,
|
|
21070
21267
|
cause: error48
|
|
21071
21268
|
});
|
|
21072
21269
|
}
|
|
@@ -21319,6 +21516,20 @@ child.once('close', async () => {
|
|
|
21319
21516
|
async close() {
|
|
21320
21517
|
if (this.closed) return;
|
|
21321
21518
|
this.closed = true;
|
|
21519
|
+
if (this.processCloseObserved || this.process.exitCode !== null) {
|
|
21520
|
+
if (this.guardian) {
|
|
21521
|
+
await rm2(`${this.guardian.receiptPath}.shutdown-intent`, { force: true }).catch(() => void 0);
|
|
21522
|
+
}
|
|
21523
|
+
return;
|
|
21524
|
+
}
|
|
21525
|
+
this.shutdownRequested = true;
|
|
21526
|
+
if (this.guardian) {
|
|
21527
|
+
await writeFile(
|
|
21528
|
+
`${this.guardian.receiptPath}.shutdown-intent`,
|
|
21529
|
+
this.guardian.processToken,
|
|
21530
|
+
{ mode: 384 }
|
|
21531
|
+
).catch(() => void 0);
|
|
21532
|
+
}
|
|
21322
21533
|
this.process.stdin.end();
|
|
21323
21534
|
const exited = await new Promise((resolve6) => {
|
|
21324
21535
|
if (this.process.exitCode !== null) {
|
|
@@ -21527,11 +21738,12 @@ import {
|
|
|
21527
21738
|
import { createHash as createHash4, randomBytes as randomBytes3 } from "node:crypto";
|
|
21528
21739
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
21529
21740
|
import { isAbsolute as isAbsolute3, join as join4, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
|
|
21530
|
-
var MAX_PROMPT_BYTES2, CODEX_MODEL_NAME_PATTERN, CODEX_REASONING_EFFORT_PATTERN, codexRecoveryCheckpointProcessFingerprint, proveCodexSameBootQuiescence, tokenUsageReceiptSchema, turnResultReceiptSchema, terminalReceiptSchema, recoveryCheckpointSchema, recoveryFileSchema, FileCodexAttemptRecoveryStore, utf8Bytes, assertAttemptActive, tomlString, permissionConfig, ensureDedicatedCodexHome, createIsolatedCodexAttemptResources, createIsolatedCodexHostResources, validateAttemptInput, isStrictDescendant, assertRecoveryResourceScope, removeRecoveredThread, confirmGuardianTerminatedForRecovery, reconcileCodexAttemptRecovery, CodexSubscriptionAdapter;
|
|
21741
|
+
var MAX_PROMPT_BYTES2, CODEX_MODEL_NAME_PATTERN, CODEX_REASONING_EFFORT_PATTERN, codexRecoveryCheckpointProcessFingerprint, proveCodexSameBootQuiescence, tokenUsageReceiptSchema, turnResultReceiptSchema, terminalReceiptSchema, recoveryCheckpointSchema, recoveryFileSchema, FileCodexAttemptRecoveryStore, utf8Bytes, assertAttemptActive, tomlString, permissionConfig, ensureDedicatedCodexHome, createIsolatedCodexAttemptResources, createIsolatedCodexHostResources, validateAttemptInput, isStrictDescendant, assertRecoveryResourceScope, removeRecoveredThread, confirmGuardianTerminatedForRecovery, recoveredCodexProcessExit, reconcileCodexAttemptRecovery, CodexSubscriptionAdapter;
|
|
21531
21742
|
var init_codex_adapter = __esm({
|
|
21532
21743
|
"lib/inference-host/codex-adapter.ts"() {
|
|
21533
21744
|
"use strict";
|
|
21534
21745
|
init_zod();
|
|
21746
|
+
init_external_inference_contract();
|
|
21535
21747
|
init_codex_app_server();
|
|
21536
21748
|
init_codex_binary();
|
|
21537
21749
|
init_config();
|
|
@@ -21606,7 +21818,8 @@ var init_codex_adapter = __esm({
|
|
|
21606
21818
|
dispatchOutcome: external_exports.enum(["not_dispatched", "confirmed_dispatched", "outcome_unknown"]),
|
|
21607
21819
|
httpStatusCode: external_exports.number().int().min(100).max(599).nullable().optional(),
|
|
21608
21820
|
retryAtMs: external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).nullable().optional(),
|
|
21609
|
-
usage: tokenUsageReceiptSchema.nullable().optional()
|
|
21821
|
+
usage: tokenUsageReceiptSchema.nullable().optional(),
|
|
21822
|
+
processExit: codexProcessExitDiagnosticsSchema.nullable().optional()
|
|
21610
21823
|
})
|
|
21611
21824
|
})
|
|
21612
21825
|
]);
|
|
@@ -21622,6 +21835,7 @@ var init_codex_adapter = __esm({
|
|
|
21622
21835
|
processToken: external_exports.string().regex(/^[0-9a-f]{64}$/u).nullable(),
|
|
21623
21836
|
processReceiptPath: external_exports.string().min(1).max(4096).nullable(),
|
|
21624
21837
|
processState: external_exports.enum(["unmanaged", "spawn_intent", "running", "terminated"]),
|
|
21838
|
+
sessionGeneration: external_exports.number().int().positive().max(2147483647).nullable().optional(),
|
|
21625
21839
|
bootIdentity: external_exports.string().min(1).max(4096).nullable().optional(),
|
|
21626
21840
|
cleanupConfirmed: external_exports.boolean(),
|
|
21627
21841
|
adapterRequestId: external_exports.string().min(1).max(512).nullable(),
|
|
@@ -22016,6 +22230,30 @@ var init_codex_adapter = __esm({
|
|
|
22016
22230
|
throw error48;
|
|
22017
22231
|
}
|
|
22018
22232
|
};
|
|
22233
|
+
recoveredCodexProcessExit = (checkpoint, receipt) => {
|
|
22234
|
+
const termination = receipt?.termination;
|
|
22235
|
+
const sessionGeneration = checkpoint.sessionGeneration ?? null;
|
|
22236
|
+
if (!termination || termination.expected || sessionGeneration === null) return null;
|
|
22237
|
+
const signal = termination.signal;
|
|
22238
|
+
const exitCode = signal === null ? termination.exit_code : null;
|
|
22239
|
+
return {
|
|
22240
|
+
schema_version: "external_inference_process_exit_v1",
|
|
22241
|
+
runtime: "codex_app_server",
|
|
22242
|
+
source: "child_receipt",
|
|
22243
|
+
session_generation: sessionGeneration,
|
|
22244
|
+
expected_shutdown: false,
|
|
22245
|
+
exit_class: signal !== null ? "signal" : exitCode === null ? "unknown" : exitCode === 0 ? "zero" : "nonzero",
|
|
22246
|
+
exit_code: exitCode,
|
|
22247
|
+
signal,
|
|
22248
|
+
uptime_ms: termination.uptime_ms,
|
|
22249
|
+
pending_request_count: null,
|
|
22250
|
+
active_thread_count: null,
|
|
22251
|
+
stderr_nonempty: null,
|
|
22252
|
+
stderr_bytes_observed: null,
|
|
22253
|
+
stderr_truncated: null,
|
|
22254
|
+
stderr_class: "unknown"
|
|
22255
|
+
};
|
|
22256
|
+
};
|
|
22019
22257
|
reconcileCodexAttemptRecovery = async (options) => {
|
|
22020
22258
|
const attempts = await options.recoveryHooks.loadAll?.() ?? {};
|
|
22021
22259
|
const currentBootIdentity = options.bootIdentity ?? await readInferenceSystemBootIdentity();
|
|
@@ -22056,11 +22294,27 @@ var init_codex_adapter = __esm({
|
|
|
22056
22294
|
assertRecoveryResourceScope(checkpoint);
|
|
22057
22295
|
await removeRecoveredThread(checkpoint, options.codexHome);
|
|
22058
22296
|
await rm3(checkpoint.resourceRoot, { recursive: true, force: true });
|
|
22297
|
+
const recoveredProcessExit = recoveredCodexProcessExit(
|
|
22298
|
+
checkpoint,
|
|
22299
|
+
await readCodexGuardianReceipt(guardian.receiptPath)
|
|
22300
|
+
);
|
|
22301
|
+
const dispatchOutcome = crossedBoot ? "outcome_unknown" : checkpoint.dispatchOutcome;
|
|
22059
22302
|
await options.recoveryHooks.save({
|
|
22060
22303
|
...checkpoint,
|
|
22061
22304
|
processState: "terminated",
|
|
22062
22305
|
cleanupConfirmed: true,
|
|
22063
|
-
dispatchOutcome
|
|
22306
|
+
dispatchOutcome,
|
|
22307
|
+
terminal: checkpoint.terminal ?? (recoveredProcessExit ? {
|
|
22308
|
+
kind: "failed",
|
|
22309
|
+
error: {
|
|
22310
|
+
message: "Codex app-server transport became unavailable.",
|
|
22311
|
+
category: "transport",
|
|
22312
|
+
code: "codex_process_closed",
|
|
22313
|
+
retryable: true,
|
|
22314
|
+
dispatchOutcome,
|
|
22315
|
+
processExit: recoveredProcessExit
|
|
22316
|
+
}
|
|
22317
|
+
} : null)
|
|
22064
22318
|
});
|
|
22065
22319
|
reconciled += 1;
|
|
22066
22320
|
}
|
|
@@ -22074,8 +22328,15 @@ var init_codex_adapter = __esm({
|
|
|
22074
22328
|
this.durableSessionStart = null;
|
|
22075
22329
|
this.closing = false;
|
|
22076
22330
|
this.adapterClosePromise = null;
|
|
22331
|
+
this.sessionGeneration = 0;
|
|
22077
22332
|
this.dependencies = dependencies;
|
|
22078
22333
|
}
|
|
22334
|
+
emitDiagnostic(event) {
|
|
22335
|
+
try {
|
|
22336
|
+
this.dependencies.emitDiagnosticEvent?.(event);
|
|
22337
|
+
} catch {
|
|
22338
|
+
}
|
|
22339
|
+
}
|
|
22079
22340
|
async readAccountRateLimits(deadlineAtMs, signal) {
|
|
22080
22341
|
const codexHome = this.dependencies.codexHome;
|
|
22081
22342
|
if (!codexHome) {
|
|
@@ -22094,6 +22355,9 @@ var init_codex_adapter = __esm({
|
|
|
22094
22355
|
return await durableSession.session.readAccountRateLimits(deadlineAtMs, signal);
|
|
22095
22356
|
}
|
|
22096
22357
|
async startDurableSession(codexHome, deadlineAtMs) {
|
|
22358
|
+
this.sessionGeneration = Math.min(this.sessionGeneration + 1, 2147483647);
|
|
22359
|
+
const sessionGeneration = this.sessionGeneration;
|
|
22360
|
+
const activeAttemptIds = /* @__PURE__ */ new Set();
|
|
22097
22361
|
const binary = await (this.dependencies.resolveBinary ?? resolvePinnedCodexBinary)();
|
|
22098
22362
|
const guardianManaged = Boolean(
|
|
22099
22363
|
this.dependencies.recoveryHooks && !this.dependencies.spawnProcess
|
|
@@ -22108,10 +22372,26 @@ var init_codex_adapter = __esm({
|
|
|
22108
22372
|
codexHome,
|
|
22109
22373
|
deadlineAtMs,
|
|
22110
22374
|
spawnProcess: this.dependencies.spawnProcess,
|
|
22111
|
-
guardian: processToken && processReceiptPath ? { processToken, receiptPath: processReceiptPath, bootIdentity: bootIdentity ?? void 0 } : void 0
|
|
22375
|
+
guardian: processToken && processReceiptPath ? { processToken, receiptPath: processReceiptPath, bootIdentity: bootIdentity ?? void 0 } : void 0,
|
|
22376
|
+
sessionGeneration,
|
|
22377
|
+
onProcessExit: (diagnostics) => {
|
|
22378
|
+
this.emitDiagnostic({
|
|
22379
|
+
event: "codex_app_server_closed",
|
|
22380
|
+
process_exit: diagnostics,
|
|
22381
|
+
active_attempt_ids: [...activeAttemptIds].sort().slice(0, 64),
|
|
22382
|
+
active_attempt_ids_truncated: activeAttemptIds.size > 64
|
|
22383
|
+
});
|
|
22384
|
+
}
|
|
22385
|
+
});
|
|
22386
|
+
this.emitDiagnostic({
|
|
22387
|
+
event: "codex_app_server_session_started",
|
|
22388
|
+
session_generation: sessionGeneration,
|
|
22389
|
+
replacement: sessionGeneration > 1
|
|
22112
22390
|
});
|
|
22113
22391
|
return {
|
|
22114
22392
|
session,
|
|
22393
|
+
sessionGeneration,
|
|
22394
|
+
activeAttemptIds,
|
|
22115
22395
|
codexHome,
|
|
22116
22396
|
capabilityPreflight: null,
|
|
22117
22397
|
processToken,
|
|
@@ -22351,6 +22631,7 @@ var init_codex_adapter = __esm({
|
|
|
22351
22631
|
const receipt = await readCodexGuardianReceipt(checkpoint.processReceiptPath);
|
|
22352
22632
|
if (checkpoint.processState === "terminated" || receipt === null || receipt.state === "terminated") {
|
|
22353
22633
|
await rm3(checkpoint.processReceiptPath, { force: true });
|
|
22634
|
+
await rm3(`${checkpoint.processReceiptPath}.shutdown-intent`, { force: true });
|
|
22354
22635
|
}
|
|
22355
22636
|
}
|
|
22356
22637
|
}
|
|
@@ -22398,6 +22679,7 @@ var init_codex_adapter = __esm({
|
|
|
22398
22679
|
for (const session of sessions) {
|
|
22399
22680
|
if (session.processReceiptPath && unconfirmedReceiptPaths !== null && !unconfirmedReceiptPaths.has(resolve3(session.processReceiptPath))) {
|
|
22400
22681
|
await rm3(session.processReceiptPath, { force: true });
|
|
22682
|
+
await rm3(`${session.processReceiptPath}.shutdown-intent`, { force: true });
|
|
22401
22683
|
}
|
|
22402
22684
|
}
|
|
22403
22685
|
})();
|
|
@@ -22442,7 +22724,8 @@ var init_codex_adapter = __esm({
|
|
|
22442
22724
|
dispatchOutcome: recovered.dispatchOutcome,
|
|
22443
22725
|
httpStatusCode: recovered.httpStatusCode,
|
|
22444
22726
|
retryAtMs: recovered.retryAtMs,
|
|
22445
|
-
usage: recovered.usage
|
|
22727
|
+
usage: recovered.usage,
|
|
22728
|
+
processExit: recovered.processExit
|
|
22446
22729
|
});
|
|
22447
22730
|
}
|
|
22448
22731
|
throw new CodexAppServerError({
|
|
@@ -22475,6 +22758,7 @@ var init_codex_adapter = __esm({
|
|
|
22475
22758
|
input.deadlineAtMs,
|
|
22476
22759
|
input.signal
|
|
22477
22760
|
);
|
|
22761
|
+
sessionLease.activeAttemptIds.add(input.attemptId);
|
|
22478
22762
|
session = sessionLease.session;
|
|
22479
22763
|
baseCheckpoint = {
|
|
22480
22764
|
schemaVersion: "vtx_codex_attempt_recovery_v1",
|
|
@@ -22488,6 +22772,7 @@ var init_codex_adapter = __esm({
|
|
|
22488
22772
|
processToken: sessionLease.processToken,
|
|
22489
22773
|
processReceiptPath: sessionLease.processReceiptPath,
|
|
22490
22774
|
processState: sessionLease.processToken ? "running" : "unmanaged",
|
|
22775
|
+
sessionGeneration: sessionLease.sessionGeneration,
|
|
22491
22776
|
bootIdentity: sessionLease.bootIdentity,
|
|
22492
22777
|
cleanupConfirmed: false,
|
|
22493
22778
|
adapterRequestId: null,
|
|
@@ -22586,7 +22871,8 @@ var init_codex_adapter = __esm({
|
|
|
22586
22871
|
dispatchOutcome,
|
|
22587
22872
|
httpStatusCode: error48.httpStatusCode,
|
|
22588
22873
|
retryAtMs: error48.retryAtMs,
|
|
22589
|
-
usage: error48.usage
|
|
22874
|
+
usage: error48.usage,
|
|
22875
|
+
processExit: error48.processExit
|
|
22590
22876
|
}
|
|
22591
22877
|
}
|
|
22592
22878
|
};
|
|
@@ -22602,6 +22888,7 @@ var init_codex_adapter = __esm({
|
|
|
22602
22888
|
httpStatusCode: error48.httpStatusCode,
|
|
22603
22889
|
retryAtMs: error48.retryAtMs,
|
|
22604
22890
|
usage: error48.usage,
|
|
22891
|
+
processExit: error48.processExit,
|
|
22605
22892
|
cause: error48
|
|
22606
22893
|
});
|
|
22607
22894
|
}
|
|
@@ -22632,6 +22919,7 @@ var init_codex_adapter = __esm({
|
|
|
22632
22919
|
}
|
|
22633
22920
|
throw classified;
|
|
22634
22921
|
} finally {
|
|
22922
|
+
sessionLease?.activeAttemptIds.delete(input.attemptId);
|
|
22635
22923
|
const cleanup = async () => {
|
|
22636
22924
|
let cleanupError = sessionInvalidationError;
|
|
22637
22925
|
if (session && threadId) {
|
|
@@ -29762,7 +30050,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
|
|
|
29762
30050
|
envelopePublicKey: options.envelopePublicKey
|
|
29763
30051
|
};
|
|
29764
30052
|
}
|
|
29765
|
-
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, 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, 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;
|
|
30053
|
+
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, 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;
|
|
29766
30054
|
var init_runner = __esm({
|
|
29767
30055
|
"lib/inference-host/runner.ts"() {
|
|
29768
30056
|
"use strict";
|
|
@@ -29784,6 +30072,8 @@ var init_runner = __esm({
|
|
|
29784
30072
|
DEFAULT_DRAIN_TIMEOUT_MS = 3e4;
|
|
29785
30073
|
DEFAULT_REMOTE_RETRY_LIMIT = 3;
|
|
29786
30074
|
MIN_SLEEP_MS = 10;
|
|
30075
|
+
MIN_HOST_HEARTBEAT_GAP_DIAGNOSTIC_MS = 1e4;
|
|
30076
|
+
HOST_HEARTBEAT_GAP_DIAGNOSTIC_FACTOR = 3;
|
|
29787
30077
|
DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
29788
30078
|
MIN_CLAIM_START_WINDOW_MS = 5e3;
|
|
29789
30079
|
MAX_ATTEMPT_START_RETRY_DELAY_MS = 15e3;
|
|
@@ -30779,6 +31069,26 @@ var init_runner = __esm({
|
|
|
30779
31069
|
}
|
|
30780
31070
|
};
|
|
30781
31071
|
await hostHeartbeat("healthy");
|
|
31072
|
+
let lastHostHeartbeatSucceededAt = now();
|
|
31073
|
+
let hostHeartbeatGapOpen = false;
|
|
31074
|
+
const hostHeartbeatGapThresholdMs = Math.max(
|
|
31075
|
+
MIN_HOST_HEARTBEAT_GAP_DIAGNOSTIC_MS,
|
|
31076
|
+
settings.hostHeartbeatMs * HOST_HEARTBEAT_GAP_DIAGNOSTIC_FACTOR
|
|
31077
|
+
);
|
|
31078
|
+
const observeHostHeartbeatGap = (observedAt) => {
|
|
31079
|
+
const gapMs = Math.max(0, observedAt - lastHostHeartbeatSucceededAt);
|
|
31080
|
+
if (gapMs >= hostHeartbeatGapThresholdMs && !hostHeartbeatGapOpen) {
|
|
31081
|
+
hostHeartbeatGapOpen = true;
|
|
31082
|
+
emitDiagnostic("host_heartbeat_gap_detected", {
|
|
31083
|
+
gap_ms: gapMs,
|
|
31084
|
+
configured_interval_ms: settings.hostHeartbeatMs,
|
|
31085
|
+
diagnostic_threshold_ms: hostHeartbeatGapThresholdMs,
|
|
31086
|
+
active_attempts: active.size,
|
|
31087
|
+
host_heartbeat_sequence: receipt.host_heartbeat_sequence
|
|
31088
|
+
});
|
|
31089
|
+
}
|
|
31090
|
+
return gapMs;
|
|
31091
|
+
};
|
|
30782
31092
|
let nextHostHeartbeatAt = now() + settings.hostHeartbeatMs;
|
|
30783
31093
|
let nextAdvertisementAttemptAt = 0;
|
|
30784
31094
|
let nextProviderRateLimitRefreshAt = now() + settings.providerRateLimitRefreshMs;
|
|
@@ -31045,6 +31355,7 @@ var init_runner = __esm({
|
|
|
31045
31355
|
}
|
|
31046
31356
|
}
|
|
31047
31357
|
if (currentTime >= nextHostHeartbeatAt) {
|
|
31358
|
+
observeHostHeartbeatGap(currentTime);
|
|
31048
31359
|
try {
|
|
31049
31360
|
const refreshPendingAcrossExpiry = receipt.pending_advertisement !== null && expiresAt <= currentTime && nextAdvertisementAttemptAt > currentTime;
|
|
31050
31361
|
await hostHeartbeat(
|
|
@@ -31053,6 +31364,19 @@ var init_runner = __esm({
|
|
|
31053
31364
|
false,
|
|
31054
31365
|
refreshPendingAcrossExpiry
|
|
31055
31366
|
);
|
|
31367
|
+
const heartbeatSucceededAt = now();
|
|
31368
|
+
const gapMs = observeHostHeartbeatGap(heartbeatSucceededAt);
|
|
31369
|
+
if (hostHeartbeatGapOpen) {
|
|
31370
|
+
emitDiagnostic("host_heartbeat_gap_recovered", {
|
|
31371
|
+
gap_ms: gapMs,
|
|
31372
|
+
configured_interval_ms: settings.hostHeartbeatMs,
|
|
31373
|
+
diagnostic_threshold_ms: hostHeartbeatGapThresholdMs,
|
|
31374
|
+
active_attempts: active.size,
|
|
31375
|
+
host_heartbeat_sequence: receipt.host_heartbeat_sequence
|
|
31376
|
+
});
|
|
31377
|
+
hostHeartbeatGapOpen = false;
|
|
31378
|
+
}
|
|
31379
|
+
lastHostHeartbeatSucceededAt = heartbeatSucceededAt;
|
|
31056
31380
|
} catch (error48) {
|
|
31057
31381
|
if (controlPlaneFatal(error48)) {
|
|
31058
31382
|
requestDrain("authority_lost");
|
|
@@ -31612,6 +31936,7 @@ var init_runner = __esm({
|
|
|
31612
31936
|
});
|
|
31613
31937
|
}
|
|
31614
31938
|
const classified = classifyFailure(heartbeatFailure ?? error48, adapterResult);
|
|
31939
|
+
const processExit = heartbeatFailure === void 0 && error48 instanceof CodexAppServerError && error48.code === "codex_process_closed" && error48.processExit?.expected_shutdown === false ? error48.processExit : null;
|
|
31615
31940
|
const heartbeatAmbiguous = ambiguousHeartbeatTransport(heartbeatFailure);
|
|
31616
31941
|
const failure = heartbeatAmbiguous ? {
|
|
31617
31942
|
...classified,
|
|
@@ -31665,6 +31990,7 @@ var init_runner = __esm({
|
|
|
31665
31990
|
failure_category: failure.category,
|
|
31666
31991
|
failure_code: failure.code,
|
|
31667
31992
|
retryable: failure.retryable,
|
|
31993
|
+
...processExit ? { process_exit: processExit } : {},
|
|
31668
31994
|
membership_disposition: membershipFailureDisposition({
|
|
31669
31995
|
...failure,
|
|
31670
31996
|
dispatchOutcome
|
|
@@ -31699,6 +32025,7 @@ var init_runner = __esm({
|
|
|
31699
32025
|
failure_category: failureRequest.failure_category,
|
|
31700
32026
|
failure_code: failureRequest.failure_code,
|
|
31701
32027
|
retryable: failureRequest.retryable,
|
|
32028
|
+
process_exit: failureRequest.process_exit ?? null,
|
|
31702
32029
|
dispatch_outcome: failureRequest.outcome.dispatch_outcome,
|
|
31703
32030
|
response_outcome: failureRequest.outcome.response_outcome,
|
|
31704
32031
|
latency_ms: adapterResult?.latencyMs ?? null,
|
|
@@ -33692,6 +34019,17 @@ Durable service:
|
|
|
33692
34019
|
}
|
|
33693
34020
|
};
|
|
33694
34021
|
defaultRunForeground = async (options) => {
|
|
34022
|
+
const localState = await readInferenceHostLocalState(options.config.statePath);
|
|
34023
|
+
const emitCodexDiagnostic = (event) => {
|
|
34024
|
+
options.emitDiagnosticEvent?.({
|
|
34025
|
+
...event,
|
|
34026
|
+
schema_version: "vtx_inference_host_diagnostic_v1",
|
|
34027
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34028
|
+
instance_name: options.config.instanceName,
|
|
34029
|
+
host_id: localState?.host_id ?? null,
|
|
34030
|
+
display_name: options.displayName
|
|
34031
|
+
});
|
|
34032
|
+
};
|
|
33695
34033
|
const adapter = new CodexSubscriptionAdapter({
|
|
33696
34034
|
resolveBinary: async () => options.verifiedBinary,
|
|
33697
34035
|
createAttemptResources: options.hostResources.createAttemptResources,
|
|
@@ -33699,7 +34037,8 @@ Durable service:
|
|
|
33699
34037
|
guardianReceiptRoot: codexGuardianReceiptRoot(options.config),
|
|
33700
34038
|
recoveryHooks: new FileCodexAttemptRecoveryStore(
|
|
33701
34039
|
codexRecoveryPath(options.config)
|
|
33702
|
-
)
|
|
34040
|
+
),
|
|
34041
|
+
emitDiagnosticEvent: emitCodexDiagnostic
|
|
33703
34042
|
});
|
|
33704
34043
|
const dependencies = createDefaultInferenceHostRunnerDependencies({
|
|
33705
34044
|
apiUrl: options.config.apiUrl,
|
|
@@ -34376,7 +34715,15 @@ Waiting for approval...
|
|
|
34376
34715
|
const emitDiagnosticEvent = parsed.json ? (event) => (dependencies.emitStdout ?? ((text) => {
|
|
34377
34716
|
process.stdout.write(text);
|
|
34378
34717
|
}))(`${JSON.stringify(event)}
|
|
34379
|
-
`) :
|
|
34718
|
+
`) : adapterId === "codex" ? (event) => {
|
|
34719
|
+
if (!["codex_app_server_closed", "codex_app_server_session_started"].includes(
|
|
34720
|
+
String(event.event ?? "")
|
|
34721
|
+
)) return;
|
|
34722
|
+
(dependencies.emitStderr ?? ((text) => {
|
|
34723
|
+
process.stderr.write(text);
|
|
34724
|
+
}))(`[VTX inference-host] ${JSON.stringify(event)}
|
|
34725
|
+
`);
|
|
34726
|
+
} : void 0;
|
|
34380
34727
|
if (adapterId !== "codex") {
|
|
34381
34728
|
const prepared = await (dependencies.prepareDurableAdapter ?? preparePortableDurableAdapter)(
|
|
34382
34729
|
adapterId,
|