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,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `quox policy` — the governance compiler from the terminal (OPGOV quox#582).
|
|
3
|
+
*
|
|
4
|
+
* compile: plain-language rule -> deterministic quox-policy.v1 DRAFT, with
|
|
5
|
+
* the compiled policy printed in full for review (a policy nobody read is
|
|
6
|
+
* not governance). arm: moves a reviewed draft to armed; the collector
|
|
7
|
+
* refuses arming without a logged-in human. Honesty: enforcement is phase 3
|
|
8
|
+
* (IMPACT #491) and is NOT wired; an armed policy is a reviewed intent, not
|
|
9
|
+
* yet a running gate, and this command says so.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
13
|
+
import { resolveOrgId } from './helpers.js';
|
|
14
|
+
|
|
15
|
+
function isJsonOutput(program) {
|
|
16
|
+
const o = program.opts();
|
|
17
|
+
return o.json === true || o.output === 'json';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const NOT_ENFORCED_NOTE = 'note: enforcement is phase 3 (IMPACT #491) and is not wired yet; armed = reviewed intent, not a running gate.';
|
|
21
|
+
|
|
22
|
+
export function registerPolicyCommands(program, ctx) {
|
|
23
|
+
const { client, auth } = ctx;
|
|
24
|
+
|
|
25
|
+
const p = program
|
|
26
|
+
.command('policy')
|
|
27
|
+
.description('Governance compiler: plain-language rule -> reviewed, armable policy (OPGOV)');
|
|
28
|
+
|
|
29
|
+
p.command('compile <rule>')
|
|
30
|
+
.description('Compile a plain-language rule to a quox-policy.v1 draft (deterministic grammar; out-of-grammar rules are refused, never approximated)')
|
|
31
|
+
.action(async (rule) => {
|
|
32
|
+
const orgId = resolveOrgId(auth, program);
|
|
33
|
+
const ep = resolveEndpoint('governance.policy.compile', { orgId });
|
|
34
|
+
try {
|
|
35
|
+
const data = await client.post(ep.path, { service: ep.service, body: { rule } });
|
|
36
|
+
if (isJsonOutput(program)) { console.log(JSON.stringify(data, null, 2)); return; }
|
|
37
|
+
const rec = data.record;
|
|
38
|
+
console.log(`compiled DRAFT ${rec.id} (${rec.policy.effect})`);
|
|
39
|
+
console.log(JSON.stringify(rec.policy, null, 2));
|
|
40
|
+
console.log(`review it, then: quox policy arm ${rec.id}`);
|
|
41
|
+
console.log(NOT_ENFORCED_NOTE);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
const msg = err?.message || String(err);
|
|
44
|
+
if (/422|unknown/i.test(msg)) {
|
|
45
|
+
console.log('NOT COMPILED: the rule is outside the deterministic grammar and was refused rather than approximated.');
|
|
46
|
+
}
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
p.command('list')
|
|
52
|
+
.description('List compiled policies for this org')
|
|
53
|
+
.option('--state <s>', 'draft | armed | retired')
|
|
54
|
+
.action(async (opts) => {
|
|
55
|
+
const orgId = resolveOrgId(auth, program);
|
|
56
|
+
const ep = resolveEndpoint('governance.policy.list', { orgId, state: opts.state });
|
|
57
|
+
const data = await client.get(ep.path, { service: ep.service });
|
|
58
|
+
if (isJsonOutput(program)) { console.log(JSON.stringify(data, null, 2)); return; }
|
|
59
|
+
const items = data.policies || [];
|
|
60
|
+
if (!items.length) { console.log('No policies. Compile one: quox policy compile "<rule>"'); return; }
|
|
61
|
+
for (const r of items) {
|
|
62
|
+
console.log(`${r.id} [${r.state}] ${r.policy?.effect ?? '?'} ${r.rule_text}${r.approved_by ? ` (armed by ${r.approved_by})` : ''}`);
|
|
63
|
+
}
|
|
64
|
+
console.log(NOT_ENFORCED_NOTE);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
p.command('arm <id>')
|
|
68
|
+
.description('Arm a reviewed draft (requires a logged-in human; service keys are refused by design)')
|
|
69
|
+
.action(async (id) => {
|
|
70
|
+
const orgId = resolveOrgId(auth, program);
|
|
71
|
+
const ep = resolveEndpoint('governance.policy.arm', { orgId, id });
|
|
72
|
+
const data = await client.post(ep.path, { service: ep.service, body: {} });
|
|
73
|
+
if (isJsonOutput(program)) { console.log(JSON.stringify(data, null, 2)); return; }
|
|
74
|
+
const rec = data.record;
|
|
75
|
+
console.log(`ARMED ${rec.id} (${rec.policy.effect}) approved by ${rec.approved_by}`);
|
|
76
|
+
console.log(NOT_ENFORCED_NOTE);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Powers commands: MCP endpoint + hosted-repo tool deploys (LIFECYCLE-P1..P3)
|
|
3
|
+
*
|
|
4
|
+
* quox powers detect|deploy|deploy-repo|status|finalize|update|archive|restore|config|delete
|
|
5
|
+
*
|
|
6
|
+
* Backend: services/auth/routes/powers.js, mounted org-scoped at
|
|
7
|
+
* `/api/orgs/:orgId/powers/...`. Two deploy flows:
|
|
8
|
+
* - `deploy` (mcp_endpoint): probes a live MCP URL and registers it as a
|
|
9
|
+
* governed agent in one call. Requires `persona` (agent_id + name) upfront.
|
|
10
|
+
* - `deploy-repo` (mcp_hosted): kicks off an async container build from a
|
|
11
|
+
* GitHub repo (202 Accepted). Poll `status` until the build reaches a
|
|
12
|
+
* terminal state (`built`/`failed`), then call `finalize` (persona
|
|
13
|
+
* required there, NOT at deploy-repo time) to activate the agent.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { formatDetail, printSuccess, printWarning, printInfo } from '../core/output.js';
|
|
17
|
+
import { resolveOrgId } from './helpers.js';
|
|
18
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
19
|
+
|
|
20
|
+
const TERMINAL_BUILD_STATES = new Set(['built', 'failed']);
|
|
21
|
+
|
|
22
|
+
function sleep(ms) {
|
|
23
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Commander collector for repeatable --env key=value flags -> [{ key, value }]. */
|
|
27
|
+
function collectEnvVar(input, previous) {
|
|
28
|
+
const idx = input.indexOf('=');
|
|
29
|
+
if (idx === -1) {
|
|
30
|
+
throw new Error(`Invalid --env value "${input}". Expected key=value.`);
|
|
31
|
+
}
|
|
32
|
+
const key = input.slice(0, idx).trim();
|
|
33
|
+
const value = input.slice(idx + 1);
|
|
34
|
+
if (!key) {
|
|
35
|
+
throw new Error(`Invalid --env value "${input}". Key cannot be empty.`);
|
|
36
|
+
}
|
|
37
|
+
return [...previous, { key, value }];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function buildPersona(options, { requireCore = false } = {}) {
|
|
41
|
+
const persona = {};
|
|
42
|
+
if (options.agentId) persona.agent_id = options.agentId;
|
|
43
|
+
if (options.name) persona.name = options.name;
|
|
44
|
+
if (options.description !== undefined) persona.description = options.description;
|
|
45
|
+
if (options.icon) persona.icon = options.icon;
|
|
46
|
+
if (options.systemPromptAdditions) persona.system_prompt_additions = options.systemPromptAdditions;
|
|
47
|
+
if (requireCore && (!persona.agent_id || !persona.name)) {
|
|
48
|
+
throw new Error('--agent-id and --name are required.');
|
|
49
|
+
}
|
|
50
|
+
return persona;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function confirmOrSkip(message) {
|
|
54
|
+
const { default: inquirer } = await import('inquirer');
|
|
55
|
+
const ans = await inquirer.prompt([{ type: 'confirm', name: 'confirm', message, default: false }]);
|
|
56
|
+
return ans.confirm;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function registerPowersCommands(program, ctx) {
|
|
60
|
+
const { client, auth } = ctx;
|
|
61
|
+
|
|
62
|
+
const powers = program
|
|
63
|
+
.command('powers')
|
|
64
|
+
.description('Deploy and manage POWERS (MCP endpoint / hosted-repo tools)');
|
|
65
|
+
|
|
66
|
+
// ── powers detect ───────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
powers
|
|
69
|
+
.command('detect')
|
|
70
|
+
.description('Probe an MCP URL to see what kind of server it is and what tools it exposes')
|
|
71
|
+
.requiredOption('--url <url>', 'MCP server URL')
|
|
72
|
+
.option('--auth-kind <kind>', 'none|bearer|header', 'none')
|
|
73
|
+
.option('--auth-value <value>', 'auth token/header value (required if --auth-kind is bearer or header)')
|
|
74
|
+
.action(async (options) => {
|
|
75
|
+
auth.requireAuth();
|
|
76
|
+
const orgId = resolveOrgId(auth, program);
|
|
77
|
+
const body = { url: options.url, authKind: options.authKind };
|
|
78
|
+
if (options.authValue) body.authValue = options.authValue;
|
|
79
|
+
const ep = resolveEndpoint('powers.detect', { orgId });
|
|
80
|
+
const data = await client.post(ep.path, { service: ep.service, body });
|
|
81
|
+
formatDetail(data, { format: program.opts().output, title: 'Detection Result' });
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// ── powers deploy (mcp_endpoint) ────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
powers
|
|
87
|
+
.command('deploy')
|
|
88
|
+
.description('Deploy a live MCP endpoint as a governed agent (one-shot, no build)')
|
|
89
|
+
.requiredOption('--url <url>', 'MCP server URL')
|
|
90
|
+
.option('--auth-kind <kind>', 'none|bearer|header', 'none')
|
|
91
|
+
.option('--auth-value <value>', 'auth token/header value')
|
|
92
|
+
.requiredOption('--agent-id <id>', 'new agent id (lowercase letters/numbers/underscores, starts with a letter)')
|
|
93
|
+
.requiredOption('--name <name>', 'agent display name')
|
|
94
|
+
.option('--description <text>', 'agent description')
|
|
95
|
+
.option('--icon <icon>', 'agent icon')
|
|
96
|
+
.option('--system-prompt-additions <text>', 'extra system prompt text for the agent')
|
|
97
|
+
.action(async (options) => {
|
|
98
|
+
auth.requireAuth();
|
|
99
|
+
const orgId = resolveOrgId(auth, program);
|
|
100
|
+
const body = {
|
|
101
|
+
url: options.url,
|
|
102
|
+
authKind: options.authKind,
|
|
103
|
+
persona: buildPersona(options, { requireCore: true }),
|
|
104
|
+
};
|
|
105
|
+
if (options.authValue) body.authValue = options.authValue;
|
|
106
|
+
const ep = resolveEndpoint('powers.deploy', { orgId });
|
|
107
|
+
const data = await client.post(ep.path, { service: ep.service, body });
|
|
108
|
+
printSuccess(`Power deployed: agent "${data.agent_id}" (tool ${data.tool_id}).`);
|
|
109
|
+
formatDetail(data, { format: program.opts().output });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// ── powers deploy-repo (mcp_hosted) ─────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
powers
|
|
115
|
+
.command('deploy-repo')
|
|
116
|
+
.description('Deploy a public GitHub repo as a hosted MCP power (builds a container; async)')
|
|
117
|
+
.requiredOption('--repo-url <url>', 'public GitHub repo URL, e.g. https://github.com/owner/repo')
|
|
118
|
+
.option('--env <key=value>', 'env var to inject into the build (repeatable)', collectEnvVar, [])
|
|
119
|
+
.option('--agent-id <id>', 'reserve an agent id upfront (optional — can also be set at finalize)')
|
|
120
|
+
.option('--force-suffix <suffix>', 'suffix to allow deploying the same repo again as a duplicate')
|
|
121
|
+
.option('--no-poll', 'return immediately after kicking off the build instead of polling status')
|
|
122
|
+
.option('--poll-interval <ms>', 'polling interval in ms', '3000')
|
|
123
|
+
.option('--poll-timeout <ms>', 'max time to poll before giving up, in ms', '300000')
|
|
124
|
+
.action(async (options) => {
|
|
125
|
+
auth.requireAuth();
|
|
126
|
+
const orgId = resolveOrgId(auth, program);
|
|
127
|
+
|
|
128
|
+
const body = { repo_url: options.repoUrl, env_vars: options.env };
|
|
129
|
+
if (options.agentId) body.persona = { agent_id: options.agentId };
|
|
130
|
+
if (options.forceSuffix) body.force_suffix = options.forceSuffix;
|
|
131
|
+
|
|
132
|
+
const deployEp = resolveEndpoint('powers.deploy-repo', { orgId });
|
|
133
|
+
const data = await client.post(deployEp.path, { service: deployEp.service, body });
|
|
134
|
+
printSuccess(`Build started: tool_def_id=${data.tool_def_id} (${data.tool_id}), build_state=${data.build_state}.`);
|
|
135
|
+
|
|
136
|
+
if (options.poll === false) {
|
|
137
|
+
formatDetail(data, { format: program.opts().output });
|
|
138
|
+
printInfo(`Poll with: quox powers status ${data.tool_def_id}`);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const toolDefId = data.tool_def_id;
|
|
143
|
+
const pollInterval = Number(options.pollInterval);
|
|
144
|
+
const pollTimeout = Number(options.pollTimeout);
|
|
145
|
+
const statusEp = resolveEndpoint('powers.deploy-repo.status', { orgId, toolDefId });
|
|
146
|
+
const start = Date.now();
|
|
147
|
+
let status = { build_state: data.build_state };
|
|
148
|
+
|
|
149
|
+
while (!TERMINAL_BUILD_STATES.has(status.build_state) && (Date.now() - start) < pollTimeout) {
|
|
150
|
+
await sleep(pollInterval);
|
|
151
|
+
status = await client.get(statusEp.path, { service: statusEp.service });
|
|
152
|
+
printInfo(`build_state=${status.build_state}`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
formatDetail(status, { format: program.opts().output, title: 'Build Status' });
|
|
156
|
+
|
|
157
|
+
if (status.build_state === 'built') {
|
|
158
|
+
printSuccess(`Build complete. Run: quox powers finalize ${toolDefId} --agent-id <id> --name <name>`);
|
|
159
|
+
} else if (status.build_state === 'failed') {
|
|
160
|
+
printWarning(`Build failed: ${status.build_failed_reason || 'unknown reason'}`);
|
|
161
|
+
} else {
|
|
162
|
+
printWarning(`Polling timed out before the build reached a terminal state. Check later: quox powers status ${toolDefId}`);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// ── powers status ───────────────────────────────────────────────────────────
|
|
167
|
+
|
|
168
|
+
powers
|
|
169
|
+
.command('status')
|
|
170
|
+
.description('Check a hosted-repo power\'s build status')
|
|
171
|
+
.argument('<toolDefId>', 'tool definition ID')
|
|
172
|
+
.action(async (toolDefId) => {
|
|
173
|
+
auth.requireAuth();
|
|
174
|
+
const orgId = resolveOrgId(auth, program);
|
|
175
|
+
const ep = resolveEndpoint('powers.deploy-repo.status', { orgId, toolDefId });
|
|
176
|
+
const data = await client.get(ep.path, { service: ep.service });
|
|
177
|
+
formatDetail(data, { format: program.opts().output, title: 'Build Status' });
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// ── powers finalize ─────────────────────────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
powers
|
|
183
|
+
.command('finalize')
|
|
184
|
+
.description('Activate the agent for a completed hosted-repo build')
|
|
185
|
+
.argument('<toolDefId>', 'tool definition ID')
|
|
186
|
+
.requiredOption('--agent-id <id>', 'new agent id (lowercase letters/numbers/underscores, starts with a letter)')
|
|
187
|
+
.requiredOption('--name <name>', 'agent display name')
|
|
188
|
+
.option('--description <text>', 'agent description')
|
|
189
|
+
.option('--icon <icon>', 'agent icon')
|
|
190
|
+
.option('--system-prompt-additions <text>', 'extra system prompt text for the agent')
|
|
191
|
+
.action(async (toolDefId, options) => {
|
|
192
|
+
auth.requireAuth();
|
|
193
|
+
const orgId = resolveOrgId(auth, program);
|
|
194
|
+
const body = { persona: buildPersona(options, { requireCore: true }) };
|
|
195
|
+
const ep = resolveEndpoint('powers.deploy-repo.finalize', { orgId, toolDefId });
|
|
196
|
+
const data = await client.post(ep.path, { service: ep.service, body });
|
|
197
|
+
printSuccess(`Power finalized: agent "${data.agent_id}" (tool ${data.tool_id}).`);
|
|
198
|
+
formatDetail(data, { format: program.opts().output });
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// ── powers update (redeploy at a new ref) ──────────────────────────────────
|
|
202
|
+
|
|
203
|
+
powers
|
|
204
|
+
.command('update')
|
|
205
|
+
.description('Redeploy a hosted-repo power at a new git ref (branch/tag/commit)')
|
|
206
|
+
.argument('<toolDefId>', 'tool definition ID')
|
|
207
|
+
.requiredOption('--repo-ref <ref>', 'git ref to build, e.g. HEAD or a commit SHA')
|
|
208
|
+
.action(async (toolDefId, options) => {
|
|
209
|
+
auth.requireAuth();
|
|
210
|
+
const orgId = resolveOrgId(auth, program);
|
|
211
|
+
const ep = resolveEndpoint('powers.deploy-repo.update', { orgId, toolDefId });
|
|
212
|
+
const data = await client.post(ep.path, { service: ep.service, body: { repo_ref: options.repoRef } });
|
|
213
|
+
printSuccess(`Update build started for ${toolDefId} at ref "${data.repo_ref}" (build_state=${data.build_state}).`);
|
|
214
|
+
formatDetail(data, { format: program.opts().output });
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// ── powers archive / restore ────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
powers
|
|
220
|
+
.command('archive')
|
|
221
|
+
.description('Archive a hosted-repo power (disables it without deleting any rows)')
|
|
222
|
+
.argument('<toolDefId>', 'tool definition ID')
|
|
223
|
+
.action(async (toolDefId) => {
|
|
224
|
+
auth.requireAuth();
|
|
225
|
+
const orgId = resolveOrgId(auth, program);
|
|
226
|
+
const ep = resolveEndpoint('powers.deploy-repo.archive', { orgId, toolDefId });
|
|
227
|
+
const data = await client.post(ep.path, { service: ep.service });
|
|
228
|
+
printSuccess('Power archived.');
|
|
229
|
+
formatDetail(data, { format: program.opts().output });
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
powers
|
|
233
|
+
.command('restore')
|
|
234
|
+
.description('Restore a previously archived hosted-repo power')
|
|
235
|
+
.argument('<toolDefId>', 'tool definition ID')
|
|
236
|
+
.action(async (toolDefId) => {
|
|
237
|
+
auth.requireAuth();
|
|
238
|
+
const orgId = resolveOrgId(auth, program);
|
|
239
|
+
const ep = resolveEndpoint('powers.deploy-repo.restore', { orgId, toolDefId });
|
|
240
|
+
const data = await client.post(ep.path, { service: ep.service });
|
|
241
|
+
printSuccess('Power restored.');
|
|
242
|
+
formatDetail(data, { format: program.opts().output });
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// ── powers config ───────────────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
powers
|
|
248
|
+
.command('config')
|
|
249
|
+
.description('Update env vars and/or agent persona for a hosted-repo power without rebuilding')
|
|
250
|
+
.argument('<toolDefId>', 'tool definition ID')
|
|
251
|
+
.option('--env <key=value>', 'env var to set/rotate (repeatable)', collectEnvVar, [])
|
|
252
|
+
.option('--name <name>', 'new agent display name')
|
|
253
|
+
.option('--description <text>', 'new agent description')
|
|
254
|
+
.option('--icon <icon>', 'new agent icon')
|
|
255
|
+
.option('--system-prompt-additions <text>', 'new system prompt additions')
|
|
256
|
+
.action(async (toolDefId, options) => {
|
|
257
|
+
auth.requireAuth();
|
|
258
|
+
const orgId = resolveOrgId(auth, program);
|
|
259
|
+
|
|
260
|
+
const body = {};
|
|
261
|
+
if (options.env && options.env.length > 0) body.env_vars = options.env;
|
|
262
|
+
const persona = buildPersona(options);
|
|
263
|
+
if (Object.keys(persona).length > 0) body.persona = persona;
|
|
264
|
+
|
|
265
|
+
if (!body.env_vars && !body.persona) {
|
|
266
|
+
throw new Error('Specify at least one of --env or a persona field (--name/--description/--icon/--system-prompt-additions).');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const ep = resolveEndpoint('powers.deploy-repo.config', { orgId, toolDefId });
|
|
270
|
+
const data = await client.patch(ep.path, { service: ep.service, body });
|
|
271
|
+
printSuccess('Power config updated.');
|
|
272
|
+
formatDetail(data, { format: program.opts().output });
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// ── powers delete ───────────────────────────────────────────────────────────
|
|
276
|
+
|
|
277
|
+
powers
|
|
278
|
+
.command('delete')
|
|
279
|
+
.description('Permanently destroy a hosted-repo power (revokes agent, deletes credentials)')
|
|
280
|
+
.argument('<toolDefId>', 'tool definition ID')
|
|
281
|
+
.option('--force', 'skip confirmation')
|
|
282
|
+
.action(async (toolDefId, options) => {
|
|
283
|
+
auth.requireAuth();
|
|
284
|
+
const orgId = resolveOrgId(auth, program);
|
|
285
|
+
|
|
286
|
+
if (!options.force && !program.opts().yes) {
|
|
287
|
+
const ok = await confirmOrSkip(`Permanently destroy power ${toolDefId}? This retires its agent and deletes its credentials. This cannot be undone.`);
|
|
288
|
+
if (!ok) { printInfo('Cancelled.'); return; }
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const ep = resolveEndpoint('powers.deploy-repo.delete', { orgId, toolDefId });
|
|
292
|
+
const data = await client.delete(ep.path, { service: ep.service, query: { confirm: 'true' } });
|
|
293
|
+
printSuccess('Power deleted.');
|
|
294
|
+
formatDetail(data, { format: program.opts().output });
|
|
295
|
+
});
|
|
296
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `quox presence [who]` / `quox presence set present|away|sleeping`: PRESENCE (owner 2026-10-16).
|
|
3
|
+
* A human says they are not at their terminal (/afk, /sleep in quox do the same). Sessions and agents
|
|
4
|
+
* read it so they stop waiting on approvals, which still queue normally: nothing is ever auto-approved.
|
|
5
|
+
* Collector routes GET/PUT /api/v1/presence; the org is the caller's, only a human login sets its own.
|
|
6
|
+
*/
|
|
7
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
8
|
+
import { resolveOrgId } from './helpers.js';
|
|
9
|
+
|
|
10
|
+
const STATES = ['present', 'away', 'sleeping'];
|
|
11
|
+
|
|
12
|
+
function stamp(iso) {
|
|
13
|
+
const d = new Date(iso);
|
|
14
|
+
return Number.isNaN(d.getTime()) ? String(iso || '') : `${d.toISOString().slice(0, 10)} ${d.toISOString().slice(11, 16)} UTC`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** One plain line for a presence record. */
|
|
18
|
+
export function presenceText(p) {
|
|
19
|
+
if (!p || !p.away) return `${p?.who || 'they'}: present`;
|
|
20
|
+
const note = p.note ? `, "${p.note}"` : '';
|
|
21
|
+
return `${p.who}: ${p.auto ? 'away (idle)' : p.state} since ${stamp(p.since)}${note} (approvals will queue)`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The fields an approval request reports, from GET /api/v1/presence. */
|
|
25
|
+
export function approvalPresenceFields(list) {
|
|
26
|
+
const away = (list && Array.isArray(list.presence) ? list.presence : []).filter((p) => p && p.away);
|
|
27
|
+
if (!away.length) return { owner_away: false };
|
|
28
|
+
const p = away.find((x) => x.who === 'owner') || away[0];
|
|
29
|
+
return { owner_away: true, owner_away_since: p.since, owner_presence: p.state, owner_away_notice: list.notice || presenceText(p) };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Read the org's presence; null on any failure (a presence read never fails the caller). */
|
|
33
|
+
export async function readPresence(client, orgId) {
|
|
34
|
+
try {
|
|
35
|
+
const ep = resolveEndpoint('presence.list');
|
|
36
|
+
return await client.get(ep.path, { service: ep.service, query: orgId ? { org_id: orgId } : undefined, retries: 0, timeout: 5000 });
|
|
37
|
+
} catch { return null; }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function registerPresenceCommands(program, { client, auth }) {
|
|
41
|
+
const pr = program
|
|
42
|
+
.command('presence')
|
|
43
|
+
.description('Is a person at their terminal? With no name: everyone with presence on record. When someone is away, approvals queue; work on something else')
|
|
44
|
+
.argument('[who]', 'user id, email, email name, "owner" or "me"')
|
|
45
|
+
.action(async (who) => {
|
|
46
|
+
auth.requireAuth();
|
|
47
|
+
const orgId = resolveOrgId(auth, program);
|
|
48
|
+
const json = program.opts().output === 'json';
|
|
49
|
+
if (who) {
|
|
50
|
+
const ep = resolveEndpoint('presence.get', { who });
|
|
51
|
+
const d = await client.get(ep.path, { service: ep.service, query: { org_id: orgId } });
|
|
52
|
+
if (json) { console.log(JSON.stringify(d, null, 2)); return; }
|
|
53
|
+
console.log(presenceText(d.presence));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const ep = resolveEndpoint('presence.list');
|
|
57
|
+
const d = await client.get(ep.path, { service: ep.service, query: { org_id: orgId } });
|
|
58
|
+
if (json) { console.log(JSON.stringify(d, null, 2)); return; }
|
|
59
|
+
const list = Array.isArray(d.presence) ? d.presence : [];
|
|
60
|
+
if (!list.some((p) => p.away)) console.log('Everyone is present: nobody has marked themselves away.');
|
|
61
|
+
for (const p of list) console.log(presenceText(p));
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
pr
|
|
65
|
+
.command('set')
|
|
66
|
+
.description('Say where you are: present, away or sleeping (a human login only). Same as /afk, /sleep, /back in quox')
|
|
67
|
+
.argument('<state>', 'present | away | sleeping')
|
|
68
|
+
.option('--note <text>', 'a short note sessions will see ("school run")')
|
|
69
|
+
.option('--slots <list>', 'your own window slots, comma separated (hitl and triage-q always count)')
|
|
70
|
+
.option('--auto-away <minutes>', 'read as away after this many idle minutes; "off" to disable (default off)')
|
|
71
|
+
.action(async (state, options) => {
|
|
72
|
+
if (!STATES.includes(state)) throw new Error('state must be present, away or sleeping');
|
|
73
|
+
auth.requireAuth();
|
|
74
|
+
const orgId = resolveOrgId(auth, program);
|
|
75
|
+
const body = { state };
|
|
76
|
+
if (options.note !== undefined) body.note = options.note;
|
|
77
|
+
if (options.slots) body.slots = String(options.slots).split(',').map((s) => s.trim()).filter(Boolean);
|
|
78
|
+
if (options.autoAway !== undefined) {
|
|
79
|
+
const off = /^(off|0|no)$/i.test(String(options.autoAway));
|
|
80
|
+
const n = Number(options.autoAway);
|
|
81
|
+
if (!off && (!Number.isInteger(n) || n < 1 || n > 1440)) throw new Error('--auto-away is minutes (1 to 1440) or off');
|
|
82
|
+
body.auto_away_minutes = off ? 0 : n;
|
|
83
|
+
}
|
|
84
|
+
const ep = resolveEndpoint('presence.set');
|
|
85
|
+
const d = await client.put(ep.path, { service: ep.service, body, query: { org_id: orgId } });
|
|
86
|
+
if (program.opts().output === 'json') { console.log(JSON.stringify(d, null, 2)); return; }
|
|
87
|
+
console.log(presenceText(d.presence));
|
|
88
|
+
});
|
|
89
|
+
}
|