quoxcli 0.2.0 → 0.4.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.
Files changed (442) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -0
  3. package/bin/quox.js +99 -126
  4. package/lib/api/endpoints/actions.js +15 -0
  5. package/lib/api/endpoints/admin.js +46 -0
  6. package/lib/api/endpoints/agent-schedules.js +26 -0
  7. package/lib/api/endpoints/agents.js +7 -0
  8. package/lib/api/endpoints/assistants.js +12 -0
  9. package/lib/api/endpoints/away.js +15 -0
  10. package/lib/api/endpoints/blog.js +16 -0
  11. package/lib/api/endpoints/chat.js +14 -0
  12. package/lib/api/endpoints/contactsq.js +6 -0
  13. package/lib/api/endpoints/conversations.js +14 -0
  14. package/lib/api/endpoints/devServerRegistry.js +25 -0
  15. package/lib/api/endpoints/engagement.js +26 -0
  16. package/lib/api/endpoints/evidence.js +20 -0
  17. package/lib/api/endpoints/executions.js +13 -0
  18. package/lib/api/endpoints/fetchAllowlist.js +27 -0
  19. package/lib/api/endpoints/files.js +14 -0
  20. package/lib/api/endpoints/hat.js +44 -0
  21. package/lib/api/endpoints/inbox.js +20 -0
  22. package/lib/api/endpoints/index.js +26 -0
  23. package/lib/api/endpoints/loops.js +26 -0
  24. package/lib/api/endpoints/memory.js +19 -0
  25. package/lib/api/endpoints/mind.js +13 -0
  26. package/lib/api/endpoints/mon.js +179 -0
  27. package/lib/api/endpoints/objectives.js +12 -0
  28. package/lib/api/endpoints/plugins.js +18 -0
  29. package/lib/api/endpoints/presence.js +33 -0
  30. package/lib/api/endpoints/quoxplan.js +7 -0
  31. package/lib/api/endpoints/quoxseo.js +12 -0
  32. package/lib/api/endpoints/router.js +17 -0
  33. package/lib/api/endpoints/safety.js +7 -0
  34. package/lib/api/endpoints/server.js +21 -0
  35. package/lib/api/endpoints/setup.js +6 -0
  36. package/lib/api/endpoints/skills.js +20 -0
  37. package/lib/api/endpoints/stepup.js +20 -0
  38. package/lib/api/endpoints/teams.js +2 -2
  39. package/lib/api/endpoints/triggers.js +26 -0
  40. package/lib/api/endpoints/v1.js +120 -0
  41. package/lib/api/endpoints/ward.js +7 -0
  42. package/lib/api/endpoints/workflows.js +7 -0
  43. package/lib/api/endpoints/x.js +8 -0
  44. package/lib/commands/actions.js +131 -0
  45. package/lib/commands/admin.js +16 -0
  46. package/lib/commands/agent.js +170 -27
  47. package/lib/commands/agentAttach.js +140 -13
  48. package/lib/commands/approvals.js +78 -1
  49. package/lib/commands/aside.js +24 -0
  50. package/lib/commands/ask.js +146 -0
  51. package/lib/commands/assistant.js +59 -4
  52. package/lib/commands/auth.js +8 -2
  53. package/lib/commands/backup.js +8 -4
  54. package/lib/commands/blog.js +110 -0
  55. package/lib/commands/brain.js +105 -14
  56. package/lib/commands/build.js +19 -5
  57. package/lib/commands/chat.js +180 -26
  58. package/lib/commands/chatCompanion.js +27 -0
  59. package/lib/commands/chatState.js +45 -0
  60. package/lib/commands/claude.js +35 -38
  61. package/lib/commands/contacts.js +134 -4
  62. package/lib/commands/contactsSendAt.js +21 -0
  63. package/lib/commands/conversation.js +35 -4
  64. package/lib/commands/dashboard.js +43 -0
  65. package/lib/commands/department.js +28 -7
  66. package/lib/commands/devResident.js +15 -3
  67. package/lib/commands/devSupervisor.js +13 -1
  68. package/lib/commands/discord.js +75 -39
  69. package/lib/commands/done.js +98 -28
  70. package/lib/commands/engagement.js +107 -6
  71. package/lib/commands/evidence.js +154 -0
  72. package/lib/commands/ext.js +23 -0
  73. package/lib/commands/fetchAllowlist.js +71 -0
  74. package/lib/commands/file.js +38 -1
  75. package/lib/commands/fleet.js +336 -4
  76. package/lib/commands/governance.js +12 -3
  77. package/lib/commands/gripe.js +44 -13
  78. package/lib/commands/hat.js +254 -9
  79. package/lib/commands/helpers.js +18 -1
  80. package/lib/commands/hyperion.js +58 -0
  81. package/lib/commands/image.js +68 -0
  82. package/lib/commands/inbox.js +74 -23
  83. package/lib/commands/kuma.js +1050 -0
  84. package/lib/commands/kumaSla.js +174 -0
  85. package/lib/commands/licence.js +52 -155
  86. package/lib/commands/loop.js +291 -0
  87. package/lib/commands/lucid.js +10 -4
  88. package/lib/commands/memory.js +85 -8
  89. package/lib/commands/mind.js +71 -0
  90. package/lib/commands/mon.js +69 -2
  91. package/lib/commands/monitoring.js +1 -1
  92. package/lib/commands/motion.js +2 -2
  93. package/lib/commands/nucleus.js +48 -17
  94. package/lib/commands/objective.js +59 -1
  95. package/lib/commands/offload.js +89 -0
  96. package/lib/commands/onboard.js +2 -1
  97. package/lib/commands/org.js +30 -3
  98. package/lib/commands/peek.js +28 -0
  99. package/lib/commands/plan.js +38 -0
  100. package/lib/commands/plugin.js +110 -0
  101. package/lib/commands/presence.js +89 -0
  102. package/lib/commands/provider.js +217 -0
  103. package/lib/commands/qlarity.js +19 -3
  104. package/lib/commands/quoxchat.js +13 -4
  105. package/lib/commands/quoxseo.js +69 -0
  106. package/lib/commands/reach.js +2 -1
  107. package/lib/commands/research.js +79 -0
  108. package/lib/commands/router.js +77 -0
  109. package/lib/commands/rows.js +367 -0
  110. package/lib/commands/run.js +82 -10
  111. package/lib/commands/scope.js +2 -2
  112. package/lib/commands/server.js +405 -0
  113. package/lib/commands/setup.js +33 -7
  114. package/lib/commands/shortcut.js +41 -0
  115. package/lib/commands/skills.js +68 -9
  116. package/lib/commands/slot.js +260 -7
  117. package/lib/commands/status.js +1 -1
  118. package/lib/commands/team.js +3 -1
  119. package/lib/commands/tips.js +23 -0
  120. package/lib/commands/tool.js +133 -45
  121. package/lib/commands/trace.js +12 -7
  122. package/lib/commands/trigger.js +95 -0
  123. package/lib/commands/update.js +46 -0
  124. package/lib/commands/vault.js +31 -8
  125. package/lib/commands/vm.js +237 -0
  126. package/lib/commands/voice.js +34 -3
  127. package/lib/commands/volt.js +45 -3
  128. package/lib/commands/walkthrough.js +32 -0
  129. package/lib/commands/watch.js +73 -21
  130. package/lib/commands/welcome.js +14 -0
  131. package/lib/commands/workflow.js +189 -32
  132. package/lib/commands/x.js +13 -4
  133. package/lib/commands/youtube.js +172 -0
  134. package/lib/core/actingAs.js +2 -2
  135. package/lib/core/actionItems.js +115 -0
  136. package/lib/core/activeSummary.js +186 -0
  137. package/lib/core/agentAlias.js +2 -0
  138. package/lib/core/agentFamilies.js +7 -0
  139. package/lib/core/aside.js +54 -0
  140. package/lib/core/askDecision.js +60 -0
  141. package/lib/core/auth.js +164 -13
  142. package/lib/core/callerSource.js +1 -1
  143. package/lib/core/cliBuild.js +62 -0
  144. package/lib/core/client.js +152 -35
  145. package/lib/core/commandRegistrars.js +130 -0
  146. package/lib/core/config.js +143 -25
  147. package/lib/core/customHats.js +168 -0
  148. package/lib/core/doneEngineFetch.js +8 -0
  149. package/lib/core/errors.js +329 -20
  150. package/lib/core/findingReconcile.js +90 -0
  151. package/lib/core/global-flags.js +105 -5
  152. package/lib/core/governedSession.js +1 -3
  153. package/lib/core/hyperion.js +102 -0
  154. package/lib/core/inboxResolution.js +65 -0
  155. package/lib/core/lazyCommands.js +4 -1
  156. package/lib/core/liveSessionsReport.js +1 -1
  157. package/lib/core/loopGlyph.js +97 -0
  158. package/lib/core/offload.js +533 -0
  159. package/lib/core/org-override.js +1 -1
  160. package/lib/core/orgResolve.js +70 -0
  161. package/lib/core/output.js +11 -11
  162. package/lib/core/peek.js +126 -0
  163. package/lib/core/profileUsers.js +51 -0
  164. package/lib/core/promptCancel.js +18 -0
  165. package/lib/core/repoPath.js +11 -0
  166. package/lib/core/residentSeed.js +3 -1
  167. package/lib/core/rootOptions.js +39 -0
  168. package/lib/core/router.js +168 -0
  169. package/lib/core/selfUpdate.js +188 -0
  170. package/lib/core/sessionHeartbeat.js +12 -8
  171. package/lib/core/sessionsOverview.js +64 -0
  172. package/lib/core/shortcut.js +83 -0
  173. package/lib/core/slotKeeper.js +248 -3
  174. package/lib/core/slotWake.js +120 -0
  175. package/lib/core/supervisorEngine.js +71 -2
  176. package/lib/core/version.js +1 -1
  177. package/lib/core/vm.js +366 -0
  178. package/lib/core/vmTui.js +86 -0
  179. package/lib/core/walkthrough.js +35 -0
  180. package/lib/dragon/companionView.js +34 -0
  181. package/lib/dragon/frames.js +118 -0
  182. package/lib/dragon/jobs.js +123 -0
  183. package/lib/dragon/renderWorker.js +15 -0
  184. package/lib/dragon/select.js +72 -0
  185. package/lib/evidence/bundleExport.js +47 -0
  186. package/lib/evidence/bundleVerify.js +77 -0
  187. package/lib/hyperion/deck.js +29 -0
  188. package/lib/lucid/LucidCard.jsx +68 -0
  189. package/lib/lucid/LucidIntro.jsx +45 -58
  190. package/lib/lucid/cards.js +86 -0
  191. package/lib/lucid/markdown.js +81 -0
  192. package/lib/lucid/motion.js +56 -0
  193. package/lib/quoxon/EXTENSIONS.md +23 -0
  194. package/lib/quoxon/activity.js +14 -2
  195. package/lib/quoxon/aocl.js +117 -0
  196. package/lib/quoxon/api.js +690 -25
  197. package/lib/quoxon/app.js +3586 -250
  198. package/lib/quoxon/approvalFacts.js +96 -0
  199. package/lib/quoxon/approvalSentence.js +44 -0
  200. package/lib/quoxon/approvalsView.js +384 -0
  201. package/lib/quoxon/asideView.js +40 -0
  202. package/lib/quoxon/ask.js +121 -0
  203. package/lib/quoxon/away.js +52 -0
  204. package/lib/quoxon/bang.js +224 -0
  205. package/lib/quoxon/bulkRisk.js +17 -0
  206. package/lib/quoxon/capabilities.js +13 -6
  207. package/lib/quoxon/cells.js +53 -0
  208. package/lib/quoxon/commandShort.js +124 -0
  209. package/lib/quoxon/commands.js +429 -39
  210. package/lib/quoxon/connect.js +210 -23
  211. package/lib/quoxon/connectCard.js +19 -2
  212. package/lib/quoxon/consent.js +86 -0
  213. package/lib/quoxon/copy.js +4 -3
  214. package/lib/quoxon/countdownLine.js +20 -0
  215. package/lib/quoxon/deck.js +30 -0
  216. package/lib/quoxon/demo.autoplay.js +29 -0
  217. package/lib/quoxon/demo.fixtures.js +1 -1
  218. package/lib/quoxon/demo.js +46 -3
  219. package/lib/quoxon/devObserver.js +20 -0
  220. package/lib/quoxon/dividerAocl.js +192 -0
  221. package/lib/quoxon/dividerRule.js +57 -0
  222. package/lib/quoxon/dragonCompanion.js +255 -0
  223. package/lib/quoxon/dragonModes.js +151 -0
  224. package/lib/quoxon/dragonMoments.js +82 -0
  225. package/lib/quoxon/dragonReads.js +68 -0
  226. package/lib/quoxon/dragonView.js +41 -0
  227. package/lib/quoxon/earlyInput.js +40 -0
  228. package/lib/quoxon/echo.js +15 -0
  229. package/lib/quoxon/egg.js +2 -2
  230. package/lib/quoxon/events.js +266 -26
  231. package/lib/quoxon/extensions.js +276 -0
  232. package/lib/quoxon/feedback.js +50 -0
  233. package/lib/quoxon/gallery.js +21 -7
  234. package/lib/quoxon/handoffOffer.js +78 -0
  235. package/lib/quoxon/hatSwitch.js +37 -0
  236. package/lib/quoxon/headless.js +161 -0
  237. package/lib/quoxon/hostUrls.js +41 -0
  238. package/lib/quoxon/inboxView.js +79 -0
  239. package/lib/quoxon/indicator.js +6 -2
  240. package/lib/quoxon/installCli.js +79 -0
  241. package/lib/quoxon/intent.js +12 -1
  242. package/lib/quoxon/keys.js +51 -8
  243. package/lib/quoxon/launcher.js +103 -0
  244. package/lib/quoxon/loopCard.js +456 -0
  245. package/lib/quoxon/loopCards.js +180 -0
  246. package/lib/quoxon/loopStream.js +87 -0
  247. package/lib/quoxon/main.js +101 -160
  248. package/lib/quoxon/markdown.js +45 -21
  249. package/lib/quoxon/markdownSettle.js +19 -0
  250. package/lib/quoxon/matrixDomains.json +46 -0
  251. package/lib/quoxon/mentions.js +90 -0
  252. package/lib/quoxon/mind.js +103 -0
  253. package/lib/quoxon/mode.js +46 -0
  254. package/lib/quoxon/model.js +132 -26
  255. package/lib/quoxon/modelPrefs.js +345 -0
  256. package/lib/quoxon/motion/clock.js +3 -2
  257. package/lib/quoxon/motion/level.js +91 -0
  258. package/lib/quoxon/mouse.js +222 -0
  259. package/lib/quoxon/noai.js +57 -0
  260. package/lib/quoxon/objectiveOffer.js +82 -0
  261. package/lib/quoxon/objects/away.js +72 -0
  262. package/lib/quoxon/objects/fetch.js +17 -5
  263. package/lib/quoxon/objects/fleet.js +149 -0
  264. package/lib/quoxon/objects/health.js +186 -0
  265. package/lib/quoxon/objects/index.js +46 -7
  266. package/lib/quoxon/objects/mirror.js +137 -0
  267. package/lib/quoxon/objects/model.js +33 -0
  268. package/lib/quoxon/objects/peek.js +17 -0
  269. package/lib/quoxon/objects/proof.js +12 -4
  270. package/lib/quoxon/objects/prove.js +130 -0
  271. package/lib/quoxon/objects/replay.js +125 -0
  272. package/lib/quoxon/objects/sitrep.js +58 -0
  273. package/lib/quoxon/objects/view.js +11 -0
  274. package/lib/quoxon/onboarding/copy.js +32 -4
  275. package/lib/quoxon/onboarding/credential.js +17 -4
  276. package/lib/quoxon/onboarding/dockerOffer.js +45 -0
  277. package/lib/quoxon/onboarding/failureCause.js +33 -0
  278. package/lib/quoxon/onboarding/finish.js +15 -0
  279. package/lib/quoxon/onboarding/index.js +34 -7
  280. package/lib/quoxon/onboarding/installRunner.js +64 -5
  281. package/lib/quoxon/onboarding/preflight.js +17 -3
  282. package/lib/quoxon/onboarding/probe.js +65 -0
  283. package/lib/quoxon/onboarding/shortcutOffer.js +28 -0
  284. package/lib/quoxon/onboarding/view.js +76 -19
  285. package/lib/quoxon/orgLabel.js +10 -0
  286. package/lib/quoxon/orgSwitch.js +59 -0
  287. package/lib/quoxon/ownBroadcast.js +22 -0
  288. package/lib/quoxon/palette.js +43 -0
  289. package/lib/quoxon/planSteps.js +51 -0
  290. package/lib/quoxon/print.js +12 -5
  291. package/lib/quoxon/profileSwitch.js +53 -0
  292. package/lib/quoxon/promptHistory.js +41 -0
  293. package/lib/quoxon/providers.js +48 -0
  294. package/lib/quoxon/qart.js +20 -51
  295. package/lib/quoxon/qdragon.js +410 -0
  296. package/lib/quoxon/qdragonFly.js +62 -0
  297. package/lib/quoxon/qdragonScenes.js +282 -0
  298. package/lib/quoxon/qeyes.js +213 -0
  299. package/lib/quoxon/qmotion.js +75 -37
  300. package/lib/quoxon/render.js +740 -124
  301. package/lib/quoxon/resend.js +72 -0
  302. package/lib/quoxon/roster.js +117 -17
  303. package/lib/quoxon/route.js +6 -5
  304. package/lib/quoxon/rows.js +954 -0
  305. package/lib/quoxon/rowsStore.js +80 -0
  306. package/lib/quoxon/screenContext.js +150 -0
  307. package/lib/quoxon/screenFrames.js +254 -0
  308. package/lib/quoxon/serverChip.js +42 -0
  309. package/lib/quoxon/session.js +182 -2
  310. package/lib/quoxon/sessionDead.js +17 -0
  311. package/lib/quoxon/signin.js +125 -0
  312. package/lib/quoxon/slash/agents.js +112 -0
  313. package/lib/quoxon/slash/argSources.js +65 -0
  314. package/lib/quoxon/slash/args.js +65 -0
  315. package/lib/quoxon/slash/automate.js +89 -0
  316. package/lib/quoxon/slash/broadcast.js +140 -0
  317. package/lib/quoxon/slash/broadcastRun.js +108 -0
  318. package/lib/quoxon/slash/card.js +30 -0
  319. package/lib/quoxon/slash/challenge.js +114 -0
  320. package/lib/quoxon/slash/cliCommand.js +94 -0
  321. package/lib/quoxon/slash/cliLeaves.json +1023 -0
  322. package/lib/quoxon/slash/compact.js +1 -1
  323. package/lib/quoxon/slash/confirm.js +30 -0
  324. package/lib/quoxon/slash/crystallize.js +69 -0
  325. package/lib/quoxon/slash/dashboard.js +136 -0
  326. package/lib/quoxon/slash/draft.js +54 -0
  327. package/lib/quoxon/slash/evidenceCmd.js +34 -0
  328. package/lib/quoxon/slash/hatWalk.js +206 -0
  329. package/lib/quoxon/slash/inverses.js +77 -0
  330. package/lib/quoxon/slash/killer.js +24 -0
  331. package/lib/quoxon/slash/killerApi.js +16 -0
  332. package/lib/quoxon/slash/ledger.js +13 -8
  333. package/lib/quoxon/slash/listView.js +3 -1
  334. package/lib/quoxon/slash/modelCmd.js +261 -0
  335. package/lib/quoxon/slash/palette.js +22 -8
  336. package/lib/quoxon/slash/paletteController.js +117 -7
  337. package/lib/quoxon/slash/panels.js +21 -6
  338. package/lib/quoxon/slash/picker.js +20 -2
  339. package/lib/quoxon/slash/qpeCmd.js +35 -0
  340. package/lib/quoxon/slash/restart.js +95 -13
  341. package/lib/quoxon/slash/resume.js +18 -1
  342. package/lib/quoxon/slash/rowCmd.js +157 -0
  343. package/lib/quoxon/slash/rowWalk.js +175 -0
  344. package/lib/quoxon/slash/settings.js +16 -6
  345. package/lib/quoxon/slash/spawn.js +177 -0
  346. package/lib/quoxon/slash/stepUp.js +274 -0
  347. package/lib/quoxon/slash/stepUpCard.js +60 -0
  348. package/lib/quoxon/slash/stepUpCmds.js +78 -0
  349. package/lib/quoxon/slash/todoCmd.js +122 -0
  350. package/lib/quoxon/slash/undoApi.js +38 -0
  351. package/lib/quoxon/slash/undoCmd.js +49 -0
  352. package/lib/quoxon/slash/undoWish.js +15 -0
  353. package/lib/quoxon/slash/watch.js +164 -0
  354. package/lib/quoxon/slash/wish.js +23 -0
  355. package/lib/quoxon/slash/wishCmd.js +32 -0
  356. package/lib/quoxon/slotChat.js +300 -0
  357. package/lib/quoxon/slotFormat.js +195 -0
  358. package/lib/quoxon/slotRun.js +131 -0
  359. package/lib/quoxon/sound/mapping.js +2 -1
  360. package/lib/quoxon/stray.js +22 -0
  361. package/lib/quoxon/suggestCommand.js +90 -0
  362. package/lib/quoxon/term.js +46 -11
  363. package/lib/quoxon/textBuffer.js +176 -2
  364. package/lib/quoxon/theme.js +58 -25
  365. package/lib/quoxon/tips.js +433 -0
  366. package/lib/quoxon/toolCards.js +30 -0
  367. package/lib/quoxon/toolError.js +41 -0
  368. package/lib/quoxon/transcript.js +42 -4
  369. package/lib/quoxon/web/qface.js +18 -10
  370. package/lib/quoxon/welcome.js +1 -1
  371. package/lib/quoxon/whatsnew.js +136 -0
  372. package/lib/quoxon/whatsnew.jsonl +134 -0
  373. package/lib/quoxon/windowOrg.js +123 -0
  374. package/lib/server/devServers.js +137 -0
  375. package/lib/server/diag.js +129 -0
  376. package/lib/server/doctor.js +71 -0
  377. package/lib/server/install.js +149 -0
  378. package/lib/server/pluginEnable.js +161 -0
  379. package/lib/server/skew.js +56 -0
  380. package/lib/server/snapshot.js +131 -0
  381. package/lib/server/status.js +128 -0
  382. package/lib/server/sys.js +65 -0
  383. package/lib/server/uninstall.js +63 -0
  384. package/lib/server/update.js +234 -0
  385. package/lib/toolOutputShape.js +315 -0
  386. package/lib/tui/views/HyperionDeck.jsx +79 -0
  387. package/lib/tui/views/LucidDeck.jsx +209 -217
  388. package/package.json +5 -1
  389. package/vendor/dragonlab/SOURCE +4 -0
  390. package/vendor/dragonlab/design/cipher/v1/cipher-master.svg +46 -0
  391. package/vendor/dragonlab/design/cipher/v2/character.mjs +49 -0
  392. package/vendor/dragonlab/design/cipher/v2/review.mjs +33 -0
  393. package/vendor/dragonlab/design/cipher/v2/watch.mjs +56 -0
  394. package/vendor/dragonlab/design/drago/v1/character.mjs +19 -0
  395. package/vendor/dragonlab/design/drago/v1/drago-master.svg +56 -0
  396. package/vendor/dragonlab/design/drago/v2/character.mjs +87 -0
  397. package/vendor/dragonlab/design/drago/v4/character.mjs +67 -0
  398. package/vendor/dragonlab/design/drago/v4/profile.mjs +35 -0
  399. package/vendor/dragonlab/design/drago/v4/review.mjs +33 -0
  400. package/vendor/dragonlab/design/drago/v4/watch.mjs +56 -0
  401. package/vendor/dragonlab/design/hyperion/v1/hyperion-master.svg +56 -0
  402. package/vendor/dragonlab/design/hyperion/v2/character.mjs +79 -0
  403. package/vendor/dragonlab/design/hyperion/v2/review.mjs +33 -0
  404. package/vendor/dragonlab/design/hyperion/v2/watch.mjs +56 -0
  405. package/vendor/dragonlab/design/lucid/recovery/arrival.mjs +22 -0
  406. package/vendor/dragonlab/design/lucid/recovery/character.mjs +106 -0
  407. package/vendor/dragonlab/design/lucid/recovery/layout.mjs +50 -0
  408. package/vendor/dragonlab/design/lucid/recovery/lucid-master.svg +78 -0
  409. package/vendor/dragonlab/design/lucid/recovery/motion.mjs +42 -0
  410. package/vendor/dragonlab/design/lucid/recovery/render.mjs +121 -0
  411. package/vendor/dragonlab/design/lucid/recovery/review.mjs +68 -0
  412. package/vendor/dragonlab/design/lucid/recovery/verify.mjs +84 -0
  413. package/vendor/dragonlab/design/lucid/recovery/watch.mjs +56 -0
  414. package/vendor/dragonlab/design/seer/v1/seer-master.svg +53 -0
  415. package/vendor/dragonlab/design/seer/v2/character.mjs +88 -0
  416. package/vendor/dragonlab/design/seer/v3/character.mjs +33 -0
  417. package/vendor/dragonlab/design/seer/v4/character.mjs +66 -0
  418. package/vendor/dragonlab/design/seer/v4/review.mjs +33 -0
  419. package/vendor/dragonlab/design/seer/v4/watch.mjs +56 -0
  420. package/vendor/dragonlab/design/stage3/companion-review.mjs +28 -0
  421. package/vendor/dragonlab/design/stage3/sentinel-art.js +39 -0
  422. package/vendor/dragonlab/design/stage3/sentinel-braille.js +216 -0
  423. package/vendor/dragonlab/design/stage3/sentinel-character.js +257 -0
  424. package/vendor/dragonlab/design/stage3/sentinel-icon.js +103 -0
  425. package/vendor/dragonlab/design/stage3/sentinel-warden-eyes.js +95 -0
  426. package/vendor/dragonlab/design/stage3/svg-coverage.js +148 -0
  427. package/vendor/dragonlab/factory/svg-rig.mjs +63 -0
  428. package/vendor/dragonlab/integration/companions-v1/characters.mjs +88 -0
  429. package/vendor/dragonlab/integration/companions-v1/cipher.mjs +2 -0
  430. package/vendor/dragonlab/integration/companions-v1/companion.mjs +63 -0
  431. package/vendor/dragonlab/integration/companions-v1/drago.mjs +2 -0
  432. package/vendor/dragonlab/integration/companions-v1/hyperion.mjs +2 -0
  433. package/vendor/dragonlab/integration/companions-v1/lucid.mjs +2 -0
  434. package/vendor/dragonlab/integration/companions-v1/seer.mjs +2 -0
  435. package/vendor/dragonlab/integration/companions-v1/sentinel.mjs +2 -0
  436. package/vendor/dragonlab/integration/companions-v1/view.mjs +28 -0
  437. package/vendor/dragonlab/integration/hyperion-v3/activity.mjs +76 -0
  438. package/vendor/dragonlab/lib/power-effects.js +294 -0
  439. package/vendor/dragonlab/lib/power-registry.js +74 -0
  440. package/vendor/dragonlab/vendor/quox-dragon/qart.js +348 -0
  441. package/vendor/dragonlab/vendor/quox-dragon/qeyes.js +213 -0
  442. package/lib/core/websiteSession.js +0 -148
@@ -0,0 +1,72 @@
1
+ /**
2
+ * QUOXON-FW3: a message typed while the server is restarting is kept, not dropped (pure helpers).
3
+ * A send is only retried when the connection failed BEFORE any event arrived (so no turn started and
4
+ * nothing can run twice); the caller enforces that.
5
+ */
6
+ export const SERVER_RESTARTING = "Quox server is restarting. I'll send this when it is back. Esc cancels.";
7
+ export const MAX_WAIT_MS = 180000;
8
+
9
+ /** True for "could not reach the server at all" (refused / fetch failed), never for an HTTP answer. */
10
+ export function isServerDown(e) {
11
+ if (!e || e.status) return false;
12
+ const code = e.cause?.code || e.code || '';
13
+ const msg = String(e.message || '');
14
+ return /ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN|UND_ERR_SOCKET/.test(String(code)) || /Could not connect to|fetch failed|ECONNREFUSED/i.test(msg);
15
+ }
16
+
17
+ /** gh #1157: resume during a collector restart. Connection-class failures (refused, fetch failed, hang up, 502/503/504) are worth retrying; 401/404 are answers. */
18
+ export function isResumeRetryable(e) {
19
+ if (!e) return false;
20
+ if (e.status) return [502, 503, 504].includes(Number(e.status));
21
+ return isServerDown(e) || /socket hang up|ECONNRESET|other side closed|terminated/i.test(String(e.message || ''));
22
+ }
23
+ /** 2, 4, 8, 15, 30 s, then 30 s steps: about 2 minutes in all before giving up. */
24
+ export const RESUME_RETRY_DELAYS = [2000, 4000, 8000, 15000, 30000, 30000, 30000];
25
+ export const RESUME_RECONNECTING = 'Quox server restarting, reconnecting to your conversation…';
26
+
27
+ /** 1s, 2s, 4s, 8s, then 10s (capped). */
28
+ export const backoffMs = (i) => Math.min(10000, 1000 * 2 ** i);
29
+
30
+ const sleepFor = (ms, signal) => new Promise((r) => {
31
+ if (signal?.aborted) return r();
32
+ const t = setTimeout(done, ms);
33
+ function done() { clearTimeout(t); signal?.removeEventListener?.('abort', done); r(); }
34
+ signal?.addEventListener?.('abort', done, { once: true });
35
+ });
36
+
37
+ /**
38
+ * Poll health with backoff until it answers 2xx. -> 'up' | 'cancelled' | 'timeout'.
39
+ * delays: optional array (tests); else backoffMs. Total waiting is bounded by maxMs of scheduled sleep.
40
+ */
41
+ export async function waitForServer({ health, signal, delays = null, maxMs = MAX_WAIT_MS }) {
42
+ let waited = 0;
43
+ for (let i = 0; ; i++) {
44
+ if (signal?.aborted) return 'cancelled';
45
+ const d = delays ? delays[Math.min(i, delays.length - 1)] : backoffMs(i);
46
+ if (waited >= maxMs || (delays && i >= delays.length * 4)) return 'timeout';
47
+ await sleepFor(d, signal);
48
+ waited += d;
49
+ if (signal?.aborted) return 'cancelled';
50
+ let r = null;
51
+ try { r = await health(3000); } catch { r = null; }
52
+ if (r?.ok) return 'up';
53
+ }
54
+ }
55
+
56
+ /**
57
+ * QUOXON-FW4: a stream that died mid-turn ("terminated" is undici's wording) gets a cause and a way
58
+ * forward instead of a bare word. Returns null when the error is not a transport/timeout failure.
59
+ */
60
+ export function explainTermination(e) {
61
+ if (!e || e.status) return null;
62
+ const msg = String(e.message || '');
63
+ const code = String(e.cause?.code || e.code || '');
64
+ if (e.name === 'TimeoutError' || /timed? ?out|ETIMEDOUT|UND_ERR_(HEADERS|BODY)_TIMEOUT/i.test(`${msg} ${code}`)) return `The turn timed out before the server finished.`;
65
+ if (/^terminated$/i.test(msg.trim()) || /ECONNRESET|UND_ERR_SOCKET|other side closed|premature close|aborted/i.test(`${msg} ${code}`)) {
66
+ return `The connection to the server was cut mid-turn (likely a server restart, proxy timeout or provider error).`;
67
+ }
68
+ return null;
69
+ }
70
+
71
+ /** The second line after a cut turn: the message is kept, and what to do next. */
72
+ export const RETRY_HINT = 'Your message is kept: press Up to recall it, then Enter to resend. Anything it started may or may not have finished; check before repeating it.';
@@ -5,8 +5,11 @@
5
5
  * nothing (never a placeholder row).
6
6
  */
7
7
  import { clip } from './theme.js';
8
+ import { humanReason, wrapText } from './loopCard.js';
8
9
 
9
10
  export const GLYPH = { running: '◐', waiting: '⏸', done: '✔', failed: '✖' };
11
+ /** A row that ended without finishing says HOW: failed is the only error; the rest are neutral (no error colour). */
12
+ export const OUTCOME_GLYPH = { failed: '✖', halted: '⚠', cancelled: '○', expired: '○', rejected: '⊘' };
10
13
  export const FRESH_MS = 10 * 60 * 1000; // finished rows linger this long
11
14
  export const USER_DONE_MS = 20 * 1000; // a user-started completion vanishes quickly: rows come and go
12
15
  export const PENDING_FRESH_MS = 24 * 3600 * 1000; // an older "pending" is stale, not waiting
@@ -36,7 +39,22 @@ export function elapsed(ms) {
36
39
 
37
40
  const ACTIVE_RE = /^(running|planning|decompos|executing|in_progress|active)/;
38
41
  const WAITING_RE = /^(paused|awaiting|blocked|plan_review|pending_approval|waiting)/;
39
- const FAILED = new Set(['failed', 'error', 'halted', 'cancelled', 'canceled', 'timed_out', 'timeout']);
42
+ const FAILED = new Set(['failed', 'error', 'halted', 'cancelled', 'canceled', 'timed_out', 'timeout', 'expired', 'rejected']);
43
+ /** The word for how an ended row ended (state stays 'failed' for the ended-badly group; this says which). */
44
+ export function outcomeOf(status) {
45
+ const st = String(status || '').toLowerCase();
46
+ if (st === 'halted') return 'halted';
47
+ if (st === 'cancelled' || st === 'canceled') return 'cancelled';
48
+ if (st === 'expired') return 'expired';
49
+ if (st === 'rejected') return 'rejected';
50
+ return 'failed';
51
+ }
52
+ /** Word, glyph and whether it is an error, for a row. Non-failed states return their own state. */
53
+ export function endWord(r) { return r.state === 'failed' ? (r.outcome || outcomeOf(r.status)) : r.state; }
54
+ /** A human-halted loop keeps objective status 'failed'; the server says loop_state 'halted' (older servers: the halt text). */
55
+ const HALT_TEXT = /^Loop (?:halted on demand|stopped by human review)/i;
56
+ const isHaltedLoop = (o) => o.execution_mode === 'loop' && (o.loop_state === 'halted' || String(o.status || '').toLowerCase() === 'halted' || (String(o.status || '').toLowerCase() === 'failed' && HALT_TEXT.test(String(o.error_message || ''))));
57
+ export const glyphOf = (r) => (r.state === 'failed' ? OUTCOME_GLYPH[endWord(r)] : GLYPH[r.state]);
40
58
 
41
59
  /** How long a finished row lingers before it leaves the roster (null while running/waiting). */
42
60
  const expiryFor = (state, doneMs) => state === 'done' ? doneMs : state === 'failed' ? FRESH_MS : null;
@@ -59,6 +77,8 @@ function stateOf(status, { startedAt, createdAt, finishedAt, now, doneMs = FRESH
59
77
  return null;
60
78
  }
61
79
 
80
+ const latest = (...ts) => { const v = ts.filter((t) => t != null); return v.length ? Math.max(...v) : null; };
81
+
62
82
  export function fromObjective(o, now = Date.now()) {
63
83
  const startedAt = parseTime(o.started_at);
64
84
  const createdAt = parseTime(o.created_at);
@@ -68,17 +88,22 @@ export function fromObjective(o, now = Date.now()) {
68
88
  if (!state) return null;
69
89
  const loop = o.execution_mode === 'loop';
70
90
  let activity = '';
71
- if (state === 'failed' && o.error_message) activity = String(o.error_message);
91
+ const haltedLoop = state === 'failed' && isHaltedLoop(o);
92
+ // a halted loop reads its clean sentence (the server's loop_reason, with the person's name), never the raw record text
93
+ const shownError = !haltedLoop ? o.error_message : (o.loop_reason || ((n) => (n ? `Stopped by ${n[1].trim()}` : 'Halted on demand'))(/^Loop halted on demand by \S+ \(([^)]{1,80})\)/i.exec(String(o.error_message || ''))));
94
+ if (state === 'failed' && shownError) activity = humanReason(shownError); // the sentence whole, minus the raw spawner prefix; the view decides how to show it
95
+ else if (loop && state === 'done') activity = o.iteration_count > 0 ? `${o.iteration_count} turn${o.iteration_count === 1 ? '' : 's'}` : ''; // the row prints "done <age>" itself; a stale "iter 0/5" beside it was the lie
72
96
  else if (loop && o.max_iterations) activity = `iter ${o.iteration_count || 0}/${o.max_iterations}`;
73
97
  else if (o.task_count) activity = `${o.tasks_completed || 0}/${o.task_count} tasks`;
74
98
  else if (state === 'waiting') activity = 'waiting to start';
75
99
  const from = startedAt ?? createdAt;
76
100
  return {
77
101
  key: `objective:${o.id}`, id: o.id, source: 'objectives', background: false, kind: loop ? 'loop' : 'objective', state,
78
- name: o.title || o.id, activity, status: o.status,
102
+ name: o.title || o.id, activity, status: o.status, ...(haltedLoop ? { outcome: 'halted' } : {}),
79
103
  startedAt: from, finishedAt, ageMs: from != null ? (state === 'done' || state === 'failed' ? (finishedAt ?? now) - from : now - from) : null,
80
104
  expiryMs: expiryFor(state, USER_DONE_MS),
81
- detail: { description: o.description, error: o.error_message, tokens: o.tokens_used, toolCalls: o.tool_calls_used }
105
+ progressAt: latest(parseTime(o.updated_at), parseTime(o.last_progress_at), parseTime(o.last_heartbeat_at)),
106
+ detail: { description: o.description, error: shownError ? humanReason(shownError) : shownError, tokens: o.tokens_used, toolCalls: o.tool_calls_used }
82
107
  };
83
108
  }
84
109
 
@@ -95,7 +120,8 @@ const BACKGROUND_BY = /^(schedule|cron|interval|webhook|event|system)\b/i;
95
120
  export function isBackgroundExecution(e, userId = null) {
96
121
  const by = e?.triggeredBy == null ? '' : String(e.triggeredBy);
97
122
  if (BACKGROUND_BY.test(by)) return true;
98
- if (userId && by && by === String(userId)) return false;
123
+ // quoxflow records a person-started run as user:<id> (RunActor); a bare id is an older row
124
+ if (userId && by && (by === String(userId) || by === `user:${userId}`)) return false;
99
125
  return !USER_TRIGGERS.has(String(e?.triggerData?.trigger || '').toLowerCase());
100
126
  }
101
127
 
@@ -114,6 +140,7 @@ export function fromExecution(e, now = Date.now(), { userId = null } = {}) {
114
140
  name: e.workflowName || e.workflowId || e.id, activity, status: e.status,
115
141
  startedAt, finishedAt, ageMs: startedAt != null ? (state === 'done' || state === 'failed' ? (finishedAt ?? now) - startedAt : now - startedAt) : null,
116
142
  expiryMs: expiryFor(state, background ? FRESH_MS : USER_DONE_MS),
143
+ progressAt: latest(parseTime(e.updatedAt), parseTime(e.lastHeartbeatAt)),
117
144
  detail: { workflowId: e.workflowId, correlationId: e.correlationId, trigger: e.triggerData?.trigger, error: e.error }
118
145
  };
119
146
  }
@@ -169,40 +196,113 @@ export function toneName(r, pos, now = Date.now()) {
169
196
 
170
197
  /** Live age text: a clock for running/waiting rows, recency ("done 3s ago") for finished ones. */
171
198
  export function ageText(r, now = Date.now()) {
172
- if (r.state === 'done' || r.state === 'failed') return r.finishedAt != null ? `${r.state === 'done' ? 'done' : 'failed'} ${elapsed(now - r.finishedAt)} ago` : '';
199
+ if (r.state === 'done' || r.state === 'failed') return r.finishedAt != null ? `${endWord(r)} ${elapsed(now - r.finishedAt)} ago` : '';
173
200
  return r.startedAt != null ? elapsed(now - r.startedAt) : '';
174
201
  }
175
202
 
203
+ /* ---- pulse: is it moving? ---------------------------------------------------------------- */
204
+
205
+ export const PULSE_MOVING_MS = 2 * 60 * 1000; // progress this recently = moving
206
+ export const PULSE_STALL_MS = 15 * 60 * 1000; // running with no progress this long = stalled
207
+ export const SPIN = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
208
+ export const SPIN_MS = 120;
209
+
210
+ const sigOf = (r) => `${r.state}|${r.status}|${r.activity}`;
211
+
212
+ /**
213
+ * Remember what each row looked like at the last poll so "state changed / iteration advanced" is noticed.
214
+ * Sets r.progressAt (newest of the API's own timestamp and the change we saw; null = nothing seen yet) and
215
+ * r.watchSince (when we first saw the row). Mutates rows and memo (key -> { sig, watchSince, changedAt }).
216
+ */
217
+ export function applyProgress(rows, memo, now = Date.now()) {
218
+ const keep = new Set();
219
+ for (const r of rows) {
220
+ keep.add(r.key);
221
+ const sig = sigOf(r);
222
+ let m = memo.get(r.key);
223
+ if (!m) { m = { sig, watchSince: now, changedAt: null }; memo.set(r.key, m); }
224
+ else if (m.sig !== sig) { m.sig = sig; m.changedAt = now; }
225
+ r.progressAt = latest(r.progressAt, m.changedAt);
226
+ r.watchSince = m.watchSince;
227
+ }
228
+ for (const k of [...memo.keys()]) if (!keep.has(k)) memo.delete(k);
229
+ return rows;
230
+ }
231
+
232
+ /** -> { kind: 'moving' | 'idle' | 'stalled' | 'none', glyph, role }. motion=false gives static glyphs. */
233
+ export function pulseOf(r, now = Date.now(), { motion = false } = {}) {
234
+ if (r.kind === 'approval' || r.state === 'done' || r.state === 'failed') return { kind: 'none', glyph: ' ', role: 'dim' };
235
+ if (r.state !== 'running') return { kind: 'idle', glyph: '·', role: 'dim' };
236
+ const last = latest(r.progressAt, r.startedAt != null && now - r.startedAt < PULSE_MOVING_MS ? r.startedAt : null);
237
+ if (last != null && now - last < PULSE_MOVING_MS) return { kind: 'moving', glyph: motion ? SPIN[Math.floor(now / SPIN_MS) % SPIN.length] : '●', role: 'sky' };
238
+ const ref = last ?? r.watchSince;
239
+ if (ref != null && now - ref > PULSE_STALL_MS) return { kind: 'stalled', glyph: '!', role: 'warn' };
240
+ return { kind: 'idle', glyph: '·', role: 'dim' };
241
+ }
242
+
176
243
  export function countsLine(rows) {
177
244
  const n = (s) => rows.filter(r => r.state === s).length;
178
- return [['running', 'running'], ['waiting', 'waiting'], ['failed', 'failed'], ['done', 'finished']]
179
- .filter(([s]) => n(s)).map(([s, w]) => `${GLYPH[s]} ${n(s)} ${w}`).join(' · ');
245
+ const o = (w) => rows.filter(r => r.state === 'failed' && endWord(r) === w).length;
246
+ return [['running', 'running', n('running'), GLYPH.running], ['waiting', 'waiting', n('waiting'), GLYPH.waiting],
247
+ ['failed', 'failed', o('failed'), OUTCOME_GLYPH.failed], ['halted', 'halted', o('halted'), OUTCOME_GLYPH.halted], ['cancelled', 'cancelled', o('cancelled'), OUTCOME_GLYPH.cancelled],
248
+ ['expired', 'expired', o('expired'), OUTCOME_GLYPH.expired], ['rejected', 'rejected', o('rejected'), OUTCOME_GLYPH.rejected], ['done', 'finished', n('done'), GLYPH.done]]
249
+ .filter(([, , k]) => k).map(([, w, k, g]) => `${g} ${k} ${w}`).join(' · ');
180
250
  }
181
251
 
182
252
  /**
183
253
  * View model. mode: 'hidden' (off or nothing running) | 'summary' (narrow or short terminal) | 'full'.
184
254
  * lines: [{ state, text, selected }] where text is already clipped to cols.
185
255
  */
186
- export function rosterView({ rows, cols, termRows = 40, max = MAX_ROWS, on = true, sel = 0, focus = false, now = Date.now() }) {
256
+ /**
257
+ * Two or more waiting approvals are ONE row ("⏸ 4 approvals waiting · oldest 41m · newest: <title>… · /approvals"), not
258
+ * one row each plus a summary line (owner, live 05:29): the bottom area must never grow with the inbox. A single approval
259
+ * keeps its own row. Focus (the user is walking the roster) shows the real rows so selection stays truthful.
260
+ */
261
+ export function collapseApprovals(rows, now = Date.now()) {
262
+ const aps = rows.filter(r => r.kind === 'approval' && r.state === 'waiting');
263
+ if (aps.length < 2) return rows;
264
+ const started = aps.map(r => r.startedAt).filter(x => x != null);
265
+ const newest = aps.reduce((a, b) => ((b.startedAt ?? -Infinity) > (a.startedAt ?? -Infinity) ? b : a));
266
+ const one = { key: 'approval:*', id: '*', source: 'approvals', kind: 'approval', state: 'waiting', background: false, collapsed: true, count: aps.length,
267
+ name: `${aps.length} approvals waiting`, activity: '/approvals', status: 'pending', startedAt: started.length ? Math.min(...started) : null, finishedAt: null,
268
+ oldestMs: started.length ? now - Math.min(...started) : null, newestTitle: String(newest.detail?.description || newest.name || ''), detail: {} };
269
+ let placed = false;
270
+ return rows.flatMap(r => (aps.includes(r) ? (placed ? [] : (placed = true, [one])) : [r]));
271
+ }
272
+
273
+ const KIND_ICON = { loop: '∞', objective: '◎' }; // QuoxGlyph registry keys qloop / objective
274
+ export const kindLabel = k => (KIND_ICON[k] ? `${KIND_ICON[k]} ${k}` : k);
275
+
276
+ export function rosterView({ rows, cols, termRows = 40, max = MAX_ROWS, on = true, sel = 0, focus = false, now = Date.now(), motion = false }) {
187
277
  if (!on || !rows.length) return { mode: 'hidden', lines: [], more: 0 };
278
+ if (!focus) rows = collapseApprovals(rows, now);
188
279
  if (cols < MIN_FULL_COLS || termRows < MIN_FULL_ROWS) {
189
280
  return { mode: 'summary', lines: [], more: 0, summary: clip(' ' + countsLine(rows) + ' · /roster', cols - 1) };
190
281
  }
191
282
  const shown = rows.slice(0, max);
192
283
  const ageW = Math.max(5, ...shown.map(r => [...ageText(r, now)].length));
193
- let pos = 0;
194
- const kindW = Math.min(9, Math.max(...shown.map(r => r.kind.length)));
284
+ let pos = 0, reasonShown = false;
285
+ const kindW = Math.min(11, Math.max(...shown.map(r => [...kindLabel(r.kind)].length)));
195
286
  const lines = shown.map((r, i) => {
196
287
  const el = ageText(r, now).padStart(ageW);
197
288
  const tone = toneName(r, pos, now); if (r.kind !== 'approval') pos++;
198
289
  const actW = Math.min(18, Math.max(0, ...shown.map(x => [...(x.activity || '')].length)));
199
- const act = clip(r.activity || '', actW).padEnd(actW);
200
- const fixed = 1 + 1 + 1 + kindW + 1 + 1 + actW + 1 + ageW; // marker glyph kind name act elapsed
290
+ const longReason = r.state === 'failed' && [...(r.activity || '')].length > actW; // a reason is never cut: the column says "stopped", the sentence follows wrapped
291
+ const act = (longReason ? clip('stopped', actW) : clip(r.activity || '', actW)).padEnd(actW);
292
+ const fixed = 1 + 1 + 1 + kindW + 1 + 1 + actW + 1 + ageW + 2; // pulse column (space + glyph); marker glyph kind name act elapsed
201
293
  const nameW = Math.max(8, cols - 2 - fixed - 1);
202
294
  const name = clip(r.name, nameW).padEnd(nameW);
203
295
  const marker = focus && i === sel ? '›' : ' ';
204
- const rest = `${r.kind.padEnd(kindW)} ${name} ${act} ${el}`;
205
- return { key: r.key, state: r.state, tone, selected: focus && i === sel, marker, glyph: GLYPH[r.state], rest: ' ' + rest, text: `${marker}${GLYPH[r.state]} ${rest}` };
296
+ if (r.collapsed) { // one summary row: count, oldest age, newest title, where to go; clipped to the line
297
+ const head = `${r.count} approvals waiting · oldest ${elapsed(r.oldestMs)} · newest: `, tail = ' · /approvals';
298
+ const room = cols - 5 - [...head].length - [...tail].length;
299
+ const text = room >= 12 ? `${head}${clip(r.newestTitle, room)}${tail}` : clip(`${r.count} approvals waiting · oldest ${elapsed(r.oldestMs)}${tail}`, cols - 4); // too narrow for a title
300
+ return { key: r.key, kind: 'approval', state: r.state, tone: toneName(r, pos, now), selected: false, marker: ' ', glyph: GLYPH[r.state], rest: ' ' + text, pulse: '', pulseRole: 'dim', pulseKind: 'none', text: ` ${GLYPH[r.state]} ${text}` };
301
+ }
302
+ const rest = `${kindLabel(r.kind).padEnd(kindW)} ${name} ${act} ${el}`;
303
+ const p = pulseOf(r, now, { motion });
304
+ const extra = longReason && !reasonShown ? (reasonShown = true, wrapText(r.activity, Math.max(20, cols - 8))) : null; // spelled out for the newest stopped row only: the bar must not grow with every old failure
305
+ return { key: r.key, kind: r.kind, state: r.state, tone, extra, selected: focus && i === sel, marker, glyph: glyphOf(r), glyphRole: r.state === 'failed' && endWord(r) === 'halted' ? 'warn' : r.state === 'failed' && endWord(r) !== 'failed' ? 'dim' : null, rest: ' ' + rest, pulse: ' ' + p.glyph, pulseRole: p.role, pulseKind: p.kind, text: `${marker}${glyphOf(r)} ${rest} ${p.glyph}` };
206
306
  });
207
307
  return { mode: 'full', lines, more: Math.max(0, rows.length - shown.length) };
208
308
  }
@@ -210,12 +310,12 @@ export function rosterView({ rows, cols, termRows = 40, max = MAX_ROWS, on = tru
210
310
  export function peekLines(row, now = Date.now()) {
211
311
  if (!row) return [];
212
312
  const age = ageText(row, now);
213
- const out = [`${row.kind} ${row.id}`, `status ${row.status} · ${row.state}${age ? ` · ${age}` : ''}`, `name ${row.name}`];
313
+ const out = [`${row.kind} ${row.id}`, `status ${row.status} · ${endWord(row)}${age ? ` · ${age}` : ''}`, `name ${row.name}`];
214
314
  if (row.activity) out.push(`activity ${row.activity}`);
215
315
  const d = row.detail || {};
216
316
  if (d.description) out.push(`goal ${d.description}`);
217
317
  if (d.workflowId) out.push(`workflow ${d.workflowId}`);
218
318
  if (d.trigger) out.push(`trigger ${d.trigger}`);
219
- if (d.error && row.state === 'failed') out.push(`error ${typeof d.error === 'string' ? d.error : JSON.stringify(d.error)}`);
319
+ if (d.error && row.state === 'failed') out.push(`error ${typeof d.error === 'string' ? humanReason(d.error) : JSON.stringify(d.error)}`);
220
320
  return out;
221
321
  }
@@ -5,9 +5,9 @@
5
5
  */
6
6
  const VALUE_FLAGS = new Set(['-p', '--profile', '-n', '--name']);
7
7
  const LEVELS = new Set(['off', 'on', 'full']); // `--verbose` alone means on; it only takes a value that is a level
8
- const PRINT_VALUE_FLAGS = new Set(['--output', '--conversation', '--turn-id', '--timeout', '--provider', '--model']);
9
- const BOOL_FLAGS = new Set(['--demo', '--demo-onboarding', '--no-clear', '--color', '--service-key']);
10
- const ALL_FLAGS = new Set([...VALUE_FLAGS, ...PRINT_VALUE_FLAGS, ...BOOL_FLAGS, '--print', '--resume', '-h', '--help', '--']);
8
+ const PRINT_VALUE_FLAGS = new Set(['--output', '--conversation', '--turn-id', '--timeout', '--provider', '--model', '--agent', '--prompt-profile']);
9
+ const BOOL_FLAGS = new Set(['--demo', '--autoplay', '--demo-onboarding', '--no-clear', '--color', '--service-key']);
10
+ const ALL_FLAGS = new Set([...VALUE_FLAGS, ...PRINT_VALUE_FLAGS, ...BOOL_FLAGS, '--print', '--resume', '--autoplay-exit', '-h', '--help', '--']);
11
11
 
12
12
  export function routesToQuoxon(argv, isTTY) {
13
13
  let print = false;
@@ -18,17 +18,18 @@ export function routesToQuoxon(argv, isTTY) {
18
18
  for (let i = 0; i < argv.length; i++) {
19
19
  const a = argv[i];
20
20
  if (a === '--') { return print; } // everything after -- is the prompt
21
- if (a === '--print') { print = true; const n = argv[i + 1]; if (n !== undefined && !ALL_FLAGS.has(n) && !/^--(profile|verbose|output|conversation|turn-id|timeout|print|provider|model)=/.test(n)) i++; }
21
+ if (a === '--print') { print = true; const n = argv[i + 1]; if (n !== undefined && !ALL_FLAGS.has(n) && !/^--(profile|verbose|output|conversation|turn-id|timeout|print|provider|model|agent|prompt-profile)=/.test(n)) i++; }
22
22
  else if (a.startsWith('--print=')) print = true;
23
23
  else if (a === '-h' || a === '--help') help = true;
24
24
  else if (a === '--verbose') { if (LEVELS.has(argv[i + 1])) i++; }
25
25
  else if (a === '--resume') { const n = argv[i + 1]; if (n !== undefined && !n.startsWith('-')) i++; } // optional id or name
26
+ else if (a === '--autoplay-exit') { if (/^\d+(\.\d+)?$/.test(argv[i + 1] || '')) i++; } // optional seconds
26
27
  else if (a.startsWith('--resume=')) { /* inline value */ }
27
28
  else if (VALUE_FLAGS.has(a)) i++;
28
29
  else if (/^--(profile|verbose|name)=/.test(a)) { /* inline value */ }
29
30
  else if (BOOL_FLAGS.has(a)) { /* no value */ }
30
31
  else if (PRINT_VALUE_FLAGS.has(a)) i++;
31
- else if (/^--(output|conversation|turn-id|timeout|provider|model)=/.test(a)) { /* inline value */ }
32
+ else if (/^--(output|conversation|turn-id|timeout|provider|model|agent|prompt-profile)=/.test(a)) { /* inline value */ }
32
33
  else if (hasPrint && !a.startsWith('-')) { print = true; } // the prompt, wherever it sits among the flags
33
34
  else return false; // subcommand, positional, --help, --version, unknown flag
34
35
  }