@phnx-labs/agents-cli 1.20.72 → 1.20.74

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 (234) hide show
  1. package/CHANGELOG.md +395 -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 +21 -5
  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/export.d.ts +11 -0
  16. package/dist/commands/export.js +215 -0
  17. package/dist/commands/feed.d.ts +13 -0
  18. package/dist/commands/feed.js +130 -29
  19. package/dist/commands/hq.d.ts +2 -0
  20. package/dist/commands/hq.js +58 -0
  21. package/dist/commands/import.js +51 -3
  22. package/dist/commands/lease.d.ts +19 -0
  23. package/dist/commands/lease.js +138 -11
  24. package/dist/commands/login.d.ts +2 -0
  25. package/dist/commands/login.js +123 -0
  26. package/dist/commands/logs.js +1 -1
  27. package/dist/commands/mine.d.ts +27 -0
  28. package/dist/commands/mine.js +207 -0
  29. package/dist/commands/monitors.js +79 -49
  30. package/dist/commands/plugins.js +1 -0
  31. package/dist/commands/profiles.js +158 -0
  32. package/dist/commands/repo.js +2 -60
  33. package/dist/commands/resources.d.ts +5 -0
  34. package/dist/commands/resources.js +95 -0
  35. package/dist/commands/routines.d.ts +2 -0
  36. package/dist/commands/routines.js +139 -37
  37. package/dist/commands/secrets.js +234 -47
  38. package/dist/commands/send.d.ts +15 -0
  39. package/dist/commands/send.js +62 -0
  40. package/dist/commands/sessions-tail.d.ts +1 -0
  41. package/dist/commands/sessions-tail.js +20 -9
  42. package/dist/commands/sessions.js +18 -3
  43. package/dist/commands/setup-mine.d.ts +18 -0
  44. package/dist/commands/setup-mine.js +106 -0
  45. package/dist/commands/setup-share.js +2 -2
  46. package/dist/commands/setup.js +9 -2
  47. package/dist/commands/share.d.ts +8 -1
  48. package/dist/commands/share.js +122 -37
  49. package/dist/commands/ssh.d.ts +9 -0
  50. package/dist/commands/ssh.js +196 -26
  51. package/dist/commands/sync.js +1 -1
  52. package/dist/commands/teams.js +11 -2
  53. package/dist/commands/versions.js +36 -5
  54. package/dist/commands/view.js +75 -27
  55. package/dist/index.js +80 -10
  56. package/dist/lib/activity.d.ts +124 -0
  57. package/dist/lib/activity.js +542 -0
  58. package/dist/lib/agents.d.ts +35 -0
  59. package/dist/lib/agents.js +79 -6
  60. package/dist/lib/artifact-actions.d.ts +1 -1
  61. package/dist/lib/artifact-actions.js +1 -1
  62. package/dist/lib/ask-classifier.d.ts +2 -1
  63. package/dist/lib/ask-classifier.js +3 -3
  64. package/dist/lib/auth-health.d.ts +32 -4
  65. package/dist/lib/auth-health.js +40 -1
  66. package/dist/lib/auto-pull.js +8 -1
  67. package/dist/lib/brand.d.ts +40 -0
  68. package/dist/lib/brand.js +122 -0
  69. package/dist/lib/browser/drivers/ssh.js +4 -7
  70. package/dist/lib/browser/service.js +6 -8
  71. package/dist/lib/channels/providers/index.d.ts +2 -0
  72. package/dist/lib/channels/providers/index.js +20 -0
  73. package/dist/lib/channels/providers/mailbox.d.ts +2 -0
  74. package/dist/lib/channels/providers/mailbox.js +26 -0
  75. package/dist/lib/channels/providers/openclaw-telegram.d.ts +2 -0
  76. package/dist/lib/channels/providers/openclaw-telegram.js +34 -0
  77. package/dist/lib/channels/providers/rush.d.ts +6 -0
  78. package/dist/lib/channels/providers/rush.js +55 -0
  79. package/dist/lib/channels/registry.d.ts +42 -0
  80. package/dist/lib/channels/registry.js +20 -0
  81. package/dist/lib/channels/resolve.d.ts +11 -0
  82. package/dist/lib/channels/resolve.js +12 -0
  83. package/dist/lib/cli-resources.d.ts +18 -0
  84. package/dist/lib/cli-resources.js +53 -4
  85. package/dist/lib/cloud/codex.js +6 -3
  86. package/dist/lib/cloud/factory.d.ts +1 -0
  87. package/dist/lib/cloud/factory.js +10 -4
  88. package/dist/lib/cloud/rush.d.ts +3 -1
  89. package/dist/lib/cloud/rush.js +6 -1
  90. package/dist/lib/cloud/types.d.ts +2 -0
  91. package/dist/lib/codex-home.d.ts +35 -0
  92. package/dist/lib/codex-home.js +136 -0
  93. package/dist/lib/config-transfer.d.ts +16 -0
  94. package/dist/lib/config-transfer.js +56 -0
  95. package/dist/lib/crabbox/cli.d.ts +44 -0
  96. package/dist/lib/crabbox/cli.js +120 -20
  97. package/dist/lib/crabbox/lease.d.ts +52 -1
  98. package/dist/lib/crabbox/lease.js +117 -16
  99. package/dist/lib/crabbox/progress.d.ts +31 -0
  100. package/dist/lib/crabbox/progress.js +76 -0
  101. package/dist/lib/crabbox/runtimes.d.ts +4 -0
  102. package/dist/lib/crabbox/runtimes.js +33 -8
  103. package/dist/lib/crabbox/setup-copy.d.ts +87 -0
  104. package/dist/lib/crabbox/setup-copy.js +127 -0
  105. package/dist/lib/daemon.d.ts +5 -5
  106. package/dist/lib/daemon.js +9 -9
  107. package/dist/lib/drive-sync.js +6 -3
  108. package/dist/lib/event-stream.d.ts +36 -0
  109. package/dist/lib/event-stream.js +68 -0
  110. package/dist/lib/events.d.ts +1 -1
  111. package/dist/lib/exec.d.ts +11 -0
  112. package/dist/lib/exec.js +23 -2
  113. package/dist/lib/export.d.ts +72 -0
  114. package/dist/lib/export.js +269 -0
  115. package/dist/lib/feed-policy.d.ts +1 -1
  116. package/dist/lib/feed-policy.js +14 -9
  117. package/dist/lib/feed-ranking.d.ts +32 -0
  118. package/dist/lib/feed-ranking.js +224 -0
  119. package/dist/lib/feed.d.ts +35 -2
  120. package/dist/lib/feed.js +66 -3
  121. package/dist/lib/fleet/auth-sync.d.ts +53 -0
  122. package/dist/lib/fleet/auth-sync.js +92 -0
  123. package/dist/lib/fleet/remote-login.d.ts +187 -0
  124. package/dist/lib/fleet/remote-login.js +556 -0
  125. package/dist/lib/format.d.ts +30 -3
  126. package/dist/lib/format.js +34 -5
  127. package/dist/lib/fs-atomic.d.ts +7 -2
  128. package/dist/lib/fs-atomic.js +8 -12
  129. package/dist/lib/git.d.ts +16 -0
  130. package/dist/lib/git.js +79 -2
  131. package/dist/lib/heal.js +11 -3
  132. package/dist/lib/hosts/progress.d.ts +28 -10
  133. package/dist/lib/hosts/progress.js +79 -22
  134. package/dist/lib/hosts/remote-cmd.js +4 -0
  135. package/dist/lib/hq/floor.d.ts +87 -0
  136. package/dist/lib/hq/floor.js +226 -0
  137. package/dist/lib/import.d.ts +23 -0
  138. package/dist/lib/import.js +74 -2
  139. package/dist/lib/isolation-boundary-report.d.ts +10 -0
  140. package/dist/lib/isolation-boundary-report.js +35 -0
  141. package/dist/lib/menubar/install-menubar.js +14 -20
  142. package/dist/lib/notify.d.ts +1 -0
  143. package/dist/lib/notify.js +3 -3
  144. package/dist/lib/open-url.d.ts +2 -0
  145. package/dist/lib/open-url.js +19 -0
  146. package/dist/lib/openclaw-keychain.d.ts +56 -0
  147. package/dist/lib/openclaw-keychain.js +236 -0
  148. package/dist/lib/overdue.js +10 -0
  149. package/dist/lib/permissions.d.ts +44 -1
  150. package/dist/lib/permissions.js +284 -7
  151. package/dist/lib/project-launch.d.ts +6 -12
  152. package/dist/lib/project-launch.js +13 -228
  153. package/dist/lib/project-resources.d.ts +7 -0
  154. package/dist/lib/project-resources.js +306 -0
  155. package/dist/lib/pty-client.d.ts +27 -0
  156. package/dist/lib/pty-client.js +136 -10
  157. package/dist/lib/refresh.js +14 -10
  158. package/dist/lib/resource-profiles.d.ts +26 -0
  159. package/dist/lib/resource-profiles.js +157 -0
  160. package/dist/lib/resources/permissions.js +7 -1
  161. package/dist/lib/resources/types.d.ts +1 -1
  162. package/dist/lib/resources.d.ts +1 -1
  163. package/dist/lib/resources.js +32 -3
  164. package/dist/lib/routines.d.ts +11 -0
  165. package/dist/lib/routines.js +56 -15
  166. package/dist/lib/runner.d.ts +1 -0
  167. package/dist/lib/runner.js +66 -5
  168. package/dist/lib/secrets/bundles.d.ts +16 -3
  169. package/dist/lib/secrets/bundles.js +206 -37
  170. package/dist/lib/secrets/icloud-import.d.ts +2 -2
  171. package/dist/lib/secrets/icloud-import.js +9 -6
  172. package/dist/lib/secrets/mcp.js +1 -1
  173. package/dist/lib/secrets/vault-age-helper.d.ts +1 -0
  174. package/dist/lib/secrets/vault-age-helper.js +34 -0
  175. package/dist/lib/secrets/vault.d.ts +49 -0
  176. package/dist/lib/secrets/vault.js +397 -0
  177. package/dist/lib/self-heal/checks/path.js +3 -1
  178. package/dist/lib/self-heal/checks/shadowing.js +10 -2
  179. package/dist/lib/self-heal/checks/shims.js +19 -11
  180. package/dist/lib/session/cloud.d.ts +2 -2
  181. package/dist/lib/session/cloud.js +2 -2
  182. package/dist/lib/session/db.d.ts +4 -0
  183. package/dist/lib/session/db.js +44 -7
  184. package/dist/lib/session/discover.d.ts +2 -0
  185. package/dist/lib/session/discover.js +114 -3
  186. package/dist/lib/session/stream-render.d.ts +3 -0
  187. package/dist/lib/session/stream-render.js +130 -0
  188. package/dist/lib/session/types.d.ts +6 -0
  189. package/dist/lib/share/analytics.d.ts +13 -0
  190. package/dist/lib/share/analytics.js +45 -0
  191. package/dist/lib/share/config.d.ts +19 -5
  192. package/dist/lib/share/config.js +44 -8
  193. package/dist/lib/share/provision.d.ts +58 -6
  194. package/dist/lib/share/provision.js +97 -22
  195. package/dist/lib/share/publish.d.ts +36 -13
  196. package/dist/lib/share/publish.js +55 -8
  197. package/dist/lib/share/worker-template.js +83 -17
  198. package/dist/lib/shims.d.ts +35 -0
  199. package/dist/lib/shims.js +159 -13
  200. package/dist/lib/ssh-exec.d.ts +14 -0
  201. package/dist/lib/ssh-exec.js +57 -0
  202. package/dist/lib/staleness/detectors/hooks.js +25 -1
  203. package/dist/lib/staleness/detectors/permissions.js +66 -0
  204. package/dist/lib/staleness/detectors/workflows.js +20 -0
  205. package/dist/lib/staleness/writers/hooks.js +58 -4
  206. package/dist/lib/staleness/writers/permissions.js +2 -2
  207. package/dist/lib/staleness/writers/skills.js +1 -1
  208. package/dist/lib/staleness/writers/sources.d.ts +10 -1
  209. package/dist/lib/staleness/writers/sources.js +68 -1
  210. package/dist/lib/star-nudge.d.ts +45 -0
  211. package/dist/lib/star-nudge.js +91 -0
  212. package/dist/lib/startup/command-registry.d.ts +7 -1
  213. package/dist/lib/startup/command-registry.js +19 -3
  214. package/dist/lib/state.d.ts +2 -0
  215. package/dist/lib/state.js +17 -4
  216. package/dist/lib/subagents-registry.d.ts +2 -0
  217. package/dist/lib/subagents-registry.js +3 -0
  218. package/dist/lib/teams/parsers.js +214 -6
  219. package/dist/lib/teams/supervisor.d.ts +7 -0
  220. package/dist/lib/teams/supervisor.js +2 -1
  221. package/dist/lib/template.d.ts +1 -1
  222. package/dist/lib/template.js +1 -1
  223. package/dist/lib/triggers/webhook.js +36 -3
  224. package/dist/lib/types.d.ts +84 -0
  225. package/dist/lib/uninstall.js +1 -45
  226. package/dist/lib/version.d.ts +40 -0
  227. package/dist/lib/version.js +94 -16
  228. package/dist/lib/versions.d.ts +24 -0
  229. package/dist/lib/versions.js +269 -78
  230. package/dist/lib/workflows.d.ts +2 -0
  231. package/dist/lib/workflows.js +88 -0
  232. package/package.json +2 -1
  233. package/dist/commands/daemon.d.ts +0 -10
  234. package/dist/commands/daemon.js +0 -121
@@ -267,9 +267,13 @@ function reportResults(results) {
267
267
  }
268
268
  console.log(chalk.green('Fleet reconciled.'));
269
269
  }
270
- export function registerApplyCommand(program) {
271
- const applyCmd = program
272
- .command('apply')
270
+ /**
271
+ * Attach the reconcile options + action to a command node. Shared by the
272
+ * top-level `agents apply` and its `agents fleet apply` alias so the two can
273
+ * never drift — identical flags, identical engine.
274
+ */
275
+ export function configureApplyCommand(cmd) {
276
+ return cmd
273
277
  .description('Reconcile the fleet to a declared profile: install agents, sync config, propagate login.')
274
278
  .option('-f, --file <path>', 'Manifest file carrying a fleet: block (default: agents.yaml)')
275
279
  .option('--plan', 'Show the reconcile plan and exit (no changes)')
@@ -292,6 +296,9 @@ export function registerApplyCommand(program) {
292
296
  process.exit(1);
293
297
  }
294
298
  });
299
+ }
300
+ export function registerApplyCommand(program) {
301
+ const applyCmd = configureApplyCommand(program.command('apply'));
295
302
  setHelpSections(applyCmd, {
296
303
  examples: `
297
304
  # Preview what would change across the fleet
@@ -305,3 +312,21 @@ export function registerApplyCommand(program) {
305
312
  `,
306
313
  });
307
314
  }
315
+ /**
316
+ * Surface `agents apply` under the fleet command tree as `agents fleet apply`
317
+ * (and `agents devices apply`). Same reconcile engine as the top-level command —
318
+ * a discoverability alias for users who reach for `fleet` as the verb. Kept in
319
+ * lockstep via {@link configureApplyCommand}.
320
+ */
321
+ export function registerFleetApplyAlias(devicesCmd) {
322
+ const sub = configureApplyCommand(devicesCmd.command('apply'));
323
+ setHelpSections(sub, {
324
+ examples: `
325
+ # Preview the fleet reconcile
326
+ agents fleet apply --plan
327
+
328
+ # Reconcile every device to the profile
329
+ agents fleet apply -y
330
+ `,
331
+ });
332
+ }
@@ -1420,7 +1420,7 @@ function registerTaskCommands(browser) {
1420
1420
  process.exit(1);
1421
1421
  }
1422
1422
  try {
1423
- const { env } = readAndResolveBundleEnv(parsed.bundle, { caller: 'browser type', keys: [parsed.key], agentOnly: isHeadlessSecretsContext() });
1423
+ const { env } = readAndResolveBundleEnv(parsed.bundle, { caller: 'browser type', keys: [parsed.key], keyMode: 'storage', agentOnly: isHeadlessSecretsContext() });
1424
1424
  if (!(parsed.key in env)) {
1425
1425
  console.error(`Key "${parsed.key}" not in bundle "${parsed.bundle}".`);
1426
1426
  process.exit(1);
@@ -10,6 +10,7 @@ import { MissingTargetError, MAX_IMAGES_PER_DISPATCH } from '../lib/cloud/types.
10
10
  import { normalizeTriggerEvent, validateTrigger, writeJob, jobExists, GITHUB_TRIGGER_EVENTS } from '../lib/routines.js';
11
11
  import { machineId } from '../lib/machine-id.js';
12
12
  import { emit } from '../lib/events.js';
13
+ import { shareRuntimeEnv } from '../lib/share/config.js';
13
14
  /** Map a supported image file extension to its wire mimeType. Rejects anything else. */
14
15
  function imageMimeFromPath(file) {
15
16
  const ext = path.extname(file).toLowerCase();
@@ -155,6 +156,8 @@ Examples:
155
156
  })
156
157
  .option('--branch <name>', 'Target git branch')
157
158
  .option('--on <event>', 'Register this run as an event trigger instead of dispatching now: pull_request (pr), push, issue_comment, workflow_run. Persists a trigger-bound routine.')
159
+ .option('--action <name>', 'GitHub webhook action filter for --on triggers (e.g. labeled)')
160
+ .option('--label <name>', 'GitHub label filter for --on triggers')
158
161
  .option('--name <name>', 'Routine name to register under (with --on). Defaults to a generated name.')
159
162
  .option('-p, --prompt <text>', 'Inline prompt (alternative to positional argument)')
160
163
  .option('--timeout <duration>', 'Kill after duration (e.g., 30m, 2h)')
@@ -205,7 +208,7 @@ Examples:
205
208
  // Resolve prompt: --prompt flag, positional arg, or file
206
209
  let prompt = options.prompt || positionalPrompt;
207
210
  if (!prompt)
208
- die('Prompt is required. Pass it as an argument or with --prompt.');
211
+ die('Prompt is required. Pass it as an argument or with --prompt.', 1, { json, hint: 'agents cloud run "<task>" --repo <owner/repo>' });
209
212
  // If prompt is a file path, read it and tell the user
210
213
  if (fs.existsSync(prompt) && fs.statSync(prompt).isFile()) {
211
214
  const filePath = prompt;
@@ -220,7 +223,7 @@ Examples:
220
223
  // something to the host provider, so it implies --provider host rather
221
224
  // than silently riding along to a cloud backend that would ignore it.
222
225
  if (options.host && options.provider && options.provider !== 'host') {
223
- die(`--host targets your own machines (--provider host), not ${options.provider}. Drop --host, or use --provider host.`);
226
+ die(`--host targets your own machines (--provider host), not ${options.provider}. Drop --host, or use --provider host.`, 1, { json });
224
227
  }
225
228
  const explicitProvider = options.provider ?? (options.host ? 'host' : undefined);
226
229
  // Agent-aware: with no --provider, the agent routes to its native cloud
@@ -245,6 +248,9 @@ Examples:
245
248
  model: options.model,
246
249
  providerOptions: {},
247
250
  };
251
+ const shareEnv = shareRuntimeEnv({ agentOnly: true });
252
+ if (shareEnv)
253
+ dispatchOptions.env = shareEnv;
248
254
  if (options.env)
249
255
  dispatchOptions.providerOptions.env = options.env;
250
256
  if (options.computer)
@@ -272,21 +278,25 @@ Examples:
272
278
  if (options.on) {
273
279
  const event = normalizeTriggerEvent(options.on);
274
280
  if (!event) {
275
- die(`Unknown --on event "${options.on}". Use one of: ${GITHUB_TRIGGER_EVENTS.join(', ')} (aliases: pr, comment, workflow).`);
281
+ die(`Unknown --on event "${options.on}". Use one of: ${GITHUB_TRIGGER_EVENTS.join(', ')} (aliases: pr, comment, workflow).`, 1, { json });
276
282
  }
277
283
  const trigger = { type: 'github_event', event: event };
278
284
  if (repoValues[0])
279
285
  trigger.repo = repoValues[0];
280
286
  if (options.branch)
281
287
  trigger.branch = options.branch;
288
+ if (options.action)
289
+ trigger.action = options.action;
290
+ if (options.label)
291
+ trigger.label = options.label;
282
292
  const triggerErrors = validateTrigger(trigger);
283
293
  if (triggerErrors.length > 0)
284
- die(`Invalid trigger: ${triggerErrors.join(', ')}`);
294
+ die(`Invalid trigger: ${triggerErrors.join(', ')}`, 1, { json });
285
295
  dispatchOptions.trigger = trigger;
286
296
  const routineName = options.name
287
297
  || `cloud-${event}-${(repoValues[0] || 'any').replace(/[^a-z0-9]+/gi, '-')}`.toLowerCase();
288
298
  if (jobExists(routineName)) {
289
- die(`A routine named "${routineName}" already exists. Pass --name to register under a different name.`);
299
+ die(`A routine named "${routineName}" already exists. Pass --name to register under a different name.`, 1, { json });
290
300
  }
291
301
  const routine = {
292
302
  name: routineName,
@@ -329,15 +339,15 @@ Examples:
329
339
  const caps = provider.capabilities();
330
340
  if (imagePaths.length > 0) {
331
341
  if (!caps.images)
332
- die(`${provider.name} does not support image attachments.`);
342
+ die(`${provider.name} does not support image attachments.`, 1, { json });
333
343
  if (imagePaths.length > MAX_IMAGES_PER_DISPATCH) {
334
- die(`Too many images: ${imagePaths.length}. Max is ${MAX_IMAGES_PER_DISPATCH} per dispatch.`);
344
+ die(`Too many images: ${imagePaths.length}. Max is ${MAX_IMAGES_PER_DISPATCH} per dispatch.`, 1, { json });
335
345
  }
336
346
  dispatchOptions.images = imagePaths.map(readImageAttachment);
337
347
  }
338
348
  if (skillIds.length > 0) {
339
349
  if (!caps.skills)
340
- die(`${provider.name} does not support ride-along skills.`);
350
+ die(`${provider.name} does not support ride-along skills.`, 1, { json });
341
351
  dispatchOptions.skills = skillIds.map(parseSkillRef);
342
352
  }
343
353
  // Dispatch. On a missing pre-provisioned target (Codex env / Factory
@@ -362,18 +372,18 @@ Examples:
362
372
  if (err instanceof MissingTargetError) {
363
373
  const picked = await pickMissingTarget(provider, err, json);
364
374
  if (!picked) {
365
- die(err.guidance ? `${err.message}\n\n${err.guidance}` : err.message);
375
+ die(err.guidance ? `${err.message}\n\n${err.guidance}` : err.message, 1, { json });
366
376
  }
367
377
  dispatchOptions.providerOptions[err.kind] = picked;
368
378
  try {
369
379
  task = await dispatchOnce();
370
380
  }
371
381
  catch (err2) {
372
- die(err2.message);
382
+ die(err2.message, 1, { json });
373
383
  }
374
384
  }
375
385
  else {
376
- die(err.message);
386
+ die(err.message, 1, { json });
377
387
  }
378
388
  }
379
389
  // Persist locally
@@ -1,3 +1,5 @@
1
+ import { IsolationBoundaryError } from '../lib/shims.js';
2
+ import { explainIsolationBoundary } from '../lib/isolation-boundary-report.js';
1
3
  import { addHostOption } from '../lib/hosts/option.js';
2
4
  import { buildRemoteAgentsInvocation } from '../lib/hosts/remote-cmd.js';
3
5
  import { loadDevices, isControlDevice } from '../lib/devices/registry.js';
@@ -352,13 +354,13 @@ function parseTargetArg(arg) {
352
354
  const versions = listInstalledVersions(agent);
353
355
  if (versions.length === 0)
354
356
  return { error: `${AGENTS[agent].name} has no installed versions. Run \`agents add ${agent}@<version>\` first.` };
355
- return { agent, versions };
357
+ return { agent, versions, versionExplicit: false };
356
358
  }
357
359
  if (versionPart === 'default') {
358
360
  const def = getGlobalDefault(agent);
359
361
  if (!def)
360
362
  return { error: `${AGENTS[agent].name} has no default version pinned. Run \`agents use ${agent}@<version>\`.` };
361
- return { agent, versions: [def] };
363
+ return { agent, versions: [def], versionExplicit: true };
362
364
  }
363
365
  const spec = parseAgentSpec(`${agent}@${versionPart}`);
364
366
  if (!spec)
@@ -366,7 +368,7 @@ function parseTargetArg(arg) {
366
368
  if (!isVersionInstalled(agent, versionPart)) {
367
369
  return { error: `${AGENTS[agent].name}@${versionPart} is not installed. Installed: ${listInstalledVersions(agent).join(', ') || '(none)'}` };
368
370
  }
369
- return { agent, versions: [versionPart] };
371
+ return { agent, versions: [versionPart], versionExplicit: true };
370
372
  }
371
373
  function parseKindFilter(arg) {
372
374
  if (!arg)
@@ -601,10 +603,14 @@ async function runFix(parsed, opts) {
601
603
  // left to heal's neutral default rather than process.cwd().
602
604
  if (!opts.json)
603
605
  console.log(chalk.bold('Healing…'));
606
+ // `agents doctor <agent> --fix` is a SWEEP, same as the bare form — leave the
607
+ // version list to heal() so it applies its isolated-copy filter. Passing the
608
+ // enumerated list here would smuggle isolated versions past that filter.
609
+ // A named version (`<agent>@<version>`) is explicit consent and is passed through.
604
610
  const result = await heal({
605
611
  mode: 'full',
606
612
  agent: parsed?.agent,
607
- versions: parsed?.versions,
613
+ versions: parsed?.versionExplicit ? parsed.versions : undefined,
608
614
  });
609
615
  if (opts.json) {
610
616
  console.log(JSON.stringify(result, null, 2));
@@ -686,7 +692,17 @@ export function registerDoctorCommand(program) {
686
692
  // adoptShadowingLauncher resolves the launcher itself (PATH shadow, then
687
693
  // the durable ~/.local/bin symlink), so it forces the take-over even when
688
694
  // this shell's PATH already has the shim first.
689
- const result = adoptShadowingLauncher(agent);
695
+ let result;
696
+ try {
697
+ result = adoptShadowingLauncher(agent);
698
+ }
699
+ catch (err) {
700
+ if (err instanceof IsolationBoundaryError) {
701
+ explainIsolationBoundary(err);
702
+ process.exit(1);
703
+ }
704
+ throw err;
705
+ }
690
706
  if (result.adopted) {
691
707
  console.log(chalk.green(`Adopted ${AGENTS[agent].cliCommand} launcher (${result.launcher} -> shim). Original recorded for --release; version management now wins regardless of PATH order.`));
692
708
  }
@@ -1,16 +1,17 @@
1
1
  /**
2
- * `agents events` — read the structured audit/event log.
2
+ * `agents events` — read the unified event stream.
3
3
  *
4
- * The event log (`~/.agents/events.jsonl`) records every
5
- * `agents <module> <cmd>` invocation plus richer typed events (secrets access,
6
- * version installs, ...), each stamped with who ran it and from where (OS user,
7
- * local vs SSH, remote client IP). This command reads it back — the audit trail
8
- * for "who accessed a secret / created a team / started an agent, and from which
9
- * host?".
4
+ * One stream over BOTH operational events (`~/.agents/events.jsonl`: every
5
+ * `agents <module> <cmd>` invocation plus typed events like secrets access,
6
+ * version installs) AND agent-semantic events (the per-session activity logs:
7
+ * plans, PRs, worktrees, sub-agents, artifacts). Each is stamped with who ran
8
+ * it and from where. This is the audit trail for "who accessed a secret /
9
+ * created a team" AND the activity trail for "what did the agents just do".
10
10
  *
11
- * Filter by `--module` (top-level group, e.g. teams), `--command` (path prefix,
12
- * e.g. "teams create"), `--event` (typed event), `--agent`, and `--since`.
13
- * `--follow` tails today's log live.
11
+ * Filter by `--module` (top-level group, e.g. teams; `activity` for agent
12
+ * events), `--command` (path prefix), `--event` (typed event), `--agent`, and
13
+ * `--since`. `--audit` restricts to operational events only. `--follow` tails
14
+ * today's operational log live.
14
15
  */
15
16
  import type { Command } from 'commander';
16
17
  export declare function registerEventsCommand(program: Command): void;
@@ -1,20 +1,22 @@
1
1
  /**
2
- * `agents events` — read the structured audit/event log.
2
+ * `agents events` — read the unified event stream.
3
3
  *
4
- * The event log (`~/.agents/events.jsonl`) records every
5
- * `agents <module> <cmd>` invocation plus richer typed events (secrets access,
6
- * version installs, ...), each stamped with who ran it and from where (OS user,
7
- * local vs SSH, remote client IP). This command reads it back — the audit trail
8
- * for "who accessed a secret / created a team / started an agent, and from which
9
- * host?".
4
+ * One stream over BOTH operational events (`~/.agents/events.jsonl`: every
5
+ * `agents <module> <cmd>` invocation plus typed events like secrets access,
6
+ * version installs) AND agent-semantic events (the per-session activity logs:
7
+ * plans, PRs, worktrees, sub-agents, artifacts). Each is stamped with who ran
8
+ * it and from where. This is the audit trail for "who accessed a secret /
9
+ * created a team" AND the activity trail for "what did the agents just do".
10
10
  *
11
- * Filter by `--module` (top-level group, e.g. teams), `--command` (path prefix,
12
- * e.g. "teams create"), `--event` (typed event), `--agent`, and `--since`.
13
- * `--follow` tails today's log live.
11
+ * Filter by `--module` (top-level group, e.g. teams; `activity` for agent
12
+ * events), `--command` (path prefix), `--event` (typed event), `--agent`, and
13
+ * `--since`. `--audit` restricts to operational events only. `--follow` tails
14
+ * today's operational log live.
14
15
  */
15
16
  import chalk from 'chalk';
16
17
  import * as fs from 'fs';
17
- import { query, getLogsPath } from '../lib/events.js';
18
+ import { getLogsPath } from '../lib/events.js';
19
+ import { readUnifiedEvents } from '../lib/event-stream.js';
18
20
  /** Parse `--since`: relative offsets (30s/5m/2h/7d/4w) or an ISO/absolute date. */
19
21
  function parseSince(s) {
20
22
  const m = s.match(/^(\d+)([smhdw])$/);
@@ -42,6 +44,11 @@ function detailFor(r) {
42
44
  if (r.command)
43
45
  return r.command;
44
46
  const bits = [];
47
+ // Agent-semantic (activity) events carry detail/url instead of a command.
48
+ if (typeof r.detail === 'string')
49
+ bits.push(r.detail);
50
+ if (typeof r.url === 'string')
51
+ bits.push(chalk.gray(r.url));
45
52
  if (typeof r.team === 'string')
46
53
  bits.push(`team=${r.team}`);
47
54
  if (typeof r.bundle === 'string')
@@ -66,23 +73,24 @@ function renderRow(r) {
66
73
  export function registerEventsCommand(program) {
67
74
  program
68
75
  .command('events')
69
- .description('Read the structured audit/event log (who ran what, from where)')
70
- .option('--module <name>', 'Only events from this command group (e.g. teams, secrets)')
76
+ .description('Read the unified event stream (operational + agent activity)')
77
+ .option('--module <name>', 'Only events from this group (e.g. teams, secrets, activity)')
71
78
  .option('--command <path>', 'Only this command path — prefix match (e.g. "teams create")')
72
- .option('--event <type>', 'Only this typed event (repeatable, e.g. secrets.get)', collect, [])
79
+ .option('--event <type>', 'Only this typed event (repeatable, e.g. secrets.get, pr.opened)', collect, [])
73
80
  .option('--agent <name>', 'Only events tagged with this agent')
74
81
  .option('--since <time>', 'Only events newer than this (e.g. 2h, 7d, or ISO date)')
82
+ .option('--audit', 'Operational events only (skip agent activity)')
75
83
  .option('--limit <n>', 'Max records to show (default 50)', '50')
76
84
  .option('--json', 'Output raw records as JSON')
77
- .option('-f, --follow', "Tail today's log live")
85
+ .option('-f, --follow', "Tail today's operational log live")
78
86
  .addHelpText('after', `
79
87
  Examples:
80
- agents events Recent activity across everything
81
- agents events --module teams Team lifecycle (create / add / disband)
88
+ agents events Everything ops + agent activity
89
+ agents events --module activity Agent activity only (plans / PRs / worktrees)
90
+ agents events --audit Operational events only (secrets / teams / ...)
91
+ agents events --event pr.opened --since 7d
82
92
  agents events --module secrets Every secret accessed or revealed
83
- agents events --command "teams create" Just team creations
84
- agents events --event secrets.get --since 7d --json
85
- agents events -f Live tail`)
93
+ agents events -f Live tail (operational)`)
86
94
  .action(async (options) => {
87
95
  if (options.follow) {
88
96
  await followLog();
@@ -97,13 +105,14 @@ Examples:
97
105
  console.error(chalk.red(err.message));
98
106
  process.exit(2);
99
107
  }
100
- const records = query({
108
+ const records = readUnifiedEvents({
101
109
  startDate,
102
110
  eventTypes: options.event && options.event.length ? options.event : undefined,
103
111
  agent: options.agent,
104
112
  command: options.command,
105
113
  module: options.module,
106
114
  limit,
115
+ includeActivity: !options.audit,
107
116
  });
108
117
  if (options.json) {
109
118
  console.log(JSON.stringify(records, null, 2));
@@ -21,6 +21,7 @@ export declare function runAccountPickerConflicts(options: {
21
21
  strategy?: string;
22
22
  balanced?: boolean;
23
23
  lease?: string | boolean;
24
+ box?: string;
24
25
  host?: string;
25
26
  device?: string;
26
27
  on?: string;
@@ -34,6 +35,39 @@ export interface CopyCredsGateHost {
34
35
  /** `devices` = registered Tailscale fleet host; `local` = ssh-config/inline. */
35
36
  provider?: string;
36
37
  }
38
+ /**
39
+ * Whether `cwd` is inside a git work tree.
40
+ *
41
+ * `--lease` / `--box` sync the working directory to the box through crabbox,
42
+ * which enumerates the files to copy with `git ls-files`. Outside a git repo
43
+ * that exits 128 (`fatal: not a git repository`) and the whole run dies at
44
+ * "build sync file list: exit status 128" — AFTER the box is provisioned and
45
+ * billed. Checking this up front lets the caller fail fast, before provisioning.
46
+ */
47
+ export declare function isInsideGitWorkTree(cwd: string): boolean;
48
+ /** Absolute git toplevel for `cwd`, or null when it is not a git repo. */
49
+ export declare function gitToplevel(cwd: string): string | null;
50
+ /**
51
+ * Network mode for a `--lease` run (F5, RUSH-1924). `--tailscale` forces the
52
+ * tailnet, `--no-tailscale` forces public, and neither (undefined) defaults to
53
+ * the tailnet ONLY in a reuse context (`--reuse`, `--box`, or a picked warm
54
+ * box) — a one-shot solo `--lease` stays public. Pure so it is unit-testable;
55
+ * the caller downgrades to `'public'` when no auth key is configured.
56
+ */
57
+ export declare function computeNetMode(opts: {
58
+ tailscale?: boolean;
59
+ reuseContext: boolean;
60
+ }): 'public' | 'tailscale';
61
+ /** True when `repoRoot` is in the remembered always-fresh set. Pure. */
62
+ export declare function isAlwaysFreshRepo(repos: string[], repoRoot: string): boolean;
63
+ /** Add `repoRoot` to the always-fresh set (idempotent). Pure. */
64
+ export declare function addAlwaysFreshRepo(repos: string[], repoRoot: string): string[];
65
+ /** Path to the always-fresh state file under the USER agents dir (CLI-written per-user preference, never the maintainer-owned `.system` repo). */
66
+ export declare function leaseFreshReposPath(): string;
67
+ /** Read the remembered always-fresh repo roots (empty on any read/parse error). */
68
+ export declare function readAlwaysFreshRepos(): string[];
69
+ /** Persist the always-fresh repo roots. Best-effort — never throws. */
70
+ export declare function writeAlwaysFreshRepos(repos: string[]): void;
37
71
  /** Outcome of the `--copy-creds` security gate (RUSH-1767). */
38
72
  export interface CopyCredsGateDecision {
39
73
  /** Ship credentials? True only when the host key is pinned in the managed store. */