quoxcli 0.0.0-stage → 0.3.1

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 (516) hide show
  1. package/LICENSE +35 -0
  2. package/README.md +144 -2
  3. package/bin/quox.js +265 -0
  4. package/bin/quoxon.js +8 -0
  5. package/lib/api/endpoints/admin.js +151 -0
  6. package/lib/api/endpoints/aee.js +38 -0
  7. package/lib/api/endpoints/agent-attach.js +126 -0
  8. package/lib/api/endpoints/agent-schedules.js +26 -0
  9. package/lib/api/endpoints/agents.js +63 -0
  10. package/lib/api/endpoints/assistants.js +62 -0
  11. package/lib/api/endpoints/audit.js +14 -0
  12. package/lib/api/endpoints/auth.js +50 -0
  13. package/lib/api/endpoints/awareness.js +34 -0
  14. package/lib/api/endpoints/away.js +15 -0
  15. package/lib/api/endpoints/backup-schedules.js +20 -0
  16. package/lib/api/endpoints/backups.js +86 -0
  17. package/lib/api/endpoints/brain.js +140 -0
  18. package/lib/api/endpoints/budgets.js +62 -0
  19. package/lib/api/endpoints/calendarq.js +71 -0
  20. package/lib/api/endpoints/catalog.js +14 -0
  21. package/lib/api/endpoints/chat.js +61 -0
  22. package/lib/api/endpoints/consent.js +26 -0
  23. package/lib/api/endpoints/contactsq.js +68 -0
  24. package/lib/api/endpoints/conversations.js +46 -0
  25. package/lib/api/endpoints/custom-roles.js +92 -0
  26. package/lib/api/endpoints/divisions.js +56 -0
  27. package/lib/api/endpoints/domains.js +38 -0
  28. package/lib/api/endpoints/engagement.js +231 -0
  29. package/lib/api/endpoints/engine.js +11 -0
  30. package/lib/api/endpoints/entity.js +50 -0
  31. package/lib/api/endpoints/executions.js +45 -0
  32. package/lib/api/endpoints/fetchAllowlist.js +27 -0
  33. package/lib/api/endpoints/file.js +20 -0
  34. package/lib/api/endpoints/files.js +40 -0
  35. package/lib/api/endpoints/github.js +21 -0
  36. package/lib/api/endpoints/governance.js +43 -0
  37. package/lib/api/endpoints/hat.js +66 -0
  38. package/lib/api/endpoints/inbox.js +52 -0
  39. package/lib/api/endpoints/inboxq.js +120 -0
  40. package/lib/api/endpoints/index.js +242 -0
  41. package/lib/api/endpoints/invites.js +19 -0
  42. package/lib/api/endpoints/llm-policy.js +43 -0
  43. package/lib/api/endpoints/lucid.js +89 -0
  44. package/lib/api/endpoints/members.js +32 -0
  45. package/lib/api/endpoints/memory.js +94 -0
  46. package/lib/api/endpoints/mfa.js +32 -0
  47. package/lib/api/endpoints/mind.js +13 -0
  48. package/lib/api/endpoints/mon.js +184 -0
  49. package/lib/api/endpoints/notesq.js +43 -0
  50. package/lib/api/endpoints/objectives.js +68 -0
  51. package/lib/api/endpoints/orgs.js +38 -0
  52. package/lib/api/endpoints/plugins.js +152 -0
  53. package/lib/api/endpoints/powers.js +75 -0
  54. package/lib/api/endpoints/presence.js +33 -0
  55. package/lib/api/endpoints/prompts.js +69 -0
  56. package/lib/api/endpoints/qlarity.js +122 -0
  57. package/lib/api/endpoints/quoxbox.js +55 -0
  58. package/lib/api/endpoints/quoxchat.js +54 -0
  59. package/lib/api/endpoints/quoxflow.js +32 -0
  60. package/lib/api/endpoints/quoxplan.js +121 -0
  61. package/lib/api/endpoints/quoxseo.js +114 -0
  62. package/lib/api/endpoints/reach.js +47 -0
  63. package/lib/api/endpoints/router.js +17 -0
  64. package/lib/api/endpoints/runs.js +38 -0
  65. package/lib/api/endpoints/safety.js +53 -0
  66. package/lib/api/endpoints/scim.js +46 -0
  67. package/lib/api/endpoints/scopes.js +14 -0
  68. package/lib/api/endpoints/security.js +69 -0
  69. package/lib/api/endpoints/setup.js +90 -0
  70. package/lib/api/endpoints/skills.js +200 -0
  71. package/lib/api/endpoints/sso.js +67 -0
  72. package/lib/api/endpoints/stepup.js +20 -0
  73. package/lib/api/endpoints/tags.js +32 -0
  74. package/lib/api/endpoints/teams.js +56 -0
  75. package/lib/api/endpoints/telephony.js +46 -0
  76. package/lib/api/endpoints/tg.js +56 -0
  77. package/lib/api/endpoints/tools.js +50 -0
  78. package/lib/api/endpoints/traces.js +157 -0
  79. package/lib/api/endpoints/triggers.js +96 -0
  80. package/lib/api/endpoints/user-library.js +41 -0
  81. package/lib/api/endpoints/users.js +20 -0
  82. package/lib/api/endpoints/v1.js +585 -0
  83. package/lib/api/endpoints/vault.js +192 -0
  84. package/lib/api/endpoints/voice.js +22 -0
  85. package/lib/api/endpoints/volt.js +84 -0
  86. package/lib/api/endpoints/ward.js +47 -0
  87. package/lib/api/endpoints/webhooks.js +46 -0
  88. package/lib/api/endpoints/workflows.js +169 -0
  89. package/lib/api/endpoints/x.js +32 -0
  90. package/lib/api/endpoints.js +15 -0
  91. package/lib/commands/actions.js +61 -0
  92. package/lib/commands/admin.js +375 -0
  93. package/lib/commands/aee.js +99 -0
  94. package/lib/commands/agent.js +337 -0
  95. package/lib/commands/agentAttach.js +1528 -0
  96. package/lib/commands/approvals.js +119 -0
  97. package/lib/commands/aside.js +24 -0
  98. package/lib/commands/ask.js +144 -0
  99. package/lib/commands/assistant.js +169 -0
  100. package/lib/commands/auth.js +464 -0
  101. package/lib/commands/awareness.js +88 -0
  102. package/lib/commands/backup.js +377 -0
  103. package/lib/commands/brain.js +1085 -0
  104. package/lib/commands/budget.js +241 -0
  105. package/lib/commands/build.js +170 -0
  106. package/lib/commands/calendar.js +216 -0
  107. package/lib/commands/capabilities.js +34 -0
  108. package/lib/commands/chat.js +295 -0
  109. package/lib/commands/claude.js +380 -0
  110. package/lib/commands/config-cmd.js +106 -0
  111. package/lib/commands/consent.js +84 -0
  112. package/lib/commands/contacts.js +1016 -0
  113. package/lib/commands/contactsSelftest.js +132 -0
  114. package/lib/commands/conversation.js +105 -0
  115. package/lib/commands/dashboard.js +43 -0
  116. package/lib/commands/department.js +96 -0
  117. package/lib/commands/dev.js +620 -0
  118. package/lib/commands/devResident.js +326 -0
  119. package/lib/commands/devSupervisor.js +1062 -0
  120. package/lib/commands/discord.js +132 -0
  121. package/lib/commands/doctor.js +181 -0
  122. package/lib/commands/domain.js +114 -0
  123. package/lib/commands/done.js +347 -0
  124. package/lib/commands/engagement.js +597 -0
  125. package/lib/commands/entity.js +119 -0
  126. package/lib/commands/facebook.js +212 -0
  127. package/lib/commands/fetchAllowlist.js +71 -0
  128. package/lib/commands/file.js +165 -0
  129. package/lib/commands/fleet.js +1189 -0
  130. package/lib/commands/governance.js +647 -0
  131. package/lib/commands/gripe.js +355 -0
  132. package/lib/commands/hat.js +374 -0
  133. package/lib/commands/helpers.js +96 -0
  134. package/lib/commands/hyperion.js +58 -0
  135. package/lib/commands/inbox.js +173 -0
  136. package/lib/commands/instagram.js +264 -0
  137. package/lib/commands/integration.js +100 -0
  138. package/lib/commands/inventory.js +115 -0
  139. package/lib/commands/invites.js +45 -0
  140. package/lib/commands/licence.js +139 -0
  141. package/lib/commands/linkedin.js +178 -0
  142. package/lib/commands/llm-policy.js +117 -0
  143. package/lib/commands/llm.js +45 -0
  144. package/lib/commands/lucid.js +597 -0
  145. package/lib/commands/mail.js +531 -0
  146. package/lib/commands/memory.js +361 -0
  147. package/lib/commands/mind.js +71 -0
  148. package/lib/commands/mon.js +581 -0
  149. package/lib/commands/monitoring.js +86 -0
  150. package/lib/commands/motion.js +22 -0
  151. package/lib/commands/notes.js +1246 -0
  152. package/lib/commands/notesBatch.js +160 -0
  153. package/lib/commands/notesBridges.js +56 -0
  154. package/lib/commands/notesLinks.js +60 -0
  155. package/lib/commands/notification.js +57 -0
  156. package/lib/commands/nucleus.js +123 -0
  157. package/lib/commands/objective.js +240 -0
  158. package/lib/commands/offload.js +89 -0
  159. package/lib/commands/onboard.js +329 -0
  160. package/lib/commands/open.js +56 -0
  161. package/lib/commands/org.js +276 -0
  162. package/lib/commands/peek.js +28 -0
  163. package/lib/commands/plan.js +944 -0
  164. package/lib/commands/plugin-doctor.js +1091 -0
  165. package/lib/commands/plugin.js +649 -0
  166. package/lib/commands/policy.js +78 -0
  167. package/lib/commands/powers.js +296 -0
  168. package/lib/commands/presence.js +89 -0
  169. package/lib/commands/prompt.js +350 -0
  170. package/lib/commands/provider.js +159 -0
  171. package/lib/commands/qlarity.js +706 -0
  172. package/lib/commands/quoxbox.js +270 -0
  173. package/lib/commands/quoxchat.js +275 -0
  174. package/lib/commands/quoxseo.js +378 -0
  175. package/lib/commands/reach.js +159 -0
  176. package/lib/commands/role.js +286 -0
  177. package/lib/commands/router.js +77 -0
  178. package/lib/commands/rows.js +358 -0
  179. package/lib/commands/run.js +187 -0
  180. package/lib/commands/safety.js +107 -0
  181. package/lib/commands/scim.js +88 -0
  182. package/lib/commands/scope.js +58 -0
  183. package/lib/commands/security.js +157 -0
  184. package/lib/commands/server.js +292 -0
  185. package/lib/commands/service.js +89 -0
  186. package/lib/commands/settings.js +99 -0
  187. package/lib/commands/setup.js +569 -0
  188. package/lib/commands/skillManifest.js +113 -0
  189. package/lib/commands/skillRightsFormat.js +38 -0
  190. package/lib/commands/skills.js +687 -0
  191. package/lib/commands/slot.js +1451 -0
  192. package/lib/commands/sso.js +229 -0
  193. package/lib/commands/status.js +137 -0
  194. package/lib/commands/tag.js +91 -0
  195. package/lib/commands/team.js +142 -0
  196. package/lib/commands/tg.js +240 -0
  197. package/lib/commands/tiktok.js +218 -0
  198. package/lib/commands/tips.js +23 -0
  199. package/lib/commands/tool.js +304 -0
  200. package/lib/commands/trace.js +530 -0
  201. package/lib/commands/trigger.js +223 -0
  202. package/lib/commands/update.js +46 -0
  203. package/lib/commands/vault.js +1447 -0
  204. package/lib/commands/vm.js +237 -0
  205. package/lib/commands/voice.js +213 -0
  206. package/lib/commands/volt.js +570 -0
  207. package/lib/commands/walkthrough.js +32 -0
  208. package/lib/commands/watch.js +167 -0
  209. package/lib/commands/webhook.js +137 -0
  210. package/lib/commands/welcome.js +14 -0
  211. package/lib/commands/workflow.js +660 -0
  212. package/lib/commands/x.js +448 -0
  213. package/lib/core/actingAs.js +136 -0
  214. package/lib/core/activeSummary.js +186 -0
  215. package/lib/core/aee.js +53 -0
  216. package/lib/core/agentAlias.js +163 -0
  217. package/lib/core/approvalContext.js +61 -0
  218. package/lib/core/aside.js +54 -0
  219. package/lib/core/askDecision.js +60 -0
  220. package/lib/core/auth.js +501 -0
  221. package/lib/core/banner.js +143 -0
  222. package/lib/core/brainPrime.js +90 -0
  223. package/lib/core/callerSource.js +129 -0
  224. package/lib/core/claudeLs.js +94 -0
  225. package/lib/core/cliBuild.js +62 -0
  226. package/lib/core/client.js +693 -0
  227. package/lib/core/commandRegistrars.js +121 -0
  228. package/lib/core/completions.js +163 -0
  229. package/lib/core/config.js +669 -0
  230. package/lib/core/confirm.js +37 -0
  231. package/lib/core/customHats.js +168 -0
  232. package/lib/core/deeplinks.js +76 -0
  233. package/lib/core/doneEngineFetch.js +227 -0
  234. package/lib/core/errors.js +441 -0
  235. package/lib/core/global-flags.js +190 -0
  236. package/lib/core/governedSession.js +402 -0
  237. package/lib/core/hyperion.js +102 -0
  238. package/lib/core/inboxResolution.js +65 -0
  239. package/lib/core/lazyCommands.js +122 -0
  240. package/lib/core/liveSessionsReport.js +112 -0
  241. package/lib/core/offload.js +504 -0
  242. package/lib/core/org-override.js +52 -0
  243. package/lib/core/orgResolve.js +70 -0
  244. package/lib/core/output.js +239 -0
  245. package/lib/core/peek.js +126 -0
  246. package/lib/core/prodEnv.js +7 -0
  247. package/lib/core/profileUsers.js +51 -0
  248. package/lib/core/promptCancel.js +18 -0
  249. package/lib/core/quoxglyph.js +158 -0
  250. package/lib/core/repoPath.js +11 -0
  251. package/lib/core/residentAlarm.js +282 -0
  252. package/lib/core/residentAuth.js +243 -0
  253. package/lib/core/residentPump.js +229 -0
  254. package/lib/core/residentSeed.js +106 -0
  255. package/lib/core/rootOptions.js +39 -0
  256. package/lib/core/router.js +168 -0
  257. package/lib/core/selfUpdate.js +188 -0
  258. package/lib/core/sessionHeartbeat.js +192 -0
  259. package/lib/core/sessionsOverview.js +224 -0
  260. package/lib/core/slotKeeper.js +527 -0
  261. package/lib/core/slotWake.js +120 -0
  262. package/lib/core/supervisorEngine.js +933 -0
  263. package/lib/core/systemdInstaller.js +256 -0
  264. package/lib/core/version.js +87 -0
  265. package/lib/core/vm.js +361 -0
  266. package/lib/core/vmTui.js +86 -0
  267. package/lib/core/walkthrough.js +35 -0
  268. package/lib/hyperion/deck.js +29 -0
  269. package/lib/lucid/LucidCard.jsx +68 -0
  270. package/lib/lucid/LucidIntro.jsx +92 -0
  271. package/lib/lucid/blind.js +71 -0
  272. package/lib/lucid/cards.js +86 -0
  273. package/lib/lucid/deck.js +32 -0
  274. package/lib/lucid/fmt.js +139 -0
  275. package/lib/lucid/markdown.js +81 -0
  276. package/lib/lucid/motion.js +56 -0
  277. package/lib/lucid/sitrep.js +173 -0
  278. package/lib/plugins/loader.js +93 -0
  279. package/lib/quoxon/activity.js +116 -0
  280. package/lib/quoxon/aocl.js +117 -0
  281. package/lib/quoxon/api.js +952 -0
  282. package/lib/quoxon/app.js +4032 -0
  283. package/lib/quoxon/approvalFacts.js +94 -0
  284. package/lib/quoxon/approvalsView.js +325 -0
  285. package/lib/quoxon/asideView.js +40 -0
  286. package/lib/quoxon/ask.js +121 -0
  287. package/lib/quoxon/away.js +52 -0
  288. package/lib/quoxon/bang.js +224 -0
  289. package/lib/quoxon/bulkRisk.js +17 -0
  290. package/lib/quoxon/capabilities.js +82 -0
  291. package/lib/quoxon/cells.js +53 -0
  292. package/lib/quoxon/commandShort.js +112 -0
  293. package/lib/quoxon/commands.js +479 -0
  294. package/lib/quoxon/connect.js +654 -0
  295. package/lib/quoxon/connectCard.js +45 -0
  296. package/lib/quoxon/consent.js +86 -0
  297. package/lib/quoxon/context.js +68 -0
  298. package/lib/quoxon/copy.js +34 -0
  299. package/lib/quoxon/countdownLine.js +11 -0
  300. package/lib/quoxon/demo.autoplay.js +29 -0
  301. package/lib/quoxon/demo.fixtures.js +24 -0
  302. package/lib/quoxon/demo.js +76 -0
  303. package/lib/quoxon/devObserver.js +20 -0
  304. package/lib/quoxon/dividerAocl.js +191 -0
  305. package/lib/quoxon/dividerRule.js +57 -0
  306. package/lib/quoxon/dragonModes.js +150 -0
  307. package/lib/quoxon/dragonView.js +41 -0
  308. package/lib/quoxon/earlyInput.js +40 -0
  309. package/lib/quoxon/echo.js +15 -0
  310. package/lib/quoxon/egg.js +36 -0
  311. package/lib/quoxon/events.js +677 -0
  312. package/lib/quoxon/feedback.js +50 -0
  313. package/lib/quoxon/gallery.js +237 -0
  314. package/lib/quoxon/handoffOffer.js +78 -0
  315. package/lib/quoxon/hatSwitch.js +37 -0
  316. package/lib/quoxon/headless.js +161 -0
  317. package/lib/quoxon/hostUrls.js +41 -0
  318. package/lib/quoxon/indicator.js +197 -0
  319. package/lib/quoxon/intent.js +52 -0
  320. package/lib/quoxon/keys.js +164 -0
  321. package/lib/quoxon/launcher.js +103 -0
  322. package/lib/quoxon/main.js +176 -0
  323. package/lib/quoxon/markdown.js +341 -0
  324. package/lib/quoxon/markdownSettle.js +19 -0
  325. package/lib/quoxon/matrixDomains.json +46 -0
  326. package/lib/quoxon/mentions.js +90 -0
  327. package/lib/quoxon/mind.js +103 -0
  328. package/lib/quoxon/mode.js +46 -0
  329. package/lib/quoxon/model.js +311 -0
  330. package/lib/quoxon/modelPrefs.js +345 -0
  331. package/lib/quoxon/motion/clock.js +70 -0
  332. package/lib/quoxon/motion/color.js +35 -0
  333. package/lib/quoxon/motion/frame.js +14 -0
  334. package/lib/quoxon/motion/level.js +91 -0
  335. package/lib/quoxon/motion/reveal.js +54 -0
  336. package/lib/quoxon/motion/ring.js +79 -0
  337. package/lib/quoxon/mouse.js +211 -0
  338. package/lib/quoxon/noai.js +57 -0
  339. package/lib/quoxon/objects/agent.js +61 -0
  340. package/lib/quoxon/objects/away.js +72 -0
  341. package/lib/quoxon/objects/crystal.js +100 -0
  342. package/lib/quoxon/objects/fetch.js +182 -0
  343. package/lib/quoxon/objects/fleet.js +149 -0
  344. package/lib/quoxon/objects/health.js +186 -0
  345. package/lib/quoxon/objects/index.js +106 -0
  346. package/lib/quoxon/objects/ladder.js +71 -0
  347. package/lib/quoxon/objects/memory.js +44 -0
  348. package/lib/quoxon/objects/mirror.js +137 -0
  349. package/lib/quoxon/objects/model.js +118 -0
  350. package/lib/quoxon/objects/peek.js +17 -0
  351. package/lib/quoxon/objects/proof.js +110 -0
  352. package/lib/quoxon/objects/prove.js +130 -0
  353. package/lib/quoxon/objects/replay.js +125 -0
  354. package/lib/quoxon/objects/sitrep.js +58 -0
  355. package/lib/quoxon/objects/skill.js +105 -0
  356. package/lib/quoxon/objects/view.js +87 -0
  357. package/lib/quoxon/objects/workflow.js +119 -0
  358. package/lib/quoxon/observers.js +42 -0
  359. package/lib/quoxon/onboarding/copy.js +263 -0
  360. package/lib/quoxon/onboarding/credential.js +108 -0
  361. package/lib/quoxon/onboarding/detect.js +22 -0
  362. package/lib/quoxon/onboarding/dockerOffer.js +45 -0
  363. package/lib/quoxon/onboarding/failureCause.js +33 -0
  364. package/lib/quoxon/onboarding/finish.js +134 -0
  365. package/lib/quoxon/onboarding/index.js +94 -0
  366. package/lib/quoxon/onboarding/installRunner.js +284 -0
  367. package/lib/quoxon/onboarding/intent.js +53 -0
  368. package/lib/quoxon/onboarding/journey.js +73 -0
  369. package/lib/quoxon/onboarding/preflight.js +156 -0
  370. package/lib/quoxon/onboarding/probe.js +65 -0
  371. package/lib/quoxon/onboarding/runner.js +58 -0
  372. package/lib/quoxon/onboarding/view.js +682 -0
  373. package/lib/quoxon/orgLabel.js +10 -0
  374. package/lib/quoxon/orgSwitch.js +33 -0
  375. package/lib/quoxon/ownBroadcast.js +22 -0
  376. package/lib/quoxon/palette.js +43 -0
  377. package/lib/quoxon/print.js +98 -0
  378. package/lib/quoxon/profileSwitch.js +53 -0
  379. package/lib/quoxon/promptHistory.js +41 -0
  380. package/lib/quoxon/providers.js +48 -0
  381. package/lib/quoxon/qart.js +348 -0
  382. package/lib/quoxon/qdragon.js +410 -0
  383. package/lib/quoxon/qdragonFly.js +61 -0
  384. package/lib/quoxon/qdragonScenes.js +282 -0
  385. package/lib/quoxon/qeyes.js +213 -0
  386. package/lib/quoxon/qglyph.js +143 -0
  387. package/lib/quoxon/qhello.js +58 -0
  388. package/lib/quoxon/qmotion.js +132 -0
  389. package/lib/quoxon/render.js +1167 -0
  390. package/lib/quoxon/resend.js +72 -0
  391. package/lib/quoxon/roster.js +307 -0
  392. package/lib/quoxon/route.js +39 -0
  393. package/lib/quoxon/rows.js +711 -0
  394. package/lib/quoxon/rowsStore.js +80 -0
  395. package/lib/quoxon/rules.js +130 -0
  396. package/lib/quoxon/screenContext.js +150 -0
  397. package/lib/quoxon/screenFrames.js +254 -0
  398. package/lib/quoxon/session.js +238 -0
  399. package/lib/quoxon/sessionDead.js +17 -0
  400. package/lib/quoxon/signin.js +125 -0
  401. package/lib/quoxon/skills.js +30 -0
  402. package/lib/quoxon/slash/agents.js +112 -0
  403. package/lib/quoxon/slash/argSources.js +65 -0
  404. package/lib/quoxon/slash/args.js +65 -0
  405. package/lib/quoxon/slash/automate.js +89 -0
  406. package/lib/quoxon/slash/broadcast.js +140 -0
  407. package/lib/quoxon/slash/broadcastRun.js +108 -0
  408. package/lib/quoxon/slash/card.js +30 -0
  409. package/lib/quoxon/slash/challenge.js +114 -0
  410. package/lib/quoxon/slash/cliCommand.js +53 -0
  411. package/lib/quoxon/slash/cliLeaves.json +948 -0
  412. package/lib/quoxon/slash/compact.js +90 -0
  413. package/lib/quoxon/slash/confirm.js +30 -0
  414. package/lib/quoxon/slash/crystallize.js +69 -0
  415. package/lib/quoxon/slash/dashboard.js +136 -0
  416. package/lib/quoxon/slash/draft.js +54 -0
  417. package/lib/quoxon/slash/hatWalk.js +206 -0
  418. package/lib/quoxon/slash/inverses.js +77 -0
  419. package/lib/quoxon/slash/killer.js +24 -0
  420. package/lib/quoxon/slash/killerApi.js +16 -0
  421. package/lib/quoxon/slash/ledger.js +88 -0
  422. package/lib/quoxon/slash/listView.js +30 -0
  423. package/lib/quoxon/slash/modelCmd.js +261 -0
  424. package/lib/quoxon/slash/palette.js +118 -0
  425. package/lib/quoxon/slash/paletteController.js +169 -0
  426. package/lib/quoxon/slash/panels.js +116 -0
  427. package/lib/quoxon/slash/picker.js +56 -0
  428. package/lib/quoxon/slash/restart.js +202 -0
  429. package/lib/quoxon/slash/resume.js +59 -0
  430. package/lib/quoxon/slash/rowCmd.js +157 -0
  431. package/lib/quoxon/slash/rowWalk.js +175 -0
  432. package/lib/quoxon/slash/settings.js +60 -0
  433. package/lib/quoxon/slash/spawn.js +177 -0
  434. package/lib/quoxon/slash/stepUp.js +274 -0
  435. package/lib/quoxon/slash/stepUpCard.js +60 -0
  436. package/lib/quoxon/slash/stepUpCmds.js +78 -0
  437. package/lib/quoxon/slash/undoApi.js +38 -0
  438. package/lib/quoxon/slash/undoCmd.js +49 -0
  439. package/lib/quoxon/slash/undoWish.js +15 -0
  440. package/lib/quoxon/slash/watch.js +164 -0
  441. package/lib/quoxon/slash/wish.js +23 -0
  442. package/lib/quoxon/slash/wishCmd.js +32 -0
  443. package/lib/quoxon/slotChat.js +300 -0
  444. package/lib/quoxon/slotFormat.js +195 -0
  445. package/lib/quoxon/slotRun.js +131 -0
  446. package/lib/quoxon/sound/index.js +186 -0
  447. package/lib/quoxon/sound/mapping.js +120 -0
  448. package/lib/quoxon/sound/output.js +52 -0
  449. package/lib/quoxon/sound/synth.js +122 -0
  450. package/lib/quoxon/stray.js +22 -0
  451. package/lib/quoxon/suggestCommand.js +59 -0
  452. package/lib/quoxon/term.js +141 -0
  453. package/lib/quoxon/textBuffer.js +416 -0
  454. package/lib/quoxon/theme.js +286 -0
  455. package/lib/quoxon/tips.js +433 -0
  456. package/lib/quoxon/toolError.js +41 -0
  457. package/lib/quoxon/transcript.js +188 -0
  458. package/lib/quoxon/web/qface.js +89 -0
  459. package/lib/quoxon/welcome.js +52 -0
  460. package/lib/quoxon/whatsnew.js +136 -0
  461. package/lib/quoxon/whatsnew.jsonl +89 -0
  462. package/lib/quoxon/windowOrg.js +113 -0
  463. package/lib/server/diag.js +129 -0
  464. package/lib/server/doctor.js +71 -0
  465. package/lib/server/install.js +149 -0
  466. package/lib/server/pluginEnable.js +161 -0
  467. package/lib/server/skew.js +56 -0
  468. package/lib/server/snapshot.js +131 -0
  469. package/lib/server/status.js +128 -0
  470. package/lib/server/sys.js +65 -0
  471. package/lib/server/uninstall.js +63 -0
  472. package/lib/server/update.js +234 -0
  473. package/lib/toolOutputShape.js +315 -0
  474. package/lib/tui/app.jsx +289 -0
  475. package/lib/tui/components/Breadcrumb.jsx +42 -0
  476. package/lib/tui/components/ChatInput.jsx +68 -0
  477. package/lib/tui/components/Confirm.jsx +32 -0
  478. package/lib/tui/components/DataTable.jsx +270 -0
  479. package/lib/tui/components/DetailPanel.jsx +241 -0
  480. package/lib/tui/components/HelpOverlay.jsx +67 -0
  481. package/lib/tui/components/Layout.jsx +129 -0
  482. package/lib/tui/components/Palette.jsx +141 -0
  483. package/lib/tui/components/SearchInput.jsx +125 -0
  484. package/lib/tui/components/Sparkline.jsx +55 -0
  485. package/lib/tui/components/StatusBar.jsx +133 -0
  486. package/lib/tui/components/Toast.jsx +52 -0
  487. package/lib/tui/hooks/useApi.js +44 -0
  488. package/lib/tui/hooks/useHealth.js +90 -0
  489. package/lib/tui/hooks/usePolledApi.js +86 -0
  490. package/lib/tui/hooks/useTerminalSize.js +46 -0
  491. package/lib/tui/index.js +56 -0
  492. package/lib/tui/intro/Intro.jsx +332 -0
  493. package/lib/tui/jsx-loader.js +32 -0
  494. package/lib/tui/keys.js +87 -0
  495. package/lib/tui/registry.js +49 -0
  496. package/lib/tui/theme.js +103 -0
  497. package/lib/tui/views/AdminView.jsx +398 -0
  498. package/lib/tui/views/AgentView.jsx +204 -0
  499. package/lib/tui/views/BackupView.jsx +225 -0
  500. package/lib/tui/views/BrainView.jsx +223 -0
  501. package/lib/tui/views/ChatView.jsx +468 -0
  502. package/lib/tui/views/FilesView.jsx +218 -0
  503. package/lib/tui/views/FleetView.jsx +234 -0
  504. package/lib/tui/views/GovernanceView.jsx +453 -0
  505. package/lib/tui/views/HealthView.jsx +216 -0
  506. package/lib/tui/views/HyperionDeck.jsx +79 -0
  507. package/lib/tui/views/InboxView.jsx +228 -0
  508. package/lib/tui/views/LucidDeck.jsx +719 -0
  509. package/lib/tui/views/MainMenu.jsx +123 -0
  510. package/lib/tui/views/MemoryView.jsx +377 -0
  511. package/lib/tui/views/ObjectivesView.jsx +230 -0
  512. package/lib/tui/views/OrgView.jsx +229 -0
  513. package/lib/tui/views/ToolView.jsx +221 -0
  514. package/lib/tui/views/VaultView.jsx +422 -0
  515. package/lib/tui/views/WorkflowView.jsx +329 -0
  516. package/package.json +75 -4
@@ -0,0 +1,125 @@
1
+ /**
2
+ * /replay [run | conversation id] [page]: reconstruct a previous agent run from the audit trail, in order:
3
+ * the decisions (turn messages), each tool with an args summary, its output and its receipt. Read-only:
4
+ * nothing is re-executed (sandbox re-execution is not available). Default is the last turn of this
5
+ * conversation. Sources: the conversation's saved turns, this session's tool calls, and AEE envelopes
6
+ * (GET /aee/:id, GET /aee/query?corr=). A conversation id replays the messages only: the server does not link
7
+ * tool envelopes to a conversation, so the view says so and points at /replay <envelope id> for a tool run.
8
+ */
9
+ import { seg, fit, fitRow, short, dur, boxWidth, parseTs } from './model.js';
10
+
11
+ export const PAGE = 6;
12
+
13
+ /** '' | '2' | 'abc' | 'abc 3' | 'abc page 3' | 'page 3' -> { ref, page } */
14
+ export function parseReplayArg(arg) {
15
+ let t = String(arg || '').trim();
16
+ let page = 1;
17
+ const m = /(?:^|\s)(?:page\s+)?(\d{1,4})$/i.exec(t);
18
+ const pm = /(?:^|\s)page\s+(\d{1,4})$/i.exec(t);
19
+ if (pm) { page = Number(pm[1]); t = t.slice(0, pm.index).trim(); }
20
+ else if (m && (m.index > 0 || t === m[1]) && !/^\d{5,}$/.test(t)) { page = Number(m[1]); t = t.slice(0, m.index).trim(); }
21
+ return { ref: t || null, page: Math.max(1, page) };
22
+ }
23
+
24
+ const receiptOf = (c) => `${c.envelopeId ? `receipt ${c.envelopeId}` : 'no receipt id'}${c.receipt?.verified && c.receipt.ward_seq != null ? ` · WARD seq ${c.receipt.ward_seq}` : ''}`;
25
+
26
+ /** { messages: [{ role, content }], calls: [tool blocks] } -> steps: the question, each tool, then the answer. */
27
+ export function buildTurnSteps({ messages = [], calls = [] }) {
28
+ const steps = [];
29
+ const users = messages.filter(m => m.role === 'user'), agents = messages.filter(m => m.role !== 'user');
30
+ for (const m of users) steps.push({ kind: 'user', text: String(m.content ?? '') });
31
+ for (const c of calls) steps.push({ kind: 'tool', tool: c.tool, args: c.summary || '', status: c.status, out: c.resultSummary || '', ms: c.durationMs, receipt: receiptOf(c), id: c.envelopeId || null });
32
+ for (const m of agents) steps.push({ kind: 'agent', text: String(m.content ?? '') });
33
+ return steps;
34
+ }
35
+
36
+ /** AEE envelopes of one correlation id -> steps in time order. */
37
+ export function buildEnvelopeSteps(envs = []) {
38
+ const sorted = [...envs].sort((a, b) => (parseTs(a.ts) ?? 0) - (parseTs(b.ts) ?? 0));
39
+ return sorted.map((e) => {
40
+ const p = e.payload || {};
41
+ const intent = String(e.intent || '');
42
+ if (/^ops\.tool\./.test(intent)) {
43
+ const ok = p.success !== false && !/\.failed$|\.denied$/.test(intent);
44
+ return { kind: 'tool', id: e.id, tool: p.tool_name || intent, args: p.input_summary || p.summary || '', status: /\.denied$/.test(intent) ? 'denied' : ok ? 'ok' : 'failed', out: ok ? (p.result_summary || '') : (p.error || intent), ms: p.duration_ms, receipt: `receipt ${e.id}` };
45
+ }
46
+ if (intent === 'aocl.policy.evaluated') return { kind: 'policy', id: e.id, text: p.allPassed === false ? 'policy blocked' : 'policy passed', receipt: `receipt ${e.id}` };
47
+ if (intent === 'aocl.identity.verified') return { kind: 'policy', id: e.id, text: 'identity verified', receipt: `receipt ${e.id}` };
48
+ return { kind: 'event', id: e.id, text: `${intent || 'envelope'}${e.from ? ` from ${e.from}` : ''}`, receipt: `receipt ${e.id}` };
49
+ });
50
+ }
51
+
52
+ const MARK = { ok: ['✔', 'ok'], failed: ['✖', 'error'], denied: ['✖', 'error'] };
53
+
54
+ /** d: { steps, page, size, title, notes } -> view { box, rows } */
55
+ export function replayView(d, cols) {
56
+ const w = boxWidth(cols, 96), inner = w - 4, nw = w < 60;
57
+ const size = d.size || PAGE;
58
+ const steps = d.steps || [];
59
+ const pages = Math.max(1, Math.ceil(steps.length / size));
60
+ const page = Math.min(Math.max(1, d.page || 1), pages);
61
+ const rows = [];
62
+ if (!steps.length) rows.push([seg('nothing recorded for this run', 'muted')]);
63
+ const base = (page - 1) * size;
64
+ steps.slice(base, base + size).forEach((s, i) => {
65
+ const n = String(base + i + 1).padStart(2);
66
+ const label = s.kind === 'user' ? 'you' : s.kind === 'agent' ? 'agent' : s.kind === 'tool' ? 'tool' : s.kind === 'policy' ? 'guard' : 'event';
67
+ const lrole = s.kind === 'user' ? 'sky' : s.kind === 'agent' ? 'violet' : s.kind === 'tool' ? 'indigo' : 'muted';
68
+ if (s.kind === 'tool') {
69
+ const [m, mr] = MARK[s.status] || ['○', 'muted'];
70
+ rows.push([seg(n + ' ', 'muted'), seg(label.padEnd(6), lrole, true), seg(`${s.tool} `, 'value', true), seg(m, mr), seg(` ${s.status || 'unknown'}${s.ms != null ? ` ${dur(s.ms)}` : ''}`, mr)]);
71
+ if (s.args) rows.push([seg(' args ', 'muted'), seg(s.args, 'value')]);
72
+ if (s.out) rows.push([seg(' output ', 'muted'), seg(s.out, s.status === 'ok' ? 'value' : 'warn')]);
73
+ rows.push([seg(' ', 'muted'), seg(s.receipt || 'no receipt id', 'muted')]);
74
+ } else {
75
+ rows.push([seg(n + ' ', 'muted'), seg(label.padEnd(6), lrole, true), seg(s.text || '', s.kind === 'event' ? 'muted' : 'value')]);
76
+ if (s.receipt && s.kind !== 'user' && s.kind !== 'agent') rows.push([seg(' ', 'muted'), seg(s.receipt, 'muted')]);
77
+ }
78
+ });
79
+ for (const n of d.notes || []) rows.push([seg(`note: ${n}`, 'warn')]);
80
+ rows.push([seg(`page ${page} of ${pages}`, 'value', true), seg(page < pages ? `${nw ? '' : ' · '}${nw ? ' ' : ''}/replay${d.ref ? ` ${short(d.ref, 12)}` : ''} ${page + 1} for the next` : '', 'muted')]);
81
+ rows.push([seg('read-only: rebuilt from the audit trail, nothing is re-run', 'muted')]);
82
+ return { box: { width: w, title: `Replay · ${d.title || 'last turn'}`, titleRole: 'violet', border: 'violet' }, rows: rows.map(r => fitRow(r, inner)) };
83
+ }
84
+
85
+ /** Fetchers for createObjectsApi. deps: { get, listOf, why, verifyReceipt, aeeGet } */
86
+ export function replayFetchers({ get, listOf, why, verifyReceipt, aeeGet }) {
87
+ const turns = async (id) => listOf(await get('collector', `/api/v1/conversations/${encodeURIComponent(id)}/turns`, { limit: 200 }, 12000), 'turns');
88
+ const corrList = async (corr) => listOf(await get('collector', '/aee/query', { corr, limit: 100 }, 12000), 'envelopes');
89
+ return {
90
+ /** a: { ref, page, conversationId, calls } -> { data } | { error, tone } */
91
+ async replay(a) {
92
+ const page = a.page || 1;
93
+ if (!a.ref) {
94
+ const calls = await Promise.all((a.calls || []).slice(-12).map(async (c) => {
95
+ if (!c.envelopeId || (c.receipt?.verified && c.receipt.ward_seq != null)) return c;
96
+ const r = await verifyReceipt(c.envelopeId, 6);
97
+ const res = r.ok ? r.result : null;
98
+ return res?.status === 'WITNESSED' ? { ...c, receipt: { verified: true, ward_seq: res.entry?.seq } } : c;
99
+ }));
100
+ let messages = [], notes = [];
101
+ try {
102
+ const rows = await turns(a.conversationId);
103
+ let from = 0;
104
+ for (let i = rows.length - 1; i >= 0; i--) if (rows[i].role === 'user') { from = i; break; }
105
+ messages = rows.slice(from).filter(r => r.role === 'user' || r.role === 'assistant');
106
+ } catch (e) { notes.push(`the saved turn messages could not be read (${why(e)}); showing tool calls only`); }
107
+ return { data: { steps: buildTurnSteps({ messages, calls }), page, title: 'last turn', notes } };
108
+ }
109
+ let rows = null;
110
+ try { rows = await turns(a.ref); } catch (e) { if (e?.status && e.status !== 404 && e.status !== 400) return { error: `replay: ${why(e)}`, tone: 'warn' }; }
111
+ if (rows && rows.length) {
112
+ const steps = rows.filter(r => r.role === 'user' || r.role === 'assistant').map(r => ({ kind: r.role === 'user' ? 'user' : 'agent', text: String(r.content ?? '') }));
113
+ return { data: { steps, page, ref: a.ref, title: `conversation ${short(a.ref, 12)}`, notes: ['tool calls are not linked to a conversation id on the server: /replay <envelope id> replays a tool run'] } };
114
+ }
115
+ let corr = a.ref, seen = null;
116
+ const env = await aeeGet(a.ref);
117
+ if (env.ok && env.env) { seen = env.env; corr = env.env.corr || a.ref; }
118
+ let list = [];
119
+ try { list = await corrList(corr); } catch (e) { return { error: `replay: ${why(e)}`, tone: 'warn' }; }
120
+ if (seen && !list.some(e => e.id === seen.id)) list = [...list, seen];
121
+ if (!list.length) return { error: `No run, conversation or envelope called "${a.ref}".`, tone: 'warn' };
122
+ return { data: { steps: buildEnvelopeSteps(list), page, ref: a.ref, title: `run ${short(corr, 14)}`, notes: [] } };
123
+ }
124
+ };
125
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * /sitrep: the situation NOW, from persisted data only (no model call): approvals waiting (auth inbox),
3
+ * what needs you (LUCID needs_you, by urgency), running work (LUCID in_motion), and what Quox cannot see
4
+ * (LUCID silent / failing / unconnected feeds, plus any source this card could not read). /away is the
5
+ * "since you were last here" digest; this is the present tense.
6
+ */
7
+ import { seg, fit, plural, boxWidth, parseTs, ago } from './model.js';
8
+
9
+ const URG = { now: 0, today: 1, 'this week': 2, whenever: 3, fyi: 4 };
10
+ const hrs = (ms) => { const m = Math.round((ms || 0) / 60000); return m < 60 ? `${m}m` : m < 2880 ? `${Math.round(m / 60)}h` : `${Math.round(m / 1440)}d`; };
11
+
12
+ /** sit/appr: { ok, v | error } parts. -> { approvals: [..]|null, needs, running, blind } */
13
+ export function sitrepData(sit, appr, now = Date.now()) {
14
+ const blind = [];
15
+ let needs = [], running = [];
16
+ if (sit?.ok) {
17
+ const s = sit.v?.situation || sit.v || {};
18
+ needs = (s.needs_you || []).filter(n => n.kind !== 'approval')
19
+ .map(n => ({ title: n.L0 || n.ref, urgency: n.urgency, ts: n.L1?.when?.since ?? n.status_since ?? null, ref: n.ref }))
20
+ .sort((a, b) => (URG[a.urgency] ?? 5) - (URG[b.urgency] ?? 5) || (parseTs(b.ts) ?? 0) - (parseTs(a.ts) ?? 0));
21
+ running = (s.in_motion || []).map(m => ({ title: m.L0 || m.ref, ref: m.ref }));
22
+ const cs = s.cannot_see || {};
23
+ for (const x of cs.silent || []) blind.push({ source: `lucid:${x.feed}`, reason: `silent ${hrs(x.silent_ms)}` });
24
+ for (const x of cs.failing || []) blind.push({ source: `lucid:${x.feed}`, reason: `failing: ${x.error}` });
25
+ for (const n of cs.unwired || []) blind.push({ source: `lucid:${n}`, reason: 'not connected' });
26
+ } else blind.push({ source: 'lucid', reason: sit?.error || 'not read' });
27
+ let approvals = null;
28
+ if (appr?.ok) approvals = (appr.v || []).map(a => ({ title: a.title || a.summary || a.id, ts: a.created_at, ref: a.id }));
29
+ else blind.push({ source: 'approvals', reason: appr?.error || 'not read' });
30
+ return { approvals, needs, running, blind, now };
31
+ }
32
+
33
+ /** d: sitrepData(...) + now */
34
+ export function sitrepCard(d, cols, { maxNeeds = 5, maxRunning = 3, maxApprovals = 3 } = {}) {
35
+ const now = d.now ?? Date.now();
36
+ const w = boxWidth(cols, 96), inner = w - 4;
37
+ const rows = [];
38
+ const ap = d.approvals || [], needs = d.needs || [], run = d.running || [];
39
+ const line = (g, role, title, meta) => {
40
+ const m = meta ? ` ${meta}` : '';
41
+ return [seg(g, role), seg(fit(title, Math.max(8, inner - 2 - m.length)), 'value'), seg(m, 'muted')];
42
+ };
43
+ for (const a of ap.slice(0, maxApprovals)) rows.push(line('⚠ ', 'warn', `Approval: ${a.title}`, a.ts ? `waiting ${ago(a.ts, now)}` : ''));
44
+ if (ap.length > maxApprovals) rows.push([seg(`+${ap.length - maxApprovals} more approvals · /approvals`, 'muted')]);
45
+ for (const n of needs.slice(0, maxNeeds)) rows.push(line(n.urgency === 'now' ? '⚠ ' : '◐ ', n.urgency === 'now' ? 'warn' : 'muted', n.title, n.urgency || ''));
46
+ if (needs.length > maxNeeds) rows.push([seg(`+${needs.length - maxNeeds} more · quox lucid`, 'muted')]);
47
+ if (!ap.length && !needs.length) rows.push([seg('Nothing needs you right now.', 'muted')]);
48
+ if (run.length) {
49
+ rows.push([seg(' ')]);
50
+ for (const r of run.slice(0, maxRunning)) rows.push(line('◐ ', 'indigo', r.title, ''));
51
+ if (run.length > maxRunning) rows.push([seg(`+${run.length - maxRunning} more running · /roster all`, 'muted')]);
52
+ }
53
+ if ((d.blind || []).length) rows.push([seg(fit(`Can't see: ${d.blind.map(b => (b.reason ? `${b.source} (${b.reason})` : b.source)).join(', ')}`, inner), 'faint')]);
54
+ const right = w < 60
55
+ ? [d.approvals ? `${ap.length} ap` : null, `${needs.length} need`, `${run.length} run`].filter(Boolean).join(' · ')
56
+ : [d.approvals ? plural(ap.length, 'approval') : null, `${needs.length} need you`, `${run.length} running`].filter(Boolean).join(' · ');
57
+ return { box: { width: w, title: 'Situation now', titleRole: 'value', right, rightRole: 'muted', border: ap.length || needs.some(n => n.urgency === 'now') ? 'warn' : 'muted' }, rows };
58
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * E1 skill card from a real QSKL skill record (GET /quoxflow/skills/:id) plus, when reachable, its
3
+ * quoxflow scoreboard row (GET /api/quox-skills/scoreboards). Tests: the record carries test
4
+ * DEFINITIONS in `tests`; results exist only once run-tests has written `evals.tests`
5
+ * ({ total, passed, failed, last_run_at, results }). Never shows a pass that was not recorded.
6
+ */
7
+ import { seg, fit, ago, day, plural, short, boxWidth } from './model.js';
8
+
9
+ const EDITION_ROLE = { stable: 'ok', experimental: 'warn', archived: 'muted' };
10
+
11
+ /** -> { word, role } for the review state the record actually states. */
12
+ export function reviewState(s) {
13
+ if (s?.reviewNeeded) return { word: 'review needed', role: 'warn' };
14
+ const e = String(s?.edition || s?.status || '').toLowerCase();
15
+ return e ? { word: e, role: EDITION_ROLE[e] || 'muted' } : { word: 'state unknown', role: 'muted' };
16
+ }
17
+
18
+ /** -> { dots:[{ch,role}], text, role } or null when the skill has no tests at all. */
19
+ export function testsSummary(s, now) {
20
+ const run = s?.evals?.tests;
21
+ if (run && Number.isFinite(Number(run.total))) {
22
+ const total = Number(run.total), passed = Number(run.passed) || 0, failed = Number(run.failed) || 0;
23
+ const res = Array.isArray(run.results) ? run.results : null;
24
+ const dots = res && res.length === total
25
+ ? res.map(r => ({ ch: '●', role: r.passed === true || r.status === 'passed' || r.ok === true ? 'ok' : 'error' }))
26
+ : [...Array(passed).fill({ ch: '●', role: 'ok' }), ...Array(Math.max(0, total - passed)).fill({ ch: '●', role: 'error' })];
27
+ const when = run.last_run_at ? ` · ${ago(run.last_run_at, now)} ago` : '';
28
+ if (passed === total && total > 0) return { dots, text: `${passed}/${total} pass${when}`, role: 'ok' };
29
+ return { dots, text: `${passed}/${total} pass · ${failed || total - passed} failing${when}`, role: 'error' };
30
+ }
31
+ const defined = s?.tests && typeof s.tests === 'object' ? Object.keys(s.tests).length : 0;
32
+ if (!defined) return null;
33
+ return { dots: Array(defined).fill({ ch: '○', role: 'muted' }), text: `${defined} defined · never run`, role: 'muted' };
34
+ }
35
+
36
+ const sourceOf = (s) => {
37
+ const parts = [];
38
+ if (s.category) parts.push(s.category);
39
+ if (s.createdAt) parts.push(`created ${day(s.createdAt)}`);
40
+ const tag = (s.tags || []).find(t => /^source:/.test(t));
41
+ if (tag) parts.push(`from ${tag.split(':')[1] === 'notesq' ? 'NotesQ' : tag.split(':')[1]}`);
42
+ if (s.authoringEnvelopeId) parts.push(`authored in ${short(s.authoringEnvelopeId, 12)}`);
43
+ if (s.lastPatchedBy) parts.push('patched since');
44
+ return parts.join(' · ');
45
+ };
46
+
47
+ /**
48
+ * d: { skill, scoreboard: { ok, row } | null, agentName?: (id) => string, now }
49
+ * -> view { box, rows }
50
+ */
51
+ export function skillCard(d, cols) {
52
+ const s = d.skill || {};
53
+ const now = d.now ?? Date.now();
54
+ const w = boxWidth(cols, 72), inner = w - 4, nw = w < 50;
55
+ const rv = reviewState(s);
56
+ const name = s.name || s.id;
57
+ const right = s.version ? (nw ? `v${s.version}` : `v${s.version} · ${rv.word}`) : rv.word;
58
+ const rows = [];
59
+ if (s.description) rows.push([seg(fit(s.description, inner))]);
60
+ if (nw) rows.push([seg(rv.word, rv.role)]);
61
+
62
+ const agentName = d.agentName || ((id) => id);
63
+ const agents = (s.bestForAgents || []).map(id => String(agentName(id) || id));
64
+ const t = testsSummary(s, now);
65
+ const testRow = [];
66
+ if (t) {
67
+ testRow.push(seg('tests ', 'muted'));
68
+ for (const dt of t.dots.slice(0, 8)) testRow.push(seg(dt.ch, dt.role));
69
+ testRow.push(seg(` ${t.text}`, t.role));
70
+ } else testRow.push(seg('tests ', 'muted'), seg('none defined', 'muted'));
71
+ if (!nw && agents.length) {
72
+ testRow.push(seg(' agents ', 'muted'));
73
+ agents.slice(0, 3).forEach((a, i) => { if (i) testRow.push(seg(' ')); testRow.push(seg(a.toUpperCase(), `agent:${a}`)); });
74
+ if (agents.length > 3) testRow.push(seg(` +${agents.length - 3}`, 'muted'));
75
+ }
76
+ rows.push(testRow);
77
+ if (nw && agents.length) rows.push([seg('agents ', 'muted'), seg(agents.slice(0, 3).map(a => a.toUpperCase()).join(', '), `agent:${agents[0]}`)]);
78
+
79
+ const src = sourceOf(s);
80
+ if (src) rows.push([seg(fit(src, inner), 'muted')]);
81
+
82
+ const use = [];
83
+ const sb = d.scoreboard;
84
+ if (sb?.ok) {
85
+ const r = sb.row;
86
+ const n30 = Number(r?.total_invocations_30d) || 0;
87
+ if (!r || !n30) use.push(r?.last_used_at ? `no runs in 30d · last ${ago(r.last_used_at, now)} ago` : 'no recorded runs');
88
+ else {
89
+ use.push(`used ${plural(n30, 'time')} in 30d`);
90
+ if (r.last_used_at) use.push(`last ${ago(r.last_used_at, now)} ago`);
91
+ if (r.success_rate_30d != null) use.push(`${Math.round(Number(r.success_rate_30d) * 100)}% ok`);
92
+ }
93
+ }
94
+ const judge = s.evals?.judge;
95
+ if (judge && judge.avg_score != null) use.push(`judge ${judge.avg_score}/5${judge.scored_at ? ` (${day(judge.scored_at)})` : ''}`);
96
+ if (use.length) rows.push([seg(fit(use.join(' · '), inner), 'muted')]);
97
+
98
+ if (!nw && Array.isArray(s.policySatisfies) && s.policySatisfies.length) rows.push([seg(fit(`satisfies ${s.policySatisfies.join(', ')}`, inner), 'muted')]);
99
+
100
+ // Next possibility: only a capability that exists today. /skill runs a skill through a governed turn.
101
+ if (String(s.edition).toLowerCase() !== 'archived') rows.push([seg('next ', 'muted'), seg(`/skill ${name}`, 'key'), seg(nw ? ' runs it' : ' [args] runs it (governed turn)', 'muted')]);
102
+ else rows.push([seg('archived: kept for the record, not offered to agents', 'muted')]);
103
+
104
+ return { box: { width: w, title: `Skill · ${name}`, right, rightRole: rv.role, border: 'sky' }, rows };
105
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * <ObjectView/>: the one Ink component for the inline object views. It maps a pure view (rows of
3
+ * { text, role } segments, optional box) to <Text> runs. `t` is seconds since arrival for the lab's
4
+ * decode-in (rows start 0.1 s apart); the default Infinity is the settled card, which is what history
5
+ * shows while there is no shared motion clock on main. Quiet (NO_COLOR or reduced motion) is always
6
+ * settled; NO_COLOR also drops every colour (c() returns undefined).
7
+ */
8
+ import React from 'react';
9
+ import { Box, Text } from 'ink';
10
+ import { c, agentColor, mono } from '../theme.js';
11
+ import { reducedMotion } from '../motion/clock.js';
12
+ import { buildObject } from './index.js';
13
+ import { decodeRow, padRow, fit, len } from './model.js';
14
+
15
+ const h = React.createElement;
16
+
17
+ /** Role -> Ink colour. agent:<name> uses the stable agent shade. */
18
+ export function roleColor(role) {
19
+ if (mono()) return undefined;
20
+ if (typeof role === 'string' && role.startsWith('agent:')) return agentColor(role.slice(6));
21
+ return c(role || 'value');
22
+ }
23
+
24
+ function runsOf(cells, key) {
25
+ const out = [];
26
+ let run = '', role, bold = false, glyph = false, k = 0;
27
+ const flush = () => { if (run) out.push(h(Text, { key: `${key}-${k++}`, color: glyph ? roleColor('faint') : roleColor(role), bold }, run)); run = ''; };
28
+ for (const cl of cells) {
29
+ if (cl.role !== role || cl.bold !== bold || cl.glyph !== glyph) { flush(); role = cl.role; bold = cl.bold; glyph = cl.glyph; }
30
+ run += cl.ch;
31
+ }
32
+ flush();
33
+ return out;
34
+ }
35
+
36
+ /** Rows start this far apart (at most 0.1 s, the lab) so the last one lands inside the 0.65 s reveal window. */
37
+ export const STAGGER_SPAN = 0.3;
38
+ export const rowStart = (i, n) => i * Math.min(0.1, STAGGER_SPAN / Math.max(1, n - 1));
39
+ const rowNode = (row, i, n, t, key) => h(Text, { key, wrap: 'truncate' }, ...runsOf(decodeRow(row, t, rowStart(i, n), 0.25, 70 + i), key));
40
+
41
+ export function ObjectView({ item, cols, fx = null, t = fx && fx.e != null ? fx.e : Infinity, now }) {
42
+ const view = buildObject(item.obj || item, cols, now);
43
+ const tt = reducedMotion() ? Infinity : t;
44
+ const rows = view.rows || [];
45
+ if (!view.box) {
46
+ return h(Box, { flexDirection: 'column', marginTop: 1, paddingLeft: 2 }, ...rows.map((r, i) => rowNode(r, i, rows.length, tt, `r${i}`)));
47
+ }
48
+ const b = view.box, w = b.width, inner = w - 4;
49
+ const bc = roleColor(b.border || 'muted');
50
+ const right = b.right ? ` ${b.right} ` : '';
51
+ const title = b.title ? ` ${fit(b.title, Math.max(4, w - 6 - (right ? len(right) + 1 : 0)))} ` : '';
52
+ const fill = Math.max(0, w - 3 - len(title) - len(right) - 1);
53
+ const top = h(Text, { key: 'top', wrap: 'truncate' },
54
+ h(Text, { color: bc }, '╭─'),
55
+ h(Text, { color: roleColor(b.titleRole || 'value'), bold: true }, title),
56
+ h(Text, { color: bc }, '─'.repeat(fill)),
57
+ h(Text, { color: roleColor(b.rightRole || 'muted') }, right),
58
+ h(Text, { color: bc }, '─╮'));
59
+ const body = rows.map((r, i) => h(Text, { key: `b${i}`, wrap: 'truncate' },
60
+ h(Text, { color: bc }, '│ '), ...runsOf(decodeRow(padRow(r, inner), tt, rowStart(i, rows.length), 0.25, 70 + i), `b${i}`), h(Text, { color: bc }, ' │')));
61
+ const bottom = h(Text, { key: 'bot', color: bc }, '╰' + '─'.repeat(w - 2) + '╯');
62
+ return h(Box, { flexDirection: 'column', marginTop: 1, paddingLeft: 1 }, top, ...body, bottom);
63
+ }
64
+
65
+ /**
66
+ * TUI-UX #5: would this card (rows + border + margin) be taller than the terminal? Ink cannot erase rows that already scrolled
67
+ * off the top of a live region, so a decode-in on such a card leaves a half-decoded copy in scrollback. Callers skip the
68
+ * animation for it and commit it settled.
69
+ */
70
+ export function cardTallerThanScreen(item, cols, termRows, now) {
71
+ if (!Number.isFinite(termRows) || termRows <= 0) return false;
72
+ const view = buildObject(item.obj || item, cols, now);
73
+ return (view.rows || []).length + (view.box ? 3 : 1) + 2 >= termRows; // top + bottom border, marginTop, plus the composer line
74
+ }
75
+
76
+ /** Plain text of a view at a width (tests, transcripts, --print): the box drawn with the same geometry. */
77
+ export function objectText(item, cols, now) {
78
+ const view = buildObject(item.obj || item, cols, now);
79
+ const rt = (r) => r.map(s => s.text).join('');
80
+ if (!view.box) return view.rows.map(r => ' ' + rt(fitRowText(r, cols - 2))).join('\n');
81
+ const b = view.box, w = b.width, inner = w - 4;
82
+ const right = b.right ? ` ${b.right} ` : '';
83
+ const title = b.title ? ` ${fit(b.title, Math.max(4, w - 6 - (right ? len(right) + 1 : 0)))} ` : '';
84
+ const fill = Math.max(0, w - 3 - len(title) - len(right) - 1);
85
+ return [` ╭─${title}${'─'.repeat(fill)}${right}─╮`, ...view.rows.map(r => ` │ ${rt(padRow(r, inner))} │`), ` ╰${'─'.repeat(w - 2)}╯`].join('\n');
86
+ }
87
+ const fitRowText = (r, n) => padRow(r, n).filter((s, i, a) => !(i === a.length - 1 && /^ +$/.test(s.text)));
@@ -0,0 +1,119 @@
1
+ /**
2
+ * E2 workflow step flow from ONE real execution: the step list comes from the workflow definition
3
+ * (GET /api/workflows/:id on quoxflow) in edge order, and each step's state and timing from that
4
+ * execution's AEE envelopes (GET /api/executions/:id/envelopes: quox.flow.node.started | completed |
5
+ * failed | skipped, keyed by payload.nodeId). Only the running step moves; a human gate
6
+ * (approval:gate, human:task) that is reached shows amber. A step with no envelope is shown as
7
+ * not reached, and when no envelopes could be read every state is '?', never guessed.
8
+ */
9
+ import { seg, fit, dur, hhmm, short, parseTs } from './model.js';
10
+
11
+ export const isGateType = (type) => /^(approval|human|hitl)[:_-]|(^|:)(approval|hitl|human)(gate|task)?$/i.test(String(type || ''));
12
+
13
+ /** Definition nodes in execution order (Kahn over edges; definition order breaks ties). */
14
+ export function orderNodes(def) {
15
+ const nodes = Array.isArray(def?.nodes) ? def.nodes : [];
16
+ const edges = Array.isArray(def?.edges) ? def.edges : [];
17
+ const ids = nodes.map(n => n.id);
18
+ const indeg = new Map(ids.map(id => [id, 0]));
19
+ for (const e of edges) if (indeg.has(e.target) && indeg.has(e.source)) indeg.set(e.target, indeg.get(e.target) + 1);
20
+ const out = [], seen = new Set();
21
+ const queue = ids.filter(id => indeg.get(id) === 0);
22
+ while (queue.length) {
23
+ const id = queue.shift();
24
+ if (seen.has(id)) continue;
25
+ seen.add(id); out.push(id);
26
+ for (const e of edges) if (e.source === id && indeg.has(e.target)) { indeg.set(e.target, indeg.get(e.target) - 1); if (indeg.get(e.target) === 0) queue.push(e.target); }
27
+ }
28
+ for (const id of ids) if (!seen.has(id)) out.push(id); // a cycle or dangling edge: keep definition order
29
+ const byId = new Map(nodes.map(n => [n.id, n]));
30
+ return out.map(id => byId.get(id));
31
+ }
32
+
33
+ /** nodeId -> { started, completed, failed, skipped, payload, nodeName, nodeType } from envelopes. */
34
+ export function nodeStates(envelopes) {
35
+ const st = new Map();
36
+ for (const e of envelopes || []) {
37
+ const p = e?.payload || {};
38
+ const id = p.nodeId;
39
+ if (!id || !/^quox\.flow\.node\./.test(String(e.intent || ''))) continue;
40
+ const s = st.get(id) || { id };
41
+ const ts = parseTs(e.ts);
42
+ const kind = String(e.intent).slice('quox.flow.node.'.length);
43
+ if (kind === 'started') { if (s.started == null || ts < s.started) s.started = ts; s.nodeName ??= p.nodeName; s.nodeType ??= p.nodeType; }
44
+ else if (kind === 'completed') { s.completed = ts; s.result = p; }
45
+ else if (kind === 'failed') { s.failed = ts; s.error = p.error || p.message || null; }
46
+ else if (kind === 'skipped') s.skipped = ts;
47
+ st.set(id, s);
48
+ }
49
+ return st;
50
+ }
51
+
52
+ const triggerDetail = (n) => {
53
+ const c = n?.config || {};
54
+ return c.label || c.expression || c.event || c.path || '';
55
+ };
56
+
57
+ /**
58
+ * d: { execution, envelopes: [] | null, def: { nodes, edges } | null, now }
59
+ * -> view { rows } (no box: the lab draws this as an indented flow)
60
+ */
61
+ export function stepFlow(d, cols) {
62
+ const ex = d.execution || {};
63
+ const now = d.now ?? Date.now();
64
+ const nw = cols < 60;
65
+ const rows = [];
66
+ const status = String(ex.status || 'unknown');
67
+ const head = [seg(ex.workflowName || ex.workflowId || 'workflow', 'value', true), seg(' ')];
68
+ const meta = [`run ${short(ex.id, 10)}`, status];
69
+ if (!nw && ex.startedAt) meta.push(`started ${hhmm(ex.startedAt)}`);
70
+ head.push(seg(meta.join(' · '), status === 'failed' ? 'error' : 'muted'));
71
+ rows.push(head);
72
+
73
+ const states = d.envelopes ? nodeStates(d.envelopes) : null;
74
+ let nodes = d.def ? orderNodes(d.def) : [];
75
+ if (!nodes.length && states) nodes = [...states.values()].filter(s => !/_replay_\d+$/.test(s.id)).map(s => ({ id: s.id, name: s.nodeName, type: s.nodeType }));
76
+ if (!nodes.length) {
77
+ rows.push([seg(d.envelopes ? 'No step records for this run.' : 'Steps could not be read for this run (no definition or envelopes).', 'muted')]);
78
+ return { rows };
79
+ }
80
+ const running = status === 'running' || status === 'paused';
81
+ const nameW = Math.min(Math.max(12, Math.floor((cols - 8) * 0.45)), Math.max(8, ...nodes.map(n => [...String(n.name || n.id)].length)));
82
+ for (const n of nodes) {
83
+ const s = states?.get(n.id);
84
+ const type = n.type || s?.nodeType || '';
85
+ const gate = isGateType(type);
86
+ let mark = '?', mrole = 'muted', nrole = 'value', det = '', drole = 'muted', bold = false;
87
+ if (!states) { det = 'state not readable'; }
88
+ else if (/^trigger/.test(type)) { mark = '●'; mrole = 'sky'; det = triggerDetail(n); }
89
+ else if (s?.failed != null) { mark = '✖'; mrole = 'error'; det = fit(s.error ? `failed: ${s.error}` : 'failed', 60); drole = 'error'; }
90
+ else if (s?.completed != null) {
91
+ mark = '✓'; mrole = 'ok';
92
+ const r = s.result || {};
93
+ const bits = [];
94
+ if (r.actions_taken != null) bits.push(`${r.actions_taken} action${r.actions_taken === 1 ? '' : 's'}`);
95
+ if (s.started != null) bits.push(dur(s.completed - s.started));
96
+ det = bits.join(' · ');
97
+ } else if (s?.skipped != null) { mark = '○'; mrole = 'faint'; nrole = 'muted'; det = 'skipped'; }
98
+ else if (s?.started != null && running) {
99
+ if (gate) { mark = '◐'; mrole = 'warn'; det = 'waiting for approval'; drole = 'warn'; }
100
+ else { mark = '◐'; mrole = 'sky'; bold = true; det = `running · ${dur(now - s.started)}`; }
101
+ } else if (s?.started != null) { mark = '?'; det = `started, no end recorded (run ${status})`; drole = 'warn'; }
102
+ else { mark = '○'; mrole = 'faint'; nrole = 'muted'; if (gate && running) { det = 'human gate'; drole = 'warn'; } }
103
+ rows.push([seg(' │', 'faint')]);
104
+ const nm = fit(n.name || n.id, nameW);
105
+ const row = [seg(' '), seg(mark, mrole, bold), seg(' '), seg(nm, nrole, bold)];
106
+ if (det) {
107
+ const pad = nw ? ' ' : ' '.repeat(Math.max(2, nameW + 2 - [...nm].length));
108
+ row.push(seg(pad), seg(fit(det, Math.max(6, cols - 6 - (nw ? [...nm].length + 2 : nameW + 2))), drole));
109
+ }
110
+ rows.push(row);
111
+ }
112
+ if (!running && (ex.duration != null || ex.completedAt)) {
113
+ const total = ex.duration != null ? dur(ex.duration) : dur(parseTs(ex.completedAt) - parseTs(ex.startedAt));
114
+ rows.push([seg(' ')]);
115
+ if (status === 'failed') rows.push([seg('✖ ', 'error'), seg(fit(`failed${total ? ` after ${total}` : ''}${ex.error ? `: ${typeof ex.error === 'string' ? ex.error : ex.error.message || ''}` : ''}`, cols - 6), 'error')]);
116
+ else rows.push([seg(status === 'completed' ? '✔ ' : '· ', status === 'completed' ? 'ok' : 'muted'), seg(`${status}${total ? ` in ${total}` : ''}${ex.envelopeCount != null ? ` · ${ex.envelopeCount} envelopes` : ''}`, 'muted')]);
117
+ }
118
+ return { rows };
119
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * /observers: facts from persisted data only (LUCID situation, LUCID changes, lessons taught,
3
+ * reflect / learn / insight counters). No model-generated text: every line is a stored field
4
+ * or a count of them. Pure: takes api.observers() output, returns [[text, tone]].
5
+ */
6
+ import { clip } from './theme.js';
7
+
8
+ const why = (p) => (p.unavailable ? 'no endpoint on this server' : `unreadable (${p.error})`);
9
+
10
+ export function observerLines(o, cols = 80) {
11
+ const out = [];
12
+ const add = (t, tone) => out.push([clip(t, cols - 4), tone]);
13
+ const sit = o.situation;
14
+ if (!sit?.ok) add(`◉ LUCID situation: ${why(sit || { error: 'no answer' })}`, 'warn');
15
+ else {
16
+ const s = sit.v?.situation || {};
17
+ add(`◉ LUCID: ${s.L0 || 'no summary recorded'}`);
18
+ const needs = s.needs_you || [];
19
+ needs.slice(0, 3).forEach(n => add(` needs you: ${n.L0 || n.ref}`, 'warn'));
20
+ if (needs.length > 3) add(` +${needs.length - 3} more needing you (quox lucid)`);
21
+ const cs = s.cannot_see || {};
22
+ const blind = [...(cs.unwired || []).map(x => `${x} not wired`), ...(cs.silent || []).map(x => `${x.feed} silent`), ...(cs.failing || []).map(x => `${x.feed || x} failing`)];
23
+ if (cs.coverage) add(` sees ${cs.coverage.live} of ${cs.coverage.expected} sources${blind.length ? `; ${blind.join(', ')}` : ''}`);
24
+ const total = s.changed_total ?? (s.changed || []).length;
25
+ const range = s.cursor ? ` (journal ${s.cursor.from} to ${s.cursor.to})` : '';
26
+ add(`◉ Changed since you last looked: ${total}${range}`);
27
+ (s.changed || []).slice(0, 5).forEach(c => add(` ${c.L0 || c.ref}${c.from && c.to ? ` (${c.from} to ${c.to})` : ''}`));
28
+ if (total > 5) add(` +${total - 5} more (quox lucid since-last)`);
29
+ }
30
+ out.push(['', undefined]);
31
+ add('Self-learning records');
32
+ const les = o.lessons;
33
+ add(les?.ok ? ` LUCID lessons taught: ${(les.v?.lessons || []).length}` : ` LUCID lessons: ${why(les || { error: 'no answer' })}`);
34
+ for (const p of o.learning || []) {
35
+ if (!p.ok) { add(` ${p.label || 'stat'}: ${why(p)}`); continue; }
36
+ const f = p.v.fields || {};
37
+ const last = f.lastOutcomeAt || f.lastObservationAt || f.lastSignalAt || f.lastClusterAt;
38
+ add(` ${p.v.label}: ${p.v.text || 'no data'}${last ? ` · last ${last}` : ''}`);
39
+ }
40
+ add(' Memory consolidation: no read API found, not shown.');
41
+ return out;
42
+ }