compact-agent 1.31.2 → 1.32.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/dist/command-palette.d.ts +21 -0
- package/dist/command-palette.js +106 -0
- package/dist/command-palette.js.map +1 -0
- package/dist/index.js +215 -6
- package/dist/index.js.map +1 -1
- package/dist/openrouter-models.d.ts +44 -0
- package/dist/openrouter-models.js +112 -0
- package/dist/openrouter-models.js.map +1 -0
- package/dist/picker.d.ts +34 -0
- package/dist/picker.js +225 -0
- package/dist/picker.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command palette catalog — the slash commands exposed via the
|
|
3
|
+
* Space-at-empty quick picker. Hand-curated rather than auto-
|
|
4
|
+
* extracted from handleSlashCommand's switch, because:
|
|
5
|
+
*
|
|
6
|
+
* 1. The switch contains alias arms (/branch → /fork, /quit → /exit,
|
|
7
|
+
* etc.) that would clutter a UI listing.
|
|
8
|
+
* 2. Some commands are internal sentinels (__DICTATE__, __SWARM__)
|
|
9
|
+
* that should never appear to users.
|
|
10
|
+
* 3. Curating gives us a tight description column for each entry —
|
|
11
|
+
* the picker shows label + hint + description, and a hand-
|
|
12
|
+
* written one-liner is more scannable than a parsed comment.
|
|
13
|
+
*
|
|
14
|
+
* Categories mirror /help's grouping so muscle memory transfers.
|
|
15
|
+
*/
|
|
16
|
+
export interface CommandEntry {
|
|
17
|
+
command: string;
|
|
18
|
+
description: string;
|
|
19
|
+
category: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const COMMAND_CATALOG: CommandEntry[];
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command palette catalog — the slash commands exposed via the
|
|
3
|
+
* Space-at-empty quick picker. Hand-curated rather than auto-
|
|
4
|
+
* extracted from handleSlashCommand's switch, because:
|
|
5
|
+
*
|
|
6
|
+
* 1. The switch contains alias arms (/branch → /fork, /quit → /exit,
|
|
7
|
+
* etc.) that would clutter a UI listing.
|
|
8
|
+
* 2. Some commands are internal sentinels (__DICTATE__, __SWARM__)
|
|
9
|
+
* that should never appear to users.
|
|
10
|
+
* 3. Curating gives us a tight description column for each entry —
|
|
11
|
+
* the picker shows label + hint + description, and a hand-
|
|
12
|
+
* written one-liner is more scannable than a parsed comment.
|
|
13
|
+
*
|
|
14
|
+
* Categories mirror /help's grouping so muscle memory transfers.
|
|
15
|
+
*/
|
|
16
|
+
export const COMMAND_CATALOG = [
|
|
17
|
+
// ── General ──
|
|
18
|
+
{ command: '/help', description: 'Show the full command reference', category: 'General' },
|
|
19
|
+
{ command: '/clear', description: 'Reset the conversation (also resets side-channel state)', category: 'General' },
|
|
20
|
+
{ command: '/back', description: 'Rewind to before the nth most-recent user turn', category: 'General' },
|
|
21
|
+
{ command: '/fork', description: 'Branch the current conversation; previous still resumable', category: 'General' },
|
|
22
|
+
{ command: '/btw', description: 'Side question that doesn\'t pollute the main thread', category: 'General' },
|
|
23
|
+
{ command: '/editor', description: 'Open $EDITOR for a multi-line prompt', category: 'General' },
|
|
24
|
+
{ command: '/history', description: 'Message count + token estimate', category: 'General' },
|
|
25
|
+
{ command: '/export', description: 'Export conversation (md/json/txt)', category: 'General' },
|
|
26
|
+
{ command: '/walkthrough', description: 'Agent-led tour of compact-agent', category: 'General' },
|
|
27
|
+
{ command: '/config', description: 'Reconfigure provider / model / key (re-runs the setup wizard)', category: 'General' },
|
|
28
|
+
{ command: '/theme', description: 'Change display mode (full/compact/minimal)', category: 'General' },
|
|
29
|
+
{ command: '/palette', description: 'Switch color palette (run /palettes to list)', category: 'General' },
|
|
30
|
+
// ── Model & Provider ──
|
|
31
|
+
{ command: '/model', description: 'Switch model (no arg → interactive picker on OpenRouter)', category: 'Model' },
|
|
32
|
+
{ command: '/models', description: 'List available models for the current provider', category: 'Model' },
|
|
33
|
+
{ command: '/fallback', description: 'Set/show the model auto-retried on cryptic errors', category: 'Model' },
|
|
34
|
+
{ command: '/provider', description: 'Show provider info (URL, masked key)', category: 'Model' },
|
|
35
|
+
{ command: '/keys', description: 'Multi-key rotation pool (/keys add, status, remove)', category: 'Model' },
|
|
36
|
+
{ command: '/route', description: 'Auto-route to a model based on the next message', category: 'Model' },
|
|
37
|
+
// ── Modes ──
|
|
38
|
+
{ command: '/mode', description: 'Switch mode (dev/review/tdd/research/plan/debug/architect/hermes/design)', category: 'Modes' },
|
|
39
|
+
{ command: '/modes', description: 'List all available modes', category: 'Modes' },
|
|
40
|
+
{ command: '/hermes', description: 'Switch to Hermes mode (self-improving learning loop)', category: 'Modes' },
|
|
41
|
+
{ command: '/design', description: 'Switch to design mode (Stitch-powered UI work)', category: 'Modes' },
|
|
42
|
+
// ── Session ──
|
|
43
|
+
{ command: '/sessions', description: 'List saved sessions', category: 'Session' },
|
|
44
|
+
{ command: '/save', description: 'Save current session', category: 'Session' },
|
|
45
|
+
{ command: '/resume', description: 'Resume a saved session (accepts id, prefix, or "last")', category: 'Session' },
|
|
46
|
+
{ command: '/delete', description: 'Delete a session', category: 'Session' },
|
|
47
|
+
// ── Git ──
|
|
48
|
+
{ command: '/commit', description: 'AI-generated commit message', category: 'Git' },
|
|
49
|
+
{ command: '/pr', description: 'AI-generated pull request', category: 'Git' },
|
|
50
|
+
{ command: '/diff', description: 'Show git diff', category: 'Git' },
|
|
51
|
+
{ command: '/log', description: 'Show git log', category: 'Git' },
|
|
52
|
+
// ── Code Quality ──
|
|
53
|
+
{ command: '/review', description: 'AI code review (severity-rated findings)', category: 'Code Quality' },
|
|
54
|
+
{ command: '/auto-review', description: 'Code review with auto-detected language lens', category: 'Code Quality' },
|
|
55
|
+
{ command: '/tdd', description: 'Test-driven workflow (RED → GREEN → REFACTOR)', category: 'Code Quality' },
|
|
56
|
+
{ command: '/security-review', description: 'Security-focused audit', category: 'Code Quality' },
|
|
57
|
+
{ command: '/audit', description: 'Local-only project health check', category: 'Code Quality' },
|
|
58
|
+
{ command: '/verify', description: 'Run tests, fix failures, repeat until green', category: 'Code Quality' },
|
|
59
|
+
{ command: '/build-fix', description: 'Auto-detect language + fix build errors', category: 'Code Quality' },
|
|
60
|
+
{ command: '/test-coverage', description: 'Analyze coverage, suggest missing tests', category: 'Code Quality' },
|
|
61
|
+
{ command: '/refactor', description: 'Dead code detection + cleanup', category: 'Code Quality' },
|
|
62
|
+
{ command: '/hunt-silent', description: 'Silent-failure-hunter agent (empty catches, log-and-forget)', category: 'Code Quality' },
|
|
63
|
+
{ command: '/explore', description: 'Code-explorer agent (codebase reconnaissance pass)', category: 'Code Quality' },
|
|
64
|
+
{ command: '/types', description: 'Type-design-analyzer agent (type system critique)', category: 'Code Quality' },
|
|
65
|
+
{ command: '/architect', description: 'Code-architect agent (structural critique)', category: 'Code Quality' },
|
|
66
|
+
{ command: '/simplify', description: 'Code-simplifier agent (find + collapse incidental complexity)', category: 'Code Quality' },
|
|
67
|
+
{ command: '/e2e', description: 'Generate E2E tests', category: 'Code Quality' },
|
|
68
|
+
// ── Tools & Config ──
|
|
69
|
+
{ command: '/tools', description: 'List currently-available tools', category: 'Config' },
|
|
70
|
+
{ command: '/perm', description: 'Permission mode (ask/auto/yolo)', category: 'Config' },
|
|
71
|
+
{ command: '/sandbox', description: 'OS-native bash sandbox (off/standard/strict)', category: 'Config' },
|
|
72
|
+
{ command: '/dry-run', description: 'Toggle dry-run mode (preview tool calls)', category: 'Config' },
|
|
73
|
+
{ command: '/thinking', description: 'Toggle thinking/reasoning display', category: 'Config' },
|
|
74
|
+
{ command: '/cd', description: 'Change working directory', category: 'Config' },
|
|
75
|
+
{ command: '/hooks', description: 'List configured hooks', category: 'Config' },
|
|
76
|
+
// ── Planning ──
|
|
77
|
+
{ command: '/plan', description: 'Structured implementation planning', category: 'Planning' },
|
|
78
|
+
{ command: '/checkpoint', description: 'Save git-state checkpoint inside this session', category: 'Planning' },
|
|
79
|
+
{ command: '/search-first', description: 'Research before coding', category: 'Planning' },
|
|
80
|
+
{ command: '/update-docs', description: 'Sync documentation with code', category: 'Planning' },
|
|
81
|
+
// ── Orchestration ──
|
|
82
|
+
{ command: '/orchestrate', description: 'Decompose into parallel sub-agents', category: 'Orchestration' },
|
|
83
|
+
{ command: '/swarm', description: 'Parallel fan-out: N agents on the same task', category: 'Orchestration' },
|
|
84
|
+
{ command: '/multi-plan', description: 'Multi-agent planning', category: 'Orchestration' },
|
|
85
|
+
// ── Skills & Memory ──
|
|
86
|
+
{ command: '/skills', description: 'List learned + bundled ECC skills', category: 'Skills' },
|
|
87
|
+
{ command: '/skill-show', description: 'Print the full prompt of a specific skill', category: 'Skills' },
|
|
88
|
+
{ command: '/ecc-guide', description: 'Browse the bundled ECC corpus', category: 'Skills' },
|
|
89
|
+
{ command: '/memory', description: 'MemPalace: status, search, recall, list', category: 'Skills' },
|
|
90
|
+
{ command: '/learn', description: 'Extract patterns from this session into instincts', category: 'Skills' },
|
|
91
|
+
// ── Cost & Usage ──
|
|
92
|
+
{ command: '/usage', description: 'Token + cost summary', category: 'Cost' },
|
|
93
|
+
{ command: '/budget', description: 'Set daily/monthly USD budget', category: 'Cost' },
|
|
94
|
+
// ── Debug ──
|
|
95
|
+
{ command: '/debug', description: 'Toggle debug instrumentation + tail event log', category: 'Debug' },
|
|
96
|
+
// ── Voice / Accessibility ──
|
|
97
|
+
{ command: '/voice', description: 'Voice config + master switch', category: 'Voice' },
|
|
98
|
+
{ command: '/accessibility', description: 'Screen-reader mode, audio cues, destructive-confirm', category: 'Voice' },
|
|
99
|
+
{ command: '/dictate', description: 'One-shot record + transcribe', category: 'Voice' },
|
|
100
|
+
// ── Stitch ──
|
|
101
|
+
{ command: '/stitch', description: 'Show Stitch config status', category: 'Stitch' },
|
|
102
|
+
{ command: '/stitch-config', description: 'Save your Stitch API key', category: 'Stitch' },
|
|
103
|
+
// ── Exit ──
|
|
104
|
+
{ command: '/exit', description: 'Quit the REPL', category: 'General' },
|
|
105
|
+
];
|
|
106
|
+
//# sourceMappingURL=command-palette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-palette.js","sourceRoot":"","sources":["../src/command-palette.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -351,7 +351,21 @@ async function askWithDecoratedPrompt(rl, sessionTag, modeTag, promptGlyph) {
|
|
|
351
351
|
return rl.question(theme.prompt(promptGlyph));
|
|
352
352
|
}
|
|
353
353
|
/**
|
|
354
|
-
* Parse slash command
|
|
354
|
+
* Parse a slash command into (cmd, args).
|
|
355
|
+
*
|
|
356
|
+
* Args normalization: leading + trailing angle brackets are stripped
|
|
357
|
+
* automatically. The /help text uses `<arg>` as placeholder syntax
|
|
358
|
+
* (e.g. `/resume <session-id>`, `/model <name>`), and users routinely
|
|
359
|
+
* paste the placeholder literally — `/resume <abc123>` instead of
|
|
360
|
+
* `/resume abc123`. Stripping at the parser level means every
|
|
361
|
+
* command gets the same forgiving treatment without each handler
|
|
362
|
+
* having to defensively unwrap.
|
|
363
|
+
*
|
|
364
|
+
* Quotes / brackets other than `<>` are intentionally NOT stripped
|
|
365
|
+
* here. Some commands legitimately take quoted strings (e.g.
|
|
366
|
+
* `/article "How to be a vibe coder"`) — those commands should
|
|
367
|
+
* handle their own quote semantics. Only the `<>` placeholder
|
|
368
|
+
* pattern is normalized universally.
|
|
355
369
|
*/
|
|
356
370
|
function parseSlashCommand(input) {
|
|
357
371
|
const trimmed = input.trim();
|
|
@@ -360,8 +374,14 @@ function parseSlashCommand(input) {
|
|
|
360
374
|
return { cmd: trimmed.toLowerCase(), args: '' };
|
|
361
375
|
}
|
|
362
376
|
const cmd = trimmed.slice(0, spaceIdx).toLowerCase();
|
|
363
|
-
|
|
364
|
-
//
|
|
377
|
+
let argsRaw = trimmed.slice(spaceIdx + 1).trim();
|
|
378
|
+
// Strip leading + trailing `<>` if they wrap the entire arg
|
|
379
|
+
// string. Keeps `<>` inside the arg untouched (e.g. paths with
|
|
380
|
+
// angle brackets in regex-style queries) — only the outermost
|
|
381
|
+
// wrap is removed.
|
|
382
|
+
if (argsRaw.startsWith('<') && argsRaw.endsWith('>') && argsRaw.length > 2) {
|
|
383
|
+
argsRaw = argsRaw.slice(1, -1).trim();
|
|
384
|
+
}
|
|
365
385
|
return { cmd, args: argsRaw };
|
|
366
386
|
}
|
|
367
387
|
// ── Slash Commands ────────────────────────────────────────
|
|
@@ -810,10 +830,20 @@ export function handleSlashCommand(input, config, messages, session, mode) {
|
|
|
810
830
|
resetClient();
|
|
811
831
|
console.log(chalk.green(` Model: ${config.model} (custom)`));
|
|
812
832
|
}
|
|
833
|
+
return { handled: true };
|
|
813
834
|
}
|
|
814
|
-
|
|
815
|
-
|
|
835
|
+
// No args. On OpenRouter, the user wants the interactive
|
|
836
|
+
// picker (catalog + pricing). On other providers we don't
|
|
837
|
+
// have an equivalent catalog endpoint, so keep the legacy
|
|
838
|
+
// "show current" behavior.
|
|
839
|
+
if (/openrouter/i.test(config.provider)) {
|
|
840
|
+
// The picker is async; handleSlashCommand is sync. Use the
|
|
841
|
+
// sentinel-injectPrompt pattern that /dictate + /swarm
|
|
842
|
+
// already use to defer async work to the main REPL loop.
|
|
843
|
+
return { handled: true, injectPrompt: '__PICK_MODEL__' };
|
|
816
844
|
}
|
|
845
|
+
console.log(chalk.dim(` Current: ${config.model}`));
|
|
846
|
+
console.log(chalk.dim(' (interactive picker is OpenRouter-only — pass a model name explicitly with /model <id>)'));
|
|
817
847
|
return { handled: true };
|
|
818
848
|
case '/models':
|
|
819
849
|
printModelOptions(config);
|
|
@@ -2538,7 +2568,34 @@ export function handleSlashCommand(input, config, messages, session, mode) {
|
|
|
2538
2568
|
}
|
|
2539
2569
|
// ── Main ──────────────────────────────────────────────────
|
|
2540
2570
|
async function main() {
|
|
2541
|
-
|
|
2571
|
+
// Slash-command completer: bash-style Tab completion. Triggered
|
|
2572
|
+
// only when the typed line starts with '/' so it doesn't interfere
|
|
2573
|
+
// with regular prose. When the user has typed a unique prefix, Tab
|
|
2574
|
+
// completes to the full command. When multiple commands share the
|
|
2575
|
+
// prefix, readline's default behavior is to print the list of
|
|
2576
|
+
// candidates on the next Tab press — same UX as bash/zsh.
|
|
2577
|
+
//
|
|
2578
|
+
// This is COMPLEMENTARY to the '/' keypress trigger that opens the
|
|
2579
|
+
// alt-screen picker: that's the "I want to browse" path; this is
|
|
2580
|
+
// the "I know what I'm typing, just save me keystrokes" path. The
|
|
2581
|
+
// two coexist because pressing '/' fires the picker only at an
|
|
2582
|
+
// empty buffer — once the user has typed beyond '/', Tab takes
|
|
2583
|
+
// over via this completer.
|
|
2584
|
+
const { COMMAND_CATALOG } = await import('./command-palette.js');
|
|
2585
|
+
const slashCommandNames = COMMAND_CATALOG.map((c) => c.command);
|
|
2586
|
+
const rl = readline.createInterface({
|
|
2587
|
+
input: stdin,
|
|
2588
|
+
output: stdout,
|
|
2589
|
+
completer: (line) => {
|
|
2590
|
+
if (!line.startsWith('/'))
|
|
2591
|
+
return [[], line];
|
|
2592
|
+
const matches = slashCommandNames.filter((c) => c.startsWith(line));
|
|
2593
|
+
// readline contract: return [matches, lineWeMatchedAgainst].
|
|
2594
|
+
// If matches is empty, readline beeps; otherwise it completes
|
|
2595
|
+
// to common prefix or lists candidates.
|
|
2596
|
+
return [matches.length > 0 ? matches : slashCommandNames, line];
|
|
2597
|
+
},
|
|
2598
|
+
});
|
|
2542
2599
|
// Initialize subsystems
|
|
2543
2600
|
initHooksDir();
|
|
2544
2601
|
// First-run ECC install — silent if already installed, silent if resources missing.
|
|
@@ -2715,10 +2772,18 @@ async function main() {
|
|
|
2715
2772
|
'tab', // Shift+Tab cycles perm modes
|
|
2716
2773
|
'escape', // Esc-Esc rewind at empty prompt
|
|
2717
2774
|
',', '.', // Alt+, / Alt+. reasoning effort
|
|
2775
|
+
'space', // Space at empty prompt → command palette
|
|
2776
|
+
'/', // / at empty prompt → palette filtered to '/'
|
|
2718
2777
|
// Shifted F-keys carry the Tier-2 and Tier-3 a11y functions. Each
|
|
2719
2778
|
// is checked alongside key.shift below, so a bare F1 still routes
|
|
2720
2779
|
// to "status" while Shift+F1 routes to "queued input."
|
|
2721
2780
|
]);
|
|
2781
|
+
// Re-entry guard for the picker. The keypress listener can fire
|
|
2782
|
+
// again while the picker is still in alt-screen mode (the user
|
|
2783
|
+
// pressed something the picker handled but we still saw the
|
|
2784
|
+
// 'keypress' event), so we need to make sure we don't open a
|
|
2785
|
+
// second picker on top of the first.
|
|
2786
|
+
let pickerActive = false;
|
|
2722
2787
|
// Define the hotkey listener as a NAMED, TAGGED function so
|
|
2723
2788
|
// suppressInputDuringStream() in query.ts can isolate it among stdin's
|
|
2724
2789
|
// 'keypress' listeners. During streaming we detach readline's own
|
|
@@ -2749,6 +2814,17 @@ async function main() {
|
|
|
2749
2814
|
return;
|
|
2750
2815
|
if (name === 'escape' && (shift || ctrl || meta))
|
|
2751
2816
|
return;
|
|
2817
|
+
// Space is ours ONLY when the input buffer is empty and we're
|
|
2818
|
+
// at a prompt (not mid-streaming). The check happens in the
|
|
2819
|
+
// dedicated branch below; here we just defer if there's any
|
|
2820
|
+
// modifier (Shift+Space, Ctrl+Space, etc. aren't us).
|
|
2821
|
+
if (name === 'space' && (shift || ctrl || meta))
|
|
2822
|
+
return;
|
|
2823
|
+
// Slash autocomplete: '/' at empty prompt opens the picker
|
|
2824
|
+
// pre-filtered to '/'. Modified variants (Ctrl+/, etc.) are
|
|
2825
|
+
// not ours.
|
|
2826
|
+
if (name === '/' && (shift || ctrl || meta))
|
|
2827
|
+
return;
|
|
2752
2828
|
const a = getAccessibilityConfig(config);
|
|
2753
2829
|
const tts = getTtsConfig(config);
|
|
2754
2830
|
// Helper: print to stdout (always — picked up by the OS screen reader)
|
|
@@ -2921,6 +2997,103 @@ async function main() {
|
|
|
2921
2997
|
// Any other shifted F-key: no-op (don't fall through to bare).
|
|
2922
2998
|
return;
|
|
2923
2999
|
}
|
|
3000
|
+
// ── Space (bare): command palette at empty prompt ──
|
|
3001
|
+
// Pressing Space when the input buffer is empty opens the
|
|
3002
|
+
// command palette — an alt-screen picker showing every slash
|
|
3003
|
+
// command, arrow-key navigable, type-to-filter, Enter to run.
|
|
3004
|
+
// When the buffer has content (the user is typing a real
|
|
3005
|
+
// message that begins with a space-separated word) the keypress
|
|
3006
|
+
// listener stays out of the way and lets readline handle the
|
|
3007
|
+
// space normally.
|
|
3008
|
+
if (name === 'space' || name === '/') {
|
|
3009
|
+
if (pickerActive)
|
|
3010
|
+
return;
|
|
3011
|
+
const buf = rl.line ?? '';
|
|
3012
|
+
// Space is only triggered at an empty buffer (mid-typing
|
|
3013
|
+
// space should insert normally). '/' has a more permissive
|
|
3014
|
+
// trigger: it fires at empty buffer OR at exactly "/"
|
|
3015
|
+
// (which is the state right after the user pressed '/'
|
|
3016
|
+
// and the byte landed in the buffer). Either way, only
|
|
3017
|
+
// empty + single-/ states open the picker; longer buffers
|
|
3018
|
+
// pass through.
|
|
3019
|
+
if (name === 'space' && buf.length > 0)
|
|
3020
|
+
return;
|
|
3021
|
+
if (name === '/' && buf !== '' && buf !== '/')
|
|
3022
|
+
return;
|
|
3023
|
+
// Mid-stream is suppressed by the input guard already;
|
|
3024
|
+
// this listener still fires but we shouldn't open a picker
|
|
3025
|
+
// on top of a streaming turn.
|
|
3026
|
+
const turnCtl = globalThis.__turnAbortCtl;
|
|
3027
|
+
if (turnCtl && !turnCtl.signal.aborted)
|
|
3028
|
+
return;
|
|
3029
|
+
const triggerChar = name === '/' ? '/' : ' ';
|
|
3030
|
+
// Open the palette. The picker is async and takes stdin into
|
|
3031
|
+
// raw mode for its lifetime — we fire-and-forget here.
|
|
3032
|
+
pickerActive = true;
|
|
3033
|
+
// The trigger character is already in readline's buffer at
|
|
3034
|
+
// this point (the keypress listener is an observer, not a
|
|
3035
|
+
// gate). Clear it so the prompt is clean once the picker
|
|
3036
|
+
// exits.
|
|
3037
|
+
try {
|
|
3038
|
+
const rlAny = rl;
|
|
3039
|
+
rlAny.line = '';
|
|
3040
|
+
rlAny._refreshLine?.();
|
|
3041
|
+
}
|
|
3042
|
+
catch { /* noop */ }
|
|
3043
|
+
void (async () => {
|
|
3044
|
+
try {
|
|
3045
|
+
const { pick } = await import('./picker.js');
|
|
3046
|
+
const { COMMAND_CATALOG } = await import('./command-palette.js');
|
|
3047
|
+
const items = COMMAND_CATALOG.map((c) => ({
|
|
3048
|
+
label: c.command,
|
|
3049
|
+
hint: c.category,
|
|
3050
|
+
description: c.description,
|
|
3051
|
+
value: c.command,
|
|
3052
|
+
}));
|
|
3053
|
+
const selected = await pick(items, {
|
|
3054
|
+
title: 'compact-agent · command palette',
|
|
3055
|
+
footer: 'type to filter · ↑↓ to navigate · Enter to run · Esc to cancel',
|
|
3056
|
+
// '/' trigger: pre-fill filter so the user's mental
|
|
3057
|
+
// model ("I typed / and now I see slash commands") is
|
|
3058
|
+
// preserved. Space trigger: blank filter, browse all.
|
|
3059
|
+
initialFilter: name === '/' ? '/' : undefined,
|
|
3060
|
+
});
|
|
3061
|
+
if (selected) {
|
|
3062
|
+
globalThis.__crowcoderQueuedInput = selected + '\n';
|
|
3063
|
+
try {
|
|
3064
|
+
rl.emit('line', '');
|
|
3065
|
+
}
|
|
3066
|
+
catch { /* noop */ }
|
|
3067
|
+
}
|
|
3068
|
+
else if (triggerChar === '/') {
|
|
3069
|
+
// Cancel from '/'-triggered picker: restore the '/'
|
|
3070
|
+
// to the buffer so the user can keep typing the
|
|
3071
|
+
// command manually (e.g. they wanted /model claude-
|
|
3072
|
+
// sonnet-4 directly, not the picker). Don't resolve
|
|
3073
|
+
// rl.question — leave readline waiting for input.
|
|
3074
|
+
try {
|
|
3075
|
+
const rlAny = rl;
|
|
3076
|
+
rlAny.line = '/';
|
|
3077
|
+
rlAny._refreshLine?.();
|
|
3078
|
+
}
|
|
3079
|
+
catch { /* noop */ }
|
|
3080
|
+
}
|
|
3081
|
+
else {
|
|
3082
|
+
// Cancel from space-triggered picker: prompt is clean,
|
|
3083
|
+
// resolve readline with empty so the loop iterates
|
|
3084
|
+
// back to a fresh prompt.
|
|
3085
|
+
try {
|
|
3086
|
+
rl.emit('line', '');
|
|
3087
|
+
}
|
|
3088
|
+
catch { /* noop */ }
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
finally {
|
|
3092
|
+
pickerActive = false;
|
|
3093
|
+
}
|
|
3094
|
+
})();
|
|
3095
|
+
return;
|
|
3096
|
+
}
|
|
2924
3097
|
// ── Esc (bare): rewind chord at empty prompt ───────
|
|
2925
3098
|
// Two bare Esc presses within 500ms at an empty input buffer
|
|
2926
3099
|
// triggers /back (rewind one user turn). Matches the muscle
|
|
@@ -3349,6 +3522,42 @@ async function main() {
|
|
|
3349
3522
|
console.log(theme.dim(' [dictate] ') + chalk.white(transcript));
|
|
3350
3523
|
messages.push({ role: 'user', content: transcript });
|
|
3351
3524
|
}
|
|
3525
|
+
else if (result.injectPrompt === '__PICK_MODEL__') {
|
|
3526
|
+
// OpenRouter model picker — same sentinel-into-the-REPL
|
|
3527
|
+
// pattern as /dictate + /swarm because handleSlashCommand
|
|
3528
|
+
// is sync but fetching the catalog + showing the picker
|
|
3529
|
+
// is async. Selection sets config.model + saves; no
|
|
3530
|
+
// injectPrompt cascades into runQuery.
|
|
3531
|
+
const { pick } = await import('./picker.js');
|
|
3532
|
+
const { fetchOpenRouterModels, formatPricing } = await import('./openrouter-models.js');
|
|
3533
|
+
console.log(chalk.dim(' Fetching OpenRouter catalog…'));
|
|
3534
|
+
const models = await fetchOpenRouterModels();
|
|
3535
|
+
if (models.length === 0) {
|
|
3536
|
+
console.log(chalk.yellow(' Could not fetch model catalog (network error or rate limit).'));
|
|
3537
|
+
console.log(chalk.dim(' Use /model <id> with a known model name, or check your connection.'));
|
|
3538
|
+
continue;
|
|
3539
|
+
}
|
|
3540
|
+
const items = models.map((m) => ({
|
|
3541
|
+
label: m.id,
|
|
3542
|
+
hint: formatPricing(m),
|
|
3543
|
+
description: m.name !== m.id ? m.name : undefined,
|
|
3544
|
+
value: m.id,
|
|
3545
|
+
}));
|
|
3546
|
+
const selected = await pick(items, {
|
|
3547
|
+
title: `compact-agent · OpenRouter models (current: ${config.model})`,
|
|
3548
|
+
footer: 'type to filter · ↑↓ to navigate · Enter to pick · Esc to cancel · free models float to the top',
|
|
3549
|
+
});
|
|
3550
|
+
if (selected) {
|
|
3551
|
+
config.model = selected;
|
|
3552
|
+
saveConfig(config);
|
|
3553
|
+
resetClient();
|
|
3554
|
+
console.log(chalk.green(` Model: ${config.model}`));
|
|
3555
|
+
}
|
|
3556
|
+
else {
|
|
3557
|
+
console.log(chalk.dim(' Cancelled — model unchanged.'));
|
|
3558
|
+
}
|
|
3559
|
+
continue;
|
|
3560
|
+
}
|
|
3352
3561
|
else if (result.injectPrompt.startsWith('__SWARM__')) {
|
|
3353
3562
|
// Swarm dispatch: __SWARM__<agentsCsv>|||<task>. Same sentinel
|
|
3354
3563
|
// trick as /dictate so the slash handler stays sync; the async
|