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,173 @@
1
+ /**
2
+ * Inbox / HITL commands: list, get, respond
3
+ */
4
+
5
+ import { formatOutput, formatDetail, printSuccess } from '../core/output.js';
6
+ import { resolveOrgId } from './helpers.js';
7
+ import { resolveEndpoint } from '../api/endpoints.js';
8
+ import { attachWalkthrough } from './walkthrough.js';
9
+ import { getApprovalContext, formatApprovalContext, approvalListColumns } from '../core/approvalContext.js';
10
+ import { QuoxUserError } from '../core/errors.js';
11
+ import { resolutionFromItem, alreadyResolvedError } from '../core/inboxResolution.js';
12
+ import chalk from 'chalk';
13
+
14
+ export function registerInboxCommands(program, ctx) {
15
+ const { client, auth } = ctx;
16
+
17
+ // An agent hands back a tool approvalId (tool_approvals.approval_id), stored on the card as
18
+ // aee_correlation_id. The server now resolves it on GET and respond (CLI-ERRORS); this client-side
19
+ // scan stays as the fallback for an older server. A failed scan is reported, never read as "no card".
20
+ async function findByApprovalId(orgId, id) {
21
+ const list = resolveEndpoint('inbox.list', { orgId });
22
+ const data = await client.get(list.path, { service: list.service, query: { status: 'all', kind: 'approval', limit: 200 } });
23
+ const items = (data && (data.items || data)) || [];
24
+ const hit = Array.isArray(items) && items.find((it) => it.aee_correlation_id === id || (it.payload && it.payload.approval_id === id));
25
+ return hit ? hit.id : null;
26
+ }
27
+
28
+ function notFound(id, cause) {
29
+ const err = new QuoxUserError(`No inbox item or approval with id ${id} in this org, open or resolved.`, {
30
+ next: "if it came from another org, switch with `quox org switch <org>`; `quox inbox list --status all` lists this org's items.",
31
+ exitCode: 5, code: 'not_found', status: 404, body: cause?.body,
32
+ });
33
+ return err;
34
+ }
35
+
36
+ async function resolveItemId(orgId, id) {
37
+ const direct = resolveEndpoint('inbox.get', { orgId, itemId: id });
38
+ try {
39
+ const data = await client.get(direct.path, { service: direct.service });
40
+ // the server resolves an approvalId to its card; post to the card's own id
41
+ return (data && data.item && data.item.id) || id;
42
+ } catch (err) {
43
+ if (!err || err.status !== 404) throw err;
44
+ const hit = await findByApprovalId(orgId, id);
45
+ if (hit) return hit;
46
+ throw notFound(id, err);
47
+ }
48
+ }
49
+
50
+ const inbox = program
51
+ .command('inbox')
52
+ .description('Manage inbox and approval requests');
53
+ attachWalkthrough(inbox, ctx, program);
54
+
55
+ inbox
56
+ .command('list')
57
+ .description('List inbox items')
58
+ .option('--status <status>', 'filter: one status, a comma list (resolved,cancelled,expired), or all (includes answered approvals). Default: active only')
59
+ .option('--decision <decision>', 'with resolved/all: approved or rejected')
60
+ .option('--page <n>', 'page number (newest first)')
61
+ .option('--priority <priority>', 'filter: low, normal, high, urgent')
62
+ .option('--awaiting-human', 'org-wide: approvals waiting for a human (see-only, cannot act)')
63
+ .option('--limit <n>', 'max results', '50')
64
+ .action(async (options) => {
65
+ auth.requireAuth();
66
+ const orgId = resolveOrgId(auth, program);
67
+ const query = { limit: options.limit };
68
+ if (options.status) query.status = options.status;
69
+ if (options.decision) query.decision = options.decision;
70
+ if (options.page) query.page = options.page;
71
+ if (options.priority) query.priority = options.priority;
72
+ if (options.awaitingHuman) query.awaiting_human = 'true';
73
+ const data = await client.get(resolveEndpoint('inbox.list', { orgId }).path, { service: resolveEndpoint('inbox.list', { orgId }).service, query });
74
+ // HITL-CONTEXT: Source + Reason columns from payload.approval_context so a
75
+ // stale approval still says who asked and why without opening it.
76
+ const items = (data.items || data || []).map((it) => ({ ...it, ...approvalListColumns(it) }));
77
+ formatOutput({
78
+ columns: ['id', 'kind', 'priority', 'title', 'source', 'reason', 'status', 'created_at'],
79
+ headers: ['ID', 'Kind', 'Priority', 'Title', 'Source', 'Reason', 'Status', 'Created'],
80
+ rows: items,
81
+ }, { format: program.opts().output });
82
+ });
83
+
84
+ inbox
85
+ .command('get')
86
+ .alias('show')
87
+ .description('Get inbox item details (alias: show), including the approval context: source, on behalf of, reason, method, why approval')
88
+ .argument('<itemId>', 'inbox item ID, or a tool approvalId from an agent')
89
+ .action(async (givenId) => {
90
+ auth.requireAuth();
91
+ const orgId = resolveOrgId(auth, program);
92
+ const itemId = await resolveItemId(orgId, givenId);
93
+ const data = await client.get(resolveEndpoint('inbox.get', { orgId, itemId }).path, { service: resolveEndpoint('inbox.get', { orgId, itemId }).service });
94
+ const item = data.item || data;
95
+ const format = program.opts().output;
96
+ const context = getApprovalContext(item);
97
+ if (context && format !== 'json') {
98
+ // Lead with the context block: it is what a human needs to decide.
99
+ console.log(formatApprovalContext(context));
100
+ console.log('');
101
+ const { payload, ...rest } = item;
102
+ const { approval_context: _omit, ...payloadRest } = payload || {};
103
+ formatDetail({ ...rest, payload: payloadRest }, { format });
104
+ return;
105
+ }
106
+ formatDetail(item, { format });
107
+ });
108
+
109
+ inbox
110
+ .command('respond')
111
+ .description('Respond to an inbox item')
112
+ .argument('<itemId>', 'inbox item ID, or a tool approvalId from an agent')
113
+ .requiredOption('--action <action>', 'action: approve, reject, defer, resolve')
114
+ .option('--comment <text>', 'response comment')
115
+ .action(async (givenId, options) => {
116
+ auth.requireAuth();
117
+ const orgId = resolveOrgId(auth, program);
118
+ const format = program.opts().output;
119
+ const post = (itemId) => {
120
+ const ep = resolveEndpoint('inbox.respond', { orgId, itemId });
121
+ return client.post(ep.path, { service: ep.service, body: { action: options.action, comment: options.comment } });
122
+ };
123
+ // Resolve an approvalId to its card (server-side on a current server, else the client scan). When
124
+ // this profile cannot see the card, still ask the server: it knows WHY (an agent login, another
125
+ // org, already decided) and says so, where "not found" would hide it.
126
+ let itemId = givenId;
127
+ try { itemId = await resolveItemId(orgId, givenId); } catch (err) { if (err?.code !== 'not_found') throw err; }
128
+ let result;
129
+ try {
130
+ result = await post(itemId);
131
+ } catch (err) {
132
+ if (err?.status === 404) throw notFound(givenId, err);
133
+ if (!result) {
134
+ const resolution = await alreadyResolvedFrom(err, orgId, itemId, options.action);
135
+ if (!resolution) throw err;
136
+ if (!resolution.matches) throw alreadyResolvedError(resolution, err);
137
+ if (format === 'json') console.log(JSON.stringify({ success: true, already_resolved: true, ...resolution }));
138
+ else if (format !== 'quiet') console.log(chalk.green(`✔ ${resolution.message}`));
139
+ return;
140
+ }
141
+ }
142
+ if (result?.item?.status === 'expired') {
143
+ throw new QuoxUserError(result.message || 'This approval had expired, so nothing ran.', {
144
+ next: 're-run the original command to ask for a fresh approval.', exitCode: 1, code: 'approval_expired',
145
+ });
146
+ }
147
+ const PAST = { approve: 'approved', reject: 'rejected', deny: 'denied', defer: 'deferred', resolve: 'resolved', answer: 'answered' };
148
+ printSuccess(`Item ${PAST[options.action] || `${options.action} recorded`}.`);
149
+ });
150
+
151
+ // A respond on a closed card: the server's structured answer, else (older server) read the card.
152
+ async function alreadyResolvedFrom(err, orgId, givenId, action) {
153
+ if (!err || err.status !== 400) return null;
154
+ const body = err.body || {};
155
+ if (body.code === 'already_resolved' && body.resolution) return { ...body.resolution, message: body.message };
156
+ if (!/not open for response/i.test(`${body.error || ''} ${err.message || ''}`)) return null;
157
+ try {
158
+ const ep = resolveEndpoint('inbox.get', { orgId, itemId: givenId });
159
+ const data = await client.get(ep.path, { service: ep.service });
160
+ return resolutionFromItem(data.item || data, action);
161
+ } catch { return null; }
162
+ }
163
+
164
+ inbox
165
+ .command('stats')
166
+ .description('Show inbox statistics')
167
+ .action(async () => {
168
+ auth.requireAuth();
169
+ const orgId = resolveOrgId(auth, program);
170
+ const data = await client.get(resolveEndpoint('inbox.stats.list', { orgId }).path, { service: resolveEndpoint('inbox.stats.list', { orgId }).service });
171
+ formatDetail(data.stats || data, { format: program.opts().output, title: 'Inbox Stats' });
172
+ });
173
+ }
@@ -0,0 +1,264 @@
1
+ /**
2
+ * `quox instagram` — Instagram plugin verbs, IG-3 (facebook CLI parity).
3
+ *
4
+ * quox instagram publish "<caption>" --account <ig_user_id> (--image <https url> | --video <https url>) [--reel]
5
+ * quox instagram accounts [--page <page_id>]
6
+ * quox instagram media --account <ig_user_id> [--limit <n>]
7
+ * quox instagram insights (--media <media_id> | --account <ig_user_id>) [--metrics <a,b,c>] [--period <period>]
8
+ * quox instagram comments --media <media_id> [--limit <n>]
9
+ * quox instagram reply <comment_id> "<message>"
10
+ * quox instagram quota --account <ig_user_id>
11
+ *
12
+ * The write verbs (publish, reply) execute the instagram connector tool
13
+ * through the governed collector endpoint (POST /api/v1/tools/execute ->
14
+ * connector bridge). The bridge gates them on requiresApproval: it files an
15
+ * owner approval card and returns immediately with
16
+ * { pending:true, status:'awaiting_approval', approvalId, inbox_item_id }.
17
+ * The actual Meta Graph API write (create-container -> poll -> publish, or
18
+ * the comment reply) only happens once the owner approves via the dashboard
19
+ * inbox or `quox inbox respond <id> --action approve`.
20
+ * Reads (accounts, media, insights, comments, quota) execute directly.
21
+ *
22
+ * Instagram is its own plugin on the SAME shared 'meta' vault credential as
23
+ * facebook_pages; there is no separate Instagram credential to configure.
24
+ */
25
+
26
+ import { formatDetail, printSuccess, printInfo } from '../core/output.js';
27
+ import { resolveEndpoint } from '../api/endpoints.js';
28
+ import { resolveOrgId } from './helpers.js';
29
+
30
+ /**
31
+ * Execute one instagram connector tool via the governed collector endpoint.
32
+ * A pending-approval response is a SUCCESS shape here (the card was filed);
33
+ * only a non-pending success:false is an error.
34
+ */
35
+ async function executeInstagramTool({ client, auth, program }, toolName, input) {
36
+ auth.requireAuth();
37
+ const orgId = resolveOrgId(auth, program);
38
+ const ep = resolveEndpoint('v1.tools.execute');
39
+ const body = { tool_name: toolName, input, org_id: orgId };
40
+ const data = await client.post(ep.path, { service: ep.service, body });
41
+ if (data && data.success === false && !data.pending) {
42
+ throw new Error(`${toolName} via POST ${ep.path} returned success:false: ${data.error || 'unknown error'}`);
43
+ }
44
+ return data;
45
+ }
46
+
47
+ function printAwaitingApproval(action, data) {
48
+ const itemRef = data.inbox_item_id || data.approvalId || 'unknown';
49
+ printSuccess(`${action} filed for owner approval - inbox item ${itemRef} (awaiting approval). Nothing publishes until an approver says yes.`);
50
+ if (data.inbox_item_id) {
51
+ printInfo(`Review and approve: quox inbox get ${data.inbox_item_id} (or: quox inbox respond ${data.inbox_item_id} --action approve)`);
52
+ }
53
+ }
54
+
55
+ export function registerInstagramCommands(program, ctx) {
56
+ const { client, auth } = ctx;
57
+
58
+ const instagram = program
59
+ .command('instagram')
60
+ .description('Instagram publishing and monitoring (organic): governed, HITL-approved via HITL Inbox, on the shared Meta credential');
61
+
62
+ // ── instagram publish ────────────────────────────────────────────────────
63
+
64
+ instagram
65
+ .command('publish')
66
+ .description('Publish a single image, video, or reel to an Instagram account. Files an owner approval card and returns immediately; never publishes directly.')
67
+ .argument('[caption]', 'post caption (optional)')
68
+ .requiredOption('--account <ig_user_id>', 'Instagram professional account ID (from `quox instagram accounts`)')
69
+ .option('--image <url>', 'https URL of an image to publish (exactly one of --image/--video is required)')
70
+ .option('--video <url>', 'https URL of a video to publish (exactly one of --image/--video is required)')
71
+ .option('--reel', 'publish the video as a reel (only valid with --video)')
72
+ .action(async (caption, options) => {
73
+ if (!options.image && !options.video) {
74
+ throw new Error('instagram publish requires exactly one of --image or --video');
75
+ }
76
+ if (options.image && options.video) {
77
+ throw new Error('instagram publish accepts exactly one of --image or --video, not both');
78
+ }
79
+ if (options.reel && !options.video) {
80
+ throw new Error('--reel is only valid with --video');
81
+ }
82
+
83
+ const input = { ig_user_id: options.account };
84
+ if (caption) input.caption = caption;
85
+ if (options.image) {
86
+ input.image_url = options.image;
87
+ input.media_type = 'IMAGE';
88
+ } else {
89
+ input.video_url = options.video;
90
+ input.media_type = options.reel ? 'REELS' : 'VIDEO';
91
+ }
92
+
93
+ const data = await executeInstagramTool({ client, auth, program }, 'instagram_publish_media', input);
94
+
95
+ if (program.opts().output === 'json') {
96
+ formatDetail(data, { format: 'json' });
97
+ return;
98
+ }
99
+ printAwaitingApproval('Publish', data);
100
+ });
101
+
102
+ // ── instagram accounts (discover, read) ──────────────────────────────────
103
+
104
+ instagram
105
+ .command('accounts')
106
+ .description('Discover the Instagram professional account linked to a Facebook Page (read-only, no approval needed).')
107
+ .option('--page <page_id>', 'Facebook Page ID to resolve (optional; checks every Page this token can manage when omitted)')
108
+ .action(async (options) => {
109
+ const input = {};
110
+ if (options.page) input.page_id = options.page;
111
+ const data = await executeInstagramTool({ client, auth, program }, 'instagram_discover_account', input);
112
+
113
+ if (program.opts().output === 'json') {
114
+ formatDetail(data, { format: 'json' });
115
+ return;
116
+ }
117
+ const result = data.result || {};
118
+ if (!result.ig_user_id) {
119
+ printInfo('No Instagram account resolved.');
120
+ return;
121
+ }
122
+ console.log(`${result.ig_user_id} @${result.username || 'unknown'} linked page: ${result.linked_page?.name || result.linked_page?.id || 'unknown'}`);
123
+ });
124
+
125
+ // ── instagram media (read) ───────────────────────────────────────────────
126
+
127
+ instagram
128
+ .command('media')
129
+ .description('List recent media on an Instagram account (read-only, no approval needed).')
130
+ .requiredOption('--account <ig_user_id>', 'Instagram professional account ID')
131
+ .option('--limit <n>', 'max media items to return (max 50)', '10')
132
+ .action(async (options) => {
133
+ const limit = Math.min(parseInt(options.limit, 10) || 10, 50);
134
+ const data = await executeInstagramTool({ client, auth, program }, 'instagram_list_media', {
135
+ ig_user_id: options.account,
136
+ limit,
137
+ });
138
+
139
+ if (program.opts().output === 'json') {
140
+ formatDetail(data, { format: 'json' });
141
+ return;
142
+ }
143
+ const media = data.result || [];
144
+ if (media.length === 0) {
145
+ printInfo('No media returned.');
146
+ return;
147
+ }
148
+ for (const m of media) {
149
+ console.log(`${m.id} ${m.media_type || ''} ${m.timestamp || ''}`);
150
+ console.log(` ${String(m.caption || '').replace(/\n/g, '\n ')}`);
151
+ }
152
+ });
153
+
154
+ // ── instagram insights (read) ────────────────────────────────────────────
155
+
156
+ instagram
157
+ .command('insights')
158
+ .description('Show media or account insights (reach, saved, likes, comments, shares, views, follower_count).')
159
+ .option('--media <media_id>', 'Instagram media ID (media-level insights)')
160
+ .option('--account <ig_user_id>', 'Instagram professional account ID (account-level insights)')
161
+ .option('--metrics <metrics>', 'comma-separated metric names')
162
+ .option('--period <period>', 'day|week|days_28|lifetime (account-level only)')
163
+ .action(async (options) => {
164
+ if (!options.media && !options.account) {
165
+ throw new Error('instagram insights requires exactly one of --media or --account');
166
+ }
167
+ if (options.media && options.account) {
168
+ throw new Error('instagram insights accepts exactly one of --media or --account, not both');
169
+ }
170
+
171
+ let data;
172
+ if (options.media) {
173
+ const input = { media_id: options.media };
174
+ if (options.metrics) input.metrics = options.metrics;
175
+ data = await executeInstagramTool({ client, auth, program }, 'instagram_get_media_insights', input);
176
+ } else {
177
+ const input = { ig_user_id: options.account };
178
+ if (options.metrics) input.metrics = options.metrics;
179
+ if (options.period) input.period = options.period;
180
+ data = await executeInstagramTool({ client, auth, program }, 'instagram_get_account_insights', input);
181
+ }
182
+
183
+ if (program.opts().output === 'json') {
184
+ formatDetail(data, { format: 'json' });
185
+ return;
186
+ }
187
+ const series = data.result || [];
188
+ if (series.length === 0) {
189
+ printInfo('No insights returned.');
190
+ return;
191
+ }
192
+ for (const m of series) {
193
+ const latest = (m.values || [])[m.values.length - 1];
194
+ console.log(`${m.title || m.name}: ${latest ? JSON.stringify(latest.value) : 'unknown'}`);
195
+ }
196
+ });
197
+
198
+ // ── instagram comments (read) ────────────────────────────────────────────
199
+
200
+ instagram
201
+ .command('comments')
202
+ .description('List comments on an Instagram media item.')
203
+ .requiredOption('--media <media_id>', 'Instagram media ID')
204
+ .option('--limit <n>', 'max comments to return (max 100)', '25')
205
+ .action(async (options) => {
206
+ const limit = Math.min(parseInt(options.limit, 10) || 25, 100);
207
+ const data = await executeInstagramTool({ client, auth, program }, 'instagram_get_comments', {
208
+ media_id: options.media,
209
+ limit,
210
+ });
211
+
212
+ if (program.opts().output === 'json') {
213
+ formatDetail(data, { format: 'json' });
214
+ return;
215
+ }
216
+ const comments = data.result || [];
217
+ if (comments.length === 0) {
218
+ printInfo('No comments returned.');
219
+ return;
220
+ }
221
+ for (const c of comments) {
222
+ console.log(`${c.id} ${c.username || 'unknown'} ${c.timestamp || ''}`);
223
+ console.log(` ${String(c.text || '').replace(/\n/g, '\n ')}`);
224
+ }
225
+ });
226
+
227
+ // ── instagram reply ──────────────────────────────────────────────────────
228
+
229
+ instagram
230
+ .command('reply')
231
+ .description('Reply to a comment on an Instagram media item. Files an owner approval card and returns immediately; never replies directly.')
232
+ .argument('<comment_id>', 'Instagram comment ID to reply to')
233
+ .argument('<message>', 'reply text')
234
+ .action(async (commentId, message) => {
235
+ const data = await executeInstagramTool({ client, auth, program }, 'instagram_reply_comment', { comment_id: commentId, message });
236
+
237
+ if (program.opts().output === 'json') {
238
+ formatDetail(data, { format: 'json' });
239
+ return;
240
+ }
241
+ printAwaitingApproval('Reply', data);
242
+ });
243
+
244
+ // ── instagram quota (read) ───────────────────────────────────────────────
245
+
246
+ instagram
247
+ .command('quota')
248
+ .description('Show the rolling 24-hour publishing quota for an Instagram account (hard cap: 100 API-published posts).')
249
+ .requiredOption('--account <ig_user_id>', 'Instagram professional account ID')
250
+ .action(async (options) => {
251
+ const data = await executeInstagramTool({ client, auth, program }, 'instagram_get_publishing_limit', { ig_user_id: options.account });
252
+
253
+ if (program.opts().output === 'json') {
254
+ formatDetail(data, { format: 'json' });
255
+ return;
256
+ }
257
+ const result = data.result || {};
258
+ if (result.quota_usage == null) {
259
+ printInfo('No quota data returned.');
260
+ return;
261
+ }
262
+ console.log(`${result.quota_usage} / ${result.quota_total ?? 'unknown'} posts used (rolling ${result.quota_duration ? `${Math.round(result.quota_duration / 3600)}h` : '24h'} window)`);
263
+ });
264
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Integration commands — DEPRECATED alias of `quox vault`.
3
+ *
4
+ * VAULT-INTEG P6: this used to be a second, parallel implementation of
5
+ * credential CRUD that could not actually supply secret field values (its
6
+ * `create`/`update` sent a `config` body key the real route
7
+ * (POST/PUT /orgs/:orgId/integrations) never reads — it expects
8
+ * `credentials`). `quox vault` is the one working implementation; every
9
+ * subcommand here just prints a one-line deprecation note to stderr and
10
+ * forwards into the exact same action factories `quox vault` itself wires
11
+ * up (see lib/commands/vault.js `make*Action` exports), so a script that
12
+ * already calls `quox integration ...` keeps working (same HTTP calls, same
13
+ * exit codes) without a second copy of the request/response handling to
14
+ * drift out of sync.
15
+ */
16
+
17
+ import {
18
+ makeVaultListAction,
19
+ makeVaultGetAction,
20
+ makeVaultCreateAction,
21
+ makeVaultUpdateAction,
22
+ makeVaultDeleteAction,
23
+ makeVaultTestAction,
24
+ } from './vault.js';
25
+
26
+ function warnDeprecated(subcommand, replacement) {
27
+ console.error(`quox integration ${subcommand} is deprecated; use \`quox vault ${replacement}\` instead.`);
28
+ }
29
+
30
+ export function registerIntegrationCommands(program, ctx) {
31
+ const integration = program
32
+ .command('integration')
33
+ .description('DEPRECATED: alias of `quox vault` — kept for existing scripts');
34
+
35
+ integration
36
+ .command('list')
37
+ .description('DEPRECATED — alias of `quox vault list`')
38
+ .option('--type <type>', 'filter by integration type')
39
+ .option('--status <status>', 'filter by test status (success|failed|untested)')
40
+ .action(async (options) => {
41
+ warnDeprecated('list', 'list');
42
+ return makeVaultListAction(ctx, program)(options);
43
+ });
44
+
45
+ integration
46
+ .command('get')
47
+ .description('DEPRECATED — alias of `quox vault get`')
48
+ .argument('<integrationId>', 'integration ID')
49
+ .action(async (integrationId) => {
50
+ warnDeprecated('get', 'get');
51
+ return makeVaultGetAction(ctx, program)(integrationId);
52
+ });
53
+
54
+ integration
55
+ .command('create')
56
+ .description('DEPRECATED — alias of `quox vault create`')
57
+ .option('--type <type>', 'integration type (skip prompt)')
58
+ .option('--label <label>', 'display label (skip prompt)')
59
+ .option('--set-default', 'set as default for this type')
60
+ .option('--no-test', 'skip connection test after creation')
61
+ .option('--credentials-file <path>', 'JSON object of {field: value} for the credential fields (use 0600; supports "env:VAR_NAME" values)')
62
+ .option('--credentials-stdin', 'read that same JSON object from stdin (never touches argv or disk)')
63
+ .option('--metadata <json>', 'JSON object of non-secret metadata tags')
64
+ .option('--repos <patterns>', 'repositories this credential covers: comma-separated owner/name, owner/*, or *')
65
+ .option('--no-input', 'never prompt; fail with a clear error if a required field is missing')
66
+ .action(async (options) => {
67
+ warnDeprecated('create', 'create');
68
+ return makeVaultCreateAction(ctx, program)(options);
69
+ });
70
+
71
+ integration
72
+ .command('update')
73
+ .description('DEPRECATED — alias of `quox vault update`')
74
+ .argument('<integrationId>', 'integration ID')
75
+ .option('--label <label>', 'new label')
76
+ .option('--description <desc>', 'new description')
77
+ .action(async (integrationId, options) => {
78
+ warnDeprecated('update', 'update');
79
+ return makeVaultUpdateAction(ctx, program)(integrationId, options);
80
+ });
81
+
82
+ integration
83
+ .command('delete')
84
+ .description('DEPRECATED — alias of `quox vault delete`')
85
+ .argument('<integrationId>', 'integration ID')
86
+ .option('--force', 'skip confirmation')
87
+ .action(async (integrationId, options) => {
88
+ warnDeprecated('delete', 'delete');
89
+ return makeVaultDeleteAction(ctx, program)(integrationId, options);
90
+ });
91
+
92
+ integration
93
+ .command('test')
94
+ .description('DEPRECATED — alias of `quox vault test`')
95
+ .argument('<integrationId>', 'integration ID')
96
+ .action(async (integrationId) => {
97
+ warnDeprecated('test', 'test');
98
+ return makeVaultTestAction(ctx, program)(integrationId);
99
+ });
100
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * `quox inventory` — the org's agent CMDB from the terminal (OPGOV quox#573).
3
+ *
4
+ * Org-wide rollup of the SAME grant graph `quox reach` evaluates per agent:
5
+ * which agents exist (core roster + org-created), their declared model
6
+ * routing, and per agent the granted tools / credentials / hosts / egress /
7
+ * delegation counts plus the least-privilege unused-grant signal. The
8
+ * collector computes it (GET /orgs/:orgId/inventory, witnessed as
9
+ * quox.reach.inventory); this command only renders.
10
+ *
11
+ * Honesty: 'unknown' cells are real values, not absences — a registry or
12
+ * layer that failed to enumerate says so, and `totals.complete` is only true
13
+ * when NOTHING was unknown anywhere. A '?' in the table is a '?'.
14
+ */
15
+
16
+ import { resolveEndpoint } from '../api/endpoints.js';
17
+ import { resolveOrgId } from './helpers.js';
18
+
19
+ function isJsonOutput(program) {
20
+ const o = program.opts();
21
+ return o.json === true || o.output === 'json';
22
+ }
23
+
24
+ function cell(v, width) {
25
+ const s = v === 'unknown' ? '?' : String(v ?? '-');
26
+ return s.padStart(width);
27
+ }
28
+
29
+ export function registerInventoryCommands(program, ctx) {
30
+ const { client, auth } = ctx;
31
+
32
+ program
33
+ .command('inventory')
34
+ .description("Org agent inventory (the agent CMDB): agents, models, tool/credential grants, delegation, unused-grant drift")
35
+ .option('--days <n>', 'observed-usage window for the unused-grant column (default 30)')
36
+ .option('--unused', 'ALSO compute the org-wide unused-grant pass (SLOW: minutes at org scale; for one agent use quox reach unused <agentId>)')
37
+ .option('--drift', 'diff against the last stored snapshot and store this rollup as the new baseline (witnessed as quox.reach.inventory_drift)')
38
+ .action(async (options) => {
39
+ const orgId = resolveOrgId(auth, program);
40
+ if (options.drift === true) {
41
+ const dep = resolveEndpoint('reach.org.inventory.drift', { orgId });
42
+ const result = await client.get(dep.path, { service: dep.service, timeout: 330000 });
43
+ if (!result || result.schema !== 'inventory-drift.v1') {
44
+ throw new Error(`unexpected response (schema ${result?.schema ?? 'missing'}, expected inventory-drift.v1): refusing to render. Check the collector URL points at a real collector.`);
45
+ }
46
+ if (isJsonOutput(program)) {
47
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
48
+ return;
49
+ }
50
+ if (result.baseline) {
51
+ process.stdout.write(`\u{1F4A5} REACH │ inventory drift │ baseline stored (snapshot #${result.snapshot_id}) · nothing to diff yet · re-run after the next change\n`);
52
+ return;
53
+ }
54
+ const d = result.drift || {};
55
+ const summary = d.changed
56
+ ? `+${(d.agents_added || []).length} agents · −${(d.agents_removed || []).length} · ${(d.model_changes || []).length} model · ${(d.reach_changes || []).length} reach · ${(d.visibility_changes || []).length} visibility`
57
+ : 'no change';
58
+ const trust = d.prev_complete && d.curr_complete ? '' : ' · CAUTION: one side of the diff was INCOMPLETE';
59
+ process.stdout.write(`\u{1F4A5} REACH │ inventory drift │ ${summary} · since ${result.prev_taken_at}${trust}\n`);
60
+ for (const a of d.agents_added || []) process.stdout.write(` + ${a.id} (${a.source}${a.model ? `, ${a.model}` : ''})\n`);
61
+ for (const a of d.agents_removed || []) process.stdout.write(` - ${a.id} (${a.source}${a.model ? `, ${a.model}` : ''})\n`);
62
+ for (const m of d.model_changes || []) process.stdout.write(` ~ ${m.id} model ${m.from ?? 'default'} → ${m.to ?? 'default'}\n`);
63
+ for (const r of d.reach_changes || []) {
64
+ const zones = ['tools', 'credentials', 'delegates'].filter((z) => r[z]).map((z) => `${z} ${r[z].from}→${r[z].to}`).join(', ');
65
+ process.stdout.write(` ~ ${r.id} ${zones}\n`);
66
+ }
67
+ for (const v of d.visibility_changes || []) process.stdout.write(` ! ${v.id} ${v.from} → ${v.to}\n`);
68
+ return;
69
+ }
70
+ const ep = resolveEndpoint('reach.org.inventory', {
71
+ orgId,
72
+ days: options.days,
73
+ unused: options.unused === true,
74
+ });
75
+ // The first cold rollup resolves reach for every agent in the org and
76
+ // can take minutes; the collector caches per-agent reach for 10 min so
77
+ // re-runs are fast. 330s ceiling, not the default 30s.
78
+ const result = await client.get(ep.path, { service: ep.service, timeout: 330000 });
79
+ // A 200 with the wrong shape once rendered a confident empty table
80
+ // ("? agents", "undefined unknown") from a non-collector endpoint. A
81
+ // response that is not inventory.v1 is an error, never a rollup.
82
+ if (!result || result.schema !== 'inventory.v1') {
83
+ throw new Error(`unexpected response (schema ${result?.schema ?? 'missing'}, expected inventory.v1): refusing to render. Check the collector URL points at a real collector.`);
84
+ }
85
+
86
+ if (isJsonOutput(program)) {
87
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
88
+ return;
89
+ }
90
+
91
+ const t = result.totals || {};
92
+ const completeness = t.complete ? 'complete' : `INCOMPLETE (${t.agents_reach_unknown} agent(s) unknown, ${(result.unknowns || []).length} registry gap(s))`;
93
+ process.stdout.write(
94
+ `\u{1F4A5} REACH │ inventory │ ${t.agents ?? '?'} agents · ${t.tool_grants ?? '?'} tool grants · ${t.credential_grants ?? '?'} cred grants · ${completeness} · ${result.duration_ms ?? '?'}ms\n\n`
95
+ );
96
+
97
+ const header = `${'agent'.padEnd(22)}${'src'.padEnd(6)}${'model'.padEnd(18)}${cell('tools', 6)}${cell('creds', 6)}${cell('hosts', 6)}${cell('deleg', 6)}${cell('unused', 7)} badge`;
98
+ process.stdout.write(`${header}\n${'─'.repeat(header.length)}\n`);
99
+ for (const a of result.agents || []) {
100
+ const r = a.reach;
101
+ const row = r === 'unknown'
102
+ ? `${a.id.padEnd(22)}${(a.source || '?').padEnd(6)}${(a.model || 'default').padEnd(18)}${cell('unknown', 6)}${cell('?', 6)}${cell('?', 6)}${cell('?', 6)}${cell('?', 7)} reach failed: ${a.reach_error || '?'}`
103
+ : `${a.id.padEnd(22)}${(a.source || '?').padEnd(6)}${(a.model || 'default').padEnd(18)}${cell(r.tools, 6)}${cell(r.credentials, 6)}${cell(r.hosts, 6)}${cell(r.delegates, 6)}${cell(a.unused_grants ?? '-', 7)} ${r.badge?.level || '-'}${(r.unknown_zones || []).length ? ` (?: ${r.unknown_zones.join(',')})` : ''}`;
104
+ process.stdout.write(`${row}\n`);
105
+ }
106
+
107
+ if ((result.unknowns || []).length) {
108
+ process.stdout.write('\nregistry gaps (first-class UNKNOWN, not zero):\n');
109
+ for (const u of result.unknowns) process.stdout.write(` · [${u.source}] ${u.statement}\n`);
110
+ }
111
+ process.stdout.write(`\nunused-grant window: ${result.unused_window_days ?? 'skipped'} days · '?' = source did not enumerate · witnessed as quox.reach.inventory\n`);
112
+ });
113
+ }
114
+
115
+ export default registerInventoryCommands;