@yhong91/cpac 0.1.15 → 0.1.17
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 +2 -0
- package/dist/cpac.js +56 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -259,6 +259,8 @@ Codex App/CLI 发给本地代理的 ChatGPT bearer 不会转发到 CPA;代理
|
|
|
259
259
|
|
|
260
260
|
Codex App 的长驻 `app-server` 可能缓存旧目录。`inject` 会删除 `models_cache.json`;如果选择器仍未更新,请重启 Codex App。
|
|
261
261
|
|
|
262
|
+
注入命令可选 `--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 组合使用会直接报错。
|
|
263
|
+
|
|
262
264
|
第一次注入时,原文件按原始 bytes 备份到 `state_dir/config.toml.backup`。重复注入不会覆盖首次备份,并会保留 CPAC 管理字段之外的用户编辑。`restore` 按原 mode 逐字节恢复首次备份、关闭 CPAC loopback 代理;若原文件不存在,则删除注入创建的 `config.toml`。
|
|
263
265
|
|
|
264
266
|
loopback 代理是 detached 用户进程,不安装系统服务。机器重启或进程意外退出后,`cpac status` 会报告 `loopback proxy stopped`;重新执行 `cpac inject` 即可恢复。
|
package/dist/cpac.js
CHANGED
|
@@ -258,6 +258,29 @@ export async function fetchCatalog(cpaUrl, apiKey) {
|
|
|
258
258
|
modelCount: models.length,
|
|
259
259
|
};
|
|
260
260
|
}
|
|
261
|
+
// Codex treats a catalog model's context_window as its input budget, not a
|
|
262
|
+
// display label; upstream keeps it a conservative operating cap while
|
|
263
|
+
// max_context_window holds the real ceiling (gpt-5.6: 272k vs ~921k, measured
|
|
264
|
+
// by opencodex). Opt-in lift: raise context_window to max_context_window and
|
|
265
|
+
// set auto_compact_token_limit at 90% (Codex's own convention), keeping
|
|
266
|
+
// compaction ahead of the hard ceiling.
|
|
267
|
+
export function liftContextWindows(bytes) {
|
|
268
|
+
const document = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
269
|
+
for (const model of document.models) {
|
|
270
|
+
const maxWindow = typeof model.max_context_window === "number" &&
|
|
271
|
+
model.max_context_window > 0
|
|
272
|
+
? Math.floor(model.max_context_window)
|
|
273
|
+
: 0;
|
|
274
|
+
const window = typeof model.context_window === "number"
|
|
275
|
+
? Math.floor(model.context_window)
|
|
276
|
+
: 0;
|
|
277
|
+
if (maxWindow <= window)
|
|
278
|
+
continue;
|
|
279
|
+
model.context_window = maxWindow;
|
|
280
|
+
model.auto_compact_token_limit = Math.floor(maxWindow * 0.9);
|
|
281
|
+
}
|
|
282
|
+
return Buffer.from(`${JSON.stringify(document, null, 2)}\n`);
|
|
283
|
+
}
|
|
261
284
|
// Move `order` slugs to the front of the rich catalog (stable for the rest),
|
|
262
285
|
// so the Codex client's first-5 spawn_agent advertisement picks them.
|
|
263
286
|
export function reorderCatalog(bytes, order) {
|
|
@@ -1173,7 +1196,7 @@ function proxyFingerprint(config, apiKey) {
|
|
|
1173
1196
|
.update(apiKey)
|
|
1174
1197
|
.digest("hex");
|
|
1175
1198
|
}
|
|
1176
|
-
export async function inject(config, v2Off = false) {
|
|
1199
|
+
export async function inject(config, v2Off = false, maxContext = false) {
|
|
1177
1200
|
const apiKey = process.env[config.api_key_env]?.trim();
|
|
1178
1201
|
if (!apiKey)
|
|
1179
1202
|
throw new CPACError(`environment variable ${config.api_key_env} is not set`);
|
|
@@ -1211,6 +1234,8 @@ export async function inject(config, v2Off = false) {
|
|
|
1211
1234
|
const catalog = await fetchCatalog(config.cpa_url, apiKey);
|
|
1212
1235
|
if (config.spawn_models?.length)
|
|
1213
1236
|
catalog.bytes = reorderCatalog(catalog.bytes, config.spawn_models);
|
|
1237
|
+
if (maxContext)
|
|
1238
|
+
catalog.bytes = liftContextWindows(catalog.bytes);
|
|
1214
1239
|
const stateDirExisted = existsSync(config.state_dir);
|
|
1215
1240
|
if (!state &&
|
|
1216
1241
|
STATE_FILES.some((name) => existsSync(join(config.state_dir, name)))) {
|
|
@@ -1729,6 +1754,13 @@ export function isKimiConfigInstalled() {
|
|
|
1729
1754
|
function writeKimiBlock(path, block) {
|
|
1730
1755
|
let content = existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
1731
1756
|
content = content.replace(kimiBlockRegex, "");
|
|
1757
|
+
// A truncated managed block (start marker without the end marker) leaves its
|
|
1758
|
+
// tables behind; appending again would duplicate [providers.cpac], make the
|
|
1759
|
+
// file invalid TOML, and block `kimi login`. The block is always appended
|
|
1760
|
+
// last, so dropping from an orphaned start marker to EOF is safe.
|
|
1761
|
+
const orphan = content.indexOf(KIMI_BLOCK_START);
|
|
1762
|
+
if (orphan !== -1)
|
|
1763
|
+
content = content.slice(0, orphan);
|
|
1732
1764
|
if (block) {
|
|
1733
1765
|
content = `${content}${content && !content.endsWith("\n") ? "\n" : ""}${block}\n`;
|
|
1734
1766
|
}
|
|
@@ -1838,12 +1870,12 @@ const TARGETS = [
|
|
|
1838
1870
|
return false;
|
|
1839
1871
|
}
|
|
1840
1872
|
},
|
|
1841
|
-
install: async (config, dryRun, v2Off) => {
|
|
1873
|
+
install: async (config, dryRun, v2Off, maxContext) => {
|
|
1842
1874
|
if (dryRun) {
|
|
1843
1875
|
console.log("would inject CPA catalog and loopback proxy into Codex");
|
|
1844
1876
|
return;
|
|
1845
1877
|
}
|
|
1846
|
-
await inject(config, v2Off);
|
|
1878
|
+
await inject(config, v2Off, maxContext);
|
|
1847
1879
|
},
|
|
1848
1880
|
uninstall: async (config, dryRun) => {
|
|
1849
1881
|
if (dryRun) {
|
|
@@ -1927,12 +1959,17 @@ export async function runInstall(config, requested, options) {
|
|
|
1927
1959
|
if (selected.length === 0) {
|
|
1928
1960
|
throw new CPACError(`no supported targets detected; use --target ${TARGETS.map((target) => target.id).join(",")} or --all`);
|
|
1929
1961
|
}
|
|
1962
|
+
// Catalog context lifting is Codex-specific; refuse to silently skip it on
|
|
1963
|
+
// other targets so the flag never gains cross-agent meaning.
|
|
1964
|
+
if (options.maxContext && selected.some((target) => target.id !== "codex")) {
|
|
1965
|
+
throw new CPACError("--max_context is only valid with --target codex");
|
|
1966
|
+
}
|
|
1930
1967
|
for (const target of selected) {
|
|
1931
1968
|
if (target.installed(config) && !options.force) {
|
|
1932
1969
|
console.log(`${target.id}: already installed; use --force to reinstall`);
|
|
1933
1970
|
continue;
|
|
1934
1971
|
}
|
|
1935
|
-
await target.install(config, options.dryRun, options.v2Off);
|
|
1972
|
+
await target.install(config, options.dryRun, options.v2Off, options.maxContext);
|
|
1936
1973
|
}
|
|
1937
1974
|
return 0;
|
|
1938
1975
|
}
|
|
@@ -1998,7 +2035,7 @@ export async function runUpgrade(checkOnly) {
|
|
|
1998
2035
|
function usage() {
|
|
1999
2036
|
return [
|
|
2000
2037
|
"Usage: cpac",
|
|
2001
|
-
" cpac inject [--v2_off] [--v2_models] [--config PATH]",
|
|
2038
|
+
" cpac inject [--v2_off] [--v2_models] [--max_context] [--config PATH]",
|
|
2002
2039
|
" cpac <status|restore> [--config PATH]",
|
|
2003
2040
|
" cpac proxy [--config PATH]",
|
|
2004
2041
|
" cpac claude [--config PATH] [--] [claude args...]",
|
|
@@ -2007,7 +2044,7 @@ function usage() {
|
|
|
2007
2044
|
" cpac pi <install|uninstall|status> [--config PATH]",
|
|
2008
2045
|
" cpac kimi <install|uninstall|status> [--config PATH]",
|
|
2009
2046
|
" cpac detect [--json] [--home PATH]",
|
|
2010
|
-
" cpac install [--target codex,pi,kimi] [--all] [--dry-run] [--force] [--v2_off] [--v2_models] [--home PATH]",
|
|
2047
|
+
" cpac install [--target codex,pi,kimi] [--all] [--dry-run] [--force] [--v2_off] [--v2_models] [--max_context] [--home PATH]",
|
|
2011
2048
|
" cpac uninstall [--target codex,pi,kimi] [--all] [--dry-run] [--home PATH]",
|
|
2012
2049
|
" cpac upgrade [--check]",
|
|
2013
2050
|
" cpac version",
|
|
@@ -2036,6 +2073,7 @@ function parseArgs(args) {
|
|
|
2036
2073
|
check: false,
|
|
2037
2074
|
v2Off: false,
|
|
2038
2075
|
v2Models: false,
|
|
2076
|
+
maxContext: false,
|
|
2039
2077
|
};
|
|
2040
2078
|
for (let index = 1; index < args.length; index++) {
|
|
2041
2079
|
const arg = args[index];
|
|
@@ -2076,6 +2114,9 @@ function parseArgs(args) {
|
|
|
2076
2114
|
else if (arg === "--v2_models" || arg === "--v2-models") {
|
|
2077
2115
|
parsed.v2Models = true;
|
|
2078
2116
|
}
|
|
2117
|
+
else if (arg === "--max_context" || arg === "--max-context") {
|
|
2118
|
+
parsed.maxContext = true;
|
|
2119
|
+
}
|
|
2079
2120
|
else {
|
|
2080
2121
|
throw new CPACError(`unknown option: ${arg}`);
|
|
2081
2122
|
}
|
|
@@ -2187,6 +2228,7 @@ function parseArgs(args) {
|
|
|
2187
2228
|
const positional = [];
|
|
2188
2229
|
let v2Off = false;
|
|
2189
2230
|
let v2Models = false;
|
|
2231
|
+
let maxContext = false;
|
|
2190
2232
|
for (let index = 0; index < args.length; index += 1) {
|
|
2191
2233
|
if (args[index] === "--config") {
|
|
2192
2234
|
const value = args[++index];
|
|
@@ -2200,6 +2242,9 @@ function parseArgs(args) {
|
|
|
2200
2242
|
else if (args[index] === "--v2_models" || args[index] === "--v2-models") {
|
|
2201
2243
|
v2Models = true;
|
|
2202
2244
|
}
|
|
2245
|
+
else if (args[index] === "--max_context" || args[index] === "--max-context") {
|
|
2246
|
+
maxContext = true;
|
|
2247
|
+
}
|
|
2203
2248
|
else if (args[index].startsWith("-")) {
|
|
2204
2249
|
throw new CPACError(`unknown option: ${args[index]}`);
|
|
2205
2250
|
}
|
|
@@ -2210,11 +2255,11 @@ function parseArgs(args) {
|
|
|
2210
2255
|
!["inject", "status", "restore", "proxy"].includes(positional[0])) {
|
|
2211
2256
|
throw new CPACError(usage());
|
|
2212
2257
|
}
|
|
2213
|
-
if (positional[0] !== "inject" && (v2Off || v2Models)) {
|
|
2214
|
-
throw new CPACError("--v2_off / --v2_models is only valid with inject or install");
|
|
2258
|
+
if (positional[0] !== "inject" && (v2Off || v2Models || maxContext)) {
|
|
2259
|
+
throw new CPACError("--v2_off / --v2_models / --max_context is only valid with inject or install");
|
|
2215
2260
|
}
|
|
2216
2261
|
if (positional[0] === "inject") {
|
|
2217
|
-
return { command: "inject", configPath, v2Off, v2Models };
|
|
2262
|
+
return { command: "inject", configPath, v2Off, v2Models, maxContext };
|
|
2218
2263
|
}
|
|
2219
2264
|
return {
|
|
2220
2265
|
command: positional[0],
|
|
@@ -2252,6 +2297,7 @@ export async function main(args = process.argv.slice(2)) {
|
|
|
2252
2297
|
dryRun: parsed.dryRun,
|
|
2253
2298
|
force: parsed.force,
|
|
2254
2299
|
v2Off: parsed.v2Off,
|
|
2300
|
+
maxContext: parsed.maxContext,
|
|
2255
2301
|
});
|
|
2256
2302
|
}
|
|
2257
2303
|
if (parsed.command === "uninstall")
|
|
@@ -2285,7 +2331,7 @@ export async function main(args = process.argv.slice(2)) {
|
|
|
2285
2331
|
console.log(`spawn_models saved to ${parsed.configPath}: ${picked.join(", ")}`);
|
|
2286
2332
|
injectConfig = { ...config, spawn_models: picked };
|
|
2287
2333
|
}
|
|
2288
|
-
await inject(injectConfig, parsed.v2Off);
|
|
2334
|
+
await inject(injectConfig, parsed.v2Off, parsed.maxContext);
|
|
2289
2335
|
}
|
|
2290
2336
|
else if (parsed.command === "restore")
|
|
2291
2337
|
await restore(config);
|