@prestyj/cli 5.30.0 → 5.30.2

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 (334) hide show
  1. package/README.md +54 -39
  2. package/assets/skills/bulletproof/SKILL.md +1 -1
  3. package/assets/skills/clarify/SKILL.md +1 -1
  4. package/assets/skills/code-review/SKILL.md +1 -1
  5. package/assets/skills/compliance-guard/SKILL.md +1 -1
  6. package/assets/skills/durable/SKILL.md +1 -1
  7. package/assets/skills/evidence-led-ui/SKILL.md +1 -1
  8. package/assets/skills/lean/SKILL.md +1 -1
  9. package/assets/skills/refactoring/SKILL.md +1 -1
  10. package/assets/skills/root-cause/SKILL.md +1 -1
  11. package/assets/skills/shared-language/SKILL.md +1 -1
  12. package/assets/skills/tdd/SKILL.md +1 -1
  13. package/dist/app-sidecar/app-settings.d.ts +63 -0
  14. package/dist/app-sidecar/app-settings.js +147 -0
  15. package/dist/app-sidecar/app-settings.js.map +1 -0
  16. package/dist/app-sidecar/attachments.d.ts +11 -0
  17. package/dist/app-sidecar/attachments.js +47 -0
  18. package/dist/app-sidecar/attachments.js.map +1 -0
  19. package/dist/app-sidecar/auth-routes.d.ts +3 -0
  20. package/dist/app-sidecar/auth-routes.js +293 -0
  21. package/dist/app-sidecar/auth-routes.js.map +1 -0
  22. package/dist/app-sidecar/autopilot-runner.d.ts +62 -0
  23. package/dist/app-sidecar/autopilot-runner.js +373 -0
  24. package/dist/app-sidecar/autopilot-runner.js.map +1 -0
  25. package/dist/app-sidecar/file-search.d.ts +15 -0
  26. package/dist/app-sidecar/file-search.js +103 -0
  27. package/dist/app-sidecar/file-search.js.map +1 -0
  28. package/dist/app-sidecar/hf-pull-manager.d.ts +20 -0
  29. package/dist/app-sidecar/hf-pull-manager.js +224 -0
  30. package/dist/app-sidecar/hf-pull-manager.js.map +1 -0
  31. package/dist/app-sidecar/history-routes.d.ts +3 -0
  32. package/dist/app-sidecar/history-routes.js +375 -0
  33. package/dist/app-sidecar/history-routes.js.map +1 -0
  34. package/dist/app-sidecar/history.d.ts +67 -0
  35. package/dist/app-sidecar/history.js +23 -0
  36. package/dist/app-sidecar/history.js.map +1 -0
  37. package/dist/app-sidecar/http.d.ts +5 -0
  38. package/dist/app-sidecar/http.js +27 -0
  39. package/dist/app-sidecar/http.js.map +1 -0
  40. package/dist/app-sidecar/integration-routes.d.ts +3 -0
  41. package/dist/app-sidecar/integration-routes.js +286 -0
  42. package/dist/app-sidecar/integration-routes.js.map +1 -0
  43. package/dist/app-sidecar/json-mode.d.ts +10 -0
  44. package/dist/app-sidecar/json-mode.js +73 -0
  45. package/dist/app-sidecar/json-mode.js.map +1 -0
  46. package/dist/app-sidecar/keep-awake.d.ts +4 -0
  47. package/dist/app-sidecar/keep-awake.js +5 -0
  48. package/dist/app-sidecar/keep-awake.js.map +1 -0
  49. package/dist/app-sidecar/mcp-routes.d.ts +3 -0
  50. package/dist/app-sidecar/mcp-routes.js +185 -0
  51. package/dist/app-sidecar/mcp-routes.js.map +1 -0
  52. package/dist/app-sidecar/mcp-rows.d.ts +31 -0
  53. package/dist/app-sidecar/mcp-rows.js +77 -0
  54. package/dist/app-sidecar/mcp-rows.js.map +1 -0
  55. package/dist/app-sidecar/nolan-context.d.ts +20 -0
  56. package/dist/app-sidecar/nolan-context.js +55 -0
  57. package/dist/app-sidecar/nolan-context.js.map +1 -0
  58. package/dist/app-sidecar/progress-manager.d.ts +10 -0
  59. package/dist/app-sidecar/progress-manager.js +116 -0
  60. package/dist/app-sidecar/progress-manager.js.map +1 -0
  61. package/dist/app-sidecar/prompt-routes.d.ts +3 -0
  62. package/dist/app-sidecar/prompt-routes.js +355 -0
  63. package/dist/app-sidecar/prompt-routes.js.map +1 -0
  64. package/dist/app-sidecar/repo-polls.d.ts +18 -0
  65. package/dist/app-sidecar/repo-polls.js +45 -0
  66. package/dist/app-sidecar/repo-polls.js.map +1 -0
  67. package/dist/app-sidecar/route-context.d.ts +147 -0
  68. package/dist/app-sidecar/route-context.js +2 -0
  69. package/dist/app-sidecar/route-context.js.map +1 -0
  70. package/dist/app-sidecar/run-control-routes.d.ts +3 -0
  71. package/dist/app-sidecar/run-control-routes.js +437 -0
  72. package/dist/app-sidecar/run-control-routes.js.map +1 -0
  73. package/dist/app-sidecar/session-routes.d.ts +3 -0
  74. package/dist/app-sidecar/session-routes.js +115 -0
  75. package/dist/app-sidecar/session-routes.js.map +1 -0
  76. package/dist/app-sidecar/session-types.d.ts +39 -0
  77. package/dist/app-sidecar/session-types.js +5 -0
  78. package/dist/app-sidecar/session-types.js.map +1 -0
  79. package/dist/app-sidecar/task-routes.d.ts +3 -0
  80. package/dist/app-sidecar/task-routes.js +232 -0
  81. package/dist/app-sidecar/task-routes.js.map +1 -0
  82. package/dist/app-sidecar/usage.d.ts +19 -0
  83. package/dist/app-sidecar/usage.js +153 -0
  84. package/dist/app-sidecar/usage.js.map +1 -0
  85. package/dist/app-sidecar/workspace-routes.d.ts +3 -0
  86. package/dist/app-sidecar/workspace-routes.js +374 -0
  87. package/dist/app-sidecar/workspace-routes.js.map +1 -0
  88. package/dist/app-sidecar.js +541 -3971
  89. package/dist/app-sidecar.js.map +1 -1
  90. package/dist/chat-agents/jiwa.js +2 -0
  91. package/dist/chat-agents/jiwa.js.map +1 -1
  92. package/dist/chat-agents/memory.js +2 -0
  93. package/dist/chat-agents/memory.js.map +1 -1
  94. package/dist/cli/auth.js +13 -9
  95. package/dist/cli/auth.js.map +1 -1
  96. package/dist/cli.js +10 -11
  97. package/dist/cli.js.map +1 -1
  98. package/dist/config.js +1 -1
  99. package/dist/core/acceptance-checks.js +3 -9
  100. package/dist/core/acceptance-checks.js.map +1 -1
  101. package/dist/core/agent-session/helpers.d.ts +26 -0
  102. package/dist/core/agent-session/helpers.js +47 -0
  103. package/dist/core/agent-session/helpers.js.map +1 -0
  104. package/dist/core/agent-session/mcp-tools.d.ts +68 -0
  105. package/dist/core/agent-session/mcp-tools.js +195 -0
  106. package/dist/core/agent-session/mcp-tools.js.map +1 -0
  107. package/dist/core/agent-session/run-loop-monitor.d.ts +63 -0
  108. package/dist/core/agent-session/run-loop-monitor.js +164 -0
  109. package/dist/core/agent-session/run-loop-monitor.js.map +1 -0
  110. package/dist/core/agent-session/transcript-markers.d.ts +57 -0
  111. package/dist/core/agent-session/transcript-markers.js +166 -0
  112. package/dist/core/agent-session/transcript-markers.js.map +1 -0
  113. package/dist/core/agent-session/verification-tracker.d.ts +50 -0
  114. package/dist/core/agent-session/verification-tracker.js +269 -0
  115. package/dist/core/agent-session/verification-tracker.js.map +1 -0
  116. package/dist/core/agent-session.d.ts +27 -87
  117. package/dist/core/agent-session.js +166 -713
  118. package/dist/core/agent-session.js.map +1 -1
  119. package/dist/core/auth-providers.js +3 -3
  120. package/dist/core/auth-providers.js.map +1 -1
  121. package/dist/core/autopilot-cycle.d.ts +8 -2
  122. package/dist/core/autopilot-cycle.js +22 -3
  123. package/dist/core/autopilot-cycle.js.map +1 -1
  124. package/dist/core/bundled-agents.js +6 -6
  125. package/dist/core/bundled-agents.js.map +1 -1
  126. package/dist/core/checklist-git.d.ts +19 -0
  127. package/dist/core/checklist-git.js +54 -0
  128. package/dist/core/checklist-git.js.map +1 -0
  129. package/dist/core/checklist-items.d.ts +10 -1
  130. package/dist/core/checklist-items.js +22 -0
  131. package/dist/core/checklist-items.js.map +1 -1
  132. package/dist/core/checklist-prompt.d.ts +14 -3
  133. package/dist/core/checklist-prompt.js +38 -8
  134. package/dist/core/checklist-prompt.js.map +1 -1
  135. package/dist/core/checklist-snapshot.d.ts +5 -1
  136. package/dist/core/checklist-snapshot.js +20 -3
  137. package/dist/core/checklist-snapshot.js.map +1 -1
  138. package/dist/core/checklist-store.d.ts +5 -1
  139. package/dist/core/checklist-store.js +35 -4
  140. package/dist/core/checklist-store.js.map +1 -1
  141. package/dist/core/context-limits.js +1 -1
  142. package/dist/core/context-limits.js.map +1 -1
  143. package/dist/core/event-bus.d.ts +1 -1
  144. package/dist/core/event-bus.js +39 -13
  145. package/dist/core/event-bus.js.map +1 -1
  146. package/dist/core/extensions/plugin-bundles.js +4 -2
  147. package/dist/core/extensions/plugin-bundles.js.map +1 -1
  148. package/dist/core/hashline.d.ts +10 -8
  149. package/dist/core/hashline.js.map +1 -1
  150. package/dist/core/mcp/client.js +2 -0
  151. package/dist/core/mcp/client.js.map +1 -1
  152. package/dist/core/mcp/loopback.d.ts +2 -2
  153. package/dist/core/mcp/loopback.js +2 -2
  154. package/dist/core/mcp/shared-pool.js +4 -3
  155. package/dist/core/mcp/shared-pool.js.map +1 -1
  156. package/dist/core/persistent-shell.js +2 -1
  157. package/dist/core/persistent-shell.js.map +1 -1
  158. package/dist/core/plan-handoff.d.ts +30 -0
  159. package/dist/core/plan-handoff.js +10 -0
  160. package/dist/core/plan-handoff.js.map +1 -0
  161. package/dist/core/plan-submission-gate.d.ts +28 -0
  162. package/dist/core/plan-submission-gate.js +27 -0
  163. package/dist/core/plan-submission-gate.js.map +1 -0
  164. package/dist/core/process-manager.js +9 -1
  165. package/dist/core/process-manager.js.map +1 -1
  166. package/dist/core/project-health-scan.d.ts +109 -0
  167. package/dist/core/project-health-scan.js +673 -0
  168. package/dist/core/project-health-scan.js.map +1 -0
  169. package/dist/core/project-health-score.d.ts +41 -0
  170. package/dist/core/project-health-score.js +257 -0
  171. package/dist/core/project-health-score.js.map +1 -0
  172. package/dist/core/prompt-commands.js +44 -6
  173. package/dist/core/prompt-commands.js.map +1 -1
  174. package/dist/core/session-manager.js.map +1 -1
  175. package/dist/core/session-storage.d.ts +1 -0
  176. package/dist/core/session-storage.js +1 -1
  177. package/dist/core/session-storage.js.map +1 -1
  178. package/dist/core/skills.js +6 -9
  179. package/dist/core/skills.js.map +1 -1
  180. package/dist/core/style-packs/index.js +2 -11
  181. package/dist/core/style-packs/index.js.map +1 -1
  182. package/dist/core/style-packs/packs.d.ts +3 -12
  183. package/dist/core/style-packs/packs.js +132 -173
  184. package/dist/core/style-packs/packs.js.map +1 -1
  185. package/dist/core/subagent-manager.js +11 -6
  186. package/dist/core/subagent-manager.js.map +1 -1
  187. package/dist/core/subagent-receipt.js +3 -4
  188. package/dist/core/subagent-receipt.js.map +1 -1
  189. package/dist/core/ui-adoption.js +2 -0
  190. package/dist/core/ui-adoption.js.map +1 -1
  191. package/dist/core/ui-registry.js +5 -4
  192. package/dist/core/ui-registry.js.map +1 -1
  193. package/dist/core/verification-evidence.d.ts +21 -2
  194. package/dist/core/verification-evidence.js +283 -8
  195. package/dist/core/verification-evidence.js.map +1 -1
  196. package/dist/core/verification-gate.js +4 -2
  197. package/dist/core/verification-gate.js.map +1 -1
  198. package/dist/core/verify-commands.js +2 -3
  199. package/dist/core/verify-commands.js.map +1 -1
  200. package/dist/modes/agent-home-mode.js +1 -4
  201. package/dist/modes/agent-home-mode.js.map +1 -1
  202. package/dist/modes/subagent-worker-mode.js +13 -8
  203. package/dist/modes/subagent-worker-mode.js.map +1 -1
  204. package/dist/system-prompt.js +70 -87
  205. package/dist/system-prompt.js.map +1 -1
  206. package/dist/tools/ask-user.js +13 -74
  207. package/dist/tools/ask-user.js.map +1 -1
  208. package/dist/tools/bash.d.ts +3 -1
  209. package/dist/tools/bash.js +28 -84
  210. package/dist/tools/bash.js.map +1 -1
  211. package/dist/tools/checklist.d.ts +7 -14
  212. package/dist/tools/checklist.js +22 -41
  213. package/dist/tools/checklist.js.map +1 -1
  214. package/dist/tools/code-nav.js +7 -29
  215. package/dist/tools/code-nav.js.map +1 -1
  216. package/dist/tools/edit.d.ts +4 -9
  217. package/dist/tools/edit.js +175 -65
  218. package/dist/tools/edit.js.map +1 -1
  219. package/dist/tools/enter-plan.js +2 -7
  220. package/dist/tools/enter-plan.js.map +1 -1
  221. package/dist/tools/exit-plan.js +2 -3
  222. package/dist/tools/exit-plan.js.map +1 -1
  223. package/dist/tools/find.js +3 -4
  224. package/dist/tools/find.js.map +1 -1
  225. package/dist/tools/grep.js +9 -20
  226. package/dist/tools/grep.js.map +1 -1
  227. package/dist/tools/index.js +10 -7
  228. package/dist/tools/index.js.map +1 -1
  229. package/dist/tools/ls.js +3 -3
  230. package/dist/tools/ls.js.map +1 -1
  231. package/dist/tools/prompt-hints.js +34 -47
  232. package/dist/tools/prompt-hints.js.map +1 -1
  233. package/dist/tools/read-only-bash.js +3 -0
  234. package/dist/tools/read-only-bash.js.map +1 -1
  235. package/dist/tools/read.js +8 -20
  236. package/dist/tools/read.js.map +1 -1
  237. package/dist/tools/search-code.js +4 -12
  238. package/dist/tools/search-code.js.map +1 -1
  239. package/dist/tools/skill.js +13 -7
  240. package/dist/tools/skill.js.map +1 -1
  241. package/dist/tools/subagent-control.js +7 -22
  242. package/dist/tools/subagent-control.js.map +1 -1
  243. package/dist/tools/subagent.js +1 -1
  244. package/dist/tools/subagent.js.map +1 -1
  245. package/dist/tools/task-output.js +4 -15
  246. package/dist/tools/task-output.js.map +1 -1
  247. package/dist/tools/task-send.js +5 -17
  248. package/dist/tools/task-send.js.map +1 -1
  249. package/dist/tools/task-stop.js +2 -2
  250. package/dist/tools/task-stop.js.map +1 -1
  251. package/dist/tools/tool-search.js +2 -7
  252. package/dist/tools/tool-search.js.map +1 -1
  253. package/dist/tools/tool-tiers.d.ts +21 -4
  254. package/dist/tools/tool-tiers.js +44 -17
  255. package/dist/tools/tool-tiers.js.map +1 -1
  256. package/dist/tools/web-fetch.js +7 -33
  257. package/dist/tools/web-fetch.js.map +1 -1
  258. package/dist/tools/write.js +3 -4
  259. package/dist/tools/write.js.map +1 -1
  260. package/dist/ui/App.js +20 -26
  261. package/dist/ui/App.js.map +1 -1
  262. package/dist/ui/components/Footer.js +1 -2
  263. package/dist/ui/components/Footer.js.map +1 -1
  264. package/dist/ui/components/InputArea.js +0 -2
  265. package/dist/ui/components/InputArea.js.map +1 -1
  266. package/dist/ui/components/ToolExecution.js +4 -3
  267. package/dist/ui/components/ToolExecution.js.map +1 -1
  268. package/dist/ui/hooks/useAgentLoop.js +7 -6
  269. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  270. package/dist/ui/sessions.js +1 -5
  271. package/dist/ui/sessions.js.map +1 -1
  272. package/dist/ui/utils/highlight.d.ts +0 -5
  273. package/dist/ui/utils/highlight.js +3 -49
  274. package/dist/ui/utils/highlight.js.map +1 -1
  275. package/dist/ui/utils/markdown-renderer.d.ts +6 -0
  276. package/dist/ui/utils/markdown-renderer.js +21 -5
  277. package/dist/ui/utils/markdown-renderer.js.map +1 -1
  278. package/dist/utils/process.js +3 -3
  279. package/dist/utils/process.js.map +1 -1
  280. package/dist/utils/shared-poll.d.ts +37 -0
  281. package/dist/utils/shared-poll.js +104 -0
  282. package/dist/utils/shared-poll.js.map +1 -0
  283. package/package.json +8 -8
  284. package/dist/core/api-benchmark.d.ts +0 -63
  285. package/dist/core/api-benchmark.js +0 -381
  286. package/dist/core/api-benchmark.js.map +0 -1
  287. package/dist/core/bash-spawn-benchmark.d.ts +0 -1
  288. package/dist/core/bash-spawn-benchmark.js +0 -139
  289. package/dist/core/bash-spawn-benchmark.js.map +0 -1
  290. package/dist/core/cache-warm-benchmark.d.ts +0 -21
  291. package/dist/core/cache-warm-benchmark.js +0 -170
  292. package/dist/core/cache-warm-benchmark.js.map +0 -1
  293. package/dist/core/fast-apply-benchmark.d.ts +0 -25
  294. package/dist/core/fast-apply-benchmark.js +0 -284
  295. package/dist/core/fast-apply-benchmark.js.map +0 -1
  296. package/dist/core/hashline-edit-benchmark.d.ts +0 -88
  297. package/dist/core/hashline-edit-benchmark.js +0 -518
  298. package/dist/core/hashline-edit-benchmark.js.map +0 -1
  299. package/dist/core/semantic-search-benchmark.d.ts +0 -36
  300. package/dist/core/semantic-search-benchmark.js +0 -211
  301. package/dist/core/semantic-search-benchmark.js.map +0 -1
  302. package/dist/core/speed-benchmark.d.ts +0 -132
  303. package/dist/core/speed-benchmark.js +0 -410
  304. package/dist/core/speed-benchmark.js.map +0 -1
  305. package/dist/ui/activity-phrases.d.ts +0 -10
  306. package/dist/ui/activity-phrases.js +0 -184
  307. package/dist/ui/activity-phrases.js.map +0 -1
  308. package/dist/ui/components/PlanApproval.d.ts +0 -7
  309. package/dist/ui/components/PlanApproval.js +0 -60
  310. package/dist/ui/components/PlanApproval.js.map +0 -1
  311. package/dist/ui/components/PlanBanner.d.ts +0 -5
  312. package/dist/ui/components/PlanBanner.js +0 -31
  313. package/dist/ui/components/PlanBanner.js.map +0 -1
  314. package/dist/ui/components/PlanProgress.d.ts +0 -6
  315. package/dist/ui/components/PlanProgress.js +0 -30
  316. package/dist/ui/components/PlanProgress.js.map +0 -1
  317. package/dist/ui/hooks/useMinDisplayTime.d.ts +0 -10
  318. package/dist/ui/hooks/useMinDisplayTime.js +0 -34
  319. package/dist/ui/hooks/useMinDisplayTime.js.map +0 -1
  320. package/dist/ui/hooks/useSessionManager.d.ts +0 -12
  321. package/dist/ui/hooks/useSessionManager.js +0 -43
  322. package/dist/ui/hooks/useSessionManager.js.map +0 -1
  323. package/dist/ui/hooks/useSlashCommands.d.ts +0 -6
  324. package/dist/ui/hooks/useSlashCommands.js +0 -11
  325. package/dist/ui/hooks/useSlashCommands.js.map +0 -1
  326. package/dist/ui/terminal-history-spacing.d.ts +0 -1
  327. package/dist/ui/terminal-history-spacing.js +0 -2
  328. package/dist/ui/terminal-history-spacing.js.map +0 -1
  329. package/dist/ui/utils/markdown-cache.d.ts +0 -10
  330. package/dist/ui/utils/markdown-cache.js +0 -58
  331. package/dist/ui/utils/markdown-cache.js.map +0 -1
  332. package/dist/ui/utils/token-to-ansi.d.ts +0 -8
  333. package/dist/ui/utils/token-to-ansi.js +0 -323
  334. package/dist/ui/utils/token-to-ansi.js.map +0 -1
@@ -0,0 +1,232 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { loadTasksSync, saveTasksSync, pruneDoneTasksSync, } from "../core/task-store.js";
3
+ import { readChecklistSnapshot } from "../core/checklist-snapshot.js";
4
+ import { log } from "../core/logger.js";
5
+ import { RADIO_STATIONS, getCurrentStation, getRadioVolume, playRadio, setRadioVolume, stopRadio, } from "../core/radio.js";
6
+ import { readBody, json } from "./http.js";
7
+ export function handleTaskRoutes(ctx, req, res, url, method) {
8
+ if (method === "GET" && url === "/tasks") {
9
+ json(res, 200, { tasks: pruneDoneTasksSync(ctx.cwd) });
10
+ return true;
11
+ }
12
+ if (method === "GET" && url === "/checklist") {
13
+ const controller = new AbortController();
14
+ res.once("close", () => controller.abort());
15
+ void (async () => {
16
+ try {
17
+ const result = await readChecklistSnapshot(ctx.cwd, new Date(), controller.signal);
18
+ if (res.destroyed)
19
+ return;
20
+ if (!result.ok) {
21
+ log("WARN", "app-sidecar", "checklist read failed", { error: result.error });
22
+ json(res, 500, { error: result.error });
23
+ return;
24
+ }
25
+ json(res, 200, result.value);
26
+ }
27
+ catch (error) {
28
+ log("WARN", "app-sidecar", "checklist snapshot failed", { error: String(error) });
29
+ if (!res.destroyed)
30
+ json(res, 500, { error: "Could not read the project checklist" });
31
+ }
32
+ })();
33
+ return true;
34
+ }
35
+ // ── Radio (app-wide) ──────────────────────────────────────
36
+ // Radio is now APP-WIDE: all windows share one daemon process, and the
37
+ // player lives in `core/radio.ts` module-level singletons (one stream for
38
+ // the whole app). Any window's /radio reads/controls that single stream —
39
+ // starting a station in one window replaces whatever was playing, and every
40
+ // window's footer reflects the same `current`. This intentionally prevents
41
+ // duplicate audio across windows (the original per-window goal), now for
42
+ // free. (To restore per-window radio, key playback by sessionId.)
43
+ if (method === "GET" && url === "/radio") {
44
+ json(res, 200, {
45
+ stations: RADIO_STATIONS,
46
+ current: getCurrentStation(),
47
+ volume: getRadioVolume(),
48
+ });
49
+ return true;
50
+ }
51
+ if (method === "POST" && url === "/radio/volume") {
52
+ void readBody(req, res).then((raw) => {
53
+ if (raw === null)
54
+ return;
55
+ let volume;
56
+ try {
57
+ volume = Number(JSON.parse(raw).volume);
58
+ }
59
+ catch {
60
+ json(res, 400, { error: "invalid JSON body" });
61
+ return;
62
+ }
63
+ if (!Number.isFinite(volume)) {
64
+ json(res, 400, { error: "volume must be a number" });
65
+ return;
66
+ }
67
+ const result = setRadioVolume(volume);
68
+ if (!result.ok) {
69
+ json(res, 400, { error: result.error ?? "Radio volume failed to update." });
70
+ return;
71
+ }
72
+ json(res, 200, { current: getCurrentStation(), volume: getRadioVolume() });
73
+ });
74
+ return true;
75
+ }
76
+ if (method === "POST" && url === "/radio") {
77
+ void readBody(req, res).then((raw) => {
78
+ if (raw === null)
79
+ return;
80
+ let station;
81
+ try {
82
+ station = JSON.parse(raw).station ?? "";
83
+ }
84
+ catch {
85
+ json(res, 400, { error: "invalid JSON body" });
86
+ return;
87
+ }
88
+ if (!station || station === "off") {
89
+ stopRadio();
90
+ json(res, 200, { current: null });
91
+ return;
92
+ }
93
+ const result = playRadio(station);
94
+ if (!result.ok) {
95
+ json(res, 400, { error: result.error ?? "Radio failed to start." });
96
+ return;
97
+ }
98
+ json(res, 200, { current: getCurrentStation() });
99
+ });
100
+ return true;
101
+ }
102
+ if (method === "POST" && url === "/tasks/run") {
103
+ void readBody(req, res).then((raw) => {
104
+ if (raw === null)
105
+ return;
106
+ let id;
107
+ let all;
108
+ try {
109
+ const body = JSON.parse(raw);
110
+ id = body.id ?? null;
111
+ all = Boolean(body.all);
112
+ }
113
+ catch {
114
+ json(res, 400, { error: "invalid JSON body" });
115
+ return;
116
+ }
117
+ if (ctx.running) {
118
+ json(res, 409, { error: "cannot run a task while the agent is running" });
119
+ return;
120
+ }
121
+ json(res, 202, { accepted: true });
122
+ void ctx.runTasks(id, all);
123
+ });
124
+ return true;
125
+ }
126
+ if (method === "POST" && url === "/tasks/add") {
127
+ void readBody(req, res).then((raw) => {
128
+ if (raw === null)
129
+ return;
130
+ let title;
131
+ let prompt;
132
+ try {
133
+ const body = JSON.parse(raw);
134
+ title = (body.title ?? "").trim();
135
+ prompt = (body.prompt ?? "").trim();
136
+ }
137
+ catch {
138
+ json(res, 400, { error: "invalid JSON body" });
139
+ return;
140
+ }
141
+ if (!title) {
142
+ json(res, 400, { error: "missing task title" });
143
+ return;
144
+ }
145
+ const tasks = loadTasksSync(ctx.cwd);
146
+ const newTask = {
147
+ id: randomUUID(),
148
+ title,
149
+ prompt: prompt || title,
150
+ status: "pending",
151
+ createdAt: new Date().toISOString(),
152
+ };
153
+ const next = [...tasks, newTask];
154
+ saveTasksSync(ctx.cwd, next);
155
+ ctx.broadcast("tasks_list", { tasks: next });
156
+ json(res, 200, { tasks: next });
157
+ });
158
+ return true;
159
+ }
160
+ if (method === "POST" && url === "/tasks/update") {
161
+ void readBody(req, res).then((raw) => {
162
+ if (raw === null)
163
+ return;
164
+ let id;
165
+ let status;
166
+ let title;
167
+ let prompt;
168
+ try {
169
+ const body = JSON.parse(raw);
170
+ id = (body.id ?? "").trim();
171
+ status = body.status;
172
+ title = body.title;
173
+ prompt = body.prompt;
174
+ }
175
+ catch {
176
+ json(res, 400, { error: "invalid JSON body" });
177
+ return;
178
+ }
179
+ if (!id) {
180
+ json(res, 400, { error: "missing task id" });
181
+ return;
182
+ }
183
+ if (status && status !== "pending" && status !== "in-progress" && status !== "done") {
184
+ json(res, 400, { error: `invalid status: ${status}` });
185
+ return;
186
+ }
187
+ const tasks = loadTasksSync(ctx.cwd);
188
+ const task = tasks.find((t) => t.id === id || t.id.startsWith(id));
189
+ if (!task) {
190
+ json(res, 404, { error: `no task found matching id "${id}"` });
191
+ return;
192
+ }
193
+ const next = tasks.map((t) => t.id === task.id
194
+ ? {
195
+ ...t,
196
+ ...(status ? { status: status } : {}),
197
+ ...(typeof title === "string" && title.trim() ? { title: title.trim() } : {}),
198
+ ...(typeof prompt === "string" && prompt.trim() ? { prompt: prompt.trim() } : {}),
199
+ }
200
+ : t);
201
+ saveTasksSync(ctx.cwd, next);
202
+ ctx.broadcast("tasks_list", { tasks: next });
203
+ json(res, 200, { tasks: next });
204
+ });
205
+ return true;
206
+ }
207
+ if (method === "POST" && url === "/tasks/delete") {
208
+ void readBody(req, res).then((raw) => {
209
+ if (raw === null)
210
+ return;
211
+ let id;
212
+ try {
213
+ id = JSON.parse(raw).id ?? "";
214
+ }
215
+ catch {
216
+ json(res, 400, { error: "invalid JSON body" });
217
+ return;
218
+ }
219
+ if (!id.trim()) {
220
+ json(res, 400, { error: "missing task id" });
221
+ return;
222
+ }
223
+ const remaining = loadTasksSync(ctx.cwd).filter((t) => t.id !== id && !t.id.startsWith(id));
224
+ saveTasksSync(ctx.cwd, remaining);
225
+ ctx.broadcast("tasks_list", { tasks: remaining });
226
+ json(res, 200, { tasks: remaining });
227
+ });
228
+ return true;
229
+ }
230
+ return false;
231
+ }
232
+ //# sourceMappingURL=task-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-routes.js","sourceRoot":"","sources":["../../src/app-sidecar/task-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,aAAa,EACb,aAAa,EACb,kBAAkB,GAEnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,cAAc,EACd,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG3C,MAAM,UAAU,gBAAgB,CAC9B,GAAwB,EACxB,GAAyB,EACzB,GAAwB,EACxB,GAAW,EACX,MAAc;IAEd,IAAI,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;gBACnF,IAAI,GAAG,CAAC,SAAS;oBAAE,OAAO;gBAC1B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBACf,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,uBAAuB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;oBAC7E,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;oBACxC,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,2BAA2B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAClF,IAAI,CAAC,GAAG,CAAC,SAAS;oBAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;YACxF,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6DAA6D;IAC7D,uEAAuE;IACvE,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,2EAA2E;IAC3E,yEAAyE;IACzE,kEAAkE;IAClE,IAAI,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE;YACb,QAAQ,EAAE,cAAc;YACxB,OAAO,EAAE,iBAAiB,EAAE;YAC5B,MAAM,EAAE,cAAc,EAAE;SACzB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;QACjD,KAAK,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO;YACzB,IAAI,MAAc,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC,MAAM,CAAC,CAAC;YACnE,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBAC/C,OAAO;YACT,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7B,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YACD,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,gCAAgC,EAAE,CAAC,CAAC;gBAC5E,OAAO;YACT,CAAC;YACD,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC1C,KAAK,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO;YACzB,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC,OAAO,IAAI,EAAE,CAAC;YACpE,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBAC/C,OAAO;YACT,CAAC;YACD,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;gBAClC,SAAS,EAAE,CAAC;gBACZ,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YACD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,wBAAwB,EAAE,CAAC,CAAC;gBACpE,OAAO;YACT,CAAC;YACD,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;QAC9C,KAAK,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO;YACzB,IAAI,EAAiB,CAAC;YACtB,IAAI,GAAY,CAAC;YACjB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0C,CAAC;gBACtE,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC;gBACrB,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBAC/C,OAAO;YACT,CAAC;YACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAChB,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,8CAA8C,EAAE,CAAC,CAAC;gBAC1E,OAAO;YACT,CAAC;YACD,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACnC,KAAK,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;QAC9C,KAAK,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO;YACzB,IAAI,KAAa,CAAC;YAClB,IAAI,MAAc,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwC,CAAC;gBACpE,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAClC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBAC/C,OAAO;YACT,CAAC;YACD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG;gBACd,EAAE,EAAE,UAAU,EAAE;gBAChB,KAAK;gBACL,MAAM,EAAE,MAAM,IAAI,KAAK;gBACvB,MAAM,EAAE,SAAkB;gBAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC;YACF,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC;YACjC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;QACjD,KAAK,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO;YACzB,IAAI,EAAU,CAAC;YACf,IAAI,MAA0B,CAAC;YAC/B,IAAI,KAAyB,CAAC;YAC9B,IAAI,MAA0B,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAK1B,CAAC;gBACF,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC5B,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;gBACrB,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;gBACnB,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBAC/C,OAAO;YACT,CAAC;YACD,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;gBAC7C,OAAO;YACT,CAAC;YACD,IAAI,MAAM,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,aAAa,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACpF,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,MAAM,EAAE,EAAE,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;YACnE,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,8BAA8B,EAAE,GAAG,EAAE,CAAC,CAAC;gBAC/D,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3B,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE;gBACd,CAAC,CAAC;oBACE,GAAG,CAAC;oBACJ,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACnD,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7E,GAAG,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAClF;gBACH,CAAC,CAAC,CAAC,CACN,CAAC;YACF,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;QACjD,KAAK,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO;YACzB,IAAI,EAAU,CAAC;YACf,IAAI,CAAC;gBACH,EAAE,GAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC,EAAE,IAAI,EAAE,CAAC;YACrD,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBAC/C,OAAO;YACT,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;gBACf,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;gBAC7C,OAAO;YACT,CAAC;YACD,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5F,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAClC,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAClD,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type SubscriptionUsageProvider, type SubscriptionUsageSnapshot } from "@prestyj/core";
2
+ import type { AuthStorage } from "../core/auth-storage.js";
3
+ export type UsageResult = (SubscriptionUsageSnapshot & {
4
+ connected: true;
5
+ error?: never;
6
+ stale?: boolean;
7
+ }) | {
8
+ provider: SubscriptionUsageProvider;
9
+ displayName: string;
10
+ connected: boolean;
11
+ windows: [];
12
+ fetchedAt: number;
13
+ error?: string;
14
+ stale?: boolean;
15
+ };
16
+ /** Daemon-level subscription-usage fetcher with caching, 429 backoff and last-good replay. */
17
+ export declare function createUsageService(auth: AuthStorage): {
18
+ subscriptionUsage: (provider: SubscriptionUsageProvider) => Promise<UsageResult>;
19
+ };
@@ -0,0 +1,153 @@
1
+ import { fetchSubscriptionUsage, SubscriptionUsageError, oauthStorageKey, } from "@prestyj/core";
2
+ import { log } from "../core/logger.js";
3
+ /** Daemon-level subscription-usage fetcher with caching, 429 backoff and last-good replay. */
4
+ export function createUsageService(auth) {
5
+ const usageCache = new Map();
6
+ const usageRequests = new Map();
7
+ // Last snapshot that actually carried windows, per provider. Replayed while a
8
+ // fetch is failing so the title meter never blinks out of existence. Bounded
9
+ // by USAGE_LAST_GOOD_MAX_AGE_MS — a provider that never recovers must stop
10
+ // reporting rather than freeze a percentage (and a long-past reset time) on
11
+ // screen forever. The 429 backoff alone runs to 24h, far past any usefulness.
12
+ const usageLastGood = new Map();
13
+ const USAGE_LAST_GOOD_MAX_AGE_MS = 30 * 60_000;
14
+ // 429 backoff: quota endpoints are auxiliary UI data. Honor Retry-After when
15
+ // provided; otherwise retain the unavailable snapshot for 30 minutes. Clamp
16
+ // the provider value so a malformed header can neither hammer the endpoint
17
+ // nor suppress usage data forever.
18
+ const usageRateLimitedUntil = new Map();
19
+ // Providers currently in a logged rate-limit episode (cleared on success).
20
+ const usageRateLimitLogged = new Set();
21
+ const USAGE_RATE_LIMIT_FALLBACK_BACKOFF_MS = 30 * 60_000;
22
+ const USAGE_RATE_LIMIT_MIN_BACKOFF_MS = 60_000;
23
+ const USAGE_RATE_LIMIT_MAX_BACKOFF_MS = 24 * 60 * 60_000;
24
+ function clearUsageRateLimit(provider) {
25
+ usageRateLimitedUntil.delete(provider);
26
+ if (usageRateLimitLogged.delete(provider)) {
27
+ log("INFO", "app-sidecar", "subscription usage recovered", { provider });
28
+ }
29
+ }
30
+ async function fetchUsageProvider(provider) {
31
+ const displayName = provider === "anthropic" ? "Anthropic" : provider === "openai" ? "Codex" : "Kimi";
32
+ // Kimi plan usage is tracked on the OAuth credential specifically — the
33
+ // Moonshot platform API key is metered per-token, not per plan window.
34
+ const authKey = oauthStorageKey(provider) ?? provider;
35
+ if (!(await auth.hasProviderAuth(authKey))) {
36
+ // Logged out: drop the replay cache so a later login on a DIFFERENT
37
+ // account can never inherit the previous one's numbers.
38
+ usageLastGood.delete(provider);
39
+ return { provider, displayName, connected: false, windows: [], fetchedAt: Date.now() };
40
+ }
41
+ try {
42
+ let credentials = await auth.resolveCredentials(authKey);
43
+ try {
44
+ const snapshot = {
45
+ ...(await fetchSubscriptionUsage(provider, credentials)),
46
+ connected: true,
47
+ };
48
+ clearUsageRateLimit(provider);
49
+ return snapshot;
50
+ }
51
+ catch (error) {
52
+ // A provider can revoke an access token before its stored expiry. Refresh
53
+ // once on 401, matching inference auth recovery, then retry the usage call.
54
+ if (error instanceof SubscriptionUsageError && error.status === 401) {
55
+ // Name the rejected token. This poller runs on a timer alongside live
56
+ // agent runs, so an unconditional refresh here would invalidate the
57
+ // token those runs are holding and fail them mid-turn — a background
58
+ // status check must never be able to log out the foreground.
59
+ credentials = await auth.resolveCredentials(authKey, {
60
+ forceRefresh: true,
61
+ rejectedToken: credentials.accessToken,
62
+ });
63
+ const snapshot = {
64
+ ...(await fetchSubscriptionUsage(provider, credentials)),
65
+ connected: true,
66
+ };
67
+ clearUsageRateLimit(provider);
68
+ return snapshot;
69
+ }
70
+ throw error;
71
+ }
72
+ }
73
+ catch (error) {
74
+ const message = error instanceof Error ? error.message : String(error);
75
+ if (error instanceof SubscriptionUsageError && error.status === 429) {
76
+ const backoffMs = Math.min(USAGE_RATE_LIMIT_MAX_BACKOFF_MS, Math.max(USAGE_RATE_LIMIT_MIN_BACKOFF_MS, error.retryAfterMs ?? USAGE_RATE_LIMIT_FALLBACK_BACKOFF_MS));
77
+ usageRateLimitedUntil.set(provider, Date.now() + backoffMs);
78
+ // Rate limits on this auxiliary endpoint are expected (every GG process
79
+ // on the machine polls it) and already handled by the backoff plus the
80
+ // last-good replay. Log the transition, not every retry.
81
+ if (!usageRateLimitLogged.has(provider)) {
82
+ usageRateLimitLogged.add(provider);
83
+ log("INFO", "app-sidecar", "subscription usage rate-limited; backing off", {
84
+ provider,
85
+ backoffMs: String(backoffMs),
86
+ });
87
+ }
88
+ }
89
+ else {
90
+ log("WARN", "app-sidecar", "subscription usage fetch failed", { provider, message });
91
+ }
92
+ const connected = await auth.hasProviderAuth(authKey);
93
+ // Transient failures (notably the 429s these auxiliary quota endpoints
94
+ // hand out) must not blank the meter. Keep serving the last good
95
+ // snapshot, flagged `stale`, so the bar stays put instead of flickering
96
+ // out for the whole backoff window and back in on the next success.
97
+ // Past the max age it's dropped — no data beats confidently wrong data.
98
+ const lastGood = usageLastGood.get(provider);
99
+ if (lastGood && Date.now() - lastGood.fetchedAt >= USAGE_LAST_GOOD_MAX_AGE_MS) {
100
+ usageLastGood.delete(provider);
101
+ }
102
+ else if (connected && lastGood) {
103
+ return { ...lastGood, stale: true };
104
+ }
105
+ return {
106
+ provider,
107
+ displayName,
108
+ connected,
109
+ windows: [],
110
+ fetchedAt: Date.now(),
111
+ error: connected ? "Usage is temporarily unavailable." : undefined,
112
+ };
113
+ }
114
+ }
115
+ async function subscriptionUsage(provider) {
116
+ const cached = usageCache.get(provider);
117
+ if (cached && cached.expiresAt > Date.now())
118
+ return cached.result;
119
+ const inFlight = usageRequests.get(provider);
120
+ if (inFlight)
121
+ return inFlight;
122
+ const request = fetchUsageProvider(provider);
123
+ usageRequests.set(provider, request);
124
+ try {
125
+ const result = await request;
126
+ // Never re-store a replay — it would keep its original `fetchedAt`, but
127
+ // writing it back muddies the "last GOOD" contract for no gain.
128
+ if (result.connected && !result.error && !result.stale && result.windows.length > 0) {
129
+ usageLastGood.set(provider, result);
130
+ }
131
+ // Anthropic can return utilization before it assigns reset timestamps
132
+ // (notably before the account's first active request). Retry that partial
133
+ // snapshot quickly; complete snapshots keep the normal one-minute cache.
134
+ const missingReset = result.connected &&
135
+ result.windows.length > 0 &&
136
+ result.windows.some((window) => window.resetsAt === undefined);
137
+ const rateLimitedUntil = usageRateLimitedUntil.get(provider) ?? 0;
138
+ usageCache.set(provider, {
139
+ result,
140
+ expiresAt: rateLimitedUntil > Date.now()
141
+ ? rateLimitedUntil
142
+ : Date.now() + (missingReset ? 10_000 : 60_000),
143
+ });
144
+ return result;
145
+ }
146
+ finally {
147
+ if (usageRequests.get(provider) === request)
148
+ usageRequests.delete(provider);
149
+ }
150
+ }
151
+ return { subscriptionUsage };
152
+ }
153
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/app-sidecar/usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type http from "node:http";
2
+ import type { SessionRouteContext } from "./route-context.js";
3
+ export declare function handleWorkspaceRoutes(ctx: SessionRouteContext, req: http.IncomingMessage, res: http.ServerResponse, url: string, method: string): boolean;