@prestyj/cli 4.10.3 → 4.12.0
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.
- package/README.md +4 -4
- package/dist/app-sidecar.d.ts +2 -0
- package/dist/app-sidecar.d.ts.map +1 -0
- package/dist/app-sidecar.js +1720 -0
- package/dist/app-sidecar.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -25
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +162 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +544 -23
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/api-benchmark.d.ts +64 -0
- package/dist/core/api-benchmark.d.ts.map +1 -0
- package/dist/core/api-benchmark.js +381 -0
- package/dist/core/api-benchmark.js.map +1 -0
- package/dist/core/auth-providers.d.ts +18 -0
- package/dist/core/auth-providers.d.ts.map +1 -0
- package/dist/core/auth-providers.js +71 -0
- package/dist/core/auth-providers.js.map +1 -0
- package/dist/core/event-bus.d.ts +6 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +1 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/mcp/client.d.ts +21 -0
- package/dist/core/mcp/client.d.ts.map +1 -1
- package/dist/core/mcp/client.js +167 -5
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/index.d.ts +3 -1
- package/dist/core/mcp/index.d.ts.map +1 -1
- package/dist/core/mcp/index.js +2 -0
- package/dist/core/mcp/index.js.map +1 -1
- package/dist/core/mcp/oauth-provider.d.ts +51 -0
- package/dist/core/mcp/oauth-provider.d.ts.map +1 -0
- package/dist/core/mcp/oauth-provider.js +95 -0
- package/dist/core/mcp/oauth-provider.js.map +1 -0
- package/dist/core/mcp/oauth-store.d.ts +39 -0
- package/dist/core/mcp/oauth-store.d.ts.map +1 -0
- package/dist/core/mcp/oauth-store.js +63 -0
- package/dist/core/mcp/oauth-store.js.map +1 -0
- package/dist/core/mcp/oauth-store.test.d.ts +2 -0
- package/dist/core/mcp/oauth-store.test.d.ts.map +1 -0
- package/dist/core/mcp/oauth-store.test.js +94 -0
- package/dist/core/mcp/oauth-store.test.js.map +1 -0
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +5 -1
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/project-discovery.d.ts +41 -0
- package/dist/core/project-discovery.d.ts.map +1 -0
- package/dist/core/project-discovery.js +441 -0
- package/dist/core/project-discovery.js.map +1 -0
- package/dist/core/prompt-commands.d.ts.map +1 -1
- package/dist/core/prompt-commands.js +203 -0
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/prompt-commands.test.js +39 -0
- package/dist/core/prompt-commands.test.js.map +1 -1
- package/dist/core/radio.d.ts +44 -0
- package/dist/core/radio.d.ts.map +1 -0
- package/dist/core/radio.js +250 -0
- package/dist/core/radio.js.map +1 -0
- package/dist/core/resolve-start.d.ts +29 -0
- package/dist/core/resolve-start.d.ts.map +1 -0
- package/dist/core/resolve-start.js +35 -0
- package/dist/core/resolve-start.js.map +1 -0
- package/dist/core/resolve-start.test.d.ts +2 -0
- package/dist/core/resolve-start.test.d.ts.map +1 -0
- package/dist/core/resolve-start.test.js +66 -0
- package/dist/core/resolve-start.test.js.map +1 -0
- package/dist/core/settings-manager.d.ts +5 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +5 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/shell-path.d.ts +12 -0
- package/dist/core/shell-path.d.ts.map +1 -0
- package/dist/core/shell-path.js +166 -0
- package/dist/core/shell-path.js.map +1 -0
- package/dist/core/shell.d.ts +51 -0
- package/dist/core/shell.d.ts.map +1 -0
- package/dist/core/shell.js +82 -0
- package/dist/core/shell.js.map +1 -0
- package/dist/core/shell.test.d.ts +2 -0
- package/dist/core/shell.test.d.ts.map +1 -0
- package/dist/core/shell.test.js +87 -0
- package/dist/core/shell.test.js.map +1 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +10 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/speed-benchmark.d.ts +133 -0
- package/dist/core/speed-benchmark.d.ts.map +1 -0
- package/dist/core/speed-benchmark.js +410 -0
- package/dist/core/speed-benchmark.js.map +1 -0
- package/dist/core/speed-benchmark.test.d.ts +2 -0
- package/dist/core/speed-benchmark.test.d.ts.map +1 -0
- package/dist/core/speed-benchmark.test.js +97 -0
- package/dist/core/speed-benchmark.test.js.map +1 -0
- package/dist/core/telegram-config.d.ts +21 -0
- package/dist/core/telegram-config.d.ts.map +1 -0
- package/dist/core/telegram-config.js +52 -0
- package/dist/core/telegram-config.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/interactive.d.ts.map +1 -1
- package/dist/interactive.js +4 -3
- package/dist/interactive.js.map +1 -1
- package/dist/modes/serve-mode.d.ts +24 -0
- package/dist/modes/serve-mode.d.ts.map +1 -1
- package/dist/modes/serve-mode.js +54 -19
- package/dist/modes/serve-mode.js.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +17 -1
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/generate-image.d.ts +39 -0
- package/dist/tools/generate-image.d.ts.map +1 -0
- package/dist/tools/generate-image.js +301 -0
- package/dist/tools/generate-image.js.map +1 -0
- package/dist/tools/generate-image.test.d.ts +2 -0
- package/dist/tools/generate-image.test.d.ts.map +1 -0
- package/dist/tools/generate-image.test.js +223 -0
- package/dist/tools/generate-image.test.js.map +1 -0
- package/dist/tools/goal-mode.test.js +1 -1
- package/dist/tools/goal-mode.test.js.map +1 -1
- package/dist/tools/goals.d.ts +7 -7
- package/dist/tools/index.d.ts +15 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +17 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan-mode.test.js +5 -5
- package/dist/tools/plan-mode.test.js.map +1 -1
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +2 -0
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/safe-env.d.ts.map +1 -1
- package/dist/tools/safe-env.js +27 -0
- package/dist/tools/safe-env.js.map +1 -1
- package/dist/tools/subagent.d.ts +2 -4
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +24 -23
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/tasks.d.ts +1 -7
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +4 -31
- package/dist/tools/tasks.js.map +1 -1
- package/dist/ui/App.d.ts +1 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/hooks/usePixelFixFlow.d.ts +1 -1
- package/dist/ui/hooks/usePixelFixFlow.d.ts.map +1 -1
- package/dist/ui/hooks/usePixelFixFlow.js +1 -1
- package/dist/ui/hooks/usePixelFixFlow.js.map +1 -1
- package/dist/ui/hooks/useTranscriptHistory.d.ts +2 -0
- package/dist/ui/hooks/useTranscriptHistory.d.ts.map +1 -1
- package/dist/ui/hooks/useTranscriptHistory.js +3 -2
- package/dist/ui/hooks/useTranscriptHistory.js.map +1 -1
- package/dist/ui/long-prompt-regression-harness.test.js +8 -8
- package/dist/ui/render.d.ts +1 -1
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +60 -8
- package/dist/ui/render.js.map +1 -1
- package/dist/ui/startup-banner-order.test.js +1 -1
- package/dist/ui/startup-banner-order.test.js.map +1 -1
- package/dist/ui/terminal-history-repaint.test.d.ts +2 -0
- package/dist/ui/terminal-history-repaint.test.d.ts.map +1 -0
- package/dist/ui/terminal-history-repaint.test.js +73 -0
- package/dist/ui/terminal-history-repaint.test.js.map +1 -0
- package/dist/ui/terminal-history.d.ts +1 -0
- package/dist/ui/terminal-history.d.ts.map +1 -1
- package/dist/ui/terminal-history.js +31 -2
- package/dist/ui/terminal-history.js.map +1 -1
- package/dist/utils/git.d.ts +6 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +12 -0
- package/dist/utils/git.js.map +1 -1
- package/package.json +6 -6
|
@@ -192,6 +192,97 @@ If the user chooses D, stop after the report.
|
|
|
192
192
|
- **No finding without a concrete, code-grounded first-run scenario.** No "could be polished" nudges.
|
|
193
193
|
- **Report-first.** No edits, installs, or commits until the user picks an option.
|
|
194
194
|
- **Every generated task must end with the exact line:** use kencode to reference working code. /commit when done.`,
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: "test-drive",
|
|
198
|
+
aliases: ["qa", "td"],
|
|
199
|
+
description: "Actually run the app, click around, screenshot, file bugs as tasks",
|
|
200
|
+
prompt: `# /test-drive: Empirically Test the App and File Bugs as Tasks
|
|
201
|
+
|
|
202
|
+
You are a hands-on QA agent. Your job is to ACTUALLY RUN this app and use it like a real user — launch it, click around, type into it, navigate every reachable surface, and LOOK at the result with your own eyes (screenshots / captured output / logs). This is empirical, not a code review: you must drive the running app, not just read source. Every bug you find is recorded so it can be fixed later by another agent working through the task list — except bugs that block YOU from testing further, which you fix immediately so you can keep going.
|
|
203
|
+
|
|
204
|
+
This command is **project-agnostic**. Profile what THIS app is and how it runs before testing. If the user passed arguments to /test-drive, treat them as the area/flow to focus the test pass on, but still sanity-check the rest of the app.
|
|
205
|
+
|
|
206
|
+
## Phase 0: Figure out how to run it
|
|
207
|
+
|
|
208
|
+
Inspect the project (manifests, scripts, README, entry points) and determine how a user actually runs this app, then start it:
|
|
209
|
+
|
|
210
|
+
- **Web app / dev server** — find the dev/start script (e.g. \`pnpm dev\`, \`npm start\`, \`vite\`). Launch it with bash as a **background process** (\`run_in_background: true\`), wait for it to be ready, and read its output with task_output to learn the local URL (e.g. http://localhost:3000).
|
|
211
|
+
- **CLI / TUI** — run the binary/entry command. For interactive programs, launch as a background process and drive it with task_send (type input / answer prompts) + task_output (read what it printed). Use task_stop to end it.
|
|
212
|
+
- **Desktop app (Tauri/Electron/etc.)** — start it the way the project documents. If it exposes a local webview URL or dev server, point the screenshot tool at that; otherwise launch it and rely on captured logs/output for evidence.
|
|
213
|
+
- **Library / no runnable surface** — there's nothing to "click around." Run its examples/tests/demo instead, or report that there is no interactive surface to test and stop.
|
|
214
|
+
|
|
215
|
+
If you cannot get the app to start at all, that is itself the first blocking bug — fix it (Phase 2, blocking path) so you have something to test, then continue.
|
|
216
|
+
|
|
217
|
+
## Phase 1: Drive it and LOOK — use your eyes
|
|
218
|
+
|
|
219
|
+
Exercise the app like a real user, surface by surface. Use the real perception tools available to you:
|
|
220
|
+
|
|
221
|
+
- **screenshot tool** — your eyes for anything with a UI. Open each URL/screen, run \`actions\` (click / type / wait) to walk real flows, and CAPTURE the result so you actually see what rendered. Vary viewport for responsive surfaces and use \`full_page\` for long pages. Don't assume a screen works — look at it.
|
|
222
|
+
- **task_output / task_send** — your eyes and hands for CLIs, TUIs, and dev-server logs: read what the process emitted, type input to drive it, watch for errors/stack traces/warnings in the output.
|
|
223
|
+
- **bash** — hit health/API endpoints, trigger flows, and inspect logs the app writes.
|
|
224
|
+
|
|
225
|
+
Walk the real journeys, not just the happy path that's easy to reach. For each surface, exercise:
|
|
226
|
+
|
|
227
|
+
1. **Primary flows** — the main things a user comes here to do, start to finish.
|
|
228
|
+
2. **Inputs & forms** — submit valid input, empty input, and obviously wrong input; check validation and error messages.
|
|
229
|
+
3. **Navigation** — every reachable link/button/route/tab/command; look for dead ends, broken links, blank screens, 404s, console/stderr errors.
|
|
230
|
+
4. **States** — empty, loading, error, offline/slow, and "no data yet" states. These are where apps break most.
|
|
231
|
+
5. **Visual integrity** — overlapping/cut-off/misaligned elements, unstyled flashes, illegible text, broken images — things only visible by actually looking at a screenshot.
|
|
232
|
+
|
|
233
|
+
As you go, keep a running list of every bug with: what you did, what you expected, what actually happened, the evidence (screenshot path / captured output / log line), and the file/area it most likely lives in.
|
|
234
|
+
|
|
235
|
+
## Phase 2: Triage each bug — blocking vs deferrable
|
|
236
|
+
|
|
237
|
+
For every bug, decide one of two paths:
|
|
238
|
+
|
|
239
|
+
**A) BLOCKING — it stops you from testing further.** The app won't start, a screen crashes, a flow can't be completed, or a broken gate hides everything behind it. You cannot meaningfully continue the test pass until it's fixed. **Fix these immediately**, right now, so you can keep testing:
|
|
240
|
+
|
|
241
|
+
1. Reproduce it and find the root cause in the code.
|
|
242
|
+
2. Use the \`mcp__kencode-search__searchCode\` tool to reference how real projects implement the same pattern correctly, and base your fix on that working code. (If the kencode-search MCP tool isn't connected, note that and fix using project conventions + authoritative docs.)
|
|
243
|
+
3. Implement the fix, then re-run the app and CONFIRM with your eyes (re-screenshot / re-read output) that the bug is actually gone.
|
|
244
|
+
4. Commit the fix by running the \`/commit\` command, so each fix lands on working, committed code before you continue.
|
|
245
|
+
5. Resume the test pass from where you were blocked.
|
|
246
|
+
|
|
247
|
+
**B) DEFERRABLE — it's a real bug but you can keep testing around it.** Cosmetic issues, non-blocking errors, secondary-flow breakage, edge-case mishandling. **Do NOT fix these now.** Record them and move on — they'll be handed off as tasks for another agent to fix in a later session.
|
|
248
|
+
|
|
249
|
+
When unsure, prefer DEFER: only fix inline what genuinely blocks the test pass. The point is to keep driving the app and cataloguing bugs, not to stop and fix everything.
|
|
250
|
+
|
|
251
|
+
## Phase 3: File deferrable bugs as tasks
|
|
252
|
+
|
|
253
|
+
For every deferrable bug (or a tightly-coupled group), add one task with the \`tasks\` tool (action=add). Running /test-drive is the user's explicit request to populate the task list, so this is expected — but only file REAL, reproduced bugs, not speculation. **Before filing, trace each bug to its root cause and confirm it's an actual code defect — not bad seed/test/mock data, a misconfig, or expected behavior.** This app is full of synthetic data, so "these numbers look insane" is very often just the data, not a bug. Reading the code/data/DB to establish cause is REQUIRED here, not an "assumption" — the no-assumptions rule means don't claim a screen works without looking, it does not mean skip root-cause analysis. For any numeric/calculation bug, reproduce the arithmetic from the underlying inputs before filing. Order tasks by user impact and severity. Each task needs a short title and a standalone prompt (the next agent has NO context from this session) that includes:
|
|
254
|
+
|
|
255
|
+
- **The bug**: what you did, what you expected, what actually happened.
|
|
256
|
+
- **Reproduction steps**: the exact flow to trigger it (URL/screen/command + clicks/inputs).
|
|
257
|
+
- **Evidence**: the screenshot path / captured output / log line you saw.
|
|
258
|
+
- **Root cause**: the traced reason it's a code defect (not data/config/expected behavior) — for numeric bugs, the inputs and the arithmetic you reproduced.
|
|
259
|
+
- **Where to look**: the file(s)/area the bug most likely lives in.
|
|
260
|
+
|
|
261
|
+
End EVERY task's standalone prompt with this exact line, verbatim, on its own line:
|
|
262
|
+
|
|
263
|
+
use kencode to reference working code. /commit when done.
|
|
264
|
+
|
|
265
|
+
That line guarantees the next agent bases its fix on real working code (via the kencode MCP) and commits it.
|
|
266
|
+
|
|
267
|
+
## Phase 4: Report
|
|
268
|
+
|
|
269
|
+
When the test pass is done (or you've covered the focus area), summarize:
|
|
270
|
+
|
|
271
|
+
- What you ran and which surfaces/flows you actually drove (with screenshot/output evidence).
|
|
272
|
+
- **Blocking bugs you fixed inline** — each with its root cause and the commit.
|
|
273
|
+
- **Deferrable bugs filed as tasks** — a short list of titles.
|
|
274
|
+
|
|
275
|
+
Then tell the user exactly: "Tasks added. Press Ctrl+T to open the task list and run them." Do not start executing those deferred tasks unless the user explicitly says so.
|
|
276
|
+
|
|
277
|
+
## Rules
|
|
278
|
+
|
|
279
|
+
- **Actually run the app and look.** Don't claim a screen works without observing it — a screenshot, captured output, or log line. No "this should work." But observation alone is not a filed bug: confirming a defect requires tracing the cause, which means reading the code/data/inputs.
|
|
280
|
+
- **Trace cause before filing.** A symptom is not a bug until you've traced it to a code defect and ruled out bad seed/test/mock data, misconfig, and expected behavior. For numeric/calculation bugs, reproduce the arithmetic from the underlying inputs.
|
|
281
|
+
- **An AI/agent (or the model itself) noticing something looks wrong is NOT evidence** — a model flags "big number vs small position" the same way whether the cause is data or logic. Only reproduced behavior plus a traced cause counts.
|
|
282
|
+
- **Only fix what blocks you.** Blocking bugs get fixed inline (kencode-referenced + \`/commit\`); everything else becomes a task. When in doubt, defer.
|
|
283
|
+
- **Every fix is on working, committed code** — reference real code via kencode, verify the fix by re-running, then \`/commit\`.
|
|
284
|
+
- **Every filed task ends with the exact line:** use kencode to reference working code. /commit when done.
|
|
285
|
+
- **File only reproduced bugs with a traced root cause.** No speculative or "could be improved" tasks, and no symptoms with an unverified cause — this is a bug hunt, not a polish wishlist.`,
|
|
195
286
|
},
|
|
196
287
|
{
|
|
197
288
|
name: "elon",
|
|
@@ -303,6 +394,118 @@ If the user chooses D, stop after the report.
|
|
|
303
394
|
- **App-wide first, specific areas second** — in both the hunt and the ledger.
|
|
304
395
|
- **No deletion without code-grounded evidence** that the thing is dead weight (no callers / write-only / unreachable / redundant). No "feels bloated" nudges.
|
|
305
396
|
- **Report-first. No deletions, edits, installs, or commits until the user picks an option.**
|
|
397
|
+
- **Every generated task must end with the exact line:** use kencode to reference working code. /commit when done.`,
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
name: "elon-2",
|
|
401
|
+
aliases: ["step-2", "add-back"],
|
|
402
|
+
description: "Finish the Elon algorithm: add back the ~10%, then simplify/accelerate/automate",
|
|
403
|
+
prompt: `# /elon-2: The Add-Back & Optimize Pass
|
|
404
|
+
|
|
405
|
+
This is the SECOND HALF of /elon, and it only makes sense AFTER deletions have landed. /elon runs steps 1–2 of Elon Musk's algorithm — make the requirement less dumb, then delete the part/process — and it deletes aggressively, on purpose, until things break. /elon-2 runs the rest of the same algorithm, IN ORDER:
|
|
406
|
+
|
|
407
|
+
1. ~~Make the requirement less dumb~~ — done by /elon.
|
|
408
|
+
2. ~~Delete the part or process~~ — done by /elon.
|
|
409
|
+
3. **Simplify** — only what survived deletion.
|
|
410
|
+
4. **Accelerate** — only what survived simplification.
|
|
411
|
+
5. **Automate** — last, never first.
|
|
412
|
+
|
|
413
|
+
Before step 3, this command does the move /elon deliberately leaves undone — the famous Musk rule: **"if you're not adding ~10% back, you didn't delete enough."** Aggressive deletion overshoots; some small piece you cut was actually load-bearing and has to come back. **Phase 1 recovers that ~10%.** Only then do steps 3–5 run, on what survived.
|
|
414
|
+
|
|
415
|
+
This command is **project-agnostic** and **report-first**: the only deliverable is a single ranked ledger, after which you hand the work off as tasks. **Do not edit, install, or implement anything until the user confirms by choosing an option at the end.**
|
|
416
|
+
|
|
417
|
+
If the user passed arguments to /elon-2, treat them as a focus area: narrow the pass to that feature/surface, but still run the full algorithm within it.
|
|
418
|
+
|
|
419
|
+
**Hard scope rules:**
|
|
420
|
+
- **Add-backs are strictly the minimal load-bearing piece that broke.** Restoring functionality the deletions removed is NOT re-adding scope. If an "add-back" is really a net-new capability or a scope re-expansion, that is /expand — drop it here.
|
|
421
|
+
- **Steps 3–5 operate ONLY on survivors.** Never simplify, accelerate, or automate something that should have been deleted — /elon already made those calls. Do not re-litigate deletions (revert-the-whole-deletion is the one exception, see Phase 1).
|
|
422
|
+
- **Order is law.** Add-back → simplify → accelerate → automate. Never accelerate or automate something before it has been simplified.
|
|
423
|
+
|
|
424
|
+
## Phase 0: Establish what changed + a baseline oracle (main agent)
|
|
425
|
+
|
|
426
|
+
You cannot add back what broke without knowing what was cut. Build two maps from real evidence, not memory:
|
|
427
|
+
|
|
428
|
+
- **Deletion map** — what /elon actually removed. Derive it from \`git log\`/\`git diff\` over the relevant range, completed deletion tasks, and removed files/symbols/flags/dependencies. For each deletion, note its predicted add-back (zero / fold-in / seam) from the /elon ledger if available.
|
|
429
|
+
- **Survivor map** — the user-facing surfaces, flows, and internal pieces that remain after the deletions.
|
|
430
|
+
|
|
431
|
+
Then run the project's own **build / typecheck / test / lint** (whatever it has) to capture a baseline oracle: what is broken right now, after the deletions. Note dangling imports, broken routes, failing tests, dead references, and any flow that no longer completes.
|
|
432
|
+
|
|
433
|
+
## Phase 1: Add-back recovery (the ~10%)
|
|
434
|
+
|
|
435
|
+
Empirically find what the deletions broke or over-cut. Spawn subagents in parallel using the subagent tool (call the subagent tool multiple times in a single response), one per high-risk deletion cluster from the deletion map (cap at 6).
|
|
436
|
+
|
|
437
|
+
Each subagent must:
|
|
438
|
+
|
|
439
|
+
1. Walk the deletion and find **breakage evidence** grounded in code: failing build/typecheck/test output, dangling references to removed symbols, routes/commands that no longer resolve, a real user flow that now dead-ends, behavior that callers still expect.
|
|
440
|
+
2. For every breakage, identify the **minimal add-back** — the smallest piece of the deleted thing that must return so dependents work again (mirror the zero / fold-in / seam shapes from /elon). Cite the file:line that proves the breakage and what the restore touches.
|
|
441
|
+
3. **Right-size the add-back.** If the minimal restore is large, vague, or "we'd basically rebuild the deleted thing," that is the signal the deletion itself was wrong — flag it as **REVERT** (undo the whole deletion) rather than a partial add-back. A small, well-scoped add-back is a true ~10%; a large one means the cut went too far.
|
|
442
|
+
|
|
443
|
+
A deletion that broke nothing needs no add-back — that is a clean cut, leave it. The goal is to restore the minimum, not to undo the diet.
|
|
444
|
+
|
|
445
|
+
## Phase 2: Steps 3–5 on survivors (in order)
|
|
446
|
+
|
|
447
|
+
For the survivor map only, spawn subagents in parallel (cap at 6 total across the three steps) to find optimization candidates, strictly in algorithm order:
|
|
448
|
+
|
|
449
|
+
- **Step 3 — Simplify.** Indirection, layers, branches, or config that only existed to serve now-deleted things and can be collapsed or inlined; survivors that can be merged; flows that can be flattened. This is where most leverage lives post-deletion.
|
|
450
|
+
- **Step 4 — Accelerate.** Only what survived simplification: hot paths, redundant work, slow startup, repeated computation that can be sped up. A candidate may not be accelerated until it has been simplified first.
|
|
451
|
+
- **Step 5 — Automate.** Last: manual steps in surviving flows that the system should do for the user. Never propose automating something that should instead be simplified away.
|
|
452
|
+
|
|
453
|
+
Each subagent must cite file:line anchors, name which step it belongs to, and estimate effort (small / medium / large) and leverage.
|
|
454
|
+
|
|
455
|
+
## Phase 3: Validate against the repo (main agent)
|
|
456
|
+
|
|
457
|
+
For every candidate:
|
|
458
|
+
|
|
459
|
+
1. **Add-backs:** confirm the breakage is real against the baseline oracle and that the restore is genuinely minimal. If the restore turns out large, reclassify as REVERT or drop it.
|
|
460
|
+
2. **Simplify/accelerate/automate:** confirm the candidate is a survivor (not something that should have been deleted), and that the step order holds (nothing accelerated/automated before being simplified).
|
|
461
|
+
3. Confirm scope: add-backs restore removed behavior only — anything that is net-new capability is /expand, make-it-work polish is /raise-floor, security is /bullet-proof. Drop out-of-scope items.
|
|
462
|
+
4. Merge duplicates. Rank by **completion leverage = (breakage severity or surface improved) ÷ effort**, with all add-backs ahead of all step 3–5 work.
|
|
463
|
+
|
|
464
|
+
## Phase 4: The completion ledger (report)
|
|
465
|
+
|
|
466
|
+
Output the report. **Add-back (recover) rows first, then simplify, then accelerate, then automate** — algorithm order. Start with one line: project name + a one-sentence summary of how far the deletions overshot and where the biggest post-deletion wins are. Then a single table:
|
|
467
|
+
|
|
468
|
+
| ID | Step | Candidate | Evidence (file:line) | What it restores / improves | Effort | Leverage |
|
|
469
|
+
|---|---|---|---|---|---|---|
|
|
470
|
+
| E2-001 | add-back | re-add the one default the deleted settings screen applied | flow X dead-ends after delete (path:line) | onboarding applies the default inline; nothing else returns | small | high |
|
|
471
|
+
| E2-002 | simplify | inline the adapter layer that only wrapped the deleted backend | single caller left (path:line) | one fewer indirection; survivors merge | small | high |
|
|
472
|
+
|
|
473
|
+
Use IDs like E2-001. Add-back rows lead, then step 3, then 4, then 5. Mark any deletion that overshot as **REVERT** with the reason. The ledger is structured so a later empirical mode can run each row against the project's build/check/test as the "is it fixed / still green?" oracle. Do not run that loop now — this is report-only.
|
|
474
|
+
|
|
475
|
+
After the table, ask exactly:
|
|
476
|
+
|
|
477
|
+
What should I do?
|
|
478
|
+
A) Add tasks for everything (add-backs first, then simplify/accelerate/automate)
|
|
479
|
+
B) Add tasks for the add-backs only (just recover what broke)
|
|
480
|
+
C) Add tasks for specific rows (give IDs, e.g. "E2-001, E2-004")
|
|
481
|
+
D) None — report only
|
|
482
|
+
|
|
483
|
+
Do not start implementing until the user chooses.
|
|
484
|
+
|
|
485
|
+
## Phase 5: Hand off as tasks
|
|
486
|
+
|
|
487
|
+
If the user chooses A, B, or C, do not implement directly. Add one task per selected row (or tightly coupled group) using the \`tasks\` tool (action=add), ordered by algorithm step then leverage — **add-backs first, then simplify, then accelerate, then automate**. Each task needs a short title and a standalone prompt that includes:
|
|
488
|
+
|
|
489
|
+
- the row ID, its step, and exactly what to restore or change (files/symbols/flags + anchors),
|
|
490
|
+
- for add-backs: the breakage it fixes and the minimal restore (never re-expand scope),
|
|
491
|
+
- the blast radius to touch (call sites, imports, tests, docs, config),
|
|
492
|
+
- the project's verification commands to prove the build/tests are green again after the change.
|
|
493
|
+
|
|
494
|
+
End EVERY task's standalone prompt with this exact line, verbatim, on its own line:
|
|
495
|
+
|
|
496
|
+
use kencode to reference working code. /commit when done.
|
|
497
|
+
|
|
498
|
+
After adding the tasks, tell the user exactly: "Tasks added. Press Ctrl+T to open the task list and run them." Do not begin executing them unless the user explicitly says so.
|
|
499
|
+
|
|
500
|
+
If the user chooses D, stop after the report.
|
|
501
|
+
|
|
502
|
+
## Rules
|
|
503
|
+
|
|
504
|
+
- **Runs after /elon.** This pass assumes deletions already landed; Phase 0 derives them from git history and completed tasks.
|
|
505
|
+
- **Add back the ~10%, no more.** Restore only the minimal load-bearing piece that broke. A large add-back means the deletion overshot — mark it REVERT, don't quietly rebuild.
|
|
506
|
+
- **Algorithm order is law.** Add-back → simplify → accelerate → automate. Never accelerate or automate before simplifying.
|
|
507
|
+
- **Survivors only for steps 3–5.** Don't optimize something that should have been deleted; don't re-add scope (that's /expand).
|
|
508
|
+
- **Report-first. No edits, installs, or commits until the user picks an option.**
|
|
306
509
|
- **Every generated task must end with the exact line:** use kencode to reference working code. /commit when done.`,
|
|
307
510
|
},
|
|
308
511
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-commands.js","sourceRoot":"","sources":["../../src/core/prompt-commands.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prompt-commands.js","sourceRoot":"","sources":["../../src/core/prompt-commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -93,6 +93,45 @@ describe("prompt commands", () => {
|
|
|
93
93
|
expect(elon?.prompt).toContain("Do not delete or start implementing until the user chooses");
|
|
94
94
|
expect(elon?.prompt).not.toContain("Create a Goal");
|
|
95
95
|
});
|
|
96
|
+
it("defines /elon-2 as the add-back + simplify/accelerate/automate completion of the algorithm", () => {
|
|
97
|
+
const elon2 = PROMPT_COMMANDS.find((command) => command.name === "elon-2");
|
|
98
|
+
expect(elon2).toBeDefined();
|
|
99
|
+
expect(elon2?.aliases).toContain("step-2");
|
|
100
|
+
expect(elon2?.aliases).toContain("add-back");
|
|
101
|
+
expect(elon2?.prompt).toContain("SECOND HALF of /elon");
|
|
102
|
+
expect(elon2?.prompt).toContain("adding ~10% back");
|
|
103
|
+
expect(elon2?.prompt).toContain("Add-back recovery");
|
|
104
|
+
expect(elon2?.prompt).toContain("Simplify");
|
|
105
|
+
expect(elon2?.prompt).toContain("Accelerate");
|
|
106
|
+
expect(elon2?.prompt).toContain("Automate");
|
|
107
|
+
expect(elon2?.prompt).toContain("REVERT");
|
|
108
|
+
expect(elon2?.prompt).toContain("completion leverage");
|
|
109
|
+
expect(elon2?.prompt).toContain("completion ledger");
|
|
110
|
+
expect(elon2?.prompt).toContain("`tasks` tool");
|
|
111
|
+
expect(elon2?.prompt).toContain("Press Ctrl+T to open the task list");
|
|
112
|
+
expect(elon2?.prompt).toContain("use kencode to reference working code. /commit when done.");
|
|
113
|
+
expect(elon2?.prompt).toContain("B) Add tasks for the add-backs only");
|
|
114
|
+
expect(elon2?.prompt).toContain("D) None — report only");
|
|
115
|
+
expect(elon2?.prompt).toContain("Do not start implementing until the user chooses");
|
|
116
|
+
expect(elon2?.prompt).not.toContain("Create a Goal");
|
|
117
|
+
});
|
|
118
|
+
it("defines /test-drive as an empirical run-the-app, fix-blockers, file-tasks QA command", () => {
|
|
119
|
+
const testDrive = PROMPT_COMMANDS.find((command) => command.name === "test-drive");
|
|
120
|
+
expect(testDrive).toBeDefined();
|
|
121
|
+
expect(testDrive?.aliases).toContain("qa");
|
|
122
|
+
expect(testDrive?.aliases).toContain("td");
|
|
123
|
+
expect(testDrive?.prompt).toContain("ACTUALLY RUN this app");
|
|
124
|
+
expect(testDrive?.prompt).toContain("project-agnostic");
|
|
125
|
+
expect(testDrive?.prompt).toContain("screenshot tool");
|
|
126
|
+
expect(testDrive?.prompt).toContain("BLOCKING");
|
|
127
|
+
expect(testDrive?.prompt).toContain("DEFERRABLE");
|
|
128
|
+
expect(testDrive?.prompt).toContain("Fix these immediately");
|
|
129
|
+
expect(testDrive?.prompt).toContain("`tasks` tool");
|
|
130
|
+
expect(testDrive?.prompt).toContain("mcp__kencode-search__searchCode");
|
|
131
|
+
expect(testDrive?.prompt).toContain("Press Ctrl+T to open the task list");
|
|
132
|
+
expect(testDrive?.prompt).toContain("use kencode to reference working code. /commit when done.");
|
|
133
|
+
expect(testDrive?.prompt).not.toContain("Create a Goal");
|
|
134
|
+
});
|
|
96
135
|
it("keeps /init focused on project-specific CLAUDE.md content", () => {
|
|
97
136
|
const init = PROMPT_COMMANDS.find((command) => command.name === "init");
|
|
98
137
|
expect(init).toBeDefined();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-commands.test.js","sourceRoot":"","sources":["../../src/core/prompt-commands.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prompt-commands.test.js","sourceRoot":"","sources":["../../src/core/prompt-commands.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAExE,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACpD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QAC1E,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QAEvF,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACtD,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QACtD,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QAC5E,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC3D,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,mBAAmB,GAAG;YAC1B,MAAM;YACN,QAAQ;YACR,QAAQ;YACR,UAAU;YACV,OAAO;YACP,UAAU;YACV,YAAY;YACZ,SAAS,OAAO,EAAE;YAClB,cAAc;SACf,CAAC;QACF,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAEjD,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;YACvC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACnF,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7F,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAE5E,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,wCAAwC,CAAC,CAAC;QAC3E,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QACrE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,kDAAkD,CAAC,CAAC;QACrF,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,6CAA6C,CAAC,CAAC;QAChF,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,kDAAkD,CAAC,CAAC;QACrF,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;QACtE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;QAErF,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACxD,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QACtE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAC;QACjF,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAC3D,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QACrD,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QAC3E,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAClC,2DAA2D,CAC5D,CAAC;QACF,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAC;QACjF,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAC;QACjF,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC9D,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,kDAAkD,CAAC,CAAC;QACzF,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;QACzF,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAExE,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACvD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QACrD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAC;QAC3E,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACpD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QACrE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,2DAA2D,CAAC,CAAC;QAC5F,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAC;QAC3E,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,4DAA4D,CAAC,CAAC;QAC7F,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;QACpG,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAE3E,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAC5B,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,2DAA2D,CAAC,CAAC;QAC7F,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,kDAAkD,CAAC,CAAC;QACpF,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,GAAG,EAAE;QAC9F,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;QAEnF,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC7D,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QACxD,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACvD,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAClD,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC7D,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QACvE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QAC1E,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,SAAS,CACjC,2DAA2D,CAC5D,CAAC;QACF,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAExE,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QAChE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;QACpE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,iDAAiD,CAAC,CAAC;QAClF,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAC1E,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAC5B,mEAAmE,CACpE,CAAC;QACF,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QACrE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QACrE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,8DAA8D,CAAC,CAAC;QAC/F,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACrD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QAC7D,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC5D,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QACzE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internet radio — stream a free station while you work. Ported from gg-boss's
|
|
3
|
+
* radio so the ezcoder-app windows offer the same curated, royalty-free, no-API-key
|
|
4
|
+
* streams (SomaFM started in 2000, Radio Paradise in 2006).
|
|
5
|
+
*
|
|
6
|
+
* Playback runs inside the per-window app sidecar process, so each window's
|
|
7
|
+
* radio is fully independent — opening more windows never duplicates audio.
|
|
8
|
+
*
|
|
9
|
+
* Player binary detection: mpv > ffplay > mpg123 > cvlc. macOS's built-in
|
|
10
|
+
* afplay isn't a streaming player, so users without any of those get a one-line
|
|
11
|
+
* "install mpv" hint and the request no-ops gracefully.
|
|
12
|
+
*
|
|
13
|
+
* One station at a time — switching stations or selecting "off" kills the
|
|
14
|
+
* existing player process before spawning a new one.
|
|
15
|
+
*/
|
|
16
|
+
export interface RadioStation {
|
|
17
|
+
/** Stable identifier used by the picker + state. */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Display name in the picker. */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Short subtitle shown next to the name. */
|
|
22
|
+
description: string;
|
|
23
|
+
/** Direct stream URL — must be MP3/AAC/Ogg, anything mpv handles. */
|
|
24
|
+
url: string;
|
|
25
|
+
}
|
|
26
|
+
export declare const RADIO_STATIONS: readonly RadioStation[];
|
|
27
|
+
export declare function getCurrentStation(): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Stop whatever's currently playing. Idempotent — safe to call when nothing
|
|
30
|
+
* is playing. Sends SIGTERM (graceful), child cleans up the audio device.
|
|
31
|
+
*/
|
|
32
|
+
export declare function stopRadio(): void;
|
|
33
|
+
export interface PlayResult {
|
|
34
|
+
ok: boolean;
|
|
35
|
+
/** Friendly error to surface to the user when ok=false. */
|
|
36
|
+
error?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Spawn a streaming player for the given station. If one is already playing,
|
|
40
|
+
* it's killed first. Returns ok=false with a hint if no compatible player is
|
|
41
|
+
* installed — caller should surface the error to the user.
|
|
42
|
+
*/
|
|
43
|
+
export declare function playRadio(stationId: string): PlayResult;
|
|
44
|
+
//# sourceMappingURL=radio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radio.d.ts","sourceRoot":"","sources":["../../src/core/radio.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAyBjD,CAAC;AAqEF,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjD;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,IAAI,CAqBhC;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA6CD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CA2DvD"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { log } from "./logger.js";
|
|
5
|
+
export const RADIO_STATIONS = [
|
|
6
|
+
{
|
|
7
|
+
id: "somafm-groove-salad",
|
|
8
|
+
name: "SomaFM · Groove Salad",
|
|
9
|
+
description: "Chilled downtempo, ambient grooves",
|
|
10
|
+
url: "http://ice1.somafm.com/groovesalad-128-mp3",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: "somafm-drone-zone",
|
|
14
|
+
name: "SomaFM · Drone Zone",
|
|
15
|
+
description: "Atmospheric textures with minimal beats",
|
|
16
|
+
url: "http://ice1.somafm.com/dronezone-128-mp3",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "radio-paradise",
|
|
20
|
+
name: "Radio Paradise",
|
|
21
|
+
description: "Eclectic mix — rock, electronica, jazz",
|
|
22
|
+
url: "http://stream.radioparadise.com/mp3-128",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "george-fm",
|
|
26
|
+
name: "George FM",
|
|
27
|
+
description: "NZ dance + electronic",
|
|
28
|
+
url: "https://mediaworks.streamguys1.com/george_net_icy",
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* Well-known directories where streaming players get installed but which a
|
|
33
|
+
* GUI app's minimal PATH usually omits. macOS apps launched from Finder/Dock
|
|
34
|
+
* inherit only `/usr/bin:/bin:/usr/sbin:/sbin` — not Homebrew (`/opt/homebrew/bin`
|
|
35
|
+
* on Apple Silicon, `/usr/local/bin` on Intel) or MacPorts (`/opt/local/bin`),
|
|
36
|
+
* so `spawn("mpv")` ENOENTs even when mpv is installed. We search these in
|
|
37
|
+
* addition to PATH. Linux dirs cover the common package-manager prefixes.
|
|
38
|
+
*/
|
|
39
|
+
function extraPlayerDirs() {
|
|
40
|
+
switch (process.platform) {
|
|
41
|
+
case "darwin":
|
|
42
|
+
return ["/opt/homebrew/bin", "/usr/local/bin", "/opt/local/bin"];
|
|
43
|
+
case "linux":
|
|
44
|
+
return ["/usr/bin", "/usr/local/bin", "/bin", "/snap/bin"];
|
|
45
|
+
default:
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve a player command to a runnable path. Probes PATH plus the well-known
|
|
51
|
+
* install dirs and returns the first absolute hit, so GUI apps find players in
|
|
52
|
+
* Homebrew/MacPorts dirs their minimal PATH omits. Returns null when the binary
|
|
53
|
+
* isn't found anywhere we look.
|
|
54
|
+
*
|
|
55
|
+
* Windows is left to the OS: executables carry extensions (.exe/.cmd) resolved
|
|
56
|
+
* via PATHEXT, and GUI apps there inherit a usable PATH — so we return `cmd`
|
|
57
|
+
* unchanged and let spawn do its normal lookup (probing bare names here would
|
|
58
|
+
* miss `mpv.exe` and regress Windows).
|
|
59
|
+
*/
|
|
60
|
+
function resolvePlayerPath(cmd) {
|
|
61
|
+
// An explicit path is used as-is.
|
|
62
|
+
if (cmd.includes(path.sep))
|
|
63
|
+
return existsSync(cmd) ? cmd : null;
|
|
64
|
+
// Defer to the OS on Windows (PATHEXT handles the extension).
|
|
65
|
+
if (process.platform === "win32")
|
|
66
|
+
return cmd;
|
|
67
|
+
// 1) PATH (covers terminal launches + any inherited shell environment).
|
|
68
|
+
const pathDirs = (process.env.PATH ?? "").split(path.delimiter).filter(Boolean);
|
|
69
|
+
// 2) Well-known dirs a GUI PATH typically omits.
|
|
70
|
+
for (const dir of [...pathDirs, ...extraPlayerDirs()]) {
|
|
71
|
+
const candidate = path.join(dir, cmd);
|
|
72
|
+
if (existsSync(candidate))
|
|
73
|
+
return candidate;
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Streaming-capable players in priority order. Each gets its quietest flag
|
|
79
|
+
* combination — radio runs in the background, we don't want stdout/stderr
|
|
80
|
+
* spam. Stdio is also redirected to "ignore" at spawn time.
|
|
81
|
+
*/
|
|
82
|
+
const PLAYERS = [
|
|
83
|
+
{ cmd: "mpv", args: (u) => ["--really-quiet", "--no-video", "--no-terminal", u] },
|
|
84
|
+
{ cmd: "ffplay", args: (u) => ["-nodisp", "-autoexit", "-loglevel", "quiet", u] },
|
|
85
|
+
{ cmd: "mpg123", args: (u) => ["-q", u] },
|
|
86
|
+
{ cmd: "cvlc", args: (u) => ["--play-and-exit", "--quiet", u] },
|
|
87
|
+
];
|
|
88
|
+
let currentChild = null;
|
|
89
|
+
let currentStationId = null;
|
|
90
|
+
export function getCurrentStation() {
|
|
91
|
+
return currentStationId;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Stop whatever's currently playing. Idempotent — safe to call when nothing
|
|
95
|
+
* is playing. Sends SIGTERM (graceful), child cleans up the audio device.
|
|
96
|
+
*/
|
|
97
|
+
export function stopRadio() {
|
|
98
|
+
if (!currentChild)
|
|
99
|
+
return;
|
|
100
|
+
try {
|
|
101
|
+
// Detached children sit in their own process group on POSIX; kill the
|
|
102
|
+
// whole group so any helper threads/forks die too. On Windows there's no
|
|
103
|
+
// process group concept — kill() targets the child only.
|
|
104
|
+
if (process.platform !== "win32" && currentChild.pid) {
|
|
105
|
+
try {
|
|
106
|
+
process.kill(-currentChild.pid, "SIGTERM");
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
currentChild.kill("SIGTERM");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
currentChild.kill("SIGTERM");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Already exited — nothing to do.
|
|
118
|
+
}
|
|
119
|
+
currentChild = null;
|
|
120
|
+
currentStationId = null;
|
|
121
|
+
log("INFO", "radio", "stopped");
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* On WSL2, native Linux audio binaries can't reach the Windows audio device
|
|
125
|
+
* through WSLg's bridge in any useful way for streaming — detect WSL and route
|
|
126
|
+
* through the Windows host instead.
|
|
127
|
+
*/
|
|
128
|
+
function isWsl() {
|
|
129
|
+
if (process.platform !== "linux")
|
|
130
|
+
return false;
|
|
131
|
+
return !!process.env.WSL_DISTRO_NAME || existsSync("/proc/sys/fs/binfmt_misc/WSLInterop");
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Stream a station through powershell.exe + WPF MediaPlayer on the Windows host
|
|
135
|
+
* instead of a Linux binary. Returns the ChildProcess or null on spawn failure.
|
|
136
|
+
* The URL is allowlist-checked, scheme-enforced, and passed via env (never
|
|
137
|
+
* interpolated into the -Command string).
|
|
138
|
+
*/
|
|
139
|
+
function tryPlayOnWindowsHost(station) {
|
|
140
|
+
const allowedUrls = new Set(RADIO_STATIONS.map((s) => s.url));
|
|
141
|
+
if (!allowedUrls.has(station.url))
|
|
142
|
+
return null;
|
|
143
|
+
if (!/^https?:\/\//i.test(station.url))
|
|
144
|
+
return null;
|
|
145
|
+
const psScript = [
|
|
146
|
+
"Add-Type -AssemblyName presentationCore;",
|
|
147
|
+
"Add-Type -AssemblyName WindowsBase;",
|
|
148
|
+
"$p = New-Object System.Windows.Media.MediaPlayer;",
|
|
149
|
+
"$p.Open([uri]$env:GG_RADIO_URL);",
|
|
150
|
+
"$p.Play();",
|
|
151
|
+
"[System.Windows.Threading.Dispatcher]::Run();",
|
|
152
|
+
].join(" ");
|
|
153
|
+
try {
|
|
154
|
+
return spawn("powershell.exe", ["-NoProfile", "-WindowStyle", "Hidden", "-Command", psScript], {
|
|
155
|
+
detached: true,
|
|
156
|
+
stdio: "ignore",
|
|
157
|
+
env: {
|
|
158
|
+
...process.env,
|
|
159
|
+
GG_RADIO_URL: station.url,
|
|
160
|
+
WSLENV: (process.env.WSLENV ? process.env.WSLENV + ":" : "") + "GG_RADIO_URL",
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Spawn a streaming player for the given station. If one is already playing,
|
|
170
|
+
* it's killed first. Returns ok=false with a hint if no compatible player is
|
|
171
|
+
* installed — caller should surface the error to the user.
|
|
172
|
+
*/
|
|
173
|
+
export function playRadio(stationId) {
|
|
174
|
+
const station = RADIO_STATIONS.find((s) => s.id === stationId);
|
|
175
|
+
if (!station)
|
|
176
|
+
return { ok: false, error: `Unknown station: ${stationId}` };
|
|
177
|
+
// Always stop the previous stream before starting a new one.
|
|
178
|
+
stopRadio();
|
|
179
|
+
if (isWsl()) {
|
|
180
|
+
const child = tryPlayOnWindowsHost(station);
|
|
181
|
+
if (child) {
|
|
182
|
+
let errored = false;
|
|
183
|
+
child.once("error", () => {
|
|
184
|
+
errored = true;
|
|
185
|
+
});
|
|
186
|
+
if (child.pid && !errored) {
|
|
187
|
+
currentChild = child;
|
|
188
|
+
currentStationId = stationId;
|
|
189
|
+
log("INFO", "radio", "playing", {
|
|
190
|
+
station: station.id,
|
|
191
|
+
player: "powershell.exe (wsl→host)",
|
|
192
|
+
url: station.url,
|
|
193
|
+
});
|
|
194
|
+
child.unref();
|
|
195
|
+
return { ok: true };
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
for (const player of PLAYERS) {
|
|
200
|
+
// Resolve to an absolute path first so we find players in Homebrew/MacPorts
|
|
201
|
+
// dirs that a GUI app's minimal PATH omits. Skip when not installed.
|
|
202
|
+
const bin = resolvePlayerPath(player.cmd);
|
|
203
|
+
if (!bin)
|
|
204
|
+
continue;
|
|
205
|
+
try {
|
|
206
|
+
const child = spawn(bin, player.args(station.url), {
|
|
207
|
+
detached: process.platform !== "win32",
|
|
208
|
+
stdio: "ignore",
|
|
209
|
+
});
|
|
210
|
+
let errored = false;
|
|
211
|
+
child.once("error", () => {
|
|
212
|
+
errored = true;
|
|
213
|
+
});
|
|
214
|
+
if (child.pid && !errored) {
|
|
215
|
+
currentChild = child;
|
|
216
|
+
currentStationId = stationId;
|
|
217
|
+
log("INFO", "radio", "playing", {
|
|
218
|
+
station: station.id,
|
|
219
|
+
player: player.cmd,
|
|
220
|
+
url: station.url,
|
|
221
|
+
});
|
|
222
|
+
child.unref();
|
|
223
|
+
return { ok: true };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
// ENOENT or permission — try the next player.
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
log("WARN", "radio", "no compatible player found", { platform: process.platform });
|
|
231
|
+
return { ok: false, error: buildInstallHint() };
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Platform-specific one-line install hint so the user can copy-paste rather
|
|
235
|
+
* than reading generic suggestions.
|
|
236
|
+
*/
|
|
237
|
+
function buildInstallHint() {
|
|
238
|
+
const base = "Radio needs a streaming player. Install one of: mpv (recommended), ffplay, mpg123, or vlc.";
|
|
239
|
+
switch (process.platform) {
|
|
240
|
+
case "darwin":
|
|
241
|
+
return `${base} On macOS: \`brew install mpv\` (or \`brew install ffmpeg\` for ffplay).`;
|
|
242
|
+
case "linux":
|
|
243
|
+
return `${base} On Linux (Debian/Ubuntu): \`sudo apt install mpv\`. Fedora: \`sudo dnf install mpv\`. Arch: \`sudo pacman -S mpv\`.`;
|
|
244
|
+
case "win32":
|
|
245
|
+
return `${base} On Windows: \`winget install mpv.mpv\` (or download from https://mpv.io).`;
|
|
246
|
+
default:
|
|
247
|
+
return `${base} See https://mpv.io for platform installation instructions.`;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=radio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radio.js","sourceRoot":"","sources":["../../src/core/radio.ts"],"names":[],"mappings":"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"}
|