@neotx/cli 0.1.0-alpha.2 → 0.1.0-alpha.20

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 (60) hide show
  1. package/README.md +383 -0
  2. package/dist/activity-LWUVGQVN.js +86 -0
  3. package/dist/activity-LWUVGQVN.js.map +1 -0
  4. package/dist/{agents-Y6LREFXP.js → agents-PH3P7G7E.js} +2 -2
  5. package/dist/{chunk-CP54H7WA.js → chunk-3ZP3BQXB.js} +6 -11
  6. package/dist/chunk-3ZP3BQXB.js.map +1 -0
  7. package/dist/{chunk-TNJOG54I.js → chunk-F622JUDY.js} +6 -2
  8. package/dist/{chunk-TNJOG54I.js.map → chunk-F622JUDY.js.map} +1 -1
  9. package/dist/config-NYF6AJXU.js +282 -0
  10. package/dist/config-NYF6AJXU.js.map +1 -0
  11. package/dist/{cost-DNGKT4UC.js → cost-OQGFNBBG.js} +3 -8
  12. package/dist/cost-OQGFNBBG.js.map +1 -0
  13. package/dist/daemon/supervisor-worker.js +7 -1
  14. package/dist/daemon/supervisor-worker.js.map +1 -1
  15. package/dist/daemon/worker.js +27 -10
  16. package/dist/daemon/worker.js.map +1 -1
  17. package/dist/decision-PNZ2S2TU.js +362 -0
  18. package/dist/decision-PNZ2S2TU.js.map +1 -0
  19. package/dist/doctor-ZBO73UID.js +337 -0
  20. package/dist/doctor-ZBO73UID.js.map +1 -0
  21. package/dist/guide-UQRNA3FC.js +23 -0
  22. package/dist/guide-UQRNA3FC.js.map +1 -0
  23. package/dist/index.js +17 -9
  24. package/dist/index.js.map +1 -1
  25. package/dist/{init-YNSPTCA3.js → init-UYS6KS5U.js} +4 -20
  26. package/dist/init-UYS6KS5U.js.map +1 -0
  27. package/dist/log-PTHLI7ZN.js +141 -0
  28. package/dist/log-PTHLI7ZN.js.map +1 -0
  29. package/dist/{mcp-GH6CCW7A.js → mcp-XHZND5A4.js} +6 -1
  30. package/dist/mcp-XHZND5A4.js.map +1 -0
  31. package/dist/memory-6R22DFS7.js +292 -0
  32. package/dist/memory-6R22DFS7.js.map +1 -0
  33. package/dist/{run-KIU2ZE72.js → run-OF53USMD.js} +46 -20
  34. package/dist/run-OF53USMD.js.map +1 -0
  35. package/dist/{runs-CHA2JM5K.js → runs-TAASM3YF.js} +16 -12
  36. package/dist/runs-TAASM3YF.js.map +1 -0
  37. package/dist/status-LQOFOJJI.js +90 -0
  38. package/dist/status-LQOFOJJI.js.map +1 -0
  39. package/dist/{supervise-KIB2EYY4.js → supervise-FI6MYULH.js} +33 -28
  40. package/dist/supervise-FI6MYULH.js.map +1 -0
  41. package/dist/supervisor-3RUX5SPH.js +16 -0
  42. package/dist/supervisor-3RUX5SPH.js.map +1 -0
  43. package/dist/{tui-QS3RPHKH.js → tui-JJ6CD2YW.js} +377 -43
  44. package/dist/tui-JJ6CD2YW.js.map +1 -0
  45. package/dist/version-XVOAMGDD.js +26 -0
  46. package/dist/version-XVOAMGDD.js.map +1 -0
  47. package/dist/webhooks-PUKAHFHE.js +151 -0
  48. package/dist/webhooks-PUKAHFHE.js.map +1 -0
  49. package/package.json +22 -4
  50. package/dist/chunk-CP54H7WA.js.map +0 -1
  51. package/dist/cost-DNGKT4UC.js.map +0 -1
  52. package/dist/doctor-GC4NH7H6.js +0 -173
  53. package/dist/doctor-GC4NH7H6.js.map +0 -1
  54. package/dist/init-YNSPTCA3.js.map +0 -1
  55. package/dist/mcp-GH6CCW7A.js.map +0 -1
  56. package/dist/run-KIU2ZE72.js.map +0 -1
  57. package/dist/runs-CHA2JM5K.js.map +0 -1
  58. package/dist/supervise-KIB2EYY4.js.map +0 -1
  59. package/dist/tui-QS3RPHKH.js.map +0 -1
  60. /package/dist/{agents-Y6LREFXP.js.map → agents-PH3P7G7E.js.map} +0 -0
package/README.md ADDED
@@ -0,0 +1,383 @@
1
+ # @neotx/cli
2
+
3
+ The `neo` command-line interface for orchestrating autonomous developer agents. This thin wrapper over `@neotx/core` provides a user-friendly CLI for dispatching agents, monitoring runs, managing costs, and running the supervisor daemon.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @neotx/cli
9
+ ```
10
+
11
+ Or with pnpm:
12
+
13
+ ```bash
14
+ pnpm add -g @neotx/cli
15
+ ```
16
+
17
+ Requires Node.js 22 or later.
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ # Initialize a repository for neo
23
+ neo init
24
+
25
+ # Check your environment
26
+ neo doctor
27
+
28
+ # Run an agent
29
+ neo run developer --prompt "Add input validation to the login form"
30
+
31
+ # Watch a detached run
32
+ neo logs -f --run <run-id>
33
+
34
+ # Start the supervisor daemon
35
+ neo supervise
36
+ ```
37
+
38
+ ## Commands
39
+
40
+ ### `neo init`
41
+
42
+ Initialize a `.neo/` project directory and register the repo in your global config.
43
+
44
+ ```bash
45
+ neo init
46
+ neo init --force # Re-register even if already initialized
47
+ ```
48
+
49
+ Creates:
50
+ - `.neo/agents/` directory for project-local agent definitions
51
+ - Registers the repo in global config
52
+ - Registers the repo in `~/.neo/config.yml`
53
+
54
+ ### `neo run <agent>`
55
+
56
+ Dispatch an agent to execute a task in an isolated clone.
57
+
58
+ ```bash
59
+ neo run developer --prompt "Implement user authentication"
60
+ neo run architect --prompt "Design the caching layer" --repo /path/to/repo
61
+ neo run reviewer --prompt "Review the auth changes" --priority high
62
+ ```
63
+
64
+ **Arguments:**
65
+ - `<agent>` - Agent name (e.g., `developer`, `architect`, `reviewer`)
66
+
67
+ **Options:**
68
+ | Flag | Description |
69
+ |------|-------------|
70
+ | `--prompt` | Task description for the agent (required) |
71
+ | `--repo` | Target repository path (default: `.`) |
72
+ | `--priority` | Priority level: `critical`, `high`, `medium`, `low` |
73
+ | `--meta` | Metadata as JSON string |
74
+ | `--output json` | Output as JSON |
75
+ | `-d, --detach` | Run in background (default: `true`) |
76
+ | `-s, --sync` | Run in foreground (blocking) |
77
+
78
+ By default, runs are **detached** — the command returns immediately with a run ID while the agent works in the background. Use `--sync` to run in the foreground.
79
+
80
+ ```bash
81
+ # Detached (default) - returns immediately
82
+ neo run developer --prompt "Fix the login bug"
83
+ # Output: Detached run started: abc123...
84
+ # Logs: neo logs -f abc123
85
+
86
+ # Foreground - blocks until complete
87
+ neo run developer --prompt "Fix the login bug" --sync
88
+ ```
89
+
90
+ ### `neo runs [run-id]`
91
+
92
+ List runs or show details of a specific run.
93
+
94
+ ```bash
95
+ neo runs # List recent runs
96
+ neo runs abc123 # Show details for run abc123 (prefix match works)
97
+ neo runs --all # Show runs from all repos
98
+ neo runs --repo my-project # Filter by repo
99
+ neo runs --last 10 # Show only the last 10 runs
100
+ neo runs --status running # Filter by status
101
+ neo runs --output json # Output as JSON
102
+ neo runs --short # Compact output (useful for scripts)
103
+ ```
104
+
105
+ **Options:**
106
+ | Flag | Description |
107
+ |------|-------------|
108
+ | `--all` | Show runs from all repos |
109
+ | `--repo` | Filter by repo name or path |
110
+ | `--last` | Show only the last N runs |
111
+ | `--status` | Filter: `completed`, `failed`, `running` |
112
+ | `--short` | Compact output |
113
+ | `--output json` | Output as JSON |
114
+
115
+ ### `neo logs`
116
+
117
+ Show event logs from journals (session starts, completions, failures, costs).
118
+
119
+ ```bash
120
+ neo logs # Show last 20 events
121
+ neo logs --last 50 # Show last 50 events
122
+ neo logs --type session:complete # Filter by event type
123
+ neo logs --run abc123 # Filter by run ID (prefix match)
124
+ neo logs -f --run abc123 # Follow a detached run's log in real time
125
+ neo logs --output json # Output as JSON
126
+ ```
127
+
128
+ **Options:**
129
+ | Flag | Description |
130
+ |------|-------------|
131
+ | `--last` | Number of events to show (default: 20) |
132
+ | `--type` | Filter: `session:start`, `session:complete`, `session:fail`, `cost:update`, `budget:alert` |
133
+ | `--run` | Filter by run ID (prefix match) |
134
+ | `-f, --follow` | Follow a detached run log in real time (requires `--run`) |
135
+ | `--short` | Compact output |
136
+ | `--output json` | Output as JSON |
137
+
138
+ ### `neo log <type> <message>`
139
+
140
+ Log a structured progress report to the supervisor activity log.
141
+
142
+ ```bash
143
+ neo log progress "3/5 endpoints done"
144
+ neo log action "Pushed to branch"
145
+ neo log decision "Chose JWT over sessions — simpler for MVP"
146
+ neo log blocker "Tests failing, missing dependency"
147
+ neo log milestone "All tests passing, PR opened"
148
+ neo log discovery "Repo uses Prisma + PostgreSQL"
149
+ ```
150
+
151
+ **Arguments:**
152
+ - `<type>` - Report type: `progress`, `action`, `decision`, `blocker`, `milestone`, `discovery`
153
+ - `<message>` - Message to log
154
+
155
+ **Options:**
156
+ | Flag | Description |
157
+ |------|-------------|
158
+ | `--name` | Supervisor instance name (default: `supervisor`) |
159
+
160
+ ### `neo cost`
161
+
162
+ Show cost breakdown from journals (today, by agent, by run).
163
+
164
+ ```bash
165
+ neo cost # Show costs for current repo
166
+ neo cost --all # Show costs from all repos
167
+ neo cost --repo my-app # Filter by repo
168
+ neo cost --short # Compact output
169
+ neo cost --output json # Output as JSON
170
+ ```
171
+
172
+ **Options:**
173
+ | Flag | Description |
174
+ |------|-------------|
175
+ | `--all` | Show costs from all repos |
176
+ | `--repo` | Filter by repo name or path |
177
+ | `--short` | Compact output |
178
+ | `--output json` | Output as JSON |
179
+
180
+ ### `neo agents`
181
+
182
+ List available agents (built-in and custom from `.neo/agents/`).
183
+
184
+ ```bash
185
+ neo agents # List all agents
186
+ neo agents --output json
187
+ ```
188
+
189
+ Shows agent name, model, sandbox mode, and source (built-in or custom).
190
+
191
+ ### `neo repos [action] [target]`
192
+
193
+ Manage registered repositories.
194
+
195
+ ```bash
196
+ neo repos # List registered repos
197
+ neo repos add /path/to/repo # Add a repo
198
+ neo repos add . --name my-project # Add with custom name
199
+ neo repos add . --branch develop # Add with specific default branch
200
+ neo repos remove my-project # Remove by name or path
201
+ neo repos --output json # Output as JSON
202
+ ```
203
+
204
+ **Actions:**
205
+ - `add` - Register a repository
206
+ - `remove` - Unregister a repository
207
+ - (omit) - List all registered repos
208
+
209
+ **Options for `add`:**
210
+ | Flag | Description |
211
+ |------|-------------|
212
+ | `--name` | Custom name for the repo |
213
+ | `--branch` | Default branch (auto-detected if omitted) |
214
+
215
+ ### `neo supervise`
216
+
217
+ Manage the autonomous supervisor daemon.
218
+
219
+ ```bash
220
+ neo supervise # Start daemon + open TUI (default)
221
+ neo supervise -d # Start daemon headless (no TUI)
222
+ neo supervise --status # Show supervisor status
223
+ neo supervise --kill # Stop the running supervisor
224
+ neo supervise --message "Focus on the auth module" # Send a message
225
+ neo supervise --name prod # Use a named instance
226
+ ```
227
+
228
+ **Options:**
229
+ | Flag | Description |
230
+ |------|-------------|
231
+ | `--name` | Supervisor instance name (default: `supervisor`) |
232
+ | `-d, --detach` | Start daemon without opening the TUI |
233
+ | `--status` | Show supervisor status |
234
+ | `--kill` | Stop the running supervisor |
235
+ | `--attach` | Open the TUI (same as default, explicit flag) |
236
+ | `--message` | Send a message to the supervisor inbox |
237
+
238
+ By default, `neo supervise` starts the daemon (if not running) and opens the TUI. If the daemon is already running, it opens the TUI directly. Use `-d` for headless mode.
239
+
240
+ #### Supervisor TUI
241
+
242
+ The TUI provides a live dashboard for monitoring the supervisor:
243
+
244
+ - **Header**: PID, port, heartbeat count, uptime, live status
245
+ - **Budget panel**: Real-time cost tracking with progress bar and sparkline
246
+ - **Activity feed**: Live stream of supervisor actions, decisions, and events
247
+ - **Input**: Send messages to the supervisor
248
+
249
+ **Controls:**
250
+ - `Enter` - Send message
251
+ - `Esc` - Quit TUI (daemon keeps running)
252
+
253
+ ### `neo mcp <action>`
254
+
255
+ Manage MCP (Model Context Protocol) server integrations.
256
+
257
+ ```bash
258
+ neo mcp list # List configured MCP servers
259
+ neo mcp add linear # Add using a preset
260
+ neo mcp add github # Add GitHub integration
261
+ neo mcp add custom --type stdio --command "node" --serverArgs "server.js"
262
+ neo mcp add api --type http --url "https://api.example.com/mcp"
263
+ neo mcp remove linear # Remove an MCP server
264
+ ```
265
+
266
+ **Available presets:**
267
+ - `linear` - Linear issue tracking (requires `LINEAR_API_KEY`)
268
+ - `notion` - Notion workspace (requires `NOTION_TOKEN`)
269
+ - `github` - GitHub repositories (requires `GITHUB_TOKEN`)
270
+ - `jira` - Jira projects (requires `JIRA_API_TOKEN`, `JIRA_URL`)
271
+ - `slack` - Slack workspace (requires `SLACK_BOT_TOKEN`)
272
+
273
+ **Custom server options:**
274
+ | Flag | Description |
275
+ |------|-------------|
276
+ | `--type` | Server type: `stdio` or `http` |
277
+ | `--command` | Command for stdio servers |
278
+ | `--serverArgs` | Comma-separated args for stdio servers |
279
+ | `--url` | URL for http servers |
280
+
281
+ ### `neo doctor`
282
+
283
+ Check environment prerequisites and configuration.
284
+
285
+ ```bash
286
+ neo doctor
287
+ neo doctor --output json
288
+ ```
289
+
290
+ Checks:
291
+ - Node.js version (requires >= 22)
292
+ - Git version (requires >= 2.20)
293
+ - Global config validity
294
+ - Repo registration status
295
+ - Claude CLI installation
296
+ - Agent definitions
297
+ - Journal directory permissions
298
+
299
+ ## Detached Runs
300
+
301
+ By default, `neo run` executes agents in **detached mode**:
302
+
303
+ ```bash
304
+ neo run developer --prompt "Add tests for the API"
305
+ # ✓ Detached run started: eeb76521-e806-46cd-8451-87490cfe7281
306
+ # PID: 12345
307
+ # Logs: neo logs -f eeb76521
308
+ ```
309
+
310
+ The agent runs in a background process while you continue working. To monitor:
311
+
312
+ ```bash
313
+ # Follow logs in real time
314
+ neo logs -f --run eeb76521
315
+
316
+ # Check run status
317
+ neo runs eeb76521
318
+
319
+ # List all running
320
+ neo runs --status running
321
+ ```
322
+
323
+ For blocking execution, use `--sync`:
324
+
325
+ ```bash
326
+ neo run developer --prompt "Quick fix" --sync
327
+ # Blocks until complete, shows progress inline
328
+ ```
329
+
330
+ ## JSON Output
331
+
332
+ All commands support `--output json` for scripting and automation:
333
+
334
+ ```bash
335
+ neo runs --output json | jq '.[] | select(.status == "failed")'
336
+ neo cost --output json | jq '.today.total'
337
+ neo agents --output json | jq '.[].name'
338
+ neo doctor --output json | jq '.checks[] | select(.status == "fail")'
339
+ ```
340
+
341
+ ## Global Configuration
342
+
343
+ Neo stores global configuration in `~/.neo/config.yml`:
344
+
345
+ ```yaml
346
+ budget:
347
+ dailyCapUsd: 50
348
+
349
+ repos:
350
+ - path: /Users/you/projects/my-app
351
+ defaultBranch: main
352
+
353
+ supervisor:
354
+ port: 7420
355
+ idleIntervalMs: 60000
356
+ idleSkipMax: 5
357
+
358
+ mcpServers:
359
+ linear:
360
+ type: stdio
361
+ command: npx
362
+ args: ["-y", "@anthropic/linear-mcp-server"]
363
+ env:
364
+ LINEAR_API_KEY: "${LINEAR_API_KEY}"
365
+ ```
366
+
367
+ Run `neo init` or `neo repos add` to register repositories. The config is auto-created with defaults if missing.
368
+
369
+ ## Project-Local Agents
370
+
371
+ Define custom agents in `.neo/agents/` within your repository:
372
+
373
+ ```
374
+ .neo/
375
+ agents/
376
+ my-custom-agent.yml
377
+ ```
378
+
379
+ These are loaded alongside built-in agents and can be used with `neo run my-custom-agent`.
380
+
381
+ ## License
382
+
383
+ MIT
@@ -0,0 +1,86 @@
1
+ import {
2
+ printError,
3
+ printJson,
4
+ printTable
5
+ } from "./chunk-YQIWMDXL.js";
6
+
7
+ // src/commands/supervisor/activity.ts
8
+ import { getSupervisorDir, StatusReader } from "@neotx/core";
9
+ import { defineCommand } from "citty";
10
+ var DEFAULT_NAME = "supervisor";
11
+ var DEFAULT_LIMIT = 50;
12
+ function formatTimestamp(iso) {
13
+ const date = new Date(iso);
14
+ const pad = (n) => n.toString().padStart(2, "0");
15
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
16
+ }
17
+ function formatActivityTable(entries) {
18
+ const headers = ["Timestamp", "Type", "Summary"];
19
+ const rows = entries.map((e) => [formatTimestamp(e.timestamp), e.type, e.summary]);
20
+ printTable(headers, rows);
21
+ }
22
+ var activity_default = defineCommand({
23
+ meta: {
24
+ name: "activity",
25
+ description: "Show supervisor activity log"
26
+ },
27
+ args: {
28
+ name: {
29
+ type: "string",
30
+ description: "Supervisor instance name",
31
+ default: DEFAULT_NAME
32
+ },
33
+ type: {
34
+ type: "string",
35
+ description: "Filter by activity type (decision, action, error, event, message, plan, dispatch)"
36
+ },
37
+ since: {
38
+ type: "string",
39
+ description: "Show activity since this ISO timestamp"
40
+ },
41
+ until: {
42
+ type: "string",
43
+ description: "Show activity until this ISO timestamp"
44
+ },
45
+ limit: {
46
+ type: "string",
47
+ description: "Maximum number of entries to show",
48
+ default: String(DEFAULT_LIMIT)
49
+ },
50
+ json: {
51
+ type: "boolean",
52
+ description: "Output as JSON",
53
+ default: false
54
+ }
55
+ },
56
+ async run({ args }) {
57
+ const name = args.name;
58
+ const dataDir = getSupervisorDir(name);
59
+ const reader = new StatusReader(dataDir);
60
+ const limit = Number.parseInt(args.limit, 10) || DEFAULT_LIMIT;
61
+ const type = args.type;
62
+ const entries = reader.queryActivity({
63
+ type,
64
+ since: args.since,
65
+ until: args.until,
66
+ limit
67
+ });
68
+ if (entries.length === 0) {
69
+ if (args.json) {
70
+ printJson([]);
71
+ return;
72
+ }
73
+ printError("No activity found");
74
+ return;
75
+ }
76
+ if (args.json) {
77
+ printJson(entries);
78
+ return;
79
+ }
80
+ formatActivityTable(entries);
81
+ }
82
+ });
83
+ export {
84
+ activity_default as default
85
+ };
86
+ //# sourceMappingURL=activity-LWUVGQVN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/supervisor/activity.ts"],"sourcesContent":["import { type ActivityEntry, getSupervisorDir, StatusReader } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printJson, printTable } from \"../../output.js\";\n\nconst DEFAULT_NAME = \"supervisor\";\nconst DEFAULT_LIMIT = 50;\n\nfunction formatTimestamp(iso: string): string {\n const date = new Date(iso);\n const pad = (n: number) => n.toString().padStart(2, \"0\");\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;\n}\n\nfunction formatActivityTable(entries: ActivityEntry[]): void {\n const headers = [\"Timestamp\", \"Type\", \"Summary\"];\n const rows = entries.map((e) => [formatTimestamp(e.timestamp), e.type, e.summary]);\n printTable(headers, rows);\n}\n\nexport default defineCommand({\n meta: {\n name: \"activity\",\n description: \"Show supervisor activity log\",\n },\n args: {\n name: {\n type: \"string\",\n description: \"Supervisor instance name\",\n default: DEFAULT_NAME,\n },\n type: {\n type: \"string\",\n description:\n \"Filter by activity type (decision, action, error, event, message, plan, dispatch)\",\n },\n since: {\n type: \"string\",\n description: \"Show activity since this ISO timestamp\",\n },\n until: {\n type: \"string\",\n description: \"Show activity until this ISO timestamp\",\n },\n limit: {\n type: \"string\",\n description: \"Maximum number of entries to show\",\n default: String(DEFAULT_LIMIT),\n },\n json: {\n type: \"boolean\",\n description: \"Output as JSON\",\n default: false,\n },\n },\n async run({ args }) {\n const name = args.name;\n const dataDir = getSupervisorDir(name);\n const reader = new StatusReader(dataDir);\n\n const limit = Number.parseInt(args.limit, 10) || DEFAULT_LIMIT;\n const type = args.type as\n | \"decision\"\n | \"action\"\n | \"error\"\n | \"event\"\n | \"message\"\n | \"plan\"\n | \"dispatch\"\n | undefined;\n\n const entries = reader.queryActivity({\n type,\n since: args.since,\n until: args.until,\n limit,\n });\n\n if (entries.length === 0) {\n if (args.json) {\n printJson([]);\n return;\n }\n printError(\"No activity found\");\n return;\n }\n\n if (args.json) {\n printJson(entries);\n return;\n }\n\n formatActivityTable(entries);\n },\n});\n"],"mappings":";;;;;;;AAAA,SAA6B,kBAAkB,oBAAoB;AACnE,SAAS,qBAAqB;AAG9B,IAAM,eAAe;AACrB,IAAM,gBAAgB;AAEtB,SAAS,gBAAgB,KAAqB;AAC5C,QAAM,OAAO,IAAI,KAAK,GAAG;AACzB,QAAM,MAAM,CAAC,MAAc,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AACvD,SAAO,GAAG,KAAK,YAAY,CAAC,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,IAAI,IAAI,KAAK,WAAW,CAAC,CAAC,IAAI,IAAI,KAAK,WAAW,CAAC,CAAC;AAC7J;AAEA,SAAS,oBAAoB,SAAgC;AAC3D,QAAM,UAAU,CAAC,aAAa,QAAQ,SAAS;AAC/C,QAAM,OAAO,QAAQ,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,SAAS,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC;AACjF,aAAW,SAAS,IAAI;AAC1B;AAEA,IAAO,mBAAQ,cAAc;AAAA,EAC3B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS,OAAO,aAAa;AAAA,IAC/B;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,MAAM,IAAI,EAAE,KAAK,GAAG;AAClB,UAAM,OAAO,KAAK;AAClB,UAAM,UAAU,iBAAiB,IAAI;AACrC,UAAM,SAAS,IAAI,aAAa,OAAO;AAEvC,UAAM,QAAQ,OAAO,SAAS,KAAK,OAAO,EAAE,KAAK;AACjD,UAAM,OAAO,KAAK;AAUlB,UAAM,UAAU,OAAO,cAAc;AAAA,MACnC;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ;AAAA,IACF,CAAC;AAED,QAAI,QAAQ,WAAW,GAAG;AACxB,UAAI,KAAK,MAAM;AACb,kBAAU,CAAC,CAAC;AACZ;AAAA,MACF;AACA,iBAAW,mBAAmB;AAC9B;AAAA,IACF;AAEA,QAAI,KAAK,MAAM;AACb,gBAAU,OAAO;AACjB;AAAA,IACF;AAEA,wBAAoB,OAAO;AAAA,EAC7B;AACF,CAAC;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveAgentsDir
3
- } from "./chunk-TNJOG54I.js";
3
+ } from "./chunk-F622JUDY.js";
4
4
  import {
5
5
  printError,
6
6
  printJson,
@@ -55,4 +55,4 @@ var agents_default = defineCommand({
55
55
  export {
56
56
  agents_default as default
57
57
  };
58
- //# sourceMappingURL=agents-Y6LREFXP.js.map
58
+ //# sourceMappingURL=agents-PH3P7G7E.js.map
@@ -4,23 +4,18 @@ import { readdir, readFile } from "fs/promises";
4
4
  import path from "path";
5
5
  import { getRunsDir, listReposFromGlobalConfig, toRepoSlug } from "@neotx/core";
6
6
  async function resolveRepoFilter(args) {
7
- if (args.all) return { mode: "all" };
8
7
  if (args.repo) {
9
8
  const repo = args.repo;
10
- const repos2 = await listReposFromGlobalConfig();
11
- const match2 = repos2.find(
9
+ const repos = await listReposFromGlobalConfig();
10
+ const match = repos.find(
12
11
  (r) => toRepoSlug(r) === repo || path.resolve(r.path) === path.resolve(repo)
13
12
  );
14
- if (match2) {
15
- return { mode: "named", repoSlug: toRepoSlug(match2), repoPath: match2.path };
13
+ if (match) {
14
+ return { mode: "named", repoSlug: toRepoSlug(match), repoPath: match.path };
16
15
  }
17
16
  return { mode: "named", repoSlug: toRepoSlug({ path: repo }), repoPath: repo };
18
17
  }
19
- const cwd = process.cwd();
20
- const repos = await listReposFromGlobalConfig();
21
- const match = repos.find((r) => path.resolve(r.path) === cwd);
22
- const slug = match ? toRepoSlug(match) : toRepoSlug({ path: cwd });
23
- return { mode: "cwd", repoSlug: slug, repoPath: cwd };
18
+ return { mode: "all" };
24
19
  }
25
20
  async function loadRunsFiltered(filter) {
26
21
  const runsDir = getRunsDir();
@@ -82,4 +77,4 @@ export {
82
77
  resolveRepoFilter,
83
78
  loadRunsFiltered
84
79
  };
85
- //# sourceMappingURL=chunk-CP54H7WA.js.map
80
+ //# sourceMappingURL=chunk-3ZP3BQXB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/repo-filter.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { PersistedRun } from \"@neotx/core\";\nimport { getRunsDir, listReposFromGlobalConfig, toRepoSlug } from \"@neotx/core\";\n\nexport interface RepoFilter {\n mode: \"all\" | \"named\";\n repoSlug?: string;\n repoPath?: string;\n}\n\n/**\n * Resolve which repos to query based on --repo flag.\n * Default: show all repos (global view).\n */\nexport async function resolveRepoFilter(args: { repo?: string | undefined }): Promise<RepoFilter> {\n if (args.repo) {\n const repo = args.repo;\n // Could be a name/slug or a path\n const repos = await listReposFromGlobalConfig();\n const match = repos.find(\n (r) => toRepoSlug(r) === repo || path.resolve(r.path) === path.resolve(repo),\n );\n if (match) {\n return { mode: \"named\", repoSlug: toRepoSlug(match), repoPath: match.path };\n }\n // Treat as path, derive slug\n return { mode: \"named\", repoSlug: toRepoSlug({ path: repo }), repoPath: repo };\n }\n\n // Default: show all runs globally\n // Users can filter by repo explicitly with --repo\n return { mode: \"all\" };\n}\n\n/**\n * Load persisted runs, filtered by RepoFilter.\n */\nexport async function loadRunsFiltered(filter: RepoFilter): Promise<PersistedRun[]> {\n const runsDir = getRunsDir();\n if (!existsSync(runsDir)) return [];\n\n const runs: PersistedRun[] = [];\n\n if (filter.mode === \"all\") {\n // Scan all slug subdirs + legacy flat files\n const entries = await readdir(runsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n await loadRunsFromDir(path.join(runsDir, entry.name), runs);\n } else if (entry.name.endsWith(\".json\")) {\n await loadRunFile(path.join(runsDir, entry.name), runs);\n }\n }\n } else {\n // Specific slug dir\n const slugDir = path.join(runsDir, filter.repoSlug ?? \"unknown\");\n await loadRunsFromDir(slugDir, runs);\n // Also check legacy flat files matching this repo\n await loadLegacyRuns(runsDir, filter.repoPath, runs);\n }\n\n runs.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n return runs;\n}\n\nasync function loadRunsFromDir(dir: string, runs: PersistedRun[]): Promise<void> {\n if (!existsSync(dir)) return;\n const files = await readdir(dir);\n for (const file of files) {\n if (!file.endsWith(\".json\")) continue;\n await loadRunFile(path.join(dir, file), runs);\n }\n}\n\nasync function loadRunFile(filePath: string, runs: PersistedRun[]): Promise<void> {\n try {\n const content = await readFile(filePath, \"utf-8\");\n runs.push(JSON.parse(content) as PersistedRun);\n } catch {\n // Skip corrupt files\n }\n}\n\nasync function loadLegacyRuns(\n runsDir: string,\n repoPath: string | undefined,\n runs: PersistedRun[],\n): Promise<void> {\n if (!repoPath) return;\n const resolvedRepo = path.resolve(repoPath);\n\n try {\n const entries = await readdir(runsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith(\".json\")) continue;\n const filePath = path.join(runsDir, entry.name);\n const content = await readFile(filePath, \"utf-8\");\n const run = JSON.parse(content) as PersistedRun;\n if (path.resolve(run.repo) === resolvedRepo) {\n // Avoid duplicates\n if (!runs.some((r) => r.runId === run.runId)) {\n runs.push(run);\n }\n }\n }\n } catch {\n // Non-critical\n }\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAC3B,SAAS,SAAS,gBAAgB;AAClC,OAAO,UAAU;AAEjB,SAAS,YAAY,2BAA2B,kBAAkB;AAYlE,eAAsB,kBAAkB,MAA0D;AAChG,MAAI,KAAK,MAAM;AACb,UAAM,OAAO,KAAK;AAElB,UAAM,QAAQ,MAAM,0BAA0B;AAC9C,UAAM,QAAQ,MAAM;AAAA,MAClB,CAAC,MAAM,WAAW,CAAC,MAAM,QAAQ,KAAK,QAAQ,EAAE,IAAI,MAAM,KAAK,QAAQ,IAAI;AAAA,IAC7E;AACA,QAAI,OAAO;AACT,aAAO,EAAE,MAAM,SAAS,UAAU,WAAW,KAAK,GAAG,UAAU,MAAM,KAAK;AAAA,IAC5E;AAEA,WAAO,EAAE,MAAM,SAAS,UAAU,WAAW,EAAE,MAAM,KAAK,CAAC,GAAG,UAAU,KAAK;AAAA,EAC/E;AAIA,SAAO,EAAE,MAAM,MAAM;AACvB;AAKA,eAAsB,iBAAiB,QAA6C;AAClF,QAAM,UAAU,WAAW;AAC3B,MAAI,CAAC,WAAW,OAAO,EAAG,QAAO,CAAC;AAElC,QAAM,OAAuB,CAAC;AAE9B,MAAI,OAAO,SAAS,OAAO;AAEzB,UAAM,UAAU,MAAM,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;AAC9D,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,YAAY,GAAG;AACvB,cAAM,gBAAgB,KAAK,KAAK,SAAS,MAAM,IAAI,GAAG,IAAI;AAAA,MAC5D,WAAW,MAAM,KAAK,SAAS,OAAO,GAAG;AACvC,cAAM,YAAY,KAAK,KAAK,SAAS,MAAM,IAAI,GAAG,IAAI;AAAA,MACxD;AAAA,IACF;AAAA,EACF,OAAO;AAEL,UAAM,UAAU,KAAK,KAAK,SAAS,OAAO,YAAY,SAAS;AAC/D,UAAM,gBAAgB,SAAS,IAAI;AAEnC,UAAM,eAAe,SAAS,OAAO,UAAU,IAAI;AAAA,EACrD;AAEA,OAAK,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AAC1D,SAAO;AACT;AAEA,eAAe,gBAAgB,KAAa,MAAqC;AAC/E,MAAI,CAAC,WAAW,GAAG,EAAG;AACtB,QAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,KAAK,SAAS,OAAO,EAAG;AAC7B,UAAM,YAAY,KAAK,KAAK,KAAK,IAAI,GAAG,IAAI;AAAA,EAC9C;AACF;AAEA,eAAe,YAAY,UAAkB,MAAqC;AAChF,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,SAAK,KAAK,KAAK,MAAM,OAAO,CAAiB;AAAA,EAC/C,QAAQ;AAAA,EAER;AACF;AAEA,eAAe,eACb,SACA,UACA,MACe;AACf,MAAI,CAAC,SAAU;AACf,QAAM,eAAe,KAAK,QAAQ,QAAQ;AAE1C,MAAI;AACF,UAAM,UAAU,MAAM,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;AAC9D,eAAW,SAAS,SAAS;AAC3B,UAAI,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,OAAO,EAAG;AACtD,YAAM,WAAW,KAAK,KAAK,SAAS,MAAM,IAAI;AAC9C,YAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,YAAM,MAAM,KAAK,MAAM,OAAO;AAC9B,UAAI,KAAK,QAAQ,IAAI,IAAI,MAAM,cAAc;AAE3C,YAAI,CAAC,KAAK,KAAK,CAAC,MAAM,EAAE,UAAU,IAAI,KAAK,GAAG;AAC5C,eAAK,KAAK,GAAG;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;","names":[]}
@@ -9,8 +9,12 @@ function resolvePackageDir(pkg) {
9
9
  function resolveAgentsDir() {
10
10
  return path.join(resolvePackageDir("@neotx/agents"), "agents");
11
11
  }
12
+ function resolveAgentsPackageDir() {
13
+ return resolvePackageDir("@neotx/agents");
14
+ }
12
15
 
13
16
  export {
14
- resolveAgentsDir
17
+ resolveAgentsDir,
18
+ resolveAgentsPackageDir
15
19
  };
16
- //# sourceMappingURL=chunk-TNJOG54I.js.map
20
+ //# sourceMappingURL=chunk-F622JUDY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/resolve.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport path from \"node:path\";\n\nconst require = createRequire(import.meta.url);\n\nfunction resolvePackageDir(pkg: string): string {\n const pkgPath = require.resolve(`${pkg}/package.json`);\n return path.dirname(pkgPath);\n}\n\nexport function resolveAgentsDir(): string {\n return path.join(resolvePackageDir(\"@neotx/agents\"), \"agents\");\n}\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AAEjB,IAAMA,WAAU,cAAc,YAAY,GAAG;AAE7C,SAAS,kBAAkB,KAAqB;AAC9C,QAAM,UAAUA,SAAQ,QAAQ,GAAG,GAAG,eAAe;AACrD,SAAO,KAAK,QAAQ,OAAO;AAC7B;AAEO,SAAS,mBAA2B;AACzC,SAAO,KAAK,KAAK,kBAAkB,eAAe,GAAG,QAAQ;AAC/D;","names":["require"]}
1
+ {"version":3,"sources":["../src/resolve.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport path from \"node:path\";\n\nconst require = createRequire(import.meta.url);\n\nfunction resolvePackageDir(pkg: string): string {\n const pkgPath = require.resolve(`${pkg}/package.json`);\n return path.dirname(pkgPath);\n}\n\nexport function resolveAgentsDir(): string {\n return path.join(resolvePackageDir(\"@neotx/agents\"), \"agents\");\n}\n\nexport function resolveAgentsPackageDir(): string {\n return resolvePackageDir(\"@neotx/agents\");\n}\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AAEjB,IAAMA,WAAU,cAAc,YAAY,GAAG;AAE7C,SAAS,kBAAkB,KAAqB;AAC9C,QAAM,UAAUA,SAAQ,QAAQ,GAAG,GAAG,eAAe;AACrD,SAAO,KAAK,QAAQ,OAAO;AAC7B;AAEO,SAAS,mBAA2B;AACzC,SAAO,KAAK,KAAK,kBAAkB,eAAe,GAAG,QAAQ;AAC/D;AAEO,SAAS,0BAAkC;AAChD,SAAO,kBAAkB,eAAe;AAC1C;","names":["require"]}