@phnx-labs/agents-cli 1.20.92 → 1.21.0
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 +385 -0
- package/README.md +3 -0
- package/dist/bin/agents +0 -0
- package/dist/commands/beta.js +3 -5
- package/dist/commands/doctor.js +23 -0
- package/dist/commands/events.js +91 -1
- package/dist/commands/exec.js +13 -0
- package/dist/commands/mailboxes.js +39 -1
- package/dist/commands/message.js +12 -1
- package/dist/commands/packages.js +14 -5
- package/dist/commands/projects.d.ts +38 -0
- package/dist/commands/projects.js +355 -48
- package/dist/commands/routines.js +27 -1
- package/dist/commands/rules.js +6 -0
- package/dist/commands/secrets.d.ts +17 -0
- package/dist/commands/secrets.js +198 -7
- package/dist/commands/send.d.ts +14 -12
- package/dist/commands/send.js +105 -35
- package/dist/commands/sessions.d.ts +17 -0
- package/dist/commands/sessions.js +16 -8
- package/dist/commands/setup-browser.js +5 -1
- package/dist/commands/setup-fleet.js +5 -0
- package/dist/commands/setup-preferences.d.ts +53 -0
- package/dist/commands/setup-preferences.js +142 -0
- package/dist/commands/setup.js +8 -9
- package/dist/commands/ssh.js +220 -10
- package/dist/commands/sync.d.ts +2 -2
- package/dist/commands/sync.js +13 -12
- package/dist/commands/view.js +4 -0
- package/dist/commands/watchdog.js +26 -3
- package/dist/index.js +38 -6
- package/dist/lib/activity.d.ts +15 -0
- package/dist/lib/activity.js +26 -2
- package/dist/lib/auto-dispatch.d.ts +6 -1
- package/dist/lib/auto-dispatch.js +7 -2
- package/dist/lib/beta.d.ts +1 -1
- package/dist/lib/beta.js +1 -1
- package/dist/lib/channels/send.d.ts +83 -0
- package/dist/lib/channels/send.js +112 -0
- package/dist/lib/daemon.d.ts +13 -0
- package/dist/lib/daemon.js +80 -60
- package/dist/lib/device-config.d.ts +82 -0
- package/dist/lib/device-config.js +296 -0
- package/dist/lib/event-provenance.d.ts +19 -0
- package/dist/lib/event-provenance.js +48 -0
- package/dist/lib/events-ingest.d.ts +46 -0
- package/dist/lib/events-ingest.js +182 -0
- package/dist/lib/events.d.ts +17 -5
- package/dist/lib/events.js +59 -56
- package/dist/lib/feed.d.ts +1 -1
- package/dist/lib/feed.js +2 -0
- package/dist/lib/git.d.ts +13 -2
- package/dist/lib/git.js +38 -6
- package/dist/lib/linear-project-counts.d.ts +129 -0
- package/dist/lib/linear-project-counts.js +206 -0
- package/dist/lib/linear-projects.d.ts +62 -0
- package/dist/lib/linear-projects.js +144 -0
- package/dist/lib/mailbox-gc.js +30 -7
- package/dist/lib/mailbox.d.ts +14 -1
- package/dist/lib/mailbox.js +35 -3
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/install-menubar.d.ts +5 -21
- package/dist/lib/menubar/install-menubar.js +35 -44
- package/dist/lib/menubar/notify-desktop.d.ts +17 -2
- package/dist/lib/menubar/notify-desktop.js +8 -2
- package/dist/lib/migrate.js +1 -1
- package/dist/lib/models.js +21 -11
- package/dist/lib/overdue.d.ts +1 -1
- package/dist/lib/overdue.js +54 -19
- package/dist/lib/project-import.d.ts +96 -0
- package/dist/lib/project-import.js +171 -0
- package/dist/lib/project-probe.d.ts +75 -0
- package/dist/lib/project-probe.js +160 -0
- package/dist/lib/project-resources.d.ts +8 -0
- package/dist/lib/project-resources.js +31 -3
- package/dist/lib/project-status.d.ts +32 -1
- package/dist/lib/project-status.js +82 -1
- package/dist/lib/projects.d.ts +6 -0
- package/dist/lib/projects.js +12 -0
- package/dist/lib/remote-agents-json.d.ts +14 -1
- package/dist/lib/remote-agents-json.js +21 -3
- package/dist/lib/routine-notify.d.ts +11 -0
- package/dist/lib/routine-notify.js +22 -0
- package/dist/lib/routines.d.ts +53 -0
- package/dist/lib/routines.js +105 -4
- package/dist/lib/rules/run-sync.d.ts +18 -0
- package/dist/lib/rules/run-sync.js +92 -0
- package/dist/lib/run-notify.js +3 -0
- package/dist/lib/scheduler.js +12 -2
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/audit.d.ts +1 -1
- package/dist/lib/secrets/audit.js +53 -10
- package/dist/lib/secrets/index.d.ts +4 -5
- package/dist/lib/secrets/index.js +4 -5
- package/dist/lib/secrets/list-filter.d.ts +20 -5
- package/dist/lib/secrets/list-filter.js +22 -6
- package/dist/lib/secrets/usage-db.d.ts +106 -0
- package/dist/lib/secrets/usage-db.js +236 -0
- package/dist/lib/session/active.d.ts +16 -2
- package/dist/lib/session/active.js +8 -4
- package/dist/lib/session/bundle.js +5 -1
- package/dist/lib/session/remote-active.d.ts +5 -1
- package/dist/lib/session/remote-active.js +4 -1
- package/dist/lib/session/remote-list.d.ts +1 -15
- package/dist/lib/session/remote-list.js +22 -111
- package/dist/lib/session/sync/config.d.ts +13 -5
- package/dist/lib/session/sync/config.js +21 -13
- package/dist/lib/sqlite.js +28 -1
- package/dist/lib/startup/command-registry.d.ts +0 -2
- package/dist/lib/startup/command-registry.js +1 -5
- package/dist/lib/state.d.ts +19 -2
- package/dist/lib/state.js +99 -10
- package/dist/lib/sync-umbrella.d.ts +11 -23
- package/dist/lib/sync-umbrella.js +14 -45
- package/dist/lib/teams/agents.d.ts +35 -3
- package/dist/lib/teams/agents.js +52 -8
- package/dist/lib/teams/scheduler.d.ts +29 -2
- package/dist/lib/teams/scheduler.js +60 -16
- package/dist/lib/types.d.ts +22 -5
- package/dist/lib/versions.d.ts +6 -0
- package/dist/lib/versions.js +6 -4
- package/package.json +1 -2
- package/dist/commands/drive.d.ts +0 -10
- package/dist/commands/drive.js +0 -183
- package/dist/commands/hq.d.ts +0 -2
- package/dist/commands/hq.js +0 -58
- package/dist/commands/sessions-sync.d.ts +0 -17
- package/dist/commands/sessions-sync.js +0 -135
- package/dist/commands/sync-provision.d.ts +0 -23
- package/dist/commands/sync-provision.js +0 -107
- package/dist/lib/drive-sync.d.ts +0 -45
- package/dist/lib/drive-sync.js +0 -238
- package/dist/lib/hq/floor.d.ts +0 -87
- package/dist/lib/hq/floor.js +0 -243
- package/dist/lib/session/sync/crdt.d.ts +0 -44
- package/dist/lib/session/sync/crdt.js +0 -119
- package/dist/lib/session/sync/manifest.d.ts +0 -62
- package/dist/lib/session/sync/manifest.js +0 -100
- package/dist/lib/session/sync/provision.d.ts +0 -49
- package/dist/lib/session/sync/provision.js +0 -91
- package/dist/lib/session/sync/r2.d.ts +0 -32
- package/dist/lib/session/sync/r2.js +0 -121
- package/dist/lib/session/sync/sync.d.ts +0 -106
- package/dist/lib/session/sync/sync.js +0 -374
|
@@ -2,7 +2,9 @@ import * as os from 'os';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { die, humanDuration, relTime, truncate, visibleWidth } from '../lib/format.js';
|
|
5
|
+
import { setHelpSections } from '../lib/help.js';
|
|
5
6
|
import { listBoxes, readBox, mailboxDir, isValidMailboxId, watchMessages, } from '../lib/mailbox.js';
|
|
7
|
+
import { gcMailbox } from '../lib/mailbox-gc.js';
|
|
6
8
|
import { GLYPH, masthead, sparkline, aggregate, hourlyCounts, graphEdges, } from '../lib/comms-render.js';
|
|
7
9
|
import { getMailboxRootDir } from '../lib/state.js';
|
|
8
10
|
import { getActiveSessions } from '../lib/session/active.js';
|
|
@@ -262,6 +264,21 @@ function renderBetween(boxes, a, b, json) {
|
|
|
262
264
|
console.log(` ${truncate(m.text.replace(/\s+/g, ' ').trim(), 100)}`);
|
|
263
265
|
}
|
|
264
266
|
}
|
|
267
|
+
async function runGcCommand(opts) {
|
|
268
|
+
const sessions = await getActiveSessions();
|
|
269
|
+
const activeBoxIds = new Set(sessions.map(mailboxIdForActiveSession).filter((id) => !!id));
|
|
270
|
+
const result = gcMailbox(activeBoxIds);
|
|
271
|
+
if (opts.json) {
|
|
272
|
+
console.log(JSON.stringify(result, null, 2));
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (result.messagesDroppedDead === 0 && result.messagesDroppedExpired === 0) {
|
|
276
|
+
console.log(chalk.dim(`gc: ${result.boxesScanned} boxes scanned, no pending messages dropped.`));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
console.log(chalk.yellow(`gc: ${result.messagesDroppedDead} dead-box messages, ${result.messagesDroppedExpired} expired messages dropped ` +
|
|
280
|
+
`(${result.boxesScanned} boxes scanned, ${result.deadBoxes} dead boxes).`));
|
|
281
|
+
}
|
|
265
282
|
function renderGraph(boxes, filters, json) {
|
|
266
283
|
const nonEmpty = boxes.filter((b) => b.messages.length > 0);
|
|
267
284
|
const msgs = aggregate(nonEmpty).filter((m) => matchesFilters(m, m.toLabel, m.box, filters));
|
|
@@ -313,7 +330,7 @@ function newestMessage(box) {
|
|
|
313
330
|
return box.messages.reduce((a, b) => (a.ts >= b.ts ? a : b));
|
|
314
331
|
}
|
|
315
332
|
export function registerMailboxesCommand(program) {
|
|
316
|
-
program
|
|
333
|
+
const cmd = program
|
|
317
334
|
.command('mailboxes')
|
|
318
335
|
.alias('mailbox')
|
|
319
336
|
.argument('[id]', 'A mailbox id (session UUID / teams agentId) to inspect in full')
|
|
@@ -387,4 +404,25 @@ export function registerMailboxesCommand(program) {
|
|
|
387
404
|
}
|
|
388
405
|
renderOverview(boxes, limit, filters);
|
|
389
406
|
});
|
|
407
|
+
const gcCmd = cmd
|
|
408
|
+
.command('gc')
|
|
409
|
+
.description('Run a liveness sweep: archive pending messages in dead boxes and prune stale consumed mail.')
|
|
410
|
+
.option('--json', 'Emit the GC result as JSON')
|
|
411
|
+
.action(async (_opts, command) => runGcCommand({ json: command.optsWithGlobals().json === true }));
|
|
412
|
+
setHelpSections(gcCmd, {
|
|
413
|
+
examples: `
|
|
414
|
+
# One-shot sweep using the live session set as the liveness source
|
|
415
|
+
agents mailboxes gc
|
|
416
|
+
|
|
417
|
+
# Machine-readable summary (for scripts / monitors)
|
|
418
|
+
agents mailboxes gc --json
|
|
419
|
+
`,
|
|
420
|
+
notes: `
|
|
421
|
+
A box is considered dead when no live session (the same source
|
|
422
|
+
\`agents sessions --active\` uses) owns it. Pending messages in dead boxes
|
|
423
|
+
are archived as \`dropped: dead\`; expired messages in live boxes are
|
|
424
|
+
archived as \`dropped: expired\'. Both surfaces a failure receipt back to
|
|
425
|
+
the feed store when the message carried a blockId.
|
|
426
|
+
`,
|
|
427
|
+
});
|
|
390
428
|
}
|
package/dist/commands/message.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
3
|
import { die } from '../lib/format.js';
|
|
4
|
+
import { parseDuration } from '../lib/hooks/cache.js';
|
|
4
5
|
import { getActiveSessions } from '../lib/session/active.js';
|
|
5
6
|
import { getTaskById, updateTaskStatus } from '../lib/cloud/store.js';
|
|
6
7
|
import { resolveProvider } from '../lib/cloud/registry.js';
|
|
@@ -53,6 +54,7 @@ async function deliverViaMailbox(mailboxId, text, block, opts) {
|
|
|
53
54
|
text,
|
|
54
55
|
from: opts.from,
|
|
55
56
|
blockId: block?.blockId,
|
|
57
|
+
ttlSeconds: opts.ttlSeconds,
|
|
56
58
|
});
|
|
57
59
|
if (block) {
|
|
58
60
|
recordMessageReceipt(block.blockId, {
|
|
@@ -116,10 +118,19 @@ export function registerMessageCommand(program) {
|
|
|
116
118
|
.option('--from <who>', 'Label recorded as the sender of this message')
|
|
117
119
|
.option('--as <operator>', 'Verified operator id answering a high-consequence block')
|
|
118
120
|
.option('--surface <surface>', 'Surface that is sending this answer (feed, terminal, etc.)', 'cli')
|
|
121
|
+
.option('--ttl <dur>', 'Delivery TTL if the message is not consumed (e.g. 30m, 1h, 24h); 0 disables expiry')
|
|
119
122
|
.action(async (target, text, opts) => {
|
|
120
123
|
if (!target.trim()) {
|
|
121
124
|
die('Target must be a session/agent id or cloud task id. Run `agents sessions --active` to list running agents.');
|
|
122
125
|
}
|
|
126
|
+
let ttlSeconds;
|
|
127
|
+
if (opts.ttl !== undefined) {
|
|
128
|
+
const parsed = parseDuration(opts.ttl);
|
|
129
|
+
if (parsed == null) {
|
|
130
|
+
die(`Invalid --ttl ${JSON.stringify(opts.ttl)}: expected a duration like 30m, 1h, 24h, or 0.`);
|
|
131
|
+
}
|
|
132
|
+
ttlSeconds = parsed;
|
|
133
|
+
}
|
|
123
134
|
const sessions = await getActiveSessions();
|
|
124
135
|
const res = resolveMessageTarget(target, sessions, (id) => getTaskById(id) != null);
|
|
125
136
|
switch (res.kind) {
|
|
@@ -152,7 +163,7 @@ export function registerMessageCommand(program) {
|
|
|
152
163
|
// First-answer-wins for any path that closes an open block.
|
|
153
164
|
claimBlockAnswer(block, opts);
|
|
154
165
|
if (route.kind === 'mailbox') {
|
|
155
|
-
await deliverViaMailbox(res.id, text, block, opts);
|
|
166
|
+
await deliverViaMailbox(res.id, text, block, { from: opts.from, ttlSeconds });
|
|
156
167
|
return;
|
|
157
168
|
}
|
|
158
169
|
if (route.kind === 'tmux' || route.kind === 'iterm' || route.kind === 'pty') {
|
|
@@ -14,7 +14,7 @@ import { AGENTS, getAllCliStates, agentLabel, } from '../lib/agents.js';
|
|
|
14
14
|
import { capableAgents } from '../lib/capabilities.js';
|
|
15
15
|
import { DEFAULT_REGISTRIES } from '../lib/types.js';
|
|
16
16
|
import { getRegistries, setRegistry, removeRegistry, search as searchRegistries, resolvePackage, validatedNpmSpec, validatedPyPISpec, buildSkillIndex, verifySkillIntegrity, parseOwnerRepoFromRemote, } from '../lib/registry.js';
|
|
17
|
-
import { cloneRepo, commitAndPush, getRemoteUrl, isGitRepo } from '../lib/git.js';
|
|
17
|
+
import { cloneRepo, commitAndPush, getCurrentBranch, getRemoteUrl, isGitRepo } from '../lib/git.js';
|
|
18
18
|
import { discoverCommands, resolveCommandSource, installCommand, installCommandCentrally, } from '../lib/commands.js';
|
|
19
19
|
import { discoverSkillsFromRepo, installSkill, installSkillCentrally, } from '../lib/skills.js';
|
|
20
20
|
import { discoverHooksFromRepo, installHooks, installHooksCentrally, } from '../lib/hooks.js';
|
|
@@ -335,7 +335,7 @@ When to use:
|
|
|
335
335
|
.description('Generate a skills-index.json for a git repo and push it, making its skills discoverable via agents search/install')
|
|
336
336
|
.option('--repo <alias>', 'Publish an extra repo added via `agents repo add` (default: your ~/.agents repo)')
|
|
337
337
|
.option('--name <name>', 'Registry name to suggest in the output (default: the repo name)')
|
|
338
|
-
.option('--branch <branch>', 'Branch the raw URL
|
|
338
|
+
.option('--branch <branch>', 'Branch to push the index to and reference in the raw URL (default: the repo\'s current branch)')
|
|
339
339
|
.option('--dry-run', 'Write the index and print the URL without committing or pushing')
|
|
340
340
|
.addHelpText('after', `
|
|
341
341
|
Publish walks a repo's skills/ directory, records a sha256 of every SKILL.md,
|
|
@@ -398,20 +398,29 @@ the sha256 in the index and abort on mismatch.
|
|
|
398
398
|
for (const s of index.skills) {
|
|
399
399
|
console.log(` ${chalk.cyan(s.name)} ${chalk.gray(`sha256:${s.sha256?.slice(0, 12)}…`)}`);
|
|
400
400
|
}
|
|
401
|
+
// The branch the URL references must be the branch the index actually
|
|
402
|
+
// lands on. In a real push that's whatever commitAndPush reports back
|
|
403
|
+
// (the requested --branch, else the checked-out branch); in a dry run we
|
|
404
|
+
// resolve it the same way without pushing.
|
|
405
|
+
let urlBranch;
|
|
401
406
|
if (options.dryRun) {
|
|
407
|
+
urlBranch = options.branch || (await getCurrentBranch(repoDir));
|
|
402
408
|
console.log(chalk.gray(`\nDry run — wrote ${indexPath} but did not commit or push.`));
|
|
403
409
|
}
|
|
404
410
|
else {
|
|
405
411
|
const pushSpinner = ora('Committing and pushing skills-index.json...').start();
|
|
406
|
-
const result = await commitAndPush(repoDir, 'chore: update skills-index.json (agents publish)');
|
|
412
|
+
const result = await commitAndPush(repoDir, 'chore: update skills-index.json (agents publish)', options.branch);
|
|
407
413
|
if (!result.success) {
|
|
408
414
|
pushSpinner.fail(`Push failed: ${result.error}`);
|
|
409
415
|
console.log(chalk.gray('The index was written locally — commit and push it manually to publish.'));
|
|
410
416
|
process.exit(1);
|
|
411
417
|
}
|
|
412
|
-
|
|
418
|
+
// commitAndPush always reports the pushed branch on success; the `??`
|
|
419
|
+
// only satisfies the optional return type, it is not a behavior path.
|
|
420
|
+
urlBranch = result.branch ?? (await getCurrentBranch(repoDir));
|
|
421
|
+
pushSpinner.succeed(`Pushed skills-index.json to ${urlBranch}`);
|
|
413
422
|
}
|
|
414
|
-
const rawUrl = `https://raw.githubusercontent.com/${repoSlug}/${
|
|
423
|
+
const rawUrl = `https://raw.githubusercontent.com/${repoSlug}/${urlBranch}/skills-index.json`;
|
|
415
424
|
const registryName = options.name || repoSlug.split('/')[1] || 'my-skills';
|
|
416
425
|
console.log(chalk.bold('\nPublished. Share these with anyone who wants your skills:\n'));
|
|
417
426
|
console.log(chalk.gray(' Index URL:'));
|
|
@@ -9,4 +9,42 @@
|
|
|
9
9
|
* lifecycle state, plan completion, open PRs, and tickets in flight.
|
|
10
10
|
*/
|
|
11
11
|
import type { Command } from 'commander';
|
|
12
|
+
import { type LinearMilestone } from '../lib/linear-project-counts.js';
|
|
13
|
+
/** Recursion guard: a peer answering a probe fan-out never re-fans-out itself. */
|
|
14
|
+
export declare const PROJECTS_NO_FANOUT_ENV = "AGENTS_PROJECTS_LOCAL";
|
|
15
|
+
/**
|
|
16
|
+
* One compact trailing note for peers that didn't answer the `--fleet`
|
|
17
|
+
* fan-out — unreachable, running an agents-cli too old to carry `projects
|
|
18
|
+
* probe`, or too slow to finish inside the 12s SSH budget. Mirrors
|
|
19
|
+
* `formatUnreachableNote` (activity) with the probe-specific reasons; empty
|
|
20
|
+
* string when everything answered.
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatFleetSkippedNote(skipped: string[]): string;
|
|
23
|
+
/** One `projects list` row, pre-render. */
|
|
24
|
+
export interface ProjectListRow {
|
|
25
|
+
name: string;
|
|
26
|
+
path: string;
|
|
27
|
+
repo: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Column widths for `projects list`, sized to the rows actually being printed.
|
|
31
|
+
* Fixed padding was the bug: home-relative roots run past 50 characters, so a
|
|
32
|
+
* hardcoded 32 pushed the repo column off its gridline on every long path.
|
|
33
|
+
* Paths longer than {@link LIST_PATH_MAX} truncate rather than widen the table.
|
|
34
|
+
*/
|
|
35
|
+
export declare function computeProjectListWidths(rows: ProjectListRow[]): {
|
|
36
|
+
name: number;
|
|
37
|
+
path: number;
|
|
38
|
+
repo: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* A milestone's target date as a person would say it — "due tomorrow",
|
|
42
|
+
* "overdue by 3 days", "due Aug 21" — never a raw `2026-08-21` or a duration in
|
|
43
|
+
* hours. Linear stores a calendar date with no timezone, so both sides are
|
|
44
|
+
* compared at LOCAL midnight; parsing `YYYY-MM-DD` with `new Date(str)` would
|
|
45
|
+
* read it as UTC and shift the answer by a day for anyone west of Greenwich.
|
|
46
|
+
*/
|
|
47
|
+
export declare function formatMilestoneDue(targetDate: string, nowMs: number): string | undefined;
|
|
48
|
+
/** The `next` card line: what this project is due to hit, and how far along it is. */
|
|
49
|
+
export declare function formatNextMilestone(ms: LinearMilestone, nowMs: number): string;
|
|
12
50
|
export declare function registerProjectsCommands(program: Command): void;
|