@yhong91/cpac 0.2.5 → 0.2.7

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
@@ -166,7 +166,7 @@ cpac --help
166
166
 
167
167
  ```bash
168
168
  cpac detect [--json]
169
- cpac models [--json]
169
+ cpac models [--json] [--diff]
170
170
  cpac install [codex|pi|kimi|grok|zed|hermes|codebuddy...] [--all] [--dry-run] [--force] [--v2_off] [--v2_models] [--max_context]
171
171
  cpac sync [codex|pi|kimi|grok|zed|hermes|codebuddy...] [--all] [--dry-run] [--v2_off] [--v2_models] [--max_context]
172
172
  cpac restore <codex|pi|kimi|grok|zed|hermes|codebuddy...> | --all [--dry-run]
@@ -175,7 +175,7 @@ cpac upgrade [--check]
175
175
  cpac -v | --version
176
176
  ```
177
177
 
178
- - `models` 从远端 CPA 拉取 rich catalog,默认一行一个 slug;`--json` 输出 `cpa_url` 和模型字段(`slug` / `display_name` / `context_window`)。用来核对 catalog 里有没有某个模型(例如 `*-fast`),不写本地配置。
178
+ - `models` 从远端 CPA 拉取 rich catalog,默认一行一个 slug;`--json` 输出 `cpa_url` 和模型字段(`slug` / `display_name` / `context_window`)。用来核对 catalog 里有没有某个模型(例如 `*-fast`),不写本地配置。`--diff` 拿已保存的 `state_dir/models.json` 和当前 catalog 比 slug:`+` 是新增,`-` 是去掉;没有差别打印 `unchanged`。还没有保存列表时报错,先跑 `cpac sync`。
179
179
  - `detect` 列出每个目标是否被检测到、是否已接入 CPAC;`--json` 输出机器可读结果。
180
180
  - `install` 默认作用于检测到的目标;后面直接写 agent 名(`cpac install codex pi`),`--all` 全部。`codex` 写入 catalog 并拉起 loopback 代理;`pi`/`kimi`/`grok`/`zed`/`hermes`/`codebuddy` 写入各自配置。`--dry-run` 只打印将要做的事,`--force` 允许重装已安装目标。
181
181
  - `sync` 把 CPA 模型列表和更新时间写到 `state_dir/models.json`(默认 `~/.cpac/models.json`)。这个时间戳就是模型版本:列表没变则时间戳不变,目标上次同步到的版本相同就跳过,不同才重写。不带参数只看已安装目标;`--all` 还会装上检测到但还没接入的目标。`install` 仍总是重写。`spawn_models`、`v2_off`、`max_context` 和代理端口不改这个版本,要马上生效用 `cpac install`。`--max_context` 仍只对 `cpac install codex` 有效。
package/dist/cpac.js CHANGED
@@ -13,6 +13,7 @@ import { isZedConfigInstalled } from "./targets/zed.js";
13
13
  import { isHermesConfigInstalled } from "./targets/hermes.js";
14
14
  import { isCodebuddyConfigInstalled } from "./targets/codebuddy.js";
15
15
  import { defaultConfigPath, loadConfig, originalBytes, pickSpawnModels, readState, saveSpawnModels, stateProxy, catalogMaxContextLive, catalogModelId, catalogModelRows, catalogSlugs, fetchCatalog, } from "./config.js";
16
+ import { canonicalModels, diffModelSlugs, readModelIndex } from "./models.js";
16
17
  import { runPing } from "./ping.js";
17
18
  import { proxyIsHealthy, runProxyChild } from "./proxy.js";
18
19
  import { CPACError, expandUserPath, promptSecret, saveApiKeyExport, shellProfile, } from "./util.js";
@@ -93,11 +94,30 @@ export async function status(config) {
93
94
  return 2;
94
95
  return 0;
95
96
  }
96
- async function listModels(config, json) {
97
+ async function listModels(config, json, diff = false) {
97
98
  const apiKey = process.env[config.api_key_env]?.trim();
98
99
  if (!apiKey)
99
100
  throw new CPACError(`environment variable ${config.api_key_env} is not set`);
100
101
  const catalog = await fetchCatalog(config.cpa_url, apiKey);
102
+ if (diff) {
103
+ const index = readModelIndex(config.state_dir);
104
+ if (!index)
105
+ throw new CPACError("no saved model list; run cpac sync");
106
+ const { added, removed } = diffModelSlugs(index.models.map((model) => model.slug), canonicalModels(catalog.bytes).map((model) => model.slug));
107
+ if (json) {
108
+ console.log(JSON.stringify({ added, removed }, null, 2));
109
+ return 0;
110
+ }
111
+ if (added.length === 0 && removed.length === 0) {
112
+ console.log("unchanged");
113
+ return 0;
114
+ }
115
+ for (const slug of added)
116
+ console.log(`+ ${slug}`);
117
+ for (const slug of removed)
118
+ console.log(`- ${slug}`);
119
+ return 0;
120
+ }
101
121
  if (!json) {
102
122
  for (const slug of catalogSlugs(catalog.bytes))
103
123
  console.log(slug);
@@ -183,6 +203,7 @@ function usage() {
183
203
  "",
184
204
  "Command options:",
185
205
  opt("--json", "JSON output", "[models, detect]"),
206
+ opt("--diff", "models added or removed since the saved list", "[models]"),
186
207
  opt("--all", "every detected or installed agent", "[install, sync, restore]"),
187
208
  opt("--dry-run", "print actions without writing", "[install, sync, restore, uninstall]"),
188
209
  opt("--force", "allow reinstall of already-injected agents", "[install]"),
@@ -288,6 +309,11 @@ function parseArgs(args) {
288
309
  }
289
310
  if (arg === "--json")
290
311
  parsed.json = true;
312
+ else if (arg === "--diff") {
313
+ if (parsed.command !== "models")
314
+ throw new CPACError("--diff is only valid with models");
315
+ parsed.diff = true;
316
+ }
291
317
  else if (arg === "--all")
292
318
  parsed.all = true;
293
319
  else if (arg === "--dry-run")
@@ -654,7 +680,7 @@ export async function main(args = process.argv.slice(2)) {
654
680
  if (parsed.command === "guide")
655
681
  return await guide(config);
656
682
  if (parsed.command === "models")
657
- return await listModels(config, parsed.json);
683
+ return await listModels(config, parsed.json, parsed.diff === true);
658
684
  if (parsed.command === "detect")
659
685
  return await runDetect(config, parsed.json);
660
686
  if (parsed.command === "install") {
package/dist/models.js CHANGED
@@ -33,6 +33,14 @@ function stableValue(value) {
33
33
  stable[key] = stableValue(value[key]);
34
34
  return stable;
35
35
  }
36
+ export function diffModelSlugs(saved, live) {
37
+ const savedSet = new Set(saved);
38
+ const liveSet = new Set(live);
39
+ return {
40
+ added: live.filter((slug) => !savedSet.has(slug)),
41
+ removed: saved.filter((slug) => !liveSet.has(slug)),
42
+ };
43
+ }
36
44
  export function canonicalModels(bytes) {
37
45
  let document;
38
46
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yhong91/cpac",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Connect Codex and Claude Code to a remote CLIProxyAPI gateway",
5
5
  "type": "module",
6
6
  "bin": {