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.
- package/LICENSE +35 -0
- package/README.md +144 -2
- package/bin/quox.js +265 -0
- package/bin/quoxon.js +8 -0
- package/lib/api/endpoints/admin.js +151 -0
- package/lib/api/endpoints/aee.js +38 -0
- package/lib/api/endpoints/agent-attach.js +126 -0
- package/lib/api/endpoints/agent-schedules.js +26 -0
- package/lib/api/endpoints/agents.js +63 -0
- package/lib/api/endpoints/assistants.js +62 -0
- package/lib/api/endpoints/audit.js +14 -0
- package/lib/api/endpoints/auth.js +50 -0
- package/lib/api/endpoints/awareness.js +34 -0
- package/lib/api/endpoints/away.js +15 -0
- package/lib/api/endpoints/backup-schedules.js +20 -0
- package/lib/api/endpoints/backups.js +86 -0
- package/lib/api/endpoints/brain.js +140 -0
- package/lib/api/endpoints/budgets.js +62 -0
- package/lib/api/endpoints/calendarq.js +71 -0
- package/lib/api/endpoints/catalog.js +14 -0
- package/lib/api/endpoints/chat.js +61 -0
- package/lib/api/endpoints/consent.js +26 -0
- package/lib/api/endpoints/contactsq.js +68 -0
- package/lib/api/endpoints/conversations.js +46 -0
- package/lib/api/endpoints/custom-roles.js +92 -0
- package/lib/api/endpoints/divisions.js +56 -0
- package/lib/api/endpoints/domains.js +38 -0
- package/lib/api/endpoints/engagement.js +231 -0
- package/lib/api/endpoints/engine.js +11 -0
- package/lib/api/endpoints/entity.js +50 -0
- package/lib/api/endpoints/executions.js +45 -0
- package/lib/api/endpoints/fetchAllowlist.js +27 -0
- package/lib/api/endpoints/file.js +20 -0
- package/lib/api/endpoints/files.js +40 -0
- package/lib/api/endpoints/github.js +21 -0
- package/lib/api/endpoints/governance.js +43 -0
- package/lib/api/endpoints/hat.js +66 -0
- package/lib/api/endpoints/inbox.js +52 -0
- package/lib/api/endpoints/inboxq.js +120 -0
- package/lib/api/endpoints/index.js +242 -0
- package/lib/api/endpoints/invites.js +19 -0
- package/lib/api/endpoints/llm-policy.js +43 -0
- package/lib/api/endpoints/lucid.js +89 -0
- package/lib/api/endpoints/members.js +32 -0
- package/lib/api/endpoints/memory.js +94 -0
- package/lib/api/endpoints/mfa.js +32 -0
- package/lib/api/endpoints/mind.js +13 -0
- package/lib/api/endpoints/mon.js +184 -0
- package/lib/api/endpoints/notesq.js +43 -0
- package/lib/api/endpoints/objectives.js +68 -0
- package/lib/api/endpoints/orgs.js +38 -0
- package/lib/api/endpoints/plugins.js +152 -0
- package/lib/api/endpoints/powers.js +75 -0
- package/lib/api/endpoints/presence.js +33 -0
- package/lib/api/endpoints/prompts.js +69 -0
- package/lib/api/endpoints/qlarity.js +122 -0
- package/lib/api/endpoints/quoxbox.js +55 -0
- package/lib/api/endpoints/quoxchat.js +54 -0
- package/lib/api/endpoints/quoxflow.js +32 -0
- package/lib/api/endpoints/quoxplan.js +121 -0
- package/lib/api/endpoints/quoxseo.js +114 -0
- package/lib/api/endpoints/reach.js +47 -0
- package/lib/api/endpoints/router.js +17 -0
- package/lib/api/endpoints/runs.js +38 -0
- package/lib/api/endpoints/safety.js +53 -0
- package/lib/api/endpoints/scim.js +46 -0
- package/lib/api/endpoints/scopes.js +14 -0
- package/lib/api/endpoints/security.js +69 -0
- package/lib/api/endpoints/setup.js +90 -0
- package/lib/api/endpoints/skills.js +200 -0
- package/lib/api/endpoints/sso.js +67 -0
- package/lib/api/endpoints/stepup.js +20 -0
- package/lib/api/endpoints/tags.js +32 -0
- package/lib/api/endpoints/teams.js +56 -0
- package/lib/api/endpoints/telephony.js +46 -0
- package/lib/api/endpoints/tg.js +56 -0
- package/lib/api/endpoints/tools.js +50 -0
- package/lib/api/endpoints/traces.js +157 -0
- package/lib/api/endpoints/triggers.js +96 -0
- package/lib/api/endpoints/user-library.js +41 -0
- package/lib/api/endpoints/users.js +20 -0
- package/lib/api/endpoints/v1.js +585 -0
- package/lib/api/endpoints/vault.js +192 -0
- package/lib/api/endpoints/voice.js +22 -0
- package/lib/api/endpoints/volt.js +84 -0
- package/lib/api/endpoints/ward.js +47 -0
- package/lib/api/endpoints/webhooks.js +46 -0
- package/lib/api/endpoints/workflows.js +169 -0
- package/lib/api/endpoints/x.js +32 -0
- package/lib/api/endpoints.js +15 -0
- package/lib/commands/actions.js +61 -0
- package/lib/commands/admin.js +375 -0
- package/lib/commands/aee.js +99 -0
- package/lib/commands/agent.js +337 -0
- package/lib/commands/agentAttach.js +1528 -0
- package/lib/commands/approvals.js +119 -0
- package/lib/commands/aside.js +24 -0
- package/lib/commands/ask.js +144 -0
- package/lib/commands/assistant.js +169 -0
- package/lib/commands/auth.js +464 -0
- package/lib/commands/awareness.js +88 -0
- package/lib/commands/backup.js +377 -0
- package/lib/commands/brain.js +1085 -0
- package/lib/commands/budget.js +241 -0
- package/lib/commands/build.js +170 -0
- package/lib/commands/calendar.js +216 -0
- package/lib/commands/capabilities.js +34 -0
- package/lib/commands/chat.js +295 -0
- package/lib/commands/claude.js +380 -0
- package/lib/commands/config-cmd.js +106 -0
- package/lib/commands/consent.js +84 -0
- package/lib/commands/contacts.js +1016 -0
- package/lib/commands/contactsSelftest.js +132 -0
- package/lib/commands/conversation.js +105 -0
- package/lib/commands/dashboard.js +43 -0
- package/lib/commands/department.js +96 -0
- package/lib/commands/dev.js +620 -0
- package/lib/commands/devResident.js +326 -0
- package/lib/commands/devSupervisor.js +1062 -0
- package/lib/commands/discord.js +132 -0
- package/lib/commands/doctor.js +181 -0
- package/lib/commands/domain.js +114 -0
- package/lib/commands/done.js +347 -0
- package/lib/commands/engagement.js +597 -0
- package/lib/commands/entity.js +119 -0
- package/lib/commands/facebook.js +212 -0
- package/lib/commands/fetchAllowlist.js +71 -0
- package/lib/commands/file.js +165 -0
- package/lib/commands/fleet.js +1189 -0
- package/lib/commands/governance.js +647 -0
- package/lib/commands/gripe.js +355 -0
- package/lib/commands/hat.js +374 -0
- package/lib/commands/helpers.js +96 -0
- package/lib/commands/hyperion.js +58 -0
- package/lib/commands/inbox.js +173 -0
- package/lib/commands/instagram.js +264 -0
- package/lib/commands/integration.js +100 -0
- package/lib/commands/inventory.js +115 -0
- package/lib/commands/invites.js +45 -0
- package/lib/commands/licence.js +139 -0
- package/lib/commands/linkedin.js +178 -0
- package/lib/commands/llm-policy.js +117 -0
- package/lib/commands/llm.js +45 -0
- package/lib/commands/lucid.js +597 -0
- package/lib/commands/mail.js +531 -0
- package/lib/commands/memory.js +361 -0
- package/lib/commands/mind.js +71 -0
- package/lib/commands/mon.js +581 -0
- package/lib/commands/monitoring.js +86 -0
- package/lib/commands/motion.js +22 -0
- package/lib/commands/notes.js +1246 -0
- package/lib/commands/notesBatch.js +160 -0
- package/lib/commands/notesBridges.js +56 -0
- package/lib/commands/notesLinks.js +60 -0
- package/lib/commands/notification.js +57 -0
- package/lib/commands/nucleus.js +123 -0
- package/lib/commands/objective.js +240 -0
- package/lib/commands/offload.js +89 -0
- package/lib/commands/onboard.js +329 -0
- package/lib/commands/open.js +56 -0
- package/lib/commands/org.js +276 -0
- package/lib/commands/peek.js +28 -0
- package/lib/commands/plan.js +944 -0
- package/lib/commands/plugin-doctor.js +1091 -0
- package/lib/commands/plugin.js +649 -0
- package/lib/commands/policy.js +78 -0
- package/lib/commands/powers.js +296 -0
- package/lib/commands/presence.js +89 -0
- package/lib/commands/prompt.js +350 -0
- package/lib/commands/provider.js +159 -0
- package/lib/commands/qlarity.js +706 -0
- package/lib/commands/quoxbox.js +270 -0
- package/lib/commands/quoxchat.js +275 -0
- package/lib/commands/quoxseo.js +378 -0
- package/lib/commands/reach.js +159 -0
- package/lib/commands/role.js +286 -0
- package/lib/commands/router.js +77 -0
- package/lib/commands/rows.js +358 -0
- package/lib/commands/run.js +187 -0
- package/lib/commands/safety.js +107 -0
- package/lib/commands/scim.js +88 -0
- package/lib/commands/scope.js +58 -0
- package/lib/commands/security.js +157 -0
- package/lib/commands/server.js +292 -0
- package/lib/commands/service.js +89 -0
- package/lib/commands/settings.js +99 -0
- package/lib/commands/setup.js +569 -0
- package/lib/commands/skillManifest.js +113 -0
- package/lib/commands/skillRightsFormat.js +38 -0
- package/lib/commands/skills.js +687 -0
- package/lib/commands/slot.js +1451 -0
- package/lib/commands/sso.js +229 -0
- package/lib/commands/status.js +137 -0
- package/lib/commands/tag.js +91 -0
- package/lib/commands/team.js +142 -0
- package/lib/commands/tg.js +240 -0
- package/lib/commands/tiktok.js +218 -0
- package/lib/commands/tips.js +23 -0
- package/lib/commands/tool.js +304 -0
- package/lib/commands/trace.js +530 -0
- package/lib/commands/trigger.js +223 -0
- package/lib/commands/update.js +46 -0
- package/lib/commands/vault.js +1447 -0
- package/lib/commands/vm.js +237 -0
- package/lib/commands/voice.js +213 -0
- package/lib/commands/volt.js +570 -0
- package/lib/commands/walkthrough.js +32 -0
- package/lib/commands/watch.js +167 -0
- package/lib/commands/webhook.js +137 -0
- package/lib/commands/welcome.js +14 -0
- package/lib/commands/workflow.js +660 -0
- package/lib/commands/x.js +448 -0
- package/lib/core/actingAs.js +136 -0
- package/lib/core/activeSummary.js +186 -0
- package/lib/core/aee.js +53 -0
- package/lib/core/agentAlias.js +163 -0
- package/lib/core/approvalContext.js +61 -0
- package/lib/core/aside.js +54 -0
- package/lib/core/askDecision.js +60 -0
- package/lib/core/auth.js +501 -0
- package/lib/core/banner.js +143 -0
- package/lib/core/brainPrime.js +90 -0
- package/lib/core/callerSource.js +129 -0
- package/lib/core/claudeLs.js +94 -0
- package/lib/core/cliBuild.js +62 -0
- package/lib/core/client.js +693 -0
- package/lib/core/commandRegistrars.js +121 -0
- package/lib/core/completions.js +163 -0
- package/lib/core/config.js +669 -0
- package/lib/core/confirm.js +37 -0
- package/lib/core/customHats.js +168 -0
- package/lib/core/deeplinks.js +76 -0
- package/lib/core/doneEngineFetch.js +227 -0
- package/lib/core/errors.js +441 -0
- package/lib/core/global-flags.js +190 -0
- package/lib/core/governedSession.js +402 -0
- package/lib/core/hyperion.js +102 -0
- package/lib/core/inboxResolution.js +65 -0
- package/lib/core/lazyCommands.js +122 -0
- package/lib/core/liveSessionsReport.js +112 -0
- package/lib/core/offload.js +504 -0
- package/lib/core/org-override.js +52 -0
- package/lib/core/orgResolve.js +70 -0
- package/lib/core/output.js +239 -0
- package/lib/core/peek.js +126 -0
- package/lib/core/prodEnv.js +7 -0
- package/lib/core/profileUsers.js +51 -0
- package/lib/core/promptCancel.js +18 -0
- package/lib/core/quoxglyph.js +158 -0
- package/lib/core/repoPath.js +11 -0
- package/lib/core/residentAlarm.js +282 -0
- package/lib/core/residentAuth.js +243 -0
- package/lib/core/residentPump.js +229 -0
- package/lib/core/residentSeed.js +106 -0
- package/lib/core/rootOptions.js +39 -0
- package/lib/core/router.js +168 -0
- package/lib/core/selfUpdate.js +188 -0
- package/lib/core/sessionHeartbeat.js +192 -0
- package/lib/core/sessionsOverview.js +224 -0
- package/lib/core/slotKeeper.js +527 -0
- package/lib/core/slotWake.js +120 -0
- package/lib/core/supervisorEngine.js +933 -0
- package/lib/core/systemdInstaller.js +256 -0
- package/lib/core/version.js +87 -0
- package/lib/core/vm.js +361 -0
- package/lib/core/vmTui.js +86 -0
- package/lib/core/walkthrough.js +35 -0
- package/lib/hyperion/deck.js +29 -0
- package/lib/lucid/LucidCard.jsx +68 -0
- package/lib/lucid/LucidIntro.jsx +92 -0
- package/lib/lucid/blind.js +71 -0
- package/lib/lucid/cards.js +86 -0
- package/lib/lucid/deck.js +32 -0
- package/lib/lucid/fmt.js +139 -0
- package/lib/lucid/markdown.js +81 -0
- package/lib/lucid/motion.js +56 -0
- package/lib/lucid/sitrep.js +173 -0
- package/lib/plugins/loader.js +93 -0
- package/lib/quoxon/activity.js +116 -0
- package/lib/quoxon/aocl.js +117 -0
- package/lib/quoxon/api.js +952 -0
- package/lib/quoxon/app.js +4032 -0
- package/lib/quoxon/approvalFacts.js +94 -0
- package/lib/quoxon/approvalsView.js +325 -0
- package/lib/quoxon/asideView.js +40 -0
- package/lib/quoxon/ask.js +121 -0
- package/lib/quoxon/away.js +52 -0
- package/lib/quoxon/bang.js +224 -0
- package/lib/quoxon/bulkRisk.js +17 -0
- package/lib/quoxon/capabilities.js +82 -0
- package/lib/quoxon/cells.js +53 -0
- package/lib/quoxon/commandShort.js +112 -0
- package/lib/quoxon/commands.js +479 -0
- package/lib/quoxon/connect.js +654 -0
- package/lib/quoxon/connectCard.js +45 -0
- package/lib/quoxon/consent.js +86 -0
- package/lib/quoxon/context.js +68 -0
- package/lib/quoxon/copy.js +34 -0
- package/lib/quoxon/countdownLine.js +11 -0
- package/lib/quoxon/demo.autoplay.js +29 -0
- package/lib/quoxon/demo.fixtures.js +24 -0
- package/lib/quoxon/demo.js +76 -0
- package/lib/quoxon/devObserver.js +20 -0
- package/lib/quoxon/dividerAocl.js +191 -0
- package/lib/quoxon/dividerRule.js +57 -0
- package/lib/quoxon/dragonModes.js +150 -0
- package/lib/quoxon/dragonView.js +41 -0
- package/lib/quoxon/earlyInput.js +40 -0
- package/lib/quoxon/echo.js +15 -0
- package/lib/quoxon/egg.js +36 -0
- package/lib/quoxon/events.js +677 -0
- package/lib/quoxon/feedback.js +50 -0
- package/lib/quoxon/gallery.js +237 -0
- package/lib/quoxon/handoffOffer.js +78 -0
- package/lib/quoxon/hatSwitch.js +37 -0
- package/lib/quoxon/headless.js +161 -0
- package/lib/quoxon/hostUrls.js +41 -0
- package/lib/quoxon/indicator.js +197 -0
- package/lib/quoxon/intent.js +52 -0
- package/lib/quoxon/keys.js +164 -0
- package/lib/quoxon/launcher.js +103 -0
- package/lib/quoxon/main.js +176 -0
- package/lib/quoxon/markdown.js +341 -0
- package/lib/quoxon/markdownSettle.js +19 -0
- package/lib/quoxon/matrixDomains.json +46 -0
- package/lib/quoxon/mentions.js +90 -0
- package/lib/quoxon/mind.js +103 -0
- package/lib/quoxon/mode.js +46 -0
- package/lib/quoxon/model.js +311 -0
- package/lib/quoxon/modelPrefs.js +345 -0
- package/lib/quoxon/motion/clock.js +70 -0
- package/lib/quoxon/motion/color.js +35 -0
- package/lib/quoxon/motion/frame.js +14 -0
- package/lib/quoxon/motion/level.js +91 -0
- package/lib/quoxon/motion/reveal.js +54 -0
- package/lib/quoxon/motion/ring.js +79 -0
- package/lib/quoxon/mouse.js +211 -0
- package/lib/quoxon/noai.js +57 -0
- package/lib/quoxon/objects/agent.js +61 -0
- package/lib/quoxon/objects/away.js +72 -0
- package/lib/quoxon/objects/crystal.js +100 -0
- package/lib/quoxon/objects/fetch.js +182 -0
- package/lib/quoxon/objects/fleet.js +149 -0
- package/lib/quoxon/objects/health.js +186 -0
- package/lib/quoxon/objects/index.js +106 -0
- package/lib/quoxon/objects/ladder.js +71 -0
- package/lib/quoxon/objects/memory.js +44 -0
- package/lib/quoxon/objects/mirror.js +137 -0
- package/lib/quoxon/objects/model.js +118 -0
- package/lib/quoxon/objects/peek.js +17 -0
- package/lib/quoxon/objects/proof.js +110 -0
- package/lib/quoxon/objects/prove.js +130 -0
- package/lib/quoxon/objects/replay.js +125 -0
- package/lib/quoxon/objects/sitrep.js +58 -0
- package/lib/quoxon/objects/skill.js +105 -0
- package/lib/quoxon/objects/view.js +87 -0
- package/lib/quoxon/objects/workflow.js +119 -0
- package/lib/quoxon/observers.js +42 -0
- package/lib/quoxon/onboarding/copy.js +263 -0
- package/lib/quoxon/onboarding/credential.js +108 -0
- package/lib/quoxon/onboarding/detect.js +22 -0
- package/lib/quoxon/onboarding/dockerOffer.js +45 -0
- package/lib/quoxon/onboarding/failureCause.js +33 -0
- package/lib/quoxon/onboarding/finish.js +134 -0
- package/lib/quoxon/onboarding/index.js +94 -0
- package/lib/quoxon/onboarding/installRunner.js +284 -0
- package/lib/quoxon/onboarding/intent.js +53 -0
- package/lib/quoxon/onboarding/journey.js +73 -0
- package/lib/quoxon/onboarding/preflight.js +156 -0
- package/lib/quoxon/onboarding/probe.js +65 -0
- package/lib/quoxon/onboarding/runner.js +58 -0
- package/lib/quoxon/onboarding/view.js +682 -0
- package/lib/quoxon/orgLabel.js +10 -0
- package/lib/quoxon/orgSwitch.js +33 -0
- package/lib/quoxon/ownBroadcast.js +22 -0
- package/lib/quoxon/palette.js +43 -0
- package/lib/quoxon/print.js +98 -0
- package/lib/quoxon/profileSwitch.js +53 -0
- package/lib/quoxon/promptHistory.js +41 -0
- package/lib/quoxon/providers.js +48 -0
- package/lib/quoxon/qart.js +348 -0
- package/lib/quoxon/qdragon.js +410 -0
- package/lib/quoxon/qdragonFly.js +61 -0
- package/lib/quoxon/qdragonScenes.js +282 -0
- package/lib/quoxon/qeyes.js +213 -0
- package/lib/quoxon/qglyph.js +143 -0
- package/lib/quoxon/qhello.js +58 -0
- package/lib/quoxon/qmotion.js +132 -0
- package/lib/quoxon/render.js +1167 -0
- package/lib/quoxon/resend.js +72 -0
- package/lib/quoxon/roster.js +307 -0
- package/lib/quoxon/route.js +39 -0
- package/lib/quoxon/rows.js +711 -0
- package/lib/quoxon/rowsStore.js +80 -0
- package/lib/quoxon/rules.js +130 -0
- package/lib/quoxon/screenContext.js +150 -0
- package/lib/quoxon/screenFrames.js +254 -0
- package/lib/quoxon/session.js +238 -0
- package/lib/quoxon/sessionDead.js +17 -0
- package/lib/quoxon/signin.js +125 -0
- package/lib/quoxon/skills.js +30 -0
- package/lib/quoxon/slash/agents.js +112 -0
- package/lib/quoxon/slash/argSources.js +65 -0
- package/lib/quoxon/slash/args.js +65 -0
- package/lib/quoxon/slash/automate.js +89 -0
- package/lib/quoxon/slash/broadcast.js +140 -0
- package/lib/quoxon/slash/broadcastRun.js +108 -0
- package/lib/quoxon/slash/card.js +30 -0
- package/lib/quoxon/slash/challenge.js +114 -0
- package/lib/quoxon/slash/cliCommand.js +53 -0
- package/lib/quoxon/slash/cliLeaves.json +948 -0
- package/lib/quoxon/slash/compact.js +90 -0
- package/lib/quoxon/slash/confirm.js +30 -0
- package/lib/quoxon/slash/crystallize.js +69 -0
- package/lib/quoxon/slash/dashboard.js +136 -0
- package/lib/quoxon/slash/draft.js +54 -0
- package/lib/quoxon/slash/hatWalk.js +206 -0
- package/lib/quoxon/slash/inverses.js +77 -0
- package/lib/quoxon/slash/killer.js +24 -0
- package/lib/quoxon/slash/killerApi.js +16 -0
- package/lib/quoxon/slash/ledger.js +88 -0
- package/lib/quoxon/slash/listView.js +30 -0
- package/lib/quoxon/slash/modelCmd.js +261 -0
- package/lib/quoxon/slash/palette.js +118 -0
- package/lib/quoxon/slash/paletteController.js +169 -0
- package/lib/quoxon/slash/panels.js +116 -0
- package/lib/quoxon/slash/picker.js +56 -0
- package/lib/quoxon/slash/restart.js +202 -0
- package/lib/quoxon/slash/resume.js +59 -0
- package/lib/quoxon/slash/rowCmd.js +157 -0
- package/lib/quoxon/slash/rowWalk.js +175 -0
- package/lib/quoxon/slash/settings.js +60 -0
- package/lib/quoxon/slash/spawn.js +177 -0
- package/lib/quoxon/slash/stepUp.js +274 -0
- package/lib/quoxon/slash/stepUpCard.js +60 -0
- package/lib/quoxon/slash/stepUpCmds.js +78 -0
- package/lib/quoxon/slash/undoApi.js +38 -0
- package/lib/quoxon/slash/undoCmd.js +49 -0
- package/lib/quoxon/slash/undoWish.js +15 -0
- package/lib/quoxon/slash/watch.js +164 -0
- package/lib/quoxon/slash/wish.js +23 -0
- package/lib/quoxon/slash/wishCmd.js +32 -0
- package/lib/quoxon/slotChat.js +300 -0
- package/lib/quoxon/slotFormat.js +195 -0
- package/lib/quoxon/slotRun.js +131 -0
- package/lib/quoxon/sound/index.js +186 -0
- package/lib/quoxon/sound/mapping.js +120 -0
- package/lib/quoxon/sound/output.js +52 -0
- package/lib/quoxon/sound/synth.js +122 -0
- package/lib/quoxon/stray.js +22 -0
- package/lib/quoxon/suggestCommand.js +59 -0
- package/lib/quoxon/term.js +141 -0
- package/lib/quoxon/textBuffer.js +416 -0
- package/lib/quoxon/theme.js +286 -0
- package/lib/quoxon/tips.js +433 -0
- package/lib/quoxon/toolError.js +41 -0
- package/lib/quoxon/transcript.js +188 -0
- package/lib/quoxon/web/qface.js +89 -0
- package/lib/quoxon/welcome.js +52 -0
- package/lib/quoxon/whatsnew.js +136 -0
- package/lib/quoxon/whatsnew.jsonl +89 -0
- package/lib/quoxon/windowOrg.js +113 -0
- package/lib/server/diag.js +129 -0
- package/lib/server/doctor.js +71 -0
- package/lib/server/install.js +149 -0
- package/lib/server/pluginEnable.js +161 -0
- package/lib/server/skew.js +56 -0
- package/lib/server/snapshot.js +131 -0
- package/lib/server/status.js +128 -0
- package/lib/server/sys.js +65 -0
- package/lib/server/uninstall.js +63 -0
- package/lib/server/update.js +234 -0
- package/lib/toolOutputShape.js +315 -0
- package/lib/tui/app.jsx +289 -0
- package/lib/tui/components/Breadcrumb.jsx +42 -0
- package/lib/tui/components/ChatInput.jsx +68 -0
- package/lib/tui/components/Confirm.jsx +32 -0
- package/lib/tui/components/DataTable.jsx +270 -0
- package/lib/tui/components/DetailPanel.jsx +241 -0
- package/lib/tui/components/HelpOverlay.jsx +67 -0
- package/lib/tui/components/Layout.jsx +129 -0
- package/lib/tui/components/Palette.jsx +141 -0
- package/lib/tui/components/SearchInput.jsx +125 -0
- package/lib/tui/components/Sparkline.jsx +55 -0
- package/lib/tui/components/StatusBar.jsx +133 -0
- package/lib/tui/components/Toast.jsx +52 -0
- package/lib/tui/hooks/useApi.js +44 -0
- package/lib/tui/hooks/useHealth.js +90 -0
- package/lib/tui/hooks/usePolledApi.js +86 -0
- package/lib/tui/hooks/useTerminalSize.js +46 -0
- package/lib/tui/index.js +56 -0
- package/lib/tui/intro/Intro.jsx +332 -0
- package/lib/tui/jsx-loader.js +32 -0
- package/lib/tui/keys.js +87 -0
- package/lib/tui/registry.js +49 -0
- package/lib/tui/theme.js +103 -0
- package/lib/tui/views/AdminView.jsx +398 -0
- package/lib/tui/views/AgentView.jsx +204 -0
- package/lib/tui/views/BackupView.jsx +225 -0
- package/lib/tui/views/BrainView.jsx +223 -0
- package/lib/tui/views/ChatView.jsx +468 -0
- package/lib/tui/views/FilesView.jsx +218 -0
- package/lib/tui/views/FleetView.jsx +234 -0
- package/lib/tui/views/GovernanceView.jsx +453 -0
- package/lib/tui/views/HealthView.jsx +216 -0
- package/lib/tui/views/HyperionDeck.jsx +79 -0
- package/lib/tui/views/InboxView.jsx +228 -0
- package/lib/tui/views/LucidDeck.jsx +719 -0
- package/lib/tui/views/MainMenu.jsx +123 -0
- package/lib/tui/views/MemoryView.jsx +377 -0
- package/lib/tui/views/ObjectivesView.jsx +230 -0
- package/lib/tui/views/OrgView.jsx +229 -0
- package/lib/tui/views/ToolView.jsx +221 -0
- package/lib/tui/views/VaultView.jsx +422 -0
- package/lib/tui/views/WorkflowView.jsx +329 -0
- package/package.json +75 -4
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Budget commands: CRUD for quoxflow budget definitions + rolled-up usage.
|
|
3
|
+
*
|
|
4
|
+
* quox budget list|get|create|update|delete|usage
|
|
5
|
+
*
|
|
6
|
+
* Backend: quoxflow (NOT the auth service, NOT proxied by collector) —
|
|
7
|
+
* quoxflow/src/api/routes/budgets.ts, mounted at /api/budgets. Org scoping
|
|
8
|
+
* is via `?org_id=` query param on GETs and an `org_id` body field on
|
|
9
|
+
* writes — see cli/lib/api/endpoints/budgets.js header for the full
|
|
10
|
+
* verified org-scoping mechanism (list requires+filters org_id; get/usage
|
|
11
|
+
* check org_id against the budget's owner when present; update/delete
|
|
12
|
+
* require it in the body and 403 on mismatch).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { formatOutput, formatDetail, printSuccess, printWarning, printInfo } from '../core/output.js';
|
|
16
|
+
import { resolveOrgId } from './helpers.js';
|
|
17
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
18
|
+
|
|
19
|
+
const SCOPE_KINDS = ['org', 'objective', 'execution', 'iteration'];
|
|
20
|
+
|
|
21
|
+
function numOrUndefined(value) {
|
|
22
|
+
if (value === undefined) return undefined;
|
|
23
|
+
const n = Number(value);
|
|
24
|
+
if (Number.isNaN(n)) throw new Error(`Expected a number, got: ${value}`);
|
|
25
|
+
return n;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function registerBudgetCommands(program, ctx) {
|
|
29
|
+
const { client, auth } = ctx;
|
|
30
|
+
|
|
31
|
+
const budget = program
|
|
32
|
+
.command('budget')
|
|
33
|
+
.description('Manage quoxflow spend/usage budgets (org, objective, execution, iteration scope)');
|
|
34
|
+
|
|
35
|
+
// ── budget list ─────────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
budget
|
|
38
|
+
.command('list')
|
|
39
|
+
.description('List budgets for the active org')
|
|
40
|
+
.option('--scope <kind>', `filter by scope kind (${SCOPE_KINDS.join('|')})`)
|
|
41
|
+
.option('--scope-id <id>', 'filter by scope id')
|
|
42
|
+
.action(async (options) => {
|
|
43
|
+
auth.requireAuth();
|
|
44
|
+
const orgId = resolveOrgId(auth, program);
|
|
45
|
+
const query = { org_id: orgId };
|
|
46
|
+
if (options.scope) query.scope = options.scope;
|
|
47
|
+
if (options.scopeId) query.scope_id = options.scopeId;
|
|
48
|
+
|
|
49
|
+
const data = await client.get(resolveEndpoint('budgets.list').path, {
|
|
50
|
+
service: resolveEndpoint('budgets.list').service,
|
|
51
|
+
query,
|
|
52
|
+
});
|
|
53
|
+
const budgets = data.data?.budgets || data.budgets || [];
|
|
54
|
+
|
|
55
|
+
formatOutput({
|
|
56
|
+
columns: ['id', 'scope_kind', 'scope_id', 'period_start', 'period_end', 'max_cost_usd_micro', 'max_tokens', 'hard_stop'],
|
|
57
|
+
headers: ['ID', 'Scope', 'Scope ID', 'Period Start', 'Period End', 'Max Cost (micro-USD)', 'Max Tokens', 'Hard Stop'],
|
|
58
|
+
rows: budgets,
|
|
59
|
+
}, { format: program.opts().output, emptyMessage: 'No budgets found.' });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ── budget get ───────────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
budget
|
|
65
|
+
.command('get')
|
|
66
|
+
.description('Show budget details')
|
|
67
|
+
.argument('<id>', 'budget ID')
|
|
68
|
+
.action(async (id) => {
|
|
69
|
+
auth.requireAuth();
|
|
70
|
+
const orgId = resolveOrgId(auth, program);
|
|
71
|
+
const data = await client.get(resolveEndpoint('budgets.get', { id }).path, {
|
|
72
|
+
service: resolveEndpoint('budgets.get', { id }).service,
|
|
73
|
+
query: { org_id: orgId },
|
|
74
|
+
});
|
|
75
|
+
const b = data.data?.budget || data.budget || data;
|
|
76
|
+
|
|
77
|
+
formatDetail(b, {
|
|
78
|
+
format: program.opts().output,
|
|
79
|
+
title: `Budget: ${b.id || id}`,
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// ── budget create ────────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
budget
|
|
86
|
+
.command('create')
|
|
87
|
+
.description('Create a budget')
|
|
88
|
+
.requiredOption('--scope <kind>', `scope kind (${SCOPE_KINDS.join('|')})`)
|
|
89
|
+
.requiredOption('--scope-id <id>', 'scope id (e.g. org id, objective id, execution id, iteration id)')
|
|
90
|
+
.requiredOption('--period-start <iso>', 'period start (ISO timestamp)')
|
|
91
|
+
.requiredOption('--period-end <iso>', 'period end (ISO timestamp)')
|
|
92
|
+
.option('--max-tokens <n>', 'max total tokens (in + out)')
|
|
93
|
+
.option('--max-cost-usd-micro <n>', 'max cost in micro-USD (1 USD = 1,000,000)')
|
|
94
|
+
.option('--max-tool-calls <n>', 'max tool calls')
|
|
95
|
+
.option('--max-duration-ms <n>', 'max wall-clock duration (ms)')
|
|
96
|
+
.option('--max-iterations <n>', 'max iterations')
|
|
97
|
+
.option('--no-hard-stop', 'do not hard-stop execution when exceeded (default: hard-stop enabled)')
|
|
98
|
+
.action(async (options) => {
|
|
99
|
+
auth.requireAuth();
|
|
100
|
+
const orgId = resolveOrgId(auth, program);
|
|
101
|
+
|
|
102
|
+
if (!SCOPE_KINDS.includes(options.scope)) {
|
|
103
|
+
throw new Error(`--scope must be one of: ${SCOPE_KINDS.join(', ')}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const body = {
|
|
107
|
+
org_id: orgId,
|
|
108
|
+
scope_kind: options.scope,
|
|
109
|
+
scope_id: options.scopeId,
|
|
110
|
+
period_start: options.periodStart,
|
|
111
|
+
period_end: options.periodEnd,
|
|
112
|
+
max_tokens: numOrUndefined(options.maxTokens),
|
|
113
|
+
max_cost_usd_micro: numOrUndefined(options.maxCostUsdMicro),
|
|
114
|
+
max_tool_calls: numOrUndefined(options.maxToolCalls),
|
|
115
|
+
max_duration_ms: numOrUndefined(options.maxDurationMs),
|
|
116
|
+
max_iterations: numOrUndefined(options.maxIterations),
|
|
117
|
+
hard_stop: options.hardStop,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const data = await client.post(resolveEndpoint('budgets.create').path, {
|
|
121
|
+
service: resolveEndpoint('budgets.create').service,
|
|
122
|
+
body,
|
|
123
|
+
});
|
|
124
|
+
const b = data.data?.budget || data.budget || data;
|
|
125
|
+
printSuccess(`Budget created (${b.id}).`);
|
|
126
|
+
formatDetail(b, { format: program.opts().output });
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// ── budget update ────────────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
budget
|
|
132
|
+
.command('update')
|
|
133
|
+
.description('Update a budget')
|
|
134
|
+
.argument('<id>', 'budget ID')
|
|
135
|
+
.option('--period-start <iso>', 'new period start (ISO timestamp)')
|
|
136
|
+
.option('--period-end <iso>', 'new period end (ISO timestamp)')
|
|
137
|
+
.option('--max-tokens <n>', 'new max total tokens')
|
|
138
|
+
.option('--max-cost-usd-micro <n>', 'new max cost in micro-USD')
|
|
139
|
+
.option('--max-tool-calls <n>', 'new max tool calls')
|
|
140
|
+
.option('--max-duration-ms <n>', 'new max wall-clock duration (ms)')
|
|
141
|
+
.option('--max-iterations <n>', 'new max iterations')
|
|
142
|
+
.option('--hard-stop <bool>', 'set hard_stop (true|false)')
|
|
143
|
+
.action(async (id, options) => {
|
|
144
|
+
auth.requireAuth();
|
|
145
|
+
const orgId = resolveOrgId(auth, program);
|
|
146
|
+
|
|
147
|
+
const patch = { org_id: orgId };
|
|
148
|
+
if (options.periodStart !== undefined) patch.period_start = options.periodStart;
|
|
149
|
+
if (options.periodEnd !== undefined) patch.period_end = options.periodEnd;
|
|
150
|
+
if (options.maxTokens !== undefined) patch.max_tokens = numOrUndefined(options.maxTokens);
|
|
151
|
+
if (options.maxCostUsdMicro !== undefined) patch.max_cost_usd_micro = numOrUndefined(options.maxCostUsdMicro);
|
|
152
|
+
if (options.maxToolCalls !== undefined) patch.max_tool_calls = numOrUndefined(options.maxToolCalls);
|
|
153
|
+
if (options.maxDurationMs !== undefined) patch.max_duration_ms = numOrUndefined(options.maxDurationMs);
|
|
154
|
+
if (options.maxIterations !== undefined) patch.max_iterations = numOrUndefined(options.maxIterations);
|
|
155
|
+
if (options.hardStop !== undefined) {
|
|
156
|
+
if (options.hardStop !== 'true' && options.hardStop !== 'false') {
|
|
157
|
+
throw new Error('--hard-stop must be "true" or "false".');
|
|
158
|
+
}
|
|
159
|
+
patch.hard_stop = options.hardStop === 'true';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (Object.keys(patch).length === 1) {
|
|
163
|
+
throw new Error('Specify at least one field to update.');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const data = await client.patch(resolveEndpoint('budgets.update', { id }).path, {
|
|
167
|
+
service: resolveEndpoint('budgets.update', { id }).service,
|
|
168
|
+
body: patch,
|
|
169
|
+
});
|
|
170
|
+
const b = data.data?.budget || data.budget || data;
|
|
171
|
+
printSuccess('Budget updated.');
|
|
172
|
+
formatDetail(b, { format: program.opts().output });
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// ── budget delete ────────────────────────────────────────────────────────────
|
|
176
|
+
|
|
177
|
+
budget
|
|
178
|
+
.command('delete')
|
|
179
|
+
.description('Delete a budget')
|
|
180
|
+
.argument('<id>', 'budget ID')
|
|
181
|
+
.option('--force', 'skip confirmation')
|
|
182
|
+
.action(async (id, options) => {
|
|
183
|
+
auth.requireAuth();
|
|
184
|
+
const orgId = resolveOrgId(auth, program);
|
|
185
|
+
|
|
186
|
+
if (!options.force && !program.opts().yes) {
|
|
187
|
+
const { default: inquirer } = await import('inquirer');
|
|
188
|
+
const ans = await inquirer.prompt([{
|
|
189
|
+
type: 'confirm',
|
|
190
|
+
name: 'confirm',
|
|
191
|
+
message: `Delete budget ${id}? This cannot be undone.`,
|
|
192
|
+
default: false,
|
|
193
|
+
}]);
|
|
194
|
+
if (!ans.confirm) {
|
|
195
|
+
printInfo('Cancelled.');
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
await client.delete(resolveEndpoint('budgets.delete', { id }).path, {
|
|
201
|
+
service: resolveEndpoint('budgets.delete', { id }).service,
|
|
202
|
+
body: { org_id: orgId },
|
|
203
|
+
});
|
|
204
|
+
printSuccess('Budget deleted.');
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// ── budget usage ─────────────────────────────────────────────────────────────
|
|
208
|
+
|
|
209
|
+
budget
|
|
210
|
+
.command('usage')
|
|
211
|
+
.description('Show rolled-up usage + daily breakdown for a budget')
|
|
212
|
+
.argument('<id>', 'budget ID')
|
|
213
|
+
.option('--since <iso>', 'filter usage since this ISO timestamp')
|
|
214
|
+
.option('--until <iso>', 'filter usage until this ISO timestamp')
|
|
215
|
+
.action(async (id, options) => {
|
|
216
|
+
auth.requireAuth();
|
|
217
|
+
const orgId = resolveOrgId(auth, program);
|
|
218
|
+
const query = { org_id: orgId };
|
|
219
|
+
if (options.since) query.since = options.since;
|
|
220
|
+
if (options.until) query.until = options.until;
|
|
221
|
+
|
|
222
|
+
const data = await client.get(resolveEndpoint('budgets.usage', { id }).path, {
|
|
223
|
+
service: resolveEndpoint('budgets.usage', { id }).service,
|
|
224
|
+
query,
|
|
225
|
+
});
|
|
226
|
+
const payload = data.data || data;
|
|
227
|
+
|
|
228
|
+
formatDetail(payload.usage, {
|
|
229
|
+
format: program.opts().output,
|
|
230
|
+
title: `Budget Usage: ${id}`,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
if (program.opts().output !== 'json' && program.opts().output !== 'quiet') {
|
|
234
|
+
formatOutput({
|
|
235
|
+
columns: ['date', 'tokens_in', 'tokens_out', 'cost_usd_micro', 'tool_calls', 'duration_ms', 'iteration_count'],
|
|
236
|
+
headers: ['Date', 'Tokens In', 'Tokens Out', 'Cost (micro-USD)', 'Tool Calls', 'Duration (ms)', 'Iterations'],
|
|
237
|
+
rows: payload.daily || [],
|
|
238
|
+
}, { format: program.opts().output, emptyMessage: 'No daily usage recorded.' });
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build commands — DEVSUITE-BUILD step 4 (`quox build`).
|
|
3
|
+
*
|
|
4
|
+
* The governed superset of the thin local `quox-build` client: dispatches a
|
|
5
|
+
* PRE-REGISTERED target on a dev server through the collector's dev-build
|
|
6
|
+
* control plane (oracle-signed envelope over Bastion to the host-side
|
|
7
|
+
* quoxagent dev.build executor), reads live executor state, and reads the
|
|
8
|
+
* durable receipts mirror. The local `quox-build` spool client and the
|
|
9
|
+
* Terminal 9 daemon are untouched and keep working; this group is how any
|
|
10
|
+
* authenticated session drives builds on ANY registered dev server.
|
|
11
|
+
*
|
|
12
|
+
* `quox build <target> --host <hostId>` dispatches. Named subcommands
|
|
13
|
+
* (status/targets/history/latest) win over a target of the same name — a
|
|
14
|
+
* target literally called "status" must be dispatched via
|
|
15
|
+
* `quox build dispatch status --host …`.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { formatDetail, formatOutput, printSuccess, printWarning } from '../core/output.js';
|
|
19
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
20
|
+
|
|
21
|
+
export function registerBuildCommands(program, ctx) {
|
|
22
|
+
const { client, auth } = ctx;
|
|
23
|
+
|
|
24
|
+
const build = program
|
|
25
|
+
.command('build')
|
|
26
|
+
.description('QuoxBuild: dispatch and inspect governed builds on dev servers');
|
|
27
|
+
|
|
28
|
+
// Commander (non-positional mode) lets the PARENT consume an option it
|
|
29
|
+
// declares even when the token appears after a subcommand name, so the
|
|
30
|
+
// bare-target sugar's group-level --host/--stream/--phase/--msg would
|
|
31
|
+
// otherwise swallow the flags out from under every verb (found live on
|
|
32
|
+
// the first proof drive). Every verb therefore falls back to the group's
|
|
33
|
+
// own parsed opts.
|
|
34
|
+
const groupOpt = (options, key) => options[key] ?? build.opts()[key];
|
|
35
|
+
|
|
36
|
+
// An org with exactly one dev server needs no --host: use it and say so. With several, name them;
|
|
37
|
+
// with none, say so (proof cases code/reach-build-status / -targets exited 1 on a one-server org).
|
|
38
|
+
async function resolveHost(options) {
|
|
39
|
+
const given = groupOpt(options, 'host');
|
|
40
|
+
if (given) return given;
|
|
41
|
+
const listEp = resolveEndpoint('v1.dev.servers.list');
|
|
42
|
+
const list = await client.get(listEp.path, { service: listEp.service });
|
|
43
|
+
const ids = (Array.isArray(list?.servers) ? list.servers : []).map((s) => s.host_id).filter(Boolean);
|
|
44
|
+
if (ids.length === 1) {
|
|
45
|
+
printWarning(`No --host given; using the only dev server: ${ids[0]}`);
|
|
46
|
+
return ids[0];
|
|
47
|
+
}
|
|
48
|
+
if (ids.length === 0) throw new Error('No dev server is registered for this org (register one with `quox dev enable <hostId>`).');
|
|
49
|
+
throw new Error(`--host <hostId> is required: this org has ${ids.length} dev servers (${ids.join(', ')}).`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function dispatch(target, options) {
|
|
53
|
+
auth.requireAuth();
|
|
54
|
+
options = {
|
|
55
|
+
host: await resolveHost(options),
|
|
56
|
+
stream: groupOpt(options, 'stream'),
|
|
57
|
+
phase: groupOpt(options, 'phase'),
|
|
58
|
+
msg: groupOpt(options, 'msg'),
|
|
59
|
+
};
|
|
60
|
+
if (!options.host) {
|
|
61
|
+
throw new Error('--host <hostId> is required (the dev server that runs the build)');
|
|
62
|
+
}
|
|
63
|
+
const body = { target };
|
|
64
|
+
const stream = options.stream || process.env.QUOX_STREAM;
|
|
65
|
+
const phase = options.phase || process.env.QUOX_PHASE;
|
|
66
|
+
if (stream) body.stream = stream;
|
|
67
|
+
if (phase) body.phase = phase;
|
|
68
|
+
if (options.msg) body.msg = options.msg;
|
|
69
|
+
|
|
70
|
+
const endpoint = resolveEndpoint('v1.dev.build.dispatch', { hostId: options.host });
|
|
71
|
+
const data = await client.post(endpoint.path, { service: endpoint.service, body });
|
|
72
|
+
formatDetail(data, { format: program.opts().output, title: `Build dispatched on ${options.host}` });
|
|
73
|
+
if (data && data.dispatched) {
|
|
74
|
+
printSuccess(`${(data.targets || [target]).join(', ')} queued on ${options.host} (coalesces within the queue window).`);
|
|
75
|
+
printWarning('Queued is not built: check `quox build status --host ' + options.host + '` and the receipt before claiming green.');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
build
|
|
80
|
+
.command('dispatch')
|
|
81
|
+
.description('Queue a build of a pre-registered target on a dev server')
|
|
82
|
+
.argument('<target>', 'pre-registered target name on that host')
|
|
83
|
+
.option('--host <hostId>', 'dev server host_id')
|
|
84
|
+
.option('--stream <code>', 'roadmap stream code for the receipt (default: $QUOX_STREAM)')
|
|
85
|
+
.option('--phase <phase>', 'stream phase for the receipt (default: $QUOX_PHASE)')
|
|
86
|
+
.option('--msg <text>', 'what changed')
|
|
87
|
+
.action(dispatch);
|
|
88
|
+
|
|
89
|
+
build
|
|
90
|
+
.command('status')
|
|
91
|
+
.description('Live executor state on a dev server: readiness, prereqs, building-now, last outcomes')
|
|
92
|
+
.option('--host <hostId>', 'dev server host_id')
|
|
93
|
+
.action(async (options) => {
|
|
94
|
+
auth.requireAuth();
|
|
95
|
+
const host = await resolveHost(options);
|
|
96
|
+
const endpoint = resolveEndpoint('v1.dev.build.status', { hostId: host });
|
|
97
|
+
const data = await client.get(endpoint.path, { service: endpoint.service });
|
|
98
|
+
formatDetail(data, { format: program.opts().output, title: `Build status: ${host}` });
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
build
|
|
102
|
+
.command('targets')
|
|
103
|
+
.description("List a dev server's pre-registered build targets")
|
|
104
|
+
.option('--host <hostId>', 'dev server host_id')
|
|
105
|
+
.action(async (options) => {
|
|
106
|
+
auth.requireAuth();
|
|
107
|
+
const host = await resolveHost(options);
|
|
108
|
+
const endpoint = resolveEndpoint('v1.dev.build.targets', { hostId: host });
|
|
109
|
+
const data = await client.get(endpoint.path, { service: endpoint.service });
|
|
110
|
+
formatOutput(data.targets || [], {
|
|
111
|
+
format: program.opts().output,
|
|
112
|
+
columns: ['name', 'description', 'steps', 'verify_count'],
|
|
113
|
+
emptyMessage: 'No pre-registered targets on this host.',
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
build
|
|
118
|
+
.command('history')
|
|
119
|
+
.description('Durable build receipts (the witnessed mirror), newest first')
|
|
120
|
+
.option('--host <hostname>', 'filter to one host (receipt hostname)')
|
|
121
|
+
.option('--target <name>', 'filter to one target')
|
|
122
|
+
.option('--result <r>', 'filter by result (ok, FAIL, UNVERIFIED, INTERRUPTED)')
|
|
123
|
+
.option('--limit <n>', 'max rows (default 20)', (v) => parseInt(v, 10), 20)
|
|
124
|
+
.action(async (options) => {
|
|
125
|
+
auth.requireAuth();
|
|
126
|
+
const endpoint = resolveEndpoint('v1.build.receipts.list');
|
|
127
|
+
const params = new URLSearchParams();
|
|
128
|
+
const host = groupOpt(options, 'host');
|
|
129
|
+
if (host) params.set('host', host);
|
|
130
|
+
if (options.target) params.set('target', options.target);
|
|
131
|
+
if (options.result) params.set('result', options.result);
|
|
132
|
+
params.set('limit', String(options.limit));
|
|
133
|
+
const data = await client.get(`${endpoint.path}?${params}`, { service: endpoint.service });
|
|
134
|
+
formatOutput(data.receipts || [], {
|
|
135
|
+
format: program.opts().output,
|
|
136
|
+
columns: ['created_at', 'result', 'target', 'host', 'terminal', 'stream', 'phase', 'duration_seconds'],
|
|
137
|
+
emptyMessage: 'No build receipts recorded yet.',
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
build
|
|
142
|
+
.command('latest')
|
|
143
|
+
.description('Latest receipt per target (the build-status board)')
|
|
144
|
+
.action(async () => {
|
|
145
|
+
auth.requireAuth();
|
|
146
|
+
const endpoint = resolveEndpoint('v1.build.status.list');
|
|
147
|
+
const data = await client.get(endpoint.path, { service: endpoint.service });
|
|
148
|
+
formatOutput(data.targets || [], {
|
|
149
|
+
format: program.opts().output,
|
|
150
|
+
columns: ['target', 'result', 'host', 'created_at', 'duration_seconds'],
|
|
151
|
+
emptyMessage: 'No build receipts recorded yet.',
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Bare `quox build <target> --host …` sugar: dispatch without typing the
|
|
156
|
+
// verb, matching the muscle memory of the local quox-build client.
|
|
157
|
+
build
|
|
158
|
+
.argument('[target]', 'pre-registered target name (shorthand for `quox build dispatch <target>`)')
|
|
159
|
+
.option('--host <hostId>', 'dev server host_id')
|
|
160
|
+
.option('--stream <code>', 'roadmap stream code (default: $QUOX_STREAM)')
|
|
161
|
+
.option('--phase <phase>', 'stream phase (default: $QUOX_PHASE)')
|
|
162
|
+
.option('--msg <text>', 'what changed')
|
|
163
|
+
.action(async (target, options) => {
|
|
164
|
+
if (!target) {
|
|
165
|
+
build.help();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
await dispatch(target, options);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calendar-Q commands: connected calendars, agenda, coverage, manual sync,
|
|
3
|
+
* and (L2-C2) proposing/reconciling/reviewing approved event creation.
|
|
4
|
+
*
|
|
5
|
+
* There is deliberately NO `calendar create` command: creating an event
|
|
6
|
+
* always requires a human approval, resolved through the Approvals inbox
|
|
7
|
+
* (`quox inbox`) — not a second CLI doorway around that gate. `calendar
|
|
8
|
+
* propose` only ever builds the proposal (no external effect); an agent or a
|
|
9
|
+
* human approver is what actually triggers calendar_event_create, and that
|
|
10
|
+
* call is unconditionally gated by withApprovalGate regardless of caller.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { formatOutput, formatDetail, printSuccess } from '../core/output.js';
|
|
14
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
15
|
+
|
|
16
|
+
function isJsonOutput(program) {
|
|
17
|
+
return program.opts().output === 'json';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function printJson(data) {
|
|
21
|
+
console.log(JSON.stringify(data, null, 2));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function registerCalendarCommands(program, ctx) {
|
|
25
|
+
const { client, auth } = ctx;
|
|
26
|
+
|
|
27
|
+
const calendar = program
|
|
28
|
+
.command('calendar')
|
|
29
|
+
.description('Calendar-Q: connected calendars, agenda, coverage, sync');
|
|
30
|
+
|
|
31
|
+
// ── status ───────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
calendar
|
|
34
|
+
.command('status')
|
|
35
|
+
.description('Show connected Calendar-Q connections and their sync watermark')
|
|
36
|
+
.action(async () => {
|
|
37
|
+
auth.requireAuth();
|
|
38
|
+
const ep = resolveEndpoint('calendarq.status');
|
|
39
|
+
const data = await client.get(ep.path, { service: ep.service });
|
|
40
|
+
if (isJsonOutput(program)) return printJson(data);
|
|
41
|
+
formatOutput({
|
|
42
|
+
columns: ['connectionId', 'provider', 'resourceId', 'status', 'latestWatermarkTs'],
|
|
43
|
+
headers: ['ID', 'Provider', 'Resource', 'Status', 'Watermark'],
|
|
44
|
+
rows: data.connections || [],
|
|
45
|
+
}, { format: program.opts().output });
|
|
46
|
+
printSuccess(`${data.connectionsCount ?? 0} connection(s), ${data.layerCount ?? 0} layer(s).`);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// ── layers ───────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
calendar
|
|
52
|
+
.command('layers')
|
|
53
|
+
.description('List Calendar-Q layers')
|
|
54
|
+
.action(async () => {
|
|
55
|
+
auth.requireAuth();
|
|
56
|
+
const ep = resolveEndpoint('calendarq.layers');
|
|
57
|
+
const data = await client.get(ep.path, { service: ep.service });
|
|
58
|
+
if (isJsonOutput(program)) return printJson(data);
|
|
59
|
+
formatOutput({
|
|
60
|
+
columns: ['layerId', 'kind', 'displayName', 'visible', 'scope'],
|
|
61
|
+
headers: ['Layer', 'Kind', 'Name', 'Visible', 'Scope'],
|
|
62
|
+
rows: data.layers || [],
|
|
63
|
+
}, { format: program.opts().output });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// ── agenda ───────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
calendar
|
|
69
|
+
.command('agenda')
|
|
70
|
+
.description("Show a connection's agenda: occurrences plus coverage state")
|
|
71
|
+
.requiredOption('--connection <id>', 'Calendar-Q connection ID')
|
|
72
|
+
.option('--layers <csv>', 'comma-separated layer ids to restrict to')
|
|
73
|
+
.action(async (options) => {
|
|
74
|
+
auth.requireAuth();
|
|
75
|
+
const query = { connectionId: options.connection };
|
|
76
|
+
if (options.layers) query.layerIds = options.layers;
|
|
77
|
+
const ep = resolveEndpoint('calendarq.agenda');
|
|
78
|
+
const data = await client.get(ep.path, { service: ep.service, query });
|
|
79
|
+
if (isJsonOutput(program)) return printJson(data);
|
|
80
|
+
const coverage = data.coverage || {};
|
|
81
|
+
console.log(`Coverage: ${coverage.state} (watermark ${coverage.watermarkTs ?? 'n/a'}, window ${coverage.windowStartLocalDate} to ${coverage.windowEndLocalDateExclusive})`);
|
|
82
|
+
const occurrences = data.occurrences || [];
|
|
83
|
+
if (occurrences.length === 0) {
|
|
84
|
+
console.log('No occurrences in this window.');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
for (const occ of occurrences) console.log(occ.spokenForm);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// ── coverage ─────────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
calendar
|
|
93
|
+
.command('coverage')
|
|
94
|
+
.description('Show just the coverage/freshness state for a connection')
|
|
95
|
+
.requiredOption('--connection <id>', 'Calendar-Q connection ID')
|
|
96
|
+
.action(async (options) => {
|
|
97
|
+
auth.requireAuth();
|
|
98
|
+
const ep = resolveEndpoint('calendarq.coverage');
|
|
99
|
+
const data = await client.get(ep.path, { service: ep.service, query: { connectionId: options.connection } });
|
|
100
|
+
if (isJsonOutput(program)) return printJson(data);
|
|
101
|
+
formatDetail(data.coverage || {}, { format: program.opts().output, title: 'Calendar-Q Coverage' });
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// ── sync ─────────────────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
calendar
|
|
107
|
+
.command('sync')
|
|
108
|
+
.description('Trigger a manual sync for a connection (respects retired/backoff eligibility)')
|
|
109
|
+
.requiredOption('--connection <id>', 'Calendar-Q connection ID')
|
|
110
|
+
.action(async (options) => {
|
|
111
|
+
auth.requireAuth();
|
|
112
|
+
const ep = resolveEndpoint('calendarq.sync');
|
|
113
|
+
// A full-window provider fetch can run long; give it the same generous
|
|
114
|
+
// ceiling `quox mail sync` uses.
|
|
115
|
+
const data = await client.post(ep.path, { service: ep.service, body: { connectionId: options.connection }, timeout: 240000 });
|
|
116
|
+
if (isJsonOutput(program)) return printJson(data);
|
|
117
|
+
const result = data.result || {};
|
|
118
|
+
if (result.skipped) {
|
|
119
|
+
printSuccess(`Sync skipped for ${options.connection}: ${result.skipped}.`);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (result.failed) {
|
|
123
|
+
console.error(`Sync failed for ${options.connection}: ${result.error}`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const stats = result.stats || {};
|
|
127
|
+
printSuccess(`Synced ${options.connection}. ${stats.inserted ?? 0} occurrence(s), ${stats.omitted ?? 0} omitted, ${stats.changed ?? 0} changed.`);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// ── propose ──────────────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
calendar
|
|
133
|
+
.command('propose')
|
|
134
|
+
.description('Propose creating a single, non-recurring event (no external effect — nothing is created yet)')
|
|
135
|
+
.requiredOption('--connection <id>', 'Calendar-Q connection ID')
|
|
136
|
+
.requiredOption('--title <title>', 'Event title')
|
|
137
|
+
.requiredOption('--timezone <tz>', 'IANA timezone')
|
|
138
|
+
.option('--start <iso>', 'Start time, ISO 8601 (omit for --all-day)')
|
|
139
|
+
.option('--end <iso>', 'End time, ISO 8601, must be after --start (omit for --all-day)')
|
|
140
|
+
.option('--all-day', 'Create a single-day all-day event')
|
|
141
|
+
.option('--date <date>', "'YYYY-MM-DD', required with --all-day")
|
|
142
|
+
.option('--attendees <csv>', 'comma-separated attendee emails')
|
|
143
|
+
.option('--notify <policy>', "'none' or 'attendees'", 'none')
|
|
144
|
+
.option('--visibility <visibility>', "'default', 'private', or 'busy-only'", 'default')
|
|
145
|
+
.option('--description <text>', 'Event description')
|
|
146
|
+
.action(async (options) => {
|
|
147
|
+
auth.requireAuth();
|
|
148
|
+
const body = {
|
|
149
|
+
connectionId: options.connection,
|
|
150
|
+
title: options.title,
|
|
151
|
+
timezone: options.timezone,
|
|
152
|
+
notifyPolicy: options.notify,
|
|
153
|
+
visibility: options.visibility,
|
|
154
|
+
};
|
|
155
|
+
if (options.allDay) {
|
|
156
|
+
body.allDay = true;
|
|
157
|
+
body.dateOnly = options.date;
|
|
158
|
+
} else {
|
|
159
|
+
body.startTs = options.start ? Date.parse(options.start) : undefined;
|
|
160
|
+
body.endTs = options.end ? Date.parse(options.end) : undefined;
|
|
161
|
+
}
|
|
162
|
+
if (options.attendees) body.attendees = options.attendees.split(',').map((e) => ({ email: e.trim() })).filter((a) => a.email);
|
|
163
|
+
if (options.description) body.description = options.description;
|
|
164
|
+
|
|
165
|
+
const ep = resolveEndpoint('calendarq.propose');
|
|
166
|
+
const data = await client.post(ep.path, { service: ep.service, body });
|
|
167
|
+
if (isJsonOutput(program)) return printJson(data);
|
|
168
|
+
const p = data.proposal;
|
|
169
|
+
console.log(`Proposed "${p.title}" (proposalId ${p.proposalId}).`);
|
|
170
|
+
if ((data.overlaps || []).length > 0) {
|
|
171
|
+
console.log(`Disclosed conflicts: ${data.overlaps.map((o) => o.title).join(', ')}`);
|
|
172
|
+
} else {
|
|
173
|
+
console.log('No conflicts found against the latest synced calendar data.');
|
|
174
|
+
}
|
|
175
|
+
printSuccess('Nothing has been created yet. Approve via the Approvals inbox to actually create this event.');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// ── receipts ─────────────────────────────────────────────────────────
|
|
179
|
+
|
|
180
|
+
calendar
|
|
181
|
+
.command('receipts')
|
|
182
|
+
.description('Show Calendar-Q write-path receipts (newest first), each with its full state timeline')
|
|
183
|
+
.action(async () => {
|
|
184
|
+
auth.requireAuth();
|
|
185
|
+
const ep = resolveEndpoint('calendarq.receipts');
|
|
186
|
+
const data = await client.get(ep.path, { service: ep.service });
|
|
187
|
+
if (isJsonOutput(program)) return printJson(data);
|
|
188
|
+
const receipts = data.receipts || [];
|
|
189
|
+
if (receipts.length === 0) {
|
|
190
|
+
console.log('No receipts yet.');
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
formatOutput({
|
|
194
|
+
columns: ['createdAt', 'kind', 'operationState', 'opId'],
|
|
195
|
+
headers: ['When', 'Kind', 'State', 'Operation'],
|
|
196
|
+
rows: receipts,
|
|
197
|
+
}, { format: program.opts().output });
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// ── reconcile ────────────────────────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
calendar
|
|
203
|
+
.command('reconcile <opId>')
|
|
204
|
+
.description("Resolve an 'attempted' or 'outcome_unknown' create against provider evidence (read-only — never creates/updates/deletes)")
|
|
205
|
+
.action(async (opId) => {
|
|
206
|
+
auth.requireAuth();
|
|
207
|
+
const ep = resolveEndpoint('calendarq.reconcile', { opId });
|
|
208
|
+
const data = await client.post(ep.path, { service: ep.service, body: {} });
|
|
209
|
+
if (isJsonOutput(program)) return printJson(data);
|
|
210
|
+
if (data.pending) {
|
|
211
|
+
console.log(`Still unresolved: ${data.error}. Try again later${data.nextEligibleAt ? ` (not before ${new Date(data.nextEligibleAt).toISOString()})` : ''}.`);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
printSuccess(`Reconciled ${opId}: ${data.outcome}${data.reason ? ` (${data.reason})` : ''}.`);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* quox capabilities [name]
|
|
3
|
+
*
|
|
4
|
+
* What this Quox can do for your org right now (QUOXON E1): ready, needs setup,
|
|
5
|
+
* not available, planned, each with the server's honest reason and setup hint.
|
|
6
|
+
* Backend: collector GET /api/v1/capabilities (org from your token; 30 s cache).
|
|
7
|
+
* Same renderer as the terminal's /capabilities, so the two never disagree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
11
|
+
import { capabilityLines, findCapability, offerFor } from '../quoxon/capabilities.js';
|
|
12
|
+
|
|
13
|
+
export function registerCapabilitiesCommands(program, ctx) {
|
|
14
|
+
const { client, auth } = ctx;
|
|
15
|
+
program
|
|
16
|
+
.command('capabilities [name]')
|
|
17
|
+
.description('What this Quox can do for your org: ready, needs setup, not available, planned')
|
|
18
|
+
.action(async (name) => {
|
|
19
|
+
auth.requireAuth();
|
|
20
|
+
const ep = resolveEndpoint('v1.capabilities');
|
|
21
|
+
const data = await client.get(ep.path, { service: ep.service });
|
|
22
|
+
if (program.opts().output === 'json') { console.log(JSON.stringify(data, null, 2)); return; }
|
|
23
|
+
const res = { ok: Array.isArray(data?.capabilities), capabilities: data?.capabilities, error: 'unexpected response' };
|
|
24
|
+
if (name) {
|
|
25
|
+
const c = findCapability(name, res);
|
|
26
|
+
if (!c) { console.log(`Nothing called "${name}". quox capabilities lists them.`); process.exitCode = 1; return; }
|
|
27
|
+
console.log(`${c.name}: ${c.intent}`);
|
|
28
|
+
console.log(`Proof: ${c.evidence || 'not stated'}`);
|
|
29
|
+
console.log(offerFor(c.id, res) || `✔ ${c.name} is ready here.`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const [t] of capabilityLines(res)) console.log(t);
|
|
33
|
+
});
|
|
34
|
+
}
|