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,464 @@
1
+ /**
2
+ * Auth commands: login, logout, whoami, signup, mfa
3
+ */
4
+
5
+ import chalk from 'chalk';
6
+ import { formatDetail, printSuccess, printInfo } from '../core/output.js';
7
+ import { resolveEndpoint } from '../api/endpoints.js';
8
+ import { loadResidentProfile, residentLogin, resolveResidentBaseUrl } from '../core/residentAuth.js';
9
+ import { readStoredKit, resolveMyAttach, sessionKey, myAttachState } from './agentAttach.js';
10
+ import { resolveActing } from '../core/actingAs.js';
11
+
12
+ export function registerAuthCommands(program, ctx) {
13
+ const { config, auth, client } = ctx;
14
+
15
+ // quox login
16
+ program
17
+ .command('login')
18
+ .description('Authenticate with QuoxCORE')
19
+ .option('--email <email>', 'email address')
20
+ .option('--password <password>', 'password (prefer --password-stdin: argv is visible in process lists)')
21
+ .option('--password-stdin', 'read the password from stdin (one line) — no secret in argv or shell history')
22
+ .option('--mfa-code <code>', 'TOTP code for MFA')
23
+ .option('--org <orgId>', 'organization to log into')
24
+ .option('--resident', 'authenticate as a resident agent using the on-disk Ed25519 identity, no password, no human')
25
+ .option('--resident-profile <path>', 'path to the resident bootstrap profile (default: ~/.config/quox/resident-profile.json)')
26
+ .action(async (options) => {
27
+ // Resident agent path: signed-challenge exchange with an Ed25519 key
28
+ // on disk, entirely separate from the email/password flow below.
29
+ if (options.resident) {
30
+ const ora = (await import('ora')).default;
31
+ const spinner = ora('Authenticating (resident identity)...').start();
32
+ try {
33
+ const profile = loadResidentProfile(options.residentProfile);
34
+ const baseUrl = resolveResidentBaseUrl(config, profile);
35
+ const tokenData = await residentLogin({ baseUrl, profile });
36
+
37
+ const authData = {
38
+ access_token: tokenData.access_token,
39
+ refresh_token: null,
40
+ user_id: tokenData.user?.id || null,
41
+ email: tokenData.user?.email || null,
42
+ display_name: tokenData.user?.display_name || null,
43
+ org_id: profile.org_id,
44
+ org_name: null,
45
+ org_slug: null,
46
+ org_role: tokenData.user?.role || null,
47
+ actor_type: tokenData.user?.actor_type || null,
48
+ host_id: tokenData.user?.host_id || profile.host_id,
49
+ kind: 'resident',
50
+ resident_profile_path: profile._path,
51
+ expires_at: Date.now() + (tokenData.expires_in || 900) * 1000,
52
+ };
53
+ config.setAuth(authData);
54
+
55
+ // quox#455: persist the bootstrap's reach-back URLs onto this
56
+ // profile so every later command (collector, slots, dev) resolves
57
+ // services from what this host actually reaches, never a
58
+ // port/scheme guess. Only fill the profile URL when it is still
59
+ // the local default; an explicit URL a human set always wins.
60
+ const active = typeof config.getActiveProfile === 'function' ? config.getActiveProfile() : null;
61
+ // Any loopback URL counts as "not deliberately set". An exact-string
62
+ // check against http://localhost:3000 missed https://localhost:3000
63
+ // and left the profile base pointing at the host's own empty
64
+ // instance, which only stayed invisible because the per-service
65
+ // overrides below happen to cover the services in use today.
66
+ const urlIsDefault = (() => {
67
+ if (!active?.url) return true;
68
+ try {
69
+ return ['localhost', '127.0.0.1', '::1'].includes(new URL(active.url).hostname);
70
+ } catch {
71
+ return true;
72
+ }
73
+ })();
74
+ // quox#455 follow-up / quox#469: stamp AUTH as well as collector.
75
+ // Stamping only collector left every auth-service call (whoami, and
76
+ // the token refresh itself) resolving through getServiceUrl('auth'),
77
+ // which port-swaps the edge to loopback :3101 and is unreachable
78
+ // from any remote host. The acceptance owner hit exactly that:
79
+ // login worked zero-override while whoami and slot ops still needed
80
+ // manual QUOX_AUTH_URL/QUOX_COLLECTOR_URL.
81
+ const services = {};
82
+ if (profile.collector_url) services.collector = profile.collector_url;
83
+ if (profile.instance_url) services.auth = profile.instance_url;
84
+ config.setProfileConnection({
85
+ ...(urlIsDefault && profile.instance_url ? { url: profile.instance_url } : {}),
86
+ ...(Object.keys(services).length ? { services } : {}),
87
+ });
88
+
89
+ spinner.stop();
90
+ printSuccess(`Logged in as resident agent ${authData.email || authData.user_id || authData.host_id} (host ${authData.host_id})`);
91
+ } catch (err) {
92
+ spinner.fail('Resident login failed');
93
+ throw err;
94
+ }
95
+ return;
96
+ }
97
+
98
+ let { email, password, mfaCode } = options;
99
+ const orgId = options.org || program.opts().org;
100
+
101
+ // SVC-AUTH #447 bridge: non-interactive automation reads the secret
102
+ // from stdin (or QUOX_LOGIN_PASSWORD / QUOX_LOGIN_EMAIL env), never
103
+ // argv, so no credential lands in process lists or shell history.
104
+ if (!email && process.env.QUOX_LOGIN_EMAIL) email = process.env.QUOX_LOGIN_EMAIL;
105
+ if (!password && options.passwordStdin) {
106
+ const chunks = [];
107
+ for await (const chunk of process.stdin) chunks.push(chunk);
108
+ password = Buffer.concat(chunks).toString('utf8').split('\n')[0].trim();
109
+ if (!password) {
110
+ console.error('Error: --password-stdin given but stdin was empty');
111
+ process.exit(1);
112
+ }
113
+ }
114
+ if (!password && process.env.QUOX_LOGIN_PASSWORD) password = process.env.QUOX_LOGIN_PASSWORD;
115
+
116
+ // Interactive prompts if not provided
117
+ if (!email || !password) {
118
+ const { default: inquirer } = await import('inquirer');
119
+
120
+ if (!email) {
121
+ const ans = await inquirer.prompt([{
122
+ type: 'input',
123
+ name: 'email',
124
+ message: 'Email:',
125
+ validate: v => v.includes('@') || 'Please enter a valid email',
126
+ }]);
127
+ email = ans.email;
128
+ }
129
+
130
+ if (!password) {
131
+ const ans = await inquirer.prompt([{
132
+ type: 'password',
133
+ name: 'password',
134
+ message: 'Password:',
135
+ mask: '*',
136
+ }]);
137
+ password = ans.password;
138
+ }
139
+ }
140
+
141
+ const baseUrl = config.getServiceUrl('auth');
142
+ const ora = (await import('ora')).default;
143
+ const spinner = ora('Authenticating...').start();
144
+
145
+ try {
146
+ const result = await auth.login(baseUrl, email, password, orgId);
147
+ spinner.stop();
148
+
149
+ // Handle MFA
150
+ if (result.mfa_required) {
151
+ if (!mfaCode) {
152
+ printInfo('MFA required. Check your authenticator app.');
153
+ const { default: inquirer } = await import('inquirer');
154
+ const ans = await inquirer.prompt([{
155
+ type: 'input',
156
+ name: 'code',
157
+ message: 'TOTP code:',
158
+ }]);
159
+ mfaCode = ans.code;
160
+ }
161
+
162
+ const mfaSpinner = ora('Verifying MFA...').start();
163
+ await auth.verifyMfa(baseUrl, result.access_token, mfaCode);
164
+ mfaSpinner.succeed('MFA verified');
165
+ }
166
+
167
+ const authData = config.getAuth();
168
+ // quox#647: login resolves and SETS the active org, silently overriding
169
+ // any prior `quox org switch` (the root cause of wrong-org actions).
170
+ // Always surface the resulting active org so the reset is visible
171
+ // (owner: "at least print 'active org set to X'"). Fall back
172
+ // org_name -> org_id like whoami, since resident logins carry org_id but
173
+ // no org_name (quox#463) and this line used to blank out entirely.
174
+ const orgLabel = authData.org_name
175
+ ? `${authData.org_name} (${authData.org_slug})`
176
+ : (authData.org_id || 'unknown');
177
+ printSuccess(`Logged in as ${authData.email}`);
178
+ printInfo(`Active org set to ${orgLabel}`);
179
+ } catch (err) {
180
+ spinner.fail('Login failed');
181
+ throw err;
182
+ }
183
+ });
184
+
185
+ // quox logout
186
+ program
187
+ .command('logout')
188
+ .description('End current session')
189
+ .action(async () => {
190
+ const baseUrl = config.getServiceUrl('auth');
191
+ await auth.logout(baseUrl);
192
+ printSuccess('Logged out. Tokens cleared.');
193
+ });
194
+
195
+ // quox whoami
196
+ program
197
+ .command('whoami')
198
+ .description('Show current user and session info')
199
+ .action(async () => {
200
+ auth.requireAuth();
201
+ const data = await client.get(resolveEndpoint('auth.me.list').path, { service: resolveEndpoint('auth.me.list').service });
202
+ // A QUOX_TOKEN_FILE principal (the W4 builder uid) has no stored profile:
203
+ // render from the server's /me answer rather than crash on null.
204
+ const authData = config.getAuth() || {};
205
+
206
+ // quox#463: resident logins carry org_id but no org_name (the
207
+ // bootstrap has only the id), and this rendered a real membership as
208
+ // 'none'. Fall back to the id rather than claiming no org.
209
+ //
210
+ // quox#463 follow-up: some resident sessions have no active org_id in
211
+ // the stored session/profile at all, even though `quox org list` on
212
+ // the same session shows a real membership. Whoami is a read verb, so
213
+ // when the active org is unset we resolve it by fetching the caller's
214
+ // org memberships through the exact same endpoint `quox org list`
215
+ // uses, and display the single membership (or the first, marked as
216
+ // resolved from membership) instead of the literal 'none'. Only an
217
+ // empty membership list still says 'none'. This never writes back to
218
+ // stored auth state; it only changes what is displayed.
219
+ let orgDisplay;
220
+ if (authData.org_name) {
221
+ orgDisplay = `${authData.org_name} (${authData.org_slug})`;
222
+ } else if (authData.org_id) {
223
+ orgDisplay = authData.org_id;
224
+ } else {
225
+ let memberships = [];
226
+ try {
227
+ const orgsEp = resolveEndpoint('orgs.list');
228
+ const orgsData = await client.get(orgsEp.path, { service: orgsEp.service });
229
+ const list = orgsData.organizations || orgsData.orgs || orgsData;
230
+ memberships = Array.isArray(list) ? list : [];
231
+ } catch {
232
+ memberships = [];
233
+ }
234
+ if (memberships.length > 0) {
235
+ const m = memberships[0];
236
+ const label = m.name || m.id;
237
+ orgDisplay = `${label}${m.slug ? ` (${m.slug})` : ''} (resolved from membership)`;
238
+ } else {
239
+ orgDisplay = 'none';
240
+ }
241
+ }
242
+
243
+ const info = {
244
+ user: data.user?.display_name || data.user?.email || authData.email,
245
+ email: data.user?.email || authData.email,
246
+ user_id: data.user?.id || authData.user_id,
247
+ org: orgDisplay,
248
+ role: authData.org_role || 'n/a',
249
+ mfa: data.user?.mfa_enabled ? 'enabled' : 'disabled',
250
+ // Z2H-3c: expires_at is the ACCESS token. With a refresh token the sign-in outlives it, so do not
251
+ // present it as the session ending (a fresh owner read "expires in 60m" right after logging in).
252
+ session: authData.expires_at
253
+ ? (authData.refresh_token
254
+ ? `active, auto-renews (token refresh in ${Math.max(0, Math.round((authData.expires_at - Date.now()) / 60000))}m)`
255
+ : `expires in ${Math.max(0, Math.round((authData.expires_at - Date.now()) / 60000))}m`)
256
+ : 'unknown',
257
+ profile: config.getActiveProfileName(),
258
+ };
259
+ const fields = ['user', 'email', 'user_id', 'org', 'role', 'mfa', 'session', 'profile'];
260
+ const labels = {
261
+ user: 'User',
262
+ email: 'Email',
263
+ user_id: 'User ID',
264
+ org: 'Org',
265
+ role: 'Role',
266
+ mfa: 'MFA',
267
+ session: 'Session',
268
+ profile: 'Profile',
269
+ };
270
+
271
+ // Resident agent identity (quox#453 phase 15): only shown when the
272
+ // stored identity actually carries it, so a normal human login is
273
+ // unaffected.
274
+ const actorType = data.user?.actor_type || authData.actor_type;
275
+ const hostId = data.user?.host_id || authData.host_id;
276
+ if (actorType) {
277
+ info.actor_type = actorType;
278
+ labels.actor_type = 'Actor Type';
279
+ fields.splice(fields.indexOf('role') + 1, 0, 'actor_type');
280
+ }
281
+ if (hostId) {
282
+ info.host_id = hostId;
283
+ labels.host_id = 'Host ID';
284
+ fields.splice(fields.indexOf('mfa'), 0, 'host_id');
285
+ }
286
+
287
+ formatDetail(info, {
288
+ format: program.opts().output,
289
+ fields,
290
+ labels,
291
+ });
292
+
293
+ // F4 (QuoxIdentity CLI finding-fix): whoami answered "who is this
294
+ // token" but not "is this session also attached as an agent identity".
295
+ // QUOXIDENTITY P9: report only THIS session's agent (resolved
296
+ // session-scoped), not every attach on the box — the old scan listed
297
+ // every session's lease, which is exactly the "single resident sees all"
298
+ // flaw. A scan failure must never fail whoami itself.
299
+ try {
300
+ // Show what PLAIN verbs would act as (whoami itself is exempt from the default).
301
+ const acting = await resolveActing({ argv: process.argv.slice(2).filter((x) => x !== 'whoami') .concat(['_probe']) });
302
+ if (acting.source === 'flag' || acting.source === 'env' || acting.source === 'default') {
303
+ const askit = readStoredKit(acting.name);
304
+ const why = acting.source === 'flag' ? '--as' : acting.source === 'env' ? 'QUOX_AS' : 'default: attached session';
305
+ printInfo(
306
+ ` Acting as ${acting.name} (${why})`
307
+ + (askit?.lease?.id ? ` (attach lease ${askit.lease.id}, expires ${askit.lease.expires_at || 'unknown'})` : '')
308
+ );
309
+ } else if (acting.source === 'self') {
310
+ printInfo(' Acting as yourself (--as self)');
311
+ } else if (acting.source === 'profile') {
312
+ printInfo(' Acting as yourself (-p/--profile given)');
313
+ } else if (myAttachState().state === 'ambiguous') {
314
+ printInfo(' Acting as yourself: this session has more than one attach (ambiguous), so no agent default applies. Pick one with --as <agent>.');
315
+ }
316
+ } catch {
317
+ // Best effort only.
318
+ }
319
+ try {
320
+ const mine = resolveMyAttach();
321
+ if (mine) {
322
+ const kit = readStoredKit(mine.agentId);
323
+ const key = sessionKey();
324
+ printInfo(
325
+ ` attached as ${mine.agentId}`
326
+ + (kit?.lease?.id ? ` (lease ${String(kit.lease.id).slice(0, 8)}, expires ${kit.lease.expires_at || 'unknown'})` : '')
327
+ + (key ? ` · session ${key}` : '')
328
+ );
329
+ }
330
+ } catch {
331
+ // Best effort only: never fail whoami on an attach-state scan error.
332
+ }
333
+ });
334
+
335
+ // quox signup
336
+ program
337
+ .command('signup')
338
+ .description('Create a new user account')
339
+ .requiredOption('--email <email>', 'email address')
340
+ .requiredOption('--password <password>', 'password')
341
+ .requiredOption('--name <name>', 'display name')
342
+ .action(async (options) => {
343
+ const data = await client.post(resolveEndpoint('auth.signup').path, {
344
+ service: resolveEndpoint('auth.signup').service,
345
+ body: {
346
+ email: options.email,
347
+ password: options.password,
348
+ display_name: options.name,
349
+ },
350
+ noAuth: true,
351
+ });
352
+ printSuccess(`Account created for ${options.email}. Check your email for verification.`);
353
+ });
354
+
355
+ // quox mfa
356
+ const mfa = program
357
+ .command('mfa')
358
+ .description('Manage multi-factor authentication');
359
+
360
+ mfa
361
+ .command('setup')
362
+ .description('Enable MFA for your account')
363
+ .action(async () => {
364
+ auth.requireAuth();
365
+ const data = await client.post(resolveEndpoint('mfa.setup').path, { service: resolveEndpoint('mfa.setup').service });
366
+ if (data.qr_code || data.secret) {
367
+ console.log(chalk.bold('MFA Setup'));
368
+ if (data.secret) console.log(`Secret: ${data.secret}`);
369
+ if (data.qr_code) console.log(`QR URL: ${data.qr_code}`);
370
+ printInfo('Enter the code from your authenticator app to verify.');
371
+ } else {
372
+ printSuccess('MFA setup initiated. Check the response for setup instructions.');
373
+ }
374
+ });
375
+
376
+ mfa
377
+ .command('verify')
378
+ .description('Verify MFA setup with a code')
379
+ .requiredOption('--code <code>', 'TOTP verification code')
380
+ .action(async (options) => {
381
+ auth.requireAuth();
382
+ await client.post(resolveEndpoint('mfa.verify-setup').path, {
383
+ service: resolveEndpoint('mfa.verify-setup').service,
384
+ body: { code: options.code },
385
+ });
386
+ printSuccess('MFA enabled successfully.');
387
+ });
388
+
389
+ mfa
390
+ .command('disable')
391
+ .description('Disable MFA for your account')
392
+ .requiredOption('--code <code>', 'TOTP code to confirm')
393
+ .action(async (options) => {
394
+ auth.requireAuth();
395
+ await client.post(resolveEndpoint('mfa.disable').path, {
396
+ service: resolveEndpoint('mfa.disable').service,
397
+ body: { code: options.code },
398
+ });
399
+ printSuccess('MFA disabled.');
400
+ });
401
+
402
+ mfa
403
+ .command('backup-codes')
404
+ .description('View MFA backup codes')
405
+ .action(async () => {
406
+ auth.requireAuth();
407
+ const data = await client.get(resolveEndpoint('mfa.backup-codes.list').path, { service: resolveEndpoint('mfa.backup-codes.list').service });
408
+ if (program.opts().output === 'json') {
409
+ console.log(JSON.stringify(data, null, 2));
410
+ } else {
411
+ console.log(chalk.bold('Backup Codes'));
412
+ console.log(chalk.dim('Save these somewhere safe:\n'));
413
+ for (const code of (data.codes || data.backup_codes || [])) {
414
+ console.log(` ${code}`);
415
+ }
416
+ }
417
+ });
418
+
419
+ // ── quox account ────────────────────────────────────────────────────────
420
+ // fleet #390: PATCH /api/auth/me/password existed, worked and audited, but
421
+ // no command exposed it — so rotating your own password on a headless box
422
+ // meant hand-crafting a curl with a bearer token. Credential rotation is
423
+ // basic hygiene; making the correct action harder than doing nothing is
424
+ // the wrong incentive for a governance product.
425
+ const account = program
426
+ .command('account')
427
+ .description('Your own account (password, session)');
428
+
429
+ account
430
+ .command('password')
431
+ .description('Change your password')
432
+ // Values are prompted by default. --current/--new exist for automation,
433
+ // but they land in argv and shell history, so the help says so plainly
434
+ // rather than presenting them as equivalent.
435
+ .option('--current <password>', 'current password (WARNING: visible in argv/shell history — prefer the prompt)')
436
+ .option('--new <password>', 'new password (same warning)')
437
+ .action(async (options) => {
438
+ auth.requireAuth();
439
+
440
+ let current = options.current;
441
+ let next = options.new;
442
+
443
+ if (!current || !next) {
444
+ const { default: inquirer } = await import('inquirer');
445
+ if (!current) {
446
+ const a = await inquirer.prompt([{ type: 'password', name: 'v', message: 'Current password:', mask: '*' }]);
447
+ current = a.v;
448
+ }
449
+ if (!next) {
450
+ const a = await inquirer.prompt([{ type: 'password', name: 'v', message: 'New password:', mask: '*' }]);
451
+ const b = await inquirer.prompt([{ type: 'password', name: 'v', message: 'Confirm new password:', mask: '*' }]);
452
+ if (a.v !== b.v) throw new Error('New passwords do not match.');
453
+ next = a.v;
454
+ }
455
+ }
456
+
457
+ const ep = resolveEndpoint('auth.me.password');
458
+ await client.patch(ep.path, {
459
+ service: ep.service,
460
+ body: { current_password: current, new_password: next },
461
+ });
462
+ printSuccess('Password changed. Existing sessions elsewhere may need re-authentication.');
463
+ });
464
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * `quox awareness post|list|summary|remove`: QuoxAwareness ledger, the
3
+ * cross-surface situational-awareness store. Collector routes under
4
+ * /api/v1/awareness (org-scoped).
5
+ */
6
+ import { formatOutput, printSuccess } from '../core/output.js';
7
+ import { resolveEndpoint } from '../api/endpoints.js';
8
+ import { resolveOrgId } from './helpers.js';
9
+
10
+ export function registerAwarenessCommands(program, ctx) {
11
+ const { client, auth } = ctx;
12
+
13
+ const aw = program.command('awareness').description('QuoxAwareness: cross-surface situational-awareness ledger');
14
+
15
+ aw
16
+ .command('post <key> <state>')
17
+ .description('Post or update an awareness entry (upsert by key)')
18
+ .option('--title <text>', 'short title')
19
+ .option('--detail <text>', 'longer detail')
20
+ .option('--source <text>', 'who is posting this entry', 'manual')
21
+ .option('--severity <level>', 'info|warn|critical', 'info')
22
+ .option('--ttl <seconds>', 'expire the entry after this many seconds')
23
+ .action(async (key, state, options) => {
24
+ auth.requireAuth();
25
+ const ep = resolveEndpoint('awareness.post');
26
+ const body = {
27
+ key,
28
+ state,
29
+ title: options.title,
30
+ detail: options.detail,
31
+ source: options.source,
32
+ severity: options.severity,
33
+ ttl_s: options.ttl ? Number(options.ttl) : undefined,
34
+ };
35
+ const data = await client.post(ep.path, { service: ep.service, body, query: { org_id: resolveOrgId(auth, program) } });
36
+ if (program.opts().output === 'json') { console.log(JSON.stringify(data, null, 2)); return; }
37
+ printSuccess(`Posted awareness: ${key}`);
38
+ });
39
+
40
+ aw
41
+ .command('list')
42
+ .description('List awareness entries for the active org')
43
+ .option('--source <text>', 'filter by source')
44
+ .action(async (options) => {
45
+ auth.requireAuth();
46
+ const ep = resolveEndpoint('awareness.list');
47
+ const data = await client.get(ep.path, { service: ep.service, query: { org_id: resolveOrgId(auth, program), source: options.source } });
48
+ const entries = data.entries || [];
49
+ formatOutput(entries.map((e) => ({
50
+ KEY: e.key,
51
+ TITLE: e.title || '',
52
+ STATE: e.state,
53
+ SEV: e.severity || '',
54
+ SOURCE: e.source || '',
55
+ UPDATED: e.updated_at || '',
56
+ })), {
57
+ format: program.opts().output,
58
+ columns: ['KEY', 'TITLE', 'STATE', 'SEV', 'SOURCE', 'UPDATED'],
59
+ emptyMessage: 'No awareness entries. Post one with `quox awareness post <key> <state>`.',
60
+ raw: entries,
61
+ });
62
+ });
63
+
64
+ aw
65
+ .command('summary')
66
+ .description('Current-state briefing (what a reader like the voice receptionist sees)')
67
+ .action(async () => {
68
+ auth.requireAuth();
69
+ const ep = resolveEndpoint('awareness.summary');
70
+ const data = await client.get(ep.path, { service: ep.service, query: { org_id: resolveOrgId(auth, program) } });
71
+ if (program.opts().output === 'json') {
72
+ formatOutput(data, { format: 'json', raw: data });
73
+ return;
74
+ }
75
+ console.log(data.text);
76
+ });
77
+
78
+ aw
79
+ .command('remove <key>')
80
+ .description('Remove an awareness entry')
81
+ .action(async (key) => {
82
+ auth.requireAuth();
83
+ const ep = resolveEndpoint('awareness.remove', { key });
84
+ const data = await client.delete(ep.path, { service: ep.service, query: { org_id: resolveOrgId(auth, program) } });
85
+ if (program.opts().output === 'json') { console.log(JSON.stringify(data, null, 2)); return; }
86
+ printSuccess(`Removed ${key}`);
87
+ });
88
+ }