quoxcli 0.2.0 → 0.4.0
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 +1 -1
- package/README.md +2 -0
- package/bin/quox.js +99 -126
- package/lib/api/endpoints/actions.js +15 -0
- package/lib/api/endpoints/admin.js +46 -0
- package/lib/api/endpoints/agent-schedules.js +26 -0
- package/lib/api/endpoints/agents.js +7 -0
- package/lib/api/endpoints/assistants.js +12 -0
- package/lib/api/endpoints/away.js +15 -0
- package/lib/api/endpoints/blog.js +16 -0
- package/lib/api/endpoints/chat.js +14 -0
- package/lib/api/endpoints/contactsq.js +6 -0
- package/lib/api/endpoints/conversations.js +14 -0
- package/lib/api/endpoints/devServerRegistry.js +25 -0
- package/lib/api/endpoints/engagement.js +26 -0
- package/lib/api/endpoints/evidence.js +20 -0
- package/lib/api/endpoints/executions.js +13 -0
- package/lib/api/endpoints/fetchAllowlist.js +27 -0
- package/lib/api/endpoints/files.js +14 -0
- package/lib/api/endpoints/hat.js +44 -0
- package/lib/api/endpoints/inbox.js +20 -0
- package/lib/api/endpoints/index.js +26 -0
- package/lib/api/endpoints/loops.js +26 -0
- package/lib/api/endpoints/memory.js +19 -0
- package/lib/api/endpoints/mind.js +13 -0
- package/lib/api/endpoints/mon.js +179 -0
- package/lib/api/endpoints/objectives.js +12 -0
- package/lib/api/endpoints/plugins.js +18 -0
- package/lib/api/endpoints/presence.js +33 -0
- package/lib/api/endpoints/quoxplan.js +7 -0
- package/lib/api/endpoints/quoxseo.js +12 -0
- package/lib/api/endpoints/router.js +17 -0
- package/lib/api/endpoints/safety.js +7 -0
- package/lib/api/endpoints/server.js +21 -0
- package/lib/api/endpoints/setup.js +6 -0
- package/lib/api/endpoints/skills.js +20 -0
- package/lib/api/endpoints/stepup.js +20 -0
- package/lib/api/endpoints/teams.js +2 -2
- package/lib/api/endpoints/triggers.js +26 -0
- package/lib/api/endpoints/v1.js +120 -0
- package/lib/api/endpoints/ward.js +7 -0
- package/lib/api/endpoints/workflows.js +7 -0
- package/lib/api/endpoints/x.js +8 -0
- package/lib/commands/actions.js +131 -0
- package/lib/commands/admin.js +16 -0
- package/lib/commands/agent.js +170 -27
- package/lib/commands/agentAttach.js +140 -13
- package/lib/commands/approvals.js +78 -1
- package/lib/commands/aside.js +24 -0
- package/lib/commands/ask.js +146 -0
- package/lib/commands/assistant.js +59 -4
- package/lib/commands/auth.js +8 -2
- package/lib/commands/backup.js +8 -4
- package/lib/commands/blog.js +110 -0
- package/lib/commands/brain.js +105 -14
- package/lib/commands/build.js +19 -5
- package/lib/commands/chat.js +180 -26
- package/lib/commands/chatCompanion.js +27 -0
- package/lib/commands/chatState.js +45 -0
- package/lib/commands/claude.js +35 -38
- package/lib/commands/contacts.js +134 -4
- package/lib/commands/contactsSendAt.js +21 -0
- package/lib/commands/conversation.js +35 -4
- package/lib/commands/dashboard.js +43 -0
- package/lib/commands/department.js +28 -7
- package/lib/commands/devResident.js +15 -3
- package/lib/commands/devSupervisor.js +13 -1
- package/lib/commands/discord.js +75 -39
- package/lib/commands/done.js +98 -28
- package/lib/commands/engagement.js +107 -6
- package/lib/commands/evidence.js +154 -0
- package/lib/commands/ext.js +23 -0
- package/lib/commands/fetchAllowlist.js +71 -0
- package/lib/commands/file.js +38 -1
- package/lib/commands/fleet.js +336 -4
- package/lib/commands/governance.js +12 -3
- package/lib/commands/gripe.js +44 -13
- package/lib/commands/hat.js +254 -9
- package/lib/commands/helpers.js +18 -1
- package/lib/commands/hyperion.js +58 -0
- package/lib/commands/image.js +68 -0
- package/lib/commands/inbox.js +74 -23
- package/lib/commands/kuma.js +1050 -0
- package/lib/commands/kumaSla.js +174 -0
- package/lib/commands/licence.js +52 -155
- package/lib/commands/loop.js +291 -0
- package/lib/commands/lucid.js +10 -4
- package/lib/commands/memory.js +85 -8
- package/lib/commands/mind.js +71 -0
- package/lib/commands/mon.js +69 -2
- package/lib/commands/monitoring.js +1 -1
- package/lib/commands/motion.js +2 -2
- package/lib/commands/nucleus.js +48 -17
- package/lib/commands/objective.js +59 -1
- package/lib/commands/offload.js +89 -0
- package/lib/commands/onboard.js +2 -1
- package/lib/commands/org.js +30 -3
- package/lib/commands/peek.js +28 -0
- package/lib/commands/plan.js +38 -0
- package/lib/commands/plugin.js +110 -0
- package/lib/commands/presence.js +89 -0
- package/lib/commands/provider.js +217 -0
- package/lib/commands/qlarity.js +19 -3
- package/lib/commands/quoxchat.js +13 -4
- package/lib/commands/quoxseo.js +69 -0
- package/lib/commands/reach.js +2 -1
- package/lib/commands/research.js +79 -0
- package/lib/commands/router.js +77 -0
- package/lib/commands/rows.js +367 -0
- package/lib/commands/run.js +82 -10
- package/lib/commands/scope.js +2 -2
- package/lib/commands/server.js +405 -0
- package/lib/commands/setup.js +33 -7
- package/lib/commands/shortcut.js +41 -0
- package/lib/commands/skills.js +68 -9
- package/lib/commands/slot.js +260 -7
- package/lib/commands/status.js +1 -1
- package/lib/commands/team.js +3 -1
- package/lib/commands/tips.js +23 -0
- package/lib/commands/tool.js +133 -45
- package/lib/commands/trace.js +12 -7
- package/lib/commands/trigger.js +95 -0
- package/lib/commands/update.js +46 -0
- package/lib/commands/vault.js +31 -8
- package/lib/commands/vm.js +237 -0
- package/lib/commands/voice.js +34 -3
- package/lib/commands/volt.js +45 -3
- package/lib/commands/walkthrough.js +32 -0
- package/lib/commands/watch.js +73 -21
- package/lib/commands/welcome.js +14 -0
- package/lib/commands/workflow.js +189 -32
- package/lib/commands/x.js +13 -4
- package/lib/commands/youtube.js +172 -0
- package/lib/core/actingAs.js +2 -2
- package/lib/core/actionItems.js +115 -0
- package/lib/core/activeSummary.js +186 -0
- package/lib/core/agentAlias.js +2 -0
- package/lib/core/agentFamilies.js +7 -0
- package/lib/core/aside.js +54 -0
- package/lib/core/askDecision.js +60 -0
- package/lib/core/auth.js +164 -13
- package/lib/core/callerSource.js +1 -1
- package/lib/core/cliBuild.js +62 -0
- package/lib/core/client.js +152 -35
- package/lib/core/commandRegistrars.js +130 -0
- package/lib/core/config.js +143 -25
- package/lib/core/customHats.js +168 -0
- package/lib/core/doneEngineFetch.js +8 -0
- package/lib/core/errors.js +329 -20
- package/lib/core/findingReconcile.js +90 -0
- package/lib/core/global-flags.js +105 -5
- package/lib/core/governedSession.js +1 -3
- package/lib/core/hyperion.js +102 -0
- package/lib/core/inboxResolution.js +65 -0
- package/lib/core/lazyCommands.js +4 -1
- package/lib/core/liveSessionsReport.js +1 -1
- package/lib/core/loopGlyph.js +97 -0
- package/lib/core/offload.js +533 -0
- package/lib/core/org-override.js +1 -1
- package/lib/core/orgResolve.js +70 -0
- package/lib/core/output.js +11 -11
- package/lib/core/peek.js +126 -0
- package/lib/core/profileUsers.js +51 -0
- package/lib/core/promptCancel.js +18 -0
- package/lib/core/repoPath.js +11 -0
- package/lib/core/residentSeed.js +3 -1
- 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 +12 -8
- package/lib/core/sessionsOverview.js +64 -0
- package/lib/core/shortcut.js +83 -0
- package/lib/core/slotKeeper.js +248 -3
- package/lib/core/slotWake.js +120 -0
- package/lib/core/supervisorEngine.js +71 -2
- package/lib/core/version.js +1 -1
- package/lib/core/vm.js +366 -0
- package/lib/core/vmTui.js +86 -0
- package/lib/core/walkthrough.js +35 -0
- package/lib/dragon/companionView.js +34 -0
- package/lib/dragon/frames.js +118 -0
- package/lib/dragon/jobs.js +123 -0
- package/lib/dragon/renderWorker.js +15 -0
- package/lib/dragon/select.js +72 -0
- package/lib/evidence/bundleExport.js +47 -0
- package/lib/evidence/bundleVerify.js +77 -0
- package/lib/hyperion/deck.js +29 -0
- package/lib/lucid/LucidCard.jsx +68 -0
- package/lib/lucid/LucidIntro.jsx +45 -58
- package/lib/lucid/cards.js +86 -0
- package/lib/lucid/markdown.js +81 -0
- package/lib/lucid/motion.js +56 -0
- package/lib/quoxon/EXTENSIONS.md +23 -0
- package/lib/quoxon/activity.js +14 -2
- package/lib/quoxon/aocl.js +117 -0
- package/lib/quoxon/api.js +690 -25
- package/lib/quoxon/app.js +3586 -250
- package/lib/quoxon/approvalFacts.js +96 -0
- package/lib/quoxon/approvalSentence.js +44 -0
- package/lib/quoxon/approvalsView.js +384 -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 +13 -6
- package/lib/quoxon/cells.js +53 -0
- package/lib/quoxon/commandShort.js +124 -0
- package/lib/quoxon/commands.js +429 -39
- package/lib/quoxon/connect.js +210 -23
- package/lib/quoxon/connectCard.js +19 -2
- package/lib/quoxon/consent.js +86 -0
- package/lib/quoxon/copy.js +4 -3
- package/lib/quoxon/countdownLine.js +20 -0
- package/lib/quoxon/deck.js +30 -0
- package/lib/quoxon/demo.autoplay.js +29 -0
- package/lib/quoxon/demo.fixtures.js +1 -1
- package/lib/quoxon/demo.js +46 -3
- package/lib/quoxon/devObserver.js +20 -0
- package/lib/quoxon/dividerAocl.js +192 -0
- package/lib/quoxon/dividerRule.js +57 -0
- package/lib/quoxon/dragonCompanion.js +255 -0
- package/lib/quoxon/dragonModes.js +151 -0
- package/lib/quoxon/dragonMoments.js +82 -0
- package/lib/quoxon/dragonReads.js +68 -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 +2 -2
- package/lib/quoxon/events.js +266 -26
- package/lib/quoxon/extensions.js +276 -0
- package/lib/quoxon/feedback.js +50 -0
- package/lib/quoxon/gallery.js +21 -7
- 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/inboxView.js +79 -0
- package/lib/quoxon/indicator.js +6 -2
- package/lib/quoxon/installCli.js +79 -0
- package/lib/quoxon/intent.js +12 -1
- package/lib/quoxon/keys.js +51 -8
- package/lib/quoxon/launcher.js +103 -0
- package/lib/quoxon/loopCard.js +456 -0
- package/lib/quoxon/loopCards.js +180 -0
- package/lib/quoxon/loopStream.js +87 -0
- package/lib/quoxon/main.js +101 -160
- package/lib/quoxon/markdown.js +45 -21
- 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 +132 -26
- package/lib/quoxon/modelPrefs.js +345 -0
- package/lib/quoxon/motion/clock.js +3 -2
- package/lib/quoxon/motion/level.js +91 -0
- package/lib/quoxon/mouse.js +222 -0
- package/lib/quoxon/noai.js +57 -0
- package/lib/quoxon/objectiveOffer.js +82 -0
- package/lib/quoxon/objects/away.js +72 -0
- package/lib/quoxon/objects/fetch.js +17 -5
- package/lib/quoxon/objects/fleet.js +149 -0
- package/lib/quoxon/objects/health.js +186 -0
- package/lib/quoxon/objects/index.js +46 -7
- package/lib/quoxon/objects/mirror.js +137 -0
- package/lib/quoxon/objects/model.js +33 -0
- package/lib/quoxon/objects/peek.js +17 -0
- package/lib/quoxon/objects/proof.js +12 -4
- 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/view.js +11 -0
- package/lib/quoxon/onboarding/copy.js +32 -4
- package/lib/quoxon/onboarding/credential.js +17 -4
- package/lib/quoxon/onboarding/dockerOffer.js +45 -0
- package/lib/quoxon/onboarding/failureCause.js +33 -0
- package/lib/quoxon/onboarding/finish.js +15 -0
- package/lib/quoxon/onboarding/index.js +34 -7
- package/lib/quoxon/onboarding/installRunner.js +64 -5
- package/lib/quoxon/onboarding/preflight.js +17 -3
- package/lib/quoxon/onboarding/probe.js +65 -0
- package/lib/quoxon/onboarding/shortcutOffer.js +28 -0
- package/lib/quoxon/onboarding/view.js +76 -19
- package/lib/quoxon/orgLabel.js +10 -0
- package/lib/quoxon/orgSwitch.js +59 -0
- package/lib/quoxon/ownBroadcast.js +22 -0
- package/lib/quoxon/palette.js +43 -0
- package/lib/quoxon/planSteps.js +51 -0
- package/lib/quoxon/print.js +12 -5
- 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 +20 -51
- package/lib/quoxon/qdragon.js +410 -0
- package/lib/quoxon/qdragonFly.js +62 -0
- package/lib/quoxon/qdragonScenes.js +282 -0
- package/lib/quoxon/qeyes.js +213 -0
- package/lib/quoxon/qmotion.js +75 -37
- package/lib/quoxon/render.js +740 -124
- package/lib/quoxon/resend.js +72 -0
- package/lib/quoxon/roster.js +117 -17
- package/lib/quoxon/route.js +6 -5
- package/lib/quoxon/rows.js +954 -0
- package/lib/quoxon/rowsStore.js +80 -0
- package/lib/quoxon/screenContext.js +150 -0
- package/lib/quoxon/screenFrames.js +254 -0
- package/lib/quoxon/serverChip.js +42 -0
- package/lib/quoxon/session.js +182 -2
- package/lib/quoxon/sessionDead.js +17 -0
- package/lib/quoxon/signin.js +125 -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 +94 -0
- package/lib/quoxon/slash/cliLeaves.json +1023 -0
- package/lib/quoxon/slash/compact.js +1 -1
- 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/evidenceCmd.js +34 -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 +13 -8
- package/lib/quoxon/slash/listView.js +3 -1
- package/lib/quoxon/slash/modelCmd.js +261 -0
- package/lib/quoxon/slash/palette.js +22 -8
- package/lib/quoxon/slash/paletteController.js +117 -7
- package/lib/quoxon/slash/panels.js +21 -6
- package/lib/quoxon/slash/picker.js +20 -2
- package/lib/quoxon/slash/qpeCmd.js +35 -0
- package/lib/quoxon/slash/restart.js +95 -13
- package/lib/quoxon/slash/resume.js +18 -1
- package/lib/quoxon/slash/rowCmd.js +157 -0
- package/lib/quoxon/slash/rowWalk.js +175 -0
- package/lib/quoxon/slash/settings.js +16 -6
- 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/todoCmd.js +122 -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/mapping.js +2 -1
- package/lib/quoxon/stray.js +22 -0
- package/lib/quoxon/suggestCommand.js +90 -0
- package/lib/quoxon/term.js +46 -11
- package/lib/quoxon/textBuffer.js +176 -2
- package/lib/quoxon/theme.js +58 -25
- package/lib/quoxon/tips.js +433 -0
- package/lib/quoxon/toolCards.js +30 -0
- package/lib/quoxon/toolError.js +41 -0
- package/lib/quoxon/transcript.js +42 -4
- package/lib/quoxon/web/qface.js +18 -10
- package/lib/quoxon/welcome.js +1 -1
- package/lib/quoxon/whatsnew.js +136 -0
- package/lib/quoxon/whatsnew.jsonl +134 -0
- package/lib/quoxon/windowOrg.js +123 -0
- package/lib/server/devServers.js +137 -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/views/HyperionDeck.jsx +79 -0
- package/lib/tui/views/LucidDeck.jsx +209 -217
- package/package.json +5 -1
- package/vendor/dragonlab/SOURCE +4 -0
- package/vendor/dragonlab/design/cipher/v1/cipher-master.svg +46 -0
- package/vendor/dragonlab/design/cipher/v2/character.mjs +49 -0
- package/vendor/dragonlab/design/cipher/v2/review.mjs +33 -0
- package/vendor/dragonlab/design/cipher/v2/watch.mjs +56 -0
- package/vendor/dragonlab/design/drago/v1/character.mjs +19 -0
- package/vendor/dragonlab/design/drago/v1/drago-master.svg +56 -0
- package/vendor/dragonlab/design/drago/v2/character.mjs +87 -0
- package/vendor/dragonlab/design/drago/v4/character.mjs +67 -0
- package/vendor/dragonlab/design/drago/v4/profile.mjs +35 -0
- package/vendor/dragonlab/design/drago/v4/review.mjs +33 -0
- package/vendor/dragonlab/design/drago/v4/watch.mjs +56 -0
- package/vendor/dragonlab/design/hyperion/v1/hyperion-master.svg +56 -0
- package/vendor/dragonlab/design/hyperion/v2/character.mjs +79 -0
- package/vendor/dragonlab/design/hyperion/v2/review.mjs +33 -0
- package/vendor/dragonlab/design/hyperion/v2/watch.mjs +56 -0
- package/vendor/dragonlab/design/lucid/recovery/arrival.mjs +22 -0
- package/vendor/dragonlab/design/lucid/recovery/character.mjs +106 -0
- package/vendor/dragonlab/design/lucid/recovery/layout.mjs +50 -0
- package/vendor/dragonlab/design/lucid/recovery/lucid-master.svg +78 -0
- package/vendor/dragonlab/design/lucid/recovery/motion.mjs +42 -0
- package/vendor/dragonlab/design/lucid/recovery/render.mjs +121 -0
- package/vendor/dragonlab/design/lucid/recovery/review.mjs +68 -0
- package/vendor/dragonlab/design/lucid/recovery/verify.mjs +84 -0
- package/vendor/dragonlab/design/lucid/recovery/watch.mjs +56 -0
- package/vendor/dragonlab/design/seer/v1/seer-master.svg +53 -0
- package/vendor/dragonlab/design/seer/v2/character.mjs +88 -0
- package/vendor/dragonlab/design/seer/v3/character.mjs +33 -0
- package/vendor/dragonlab/design/seer/v4/character.mjs +66 -0
- package/vendor/dragonlab/design/seer/v4/review.mjs +33 -0
- package/vendor/dragonlab/design/seer/v4/watch.mjs +56 -0
- package/vendor/dragonlab/design/stage3/companion-review.mjs +28 -0
- package/vendor/dragonlab/design/stage3/sentinel-art.js +39 -0
- package/vendor/dragonlab/design/stage3/sentinel-braille.js +216 -0
- package/vendor/dragonlab/design/stage3/sentinel-character.js +257 -0
- package/vendor/dragonlab/design/stage3/sentinel-icon.js +103 -0
- package/vendor/dragonlab/design/stage3/sentinel-warden-eyes.js +95 -0
- package/vendor/dragonlab/design/stage3/svg-coverage.js +148 -0
- package/vendor/dragonlab/factory/svg-rig.mjs +63 -0
- package/vendor/dragonlab/integration/companions-v1/characters.mjs +88 -0
- package/vendor/dragonlab/integration/companions-v1/cipher.mjs +2 -0
- package/vendor/dragonlab/integration/companions-v1/companion.mjs +63 -0
- package/vendor/dragonlab/integration/companions-v1/drago.mjs +2 -0
- package/vendor/dragonlab/integration/companions-v1/hyperion.mjs +2 -0
- package/vendor/dragonlab/integration/companions-v1/lucid.mjs +2 -0
- package/vendor/dragonlab/integration/companions-v1/seer.mjs +2 -0
- package/vendor/dragonlab/integration/companions-v1/sentinel.mjs +2 -0
- package/vendor/dragonlab/integration/companions-v1/view.mjs +28 -0
- package/vendor/dragonlab/integration/hyperion-v3/activity.mjs +76 -0
- package/vendor/dragonlab/lib/power-effects.js +294 -0
- package/vendor/dragonlab/lib/power-registry.js +74 -0
- package/vendor/dragonlab/vendor/quox-dragon/qart.js +348 -0
- package/vendor/dragonlab/vendor/quox-dragon/qeyes.js +213 -0
- package/lib/core/websiteSession.js +0 -148
package/lib/quoxon/markdown.js
CHANGED
|
@@ -13,23 +13,14 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import React from 'react';
|
|
15
15
|
import { Box, Text, Transform } from 'ink';
|
|
16
|
-
import { Lexer } from 'marked';
|
|
17
16
|
import { graphemes } from './textBuffer.js';
|
|
18
|
-
import { c, mono,
|
|
17
|
+
import { c, mono, gradient, bulletRole } from './theme.js';
|
|
19
18
|
|
|
20
19
|
const h = React.createElement;
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
import { lex, splitSettled } from './markdownSettle.js';
|
|
23
22
|
|
|
24
|
-
export
|
|
25
|
-
const tokens = lex(text);
|
|
26
|
-
let last = -1;
|
|
27
|
-
for (let i = tokens.length - 1; i >= 0; i--) if (tokens[i].type !== 'space') { last = i; break; }
|
|
28
|
-
if (last <= 0) return { settled: '', rest: text };
|
|
29
|
-
let off = 0;
|
|
30
|
-
for (let i = 0; i < last; i++) off += tokens[i].raw.length;
|
|
31
|
-
return { settled: text.slice(0, off), rest: text.slice(off) };
|
|
32
|
-
}
|
|
23
|
+
export { lex, splitSettled }; // QUOXON-LATENCY: defined in markdownSettle.js so --print never loads Ink
|
|
33
24
|
|
|
34
25
|
export function healInline(text) {
|
|
35
26
|
let t = text;
|
|
@@ -128,22 +119,55 @@ function inline(tokens = [], style = {}, key = 'i') {
|
|
|
128
119
|
const w = (s) => graphemes(s).length;
|
|
129
120
|
const padTo = (s, n) => s + ' '.repeat(Math.max(0, n - w(s)));
|
|
130
121
|
|
|
131
|
-
/**
|
|
122
|
+
/** Hard-wrap plain text to `width` columns at word boundaries (long words split). Never drops text. Always >= 1 line. */
|
|
123
|
+
export function wrapCell(text, width) {
|
|
124
|
+
const width_ = Math.max(1, width);
|
|
125
|
+
const out = [];
|
|
126
|
+
for (const para of String(text ?? '').split('\n')) {
|
|
127
|
+
let cur = '';
|
|
128
|
+
for (const word of para.split(/\s+/).filter(Boolean)) {
|
|
129
|
+
let g = graphemes(word).map(x => x.text);
|
|
130
|
+
if (cur && w(cur) + 1 + g.length <= width_) { cur += ' ' + word; continue; }
|
|
131
|
+
if (cur) { out.push(cur); cur = ''; }
|
|
132
|
+
while (g.length > width_) { out.push(g.slice(0, width_).join('')); g = g.slice(width_); }
|
|
133
|
+
cur = g.join('');
|
|
134
|
+
}
|
|
135
|
+
out.push(cur);
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Plain-text table layout: { mode: 'grid'|'vertical', lines: [{ text, head?, rule? }] }. Pure, for tests.
|
|
142
|
+
* Grid when it fits, else vertical key/value blocks whose values wrap under a hanging indent. No cell is ever truncated
|
|
143
|
+
* (TUI-UX #3: the grounding warning named an id that sat in a clipped cell).
|
|
144
|
+
*/
|
|
132
145
|
export function layoutTable(header, rows, cols) {
|
|
133
146
|
const n = header.length;
|
|
134
147
|
const widths = header.map((hd, i) => Math.max(w(hd), ...rows.map(r => w(r[i] ?? '')), 1));
|
|
135
148
|
const total = widths.reduce((a, b) => a + b, 0) + 3 * (n - 1);
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
149
|
+
const gridLines = (ws) => {
|
|
150
|
+
const cellLines = (r) => {
|
|
151
|
+
const cells = r.map((cell, i) => wrapCell(cell ?? '', ws[i]));
|
|
152
|
+
const h_ = Math.max(...cells.map(x => x.length));
|
|
153
|
+
return Array.from({ length: h_ }, (_, k) => cells.map((x, i) => padTo(x[k] ?? '', ws[i])).join(' │ ').replace(/\s+$/, ''));
|
|
154
|
+
};
|
|
155
|
+
const rule = ws.map(x => '─'.repeat(x)).join('─┼─');
|
|
156
|
+
return [...cellLines(header).map(text => ({ text, head: true })), { text: rule, rule: true }, ...rows.flatMap(r => cellLines(r).map(text => ({ text })))];
|
|
157
|
+
};
|
|
158
|
+
if (total <= cols) return { mode: 'grid', lines: gridLines(widths) };
|
|
159
|
+
// vertical key: value, one block per row; values wrap under a hanging indent
|
|
142
160
|
const lines = [];
|
|
143
161
|
const keyW = Math.min(Math.max(...header.map(w)), Math.floor(cols / 3));
|
|
162
|
+
const valW = Math.max(8, cols - keyW - 2);
|
|
144
163
|
rows.forEach((r, ri) => {
|
|
145
164
|
if (ri) lines.push({ text: '' });
|
|
146
|
-
header.forEach((hd, i) =>
|
|
165
|
+
header.forEach((hd, i) => {
|
|
166
|
+
const keyLines = wrapCell(hd, keyW);
|
|
167
|
+
const val = wrapCell(r[i] ?? '', valW);
|
|
168
|
+
const count = Math.max(keyLines.length, val.length);
|
|
169
|
+
for (let k = 0; k < count; k++) lines.push({ text: `${padTo(keyLines[k] ?? '', keyW)} ${val[k] ?? ''}`.replace(/\s+$/, ''), key: k === 0 ? keyW : undefined });
|
|
170
|
+
});
|
|
147
171
|
});
|
|
148
172
|
return { mode: 'vertical', lines };
|
|
149
173
|
}
|
|
@@ -153,7 +177,7 @@ function Table({ t, cols }) {
|
|
|
153
177
|
const rows = t.rows.map(r => r.map(x => inlineText(x.tokens)));
|
|
154
178
|
const lay = layoutTable(header, rows, cols);
|
|
155
179
|
return h(Box, { flexDirection: 'column' }, ...lay.lines.map((l, i) => h(Text, {
|
|
156
|
-
key: i, bold: l.head, color: l.rule ? c('muted') : (l.head ? c('label') : undefined), wrap: '
|
|
180
|
+
key: i, bold: l.head, color: l.rule ? c('muted') : (l.head ? c('label') : undefined), wrap: 'wrap'
|
|
157
181
|
}, l.text || ' ')));
|
|
158
182
|
}
|
|
159
183
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The streaming split, without the renderer. events.js (and so `quox --print`) needs only
|
|
3
|
+
* splitSettled; importing it from markdown.js loaded React + Ink (~2 s cold) on every
|
|
4
|
+
* headless turn before the request was even sent (QUOXON-LATENCY). markdown.js re-exports
|
|
5
|
+
* both names, so the interactive client is unchanged.
|
|
6
|
+
*/
|
|
7
|
+
import { Lexer } from 'marked';
|
|
8
|
+
|
|
9
|
+
export const lex = (src) => new Lexer({ gfm: true, breaks: false }).lex(src);
|
|
10
|
+
|
|
11
|
+
export function splitSettled(text) {
|
|
12
|
+
const tokens = lex(text);
|
|
13
|
+
let last = -1;
|
|
14
|
+
for (let i = tokens.length - 1; i >= 0; i--) if (tokens[i].type !== 'space') { last = i; break; }
|
|
15
|
+
if (last <= 0) return { settled: '', rest: text };
|
|
16
|
+
let off = 0;
|
|
17
|
+
for (let i = 0; i < last; i++) off += tokens[i].raw.length;
|
|
18
|
+
return { settled: text.slice(0, off), rest: text.slice(off) };
|
|
19
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Vendored from ~/cli.quox.ai/matrix/domains.json (the proof matrix, 40 domain ids). Source: https://github.com/quoxai/cli.quox.ai matrix/domains.json. Tips name a domain from this list so the matrix can ingest them. When the matrix becomes canonical this file is replaced by the matrix export.",
|
|
3
|
+
"domains": [
|
|
4
|
+
"chat",
|
|
5
|
+
"providers",
|
|
6
|
+
"approvals",
|
|
7
|
+
"receipts",
|
|
8
|
+
"safety",
|
|
9
|
+
"hats",
|
|
10
|
+
"fleet",
|
|
11
|
+
"proxmox",
|
|
12
|
+
"monitoring",
|
|
13
|
+
"lucid",
|
|
14
|
+
"memory",
|
|
15
|
+
"qortex",
|
|
16
|
+
"vault",
|
|
17
|
+
"agents",
|
|
18
|
+
"workflows",
|
|
19
|
+
"skills",
|
|
20
|
+
"objectives",
|
|
21
|
+
"mail",
|
|
22
|
+
"calendar",
|
|
23
|
+
"contacts",
|
|
24
|
+
"notes",
|
|
25
|
+
"actions",
|
|
26
|
+
"voice",
|
|
27
|
+
"quoxchat",
|
|
28
|
+
"seo",
|
|
29
|
+
"plan",
|
|
30
|
+
"signal",
|
|
31
|
+
"browser",
|
|
32
|
+
"lens",
|
|
33
|
+
"social",
|
|
34
|
+
"comms",
|
|
35
|
+
"sessions",
|
|
36
|
+
"code",
|
|
37
|
+
"security",
|
|
38
|
+
"spend",
|
|
39
|
+
"files",
|
|
40
|
+
"plugins",
|
|
41
|
+
"identity",
|
|
42
|
+
"install",
|
|
43
|
+
"compliance",
|
|
44
|
+
"mind"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @mention completion in the composer (MENTIONS). Typing `@` at the start of a word suggests agents, fleet hosts,
|
|
3
|
+
* tasks (objectives) and receipts (this session's own tool-call envelopes). The remote lists are fetched ONCE per
|
|
4
|
+
* session on the first `@`, then every keystroke filters the cache: no request per key. A failed fetch is quiet
|
|
5
|
+
* (that kind just has no rows) and is retried at most every RETRY_MS. Tab or Enter accepts, Esc closes.
|
|
6
|
+
*/
|
|
7
|
+
export const RETRY_MS = 30000;
|
|
8
|
+
export const KIND_ORDER = ['agent', 'host', 'task', 'receipt'];
|
|
9
|
+
|
|
10
|
+
/** The @word being typed at the end of the draft -> { start (index after '@'), partial } or null. */
|
|
11
|
+
export function mentionContext(draft) {
|
|
12
|
+
const t = String(draft ?? '');
|
|
13
|
+
const m = t.match(/(^|\s)@([^\s@]*)$/);
|
|
14
|
+
if (!m) return null;
|
|
15
|
+
return { start: t.length - m[2].length, partial: m[2] };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const clean = (s) => String(s ?? '').replace(/\s+/g, ' ').trim();
|
|
19
|
+
|
|
20
|
+
/** api -> [{ value, kind, label }] from the session's remote sources, never throwing; failures named per kind. */
|
|
21
|
+
export async function loadMentions(api) {
|
|
22
|
+
const kinds = {
|
|
23
|
+
agent: async () => (await api.agents()).map(a => ({ value: String(a.agent_id), kind: 'agent', label: a.name && a.name !== a.agent_id ? clean(a.name) : '' })),
|
|
24
|
+
host: async () => {
|
|
25
|
+
const none = { status: 'absent', value: [] };
|
|
26
|
+
const [inv, beat] = await Promise.all([api.mentionHosts, api.objects?.fleetNames].map((fn, i) => (fn ? Promise.allSettled([i ? api.objects.fleetNames() : api.mentionHosts()]).then(r => r[0]) : none)));
|
|
27
|
+
const tried = [inv, beat].filter(r => r.status !== 'absent');
|
|
28
|
+
if (tried.length && tried.every(r => r.status === 'rejected')) throw tried[0].reason;
|
|
29
|
+
const out = (inv.status === 'fulfilled' ? inv.value : []).map(h => ({ value: String(h.id), kind: 'host', label: clean([h.group, h.health].filter(Boolean).join(' · ')) }));
|
|
30
|
+
for (const h of beat.status === 'fulfilled' ? beat.value || [] : []) if (!out.some(o => o.value === String(h.value))) out.push({ value: String(h.value), kind: 'host', label: clean(h.desc) });
|
|
31
|
+
return out;
|
|
32
|
+
},
|
|
33
|
+
task: async () => ((await api.mentionTasks?.()) || []).map(o => ({ value: String(o.id), kind: 'task', label: clean(`${o.title || ''}${o.status ? ` (${o.status})` : ''}`) })),
|
|
34
|
+
};
|
|
35
|
+
const out = []; const failed = [];
|
|
36
|
+
await Promise.all(Object.entries(kinds).map(async ([k, fn]) => {
|
|
37
|
+
try { out.push(...(await fn()).filter(x => x.value && /^[\w.:-]+$/.test(x.value))); } catch { failed.push(k); }
|
|
38
|
+
}));
|
|
39
|
+
return { items: out, failed };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** This session's tool calls that carry an envelope id: their receipts, newest first. Local, no request. */
|
|
43
|
+
export function receiptMentions(items) {
|
|
44
|
+
const seen = new Set(); const out = [];
|
|
45
|
+
for (const b of [...(items || [])].reverse()) {
|
|
46
|
+
if (!b || b.kind !== 'tool' || !b.envelopeId || seen.has(b.envelopeId)) continue;
|
|
47
|
+
seen.add(b.envelopeId);
|
|
48
|
+
out.push({ value: String(b.envelopeId), kind: 'receipt', label: clean(`${b.tool || 'tool call'}${b.status ? ` ${b.status}` : ''}`) });
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Prefix on the value first, then a substring of the value or its label; agents, hosts, tasks, receipts in that order. */
|
|
54
|
+
export function rankMentions(items, partial, max = 50) {
|
|
55
|
+
const q = String(partial || '').toLowerCase();
|
|
56
|
+
const seen = new Set();
|
|
57
|
+
const uniq = (items || []).filter(i => i?.value && !seen.has(`${i.kind}:${i.value}`) && seen.add(`${i.kind}:${i.value}`));
|
|
58
|
+
const order = (a, b) => KIND_ORDER.indexOf(a.kind) - KIND_ORDER.indexOf(b.kind);
|
|
59
|
+
if (!q) return uniq.sort(order).slice(0, max);
|
|
60
|
+
const pre = uniq.filter(i => i.value.toLowerCase().startsWith(q)).sort(order);
|
|
61
|
+
const sub = uniq.filter(i => !i.value.toLowerCase().startsWith(q) && (i.value.toLowerCase().includes(q) || i.label.toLowerCase().includes(q))).sort(order);
|
|
62
|
+
const out = [...pre, ...sub];
|
|
63
|
+
return out.length === 1 && out[0].value.toLowerCase() === q ? [] : out.slice(0, max);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Accepting a mention: replace the partial word, add one space. */
|
|
67
|
+
export const applyMention = (draft, cx, value) => String(draft).slice(0, cx.start) + value + ' ';
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* One cache for the session. items() returns what is loaded (never blocks) and starts the single load the first
|
|
71
|
+
* time it is asked; a failed kind is retried no sooner than RETRY_MS. loads() counts fetches (tests, /status).
|
|
72
|
+
*/
|
|
73
|
+
export function createMentionCache({ load, refresh = () => {}, now = Date.now, retryMs = RETRY_MS }) {
|
|
74
|
+
let items = []; let state = 'idle'; let failedAt = 0; let loads = 0;
|
|
75
|
+
const start = () => {
|
|
76
|
+
state = 'loading'; loads++;
|
|
77
|
+
Promise.resolve().then(load).then(
|
|
78
|
+
(r) => { items = r?.items || []; state = r?.failed?.length ? 'partial' : 'ready'; if (state === 'partial') failedAt = now(); },
|
|
79
|
+
() => { state = 'failed'; failedAt = now(); }
|
|
80
|
+
).then(() => refresh());
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
items() {
|
|
84
|
+
if (state === 'idle' || ((state === 'failed' || state === 'partial') && now() - failedAt >= retryMs)) start();
|
|
85
|
+
return items;
|
|
86
|
+
},
|
|
87
|
+
state: () => state,
|
|
88
|
+
loads: () => loads,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /mind: QuoxMind cognitive implants, read from the collector (same data as `quox mind`).
|
|
3
|
+
* Pure: takes api.mind() output, returns [[text, tone]]. Implants with nothing recorded
|
|
4
|
+
* say "no activity recorded"; nothing is invented. Lines are not clipped: notes wrap to the
|
|
5
|
+
* terminal width, so a long description reads in full (owner drive 2026-10-15).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const MARK = { healthy: '✔', degraded: '⚠', weak: '⚠', collecting: '◐', 'not-reported': '·', unreachable: '✖', 'license-required': '⛔' };
|
|
9
|
+
|
|
10
|
+
/** The 14 implant short ids (the collector's registry, in order). Used for help and for "did you mean". */
|
|
11
|
+
export const MIND_IMPLANTS = ['sense', 'repobrain', 'memory', 'temporal', 'focus', 'value', 'guard', 'qortex', 'insight', 'executive', 'predict', 'reflect', 'dream', 'learn'];
|
|
12
|
+
const SHORT_OF = { 'quox-nucleus': 'repobrain', 'quox-brain2': 'qortex' };
|
|
13
|
+
const shortOf = (id) => SHORT_OF[id] || String(id).replace(/^quox-/, '');
|
|
14
|
+
|
|
15
|
+
export const MIND_HELP_ARGS = new Set(['help', '-h', '--help', '?']);
|
|
16
|
+
|
|
17
|
+
/** /mind help: the forms and the implant ids. No server call. */
|
|
18
|
+
export function mindHelpLines() {
|
|
19
|
+
return [
|
|
20
|
+
['/mind lists every QuoxMind implant with its status and last activity. Read-only, no model call.'],
|
|
21
|
+
['/mind <implant> shows one implant in full: what it does, how it grows, its metrics.'],
|
|
22
|
+
[`Implants: ${MIND_IMPLANTS.join(', ')}.`],
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A failed /mind call as plain lines. A 404 "unknown implant" names the implant that does not exist,
|
|
28
|
+
* lists the real ones, and points at a TUI command of the same name when there is one (/mind doctor -> /doctor).
|
|
29
|
+
* Any other failure reports the server's own reason, not just "Request failed with status N".
|
|
30
|
+
*/
|
|
31
|
+
export function mindErrorLines(e, arg, { isCommand = () => false } = {}) {
|
|
32
|
+
const body = e?.body && typeof e.body === 'object' ? e.body : {};
|
|
33
|
+
const reason = body.error || body.message || (typeof e?.code === 'string' && !/^E[A-Z]/.test(e.code) ? e.code : '') || e?.message || 'failed';
|
|
34
|
+
if (arg && (e?.status === 404 || /unknown implant/i.test(reason))) {
|
|
35
|
+
const ids = Array.isArray(body.valid) && body.valid.length ? body.valid.map(shortOf) : MIND_IMPLANTS;
|
|
36
|
+
const out = [[`No implant called "${arg}". /mind <implant> shows one implant's status (read-only).`, 'warn'],
|
|
37
|
+
[`Implants: ${ids.join(', ')}.`]];
|
|
38
|
+
const cmd = String(arg).split(/\s+/)[0].toLowerCase();
|
|
39
|
+
if (isCommand(cmd)) out.push([`For the ${cmd} command, use /${cmd}.`]);
|
|
40
|
+
else out.push(['/mind on its own lists them all.']);
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
return [[`mind: ${e?.status ? `HTTP ${e.status}: ` : ''}${reason}`, 'error']];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Relative "fired" time for an ISO timestamp; 'never' when null. `now` is injectable for tests. */
|
|
47
|
+
export function fmtFired(iso, now = Date.now()) {
|
|
48
|
+
if (!iso) return 'never';
|
|
49
|
+
const t = Date.parse(iso);
|
|
50
|
+
if (Number.isNaN(t)) return String(iso);
|
|
51
|
+
const s = Math.max(0, Math.round((now - t) / 1000));
|
|
52
|
+
if (s < 60) return 'just now';
|
|
53
|
+
if (s < 3600) return `${Math.floor(s / 60)}m ago`;
|
|
54
|
+
if (s < 86400) return `${Math.floor(s / 3600)}h ago`;
|
|
55
|
+
return `${Math.floor(s / 86400)}d ago`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The firing evidence for one implant (QUOXMIND-PROOF): last fired + 7-day count from the server.
|
|
60
|
+
* Returns null when the server predates the evidence fields, so the old line is kept.
|
|
61
|
+
*/
|
|
62
|
+
function firingText(i, now) {
|
|
63
|
+
if (!('fired_7d' in i)) return null;
|
|
64
|
+
if (i.activity_error) return `firing unknown: ${i.activity_error}`;
|
|
65
|
+
if (typeof i.fired_7d !== 'number') return 'firing not tracked';
|
|
66
|
+
const idle = typeof i.idle_runs_7d === 'number' && i.idle_runs_7d > 0 ? ` (${i.idle_runs_7d} idle runs)` : '';
|
|
67
|
+
return `${i.last_fired ? `fired ${fmtFired(i.last_fired, now)}` : 'never fired'} · 7d ${i.fired_7d}${idle}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function mindLines(d, { now = Date.now() } = {}) {
|
|
71
|
+
const out = [];
|
|
72
|
+
const add = (t, tone) => out.push([t, tone]);
|
|
73
|
+
if (d.implant) {
|
|
74
|
+
const i = d.implant;
|
|
75
|
+
add(`${MARK[i.status] || '·'} ${i.name} (${i.short}) · ${i.status}${i.tier ? ` · ${i.tier}` : ''}`);
|
|
76
|
+
add(` ${i.description || i.purpose}`);
|
|
77
|
+
if (i.inspired_by) add(` inspired by: ${i.inspired_by}`);
|
|
78
|
+
if (i.summary) add(` now: ${i.summary}`);
|
|
79
|
+
add(` ${i.activity}`);
|
|
80
|
+
const fired = firingText(i, now);
|
|
81
|
+
if (fired && typeof i.fired_7d === 'number') add(` fired: ${fmtFired(i.last_fired, now)}${i.last_fired ? ` (${i.last_fired})` : ''} · 7d ${i.fired_7d}${i.activity_source ? ` · from ${i.activity_source}` : ''}`);
|
|
82
|
+
else if (fired) add(` ${fired}`);
|
|
83
|
+
if (i.how_to_grow) add(` how it grows: ${i.how_to_grow}`);
|
|
84
|
+
if (Array.isArray(i.connected_to) && i.connected_to.length) add(` connected to: ${i.connected_to.map(shortOf).join(', ')}`);
|
|
85
|
+
for (const [k, v] of Object.entries(i.metrics || {})) if (v !== null && typeof v !== 'object') add(` ${k}: ${typeof v === 'number' && !Number.isInteger(v) ? Math.round(v * 100) / 100 : v}`);
|
|
86
|
+
const others = MIND_IMPLANTS.filter(s => s !== i.short);
|
|
87
|
+
add(`This is ${i.name}'s status, read-only: nothing runs. /mind for all; others: ${others.map(s => `/mind ${s}`).join(', ')}.`, 'dim');
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
const list = d.implants || [];
|
|
91
|
+
add(`QuoxMind: ${list.length} cognitive implants`);
|
|
92
|
+
for (const i of list) {
|
|
93
|
+
const fired = firingText(i, now);
|
|
94
|
+
const tail = fired !== null
|
|
95
|
+
? `${fired}${typeof i.fired_7d === 'number' && !i.activity_error && i.summary && i.activity !== 'no activity recorded' ? ` · ${i.summary}` : ''}`
|
|
96
|
+
: (i.activity === 'no activity recorded' ? 'no activity recorded' : i.summary || i.activity);
|
|
97
|
+
add(`${MARK[i.status] || '·'} ${i.short.padEnd(10)} ${i.status.padEnd(13)} ${tail}`, i.status === 'unreachable' ? 'warn' : undefined);
|
|
98
|
+
}
|
|
99
|
+
const h = d.health;
|
|
100
|
+
if (h && typeof h.fired_7d_total === 'number') add(`${h.fired_7d_implants} of ${list.length} fired in the last 7 days (${h.fired_7d_total} firings), ${h.silent_7d} silent, ${h.activity_unknown} not tracked. /mind <id> for one.`);
|
|
101
|
+
else if (h) add(`${h.with_activity} with activity, ${h.no_activity} with none recorded${h.average_health !== null ? `, average health ${h.average_health}` : ''}. /mind <id> for one.`);
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /mode (owner 2026-10-16 "/say quoxon a but log b"): this window's mode.
|
|
3
|
+
* ask (default) Quox asks you before it acts; what needs approval is your org's policy.
|
|
4
|
+
* plan Quox investigates (read tools) and proposes the steps and exact commands; it runs nothing that
|
|
5
|
+
* changes state. The SERVER enforces it: the turn carries mode 'plan' (lib/planMode.js in the collector).
|
|
6
|
+
* auto not built. Logged as a plan: it needs standing grants first.
|
|
7
|
+
* Window-scoped: carried across /restart (QUOX_RESTART_MODE), never written to the shared profile.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const MODES = ['ask', 'plan'];
|
|
11
|
+
export const AUTO_NOT_YET = 'not available yet: auto mode needs standing grants (planned).';
|
|
12
|
+
export const PLAN_GO = 'go ahead with the plan';
|
|
13
|
+
|
|
14
|
+
/** -> 'plan' | 'ask' (anything else, including 'auto', is 'ask'). */
|
|
15
|
+
export function normMode(v) {
|
|
16
|
+
return String(v || '').trim().toLowerCase() === 'plan' ? 'plan' : 'ask';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const DESC = {
|
|
20
|
+
ask: 'ask first: Quox asks you before it acts. What needs your approval is your org\'s policy on the server (/approvals lists what is waiting).',
|
|
21
|
+
plan: 'plan only: Quox investigates with read tools and proposes the steps and the exact commands. It runs nothing that changes state; the server enforces it.',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** One line per mode for the arrow-key chooser (the same one /model uses). Auto is not offered: it is not built. */
|
|
25
|
+
export const MODE_ROWS = [
|
|
26
|
+
{ id: 'ask', text: 'ask first: Quox asks before it acts' },
|
|
27
|
+
{ id: 'plan', text: 'plan only: Quox proposes the steps and runs nothing that changes state' },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Pure: the reply to `/mode [arg]` given the current mode.
|
|
32
|
+
* -> { text, tone, mode? } where mode is set only when it changes.
|
|
33
|
+
*/
|
|
34
|
+
export function modeReply(arg, current) {
|
|
35
|
+
const cur = normMode(current);
|
|
36
|
+
const a = String(arg || '').trim().toLowerCase();
|
|
37
|
+
if (!a || /^(-h|--help|help|\?)$/.test(a)) {
|
|
38
|
+
return { tone: null, text: `mode ${DESC[cur]}\nOptions: /mode ask (the default), /mode plan (plan only). Auto mode is ${AUTO_NOT_YET}` };
|
|
39
|
+
}
|
|
40
|
+
if (a === 'auto') return { tone: 'warn', text: `/mode auto is ${AUTO_NOT_YET} Options: /mode ask, /mode plan.` };
|
|
41
|
+
if (!MODES.includes(a)) return { tone: 'warn', text: `Unknown mode '${clipWord(a)}'. Options: /mode ask, /mode plan.` };
|
|
42
|
+
if (a === cur) return { tone: 'dim', text: `Already in mode ${DESC[cur]}` };
|
|
43
|
+
return { mode: a, tone: 'ok', text: a === 'plan' ? `mode ${DESC.plan} /mode ask to go back.` : `mode ${DESC.ask}` };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function clipWord(w) { return w.length > 20 ? `${w.slice(0, 19)}…` : w; }
|