@phnx-labs/agents-cli 1.20.51 → 1.20.53

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 (142) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +12 -0
  3. package/dist/bin/agents +0 -0
  4. package/dist/commands/browser.js +215 -7
  5. package/dist/commands/cloud.d.ts +3 -0
  6. package/dist/commands/cloud.js +8 -1
  7. package/dist/commands/events.d.ts +1 -1
  8. package/dist/commands/events.js +2 -3
  9. package/dist/commands/exec.js +82 -3
  10. package/dist/commands/factory.js +8 -0
  11. package/dist/commands/feed.d.ts +38 -0
  12. package/dist/commands/feed.js +274 -0
  13. package/dist/commands/logs.d.ts +5 -1
  14. package/dist/commands/logs.js +248 -3
  15. package/dist/commands/mcp.js +7 -0
  16. package/dist/commands/memory.d.ts +9 -0
  17. package/dist/commands/memory.js +164 -0
  18. package/dist/commands/message.d.ts +11 -6
  19. package/dist/commands/message.js +140 -5
  20. package/dist/commands/routines.js +12 -0
  21. package/dist/commands/secrets-migrate.d.ts +2 -1
  22. package/dist/commands/secrets-migrate.js +88 -13
  23. package/dist/commands/secrets.d.ts +22 -0
  24. package/dist/commands/secrets.js +176 -42
  25. package/dist/commands/sessions.js +10 -1
  26. package/dist/commands/teams.js +4 -0
  27. package/dist/commands/worktree.js +4 -2
  28. package/dist/index.js +21 -22
  29. package/dist/lib/agents.js +249 -17
  30. package/dist/lib/answer-router.d.ts +75 -0
  31. package/dist/lib/answer-router.js +149 -0
  32. package/dist/lib/ask-classifier.d.ts +71 -0
  33. package/dist/lib/ask-classifier.js +197 -0
  34. package/dist/lib/browser/login-detection.d.ts +94 -0
  35. package/dist/lib/browser/login-detection.js +274 -0
  36. package/dist/lib/browser/profiles.d.ts +17 -8
  37. package/dist/lib/browser/profiles.js +27 -8
  38. package/dist/lib/browser/secret-ref.d.ts +10 -0
  39. package/dist/lib/browser/secret-ref.js +14 -0
  40. package/dist/lib/browser/service.js +14 -12
  41. package/dist/lib/cloud/antigravity.d.ts +0 -2
  42. package/dist/lib/cloud/antigravity.js +2 -17
  43. package/dist/lib/cloud/codex.js +3 -18
  44. package/dist/lib/cloud/rush.d.ts +15 -0
  45. package/dist/lib/cloud/rush.js +10 -16
  46. package/dist/lib/cloud/stream.js +2 -0
  47. package/dist/lib/cloud/types.d.ts +21 -0
  48. package/dist/lib/cloud/types.js +81 -0
  49. package/dist/lib/crabbox/cli.d.ts +1 -1
  50. package/dist/lib/crabbox/cli.js +12 -2
  51. package/dist/lib/crabbox/lease.d.ts +19 -0
  52. package/dist/lib/crabbox/lease.js +22 -11
  53. package/dist/lib/crabbox/progress.d.ts +62 -0
  54. package/dist/lib/crabbox/progress.js +129 -0
  55. package/dist/lib/crabbox/runtimes.d.ts +38 -1
  56. package/dist/lib/crabbox/runtimes.js +98 -5
  57. package/dist/lib/daemon.d.ts +12 -9
  58. package/dist/lib/daemon.js +32 -17
  59. package/dist/lib/events.d.ts +31 -5
  60. package/dist/lib/events.js +291 -101
  61. package/dist/lib/exec.js +20 -1
  62. package/dist/lib/feed-outcome.d.ts +101 -0
  63. package/dist/lib/feed-outcome.js +244 -0
  64. package/dist/lib/feed-policy.d.ts +30 -0
  65. package/dist/lib/feed-policy.js +133 -0
  66. package/dist/lib/feed.d.ts +180 -0
  67. package/dist/lib/feed.js +627 -0
  68. package/dist/lib/git.d.ts +17 -1
  69. package/dist/lib/git.js +20 -1
  70. package/dist/lib/hooks.js +529 -14
  71. package/dist/lib/hosts/passthrough.d.ts +3 -3
  72. package/dist/lib/hosts/passthrough.js +3 -3
  73. package/dist/lib/mailbox-gc.d.ts +22 -0
  74. package/dist/lib/mailbox-gc.js +161 -0
  75. package/dist/lib/mailbox.d.ts +26 -2
  76. package/dist/lib/mailbox.js +80 -5
  77. package/dist/lib/mcp.js +82 -0
  78. package/dist/lib/memory.d.ts +55 -0
  79. package/dist/lib/memory.js +274 -0
  80. package/dist/lib/notify.d.ts +16 -0
  81. package/dist/lib/notify.js +61 -0
  82. package/dist/lib/operator.d.ts +26 -0
  83. package/dist/lib/operator.js +107 -0
  84. package/dist/lib/plugins.d.ts +35 -0
  85. package/dist/lib/plugins.js +217 -0
  86. package/dist/lib/remote-agents-json.d.ts +14 -0
  87. package/dist/lib/remote-agents-json.js +94 -0
  88. package/dist/lib/resources/mcp.js +44 -0
  89. package/dist/lib/resources/memory.d.ts +15 -0
  90. package/dist/lib/resources/memory.js +46 -0
  91. package/dist/lib/resources/types.d.ts +2 -2
  92. package/dist/lib/rotate.js +2 -0
  93. package/dist/lib/runner.d.ts +43 -0
  94. package/dist/lib/runner.js +323 -74
  95. package/dist/lib/sandbox.js +6 -0
  96. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  97. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  98. package/dist/lib/secrets/agent.d.ts +21 -0
  99. package/dist/lib/secrets/agent.js +63 -1
  100. package/dist/lib/secrets/bundles.d.ts +33 -1
  101. package/dist/lib/secrets/bundles.js +76 -21
  102. package/dist/lib/secrets/icloud-import.d.ts +79 -0
  103. package/dist/lib/secrets/icloud-import.js +203 -0
  104. package/dist/lib/secrets/index.d.ts +142 -2
  105. package/dist/lib/secrets/index.js +695 -30
  106. package/dist/lib/secrets/remote.js +1 -1
  107. package/dist/lib/secrets/sync.js +1 -1
  108. package/dist/lib/session/active.d.ts +18 -0
  109. package/dist/lib/session/active.js +47 -17
  110. package/dist/lib/session/db.d.ts +9 -1
  111. package/dist/lib/session/db.js +18 -3
  112. package/dist/lib/session/discover.d.ts +13 -0
  113. package/dist/lib/session/discover.js +32 -2
  114. package/dist/lib/session/parse.d.ts +8 -0
  115. package/dist/lib/session/parse.js +42 -21
  116. package/dist/lib/session/remote-active.js +8 -89
  117. package/dist/lib/session/state.d.ts +11 -0
  118. package/dist/lib/session/state.js +50 -1
  119. package/dist/lib/session/tail.d.ts +23 -4
  120. package/dist/lib/session/tail.js +34 -16
  121. package/dist/lib/session/throughput.d.ts +30 -0
  122. package/dist/lib/session/throughput.js +86 -0
  123. package/dist/lib/shim-heal.d.ts +12 -3
  124. package/dist/lib/shim-heal.js +12 -6
  125. package/dist/lib/staleness/detectors/subagents.js +57 -3
  126. package/dist/lib/staleness/writers/hooks.js +7 -3
  127. package/dist/lib/staleness/writers/subagents.js +37 -6
  128. package/dist/lib/startup/command-registry.d.ts +2 -0
  129. package/dist/lib/startup/command-registry.js +4 -0
  130. package/dist/lib/state.d.ts +2 -0
  131. package/dist/lib/state.js +25 -8
  132. package/dist/lib/subagents.d.ts +52 -0
  133. package/dist/lib/subagents.js +315 -12
  134. package/dist/lib/teams/agents.js +6 -3
  135. package/dist/lib/teams/worktree.d.ts +8 -0
  136. package/dist/lib/teams/worktree.js +8 -0
  137. package/dist/lib/types.d.ts +20 -2
  138. package/dist/lib/versions.js +38 -48
  139. package/dist/lib/whats-new.d.ts +5 -3
  140. package/dist/lib/whats-new.js +25 -5
  141. package/package.json +4 -3
  142. package/scripts/postinstall.js +61 -1
@@ -558,15 +558,19 @@ export async function runDaemon() {
558
558
  /**
559
559
  * Read the long-lived Claude OAuth token (from `claude setup-token`) that the
560
560
  * user stored under the `claude` secrets bundle. Resolves the bundle the same
561
- * way `agents run --secrets` does, so the token is found whether it was stored
562
- * keychain-backed or as a literal. Returns null when the bundle/key isn't
563
- * configured, the Keychain read is cancelled, or the platform has no keychain —
564
- * the daemon then behaves exactly as before (relying on the interactive OAuth
565
- * session). Never throws: a misconfigured token must not block daemon startup.
561
+ * way `agents run --secrets` does. Interactive starts may prompt Keychain;
562
+ * headless auto-starts are broker-only and return null unless the user already
563
+ * unlocked the bundle in the secrets agent. That keeps a background browser
564
+ * command from hanging on an unseen biometric prompt. Never throws: an absent
565
+ * token leaves the daemon on its existing interactive OAuth session.
566
566
  */
567
- export function readDaemonClaudeOAuthToken() {
567
+ export function readDaemonClaudeOAuthToken(opts = {}) {
568
568
  try {
569
- const { env } = readAndResolveBundleEnv(DAEMON_OAUTH_BUNDLE, { caller: 'daemon' });
569
+ const allowPrompt = opts.allowPrompt ?? Boolean(process.stdin.isTTY);
570
+ const { env } = readAndResolveBundleEnv(DAEMON_OAUTH_BUNDLE, {
571
+ caller: 'daemon',
572
+ agentOnly: !allowPrompt,
573
+ });
570
574
  const token = (env[DAEMON_OAUTH_KEY] ?? '').trim();
571
575
  return token.length > 0 ? token : null;
572
576
  }
@@ -599,10 +603,9 @@ export function writeOwnerOnlyServiceManifest(filePath, content) {
599
603
  fs.writeFileSync(filePath, content, { encoding: 'utf-8', mode: 0o600 });
600
604
  }
601
605
  /** Generate a macOS launchd plist for auto-starting the daemon. */
602
- export function generateLaunchdPlist() {
606
+ export function generateLaunchdPlist(oauthToken = readDaemonClaudeOAuthToken()) {
603
607
  const agentsBin = getAgentsBinPath();
604
608
  const logPath = getLogPath();
605
- const oauthToken = readDaemonClaudeOAuthToken();
606
609
  const oauthEntry = oauthToken
607
610
  ? `
608
611
  <key>${DAEMON_OAUTH_KEY}</key>
@@ -637,9 +640,8 @@ export function generateLaunchdPlist() {
637
640
  </plist>`;
638
641
  }
639
642
  /** Generate a Linux systemd user unit for auto-starting the daemon. */
640
- export function generateSystemdUnit() {
643
+ export function generateSystemdUnit(oauthToken = readDaemonClaudeOAuthToken()) {
641
644
  const agentsBin = getAgentsBinPath();
642
- const oauthToken = readDaemonClaudeOAuthToken();
643
645
  const oauthLine = oauthToken
644
646
  ? `\nEnvironment=${DAEMON_OAUTH_KEY}=${oauthToken}`
645
647
  : '';
@@ -657,15 +659,29 @@ Environment=PATH=/usr/local/bin:/usr/bin:/bin:${os.homedir()}/.nvm/versions/node
657
659
  [Install]
658
660
  WantedBy=default.target`;
659
661
  }
660
- function getAgentsBinPath() {
662
+ export function getAgentsBinPath() {
661
663
  // Prefer the binary actively executing this code. `which agents` returns
662
664
  // whatever happens to be first on PATH, which means a side-by-side dev
663
665
  // build at ~/.local/bin would silently spawn the registry-installed
664
666
  // daemon and run stale code. process.argv[1] is the absolute path of
665
667
  // the JS entrypoint the user actually invoked.
666
668
  const argv1 = process.argv[1];
667
- if (argv1 && fs.existsSync(argv1))
669
+ if (argv1 && fs.existsSync(argv1)) {
670
+ // The package's browser/computer entrypoints are sibling shims without a
671
+ // `daemon` command. A daemon started as their IPC side effect must launch
672
+ // through the main agents entrypoint instead of replaying the shim path.
673
+ const entryName = path.basename(argv1);
674
+ const compiledShim = /^(browser|computer)\.(c|m)?js$/.test(entryName);
675
+ const installedShim = /^(browser|computer)$/.test(entryName);
676
+ if (compiledShim || installedShim) {
677
+ const agentsEntry = path.join(path.dirname(argv1), compiledShim ? 'index.js' : 'agents');
678
+ if (!fs.existsSync(agentsEntry)) {
679
+ throw new Error(`Cannot start agents daemon: main CLI entry not found at ${agentsEntry}`);
680
+ }
681
+ return agentsEntry;
682
+ }
668
683
  return argv1;
684
+ }
669
685
  try {
670
686
  return execFileSync('which', ['agents'], { encoding: 'utf-8' }).trim();
671
687
  }
@@ -799,12 +815,11 @@ function startDaemonLocked() {
799
815
  * the daemon then passes it to every routine run it spawns. An already-set
800
816
  * value (e.g. inherited from launchd) is left untouched.
801
817
  */
802
- export function buildDetachedDaemonEnv(baseEnv = process.env) {
818
+ export function buildDetachedDaemonEnv(baseEnv = process.env, oauthToken = readDaemonClaudeOAuthToken()) {
803
819
  const env = { ...baseEnv };
804
820
  if (!env.CLAUDE_CODE_OAUTH_TOKEN) {
805
- const token = readDaemonClaudeOAuthToken();
806
- if (token)
807
- env.CLAUDE_CODE_OAUTH_TOKEN = token;
821
+ if (oauthToken)
822
+ env.CLAUDE_CODE_OAUTH_TOKEN = oauthToken;
808
823
  }
809
824
  return env;
810
825
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Centralized event logging for agents-cli.
3
3
  *
4
- * Structured JSONL logs at ~/.agents/.cache/logs/events-YYYY-MM-DD.jsonl
5
- * with automatic daily rotation and rich metadata for debugging/auditing.
4
+ * Structured JSONL audit log at ~/.agents/events.jsonl with lossless numbered
5
+ * gzip rotation at 10 MB and rich metadata for debugging/auditing.
6
6
  *
7
7
  * Features:
8
8
  * - Rich metadata: hostname, platform, arch, pid, timezone
@@ -11,7 +11,9 @@
11
11
  * - Permissions: logs dir is 0700, files are 0600 (owner-only)
12
12
  * - Performance tracking: withTiming() wrapper for any async function
13
13
  */
14
- export type EventType = 'agent.run.start' | 'agent.run.end' | 'agent.spawn.start' | 'agent.spawn.end' | 'version.install' | 'version.switch' | 'version.remove' | 'skill.install' | 'skill.remove' | 'browser.launch' | 'browser.close' | 'browser.navigate' | 'browser.screenshot' | 'secrets.get' | 'secrets.set' | 'secrets.delete' | 'secrets.rename' | 'cloud.dispatch' | 'cloud.complete' | 'teams.create' | 'teams.add' | 'teams.start' | 'teams.complete' | 'teams.disband' | 'hook.fire' | 'hook.complete' | 'hook.error' | 'resource.sync' | 'command.start' | 'command.end' | 'perf.timing' | 'session.start' | 'session.end' | 'error' | 'warn' | 'info' | 'debug';
14
+ export type EventLevel = 'audit' | 'warn' | 'info' | 'debug';
15
+ export type EventType = 'agent.run.start' | 'agent.run.end' | 'agent.spawn.start' | 'agent.spawn.end' | 'version.install' | 'version.switch' | 'version.remove' | 'skill.install' | 'skill.remove' | 'browser.launch' | 'browser.close' | 'browser.navigate' | 'browser.screenshot' | 'secrets.get' | 'secrets.set' | 'secrets.delete' | 'secrets.rename' | 'cloud.dispatch' | 'cloud.complete' | 'cloud.cancel' | 'cloud.message' | 'teams.create' | 'teams.add' | 'teams.start' | 'teams.complete' | 'teams.disband' | 'hook.fire' | 'hook.complete' | 'hook.error' | 'mcp.add' | 'mcp.remove' | 'mcp.register' | 'resource.sync' | 'rotation.resolved' | 'command.start' | 'command.end' | 'perf.timing' | 'session.start' | 'session.end' | 'error' | 'warn' | 'info' | 'debug';
16
+ export declare function levelFor(event: EventType): EventLevel;
15
17
  export interface EventMeta {
16
18
  ts: string;
17
19
  tz: string;
@@ -22,6 +24,9 @@ export interface EventMeta {
22
24
  pid: number;
23
25
  ppid: number;
24
26
  event: EventType;
27
+ level: EventLevel;
28
+ caller: string;
29
+ session?: string;
25
30
  osUser: string;
26
31
  transport: 'local' | 'ssh';
27
32
  sshClientIp?: string;
@@ -67,8 +72,14 @@ export declare function redactArgs(args: string[] | undefined): string[] | undef
67
72
  * Returns undefined for null/undefined input.
68
73
  */
69
74
  export declare function truncate(str: string | null | undefined, maxLength?: number): string | undefined;
75
+ export interface CallerIdentity {
76
+ kind: string;
77
+ session?: string;
78
+ }
79
+ /** Identify the environment that invoked agents-cli, not the source callsite. */
80
+ export declare function detectCaller(env?: NodeJS.ProcessEnv, stdoutIsTTY?: boolean): CallerIdentity;
70
81
  /**
71
- * Emit a structured event to the daily log file.
82
+ * Emit a structured event to the append-only audit log.
72
83
  *
73
84
  * @param event - The event type
74
85
  * @param payload - Event-specific data (agent, version, cwd, etc.)
@@ -142,7 +153,7 @@ export declare function emitCommand(command: string, args?: string[], payload?:
142
153
  export declare function emitError(err: Error | string, payload?: EventPayload): void;
143
154
  /**
144
155
  * Remove log files older than the retention period.
145
- * Called lazily on emit or explicitly via CLI.
156
+ * Removes numbered gzip archives whose filesystem mtime exceeds retention.
146
157
  *
147
158
  * @param retentionDays - Number of days to keep (default 7, from DEFAULT_RETENTION_DAYS)
148
159
  * @returns Number of files removed
@@ -159,7 +170,9 @@ export declare function query(options: {
159
170
  startDate?: Date;
160
171
  endDate?: Date;
161
172
  eventTypes?: EventType[];
173
+ level?: EventLevel;
162
174
  agent?: string;
175
+ caller?: string;
163
176
  command?: string;
164
177
  module?: string;
165
178
  limit?: number;
@@ -177,4 +190,17 @@ export declare function getTimingStats(label: string, options?: {
177
190
  p50Ms: number;
178
191
  p95Ms: number;
179
192
  } | null;
193
+ export interface EventStats {
194
+ totalEvents: number;
195
+ byLevel: Record<string, number>;
196
+ byEvent: Record<string, number>;
197
+ byModule: Record<string, number>;
198
+ byUser: Record<string, number>;
199
+ fileCount: number;
200
+ totalBytes: number;
201
+ }
202
+ export declare function stats(options?: {
203
+ days?: number;
204
+ }): EventStats;
180
205
  export declare function getLogsPath(): string;
206
+ export declare function _resetForTest(overrideEventsPath?: string): void;