topchester-ai 0.51.0 → 0.53.0

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/dist/bin.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as runTopchesterCli } from "./cli-DkzkXlKD.mjs";
2
+ import { t as runTopchesterCli } from "./cli-CqFhOvlt.mjs";
3
3
  //#region src/bin.ts
4
4
  await runTopchesterCli();
5
5
  //#endregion
@@ -5972,8 +5972,7 @@ const rawModelsSchema = z.object({
5972
5972
  "default": modelRefSchema.optional(),
5973
5973
  "fast": modelRefSchema.optional(),
5974
5974
  "kb.summarize": modelRefSchema.optional(),
5975
- "choices": z.array(modelRefSchema).optional(),
5976
- "providers": providersSchema.optional()
5975
+ "choices": z.array(modelRefSchema).optional()
5977
5976
  }).strict();
5978
5977
  const ignorePathSchema = z.string().min(1).superRefine((value, context) => {
5979
5978
  const pattern = value.startsWith("!") ? value.slice(1) : value;
@@ -6113,9 +6112,9 @@ const topchesterConfigSchema = z.object({
6113
6112
  models: z.object({
6114
6113
  defaultPurpose: modelPurposeSchema.optional(),
6115
6114
  assignments: z.partialRecord(modelPurposeSchema, modelAssignmentSchema).optional(),
6116
- choices: z.array(modelChoiceAssignmentSchema).optional(),
6117
- providers: providersSchema.optional()
6115
+ choices: z.array(modelChoiceAssignmentSchema).optional()
6118
6116
  }).strict().optional(),
6117
+ providers: providersSchema.optional(),
6119
6118
  ignore: z.object({ paths: z.array(ignorePathSchema).optional() }).optional(),
6120
6119
  tools: z.object({ bash: bashPermissionPolicySchema.optional() }).strict().optional(),
6121
6120
  mcp: mcpConfigSchema.optional(),
@@ -6124,6 +6123,7 @@ const topchesterConfigSchema = z.object({
6124
6123
  });
6125
6124
  const rawTopchesterConfigSchema = z.object({
6126
6125
  models: rawModelsSchema.optional(),
6126
+ providers: providersSchema.optional(),
6127
6127
  ignore: z.object({ paths: z.array(ignorePathSchema).optional() }).optional(),
6128
6128
  tools: z.object({ bash: bashPermissionPolicySchema.optional() }).strict().optional(),
6129
6129
  mcp: rawMcpConfigSchema.optional(),
@@ -6209,7 +6209,7 @@ async function configureOpenRouterGlobalProvider() {
6209
6209
  const configPath = getGlobalTopchesterConfigPath();
6210
6210
  const config = readConfigObject(configPath);
6211
6211
  const models = ensurePlainObjectProperty(config, "models");
6212
- const providers = ensurePlainObjectProperty(models, "providers");
6212
+ const providers = ensurePlainObjectProperty(config, "providers");
6213
6213
  providers.default ??= "openrouter";
6214
6214
  providers.openrouter = {
6215
6215
  ...openRouterProviderDefaults,
@@ -6226,7 +6226,7 @@ async function configureCodexGlobalProvider() {
6226
6226
  const configPath = getGlobalTopchesterConfigPath();
6227
6227
  const config = readConfigObject(configPath);
6228
6228
  const models = ensurePlainObjectProperty(config, "models");
6229
- const providers = ensurePlainObjectProperty(models, "providers");
6229
+ const providers = ensurePlainObjectProperty(config, "providers");
6230
6230
  const existingChoices = ensureStringArrayProperty(models, "choices");
6231
6231
  const prioritizedChoices = new Set(codexStarterModelChoices);
6232
6232
  providers.default ??= "codex";
@@ -6285,7 +6285,7 @@ function getConfiguredModelChoices(config) {
6285
6285
  const seen = /* @__PURE__ */ new Set();
6286
6286
  const fallbackChoices = [];
6287
6287
  for (const assignment of assignments) {
6288
- const provider = assignment.provider ?? config.models?.providers?.default;
6288
+ const provider = assignment.provider ?? config.providers?.default;
6289
6289
  if (typeof provider !== "string") continue;
6290
6290
  const choice = {
6291
6291
  ...assignment,
@@ -6454,18 +6454,27 @@ function parseConfigFile(path, value) {
6454
6454
  return parsed.data;
6455
6455
  }
6456
6456
  function normalizeConfigInput(value) {
6457
- return normalizeHooksConfigInput(normalizeModelsConfigInput(value));
6458
- }
6459
- function normalizeModelsConfigInput(value) {
6460
- if (!isPlainObject(value) || !isPlainObject(value.models)) return value;
6457
+ return normalizeHooksConfigInput(normalizeModelsAndProvidersConfigInput(value));
6458
+ }
6459
+ function normalizeModelsAndProvidersConfigInput(value) {
6460
+ if (!isPlainObject(value)) return value;
6461
+ const providers = isPlainObject(value.providers) ? { ...value.providers } : {};
6462
+ if (!isPlainObject(value.models)) {
6463
+ if (Object.keys(providers).length === 0) return value;
6464
+ applyKnownProviderDefaults(providers);
6465
+ return {
6466
+ ...value,
6467
+ providers
6468
+ };
6469
+ }
6461
6470
  const models = { ...value.models };
6462
- const providers = isPlainObject(models.providers) ? { ...models.providers } : {};
6471
+ const knownProviders = getKnownModelProviders(providers);
6463
6472
  const assignments = {};
6464
- const defaultModelRef = normalizeModelRef(models.default, typeof providers.default === "string" ? providers.default : void 0);
6473
+ const defaultModelRef = normalizeModelRef(models.default, typeof providers.default === "string" ? providers.default : void 0, knownProviders);
6465
6474
  const defaultProvider = typeof providers.default === "string" ? providers.default : defaultModelRef?.provider;
6466
- const fastModelRef = normalizeModelRef(models.fast, defaultProvider);
6467
- const kbSummarizeModelRef = normalizeModelRef(models["kb.summarize"], defaultProvider);
6468
- const modelChoices = Array.isArray(models.choices) ? models.choices.map((choice) => modelRefToAssignment(normalizeModelRef(choice, void 0) ?? { model: "" })) : void 0;
6475
+ const fastModelRef = normalizeModelRef(models.fast, defaultProvider, knownProviders);
6476
+ const kbSummarizeModelRef = normalizeModelRef(models["kb.summarize"], defaultProvider, knownProviders);
6477
+ const modelChoices = Array.isArray(models.choices) ? models.choices.map((choice) => modelRefToAssignment(normalizeModelRef(choice, void 0, knownProviders) ?? { model: "" })) : void 0;
6469
6478
  if (defaultModelRef) {
6470
6479
  const assignment = modelRefToAssignment(defaultModelRef);
6471
6480
  assignments["agent.primary"] = assignment;
@@ -6491,9 +6500,9 @@ function normalizeModelsConfigInput(value) {
6491
6500
  models: {
6492
6501
  ...models,
6493
6502
  assignments,
6494
- ...modelChoices ? { choices: modelChoices } : {},
6495
- providers
6496
- }
6503
+ ...modelChoices ? { choices: modelChoices } : {}
6504
+ },
6505
+ ...Object.keys(providers).length > 0 ? { providers } : {}
6497
6506
  };
6498
6507
  }
6499
6508
  function normalizeHooksConfigInput(value) {
@@ -6512,8 +6521,8 @@ function normalizeHooksConfigInput(value) {
6512
6521
  hooks
6513
6522
  };
6514
6523
  }
6515
- function normalizeModelRef(ref, defaultProvider) {
6516
- if (typeof ref === "string") return parseModelRef(ref, defaultProvider);
6524
+ function normalizeModelRef(ref, defaultProvider, knownProviders = getKnownModelProviders()) {
6525
+ if (typeof ref === "string") return parseModelRef(ref, defaultProvider, knownProviders);
6517
6526
  if (!isPlainObject(ref) || typeof ref.name !== "string") return;
6518
6527
  return {
6519
6528
  model: ref.name,
@@ -6528,7 +6537,12 @@ function modelRefToAssignment(ref) {
6528
6537
  ...ref.toolProtocol ? { toolProtocol: ref.toolProtocol } : {}
6529
6538
  };
6530
6539
  }
6531
- function parseModelRef(ref, defaultProvider) {
6540
+ function parseModelRef(ref, defaultProvider, knownProviders) {
6541
+ const [explicitProvider, ...explicitModelParts] = ref.split("/");
6542
+ if (explicitProvider && explicitModelParts.length > 0 && knownProviders.has(explicitProvider)) return {
6543
+ provider: explicitProvider,
6544
+ model: explicitModelParts.join("/")
6545
+ };
6532
6546
  if (defaultProvider) {
6533
6547
  const providerPrefix = `${defaultProvider}/`;
6534
6548
  return ref.startsWith(providerPrefix) ? {
@@ -6546,6 +6560,13 @@ function parseModelRef(ref, defaultProvider) {
6546
6560
  };
6547
6561
  return { model: ref };
6548
6562
  }
6563
+ function getKnownModelProviders(providers = {}) {
6564
+ return new Set([
6565
+ "openrouter",
6566
+ "codex",
6567
+ ...Object.keys(providers).filter((provider) => provider !== "default")
6568
+ ]);
6569
+ }
6549
6570
  function ensureKnownProvider(providers, provider) {
6550
6571
  if (provider === "openrouter" && providers.openrouter === void 0) {
6551
6572
  providers.openrouter = { ...openRouterProviderDefaults };
@@ -6681,7 +6702,7 @@ function createModelGatewayFromConfig(config) {
6681
6702
  return new ModelGateway(normalizeModelGatewayConfig(config));
6682
6703
  }
6683
6704
  function normalizeModelGatewayConfig(config) {
6684
- const { default: defaultProvider, ...namedProviders } = config.models?.providers ?? {};
6705
+ const { default: defaultProvider, ...namedProviders } = config.providers ?? {};
6685
6706
  return {
6686
6707
  defaultPurpose: config.models?.defaultPurpose ?? "agent.primary",
6687
6708
  models: config.models?.assignments ?? {},
@@ -10070,7 +10091,7 @@ var PromptHistory = class {
10070
10091
  const STARTUP_PROMPT_HINT = "Prompt hint: Enter sends, Shift+Enter adds a line, / opens commands, ↑↓ browse history.";
10071
10092
  function getStartupThreadMessages(context) {
10072
10093
  const assignments = context.config.models?.assignments ?? {};
10073
- const providers = context.config.models?.providers ?? {};
10094
+ const providers = context.config.providers ?? {};
10074
10095
  const banner = getRandomAsciiBanner();
10075
10096
  const lines = banner ? [
10076
10097
  "",
@@ -10107,7 +10128,7 @@ function getStartupThreadMessages(context) {
10107
10128
  }
10108
10129
  function getModelSetupHint(context) {
10109
10130
  const assignments = context.config.models?.assignments ?? {};
10110
- const providers = context.config.models?.providers ?? {};
10131
+ const providers = context.config.providers ?? {};
10111
10132
  const hasAssignments = Object.keys(assignments).length > 0;
10112
10133
  const hasProviders = Object.entries(providers).some(([providerId]) => providerId !== "default");
10113
10134
  if (hasAssignments && hasProviders) return;
@@ -10177,7 +10198,7 @@ function getModelLabel(context) {
10177
10198
  const purpose = context.config.models?.defaultPurpose ?? "agent.primary";
10178
10199
  const model = context.config.models?.assignments?.[purpose] ?? context.config.models?.assignments?.fallback;
10179
10200
  if (!model) return "not set";
10180
- const provider = model.provider ?? context.config.models?.providers?.default;
10201
+ const provider = model.provider ?? context.config.providers?.default;
10181
10202
  return typeof provider === "string" ? `${model.name} [${provider}]` : model.name;
10182
10203
  }
10183
10204
  //#endregion
@@ -15199,7 +15220,7 @@ function formatModelHints(config) {
15199
15220
  ];
15200
15221
  }
15201
15222
  function formatProviderHints(config, authStoreStatus) {
15202
- const providers = config.models?.providers ?? {};
15223
+ const providers = config.providers ?? {};
15203
15224
  const namedProviders = Object.entries(providers).filter(([providerId]) => providerId !== "default");
15204
15225
  if (namedProviders.length === 0) return [section("providers"), row("configured", status("none", "muted"))];
15205
15226
  const lines = [section("providers")];
@@ -15337,8 +15358,8 @@ function createTopchesterProgram() {
15337
15358
  console.log(result.lines.join("\n"));
15338
15359
  if (!result.ok) process.exitCode = 1;
15339
15360
  });
15340
- const authCommand = program.command("auth").description("manage global provider authentication");
15341
- authCommand.command("login").description("log in to a provider").argument("<provider>", "provider id").option("--device", "use device-code login").action(async (provider, options) => {
15361
+ const authCommand = program.command("auth").description("manage global provider authentication").addHelpText("after", formatAuthCommandHelp);
15362
+ authCommand.command("login").usage("[options] <provider>").description("log in to a provider").argument("[provider]", "provider id").option("--device", "use device-code login").addHelpText("after", formatAuthLoginHelp).action(async (provider, options) => {
15342
15363
  try {
15343
15364
  await executeAuthLoginCommand(provider, options);
15344
15365
  } catch (error) {
@@ -15446,7 +15467,7 @@ function createTopchesterProgram() {
15446
15467
  }
15447
15468
  function printStartupSummary(context) {
15448
15469
  const assignments = context.config.models?.assignments ?? {};
15449
- const providers = context.config.models?.providers ?? {};
15470
+ const providers = context.config.providers ?? {};
15450
15471
  console.log(`workspace: ${context.workspaceRoot}`);
15451
15472
  console.log(`default model purpose: ${context.config.models?.defaultPurpose ?? "agent.primary"}`);
15452
15473
  if (context.devFlags.size > 0) console.log(`dev flags: ${[...context.devFlags].join(", ")}`);
@@ -15471,19 +15492,66 @@ function printStartupSummary(context) {
15471
15492
  }
15472
15493
  }
15473
15494
  }
15495
+ const AUTH_PROVIDERS = [{
15496
+ id: "codex",
15497
+ name: "Codex / ChatGPT",
15498
+ auth: "OAuth device-code login for Codex-backed model access.",
15499
+ example: "topchester auth login codex --device"
15500
+ }];
15501
+ function formatAuthCommandHelp() {
15502
+ return [
15503
+ "",
15504
+ ui.label("Supported providers:"),
15505
+ ...AUTH_PROVIDERS.map((provider) => ` ${ui.modelInline(provider.id.padEnd(8))} ${provider.name} - ${provider.auth}`),
15506
+ "",
15507
+ ui.label("Examples:"),
15508
+ ...AUTH_PROVIDERS.map((provider) => ` ${provider.example}`),
15509
+ " topchester auth status"
15510
+ ].join("\n");
15511
+ }
15512
+ function formatAuthLoginHelp() {
15513
+ return [
15514
+ "",
15515
+ ui.label("Supported providers:"),
15516
+ ...AUTH_PROVIDERS.map((provider) => ` ${ui.modelInline(provider.id.padEnd(8))} ${provider.auth}`),
15517
+ "",
15518
+ ui.label("Examples:"),
15519
+ ...AUTH_PROVIDERS.map((provider) => ` ${provider.example}`),
15520
+ "",
15521
+ ui.label("What happens:"),
15522
+ " Topchester prints a browser URL and one-time code, waits for approval, then stores tokens in the global auth store."
15523
+ ].join("\n");
15524
+ }
15525
+ function formatAuthLoginUsageError(reason) {
15526
+ return [
15527
+ ui.error(reason),
15528
+ "",
15529
+ ui.label("Usage:"),
15530
+ " topchester auth login <provider> --device",
15531
+ "",
15532
+ ui.label("Supported providers:"),
15533
+ ...AUTH_PROVIDERS.map((provider) => ` ${provider.id.padEnd(8)} ${provider.name} - ${provider.auth}`),
15534
+ "",
15535
+ ui.label("Examples:"),
15536
+ ...AUTH_PROVIDERS.map((provider) => ` ${provider.example}`),
15537
+ "",
15538
+ "Run `topchester auth login --help` for details."
15539
+ ].join("\n");
15540
+ }
15474
15541
  async function executeAuthLoginCommand(provider, options) {
15475
- if (provider !== "codex") throw new Error(`Unsupported auth provider "${provider}". Supported providers: codex.`);
15476
- if (!options.device) throw new Error("Usage: topchester auth login codex --device");
15542
+ if (!provider) throw new Error(formatAuthLoginUsageError("Missing provider."));
15543
+ if (provider !== "codex") throw new Error(formatAuthLoginUsageError(`Unsupported auth provider "${provider}".`));
15544
+ if (!options.device) throw new Error(formatAuthLoginUsageError("Codex login currently requires \"--device\"."));
15477
15545
  const deviceCode = await requestCodexDeviceCode();
15478
- console.log("Codex device login");
15479
- console.log(`verification URL: ${deviceCode.verificationUrl}`);
15480
- console.log(`user code: ${deviceCode.userCode}`);
15481
- console.log(`expires: ${new Date(deviceCode.expiresAt).toISOString()}`);
15482
- console.log("Device codes are a common phishing target. Never share this code.");
15483
- console.log("Waiting for browser approval...");
15546
+ console.log(ui.heading("Codex device login"));
15547
+ console.log(`${ui.label("verification URL:")} ${deviceCode.verificationUrl}`);
15548
+ console.log(`${ui.label("user code:")} ${ui.inverse(deviceCode.userCode)}`);
15549
+ console.log(`${ui.label("expires:")} ${new Date(deviceCode.expiresAt).toISOString()}`);
15550
+ console.log(ui.warn("Device codes are a common phishing target. Never share this code."));
15551
+ console.log(ui.label("Waiting for browser approval..."));
15484
15552
  await setAuthProvider("codex", await exchangeCodexAuthorizationCode(await pollCodexDeviceAuthorization(deviceCode), { issuer: deviceCode.issuer }));
15485
15553
  await configureCodexGlobalProvider();
15486
- console.log("Codex login saved.");
15554
+ console.log(ui.ok("Codex login saved."));
15487
15555
  console.log("Configured global Codex provider and starter model choices.");
15488
15556
  }
15489
15557
  async function formatAuthStatus() {
@@ -15582,4 +15650,4 @@ function formatDryRunSyncStatus(status) {
15582
15650
  //#endregion
15583
15651
  export { runTopchesterCli as t };
15584
15652
 
15585
- //# sourceMappingURL=cli-DkzkXlKD.mjs.map
15653
+ //# sourceMappingURL=cli-CqFhOvlt.mjs.map