quoxcli 0.3.1 → 0.5.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/CHANGELOG.md +61 -0
- package/README.md +2 -2
- package/bin/quox.js +19 -1
- package/bin/quoxon.js +6 -1
- package/lib/api/endpoints/actions.js +15 -0
- package/lib/api/endpoints/admin.js +27 -0
- package/lib/api/endpoints/agent-attach.js +7 -0
- package/lib/api/endpoints/blog.js +16 -0
- package/lib/api/endpoints/chat.js +7 -0
- package/lib/api/endpoints/compliance.js +25 -0
- package/lib/api/endpoints/contactsq.js +4 -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/hat.js +14 -0
- package/lib/api/endpoints/inbox.js +6 -0
- package/lib/api/endpoints/inboxq.js +19 -0
- package/lib/api/endpoints/index.js +14 -0
- package/lib/api/endpoints/loops.js +26 -0
- package/lib/api/endpoints/mon.js +295 -0
- package/lib/api/endpoints/objectives.js +6 -0
- package/lib/api/endpoints/quoxseo.js +6 -0
- package/lib/api/endpoints/server.js +21 -0
- package/lib/api/endpoints/setup.js +6 -0
- package/lib/api/endpoints/tools.js +13 -0
- package/lib/api/endpoints/v1.js +47 -0
- package/lib/commands/actions.js +81 -11
- package/lib/commands/admin.js +35 -0
- package/lib/commands/agent.js +11 -4
- package/lib/commands/agentAttach.js +61 -7
- package/lib/commands/approvals.js +198 -3
- package/lib/commands/ask.js +4 -2
- package/lib/commands/auth.js +64 -11
- package/lib/commands/backup.js +11 -4
- package/lib/commands/blog.js +110 -0
- package/lib/commands/capabilities.js +3 -2
- package/lib/commands/chat.js +142 -28
- package/lib/commands/chatCompanion.js +27 -0
- package/lib/commands/chatState.js +45 -0
- package/lib/commands/claude.js +7 -33
- package/lib/commands/compliance.js +109 -0
- package/lib/commands/connect.js +69 -0
- package/lib/commands/contacts.js +85 -4
- package/lib/commands/contactsSendAt.js +21 -0
- package/lib/commands/dev.js +6 -8
- package/lib/commands/doctor.js +22 -3
- package/lib/commands/engagement.js +90 -0
- package/lib/commands/evidence.js +155 -0
- package/lib/commands/ext.js +23 -0
- package/lib/commands/fleet.js +25 -0
- package/lib/commands/gripe.js +24 -13
- package/lib/commands/hat.js +76 -0
- package/lib/commands/image.js +68 -0
- package/lib/commands/inbox.js +37 -3
- package/lib/commands/inboxq.js +147 -0
- package/lib/commands/kuma.js +1123 -0
- package/lib/commands/kumaSla.js +174 -0
- package/lib/commands/licence.js +39 -1
- package/lib/commands/licenceLinkView.js +311 -0
- package/lib/commands/linkedin.js +19 -0
- package/lib/commands/loop.js +318 -0
- package/lib/commands/lucid.js +1 -0
- package/lib/commands/mail.js +161 -20
- package/lib/commands/memory.js +68 -4
- package/lib/commands/memorySync.js +158 -0
- package/lib/commands/mon.js +55 -144
- package/lib/commands/notes.js +29 -7
- package/lib/commands/notesSeal.js +259 -0
- package/lib/commands/objective.js +53 -3
- package/lib/commands/offload.js +2 -3
- package/lib/commands/org.js +21 -4
- package/lib/commands/plan.js +17 -0
- package/lib/commands/provider.js +87 -8
- package/lib/commands/qlarity.js +32 -1
- package/lib/commands/quoxseo.js +31 -0
- package/lib/commands/research.js +79 -0
- package/lib/commands/rows.js +9 -0
- package/lib/commands/run.js +20 -2
- package/lib/commands/scope.js +2 -2
- package/lib/commands/server.js +150 -0
- package/lib/commands/setup.js +127 -75
- package/lib/commands/shortcut.js +41 -0
- package/lib/commands/skills.js +24 -5
- package/lib/commands/slot.js +49 -9
- package/lib/commands/status.js +92 -44
- package/lib/commands/tool.js +30 -0
- package/lib/commands/vault.js +6 -3
- package/lib/commands/vm.js +2 -2
- package/lib/commands/walkthrough.js +14 -2
- package/lib/commands/watch.js +11 -2
- package/lib/commands/wazuh.js +824 -0
- package/lib/commands/wazuhIntake.js +317 -0
- package/lib/commands/wazuhReport.js +192 -0
- package/lib/commands/workflow.js +47 -4
- package/lib/commands/x.js +50 -0
- package/lib/commands/youtube.js +172 -0
- package/lib/core/actionItems.js +115 -0
- package/lib/core/agentAlias.js +2 -0
- package/lib/core/agentFamilies.js +7 -0
- package/lib/core/announce.js +86 -0
- package/lib/core/auth.js +20 -2
- package/lib/core/callMe.js +118 -0
- package/lib/core/client.js +37 -3
- package/lib/core/commandRegistrars.js +17 -0
- package/lib/core/config.js +29 -3
- package/lib/core/confirm.js +68 -7
- package/lib/core/crossOrgApprovals.js +69 -0
- package/lib/core/errors.js +52 -1
- package/lib/core/findingReconcile.js +90 -0
- package/lib/core/global-flags.js +1 -1
- package/lib/core/governedSession.js +136 -8
- package/lib/core/inboxResolution.js +3 -2
- package/lib/core/liveSessionsReport.js +1 -1
- package/lib/core/loginGuard.js +73 -0
- package/lib/core/loopGlyph.js +97 -0
- package/lib/core/offload.js +73 -7
- package/lib/core/org-override.js +5 -1
- package/lib/core/output.js +8 -8
- package/lib/core/profileTrust.js +182 -0
- package/lib/core/quoxglyph.js +22 -1
- package/lib/core/router.js +14 -0
- package/lib/core/sessionHeartbeat.js +12 -8
- package/lib/core/shortcut.js +83 -0
- package/lib/core/stepUpPrompt.js +99 -0
- package/lib/core/version.js +1 -1
- package/lib/core/vm.js +5 -0
- package/lib/core/walkthrough.js +9 -5
- 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/quoxon/EXTENSIONS.md +146 -0
- package/lib/quoxon/api.js +364 -27
- package/lib/quoxon/app.js +1629 -183
- package/lib/quoxon/approvalBatch.js +117 -0
- package/lib/quoxon/approvalFacts.js +64 -8
- package/lib/quoxon/approvalSentence.js +48 -0
- package/lib/quoxon/approvalsView.js +124 -7
- package/lib/quoxon/autoOpen.js +94 -0
- package/lib/quoxon/backgroundWork.js +59 -0
- package/lib/quoxon/bang.js +1 -1
- package/lib/quoxon/capabilities.js +7 -2
- package/lib/quoxon/commandShort.js +22 -3
- package/lib/quoxon/commands.js +110 -15
- package/lib/quoxon/connect.js +5 -3
- package/lib/quoxon/countdownLine.js +10 -1
- package/lib/quoxon/deck.js +30 -0
- package/lib/quoxon/deckLazy.js +58 -0
- package/lib/quoxon/demo.autoplay.js +1 -1
- package/lib/quoxon/demo.js +3 -1
- package/lib/quoxon/destructive.js +35 -0
- package/lib/quoxon/dividerAocl.js +4 -3
- package/lib/quoxon/dividerRule.js +3 -3
- package/lib/quoxon/dnd.js +71 -0
- package/lib/quoxon/dragonCompanion.js +285 -0
- package/lib/quoxon/dragonModes.js +1 -0
- package/lib/quoxon/dragonMoments.js +160 -0
- package/lib/quoxon/dragonReads.js +68 -0
- package/lib/quoxon/dragonView.js +2 -2
- package/lib/quoxon/echo.js +1 -0
- package/lib/quoxon/events.js +67 -10
- package/lib/quoxon/extensions.js +636 -0
- package/lib/quoxon/gripeQueue.js +135 -0
- package/lib/quoxon/inboxView.js +182 -0
- package/lib/quoxon/installCli.js +79 -0
- package/lib/quoxon/keys.js +4 -4
- package/lib/quoxon/loopCard.js +460 -0
- package/lib/quoxon/loopCards.js +189 -0
- package/lib/quoxon/loopStream.js +98 -0
- package/lib/quoxon/mailView.js +71 -0
- package/lib/quoxon/main.js +29 -5
- package/lib/quoxon/markdown.js +1 -1
- package/lib/quoxon/model.js +15 -0
- package/lib/quoxon/mouse.js +12 -1
- package/lib/quoxon/neverAnswered.js +20 -0
- package/lib/quoxon/objectiveOffer.js +82 -0
- package/lib/quoxon/objects/away.js +43 -5
- package/lib/quoxon/objects/index.js +22 -4
- package/lib/quoxon/objects/model.js +33 -0
- package/lib/quoxon/objects/proof.js +12 -4
- package/lib/quoxon/onboarding/connectServer.js +162 -0
- package/lib/quoxon/onboarding/copy.js +6 -0
- package/lib/quoxon/onboarding/index.js +5 -43
- package/lib/quoxon/onboarding/probe.js +20 -1
- package/lib/quoxon/onboarding/shortcutOffer.js +28 -0
- package/lib/quoxon/onboarding/view.js +16 -3
- package/lib/quoxon/orgSwitch.js +49 -1
- package/lib/quoxon/planSteps.js +51 -0
- package/lib/quoxon/print.js +8 -3
- package/lib/quoxon/profileSwitch.js +7 -0
- package/lib/quoxon/promptHistory.js +3 -1
- package/lib/quoxon/qdragonFly.js +7 -6
- package/lib/quoxon/qmotion.js +17 -0
- package/lib/quoxon/render.js +187 -41
- package/lib/quoxon/roster.js +36 -17
- package/lib/quoxon/rosterSessions.js +44 -0
- package/lib/quoxon/rows.js +244 -1
- package/lib/quoxon/screenContext.js +1 -1
- package/lib/quoxon/secretShape.js +86 -0
- package/lib/quoxon/serverChip.js +42 -0
- package/lib/quoxon/session.js +10 -0
- package/lib/quoxon/slash/agents.js +2 -1
- package/lib/quoxon/slash/argSources.js +9 -2
- package/lib/quoxon/slash/args.js +4 -2
- package/lib/quoxon/slash/broadcast.js +18 -5
- package/lib/quoxon/slash/broadcastRun.js +13 -2
- package/lib/quoxon/slash/cliCommand.js +42 -1
- package/lib/quoxon/slash/cliLeaves.json +139 -2
- package/lib/quoxon/slash/evidenceCmd.js +34 -0
- package/lib/quoxon/slash/hatWalk.js +1 -1
- package/lib/quoxon/slash/palette.js +23 -2
- package/lib/quoxon/slash/paletteController.js +10 -4
- package/lib/quoxon/slash/qpeCmd.js +35 -0
- package/lib/quoxon/slash/restart.js +31 -4
- package/lib/quoxon/slash/resume.js +18 -1
- package/lib/quoxon/slash/stepUp.js +5 -5
- package/lib/quoxon/slash/stepUpCmds.js +74 -1
- package/lib/quoxon/slash/todoCmd.js +122 -0
- package/lib/quoxon/slashSpinner.js +35 -0
- package/lib/quoxon/slotAttach.js +8 -0
- package/lib/quoxon/slotChat.js +17 -0
- package/lib/quoxon/slotFormat.js +1 -1
- package/lib/quoxon/slotOutbox.js +113 -0
- package/lib/quoxon/suggestCommand.js +34 -3
- package/lib/quoxon/term.js +25 -1
- package/lib/quoxon/toolCards.js +30 -0
- package/lib/quoxon/transcript.js +2 -1
- package/lib/quoxon/welcome.js +1 -1
- package/lib/quoxon/whatsnew.js +1 -1
- package/lib/quoxon/whatsnew.jsonl +81 -0
- package/lib/quoxon/windowOrg.js +11 -1
- package/lib/server/devServers.js +137 -0
- package/lib/server/installFlow.js +168 -0
- package/lib/server/status.js +15 -1
- package/lib/toolOutputShape.js +55 -0
- package/package.json +4 -2
- 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/quoxperticus/v2/quoxperticus-master.svg +59 -0
- package/vendor/dragonlab/design/quoxperticus/v3/character.mjs +43 -0
- package/vendor/dragonlab/design/quoxperticus/v4/character.mjs +57 -0
- package/vendor/dragonlab/design/quoxperticus/v4/review.mjs +35 -0
- package/vendor/dragonlab/design/quoxperticus/v4/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/design/vulcan/v1/character.mjs +34 -0
- package/vendor/dragonlab/design/vulcan/v1/vulcan-master.svg +57 -0
- package/vendor/dragonlab/design/vulcan/v2/character.mjs +39 -0
- package/vendor/dragonlab/design/vulcan/v3/character.mjs +41 -0
- package/vendor/dragonlab/design/vulcan/v3/review.mjs +35 -0
- package/vendor/dragonlab/design/vulcan/v3/watch.mjs +56 -0
- package/vendor/dragonlab/factory/svg-rig-contour.mjs +64 -0
- package/vendor/dragonlab/factory/svg-rig.mjs +63 -0
- package/vendor/dragonlab/integration/companions-v1/characters.mjs +108 -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/quoxperticus.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/companions-v1/vulcan.mjs +2 -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
|
@@ -101,11 +101,12 @@ export const LOOSE_SAFE = new Set(['help', 'status', 'context', 'cost', 'agents'
|
|
|
101
101
|
export function looseCommand(cmd, restArg) {
|
|
102
102
|
const words = String(restArg || '').trim().split(/\s+/).filter(Boolean);
|
|
103
103
|
for (let i = 0; i < words.length; i++) {
|
|
104
|
+
if (words[i].replace(/^\//, '').length < 2 && !words[i].startsWith('/')) continue; // a bare "r" in prose is not the /r alias
|
|
104
105
|
const e = findEntry(words[i].replace(/^\//, ''));
|
|
105
106
|
if (!e || e.kind !== 'command' || e.status !== 'active') continue;
|
|
106
107
|
const rest = words.slice(i + 1).join(' ');
|
|
107
108
|
if (LOOSE_SAFE.has(e.id)) return { run: `/${e.id}${rest ? ` ${rest}` : ''}`, name: `/${e.id}` };
|
|
108
|
-
return { suggest: `/${e.id}
|
|
109
|
+
return { suggest: `/${e.id}` }; // a command NAME only, never the user's message text
|
|
109
110
|
}
|
|
110
111
|
if (words.length && !suggestCommands(cmd).length) return { ask: `${String(cmd).replace(/^\//, '')} ${words.join(' ')}` };
|
|
111
112
|
return null;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { CHOICES, connectedChoices, providerId } from '../model.js';
|
|
7
7
|
import { liveModels } from '../modelPrefs.js';
|
|
8
8
|
import { pathItems } from '../slotChat.js';
|
|
9
|
+
import { fromOf, activeMutes } from '../inboxView.js';
|
|
9
10
|
|
|
10
11
|
/** Provider ids /connect understands (one per provider; the subscription has no key). */
|
|
11
12
|
export const connectIds = () => [
|
|
@@ -14,7 +15,7 @@ export const connectIds = () => [
|
|
|
14
15
|
).values(),
|
|
15
16
|
];
|
|
16
17
|
|
|
17
|
-
export function createArgSources({ api, getPrefs = () => ({ favourites: [], default: null }), getRows = () => [] }) {
|
|
18
|
+
export function createArgSources({ api, getPrefs = () => ({ favourites: [], default: null }), getRows = () => [], getExt = null, getInbox = null }) {
|
|
18
19
|
return async function source(src, param) {
|
|
19
20
|
switch (src) {
|
|
20
21
|
case 'providers':
|
|
@@ -38,12 +39,18 @@ export function createArgSources({ api, getPrefs = () => ({ favourites: [], defa
|
|
|
38
39
|
value: String(i + 1),
|
|
39
40
|
desc: `${f.provider} ${f.model}`,
|
|
40
41
|
}));
|
|
42
|
+
case 'ext.listed': return (getExt?.().listed?.() || []).map((v) => ({ value: v }));
|
|
43
|
+
case 'ext.loaded': return (getExt?.().loaded?.() || []).map((v) => ({ value: v }));
|
|
44
|
+
case 'ext.panels': return [...(getExt?.().panels?.() || []).map((p) => ({ value: p.name, desc: p.title })), { value: 'off', desc: 'collapse the panel region' }];
|
|
45
|
+
case 'ext.keys': return (getExt?.().keys?.(param) || []).map((d) => ({ value: d.key, desc: d.help }));
|
|
46
|
+
case 'inbox.sources': return [...new Set((getInbox?.().list?.() || []).map((i) => fromOf(i).toLowerCase()))].map((v) => ({ value: v }));
|
|
47
|
+
case 'inbox.mutes': return Object.keys(activeMutes(getInbox?.().mutes?.())).map((v) => ({ value: v }));
|
|
41
48
|
case 'rows':
|
|
42
49
|
return (getRows?.() || []).map((r) => ({ value: r.id, desc: r.source.type }));
|
|
43
50
|
case 'orgs':
|
|
44
51
|
return (await api.orgs()).map((o) => ({ value: o.slug || o.id, desc: o.name || '' }));
|
|
45
52
|
case 'agents':
|
|
46
|
-
return (await api.agents()).map((a) => ({
|
|
53
|
+
return [...(await api.agents())].sort((x, y) => String(x.agent_id).localeCompare(String(y.agent_id))).map((a) => ({
|
|
47
54
|
value: a.agent_id,
|
|
48
55
|
desc: a.name && a.name !== a.agent_id ? a.name : '',
|
|
49
56
|
}));
|
package/lib/quoxon/slash/args.js
CHANGED
|
@@ -41,7 +41,7 @@ const asItem = (x) =>
|
|
|
41
41
|
/** Static choices of a level as items. */
|
|
42
42
|
export const staticItems = (lv) => (lv?.choices || []).map(asItem);
|
|
43
43
|
|
|
44
|
-
/** Prefix matches first, then substring; the exact sole match is dropped (nothing to add). */
|
|
44
|
+
/** Prefix matches first, then substring, then display-name matches; the exact sole match is dropped (nothing to add). */
|
|
45
45
|
export function rankArgs(items, partial) {
|
|
46
46
|
const q = String(partial || '').toLowerCase();
|
|
47
47
|
const seen = new Set();
|
|
@@ -51,7 +51,9 @@ export function rankArgs(items, partial) {
|
|
|
51
51
|
const sub = uniq.filter(
|
|
52
52
|
(i) => !i.value.toLowerCase().startsWith(q) && i.value.toLowerCase().includes(q),
|
|
53
53
|
);
|
|
54
|
-
|
|
54
|
+
// A display name (desc) that matches also surfaces the item, after every id match: /attach vulcan finds forge.
|
|
55
|
+
const byDesc = uniq.filter((i) => !pre.includes(i) && !sub.includes(i) && String(i.desc || '').toLowerCase().includes(q));
|
|
56
|
+
const out = [...pre, ...sub, ...byDesc];
|
|
55
57
|
return out.length === 1 && out[0].value.toLowerCase() === q ? [] : out;
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* No I/O. v1 scope: all held slots or --slots, --priority urgent, --ack, /page. Scheduling, voice,
|
|
4
4
|
* fleet and org reach, bulletins and drafting are not built.
|
|
5
5
|
*/
|
|
6
|
-
export const BROADCAST_USAGE = 'Usage: /broadcast [--slots a,b] [--priority urgent] [--ack] <text>';
|
|
6
|
+
export const BROADCAST_USAGE = 'Usage: /broadcast [--slots a,b] [--priority urgent] [--ack] [--active [--dry-run]] <text>';
|
|
7
7
|
export const PAGE_USAGE = 'Usage: /page <slot> <text>';
|
|
8
8
|
const NOT_YET = new Set(['--fleet', '--org', '--voice', '--at']);
|
|
9
9
|
|
|
@@ -13,13 +13,15 @@ const NOT_YET = new Set(['--fleet', '--org', '--voice', '--at']);
|
|
|
13
13
|
*/
|
|
14
14
|
export function parseBroadcastArgs(arg) {
|
|
15
15
|
const toks = String(arg || '').trim().split(/\s+/).filter(Boolean);
|
|
16
|
-
let slots = null; let priority = 'normal'; let ack = false;
|
|
16
|
+
let slots = null; let priority = 'normal'; let ack = false; let active = false; let dryRun = false;
|
|
17
17
|
let i = 0;
|
|
18
18
|
for (; i < toks.length && toks[i].startsWith('--'); i += 1) {
|
|
19
19
|
const [flag, inline] = toks[i].split(/=(.*)/s);
|
|
20
20
|
if (NOT_YET.has(flag)) return { ok: false, message: `${flag} is not available yet (v1 sends to held slots in this org: --slots, --priority, --ack).` };
|
|
21
21
|
if (flag === '--all') { slots = null; continue; }
|
|
22
22
|
if (flag === '--ack') { ack = true; continue; }
|
|
23
|
+
if (flag === '--active') { active = true; continue; }
|
|
24
|
+
if (flag === '--dry-run') { dryRun = true; continue; }
|
|
23
25
|
const val = inline !== undefined ? inline : toks[++i];
|
|
24
26
|
if (flag === '--slots') {
|
|
25
27
|
const list = String(val || '').split(',').map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
@@ -34,7 +36,12 @@ export function parseBroadcastArgs(arg) {
|
|
|
34
36
|
}
|
|
35
37
|
const text = toks.slice(i).join(' ');
|
|
36
38
|
if (!text) return { ok: false, message: BROADCAST_USAGE };
|
|
37
|
-
return { ok: true, text, slots, priority, ack };
|
|
39
|
+
return { ok: true, text, slots, priority, ack, ...(active ? { active: true } : {}), ...(dryRun ? { dryRun: true } : {}) };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** QuoxGlyph announce line for a broadcast to active sessions: { reached, skipped, dryRun }. */
|
|
43
|
+
export function activeLine({ reached = 0, skipped = 0, dryRun = false } = {}) {
|
|
44
|
+
return `\u{1F4CD} QUOXSLOTS \u2502 broadcast to active \u2502 ${reached} ${dryRun ? 'would reach' : 'reached'} \u00B7 ${skipped} skipped dormant \u2714`;
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
/** `/page <slot> <text>` -> urgent, ack-required, one recipient. */
|
|
@@ -72,9 +79,10 @@ export function broadcastCard(r, { kind = 'broadcast' } = {}) {
|
|
|
72
79
|
const c = r?.counts || {};
|
|
73
80
|
const rc = roomC(r);
|
|
74
81
|
const rows = [];
|
|
75
|
-
if (!c.total) rows.push([['\u26A0 no held slots in this org to hear it', 'warn']]);
|
|
82
|
+
if (!c.total) rows.push([[r?.skipped_dormant ? `\u26A0 no active sessions to hear it \u00B7 ${r.skipped_dormant.length} dormant skipped` : '\u26A0 no held slots in this org to hear it', 'warn']]);
|
|
76
83
|
else if (c.delivered) {
|
|
77
|
-
|
|
84
|
+
const act = r?.skipped_dormant ? 'active ' : ''; // --active: say who was left alone
|
|
85
|
+
rows.push([[`\u2714 ${c.delivered} ${act}${c.delivered === 1 ? 'session has' : 'sessions have'} it${r?.skipped_dormant ? ` \u00B7 ${c.dormant_skipped ?? r.skipped_dormant.length} dormant skipped` : ''}`, 'ok']]);
|
|
78
86
|
if (namesRow(r)) rows.push([[namesRow(r), 'prose']]); // an older server sends no per-slot list: no empty row
|
|
79
87
|
}
|
|
80
88
|
for (const d of badSlots(r).slice(0, 3)) rows.push([[`\u2716 ${failText(d)}`, 'error']]);
|
|
@@ -105,7 +113,12 @@ export function broadcastSummary(r) {
|
|
|
105
113
|
const c = r?.counts || {};
|
|
106
114
|
const rc = roomC(r);
|
|
107
115
|
const lines = [];
|
|
116
|
+
if (!c.total && r.skipped_dormant) return [[`Broadcast ${r.id}: no active sessions to hear it \u00B7 ${r.skipped_dormant.length} dormant skipped${r.skipped_dormant.length ? ` (${r.skipped_dormant.join(', ')})` : ''}.`, 'warn']];
|
|
108
117
|
if (!c.total) return [[`Broadcast ${r.id}: no held slots in this org to hear it.`, 'warn']];
|
|
118
|
+
if (r.skipped_dormant) { // --active: say who was left alone
|
|
119
|
+
const dn = r.skipped_dormant;
|
|
120
|
+
lines.push([`Broadcast ${r.id} ${titleWord(r)}: ${(c.delivered || 0) + (c.queued || 0)} active have it${okSlots(r).length ? ` (${okSlots(r).map((d) => d.slot).join(', ')})` : ''} \u00B7 ${dn.length} dormant skipped${dn.length ? ` (${dn.join(', ')})` : ''}`, c.failed ? 'warn' : 'plain']);
|
|
121
|
+
} else
|
|
109
122
|
lines.push([`Broadcast ${r.id} ${titleWord(r)}: ${(c.delivered || 0) + (c.queued || 0)} of ${c.total} ${plural(c.total)} have it${okSlots(r).length ? ` (${okSlots(r).map((d) => d.slot).join(', ')})` : ''}`, c.failed ? 'warn' : 'plain']);
|
|
110
123
|
if (c.delivered && roomText(rc, ', ')) lines.push([` chat rooms: ${roomText(rc, ', ')}`, rc.failed ? 'warn' : 'plain']);
|
|
111
124
|
for (const d of badSlots(r)) lines.push([` ${failText(d)}`, 'warn']);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* One server call fans out (POST /api/v1/slots/broadcast); with --ack the sender then sees the delivery line
|
|
4
4
|
* update as recipients acknowledge. The poll is display only: the broadcast and its acks live on the server.
|
|
5
5
|
*/
|
|
6
|
-
import { parseBroadcastArgs, parsePageArgs, parseAckArgs, parseStatusArgs, broadcastSummary, broadcastCard, BROADCAST_USAGE } from './broadcast.js';
|
|
6
|
+
import { parseBroadcastArgs, parsePageArgs, parseAckArgs, parseStatusArgs, broadcastSummary, broadcastCard, BROADCAST_USAGE, activeLine } from './broadcast.js';
|
|
7
7
|
|
|
8
8
|
const roomC = (r) => ({ sent: 0, sending: 0, failed: 0, ...(r?.counts?.room || {}) });
|
|
9
9
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -22,9 +22,20 @@ export async function runBroadcast({ api, kind, arg, from, say, card = null, isC
|
|
|
22
22
|
}
|
|
23
23
|
const parsed = kind === 'page' ? parsePageArgs(arg) : parseBroadcastArgs(arg);
|
|
24
24
|
if (!parsed.ok) return say(parsed.message, parsed.message === BROADCAST_USAGE ? 'plain' : 'warn');
|
|
25
|
-
const r = await api.slotBroadcast({ text: parsed.text, slots: parsed.slots, priority: parsed.priority, ack: parsed.ack, from });
|
|
25
|
+
const r = await api.slotBroadcast({ text: parsed.text, slots: parsed.slots, priority: parsed.priority, ack: parsed.ack, active: parsed.active, ...(parsed.dryRun ? { dryRun: true } : {}), from });
|
|
26
26
|
if (!r.ok) return say(`${kind === 'page' ? 'Page' : 'Broadcast'} failed: ${r.message}`, 'warn');
|
|
27
|
+
if (r.data?.dry_run) { // BROADCAST-ACTIVE --dry-run: who would hear it, who is dormant; nothing sent, no card
|
|
28
|
+
const would = r.data.would_reach || []; const dorm = r.data.skipped_dormant || [];
|
|
29
|
+
say(activeLine({ reached: would.length, skipped: dorm.length, dryRun: true }), 'ok');
|
|
30
|
+
if (would.length) say(` would reach: ${would.join(', ')}`, 'plain');
|
|
31
|
+
if (dorm.length) say(` skipped dormant: ${dorm.join(', ')}`, 'plain');
|
|
32
|
+
return say('Dry run: nothing was sent.', 'plain');
|
|
33
|
+
}
|
|
27
34
|
show(r.data);
|
|
35
|
+
if (parsed.active && r.data?.skipped_dormant) {
|
|
36
|
+
say(activeLine({ reached: r.data.counts?.delivered || 0, skipped: r.data.skipped_dormant.length }), 'ok');
|
|
37
|
+
if (r.data.skipped_dormant.length) say(` skipped dormant: ${r.data.skipped_dormant.join(', ')}`, 'plain');
|
|
38
|
+
}
|
|
28
39
|
// PRESENCE: it reached a human slot whose human is away; approvals to them will queue.
|
|
29
40
|
if (r.data?.human_presence?.away && r.data.human_presence.notice) say(`⏸ ${r.data.human_presence.notice}`, 'warn');
|
|
30
41
|
// POKE-WAKE: a page also asks each delivered slot's keeper to wake its idle session, so the page is read now,
|
|
@@ -25,6 +25,42 @@ function variants(w) {
|
|
|
25
25
|
|
|
26
26
|
const MAX_DEPTH = 4;
|
|
27
27
|
|
|
28
|
+
// CONTACTSQ: `/contact new Cristina Cowles --relationship Wife --mobile +44...` must become a command the verb accepts.
|
|
29
|
+
// Per-leaf flag tables (value flags and bare switches), synonyms people type, and a clear refusal for anything else.
|
|
30
|
+
const CONTACTS_ADD = {
|
|
31
|
+
value: ['phone', 'email', 'kind', 'organisation', 'job-title', 'relationship', 'notes', 'given', 'family', 'middle', 'prefix', 'suffix', 'nickname', 'phonetic-given', 'phonetic-family'],
|
|
32
|
+
bare: ['org-kind'],
|
|
33
|
+
synonyms: { mobile: 'phone', tel: 'phone', telephone: 'phone', cell: 'phone', number: 'phone', 'e-mail': 'email', rel: 'relationship', org: 'organisation', company: 'organisation', title: 'job-title' },
|
|
34
|
+
lower: ['relationship', 'kind'],
|
|
35
|
+
};
|
|
36
|
+
const NORMALISERS = { 'contacts add': (args) => normaliseFlags(args, CONTACTS_ADD, 'quox contacts add') };
|
|
37
|
+
|
|
38
|
+
/** args = [...path, ...rest]. Positional words before the first flag become ONE name; flags are mapped and checked. */
|
|
39
|
+
function normaliseFlags(args, spec, verb) {
|
|
40
|
+
const head = args.slice(0, 2);
|
|
41
|
+
const rest = args.slice(2);
|
|
42
|
+
const name = [];
|
|
43
|
+
const out = [];
|
|
44
|
+
let i = 0;
|
|
45
|
+
while (i < rest.length && !rest[i].startsWith('-')) name.push(rest[i++]);
|
|
46
|
+
while (i < rest.length) {
|
|
47
|
+
const tok = rest[i++];
|
|
48
|
+
if (!tok.startsWith('--')) return { error: `Unexpected "${tok}" after the flags. Quote values with spaces. ${verb} takes: ${[...spec.value, ...spec.bare].map(f => `--${f}`).join(' ')}` };
|
|
49
|
+
const eq = tok.indexOf('=');
|
|
50
|
+
const raw = (eq > 0 ? tok.slice(2, eq) : tok.slice(2)).toLowerCase();
|
|
51
|
+
const flag = spec.synonyms[raw] || raw;
|
|
52
|
+
if (spec.bare.includes(flag)) { out.push(`--${flag}`); continue; }
|
|
53
|
+
if (!spec.value.includes(flag)) return { error: `--${raw} is not a flag of ${verb}. It takes: ${[...spec.value, ...spec.bare].map(f => `--${f}`).join(' ')}` };
|
|
54
|
+
const vals = eq > 0 ? [tok.slice(eq + 1)] : [];
|
|
55
|
+
while (i < rest.length && !rest[i].startsWith('--')) vals.push(rest[i++]);
|
|
56
|
+
if (!vals.length || !vals.join('')) return { error: `--${raw} needs a value.` };
|
|
57
|
+
let v = vals.join(' ');
|
|
58
|
+
if (spec.lower.includes(flag)) v = v.toLowerCase();
|
|
59
|
+
out.push(`--${flag}`, v);
|
|
60
|
+
}
|
|
61
|
+
return { args: [...head, ...(name.length ? [name.join(' ')] : []), ...out] };
|
|
62
|
+
}
|
|
63
|
+
|
|
28
64
|
/** -> { path, cls, args, display } | null. args is the full argv after `quox` (quoted args preserved). */
|
|
29
65
|
export function resolveCliSlash(cmd, restArg, leaves = LEAVES) {
|
|
30
66
|
const first = String(cmd || '').replace(/^\//, '');
|
|
@@ -44,7 +80,12 @@ export function resolveCliSlash(cmd, restArg, leaves = LEAVES) {
|
|
|
44
80
|
for (const p of walk(n)) {
|
|
45
81
|
const path = p.join(' ');
|
|
46
82
|
if (Object.prototype.hasOwnProperty.call(leaves, path)) {
|
|
47
|
-
|
|
83
|
+
let args = [...p, ...words.slice(n)];
|
|
84
|
+
if (NORMALISERS[path]) {
|
|
85
|
+
const nr = NORMALISERS[path](args);
|
|
86
|
+
if (nr.error) return { path, cls: leaves[path], args, display: `quox ${args.join(' ')}`, error: nr.error };
|
|
87
|
+
args = nr.args;
|
|
88
|
+
}
|
|
48
89
|
return { path, cls: leaves[path], args, display: `quox ${args.map(a => (/[\s"']/.test(a) || a === '' ? JSON.stringify(a) : a)).join(' ')}` };
|
|
49
90
|
}
|
|
50
91
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{"account password":"never",
|
|
2
|
+
"actions add":"write",
|
|
3
|
+
"actions delete":"write",
|
|
4
|
+
"actions done":"write",
|
|
2
5
|
"actions get":"read",
|
|
3
6
|
"actions list":"read",
|
|
7
|
+
"actions move":"write",
|
|
4
8
|
"active":"read",
|
|
5
9
|
"admin agent-identity mint":"never",
|
|
6
10
|
"admin config get":"read",
|
|
@@ -21,6 +25,7 @@
|
|
|
21
25
|
"admin retention stats":"read",
|
|
22
26
|
"admin service list":"read",
|
|
23
27
|
"admin stats":"read",
|
|
28
|
+
"admin users verify-email":"write",
|
|
24
29
|
"aee conversations":"read",
|
|
25
30
|
"aee get":"read",
|
|
26
31
|
"aee query":"read",
|
|
@@ -30,6 +35,7 @@
|
|
|
30
35
|
"agent attach":"never",
|
|
31
36
|
"agent attach-heartbeat":"never",
|
|
32
37
|
"agent attach-status":"read",
|
|
38
|
+
"agent attaches":"write",
|
|
33
39
|
"agent bind-slot":"write",
|
|
34
40
|
"agent create":"write",
|
|
35
41
|
"agent deactivate":"write",
|
|
@@ -49,11 +55,16 @@
|
|
|
49
55
|
"agent tool revoke":"write",
|
|
50
56
|
"agent unbind-slot":"write",
|
|
51
57
|
"agent update":"write",
|
|
58
|
+
"approvals approve":"write",
|
|
59
|
+
"approvals call-me":"write",
|
|
60
|
+
"approvals deny":"write",
|
|
52
61
|
"approvals grants create":"write",
|
|
53
62
|
"approvals grants list":"read",
|
|
54
63
|
"approvals grants revoke":"write",
|
|
64
|
+
"approvals list":"read",
|
|
55
65
|
"approvals result":"read",
|
|
56
66
|
"approvals walkthrough":"never",
|
|
67
|
+
"approvals withdraw":"write",
|
|
57
68
|
"aside":"never",
|
|
58
69
|
"ask loosening":"write",
|
|
59
70
|
"ask status":"read",
|
|
@@ -85,6 +96,10 @@
|
|
|
85
96
|
"backup server restore-status":"read",
|
|
86
97
|
"backup server status":"read",
|
|
87
98
|
"backup verify":"write",
|
|
99
|
+
"blog draft list":"read",
|
|
100
|
+
"blog draft mark-published":"write",
|
|
101
|
+
"blog draft show":"read",
|
|
102
|
+
"blog draft submit":"write",
|
|
88
103
|
"brain add":"write",
|
|
89
104
|
"brain brief":"read",
|
|
90
105
|
"brain check":"read",
|
|
@@ -139,12 +154,16 @@
|
|
|
139
154
|
"chat-status":"read",
|
|
140
155
|
"claude":"never",
|
|
141
156
|
"completion":"never",
|
|
157
|
+
"compliance jobs list":"read",
|
|
158
|
+
"compliance reports list":"read",
|
|
159
|
+
"compliance reports show":"read",
|
|
142
160
|
"config get":"read",
|
|
143
161
|
"config profile add":"write",
|
|
144
162
|
"config profile list":"read",
|
|
145
163
|
"config profile remove":"write",
|
|
146
164
|
"config profile use":"write",
|
|
147
165
|
"config set":"write",
|
|
166
|
+
"connect":"write",
|
|
148
167
|
"consent grant":"never",
|
|
149
168
|
"consent history":"read",
|
|
150
169
|
"consent list":"read",
|
|
@@ -180,8 +199,11 @@
|
|
|
180
199
|
"contacts retention run":"write",
|
|
181
200
|
"contacts retention status":"read",
|
|
182
201
|
"contacts rewrap":"never",
|
|
202
|
+
"contacts scheduled cancel":"write",
|
|
203
|
+
"contacts scheduled list":"read",
|
|
183
204
|
"contacts search":"read",
|
|
184
205
|
"contacts selftest":"write",
|
|
206
|
+
"contacts send":"write",
|
|
185
207
|
"contacts settings":"write",
|
|
186
208
|
"contacts show":"read",
|
|
187
209
|
"contacts strict-names":"write",
|
|
@@ -258,6 +280,8 @@
|
|
|
258
280
|
"engagement jobs":"read",
|
|
259
281
|
"engagement list":"read",
|
|
260
282
|
"engagement propose":"write",
|
|
283
|
+
"engagement reconcile":"write",
|
|
284
|
+
"engagement reconciliations":"write",
|
|
261
285
|
"engagement regrade-finding":"write",
|
|
262
286
|
"engagement report":"read",
|
|
263
287
|
"engagement report-finding":"write",
|
|
@@ -275,6 +299,7 @@
|
|
|
275
299
|
"engagement show":"read",
|
|
276
300
|
"engagement sync-issues":"write",
|
|
277
301
|
"engagement tools":"read",
|
|
302
|
+
"engagement verify":"read",
|
|
278
303
|
"engagement verify-finding":"write",
|
|
279
304
|
"engagement verify-target":"write",
|
|
280
305
|
"entity create":"write",
|
|
@@ -284,6 +309,12 @@
|
|
|
284
309
|
"entity relate":"write",
|
|
285
310
|
"entity search":"read",
|
|
286
311
|
"entity unrelate":"write",
|
|
312
|
+
"evidence bundle":"write",
|
|
313
|
+
"evidence status":"read",
|
|
314
|
+
"evidence verify":"read",
|
|
315
|
+
"ext add":"write",
|
|
316
|
+
"ext list":"read",
|
|
317
|
+
"ext remove":"write",
|
|
287
318
|
"facebook insights":"read",
|
|
288
319
|
"facebook lead-forms":"read",
|
|
289
320
|
"facebook leads":"read",
|
|
@@ -307,6 +338,7 @@
|
|
|
307
338
|
"fleet gpu":"read",
|
|
308
339
|
"fleet host-update":"write",
|
|
309
340
|
"fleet hosts":"read",
|
|
341
|
+
"fleet ping":"write",
|
|
310
342
|
"fleet rehome-agent":"write",
|
|
311
343
|
"fleet status":"read",
|
|
312
344
|
"fleet summary":"read",
|
|
@@ -343,14 +375,17 @@
|
|
|
343
375
|
"hat list":"read",
|
|
344
376
|
"hat reset":"write",
|
|
345
377
|
"hat show":"read",
|
|
378
|
+
"hat upgrade":"never",
|
|
346
379
|
"hat use":"never",
|
|
347
380
|
"health":"read",
|
|
348
381
|
"hyperion deck":"never",
|
|
349
382
|
"hyperion status":"read",
|
|
383
|
+
"image generate":"write",
|
|
350
384
|
"inbox get":"read",
|
|
351
385
|
"inbox list":"read",
|
|
352
386
|
"inbox respond":"write",
|
|
353
387
|
"inbox stats":"read",
|
|
388
|
+
"inbox unread":"write",
|
|
354
389
|
"inbox walkthrough":"never",
|
|
355
390
|
"instagram accounts":"read",
|
|
356
391
|
"instagram comments":"read",
|
|
@@ -368,6 +403,33 @@
|
|
|
368
403
|
"inventory":"read",
|
|
369
404
|
"invites accept":"never",
|
|
370
405
|
"invites list":"read",
|
|
406
|
+
"kuma coverage propose":"write",
|
|
407
|
+
"kuma coverage show":"read",
|
|
408
|
+
"kuma diagnose":"write",
|
|
409
|
+
"kuma down":"write",
|
|
410
|
+
"kuma hooks create":"never",
|
|
411
|
+
"kuma hooks delete":"write",
|
|
412
|
+
"kuma hooks list":"read",
|
|
413
|
+
"kuma incidents":"write",
|
|
414
|
+
"kuma maintenance end":"write",
|
|
415
|
+
"kuma maintenance list":"read",
|
|
416
|
+
"kuma maintenance open":"never",
|
|
417
|
+
"kuma monitors add":"write",
|
|
418
|
+
"kuma monitors edit":"write",
|
|
419
|
+
"kuma monitors get":"read",
|
|
420
|
+
"kuma monitors list":"read",
|
|
421
|
+
"kuma monitors pause":"write",
|
|
422
|
+
"kuma monitors remove":"write",
|
|
423
|
+
"kuma monitors resume":"write",
|
|
424
|
+
"kuma monitors wire-alerts":"write",
|
|
425
|
+
"kuma refresh":"write",
|
|
426
|
+
"kuma sla list":"read",
|
|
427
|
+
"kuma sla verify":"read",
|
|
428
|
+
"kuma status":"read",
|
|
429
|
+
"kuma status-incident draft":"write",
|
|
430
|
+
"kuma status-incident publish":"write",
|
|
431
|
+
"kuma status-incident resolve":"write",
|
|
432
|
+
"kuma uptime":"write",
|
|
371
433
|
"licence catalogue-sign":"never",
|
|
372
434
|
"licence refresh":"write",
|
|
373
435
|
"licence reissue":"never",
|
|
@@ -379,12 +441,19 @@
|
|
|
379
441
|
"linkedin org":"write",
|
|
380
442
|
"linkedin post":"write",
|
|
381
443
|
"linkedin posts":"read",
|
|
444
|
+
"linkedin whoami":"read",
|
|
382
445
|
"llm status":"read",
|
|
383
446
|
"llm-policy get":"read",
|
|
384
447
|
"llm-policy set":"write",
|
|
385
448
|
"llm-policy test":"write",
|
|
386
449
|
"login":"never",
|
|
387
450
|
"logout":"never",
|
|
451
|
+
"loop core-local add":"write",
|
|
452
|
+
"loop core-local list":"read",
|
|
453
|
+
"loop core-local remove":"write",
|
|
454
|
+
"loop list":"read",
|
|
455
|
+
"loop status":"read",
|
|
456
|
+
"loop watch":"never",
|
|
388
457
|
"lucid ack":"write",
|
|
389
458
|
"lucid area":"read",
|
|
390
459
|
"lucid ask":"read",
|
|
@@ -405,6 +474,7 @@
|
|
|
405
474
|
"lucid teach":"write",
|
|
406
475
|
"lucid told":"read",
|
|
407
476
|
"lucid why":"read",
|
|
477
|
+
"mail account pin":"write",
|
|
408
478
|
"mail accounts":"read",
|
|
409
479
|
"mail connect":"never",
|
|
410
480
|
"mail disconnect":"write",
|
|
@@ -416,10 +486,12 @@
|
|
|
416
486
|
"mail report":"write",
|
|
417
487
|
"mail resolve":"write",
|
|
418
488
|
"mail sync":"write",
|
|
489
|
+
"mail sync-status":"write",
|
|
419
490
|
"mail undo":"write",
|
|
420
491
|
"mail watch active":"write",
|
|
421
492
|
"mail watch add":"write",
|
|
422
493
|
"mail watch list":"read",
|
|
494
|
+
"mail watch rm":"write",
|
|
423
495
|
"mail zones":"read",
|
|
424
496
|
"memory core":"read",
|
|
425
497
|
"memory create":"write",
|
|
@@ -433,6 +505,7 @@
|
|
|
433
505
|
"memory reinstate":"write",
|
|
434
506
|
"memory search":"read",
|
|
435
507
|
"memory stats":"read",
|
|
508
|
+
"memory sync":"never",
|
|
436
509
|
"memory timeline":"read",
|
|
437
510
|
"memory unpin":"write",
|
|
438
511
|
"memory update":"write",
|
|
@@ -460,12 +533,17 @@
|
|
|
460
533
|
"mon docker stats":"read",
|
|
461
534
|
"mon metrics":"read",
|
|
462
535
|
"mon wazuh active-response":"write",
|
|
463
|
-
"mon wazuh agents":"read",
|
|
536
|
+
"mon wazuh agents get":"read",
|
|
464
537
|
"mon wazuh alerts":"read",
|
|
538
|
+
"mon wazuh coverage":"read",
|
|
465
539
|
"mon wazuh deploy-agent":"write",
|
|
466
540
|
"mon wazuh deploy-bulk":"write",
|
|
467
541
|
"mon wazuh deploy-history":"read",
|
|
542
|
+
"mon wazuh fim":"read",
|
|
543
|
+
"mon wazuh rootcheck":"read",
|
|
544
|
+
"mon wazuh sca":"read",
|
|
468
545
|
"mon wazuh status":"read",
|
|
546
|
+
"mon wazuh triage":"read",
|
|
469
547
|
"mon wazuh vulns":"read",
|
|
470
548
|
"monitoring health":"read",
|
|
471
549
|
"monitoring incidents get":"read",
|
|
@@ -500,6 +578,12 @@
|
|
|
500
578
|
"notes schedule resume":"write",
|
|
501
579
|
"notes schedule rm":"write",
|
|
502
580
|
"notes scorecard":"write",
|
|
581
|
+
"notes seal edit":"never",
|
|
582
|
+
"notes seal init":"write",
|
|
583
|
+
"notes seal new":"write",
|
|
584
|
+
"notes seal open":"never",
|
|
585
|
+
"notes seal print":"write",
|
|
586
|
+
"notes seal status":"read",
|
|
503
587
|
"notes search":"read",
|
|
504
588
|
"notes settings list":"read",
|
|
505
589
|
"notes settings set":"write",
|
|
@@ -520,6 +604,7 @@
|
|
|
520
604
|
"objective get":"read",
|
|
521
605
|
"objective halt":"write",
|
|
522
606
|
"objective list":"read",
|
|
607
|
+
"objective retry":"write",
|
|
523
608
|
"objective start":"write",
|
|
524
609
|
"offload release":"write",
|
|
525
610
|
"offload status":"read",
|
|
@@ -608,6 +693,7 @@
|
|
|
608
693
|
"prompt update":"write",
|
|
609
694
|
"prompt versions":"read",
|
|
610
695
|
"provider connect":"write",
|
|
696
|
+
"provider install":"write",
|
|
611
697
|
"provider list":"read",
|
|
612
698
|
"provider test":"read",
|
|
613
699
|
"qlarity allowlist":"write",
|
|
@@ -639,6 +725,9 @@
|
|
|
639
725
|
"quoxchat widgets":"read",
|
|
640
726
|
"reach agent":"read",
|
|
641
727
|
"reach unused":"read",
|
|
728
|
+
"research domains add":"write",
|
|
729
|
+
"research domains list":"read",
|
|
730
|
+
"research domains remove":"write",
|
|
642
731
|
"role agent clear":"write",
|
|
643
732
|
"role agent list":"read",
|
|
644
733
|
"role agent set":"write",
|
|
@@ -698,6 +787,7 @@
|
|
|
698
787
|
"seo gaps":"read",
|
|
699
788
|
"seo health":"read",
|
|
700
789
|
"seo keywords":"read",
|
|
790
|
+
"seo queries":"read",
|
|
701
791
|
"seo remove-site":"write",
|
|
702
792
|
"seo report deliver":"write",
|
|
703
793
|
"seo sites":"read",
|
|
@@ -710,6 +800,13 @@
|
|
|
710
800
|
"server config lan-targets":"write",
|
|
711
801
|
"server diag":"write",
|
|
712
802
|
"server doctor":"read",
|
|
803
|
+
"server go":"never",
|
|
804
|
+
"server install":"never",
|
|
805
|
+
"server list":"read",
|
|
806
|
+
"server mark":"write",
|
|
807
|
+
"server roles list":"read",
|
|
808
|
+
"server roles set":"write",
|
|
809
|
+
"server roles unset":"write",
|
|
713
810
|
"server rollback":"write",
|
|
714
811
|
"server status":"read",
|
|
715
812
|
"server uninstall":"never",
|
|
@@ -730,6 +827,8 @@
|
|
|
730
827
|
"setup license link":"write",
|
|
731
828
|
"setup license status":"read",
|
|
732
829
|
"setup status":"read",
|
|
830
|
+
"shortcut add":"write",
|
|
831
|
+
"shortcut remove":"write",
|
|
733
832
|
"signup":"never",
|
|
734
833
|
"sitrep":"read",
|
|
735
834
|
"skills disclosures":"read",
|
|
@@ -812,8 +911,10 @@
|
|
|
812
911
|
"tool exec":"write",
|
|
813
912
|
"tool get":"read",
|
|
814
913
|
"tool install":"write",
|
|
914
|
+
"tool installed":"read",
|
|
815
915
|
"tool list":"read",
|
|
816
916
|
"tool publish":"write",
|
|
917
|
+
"tool uninstall":"write",
|
|
817
918
|
"tool update":"write",
|
|
818
919
|
"trace compare":"read",
|
|
819
920
|
"trace comparison create":"write",
|
|
@@ -913,6 +1014,35 @@
|
|
|
913
1014
|
"volt verify":"read",
|
|
914
1015
|
"watch fleet":"read",
|
|
915
1016
|
"watch services":"read",
|
|
1017
|
+
"wazuh active-response":"write",
|
|
1018
|
+
"wazuh agents get":"read",
|
|
1019
|
+
"wazuh alerts":"read",
|
|
1020
|
+
"wazuh connect":"never",
|
|
1021
|
+
"wazuh coverage":"read",
|
|
1022
|
+
"wazuh deploy":"write",
|
|
1023
|
+
"wazuh deploy-bulk":"write",
|
|
1024
|
+
"wazuh deploy-history":"read",
|
|
1025
|
+
"wazuh fim":"read",
|
|
1026
|
+
"wazuh hooks create":"never",
|
|
1027
|
+
"wazuh hooks delete":"write",
|
|
1028
|
+
"wazuh hooks install":"never",
|
|
1029
|
+
"wazuh hooks list":"read",
|
|
1030
|
+
"wazuh hooks rotate":"never",
|
|
1031
|
+
"wazuh incidents close":"write",
|
|
1032
|
+
"wazuh incidents diagnose":"write",
|
|
1033
|
+
"wazuh incidents escalate":"write",
|
|
1034
|
+
"wazuh incidents show":"read",
|
|
1035
|
+
"wazuh indexer install-credential":"write",
|
|
1036
|
+
"wazuh remove":"write",
|
|
1037
|
+
"wazuh report generate":"write",
|
|
1038
|
+
"wazuh report list":"read",
|
|
1039
|
+
"wazuh report show":"read",
|
|
1040
|
+
"wazuh report verify":"read",
|
|
1041
|
+
"wazuh rootcheck":"read",
|
|
1042
|
+
"wazuh sca":"read",
|
|
1043
|
+
"wazuh status":"read",
|
|
1044
|
+
"wazuh triage":"read",
|
|
1045
|
+
"wazuh vulns":"read",
|
|
916
1046
|
"webhook create":"write",
|
|
917
1047
|
"webhook delete":"write",
|
|
918
1048
|
"webhook list":"read",
|
|
@@ -945,4 +1075,11 @@
|
|
|
945
1075
|
"x search":"write",
|
|
946
1076
|
"x status":"read",
|
|
947
1077
|
"x thread":"write",
|
|
948
|
-
"x timeline":"write"
|
|
1078
|
+
"x timeline":"write",
|
|
1079
|
+
"x whoami":"write",
|
|
1080
|
+
"youtube analytics":"write",
|
|
1081
|
+
"youtube channel":"write",
|
|
1082
|
+
"youtube comment":"write",
|
|
1083
|
+
"youtube thumbnail":"write",
|
|
1084
|
+
"youtube upload":"write",
|
|
1085
|
+
"youtube videos":"read"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /evidence: export this conversation's signed evidence bundle (the same call as `quox evidence bundle`) to
|
|
3
|
+
* ~/quox-evidence/<conversation>-<timestamp>.zip and say what is in it. /ward lists the WARD receipts the export found
|
|
4
|
+
* (newest ten, then N more). /envelope, /envelopes and /aee are pointers to /proof (the envelope ids); /volt is the
|
|
5
|
+
* VOLT run, which travels inside the bundle. Pure formatting plus one api call; the lines are { text, tone }.
|
|
6
|
+
*/
|
|
7
|
+
import { wrapHang } from '../objects/model.js';
|
|
8
|
+
export const EVIDENCE_ALIASES = ['envelope', 'envelopes', 'aee', 'volt', 'ward'];
|
|
9
|
+
const SHOWN = 10;
|
|
10
|
+
|
|
11
|
+
export async function runEvidenceCommand({ cmd, api, conversationId, cols = Infinity }) {
|
|
12
|
+
const W = Number.isFinite(cols) ? Math.max(20, cols - 4) : 1e9;
|
|
13
|
+
const wrapT = (l) => wrapHang(l.text, W, 4).map(text => ({ ...l, text }));
|
|
14
|
+
if (!api || typeof api.evidenceExport !== 'function') return [{ text: 'Evidence export is not available in this mode. In a terminal: quox evidence bundle', tone: 'warn' }].flatMap(wrapT);
|
|
15
|
+
if (!conversationId) return [{ text: 'No conversation to export yet: send a message first, or in a terminal run quox evidence bundle <conversation id>.', tone: 'warn' }].flatMap(wrapT);
|
|
16
|
+
let r;
|
|
17
|
+
try { r = await api.evidenceExport(conversationId); } catch (e) {
|
|
18
|
+
return [{ text: `Evidence export failed: ${e?.message || 'failed'}. Nothing was written.`, tone: 'warn' }].flatMap(wrapT);
|
|
19
|
+
}
|
|
20
|
+
const out = [];
|
|
21
|
+
const ok = r.verify && r.verify.ok;
|
|
22
|
+
out.push({ text: `${ok ? '✔' : '✖'} evidence bundle ${ok ? 'written and verified' : 'written but FAILED verification'}: ${r.path}`, tone: ok ? 'ok' : 'warn' });
|
|
23
|
+
out.push({ text: ` ${r.envelopes} envelopes, ${r.receipts} WARD receipts, conversation ${r.corr}`, tone: 'dim' });
|
|
24
|
+
if (cmd === '/ward') {
|
|
25
|
+
out.push({ text: ' WARD receipts for this conversation (the same bundle /evidence writes):', tone: 'dim' });
|
|
26
|
+
const rows = [...(r.receiptRows || [])].sort((a, b) => (b.seq || 0) - (a.seq || 0));
|
|
27
|
+
for (const x of rows.slice(0, SHOWN)) out.push({ text: ` WARD seq ${x.seq} envelope ${x.envelope_id}`, tone: 'dim' });
|
|
28
|
+
if (rows.length > SHOWN) out.push({ text: ` ${rows.length - SHOWN} more in the bundle`, tone: 'dim' });
|
|
29
|
+
if (!rows.length) out.push({ text: ' No WARD receipt was found for this conversation\'s envelopes yet (witnessing can lag a few seconds).', tone: 'warn' });
|
|
30
|
+
}
|
|
31
|
+
if (cmd === '/volt') out.push({ text: ' The VOLT run (if this conversation has one) is volt.json inside the bundle.', tone: 'dim' });
|
|
32
|
+
out.push({ text: ` check it offline: quox evidence verify ${r.path}`, tone: 'dim' });
|
|
33
|
+
return out.flatMap(wrapT);
|
|
34
|
+
}
|
|
@@ -122,7 +122,7 @@ export function createHatWalk({ api, say, bump = () => {} }) {
|
|
|
122
122
|
if (!m.hat) { say(`No hat matches "${arg}". Your own hats: ${hatChoices(mine) || 'none yet'}.`, 'warn'); return null; }
|
|
123
123
|
if (!isCustom(m.hat)) {
|
|
124
124
|
say(verb === 'edit'
|
|
125
|
-
? `${nameOf(m.hat)} is a built-in hat, so it is not edited here.
|
|
125
|
+
? `${nameOf(m.hat)} is a built-in hat, so it is not edited here. Reset it, or start from it with /hat new.`
|
|
126
126
|
: `${nameOf(m.hat)} is a built-in hat and cannot be deleted. It can be reset, or used as a starting point with /hat new.`, 'warn');
|
|
127
127
|
return null;
|
|
128
128
|
}
|