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,374 @@
1
+ /**
2
+ * QuoxHat commands (QUOXHAT #721 b; CUSTOM-HATS 2026-10-17).
3
+ *
4
+ * quox hat list
5
+ * quox hat show <id|key> [--rev <n>]
6
+ * quox hat reset <id|key> --yes (audited reset-to-template, built-ins)
7
+ * quox hat create <key> --name "<Name>" [--from <hat>] [--agents a,b] [--tools x,y] [--mode m] [--offer o]
8
+ * quox hat edit <hat> [--name N] [--add-agents|--remove-agents|--agents] [--add-tools|--remove-tools|--tools] [--mode m]
9
+ * quox hat delete <hat> --yes (custom hats only)
10
+ * quox hat use <hat> --conversation <id> [--yes]
11
+ *
12
+ * Custom hats (owner 2026-10-17): users who build their own agents organise them under their own
13
+ * hats, so a turn under "security" carries only the security agents, not every agent in the org.
14
+ * create/edit/delete act on CUSTOM hats only; a built-in is reset to its template, or copied with --from.
15
+ * Everything is server-side, org-scoped, revisioned and audited (services/auth/routes/quoxhat.js);
16
+ * who may create or change an org hat is the existing hat-edit permission (org manage-settings),
17
+ * a private hat (--private) only its owner. This file never decides permission itself.
18
+ *
19
+ * Backend: services/auth/routes/quoxhat.js (see cli/lib/api/endpoints/hat.js).
20
+ */
21
+
22
+ import chalk from 'chalk';
23
+ import { formatOutput, printInfo } from '../core/output.js';
24
+ import { resolveOrgId } from './helpers.js';
25
+ import { resolveEndpoint } from '../api/endpoints.js';
26
+
27
+ /** Authorization mode a hat declares; no authz block means permissive (grant ceiling). */
28
+ export function authzMode(def) {
29
+ const a = def && typeof def.authz === 'object' ? def.authz : null;
30
+ if (!a) return 'permissive';
31
+ return a.mode === 'restrictive' ? 'restrictive' : 'permissive (declared)';
32
+ }
33
+
34
+ /** "v9", "v8 (template v9 available)" or "custom". */
35
+ export function templateLabel(hat) {
36
+ if (!hat.template_key) return 'custom';
37
+ const cur = hat.template_version;
38
+ const latest = hat.template_latest;
39
+ // The latest revision's author (only on `show`, which carries history):
40
+ // anything not 'template:*' means the org edited this built-in, which
41
+ // freezes it out of automatic template upgrades until reset-to-template.
42
+ const latestAuthor = Array.isArray(hat.revisions) && hat.revisions[0] ? hat.revisions[0].created_by : null;
43
+ const customised = typeof latestAuthor === 'string' && !latestAuthor.startsWith('template:');
44
+ if (latest && cur && cur < latest) return `v${cur} (template v${latest} available)`;
45
+ return customised ? `v${cur || '?'} (edited)` : `v${cur || '?'}`;
46
+ }
47
+
48
+ function toolCounts(def) {
49
+ const explicit = Array.isArray(def?.tools?.explicit) ? def.tools.explicit.length : 0;
50
+ const bundles = Array.isArray(def?.tools?.bundles) ? def.tools.bundles : [];
51
+ const bundled = bundles.reduce((n, b) => n + (Array.isArray(b?.tools) ? b.tools.length : 0), 0);
52
+ return { explicit, bundles: bundles.length, bundled };
53
+ }
54
+
55
+ async function fetchList(client, orgId) {
56
+ const ep = resolveEndpoint('hat.list', { orgId });
57
+ return client.get(ep.path, { service: ep.service });
58
+ }
59
+
60
+ /** Resolve a hat argument (ULID or key) to its id using the org's hat list. */
61
+ export function findHat(hats, ref) {
62
+ const r = String(ref || '').trim();
63
+ return (hats || []).find(h => h.id === r) || (hats || []).find(h => h.key === r) || null;
64
+ }
65
+
66
+
67
+ export { DELEGATION_TOOLS, HAT_MODES, HAT_OFFERS, parseList, memberTools, applyMode, buildCustomDefinition, applyHatEdits } from '../core/customHats.js';
68
+ import { parseList, memberTools, buildCustomDefinition, applyHatEdits } from '../core/customHats.js';
69
+
70
+ /** Which of `ids` no registered or org agent matches. checked=false when neither list could be read. */
71
+ export async function findUnknownAgents(client, orgId, ids) {
72
+ if (!ids.length) return { unknown: [], checked: true };
73
+ const known = new Set();
74
+ let read = 0;
75
+ try {
76
+ const ep = resolveEndpoint('v1.agents.registry');
77
+ const d = await client.get(ep.path, { service: ep.service });
78
+ if (Array.isArray(d?.agents)) { read++; for (const a of d.agents) if (a?.agent_id) known.add(String(a.agent_id).toLowerCase()); }
79
+ } catch { /* named below */ }
80
+ try {
81
+ const ep = resolveEndpoint('agents.list', { orgId });
82
+ const d = await client.get(ep.path, { service: ep.service });
83
+ const rows = Array.isArray(d?.agents) ? d.agents : (Array.isArray(d) ? d : null);
84
+ if (rows) { read++; for (const a of rows) { const id = a?.agent_id || a?.agentId; if (id) known.add(String(id).toLowerCase()); } }
85
+ } catch { /* named below */ }
86
+ if (!read) return { unknown: [], checked: false };
87
+ return { unknown: ids.filter(id => !known.has(id)), checked: true };
88
+ }
89
+
90
+ function isBuiltin(h) { return !!h?.template_key; }
91
+
92
+ export function registerHatCommands(program, ctx) {
93
+ const { client, auth } = ctx;
94
+
95
+ const hat = program
96
+ .command('hat')
97
+ .description('QuoxHat: read the org hats (tools, mode, revision, enforcement); reset a built-in to its template');
98
+
99
+ // ── hat list ────────────────────────────────────────────────────────────────
100
+ hat
101
+ .command('list')
102
+ .description('List the org hats with revision, template status, mode and tool counts')
103
+ .action(async () => {
104
+ auth.requireAuth();
105
+ const orgId = resolveOrgId(auth, program);
106
+ const data = await fetchList(client, orgId);
107
+ const hats = Array.isArray(data?.hats) ? data.hats : [];
108
+ const settings = data?.settings || {};
109
+ const format = program.opts().output;
110
+
111
+ if (format === 'json') {
112
+ console.log(JSON.stringify({ hats, settings }, null, 2));
113
+ return;
114
+ }
115
+
116
+ const rows = hats.map(h => {
117
+ const c = toolCounts(h.definition);
118
+ return {
119
+ key: h.key + (settings.default_hat_id === h.id ? ' *' : ''),
120
+ name: h.name,
121
+ rev: String(h.current_revision),
122
+ status: h.status,
123
+ template: templateLabel(h),
124
+ mode: authzMode(h.definition),
125
+ privileged: h.definition?.transitions?.privileged ? 'yes' : 'no',
126
+ tools: `${c.explicit} + ${c.bundled} in ${c.bundles} bundle(s)`,
127
+ id: h.id,
128
+ };
129
+ });
130
+ formatOutput({
131
+ rows,
132
+ columns: ['key', 'name', 'rev', 'status', 'template', 'mode', 'privileged', 'tools', 'id'],
133
+ headers: ['Key', 'Name', 'Rev', 'Status', 'Template', 'Mode', 'Privileged', 'Tools (explicit + bundled)', 'ID'],
134
+ }, { format, emptyMessage: 'No hats.' });
135
+ printInfo(`Enforcement: ${settings.enforcement || 'preview'} · selection: ${settings.selection_mode || 'manual'}${settings.default_hat_id ? ' · * = org default' : ' · org default: built-in Default'}`);
136
+ });
137
+
138
+ // ── hat show ────────────────────────────────────────────────────────────────
139
+ hat
140
+ .command('show <hat>')
141
+ .description('Show one hat (id or key): tools, bundles, mode, revision history, enforcement')
142
+ .option('--rev <n>', 'show a historical revision instead of the current one')
143
+ .action(async (ref, options) => {
144
+ auth.requireAuth();
145
+ const orgId = resolveOrgId(auth, program);
146
+ let rev;
147
+ if (options.rev !== undefined) {
148
+ rev = Number(options.rev);
149
+ if (!Number.isInteger(rev) || rev < 1) throw new Error(`--rev must be a positive integer (got '${options.rev}')`);
150
+ }
151
+
152
+ const list = await fetchList(client, orgId);
153
+ const found = findHat(list?.hats, ref);
154
+ if (!found) {
155
+ const keys = (list?.hats || []).map(h => h.key).join(', ') || 'none';
156
+ throw new Error(`No hat '${ref}' in this org. Available: ${keys}`);
157
+ }
158
+
159
+ const ep = resolveEndpoint('hat.get', { orgId, hatId: found.id });
160
+ const data = await client.get(ep.path, {
161
+ service: ep.service,
162
+ ...(rev ? { query: { revision: rev } } : {}),
163
+ });
164
+ const h = data?.hat;
165
+ if (!h) throw new Error(`Hat '${ref}' not found`);
166
+ const enforcement = data.enforcement || list?.settings?.enforcement || 'preview';
167
+
168
+ if (program.opts().output === 'json') {
169
+ console.log(JSON.stringify({ hat: h, enforcement, settings: list?.settings || null }, null, 2));
170
+ return;
171
+ }
172
+
173
+ const def = h.definition || {};
174
+ const shown = h.revision_shown || h.current_revision;
175
+ const out = [];
176
+ out.push(chalk.bold(`${h.name} (${h.key})`) + chalk.dim(` ${h.id}`));
177
+ if (h.purpose) out.push(h.purpose);
178
+ out.push('');
179
+ out.push(`Revision: ${shown}${shown !== h.current_revision ? chalk.yellow(` (historical; current is ${h.current_revision})`) : ' (current)'}`);
180
+ out.push(`Digest: ${h.digest || '-'}`);
181
+ out.push(`Status: ${h.status}`);
182
+ out.push(`Template: ${templateLabel(h)}`);
183
+ out.push(`Mode: ${authzMode(def)}`);
184
+ out.push(`Enforcement: ${enforcement} (org)`);
185
+ out.push(`Transitions: confirm=${def.transitions?.confirm || 'none'} privileged=${def.transitions?.privileged ? 'yes' : 'no'}`);
186
+ out.push(`Agents: orchestrator=${def.agents?.orchestrator || '-'} specialists=${(def.agents?.specialists || []).join(', ') || 'none'}`);
187
+ out.push(`Offer: ${def.tools?.offer === 'members' ? 'members (an orchestrator turn is offered only this hat\'s tools)' : 'authorized (hat tools first, then the rest of the grant)'}`);
188
+ out.push(`Kind: ${h.template_key ? 'built-in' : 'custom'}${h.visibility === 'private' ? ' (private)' : ''}`);
189
+ out.push(`Budgets: initial_tool_target=${def.budgets?.initial_tool_target ?? '-'} max_manifest=${def.budgets?.max_manifest ?? '-'}`);
190
+ out.push('');
191
+ const explicit = def.tools?.explicit || [];
192
+ out.push(chalk.bold(`Explicit tools (${explicit.length}):`));
193
+ out.push(` ${explicit.join(', ') || 'none'}`);
194
+ const bundles = def.tools?.bundles || [];
195
+ out.push(chalk.bold(`Bundles (${bundles.length}, loaded per conversation with hat_load_bundle):`));
196
+ for (const b of bundles) out.push(` ${b.key}: ${(b.tools || []).join(', ')}`);
197
+ if (!bundles.length) out.push(' none');
198
+ const fams = def.tools?.connector_families || [];
199
+ out.push(chalk.bold('Connector families:') + ` ${fams.join(', ') || 'none'}`);
200
+ if (def.authz && typeof def.authz === 'object') {
201
+ if (Array.isArray(def.authz.allow)) out.push(`Authz allow: ${def.authz.allow.join(', ')}`);
202
+ if (Array.isArray(def.authz.deny)) out.push(`Authz deny: ${def.authz.deny.join(', ')}`);
203
+ }
204
+ const revisions = Array.isArray(h.revisions) ? h.revisions : [];
205
+ if (revisions.length) {
206
+ out.push('');
207
+ out.push(chalk.bold('Revisions:'));
208
+ for (const r of revisions) {
209
+ out.push(` ${String(r.revision).padStart(3)} ${r.created_at || ''} ${r.created_by || ''} ${r.change_reason || ''}`);
210
+ }
211
+ }
212
+ console.log(out.join('\n'));
213
+ });
214
+
215
+ // ── hat reset ───────────────────────────────────────────────────────────────
216
+ hat
217
+ .command('reset <hat>')
218
+ .description('Reset an org-edited built-in hat to its current template (drops the org edits; audited)')
219
+ .option('--yes', 'confirm: the org edits on this hat are replaced by the template')
220
+ .action(async (ref, options) => {
221
+ auth.requireAuth();
222
+ if (!options.yes) throw new Error(`Resetting '${ref}' replaces its org edits with the template. Re-run with --yes to confirm.`);
223
+ const orgId = resolveOrgId(auth, program);
224
+ const list = await fetchList(client, orgId);
225
+ const found = findHat(list?.hats, ref);
226
+ if (!found) {
227
+ const keys = (list?.hats || []).map(h => h.key).join(', ') || 'none';
228
+ throw new Error(`No hat '${ref}' in this org. Available: ${keys}`);
229
+ }
230
+ const ep = resolveEndpoint('hat.reset', { orgId, hatId: found.id });
231
+ const data = await client.post(ep.path, { service: ep.service, body: {} });
232
+ const h = data?.hat;
233
+ if (!h) throw new Error(`Reset of '${ref}' returned no hat`);
234
+ if (program.opts().output === 'json') { console.log(JSON.stringify({ hat: h }, null, 2)); return; }
235
+ console.log(` Ⓠ QUOX │ hat ${h.key} reset to template │ rev ${h.current_revision} · ${templateLabel(h)} ✔`);
236
+ });
237
+ // ── hat create (custom) ───────────────────────────────────────────────────────
238
+ hat
239
+ .command('create <key>')
240
+ .description('Create a custom hat: the agents and tools it lists are the only ones a turn under it carries')
241
+ .requiredOption('--name <name>', 'display name, e.g. "Security"')
242
+ .option('--from <hat>', 'start from a copy of this hat (key or id)')
243
+ .option('--agents <ids>', 'comma-separated agent ids this hat puts in scope (registered or your own agents)')
244
+ .option('--tools <names>', 'comma-separated tool names the orchestrator is offered under this hat')
245
+ .option('--mode <mode>', 'permissive (default: each agent keeps its own grant) or restrictive (only the listed tools are authorized, for every agent under the hat)')
246
+ .option('--offer <offer>', 'members (default: offer only this hat\'s tools) or authorized')
247
+ .option('--purpose <text>', 'one line: what this hat is for')
248
+ .option('--private', 'a private hat only you can see and wear (needs no org settings permission)')
249
+ .option('--reason <text>', 'why (kept in the revision history)')
250
+ .action(async (key, options) => {
251
+ auth.requireAuth();
252
+ const orgId = resolveOrgId(auth, program);
253
+ const k = String(key || '').trim().toLowerCase();
254
+ if (!/^[a-z0-9][a-z0-9-]{1,40}$/.test(k)) throw new Error(`Hat key '${key}' must be a lowercase slug (a-z, 0-9, hyphen), 2-41 characters.`);
255
+ const list = await fetchList(client, orgId);
256
+ const hats = list?.hats || [];
257
+ if (findHat(hats, k)) throw new Error(`A hat with key '${k}' already exists in this org. Use quox hat edit ${k}.`);
258
+ let base = null;
259
+ if (options.from) {
260
+ const from = findHat(hats, options.from);
261
+ if (!from) throw new Error(`No hat '${options.from}' to copy. Available: ${hats.map(h => h.key).join(', ') || 'none'}`);
262
+ base = from.definition;
263
+ }
264
+ const agents = options.agents !== undefined ? parseList(options.agents) : undefined;
265
+ const tools = options.tools !== undefined ? parseList(options.tools) : undefined;
266
+ const { definition, autoAdded } = buildCustomDefinition({ base, name: options.name, purpose: options.purpose, agents, tools, mode: options.mode, offer: options.offer });
267
+ const named = definition.agents.specialists;
268
+ const check = await findUnknownAgents(client, orgId, named);
269
+ if (check.unknown.length) throw new Error(`Unknown agent(s): ${check.unknown.join(', ')}. See quox agent list.`);
270
+ const ep = resolveEndpoint('hat.create', { orgId });
271
+ const data = await client.post(ep.path, { service: ep.service, body: { key: k, name: String(options.name).trim(), definition, visibility: options.private ? 'private' : 'org' } });
272
+ const h = data?.hat;
273
+ if (!h) throw new Error(`Create of '${k}' returned no hat`);
274
+ if (program.opts().output === 'json') { console.log(JSON.stringify({ hat: h, warnings: data.warnings || [], auto_added_tools: autoAdded }, null, 2)); return; }
275
+ const d = h.definition || definition;
276
+ console.log(` Ⓠ QUOX │ hat ${h.key} created │ rev ${h.current_revision} · agents ${(d.agents?.specialists || []).join(', ') || 'none'} · ${memberTools(d).length} tool(s) · offer ${d.tools?.offer || 'authorized'} · ${authzMode(d)} ✔`);
277
+ if (autoAdded.length) printInfo(`Added ${autoAdded.join(', ')} so the orchestrator can reach the hat's agents.`);
278
+ if (!check.checked) printInfo('Agent ids were not checked: the agent lists could not be read.');
279
+ if (d.authz?.mode === 'restrictive') printInfo('Restrictive: every agent working under this hat, its own agents included when delegated to, may only run the tools listed here.');
280
+ for (const w of data.warnings || []) printInfo(`warning: ${w}`);
281
+ printInfo(`Wear it: /hat ${h.key} in quox, or quox hat use ${h.key} --conversation <id>.`);
282
+ });
283
+
284
+ // ── hat edit (custom) ─────────────────────────────────────────────────────────
285
+ hat
286
+ .command('edit <hat>')
287
+ .description('Change a custom hat: add or remove agents and tools, rename, mode (appends an audited revision)')
288
+ .option('--name <name>', 'rename the hat')
289
+ .option('--purpose <text>', 'new one-line purpose')
290
+ .option('--agents <ids>', 'replace the agent list')
291
+ .option('--add-agents <ids>', 'comma-separated agents to add')
292
+ .option('--remove-agents <ids>', 'comma-separated agents to remove')
293
+ .option('--tools <names>', 'replace the explicit tool list')
294
+ .option('--add-tools <names>', 'comma-separated tools to add')
295
+ .option('--remove-tools <names>', 'comma-separated tools to remove')
296
+ .option('--mode <mode>', 'permissive or restrictive')
297
+ .option('--offer <offer>', 'members or authorized')
298
+ .option('--reason <text>', 'why (kept in the revision history)')
299
+ .action(async (ref, options) => {
300
+ auth.requireAuth();
301
+ const orgId = resolveOrgId(auth, program);
302
+ const list = await fetchList(client, orgId);
303
+ const found = findHat(list?.hats, ref);
304
+ if (!found) throw new Error(`No hat '${ref}' in this org. Available: ${(list?.hats || []).map(h => h.key).join(', ') || 'none'}`);
305
+ if (isBuiltin(found)) throw new Error(`'${found.key}' is a built-in hat: quox hat edit changes custom hats only. Reset it with quox hat reset ${found.key} --yes, or make your own from it: quox hat create <key> --name "<Name>" --from ${found.key}.`);
306
+ const opts = {
307
+ agents: options.agents !== undefined ? parseList(options.agents) : undefined,
308
+ addAgents: parseList(options.addAgents),
309
+ removeAgents: parseList(options.removeAgents),
310
+ tools: options.tools !== undefined ? parseList(options.tools) : undefined,
311
+ addTools: parseList(options.addTools),
312
+ removeTools: parseList(options.removeTools),
313
+ mode: options.mode,
314
+ offer: options.offer,
315
+ purpose: options.purpose,
316
+ };
317
+ const { definition, changes } = applyHatEdits(found.definition, opts);
318
+ const rename = options.name !== undefined && String(options.name).trim() !== found.name ? String(options.name).trim() : undefined;
319
+ if (rename !== undefined) changes.unshift(`name "${found.name}" -> "${rename}"`);
320
+ if (!changes.length) throw new Error(`Nothing to change on '${found.key}'.`);
321
+ const newAgents = [...(opts.agents || []), ...opts.addAgents];
322
+ const check = await findUnknownAgents(client, orgId, newAgents);
323
+ if (check.unknown.length) throw new Error(`Unknown agent(s): ${check.unknown.join(', ')}. See quox agent list.`);
324
+ const ep = resolveEndpoint('hat.update', { orgId, hatId: found.id });
325
+ const data = await client.put(ep.path, { service: ep.service, body: { definition, ...(rename !== undefined ? { name: rename } : {}), change_reason: options.reason || changes.join('; ') } });
326
+ const h = data?.hat;
327
+ if (!h) throw new Error(`Edit of '${found.key}' returned no hat`);
328
+ if (program.opts().output === 'json') { console.log(JSON.stringify({ hat: h, changes, warnings: data.warnings || [] }, null, 2)); return; }
329
+ console.log(` Ⓠ QUOX │ hat ${h.key} edited │ rev ${h.current_revision} · ${changes.join(' · ')} ✔`);
330
+ for (const w of data.warnings || []) printInfo(`warning: ${w}`);
331
+ });
332
+
333
+ // ── hat delete (custom) ───────────────────────────────────────────────────────
334
+ hat
335
+ .command('delete <hat>')
336
+ .description('Delete a custom hat (built-ins cannot be deleted; reset them instead). Audited.')
337
+ .option('--yes', 'confirm: conversations wearing it fall back to the default hat')
338
+ .action(async (ref, options) => {
339
+ auth.requireAuth();
340
+ const orgId = resolveOrgId(auth, program);
341
+ const list = await fetchList(client, orgId);
342
+ const found = findHat(list?.hats, ref);
343
+ if (!found) throw new Error(`No hat '${ref}' in this org. Available: ${(list?.hats || []).map(h => h.key).join(', ') || 'none'}`);
344
+ if (isBuiltin(found)) throw new Error(`'${found.key}' is a built-in hat and cannot be deleted. quox hat reset ${found.key} --yes returns it to its template.`);
345
+ if (!options.yes) throw new Error(`Deleting '${found.key}' moves every conversation wearing it back to the default hat. Re-run with --yes to confirm.`);
346
+ const ep = resolveEndpoint('hat.delete', { orgId, hatId: found.id });
347
+ const data = await client.delete(ep.path, { service: ep.service });
348
+ const d = data?.deleted;
349
+ if (!d) throw new Error(`Delete of '${found.key}' returned no confirmation`);
350
+ if (program.opts().output === 'json') { console.log(JSON.stringify({ deleted: d }, null, 2)); return; }
351
+ console.log(` Ⓠ QUOX │ hat ${d.key} deleted │ was rev ${d.revision} · ${d.bindings_cleared} conversation(s) moved to the default · ${d.user_prefs_cleared} preference(s) cleared ✔`);
352
+ });
353
+
354
+ // ── hat use ───────────────────────────────────────────────────────────────────
355
+ hat
356
+ .command('use <hat>')
357
+ .description('Wear a hat in one conversation (the same audited switch as /hat <name> in quox)')
358
+ .requiredOption('--conversation <id>', 'the conversation to switch')
359
+ .option('--yes', 'confirm a privileged hat')
360
+ .action(async (ref, options) => {
361
+ auth.requireAuth();
362
+ const orgId = resolveOrgId(auth, program);
363
+ const list = await fetchList(client, orgId);
364
+ const found = findHat(list?.hats, ref);
365
+ if (!found) throw new Error(`No hat '${ref}' in this org. Available: ${(list?.hats || []).map(h => h.key).join(', ') || 'none'}`);
366
+ if (found.definition?.transitions?.privileged && !options.yes) throw new Error(`'${found.key}' is a privileged hat. Re-run with --yes to wear it.`);
367
+ const ep = resolveEndpoint('hat.bind', { orgId, conversationId: options.conversation });
368
+ const data = await client.put(ep.path, { service: ep.service, body: { hat_id: found.id } });
369
+ const b = data?.binding;
370
+ if (!b) throw new Error(`Switch to '${found.key}' returned no binding`);
371
+ if (program.opts().output === 'json') { console.log(JSON.stringify({ binding: b, hat: { id: found.id, key: found.key } }, null, 2)); return; }
372
+ console.log(` Ⓠ QUOX │ conversation ${options.conversation} now wears ${found.key} │ rev ${b.revision} · seq ${b.seq} ✔`);
373
+ });
374
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Shared helpers for command modules
3
+ */
4
+
5
+ import { QuoxValidationError, QuoxNetworkError } from '../core/errors.js';
6
+
7
+ /**
8
+ * Resolve the active org ID from --org flag or stored auth.
9
+ * Throws if no org context is available.
10
+ */
11
+ export function resolveOrgId(auth, program) {
12
+ const orgId = auth.getOrgId(program.opts().org);
13
+ if (!orgId) {
14
+ // Ask about AUTH before blaming the org, because a logged-out user has no
15
+ // org for the obvious reason, and telling them to switch org sends them
16
+ // down a path that cannot work.
17
+ //
18
+ // 2026-08-18: a new-user setup audit ran `quox slot create audit-demo` on
19
+ // a shell with no token. It answered "No active org. Use --org <id> or
20
+ // `quox org switch <id>` first." Following that instruction gave a
21
+ // DIFFERENT error, "No authentication token provided ... Run `quox login`".
22
+ // Two errors, two dead ends, and the real first step named only in the
23
+ // second one. The owner's standing complaint about this bundle is that it
24
+ // is not "easy as pie" to set up; this was the very first command in that
25
+ // path, and it misdirected.
26
+ //
27
+ // Every command that needs an org goes through here, so the fix lands once
28
+ // for all of them.
29
+ auth.requireAuth();
30
+
31
+ // requireAuth() passing does NOT mean a USER is logged in. isLoggedIn()
32
+ // also accepts an ambient QUOX_SERVICE_KEY as the automation fallback, and
33
+ // a service key carries no organisation — so on any box that exports one
34
+ // globally (every dev box here does) a logged-out user sails past the auth
35
+ // check and lands on "No active org", which sends them to `quox org
36
+ // switch` when the real first step is `quox login`.
37
+ //
38
+ // 2026-08-19: reproduced exactly that with `quox slot list --profile local`
39
+ // on a shell with QUOX_SERVICE_KEY exported. This is the SAME misdirection
40
+ // the 2026-08-18 note above set out to kill, arriving through the one door
41
+ // that check cannot see: the fix asked "are you authenticated?" when the
42
+ // question that matters is "authenticated AS WHOM?".
43
+ const hasUserToken = Boolean(auth.getTokens?.()?.access_token);
44
+ if (!hasUserToken) {
45
+ throw new Error(
46
+ 'Authenticated with a service key, which has no organisation. '
47
+ + 'Run `quox login` to act as a user, or pass --org <id> to name the org explicitly.'
48
+ );
49
+ }
50
+
51
+ throw new Error('No active org. Use --org <id>, or pick one with `quox org list` then `quox org switch <id>`.');
52
+ }
53
+ return orgId;
54
+ }
55
+
56
+ /**
57
+ * Safely parse a JSON string from CLI input.
58
+ * Throws QuoxValidationError with a clear message on invalid JSON.
59
+ */
60
+ export function parseJSON(value, label = 'JSON') {
61
+ try {
62
+ return JSON.parse(value);
63
+ } catch {
64
+ throw new QuoxValidationError(`Invalid ${label}: not valid JSON. Check your input and try again.`);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Build a query object from common list options.
70
+ */
71
+ export function buildListQuery(options) {
72
+ const query = {};
73
+ if (options.limit) query.limit = options.limit;
74
+ if (options.offset) query.offset = options.offset;
75
+ if (options.search) query.search = options.search;
76
+ if (options.status) query.status = options.status;
77
+ if (options.sort) query.sort = options.sort;
78
+ return query;
79
+ }
80
+
81
+ /**
82
+ * Run a request; if it times out, rethrow with what timed out and how to narrow
83
+ * it (still a QuoxNetworkError, so the exit code stays 7). A bare
84
+ * "Request timed out after 30000ms" does not tell the operator which call hung
85
+ * or what to try (quox#806, quox#807).
86
+ */
87
+ export async function withTimeoutHint(what, hint, fn) {
88
+ try {
89
+ return await fn();
90
+ } catch (err) {
91
+ if (err instanceof QuoxNetworkError && /timed out/i.test(err.message || '')) {
92
+ throw new QuoxNetworkError(`${what} timed out (${err.message}). ${hint}`, err);
93
+ }
94
+ throw err;
95
+ }
96
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * `quox hyperion`: everything HYPERION (the governed Proxmox operator, agent id atlas) is doing in one place.
3
+ * Collector route GET /api/v1/proxmox/activity (org-scoped, read only).
4
+ *
5
+ * quox hyperion [status] [--json] VMs and who holds them, node load, pool counts, last 5 ops
6
+ * quox hyperion deck live full-screen view, refreshes every 10s (q quits, r refreshes)
7
+ */
8
+ import { line as glyphLine, printEvent } from '../core/quoxglyph.js';
9
+ import { fetchActivity, statusLines, summaryText } from '../core/hyperion.js';
10
+
11
+ export function registerHyperionCommands(program, ctx) {
12
+ const { client, auth } = ctx;
13
+
14
+ const hy = program
15
+ .command('hyperion')
16
+ .description('HYPERION activity: which VMs exist, who holds each and why, node load and recent operations')
17
+ .option('--json', 'print the full JSON response');
18
+
19
+ const wantJson = (cmd) => {
20
+ const o = cmd.optsWithGlobals ? cmd.optsWithGlobals() : cmd.opts();
21
+ return Boolean(o.json) || program.opts().output === 'json';
22
+ };
23
+
24
+ // An error body is not data: report the status and stop.
25
+ async function show(cmd) {
26
+ auth.requireAuth();
27
+ let data;
28
+ try {
29
+ data = await fetchActivity(client);
30
+ } catch (err) {
31
+ const status = err && (err.status || err.statusCode);
32
+ if (!status) throw err;
33
+ console.error(`HYPERION request failed: HTTP ${status}${err.message ? ` ${err.message}` : ''}`);
34
+ process.exitCode = 1;
35
+ return;
36
+ }
37
+ if (wantJson(cmd)) { console.log(JSON.stringify(data, null, 2)); return; }
38
+ printEvent(glyphLine('hyperion', 'activity', { result: summaryText(data) }));
39
+ console.log(statusLines(data).join('\n'));
40
+ }
41
+
42
+ hy.action(async (_o, cmd) => show(cmd));
43
+
44
+ hy
45
+ .command('status')
46
+ .description('Same as bare `quox hyperion`')
47
+ .option('--json', 'print the full JSON response')
48
+ .action(async (_o, cmd) => show(cmd));
49
+
50
+ hy
51
+ .command('deck')
52
+ .description('Live full-screen HYPERION deck (refreshes every 10s; r refreshes, q quits)')
53
+ .action(async () => {
54
+ auth.requireAuth();
55
+ const { launchHyperionDeck } = await import('../hyperion/deck.js');
56
+ await launchHyperionDeck({ activity: () => fetchActivity(client) });
57
+ });
58
+ }