@phnx-labs/agents-cli 1.20.72 → 1.20.73

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.
Files changed (219) hide show
  1. package/CHANGELOG.md +299 -0
  2. package/README.md +40 -4
  3. package/dist/bin/agents +0 -0
  4. package/dist/commands/activity.d.ts +12 -0
  5. package/dist/commands/activity.js +68 -0
  6. package/dist/commands/apply.d.ts +13 -0
  7. package/dist/commands/apply.js +28 -3
  8. package/dist/commands/browser.js +1 -1
  9. package/dist/commands/cloud.js +21 -11
  10. package/dist/commands/doctor.js +8 -4
  11. package/dist/commands/events.d.ts +11 -10
  12. package/dist/commands/events.js +30 -21
  13. package/dist/commands/exec.d.ts +34 -0
  14. package/dist/commands/exec.js +337 -39
  15. package/dist/commands/feed.d.ts +13 -0
  16. package/dist/commands/feed.js +130 -29
  17. package/dist/commands/hq.d.ts +2 -0
  18. package/dist/commands/hq.js +58 -0
  19. package/dist/commands/lease.d.ts +19 -0
  20. package/dist/commands/lease.js +138 -11
  21. package/dist/commands/login.d.ts +2 -0
  22. package/dist/commands/login.js +123 -0
  23. package/dist/commands/logs.js +1 -1
  24. package/dist/commands/mine.d.ts +27 -0
  25. package/dist/commands/mine.js +207 -0
  26. package/dist/commands/monitors.js +79 -49
  27. package/dist/commands/plugins.js +1 -0
  28. package/dist/commands/profiles.js +158 -0
  29. package/dist/commands/repo.js +2 -60
  30. package/dist/commands/resources.d.ts +5 -0
  31. package/dist/commands/resources.js +95 -0
  32. package/dist/commands/routines.d.ts +2 -0
  33. package/dist/commands/routines.js +139 -37
  34. package/dist/commands/secrets.js +234 -47
  35. package/dist/commands/send.d.ts +15 -0
  36. package/dist/commands/send.js +62 -0
  37. package/dist/commands/sessions-tail.d.ts +1 -0
  38. package/dist/commands/sessions-tail.js +20 -9
  39. package/dist/commands/sessions.js +18 -3
  40. package/dist/commands/setup-mine.d.ts +18 -0
  41. package/dist/commands/setup-mine.js +106 -0
  42. package/dist/commands/setup-share.js +2 -2
  43. package/dist/commands/setup.js +3 -1
  44. package/dist/commands/share.d.ts +8 -1
  45. package/dist/commands/share.js +122 -37
  46. package/dist/commands/ssh.d.ts +9 -0
  47. package/dist/commands/ssh.js +196 -26
  48. package/dist/commands/sync.js +1 -1
  49. package/dist/commands/teams.js +11 -2
  50. package/dist/index.js +79 -10
  51. package/dist/lib/activity.d.ts +124 -0
  52. package/dist/lib/activity.js +542 -0
  53. package/dist/lib/agents.js +16 -5
  54. package/dist/lib/artifact-actions.d.ts +1 -1
  55. package/dist/lib/artifact-actions.js +1 -1
  56. package/dist/lib/ask-classifier.d.ts +2 -1
  57. package/dist/lib/ask-classifier.js +3 -3
  58. package/dist/lib/auth-health.d.ts +32 -4
  59. package/dist/lib/auth-health.js +40 -1
  60. package/dist/lib/auto-pull.js +8 -1
  61. package/dist/lib/brand.d.ts +40 -0
  62. package/dist/lib/brand.js +122 -0
  63. package/dist/lib/browser/drivers/ssh.js +4 -7
  64. package/dist/lib/browser/service.js +6 -8
  65. package/dist/lib/channels/providers/index.d.ts +2 -0
  66. package/dist/lib/channels/providers/index.js +20 -0
  67. package/dist/lib/channels/providers/mailbox.d.ts +2 -0
  68. package/dist/lib/channels/providers/mailbox.js +26 -0
  69. package/dist/lib/channels/providers/openclaw-telegram.d.ts +2 -0
  70. package/dist/lib/channels/providers/openclaw-telegram.js +34 -0
  71. package/dist/lib/channels/providers/rush.d.ts +6 -0
  72. package/dist/lib/channels/providers/rush.js +55 -0
  73. package/dist/lib/channels/registry.d.ts +42 -0
  74. package/dist/lib/channels/registry.js +20 -0
  75. package/dist/lib/channels/resolve.d.ts +11 -0
  76. package/dist/lib/channels/resolve.js +12 -0
  77. package/dist/lib/cli-resources.d.ts +18 -0
  78. package/dist/lib/cli-resources.js +53 -4
  79. package/dist/lib/cloud/codex.js +6 -3
  80. package/dist/lib/cloud/factory.d.ts +1 -0
  81. package/dist/lib/cloud/factory.js +10 -4
  82. package/dist/lib/cloud/rush.d.ts +3 -1
  83. package/dist/lib/cloud/rush.js +6 -1
  84. package/dist/lib/cloud/types.d.ts +2 -0
  85. package/dist/lib/codex-home.d.ts +35 -0
  86. package/dist/lib/codex-home.js +136 -0
  87. package/dist/lib/crabbox/cli.d.ts +44 -0
  88. package/dist/lib/crabbox/cli.js +120 -20
  89. package/dist/lib/crabbox/lease.d.ts +52 -1
  90. package/dist/lib/crabbox/lease.js +117 -16
  91. package/dist/lib/crabbox/progress.d.ts +31 -0
  92. package/dist/lib/crabbox/progress.js +76 -0
  93. package/dist/lib/crabbox/runtimes.d.ts +4 -0
  94. package/dist/lib/crabbox/runtimes.js +33 -8
  95. package/dist/lib/crabbox/setup-copy.d.ts +87 -0
  96. package/dist/lib/crabbox/setup-copy.js +127 -0
  97. package/dist/lib/daemon.d.ts +5 -5
  98. package/dist/lib/daemon.js +9 -9
  99. package/dist/lib/drive-sync.js +6 -3
  100. package/dist/lib/event-stream.d.ts +36 -0
  101. package/dist/lib/event-stream.js +68 -0
  102. package/dist/lib/events.d.ts +1 -1
  103. package/dist/lib/exec.d.ts +11 -0
  104. package/dist/lib/exec.js +23 -2
  105. package/dist/lib/feed-policy.d.ts +1 -1
  106. package/dist/lib/feed-policy.js +14 -9
  107. package/dist/lib/feed-ranking.d.ts +32 -0
  108. package/dist/lib/feed-ranking.js +224 -0
  109. package/dist/lib/feed.d.ts +35 -2
  110. package/dist/lib/feed.js +66 -3
  111. package/dist/lib/fleet/auth-sync.d.ts +53 -0
  112. package/dist/lib/fleet/auth-sync.js +92 -0
  113. package/dist/lib/fleet/remote-login.d.ts +187 -0
  114. package/dist/lib/fleet/remote-login.js +556 -0
  115. package/dist/lib/format.d.ts +30 -3
  116. package/dist/lib/format.js +34 -5
  117. package/dist/lib/fs-atomic.d.ts +7 -2
  118. package/dist/lib/fs-atomic.js +8 -12
  119. package/dist/lib/git.d.ts +16 -0
  120. package/dist/lib/git.js +79 -2
  121. package/dist/lib/heal.js +11 -3
  122. package/dist/lib/hosts/progress.d.ts +28 -10
  123. package/dist/lib/hosts/progress.js +79 -22
  124. package/dist/lib/hosts/remote-cmd.js +4 -0
  125. package/dist/lib/hq/floor.d.ts +87 -0
  126. package/dist/lib/hq/floor.js +226 -0
  127. package/dist/lib/menubar/install-menubar.js +14 -20
  128. package/dist/lib/notify.d.ts +1 -0
  129. package/dist/lib/notify.js +3 -3
  130. package/dist/lib/open-url.d.ts +2 -0
  131. package/dist/lib/open-url.js +19 -0
  132. package/dist/lib/openclaw-keychain.d.ts +56 -0
  133. package/dist/lib/openclaw-keychain.js +236 -0
  134. package/dist/lib/overdue.js +10 -0
  135. package/dist/lib/permissions.d.ts +44 -1
  136. package/dist/lib/permissions.js +284 -7
  137. package/dist/lib/project-launch.d.ts +6 -12
  138. package/dist/lib/project-launch.js +13 -228
  139. package/dist/lib/project-resources.d.ts +7 -0
  140. package/dist/lib/project-resources.js +291 -0
  141. package/dist/lib/pty-client.d.ts +27 -0
  142. package/dist/lib/pty-client.js +136 -10
  143. package/dist/lib/refresh.js +14 -10
  144. package/dist/lib/resource-profiles.d.ts +26 -0
  145. package/dist/lib/resource-profiles.js +157 -0
  146. package/dist/lib/resources/permissions.js +7 -1
  147. package/dist/lib/resources/types.d.ts +1 -1
  148. package/dist/lib/resources.d.ts +1 -1
  149. package/dist/lib/resources.js +32 -3
  150. package/dist/lib/routines.d.ts +11 -0
  151. package/dist/lib/routines.js +56 -15
  152. package/dist/lib/runner.d.ts +1 -0
  153. package/dist/lib/runner.js +66 -5
  154. package/dist/lib/secrets/bundles.d.ts +16 -3
  155. package/dist/lib/secrets/bundles.js +206 -37
  156. package/dist/lib/secrets/icloud-import.d.ts +2 -2
  157. package/dist/lib/secrets/icloud-import.js +9 -6
  158. package/dist/lib/secrets/mcp.js +1 -1
  159. package/dist/lib/secrets/vault-age-helper.d.ts +1 -0
  160. package/dist/lib/secrets/vault-age-helper.js +34 -0
  161. package/dist/lib/secrets/vault.d.ts +49 -0
  162. package/dist/lib/secrets/vault.js +397 -0
  163. package/dist/lib/self-heal/checks/path.js +3 -1
  164. package/dist/lib/self-heal/checks/shadowing.js +10 -2
  165. package/dist/lib/self-heal/checks/shims.js +19 -11
  166. package/dist/lib/session/cloud.d.ts +2 -2
  167. package/dist/lib/session/cloud.js +2 -2
  168. package/dist/lib/session/db.d.ts +4 -0
  169. package/dist/lib/session/db.js +44 -7
  170. package/dist/lib/session/discover.d.ts +2 -0
  171. package/dist/lib/session/discover.js +114 -3
  172. package/dist/lib/session/stream-render.d.ts +3 -0
  173. package/dist/lib/session/stream-render.js +130 -0
  174. package/dist/lib/session/types.d.ts +6 -0
  175. package/dist/lib/share/analytics.d.ts +13 -0
  176. package/dist/lib/share/analytics.js +45 -0
  177. package/dist/lib/share/config.d.ts +19 -5
  178. package/dist/lib/share/config.js +44 -8
  179. package/dist/lib/share/provision.d.ts +58 -6
  180. package/dist/lib/share/provision.js +97 -22
  181. package/dist/lib/share/publish.d.ts +36 -13
  182. package/dist/lib/share/publish.js +55 -8
  183. package/dist/lib/share/worker-template.js +83 -17
  184. package/dist/lib/shims.d.ts +9 -0
  185. package/dist/lib/shims.js +91 -13
  186. package/dist/lib/ssh-exec.d.ts +14 -0
  187. package/dist/lib/ssh-exec.js +57 -0
  188. package/dist/lib/staleness/detectors/hooks.js +25 -1
  189. package/dist/lib/staleness/detectors/permissions.js +66 -0
  190. package/dist/lib/staleness/detectors/workflows.js +20 -0
  191. package/dist/lib/staleness/writers/hooks.js +58 -4
  192. package/dist/lib/staleness/writers/permissions.js +2 -2
  193. package/dist/lib/staleness/writers/skills.js +1 -1
  194. package/dist/lib/staleness/writers/sources.d.ts +10 -1
  195. package/dist/lib/staleness/writers/sources.js +68 -1
  196. package/dist/lib/star-nudge.d.ts +45 -0
  197. package/dist/lib/star-nudge.js +91 -0
  198. package/dist/lib/startup/command-registry.d.ts +6 -1
  199. package/dist/lib/startup/command-registry.js +17 -3
  200. package/dist/lib/state.d.ts +2 -0
  201. package/dist/lib/state.js +3 -0
  202. package/dist/lib/subagents-registry.d.ts +2 -0
  203. package/dist/lib/subagents-registry.js +3 -0
  204. package/dist/lib/teams/parsers.js +214 -6
  205. package/dist/lib/teams/supervisor.d.ts +7 -0
  206. package/dist/lib/teams/supervisor.js +2 -1
  207. package/dist/lib/template.d.ts +1 -1
  208. package/dist/lib/template.js +1 -1
  209. package/dist/lib/triggers/webhook.js +36 -3
  210. package/dist/lib/types.d.ts +73 -0
  211. package/dist/lib/version.d.ts +40 -0
  212. package/dist/lib/version.js +94 -16
  213. package/dist/lib/versions.d.ts +11 -0
  214. package/dist/lib/versions.js +208 -76
  215. package/dist/lib/workflows.d.ts +2 -0
  216. package/dist/lib/workflows.js +88 -0
  217. package/package.json +2 -1
  218. package/dist/commands/daemon.d.ts +0 -10
  219. package/dist/commands/daemon.js +0 -121
@@ -0,0 +1,91 @@
1
+ /**
2
+ * One-time "star us on GitHub" nudge.
3
+ *
4
+ * Printed a single time, ever, after a user's first *successful* headline run
5
+ * (`agents run` / `agents teams`). Modelled on the existing warn-once sentinel
6
+ * pattern (see maybeWarnMultiInstall in src/index.ts): a marker under the
7
+ * regenerable runtime-state dir records that the hint was shown so it never
8
+ * repeats. It is a plain inline line — not a toast, not a nag — and stays out
9
+ * of the way of non-interactive, CI, quiet, and JSON output.
10
+ */
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import chalk from 'chalk';
14
+ import { getRuntimeStateDir } from './state.js';
15
+ /** Canonical GitHub repo the nudge points at. */
16
+ export const REPO_URL = 'https://github.com/phnx-labs/agents-cli';
17
+ /** Sentinel written the first (and only) time the nudge is shown. */
18
+ function nudgeSentinelPath() {
19
+ return path.join(getRuntimeStateDir(), 'star-nudge-shown');
20
+ }
21
+ /** Has the star nudge already been shown on this machine? */
22
+ export function hasShownStarNudge() {
23
+ try {
24
+ return fs.existsSync(nudgeSentinelPath());
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ /**
31
+ * Pure decision: should the one-time star nudge be shown? Skipped for
32
+ * quiet/JSON output, non-interactive terminals (pipes, redirects), CI, an
33
+ * explicit opt-out, or once it has already been shown.
34
+ */
35
+ export function shouldShowStarNudge(ctx) {
36
+ if (ctx.quiet)
37
+ return false;
38
+ if (!ctx.isTTY)
39
+ return false;
40
+ if (ctx.ci)
41
+ return false;
42
+ if (ctx.optedOut)
43
+ return false;
44
+ if (ctx.alreadyShown)
45
+ return false;
46
+ return true;
47
+ }
48
+ /**
49
+ * Show the one-time star nudge if it hasn't been shown yet and the context is
50
+ * appropriate. Best-effort by contract: never throws, never blocks the run it
51
+ * follows.
52
+ *
53
+ * Skipped when: the caller asked for quiet/JSON output, stdout is not an
54
+ * interactive terminal (pipes, redirects), CI is set, or the user opted out
55
+ * with AGENTS_NO_NUDGE=1.
56
+ */
57
+ export function maybeShowStarNudge(opts = {}) {
58
+ try {
59
+ const show = shouldShowStarNudge({
60
+ quiet: opts.quiet,
61
+ isTTY: Boolean(process.stdout.isTTY),
62
+ ci: Boolean(process.env.CI),
63
+ optedOut: process.env.AGENTS_NO_NUDGE === '1',
64
+ alreadyShown: hasShownStarNudge(),
65
+ });
66
+ if (!show)
67
+ return;
68
+ // Claim the one-time slot with an ATOMIC exclusive create (O_EXCL). The
69
+ // hasShownStarNudge() check above is only a cheap fast-path; the existsSync
70
+ // + write pair is a TOCTOU race across processes, and `agents teams` spawns
71
+ // many at once. The `wx` flag makes the create itself the arbiter: exactly
72
+ // one process succeeds, every other gets EEXIST and stays silent — so the
73
+ // hint prints at most once even under concurrent completions.
74
+ const sentinel = nudgeSentinelPath();
75
+ fs.mkdirSync(path.dirname(sentinel), { recursive: true });
76
+ try {
77
+ fs.writeFileSync(sentinel, new Date().toISOString(), { flag: 'wx' });
78
+ }
79
+ catch (e) {
80
+ if (e.code === 'EEXIST')
81
+ return; // another process won the race
82
+ throw e; // real write failure -> caught by the outer best-effort guard
83
+ }
84
+ console.log('\n' +
85
+ chalk.gray('Enjoying agents-cli? Give it a star to help others find it: ') +
86
+ chalk.cyan(REPO_URL));
87
+ }
88
+ catch {
89
+ /* best-effort: a nudge must never break a successful run */
90
+ }
91
+ }
@@ -25,6 +25,7 @@ export type Registrar = (program: Command) => void;
25
25
  export type ModuleLoader = () => Promise<Registrar>;
26
26
  export declare const loadView: ModuleLoader;
27
27
  export declare const loadInspect: ModuleLoader;
28
+ export declare const loadResources: ModuleLoader;
28
29
  export declare const loadFeedback: ModuleLoader;
29
30
  export declare const loadCommands: ModuleLoader;
30
31
  export declare const loadHooks: ModuleLoader;
@@ -41,7 +42,6 @@ export declare const loadWorktree: ModuleLoader;
41
42
  export declare const loadVersions: ModuleLoader;
42
43
  export declare const loadImport: ModuleLoader;
43
44
  export declare const loadPackages: ModuleLoader;
44
- export declare const loadDaemon: ModuleLoader;
45
45
  export declare const loadRoutines: ModuleLoader;
46
46
  export declare const loadMonitors: ModuleLoader;
47
47
  export declare const loadRun: ModuleLoader;
@@ -57,6 +57,7 @@ export declare const loadCheck: ModuleLoader;
57
57
  export declare const loadStatus: ModuleLoader;
58
58
  export declare const loadProfiles: ModuleLoader;
59
59
  export declare const loadSecrets: ModuleLoader;
60
+ export declare const loadLogin: ModuleLoader;
60
61
  export declare const loadWallet: ModuleLoader;
61
62
  export declare const loadHelper: ModuleLoader;
62
63
  export declare const loadMenubar: ModuleLoader;
@@ -71,6 +72,7 @@ export declare const loadCost: ModuleLoader;
71
72
  export declare const loadOutput: ModuleLoader;
72
73
  export declare const loadBudget: ModuleLoader;
73
74
  export declare const loadAlias: ModuleLoader;
75
+ export declare const loadMine: ModuleLoader;
74
76
  export declare const loadPty: ModuleLoader;
75
77
  export declare const loadTmux: ModuleLoader;
76
78
  export declare const loadWatchdog: ModuleLoader;
@@ -90,7 +92,10 @@ export declare const loadSessions: ModuleLoader;
90
92
  export declare const loadTeams: ModuleLoader;
91
93
  export declare const loadCloud: ModuleLoader;
92
94
  export declare const loadMessage: ModuleLoader;
95
+ export declare const loadSend: ModuleLoader;
96
+ export declare const loadHq: ModuleLoader;
93
97
  export declare const loadFeed: ModuleLoader;
98
+ export declare const loadActivity: ModuleLoader;
94
99
  export declare const loadMailboxes: ModuleLoader;
95
100
  export declare const loadServe: ModuleLoader;
96
101
  export declare const loadShare: ModuleLoader;
@@ -3,6 +3,7 @@
3
3
  // them into the exact main-branch registration order for the slow path.
4
4
  export const loadView = async () => (await import('../../commands/view.js')).registerViewCommand;
5
5
  export const loadInspect = async () => (await import('../../commands/inspect.js')).registerInspectCommand;
6
+ export const loadResources = async () => (await import('../../commands/resources.js')).registerResourcesCommand;
6
7
  export const loadFeedback = async () => (await import('../../commands/feedback.js')).registerFeedbackCommand;
7
8
  export const loadCommands = async () => (await import('../../commands/commands.js')).registerCommandsCommands;
8
9
  export const loadHooks = async () => (await import('../../commands/hooks.js')).registerHooksCommands;
@@ -19,7 +20,6 @@ export const loadWorktree = async () => (await import('../../commands/worktree.j
19
20
  export const loadVersions = async () => (await import('../../commands/versions.js')).registerVersionsCommands;
20
21
  export const loadImport = async () => (await import('../../commands/import.js')).registerImportCommand;
21
22
  export const loadPackages = async () => (await import('../../commands/packages.js')).registerPackagesCommands;
22
- export const loadDaemon = async () => (await import('../../commands/daemon.js')).registerDaemonCommands;
23
23
  export const loadRoutines = async () => (await import('../../commands/routines.js')).registerRoutinesCommands;
24
24
  export const loadMonitors = async () => (await import('../../commands/monitors.js')).registerMonitorsCommands;
25
25
  export const loadRun = async () => (await import('../../commands/exec.js')).registerRunCommand;
@@ -35,6 +35,7 @@ export const loadCheck = async () => (await import('../../commands/check.js')).r
35
35
  export const loadStatus = async () => (await import('../../commands/status.js')).registerStatusCommand;
36
36
  export const loadProfiles = async () => (await import('../../commands/profiles.js')).registerProfilesCommands;
37
37
  export const loadSecrets = async () => (await import('../../commands/secrets.js')).registerSecretsCommands;
38
+ export const loadLogin = async () => (await import('../../commands/login.js')).registerLoginCommands;
38
39
  export const loadWallet = async () => (await import('../../commands/wallet.js')).registerWalletCommands;
39
40
  export const loadHelper = async () => (await import('../../commands/helper.js')).registerHelperCommand;
40
41
  export const loadMenubar = async () => (await import('../../commands/menubar.js')).registerMenubarCommands;
@@ -49,6 +50,7 @@ export const loadCost = async () => (await import('../../commands/cost.js')).reg
49
50
  export const loadOutput = async () => (await import('../../commands/output.js')).registerOutputCommand;
50
51
  export const loadBudget = async () => (await import('../../commands/budget.js')).registerBudgetCommand;
51
52
  export const loadAlias = async () => (await import('../../commands/alias.js')).registerAliasCommand;
53
+ export const loadMine = async () => (await import('../../commands/mine.js')).registerMineCommand;
52
54
  export const loadPty = async () => (await import('../../commands/pty.js')).registerPtyCommands;
53
55
  export const loadTmux = async () => (await import('../../commands/tmux.js')).registerTmuxCommands;
54
56
  export const loadWatchdog = async () => (await import('../../commands/watchdog.js')).registerWatchdogCommand;
@@ -68,7 +70,10 @@ export const loadSessions = async () => (await import('../../commands/sessions.j
68
70
  export const loadTeams = async () => (await import('../../commands/teams.js')).registerTeamsCommands;
69
71
  export const loadCloud = async () => (await import('../../commands/cloud.js')).registerCloudCommands;
70
72
  export const loadMessage = async () => (await import('../../commands/message.js')).registerMessageCommand;
73
+ export const loadSend = async () => (await import('../../commands/send.js')).registerSendCommand;
74
+ export const loadHq = async () => (await import('../../commands/hq.js')).registerHqCommand;
71
75
  export const loadFeed = async () => (await import('../../commands/feed.js')).registerFeedCommand;
76
+ export const loadActivity = async () => (await import('../../commands/activity.js')).registerActivityCommand;
72
77
  export const loadMailboxes = async () => (await import('../../commands/mailboxes.js')).registerMailboxesCommand;
73
78
  export const loadServe = async () => (await import('../../commands/serve.js')).registerServeCommand;
74
79
  export const loadShare = async () => (await import('../../commands/share.js')).registerShareCommands;
@@ -82,7 +87,7 @@ export const loadFunnel = async () => (await import('../../commands/funnel.js'))
82
87
  * inherit the root's custom help formatter rather than getting the per-command
83
88
  * recursive pass. Keeping that ordering preserves their `--help` output exactly.
84
89
  */
85
- export const LAZY_COMMAND_NAMES = new Set(['sessions', 'teams', 'cloud', 'message', 'serve']);
90
+ export const LAZY_COMMAND_NAMES = new Set(['sessions', 'teams', 'cloud', 'message', 'hq', 'serve']);
86
91
  /**
87
92
  * User-typed top-level command name -> ordered list of module loaders to run.
88
93
  *
@@ -100,6 +105,7 @@ export const LAZY_COMMAND_NAMES = new Set(['sessions', 'teams', 'cloud', 'messag
100
105
  export const COMMAND_LOADERS = {
101
106
  view: [loadView],
102
107
  inspect: [loadInspect],
108
+ resources: [loadResources],
103
109
  feedback: [loadFeedback],
104
110
  commands: [loadCommands],
105
111
  hooks: [loadHooks],
@@ -124,7 +130,6 @@ export const COMMAND_LOADERS = {
124
130
  registry: [loadPackages],
125
131
  search: [loadPackages],
126
132
  install: [loadPackages],
127
- daemon: [loadDaemon],
128
133
  routines: [loadRoutines],
129
134
  monitors: [loadMonitors],
130
135
  run: [loadRun],
@@ -137,8 +142,12 @@ export const COMMAND_LOADERS = {
137
142
  apply: [loadApply],
138
143
  check: [loadCheck],
139
144
  status: [loadStatus],
145
+ profile: [loadProfiles],
140
146
  profiles: [loadProfiles],
141
147
  secrets: [loadSecrets],
148
+ login: [loadLogin],
149
+ logout: [loadLogin],
150
+ whoami: [loadLogin],
142
151
  wallet: [loadWallet],
143
152
  helper: [loadHelper],
144
153
  menubar: [loadMenubar],
@@ -153,6 +162,7 @@ export const COMMAND_LOADERS = {
153
162
  output: [loadOutput],
154
163
  budget: [loadBudget],
155
164
  alias: [loadAlias],
165
+ mine: [loadMine],
156
166
  pty: [loadPty],
157
167
  tmux: [loadTmux],
158
168
  watchdog: [loadWatchdog],
@@ -180,7 +190,11 @@ export const COMMAND_LOADERS = {
180
190
  teams: [loadTeams],
181
191
  cloud: [loadCloud],
182
192
  message: [loadMessage],
193
+ send: [loadSend],
194
+ notify: [loadSend],
195
+ hq: [loadHq],
183
196
  feed: [loadFeed],
197
+ activity: [loadActivity],
184
198
  mailboxes: [loadMailboxes],
185
199
  mailbox: [loadMailboxes],
186
200
  serve: [loadServe],
@@ -137,6 +137,8 @@ export declare function getMonitorsHistoryDir(): string;
137
137
  export declare function getMailboxRootDir(): string;
138
138
  /** Root for open-block feed records (~/.agents/.history/feed/). */
139
139
  export declare function getFeedDir(): string;
140
+ /** Append-only per-session agent-activity event logs (~/.agents/.history/activity/). */
141
+ export declare function getActivityDir(): string;
140
142
  /** Path to installed agent CLI binaries (~/.agents/.history/versions/). */
141
143
  export declare function getVersionsDir(): string;
142
144
  /** Path to version-switching shim scripts (~/.agents/.cache/shims/). */
package/dist/lib/state.js CHANGED
@@ -101,6 +101,7 @@ const BACKUPS_DIR = path.join(HISTORY_DIR, 'backups');
101
101
  const TRASH_DIR = path.join(HISTORY_DIR, 'trash');
102
102
  const MAILBOX_DIR = path.join(HISTORY_DIR, 'mailbox');
103
103
  const FEED_DIR = path.join(HISTORY_DIR, 'feed');
104
+ const ACTIVITY_DIR = path.join(HISTORY_DIR, 'activity');
104
105
  // Cache bucket (regenerable).
105
106
  const SHIMS_DIR = path.join(CACHE_DIR, 'shims');
106
107
  const HOOK_SHIMS_DIR = path.join(SHIMS_DIR, 'hooks');
@@ -340,6 +341,8 @@ export function getMonitorsHistoryDir() { return MONITORS_HISTORY_DIR; }
340
341
  export function getMailboxRootDir() { return MAILBOX_DIR; }
341
342
  /** Root for open-block feed records (~/.agents/.history/feed/). */
342
343
  export function getFeedDir() { return FEED_DIR; }
344
+ /** Append-only per-session agent-activity event logs (~/.agents/.history/activity/). */
345
+ export function getActivityDir() { return ACTIVITY_DIR; }
343
346
  /** Path to installed agent CLI binaries (~/.agents/.history/versions/). */
344
347
  export function getVersionsDir() { return VERSIONS_DIR; }
345
348
  /** Path to version-switching shim scripts (~/.agents/.cache/shims/). */
@@ -27,6 +27,8 @@ export interface SubagentTarget {
27
27
  names(dir: string): string[];
28
28
  /** On-disk paths subagent `name` occupies (for removal / soft-delete). */
29
29
  occupied(dir: string, name: string): OccupiedEntry[];
30
+ /** Cross-item files this target owns outside any one subagent's occupied paths. */
31
+ finalizeOccupied?(dir: string): OccupiedEntry[];
30
32
  /** Rich metadata for `name`; `null` skips it from the listing. */
31
33
  read(dir: string, name: string): SubagentMeta | null;
32
34
  /** Optional post-sync pass over the just-synced subagents (Kimi's parent index). */
@@ -213,6 +213,9 @@ const kimiTarget = {
213
213
  { path: safeJoin(dir, `${name}.system.md`), kind: 'file' },
214
214
  ];
215
215
  },
216
+ finalizeOccupied(dir) {
217
+ return [{ path: safeJoin(dir, KIMI_SUBAGENTS_PARENT_FILE), kind: 'file' }];
218
+ },
216
219
  read(dir, name) {
217
220
  const yamlPath = path.join(dir, `${name}.yaml`);
218
221
  if (!fs.existsSync(yamlPath) || !fs.statSync(yamlPath).isFile())
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { extractFileOpsFromBash } from './file_ops.js';
10
10
  const claudeToolUseMap = new Map();
11
+ const droidToolUseMap = new Map();
11
12
  /** Normalize a raw JSON event from any agent type into an array of unified event objects. */
12
13
  export function normalizeEvents(agentType, raw) {
13
14
  if (agentType === 'codex') {
@@ -34,12 +35,9 @@ export function normalizeEvents(agentType, raw) {
34
35
  else if (agentType === 'kimi') {
35
36
  return normalizeKimi(raw);
36
37
  }
37
- // droid (Factory AI) intentionally falls through to the generic normalizer
38
- // below: its `-o stream-json` JSONL event schema is not yet verified against
39
- // a live run (the documented `debug` format differs from stream-json). Events
40
- // still stream and render; structured tool/file categorization will be added
41
- // once a real `droid exec -o stream-json` sample is captured. Do NOT guess the
42
- // schema here — a wrong discriminator silently mislabels every event.
38
+ else if (agentType === 'droid') {
39
+ return normalizeDroid(raw);
40
+ }
43
41
  const timestamp = new Date().toISOString();
44
42
  return [{
45
43
  type: raw.type || 'unknown',
@@ -1078,6 +1076,216 @@ function normalizeKimi(raw) {
1078
1076
  timestamp: timestamp,
1079
1077
  }];
1080
1078
  }
1079
+ // --- Droid parsing ---
1080
+ // Droid's `droid exec -o stream-json` stream mirrors the Factory session JSONL
1081
+ // envelope: session_start records plus Anthropic-shaped message content blocks.
1082
+ // Tool blocks carry the actionable file path / command in `input`; result blocks
1083
+ // only carry `tool_use_id`, so keep a small id map just like normalizeClaude.
1084
+ function normalizeDroid(raw) {
1085
+ const timestamp = typeof raw?.timestamp === 'string' ? raw.timestamp : new Date().toISOString();
1086
+ if (!raw || typeof raw !== 'object') {
1087
+ return [{
1088
+ type: 'unknown',
1089
+ agent: 'droid',
1090
+ raw: raw,
1091
+ timestamp: timestamp,
1092
+ }];
1093
+ }
1094
+ const eventType = typeof raw.type === 'string' ? raw.type : 'unknown';
1095
+ if (eventType === 'session_start') {
1096
+ return [{
1097
+ type: 'init',
1098
+ agent: 'droid',
1099
+ session_id: typeof raw.id === 'string' ? raw.id : null,
1100
+ timestamp: timestamp,
1101
+ }];
1102
+ }
1103
+ if (eventType === 'result') {
1104
+ return [{
1105
+ type: 'result',
1106
+ agent: 'droid',
1107
+ status: raw.is_error === true ? 'error' : 'success',
1108
+ message: typeof raw.result === 'string' ? raw.result : undefined,
1109
+ timestamp: timestamp,
1110
+ }];
1111
+ }
1112
+ if (eventType !== 'message') {
1113
+ return [{
1114
+ type: eventType,
1115
+ agent: 'droid',
1116
+ raw: raw,
1117
+ timestamp: timestamp,
1118
+ }];
1119
+ }
1120
+ const message = raw.message || {};
1121
+ const role = message.role === 'user' ? 'user' : 'assistant';
1122
+ const blocks = message.content;
1123
+ if (typeof blocks === 'string') {
1124
+ const content = blocks.trim();
1125
+ if (!content)
1126
+ return [];
1127
+ return role === 'assistant'
1128
+ ? [{ type: 'message', agent: 'droid', content, complete: true, timestamp }]
1129
+ : [{ type: 'user_message', agent: 'droid', content, timestamp }];
1130
+ }
1131
+ if (!Array.isArray(blocks))
1132
+ return [];
1133
+ const events = [];
1134
+ for (const block of blocks) {
1135
+ if (!block || typeof block !== 'object')
1136
+ continue;
1137
+ if (block.type === 'text') {
1138
+ const text = typeof block.text === 'string' ? block.text.trim() : '';
1139
+ if (!text)
1140
+ continue;
1141
+ if (role === 'assistant') {
1142
+ events.push({
1143
+ type: 'message',
1144
+ agent: 'droid',
1145
+ content: text,
1146
+ complete: true,
1147
+ timestamp: timestamp,
1148
+ });
1149
+ }
1150
+ else if (!text.startsWith('<system-reminder>') && !text.startsWith('Hook execution:')) {
1151
+ events.push({
1152
+ type: 'user_message',
1153
+ agent: 'droid',
1154
+ content: text,
1155
+ timestamp: timestamp,
1156
+ });
1157
+ }
1158
+ continue;
1159
+ }
1160
+ if (block.type === 'thinking') {
1161
+ const thinking = typeof block.thinking === 'string' ? block.thinking.trim() : '';
1162
+ if (thinking) {
1163
+ events.push({
1164
+ type: 'thinking',
1165
+ agent: 'droid',
1166
+ content: thinking,
1167
+ timestamp: timestamp,
1168
+ });
1169
+ }
1170
+ continue;
1171
+ }
1172
+ if (block.type === 'tool_use') {
1173
+ events.push(...normalizeDroidToolUse(block, timestamp));
1174
+ continue;
1175
+ }
1176
+ if (block.type === 'tool_result') {
1177
+ const toolUseId = typeof block.tool_use_id === 'string' ? block.tool_use_id : null;
1178
+ const toolInfo = toolUseId ? droidToolUseMap.get(toolUseId) : undefined;
1179
+ if (toolUseId)
1180
+ droidToolUseMap.delete(toolUseId);
1181
+ const content = extractDroidToolResultContent(block.content);
1182
+ if (block.is_error === true) {
1183
+ events.push({
1184
+ type: 'error',
1185
+ agent: 'droid',
1186
+ tool: toolInfo?.tool,
1187
+ content: content || 'Tool execution failed',
1188
+ timestamp: timestamp,
1189
+ });
1190
+ }
1191
+ else {
1192
+ events.push({
1193
+ type: 'tool_result',
1194
+ agent: 'droid',
1195
+ tool: toolInfo?.tool,
1196
+ tool_call_id: toolUseId,
1197
+ success: true,
1198
+ content: content.length > 500 ? content.slice(0, 497) + '...' : content,
1199
+ timestamp: timestamp,
1200
+ });
1201
+ }
1202
+ }
1203
+ }
1204
+ return events;
1205
+ }
1206
+ function normalizeDroidToolUse(block, timestamp) {
1207
+ const toolName = typeof block.name === 'string' ? block.name : 'unknown';
1208
+ const toolInput = block.input && typeof block.input === 'object' ? block.input : {};
1209
+ if (typeof block.id === 'string') {
1210
+ droidToolUseMap.set(block.id, { tool: toolName, args: toolInput });
1211
+ }
1212
+ const filePath = toolInput.file_path || toolInput.path || '';
1213
+ const command = toolInput.command || '';
1214
+ if ((toolName === 'Execute' || toolName === 'Bash') && command) {
1215
+ const events = [{
1216
+ type: 'bash',
1217
+ agent: 'droid',
1218
+ tool: toolName,
1219
+ command: command,
1220
+ timestamp: timestamp,
1221
+ }];
1222
+ const [filesRead, filesWritten, filesDeleted] = extractFileOpsFromBash(command);
1223
+ for (const path of filesRead) {
1224
+ events.push({ type: 'file_read', agent: 'droid', tool: 'bash', path, command, timestamp });
1225
+ }
1226
+ for (const path of filesWritten) {
1227
+ events.push({ type: 'file_write', agent: 'droid', tool: 'bash', path, command, timestamp });
1228
+ }
1229
+ for (const path of filesDeleted) {
1230
+ events.push({ type: 'file_delete', agent: 'droid', tool: 'bash', path, command, timestamp });
1231
+ }
1232
+ return events;
1233
+ }
1234
+ if (toolName === 'Read' && filePath) {
1235
+ return [{
1236
+ type: 'file_read',
1237
+ agent: 'droid',
1238
+ tool: toolName,
1239
+ path: filePath,
1240
+ timestamp: timestamp,
1241
+ }];
1242
+ }
1243
+ if ((toolName === 'Create' || toolName === 'Write') && filePath) {
1244
+ return [{
1245
+ type: 'file_create',
1246
+ agent: 'droid',
1247
+ tool: toolName,
1248
+ path: filePath,
1249
+ timestamp: timestamp,
1250
+ }];
1251
+ }
1252
+ if ((toolName === 'Edit' || toolName === 'MultiEdit') && filePath) {
1253
+ return [{
1254
+ type: 'file_write',
1255
+ agent: 'droid',
1256
+ tool: toolName,
1257
+ path: filePath,
1258
+ timestamp: timestamp,
1259
+ }];
1260
+ }
1261
+ if ((toolName === 'Delete' || toolName === 'Remove') && filePath) {
1262
+ return [{
1263
+ type: 'file_delete',
1264
+ agent: 'droid',
1265
+ tool: toolName,
1266
+ path: filePath,
1267
+ timestamp: timestamp,
1268
+ }];
1269
+ }
1270
+ return [{
1271
+ type: 'tool_use',
1272
+ agent: 'droid',
1273
+ tool: toolName,
1274
+ args: toolInput,
1275
+ timestamp: timestamp,
1276
+ }];
1277
+ }
1278
+ function extractDroidToolResultContent(content) {
1279
+ if (typeof content === 'string')
1280
+ return content;
1281
+ if (Array.isArray(content)) {
1282
+ return content
1283
+ .filter((part) => part && typeof part === 'object' && part.type === 'text')
1284
+ .map((part) => typeof part.text === 'string' ? part.text : '')
1285
+ .join('\n');
1286
+ }
1287
+ return '';
1288
+ }
1081
1289
  // --- Antigravity parsing ---
1082
1290
  // Intentionally conservative. Antigravity's `agy` binary advertises an
1083
1291
  // `--output-format json` flag in its docs, but the released binary errors with
@@ -51,6 +51,13 @@ export interface SupervisorResult {
51
51
  waves: number;
52
52
  stoppedBy: 'drained' | 'max-waves' | 'signal' | 'callback' | 'budget';
53
53
  elapsed_ms: number;
54
+ /**
55
+ * Number of teammates in the `failed` state when the team drained. Only set
56
+ * for `stoppedBy === 'drained'`. A drained DAG means nothing is pending or
57
+ * running — NOT that everything succeeded — so callers that treat "drained"
58
+ * as success (e.g. a completion nudge) must check `failed === 0` first.
59
+ */
60
+ failed?: number;
54
61
  /** Set when `stoppedBy === 'budget'` — the breach that terminated the team. */
55
62
  budgetBreach?: BreachInfo;
56
63
  }
@@ -80,7 +80,8 @@ export async function runSupervisor(mgr, opts) {
80
80
  const afterCallback = await mgr.listByTask(team);
81
81
  const stillLive = afterCallback.some((a) => a.status === 'pending' || a.status === 'running');
82
82
  if (!stillLive) {
83
- return { waves: wave, stoppedBy: 'drained', elapsed_ms: Date.now() - startedAt };
83
+ const failed = afterCallback.filter((a) => a.status === 'failed').length;
84
+ return { waves: wave, stoppedBy: 'drained', failed, elapsed_ms: Date.now() - startedAt };
84
85
  }
85
86
  if (stopSignal) {
86
87
  return { waves: wave, stoppedBy: 'signal', elapsed_ms: Date.now() - startedAt };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Template resolution utilities.
3
- * Ported from agents/halo/cli/pkg/template.
3
+ * Ported from the legacy agent CLI template helpers.
4
4
  *
5
5
  * Supports {{artifact.*}} and {{preflight.*}} placeholder patterns used in
6
6
  * artifact action input mappings.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Template resolution utilities.
3
- * Ported from agents/halo/cli/pkg/template.
3
+ * Ported from the legacy agent CLI template helpers.
4
4
  *
5
5
  * Supports {{artifact.*}} and {{preflight.*}} placeholder patterns used in
6
6
  * artifact action input mappings.
@@ -77,18 +77,46 @@ function linearTeamKey(payload) {
77
77
  return typeof team?.key === 'string' ? team.key : null;
78
78
  }
79
79
  function linearLabels(payload) {
80
+ // Linear webhook bodies flatten list relations: an Issue event carries
81
+ // `data.labels` as a flat array of label objects (`[{ id, name, color }]`),
82
+ // NOT the `{ nodes: [...] }` connection shape returned by the GraphQL API.
83
+ // Reading `.nodes` here made every `--label` filter match nothing.
80
84
  const data = payload.data;
81
- const labels = data?.labels;
82
- const nodes = Array.isArray(labels?.nodes) ? labels.nodes : [];
83
- return nodes
85
+ const labels = Array.isArray(data?.labels) ? data?.labels : [];
86
+ return labels
84
87
  .map((n) => n.name)
85
88
  .filter((n) => typeof n === 'string' && n.length > 0);
86
89
  }
90
+ function githubAction(payload) {
91
+ return typeof payload.action === 'string' ? payload.action : null;
92
+ }
93
+ function githubLabels(payload) {
94
+ const names = new Set();
95
+ const add = (value) => {
96
+ if (typeof value === 'string' && value.length > 0)
97
+ names.add(value);
98
+ };
99
+ const deliveryLabel = payload.label;
100
+ add(deliveryLabel?.name);
101
+ const pr = payload.pull_request;
102
+ const prLabels = Array.isArray(pr?.labels) ? pr.labels : [];
103
+ for (const label of prLabels) {
104
+ add(label.name);
105
+ }
106
+ const issue = payload.issue;
107
+ const issueLabels = Array.isArray(issue?.labels) ? issue.labels : [];
108
+ for (const label of issueLabels) {
109
+ add(label.name);
110
+ }
111
+ return [...names];
112
+ }
87
113
  function githubTriggerMatches(trigger, webhook) {
88
114
  if (webhook.source !== 'github')
89
115
  return false;
90
116
  if (trigger.event !== webhook.event)
91
117
  return false;
118
+ if (trigger.action && githubAction(webhook.payload) !== trigger.action)
119
+ return false;
92
120
  if (trigger.repo) {
93
121
  const repo = webhookRepo(webhook.payload);
94
122
  if (!repo || repo.toLowerCase() !== trigger.repo.toLowerCase())
@@ -99,6 +127,11 @@ function githubTriggerMatches(trigger, webhook) {
99
127
  if (!branches.some((b) => b === trigger.branch))
100
128
  return false;
101
129
  }
130
+ if (trigger.label) {
131
+ const expected = trigger.label.toLowerCase();
132
+ if (!githubLabels(webhook.payload).some((name) => name.toLowerCase() === expected))
133
+ return false;
134
+ }
102
135
  return true;
103
136
  }
104
137
  function linearTriggerMatches(trigger, webhook) {