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,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `quox gripe` — QUOXIFY PASS 2 (DEVSUITE phase 15).
|
|
3
|
+
*
|
|
4
|
+
* The bundle audit (note #2840, theme S9) found Gripe had no `quox` verb at
|
|
5
|
+
* all, despite one being in its own definition of done. The customer-facing
|
|
6
|
+
* filing path was chat-agent-only, which meant a user had to know an agent
|
|
7
|
+
* existed and open a chat surface to report that something was broken. The
|
|
8
|
+
* fastest possible complaint is a one-liner in the terminal you are already
|
|
9
|
+
* in, which is exactly what the original terminal-only gripe skill was for.
|
|
10
|
+
*
|
|
11
|
+
* This wraps the WORKING path rather than building a second one: it talks to
|
|
12
|
+
* the GRIPE agent over the same governed chat route the dashboard and the
|
|
13
|
+
* Discord/Telegram bridges use, and GRIPE files the issue through the GitHub
|
|
14
|
+
* connector. No parallel issue store, no second credential model (the audit
|
|
15
|
+
* flagged three entry paths with three credential models; this adds a fourth
|
|
16
|
+
* ENTRY but reuses the third's governed path deliberately).
|
|
17
|
+
*
|
|
18
|
+
* Honest prerequisite, per the audit's "disclose the prereq" finding: filing
|
|
19
|
+
* needs a configured GitHub connector for the org. If it is missing, the
|
|
20
|
+
* agent says so and this command surfaces that plainly instead of pretending
|
|
21
|
+
* an issue was created.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { formatDetail, printInfo, printWarning } from '../core/output.js';
|
|
25
|
+
import { events, line as glyphLine, printEvent } from '../core/quoxglyph.js';
|
|
26
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
27
|
+
import { resolveOrgId } from './helpers.js';
|
|
28
|
+
|
|
29
|
+
export function registerGripeCommands(program, { client, auth }) {
|
|
30
|
+
program
|
|
31
|
+
.command('gripe')
|
|
32
|
+
.description('File a one-liner complaint as a GitHub issue (via the GRIPE agent)')
|
|
33
|
+
.argument('<complaint...>', 'the gripe, e.g. "sidebar tooltip clips on resize"')
|
|
34
|
+
.option('--repo <owner/name>', 'target repo (GRIPE defaults sensibly when omitted)')
|
|
35
|
+
.option('--label <label>', 'issue label, e.g. bug, idea, fleet')
|
|
36
|
+
.option('--public', 'confirm filing to a PUBLIC repo (asks y/N; refused if text has internal hostnames/paths)')
|
|
37
|
+
.option('--yes', 'skip the confirmation step and let GRIPE file it directly')
|
|
38
|
+
.action(async (complaintParts, options) => {
|
|
39
|
+
auth.requireAuth();
|
|
40
|
+
const complaint = complaintParts.join(' ').trim();
|
|
41
|
+
if (!complaint) throw new Error('say what is wrong: quox gripe "the thing that is broken"');
|
|
42
|
+
|
|
43
|
+
const orgId = resolveOrgId(auth, program);
|
|
44
|
+
if (options.public) {
|
|
45
|
+
// QUOXON-PRIVACY: public repos only via the deterministic path with a
|
|
46
|
+
// human y/N; the GRIPE agent can never confirm a public filing.
|
|
47
|
+
if (!options.repo) throw new Error('--public needs an explicit --repo <name>');
|
|
48
|
+
const r = await fileDeterministically({ client, complaint, options, orgId, confirmPublic: promptConfirmPublic });
|
|
49
|
+
if (!r.filed) process.exitCode = 1;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
printEvent(glyphLine('quox', 'filing gripe via GRIPE'));
|
|
53
|
+
const data = await askGripe({ client, complaint, repo: options.repo, label: options.label, yes: !!options.yes, orgId });
|
|
54
|
+
|
|
55
|
+
if (program.opts().output === 'json') {
|
|
56
|
+
formatDetail(data, { format: 'json' });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const r = await settleGripe({ client, data, complaint, options, orgId });
|
|
61
|
+
console.log('');
|
|
62
|
+
if (r.superseded) printInfo(SUPERSEDED_MESSAGE);
|
|
63
|
+
else console.log(r.response || '(no response)');
|
|
64
|
+
console.log('');
|
|
65
|
+
for (const n of r.notes) {
|
|
66
|
+
if (n.kind === 'created') printEvent(events.created('quox', 'issue', n.url));
|
|
67
|
+
else if (n.kind === 'info') printInfo(n.text);
|
|
68
|
+
else printWarning(n.text);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const SUPERSEDED_MESSAGE = 'GRIPE agent did not file this itself; its reply is superseded by the direct filing below.';
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Ask the GRIPE agent to file `complaint` over the governed chat route. -> the raw chat response.
|
|
77
|
+
* Shared by `quox gripe` and the quox client's /gripe, so there is one filing path.
|
|
78
|
+
*/
|
|
79
|
+
export async function askGripe({ client, complaint, repo, label, yes = false, orgId = null }) {
|
|
80
|
+
// GRIPE's whole discipline is speed: it does not investigate, it files.
|
|
81
|
+
// So the prompt states everything up front rather than inviting a
|
|
82
|
+
// back-and-forth the terminal is a bad place for.
|
|
83
|
+
const parts = [`File this gripe: ${complaint}`];
|
|
84
|
+
if (repo) parts.push(`Repo: ${repo}.`);
|
|
85
|
+
if (label) parts.push(`Label: ${label}.`);
|
|
86
|
+
if (yes) parts.push('File it now without asking me to confirm.');
|
|
87
|
+
else parts.push('Confirm the repo, label and title with me before filing.');
|
|
88
|
+
const ep = resolveEndpoint('chat.claude');
|
|
89
|
+
const body = { prompt: parts.join(' '), selected_agent: 'gripe' };
|
|
90
|
+
// The collector tracks which tools ran PER caller-supplied session_id;
|
|
91
|
+
// sending none meant tools_used always came back [] and classification
|
|
92
|
+
// fell back to parsing prose (DEVSUITE-GRIPE phase 5). One id per run.
|
|
93
|
+
body.session_id = `GRIPE_CLI_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
94
|
+
if (orgId) body.org_id = orgId;
|
|
95
|
+
return client.post(ep.path, { service: ep.service, body, timeout: 120000 });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Decide the outcome of a GRIPE run and, with yes, run the deterministic file when the agent did not.
|
|
100
|
+
* -> { response, outcome, superseded, url, notes: [{ kind: 'created', url } | { kind: 'info'|'warn', text }] }.
|
|
101
|
+
* Prints nothing: the caller renders the notes (console for `quox gripe`, history lines for /gripe).
|
|
102
|
+
*/
|
|
103
|
+
export async function settleGripe({ client, data, complaint, options = {}, orgId = null }) {
|
|
104
|
+
const response = data?.result || data?.response || data?.text || '';
|
|
105
|
+
const yes = !!options.yes;
|
|
106
|
+
// tools_used is the collector's own record of which tools ran. Passing it
|
|
107
|
+
// is what stops the outcome from depending on how the agent phrased its
|
|
108
|
+
// reply. Absent (older collector), classification falls back to prose.
|
|
109
|
+
const toolsUsed = Array.isArray(data?.tools_used) ? data.tools_used : null;
|
|
110
|
+
const outcome = classifyGripeResponse(response, { assumedYes: yes, toolsUsed, complaint });
|
|
111
|
+
// quox#668: with --yes, a non-filing agent run is followed by the
|
|
112
|
+
// deterministic file. Printing the agent's prose first ("no tool, cannot
|
|
113
|
+
// file") right above "issue created" contradicted the real outcome. In
|
|
114
|
+
// that case the agent's reply is superseded, so say so instead of
|
|
115
|
+
// echoing a claim the next lines disprove.
|
|
116
|
+
const superseded = yes && ['no-connector', 'awaiting-confirm', 'not-filed'].some((k) => outcome.kind === k || outcome.hint === k);
|
|
117
|
+
const notes = [];
|
|
118
|
+
let url = null;
|
|
119
|
+
const det = async () => {
|
|
120
|
+
const r = await fileDeterministically({ client, complaint, options, orgId, quiet: true });
|
|
121
|
+
notes.push(...r.notes); if (r.url) url = r.url;
|
|
122
|
+
return r;
|
|
123
|
+
};
|
|
124
|
+
if (outcome.kind === 'filed') {
|
|
125
|
+
url = outcome.url; notes.push({ kind: 'created', url });
|
|
126
|
+
} else if (outcome.kind === 'filed-unknown') {
|
|
127
|
+
notes.push({ kind: 'warn', text: 'GRIPE called github_create_issue but no issue link came back. Check the repo before re-running: '
|
|
128
|
+
+ 'the issue may exist, and a re-run would file it twice.' });
|
|
129
|
+
} else if (outcome.hint === 'no-connector' || outcome.kind === 'no-connector') {
|
|
130
|
+
// quox#621: "no connector" from the AGENT is not proof the org lacks
|
|
131
|
+
// one. The agent's tool-resolution can transiently fail (the gripe
|
|
132
|
+
// filed on an immediate retry, same org) or the github_create_issue
|
|
133
|
+
// tool may not be wired to this agent (#581), while a healthy github
|
|
134
|
+
// credential sits in the vault. The deterministic path resolves that
|
|
135
|
+
// credential server-side over a DIFFERENT route (the /github/issues
|
|
136
|
+
// proxy, not the agent tool), so with --yes we try it before believing
|
|
137
|
+
// the agent: if a connector really exists this files it (turning a
|
|
138
|
+
// silent-loss-then-retry into a first-try success); only if the vault
|
|
139
|
+
// path ALSO cannot file is the connector genuinely missing, and only
|
|
140
|
+
// then do we send the user to Settings.
|
|
141
|
+
if (yes) {
|
|
142
|
+
const r = await det();
|
|
143
|
+
if (!r.filed) notes.push({ kind: 'warn', text: NO_CONNECTOR_MESSAGE });
|
|
144
|
+
} else {
|
|
145
|
+
notes.push({ kind: 'warn', text: NO_CONNECTOR_MESSAGE });
|
|
146
|
+
}
|
|
147
|
+
} else if (outcome.hint === 'auth-unavailable' || outcome.kind === 'auth-unavailable') {
|
|
148
|
+
notes.push({ kind: 'warn', text: AUTH_UNAVAILABLE_MESSAGE });
|
|
149
|
+
} else if (outcome.hint === 'awaiting-confirm' || outcome.kind === 'awaiting-confirm') {
|
|
150
|
+
if (yes) await det();
|
|
151
|
+
else notes.push({ kind: 'info', text: 'GRIPE is asking you to confirm. Re-run with --yes to file it directly.' });
|
|
152
|
+
} else if (outcome.kind === 'not-filed') {
|
|
153
|
+
if (yes) await det();
|
|
154
|
+
else notes.push({ kind: 'warn', text: 'Not filed: github_create_issue was never called on this run.' });
|
|
155
|
+
} else {
|
|
156
|
+
notes.push({ kind: 'warn', text: 'No issue URL came back, so treat this as NOT filed until you can see the issue.' });
|
|
157
|
+
}
|
|
158
|
+
return { response, outcome, superseded, url, notes };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// quox#478: --yes must GUARANTEE a headless file, not merely ask the model
|
|
162
|
+
// nicely. When the LLM run verifiably did not file (tools_used is the
|
|
163
|
+
// collector's own record), fall back to the governed GitHub proxy
|
|
164
|
+
// (POST /github/issues: user-authed, entitlement-gated, credential resolved
|
|
165
|
+
// from the org vault server-side) and file deterministically. Deliberately
|
|
166
|
+
// NOT run after 'filed-unknown' (the issue may exist; a second file would
|
|
167
|
+
// duplicate it). It IS now run after 'no-connector' with --yes (quox#621):
|
|
168
|
+
// the proxy resolves the vault credential over a DIFFERENT route than the
|
|
169
|
+
// agent tool, so it succeeds when the agent merely failed to resolve/wire the
|
|
170
|
+
// tool (#581) — and the caller falls back to NO_CONNECTOR_MESSAGE only if this
|
|
171
|
+
// also cannot file. Still NOT auto-run after auth-unavailable (a 403/429/503
|
|
172
|
+
// is a platform outage the proxy would hit too; retrying shortly is the fix).
|
|
173
|
+
// Returns { filed, url?, error? } so the caller can decide the message.
|
|
174
|
+
async function promptConfirmPublic(repo) {
|
|
175
|
+
if (!process.stdin.isTTY) return false;
|
|
176
|
+
const { createInterface } = await import('node:readline/promises');
|
|
177
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
178
|
+
try {
|
|
179
|
+
const a = await rl.question(`${repo} is PUBLIC. This issue will be world-readable. File it? [y/N] `);
|
|
180
|
+
return /^y(es)?$/i.test(a.trim());
|
|
181
|
+
} finally { rl.close(); }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export async function fileDeterministically({ client, complaint, options, orgId, quiet = false, confirmPublic = null }) {
|
|
185
|
+
const notes = [];
|
|
186
|
+
const say = (n) => { notes.push(n); if (quiet) return; if (n.kind === 'created') printEvent(events.created('quox', 'issue', n.url)); else if (n.kind === 'info') printInfo(n.text); else printWarning(n.text); };
|
|
187
|
+
const repoArg = options.repo || 'quoxai/quox';
|
|
188
|
+
const [owner, repo] = repoArg.includes('/') ? repoArg.split('/', 2) : ['quoxai', repoArg];
|
|
189
|
+
let confirmed = false;
|
|
190
|
+
if (options.public) {
|
|
191
|
+
confirmed = typeof confirmPublic === 'function' ? !!(await confirmPublic(`${owner}/${repo}`)) : false;
|
|
192
|
+
if (!confirmed) { say({ kind: 'warn', text: 'Not filed: public filing was not confirmed.' }); return { filed: false, notes }; }
|
|
193
|
+
}
|
|
194
|
+
const firstLine = complaint.split('\n')[0];
|
|
195
|
+
const title = firstLine.length > 80 ? `${firstLine.slice(0, 77)}...` : firstLine;
|
|
196
|
+
const ep = resolveEndpoint('github.issue.create');
|
|
197
|
+
try {
|
|
198
|
+
const data = await client.post(ep.path, {
|
|
199
|
+
service: ep.service,
|
|
200
|
+
body: {
|
|
201
|
+
owner,
|
|
202
|
+
repo,
|
|
203
|
+
title,
|
|
204
|
+
body: `## Gripe\n${complaint}\n\n## Context\n- Filed deterministically by \`quox gripe --yes\` (the GRIPE agent run did not file; quox#478 guarantee path)\n- Priority: minor / off-task observation\n\n## Suggested Action\nInvestigate and fix if confirmed.`,
|
|
205
|
+
labels: [options.label || 'fleet/qa'],
|
|
206
|
+
...(orgId ? { org_id: orgId } : {}),
|
|
207
|
+
...(confirmed ? { confirm_public: true } : {}),
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
const url = data?.issue?.html_url || data?.issue?.url || null;
|
|
211
|
+
if (url) {
|
|
212
|
+
say({ kind: 'created', url });
|
|
213
|
+
say({ kind: 'info', text: 'Filed via the deterministic path (the GRIPE agent run did not file; --yes now guarantees the file).' });
|
|
214
|
+
return { filed: true, url, notes };
|
|
215
|
+
}
|
|
216
|
+
say({ kind: 'warn', text: 'Deterministic file returned no issue URL; treat as NOT filed until you can see the issue.' });
|
|
217
|
+
return { filed: false, notes };
|
|
218
|
+
} catch (err) {
|
|
219
|
+
say({ kind: 'warn', text: `Not filed: the GRIPE run did not file and the deterministic fallback failed too (${err.message}).` });
|
|
220
|
+
return { filed: false, error: err.message, notes };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const NO_CONNECTOR_MESSAGE =
|
|
225
|
+
'No issue was filed: the org has no GitHub connector configured. Set one up in Settings > Integrations, then re-run.';
|
|
226
|
+
|
|
227
|
+
const AUTH_UNAVAILABLE_MESSAGE =
|
|
228
|
+
'No issue was filed: a platform authorization step failed (membership verify or credential resolve did not answer). '
|
|
229
|
+
+ 'This is NOT a missing GitHub connector. Retry shortly; if it persists, check auth service health.';
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Decide what actually happened from GRIPE's reply.
|
|
233
|
+
*
|
|
234
|
+
* Split out of the action handler so it can be tested against real agent
|
|
235
|
+
* wording. The missing-connector branch used to match
|
|
236
|
+
* /not configured|no github|credential|connector/i, which does not match what
|
|
237
|
+
* the agent actually says. Observed live on 2026-08-23:
|
|
238
|
+
*
|
|
239
|
+
* "GitHub isn't connected for this org, no issue-filing tool is available
|
|
240
|
+
* right now. Connect GitHub in Settings > Integrations and I'll file it
|
|
241
|
+
* immediately after. I'm not fabricating an issue number."
|
|
242
|
+
*
|
|
243
|
+
* None of the four alternatives appear in that sentence, so the specific,
|
|
244
|
+
* actionable "connect GitHub in Settings" advice was skipped and the user got
|
|
245
|
+
* the generic "treat this as NOT filed" instead. Both are honest, which is why
|
|
246
|
+
* this never showed up as a bug: it degraded to a vaguer truth rather than a
|
|
247
|
+
* falsehood. It still costs the user the one sentence that says what to do.
|
|
248
|
+
*
|
|
249
|
+
* Matching prose with a regex is fragile by nature and this will drift again
|
|
250
|
+
* when the agent's phrasing changes. It is deliberately biased toward the
|
|
251
|
+
* generic branch: a missed connector hint is a papercut, whereas wrongly
|
|
252
|
+
* claiming a connector problem would send someone to Settings for a fault
|
|
253
|
+
* that is not there. The URL check stays first and stays authoritative, since
|
|
254
|
+
* a real issue link is the only thing that proves filing.
|
|
255
|
+
*/
|
|
256
|
+
export function classifyGripeResponse(response, { assumedYes = false, toolsUsed = null, complaint = '' } = {}) {
|
|
257
|
+
const text = String(response ?? '');
|
|
258
|
+
const url = (text.match(/https:\/\/github\.com\/\S+\/issues\/\d+/) || [])[0];
|
|
259
|
+
if (url) return { kind: 'filed', url, certain: true };
|
|
260
|
+
|
|
261
|
+
// The Claude CLI's own error for a NATIVE call to a tool that is not native.
|
|
262
|
+
// In CLI-tools mode the catalogue runs only via `quox tool exec`, so this
|
|
263
|
+
// string means github_create_issue never ran (2026-10-10: every --yes gripe
|
|
264
|
+
// fell to "unknown" on it and never reached the direct filing).
|
|
265
|
+
if (/No such tool available/i.test(text)) {
|
|
266
|
+
return { kind: 'not-filed', certain: true, hint: null };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Structured evidence beats prose. The collector returns `tools_used` on
|
|
270
|
+
// every chat response, so whether github_create_issue actually RAN is a fact,
|
|
271
|
+
// not something to infer from English. Reading the outcome out of the agent's
|
|
272
|
+
// wording is what this function got wrong twice: once when the
|
|
273
|
+
// missing-connector phrasing changed, once when the bare word "connector"
|
|
274
|
+
// matched a healthy reply. A third regex patch would be the same mistake
|
|
275
|
+
// again, so the outcome now comes from the tool list and prose is demoted to
|
|
276
|
+
// a HINT about what to advise, where being wrong costs a sentence rather than
|
|
277
|
+
// a false claim.
|
|
278
|
+
// An EMPTY list is NOT evidence. The collector tracks MCP tool calls per
|
|
279
|
+
// caller-supplied session_id, so a request that sends none gets [] back
|
|
280
|
+
// whether or not the tool ran. Reading that as "never called" would replace a
|
|
281
|
+
// hedged truth with a confident falsehood and invite a duplicate issue.
|
|
282
|
+
// Absence of evidence is not evidence of absence.
|
|
283
|
+
if (Array.isArray(toolsUsed) && toolsUsed.length > 0) {
|
|
284
|
+
const ran = toolsUsed.some((t) => String(t).endsWith('github_create_issue'));
|
|
285
|
+
if (ran) {
|
|
286
|
+
// The tool ran and returned no link. Saying "filed" would invent an
|
|
287
|
+
// issue; saying "not filed" would send the user to file a duplicate.
|
|
288
|
+
return { kind: 'filed-unknown', certain: true };
|
|
289
|
+
}
|
|
290
|
+
return { kind: 'not-filed', certain: true, hint: adviceHint(text, assumedYes, complaint) };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// No structured evidence available (an older collector, or a surface that
|
|
294
|
+
// does not return tools_used). Fall back to the prose-only classification,
|
|
295
|
+
// unchanged, rather than degrading every caller to "unknown".
|
|
296
|
+
const hint = adviceHint(text, assumedYes, complaint);
|
|
297
|
+
if (hint === 'no-connector') return { kind: 'no-connector' };
|
|
298
|
+
if (hint === 'auth-unavailable') return { kind: 'auth-unavailable' };
|
|
299
|
+
if (hint === 'awaiting-confirm') return { kind: 'awaiting-confirm' };
|
|
300
|
+
return { kind: 'unknown' };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* What to ADVISE when nothing was filed. This is a hint, never an outcome:
|
|
305
|
+
* getting it wrong costs the user one unhelpful sentence, where getting the
|
|
306
|
+
* outcome wrong costs them a duplicate issue or a phantom one.
|
|
307
|
+
*
|
|
308
|
+
* @returns {'no-connector'|'awaiting-confirm'|null}
|
|
309
|
+
*/
|
|
310
|
+
// The platform-failure shapes adviceHint matches first. Each is a global regex so a match can be blanked.
|
|
311
|
+
const AUTH_SIGNALS = [/membership/gi, /verification .{0,20}unavailable/gi, /auth service did not answer/gi, /\b(403|503|429)\b/g];
|
|
312
|
+
|
|
313
|
+
function adviceHint(text, assumedYes, complaint = '') {
|
|
314
|
+
// 2026-10-17: GRIPE's confirmation reply echoes the complaint, so a gripe ABOUT an HTTP 403 (or the membership
|
|
315
|
+
// page) read as a platform auth failure and "File it?" became "a platform authorization step failed". A signal
|
|
316
|
+
// counts only where the user did not write it: whatever the complaint itself contains is blanked first.
|
|
317
|
+
const userText = String(complaint || '');
|
|
318
|
+
let authText = text;
|
|
319
|
+
for (const re of AUTH_SIGNALS) {
|
|
320
|
+
for (const m of new Set(userText.match(re) || [])) authText = authText.split(m).join(' ');
|
|
321
|
+
}
|
|
322
|
+
// Platform-side authorization/availability failures beat the no-connector
|
|
323
|
+
// guess. On 2026-09-21 auth's rate limiter 429'd the collector's membership
|
|
324
|
+
// verify, the tool call 403'd with "no active membership", GRIPE narrated
|
|
325
|
+
// "GitHub isn't connected", and this function turned a platform outage into
|
|
326
|
+
// "the org has no GitHub connector configured" — a confident falsehood while
|
|
327
|
+
// the vault held three healthy credentials (quox#565). These shapes come
|
|
328
|
+
// from the collector's own error strings, so match them FIRST.
|
|
329
|
+
if (AUTH_SIGNALS.some((re) => { re.lastIndex = 0; return re.test(authText); })) {
|
|
330
|
+
return 'auth-unavailable';
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Every alternative here must carry its own NEGATION. The bare words
|
|
334
|
+
// `credential` and `connector` used to be alternatives on their own, and on
|
|
335
|
+
// 2026-08-23 that fired on a reply where GRIPE said "Yes, I can see it" and
|
|
336
|
+
// then echoed the user's word inside the proposed issue title. The CLI told
|
|
337
|
+
// the user to go configure a connector that was working. `connector` and
|
|
338
|
+
// `credential` are what this feature is ABOUT, so they appear in healthy
|
|
339
|
+
// replies constantly; only a negation makes them evidence of anything.
|
|
340
|
+
const noConnector =
|
|
341
|
+
/not configured/i.test(text) ||
|
|
342
|
+
/no github/i.test(text) ||
|
|
343
|
+
/github (is|isn't|is not|was not|wasn't)\s*(n't)?\s*connect/i.test(text) ||
|
|
344
|
+
/no issue[- ]filing tool/i.test(text) ||
|
|
345
|
+
/connect github/i.test(text) ||
|
|
346
|
+
/no (\w+ ){0,2}(credential|connector|integration)/i.test(text) ||
|
|
347
|
+
/(credential|connector|integration)s?\s+(is|are)\s+(not|un)(configured|available|connected|set)/i.test(text);
|
|
348
|
+
if (noConnector) return 'no-connector';
|
|
349
|
+
|
|
350
|
+
// Only meaningful when the caller did NOT pass --yes: with --yes the prompt
|
|
351
|
+
// already told GRIPE to file without asking, so a reply with no URL is an
|
|
352
|
+
// unknown outcome, not a confirmation prompt.
|
|
353
|
+
if (!assumedYes) return 'awaiting-confirm';
|
|
354
|
+
return null;
|
|
355
|
+
}
|