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,87 @@
1
+ /**
2
+ * QuoxCLI TUI Keybindings
3
+ *
4
+ * Defines keyboard shortcuts for the TUI and help overlay entries.
5
+ * Vim-style navigation (h/j/k/l) plus standard arrow keys.
6
+ *
7
+ * Exports:
8
+ * KEYS - action name → key arrays (for useInput matching)
9
+ * KEY_HELP - ordered list of { keys, desc } for the help overlay
10
+ */
11
+
12
+ // ── Key mappings ──────────────────────────────────────────────────────
13
+ export const KEYS = {
14
+ up: ['up', 'k'],
15
+ down: ['down', 'j'],
16
+ left: ['left', 'h'],
17
+ right: ['right', 'l'],
18
+ select: ['return'],
19
+ back: ['escape'],
20
+ tab: ['tab'],
21
+ search: ['/'],
22
+ help: ['?'],
23
+ quit: ['q'],
24
+ refresh: ['r'],
25
+ delete: ['d'],
26
+ edit: ['e'],
27
+ create: ['c'],
28
+ nextPage: ['n'],
29
+ prevPage: ['p'],
30
+ // Command palette. Ctrl+K can't be expressed as a plain input string
31
+ // (matchKey's default case only compares `input === binding`), so the
32
+ // Ctrl+K half is detected directly in app.jsx via `key.ctrl && input
33
+ // === 'k'`. ':' works here since it's a normal single character.
34
+ palette: [':'],
35
+ };
36
+
37
+ // ── Help overlay entries ──────────────────────────────────────────────
38
+ export const KEY_HELP = [
39
+ { keys: '\u2191/k \u2193/j', desc: 'Navigate' },
40
+ { keys: 'Enter', desc: 'Select' },
41
+ { keys: 'Esc', desc: 'Back' },
42
+ { keys: 'Tab', desc: 'Switch panel' },
43
+ { keys: '/', desc: 'Search' },
44
+ { keys: '?', desc: 'Help' },
45
+ { keys: 'q', desc: 'Quit' },
46
+ { keys: 'r', desc: 'Refresh' },
47
+ { keys: 'n / p', desc: 'Next / prev page' },
48
+ { keys: 'c', desc: 'Create' },
49
+ { keys: 'd', desc: 'Delete' },
50
+ { keys: 'e', desc: 'Edit' },
51
+ { keys: 'Ctrl+K / :', desc: 'Command palette' },
52
+ { keys: '1-0 o i v g h', desc: 'Jump to screen (anywhere)' },
53
+ ];
54
+
55
+ /**
56
+ * Check whether a key + input flags match a named action.
57
+ *
58
+ * Usage with ink's useInput:
59
+ * useInput((input, key) => {
60
+ * if (matchKey('up', input, key)) { ... }
61
+ * });
62
+ *
63
+ * @param {string} action - key from KEYS (e.g. 'up', 'quit')
64
+ * @param {string} input - the raw character from useInput
65
+ * @param {Object} key - the key flags from useInput ({ return, escape, tab, upArrow, downArrow, leftArrow, rightArrow })
66
+ * @returns {boolean}
67
+ */
68
+ export function matchKey(action, input, key) {
69
+ const bindings = KEYS[action];
70
+ if (!bindings) return false;
71
+
72
+ for (const binding of bindings) {
73
+ switch (binding) {
74
+ case 'up': if (key.upArrow) return true; break;
75
+ case 'down': if (key.downArrow) return true; break;
76
+ case 'left': if (key.leftArrow) return true; break;
77
+ case 'right': if (key.rightArrow) return true; break;
78
+ case 'return': if (key.return) return true; break;
79
+ case 'escape': if (key.escape) return true; break;
80
+ case 'tab': if (key.tab) return true; break;
81
+ default:
82
+ if (input === binding) return true;
83
+ }
84
+ }
85
+
86
+ return false;
87
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * SCREEN_REGISTRY — single source of truth for navigable TUI screens
3
+ *
4
+ * Consumed by:
5
+ * - components/Palette.jsx — command-palette search + result list
6
+ * - app.jsx — global jump-key (hotkey -> screen id) map
7
+ * - components/Layout.jsx — breadcrumb title lookup
8
+ *
9
+ * Mirrors MainMenu.jsx's MENU_ITEMS (same ids/hotkeys) but lives outside
10
+ * views/ so non-view files (app.jsx, Palette, Layout) can import it
11
+ * without reaching into MainMenu.jsx.
12
+ *
13
+ * Each entry: { id, title, keywords, hotkey }
14
+ * id - matches app.jsx SCREENS / VIEW_COMPONENTS key
15
+ * title - human-readable label (palette list + breadcrumb segment)
16
+ * keywords - extra terms the palette substring-matches against
17
+ * hotkey - single-char global jump key (1-0, then o/i/v/g/h)
18
+ */
19
+
20
+ export const SCREEN_REGISTRY = [
21
+ { id: 'fleet', title: 'Fleet', keywords: ['status', 'agents', 'health', 'hosts'], hotkey: '1' },
22
+ { id: 'agents', title: 'Agents', keywords: ['activate', 'deactivate', 'tools'], hotkey: '2' },
23
+ { id: 'tools', title: 'Tools', keywords: ['catalog', 'install', 'manage'], hotkey: '3' },
24
+ { id: 'orgs', title: 'Organizations', keywords: ['org', 'members', 'divisions', 'switch'], hotkey: '4' },
25
+ { id: 'memory', title: 'Memory', keywords: ['entities', 'conversations', 'search'], hotkey: '5' },
26
+ { id: 'brain', title: 'Brain', keywords: ['quoxbrain', 'brain2', 'notes', 'knowledge', 'vaults', 'second brain', 'search'], hotkey: 'b' },
27
+ { id: 'workflows', title: 'Workflows', keywords: ['crud', 'run', 'steps', 'versions'], hotkey: '6' },
28
+ { id: 'chat', title: 'Chat', keywords: ['commanderq', 'interactive'], hotkey: '7' },
29
+ { id: 'admin', title: 'Admin', keywords: ['config', 'api keys', 'services', 'logs', 'retention'], hotkey: '8' },
30
+ { id: 'files', title: 'Files', keywords: ['upload', 'download', 'list', 'delete'], hotkey: '9' },
31
+ { id: 'backups', title: 'Backups', keywords: ['restore', 'verify', 'schedules'], hotkey: '0' },
32
+ { id: 'objectives', title: 'Objectives', keywords: ['goals', 'plan', 'approve', 'start', 'track'], hotkey: 'o' },
33
+ { id: 'inbox', title: 'Inbox', keywords: ['hitl', 'approvals', 'review', 'approve', 'deny'], hotkey: 'i' },
34
+ { id: 'vault', title: 'Vault', keywords: ['credentials', 'test', 'expiry', 'activity'], hotkey: 'v' },
35
+ { id: 'governance', title: 'Governance', keywords: ['ward', 'volt', 'evidence', 'policies', 'approvals'], hotkey: 'g' },
36
+ { id: 'health', title: 'Health', keywords: ['service health', 'incidents', 'sparklines'], hotkey: 'h' },
37
+ ];
38
+
39
+ /** Screen id -> title, with 'menu' -> 'Main' added for the breadcrumb root. */
40
+ export const SCREEN_TITLES = {
41
+ menu: 'Main',
42
+ ...Object.fromEntries(SCREEN_REGISTRY.map((entry) => [entry.id, entry.title])),
43
+ };
44
+
45
+ /** Screen id -> registry entry. */
46
+ export const SCREEN_BY_ID = Object.fromEntries(SCREEN_REGISTRY.map((entry) => [entry.id, entry]));
47
+
48
+ /** hotkey -> screen id, for the global jump-key handler in app.jsx. */
49
+ export const SCREEN_BY_HOTKEY = Object.fromEntries(SCREEN_REGISTRY.map((entry) => [entry.hotkey, entry.id]));
@@ -0,0 +1,103 @@
1
+ /**
2
+ * QuoxCLI TUI Theme
3
+ *
4
+ * Color palette matching QuoxCORE brand (blue/cyan/violet gradient).
5
+ * Inspired by QuoxBastion's BubbleTea TUI theme.
6
+ *
7
+ * Exports:
8
+ * colors - hex color values
9
+ * styles - chalk formatting functions
10
+ * BORDERS - box-drawing characters for panels
11
+ */
12
+
13
+ import chalk from 'chalk';
14
+
15
+ // ── Brand color palette ───────────────────────────────────────────────
16
+ export const colors = {
17
+ // Brand gradient
18
+ primary: '#3B82F6', // electric blue
19
+ secondary: '#6366F1', // indigo
20
+ accent: '#C084FC', // lilac
21
+
22
+ // Status
23
+ success: '#22C55E',
24
+ error: '#EF4444',
25
+ warning: '#FBBF24',
26
+
27
+ // Highlights
28
+ cyberBlue: '#38BDF8',
29
+ info: '#38BDF8',
30
+
31
+ // Text hierarchy
32
+ text: '#E4E4E7',
33
+ textMuted: '#A1A1AA',
34
+ dim: '#71717A',
35
+ subtle: '#3F3F46',
36
+
37
+ // Backgrounds
38
+ bgPanel: '#111827',
39
+ bgHighlight:'#1E293B',
40
+ };
41
+
42
+ // ── Chalk-based style functions ───────────────────────────────────────
43
+ export const styles = {
44
+ // Headings
45
+ title: (t) => chalk.hex(colors.primary).bold(t),
46
+ subtitle: (t) => chalk.hex(colors.secondary)(t),
47
+ heading: (t) => chalk.hex(colors.accent).bold(t),
48
+
49
+ // Text
50
+ text: (t) => chalk.hex(colors.text)(t),
51
+ muted: (t) => chalk.hex(colors.textMuted)(t),
52
+ dim: (t) => chalk.hex(colors.dim)(t),
53
+ subtle: (t) => chalk.hex(colors.subtle)(t),
54
+
55
+ // Status
56
+ success: (t) => chalk.hex(colors.success)(t),
57
+ error: (t) => chalk.hex(colors.error).bold(t),
58
+ warning: (t) => chalk.hex(colors.warning)(t),
59
+ info: (t) => chalk.hex(colors.cyberBlue)(t),
60
+
61
+ // Brand
62
+ primary: (t) => chalk.hex(colors.primary)(t),
63
+ secondary: (t) => chalk.hex(colors.secondary)(t),
64
+ accent: (t) => chalk.hex(colors.accent)(t),
65
+ cyber: (t) => chalk.hex(colors.cyberBlue).bold(t),
66
+
67
+ // Compound
68
+ label: (t) => chalk.hex(colors.textMuted).bold(t),
69
+ key: (t) => chalk.hex(colors.cyberBlue).bold(t),
70
+ value: (t) => chalk.hex(colors.text)(t),
71
+ badge: (t) => chalk.hex(colors.bgPanel).bgHex(colors.primary).bold(` ${t} `),
72
+ badgeAccent:(t) => chalk.hex(colors.bgPanel).bgHex(colors.accent).bold(` ${t} `),
73
+
74
+ // Inline status indicators
75
+ statusDot: (status) => {
76
+ const map = {
77
+ online: chalk.hex(colors.success)('\u25CF'),
78
+ healthy: chalk.hex(colors.success)('\u25CF'),
79
+ active: chalk.hex(colors.success)('\u25CF'),
80
+ warning: chalk.hex(colors.warning)('\u25CF'),
81
+ degraded:chalk.hex(colors.warning)('\u25CF'),
82
+ error: chalk.hex(colors.error)('\u25CF'),
83
+ offline: chalk.hex(colors.error)('\u25CF'),
84
+ unknown: chalk.hex(colors.dim)('\u25CB'),
85
+ };
86
+ return map[status] || map.unknown;
87
+ },
88
+ };
89
+
90
+ // ── Box-drawing border characters ─────────────────────────────────────
91
+ export const BORDERS = {
92
+ topLeft: '\u256D', // ╭
93
+ topRight: '\u256E', // ╮
94
+ bottomLeft: '\u2570', // ╰
95
+ bottomRight: '\u256F', // ╯
96
+ horizontal: '\u2500', // ─
97
+ vertical: '\u2502', // │
98
+ teeRight: '\u251C', // ├
99
+ teeLeft: '\u2524', // ┤
100
+ teeDown: '\u252C', // ┬
101
+ teeUp: '\u2534', // ┴
102
+ cross: '\u253C', // ┼
103
+ };
@@ -0,0 +1,398 @@
1
+ /**
2
+ * AdminView — Admin panel with tabbed navigation
3
+ *
4
+ * Tabs: Config | Keys | Services | Logs | Retention
5
+ *
6
+ * Each tab has its own DataTable sourced from admin API endpoints.
7
+ * Tab key cycles through tabs.
8
+ *
9
+ * API (all service: auth):
10
+ * GET /api/admin/config -> key-value pairs
11
+ * GET /api/admin/keys -> table (id, name, prefix, role, last_used)
12
+ * GET /api/admin/services -> table (id, name, status, url)
13
+ * GET /api/admin/logs -> table (timestamp, user_email, action, detail)
14
+ * GET /api/admin/retention/config -> key-value pairs
15
+ */
16
+
17
+ import React, { useState, useEffect, useCallback } from 'react';
18
+ import { Box, Text, useInput } from 'ink';
19
+ import { Layout } from '../components/Layout.jsx';
20
+ import { DataTable } from '../components/DataTable.jsx';
21
+ import { DetailPanel } from '../components/DetailPanel.jsx';
22
+ import { useApi } from '../hooks/useApi.js';
23
+ import { useTui } from '../app.jsx';
24
+ import { matchKey } from '../keys.js';
25
+ import { colors, styles } from '../theme.js';
26
+ import { resolveEndpoint } from '../../api/endpoints.js';
27
+
28
+ // ── Tab definitions ───────────────────────────────────────────────────
29
+ const TABS = ['Config', 'Keys', 'Services', 'Logs', 'Retention'];
30
+
31
+ // ── Column definitions per tab ────────────────────────────────────────
32
+ const CONFIG_COLUMNS = [
33
+ { key: 'key', label: 'Key', width: 28 },
34
+ { key: 'value', label: 'Value', width: 36 },
35
+ ];
36
+
37
+ const KEYS_COLUMNS = [
38
+ { key: 'id', label: 'ID', width: 10 },
39
+ { key: 'name', label: 'Name', width: 18 },
40
+ { key: 'prefix', label: 'Prefix', width: 12 },
41
+ { key: 'role', label: 'Role', width: 12 },
42
+ { key: 'last_used', label: 'Last Used', width: 14 },
43
+ ];
44
+
45
+ const SERVICES_COLUMNS = [
46
+ { key: 'id', label: 'ID', width: 10 },
47
+ { key: 'name', label: 'Name', width: 18 },
48
+ { key: 'status', label: 'Status', width: 12 },
49
+ { key: 'url', label: 'URL', width: 28 },
50
+ ];
51
+
52
+ const LOGS_COLUMNS = [
53
+ { key: 'timestamp', label: 'Time', width: 20 },
54
+ { key: 'user_email', label: 'User', width: 20 },
55
+ { key: 'action', label: 'Action', width: 14 },
56
+ { key: 'detail', label: 'Detail', width: 20 },
57
+ ];
58
+
59
+ const RETENTION_COLUMNS = [
60
+ { key: 'key', label: 'Key', width: 28 },
61
+ { key: 'value', label: 'Value', width: 36 },
62
+ ];
63
+
64
+ // ── Row formatters ────────────────────────────────────────────────────
65
+
66
+ function formatConfigRows(data) {
67
+ if (!data || typeof data !== 'object') return [];
68
+ if (Array.isArray(data)) {
69
+ return data.map((item) => ({
70
+ key: item.key || item.name || '',
71
+ value: String(item.value != null ? item.value : ''),
72
+ _raw: item,
73
+ }));
74
+ }
75
+ // Object key-value pairs
76
+ return Object.entries(data).map(([k, v]) => ({
77
+ key: k,
78
+ value: String(v != null ? v : ''),
79
+ _raw: { key: k, value: v },
80
+ }));
81
+ }
82
+
83
+ function formatKeysRows(keys) {
84
+ if (!Array.isArray(keys)) return [];
85
+ return keys.map((k) => ({
86
+ id: k.id || '--',
87
+ name: k.name || k.display_name || '--',
88
+ prefix: k.prefix || '--',
89
+ role: k.role || '--',
90
+ last_used: k.last_used ? formatDate(k.last_used) : '--',
91
+ _raw: k,
92
+ }));
93
+ }
94
+
95
+ function formatServicesRows(services) {
96
+ if (!Array.isArray(services)) return [];
97
+ return services.map((s) => ({
98
+ id: s.id || '--',
99
+ name: s.name || s.display_name || '--',
100
+ status: `${styles.statusDot(s.status || 'unknown')} ${s.status || 'unknown'}`,
101
+ url: s.url || s.endpoint || '--',
102
+ _raw: s,
103
+ }));
104
+ }
105
+
106
+ function formatLogsRows(logs) {
107
+ if (!Array.isArray(logs)) return [];
108
+ return logs.map((l) => ({
109
+ timestamp: l.timestamp ? formatDate(l.timestamp) : '--',
110
+ user_email: l.user_email || l.email || l.user || '--',
111
+ action: l.action || l.type || '--',
112
+ detail: truncate(l.detail || l.message || l.description || '', 18),
113
+ _raw: l,
114
+ }));
115
+ }
116
+
117
+ // ── Detail builders ───────────────────────────────────────────────────
118
+
119
+ function buildConfigDetail(raw) {
120
+ if (!raw) return null;
121
+ return {
122
+ 'Key': raw.key || raw.name,
123
+ 'Value': raw.value,
124
+ };
125
+ }
126
+
127
+ function buildKeyDetail(raw) {
128
+ if (!raw) return null;
129
+ return {
130
+ 'ID': raw.id,
131
+ 'Name': raw.name || raw.display_name,
132
+ 'Prefix': raw.prefix,
133
+ 'Role': raw.role,
134
+ 'Last Used': raw.last_used,
135
+ 'Created': raw.created_at,
136
+ 'Expires': raw.expires_at || '--',
137
+ };
138
+ }
139
+
140
+ function buildServiceDetail(raw) {
141
+ if (!raw) return null;
142
+ return {
143
+ 'ID': raw.id,
144
+ 'Name': raw.name || raw.display_name,
145
+ 'Status': raw.status,
146
+ 'URL': raw.url || raw.endpoint,
147
+ 'Version': raw.version || '--',
148
+ 'Uptime': raw.uptime || '--',
149
+ 'Last Check': raw.last_check || raw.checked_at || '--',
150
+ };
151
+ }
152
+
153
+ function buildLogDetail(raw) {
154
+ if (!raw) return null;
155
+ return {
156
+ 'Timestamp': raw.timestamp,
157
+ 'User': raw.user_email || raw.email || raw.user,
158
+ 'Action': raw.action || raw.type,
159
+ 'Detail': raw.detail || raw.message || raw.description,
160
+ 'IP': raw.ip || raw.ip_address || '--',
161
+ 'ID': raw.id,
162
+ };
163
+ }
164
+
165
+ function buildRetentionDetail(raw) {
166
+ if (!raw) return null;
167
+ return {
168
+ 'Key': raw.key || raw.name,
169
+ 'Value': raw.value,
170
+ };
171
+ }
172
+
173
+ // ── Utility ───────────────────────────────────────────────────────────
174
+
175
+ function truncate(str, max) {
176
+ if (!str) return '';
177
+ const s = String(str).replace(/\n/g, ' ');
178
+ return s.length > max ? s.slice(0, max - 1) + '\u2026' : s;
179
+ }
180
+
181
+ function formatDate(iso) {
182
+ if (!iso) return '--';
183
+ try {
184
+ const d = new Date(iso);
185
+ return d.toISOString().slice(0, 16).replace('T', ' ');
186
+ } catch {
187
+ return String(iso).slice(0, 16);
188
+ }
189
+ }
190
+
191
+ // ── Component ─────────────────────────────────────────────────────────
192
+ export function AdminView() {
193
+ const ctx = useTui();
194
+ const { client, screen, orgVersion } = ctx;
195
+ const isActive = screen === 'admin';
196
+
197
+ const [activeTab, setActiveTab] = useState(0);
198
+ const [selected, setSelected] = useState(0);
199
+
200
+ // ── Fetch config (refetches when the active org changes) ────────────
201
+ const { data: configData, loading: configLoading, error: configError, refresh: refreshConfig } = useApi(
202
+ async () => {
203
+ const res = await client.get(resolveEndpoint('admin.config.list').path, { service: resolveEndpoint('admin.config.list').service });
204
+ return res?.config || res || {};
205
+ },
206
+ [client, orgVersion]
207
+ );
208
+
209
+ // ── Fetch keys ────────────────────────────────────────────────────
210
+ const { data: keysData, loading: keysLoading, error: keysError, refresh: refreshKeys } = useApi(
211
+ async () => {
212
+ const res = await client.get(resolveEndpoint('admin.keys.list').path, { service: resolveEndpoint('admin.keys.list').service });
213
+ return res?.keys || [];
214
+ },
215
+ [client, orgVersion]
216
+ );
217
+
218
+ // ── Fetch services ────────────────────────────────────────────────
219
+ const { data: servicesData, loading: servicesLoading, error: servicesError, refresh: refreshServices } = useApi(
220
+ async () => {
221
+ const res = await client.get(resolveEndpoint('admin.services.list').path, { service: resolveEndpoint('admin.services.list').service });
222
+ return res?.services || [];
223
+ },
224
+ [client, orgVersion]
225
+ );
226
+
227
+ // ── Fetch logs ────────────────────────────────────────────────────
228
+ const { data: logsData, loading: logsLoading, error: logsError, refresh: refreshLogs } = useApi(
229
+ async () => {
230
+ const res = await client.get(resolveEndpoint('admin.logs.list').path, { service: resolveEndpoint('admin.logs.list').service });
231
+ return res?.logs || [];
232
+ },
233
+ [client, orgVersion]
234
+ );
235
+
236
+ // ── Fetch retention ───────────────────────────────────────────────
237
+ const { data: retentionData, loading: retentionLoading, error: retentionError, refresh: refreshRetention } = useApi(
238
+ async () => {
239
+ const res = await client.get(resolveEndpoint('admin.retention.config.list').path, { service: resolveEndpoint('admin.retention.config.list').service });
240
+ return res?.config || res || {};
241
+ },
242
+ [client, orgVersion]
243
+ );
244
+
245
+ // ── Active tab data ─────────────────────────────────────────────────
246
+ let columns, rows, detail, loading, error;
247
+
248
+ switch (activeTab) {
249
+ case 0: // Config
250
+ columns = CONFIG_COLUMNS;
251
+ rows = formatConfigRows(configData);
252
+ detail = rows[selected] ? buildConfigDetail(rows[selected]._raw) : null;
253
+ loading = configLoading;
254
+ error = configError;
255
+ break;
256
+ case 1: // Keys
257
+ columns = KEYS_COLUMNS;
258
+ rows = formatKeysRows(keysData);
259
+ detail = rows[selected] ? buildKeyDetail(rows[selected]._raw) : null;
260
+ loading = keysLoading;
261
+ error = keysError;
262
+ break;
263
+ case 2: // Services
264
+ columns = SERVICES_COLUMNS;
265
+ rows = formatServicesRows(servicesData);
266
+ detail = rows[selected] ? buildServiceDetail(rows[selected]._raw) : null;
267
+ loading = servicesLoading;
268
+ error = servicesError;
269
+ break;
270
+ case 3: // Logs
271
+ columns = LOGS_COLUMNS;
272
+ rows = formatLogsRows(logsData);
273
+ detail = rows[selected] ? buildLogDetail(rows[selected]._raw) : null;
274
+ loading = logsLoading;
275
+ error = logsError;
276
+ break;
277
+ case 4: // Retention
278
+ columns = RETENTION_COLUMNS;
279
+ rows = formatConfigRows(retentionData);
280
+ detail = rows[selected] ? buildRetentionDetail(rows[selected]._raw) : null;
281
+ loading = retentionLoading;
282
+ error = retentionError;
283
+ break;
284
+ }
285
+
286
+ // ── Reset selection on tab change ───────────────────────────────────
287
+ useEffect(() => {
288
+ setSelected(0);
289
+ }, [activeTab]);
290
+
291
+ // ── Refresh current tab ─────────────────────────────────────────────
292
+ const refreshCurrent = useCallback(() => {
293
+ const refreshers = [refreshConfig, refreshKeys, refreshServices, refreshLogs, refreshRetention];
294
+ refreshers[activeTab]?.();
295
+ }, [activeTab, refreshConfig, refreshKeys, refreshServices, refreshLogs, refreshRetention]);
296
+
297
+ // ── Keyboard handling ──────────────────────────────────────────────
298
+ useInput((input, key) => {
299
+ if (!isActive) return;
300
+
301
+ // Tab to switch sub-tabs
302
+ if (matchKey('tab', input, key)) {
303
+ setActiveTab((t) => (t + 1) % TABS.length);
304
+ return;
305
+ }
306
+
307
+ // Manual refresh
308
+ if (matchKey('refresh', input, key)) {
309
+ refreshCurrent();
310
+ return;
311
+ }
312
+ }, { isActive });
313
+
314
+ // ── Tab bar rendering ──────────────────────────────────────────────
315
+ const tabBar = (
316
+ <Box marginBottom={1}>
317
+ {TABS.map((tab, i) => {
318
+ const isSel = i === activeTab;
319
+ return (
320
+ <React.Fragment key={tab}>
321
+ {i > 0 && <Text color={colors.subtle}> | </Text>}
322
+ <Text
323
+ color={isSel ? colors.cyberBlue : colors.dim}
324
+ bold={isSel}
325
+ underline={isSel}
326
+ >
327
+ {tab}
328
+ </Text>
329
+ </React.Fragment>
330
+ );
331
+ })}
332
+ <Text color={colors.dim}> (Tab to switch)</Text>
333
+ </Box>
334
+ );
335
+
336
+ // ── Detail title ───────────────────────────────────────────────────
337
+ let detailTitle;
338
+ if (rows[selected]) {
339
+ switch (activeTab) {
340
+ case 0: detailTitle = rows[selected]._raw.key || rows[selected]._raw.name || 'Config'; break;
341
+ case 1: detailTitle = rows[selected]._raw.name || rows[selected]._raw.display_name || 'Key'; break;
342
+ case 2: detailTitle = rows[selected]._raw.name || rows[selected]._raw.display_name || 'Service'; break;
343
+ case 3: detailTitle = rows[selected]._raw.action || rows[selected]._raw.type || 'Log Entry'; break;
344
+ case 4: detailTitle = rows[selected]._raw.key || rows[selected]._raw.name || 'Retention'; break;
345
+ }
346
+ }
347
+
348
+ // ── Footer hint ────────────────────────────────────────────────────
349
+ const footer = [
350
+ '\u2191/k \u2193/j Navigate',
351
+ 'Tab Switch tab',
352
+ 'r Refresh',
353
+ 'Esc Back',
354
+ ].join(' ');
355
+
356
+ // ── Render ─────────────────────────────────────────────────────────
357
+ return (
358
+ <Layout
359
+ title="Admin"
360
+ subtitle={TABS[activeTab]}
361
+ footer={footer}
362
+ left={
363
+ <Box flexDirection="column">
364
+ {/* Tab bar */}
365
+ {tabBar}
366
+
367
+ {error && (
368
+ <Box marginBottom={1}>
369
+ <Text color={colors.error}>Error: {error.message}</Text>
370
+ </Box>
371
+ )}
372
+
373
+ <DataTable
374
+ columns={columns}
375
+ rows={rows}
376
+ selected={selected}
377
+ onSelectionChange={setSelected}
378
+ loading={loading}
379
+ emptyMessage={[
380
+ 'No config values set',
381
+ 'No API keys — create one via `quox admin key create`',
382
+ 'No services registered',
383
+ 'No audit events yet',
384
+ 'No retention settings configured',
385
+ ][activeTab]}
386
+ active={isActive}
387
+ />
388
+ </Box>
389
+ }
390
+ right={
391
+ <DetailPanel
392
+ title={detailTitle}
393
+ data={detail}
394
+ />
395
+ }
396
+ />
397
+ );
398
+ }