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,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invitation commands (GRIPE-712): list and accept the caller's own pending
|
|
3
|
+
* invitations without needing the emailed token.
|
|
4
|
+
*/
|
|
5
|
+
import { formatOutput, printSuccess } from '../core/output.js';
|
|
6
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
7
|
+
|
|
8
|
+
export function registerInvitesCommands(program, ctx) {
|
|
9
|
+
const { client, auth } = ctx;
|
|
10
|
+
|
|
11
|
+
const invites = program.command('invites').description('Your pending organization invitations');
|
|
12
|
+
|
|
13
|
+
invites
|
|
14
|
+
.command('list')
|
|
15
|
+
.description('List pending invitations addressed to your verified email')
|
|
16
|
+
.action(async () => {
|
|
17
|
+
auth.requireAuth();
|
|
18
|
+
const ep = resolveEndpoint('invites.mine.list');
|
|
19
|
+
const data = await client.get(ep.path, { service: ep.service });
|
|
20
|
+
const rows = (data.invites || []).map(i => ({
|
|
21
|
+
id: i.id,
|
|
22
|
+
organization: i.organization?.name || i.organization?.slug || '',
|
|
23
|
+
role: i.role,
|
|
24
|
+
invited_by: i.invited_by || '',
|
|
25
|
+
expires_at: i.expires_at || '',
|
|
26
|
+
}));
|
|
27
|
+
formatOutput({
|
|
28
|
+
columns: ['id', 'organization', 'role', 'invited_by', 'expires_at'],
|
|
29
|
+
headers: ['ID', 'Organization', 'Role', 'Invited by', 'Expires'],
|
|
30
|
+
rows,
|
|
31
|
+
}, { format: program.opts().output });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
invites
|
|
35
|
+
.command('accept')
|
|
36
|
+
.description('Accept a pending invitation by id (no emailed token needed)')
|
|
37
|
+
.argument('<id>', 'invitation id from `quox invites list`')
|
|
38
|
+
.action(async (id) => {
|
|
39
|
+
auth.requireAuth();
|
|
40
|
+
const ep = resolveEndpoint('invites.mine.accept', { inviteId: id });
|
|
41
|
+
const data = await client.post(ep.path, { service: ep.service, body: {} });
|
|
42
|
+
const org = data.organization;
|
|
43
|
+
printSuccess(`${data.message || 'Invite accepted'}${org?.name ? `: ${org.name}` : ''}. Run \`quox org switch ${org?.id || '<orgId>'}\` to use it.`);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `quox licence` (alias `license`), GRIPE-715: governed, audited licence
|
|
3
|
+
* operations from the terminal.
|
|
4
|
+
*
|
|
5
|
+
* Phase 1 (instance-local): status reads the lease (never the key), refresh
|
|
6
|
+
* runs the renewal, seats lists/cleans band holders (dry run default).
|
|
7
|
+
*
|
|
8
|
+
* Phase 2 (owner-only vendor tooling for the quox.ai website) lives in
|
|
9
|
+
* lib/vendor/licenceOwner.js and is registered only when that file is present.
|
|
10
|
+
* lib/vendor/ is excluded from the npm package (quox#1134): the public build
|
|
11
|
+
* never carries it.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { formatOutput, formatDetail, printSuccess, printInfo, printWarning } from '../core/output.js';
|
|
15
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
16
|
+
import { QuoxValidationError } from '../core/errors.js';
|
|
17
|
+
|
|
18
|
+
// quox#1134: the owner-only website verbs are vendor tooling, kept out of the published package (package.json
|
|
19
|
+
// "files" excludes lib/vendor/). Present in the dev tree, absent for every npm user.
|
|
20
|
+
let VENDOR_OWNER = null;
|
|
21
|
+
try {
|
|
22
|
+
VENDOR_OWNER = await import('../vendor/licenceOwner.js');
|
|
23
|
+
} catch (e) {
|
|
24
|
+
if (!(e?.code === 'ERR_MODULE_NOT_FOUND' && String(e?.message || '').includes('licenceOwner'))) throw e;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function registerLicenceCommands(program, ctx, { owner = VENDOR_OWNER } = {}) {
|
|
28
|
+
const { client, auth } = ctx;
|
|
29
|
+
const fetchImpl = ctx.websiteFetch || globalThis.fetch;
|
|
30
|
+
const json = () => program.opts().output === 'json';
|
|
31
|
+
|
|
32
|
+
const licence = program
|
|
33
|
+
.command('licence')
|
|
34
|
+
.alias('license')
|
|
35
|
+
.description('Instance licence status, lease refresh and seat bands')
|
|
36
|
+
.action(() => { licence.help(); });
|
|
37
|
+
if (owner) licence.addHelpText('after', owner.OWNER_HELP);
|
|
38
|
+
|
|
39
|
+
licence
|
|
40
|
+
.command('status')
|
|
41
|
+
.description('Licence id, plan, lease timestamps, governed count, entitled list with seat usage')
|
|
42
|
+
.option('--plugin <id>', 'limit to one plugin')
|
|
43
|
+
.action(async (opts) => {
|
|
44
|
+
auth.requireAuth();
|
|
45
|
+
const ep = resolveEndpoint('setup.licensing.status');
|
|
46
|
+
const d = await client.get(ep.path, { service: ep.service });
|
|
47
|
+
const bands = d.org_bands || {};
|
|
48
|
+
const pick = (id) => !opts.plugin || id === opts.plugin;
|
|
49
|
+
const entitled = (d.entitlements || []).filter(pick).map((id) => {
|
|
50
|
+
const b = bands[id];
|
|
51
|
+
return { plugin: id, seats: b ? `${b.assigned_count}/${b.allowance}` : 'whole install' };
|
|
52
|
+
});
|
|
53
|
+
const out = {
|
|
54
|
+
licenses: (d.licenses || []).map((l) => ({
|
|
55
|
+
license_id: l.license_id,
|
|
56
|
+
plans: l.plans || [],
|
|
57
|
+
lease_issued_at: l.issued_at,
|
|
58
|
+
lease_expires_at: l.lease_expires_at,
|
|
59
|
+
licence_expires_at: l.expires_at,
|
|
60
|
+
})),
|
|
61
|
+
governed_count: Array.isArray(d.governed) ? d.governed.length : 0,
|
|
62
|
+
org_id: d.org_id || null,
|
|
63
|
+
entitled,
|
|
64
|
+
entitlement_errors: d.entitlement_errors || [],
|
|
65
|
+
renewal_health: d.renewal_health || null,
|
|
66
|
+
};
|
|
67
|
+
if (opts.plugin) out.governed = (d.governed || []).includes(opts.plugin);
|
|
68
|
+
if (json()) { console.log(JSON.stringify(out, null, 2)); return; }
|
|
69
|
+
formatDetail({
|
|
70
|
+
licence_id: out.licenses.map((l) => l.license_id).join(', ') || '(none)',
|
|
71
|
+
plan: out.licenses.flatMap((l) => l.plans).join(', ') || '(none)',
|
|
72
|
+
lease_issued: out.licenses.map((l) => l.lease_issued_at || '?').join(', ') || '(none)',
|
|
73
|
+
lease_expires: out.licenses.map((l) => l.lease_expires_at).join(', ') || '(none)',
|
|
74
|
+
governed: String(out.governed_count),
|
|
75
|
+
org_id: out.org_id || '(instance scoped)',
|
|
76
|
+
entitlement_errors: out.entitlement_errors.length
|
|
77
|
+
? out.entitlement_errors.map((e) => (e.entitlement ? `${e.entitlement}: ${e.error}` : JSON.stringify(e))).join('; ')
|
|
78
|
+
: '(none)',
|
|
79
|
+
}, { title: 'Licence status' });
|
|
80
|
+
formatOutput({
|
|
81
|
+
columns: ['plugin', 'seats'],
|
|
82
|
+
headers: ['Entitled plugin', 'Seats (used/cap)'],
|
|
83
|
+
rows: entitled,
|
|
84
|
+
}, { format: program.opts().output, emptyMessage: 'No entitlements.' });
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
licence
|
|
88
|
+
.command('refresh')
|
|
89
|
+
.description('Renew the licence lease now; prints old to new lease timestamps and entitlement diff')
|
|
90
|
+
.action(async () => {
|
|
91
|
+
auth.requireAuth();
|
|
92
|
+
const ep = resolveEndpoint('setup.licensing.refresh');
|
|
93
|
+
const d = await client.post(ep.path, { service: ep.service, body: {} });
|
|
94
|
+
if (json()) { console.log(JSON.stringify(d, null, 2)); return; }
|
|
95
|
+
const byId = new Map((d.before || []).map((l) => [l.license_id, l]));
|
|
96
|
+
for (const l of d.after || []) {
|
|
97
|
+
const old = byId.get(l.license_id);
|
|
98
|
+
printInfo(`${l.license_id}: lease expires ${old ? old.lease_expires_at : '(new)'} -> ${l.lease_expires_at}`);
|
|
99
|
+
}
|
|
100
|
+
for (const r of d.results || []) printInfo(`${r.license_id}: ${r.action}${r.reason ? ` (${r.reason})` : ''}`);
|
|
101
|
+
const diff = d.entitlement_diff || { added: [], removed: [] };
|
|
102
|
+
printInfo(`entitlements added: ${diff.added.join(', ') || '(none)'}`);
|
|
103
|
+
printInfo(`entitlements removed: ${diff.removed.join(', ') || '(none)'}`);
|
|
104
|
+
printSuccess('Lease refresh complete.');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
licence
|
|
108
|
+
.command('seats')
|
|
109
|
+
.description('List a plugin band holders; --release-dead frees non-live holders (dry run unless --yes)')
|
|
110
|
+
.argument('<pluginId>', 'plugin id, e.g. notesq')
|
|
111
|
+
.option('--release-dead', 'release holders that are not live orgs (deleted orgs, user: ids)')
|
|
112
|
+
.option('--yes', 'actually release (otherwise dry run)')
|
|
113
|
+
.action(async (pluginId, opts) => {
|
|
114
|
+
auth.requireAuth();
|
|
115
|
+
const lep = resolveEndpoint('setup.licensing.seats.list', { pluginId });
|
|
116
|
+
const list = await client.get(lep.path, { service: lep.service });
|
|
117
|
+
let rel = null;
|
|
118
|
+
if (opts.releaseDead) {
|
|
119
|
+
const rep = resolveEndpoint('setup.licensing.seats.releaseDead', { pluginId });
|
|
120
|
+
rel = await client.post(rep.path, { service: rep.service, body: { dry_run: !opts.yes } });
|
|
121
|
+
}
|
|
122
|
+
if (json()) { console.log(JSON.stringify({ ...list, release: rel }, null, 2)); return; }
|
|
123
|
+
printInfo(`${pluginId}: ${list.holders.length} holder(s), cap ${list.allowance ?? '(no band)'}`);
|
|
124
|
+
formatOutput({
|
|
125
|
+
columns: ['id', 'name', 'status'],
|
|
126
|
+
headers: ['Holder', 'Org name', 'Status'],
|
|
127
|
+
rows: list.holders.map((h) => ({ id: h.id, name: h.name || '-', status: h.status })),
|
|
128
|
+
}, { format: program.opts().output, emptyMessage: 'No holders.' });
|
|
129
|
+
if (rel) {
|
|
130
|
+
if (rel.dry_run) {
|
|
131
|
+
printInfo(`DRY RUN: would release ${rel.dead.length} non-live holder(s): ${rel.dead.map((d) => d.id).join(', ') || '(none)'}. Re-run with --yes to release.`);
|
|
132
|
+
} else {
|
|
133
|
+
printSuccess(`Released ${rel.released.length} non-live holder(s): ${rel.released.join(', ') || '(none)'}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (owner) owner.registerLicenceOwnerCommands(licence, { json, fetchImpl });
|
|
139
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `quox linkedin` — LinkedIn plugin verbs, LI-OVERHAUL P9 (X CLI parity).
|
|
3
|
+
*
|
|
4
|
+
* quox linkedin post "<text>" --as <author_urn> [--visibility PUBLIC|CONNECTIONS] [--link <url>] [--image-url <https url>]
|
|
5
|
+
* quox linkedin comment <post_urn> "<text>" --as <actor_urn>
|
|
6
|
+
* quox linkedin posts <author_urn> [--count <n>]
|
|
7
|
+
* quox linkedin org <org_id>
|
|
8
|
+
*
|
|
9
|
+
* Both write verbs execute the linkedin connector tools through the governed
|
|
10
|
+
* collector endpoint (POST /api/v1/tools/execute -> connector bridge). The
|
|
11
|
+
* bridge gates them on their requiresApproval flag: each files an owner
|
|
12
|
+
* approval card and returns immediately with
|
|
13
|
+
* { pending:true, status:'awaiting_approval', approvalId, inbox_item_id }.
|
|
14
|
+
* The actual LinkedIn API write only happens once the owner approves via the
|
|
15
|
+
* dashboard inbox or `quox inbox respond <id> --action approve`. Reads
|
|
16
|
+
* (posts, org) execute directly; LinkedIn reads carry no per-call dollar
|
|
17
|
+
* cost (unlike X), only LinkedIn's own daily program quotas.
|
|
18
|
+
*
|
|
19
|
+
* URNs are explicit by design: LinkedIn addresses everything by URN
|
|
20
|
+
* (urn:li:person:xxx member, urn:li:organization:12345 org page) and the
|
|
21
|
+
* CLI has no org-scoped plugin-config lookup yet, so --as is required on
|
|
22
|
+
* writes rather than silently guessed.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { formatDetail, printSuccess, printInfo } from '../core/output.js';
|
|
26
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
27
|
+
import { resolveOrgId } from './helpers.js';
|
|
28
|
+
|
|
29
|
+
const MAX_POST_CHARS = 3000;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Execute one linkedin connector tool via the governed collector endpoint.
|
|
33
|
+
* A pending-approval response is a SUCCESS shape here (the card was filed);
|
|
34
|
+
* only a non-pending success:false is an error.
|
|
35
|
+
*/
|
|
36
|
+
async function executeLinkedInTool({ client, auth, program }, toolName, input) {
|
|
37
|
+
auth.requireAuth();
|
|
38
|
+
const orgId = resolveOrgId(auth, program);
|
|
39
|
+
const ep = resolveEndpoint('v1.tools.execute');
|
|
40
|
+
const body = { tool_name: toolName, input, org_id: orgId };
|
|
41
|
+
const data = await client.post(ep.path, { service: ep.service, body });
|
|
42
|
+
if (data && data.success === false && !data.pending) {
|
|
43
|
+
throw new Error(`${toolName} via POST ${ep.path} returned success:false: ${data.error || 'unknown error'}`);
|
|
44
|
+
}
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function printAwaitingApproval(action, data) {
|
|
49
|
+
const itemRef = data.inbox_item_id || data.approvalId || 'unknown';
|
|
50
|
+
printSuccess(`${action} filed for owner approval — inbox item ${itemRef} (awaiting approval). Nothing publishes until an approver says yes.`);
|
|
51
|
+
if (data.inbox_item_id) {
|
|
52
|
+
printInfo(`Review and approve: quox inbox get ${data.inbox_item_id} (or: quox inbox respond ${data.inbox_item_id} --action approve)`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function registerLinkedInCommands(program, ctx) {
|
|
57
|
+
const { client, auth } = ctx;
|
|
58
|
+
|
|
59
|
+
const linkedin = program
|
|
60
|
+
.command('linkedin')
|
|
61
|
+
.description('LinkedIn publishing: governed, HITL-approved via HITL Inbox');
|
|
62
|
+
|
|
63
|
+
// ── linkedin post ────────────────────────────────────────────────────────
|
|
64
|
+
|
|
65
|
+
linkedin
|
|
66
|
+
.command('post')
|
|
67
|
+
.description('Draft a LinkedIn post. Files an owner approval card and returns immediately; never posts directly.')
|
|
68
|
+
.argument('<text>', `post text, max ${MAX_POST_CHARS} characters`)
|
|
69
|
+
.requiredOption('--as <author_urn>', 'author URN (urn:li:person:xxx or urn:li:organization:12345)')
|
|
70
|
+
.option('--visibility <visibility>', 'PUBLIC or CONNECTIONS', 'PUBLIC')
|
|
71
|
+
.option('--link <url>', 'attach a link/article URL')
|
|
72
|
+
.option('--image-url <url>', 'attach an image from an https URL (max 10MB); uploaded to LinkedIn server-side before the card is filed, so the approver sees the finished attachment')
|
|
73
|
+
.action(async (text, options) => {
|
|
74
|
+
if (text.length > MAX_POST_CHARS) {
|
|
75
|
+
throw new Error(`Text is ${text.length} characters, over the ${MAX_POST_CHARS} character limit.`);
|
|
76
|
+
}
|
|
77
|
+
if (!['PUBLIC', 'CONNECTIONS'].includes(options.visibility)) {
|
|
78
|
+
throw new Error(`--visibility must be PUBLIC or CONNECTIONS, got ${options.visibility}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const input = { author: options.as, text, visibility: options.visibility };
|
|
82
|
+
if (options.link) input.link_url = options.link;
|
|
83
|
+
|
|
84
|
+
if (options.imageUrl) {
|
|
85
|
+
const media = await executeLinkedInTool({ client, auth, program }, 'linkedin_upload_media', {
|
|
86
|
+
owner: options.as,
|
|
87
|
+
image_url: options.imageUrl,
|
|
88
|
+
});
|
|
89
|
+
const urn = media?.result?.image_urn;
|
|
90
|
+
if (!urn) {
|
|
91
|
+
throw new Error(`Image upload did not return an image URN: ${JSON.stringify(media).slice(0, 200)}`);
|
|
92
|
+
}
|
|
93
|
+
printInfo(`Image uploaded (${media.result.bytes} bytes) — ${urn}`);
|
|
94
|
+
input.media_id = urn;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const data = await executeLinkedInTool({ client, auth, program }, 'linkedin_publish_post', input);
|
|
98
|
+
|
|
99
|
+
if (program.opts().output === 'json') {
|
|
100
|
+
formatDetail(data, { format: 'json' });
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
printAwaitingApproval('Post', data);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// ── linkedin comment ─────────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
linkedin
|
|
109
|
+
.command('comment')
|
|
110
|
+
.description('Draft a comment on a LinkedIn post. Files an owner approval card and returns immediately; never comments directly.')
|
|
111
|
+
.argument('<post_urn>', 'URN of the post to comment on (e.g. urn:li:share:12345)')
|
|
112
|
+
.argument('<text>', 'comment text')
|
|
113
|
+
.requiredOption('--as <actor_urn>', 'actor URN posting the comment (person or organisation)')
|
|
114
|
+
.action(async (postUrn, text, options) => {
|
|
115
|
+
const data = await executeLinkedInTool({ client, auth, program }, 'linkedin_create_comment', {
|
|
116
|
+
post_urn: postUrn,
|
|
117
|
+
actor: options.as,
|
|
118
|
+
text,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
if (program.opts().output === 'json') {
|
|
122
|
+
formatDetail(data, { format: 'json' });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
printAwaitingApproval('Comment', data);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// ── linkedin posts (read) ────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
linkedin
|
|
131
|
+
.command('posts')
|
|
132
|
+
.description('List recent posts for a member or organisation (read-only, no approval needed).')
|
|
133
|
+
.argument('<author_urn>', 'author URN (person or organisation)')
|
|
134
|
+
.option('--count <n>', 'number of posts (max 50)', '20')
|
|
135
|
+
.action(async (authorUrn, options) => {
|
|
136
|
+
const count = Math.min(parseInt(options.count, 10) || 20, 50);
|
|
137
|
+
const data = await executeLinkedInTool({ client, auth, program }, 'linkedin_get_posts', {
|
|
138
|
+
author: authorUrn,
|
|
139
|
+
count,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
if (program.opts().output === 'json') {
|
|
143
|
+
formatDetail(data, { format: 'json' });
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const posts = data.result || [];
|
|
147
|
+
if (posts.length === 0) {
|
|
148
|
+
printInfo('No posts returned.');
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
for (const p of posts) {
|
|
152
|
+
console.log(`${p.id} ${p.created_at || ''} ${p.lifecycle_state || ''}`);
|
|
153
|
+
console.log(` ${String(p.text || '').replace(/\n/g, '\n ')}`);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// ── linkedin org (read) ──────────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
linkedin
|
|
160
|
+
.command('org')
|
|
161
|
+
.description('Show a LinkedIn organisation page: name, follower count, website (read-only). Also the cheapest live credential check.')
|
|
162
|
+
.argument('<org_id>', 'numeric organisation id (e.g. 12345)')
|
|
163
|
+
.action(async (orgId) => {
|
|
164
|
+
const data = await executeLinkedInTool({ client, auth, program }, 'linkedin_get_org_info', { org_id: orgId });
|
|
165
|
+
|
|
166
|
+
if (program.opts().output === 'json') {
|
|
167
|
+
formatDetail(data, { format: 'json' });
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const org = data.result || {};
|
|
171
|
+
printSuccess(`${org.name || 'Unknown'} (urn:li:organization:${org.id})`);
|
|
172
|
+
if (org.vanity_name) printInfo(`linkedin.com/company/${org.vanity_name}`);
|
|
173
|
+
// followers can be null when networkSizes is unavailable — say unknown,
|
|
174
|
+
// never a fake 0.
|
|
175
|
+
printInfo(`Followers: ${org.followers == null ? 'unknown' : org.followers.toLocaleString()}`);
|
|
176
|
+
if (org.website) printInfo(`Website: ${org.website}`);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM routing policy commands: view/set/dry-run-test the org's execution
|
|
3
|
+
* policy (which providers/models agents are allowed to route to).
|
|
4
|
+
*
|
|
5
|
+
* quox llm-policy get|set|test
|
|
6
|
+
*
|
|
7
|
+
* Backend: services/auth/routes/llm-routing-policies.js, mounted at plain
|
|
8
|
+
* `/api` (org-scoped in the URL): GET/PUT `/api/orgs/:orgId/llm-routing-policy`,
|
|
9
|
+
* POST `/api/orgs/:orgId/llm-routing-policy/test`. See
|
|
10
|
+
* cli/lib/api/endpoints/llm-policy.js for the full verified response shapes.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
import { formatDetail, printSuccess, printWarning } from '../core/output.js';
|
|
15
|
+
import { resolveOrgId, parseJSON } from './helpers.js';
|
|
16
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a policy object from --file or --policy. Throws if neither given
|
|
20
|
+
* or the input isn't a JSON object.
|
|
21
|
+
*/
|
|
22
|
+
function resolvePolicy(options) {
|
|
23
|
+
let raw;
|
|
24
|
+
if (options.file) {
|
|
25
|
+
try {
|
|
26
|
+
raw = readFileSync(options.file, 'utf-8');
|
|
27
|
+
} catch (err) {
|
|
28
|
+
throw new Error(`Could not read ${options.file}: ${err.message}`);
|
|
29
|
+
}
|
|
30
|
+
} else if (options.policy !== undefined) {
|
|
31
|
+
raw = options.policy;
|
|
32
|
+
} else {
|
|
33
|
+
throw new Error('Policy input is required. Use --file <path> or --policy <json>.');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const policy = parseJSON(raw, options.file ? '--file contents' : '--policy');
|
|
37
|
+
if (!policy || typeof policy !== 'object' || Array.isArray(policy)) {
|
|
38
|
+
throw new Error('Policy must be a JSON object.');
|
|
39
|
+
}
|
|
40
|
+
return policy;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function registerLlmPolicyCommands(program, ctx) {
|
|
44
|
+
const { client, auth } = ctx;
|
|
45
|
+
|
|
46
|
+
const llmPolicy = program
|
|
47
|
+
.command('llm-policy')
|
|
48
|
+
.description('View, set, and dry-run-validate the org LLM routing policy');
|
|
49
|
+
|
|
50
|
+
// ── llm-policy get ──────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
llmPolicy
|
|
53
|
+
.command('get')
|
|
54
|
+
.description('Show the effective LLM routing policy for the active org')
|
|
55
|
+
.action(async () => {
|
|
56
|
+
auth.requireAuth();
|
|
57
|
+
const orgId = resolveOrgId(auth, program);
|
|
58
|
+
const data = await client.get(resolveEndpoint('llm-policy.get', { orgId }).path, {
|
|
59
|
+
service: resolveEndpoint('llm-policy.get', { orgId }).service,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (data.source === 'seed') {
|
|
63
|
+
printWarning('No org-specific policy saved — showing the built-in seed policy.');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
formatDetail(data.policy, {
|
|
67
|
+
format: program.opts().output,
|
|
68
|
+
title: `LLM Routing Policy (source: ${data.source})`,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ── llm-policy set ──────────────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
llmPolicy
|
|
75
|
+
.command('set')
|
|
76
|
+
.description('Save a new LLM routing policy for the active org (requires ORG_MANAGE_SETTINGS)')
|
|
77
|
+
.option('--file <path>', 'path to a JSON file containing the policy object')
|
|
78
|
+
.option('--policy <json>', 'inline JSON policy object')
|
|
79
|
+
.action(async (options) => {
|
|
80
|
+
auth.requireAuth();
|
|
81
|
+
const orgId = resolveOrgId(auth, program);
|
|
82
|
+
const policy = resolvePolicy(options);
|
|
83
|
+
|
|
84
|
+
const data = await client.put(resolveEndpoint('llm-policy.set', { orgId }).path, {
|
|
85
|
+
service: resolveEndpoint('llm-policy.set', { orgId }).service,
|
|
86
|
+
body: { policy },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
printSuccess('LLM routing policy saved.');
|
|
90
|
+
formatDetail(data.policy, { format: program.opts().output });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// ── llm-policy test ─────────────────────────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
llmPolicy
|
|
96
|
+
.command('test')
|
|
97
|
+
.description('Dry-run validate a policy without saving it')
|
|
98
|
+
.option('--file <path>', 'path to a JSON file containing the policy object')
|
|
99
|
+
.option('--policy <json>', 'inline JSON policy object')
|
|
100
|
+
.action(async (options) => {
|
|
101
|
+
auth.requireAuth();
|
|
102
|
+
const orgId = resolveOrgId(auth, program);
|
|
103
|
+
const policy = resolvePolicy(options);
|
|
104
|
+
|
|
105
|
+
const data = await client.post(resolveEndpoint('llm-policy.test', { orgId }).path, {
|
|
106
|
+
service: resolveEndpoint('llm-policy.test', { orgId }).service,
|
|
107
|
+
body: { policy },
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (data.valid) {
|
|
111
|
+
printSuccess('Policy is valid.');
|
|
112
|
+
} else {
|
|
113
|
+
printWarning(`Policy is invalid (${(data.errors || []).length} error(s)).`);
|
|
114
|
+
}
|
|
115
|
+
formatDetail(data, { format: program.opts().output });
|
|
116
|
+
});
|
|
117
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM commands: provider status incl. degraded state and the failover target.
|
|
3
|
+
*
|
|
4
|
+
* quox llm status
|
|
5
|
+
*
|
|
6
|
+
* Backend: collector `GET /chat/status` (same endpoint as `quox chat-status`,
|
|
7
|
+
* key 'chat.status.list'). This is the curated LLM view of it: it surfaces the
|
|
8
|
+
* failover fields shipped with the LLM failover chain work (`degraded`,
|
|
9
|
+
* `degraded_reason`, `degraded_until`, `fallback_hint`) and warns loudly when
|
|
10
|
+
* the primary provider is in a failover cooldown. Routing policy itself lives
|
|
11
|
+
* under `quox llm-policy`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { formatDetail, printWarning } from '../core/output.js';
|
|
15
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
16
|
+
|
|
17
|
+
export function registerLlmCommands(program, ctx) {
|
|
18
|
+
const { client } = ctx;
|
|
19
|
+
|
|
20
|
+
const llm = program
|
|
21
|
+
.command('llm')
|
|
22
|
+
.description('LLM provider status and failover');
|
|
23
|
+
|
|
24
|
+
llm
|
|
25
|
+
.command('status')
|
|
26
|
+
.description('Show LLM provider status, degraded state, and the failover target')
|
|
27
|
+
.action(async () => {
|
|
28
|
+
// No requireAuth: the route is public on collectors that allowlist it,
|
|
29
|
+
// but the token is attached when logged in (the dev gate requires a JWT).
|
|
30
|
+
const data = await client.get(resolveEndpoint('chat.status.list').path, { service: resolveEndpoint('chat.status.list').service });
|
|
31
|
+
|
|
32
|
+
if (data.degraded) {
|
|
33
|
+
const reason = data.degraded_reason ? ` (${data.degraded_reason})` : '';
|
|
34
|
+
const fallback = data.fallback_hint
|
|
35
|
+
? ` Failing over to ${data.fallback_hint.provider}:${data.fallback_hint.model}.`
|
|
36
|
+
: '';
|
|
37
|
+
printWarning(`Primary provider degraded${reason}.${fallback}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
formatDetail(data, {
|
|
41
|
+
format: program.opts().output,
|
|
42
|
+
title: 'LLM Status',
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|