@phnx-labs/agents-cli 1.22.41 → 1.22.43

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 (253) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +10 -4
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +25 -7
  5. package/dist/cli/command-registry.d.ts +2 -3
  6. package/dist/cli/command-registry.js +4 -8
  7. package/dist/commands/accounts.d.ts +29 -0
  8. package/dist/commands/accounts.js +220 -29
  9. package/dist/commands/alias.d.ts +7 -4
  10. package/dist/commands/alias.js +34 -9
  11. package/dist/commands/auth.d.ts +9 -0
  12. package/dist/commands/auth.js +108 -0
  13. package/dist/commands/browser-sessions-picker.js +42 -62
  14. package/dist/commands/browser.js +30 -38
  15. package/dist/commands/computer-actions.d.ts +1 -1
  16. package/dist/commands/computer-actions.js +1 -1
  17. package/dist/commands/computer-sessions-picker.js +32 -55
  18. package/dist/commands/computer.d.ts +1 -1
  19. package/dist/commands/computer.js +22 -8
  20. package/dist/commands/daemon.js +1 -1
  21. package/dist/commands/doctor.d.ts +5 -3
  22. package/dist/commands/doctor.js +23 -8
  23. package/dist/commands/exec.js +3 -2
  24. package/dist/commands/feed.js +2 -31
  25. package/dist/commands/harness.js +3 -3
  26. package/dist/commands/hooks.js +1 -1
  27. package/dist/commands/import.js +1 -1
  28. package/dist/commands/insights.js +163 -85
  29. package/dist/commands/inspect.js +2 -2
  30. package/dist/commands/mine.js +1 -1
  31. package/dist/commands/monitors.js +1 -1
  32. package/dist/commands/org.d.ts +6 -0
  33. package/dist/commands/org.js +175 -0
  34. package/dist/commands/packages.js +1 -1
  35. package/dist/commands/profiles.js +2 -2
  36. package/dist/commands/prune.js +1 -1
  37. package/dist/commands/routines.js +44 -26
  38. package/dist/commands/run-account-picker.d.ts +19 -0
  39. package/dist/commands/run-account-picker.js +81 -0
  40. package/dist/commands/sessions-picker-factory.d.ts +40 -0
  41. package/dist/commands/sessions-picker-factory.js +67 -0
  42. package/dist/commands/sessions-picker.js +124 -122
  43. package/dist/commands/setup-browser.js +4 -4
  44. package/dist/commands/setup-mine.js +1 -1
  45. package/dist/commands/setup-preferences.js +2 -2
  46. package/dist/commands/setup.js +10 -4
  47. package/dist/commands/snapshot.d.ts +1 -1
  48. package/dist/commands/snapshot.js +4 -4
  49. package/dist/commands/status.d.ts +4 -2
  50. package/dist/commands/status.js +10 -7
  51. package/dist/commands/sync.d.ts +1 -0
  52. package/dist/commands/sync.js +30 -3
  53. package/dist/commands/versions.js +1 -1
  54. package/dist/commands/view.js +7 -1
  55. package/dist/commands/webhook.js +1 -1
  56. package/dist/lib/account-capabilities.d.ts +10 -0
  57. package/dist/lib/account-capabilities.js +34 -0
  58. package/dist/lib/accounting/rotate.d.ts +5 -3
  59. package/dist/lib/accounting/rotate.js +36 -7
  60. package/dist/lib/accounting/usage.d.ts +18 -4
  61. package/dist/lib/accounting/usage.js +138 -27
  62. package/dist/lib/agent-spec/agents.d.ts +584 -0
  63. package/dist/lib/agent-spec/agents.js +3127 -0
  64. package/dist/lib/agent-spec/provider.js +1 -1
  65. package/dist/lib/agents.d.ts +2 -584
  66. package/dist/lib/agents.js +2 -3127
  67. package/dist/lib/browser/drivers/local.d.ts +8 -2
  68. package/dist/lib/browser/drivers/local.js +8 -2
  69. package/dist/lib/browser/drivers/ssh.d.ts +8 -2
  70. package/dist/lib/browser/drivers/ssh.js +10 -4
  71. package/dist/lib/browser/hygiene.d.ts +1 -1
  72. package/dist/lib/browser/hygiene.js +5 -1
  73. package/dist/lib/browser/profiles.d.ts +74 -1
  74. package/dist/lib/browser/profiles.js +114 -5
  75. package/dist/lib/browser/runtime-state.d.ts +11 -5
  76. package/dist/lib/browser/runtime-state.js +13 -9
  77. package/dist/lib/browser/service.d.ts +68 -30
  78. package/dist/lib/browser/service.js +305 -194
  79. package/dist/lib/browser/types.d.ts +95 -3
  80. package/dist/lib/browser/types.js +51 -0
  81. package/dist/lib/catchup.js +1 -1
  82. package/dist/lib/cloud/rush.d.ts +0 -15
  83. package/dist/lib/cloud/rush.js +0 -35
  84. package/dist/lib/computer/actions.d.ts +1 -1
  85. package/dist/lib/computer/actions.js +1 -1
  86. package/dist/lib/{computer-rpc.js → computer/computer-rpc.js} +5 -5
  87. package/dist/lib/computer/dispatch.d.ts +1 -1
  88. package/dist/lib/computer/download.d.ts +1 -1
  89. package/dist/lib/computer/download.js +3 -3
  90. package/dist/lib/{ssh-tunnel.d.ts → computer/ssh-tunnel.d.ts} +1 -1
  91. package/dist/lib/{ssh-tunnel.js → computer/ssh-tunnel.js} +12 -12
  92. package/dist/lib/crabbox/runtimes.d.ts +6 -2
  93. package/dist/lib/crabbox/runtimes.js +21 -5
  94. package/dist/lib/daemon/daemon.js +87 -59
  95. package/dist/lib/{runner.d.ts → daemon/runner.d.ts} +28 -11
  96. package/dist/lib/{runner.js → daemon/runner.js} +143 -123
  97. package/dist/lib/devices/doctor-findings.d.ts +1 -1
  98. package/dist/lib/devices/doctor-findings.js +4 -4
  99. package/dist/lib/devices/fleet-inventory.js +1 -1
  100. package/dist/lib/devices/harness-inventory.js +1 -1
  101. package/dist/lib/devices/health-report.js +1 -1
  102. package/dist/lib/devices/registry.js +4 -22
  103. package/dist/lib/doctor-diff.d.ts +1 -1
  104. package/dist/lib/doctor-diff.js +1 -1
  105. package/dist/lib/drift-sync.d.ts +1 -1
  106. package/dist/lib/drift-sync.js +2 -2
  107. package/dist/lib/drift.d.ts +1 -1
  108. package/dist/lib/drift.js +1 -1
  109. package/dist/lib/entitlement.d.ts +31 -0
  110. package/dist/lib/entitlement.js +137 -0
  111. package/dist/lib/exec.js +52 -205
  112. package/dist/lib/feed/feed.js +2 -8
  113. package/dist/lib/format.d.ts +9 -0
  114. package/dist/lib/format.js +16 -0
  115. package/dist/lib/fs-atomic.d.ts +7 -0
  116. package/dist/lib/fs-atomic.js +9 -0
  117. package/dist/lib/github/pr-mergeable.d.ts +49 -0
  118. package/dist/lib/github/pr-mergeable.js +157 -0
  119. package/dist/lib/github/pr-verdict.d.ts +67 -0
  120. package/dist/lib/github/pr-verdict.js +72 -0
  121. package/dist/lib/harness/adapter.d.ts +161 -0
  122. package/dist/lib/harness/adapter.js +47 -0
  123. package/dist/lib/harness/adapters/claude.d.ts +2 -0
  124. package/dist/lib/harness/adapters/claude.js +110 -0
  125. package/dist/lib/harness/adapters/codex.d.ts +2 -0
  126. package/dist/lib/harness/adapters/codex.js +83 -0
  127. package/dist/lib/harness/adapters/copilot.d.ts +2 -0
  128. package/dist/lib/harness/adapters/copilot.js +23 -0
  129. package/dist/lib/harness/adapters/cursor.d.ts +2 -0
  130. package/dist/lib/harness/adapters/cursor.js +38 -0
  131. package/dist/lib/harness/adapters/droid.d.ts +2 -0
  132. package/dist/lib/harness/adapters/droid.js +17 -0
  133. package/dist/lib/harness/adapters/grok.d.ts +2 -0
  134. package/dist/lib/harness/adapters/grok.js +14 -0
  135. package/dist/lib/harness/adapters/kimi.d.ts +2 -0
  136. package/dist/lib/harness/adapters/kimi.js +49 -0
  137. package/dist/lib/harness/adapters/muse.d.ts +2 -0
  138. package/dist/lib/harness/adapters/muse.js +44 -0
  139. package/dist/lib/harness/adapters/opencode.d.ts +2 -0
  140. package/dist/lib/harness/adapters/opencode.js +14 -0
  141. package/dist/lib/harness/exec-config-version.d.ts +8 -0
  142. package/dist/lib/harness/exec-config-version.js +22 -0
  143. package/dist/lib/harness/index.d.ts +1 -0
  144. package/dist/lib/harness/index.js +34 -0
  145. package/dist/lib/{hooks.d.ts → hooks/install.d.ts} +1 -1
  146. package/dist/lib/{hooks.js → hooks/install.js} +11 -11
  147. package/dist/lib/hosts/passthrough.d.ts +10 -0
  148. package/dist/lib/hosts/passthrough.js +28 -6
  149. package/dist/lib/hosts/session-index.js +1 -1
  150. package/dist/lib/import.js +1 -1
  151. package/dist/lib/installations/index.d.ts +4 -4
  152. package/dist/lib/installations/index.js +3 -4
  153. package/dist/lib/installations/migrate.js +6 -6
  154. package/dist/lib/{shims.d.ts → installations/shims.d.ts} +2 -2
  155. package/dist/lib/{shims.js → installations/shims.js} +13 -115
  156. package/dist/lib/installations/store.d.ts +141 -3
  157. package/dist/lib/installations/store.js +475 -5
  158. package/dist/lib/installations/versions.d.ts +40 -125
  159. package/dist/lib/installations/versions.js +57 -462
  160. package/dist/lib/isolation-boundary-report.d.ts +1 -1
  161. package/dist/lib/isolation-boundary-report.js +1 -1
  162. package/dist/lib/mailbox-gc.js +2 -3
  163. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  164. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  165. package/dist/lib/menubar/install-menubar.js +19 -8
  166. package/dist/lib/monitors/config.d.ts +2 -2
  167. package/dist/lib/monitors/config.js +3 -2
  168. package/dist/lib/monitors/dispatch.d.ts +1 -1
  169. package/dist/lib/monitors/dispatch.js +2 -2
  170. package/dist/lib/monitors/state.d.ts +1 -1
  171. package/dist/lib/origin-machine.d.ts +18 -0
  172. package/dist/lib/origin-machine.js +34 -0
  173. package/dist/lib/perf/db.js +1 -1
  174. package/dist/lib/perf/spool.js +1 -1
  175. package/dist/lib/plugins/plugins.js +1 -1
  176. package/dist/lib/plugins/skills.js +1 -1
  177. package/dist/lib/prix-account.d.ts +158 -0
  178. package/dist/lib/prix-account.js +214 -0
  179. package/dist/lib/profiles.d.ts +7 -0
  180. package/dist/lib/profiles.js +26 -1
  181. package/dist/lib/project-key.js +2 -2
  182. package/dist/lib/project-launch.js +1 -1
  183. package/dist/lib/refresh.js +2 -2
  184. package/dist/lib/resource-inventory.d.ts +1 -1
  185. package/dist/lib/resource-inventory.js +1 -1
  186. package/dist/lib/rules/rules.js +1 -1
  187. package/dist/lib/sandbox.d.ts +24 -0
  188. package/dist/lib/sandbox.js +101 -0
  189. package/dist/lib/scheduling/routines.d.ts +18 -9
  190. package/dist/lib/scheduling/routines.js +17 -9
  191. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  192. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  193. package/dist/lib/secrets/agent.js +9 -1
  194. package/dist/lib/secrets/index.js +1 -1
  195. package/dist/lib/secrets/list-filter.js +1 -1
  196. package/dist/lib/self-heal/checks/hook-runtime.js +1 -1
  197. package/dist/lib/self-heal/checks/path.js +1 -1
  198. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  199. package/dist/lib/self-heal/checks/shims.js +1 -1
  200. package/dist/lib/service-manifest.d.ts +20 -0
  201. package/dist/lib/service-manifest.js +34 -0
  202. package/dist/lib/session/cloud.js +1 -1
  203. package/dist/lib/session/db.js +1 -1
  204. package/dist/lib/session/discover.d.ts +39 -0
  205. package/dist/lib/session/discover.js +3 -3
  206. package/dist/lib/session/fork.js +1 -1
  207. package/dist/lib/session/live-metadata.js +1 -1
  208. package/dist/lib/session/origin-machine.d.ts +1 -18
  209. package/dist/lib/session/origin-machine.js +4 -34
  210. package/dist/lib/session/parse.js +24 -42
  211. package/dist/lib/session/recovery.js +1 -1
  212. package/dist/lib/session/relative-time.d.ts +1 -44
  213. package/dist/lib/session/relative-time.js +4 -120
  214. package/dist/lib/session/remote-list.js +1 -1
  215. package/dist/lib/session/remote.js +2 -2
  216. package/dist/lib/session/short-id.d.ts +1 -17
  217. package/dist/lib/session/short-id.js +4 -20
  218. package/dist/lib/session/width.d.ts +1 -29
  219. package/dist/lib/session/width.js +4 -101
  220. package/dist/lib/snapshot.d.ts +2 -2
  221. package/dist/lib/snapshot.js +1 -1
  222. package/dist/lib/staleness/prune.d.ts +1 -1
  223. package/dist/lib/staleness/prune.js +1 -1
  224. package/dist/lib/staleness/writers/hooks.js +1 -1
  225. package/dist/lib/startup/command-registry.d.ts +4 -1
  226. package/dist/lib/startup/command-registry.js +12 -5
  227. package/dist/lib/teams/agents.js +2 -19
  228. package/dist/lib/teams/parsers.js +20 -26
  229. package/dist/lib/teams/placement-probe.js +1 -1
  230. package/dist/lib/teams/registry.js +2 -21
  231. package/dist/lib/teams/scheduler.js +1 -1
  232. package/dist/lib/text/relative-time.d.ts +44 -0
  233. package/dist/lib/text/relative-time.js +120 -0
  234. package/dist/lib/text/short-id.d.ts +17 -0
  235. package/dist/lib/text/short-id.js +20 -0
  236. package/dist/lib/text/width.d.ts +29 -0
  237. package/dist/lib/text/width.js +101 -0
  238. package/dist/lib/triggers/handlers.d.ts +7 -0
  239. package/dist/lib/triggers/handlers.js +9 -1
  240. package/dist/lib/triggers/webhook.d.ts +1 -0
  241. package/dist/lib/triggers/webhook.js +3 -2
  242. package/dist/lib/uninstall.js +1 -1
  243. package/dist/lib/version.d.ts +9 -2
  244. package/dist/lib/version.js +11 -9
  245. package/dist/lib/view-types.d.ts +4 -0
  246. package/package.json +1 -1
  247. package/dist/commands/tickets.d.ts +0 -2
  248. package/dist/commands/tickets.js +0 -43
  249. package/dist/lib/observe-aliases.d.ts +0 -30
  250. package/dist/lib/observe-aliases.js +0 -38
  251. package/dist/lib/tickets/list.d.ts +0 -53
  252. package/dist/lib/tickets/list.js +0 -153
  253. /package/dist/lib/{computer-rpc.d.ts → computer/computer-rpc.d.ts} +0 -0
@@ -91,14 +91,18 @@ export function resolveInstalledLayout() {
91
91
  * binary can't read its own bundled package.json), fall back to the on-disk
92
92
  * install found via the launcher symlink so callers like the menu bar don't see
93
93
  * a bogus `unknown`.
94
+ *
95
+ * `pkgJsonPath` is an optional override of the shipping package.json path,
96
+ * accepted by both this function and {@link getCliVersionFresh}. Every
97
+ * production call site uses the zero-argument form and gets the real on-disk
98
+ * path below; the parameter exists only so a unit test can point both
99
+ * functions at a fixture package.json instead of the real one shared by every
100
+ * parallel test fork.
94
101
  */
95
- export function getCliVersion() {
102
+ export function getCliVersion(pkgJsonPath = path.join(__dirname, '..', '..', 'package.json')) {
96
103
  if (cached)
97
104
  return cached;
98
- cached =
99
- readVersionAt(path.join(__dirname, '..', '..', 'package.json')) ??
100
- readInstalledPackageVersion() ??
101
- 'unknown';
105
+ cached = readVersionAt(pkgJsonPath) ?? readInstalledPackageVersion() ?? 'unknown';
102
106
  return cached;
103
107
  }
104
108
  /** Version from the on-disk install (Bun-binary fallback). */
@@ -116,8 +120,6 @@ function readInstalledPackageVersion() {
116
120
  * is now stale and should reload onto the new code (self-healing). Returns
117
121
  * 'unknown' on any error.
118
122
  */
119
- export function getCliVersionFresh() {
120
- return (readVersionAt(path.join(__dirname, '..', '..', 'package.json')) ??
121
- readInstalledPackageVersion() ??
122
- 'unknown');
123
+ export function getCliVersionFresh(pkgJsonPath = path.join(__dirname, '..', '..', 'package.json')) {
124
+ return readVersionAt(pkgJsonPath) ?? readInstalledPackageVersion() ?? 'unknown';
123
125
  }
@@ -24,6 +24,10 @@ export interface ViewJsonVersion {
24
24
  usedPercent: number;
25
25
  resetsAt: string | null;
26
26
  }>;
27
+ unavailable?: {
28
+ reason: 'session_limit';
29
+ resetsAt: string;
30
+ };
27
31
  lastActive: string | null;
28
32
  path: string;
29
33
  configuredModel?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phnx-labs/agents-cli",
3
- "version": "1.22.41",
3
+ "version": "1.22.43",
4
4
  "description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,2 +0,0 @@
1
- import type { Command } from 'commander';
2
- export declare function registerTicketsCommand(program: Command): void;
@@ -1,43 +0,0 @@
1
- import { setHelpSections } from '../lib/help.js';
2
- import { listTickets } from '../lib/tickets/list.js';
3
- export function registerTicketsCommand(program) {
4
- const tickets = program
5
- .command('tickets')
6
- .description('Read work items from the trackers linked to this workspace.');
7
- setHelpSections(tickets, {
8
- examples: `
9
- agents tickets list --json
10
- agents tickets list --github-assigned-only --json
11
- `,
12
- notes: `
13
- The response reports each source's availability explicitly. A failed tracker
14
- never makes another tracker's rows disappear.
15
- `,
16
- });
17
- tickets
18
- .command('list')
19
- .description('List workspace tickets from Linear and GitHub.')
20
- .option('--cwd <path>', 'Workspace used to resolve tracker context')
21
- .option('--no-linear', 'Exclude Linear tickets')
22
- .option('--no-github', 'Exclude GitHub issues')
23
- .option('--github-assigned-only', 'Only include GitHub issues assigned to the current user')
24
- .option('--json', 'Output machine-readable tickets, cycle metadata, and source availability')
25
- .action(async (options) => {
26
- const result = await listTickets({
27
- cwd: options.cwd ?? process.cwd(),
28
- linear: options.linear,
29
- github: options.github,
30
- githubAssignedOnly: options.githubAssignedOnly === true,
31
- });
32
- if (options.json) {
33
- console.log(JSON.stringify(result, null, 2));
34
- return;
35
- }
36
- console.log(`${result.tickets.length} ticket${result.tickets.length === 1 ? '' : 's'}`);
37
- for (const source of ['linear', 'github']) {
38
- const status = result.sources[source];
39
- if (!status.available && status.error)
40
- console.error(`${source}: ${status.error}`);
41
- }
42
- });
43
- }
@@ -1,30 +0,0 @@
1
- /**
2
- * Observe-umbrella aliases (Phase 3 surface consolidation).
3
- *
4
- * Thin name → real command expansion. No store merge — feed / sessions / events
5
- * remain the stores; these are doors that point at the right reader.
6
- *
7
- * inbox → feed (needs-you default)
8
- *
9
- * `roster` was removed — use `agents sessions --active`.
10
- * `timeline` was removed — use `agents feed --filter updates` (RUSH-2692).
11
- * `audit` is NOT an alias here — `agents audit` is already the tamper-evident
12
- * run-dispatch log. Ops trail = `agents events` (optionally `--audit`).
13
- */
14
- export type ObserveAlias = 'inbox';
15
- export declare const OBSERVE_ALIASES: readonly ObserveAlias[];
16
- export interface ObserveExpandResult {
17
- /** argv for the real command (no program name): e.g. ['feed', '--filter', 'updates'] */
18
- argv: string[];
19
- /** One-line note for stderr (optional); empty when silent. */
20
- note: string;
21
- }
22
- /** True when `rest` already carries a `--filter` / `--filter=…` flag. */
23
- export declare function hasFilterFlag(rest: readonly string[]): boolean;
24
- /** True when `rest` already carries `--active`. */
25
- export declare function hasActiveFlag(rest: readonly string[]): boolean;
26
- /**
27
- * Expand an observe alias + remaining user args into the real command argv.
28
- * Returns null when `alias` is not an observe alias.
29
- */
30
- export declare function expandObserveAlias(alias: string, rest?: readonly string[]): ObserveExpandResult | null;
@@ -1,38 +0,0 @@
1
- /**
2
- * Observe-umbrella aliases (Phase 3 surface consolidation).
3
- *
4
- * Thin name → real command expansion. No store merge — feed / sessions / events
5
- * remain the stores; these are doors that point at the right reader.
6
- *
7
- * inbox → feed (needs-you default)
8
- *
9
- * `roster` was removed — use `agents sessions --active`.
10
- * `timeline` was removed — use `agents feed --filter updates` (RUSH-2692).
11
- * `audit` is NOT an alias here — `agents audit` is already the tamper-evident
12
- * run-dispatch log. Ops trail = `agents events` (optionally `--audit`).
13
- */
14
- export const OBSERVE_ALIASES = ['inbox'];
15
- /** True when `rest` already carries a `--filter` / `--filter=…` flag. */
16
- export function hasFilterFlag(rest) {
17
- return rest.some((a) => a === '--filter' || a.startsWith('--filter='));
18
- }
19
- /** True when `rest` already carries `--active`. */
20
- export function hasActiveFlag(rest) {
21
- return rest.some((a) => a === '--active');
22
- }
23
- /**
24
- * Expand an observe alias + remaining user args into the real command argv.
25
- * Returns null when `alias` is not an observe alias.
26
- */
27
- export function expandObserveAlias(alias, rest = []) {
28
- const tail = [...rest];
29
- switch (alias) {
30
- case 'inbox':
31
- return {
32
- argv: ['feed', ...tail],
33
- note: 'agents inbox → agents feed (needs-you inbox)',
34
- };
35
- default:
36
- return null;
37
- }
38
- }
@@ -1,53 +0,0 @@
1
- export type TicketSource = 'linear' | 'github';
2
- export interface TicketComment {
3
- body: string;
4
- createdAt?: string;
5
- author?: string;
6
- }
7
- export interface TicketRow {
8
- id: string;
9
- source: TicketSource;
10
- title: string;
11
- description?: string;
12
- status: 'todo' | 'in_progress' | 'done';
13
- priority?: 'urgent' | 'high' | 'medium' | 'low';
14
- metadata: {
15
- identifier?: string;
16
- url?: string;
17
- labels?: string[];
18
- assignee?: string;
19
- assigneeKind?: 'user' | 'agent';
20
- state?: string;
21
- createdAt?: string;
22
- dueDate?: string;
23
- project?: string;
24
- repo?: string;
25
- comments?: TicketComment[];
26
- images?: string[];
27
- };
28
- }
29
- export interface TicketListResult {
30
- tickets: TicketRow[];
31
- cycleInfo: {
32
- name: string;
33
- startsAt: string;
34
- endsAt: string;
35
- } | null;
36
- sources: {
37
- linear: {
38
- available: boolean;
39
- error?: string;
40
- };
41
- github: {
42
- available: boolean;
43
- error?: string;
44
- };
45
- };
46
- }
47
- export interface TicketListOptions {
48
- cwd: string;
49
- linear: boolean;
50
- github: boolean;
51
- githubAssignedOnly: boolean;
52
- }
53
- export declare function listTickets(options: TicketListOptions): Promise<TicketListResult>;
@@ -1,153 +0,0 @@
1
- import { execFile } from 'node:child_process';
2
- import { promisify } from 'node:util';
3
- const run = promisify(execFile);
4
- const AGENT_ASSIGNEE = /^(claude|codex|gemini|cursor|opencode|antigravity|grok|kimi|droid)$/i;
5
- function assigneeKind(name) {
6
- if (!name)
7
- return undefined;
8
- return AGENT_ASSIGNEE.test(name.trim()) ? 'agent' : 'user';
9
- }
10
- function imageUrls(...bodies) {
11
- const urls = new Set();
12
- const pattern = /!\[[^\]]*\]\(\s*(https?:\/\/[^)\s]+)|<img\b[^>]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+)/gi;
13
- for (const body of bodies) {
14
- if (typeof body !== 'string')
15
- continue;
16
- let match;
17
- while ((match = pattern.exec(body)))
18
- urls.add(match[1] || match[2]);
19
- }
20
- return urls.size > 0 ? [...urls] : undefined;
21
- }
22
- function errorMessage(error) {
23
- if (error instanceof Error)
24
- return error.message;
25
- return String(error);
26
- }
27
- async function readLinear(cwd) {
28
- const { stdout } = await run('linear', ['tasks', '--json'], {
29
- cwd,
30
- timeout: 15_000,
31
- maxBuffer: 16 * 1024 * 1024,
32
- });
33
- const data = JSON.parse(stdout);
34
- const cycle = data?.cycle;
35
- const cycleInfo = cycle?.startsAt && cycle?.endsAt
36
- ? { name: String(cycle.name ?? ''), startsAt: String(cycle.startsAt), endsAt: String(cycle.endsAt) }
37
- : null;
38
- const priority = {
39
- 1: 'urgent',
40
- 2: 'high',
41
- 3: 'medium',
42
- 4: 'low',
43
- };
44
- const tickets = (Array.isArray(data?.issues) ? data.issues : []).map((issue) => {
45
- const labels = (issue.labels?.nodes ?? []).map((label) => String(label.name));
46
- const comments = (issue.comments?.nodes ?? []).map((comment) => ({
47
- body: String(comment.body ?? ''),
48
- createdAt: comment.createdAt ? String(comment.createdAt) : undefined,
49
- author: comment.user?.name ? String(comment.user.name) : undefined,
50
- }));
51
- const stateType = String(issue.state?.type ?? '');
52
- const status = stateType === 'started'
53
- ? 'in_progress'
54
- : stateType === 'completed' || stateType === 'canceled'
55
- ? 'done'
56
- : 'todo';
57
- const identifier = String(issue.identifier ?? issue.id ?? '');
58
- return {
59
- id: `linear:${identifier}`,
60
- source: 'linear',
61
- title: String(issue.title ?? ''),
62
- description: issue.description ? String(issue.description) : undefined,
63
- status,
64
- priority: priority[Number(issue.priority)],
65
- metadata: {
66
- identifier,
67
- url: issue.url ? String(issue.url) : undefined,
68
- labels,
69
- assignee: issue.assignee?.name ? String(issue.assignee.name) : undefined,
70
- assigneeKind: assigneeKind(issue.assignee?.name),
71
- state: issue.state?.name ? String(issue.state.name) : undefined,
72
- createdAt: issue.createdAt ? String(issue.createdAt) : undefined,
73
- dueDate: issue.dueDate ? String(issue.dueDate) : undefined,
74
- project: issue.project?.name ? String(issue.project.name) : undefined,
75
- comments,
76
- images: imageUrls(issue.description, ...comments.map(comment => comment.body)),
77
- },
78
- };
79
- });
80
- return { tickets, cycleInfo };
81
- }
82
- async function readGithub(cwd, assignedOnly) {
83
- const repo = (await run('gh', ['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner'], {
84
- cwd,
85
- timeout: 5_000,
86
- })).stdout.trim();
87
- if (!repo)
88
- throw new Error('No GitHub repository resolved for this workspace.');
89
- const args = [
90
- 'issue', 'list', '--repo', repo, '--state', 'open', '--limit', '50',
91
- '--json', 'number,title,state,labels,assignees,url,body,createdAt',
92
- ];
93
- if (assignedOnly)
94
- args.push('--assignee', '@me');
95
- const { stdout } = await run('gh', args, { cwd, timeout: 15_000, maxBuffer: 16 * 1024 * 1024 });
96
- const issues = JSON.parse(stdout);
97
- return issues.map((issue) => {
98
- const assignee = issue.assignees?.[0]?.login ? String(issue.assignees[0].login) : undefined;
99
- const number = Number(issue.number);
100
- return {
101
- id: `github:${number}`,
102
- source: 'github',
103
- title: String(issue.title ?? ''),
104
- description: issue.body ? String(issue.body) : undefined,
105
- status: String(issue.state ?? '').toLowerCase() === 'closed' ? 'done' : 'todo',
106
- metadata: {
107
- identifier: `#${number}`,
108
- url: issue.url ? String(issue.url) : undefined,
109
- labels: (issue.labels ?? []).map((label) => String(label.name)),
110
- assignee,
111
- assigneeKind: assigneeKind(assignee),
112
- state: String(issue.state ?? '').toLowerCase(),
113
- createdAt: issue.createdAt ? String(issue.createdAt) : undefined,
114
- repo,
115
- images: imageUrls(issue.body),
116
- },
117
- };
118
- });
119
- }
120
- export async function listTickets(options) {
121
- const result = {
122
- tickets: [],
123
- cycleInfo: null,
124
- sources: {
125
- linear: { available: false },
126
- github: { available: false },
127
- },
128
- };
129
- const [linear, github] = await Promise.all([
130
- options.linear
131
- ? readLinear(options.cwd).then(value => ({ ok: true, value })).catch(error => ({ ok: false, error }))
132
- : Promise.resolve(null),
133
- options.github
134
- ? readGithub(options.cwd, options.githubAssignedOnly).then(value => ({ ok: true, value })).catch(error => ({ ok: false, error }))
135
- : Promise.resolve(null),
136
- ]);
137
- if (linear?.ok) {
138
- result.sources.linear.available = true;
139
- result.tickets.push(...linear.value.tickets);
140
- result.cycleInfo = linear.value.cycleInfo;
141
- }
142
- else if (linear) {
143
- result.sources.linear.error = errorMessage(linear.error);
144
- }
145
- if (github?.ok) {
146
- result.sources.github.available = true;
147
- result.tickets.push(...github.value);
148
- }
149
- else if (github) {
150
- result.sources.github.error = errorMessage(github.error);
151
- }
152
- return result;
153
- }