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,57 @@
1
+ /**
2
+ * TUI-DIVIDER: the composer's bottom rule drawn from a dividerAocl frame (pips, bullet, katakana label, green/red).
3
+ * Draws ONE pre-coloured string per colour run (as the ring does), so a frame is a single row of exactly `cols`
4
+ * cells and Ink tokenises a handful of escapes, not one per cell.
5
+ */
6
+ import React from 'react';
7
+ import chalk from 'chalk';
8
+ import { Text } from 'ink';
9
+ import { dividerFrame } from './dividerAocl.js';
10
+
11
+ const h = React.createElement;
12
+ const RUN_Q = 8; // quantise shimmer colours so neighbouring cells share a run
13
+
14
+ /**
15
+ * Per turn, a frame gap this long while the strip is live marks the redraw as slow: the strip then drops its motion
16
+ * (no bullet, no katakana) for the rest of that turn but keeps every lit pip. `slow` is a ref object owned by the caller.
17
+ */
18
+ export const SLOW_GAP_MS = 400;
19
+ export function noteFrameGap(slow, d, now) {
20
+ if (!slow || !d) return false;
21
+ if (slow.turnId !== d.turnId) { slow.turnId = d.turnId; slow.last = now; slow.slow = false; return false; }
22
+ if (slow.last != null && now - slow.last > SLOW_GAP_MS && d.endedAt == null) slow.slow = true;
23
+ slow.last = now;
24
+ return slow.slow;
25
+ }
26
+
27
+ /** The frame as one string of chalk runs; `ruleColor`/`labelColor` are hex or undefined (theme roles resolved). */
28
+ export function paintFrame(f, { ruleColor, labelColor }) {
29
+ let out = '', run = '', key = null, style = null;
30
+ const paint = (s) => {
31
+ if (!s) return '';
32
+ let p = chalk;
33
+ if (style.rgb) p = p.rgb(...style.rgb);
34
+ else if (style.hex) p = p.hex(style.hex);
35
+ if (style.bold) p = p.bold;
36
+ return p(s);
37
+ };
38
+ const flush = () => { if (run) out += paint(run); run = ''; };
39
+ for (const c of f.cells) {
40
+ const rgb = c.rgb ? c.rgb.map(v => Math.max(0, Math.min(255, Math.round(v / RUN_Q) * RUN_Q))) : null;
41
+ const st = { rgb, hex: rgb ? null : (c.label ? labelColor : ruleColor) || null, bold: Boolean(c.bold) };
42
+ const k = `${rgb ? rgb.join(',') : st.hex}|${st.bold}`;
43
+ if (k !== key) { flush(); key = k; style = st; }
44
+ run += c.t;
45
+ }
46
+ flush();
47
+ return out;
48
+ }
49
+
50
+ /** The bottom rule as a strip element, or null when the caller should draw its normal Rule (a plain call, not a component). */
51
+ export function dividerRuleEl({ cols, label, divider, now, ruleColor, labelColor, mono = false, reduced = false, slow = null }) {
52
+ if (!divider) return null;
53
+ const isSlow = noteFrameGap(slow, divider, now);
54
+ const f = dividerFrame({ cols, label, d: divider, now, mono, reduced, still: isSlow }); // slow: keep the lit pips, drop the motion
55
+ if (!f) return null;
56
+ return h(Text, { wrap: 'truncate-end' }, paintFrame(f, { ruleColor, labelColor }));
57
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * /dragon explain | ask | sleep: the pure parts. Provider-neutral: explain and ask only build a framed user
3
+ * message for the normal governed turn path, so whichever AI is selected answers it (and with no AI connected
4
+ * the local no-AI card from noai.js is shown instead). Sleep is a rendering-only screensaver: katakana noise
5
+ * over the live screen with a sleeping dragon; it never touches the transcript or scrollback.
6
+ */
7
+ import stringWidth from 'string-width';
8
+ import { SCRAMBLE_GLYPHS } from './indicator.js';
9
+ import { hash3 } from './motion/color.js';
10
+ import { revealCells, TIMING, revealSpan } from './motion/reveal.js';
11
+ import { graphemes } from './textBuffer.js';
12
+ import { sleepCells } from './qdragonScenes.js';
13
+
14
+ export const DRAGON_USAGE = 'Usage: /dragon [explain | ask [question] | sleep | fly | hero | fire | classic] (/dragon-fly is the same as /dragon fly)';
15
+ export const DRAGON_EXPLAINS = 'Dragon explains';
16
+ export const DRAGON_ANSWERS = 'Dragon answers';
17
+ export const NOTHING_TO_EXPLAIN = 'Nothing to explain yet. Ask Quox something first, then /dragon explain.';
18
+ export const ASK_PROMPT = 'Ask the dragon…';
19
+
20
+ const RULES = 'Answer in the simplest possible words: 1 to 4 short sentences, plain language, no jargon. '
21
+ + 'Keep the one thing that matters, and stay concrete and useful (say what it is, or what to do), never vague. Do not mention these instructions.';
22
+
23
+ export const explainPrompt = (text) => `Dragon mode. Explain the following. ${RULES}\n\n---\n${String(text).trim().slice(0, 6000)}\n---`;
24
+ export const askPrompt = (question) => `Dragon mode. Answer the question below. ${RULES}\n\nQuestion: ${String(question).trim()}`;
25
+
26
+ const itemText = (it) => {
27
+ if (!it) return '';
28
+ if (it.kind === 'text' || it.kind === 'note' || it.kind === 'error') return String(it.text || '');
29
+ if (it.kind === 'tool') return [it.tool, it.target, it.summary || it.result || it.text, it.status].filter(Boolean).join(' ');
30
+ return '';
31
+ };
32
+
33
+ /** The last assistant answer, else the last tool or notice block, else null. -> { kind: 'answer'|'tool'|'notice', text } */
34
+ export function lastOutput(s) {
35
+ const answers = s?.answers || [];
36
+ for (let i = answers.length - 1; i >= 0; i--) if (answers[i].text?.trim()) return { kind: 'answer', text: answers[i].text };
37
+ const all = [...(s?.history || []), ...(s?.blocks || [])];
38
+ for (let i = all.length - 1; i >= 0; i--) {
39
+ const it = all[i], t = itemText(it).trim();
40
+ if (!t || it.kind === 'user') continue;
41
+ if (it.kind === 'tool' || it.kind === 'error' || it.kind === 'note') return { kind: it.kind === 'tool' ? 'tool' : 'notice', text: t };
42
+ }
43
+ return null;
44
+ }
45
+
46
+ /** Parse the /dragon argument line -> { mode: 'pick'|'fire'|'idle'|'hero'|'explain'|'ask'|'sleep'|'fly', question? } | null (usage). */
47
+ export function parseDragonArg(restArg) {
48
+ const t = String(restArg || '').trim();
49
+ if (!t) return { mode: 'pick' };
50
+ const [w, ...rest] = t.split(/\s+/);
51
+ switch (w.toLowerCase()) {
52
+ case 'fire': return rest.length ? null : { mode: 'fire' };
53
+ case 'classic': return rest.length ? null : { mode: 'idle' };
54
+ case 'hero': return rest.length ? null : { mode: 'hero' };
55
+ // `/dragon explain <thing>` is a question about that thing (owner 2026-10-15: it used to print usage).
56
+ case 'explain': return rest.length ? { mode: 'ask', question: rest.join(' ').trim() } : { mode: 'explain' };
57
+ case 'sleep': return rest.length ? null : { mode: 'sleep' };
58
+ case 'fly': return rest.length ? null : { mode: 'fly' };
59
+ case 'ask': return { mode: 'ask', question: rest.join(' ').trim() };
60
+ // Anything else is a question for the dragon, never a usage error.
61
+ default: return { mode: 'ask', question: t };
62
+ }
63
+ }
64
+
65
+ // ---- sleep: katakana veil ---------------------------------------------------------------------------------
66
+ export const VEIL_IN_MS = 700; // text drops into katakana, left to right
67
+ export const VEIL_STEP_MS = 700; // the noise re-rolls this slowly (low frame rate; a shimmer, not a flicker)
68
+ export const WAKE_MS = Math.round(revealSpan(TIMING.row) * 1000); // the existing decode reveal, run forward
69
+
70
+ const isText = (ch) => /^[\p{L}\p{N}\p{P}\p{S}]+$/u.test(ch);
71
+ const kana = (i, k, salt) => SCRAMBLE_GLYPHS[Math.floor(hash3(i, k, salt) * SCRAMBLE_GLYPHS.length)];
72
+
73
+ /**
74
+ * One source line as veil cells at `ms` since sleep began (phase 'in' then 'asleep') or since wake began
75
+ * (phase 'wake'). Cells are { ch, kind: 'kana'|'plain'|'blank'|'glow', g }. Width of every column is preserved
76
+ * (a 2-wide char becomes two kana), so rows never change length. still: no re-rolling.
77
+ */
78
+ export function veilRow(text, ms, { phase = 'asleep', still = false, salt = 1, row = 0 } = {}) {
79
+ if (phase === 'wake') return revealCells(text, ms / 1000, TIMING.row, { salt: salt + row }).map((c) => ({ ...c }));
80
+ const gs = graphemes(String(text ?? '')).map((g) => g.text);
81
+ const n = gs.length, bucket = still ? 0 : Math.floor(ms / VEIL_STEP_MS);
82
+ const edge = phase === 'in' && !still ? (ms / VEIL_IN_MS) * n : Infinity; // cells left of the edge are veiled
83
+ const out = [];
84
+ gs.forEach((ch, i) => {
85
+ const w = stringWidth(ch);
86
+ if (w === 0) return;
87
+ if (ch === ' ' || !isText(ch) || i > edge) { out.push({ ch, kind: 'plain', g: 0 }); return; }
88
+ for (let k = 0; k < w; k++) out.push({ ch: kana(i * 2 + k + row * 131, bucket, salt), kind: 'kana', g: hash3(i, bucket + 7, salt) });
89
+ });
90
+ return out;
91
+ }
92
+
93
+ export const veilText = (cells) => cells.map((c) => c.ch).join('');
94
+ export const isVeiled = (cells) => cells.some((c) => c.kind === 'kana');
95
+
96
+ /** The visible text the screen shows, as at most `rows` lines wrapped to `cols` (tail of the transcript). */
97
+ export function sourceLines(s, cols, rows) {
98
+ const all = [...(s?.history || []), ...(s?.blocks || [])];
99
+ const lines = [];
100
+ for (let i = all.length - 1; i >= 0 && lines.length < rows; i--) {
101
+ const it = all[i];
102
+ const t = it.kind === 'user' ? `> ${it.text || ''}` : itemText(it);
103
+ if (!t.trim()) continue;
104
+ const wrapped = [];
105
+ for (const raw of t.split('\n')) {
106
+ let r = raw;
107
+ if (!r) { wrapped.push(''); continue; }
108
+ while (stringWidth(r) > cols) { let cut = cols; while (cut > 1 && stringWidth(r.slice(0, cut)) > cols) cut--; wrapped.push(r.slice(0, cut)); r = r.slice(cut); }
109
+ wrapped.push(r);
110
+ }
111
+ lines.unshift(...wrapped);
112
+ }
113
+ return lines.slice(-rows);
114
+ }
115
+
116
+ // ---- the sleep screen -----------------------------------------------------------------------------------------
117
+ export const SLEEP_HINT = 'asleep · any key wakes · /back when you return';
118
+ const VEIL_RGB = [129, 140, 248], HINT_RGB = [186, 230, 253];
119
+
120
+ /**
121
+ * The whole sleep frame as rows of { ch, rgb } cells, `rows` tall and `cols` wide. ms = since sleep began, or
122
+ * since wake began when wake is true (text decodes back, the dragon is gone). Pure: no transcript access, the
123
+ * caller passes the source lines. still (reduced motion): a static veil and a still dragon. mono: no colour.
124
+ */
125
+ export function composeSleep({ lines, cols, rows, ms = 0, wake = false, still = false, mono = false, theme = 'dark', size }) {
126
+ const phase = wake ? 'wake' : ms < VEIL_IN_MS && !still ? 'in' : 'asleep';
127
+ const col = (c) => (mono ? null : c);
128
+ const grid = Array.from({ length: rows }, () => Array.from({ length: cols }, () => ({ ch: ' ', rgb: null })));
129
+ const body = wake ? rows : rows - 1; // the last row holds the wake hint while asleep
130
+ const src = lines.slice(-body);
131
+ const top = body - src.length;
132
+ src.forEach((line, i) => {
133
+ veilRow(line, ms, { phase, still, row: i }).slice(0, cols).forEach((c, x) => {
134
+ grid[top + i][x] = { ch: c.ch, rgb: c.kind === 'kana' ? col(VEIL_RGB) : null, bold: c.kind === 'glow' && c.g > 0.5 };
135
+ });
136
+ });
137
+ if (!wake) {
138
+ const sz = size ?? (rows >= 32 && cols >= 64 ? undefined : 'mid');
139
+ const dcols = Math.min(cols, sz === 'mid' || cols < 64 ? 44 : 72);
140
+ const dc = sleepCells(ms, dcols, undefined, { theme, mono, still, size: sz });
141
+ const x0 = Math.max(0, Math.floor((cols - dcols) / 2)), y0 = Math.max(0, Math.floor((rows - 1 - dc.length) / 2));
142
+ dc.forEach((r, i) => {
143
+ if (y0 + i >= rows - 1) return;
144
+ r.forEach((c, x) => { if (x0 + x < cols) grid[y0 + i][x0 + x] = { ch: c.ch, rgb: mono ? null : c.rgb, bg: c.bg || undefined }; });
145
+ });
146
+ const hint = [...SLEEP_HINT], hx = Math.max(0, Math.floor((cols - hint.length) / 2));
147
+ hint.forEach((ch, i) => { if (hx + i < cols) grid[rows - 1][hx + i] = { ch, rgb: col(HINT_RGB) }; });
148
+ }
149
+ return grid;
150
+ }
@@ -0,0 +1,41 @@
1
+ /** Ink views for /dragon explain|ask (the talking dragon) and /dragon sleep (the screensaver). Frames come from dragonModes.js. */
2
+ import React from 'react';
3
+ import { Box, Text } from 'ink';
4
+ import { cellNodes } from './qmotion.js';
5
+ import { composeSleep } from './dragonModes.js';
6
+ import { pickCells } from './qdragonScenes.js';
7
+ import { flyFrame, flyCols } from './qdragonFly.js';
8
+ import { mono, isLight, clip } from './theme.js';
9
+ import { useFrame } from './motion/frame.js';
10
+
11
+ const h = React.createElement;
12
+
13
+ /** The sleep screen: the whole live region while asleep (and for the decode on wake). Reads the clock itself. */
14
+ export function SleepScreen({ lines, cols, rows, startedAt, wakeAt = null, still = false }) {
15
+ useFrame();
16
+ const now = Date.now();
17
+ const wake = wakeAt != null;
18
+ const ms = wake ? now - wakeAt : now - startedAt;
19
+ const grid = composeSleep({ lines, cols, rows, ms, wake, still, mono: mono(), theme: isLight() ? 'light' : 'dark' });
20
+ return h(Box, { flexDirection: 'column' }, ...grid.map((r, k) => h(Text, { key: k, wrap: 'truncate' }, ...cellNodes(r, `s${k}-`))));
21
+ }
22
+
23
+ /** The compact dragon beside an explain/ask answer: the mouth works while text streams, then it rests with idle eyes. */
24
+ export function DragonTalk({ cols, label, talking, since, still = false }) {
25
+ useFrame();
26
+ const dcols = Math.min(cols, 44);
27
+ const t = Date.now() - since;
28
+ const cells = pickCells(t, dcols, undefined, { theme: isLight() ? 'light' : 'dark', mono: mono(), still: still || !talking, talk: talking && !still, size: 'mid', mouthSide: 'right' });
29
+ return h(Box, { flexDirection: 'column', marginTop: 1 },
30
+ ...cells.map((row, k) => h(Text, { key: k, wrap: 'truncate' }, ...cellNodes(row, `t${k}-`))),
31
+ h(Text, null, clip(label, Math.max(10, cols - 2))));
32
+ }
33
+
34
+ /** /dragon-fly: one pass of the dragon in flight across the live region (qdragonFly.js). `still`: a single frame, no motion. */
35
+ export function FlyLive({ cols, rows, startedAt, still = false }) {
36
+ useFrame();
37
+ const c = flyCols(cols);
38
+ const cells = flyFrame(Date.now() - startedAt, c, { still, mono: mono(), theme: isLight() ? 'light' : 'dark', termRows: rows });
39
+ return h(Box, { flexDirection: 'column', marginTop: 1 },
40
+ ...cells.map((row, k) => h(Text, { key: k, wrap: 'truncate' }, ...cellNodes(row, `f${k}-`))));
41
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Keys typed before the app is ready (R3 audit D4). bin/quox.js calls this before it loads React, Ink or any
3
+ * command module, so the tty is raw (no cooked echo) and every key is kept for the composer. main() calls it
4
+ * again and gets the same capture. Tiny on purpose: it must not import anything heavy.
5
+ *
6
+ * A line typed while the tty was still cooked reaches us when raw mode turns on, with the kernel's ICRNL
7
+ * having turned its Enter into LF; that first read is mapped back to CR so the Enter submits as typed.
8
+ */
9
+ import { PASTE_ON, PASTE_OFF } from './keys.js';
10
+
11
+ const COOKED_MS = 50; // the read that drains the cooked line buffer arrives right after raw mode turns on
12
+ let shared = null;
13
+
14
+ export function captureEarlyInput(stdin = process.stdin, stdout = process.stdout) {
15
+ const own = stdin === process.stdin;
16
+ if (own && shared) return shared;
17
+ if (!stdin?.isTTY) return null;
18
+ const chunks = [];
19
+ const t0 = Date.now();
20
+ const fn = (d) => {
21
+ const s = typeof d === 'string' ? d : d.toString('utf8');
22
+ chunks.push(Date.now() - t0 < COOKED_MS ? s.replace(/\n/g, '\r') : s);
23
+ };
24
+ try { stdin.setRawMode?.(true); stdin.resume?.(); } catch { /* not a tty after all */ }
25
+ stdin.on('data', fn);
26
+ if (stdout?.isTTY) stdout.write(PASTE_ON);
27
+ const cap = {
28
+ chunks,
29
+ detach: () => stdin.off('data', fn),
30
+ /** Nothing will take the terminal over (help, a flag error): give it back as it was. */
31
+ release: () => {
32
+ stdin.off('data', fn);
33
+ try { stdin.setRawMode?.(false); stdin.pause?.(); } catch { /* ignore */ }
34
+ if (stdout?.isTTY) stdout.write(PASTE_OFF);
35
+ if (own) shared = null;
36
+ }
37
+ };
38
+ if (own) shared = cap;
39
+ return cap;
40
+ }
@@ -0,0 +1,15 @@
1
+ // Echo of a command the human typed, shown in the scrollback like a prompt line (wrapped in full, secrets masked).
2
+ // Owner 2026-10-15: "why truncated": the echo wraps like any prompt; only a runaway paste is capped.
3
+ import { redactSecrets } from './slotChat.js';
4
+ import { clip } from './theme.js';
5
+
6
+ const PIN_CMD = /^\/(authenticate|authorise|authorize)(\s|$)/i;
7
+
8
+ /** -> { shown, full }: `shown` is the whole command on one logical line (the view wraps it; capped at ECHO_CAP), `full` is the masked text the transcript records. */
9
+ export const ECHO_CAP = 2000;
10
+ export function echoLine(text, { cols = 100 } = {}) {
11
+ let t = String(text ?? '').trim();
12
+ if (PIN_CMD.test(t)) t = t.split(/\s+/)[0]; // a stray argument may be a PIN: never shown
13
+ const full = redactSecrets(t).text;
14
+ return { shown: clip(full.replace(/\s*\n\s*/g, ' '), ECHO_CAP), full };
15
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The launch Easter egg (CLI-QUOX). On launch the v8 dragon greets you (googly eyes open, blink, smile), rarely:
3
+ * 1 in EGG_ODDS launches, never twice in a row, never in --print, under reduced motion or off a TTY.
4
+ * /dragon plays it on demand, and the cinematic motion level always may.
5
+ *
6
+ * pickLaunchEgg is pure; launchEgg adds the one bit of persistence (did the last launch show the eye?) in
7
+ * ~/.config/quox/motion.json. QUOX_EGG=eye forces it (demos, captures); QUOX_EGG=off disables it.
8
+ */
9
+ import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
10
+ import { join, dirname } from 'node:path';
11
+ import { homedir } from 'node:os';
12
+
13
+ export const EGG_ODDS = 20;
14
+
15
+ /** Pure decision. */
16
+ export function pickLaunchEgg({ rand = Math.random, lastWasEye = false, print = false, reduced = false, tty = true, force = null } = {}) {
17
+ if (print || reduced || !tty) return false;
18
+ if (force === 'off') return false;
19
+ if (force === 'eye') return true;
20
+ if (lastWasEye) return false;
21
+ return rand() < 1 / EGG_ODDS;
22
+ }
23
+
24
+ export const eggStatePath = (env = process.env) => join(env.XDG_CONFIG_HOME || join(homedir(), '.config'), 'quox', 'motion.json');
25
+
26
+ /** Decide once for this launch and remember the outcome. Never throws: an unreadable file means "no eye last time". */
27
+ export function launchEgg({ env = process.env, tty = Boolean(process.stdout?.isTTY), print = false, rand = Math.random, path = eggStatePath(env) } = {}) {
28
+ let last = false;
29
+ try { last = Boolean(JSON.parse(readFileSync(path, 'utf8')).lastEye); } catch { /* first launch */ }
30
+ const reduced = env.QUOX_REDUCED_MOTION === '1' || Boolean(env.QUOX_TUI_LITE);
31
+ const eye = pickLaunchEgg({ rand, lastWasEye: last, print, reduced, tty, force: env.QUOX_EGG || null });
32
+ if (!print && tty) {
33
+ try { mkdirSync(dirname(path), { recursive: true }); writeFileSync(path, JSON.stringify({ lastEye: eye }) + '\n'); } catch { /* read-only home: fine */ }
34
+ }
35
+ return eye;
36
+ }