open-claude-p 1.1.2 → 1.2.1
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/CHANGELOG.md +333 -0
- package/README.ja.md +5 -5
- package/README.ko.md +5 -5
- package/README.md +10 -5
- package/README.zh.md +5 -5
- package/bin/cli.js +85 -53
- package/package.json +1 -1
- package/src/chat/index.js +51 -2
- package/src/completion/detector.js +20 -1
- package/src/index.js +93 -11
- package/src/options/forward.js +70 -0
- package/src/options/index.js +1 -0
- package/src/options/parse-argv.js +73 -2
- package/src/options/spec.js +146 -6
- package/src/options/validate.js +41 -1
|
@@ -26,15 +26,20 @@ import { OPTION_SPEC, getOption } from './spec.js';
|
|
|
26
26
|
* @property {string[]} positional
|
|
27
27
|
* @property {string[]} unknown Tokens that look like flags but were not in the spec.
|
|
28
28
|
* @property {string[]} errors Human-readable error strings.
|
|
29
|
+
* @property {Set<string>} supplied Canonical names actually present in argv.
|
|
30
|
+
* Defaults are pre-seeded into `options`, so a value alone cannot tell
|
|
31
|
+
* "user passed `--flag=false`" apart from "user passed nothing" — this
|
|
32
|
+
* set is the only way to distinguish them.
|
|
29
33
|
*/
|
|
30
34
|
|
|
31
35
|
/**
|
|
32
36
|
* @param {string[]} argv
|
|
37
|
+
* @param {Record<string, string|undefined>} [env] defaults to `process.env`
|
|
33
38
|
* @returns {ParseResult}
|
|
34
39
|
*/
|
|
35
|
-
export function parseArgv(argv) {
|
|
40
|
+
export function parseArgv(argv, env = process.env) {
|
|
36
41
|
/** @type {ParseResult} */
|
|
37
|
-
const out = { options: {}, positional: [], unknown: [], errors: [] };
|
|
42
|
+
const out = { options: {}, positional: [], unknown: [], errors: [], supplied: new Set() };
|
|
38
43
|
|
|
39
44
|
// Pre-seed defaults so the validator sees them.
|
|
40
45
|
for (const spec of OPTION_SPEC) {
|
|
@@ -43,6 +48,14 @@ export function parseArgv(argv) {
|
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
// Canonical names supplied on the command line. Used only by the
|
|
52
|
+
// env-var pass at the end: argv always wins over the environment, and
|
|
53
|
+
// that has to include an explicit opt-out like `--print-mode=false`,
|
|
54
|
+
// whose value is indistinguishable from the default if you compare
|
|
55
|
+
// values instead of tracking what was actually seen.
|
|
56
|
+
/** @type {Set<string>} */
|
|
57
|
+
const supplied = out.supplied;
|
|
58
|
+
|
|
46
59
|
let i = 0;
|
|
47
60
|
while (i < argv.length) {
|
|
48
61
|
const tok = argv[i];
|
|
@@ -63,6 +76,7 @@ export function parseArgv(argv) {
|
|
|
63
76
|
i++;
|
|
64
77
|
continue;
|
|
65
78
|
}
|
|
79
|
+
supplied.add(spec.name);
|
|
66
80
|
i = consumeOption(spec, argv, i, inline, out);
|
|
67
81
|
continue;
|
|
68
82
|
}
|
|
@@ -93,11 +107,13 @@ export function parseArgv(argv) {
|
|
|
93
107
|
);
|
|
94
108
|
break;
|
|
95
109
|
}
|
|
110
|
+
supplied.add(spec.name);
|
|
96
111
|
i = consumeOption(spec, argv, i, undefined, out);
|
|
97
112
|
consumedByValue = true;
|
|
98
113
|
break;
|
|
99
114
|
}
|
|
100
115
|
// Boolean short: just set.
|
|
116
|
+
supplied.add(spec.name);
|
|
101
117
|
out.options[spec.name] = true;
|
|
102
118
|
}
|
|
103
119
|
if (!consumedByValue) i++;
|
|
@@ -109,9 +125,64 @@ export function parseArgv(argv) {
|
|
|
109
125
|
i++;
|
|
110
126
|
}
|
|
111
127
|
|
|
128
|
+
applyEnvFallbacks(out, supplied, env);
|
|
129
|
+
|
|
112
130
|
return out;
|
|
113
131
|
}
|
|
114
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Fill in options that were not supplied on the command line from their
|
|
135
|
+
* declared `env:` variable.
|
|
136
|
+
*
|
|
137
|
+
* OPTION_SPEC has always documented an `env` field, but nothing read it —
|
|
138
|
+
* the two entries that used it (`--print-mode`, `--no-session-persistence`)
|
|
139
|
+
* were wired up by hand at their call sites instead, so any new entry that
|
|
140
|
+
* declared `env` silently did nothing. This makes the declaration real, and
|
|
141
|
+
* keeps the precedence the hand-rolled versions already used:
|
|
142
|
+
*
|
|
143
|
+
* explicit argv > environment variable > spec default
|
|
144
|
+
*
|
|
145
|
+
* Booleans accept `1` / `true` / `yes` / `on` (case-insensitive); anything
|
|
146
|
+
* else, including the empty string, leaves the option at its default so
|
|
147
|
+
* `VAR=` and `VAR=0` both read as "off". Value-taking options are coerced
|
|
148
|
+
* through the same `coerce()` path as argv, and a malformed value produces
|
|
149
|
+
* the same style of error rather than being silently ignored.
|
|
150
|
+
*
|
|
151
|
+
* @param {ParseResult} out
|
|
152
|
+
* @param {Set<string>} supplied canonical names seen on the command line
|
|
153
|
+
* @param {Record<string, string|undefined>} env
|
|
154
|
+
*/
|
|
155
|
+
function applyEnvFallbacks(out, supplied, env) {
|
|
156
|
+
for (const spec of OPTION_SPEC) {
|
|
157
|
+
if (!spec.env) continue;
|
|
158
|
+
const raw = Object.prototype.hasOwnProperty.call(env ?? {}, spec.env)
|
|
159
|
+
? env[spec.env]
|
|
160
|
+
: undefined;
|
|
161
|
+
// Library callers can pass any object as `env`; only honour real
|
|
162
|
+
// string values so a stray number/object cannot throw in `.trim()`.
|
|
163
|
+
if (typeof raw !== 'string' || raw === '') continue;
|
|
164
|
+
// Supplied on the command line — argv always wins.
|
|
165
|
+
if (supplied.has(spec.name)) continue;
|
|
166
|
+
|
|
167
|
+
if (spec.kind === 'boolean') {
|
|
168
|
+
const v = raw.trim().toLowerCase();
|
|
169
|
+
if (v === '1' || v === 'true' || v === 'yes' || v === 'on') {
|
|
170
|
+
out.options[spec.name] = true;
|
|
171
|
+
}
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (spec.kind === 'array') {
|
|
175
|
+
// Comma-separated, so a single env var can carry a repeatable flag.
|
|
176
|
+
const items = raw.split(',').map((x) => x.trim()).filter(Boolean);
|
|
177
|
+
if (items.length > 0) out.options[spec.name] = items;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const { value, error } = coerce(spec, raw);
|
|
181
|
+
if (error) out.errors.push(`${spec.env}: ${error}`);
|
|
182
|
+
else out.options[spec.name] = value;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
115
186
|
/**
|
|
116
187
|
* Consume the value(s) for `spec` starting at argv index `i` (where argv[i]
|
|
117
188
|
* is the flag token itself). `inline` is the post-`=` value when present.
|
package/src/options/spec.js
CHANGED
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
// times (occurrences accumulate); array kind also collects
|
|
18
18
|
// variadic values until the next flag-looking token.
|
|
19
19
|
// env: Optional environment-variable fallback.
|
|
20
|
+
// printModeOnly: Only forward this flag when running under
|
|
21
|
+
// `--print-mode`. For upstream flags that require
|
|
22
|
+
// `--print` and abort the process without it.
|
|
20
23
|
// description: One-line help text.
|
|
21
24
|
// forward: How this option reaches the upstream `claude` process.
|
|
22
25
|
// { type: 'argv', flag: '--name' } pass to spawn argv
|
|
@@ -72,7 +75,11 @@ export const OPTION_SPEC = [
|
|
|
72
75
|
{
|
|
73
76
|
name: 'model',
|
|
74
77
|
kind: 'string',
|
|
75
|
-
description:
|
|
78
|
+
description:
|
|
79
|
+
'Model alias or full name. Aliases resolve to the latest model in ' +
|
|
80
|
+
'that family (e.g. `fable`, `opus`, `sonnet`, `haiku`); full names ' +
|
|
81
|
+
'are passed through verbatim (e.g. `claude-opus-5`, ' +
|
|
82
|
+
'`claude-fable-5-1`, `claude-sonnet-5`).',
|
|
76
83
|
forward: { type: 'argv', flag: '--model' },
|
|
77
84
|
},
|
|
78
85
|
{
|
|
@@ -225,6 +232,24 @@ export const OPTION_SPEC = [
|
|
|
225
232
|
'(stream-json input + output only).',
|
|
226
233
|
forward: { type: 'shim' },
|
|
227
234
|
},
|
|
235
|
+
{
|
|
236
|
+
name: 'forward-subagent-text',
|
|
237
|
+
kind: 'boolean',
|
|
238
|
+
default: false,
|
|
239
|
+
description:
|
|
240
|
+
'Forward subagent text and thinking blocks as assistant/user messages ' +
|
|
241
|
+
'with `parent_tool_use_id` set. Requires `--output-format=stream-json`.',
|
|
242
|
+
forward: { type: 'argv', flag: '--forward-subagent-text' },
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
name: 'prompt-suggestions',
|
|
246
|
+
kind: 'boolean',
|
|
247
|
+
default: false,
|
|
248
|
+
description:
|
|
249
|
+
'Emit a `prompt_suggestion` message after each turn carrying a ' +
|
|
250
|
+
'predicted next user prompt (stream-json output).',
|
|
251
|
+
forward: { type: 'argv', flag: '--prompt-suggestions' },
|
|
252
|
+
},
|
|
228
253
|
{
|
|
229
254
|
name: 'include-hook-events',
|
|
230
255
|
kind: 'boolean',
|
|
@@ -236,7 +261,18 @@ export const OPTION_SPEC = [
|
|
|
236
261
|
name: 'include-partial-messages',
|
|
237
262
|
kind: 'boolean',
|
|
238
263
|
default: false,
|
|
239
|
-
|
|
264
|
+
// Upstream refuses this flag unless it is also given `--print`
|
|
265
|
+
// ("Error: --include-partial-messages requires --print and
|
|
266
|
+
// --output-format=stream-json") and exits immediately. The default
|
|
267
|
+
// PTY path drives the interactive TUI, so forwarding it there kills
|
|
268
|
+
// the spawn. ocp already synthesises `assistant-partial` events from
|
|
269
|
+
// the TUI frames on that path, so the flag has nothing to add there
|
|
270
|
+
// anyway — it is forwarded only under `--print-mode`.
|
|
271
|
+
printModeOnly: true,
|
|
272
|
+
description:
|
|
273
|
+
'Include partial assistant message chunks in stream-json output. ' +
|
|
274
|
+
'Forwarded upstream only under `--print-mode`; on the default PTY ' +
|
|
275
|
+
'path ocp emits `assistant-partial` events itself.',
|
|
240
276
|
forward: { type: 'argv', flag: '--include-partial-messages' },
|
|
241
277
|
},
|
|
242
278
|
|
|
@@ -244,8 +280,11 @@ export const OPTION_SPEC = [
|
|
|
244
280
|
{
|
|
245
281
|
name: 'effort',
|
|
246
282
|
kind: 'enum',
|
|
247
|
-
choices: ['low', 'medium', 'high', 'max'],
|
|
248
|
-
description:
|
|
283
|
+
choices: ['low', 'medium', 'high', 'xhigh', 'max'],
|
|
284
|
+
description:
|
|
285
|
+
'Effort level the model should apply (`low` | `medium` | `high` | ' +
|
|
286
|
+
'`xhigh` | `max`). `xhigh` sits between `high` and `max` and is the ' +
|
|
287
|
+
'upstream default for coding and agentic work.',
|
|
249
288
|
forward: { type: 'argv', flag: '--effort' },
|
|
250
289
|
},
|
|
251
290
|
{
|
|
@@ -281,6 +320,14 @@ export const OPTION_SPEC = [
|
|
|
281
320
|
description: 'API-side task budget in tokens. Shim-enforced.',
|
|
282
321
|
forward: { type: 'shim' },
|
|
283
322
|
},
|
|
323
|
+
{
|
|
324
|
+
name: 'autocompact',
|
|
325
|
+
kind: 'string',
|
|
326
|
+
description:
|
|
327
|
+
'Auto-compact window size: `auto`, or an explicit token budget ' +
|
|
328
|
+
'between 100k and 1M (e.g. `200000`, `500k`).',
|
|
329
|
+
forward: { type: 'argv', flag: '--autocompact' },
|
|
330
|
+
},
|
|
284
331
|
{
|
|
285
332
|
name: 'fallback-model',
|
|
286
333
|
kind: 'string',
|
|
@@ -293,8 +340,10 @@ export const OPTION_SPEC = [
|
|
|
293
340
|
name: 'permission-mode',
|
|
294
341
|
kind: 'string',
|
|
295
342
|
description:
|
|
296
|
-
'Permission mode (`
|
|
297
|
-
'`
|
|
343
|
+
'Permission mode (`acceptEdits` | `auto` | `bypassPermissions` | ' +
|
|
344
|
+
'`manual` | `dontAsk` | `plan`). `manual` is the current name for ' +
|
|
345
|
+
"the interactive prompt-on-every-tool mode; upstream still accepts " +
|
|
346
|
+
'the older `default` spelling, so ocp keeps accepting it too.',
|
|
298
347
|
forward: { type: 'argv', flag: '--permission-mode' },
|
|
299
348
|
},
|
|
300
349
|
{
|
|
@@ -305,6 +354,35 @@ export const OPTION_SPEC = [
|
|
|
305
354
|
'Allow `--dangerously-skip-permissions` as a choice without enabling it.',
|
|
306
355
|
forward: { type: 'argv', flag: '--allow-dangerously-skip-permissions' },
|
|
307
356
|
},
|
|
357
|
+
{
|
|
358
|
+
name: 'permission-prompts',
|
|
359
|
+
kind: 'enum',
|
|
360
|
+
choices: ['host', 'none'],
|
|
361
|
+
description:
|
|
362
|
+
'Who answers permission prompts: `host` (the SDK host, or the tool ' +
|
|
363
|
+
'named by `--permission-prompt-tool`) or `none` (nobody — anything ' +
|
|
364
|
+
'that would prompt is denied automatically; the permission mode ' +
|
|
365
|
+
'still decides everything else). `none` suits PTY automation, which ' +
|
|
366
|
+
'has no way to answer a prompt, when denying is preferable to ' +
|
|
367
|
+
'bypassing checks outright.',
|
|
368
|
+
forward: { type: 'argv', flag: '--permission-prompts' },
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
name: 'restricted',
|
|
372
|
+
kind: 'boolean',
|
|
373
|
+
default: false,
|
|
374
|
+
description:
|
|
375
|
+
'Restricted mode: drop the built-in tools that run commands or code ' +
|
|
376
|
+
'(Bash, PowerShell, REPL, …) and WebFetch unless `--tools` names ' +
|
|
377
|
+
'them, ignore user/project/local settings files (managed settings ' +
|
|
378
|
+
'and `--settings` still apply), confine the file tools to the ' +
|
|
379
|
+
'working directories, and refuse `bypassPermissions`. Pair with ' +
|
|
380
|
+
'`--strict-mcp-config` to skip MCP servers too. Note that ocp does ' +
|
|
381
|
+
'not get its usual clean transcript in this mode — no session ' +
|
|
382
|
+
'JSONL is written for the run, so the reply is reconstructed from ' +
|
|
383
|
+
'the TUI frames and may carry leftover box-border chrome.',
|
|
384
|
+
forward: { type: 'argv', flag: '--restricted' },
|
|
385
|
+
},
|
|
308
386
|
{
|
|
309
387
|
name: 'tools',
|
|
310
388
|
kind: 'string',
|
|
@@ -353,6 +431,29 @@ export const OPTION_SPEC = [
|
|
|
353
431
|
description: 'Append to the system prompt from a file path.',
|
|
354
432
|
forward: { type: 'argv', flag: '--append-system-prompt-file' },
|
|
355
433
|
},
|
|
434
|
+
{
|
|
435
|
+
name: 'system-prompt-snapshot',
|
|
436
|
+
kind: 'enum',
|
|
437
|
+
choices: ['on', 'off'],
|
|
438
|
+
description:
|
|
439
|
+
'Record the system prompt once per conversation and reuse it ' +
|
|
440
|
+
'verbatim on every later request and resume (`on`, the upstream ' +
|
|
441
|
+
'default), or render it fresh every request (`off`, for iterating ' +
|
|
442
|
+
'on prompt text). With `on`, a later run passing different prompt ' +
|
|
443
|
+
'text is ignored until the conversation is compacted.',
|
|
444
|
+
forward: { type: 'argv', flag: '--system-prompt-snapshot' },
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
name: 'exclude-dynamic-system-prompt-sections',
|
|
448
|
+
kind: 'boolean',
|
|
449
|
+
default: false,
|
|
450
|
+
description:
|
|
451
|
+
'Move per-machine sections (cwd, env info, memory paths, git status) ' +
|
|
452
|
+
'out of the system prompt and into the first user message, so the ' +
|
|
453
|
+
'cached prompt prefix is identical across machines and users. Ignored ' +
|
|
454
|
+
'when `--system-prompt` replaces the default prompt.',
|
|
455
|
+
forward: { type: 'argv', flag: '--exclude-dynamic-system-prompt-sections' },
|
|
456
|
+
},
|
|
356
457
|
{
|
|
357
458
|
name: 'add-dir',
|
|
358
459
|
kind: 'array',
|
|
@@ -387,6 +488,13 @@ export const OPTION_SPEC = [
|
|
|
387
488
|
description: 'Load plugins from directory (repeatable).',
|
|
388
489
|
forward: { type: 'argv', flag: '--plugin-dir' },
|
|
389
490
|
},
|
|
491
|
+
{
|
|
492
|
+
name: 'plugin-url',
|
|
493
|
+
kind: 'array',
|
|
494
|
+
repeatable: true,
|
|
495
|
+
description: 'Fetch a plugin `.zip` from a URL for this session only (repeatable).',
|
|
496
|
+
forward: { type: 'argv', flag: '--plugin-url' },
|
|
497
|
+
},
|
|
390
498
|
{
|
|
391
499
|
name: 'disable-slash-commands',
|
|
392
500
|
kind: 'boolean',
|
|
@@ -455,6 +563,38 @@ export const OPTION_SPEC = [
|
|
|
455
563
|
description: 'Run Setup hooks with the `maintenance` trigger, then continue.',
|
|
456
564
|
forward: { type: 'argv', flag: '--maintenance' },
|
|
457
565
|
},
|
|
566
|
+
{
|
|
567
|
+
name: 'safe-mode',
|
|
568
|
+
kind: 'boolean',
|
|
569
|
+
default: false,
|
|
570
|
+
description:
|
|
571
|
+
'Start with all customizations disabled (CLAUDE.md, skills, plugins, ' +
|
|
572
|
+
'hooks, MCP servers, custom commands and agents, output styles, ' +
|
|
573
|
+
'workflows, themes, keybindings). Admin policy settings still apply. ' +
|
|
574
|
+
'Sets `CLAUDE_CODE_SAFE_MODE=1`. Useful for reproducing a failure ' +
|
|
575
|
+
'without local configuration in the way.',
|
|
576
|
+
forward: { type: 'argv', flag: '--safe-mode' },
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
name: 'ax-screen-reader',
|
|
580
|
+
kind: 'boolean',
|
|
581
|
+
default: false,
|
|
582
|
+
env: 'OCP_AX_SCREEN_READER',
|
|
583
|
+
description:
|
|
584
|
+
'Ask the upstream TUI for screen-reader friendly output: flat text, ' +
|
|
585
|
+
'no decorative borders, no animations. Because ocp reconstructs its ' +
|
|
586
|
+
'answer by scraping TUI frames, this markedly reduces the amount of ' +
|
|
587
|
+
'chrome the parsers have to strip. Opt-in — it changes the captured ' +
|
|
588
|
+
'frame shape, so it is never enabled by default.',
|
|
589
|
+
forward: { type: 'argv', flag: '--ax-screen-reader' },
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
name: 'brief',
|
|
593
|
+
kind: 'boolean',
|
|
594
|
+
default: false,
|
|
595
|
+
description: 'Enable the SendUserMessage tool for agent-to-user communication.',
|
|
596
|
+
forward: { type: 'argv', flag: '--brief' },
|
|
597
|
+
},
|
|
458
598
|
{
|
|
459
599
|
name: 'debug-file',
|
|
460
600
|
kind: 'string',
|
package/src/options/validate.js
CHANGED
|
@@ -8,8 +8,14 @@
|
|
|
8
8
|
// Rules are appended to `CROSS_RULES`; the runner returns the concatenated
|
|
9
9
|
// list of human-readable errors.
|
|
10
10
|
|
|
11
|
+
// Upstream (`claude --permission-mode`) advertises: acceptEdits, auto,
|
|
12
|
+
// bypassPermissions, manual, dontAsk, plan. `manual` is the current name
|
|
13
|
+
// for the prompt-on-every-tool mode that used to be spelled `default`;
|
|
14
|
+
// upstream still accepts `default`, so we keep it here rather than
|
|
15
|
+
// breaking callers that pass it.
|
|
11
16
|
const PERMISSION_MODES = new Set([
|
|
12
|
-
'
|
|
17
|
+
'acceptEdits', 'auto', 'bypassPermissions', 'manual', 'dontAsk', 'plan',
|
|
18
|
+
'default',
|
|
13
19
|
]);
|
|
14
20
|
|
|
15
21
|
/** @type {Array<(options: Record<string, unknown>) => string | undefined>} */
|
|
@@ -85,6 +91,40 @@ export const CROSS_RULES = [
|
|
|
85
91
|
return '`--fork-session` requires `--resume <id>` or `--continue`.';
|
|
86
92
|
}
|
|
87
93
|
},
|
|
94
|
+
// R11. forward-subagent-text => stream-json output. Upstream only emits
|
|
95
|
+
// the extra assistant/user messages on the stream-json channel.
|
|
96
|
+
(o) => {
|
|
97
|
+
if (o['forward-subagent-text'] === true && o['output-format'] !== 'stream-json') {
|
|
98
|
+
return '`--forward-subagent-text` requires `--output-format=stream-json`.';
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
// R12. prompt-suggestions => stream-json output. The suggestion arrives
|
|
102
|
+
// as its own `prompt_suggestion` event; the text and json adapters
|
|
103
|
+
// have nowhere to put it.
|
|
104
|
+
(o) => {
|
|
105
|
+
if (o['prompt-suggestions'] === true && o['output-format'] !== 'stream-json') {
|
|
106
|
+
return '`--prompt-suggestions` requires `--output-format=stream-json`.';
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
// R13. autocompact takes `auto` or a token budget in the 100k–1M range.
|
|
110
|
+
// Accepts a bare integer or a `k`/`m` suffix.
|
|
111
|
+
(o) => {
|
|
112
|
+
const v = o.autocompact;
|
|
113
|
+
if (v === undefined) return undefined;
|
|
114
|
+
if (typeof v !== 'string' || v === '') {
|
|
115
|
+
return '`--autocompact` must be `auto` or a token budget between 100k and 1M.';
|
|
116
|
+
}
|
|
117
|
+
if (v === 'auto') return undefined;
|
|
118
|
+
const m = /^(\d+(?:\.\d+)?)([km])?$/i.exec(v.trim());
|
|
119
|
+
if (!m) {
|
|
120
|
+
return `\`--autocompact\` must be \`auto\` or a token budget between 100k and 1M; got ${JSON.stringify(v)}.`;
|
|
121
|
+
}
|
|
122
|
+
const mult = m[2] ? { k: 1e3, m: 1e6 }[m[2].toLowerCase()] : 1;
|
|
123
|
+
const tokens = Number(m[1]) * mult;
|
|
124
|
+
if (!(tokens >= 100_000 && tokens <= 1_000_000)) {
|
|
125
|
+
return `\`--autocompact\` token budget must be between 100k and 1M; got ${JSON.stringify(v)}.`;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
88
128
|
];
|
|
89
129
|
|
|
90
130
|
/**
|