@vtxmacro/cli 2026.8.37 → 2026.8.39
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 +10 -10
- package/bin/vtx.js +411 -65
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,10 +58,10 @@ exposed. Before starting a Trader, confirm that the VTX AI page shows the
|
|
|
58
58
|
intended authenticated ChatGPT email and plan. The host reads the live Codex
|
|
59
59
|
account window: a reached limit pauses new dispatch until its reported reset,
|
|
60
60
|
while a transient throttle uses a short bounded cooldown.
|
|
61
|
-
The selected AI model row
|
|
62
|
-
|
|
63
|
-
Account-wide quota percentages remain in
|
|
64
|
-
profile-scoped selector.
|
|
61
|
+
The selected AI model row estimates the open VTX profile's attributable
|
|
62
|
+
membership burn rate for that subscription, expressed as equivalent percentage
|
|
63
|
+
points per hour, day, and seven days. Account-wide quota percentages remain in
|
|
64
|
+
safe host diagnostics instead of the profile-scoped selector.
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
vtx inference-host login
|
|
@@ -86,12 +86,12 @@ distinct. Use `service uninstall --instance <name>` to remove one worker;
|
|
|
86
86
|
unqualified `service uninstall` removes the whole supervisor. The legacy
|
|
87
87
|
unqualified host commands continue to target `default`.
|
|
88
88
|
|
|
89
|
-
For
|
|
90
|
-
compatible
|
|
91
|
-
unusable authentication, and exhausted recoverable
|
|
92
|
-
advance the same logical call. VTX never changes
|
|
93
|
-
response mode, and never cascades a bad request,
|
|
94
|
-
dispatch outcome.
|
|
89
|
+
For each VTX profile and lane, **Subscription #1** is tried first and later
|
|
90
|
+
compatible subscriptions follow in the saved Account cascade order.
|
|
91
|
+
Quota/credits exhaustion, unusable authentication, and exhausted recoverable
|
|
92
|
+
provider failures can advance the same logical call. VTX never changes
|
|
93
|
+
provider, model, effort, or response mode, and never cascades a bad request,
|
|
94
|
+
policy rejection, or uncertain dispatch outcome.
|
|
95
95
|
|
|
96
96
|
Automated hosts do not impose a subscription-specific profile-count or
|
|
97
97
|
concurrency limit by default. Set an explicit positive integer with
|
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.39",
|
|
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, 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, 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;
|
|
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, 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;
|
|
14379
14379
|
var init_external_inference_contract = __esm({
|
|
14380
14380
|
"lib/external-inference-contract.ts"() {
|
|
14381
14381
|
"use strict";
|
|
@@ -14646,6 +14646,15 @@ var init_external_inference_contract = __esm({
|
|
|
14646
14646
|
response_mode_hint: responseModeSchema,
|
|
14647
14647
|
binding_state: external_exports.literal("rebind_required")
|
|
14648
14648
|
});
|
|
14649
|
+
orderedFallbackHostIdsSchema = external_exports.array(identifierSchema).max(127).refine(
|
|
14650
|
+
(values) => new Set(values).size === values.length,
|
|
14651
|
+
{ message: "fallback host IDs must be unique" }
|
|
14652
|
+
);
|
|
14653
|
+
externalInferenceFallbackHostIdsSchema = external_exports.strictObject({
|
|
14654
|
+
main: orderedFallbackHostIdsSchema,
|
|
14655
|
+
review: orderedFallbackHostIdsSchema,
|
|
14656
|
+
screener: orderedFallbackHostIdsSchema
|
|
14657
|
+
});
|
|
14649
14658
|
liveModelControllerSchema = external_exports.discriminatedUnion("kind", [
|
|
14650
14659
|
nativeModelControllerSchema,
|
|
14651
14660
|
externalAgentModelControllerSchema
|
|
@@ -16245,6 +16254,109 @@ function resolveInferenceHostConfig(env = process.env) {
|
|
|
16245
16254
|
supervisorProcessLockPath: join(baseDir, "host.lock")
|
|
16246
16255
|
};
|
|
16247
16256
|
}
|
|
16257
|
+
async function writeInferenceHostCredentialContext(config2) {
|
|
16258
|
+
const context = credentialContextForConfig(config2);
|
|
16259
|
+
await writeAtomicInferencePrivateFile(
|
|
16260
|
+
inferenceHostCredentialContextPath(config2),
|
|
16261
|
+
`${JSON.stringify(context, null, 2)}
|
|
16262
|
+
`
|
|
16263
|
+
);
|
|
16264
|
+
}
|
|
16265
|
+
async function writeInferenceHostCredentialContextTransition(config2, previous, candidate = credentialContextForConfig(config2), operation = "selection", phase = "prepared") {
|
|
16266
|
+
const transition = {
|
|
16267
|
+
schema_version: "vtx_inference_credential_context_transition_v1",
|
|
16268
|
+
operation,
|
|
16269
|
+
phase,
|
|
16270
|
+
previous,
|
|
16271
|
+
candidate
|
|
16272
|
+
};
|
|
16273
|
+
await writeAtomicInferencePrivateFile(
|
|
16274
|
+
inferenceHostCredentialContextTransitionPath(config2),
|
|
16275
|
+
`${JSON.stringify(transition, null, 2)}
|
|
16276
|
+
`
|
|
16277
|
+
);
|
|
16278
|
+
}
|
|
16279
|
+
async function readInferenceHostCredentialContextTransition(config2) {
|
|
16280
|
+
const raw = await readInferencePrivateFile(
|
|
16281
|
+
inferenceHostCredentialContextTransitionPath(config2),
|
|
16282
|
+
"Inference host credential context transition"
|
|
16283
|
+
);
|
|
16284
|
+
if (raw === null) return null;
|
|
16285
|
+
let value;
|
|
16286
|
+
try {
|
|
16287
|
+
value = JSON.parse(raw);
|
|
16288
|
+
} catch {
|
|
16289
|
+
throw new Error("Inference host credential context transition is not valid JSON.");
|
|
16290
|
+
}
|
|
16291
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
16292
|
+
throw new Error("Inference host credential context transition is invalid.");
|
|
16293
|
+
}
|
|
16294
|
+
const record2 = value;
|
|
16295
|
+
const expectedKeys = ["schema_version", "operation", "phase", "previous", "candidate"];
|
|
16296
|
+
if (Object.keys(record2).sort().join("\0") !== expectedKeys.sort().join("\0") || record2.schema_version !== "vtx_inference_credential_context_transition_v1" || record2.operation !== "selection" && record2.operation !== "cleanup" || record2.phase !== "prepared" && record2.phase !== "committed") {
|
|
16297
|
+
throw new Error("Inference host credential context transition is invalid.");
|
|
16298
|
+
}
|
|
16299
|
+
return {
|
|
16300
|
+
schema_version: "vtx_inference_credential_context_transition_v1",
|
|
16301
|
+
operation: record2.operation,
|
|
16302
|
+
phase: record2.phase,
|
|
16303
|
+
previous: record2.previous === null ? null : assertInferenceHostCredentialContext(record2.previous, config2),
|
|
16304
|
+
candidate: record2.candidate === null ? null : assertInferenceHostCredentialContext(record2.candidate, config2)
|
|
16305
|
+
};
|
|
16306
|
+
}
|
|
16307
|
+
async function clearInferenceHostCredentialContextTransition(config2) {
|
|
16308
|
+
await clearInferencePrivateFile(
|
|
16309
|
+
inferenceHostCredentialContextTransitionPath(config2),
|
|
16310
|
+
"Inference host credential context transition"
|
|
16311
|
+
);
|
|
16312
|
+
}
|
|
16313
|
+
async function clearInferenceHostCredentialContext(config2) {
|
|
16314
|
+
await clearInferencePrivateFile(
|
|
16315
|
+
inferenceHostCredentialContextPath(config2),
|
|
16316
|
+
"Inference host credential context"
|
|
16317
|
+
);
|
|
16318
|
+
}
|
|
16319
|
+
async function readInferenceHostCredentialContext(config2) {
|
|
16320
|
+
const raw = await readInferencePrivateFile(
|
|
16321
|
+
inferenceHostCredentialContextPath(config2),
|
|
16322
|
+
"Inference host credential context"
|
|
16323
|
+
);
|
|
16324
|
+
if (raw === null) return null;
|
|
16325
|
+
let value;
|
|
16326
|
+
try {
|
|
16327
|
+
value = JSON.parse(raw);
|
|
16328
|
+
} catch {
|
|
16329
|
+
throw new Error("Inference host credential context is not valid JSON.");
|
|
16330
|
+
}
|
|
16331
|
+
return assertInferenceHostCredentialContext(value, config2);
|
|
16332
|
+
}
|
|
16333
|
+
function assertInferenceHostCredentialContext(value, config2) {
|
|
16334
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
16335
|
+
throw new Error("Inference host credential context is invalid.");
|
|
16336
|
+
}
|
|
16337
|
+
const record2 = value;
|
|
16338
|
+
const expectedKeys = [
|
|
16339
|
+
"schema_version",
|
|
16340
|
+
"instance_name",
|
|
16341
|
+
"credential_store_mode",
|
|
16342
|
+
"credential_file_path"
|
|
16343
|
+
];
|
|
16344
|
+
if (Object.keys(record2).sort().join("\0") !== expectedKeys.sort().join("\0") || record2.schema_version !== "vtx_inference_credential_context_v1" || record2.instance_name !== config2.instanceName || record2.credential_store_mode !== "os" && record2.credential_store_mode !== "file" || (record2.credential_store_mode === "os" ? record2.credential_file_path !== null : typeof record2.credential_file_path !== "string" || !record2.credential_file_path)) {
|
|
16345
|
+
throw new Error("Inference host credential context is invalid.");
|
|
16346
|
+
}
|
|
16347
|
+
const credentialFilePath = record2.credential_store_mode === "file" ? requireNamedInstancePath(
|
|
16348
|
+
config2.instanceName,
|
|
16349
|
+
config2.instanceName === DEFAULT_INFERENCE_HOST_INSTANCE ? config2.baseDir : join(config2.baseDir, "instances", config2.instanceName),
|
|
16350
|
+
record2.credential_file_path,
|
|
16351
|
+
"Stored inference credential path"
|
|
16352
|
+
) : null;
|
|
16353
|
+
return {
|
|
16354
|
+
schema_version: "vtx_inference_credential_context_v1",
|
|
16355
|
+
instance_name: config2.instanceName,
|
|
16356
|
+
credential_store_mode: record2.credential_store_mode,
|
|
16357
|
+
credential_file_path: credentialFilePath
|
|
16358
|
+
};
|
|
16359
|
+
}
|
|
16248
16360
|
function assertLocalState(value) {
|
|
16249
16361
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
16250
16362
|
throw new Error("Inference host local state is invalid.");
|
|
@@ -16619,7 +16731,7 @@ async function acquireInferenceHostProcessLock(path, dependencies = {}) {
|
|
|
16619
16731
|
}
|
|
16620
16732
|
};
|
|
16621
16733
|
}
|
|
16622
|
-
var INFERENCE_CREDENTIAL_NAMESPACE, MAX_INFERENCE_PRIVATE_FILE_BYTES, WINDOWS_PRIVATE_ACL_BROKER_SCRIPT, windowsPrivateAclBrokerInvocation, WindowsPrivateAclBroker, defaultWindowsPrivateAclBroker, runWindowsPrivateAcl, windowsAclCache, windowsAclIdentity, aclCacheKey, secureWindowsPrivatePath, invalidateWindowsAclCache, rebindHardenedWindowsAclAfterRename, rebindHardenedWindowsDirectoryAfterOwnedMutation, isDefaultWindowsPrivatePath, secureExistingWindowsPath, linuxProcessIdentity, windowsProcessIdentity, darwinProcessIdentity, runSmallIdentityCommand, cachedSystemBootIdentity, readInferenceSystemBootIdentity, defaultProcessIdentity, defaultCurrentProcessIdentity, processLockObservationCache, inferenceProcessIdentitiesMatch, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity;
|
|
16734
|
+
var INFERENCE_CREDENTIAL_NAMESPACE, MAX_INFERENCE_PRIVATE_FILE_BYTES, WINDOWS_PRIVATE_ACL_BROKER_SCRIPT, windowsPrivateAclBrokerInvocation, WindowsPrivateAclBroker, defaultWindowsPrivateAclBroker, runWindowsPrivateAcl, windowsAclCache, windowsAclIdentity, aclCacheKey, secureWindowsPrivatePath, invalidateWindowsAclCache, rebindHardenedWindowsAclAfterRename, rebindHardenedWindowsDirectoryAfterOwnedMutation, isDefaultWindowsPrivatePath, secureExistingWindowsPath, linuxProcessIdentity, windowsProcessIdentity, darwinProcessIdentity, runSmallIdentityCommand, cachedSystemBootIdentity, readInferenceSystemBootIdentity, defaultProcessIdentity, defaultCurrentProcessIdentity, processLockObservationCache, inferenceProcessIdentitiesMatch, DEFAULT_INFERENCE_HOST_INSTANCE, SAFE_INFERENCE_HOST_INSTANCE, requireNamedInstancePath, credentialStoreIdentity, inferenceHostCredentialContextPath, inferenceHostCredentialContextTransitionPath, credentialContextForConfig;
|
|
16623
16735
|
var init_config = __esm({
|
|
16624
16736
|
"lib/inference-host/config.ts"() {
|
|
16625
16737
|
"use strict";
|
|
@@ -17138,6 +17250,17 @@ while(($line=[Console]::In.ReadLine()) -ne $null) {
|
|
|
17138
17250
|
if (process.platform === "darwin") return "os:macos-keychain";
|
|
17139
17251
|
return `os:${process.platform}:unsupported`;
|
|
17140
17252
|
};
|
|
17253
|
+
inferenceHostCredentialContextPath = (config2) => join(
|
|
17254
|
+
config2.instanceName === DEFAULT_INFERENCE_HOST_INSTANCE ? config2.baseDir : join(config2.baseDir, "instances", config2.instanceName),
|
|
17255
|
+
"credential-context.json"
|
|
17256
|
+
);
|
|
17257
|
+
inferenceHostCredentialContextTransitionPath = (config2) => `${inferenceHostCredentialContextPath(config2)}.pending`;
|
|
17258
|
+
credentialContextForConfig = (config2) => ({
|
|
17259
|
+
schema_version: "vtx_inference_credential_context_v1",
|
|
17260
|
+
instance_name: config2.instanceName,
|
|
17261
|
+
credential_store_mode: config2.credentialStoreMode,
|
|
17262
|
+
credential_file_path: config2.credentialStoreMode === "file" ? resolve(config2.credentialFilePath) : null
|
|
17263
|
+
});
|
|
17141
17264
|
}
|
|
17142
17265
|
});
|
|
17143
17266
|
|
|
@@ -19382,7 +19505,7 @@ async function logoutCodexSubscription(options) {
|
|
|
19382
19505
|
await session.close();
|
|
19383
19506
|
}
|
|
19384
19507
|
}
|
|
19385
|
-
var CODEX_INFERENCE_PERMISSION_PROFILE, CODEX_REASONING_CONTENT_MAX_UTF8_BYTES, CODEX_REASONING_SUMMARY_MAX_UTF8_BYTES, 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, WINDOWS_RECEIPT_REPLACE_ERROR_CODES, replaceCodexGuardianReceiptFile, writeCodexGuardianSpawnIntent, parseGuardianReceipt, readCodexGuardianReceipt, waitForCodexGuardianState, defaultSpawn, CodexAppServerSession;
|
|
19508
|
+
var CODEX_INFERENCE_PERMISSION_PROFILE, CODEX_REASONING_CONTENT_MAX_UTF8_BYTES, CODEX_REASONING_SUMMARY_MAX_UTF8_BYTES, 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, WINDOWS_RECEIPT_REPLACE_ERROR_CODES, MAX_RETIRED_RESPONSE_IDS, LATE_RESPONSE_SAFE_METHODS, replaceCodexGuardianReceiptFile, writeCodexGuardianSpawnIntent, parseGuardianReceipt, readCodexGuardianReceipt, waitForCodexGuardianState, defaultSpawn, CodexAppServerSession;
|
|
19386
19509
|
var init_codex_app_server = __esm({
|
|
19387
19510
|
"lib/inference-host/codex-app-server.ts"() {
|
|
19388
19511
|
"use strict";
|
|
@@ -19845,6 +19968,8 @@ child.once('close', async () => {
|
|
|
19845
19968
|
"ENOTEMPTY",
|
|
19846
19969
|
"EPERM"
|
|
19847
19970
|
]);
|
|
19971
|
+
MAX_RETIRED_RESPONSE_IDS = 256;
|
|
19972
|
+
LATE_RESPONSE_SAFE_METHODS = /* @__PURE__ */ new Set(["account/rateLimits/read"]);
|
|
19848
19973
|
replaceCodexGuardianReceiptFile = async (temporaryPath, receiptPath, options = {}) => {
|
|
19849
19974
|
const platform = options.platform ?? process.platform;
|
|
19850
19975
|
const renameFile = options.renameFile ?? rename2;
|
|
@@ -19967,6 +20092,7 @@ child.once('close', async () => {
|
|
|
19967
20092
|
CodexAppServerSession = class _CodexAppServerSession {
|
|
19968
20093
|
constructor(options) {
|
|
19969
20094
|
this.pending = /* @__PURE__ */ new Map();
|
|
20095
|
+
this.retiredResponseIds = /* @__PURE__ */ new Map();
|
|
19970
20096
|
this.notificationListeners = /* @__PURE__ */ new Set();
|
|
19971
20097
|
this.fatalListeners = /* @__PURE__ */ new Set();
|
|
19972
20098
|
this.accountLoginCompletions = /* @__PURE__ */ new Map();
|
|
@@ -20105,6 +20231,9 @@ child.once('close', async () => {
|
|
|
20105
20231
|
if (typeof id2 === "number" && Number.isSafeInteger(id2) && !("method" in message)) {
|
|
20106
20232
|
const pending = this.pending.get(id2);
|
|
20107
20233
|
if (!pending) {
|
|
20234
|
+
const retiredMethod = this.retiredResponseIds.get(id2);
|
|
20235
|
+
this.retiredResponseIds.delete(id2);
|
|
20236
|
+
if (retiredMethod && LATE_RESPONSE_SAFE_METHODS.has(retiredMethod)) return;
|
|
20108
20237
|
this.failTransport("unexpected_response_id");
|
|
20109
20238
|
return;
|
|
20110
20239
|
}
|
|
@@ -20169,6 +20298,14 @@ child.once('close', async () => {
|
|
|
20169
20298
|
this.pending.clear();
|
|
20170
20299
|
for (const listener of this.fatalListeners) listener(this.fatalError);
|
|
20171
20300
|
}
|
|
20301
|
+
retireResponseId(id2, method) {
|
|
20302
|
+
this.retiredResponseIds.set(id2, method);
|
|
20303
|
+
while (this.retiredResponseIds.size > MAX_RETIRED_RESPONSE_IDS) {
|
|
20304
|
+
const oldest = this.retiredResponseIds.keys().next().value;
|
|
20305
|
+
if (typeof oldest !== "number") break;
|
|
20306
|
+
this.retiredResponseIds.delete(oldest);
|
|
20307
|
+
}
|
|
20308
|
+
}
|
|
20172
20309
|
write(message) {
|
|
20173
20310
|
if (this.closed || this.fatalError || this.process.exitCode !== null) {
|
|
20174
20311
|
throw this.fatalError ?? new CodexAppServerError({
|
|
@@ -20207,6 +20344,7 @@ child.once('close', async () => {
|
|
|
20207
20344
|
const pending = { resolve: resolve6, reject, timer: null, abortCleanup: null };
|
|
20208
20345
|
pending.timer = setTimeout(() => {
|
|
20209
20346
|
this.pending.delete(id2);
|
|
20347
|
+
this.retireResponseId(id2, method);
|
|
20210
20348
|
pending.abortCleanup?.();
|
|
20211
20349
|
reject(new CodexAppServerError({
|
|
20212
20350
|
message: "Codex app-server request timed out.",
|
|
@@ -20218,6 +20356,7 @@ child.once('close', async () => {
|
|
|
20218
20356
|
if (options.signal) {
|
|
20219
20357
|
const onAbort = () => {
|
|
20220
20358
|
this.pending.delete(id2);
|
|
20359
|
+
this.retireResponseId(id2, method);
|
|
20221
20360
|
if (pending.timer) clearTimeout(pending.timer);
|
|
20222
20361
|
pending.abortCleanup?.();
|
|
20223
20362
|
reject(new CodexAppServerError({
|
|
@@ -22110,9 +22249,21 @@ var init_codex_adapter = __esm({
|
|
|
22110
22249
|
dispatchOutcome: checkpoint.dispatchOutcome
|
|
22111
22250
|
});
|
|
22112
22251
|
}
|
|
22113
|
-
|
|
22114
|
-
if (
|
|
22115
|
-
|
|
22252
|
+
let sharedReceiptStillRequired = true;
|
|
22253
|
+
if (recoveryHooks.loadAll) {
|
|
22254
|
+
try {
|
|
22255
|
+
const checkpoints = await recoveryHooks.loadAll();
|
|
22256
|
+
const receiptPath = resolve3(checkpoint.processReceiptPath);
|
|
22257
|
+
sharedReceiptStillRequired = Object.values(checkpoints).some((candidate) => candidate.attemptId !== attemptId && !candidate.cleanupConfirmed && candidate.processReceiptPath !== null && resolve3(candidate.processReceiptPath) === receiptPath);
|
|
22258
|
+
} catch {
|
|
22259
|
+
sharedReceiptStillRequired = true;
|
|
22260
|
+
}
|
|
22261
|
+
}
|
|
22262
|
+
if (!sharedReceiptStillRequired) {
|
|
22263
|
+
const receipt = await readCodexGuardianReceipt(checkpoint.processReceiptPath);
|
|
22264
|
+
if (checkpoint.processState === "terminated" || receipt === null || receipt.state === "terminated") {
|
|
22265
|
+
await rm3(checkpoint.processReceiptPath, { force: true });
|
|
22266
|
+
}
|
|
22116
22267
|
}
|
|
22117
22268
|
}
|
|
22118
22269
|
await recoveryHooks.clear(attemptId);
|
|
@@ -31510,9 +31661,9 @@ ${result2.stderr}`)) {
|
|
|
31510
31661
|
const runtime = await this.waitForManifestApplied(restoredManifest);
|
|
31511
31662
|
return await this.status(runtime);
|
|
31512
31663
|
}
|
|
31513
|
-
async waitForManifestApplied(manifest, targetInstanceName) {
|
|
31664
|
+
async waitForManifestApplied(manifest, targetInstanceName, maxAttempts = this.reconcileWaitAttempts) {
|
|
31514
31665
|
let consecutiveReadyObservations = 0;
|
|
31515
|
-
for (let attempt = 0; attempt <
|
|
31666
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
31516
31667
|
let runtime = null;
|
|
31517
31668
|
try {
|
|
31518
31669
|
runtime = await readRuntimeAcrossAtomicReplacement(this.runtimePath());
|
|
@@ -31648,7 +31799,12 @@ ${cleanup.stderr}`)) {
|
|
|
31648
31799
|
previous,
|
|
31649
31800
|
targetInstanceName && previous.workers.some(
|
|
31650
31801
|
(worker) => worker.instance_name === targetInstanceName
|
|
31651
|
-
) ? targetInstanceName : void 0
|
|
31802
|
+
) ? targetInstanceName : void 0,
|
|
31803
|
+
// A failed generation may still be draining while the manager
|
|
31804
|
+
// restores the previous manifest. Never give rollback less than
|
|
31805
|
+
// a bounded 100-observation confirmation window, even when a
|
|
31806
|
+
// caller intentionally shortens forward-readiness checks.
|
|
31807
|
+
Math.max(this.reconcileWaitAttempts, 100)
|
|
31652
31808
|
);
|
|
31653
31809
|
} catch (rollbackError) {
|
|
31654
31810
|
throw new Error(
|
|
@@ -32288,7 +32444,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
32288
32444
|
return { exitCode: 0, stdout: INFERENCE_HOST_HELP, stderr: "" };
|
|
32289
32445
|
}
|
|
32290
32446
|
const parsed = parseInferenceHostArgs(argv2, env);
|
|
32291
|
-
const config2 = await resolveInferenceHostCommandConfig(parsed, env);
|
|
32447
|
+
const config2 = await resolveInferenceHostCommandConfig(parsed, env, dependencies);
|
|
32292
32448
|
if (parsed.command === "login") {
|
|
32293
32449
|
return await login(config2, parsed, env, dependencies, warnings);
|
|
32294
32450
|
}
|
|
@@ -32355,7 +32511,7 @@ async function runInferenceHostCli(argv2, env = process.env, dependencies = {})
|
|
|
32355
32511
|
};
|
|
32356
32512
|
}
|
|
32357
32513
|
}
|
|
32358
|
-
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, parseHostConcurrency, parseInferenceHostArgs, defaultOpenBrowser, registerInferenceHostServiceControlInput, defaultRegisterLifecycleSignalHandlers, lifecycleCancellation, configuredCredentialStore, accountKeyForState, assertCredentialMatchesState2, revocationCheckpointForCredential, assertRevocationCheckpointMatchesLocalIdentity, fileExistsPrivately, inspectCodexAuthentication, clearLocalRuntimeArtifacts, assertDurableServiceUninstalled, assertLocalRuntimeArtifactsMayBeDiscarded, defaultRunForeground, login, codexLogin, codexLogout, localStatus, doctor, cleanupLogin, runHost, defaultReadStdin, parseAgentStdin, agentOperationId, agentSession, agentConnect, agentRun, agentNext, agentComplete, agentFail, withAgentCommandLock, serviceCommand, hasExplicitCredentialStoreConfiguration, commandUsesInstalledServiceCredentials, resolveInferenceHostCommandConfig;
|
|
32514
|
+
var INFERENCE_HOST_CLI_VERSION, runtimeReceiptPath, codexRecoveryPath, codexGuardianReceiptRoot, revocationCheckpointPath, foregroundHostLockPath, credentialLifecycleLockPath, AGENT_HEARTBEAT_INTERVAL_MS, AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS, retryableAgentHeartbeatError, assertRevocationCheckpoint, readRevocationCheckpoint, writeRevocationCheckpoint, clearRevocationCheckpoint, render, INFERENCE_HOST_HELP, parseHostConcurrency, parseInferenceHostArgs, defaultOpenBrowser, registerInferenceHostServiceControlInput, defaultRegisterLifecycleSignalHandlers, lifecycleCancellation, configuredCredentialStore, restoreInferenceHostCredentialContext, recoverInferenceHostCredentialContextTransition, accountKeyForState, assertCredentialMatchesState2, revocationCheckpointForCredential, assertRevocationCheckpointMatchesLocalIdentity, fileExistsPrivately, inspectCodexAuthentication, clearLocalRuntimeArtifacts, assertDurableServiceUninstalled, assertLocalRuntimeArtifactsMayBeDiscarded, defaultRunForeground, login, codexLogin, codexLogout, localStatus, doctor, cleanupLogin, runHost, defaultReadStdin, parseAgentStdin, agentOperationId, agentSession, agentConnect, agentRun, agentNext, agentComplete, agentFail, withAgentCommandLock, serviceCommand, hasExplicitCredentialStoreConfiguration, credentialEnvironmentForIdentity, commandRequiresRetainedCredentialStore, commandUsesInstalledServiceCredentials, resolveInferenceHostCommandConfig;
|
|
32359
32515
|
var init_cli = __esm({
|
|
32360
32516
|
"lib/inference-host/cli.ts"() {
|
|
32361
32517
|
"use strict";
|
|
@@ -32379,6 +32535,7 @@ var init_cli = __esm({
|
|
|
32379
32535
|
codexGuardianReceiptRoot = (config2) => `${config2.statePath}.codex-processes`;
|
|
32380
32536
|
revocationCheckpointPath = (config2) => `${config2.statePath}.revoke.json`;
|
|
32381
32537
|
foregroundHostLockPath = (config2) => `${config2.processLockPath}.foreground`;
|
|
32538
|
+
credentialLifecycleLockPath = (config2) => `${inferenceHostCredentialContextPath(config2)}.lock`;
|
|
32382
32539
|
AGENT_HEARTBEAT_INTERVAL_MS = 3e3;
|
|
32383
32540
|
AGENT_HEARTBEAT_MAX_RETRY_DELAY_MS = 9e3;
|
|
32384
32541
|
retryableAgentHeartbeatError = (error48) => {
|
|
@@ -32647,6 +32804,36 @@ Durable service:
|
|
|
32647
32804
|
};
|
|
32648
32805
|
};
|
|
32649
32806
|
configuredCredentialStore = (config2, dependencies, warn) => dependencies.createCredentialStore?.(config2, warn) ?? createConfiguredInferenceCredentialStore(config2, { warn });
|
|
32807
|
+
restoreInferenceHostCredentialContext = async (config2, previous) => {
|
|
32808
|
+
if (!previous) {
|
|
32809
|
+
await clearInferenceHostCredentialContext(config2);
|
|
32810
|
+
return;
|
|
32811
|
+
}
|
|
32812
|
+
await writeInferenceHostCredentialContext({
|
|
32813
|
+
...config2,
|
|
32814
|
+
credentialStoreMode: previous.credential_store_mode,
|
|
32815
|
+
credentialFilePath: previous.credential_file_path
|
|
32816
|
+
});
|
|
32817
|
+
};
|
|
32818
|
+
recoverInferenceHostCredentialContextTransition = async (config2, selectedEnv, dependencies) => {
|
|
32819
|
+
const transition = await readInferenceHostCredentialContextTransition(config2);
|
|
32820
|
+
if (!transition) return;
|
|
32821
|
+
const localState = await readInferenceHostLocalState(config2.statePath);
|
|
32822
|
+
const candidateRecovery = transition.candidate ? await configuredCredentialStore(
|
|
32823
|
+
resolveInferenceHostConfig({
|
|
32824
|
+
...selectedEnv,
|
|
32825
|
+
VTX_INFERENCE_HOST_CREDENTIAL_STORE: transition.candidate.credential_store_mode,
|
|
32826
|
+
VTX_INFERENCE_HOST_CREDENTIAL_FILE: transition.candidate.credential_file_path ?? void 0
|
|
32827
|
+
}),
|
|
32828
|
+
dependencies,
|
|
32829
|
+
() => void 0
|
|
32830
|
+
).readRecovery?.() ?? null : null;
|
|
32831
|
+
await restoreInferenceHostCredentialContext(
|
|
32832
|
+
config2,
|
|
32833
|
+
transition.operation === "selection" ? localState || candidateRecovery ? transition.candidate : transition.previous : transition.phase === "committed" && !localState ? null : transition.previous
|
|
32834
|
+
);
|
|
32835
|
+
await clearInferenceHostCredentialContextTransition(config2);
|
|
32836
|
+
};
|
|
32650
32837
|
accountKeyForState = (state) => inferenceCredentialAccountKey({
|
|
32651
32838
|
issuer: state.issuer,
|
|
32652
32839
|
clientId: state.client_id,
|
|
@@ -32780,8 +32967,15 @@ Durable service:
|
|
|
32780
32967
|
}).run();
|
|
32781
32968
|
};
|
|
32782
32969
|
login = async (config2, parsed, env, dependencies, warnings) => {
|
|
32783
|
-
const
|
|
32970
|
+
const credentialLock = await acquireInferenceHostProcessLock(
|
|
32971
|
+
credentialLifecycleLockPath(config2)
|
|
32972
|
+
);
|
|
32973
|
+
let lock2 = null;
|
|
32974
|
+
let previousCredentialContext;
|
|
32975
|
+
let selectedStore = null;
|
|
32976
|
+
let localStateCommitted = false;
|
|
32784
32977
|
try {
|
|
32978
|
+
lock2 = await acquireInferenceHostProcessLock(config2.processLockPath);
|
|
32785
32979
|
if (await readRevocationCheckpoint(config2)) {
|
|
32786
32980
|
throw new Error("Inference host revocation recovery must finish before login.");
|
|
32787
32981
|
}
|
|
@@ -32791,18 +32985,41 @@ Durable service:
|
|
|
32791
32985
|
const store = configuredCredentialStore(config2, dependencies, (message) => {
|
|
32792
32986
|
warnings.push(message);
|
|
32793
32987
|
});
|
|
32988
|
+
selectedStore = store;
|
|
32989
|
+
if (!store.writeRecovery || !store.removeRecovery || !store.readRecovery) {
|
|
32990
|
+
throw new Error("Inference host credential store does not support durable login recovery.");
|
|
32991
|
+
}
|
|
32794
32992
|
if (await store.readRecovery?.()) {
|
|
32795
32993
|
throw new Error("Inference host credential recovery is required before login.");
|
|
32796
32994
|
}
|
|
32995
|
+
previousCredentialContext = await readInferenceHostCredentialContext(config2);
|
|
32996
|
+
await writeInferenceHostCredentialContextTransition(config2, previousCredentialContext);
|
|
32997
|
+
await writeInferenceHostCredentialContext(config2);
|
|
32797
32998
|
const keyPair = generateExternalInferenceEnvelopeKeyPair();
|
|
32798
32999
|
const hostId = randomUUID2();
|
|
32799
33000
|
const beginLogin = dependencies.beginLogin ?? beginInferenceOAuthLogin;
|
|
33001
|
+
const loginStore = {
|
|
33002
|
+
kind: store.kind,
|
|
33003
|
+
read: store.read.bind(store),
|
|
33004
|
+
remove: store.remove.bind(store),
|
|
33005
|
+
readRecovery: store.readRecovery.bind(store),
|
|
33006
|
+
writeRecovery: store.writeRecovery.bind(store),
|
|
33007
|
+
removeRecovery: store.removeRecovery.bind(store),
|
|
33008
|
+
write: async (accountKey, credential, options) => {
|
|
33009
|
+
await store.writeRecovery(accountKey, credential);
|
|
33010
|
+
try {
|
|
33011
|
+
await store.write(accountKey, credential, options);
|
|
33012
|
+
} catch (error48) {
|
|
33013
|
+
throw error48;
|
|
33014
|
+
}
|
|
33015
|
+
}
|
|
33016
|
+
};
|
|
32800
33017
|
const pending = await beginLogin({
|
|
32801
33018
|
apiUrl: config2.apiUrl,
|
|
32802
33019
|
hostId,
|
|
32803
33020
|
x25519PrivateKey: keyPair.private_key,
|
|
32804
33021
|
keyGeneration: 1,
|
|
32805
|
-
store
|
|
33022
|
+
store: loginStore
|
|
32806
33023
|
});
|
|
32807
33024
|
const emitStdout = dependencies.emitStdout ?? ((text) => {
|
|
32808
33025
|
process.stdout.write(text);
|
|
@@ -32846,6 +33063,7 @@ Waiting for approval...
|
|
|
32846
33063
|
store
|
|
32847
33064
|
});
|
|
32848
33065
|
remoteCleanupConfirmed = true;
|
|
33066
|
+
await store.removeRecovery?.();
|
|
32849
33067
|
} catch {
|
|
32850
33068
|
if (!store.writeRecovery) {
|
|
32851
33069
|
throw new Error(
|
|
@@ -32864,6 +33082,9 @@ Waiting for approval...
|
|
|
32864
33082
|
}
|
|
32865
33083
|
throw stateError;
|
|
32866
33084
|
}
|
|
33085
|
+
localStateCommitted = true;
|
|
33086
|
+
await store.removeRecovery?.();
|
|
33087
|
+
await clearInferenceHostCredentialContextTransition(config2);
|
|
32867
33088
|
return {
|
|
32868
33089
|
exitCode: 0,
|
|
32869
33090
|
stdout: render({
|
|
@@ -32876,8 +33097,18 @@ Waiting for approval...
|
|
|
32876
33097
|
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
32877
33098
|
` : ""
|
|
32878
33099
|
};
|
|
33100
|
+
} catch (error48) {
|
|
33101
|
+
const recovery = await selectedStore?.readRecovery?.() ?? null;
|
|
33102
|
+
if (!recovery && !localStateCommitted && previousCredentialContext !== void 0) {
|
|
33103
|
+
await restoreInferenceHostCredentialContext(config2, previousCredentialContext);
|
|
33104
|
+
await clearInferenceHostCredentialContextTransition(config2);
|
|
33105
|
+
} else if (recovery) {
|
|
33106
|
+
await clearInferenceHostCredentialContextTransition(config2);
|
|
33107
|
+
}
|
|
33108
|
+
throw error48;
|
|
32879
33109
|
} finally {
|
|
32880
|
-
await lock2
|
|
33110
|
+
await lock2?.release();
|
|
33111
|
+
await credentialLock.release();
|
|
32881
33112
|
}
|
|
32882
33113
|
};
|
|
32883
33114
|
codexLogin = async (config2, parsed, env, dependencies) => {
|
|
@@ -33111,10 +33342,14 @@ Waiting for approval...
|
|
|
33111
33342
|
};
|
|
33112
33343
|
};
|
|
33113
33344
|
cleanupLogin = async (config2, parsed, dependencies, warnings, revoke) => {
|
|
33114
|
-
await
|
|
33115
|
-
|
|
33345
|
+
const credentialLock = await acquireInferenceHostProcessLock(
|
|
33346
|
+
credentialLifecycleLockPath(config2)
|
|
33347
|
+
);
|
|
33348
|
+
let lock2 = null;
|
|
33116
33349
|
let keeperLock = null;
|
|
33117
33350
|
try {
|
|
33351
|
+
await assertDurableServiceUninstalled(config2);
|
|
33352
|
+
lock2 = await acquireInferenceHostProcessLock(config2.processLockPath);
|
|
33118
33353
|
try {
|
|
33119
33354
|
keeperLock = await acquireInferenceHostProcessLock(foregroundHostLockPath(config2));
|
|
33120
33355
|
} catch (error48) {
|
|
@@ -33141,8 +33376,35 @@ Waiting for approval...
|
|
|
33141
33376
|
state,
|
|
33142
33377
|
oauthRecovery
|
|
33143
33378
|
);
|
|
33379
|
+
}
|
|
33380
|
+
let cleanupTransitionStaged = false;
|
|
33381
|
+
const stageCleanupTransition = async () => {
|
|
33382
|
+
if (cleanupTransitionStaged) return;
|
|
33383
|
+
const selectedContext = await readInferenceHostCredentialContext(config2);
|
|
33384
|
+
await writeInferenceHostCredentialContextTransition(
|
|
33385
|
+
config2,
|
|
33386
|
+
selectedContext,
|
|
33387
|
+
null,
|
|
33388
|
+
"cleanup",
|
|
33389
|
+
"prepared"
|
|
33390
|
+
);
|
|
33391
|
+
cleanupTransitionStaged = true;
|
|
33392
|
+
};
|
|
33393
|
+
const commitCleanupTransition = async () => {
|
|
33394
|
+
await writeInferenceHostCredentialContextTransition(
|
|
33395
|
+
config2,
|
|
33396
|
+
await readInferenceHostCredentialContext(config2),
|
|
33397
|
+
null,
|
|
33398
|
+
"cleanup",
|
|
33399
|
+
"committed"
|
|
33400
|
+
);
|
|
33401
|
+
};
|
|
33402
|
+
if (revocationCheckpoint) {
|
|
33403
|
+
await stageCleanupTransition();
|
|
33404
|
+
await commitCleanupTransition();
|
|
33144
33405
|
} else if (oauthRecovery) {
|
|
33145
33406
|
if (revoke) {
|
|
33407
|
+
await stageCleanupTransition();
|
|
33146
33408
|
const metadata = await (dependencies.discoverOAuth ?? discoverInferenceOAuth)(config2.apiUrl);
|
|
33147
33409
|
await (dependencies.revokeCredential ?? revokeInferenceCredential)({
|
|
33148
33410
|
metadata,
|
|
@@ -33157,9 +33419,12 @@ Waiting for approval...
|
|
|
33157
33419
|
config2.credentialStoreIdentity
|
|
33158
33420
|
);
|
|
33159
33421
|
await writeRevocationCheckpoint(config2, revocationCheckpoint);
|
|
33422
|
+
await commitCleanupTransition();
|
|
33160
33423
|
} else {
|
|
33424
|
+
await stageCleanupTransition();
|
|
33161
33425
|
await store.remove(oauthRecovery.accountKey);
|
|
33162
33426
|
await store.removeRecovery?.();
|
|
33427
|
+
await commitCleanupTransition();
|
|
33163
33428
|
}
|
|
33164
33429
|
} else if (state) {
|
|
33165
33430
|
const accountKey = accountKeyForState(state);
|
|
@@ -33169,6 +33434,7 @@ Waiting for approval...
|
|
|
33169
33434
|
if (!credential) {
|
|
33170
33435
|
throw new Error("Inference host credential is unavailable; remote revoke cannot be confirmed.");
|
|
33171
33436
|
}
|
|
33437
|
+
await stageCleanupTransition();
|
|
33172
33438
|
const metadata = await (dependencies.discoverOAuth ?? discoverInferenceOAuth)(config2.apiUrl);
|
|
33173
33439
|
await (dependencies.revokeCredential ?? revokeInferenceCredential)({
|
|
33174
33440
|
metadata,
|
|
@@ -33183,11 +33449,16 @@ Waiting for approval...
|
|
|
33183
33449
|
config2.credentialStoreIdentity
|
|
33184
33450
|
);
|
|
33185
33451
|
await writeRevocationCheckpoint(config2, revocationCheckpoint);
|
|
33452
|
+
await commitCleanupTransition();
|
|
33186
33453
|
} else {
|
|
33454
|
+
await stageCleanupTransition();
|
|
33187
33455
|
await store.remove(accountKey);
|
|
33456
|
+
await commitCleanupTransition();
|
|
33188
33457
|
}
|
|
33189
33458
|
} else if (!revoke && store.kind === "file") {
|
|
33459
|
+
await stageCleanupTransition();
|
|
33190
33460
|
await store.remove("");
|
|
33461
|
+
await commitCleanupTransition();
|
|
33191
33462
|
} else if (revoke) {
|
|
33192
33463
|
throw new Error("Inference host is not logged in; there is no exact grant to revoke.");
|
|
33193
33464
|
}
|
|
@@ -33207,14 +33478,18 @@ Waiting for approval...
|
|
|
33207
33478
|
{ cause: error48 }
|
|
33208
33479
|
);
|
|
33209
33480
|
}
|
|
33210
|
-
await clearLocalRuntimeArtifacts(config2);
|
|
33211
33481
|
await store.remove(revocationCheckpoint.account_key);
|
|
33212
33482
|
if (revocationCheckpoint.remove_credential_recovery) {
|
|
33213
33483
|
await store.removeRecovery?.();
|
|
33214
33484
|
}
|
|
33485
|
+
await (dependencies.clearLocalRuntimeArtifacts ?? clearLocalRuntimeArtifacts)(config2);
|
|
33486
|
+
await clearInferenceHostCredentialContext(config2);
|
|
33215
33487
|
await clearRevocationCheckpoint(config2);
|
|
33488
|
+
await clearInferenceHostCredentialContextTransition(config2);
|
|
33216
33489
|
} else {
|
|
33217
|
-
await clearLocalRuntimeArtifacts(config2);
|
|
33490
|
+
await (dependencies.clearLocalRuntimeArtifacts ?? clearLocalRuntimeArtifacts)(config2);
|
|
33491
|
+
await clearInferenceHostCredentialContext(config2);
|
|
33492
|
+
await clearInferenceHostCredentialContextTransition(config2);
|
|
33218
33493
|
}
|
|
33219
33494
|
return {
|
|
33220
33495
|
exitCode: 0,
|
|
@@ -33228,7 +33503,8 @@ Waiting for approval...
|
|
|
33228
33503
|
};
|
|
33229
33504
|
} finally {
|
|
33230
33505
|
await keeperLock?.release();
|
|
33231
|
-
await lock2
|
|
33506
|
+
await lock2?.release();
|
|
33507
|
+
await credentialLock.release();
|
|
33232
33508
|
}
|
|
33233
33509
|
};
|
|
33234
33510
|
runHost = async (config2, parsed, env, dependencies, warnings) => {
|
|
@@ -33775,44 +34051,52 @@ Waiting for approval...
|
|
|
33775
34051
|
dependencies.serviceDependencies
|
|
33776
34052
|
) ?? new InferenceHostServiceManager(config2, dependencies.serviceDependencies);
|
|
33777
34053
|
if (action === "install") {
|
|
33778
|
-
const
|
|
33779
|
-
|
|
33780
|
-
|
|
33781
|
-
|
|
33782
|
-
|
|
33783
|
-
|
|
33784
|
-
|
|
33785
|
-
|
|
33786
|
-
|
|
33787
|
-
|
|
33788
|
-
|
|
33789
|
-
|
|
33790
|
-
|
|
33791
|
-
|
|
33792
|
-
|
|
33793
|
-
|
|
33794
|
-
|
|
33795
|
-
|
|
33796
|
-
|
|
33797
|
-
|
|
33798
|
-
|
|
33799
|
-
|
|
33800
|
-
|
|
33801
|
-
|
|
33802
|
-
|
|
33803
|
-
|
|
33804
|
-
|
|
33805
|
-
|
|
33806
|
-
|
|
33807
|
-
|
|
33808
|
-
|
|
33809
|
-
|
|
33810
|
-
|
|
33811
|
-
|
|
33812
|
-
|
|
33813
|
-
|
|
34054
|
+
const credentialLock = await acquireInferenceHostProcessLock(
|
|
34055
|
+
credentialLifecycleLockPath(config2)
|
|
34056
|
+
);
|
|
34057
|
+
try {
|
|
34058
|
+
const adapter = parsed.adapter || "codex";
|
|
34059
|
+
if (adapter !== "codex") {
|
|
34060
|
+
throw new Error(
|
|
34061
|
+
`Adapter ${adapter} does not have a supported durable service integration. Use foreground agent-run instead.`
|
|
34062
|
+
);
|
|
34063
|
+
}
|
|
34064
|
+
const state = await readInferenceHostLocalState(config2.statePath);
|
|
34065
|
+
if (!state) throw new Error("Run vtx inference-host login before installing the service.");
|
|
34066
|
+
const store = configuredCredentialStore(config2, dependencies, (message) => warnings.push(message));
|
|
34067
|
+
const credential = await store.read(accountKeyForState(state));
|
|
34068
|
+
if (!credential) throw new Error("Inference-host credential is missing. Run login again.");
|
|
34069
|
+
assertCredentialMatchesState2(state, credential);
|
|
34070
|
+
if (parsed.modelId || parsed.modelLabel || parsed.reasoningEffort) {
|
|
34071
|
+
throw new Error("Automated Codex service does not accept agent model or effort options.");
|
|
34072
|
+
}
|
|
34073
|
+
const auth = await inspectCodexAuthentication(config2);
|
|
34074
|
+
if (!auth.present || !auth.private) {
|
|
34075
|
+
throw new Error("Run vtx inference-host codex-login before installing the automated Codex service.");
|
|
34076
|
+
}
|
|
34077
|
+
const binary = await (dependencies.resolveBinary ?? resolvePinnedCodexBinary)(env);
|
|
34078
|
+
const preflight = await (dependencies.preflightCodex ?? preflightCodexSubscription)({
|
|
34079
|
+
binary,
|
|
34080
|
+
codexHome: config2.codexHomePath,
|
|
34081
|
+
deadlineAtMs: Date.now() + 3e4
|
|
34082
|
+
});
|
|
34083
|
+
const status = await manager.install({
|
|
34084
|
+
adapter: "codex",
|
|
34085
|
+
displayName: parsed.displayName,
|
|
34086
|
+
maxConcurrency: parsed.maxConcurrency,
|
|
34087
|
+
authenticatedAccountEmail: preflight?.authenticated_account_email ?? null,
|
|
34088
|
+
authenticatedAccountPlan: preflight?.authenticated_account_plan ?? null
|
|
34089
|
+
});
|
|
34090
|
+
await writeInferenceHostCredentialContext(config2);
|
|
34091
|
+
return {
|
|
34092
|
+
exitCode: 0,
|
|
34093
|
+
stdout: render({ status: "service_installed", ...status }, parsed.json),
|
|
34094
|
+
stderr: warnings.length > 0 ? `${warnings.join("\n")}
|
|
33814
34095
|
` : ""
|
|
33815
|
-
|
|
34096
|
+
};
|
|
34097
|
+
} finally {
|
|
34098
|
+
await credentialLock.release();
|
|
34099
|
+
}
|
|
33816
34100
|
}
|
|
33817
34101
|
if (parsed.adapter || parsed.modelId || parsed.modelLabel || parsed.reasoningEffort) {
|
|
33818
34102
|
throw new Error("Service adapter and model options are accepted only by service install.");
|
|
@@ -33839,36 +34123,98 @@ Waiting for approval...
|
|
|
33839
34123
|
return { exitCode: lifecycleMatches ? 0 : 1, stdout: render(status, parsed.json), stderr: "" };
|
|
33840
34124
|
}
|
|
33841
34125
|
if (action === "uninstall") {
|
|
33842
|
-
const
|
|
33843
|
-
|
|
34126
|
+
const credentialLock = await acquireInferenceHostProcessLock(
|
|
34127
|
+
credentialLifecycleLockPath(config2)
|
|
34128
|
+
);
|
|
34129
|
+
try {
|
|
34130
|
+
if (parsed.instanceExplicit) {
|
|
34131
|
+
const retained = await readInferenceHostCredentialContext(config2);
|
|
34132
|
+
const retainedIdentity = retained ? resolveInferenceHostConfig({
|
|
34133
|
+
...env,
|
|
34134
|
+
VTX_INFERENCE_HOST_INSTANCE: config2.instanceName,
|
|
34135
|
+
VTX_INFERENCE_HOST_CREDENTIAL_STORE: retained.credential_store_mode,
|
|
34136
|
+
VTX_INFERENCE_HOST_CREDENTIAL_FILE: retained.credential_file_path ?? void 0
|
|
34137
|
+
}).credentialStoreIdentity : null;
|
|
34138
|
+
if (retainedIdentity !== config2.credentialStoreIdentity) {
|
|
34139
|
+
await writeInferenceHostCredentialContext(config2);
|
|
34140
|
+
}
|
|
34141
|
+
}
|
|
34142
|
+
const status = parsed.instanceExplicit ? await manager.uninstallInstance(config2.instanceName) : await manager.uninstall();
|
|
34143
|
+
return { exitCode: 0, stdout: render({ status: "service_uninstalled", ...status }, parsed.json), stderr: "" };
|
|
34144
|
+
} finally {
|
|
34145
|
+
await credentialLock.release();
|
|
34146
|
+
}
|
|
33844
34147
|
}
|
|
33845
34148
|
throw new Error("Usage: vtx inference-host service <install|start|stop|status|logs|uninstall>.");
|
|
33846
34149
|
};
|
|
33847
34150
|
hasExplicitCredentialStoreConfiguration = (env) => Boolean(
|
|
33848
34151
|
String(env.VTX_INFERENCE_HOST_CREDENTIAL_STORE || "").trim() || String(env.VTX_INFERENCE_HOST_CREDENTIAL_FILE || "").trim()
|
|
33849
34152
|
);
|
|
33850
|
-
|
|
33851
|
-
|
|
34153
|
+
credentialEnvironmentForIdentity = (identity) => {
|
|
34154
|
+
if (identity.startsWith("file:")) {
|
|
34155
|
+
const path = identity.slice("file:".length);
|
|
34156
|
+
if (!path) throw new Error("Inference host credential store identity is invalid.");
|
|
34157
|
+
return {
|
|
34158
|
+
VTX_INFERENCE_HOST_CREDENTIAL_STORE: "file",
|
|
34159
|
+
VTX_INFERENCE_HOST_CREDENTIAL_FILE: path
|
|
34160
|
+
};
|
|
34161
|
+
}
|
|
34162
|
+
if (identity.startsWith("os:")) {
|
|
34163
|
+
return {
|
|
34164
|
+
VTX_INFERENCE_HOST_CREDENTIAL_STORE: "os",
|
|
34165
|
+
VTX_INFERENCE_HOST_CREDENTIAL_FILE: void 0
|
|
34166
|
+
};
|
|
34167
|
+
}
|
|
34168
|
+
throw new Error("Inference host credential store identity is invalid.");
|
|
34169
|
+
};
|
|
34170
|
+
commandRequiresRetainedCredentialStore = (parsed) => parsed.command === "logout" || parsed.command === "revoke" || parsed.command === "service" && parsed.instanceExplicit && (parsed.serviceAction === "install" || parsed.serviceAction === "uninstall");
|
|
34171
|
+
commandUsesInstalledServiceCredentials = (parsed) => parsed.command === "login" || parsed.command === "logout" || parsed.command === "revoke" || parsed.command === "status" || parsed.command === "doctor" || parsed.command === "service" && parsed.serviceAction === "install" || parsed.command === "service" && parsed.serviceAction === "uninstall" && parsed.instanceExplicit;
|
|
34172
|
+
resolveInferenceHostCommandConfig = async (parsed, env, dependencies) => {
|
|
33852
34173
|
const selectedEnv = {
|
|
33853
34174
|
...env,
|
|
33854
34175
|
VTX_INFERENCE_HOST_INSTANCE: parsed.instanceName
|
|
33855
34176
|
};
|
|
33856
34177
|
const baseConfig = resolveInferenceHostConfig(selectedEnv);
|
|
33857
|
-
if (!commandUsesInstalledServiceCredentials(parsed)
|
|
33858
|
-
|
|
34178
|
+
if (!commandUsesInstalledServiceCredentials(parsed)) return baseConfig;
|
|
34179
|
+
if (await readInferenceHostCredentialContextTransition(baseConfig)) {
|
|
34180
|
+
const credentialLock = await acquireInferenceHostProcessLock(
|
|
34181
|
+
credentialLifecycleLockPath(baseConfig)
|
|
34182
|
+
);
|
|
34183
|
+
try {
|
|
34184
|
+
await recoverInferenceHostCredentialContextTransition(baseConfig, selectedEnv, dependencies);
|
|
34185
|
+
} finally {
|
|
34186
|
+
await credentialLock.release();
|
|
34187
|
+
}
|
|
33859
34188
|
}
|
|
33860
34189
|
const manifestPath = `${baseConfig.supervisorStatePath}.service.json`;
|
|
33861
34190
|
const manifest = await readInferenceHostServiceManifest(manifestPath);
|
|
33862
|
-
|
|
34191
|
+
const installedEnvironment = manifest?.workers.find(
|
|
34192
|
+
(worker) => worker.instance_name === baseConfig.instanceName
|
|
34193
|
+
)?.runtime_environment;
|
|
34194
|
+
const persistedContext = installedEnvironment ? null : await readInferenceHostCredentialContext(baseConfig);
|
|
34195
|
+
const revocationCheckpoint = !installedEnvironment && !persistedContext && parsed.command === "revoke" ? await readRevocationCheckpoint(baseConfig) : null;
|
|
34196
|
+
const retainedEnvironment = installedEnvironment ?? (persistedContext ? {
|
|
34197
|
+
VTX_INFERENCE_HOST_CREDENTIAL_STORE: persistedContext.credential_store_mode,
|
|
34198
|
+
VTX_INFERENCE_HOST_CREDENTIAL_FILE: persistedContext.credential_file_path ?? void 0
|
|
34199
|
+
} : revocationCheckpoint ? credentialEnvironmentForIdentity(revocationCheckpoint.credential_store_identity) : null);
|
|
34200
|
+
if (!retainedEnvironment) return baseConfig;
|
|
33863
34201
|
const installedConfig = resolveInferenceHostConfig({
|
|
33864
34202
|
...selectedEnv,
|
|
33865
|
-
...
|
|
34203
|
+
...retainedEnvironment
|
|
33866
34204
|
});
|
|
33867
34205
|
if (resolve5(installedConfig.statePath) !== resolve5(baseConfig.statePath)) {
|
|
33868
34206
|
throw new Error(
|
|
33869
34207
|
"Installed inference-host service manifest does not match the requested local state path."
|
|
33870
34208
|
);
|
|
33871
34209
|
}
|
|
34210
|
+
if (hasExplicitCredentialStoreConfiguration(env)) {
|
|
34211
|
+
if (commandRequiresRetainedCredentialStore(parsed) && baseConfig.credentialStoreIdentity !== installedConfig.credentialStoreIdentity) {
|
|
34212
|
+
throw new Error(
|
|
34213
|
+
"Explicit inference credential store does not match the retained store for this host. Log out or revoke with the retained store before switching."
|
|
34214
|
+
);
|
|
34215
|
+
}
|
|
34216
|
+
return baseConfig;
|
|
34217
|
+
}
|
|
33872
34218
|
return installedConfig;
|
|
33873
34219
|
};
|
|
33874
34220
|
}
|