@yhong91/cpac 0.2.4 → 0.2.6

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 CHANGED
@@ -348,14 +348,14 @@ cpac codebuddy -p "检查当前项目" # 非交互模式
348
348
 
349
349
  `~/.codebuddy/models.json` 是 CodeBuddy 官方放置第三方模型的地方,CPAC 只做**合并**:为每个 catalog slug 写一条 `models[]` 条目(`vendor: "CPAC"`、占位 `apiKey`(`cpac`)、`url` 指向 loopback `/v1/chat/completions`),你在同一文件里自己加的模型条目原样保留。loopback 代理把入站 Authorization 换成真实 `CPA_API_KEY`。
350
350
 
351
- - 字段映射:`maxInputTokens` 取 catalog 的 `context_window`(不是 `max_context_window`),`maxOutputTokens` 取 `max_output_tokens`,catalog 没给就不写这两个键;`supportsImages` / `supportsReasoning` 按 `input_modalities` / `supported_reasoning_levels` 推导,`supportsToolCall` 恒为 true。
351
+ - 字段映射:`name` 和 `id` 都用 catalog slug,不用 `display_name`。CodeBuddy 会把 `id` 改成 `custom-local:<slug>`,`/model` 和 `--model` 只按 `name` 或 `id` 匹配,不认 alias。`maxInputTokens` 取 `context_window`(不是 `max_context_window`),`maxOutputTokens` 取 `max_output_tokens`,catalog 没给就不写这两个键;`supportsImages` / `supportsReasoning` 按 `input_modalities` / `supported_reasoning_levels` 推导,`supportsToolCall` 恒为 true。
352
352
  - 不写 `relatedModels`:CodeBuddy 的 lite / reasoning 场景因此回落到主模型,而不是借用内置默认值。
353
353
  - `availableModels` 只在你已经设置过时才改写(缺失即「显示全部」);改写只并入 CPA slug,不会删掉你列出的 id。
354
354
  - 归属识别:`apiKey` 为 `cpac` 且 `url` 是 loopback `…/chat/completions` 的条目才算 CPAC 的,`cpac sync codebuddy` 只替换这些条目。
355
355
  - 恢复:注入后未改 → 逐字节还原原文件(原本没有该文件则删除它);改过 → 只剥 CPAC 条目,你的模型和 `availableModels` 留下。
356
356
  - 模型选择仍由 CodeBuddy 决定:用 `/model` 选 CPA 模型或用 `CODEBUDDY_MODEL` 指定默认模型,CPAC 不改 `settings.json`。
357
357
 
358
- 配置目录尊重 `CODEBUDDY_CONFIG_DIR`(否则 `~/.codebuddy`)。首次写入前若 `models.json` 已存在,会在 `state_dir/codebuddy/models.json` 保留原始快照。
358
+ 配置目录尊重 `CODEBUDDY_CONFIG_DIR`(否则 `~/.codebuddy`)。首次写入前若 `models.json` 已存在,会在 `state_dir/codebuddy/models.json` 保留原始快照。官方字段、`availableModels` 和 2.105.2 的 `custom-local:` 前缀见 `docs/codebuddy-models.md`。
359
359
 
360
360
  ### 手动打开 5h 窗口
361
361
 
package/dist/agents.js CHANGED
@@ -419,6 +419,18 @@ function syncTargetIds(config, requested, all) {
419
419
  }
420
420
  return selected.map((target) => target.id);
421
421
  }
422
+ function formatModelVersion(iso) {
423
+ const date = new Date(iso);
424
+ if (Number.isNaN(date.getTime()))
425
+ return iso;
426
+ const pad = (value) => String(value).padStart(2, "0");
427
+ const clock = `${pad(date.getHours())}:${pad(date.getMinutes())}`;
428
+ // ponytail: minute display; the stored ISO still separates same-minute updates
429
+ const monthDay = `${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
430
+ return date.getFullYear() === new Date().getFullYear()
431
+ ? `${monthDay} ${clock}`
432
+ : `${date.getFullYear()}-${monthDay} ${clock}`;
433
+ }
422
434
  export async function runSync(config, requested, options) {
423
435
  const ids = syncTargetIds(config, requested, options.all);
424
436
  if (options.maxContext && ids.some((id) => id !== "codex")) {
@@ -427,24 +439,36 @@ export async function runSync(config, requested, options) {
427
439
  const apiKey = await resolveApiKey(config.api_key_env);
428
440
  const catalog = await fetchCatalog(config.cpa_url, apiKey);
429
441
  const { index, changed } = refreshModelIndex(config.state_dir, catalog.bytes, new Date().toISOString(), !options.dryRun);
430
- console.log(`models ${index.updated_at}${changed ? (options.dryRun ? " would update" : " updated") : " unchanged"}`);
442
+ console.log(`models ${formatModelVersion(index.updated_at)}${changed ? (options.dryRun ? " would update" : " updated") : " unchanged"}`);
431
443
  const pending = ids.filter((id) => index.applied[id] !== index.updated_at);
432
444
  for (const id of ids) {
433
- if (index.applied[id] === index.updated_at) {
434
- console.log(`${id}: model version ${index.updated_at} unchanged`);
435
- }
445
+ const applied = index.applied[id];
446
+ if (applied === index.updated_at)
447
+ console.log(` ${id}: unchanged`);
448
+ else if (applied)
449
+ console.log(` ${id}: ${formatModelVersion(applied)}`);
436
450
  }
437
451
  if (pending.length === 0)
438
452
  return 0;
439
453
  // ponytail: version is the model-list timestamp only. spawn_models, v2_off,
440
454
  // max_context, and the proxy port do not bump it; cpac install still rewrites.
441
- const code = await runInstall(config, pending, {
442
- all: false,
443
- dryRun: options.dryRun,
444
- force: true,
445
- v2Off: options.v2Off,
446
- maxContext: options.maxContext,
447
- });
455
+ const log = console.log;
456
+ console.log = (msg) => {
457
+ log(String(msg ?? "").replace(/^/gm, " "));
458
+ };
459
+ let code;
460
+ try {
461
+ code = await runInstall(config, pending, {
462
+ all: false,
463
+ dryRun: options.dryRun,
464
+ force: true,
465
+ v2Off: options.v2Off,
466
+ maxContext: options.maxContext,
467
+ });
468
+ }
469
+ finally {
470
+ console.log = log;
471
+ }
448
472
  if (!options.dryRun && code === 0) {
449
473
  markModelsApplied(config.state_dir, pending, index.updated_at);
450
474
  }
@@ -79,9 +79,9 @@ function positiveInt(value) {
79
79
  function buildModel(row, slug, port) {
80
80
  const model = {
81
81
  id: slug,
82
- name: typeof row.display_name === "string" && row.display_name.trim()
83
- ? row.display_name.trim()
84
- : slug,
82
+ // CodeBuddy 2.105.2 prefixes id with custom-local: and matches
83
+ // /model and --model on name or id only, not aliases.
84
+ name: slug,
85
85
  vendor: CODEBUDDY_VENDOR,
86
86
  apiKey: CODEBUDDY_API_KEY_PLACEHOLDER,
87
87
  url: `http://127.0.0.1:${port}/v1/chat/completions`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yhong91/cpac",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Connect Codex and Claude Code to a remote CLIProxyAPI gateway",
5
5
  "type": "module",
6
6
  "bin": {