@yhong91/cpac 0.1.29 → 0.1.30

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
@@ -248,7 +248,7 @@ Codex App 的长驻 `app-server` 可能缓存旧目录。`inject` 会删除 `mod
248
248
 
249
249
  注入命令可选 `--max_context`(`cpac inject --max_context` 或 `cpac install --target codex --max_context`,默认不带):把 catalog 中 `max_context_window` 高于 `context_window` 的模型提升到上限,并把 `auto_compact_token_limit` 设为上限的 90%。Codex 把 `context_window` 当输入预算而非展示标签,上游默认保留保守运营值(如 GPT-5.6 家族 272k),带上该参数后可用到实测上限(约 921k,opencodex 实测);90% 压缩线确保在硬上限前触发 auto-compact。不带参数注入的仍是原本上下文的目录。该参数仅限 codex,与其他 target 组合使用会直接报错。
250
250
 
251
- 第一次注入时,原文件按原始 bytes 备份到 `state_dir/config.toml.backup`。重复注入不会覆盖首次备份,并会保留 CPAC 管理字段之外的用户编辑。`restore`:若 `config.toml` 相对首次注入未改,按原 mode 逐字节还原备份;若用户在注入期间改过文件,只撤掉 CPAC 写入的 catalog、url 和标记。原先没有 `config.toml` 且撤掉后为空则删除文件。关闭 CPAC loopback 代理。
251
+ 第一次注入时,原文件按原始 bytes 备份到 `state_dir/codex/config.toml`。重复注入不会覆盖首次备份,并会保留 CPAC 管理字段之外的用户编辑。`restore`:若 `config.toml` 相对首次注入未改,按原 mode 逐字节还原备份;若用户在注入期间改过文件,只撤掉 CPAC 写入的 catalog、url 和标记。原先没有 `config.toml` 且撤掉后为空则删除文件。关闭 CPAC loopback 代理。
252
252
 
253
253
  loopback 代理是 detached 用户进程,不安装系统服务。机器重启或进程意外退出后,`cpac status` 会报告 `loopback proxy stopped`;重新执行 `cpac inject` 即可恢复。
254
254
 
@@ -265,6 +265,11 @@ cpac proxy
265
265
  ```text
266
266
  Codex 配置:$CODEX_HOME/config.toml,未设置 CODEX_HOME 时为 ~/.codex/config.toml
267
267
  CPAC state:~/.cpac
268
+ 各 agent 配置备份:~/.cpac/<agent>/<原文件名>
269
+ Codex ~/.cpac/codex/config.toml
270
+ Pi ~/.cpac/pi/pi-cpac.ts
271
+ Kimi ~/.cpac/kimi/config.toml
272
+ Grok ~/.cpac/grok/config.toml
268
273
  ```
269
274
 
270
275
  为防止误删或覆盖,`state_dir` 不能是文件系统根目录、用户 home、系统临时目录,也不能包含 Codex 配置文件。
@@ -307,7 +312,7 @@ cpac kimi install
307
312
  cpac restore --target kimi
308
313
  ```
309
314
 
310
- Kimi Code 配置目录尊重 `KIMI_CODE_HOME` 环境变量。首次写入前若 `config.toml` 已存在,会在同目录保留一份原始快照 `config.toml.cpac-backup`(只存最早版本),万一文件损坏可手动复制回去。
315
+ Kimi Code 配置目录尊重 `KIMI_CODE_HOME` 环境变量。首次写入前若 `config.toml` 已存在,会在 `state_dir/kimi/config.toml` 保留一份原始快照(只存最早版本),万一文件损坏可手动复制回去。
311
316
 
312
317
  ## 环境变量
313
318
 
package/dist/config.js CHANGED
@@ -452,7 +452,9 @@ export function originalBytes(stateDir, state, expectedPath) {
452
452
  if (!state.config_existed)
453
453
  return new Uint8Array();
454
454
  try {
455
- return readFileSync(join(stateDir, "config.toml.backup"));
455
+ const next = join(stateDir, "codex", "config.toml");
456
+ const prev = join(stateDir, "config.toml.backup");
457
+ return readFileSync(existsSync(next) ? next : prev);
456
458
  }
457
459
  catch (error) {
458
460
  throw new CPACError(`cannot read original config backup: ${error instanceof Error ? error.message : String(error)}`);
@@ -461,6 +463,15 @@ export function originalBytes(stateDir, state, expectedPath) {
461
463
  export function cleanupStateFiles(stateDir) {
462
464
  for (const name of STATE_FILES)
463
465
  rmSync(join(stateDir, name), { force: true });
466
+ rmSync(join(stateDir, "codex", "config.toml"), { force: true });
467
+ try {
468
+ rmdirSync(join(stateDir, "codex"));
469
+ }
470
+ catch (error) {
471
+ const code = error.code;
472
+ if (code !== "ENOENT" && code !== "ENOTEMPTY" && code !== "EEXIST")
473
+ throw error;
474
+ }
464
475
  try {
465
476
  rmdirSync(stateDir);
466
477
  }
@@ -286,7 +286,8 @@ export async function inject(config, v2Off = false, maxContext = false) {
286
286
  catalog.bytes = liftContextWindows(catalog.bytes);
287
287
  const stateDirExisted = existsSync(config.state_dir);
288
288
  if (!state &&
289
- STATE_FILES.some((name) => existsSync(join(config.state_dir, name)))) {
289
+ (STATE_FILES.some((name) => existsSync(join(config.state_dir, name))) ||
290
+ existsSync(join(config.state_dir, "codex", "config.toml")))) {
290
291
  throw new CPACError("state_dir contains CPAC files without a valid state; refusing to overwrite them");
291
292
  }
292
293
  const fingerprint = proxyFingerprint(config, apiKey);
@@ -350,7 +351,7 @@ export async function inject(config, v2Off = false, maxContext = false) {
350
351
  let configWritten = false;
351
352
  try {
352
353
  if (existed)
353
- atomicWrite(join(config.state_dir, "config.toml.backup"), original);
354
+ atomicWrite(join(config.state_dir, "codex", "config.toml"), original);
354
355
  atomicWrite(catalogPath, catalog.bytes);
355
356
  atomicWrite(config.codex_config, injected, originalMode);
356
357
  configWritten = true;
@@ -93,7 +93,7 @@ export async function installGrokConfig(config) {
93
93
  lines.pop();
94
94
  lines.push(GROK_BLOCK_END);
95
95
  const target = grokConfigPath();
96
- ensureCpacBackup(target);
96
+ ensureCpacBackup(config.state_dir, "grok", target);
97
97
  writeGrokBlock(target, lines.join("\n"));
98
98
  console.log(`Installed Grok Build provider config: ${target}`);
99
99
  if (!recorded || !(await proxyIsHealthy(recorded))) {
@@ -159,7 +159,7 @@ export async function installKimiConfig(config) {
159
159
  }
160
160
  lines.push(KIMI_BLOCK_END);
161
161
  const target = kimiConfigPath();
162
- ensureCpacBackup(target);
162
+ ensureCpacBackup(config.state_dir, "kimi", target);
163
163
  writeKimiBlock(target, lines.join("\n"));
164
164
  console.log(`Installed Kimi Code provider config: ${target}`);
165
165
  if (!recorded || !(await proxyIsHealthy(recorded))) {
@@ -20,7 +20,7 @@ export async function installPiExtension(config) {
20
20
  const dir = piExtensionsDir();
21
21
  mkdirSync(dir, { recursive: true, mode: 0o700 });
22
22
  const target = join(dir, "pi-cpac.ts");
23
- ensureCpacBackup(target);
23
+ ensureCpacBackup(config.state_dir, "pi", target);
24
24
  atomicWrite(target, Buffer.from(piExtensionContent(config.cpa_url)), 0o644);
25
25
  for (const legacy of ["cpac.ts", "pi-cpa.ts"]) {
26
26
  const legacyPath = join(dir, legacy);
package/dist/util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { chmodSync, closeSync, copyFileSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
2
2
  import { homedir } from "node:os";
3
- import { dirname, join, parse } from "node:path";
3
+ import { basename, dirname, join, parse } from "node:path";
4
4
  import { createInterface } from "node:readline/promises";
5
5
  import { Writable } from "node:stream";
6
6
  let atomicSequence = 0;
@@ -9,13 +9,28 @@ export class CPACError extends Error {
9
9
  export function objectValue(value) {
10
10
  return typeof value === "object" && value !== null && !Array.isArray(value);
11
11
  }
12
- export function ensureCpacBackup(target) {
13
- if (!existsSync(target))
14
- return;
15
- const backup = `${target}.cpac-backup`;
16
- if (existsSync(backup))
17
- return;
18
- copyFileSync(target, backup);
12
+ export function ensureCpacBackup(stateDir, agent, target) {
13
+ const dest = join(stateDir, agent, basename(target));
14
+ const sidecar = `${target}.cpac-backup`;
15
+ if (!existsSync(dest)) {
16
+ const source = existsSync(sidecar)
17
+ ? sidecar
18
+ : existsSync(target)
19
+ ? target
20
+ : null;
21
+ if (!source)
22
+ return;
23
+ mkdirSync(dirname(dest), { recursive: true, mode: 0o700 });
24
+ try {
25
+ chmodSync(stateDir, 0o700);
26
+ }
27
+ catch {
28
+ // Directory may already have the desired mode.
29
+ }
30
+ copyFileSync(source, dest);
31
+ }
32
+ if (existsSync(sidecar))
33
+ unlinkSync(sidecar);
19
34
  }
20
35
  export function expandUserPath(value) {
21
36
  if (value === "~")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yhong91/cpac",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "description": "Connect Codex and Claude Code to a remote CLIProxyAPI gateway",
5
5
  "type": "module",
6
6
  "bin": {