@phnx-labs/agents-cli 1.20.7 → 1.20.9
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 +6 -0
- package/README.md +1 -1
- package/dist/commands/computer-actions.d.ts +19 -0
- package/dist/commands/computer-actions.js +159 -1
- package/dist/commands/computer.js +2 -2
- package/dist/commands/daemon.js +6 -6
- package/dist/commands/import.js +3 -6
- package/dist/commands/inspect.js +17 -8
- package/dist/commands/models.js +2 -1
- package/dist/commands/plugins.js +3 -2
- package/dist/commands/refresh-rules.js +4 -4
- package/dist/commands/routines.js +8 -7
- package/dist/commands/sessions.js +17 -2
- package/dist/commands/setup.js +2 -2
- package/dist/commands/subagents.js +2 -1
- package/dist/commands/usage.js +11 -3
- package/dist/commands/versions.js +2 -2
- package/dist/index.js +69 -47
- package/dist/lib/agents.d.ts +18 -1
- package/dist/lib/agents.js +89 -23
- package/dist/lib/browser/chrome.d.ts +4 -3
- package/dist/lib/browser/chrome.js +87 -12
- package/dist/lib/browser/ipc.js +59 -13
- package/dist/lib/computer-rpc.d.ts +2 -0
- package/dist/lib/computer-rpc.js +21 -1
- package/dist/lib/daemon.js +20 -8
- package/dist/lib/fs-walk.d.ts +7 -1
- package/dist/lib/fs-walk.js +45 -11
- package/dist/lib/git.js +5 -2
- package/dist/lib/log-follow.d.ts +7 -0
- package/dist/lib/log-follow.js +65 -0
- package/dist/lib/platform/index.d.ts +1 -0
- package/dist/lib/platform/index.js +1 -0
- package/dist/lib/platform/ipc.d.ts +11 -0
- package/dist/lib/platform/ipc.js +21 -0
- package/dist/lib/platform/paths.d.ts +7 -0
- package/dist/lib/platform/paths.js +9 -0
- package/dist/lib/platform/process.d.ts +9 -1
- package/dist/lib/platform/process.js +27 -0
- package/dist/lib/plugins.js +5 -3
- package/dist/lib/refresh.js +2 -2
- package/dist/lib/self-update.d.ts +86 -0
- package/dist/lib/self-update.js +178 -0
- package/dist/lib/shims.d.ts +13 -8
- package/dist/lib/shims.js +46 -11
- package/dist/lib/versions.js +3 -3
- package/package.json +1 -1
- package/scripts/postinstall.js +36 -26
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
**Single-typo agent names auto-correct everywhere, not just `agents run`**
|
|
6
|
+
|
|
7
|
+
- `agents view cladue` used to print `Unknown agent 'cladue'` even though `agents run cladue` auto-corrected. `resolveAgentName` — the canonical resolver behind `view`, `usage`, `inspect`, `doctor`, `sync`, `models`, `skills`, `hooks`, `import`, `sessions --agent`, and every `agent@version` spec (`agents add claud@latest`, `agents use codx@2.1.170`) — now falls back to Damerau-Levenshtein distance-1 matching against canonical ids and multi-letter aliases: `cladue` -> `claude` (transposition), `kim` -> `kimi`, `codx` -> `codex`, `gemni` -> `gemini`.
|
|
8
|
+
- Corrections apply only when unambiguous: every distance-1 candidate must agree on one agent. `kiri` (one edit from both `kiro` and `kimi`) and inputs under 3 characters still error. `agents run` keeps its existing exact -> profile -> workflow -> fuzzy precedence, so a profile named `claud` still beats the typo correction.
|
|
9
|
+
- Fixes `kimi` being listed as a valid agent but missing from the alias map — `agents view kimi` previously errored. Added `kimi` / `kimi-code` entries.
|
|
10
|
+
|
|
5
11
|
## 1.20.7
|
|
6
12
|
|
|
7
13
|
**`agents inspect` — DotAgents repo targets (#256)**
|
package/README.md
CHANGED
|
@@ -122,7 +122,7 @@ agents run codex "Fix the issues Claude found"
|
|
|
122
122
|
agents run gemini "Write tests for the fixed code"
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
Each resolves to the project-pinned version with skills, MCP servers, and permissions already synced.
|
|
125
|
+
Each resolves to the project-pinned version with skills, MCP servers, and permissions already synced. Single-typo names auto-correct across every command — `agents view cladue` resolves to `claude`, `agents add codx@latest` to `codex`.
|
|
126
126
|
|
|
127
127
|
### Rate-limited? Keep working.
|
|
128
128
|
|
|
@@ -31,6 +31,25 @@ export declare function buildElementOrCoords(opts: {
|
|
|
31
31
|
ok: false;
|
|
32
32
|
error: string;
|
|
33
33
|
};
|
|
34
|
+
export declare function buildRaiseParams(opts: {
|
|
35
|
+
windowId?: number;
|
|
36
|
+
title?: string;
|
|
37
|
+
}): Record<string, unknown>;
|
|
38
|
+
export declare function buildWaitParams(opts: {
|
|
39
|
+
duration?: number;
|
|
40
|
+
id?: string;
|
|
41
|
+
until?: string;
|
|
42
|
+
role?: string;
|
|
43
|
+
label?: string;
|
|
44
|
+
identifier?: string;
|
|
45
|
+
timeout?: number;
|
|
46
|
+
}): {
|
|
47
|
+
ok: true;
|
|
48
|
+
params: Record<string, unknown>;
|
|
49
|
+
} | {
|
|
50
|
+
ok: false;
|
|
51
|
+
error: string;
|
|
52
|
+
};
|
|
34
53
|
export declare function withClient<T>(fn: (client: ComputerClient) => Promise<T>): Promise<T>;
|
|
35
54
|
export declare function unwrap(r: RPCResponse): Record<string, unknown>;
|
|
36
55
|
export declare function registerActionCommands(program: Command): void;
|
|
@@ -60,6 +60,51 @@ export function buildElementOrCoords(opts) {
|
|
|
60
60
|
return { ok: true, params: { x: opts.x, y: opts.y } };
|
|
61
61
|
return { ok: false, error: 'pass --id <@eN> (from `describe`) or --x <n> --y <n>' };
|
|
62
62
|
}
|
|
63
|
+
// Build the focus_window params for `raise`. Pure + tested: window_id and
|
|
64
|
+
// title are both optional refinements over the app-level activate.
|
|
65
|
+
export function buildRaiseParams(opts) {
|
|
66
|
+
const params = {};
|
|
67
|
+
if (opts.windowId != null)
|
|
68
|
+
params.window_id = opts.windowId;
|
|
69
|
+
if (opts.title)
|
|
70
|
+
params.title = opts.title;
|
|
71
|
+
return params;
|
|
72
|
+
}
|
|
73
|
+
// Build the wait RPC params. Pure + tested. Three modes, mirroring the
|
|
74
|
+
// daemon's Wait.run: --duration (unconditional sleep), --id + --until
|
|
75
|
+
// (cached-element poll), or --role/--label/--identifier (live locator poll).
|
|
76
|
+
export function buildWaitParams(opts) {
|
|
77
|
+
if (opts.duration != null) {
|
|
78
|
+
return { ok: true, params: { duration_ms: opts.duration } };
|
|
79
|
+
}
|
|
80
|
+
const params = {};
|
|
81
|
+
if (opts.until)
|
|
82
|
+
params.until = opts.until;
|
|
83
|
+
if (opts.timeout != null)
|
|
84
|
+
params.timeout_ms = opts.timeout;
|
|
85
|
+
if (opts.id) {
|
|
86
|
+
return { ok: true, params: { ...params, element_id: opts.id } };
|
|
87
|
+
}
|
|
88
|
+
const locator = {};
|
|
89
|
+
if (opts.role)
|
|
90
|
+
locator.role = opts.role;
|
|
91
|
+
if (opts.label)
|
|
92
|
+
locator.label = opts.label;
|
|
93
|
+
if (opts.identifier)
|
|
94
|
+
locator.identifier = opts.identifier;
|
|
95
|
+
if (Object.keys(locator).length === 0) {
|
|
96
|
+
return { ok: false, error: 'pass --duration <ms>, --id <@eN>, or a locator (--role/--label/--identifier)' };
|
|
97
|
+
}
|
|
98
|
+
return { ok: true, params: { ...params, locator } };
|
|
99
|
+
}
|
|
100
|
+
// postToPid keyboard delivery is dropped by key-window-gated apps (Parallels
|
|
101
|
+
// VMs and friends) — when the daemon reports the target was not frontmost,
|
|
102
|
+
// the keystrokes may have landed nowhere. Surface that loudly on stderr.
|
|
103
|
+
function warnIfNotFrontmost(res) {
|
|
104
|
+
if (res.frontmost === false) {
|
|
105
|
+
console.error('warning: target was not the frontmost app — keystrokes may have been dropped. Run `agents computer raise` first.');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
63
108
|
function reportMissingHelper() {
|
|
64
109
|
console.error('helper not built. Run: ./packages/computer-helper/scripts/build.sh debug');
|
|
65
110
|
process.exit(1);
|
|
@@ -99,6 +144,12 @@ async function resolveTargetPid(client, opts) {
|
|
|
99
144
|
}
|
|
100
145
|
return picked.app.pid;
|
|
101
146
|
}
|
|
147
|
+
// --raise flag: app-level focus_window before the main action so coordinate
|
|
148
|
+
// clicks and keystrokes land on a visible, key window.
|
|
149
|
+
async function raiseIfRequested(client, pid, raise) {
|
|
150
|
+
if (raise)
|
|
151
|
+
unwrap(await client.call('focus_window', { pid }));
|
|
152
|
+
}
|
|
102
153
|
function emit(result, json, human) {
|
|
103
154
|
if (json) {
|
|
104
155
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -158,6 +209,7 @@ export function registerActionCommands(program) {
|
|
|
158
209
|
.description('Click an element (--id) or screen coordinate (--x --y)')
|
|
159
210
|
.option('--count <n>', 'Click count (2 = double-click)', (v) => parseInt(v, 10))
|
|
160
211
|
.option('--background', 'Focus-safe postToPid delivery (plain AppKit only; skips HID tap)')
|
|
212
|
+
.option('--raise', 'Bring the target app to the front first')
|
|
161
213
|
.option('--json', 'Emit JSON'))).action(async (opts) => {
|
|
162
214
|
await withClient(async (client) => {
|
|
163
215
|
const pid = await resolveTargetPid(client, opts);
|
|
@@ -166,6 +218,7 @@ export function registerActionCommands(program) {
|
|
|
166
218
|
console.error(spec.error);
|
|
167
219
|
process.exit(1);
|
|
168
220
|
}
|
|
221
|
+
await raiseIfRequested(client, pid, opts.raise);
|
|
169
222
|
const params = { pid, ...spec.params };
|
|
170
223
|
if (opts.count != null)
|
|
171
224
|
params.count = opts.count;
|
|
@@ -221,13 +274,19 @@ export function registerActionCommands(program) {
|
|
|
221
274
|
.description('Type an arbitrary unicode string into the focused field (focus first via click/focus)')
|
|
222
275
|
.requiredOption('--text <s>', 'Text to type')
|
|
223
276
|
.option('--commit', 'Press Return after typing')
|
|
277
|
+
.option('--raise', 'Bring the target app to the front first')
|
|
278
|
+
.option('--require-frontmost', 'Fail (not warn) if the target is not the frontmost app')
|
|
224
279
|
.option('--json', 'Emit JSON')).action(async (opts) => {
|
|
225
280
|
await withClient(async (client) => {
|
|
226
281
|
const pid = await resolveTargetPid(client, opts);
|
|
282
|
+
await raiseIfRequested(client, pid, opts.raise);
|
|
227
283
|
const params = { pid, text: opts.text };
|
|
228
284
|
if (opts.commit)
|
|
229
285
|
params.commit = true;
|
|
286
|
+
if (opts.requireFrontmost)
|
|
287
|
+
params.require_frontmost = true;
|
|
230
288
|
const res = unwrap(await client.call('type_text', params));
|
|
289
|
+
warnIfNotFrontmost(res);
|
|
231
290
|
emit(res, Boolean(opts.json), () => `typed ${res.chars ?? opts.text.length} char(s)`);
|
|
232
291
|
});
|
|
233
292
|
});
|
|
@@ -236,10 +295,17 @@ export function registerActionCommands(program) {
|
|
|
236
295
|
.command('key')
|
|
237
296
|
.description('Send a key chord, e.g. "cmd+shift+s", "enter", "esc"')
|
|
238
297
|
.requiredOption('--keys <chord>', 'Key chord')
|
|
298
|
+
.option('--raise', 'Bring the target app to the front first')
|
|
299
|
+
.option('--require-frontmost', 'Fail (not warn) if the target is not the frontmost app')
|
|
239
300
|
.option('--json', 'Emit JSON')).action(async (opts) => {
|
|
240
301
|
await withClient(async (client) => {
|
|
241
302
|
const pid = await resolveTargetPid(client, opts);
|
|
242
|
-
|
|
303
|
+
await raiseIfRequested(client, pid, opts.raise);
|
|
304
|
+
const params = { pid, keys: opts.keys };
|
|
305
|
+
if (opts.requireFrontmost)
|
|
306
|
+
params.require_frontmost = true;
|
|
307
|
+
const res = unwrap(await client.call('key', params));
|
|
308
|
+
warnIfNotFrontmost(res);
|
|
243
309
|
emit(res, Boolean(opts.json), () => `sent ${opts.keys}`);
|
|
244
310
|
});
|
|
245
311
|
});
|
|
@@ -251,6 +317,7 @@ export function registerActionCommands(program) {
|
|
|
251
317
|
.requiredOption('--to <x,y>', 'End coordinate "x,y"')
|
|
252
318
|
.option('--button <left|right>', 'Mouse button', 'left')
|
|
253
319
|
.option('--background', 'Focus-safe postToPid delivery (plain AppKit only)')
|
|
320
|
+
.option('--raise', 'Bring the target app to the front first')
|
|
254
321
|
.option('--json', 'Emit JSON')).action(async (opts) => {
|
|
255
322
|
let from;
|
|
256
323
|
let to;
|
|
@@ -264,6 +331,7 @@ export function registerActionCommands(program) {
|
|
|
264
331
|
}
|
|
265
332
|
await withClient(async (client) => {
|
|
266
333
|
const pid = await resolveTargetPid(client, opts);
|
|
334
|
+
await raiseIfRequested(client, pid, opts.raise);
|
|
267
335
|
const params = {
|
|
268
336
|
pid,
|
|
269
337
|
from: [from.x, from.y],
|
|
@@ -282,9 +350,11 @@ export function registerActionCommands(program) {
|
|
|
282
350
|
.description('Scroll by a pixel delta at an element or coordinate')
|
|
283
351
|
.option('--dy <n>', 'Vertical delta (negative = down)', (v) => parseInt(v, 10))
|
|
284
352
|
.option('--dx <n>', 'Horizontal delta', (v) => parseInt(v, 10))
|
|
353
|
+
.option('--raise', 'Bring the target app to the front first')
|
|
285
354
|
.option('--json', 'Emit JSON'))).action(async (opts) => {
|
|
286
355
|
await withClient(async (client) => {
|
|
287
356
|
const pid = await resolveTargetPid(client, opts);
|
|
357
|
+
await raiseIfRequested(client, pid, opts.raise);
|
|
288
358
|
const params = { pid };
|
|
289
359
|
if (opts.id)
|
|
290
360
|
params.element_id = opts.id;
|
|
@@ -325,4 +395,92 @@ export function registerActionCommands(program) {
|
|
|
325
395
|
emit(res, Boolean(opts.json), () => `focused ${opts.id}`);
|
|
326
396
|
});
|
|
327
397
|
});
|
|
398
|
+
// raise — bring an app (or one of its windows) to the front. The window
|
|
399
|
+
// forms (--window-id/--title) also switch macOS Spaces, which is the only
|
|
400
|
+
// way to reach a fullscreen-Space window (VM, fullscreen editor) for
|
|
401
|
+
// capture and HID-tap input.
|
|
402
|
+
addTargetOpts(program
|
|
403
|
+
.command('raise')
|
|
404
|
+
.description('Bring an app (or a specific window) to the front — switches Spaces for fullscreen windows')
|
|
405
|
+
.option('--window-id <n>', 'Raise a specific window by id (from `screenshot --list`)', (v) => parseInt(v, 10))
|
|
406
|
+
.option('--title <s>', 'Raise the window whose title contains this string')
|
|
407
|
+
.option('--json', 'Emit JSON')).action(async (opts) => {
|
|
408
|
+
await withClient(async (client) => {
|
|
409
|
+
const pid = await resolveTargetPid(client, opts);
|
|
410
|
+
const res = unwrap(await client.call('focus_window', { pid, ...buildRaiseParams(opts) }));
|
|
411
|
+
emit(res, Boolean(opts.json), () => {
|
|
412
|
+
const scope = res.raised_window ? `window ${res.title ?? res.window_id ?? ''}`.trim() : 'app';
|
|
413
|
+
return `raised ${scope} (${res.focus_elapsed_ms ?? 0}ms)`;
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
});
|
|
417
|
+
// wait — settle the UI before the next action
|
|
418
|
+
addTargetOpts(program
|
|
419
|
+
.command('wait')
|
|
420
|
+
.description('Wait for a duration (--duration) or for an element (--id / --role/--label) to satisfy --until')
|
|
421
|
+
.option('--duration <ms>', 'Unconditional sleep in ms (50-30000)', (v) => parseInt(v, 10))
|
|
422
|
+
.option('--id <@eN>', 'Element id from `describe` to poll')
|
|
423
|
+
.option('--until <cond>', 'Condition: exists | enabled | disappears (default: exists)')
|
|
424
|
+
.option('--role <s>', 'Locator: AX role (e.g. AXButton)')
|
|
425
|
+
.option('--label <s>', 'Locator: element label')
|
|
426
|
+
.option('--identifier <s>', 'Locator: AX identifier')
|
|
427
|
+
.option('--timeout <ms>', 'Poll timeout in ms (default 5000)', (v) => parseInt(v, 10))
|
|
428
|
+
.option('--json', 'Emit JSON')).action(async (opts) => {
|
|
429
|
+
const spec = buildWaitParams(opts);
|
|
430
|
+
if (!spec.ok) {
|
|
431
|
+
console.error(spec.error);
|
|
432
|
+
process.exit(1);
|
|
433
|
+
}
|
|
434
|
+
await withClient(async (client) => {
|
|
435
|
+
const params = { ...spec.params };
|
|
436
|
+
// duration-only waits don't need a target pid
|
|
437
|
+
if (params.duration_ms == null)
|
|
438
|
+
params.pid = await resolveTargetPid(client, opts);
|
|
439
|
+
const res = unwrap(await client.call('wait', params));
|
|
440
|
+
emit(res, Boolean(opts.json), () => res.satisfied ? `satisfied (${res.waited_ms}ms)` : `timed out (${res.waited_ms}ms)`);
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
// get-text — read text without OCR
|
|
444
|
+
addTargetOpts(program
|
|
445
|
+
.command('get-text')
|
|
446
|
+
.description('Extract visible text from the app (or a subtree via --id)')
|
|
447
|
+
.option('--id <@eN>', 'Element id from `describe` to scope the extraction')
|
|
448
|
+
.option('--max-chars <n>', 'Cap the extracted text length', (v) => parseInt(v, 10))
|
|
449
|
+
.option('--json', 'Emit JSON')).action(async (opts) => {
|
|
450
|
+
await withClient(async (client) => {
|
|
451
|
+
const pid = await resolveTargetPid(client, opts);
|
|
452
|
+
const params = { pid };
|
|
453
|
+
if (opts.id)
|
|
454
|
+
params.element_id = opts.id;
|
|
455
|
+
if (opts.maxChars != null)
|
|
456
|
+
params.max_chars = opts.maxChars;
|
|
457
|
+
const res = unwrap(await client.call('get_text', params));
|
|
458
|
+
emit(res, Boolean(opts.json), () => String(res.text ?? ''));
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
// launch — start an app (no target resolution: it isn't running yet)
|
|
462
|
+
program
|
|
463
|
+
.command('launch')
|
|
464
|
+
.description('Launch an app by bundle id, path, or name')
|
|
465
|
+
.option('--bundle <id>', 'Bundle id (e.g. com.apple.TextEdit)')
|
|
466
|
+
.option('--path <p>', 'Path to the .app bundle')
|
|
467
|
+
.option('--name <s>', 'App name (resolved via /Applications and LaunchServices)')
|
|
468
|
+
.option('--json', 'Emit JSON')
|
|
469
|
+
.action(async (opts) => {
|
|
470
|
+
if (!opts.bundle && !opts.path && !opts.name) {
|
|
471
|
+
console.error('pass one of --bundle, --path, --name');
|
|
472
|
+
process.exit(1);
|
|
473
|
+
}
|
|
474
|
+
await withClient(async (client) => {
|
|
475
|
+
const params = {};
|
|
476
|
+
if (opts.bundle)
|
|
477
|
+
params.bundle_id = opts.bundle;
|
|
478
|
+
if (opts.path)
|
|
479
|
+
params.path = opts.path;
|
|
480
|
+
if (opts.name)
|
|
481
|
+
params.name = opts.name;
|
|
482
|
+
const res = unwrap(await client.call('launch_app', params));
|
|
483
|
+
emit(res, Boolean(opts.json), () => `launched ${res.name} (pid ${res.pid})`);
|
|
484
|
+
});
|
|
485
|
+
});
|
|
328
486
|
}
|
|
@@ -9,8 +9,8 @@ import { registerActionCommands, withClient, unwrap, pickTarget } from './comput
|
|
|
9
9
|
const COMPUTER_HELP_GROUPS = [
|
|
10
10
|
{ title: 'Installation', names: ['setup'] },
|
|
11
11
|
{ title: 'Daemon lifecycle', names: ['start', 'stop', 'reload', 'status'] },
|
|
12
|
-
{ title: 'Observe', names: ['apps', 'describe', 'screenshot'] },
|
|
13
|
-
{ title: 'Interact', names: ['click', 'right-click', 'type', 'type-text', 'key', 'drag', 'scroll', 'ax-action', 'focus'] },
|
|
12
|
+
{ title: 'Observe', names: ['apps', 'describe', 'screenshot', 'get-text'] },
|
|
13
|
+
{ title: 'Interact', names: ['launch', 'raise', 'click', 'right-click', 'type', 'type-text', 'key', 'drag', 'scroll', 'ax-action', 'focus', 'wait'] },
|
|
14
14
|
];
|
|
15
15
|
export function registerComputerCommand(program) {
|
|
16
16
|
const computer = program
|
package/dist/commands/daemon.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* aliases for `agents routines` scheduler lifecycle commands. Scheduled
|
|
6
6
|
* for removal in v2.0.
|
|
7
7
|
*/
|
|
8
|
-
import { spawn } from 'child_process';
|
|
9
8
|
import chalk from 'chalk';
|
|
10
9
|
import * as path from 'path';
|
|
11
10
|
import { startDaemon, stopDaemon, isDaemonRunning, readDaemonPid, readDaemonLog, runDaemon, } from '../lib/daemon.js';
|
|
@@ -92,12 +91,13 @@ you never need to start it manually.
|
|
|
92
91
|
warnDeprecated('logs', 'agents routines scheduler-logs');
|
|
93
92
|
if (options.follow) {
|
|
94
93
|
const { getDaemonDir } = await import('../lib/state.js');
|
|
94
|
+
const { followFile } = await import('../lib/log-follow.js');
|
|
95
95
|
const logPath = path.join(getDaemonDir(), 'logs.jsonl');
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
process.on('SIGINT', () => {
|
|
96
|
+
const recent = readDaemonLog(parseInt(options.lines, 10));
|
|
97
|
+
if (recent)
|
|
98
|
+
console.log(recent);
|
|
99
|
+
const stop = followFile(logPath, (text) => process.stdout.write(text), { fromEnd: true });
|
|
100
|
+
process.on('SIGINT', () => { stop(); process.exit(0); });
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
const lines = parseInt(options.lines, 10);
|
package/dist/commands/import.js
CHANGED
|
@@ -27,20 +27,17 @@ import * as os from 'os';
|
|
|
27
27
|
import * as path from 'path';
|
|
28
28
|
import { confirm } from '@inquirer/prompts';
|
|
29
29
|
import { ALL_AGENT_IDS } from '../lib/agents.js';
|
|
30
|
-
import { AGENTS, getCliPath, getCliVersion, agentLabel } from '../lib/agents.js';
|
|
30
|
+
import { AGENTS, getCliPath, getCliVersion, agentLabel, resolveAgentName } from '../lib/agents.js';
|
|
31
31
|
import { getVersionDir } from '../lib/versions.js';
|
|
32
32
|
import { finalizeImport, importAgentBinary, importAgentConfig, importInstallScriptBinary, isValidImportVersion, resolvePackageDirFromBinary, } from '../lib/import.js';
|
|
33
33
|
import { isPromptCancelled, isInteractiveTerminal } from './utils.js';
|
|
34
|
-
function isValidAgentId(value) {
|
|
35
|
-
return ALL_AGENT_IDS.includes(value);
|
|
36
|
-
}
|
|
37
34
|
async function runImport(agentArg, opts) {
|
|
38
|
-
|
|
35
|
+
const agentId = resolveAgentName(agentArg);
|
|
36
|
+
if (!agentId) {
|
|
39
37
|
console.error(chalk.red(`Unknown agent: ${agentArg}`));
|
|
40
38
|
console.error(chalk.gray(`Known agents: ${ALL_AGENT_IDS.join(', ')}`));
|
|
41
39
|
process.exit(1);
|
|
42
40
|
}
|
|
43
|
-
const agentId = agentArg;
|
|
44
41
|
const agent = AGENTS[agentId];
|
|
45
42
|
// installScript-based agents (Grok, Antigravity, Cursor, Kiro, Goose, Roo)
|
|
46
43
|
// don't have an npm package; their binary lives wherever the curl/brew
|
package/dist/commands/inspect.js
CHANGED
|
@@ -17,7 +17,7 @@ import * as os from 'os';
|
|
|
17
17
|
import * as path from 'path';
|
|
18
18
|
import chalk from 'chalk';
|
|
19
19
|
import * as yaml from 'yaml';
|
|
20
|
-
import { AGENTS, getCliState } from '../lib/agents.js';
|
|
20
|
+
import { AGENTS, getCliState, resolveAgentName } from '../lib/agents.js';
|
|
21
21
|
import { supports } from '../lib/capabilities.js';
|
|
22
22
|
import { readMeta, getUserAgentsDir, getSystemAgentsDir, getProjectAgentsDir, getEnabledExtraRepos, } from '../lib/state.js';
|
|
23
23
|
import { getVersionHomePath } from '../lib/versions.js';
|
|
@@ -63,12 +63,16 @@ export async function inspectAction(target, options) {
|
|
|
63
63
|
await inspectRepo(repo, options);
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
// Repo targets take precedence over typo correction; only fall through to
|
|
67
|
+
// parseTarget when the key resolves to an agent (alias or single-edit fix).
|
|
68
|
+
if (!resolveAgentName(agentKey)) {
|
|
69
|
+
const extras = getEnabledExtraRepos();
|
|
70
|
+
console.error(chalk.red(`Unknown target: ${target}`));
|
|
71
|
+
console.error(chalk.gray(`Agents: ${Object.keys(AGENTS).join(', ')}`));
|
|
72
|
+
const aliases = extras.length > 0 ? `, ${extras.map(e => e.alias).join(', ')}` : '';
|
|
73
|
+
console.error(chalk.gray(`Repos: user, system, project${aliases} — or a path to a repo with a .agents/ dir`));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
72
76
|
}
|
|
73
77
|
const { agent, version } = parseTarget(target);
|
|
74
78
|
const versionHome = getVersionHomePath(agent, version);
|
|
@@ -93,7 +97,12 @@ export async function inspectAction(target, options) {
|
|
|
93
97
|
}
|
|
94
98
|
function parseTarget(target) {
|
|
95
99
|
const [rawAgent, rawVersion] = target.split('@');
|
|
96
|
-
const agent = (rawAgent || '')
|
|
100
|
+
const agent = resolveAgentName(rawAgent || '');
|
|
101
|
+
if (!agent) {
|
|
102
|
+
console.error(chalk.red(`Unknown agent: ${rawAgent}`));
|
|
103
|
+
console.error(chalk.gray(`Known agents: ${Object.keys(AGENTS).join(', ')}`));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
97
106
|
let version = rawVersion;
|
|
98
107
|
if (!version || version === 'default') {
|
|
99
108
|
const meta = readMeta();
|
package/dist/commands/models.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import * as fs from 'fs';
|
|
10
|
+
import { homeDir } from '../lib/platform/index.js';
|
|
10
11
|
import { resolveAgentName, formatAgentError, agentLabel, } from '../lib/agents.js';
|
|
11
12
|
import { listInstalledVersions, getGlobalDefault, resolveVersion, resolveVersionAlias } from '../lib/versions.js';
|
|
12
13
|
import { getModelCatalog, locateModelSource } from '../lib/models.js';
|
|
@@ -166,5 +167,5 @@ function printCatalog(agent, version, isDefault, options) {
|
|
|
166
167
|
}
|
|
167
168
|
/** Abbreviate a path by replacing the home directory with ~. */
|
|
168
169
|
function shortPath(p) {
|
|
169
|
-
return p.replace(
|
|
170
|
+
return p.replace(homeDir(), '~');
|
|
170
171
|
}
|
package/dist/commands/plugins.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import * as fs from 'fs';
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import chalk from 'chalk';
|
|
11
|
+
import { homeDir } from '../lib/platform/index.js';
|
|
11
12
|
import { input } from '@inquirer/prompts';
|
|
12
13
|
import { agentLabel } from '../lib/agents.js';
|
|
13
14
|
import { capableAgents, isCapable } from '../lib/capabilities.js';
|
|
@@ -21,7 +22,7 @@ import { safeJoin } from '../lib/paths.js';
|
|
|
21
22
|
import { discoverMarketplaces } from '../lib/plugin-marketplace.js';
|
|
22
23
|
/** Replace the home directory prefix with ~ for display. */
|
|
23
24
|
function formatPath(p) {
|
|
24
|
-
const home =
|
|
25
|
+
const home = homeDir();
|
|
25
26
|
if (home && p.startsWith(home)) {
|
|
26
27
|
return '~' + p.slice(home.length);
|
|
27
28
|
}
|
|
@@ -355,7 +356,7 @@ Examples:
|
|
|
355
356
|
});
|
|
356
357
|
}
|
|
357
358
|
const name = nameArg;
|
|
358
|
-
const pluginsDir = path.join(
|
|
359
|
+
const pluginsDir = path.join(homeDir(), '.agents', 'plugins');
|
|
359
360
|
const pluginRoot = safeJoin(pluginsDir, name);
|
|
360
361
|
// Use discovered plugin when present; fall back to name+root if source is already gone
|
|
361
362
|
const plugin = getPlugin(name);
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Recompiles only when source files have changed.
|
|
7
7
|
*/
|
|
8
8
|
import chalk from 'chalk';
|
|
9
|
-
import { AGENTS } from '../lib/agents.js';
|
|
9
|
+
import { AGENTS, resolveAgentName } from '../lib/agents.js';
|
|
10
10
|
import { isVersionInstalled } from '../lib/versions.js';
|
|
11
11
|
import { ensureRulesFresh, supportsRulesImports } from '../lib/rules/compile.js';
|
|
12
12
|
/**
|
|
@@ -23,12 +23,12 @@ export function registerRefreshRulesCommand(program) {
|
|
|
23
23
|
.requiredOption('--agent-version <version>', 'Installed version whose rules file should be refreshed')
|
|
24
24
|
.option('--quiet', 'Suppress all output (exit code indicates success)', false)
|
|
25
25
|
.action((opts) => {
|
|
26
|
-
const agentId = opts.agent;
|
|
26
|
+
const agentId = resolveAgentName(opts.agent);
|
|
27
27
|
const version = opts.agentVersion;
|
|
28
28
|
const quiet = !!opts.quiet;
|
|
29
|
-
if (!
|
|
29
|
+
if (!agentId) {
|
|
30
30
|
if (!quiet)
|
|
31
|
-
console.error(chalk.red(`Unknown agent '${
|
|
31
|
+
console.error(chalk.red(`Unknown agent '${opts.agent}'`));
|
|
32
32
|
process.exitCode = 1;
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
@@ -14,6 +14,7 @@ import { isDaemonRunning, signalDaemonReload, startDaemon, stopDaemon, readDaemo
|
|
|
14
14
|
import { humanizeCron, humanizeNextRun, formatRepoLink, REPO_DISPLAY_MAX } from '../lib/routines-format.js';
|
|
15
15
|
import { listJobs as listAllJobs, deleteJob, readJob, validateJob, writeJob, setJobEnabled, listRuns, getLatestRun, getRunDir, getJobPath, parseAtTime, } from '../lib/routines.js';
|
|
16
16
|
import { getRoutinesDir } from '../lib/state.js';
|
|
17
|
+
import { IS_WINDOWS } from '../lib/platform/index.js';
|
|
17
18
|
import { safeJoin } from '../lib/paths.js';
|
|
18
19
|
import { executeJob, executeJobDetached } from '../lib/runner.js';
|
|
19
20
|
import { JobScheduler } from '../lib/scheduler.js';
|
|
@@ -385,7 +386,7 @@ export function registerRoutinesCommands(program) {
|
|
|
385
386
|
console.log(chalk.gray(`Created new job file: ${newPath}`));
|
|
386
387
|
}
|
|
387
388
|
const targetPath = jobPath || path.join(getRoutinesDir(), `${name}.yml`);
|
|
388
|
-
const editor = process.env.EDITOR || process.env.VISUAL || 'vi';
|
|
389
|
+
const editor = process.env.EDITOR || process.env.VISUAL || (IS_WINDOWS ? 'notepad' : 'vi');
|
|
389
390
|
const editorParts = editor.split(/\s+/).filter(Boolean);
|
|
390
391
|
const editorBin = editorParts[0];
|
|
391
392
|
const editorArgs = [...editorParts.slice(1), targetPath];
|
|
@@ -691,14 +692,14 @@ export function registerRoutinesCommands(program) {
|
|
|
691
692
|
.option('-f, --follow', 'Stream log output in real time (like tail -f)')
|
|
692
693
|
.action(async (options) => {
|
|
693
694
|
if (options.follow) {
|
|
694
|
-
const { spawn } = await import('child_process');
|
|
695
695
|
const { getDaemonDir } = await import('../lib/state.js');
|
|
696
|
+
const { followFile } = await import('../lib/log-follow.js');
|
|
696
697
|
const logPath = path.join(getDaemonDir(), 'logs.jsonl');
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
process.on('SIGINT', () => {
|
|
698
|
+
const recent = readDaemonLog(parseInt(options.lines, 10));
|
|
699
|
+
if (recent)
|
|
700
|
+
console.log(recent);
|
|
701
|
+
const stop = followFile(logPath, (text) => process.stdout.write(text), { fromEnd: true });
|
|
702
|
+
process.on('SIGINT', () => { stop(); process.exit(0); });
|
|
702
703
|
return;
|
|
703
704
|
}
|
|
704
705
|
const lines = parseInt(options.lines, 10);
|
|
@@ -23,6 +23,7 @@ import { parseSession } from '../lib/session/parse.js';
|
|
|
23
23
|
import { renderConversationMarkdown, renderSummary, renderSummaryHeader, computeSummaryStats, renderJson, filterEvents, parseRoleList } from '../lib/session/render.js';
|
|
24
24
|
import { renderMarkdown } from '../lib/markdown.js';
|
|
25
25
|
import { colorAgent, resolveAgentName } from '../lib/agents.js';
|
|
26
|
+
import { fuzzyMatch, FUZZY_PRESETS } from '../lib/fuzzy.js';
|
|
26
27
|
import { resolveVersionAliasLoose } from '../lib/versions.js';
|
|
27
28
|
import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
|
|
28
29
|
import { sessionPicker } from './sessions-picker.js';
|
|
@@ -822,8 +823,22 @@ function parseAgentFilter(agentName) {
|
|
|
822
823
|
if (!agentName)
|
|
823
824
|
return {};
|
|
824
825
|
const [name, version] = agentName.split('@', 2);
|
|
825
|
-
|
|
826
|
-
|
|
826
|
+
let agent = SESSION_AGENTS.includes(name)
|
|
827
|
+
? name
|
|
828
|
+
: null;
|
|
829
|
+
if (!agent) {
|
|
830
|
+
// Aliases and single-typo corrections (cladue -> claude). SESSION_AGENTS
|
|
831
|
+
// includes ids (rush, hermes) that resolveAgentName doesn't know, so fall
|
|
832
|
+
// back to fuzzy-matching the session list directly.
|
|
833
|
+
const resolved = resolveAgentName(name);
|
|
834
|
+
if (resolved && SESSION_AGENTS.includes(resolved)) {
|
|
835
|
+
agent = resolved;
|
|
836
|
+
}
|
|
837
|
+
else {
|
|
838
|
+
agent = fuzzyMatch(name, SESSION_AGENTS, FUZZY_PRESETS.agents);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
if (!agent) {
|
|
827
842
|
console.error(chalk.red(`Unknown agent: ${name}. Use: ${SESSION_AGENTS.join(', ')}`));
|
|
828
843
|
process.exit(1);
|
|
829
844
|
}
|
package/dist/commands/setup.js
CHANGED
|
@@ -145,8 +145,8 @@ export async function runSetup(program, options = {}) {
|
|
|
145
145
|
if (!isShimsInPath()) {
|
|
146
146
|
const pathResult = addShimsToPath();
|
|
147
147
|
if (pathResult.success && !pathResult.alreadyPresent) {
|
|
148
|
-
console.log(chalk.green(`\nAdded shims to
|
|
149
|
-
console.log(chalk.gray(
|
|
148
|
+
console.log(chalk.green(`\nAdded shims to ${pathResult.location}`));
|
|
149
|
+
console.log(chalk.gray(pathResult.reloadHint));
|
|
150
150
|
}
|
|
151
151
|
else if (!pathResult.success) {
|
|
152
152
|
console.log(chalk.yellow('\nTo enable version switching, add shims to PATH:'));
|
|
@@ -10,6 +10,7 @@ import ora from 'ora';
|
|
|
10
10
|
import * as fs from 'fs';
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import { agentLabel } from '../lib/agents.js';
|
|
13
|
+
import { homeDir } from '../lib/platform/index.js';
|
|
13
14
|
import { capableAgents } from '../lib/capabilities.js';
|
|
14
15
|
import { cloneRepo } from '../lib/git.js';
|
|
15
16
|
import { discoverSubagentsFromRepo, installSubagentCentrally, listInstalledSubagents, getInstalledSubagent, listSubagentsForAgent, iterSubagentsCapableVersions, removeSubagentFromVersion, } from '../lib/subagents.js';
|
|
@@ -19,7 +20,7 @@ import { requireDestructiveArg, promptRemovalTargets, parseCommaSeparatedList, r
|
|
|
19
20
|
import { showResourceList, buildTargetsSection, } from './resource-view.js';
|
|
20
21
|
/** Replace the home directory prefix with ~ for display. */
|
|
21
22
|
function formatPath(p) {
|
|
22
|
-
const home =
|
|
23
|
+
const home = homeDir();
|
|
23
24
|
if (home && p.startsWith(home)) {
|
|
24
25
|
return '~' + p.slice(home.length);
|
|
25
26
|
}
|
package/dist/commands/usage.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { ALL_AGENT_IDS, AGENTS, getAccountInfo, agentLabel, } from '../lib/agents.js';
|
|
2
|
+
import { ALL_AGENT_IDS, AGENTS, getAccountInfo, agentLabel, resolveAgentName, formatAgentError, } from '../lib/agents.js';
|
|
3
3
|
import { listInstalledVersions, getGlobalDefault, getVersionHomePath } from '../lib/versions.js';
|
|
4
4
|
import { formatUsageSection, getUsageInfoForIdentity } from '../lib/usage.js';
|
|
5
5
|
/** Agents whose CLI surfaces usage data we can read today. */
|
|
@@ -15,9 +15,17 @@ Examples:
|
|
|
15
15
|
agents usage codex Show usage for Codex only
|
|
16
16
|
`)
|
|
17
17
|
.action(async (agentFilter) => {
|
|
18
|
-
|
|
18
|
+
let filter;
|
|
19
|
+
if (agentFilter) {
|
|
20
|
+
const resolved = resolveAgentName(agentFilter);
|
|
21
|
+
if (!resolved) {
|
|
22
|
+
console.error(chalk.red(formatAgentError(agentFilter)));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
filter = resolved;
|
|
26
|
+
}
|
|
19
27
|
const targets = filter
|
|
20
|
-
? [filter]
|
|
28
|
+
? [filter]
|
|
21
29
|
: ALL_AGENT_IDS.filter((id) => listInstalledVersions(id).length > 0);
|
|
22
30
|
if (targets.length === 0) {
|
|
23
31
|
console.log(chalk.gray('No agents installed. Run `agents add <agent>` first.'));
|
|
@@ -402,8 +402,8 @@ export function registerVersionsCommands(program) {
|
|
|
402
402
|
if (!isShimsInPath()) {
|
|
403
403
|
const pathResult = addShimsToPath();
|
|
404
404
|
if (pathResult.success && !pathResult.alreadyPresent) {
|
|
405
|
-
console.log(chalk.green(` Added shims to
|
|
406
|
-
console.log(chalk.gray('
|
|
405
|
+
console.log(chalk.green(` Added shims to ${pathResult.location}`));
|
|
406
|
+
console.log(chalk.gray(' ' + pathResult.reloadHint));
|
|
407
407
|
}
|
|
408
408
|
else if (!pathResult.success) {
|
|
409
409
|
console.log(chalk.yellow('\nCould not auto-add shims to PATH:'));
|