quoxcli 0.4.0 → 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.
Files changed (175) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +2 -2
  3. package/bin/quox.js +19 -1
  4. package/bin/quoxon.js +6 -1
  5. package/lib/api/endpoints/admin.js +7 -0
  6. package/lib/api/endpoints/agent-attach.js +7 -0
  7. package/lib/api/endpoints/compliance.js +25 -0
  8. package/lib/api/endpoints/inbox.js +6 -0
  9. package/lib/api/endpoints/inboxq.js +19 -0
  10. package/lib/api/endpoints/index.js +2 -0
  11. package/lib/api/endpoints/mon.js +122 -0
  12. package/lib/api/endpoints/tools.js +13 -0
  13. package/lib/api/endpoints/v1.js +13 -0
  14. package/lib/commands/admin.js +35 -0
  15. package/lib/commands/agentAttach.js +15 -0
  16. package/lib/commands/approvals.js +193 -3
  17. package/lib/commands/ask.js +1 -1
  18. package/lib/commands/auth.js +64 -11
  19. package/lib/commands/backup.js +11 -4
  20. package/lib/commands/capabilities.js +3 -2
  21. package/lib/commands/chat.js +15 -0
  22. package/lib/commands/claude.js +4 -1
  23. package/lib/commands/compliance.js +109 -0
  24. package/lib/commands/connect.js +69 -0
  25. package/lib/commands/dev.js +6 -8
  26. package/lib/commands/doctor.js +22 -3
  27. package/lib/commands/evidence.js +2 -1
  28. package/lib/commands/gripe.js +24 -13
  29. package/lib/commands/inbox.js +37 -3
  30. package/lib/commands/inboxq.js +147 -0
  31. package/lib/commands/kuma.js +78 -5
  32. package/lib/commands/licenceLinkView.js +311 -0
  33. package/lib/commands/linkedin.js +19 -0
  34. package/lib/commands/loop.js +30 -3
  35. package/lib/commands/lucid.js +1 -0
  36. package/lib/commands/mail.js +161 -20
  37. package/lib/commands/memory.js +68 -4
  38. package/lib/commands/memorySync.js +158 -0
  39. package/lib/commands/mon.js +55 -144
  40. package/lib/commands/notes.js +29 -7
  41. package/lib/commands/notesSeal.js +259 -0
  42. package/lib/commands/objective.js +5 -2
  43. package/lib/commands/offload.js +2 -3
  44. package/lib/commands/plan.js +17 -0
  45. package/lib/commands/provider.js +29 -8
  46. package/lib/commands/qlarity.js +32 -1
  47. package/lib/commands/run.js +2 -1
  48. package/lib/commands/server.js +37 -0
  49. package/lib/commands/setup.js +127 -75
  50. package/lib/commands/skills.js +4 -1
  51. package/lib/commands/slot.js +49 -9
  52. package/lib/commands/status.js +92 -44
  53. package/lib/commands/tool.js +30 -0
  54. package/lib/commands/vault.js +6 -3
  55. package/lib/commands/walkthrough.js +14 -2
  56. package/lib/commands/watch.js +11 -2
  57. package/lib/commands/wazuh.js +824 -0
  58. package/lib/commands/wazuhIntake.js +317 -0
  59. package/lib/commands/wazuhReport.js +192 -0
  60. package/lib/commands/workflow.js +47 -4
  61. package/lib/commands/x.js +50 -0
  62. package/lib/core/announce.js +86 -0
  63. package/lib/core/auth.js +20 -2
  64. package/lib/core/callMe.js +118 -0
  65. package/lib/core/client.js +27 -1
  66. package/lib/core/commandRegistrars.js +8 -0
  67. package/lib/core/config.js +28 -2
  68. package/lib/core/confirm.js +68 -7
  69. package/lib/core/crossOrgApprovals.js +69 -0
  70. package/lib/core/errors.js +52 -1
  71. package/lib/core/governedSession.js +135 -5
  72. package/lib/core/inboxResolution.js +3 -2
  73. package/lib/core/loginGuard.js +73 -0
  74. package/lib/core/offload.js +37 -0
  75. package/lib/core/org-override.js +5 -1
  76. package/lib/core/output.js +1 -1
  77. package/lib/core/profileTrust.js +182 -0
  78. package/lib/core/quoxglyph.js +22 -1
  79. package/lib/core/router.js +14 -0
  80. package/lib/core/stepUpPrompt.js +99 -0
  81. package/lib/core/version.js +1 -1
  82. package/lib/core/walkthrough.js +9 -5
  83. package/lib/dragon/select.js +2 -2
  84. package/lib/quoxon/EXTENSIONS.md +142 -19
  85. package/lib/quoxon/api.js +185 -34
  86. package/lib/quoxon/app.js +1032 -152
  87. package/lib/quoxon/approvalBatch.js +117 -0
  88. package/lib/quoxon/approvalFacts.js +56 -2
  89. package/lib/quoxon/approvalSentence.js +8 -4
  90. package/lib/quoxon/approvalsView.js +69 -11
  91. package/lib/quoxon/autoOpen.js +94 -0
  92. package/lib/quoxon/backgroundWork.js +59 -0
  93. package/lib/quoxon/bang.js +1 -1
  94. package/lib/quoxon/capabilities.js +7 -2
  95. package/lib/quoxon/commandShort.js +7 -0
  96. package/lib/quoxon/commands.js +40 -10
  97. package/lib/quoxon/connect.js +5 -3
  98. package/lib/quoxon/deckLazy.js +58 -0
  99. package/lib/quoxon/destructive.js +35 -0
  100. package/lib/quoxon/dnd.js +71 -0
  101. package/lib/quoxon/dragonCompanion.js +37 -7
  102. package/lib/quoxon/dragonMoments.js +78 -0
  103. package/lib/quoxon/echo.js +1 -0
  104. package/lib/quoxon/events.js +43 -7
  105. package/lib/quoxon/extensions.js +398 -38
  106. package/lib/quoxon/gripeQueue.js +135 -0
  107. package/lib/quoxon/inboxView.js +125 -22
  108. package/lib/quoxon/keys.js +2 -2
  109. package/lib/quoxon/loopCard.js +5 -1
  110. package/lib/quoxon/loopCards.js +17 -8
  111. package/lib/quoxon/loopStream.js +20 -9
  112. package/lib/quoxon/mailView.js +71 -0
  113. package/lib/quoxon/main.js +20 -5
  114. package/lib/quoxon/markdown.js +1 -1
  115. package/lib/quoxon/model.js +15 -0
  116. package/lib/quoxon/neverAnswered.js +20 -0
  117. package/lib/quoxon/objects/away.js +43 -5
  118. package/lib/quoxon/onboarding/connectServer.js +162 -0
  119. package/lib/quoxon/onboarding/copy.js +6 -0
  120. package/lib/quoxon/onboarding/index.js +5 -43
  121. package/lib/quoxon/onboarding/probe.js +20 -1
  122. package/lib/quoxon/onboarding/view.js +16 -3
  123. package/lib/quoxon/orgSwitch.js +22 -0
  124. package/lib/quoxon/print.js +2 -0
  125. package/lib/quoxon/profileSwitch.js +7 -0
  126. package/lib/quoxon/promptHistory.js +3 -1
  127. package/lib/quoxon/render.js +63 -14
  128. package/lib/quoxon/roster.js +10 -5
  129. package/lib/quoxon/rosterSessions.js +44 -0
  130. package/lib/quoxon/screenContext.js +1 -1
  131. package/lib/quoxon/secretShape.js +86 -0
  132. package/lib/quoxon/slash/agents.js +2 -1
  133. package/lib/quoxon/slash/argSources.js +9 -2
  134. package/lib/quoxon/slash/args.js +4 -2
  135. package/lib/quoxon/slash/broadcast.js +18 -5
  136. package/lib/quoxon/slash/broadcastRun.js +13 -2
  137. package/lib/quoxon/slash/cliLeaves.json +63 -1
  138. package/lib/quoxon/slash/hatWalk.js +1 -1
  139. package/lib/quoxon/slash/palette.js +22 -1
  140. package/lib/quoxon/slash/paletteController.js +10 -4
  141. package/lib/quoxon/slash/restart.js +7 -4
  142. package/lib/quoxon/slash/stepUp.js +5 -5
  143. package/lib/quoxon/slash/stepUpCmds.js +74 -1
  144. package/lib/quoxon/slashSpinner.js +35 -0
  145. package/lib/quoxon/slotAttach.js +8 -0
  146. package/lib/quoxon/slotChat.js +17 -0
  147. package/lib/quoxon/slotFormat.js +1 -1
  148. package/lib/quoxon/slotOutbox.js +113 -0
  149. package/lib/quoxon/suggestCommand.js +1 -1
  150. package/lib/quoxon/term.js +25 -1
  151. package/lib/quoxon/transcript.js +2 -1
  152. package/lib/quoxon/welcome.js +1 -1
  153. package/lib/quoxon/whatsnew.js +1 -1
  154. package/lib/quoxon/whatsnew.jsonl +36 -0
  155. package/lib/server/installFlow.js +168 -0
  156. package/lib/server/status.js +15 -1
  157. package/lib/toolOutputShape.js +55 -0
  158. package/package.json +3 -2
  159. package/vendor/dragonlab/SOURCE +3 -3
  160. package/vendor/dragonlab/design/quoxperticus/v2/quoxperticus-master.svg +59 -0
  161. package/vendor/dragonlab/design/quoxperticus/v3/character.mjs +43 -0
  162. package/vendor/dragonlab/design/quoxperticus/v4/character.mjs +57 -0
  163. package/vendor/dragonlab/design/quoxperticus/v4/review.mjs +35 -0
  164. package/vendor/dragonlab/design/quoxperticus/v4/watch.mjs +56 -0
  165. package/vendor/dragonlab/design/vulcan/v1/character.mjs +34 -0
  166. package/vendor/dragonlab/design/vulcan/v1/vulcan-master.svg +57 -0
  167. package/vendor/dragonlab/design/vulcan/v2/character.mjs +39 -0
  168. package/vendor/dragonlab/design/vulcan/v3/character.mjs +41 -0
  169. package/vendor/dragonlab/design/vulcan/v3/review.mjs +35 -0
  170. package/vendor/dragonlab/design/vulcan/v3/watch.mjs +56 -0
  171. package/vendor/dragonlab/factory/svg-rig-contour.mjs +64 -0
  172. package/vendor/dragonlab/integration/companions-v1/characters.mjs +20 -0
  173. package/vendor/dragonlab/integration/companions-v1/quoxperticus.mjs +2 -0
  174. package/vendor/dragonlab/integration/companions-v1/view.mjs +1 -1
  175. package/vendor/dragonlab/integration/companions-v1/vulcan.mjs +2 -0
@@ -4,11 +4,13 @@
4
4
  * quox vault <subcommand> [options]
5
5
  */
6
6
 
7
+ import { withStepUp } from '../core/stepUpPrompt.js';
7
8
  import chalk from 'chalk';
8
9
  import Table from 'cli-table3';
9
10
  import ora from 'ora';
10
11
  import { formatOutput, formatDetail, printSuccess, printWarning, printInfo } from '../core/output.js';
11
12
  import { events, printEvent, line as glyphLine } from '../core/quoxglyph.js';
13
+ import { announce, announceOnFail } from '../core/announce.js';
12
14
  import { resolveOrgId } from './helpers.js';
13
15
  import { resolveEndpoint } from '../api/endpoints.js';
14
16
 
@@ -177,7 +179,7 @@ export function makeVaultGetAction({ client, auth }, program) {
177
179
  }
178
180
 
179
181
  export function makeVaultCreateAction({ client, auth }, program) {
180
- return async (options) => {
182
+ return announceOnFail('vault', (options) => `create credential ${options?.label || ''}`.trim(), async (options) => {
181
183
  auth.requireAuth();
182
184
  const orgId = resolveOrgId(auth, program);
183
185
 
@@ -397,9 +399,10 @@ export function makeVaultCreateAction({ client, auth }, program) {
397
399
  printInfo(`note: not set as default — run "quox vault set-default ${result.id}" to make it the active ${result.integration_type || integrationType} credential`);
398
400
  }
399
401
 
402
+ announce('vault', `credential created ${result.label || ''}`.trim(), { result: `${result.id} · ${result.integration_type || integrationType}` });
400
403
  formatDetail(result, { format: program.opts().output });
401
404
  return result;
402
- };
405
+ });
403
406
  }
404
407
 
405
408
  export function makeVaultUpdateAction({ client, auth }, program) {
@@ -1305,7 +1308,7 @@ export function registerVaultCommands(program, ctx) {
1305
1308
  throw new Error('--duration must be a positive number of minutes.');
1306
1309
  }
1307
1310
  const ep = resolveEndpoint('vault.leases.approve', { orgId, leaseId });
1308
- const result = await client.post(ep.path, { service: ep.service, body: { duration_minutes: duration } });
1311
+ const result = await withStepUp((headers) => client.post(ep.path, { service: ep.service, headers, body: { duration_minutes: duration } }), { client, orgId, io: ctx.stepUpIO, what: 'This lease approval' });
1309
1312
  printEvent(events.updated('quox', 'credential lease', leaseId, `approved for ${duration}m`));
1310
1313
  formatDetail(result, { format: program.opts().output });
1311
1314
  });
@@ -3,14 +3,17 @@ import { createInterface } from 'node:readline';
3
3
  import { resolveEndpoint } from '../api/endpoints.js';
4
4
  import { resolveOrgId } from './helpers.js';
5
5
  import { runWalkthrough } from '../core/walkthrough.js';
6
+ import { otherOrgsWaiting, crossOrgLines, clientForTarget } from '../core/crossOrgApprovals.js';
6
7
 
7
- export function attachWalkthrough(parent, { client, auth }, program) {
8
+ export function attachWalkthrough(parent, { client: baseClient, auth, clientForOrg }, program) {
8
9
  parent
9
10
  .command('walkthrough')
10
11
  .description('Walk through the questions waiting for you one at a time: what it does, why, my advice, then your choice')
11
12
  .action(async () => {
12
13
  auth.requireAuth();
13
14
  const orgId = resolveOrgId(auth, program);
15
+ const sessionOrg = auth.getOrgId();
16
+ const client = await clientForTarget({ client: baseClient, clientForOrg, sessionOrgId: sessionOrg, orgId });
14
17
  const lp = resolveEndpoint('inbox.list', { orgId });
15
18
  const data = await client.get(lp.path, { service: lp.service, query: { status: 'open', limit: 200 } });
16
19
  const items = (data && (data.items || data)) || [];
@@ -24,9 +27,18 @@ export function attachWalkthrough(parent, { client, auth }, program) {
24
27
  readLine, write: (l) => console.log(l),
25
28
  answer: async (it, key, note) => {
26
29
  const ep = resolveEndpoint('inbox.respond', { orgId, itemId: it.id });
27
- await client.post(ep.path, { service: ep.service, body: { action: 'answer', option: key, ...(note ? { comment: String(note).slice(0, 4000) } : {}) } });
30
+ const comment = note ? { comment: String(note).slice(0, 4000) } : {};
31
+ if (it.__approval) { // a policy-held approval: the same respond path as `quox approvals approve|deny`
32
+ // No PIN prompt here (the walk owns stdin): a server step-up refusal leaves it open, `quox approvals approve <id>` takes the PIN.
33
+ await client.post(ep.path, { service: ep.service, body: { action: key === 'y' ? 'approve' : 'reject', ...comment } });
34
+ return;
35
+ }
36
+ await client.post(ep.path, { service: ep.service, body: { action: 'answer', option: key, ...comment } });
28
37
  },
29
38
  });
30
39
  } finally { rl.close(); }
40
+ // Approvals waiting in the user's OTHER orgs: a count and the command, never the cards.
41
+ const more = crossOrgLines(await otherOrgsWaiting({ client: baseClient, currentOrgId: orgId }), 'walkthrough');
42
+ for (const l of more) console.log(l);
31
43
  });
32
44
  }
@@ -52,6 +52,14 @@ export async function probeService(url, fetchImpl = fetch, timeoutMs = 8000) {
52
52
  }
53
53
  }
54
54
 
55
+ /** Parse --interval: honour it down to `min`, report when it was raised. */
56
+ export function clampInterval(raw, min, def) {
57
+ const n = parseInt(raw, 10);
58
+ if (!Number.isFinite(n) || n <= 0) return { seconds: def, clamped: false };
59
+ if (n < min) return { seconds: min, clamped: true };
60
+ return { seconds: n, clamped: false };
61
+ }
62
+
55
63
  export function registerWatchCommands(program, { client, auth, config }) {
56
64
  const watch = program
57
65
  .command('watch')
@@ -126,7 +134,8 @@ export function registerWatchCommands(program, { client, auth, config }) {
126
134
  .description('Live service health dashboard')
127
135
  .option('--interval <seconds>', 'Refresh interval', '10')
128
136
  .action(async (opts) => {
129
- const interval = Math.max(5, parseInt(opts.interval, 10) || 10) * 1000;
137
+ const iv = clampInterval(opts.interval, 1, 10);
138
+ const interval = iv.seconds * 1000;
130
139
  const services = [
131
140
  { name: 'auth', port: 3101, path: '/health' },
132
141
  { name: 'collector', port: 9848, path: '/health' },
@@ -157,7 +166,7 @@ export function registerWatchCommands(program, { client, auth, config }) {
157
166
  else if (r.status === 'timeout') console.log(` ${chalk.yellow('●')} ${r.name.padEnd(14)} ${chalk.yellow('slow (no answer in ' + Math.round(r.latency_ms / 1000) + 's)')}`);
158
167
  else console.log(` ${chalk.red('●')} ${r.name.padEnd(14)} ${chalk.red('down')} ${chalk.dim(r.reason || '')}`);
159
168
  }
160
- console.log(chalk.dim('\n refreshing every ' + (interval / 1000) + 's'));
169
+ console.log(chalk.dim('\n refreshing every ' + (interval / 1000) + 's' + (iv.clamped ? ' (minimum is 1s)' : '')));
161
170
  };
162
171
 
163
172
  await tick();