@vtxmacro/cli 2026.8.25 → 2026.8.26

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.
Files changed (3) hide show
  1. package/README.md +7 -6
  2. package/bin/vtx.js +79 -51
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -51,12 +51,13 @@ credential.
51
51
 
52
52
  Before the first Codex login, enable **Device code authorization for Codex** in
53
53
  ChatGPT Security settings. Only enter a device code from a login you initiated,
54
- and never share it. The automated host advertises `gpt-5.6-sol` with
55
- `medium`, `high`, and `xhigh` reasoning effort. Before starting a Trader,
56
- confirm that the VTX AI page shows the intended authenticated ChatGPT email and
57
- plan. The host reads the live Codex account window: a reached limit pauses new
58
- dispatch until its reported reset, while a transient throttle uses a short
59
- bounded cooldown.
54
+ and never share it. The automated host reads the authenticated Codex model
55
+ picker and advertises every visible model with that model's exact display name,
56
+ default effort, and supported reasoning efforts. Hidden Codex entries are not
57
+ exposed. Before starting a Trader, confirm that the VTX AI page shows the
58
+ intended authenticated ChatGPT email and plan. The host reads the live Codex
59
+ account window: a reached limit pauses new dispatch until its reported reset,
60
+ while a transient throttle uses a short bounded cooldown.
60
61
 
61
62
  ```bash
62
63
  vtx inference-host login
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.25",
41
+ package_version: "2026.8.26",
42
42
  codex_package_name: "@openai/codex",
43
43
  codex_version: "0.147.0",
44
44
  platforms: {
@@ -19074,10 +19074,20 @@ async function preflightCodexSubscription(options) {
19074
19074
  });
19075
19075
  }
19076
19076
  const rateLimits = await session.readAccountRateLimits(options.deadlineAtMs, options.signal);
19077
+ const modelCapabilities = await session.readModelCapabilities(options.deadlineAtMs, options.signal);
19078
+ if (modelCapabilities.length === 0) {
19079
+ throw new CodexAppServerError({
19080
+ message: "Codex did not return any visible models with supported reasoning efforts.",
19081
+ category: "model",
19082
+ code: "model_catalog_empty",
19083
+ retryable: false
19084
+ });
19085
+ }
19077
19086
  return {
19078
19087
  authenticated_account_email: account.authenticatedChatGptAccount.email,
19079
19088
  authenticated_account_plan: account.authenticatedChatGptAccount.planType,
19080
- rate_limits: rateLimits
19089
+ rate_limits: rateLimits,
19090
+ model_capabilities: modelCapabilities
19081
19091
  };
19082
19092
  } finally {
19083
19093
  await session.close();
@@ -20144,7 +20154,7 @@ child.once('close', async () => {
20144
20154
  });
20145
20155
  }
20146
20156
  const result2 = await this.request("model/list", {
20147
- includeHidden: true,
20157
+ includeHidden: false,
20148
20158
  ...cursor ? { cursor } : {}
20149
20159
  }, {
20150
20160
  timeoutMs: Math.max(1, deadlineAtMs - Date.now()),
@@ -20154,17 +20164,24 @@ child.once('close', async () => {
20154
20164
  for (const raw of data) {
20155
20165
  const candidate = objectOrNull(raw);
20156
20166
  if (!candidate) continue;
20157
- const id2 = typeof candidate.id === "string" && candidate.id.trim() ? candidate.id.trim() : null;
20158
- const model = typeof candidate.model === "string" && candidate.model.trim() ? candidate.model.trim() : null;
20159
- if (!id2 && !model) continue;
20167
+ const id2 = typeof candidate.id === "string" ? candidate.id.trim() : "";
20168
+ const model = typeof candidate.model === "string" ? candidate.model.trim() : "";
20169
+ const displayName = typeof candidate.displayName === "string" ? candidate.displayName.trim() : "";
20170
+ const hidden = candidate.hidden === true;
20160
20171
  const supportedReasoningEfforts = Array.isArray(candidate.supportedReasoningEfforts) ? candidate.supportedReasoningEfforts.flatMap((item) => {
20161
20172
  const reasoningEffort = objectOrNull(item)?.reasoningEffort;
20162
20173
  return typeof reasoningEffort === "string" && reasoningEffort.trim() ? [reasoningEffort.trim()] : [];
20163
20174
  }) : [];
20175
+ const defaultReasoningEffort = typeof candidate.defaultReasoningEffort === "string" ? candidate.defaultReasoningEffort.trim() : "";
20176
+ if (!id2 || !model || !displayName || hidden || supportedReasoningEfforts.length === 0 || new Set(supportedReasoningEfforts).size !== supportedReasoningEfforts.length || !supportedReasoningEfforts.includes(defaultReasoningEffort)) continue;
20164
20177
  capabilities.push(Object.freeze({
20165
20178
  id: id2,
20166
20179
  model,
20167
- supportedReasoningEfforts: Object.freeze(supportedReasoningEfforts)
20180
+ displayName,
20181
+ hidden,
20182
+ supportedReasoningEfforts: Object.freeze(supportedReasoningEfforts),
20183
+ defaultReasoningEffort,
20184
+ isDefault: candidate.isDefault === true
20168
20185
  }));
20169
20186
  }
20170
20187
  cursor = typeof result2.nextCursor === "string" && result2.nextCursor ? result2.nextCursor : null;
@@ -20952,7 +20969,7 @@ import {
20952
20969
  import { randomBytes as randomBytes3 } from "node:crypto";
20953
20970
  import { tmpdir as tmpdir2 } from "node:os";
20954
20971
  import { isAbsolute as isAbsolute2, join as join4, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
20955
- var INITIAL_CODEX_INFERENCE_MODEL, SUPPORTED_CODEX_REASONING_EFFORTS, MAX_PROMPT_BYTES2, tokenUsageReceiptSchema, turnResultReceiptSchema, terminalReceiptSchema, recoveryCheckpointSchema, recoveryFileSchema, FileCodexAttemptRecoveryStore, utf8Bytes, assertAttemptActive, tomlString, permissionConfig, ensureDedicatedCodexHome, createIsolatedCodexAttemptResources, createIsolatedCodexHostResources, validateAttemptInput, isStrictDescendant, assertRecoveryResourceScope, removeRecoveredThread, confirmGuardianTerminatedForRecovery, reconcileCodexAttemptRecovery, CodexSubscriptionAdapter;
20972
+ var MAX_PROMPT_BYTES2, CODEX_MODEL_NAME_PATTERN, CODEX_REASONING_EFFORT_PATTERN, tokenUsageReceiptSchema, turnResultReceiptSchema, terminalReceiptSchema, recoveryCheckpointSchema, recoveryFileSchema, FileCodexAttemptRecoveryStore, utf8Bytes, assertAttemptActive, tomlString, permissionConfig, ensureDedicatedCodexHome, createIsolatedCodexAttemptResources, createIsolatedCodexHostResources, validateAttemptInput, isStrictDescendant, assertRecoveryResourceScope, removeRecoveredThread, confirmGuardianTerminatedForRecovery, reconcileCodexAttemptRecovery, CodexSubscriptionAdapter;
20956
20973
  var init_codex_adapter = __esm({
20957
20974
  "lib/inference-host/codex-adapter.ts"() {
20958
20975
  "use strict";
@@ -20960,16 +20977,9 @@ var init_codex_adapter = __esm({
20960
20977
  init_codex_app_server();
20961
20978
  init_codex_binary();
20962
20979
  init_config();
20963
- INITIAL_CODEX_INFERENCE_MODEL = "gpt-5.6-sol";
20964
- SUPPORTED_CODEX_REASONING_EFFORTS = [
20965
- "low",
20966
- "medium",
20967
- "high",
20968
- "xhigh",
20969
- "max",
20970
- "ultra"
20971
- ];
20972
20980
  MAX_PROMPT_BYTES2 = 3e5;
20981
+ CODEX_MODEL_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$/u;
20982
+ CODEX_REASONING_EFFORT_PATTERN = /^[a-z][a-z0-9_-]{0,31}$/u;
20973
20983
  tokenUsageReceiptSchema = external_exports.strictObject({
20974
20984
  inputTokens: external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
20975
20985
  cachedInputTokens: external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
@@ -20981,10 +20991,10 @@ var init_codex_adapter = __esm({
20981
20991
  });
20982
20992
  turnResultReceiptSchema = external_exports.strictObject({
20983
20993
  text: external_exports.string().min(1).max(MAX_PROMPT_BYTES2),
20984
- requestedModel: external_exports.literal(INITIAL_CODEX_INFERENCE_MODEL),
20985
- effectiveModel: external_exports.literal(INITIAL_CODEX_INFERENCE_MODEL),
20986
- requestedReasoningEffort: external_exports.enum(SUPPORTED_CODEX_REASONING_EFFORTS),
20987
- effectiveReasoningEffort: external_exports.enum(SUPPORTED_CODEX_REASONING_EFFORTS),
20994
+ requestedModel: external_exports.string().regex(CODEX_MODEL_NAME_PATTERN),
20995
+ effectiveModel: external_exports.string().regex(CODEX_MODEL_NAME_PATTERN),
20996
+ requestedReasoningEffort: external_exports.string().regex(CODEX_REASONING_EFFORT_PATTERN),
20997
+ effectiveReasoningEffort: external_exports.string().regex(CODEX_REASONING_EFFORT_PATTERN),
20988
20998
  adapterRequestId: external_exports.string().min(1).max(512),
20989
20999
  adapterResponseId: external_exports.string().min(1).max(512),
20990
21000
  usage: tokenUsageReceiptSchema,
@@ -20992,7 +21002,7 @@ var init_codex_adapter = __esm({
20992
21002
  timeToFirstTokenMs: external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).nullable(),
20993
21003
  terminalStatus: external_exports.literal("completed")
20994
21004
  }).superRefine((value, context) => {
20995
- if (value.usage.cachedInputTokens > value.usage.inputTokens || value.usage.reasoningOutputTokens > value.usage.outputTokens || value.usage.totalTokens !== value.usage.inputTokens + value.usage.outputTokens || value.effectiveReasoningEffort !== value.requestedReasoningEffort) {
21005
+ if (value.usage.cachedInputTokens > value.usage.inputTokens || value.usage.reasoningOutputTokens > value.usage.outputTokens || value.usage.totalTokens !== value.usage.inputTokens + value.usage.outputTokens || value.effectiveModel !== value.requestedModel || value.effectiveReasoningEffort !== value.requestedReasoningEffort) {
20996
21006
  context.addIssue({ code: "custom", message: "Invalid Codex recovery usage or identity." });
20997
21007
  }
20998
21008
  });
@@ -21215,9 +21225,9 @@ var init_codex_adapter = __esm({
21215
21225
  retryable: false
21216
21226
  });
21217
21227
  }
21218
- if (input.requestedModel !== INITIAL_CODEX_INFERENCE_MODEL || !SUPPORTED_CODEX_REASONING_EFFORTS.includes(input.requestedReasoningEffort)) {
21228
+ if (!CODEX_MODEL_NAME_PATTERN.test(input.requestedModel) || !CODEX_REASONING_EFFORT_PATTERN.test(input.requestedReasoningEffort)) {
21219
21229
  throw new CodexAppServerError({
21220
- message: "Codex model selection is not admitted by the pinned adapter.",
21230
+ message: "Codex model selection is not a valid catalog identity.",
21221
21231
  category: "model",
21222
21232
  code: "model_selection_not_admitted",
21223
21233
  retryable: false
@@ -28644,7 +28654,7 @@ function createDefaultInferenceHostRunnerDependencies(options) {
28644
28654
  envelopePublicKey: options.envelopePublicKey
28645
28655
  };
28646
28656
  }
28647
- var import_ajv, RUNTIME_RECEIPT_SCHEMA_VERSION, ATTEMPT_RECEIPT_SCHEMA_VERSION, DEFAULT_ADVERTISEMENT_TTL_MS, DEFAULT_ADVERTISEMENT_REFRESH_LEAD_MS, DEFAULT_HOST_HEARTBEAT_MS, DEFAULT_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, DEFAULT_MAX_CONCURRENCY, MIN_SLEEP_MS, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, CODEX_INFERENCE_ADVERTISED_MODEL, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, safeFailureCode, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner;
28657
+ var import_ajv, RUNTIME_RECEIPT_SCHEMA_VERSION, ATTEMPT_RECEIPT_SCHEMA_VERSION, DEFAULT_ADVERTISEMENT_TTL_MS, DEFAULT_ADVERTISEMENT_REFRESH_LEAD_MS, DEFAULT_HOST_HEARTBEAT_MS, DEFAULT_ATTEMPT_HEARTBEAT_MS, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_REMOTE_RETRY_LIMIT, DEFAULT_MAX_CONCURRENCY, MIN_SLEEP_MS, DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS, MIN_CLAIM_START_WINDOW_MS, buildCodexInferenceAdvertisedModels, FileInferenceHostRuntimeReceiptStore, InferenceHostRecoveryRequiredError, InferenceHostRunnerError, defaultSleep, abortError, defaultRegisterSignalHandlers, safeInteger, exactObjectKeys, validIso, validateAttemptReceipt, validateRuntimeReceipt, sha256, stableOperationId, buildAttemptStartRequest, isoAt, finitePositiveOption, validateRunnerOptions, assertLocalCredentialIdentity, retryableRemoteError, remoteRetryAfterMs, controlPlaneFatal, defaultValidateOutput, objectRecord, positiveUtf8ByteLimit, assertCompilableOutputSchema, parseOutputContract, safeFailureCode, exactJson2, runnerIdentityMismatch, assertAdvertisementResult, assertHostHeartbeatResult, assertClaimResult, assertStartResult, assertJobHeartbeatResult, assertTerminalResult, classifyFailure, ambiguousHeartbeatTransport, reportedTokenUsage, reportedUsage, InferenceHostRunner;
28648
28658
  var init_runner = __esm({
28649
28659
  "lib/inference-host/runner.ts"() {
28650
28660
  "use strict";
@@ -28652,7 +28662,6 @@ var init_runner = __esm({
28652
28662
  init_external_inference_contract();
28653
28663
  init_config();
28654
28664
  init_credential_store();
28655
- init_codex_adapter();
28656
28665
  init_codex_app_server();
28657
28666
  init_crypto();
28658
28667
  init_mcp_client();
@@ -28669,21 +28678,38 @@ var init_runner = __esm({
28669
28678
  MIN_SLEEP_MS = 10;
28670
28679
  DEFAULT_CODEX_ACCOUNT_COOLDOWN_MS = 5 * 60 * 1e3;
28671
28680
  MIN_CLAIM_START_WINDOW_MS = 5e3;
28672
- CODEX_INFERENCE_ADVERTISED_MODEL = Object.freeze({
28673
- model_id: INITIAL_CODEX_INFERENCE_MODEL,
28674
- label: "Codex GPT-5.6 Sol",
28675
- adapter: "codex",
28676
- supported_lanes: ["main", "review", "screener"],
28677
- supported_reasoning_efforts: [...SUPPORTED_CODEX_REASONING_EFFORTS],
28678
- default_reasoning_effort: "medium",
28679
- supported_response_modes: ["provider_response", "decision_candidate"],
28680
- allowed_model_identities: [{
28681
- requested_model: INITIAL_CODEX_INFERENCE_MODEL,
28682
- effective_models: [INITIAL_CODEX_INFERENCE_MODEL]
28683
- }],
28684
- structured_output: true,
28685
- same_attempt_recovery: true
28686
- });
28681
+ buildCodexInferenceAdvertisedModels = (capabilities, adapterRuntimeVersion) => {
28682
+ const visible = capabilities.filter((capability) => !capability.hidden);
28683
+ if (visible.length === 0 || visible.length > 64) {
28684
+ throw new InferenceHostRunnerError(
28685
+ "invalid_configuration",
28686
+ visible.length === 0 ? "Codex did not return any visible models that VTX can advertise." : "Codex returned more models than the VTX advertisement contract can represent."
28687
+ );
28688
+ }
28689
+ const models = visible.map((capability) => ({
28690
+ model_id: capability.model,
28691
+ label: capability.displayName,
28692
+ adapter: "codex",
28693
+ supported_lanes: ["main", "review", "screener"],
28694
+ supported_reasoning_efforts: [...capability.supportedReasoningEfforts],
28695
+ default_reasoning_effort: capability.defaultReasoningEffort,
28696
+ supported_response_modes: ["provider_response", "decision_candidate"],
28697
+ allowed_model_identities: [{
28698
+ requested_model: capability.model,
28699
+ effective_models: [capability.model]
28700
+ }],
28701
+ structured_output: true,
28702
+ same_attempt_recovery: true,
28703
+ adapter_runtime_version: adapterRuntimeVersion
28704
+ }));
28705
+ if (new Set(models.map((model) => model.model_id)).size !== models.length) {
28706
+ throw new InferenceHostRunnerError(
28707
+ "invalid_configuration",
28708
+ "Codex returned duplicate runtime model identities."
28709
+ );
28710
+ }
28711
+ return models;
28712
+ };
28687
28713
  FileInferenceHostRuntimeReceiptStore = class {
28688
28714
  constructor(path) {
28689
28715
  this.path = path;
@@ -28926,6 +28952,10 @@ var init_runner = __esm({
28926
28952
  );
28927
28953
  }
28928
28954
  return {
28955
+ advertisedModels: buildCodexInferenceAdvertisedModels(
28956
+ options.codexModelCapabilities,
28957
+ options.adapterRuntimeVersion
28958
+ ),
28929
28959
  maxConcurrency: finitePositiveOption(
28930
28960
  options.maxConcurrency,
28931
28961
  DEFAULT_MAX_CONCURRENCY,
@@ -29397,12 +29427,7 @@ var init_runner = __esm({
29397
29427
  health,
29398
29428
  advertised_at: isoAt(advertisedAt),
29399
29429
  expires_at: isoAt(advertisedAt + settings.advertisementTtlMs),
29400
- models: [{
29401
- ...CODEX_INFERENCE_ADVERTISED_MODEL,
29402
- supported_lanes: [...CODEX_INFERENCE_ADVERTISED_MODEL.supported_lanes],
29403
- supported_response_modes: [...CODEX_INFERENCE_ADVERTISED_MODEL.supported_response_modes],
29404
- adapter_runtime_version: this.options.adapterRuntimeVersion
29405
- }]
29430
+ models: settings.advertisedModels
29406
29431
  });
29407
29432
  receipt = {
29408
29433
  ...receipt,
@@ -29983,7 +30008,7 @@ var init_runner = __esm({
29983
30008
  systemPrompt: jobInput.system_prompt,
29984
30009
  userPrompt: jobInput.user_prompt,
29985
30010
  outputSchemaJson: outputContract.adapterSchemaJson,
29986
- requestedModel: INITIAL_CODEX_INFERENCE_MODEL,
30011
+ requestedModel: jobInput.requested_model,
29987
30012
  requestedReasoningEffort: jobInput.requested_reasoning_effort,
29988
30013
  deadlineAtMs: Date.parse(jobInput.deadline_at),
29989
30014
  signal: attemptAbort.signal
@@ -30210,9 +30235,10 @@ var init_runner = __esm({
30210
30235
  }
30211
30236
  }
30212
30237
  validateImmutableSelection(jobInput) {
30213
- if (jobInput.requested_model !== INITIAL_CODEX_INFERENCE_MODEL || !SUPPORTED_CODEX_REASONING_EFFORTS.includes(
30214
- jobInput.requested_reasoning_effort
30215
- ) || jobInput.controller.model_id !== INITIAL_CODEX_INFERENCE_MODEL || jobInput.controller.reasoning_effort !== jobInput.requested_reasoning_effort) {
30238
+ const advertisedModel = this.options.codexModelCapabilities.find(
30239
+ (candidate) => !candidate.hidden && candidate.model === jobInput.requested_model
30240
+ );
30241
+ if (!advertisedModel || !advertisedModel.supportedReasoningEfforts.includes(jobInput.requested_reasoning_effort) || jobInput.controller.model_id !== jobInput.requested_model || jobInput.controller.reasoning_effort !== jobInput.requested_reasoning_effort) {
30216
30242
  throw new InferenceHostRunnerError(
30217
30243
  "unsupported_model_selection",
30218
30244
  "The claimed model or reasoning effort was not advertised by this host."
@@ -31368,6 +31394,7 @@ Durable service:
31368
31394
  authenticatedAccountEmail: options.authenticatedAccountEmail,
31369
31395
  authenticatedAccountPlan: options.authenticatedAccountPlan,
31370
31396
  codexRateLimits: options.codexRateLimits,
31397
+ codexModelCapabilities: options.codexModelCapabilities,
31371
31398
  protocolVersion: EXTERNAL_INFERENCE_CONTRACT_VERSION,
31372
31399
  adapterRuntimeVersion: INFERENCE_HOST_CLI_VERSION,
31373
31400
  maxConcurrency: options.maxConcurrency,
@@ -31868,6 +31895,7 @@ Waiting for approval...
31868
31895
  authenticatedAccountEmail: preflight?.authenticated_account_email ?? null,
31869
31896
  authenticatedAccountPlan: preflight?.authenticated_account_plan ?? null,
31870
31897
  codexRateLimits: preflight?.rate_limits ?? null,
31898
+ codexModelCapabilities: preflight?.model_capabilities ?? [],
31871
31899
  maxConcurrency: parsed.maxConcurrency,
31872
31900
  once: parsed.once,
31873
31901
  env,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtxmacro/cli",
3
- "version": "2026.8.25",
3
+ "version": "2026.8.26",
4
4
  "description": "VTX Macro CLI, MCP server, and durable subscription inference host.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",