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,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool commands: CRUD, catalog, install, publish
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import { missingReasonWarning } from '../core/callerSource.js';
|
|
7
|
+
import { formatOutput, formatDetail, printSuccess } from '../core/output.js';
|
|
8
|
+
import { resolveOrgId, parseJSON } from './helpers.js';
|
|
9
|
+
import { resolveEndpoint } from '../api/endpoints.js';
|
|
10
|
+
import { capInline, checkShape, shapeOutput, shapeRecord } from '../toolOutputShape.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* QUOXON-LATENCY L2: the per-turn credential. QUOX_AUTH_TOKEN (cold spawn) or, on a warm
|
|
14
|
+
* `claude` spare, QUOX_AUTH_TOKEN_FILE: a file the collector writes for one turn and
|
|
15
|
+
* deletes when it ends. When the file variable is set it is the ONLY credential: a
|
|
16
|
+
* missing or empty file fails closed, never falling back to a stored session or the
|
|
17
|
+
* service key.
|
|
18
|
+
*/
|
|
19
|
+
function readTurnToken(env) {
|
|
20
|
+
if (env.QUOX_AUTH_TOKEN) return env.QUOX_AUTH_TOKEN;
|
|
21
|
+
if (!env.QUOX_AUTH_TOKEN_FILE) return '';
|
|
22
|
+
let token = '';
|
|
23
|
+
try { token = fs.readFileSync(env.QUOX_AUTH_TOKEN_FILE, 'utf8').trim(); } catch { token = ''; }
|
|
24
|
+
if (!token) throw new Error('No turn credential: QUOX_AUTH_TOKEN_FILE holds no token (the turn has ended). Refusing to use any other credential.');
|
|
25
|
+
return token;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const failedOf = (data) => !!((data && data.success === false) || (data && data.result && data.result.success === false));
|
|
29
|
+
|
|
30
|
+
export function registerToolCommands(program, ctx) {
|
|
31
|
+
const { client, auth } = ctx;
|
|
32
|
+
|
|
33
|
+
const tool = program
|
|
34
|
+
.command('tool')
|
|
35
|
+
.description('Manage tools and tool catalog');
|
|
36
|
+
|
|
37
|
+
tool
|
|
38
|
+
.command('list')
|
|
39
|
+
.description('List tools in the organization')
|
|
40
|
+
.option('--type <type>', 'filter by type: mcp, function, api, script, workflow')
|
|
41
|
+
.option('--status <status>', 'filter by status: active, draft')
|
|
42
|
+
.action(async (options) => {
|
|
43
|
+
auth.requireAuth();
|
|
44
|
+
const orgId = resolveOrgId(auth, program);
|
|
45
|
+
const query = {};
|
|
46
|
+
if (options.type) query.type = options.type;
|
|
47
|
+
if (options.status) query.status = options.status;
|
|
48
|
+
const data = await client.get(resolveEndpoint('tools.list', { orgId }).path, { service: resolveEndpoint('tools.list', { orgId }).service, query });
|
|
49
|
+
formatOutput({
|
|
50
|
+
// fleet #392: column is tool_type.
|
|
51
|
+
columns: ['id', 'name', 'tool_type', 'status', 'risk_level', 'created_at'],
|
|
52
|
+
headers: ['ID', 'Name', 'Type', 'Status', 'Risk', 'Created'],
|
|
53
|
+
rows: data.items || data.tools || data,
|
|
54
|
+
}, { format: program.opts().output });
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
tool
|
|
58
|
+
.command('get')
|
|
59
|
+
.description('Get tool details')
|
|
60
|
+
.argument('<toolId>', 'tool ID')
|
|
61
|
+
.action(async (toolId) => {
|
|
62
|
+
auth.requireAuth();
|
|
63
|
+
const orgId = resolveOrgId(auth, program);
|
|
64
|
+
const data = await client.get(resolveEndpoint('tools.get', { orgId, toolId }).path, { service: resolveEndpoint('tools.get', { orgId, toolId }).service });
|
|
65
|
+
formatDetail(data.tool || data, { format: program.opts().output, title: data.tool?.name || data.name });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
tool
|
|
69
|
+
.command('create')
|
|
70
|
+
.description('Create a new tool')
|
|
71
|
+
.requiredOption('--name <name>', 'tool name')
|
|
72
|
+
.requiredOption('--type <type>', 'type: mcp, function, api, script, workflow')
|
|
73
|
+
.option('--description <desc>', 'description')
|
|
74
|
+
.option('--risk-level <level>', 'risk level: low, medium, high', 'low')
|
|
75
|
+
.option('--spec <json>', 'tool spec as JSON string')
|
|
76
|
+
.action(async (options) => {
|
|
77
|
+
auth.requireAuth();
|
|
78
|
+
const orgId = resolveOrgId(auth, program);
|
|
79
|
+
const body = {
|
|
80
|
+
name: options.name,
|
|
81
|
+
tool_type: options.type, // #987: auth reads tool_type ('type' made every create 400)
|
|
82
|
+
risk_level: options.riskLevel,
|
|
83
|
+
};
|
|
84
|
+
if (options.description) body.description = options.description;
|
|
85
|
+
if (options.spec) body.spec = parseJSON(options.spec, '--spec');
|
|
86
|
+
await client.post(resolveEndpoint('tools.create', { orgId }).path, { service: resolveEndpoint('tools.create', { orgId }).service, body });
|
|
87
|
+
printSuccess(`Tool "${options.name}" created.`);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
tool
|
|
91
|
+
.command('update')
|
|
92
|
+
.description('Update a tool')
|
|
93
|
+
.argument('<toolId>', 'tool ID')
|
|
94
|
+
.option('--name <name>', 'new name')
|
|
95
|
+
.option('--description <desc>', 'new description')
|
|
96
|
+
.option('--status <status>', 'new status')
|
|
97
|
+
.action(async (toolId, options) => {
|
|
98
|
+
auth.requireAuth();
|
|
99
|
+
const orgId = resolveOrgId(auth, program);
|
|
100
|
+
const body = {};
|
|
101
|
+
if (options.name) body.name = options.name;
|
|
102
|
+
if (options.description) body.description = options.description;
|
|
103
|
+
if (options.status) body.status = options.status;
|
|
104
|
+
await client.patch(resolveEndpoint('tools.update', { orgId, toolId }).path, { service: resolveEndpoint('tools.update', { orgId, toolId }).service, body });
|
|
105
|
+
printSuccess('Tool updated.');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
tool
|
|
109
|
+
.command('delete')
|
|
110
|
+
.description('Delete a tool')
|
|
111
|
+
.argument('<toolId>', 'tool ID')
|
|
112
|
+
.action(async (toolId) => {
|
|
113
|
+
auth.requireAuth();
|
|
114
|
+
const orgId = resolveOrgId(auth, program);
|
|
115
|
+
await client.delete(resolveEndpoint('tools.delete', { orgId, toolId }).path, { service: resolveEndpoint('tools.delete', { orgId, toolId }).service });
|
|
116
|
+
printSuccess('Tool deleted.');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
tool
|
|
120
|
+
.command('publish')
|
|
121
|
+
.description('Publish a tool')
|
|
122
|
+
.argument('<toolId>', 'tool ID')
|
|
123
|
+
.action(async (toolId) => {
|
|
124
|
+
auth.requireAuth();
|
|
125
|
+
const orgId = resolveOrgId(auth, program);
|
|
126
|
+
await client.post(resolveEndpoint('tools.publish', { orgId, toolId }).path, { service: resolveEndpoint('tools.publish', { orgId, toolId }).service });
|
|
127
|
+
printSuccess('Tool published.');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
tool
|
|
131
|
+
.command('catalog')
|
|
132
|
+
.description('Browse the tool catalog')
|
|
133
|
+
.option('--search <query>', 'search tools')
|
|
134
|
+
.option('--category <cat>', 'filter by category')
|
|
135
|
+
.action(async (options) => {
|
|
136
|
+
auth.requireAuth();
|
|
137
|
+
const query = {};
|
|
138
|
+
if (options.search) query.search = options.search;
|
|
139
|
+
if (options.category) query.category = options.category;
|
|
140
|
+
const data = await client.get(resolveEndpoint('catalog.list').path, { service: resolveEndpoint('catalog.list').service, query });
|
|
141
|
+
// NOTE: display the business key `tool_id` (not the catalog row `id`)
|
|
142
|
+
// as the identifier column — `tool install <toolId>` and the
|
|
143
|
+
// POST /api/tools/install-to-scope handler both validate against
|
|
144
|
+
// tool_definitions.tool_id, not tool_definitions.id. Showing `id`
|
|
145
|
+
// here previously led users to copy the wrong value into `install`.
|
|
146
|
+
formatOutput({
|
|
147
|
+
columns: ['tool_id', 'name', 'category', 'risk_level', 'description'],
|
|
148
|
+
headers: ['Tool ID', 'Name', 'Category', 'Risk', 'Description'],
|
|
149
|
+
rows: data.items || data.tools || data,
|
|
150
|
+
}, { format: program.opts().output });
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
tool
|
|
154
|
+
.command('exec')
|
|
155
|
+
.description('Execute a governed tool via the collector (POST /api/v1/tools/execute). Large output: use --select/--summary, never a shell pipe.')
|
|
156
|
+
.argument('<name>', 'tool name/id (the TOOL_DEFS key, e.g. "codebase_query")')
|
|
157
|
+
.option('--args <json>', "tool arguments as a JSON string, e.g. '{\"query\":\"...\"}'", '{}')
|
|
158
|
+
// #620: docs/muscle-memory reach for --input; accept it as an alias for
|
|
159
|
+
// --args so the documented form works. --args still wins if both given.
|
|
160
|
+
.option('--input <json>', 'alias for --args (tool arguments as a JSON string)')
|
|
161
|
+
.option('--reason <text>', 'why you are running this; shown on the approval card if the call is held for a human')
|
|
162
|
+
// #970: governed shaping of a large result (the receipt records the shape). Grammar:
|
|
163
|
+
// a.b, a[0], list[field=value], list[field~text], list[*].field, list[*].{a,b}, list[field=value].name, count(list).
|
|
164
|
+
.option('--select <path>', 'return only this part of the result, e.g. agents[status=disconnected].name, streams[name~license] (contains, any case), layers[*].state (every item), containers[*].{host,name,status} (several fields in one call), count(urls), or several paths at once: total,count(urls)')
|
|
165
|
+
.option('--summary', 'honest summary of the main list: total, per-status counts, first N items ("showing N of M")')
|
|
166
|
+
.option('--limit <n>', 'cap the list to N items (with --summary: the sample size, default 10)')
|
|
167
|
+
.action(async (name, options) => {
|
|
168
|
+
// Prefer whichever was explicitly given; --args carries the '{}' default
|
|
169
|
+
// so it is always defined, hence check --input first.
|
|
170
|
+
const usedInput = options.input !== undefined && (options.args === undefined || options.args === '{}');
|
|
171
|
+
const raw = usedInput ? options.input : options.args;
|
|
172
|
+
const input = parseJSON(raw, usedInput ? '--input' : '--args');
|
|
173
|
+
const shape = { select: options.select, summary: !!options.summary, limit: options.limit };
|
|
174
|
+
// A malformed shape fails BEFORE the tool runs: nothing executes, nothing to receipt.
|
|
175
|
+
const shapeErr = checkShape(shape);
|
|
176
|
+
if (shapeErr) throw new Error(shapeErr);
|
|
177
|
+
const outputShape = shapeRecord(shape);
|
|
178
|
+
const data = await executeGovernedTool({ client, auth, program }, name, input, { reason: options.reason, outputShape });
|
|
179
|
+
// Shape only a completed, successful result: a held or failed call is shown whole.
|
|
180
|
+
let shown = data;
|
|
181
|
+
const held = data && (data.pending || data._approval || data.status === 'pending_approval' || data.status === 'held');
|
|
182
|
+
if (outputShape && data && !held && !failedOf(data)) {
|
|
183
|
+
const wrapped = data.result !== undefined;
|
|
184
|
+
const value = shapeOutput(wrapped ? data.result : data, shape).value;
|
|
185
|
+
shown = wrapped ? { ...data, result: value, output_shape: outputShape } : { result: value, output_shape: outputShape };
|
|
186
|
+
}
|
|
187
|
+
// BASH-FALLBACK: on the model-driven path (a per-turn credential is set) an oversized
|
|
188
|
+
// result would be saved to a file by the Bash tool and the model would reach for jq on
|
|
189
|
+
// it, which the guard denies. Keep it inline as the honest summary view instead. Never
|
|
190
|
+
// for a held or failed call (the approval/error is shown whole), never for a human.
|
|
191
|
+
let modelPath = false;
|
|
192
|
+
try { modelPath = !!readTurnToken(process.env); } catch { modelPath = false; }
|
|
193
|
+
if (modelPath && data && !held && !failedOf(data)) {
|
|
194
|
+
const wrapped = shown && shown.result !== undefined;
|
|
195
|
+
const capped = capInline(wrapped ? shown.result : shown);
|
|
196
|
+
if (capped.capped) shown = wrapped ? { ...shown, result: capped.value } : capped.value;
|
|
197
|
+
}
|
|
198
|
+
// quox#1031 (same class as #999): a refused or failed call must exit non-zero, or a script reads
|
|
199
|
+
// success on failure. A HELD (pending) call awaits a human, so it stays 0.
|
|
200
|
+
const failed = failedOf(data);
|
|
201
|
+
if (failed && !(data && data.pending)) process.exitCode = 1;
|
|
202
|
+
|
|
203
|
+
if (program.opts().output === 'json') {
|
|
204
|
+
console.log(JSON.stringify(shown, null, 2));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const result = shown && (shown.result !== undefined ? shown.result : shown);
|
|
208
|
+
if (typeof result === 'string') {
|
|
209
|
+
console.log(result);
|
|
210
|
+
} else {
|
|
211
|
+
console.log(JSON.stringify(result, null, 2));
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
tool
|
|
216
|
+
.command('install')
|
|
217
|
+
.description('Install a tool from the catalog')
|
|
218
|
+
.argument('<toolId>', 'catalog tool_id (the "Tool ID" column from `tool catalog`, not its row id)')
|
|
219
|
+
.action(async (toolId) => {
|
|
220
|
+
auth.requireAuth();
|
|
221
|
+
// org_id is derived server-side from the JWT — no :orgId in the path.
|
|
222
|
+
await client.post(resolveEndpoint('tools.install-to-scope').path, {
|
|
223
|
+
service: resolveEndpoint('tools.install-to-scope').service,
|
|
224
|
+
body: { tool_id: toolId },
|
|
225
|
+
});
|
|
226
|
+
printSuccess('Tool installed.');
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* POST /api/v1/tools/execute for one governed tool, with the full identity
|
|
232
|
+
* contract `tool exec` established (per-turn QUOX_AUTH_TOKEN, org resolution,
|
|
233
|
+
* hat session/user/agent forwarding). Shared so a named verb that wraps a tool
|
|
234
|
+
* (e.g. `quox actions list`, #839) authenticates exactly like `tool exec`.
|
|
235
|
+
* Returns the raw response body.
|
|
236
|
+
*/
|
|
237
|
+
// quox#1034: the HTTP budget for one governed tool call. 120 s for a person at a terminal. A caller that spawns
|
|
238
|
+
// the CLI with a longer budget of its own (the collector's CLI-tools chat path, where delegate_to_agent waits up to
|
|
239
|
+
// the specialist's delegation.wait_ms, Browser-Q 180 s) states it in QUOX_TOOL_EXEC_TIMEOUT_MS, so the client hop
|
|
240
|
+
// never gives up before the server's own deadline and detach do. Capped at 15 minutes.
|
|
241
|
+
export function toolExecTimeoutMs(env = process.env) {
|
|
242
|
+
const n = Number(env && env.QUOX_TOOL_EXEC_TIMEOUT_MS);
|
|
243
|
+
if (!Number.isFinite(n) || n < 1000) return 120000;
|
|
244
|
+
return Math.min(Math.floor(n), 900000);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export async function executeGovernedTool({ client, auth, program }, name, input, { reason, outputShape } = {}) {
|
|
248
|
+
// QUOXON-IDENTITY: QUOX_AUTH_TOKEN is the collector's per-turn scoped
|
|
249
|
+
// credential for the model-driven CLI-tools path. When set it is the ONLY
|
|
250
|
+
// credential: sent as the bearer, never the service key, no stored-session
|
|
251
|
+
// or refresh fallback, and org/user come from the token (not the body).
|
|
252
|
+
const turnToken = readTurnToken(process.env);
|
|
253
|
+
if (!turnToken) auth.requireAuth();
|
|
254
|
+
const body = { tool_name: name, input };
|
|
255
|
+
if (reason) body.reason = String(reason);
|
|
256
|
+
// #970: the collector records the view the caller was shown in the tool receipt.
|
|
257
|
+
if (outputShape) body.output_shape = outputShape;
|
|
258
|
+
{ const w = missingReasonWarning(name, reason); if (w) console.error(w); }
|
|
259
|
+
|
|
260
|
+
// Same org-resolution precedence as `fleet exec` (lib/commands/fleet.js):
|
|
261
|
+
// the collector's /api/v1/tools/execute requires org_id in the body for
|
|
262
|
+
// service-key authenticated callers (isServiceKeyAuth = !req.user,
|
|
263
|
+
// services/collector/server.js ~8326) since there is no session to
|
|
264
|
+
// derive org from. A human-logged-in caller has req.user and the
|
|
265
|
+
// server derives org from the session instead — --org / QUOX_ORG_ID
|
|
266
|
+
// still wins when set explicitly.
|
|
267
|
+
const orgId = turnToken ? null : auth.getOrgId(program.opts().org || process.env.QUOX_ORG_ID);
|
|
268
|
+
if (!orgId && !turnToken && process.env.QUOX_SERVICE_KEY) {
|
|
269
|
+
throw new Error(
|
|
270
|
+
'QUOX_SERVICE_KEY is set but no org could be resolved. '
|
|
271
|
+
+ 'Set QUOX_ORG_ID=<org> for automation callers, or pass --org <id>.'
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
if (orgId) body.org_id = orgId;
|
|
275
|
+
|
|
276
|
+
// QUOXHAT T0 (2026-10-01): automation callers (the collector's
|
|
277
|
+
// CLI-tools chat path) carry the conversation + acting user in env,
|
|
278
|
+
// exactly like QUOX_ORG_ID above. The collector's execute route keys
|
|
279
|
+
// hat-binding resolution on body.session_id and user prefs on
|
|
280
|
+
// body.user_id; without them every CLI-tools execution ran against the
|
|
281
|
+
// org default hat and user-less. Interactive humans have neither set.
|
|
282
|
+
if (process.env.QUOX_SESSION_ID) body.session_id = process.env.QUOX_SESSION_ID;
|
|
283
|
+
if (process.env.QUOX_USER_ID && !turnToken) body.user_id = process.env.QUOX_USER_ID;
|
|
284
|
+
// QUOXHAT #657 P-C.2: forward the ACTING AGENT so a specialist's CLI-tools
|
|
285
|
+
// chat turn executes as that specialist, not the orchestrator. Without it
|
|
286
|
+
// the spawned CLI is a service caller with no agent_id, which the
|
|
287
|
+
// collector defaults to 'quox' — so under enforce a restricted specialist
|
|
288
|
+
// would silently run tools against the orchestrator's broad grant (the
|
|
289
|
+
// "CLI exec silently becomes quox" bypass). The collector sets this from
|
|
290
|
+
// its own selected_agent; a service-key caller's known agent_id is
|
|
291
|
+
// trusted, and the P-B gate then authorizes against the specialist's own
|
|
292
|
+
// grant ceiling ∩ the hat mode.
|
|
293
|
+
if (process.env.QUOX_AGENT_ID) body.agent_id = process.env.QUOX_AGENT_ID;
|
|
294
|
+
|
|
295
|
+
const ep = resolveEndpoint('v1.tools.execute');
|
|
296
|
+
// noAuth: client.js adds no service key / stored session / refresh retry.
|
|
297
|
+
const data = await client.post(ep.path, {
|
|
298
|
+
service: ep.service,
|
|
299
|
+
body,
|
|
300
|
+
timeout: toolExecTimeoutMs(process.env),
|
|
301
|
+
...(turnToken ? { noAuth: true, noActAs: true, headers: { Authorization: `Bearer ${turnToken}` } } : {}),
|
|
302
|
+
});
|
|
303
|
+
return data;
|
|
304
|
+
}
|