@poolzin/pool-bot 2026.3.7 → 2026.3.10

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 (150) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +147 -69
  3. package/dist/.buildstamp +1 -1
  4. package/dist/agents/error-classifier.js +251 -0
  5. package/dist/agents/skills/security.js +211 -0
  6. package/dist/build-info.json +3 -3
  7. package/dist/cli/cron-cli/register.cron-dashboard.js +339 -0
  8. package/dist/cli/cron-cli/register.js +2 -0
  9. package/dist/cli/errors.js +187 -0
  10. package/dist/cli/lazy-commands.example.js +113 -0
  11. package/dist/cli/lazy-commands.js +329 -0
  12. package/dist/cli/program/command-registry.js +26 -0
  13. package/dist/cli/program/register.maintenance.js +21 -0
  14. package/dist/cli/program/register.skills.js +4 -0
  15. package/dist/cli/program/register.subclis.js +9 -0
  16. package/dist/cli/swarm-cli/register.js +8 -0
  17. package/dist/cli/swarm-cli/register.swarm-status.js +488 -0
  18. package/dist/cli/telemetry-cli/register.js +10 -0
  19. package/dist/cli/telemetry-cli/register.telemetry-alerts.js +176 -0
  20. package/dist/cli/telemetry-cli/register.telemetry-metrics.js +323 -0
  21. package/dist/cli/telemetry-cli/register.telemetry-status.js +179 -0
  22. package/dist/commands/doctor-checks.js +498 -0
  23. package/dist/config/config.js +1 -0
  24. package/dist/config/secrets-integration.js +88 -0
  25. package/dist/context-engine/index.js +33 -0
  26. package/dist/context-engine/legacy.js +179 -0
  27. package/dist/context-engine/registry.js +86 -0
  28. package/dist/context-engine/summarizing.js +290 -0
  29. package/dist/context-engine/types.js +7 -0
  30. package/dist/cron/service/timer.js +18 -0
  31. package/dist/gateway/protocol/index.js +5 -2
  32. package/dist/gateway/protocol/schema/error-codes.js +1 -0
  33. package/dist/gateway/protocol/schema/swarm.js +80 -0
  34. package/dist/gateway/protocol/schema.js +1 -0
  35. package/dist/gateway/server-close.js +4 -0
  36. package/dist/gateway/server-constants.js +1 -0
  37. package/dist/gateway/server-cron.js +29 -0
  38. package/dist/gateway/server-maintenance.js +35 -2
  39. package/dist/gateway/server-methods/swarm.js +58 -0
  40. package/dist/gateway/server-methods/telemetry.js +71 -0
  41. package/dist/gateway/server-methods-list.js +8 -0
  42. package/dist/gateway/server-methods.js +9 -2
  43. package/dist/gateway/server.impl.js +33 -16
  44. package/dist/infra/abort-pattern.js +106 -0
  45. package/dist/infra/retry.js +96 -0
  46. package/dist/secrets/index.js +28 -0
  47. package/dist/secrets/resolver.js +185 -0
  48. package/dist/secrets/runtime.js +142 -0
  49. package/dist/secrets/types.js +11 -0
  50. package/dist/security/dangerous-tools.js +80 -0
  51. package/dist/security/types.js +12 -0
  52. package/dist/skills/commands.js +333 -0
  53. package/dist/skills/index.js +164 -0
  54. package/dist/skills/loader.js +282 -0
  55. package/dist/skills/parser.js +446 -0
  56. package/dist/skills/registry.js +394 -0
  57. package/dist/skills/security.js +312 -0
  58. package/dist/skills/types.js +21 -0
  59. package/dist/swarm/service.js +247 -0
  60. package/dist/telemetry/alert-engine.js +258 -0
  61. package/dist/telemetry/cron-instrumentation.js +49 -0
  62. package/dist/telemetry/gateway-instrumentation.js +80 -0
  63. package/dist/telemetry/instrumentation.js +66 -0
  64. package/dist/telemetry/service.js +345 -0
  65. package/dist/test-utils/index.js +219 -0
  66. package/dist/tui/components/assistant-message.js +6 -2
  67. package/dist/tui/components/hyperlink-markdown.js +32 -0
  68. package/dist/tui/components/searchable-select-list.js +12 -1
  69. package/dist/tui/components/user-message.js +6 -2
  70. package/dist/tui/index.js +611 -0
  71. package/dist/tui/theme/theme-detection.js +226 -0
  72. package/dist/tui/tui-command-handlers.js +20 -0
  73. package/dist/tui/tui-formatters.js +4 -3
  74. package/dist/tui/utils/ctrl-c-handler.js +67 -0
  75. package/dist/tui/utils/osc8-hyperlinks.js +208 -0
  76. package/dist/tui/utils/safe-stop.js +180 -0
  77. package/dist/tui/utils/session-key-utils.js +81 -0
  78. package/dist/tui/utils/text-sanitization.js +284 -0
  79. package/dist/utils/lru-cache.js +116 -0
  80. package/dist/utils/performance.js +199 -0
  81. package/dist/utils/retry.js +240 -0
  82. package/docs/INTEGRATION_PLAN.md +475 -0
  83. package/docs/INTEGRATION_SUMMARY.md +215 -0
  84. package/docs/MELHORIAS_IMPLEMENTADAS.md +228 -0
  85. package/docs/MELHORIAS_PROFISSIONAIS.md +282 -0
  86. package/docs/PLANO_ACAO_TUI.md +357 -0
  87. package/docs/PROGRESSO_TUI.md +66 -0
  88. package/docs/RELATORIO_FINAL.md +217 -0
  89. package/docs/diagnostico-shell-completion.md +265 -0
  90. package/docs/features/advanced-memory.md +585 -0
  91. package/docs/features/discord-components-v2.md +277 -0
  92. package/docs/features/swarm.md +100 -0
  93. package/docs/features/telemetry.md +284 -0
  94. package/docs/integrations/HEXSTRIKE_PLAN.md +796 -0
  95. package/docs/integrations/INTEGRATION_PLAN.md +744 -0
  96. package/docs/integrations/PAGE_AGENT_PLAN.md +370 -0
  97. package/docs/integrations/XYOPS_PLAN.md +978 -0
  98. package/docs/models/provider-infrastructure.md +400 -0
  99. package/docs/security/exec-approvals.md +294 -0
  100. package/docs/skills/IMPLEMENTATION_SUMMARY.md +145 -0
  101. package/docs/skills/SKILL.md +524 -0
  102. package/docs/skills.md +405 -0
  103. package/extensions/bluebubbles/package.json +1 -1
  104. package/extensions/copilot-proxy/package.json +1 -1
  105. package/extensions/diagnostics-otel/package.json +1 -1
  106. package/extensions/discord/package.json +1 -1
  107. package/extensions/feishu/package.json +1 -1
  108. package/extensions/google-antigravity-auth/package.json +1 -1
  109. package/extensions/google-gemini-cli-auth/package.json +1 -1
  110. package/extensions/googlechat/package.json +1 -1
  111. package/extensions/hexstrike-bridge/README.md +119 -0
  112. package/extensions/hexstrike-bridge/index.test.ts +247 -0
  113. package/extensions/hexstrike-bridge/index.ts +487 -0
  114. package/extensions/hexstrike-bridge/package.json +17 -0
  115. package/extensions/imessage/package.json +1 -1
  116. package/extensions/irc/package.json +1 -1
  117. package/extensions/line/package.json +1 -1
  118. package/extensions/llm-task/package.json +1 -1
  119. package/extensions/lobster/package.json +1 -1
  120. package/extensions/matrix/CHANGELOG.md +5 -0
  121. package/extensions/matrix/package.json +1 -1
  122. package/extensions/mattermost/package.json +1 -1
  123. package/extensions/mcp-server/index.ts +14 -0
  124. package/extensions/mcp-server/package.json +11 -0
  125. package/extensions/mcp-server/src/service.ts +540 -0
  126. package/extensions/memory-core/package.json +1 -1
  127. package/extensions/memory-lancedb/package.json +1 -1
  128. package/extensions/minimax-portal-auth/package.json +1 -1
  129. package/extensions/msteams/CHANGELOG.md +5 -0
  130. package/extensions/msteams/package.json +1 -1
  131. package/extensions/nextcloud-talk/package.json +1 -1
  132. package/extensions/nostr/CHANGELOG.md +5 -0
  133. package/extensions/nostr/package.json +1 -1
  134. package/extensions/open-prose/package.json +1 -1
  135. package/extensions/openai-codex-auth/package.json +1 -1
  136. package/extensions/signal/package.json +1 -1
  137. package/extensions/slack/package.json +1 -1
  138. package/extensions/telegram/package.json +1 -1
  139. package/extensions/tlon/package.json +1 -1
  140. package/extensions/twitch/CHANGELOG.md +5 -0
  141. package/extensions/twitch/package.json +1 -1
  142. package/extensions/voice-call/CHANGELOG.md +5 -0
  143. package/extensions/voice-call/package.json +1 -1
  144. package/extensions/whatsapp/package.json +1 -1
  145. package/extensions/zalo/CHANGELOG.md +5 -0
  146. package/extensions/zalo/package.json +1 -1
  147. package/extensions/zalouser/CHANGELOG.md +5 -0
  148. package/extensions/zalouser/package.json +1 -1
  149. package/package.json +8 -1
  150. package/skills/example-skill/SKILL.md +195 -0
@@ -272,6 +272,15 @@ const entries = [
272
272
  mod.registerCompletionCli(program);
273
273
  },
274
274
  },
275
+ {
276
+ name: "telemetry",
277
+ description: "OpenTelemetry observability and metrics",
278
+ hasSubcommands: true,
279
+ register: async (program) => {
280
+ const mod = await import("../telemetry-cli/register.js");
281
+ mod.registerTelemetryCli(program);
282
+ },
283
+ },
275
284
  ];
276
285
  export function getSubCliEntries() {
277
286
  return entries;
@@ -0,0 +1,8 @@
1
+ import { registerSwarmCreateCommand, registerSwarmListCommand, registerSwarmStatusCommand, } from "./register.swarm-status.js";
2
+ export function registerSwarmCommand(program) {
3
+ const swarm = program.command("swarm").description("Agent swarm coordination and management");
4
+ registerSwarmStatusCommand(swarm);
5
+ registerSwarmListCommand(swarm);
6
+ registerSwarmCreateCommand(swarm);
7
+ return swarm;
8
+ }
@@ -0,0 +1,488 @@
1
+ import { danger } from "../../globals.js";
2
+ import { defaultRuntime } from "../../runtime.js";
3
+ import { colorize, isRich, theme } from "../../terminal/theme.js";
4
+ import { renderTable } from "../../terminal/table.js";
5
+ import { addGatewayClientOptions, callGatewayFromCli } from "../gateway-rpc.js";
6
+ // Status icons
7
+ const STATUS_ICONS = {
8
+ idle: "◌",
9
+ working: "▶",
10
+ error: "✖",
11
+ offline: "⊘",
12
+ pending: "○",
13
+ assigned: "◎",
14
+ in_progress: "◐",
15
+ completed: "●",
16
+ failed: "✖",
17
+ active: "●",
18
+ paused: "⏸",
19
+ };
20
+ // Format member status with icon
21
+ function formatMemberStatus(status, rich) {
22
+ const icon = STATUS_ICONS[status] ?? "?";
23
+ if (!rich)
24
+ return status;
25
+ switch (status) {
26
+ case "idle":
27
+ return `${colorize(rich, theme.success, icon)} ${status}`;
28
+ case "working":
29
+ return `${colorize(rich, theme.warn, icon)} ${status}`;
30
+ case "error":
31
+ return `${colorize(rich, theme.error, icon)} ${status}`;
32
+ case "offline":
33
+ return `${colorize(rich, theme.muted, icon)} ${status}`;
34
+ default:
35
+ return status;
36
+ }
37
+ }
38
+ // Format task status with icon
39
+ function formatTaskStatus(status, rich) {
40
+ const icon = STATUS_ICONS[status] ?? "?";
41
+ if (!rich)
42
+ return status;
43
+ switch (status) {
44
+ case "completed":
45
+ return `${colorize(rich, theme.success, icon)} ${status}`;
46
+ case "in_progress":
47
+ return `${colorize(rich, theme.warn, icon)} ${status}`;
48
+ case "failed":
49
+ return `${colorize(rich, theme.error, icon)} ${status}`;
50
+ case "assigned":
51
+ return `${colorize(rich, theme.accent, icon)} ${status}`;
52
+ default:
53
+ return `${colorize(rich, theme.muted, icon)} ${status}`;
54
+ }
55
+ }
56
+ // Format swarm status
57
+ function formatSwarmStatus(status, rich) {
58
+ const icon = STATUS_ICONS[status] ?? "?";
59
+ if (!rich)
60
+ return status;
61
+ switch (status) {
62
+ case "active":
63
+ return `${colorize(rich, theme.success, icon)} ${status}`;
64
+ case "paused":
65
+ return `${colorize(rich, theme.warn, icon)} ${status}`;
66
+ case "completed":
67
+ return `${colorize(rich, theme.accentBright, icon)} ${status}`;
68
+ case "error":
69
+ return `${colorize(rich, theme.error, icon)} ${status}`;
70
+ default:
71
+ return status;
72
+ }
73
+ }
74
+ // Format relative time
75
+ function formatRelativeTime(ms) {
76
+ const now = Date.now();
77
+ const delta = now - ms;
78
+ if (delta < 60_000)
79
+ return "just now";
80
+ if (delta < 3_600_000)
81
+ return `${Math.round(delta / 60_000)}m ago`;
82
+ if (delta < 86_400_000)
83
+ return `${Math.round(delta / 3_600_000)}h ago`;
84
+ return `${Math.round(delta / 86_400_000)}d ago`;
85
+ }
86
+ // Print swarm header
87
+ function printSwarmHeader(swarm, runtime = defaultRuntime) {
88
+ const rich = isRich();
89
+ runtime.log("");
90
+ if (rich) {
91
+ runtime.log(colorize(rich, theme.heading, "╔═══════════════════════════════════════════════════════════╗"));
92
+ runtime.log(colorize(rich, theme.heading, `║ 🐝 SWARM: ${swarm.name.slice(0, 40).padEnd(40)} ║`));
93
+ runtime.log(colorize(rich, theme.heading, "╚═══════════════════════════════════════════════════════════╝"));
94
+ }
95
+ else {
96
+ runtime.log("═══════════════════════════════════════════════════════════");
97
+ runtime.log(`SWARM: ${swarm.name}`);
98
+ runtime.log("═══════════════════════════════════════════════════════════");
99
+ }
100
+ if (swarm.description) {
101
+ runtime.log(` ${swarm.description}`);
102
+ }
103
+ runtime.log("");
104
+ }
105
+ // Print swarm stats
106
+ function printSwarmStats(swarm, runtime = defaultRuntime) {
107
+ const rich = isRich();
108
+ const totalTasks = swarm.tasks.length;
109
+ const completedTasks = swarm.tasks.filter((t) => t.status === "completed").length;
110
+ const failedTasks = swarm.tasks.filter((t) => t.status === "failed").length;
111
+ const inProgressTasks = swarm.tasks.filter((t) => t.status === "in_progress").length;
112
+ const pendingTasks = swarm.tasks.filter((t) => t.status === "pending" || t.status === "assigned").length;
113
+ const activeMembers = swarm.members.filter((m) => m.status !== "offline").length;
114
+ const workingMembers = swarm.members.filter((m) => m.status === "working").length;
115
+ const completionRate = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
116
+ if (rich) {
117
+ const stats = [
118
+ `${colorize(rich, theme.info, "Status:")} ${formatSwarmStatus(swarm.status, rich)}`,
119
+ `${colorize(rich, theme.info, "Strategy:")} ${swarm.strategy}`,
120
+ `${colorize(rich, theme.info, "Members:")} ${activeMembers}/${swarm.members.length} active`,
121
+ `${colorize(rich, theme.info, "Working:")} ${workingMembers}`,
122
+ ].join(" │ ");
123
+ runtime.log(` ${stats}`);
124
+ const taskStats = [
125
+ `${colorize(rich, theme.success, "Completed:")} ${completedTasks}`,
126
+ `${colorize(rich, theme.warn, "In Progress:")} ${inProgressTasks}`,
127
+ `${colorize(rich, theme.muted, "Pending:")} ${pendingTasks}`,
128
+ `${colorize(rich, theme.error, "Failed:")} ${failedTasks}`,
129
+ `${colorize(rich, theme.accent, "Completion:")} ${completionRate}%`,
130
+ ].join(" │ ");
131
+ runtime.log(` ${taskStats}`);
132
+ }
133
+ else {
134
+ runtime.log(` Status: ${swarm.status} | Strategy: ${swarm.strategy}`);
135
+ runtime.log(` Members: ${activeMembers}/${swarm.members.length} active | Working: ${workingMembers}`);
136
+ runtime.log(` Tasks: ${completedTasks} completed | ${inProgressTasks} in progress | ${pendingTasks} pending | ${failedTasks} failed`);
137
+ runtime.log(` Completion Rate: ${completionRate}%`);
138
+ }
139
+ runtime.log("");
140
+ }
141
+ // Print members table
142
+ function printMembersTable(members, runtime = defaultRuntime) {
143
+ const rich = isRich();
144
+ if (members.length === 0) {
145
+ runtime.log(rich ? colorize(rich, theme.muted, " No swarm members.") : " No swarm members.");
146
+ return;
147
+ }
148
+ const sortedMembers = [...members].sort((a, b) => {
149
+ // Sort by status (working first, then idle, then error/offline)
150
+ const statusOrder = { working: 0, idle: 1, error: 2, offline: 3 };
151
+ return statusOrder[a.status] - statusOrder[b.status];
152
+ });
153
+ const columns = [
154
+ {
155
+ key: "agent",
156
+ header: rich ? colorize(rich, theme.heading, "Agent") : "Agent",
157
+ align: "left",
158
+ minWidth: 15,
159
+ flex: true,
160
+ },
161
+ {
162
+ key: "status",
163
+ header: rich ? colorize(rich, theme.heading, "Status") : "Status",
164
+ align: "left",
165
+ minWidth: 12,
166
+ maxWidth: 14,
167
+ },
168
+ {
169
+ key: "task",
170
+ header: rich ? colorize(rich, theme.heading, "Current Task") : "Current Task",
171
+ align: "left",
172
+ minWidth: 20,
173
+ flex: true,
174
+ },
175
+ {
176
+ key: "capabilities",
177
+ header: rich ? colorize(rich, theme.heading, "Capabilities") : "Capabilities",
178
+ align: "left",
179
+ minWidth: 15,
180
+ maxWidth: 20,
181
+ },
182
+ {
183
+ key: "completed",
184
+ header: rich ? colorize(rich, theme.heading, "Done") : "Done",
185
+ align: "right",
186
+ minWidth: 6,
187
+ maxWidth: 8,
188
+ },
189
+ {
190
+ key: "heartbeat",
191
+ header: rich ? colorize(rich, theme.heading, "Last Seen") : "Last Seen",
192
+ align: "right",
193
+ minWidth: 10,
194
+ maxWidth: 12,
195
+ },
196
+ ];
197
+ const rows = sortedMembers.map((member) => {
198
+ const capabilities = member.capabilities.slice(0, 3).join(", ") + (member.capabilities.length > 3 ? "..." : "");
199
+ return {
200
+ agent: rich ? colorize(rich, theme.info, member.agentId) : member.agentId,
201
+ status: formatMemberStatus(member.status, rich),
202
+ task: member.currentTaskId
203
+ ? rich
204
+ ? colorize(rich, theme.accent, member.currentTaskId.slice(0, 25))
205
+ : member.currentTaskId.slice(0, 25)
206
+ : rich
207
+ ? colorize(rich, theme.muted, "-")
208
+ : "-",
209
+ capabilities: capabilities || (rich ? colorize(rich, theme.muted, "-") : "-"),
210
+ completed: String(member.completedTasks),
211
+ heartbeat: formatRelativeTime(member.lastHeartbeatAt),
212
+ };
213
+ });
214
+ const table = renderTable({
215
+ columns,
216
+ rows,
217
+ border: rich ? "unicode" : "ascii",
218
+ padding: 1,
219
+ });
220
+ runtime.log(rich ? colorize(rich, theme.heading, " Members:") : " Members:");
221
+ runtime.log(table);
222
+ }
223
+ // Print tasks table
224
+ function printTasksTable(tasks, runtime = defaultRuntime) {
225
+ const rich = isRich();
226
+ if (tasks.length === 0) {
227
+ runtime.log(rich ? colorize(rich, theme.muted, " No tasks.") : " No tasks.");
228
+ return;
229
+ }
230
+ // Sort: in_progress first, then assigned, pending, completed, failed
231
+ const statusOrder = {
232
+ in_progress: 0,
233
+ assigned: 1,
234
+ pending: 2,
235
+ completed: 3,
236
+ failed: 4,
237
+ };
238
+ const sortedTasks = [...tasks]
239
+ .sort((a, b) => {
240
+ if (statusOrder[a.status] !== statusOrder[b.status]) {
241
+ return statusOrder[a.status] - statusOrder[b.status];
242
+ }
243
+ return b.priority - a.priority;
244
+ })
245
+ .slice(0, 20); // Show top 20 tasks
246
+ const columns = [
247
+ {
248
+ key: "id",
249
+ header: rich ? colorize(rich, theme.heading, "Task") : "Task",
250
+ align: "left",
251
+ minWidth: 12,
252
+ maxWidth: 16,
253
+ },
254
+ {
255
+ key: "status",
256
+ header: rich ? colorize(rich, theme.heading, "Status") : "Status",
257
+ align: "left",
258
+ minWidth: 12,
259
+ maxWidth: 14,
260
+ },
261
+ {
262
+ key: "priority",
263
+ header: rich ? colorize(rich, theme.heading, "Prio") : "Prio",
264
+ align: "center",
265
+ minWidth: 6,
266
+ maxWidth: 8,
267
+ },
268
+ {
269
+ key: "assigned",
270
+ header: rich ? colorize(rich, theme.heading, "Assigned To") : "Assigned To",
271
+ align: "left",
272
+ minWidth: 12,
273
+ flex: true,
274
+ },
275
+ {
276
+ key: "description",
277
+ header: rich ? colorize(rich, theme.heading, "Description") : "Description",
278
+ align: "left",
279
+ minWidth: 25,
280
+ flex: true,
281
+ },
282
+ ];
283
+ const rows = sortedTasks.map((task) => {
284
+ const prioColor = task.priority >= 8 ? theme.error : task.priority >= 5 ? theme.warn : theme.muted;
285
+ return {
286
+ id: rich ? colorize(rich, theme.accent, task.id.slice(0, 12)) : task.id.slice(0, 12),
287
+ status: formatTaskStatus(task.status, rich),
288
+ priority: rich ? colorize(rich, prioColor, String(task.priority)) : String(task.priority),
289
+ assigned: task.assignedTo
290
+ ? rich
291
+ ? colorize(rich, theme.info, task.assignedTo)
292
+ : task.assignedTo
293
+ : rich
294
+ ? colorize(rich, theme.muted, "-")
295
+ : "-",
296
+ description: task.description.slice(0, 40) + (task.description.length > 40 ? "..." : ""),
297
+ };
298
+ });
299
+ const table = renderTable({
300
+ columns,
301
+ rows,
302
+ border: rich ? "unicode" : "ascii",
303
+ padding: 1,
304
+ });
305
+ runtime.log(rich ? colorize(rich, theme.heading, " Tasks:") : " Tasks:");
306
+ if (tasks.length > 20) {
307
+ runtime.log(rich
308
+ ? colorize(rich, theme.muted, ` (showing top 20 of ${tasks.length} tasks)`)
309
+ : ` (showing top 20 of ${tasks.length} tasks)`);
310
+ }
311
+ runtime.log(table);
312
+ }
313
+ // Print legend
314
+ function printLegend(runtime = defaultRuntime) {
315
+ const rich = isRich();
316
+ runtime.log("");
317
+ if (rich) {
318
+ runtime.log(colorize(rich, theme.muted, " Legend:"));
319
+ runtime.log(` Members: ${colorize(rich, theme.success, STATUS_ICONS.idle)} idle ${colorize(rich, theme.warn, STATUS_ICONS.working)} working ${colorize(rich, theme.error, STATUS_ICONS.error)} error ${colorize(rich, theme.muted, STATUS_ICONS.offline)} offline`);
320
+ runtime.log(` Tasks: ${colorize(rich, theme.muted, STATUS_ICONS.pending)} pending ${colorize(rich, theme.accent, STATUS_ICONS.assigned)} assigned ${colorize(rich, theme.warn, STATUS_ICONS.in_progress)} in progress ${colorize(rich, theme.success, STATUS_ICONS.completed)} completed ${colorize(rich, theme.error, STATUS_ICONS.failed)} failed`);
321
+ }
322
+ else {
323
+ runtime.log(" Legend:");
324
+ runtime.log(" Members: ◌ idle ▶ working ✖ error ⊘ offline");
325
+ runtime.log(" Tasks: ○ pending ◎ assigned ◐ in progress ● completed ✖ failed");
326
+ }
327
+ }
328
+ // Print footer
329
+ function printFooter(runtime = defaultRuntime) {
330
+ const rich = isRich();
331
+ runtime.log("");
332
+ if (rich) {
333
+ runtime.log(colorize(rich, theme.muted, " Commands: poolbot swarm list | poolbot swarm create --help | poolbot swarm task add"));
334
+ }
335
+ else {
336
+ runtime.log(" Commands: poolbot swarm list | poolbot swarm create --help | poolbot swarm task add");
337
+ }
338
+ runtime.log("");
339
+ }
340
+ export function registerSwarmStatusCommand(swarm) {
341
+ addGatewayClientOptions(swarm
342
+ .command("status")
343
+ .description("Show swarm status dashboard")
344
+ .option("--id <swarmId>", "Swarm ID", "default")
345
+ .option("--json", "Output JSON", false)
346
+ .action(async (opts) => {
347
+ try {
348
+ const res = await callGatewayFromCli("swarm.status", opts, { swarmId: opts.id });
349
+ const swarmData = res.swarm;
350
+ if (!swarmData) {
351
+ defaultRuntime.error(danger("Swarm not found"));
352
+ defaultRuntime.exit(1);
353
+ }
354
+ if (opts.json) {
355
+ defaultRuntime.log(JSON.stringify(swarmData, null, 2));
356
+ return;
357
+ }
358
+ printSwarmHeader(swarmData);
359
+ printSwarmStats(swarmData);
360
+ printMembersTable(swarmData.members);
361
+ defaultRuntime.log("");
362
+ printTasksTable(swarmData.tasks);
363
+ printLegend();
364
+ printFooter();
365
+ }
366
+ catch (err) {
367
+ defaultRuntime.error(danger(String(err)));
368
+ defaultRuntime.exit(1);
369
+ }
370
+ }));
371
+ }
372
+ export function registerSwarmListCommand(swarm) {
373
+ addGatewayClientOptions(swarm
374
+ .command("list")
375
+ .alias("ls")
376
+ .description("List all swarms")
377
+ .option("--json", "Output JSON", false)
378
+ .action(async (opts) => {
379
+ try {
380
+ const res = await callGatewayFromCli("swarm.list", opts, {});
381
+ const swarms = res.swarms;
382
+ if (opts.json) {
383
+ defaultRuntime.log(JSON.stringify(swarms, null, 2));
384
+ return;
385
+ }
386
+ const rich = isRich();
387
+ const columns = [
388
+ {
389
+ key: "id",
390
+ header: rich ? colorize(rich, theme.heading, "ID") : "ID",
391
+ align: "left",
392
+ minWidth: 12,
393
+ maxWidth: 14,
394
+ },
395
+ {
396
+ key: "name",
397
+ header: rich ? colorize(rich, theme.heading, "Name") : "Name",
398
+ align: "left",
399
+ minWidth: 20,
400
+ flex: true,
401
+ },
402
+ {
403
+ key: "status",
404
+ header: rich ? colorize(rich, theme.heading, "Status") : "Status",
405
+ align: "left",
406
+ minWidth: 10,
407
+ maxWidth: 12,
408
+ },
409
+ {
410
+ key: "members",
411
+ header: rich ? colorize(rich, theme.heading, "Members") : "Members",
412
+ align: "center",
413
+ minWidth: 8,
414
+ maxWidth: 10,
415
+ },
416
+ {
417
+ key: "tasks",
418
+ header: rich ? colorize(rich, theme.heading, "Tasks") : "Tasks",
419
+ align: "center",
420
+ minWidth: 8,
421
+ maxWidth: 10,
422
+ },
423
+ ];
424
+ const rows = swarms.map((s) => ({
425
+ id: rich ? colorize(rich, theme.accent, s.id) : s.id,
426
+ name: rich ? colorize(rich, theme.info, s.name) : s.name,
427
+ status: formatSwarmStatus(s.status, rich),
428
+ members: String(s.members),
429
+ tasks: String(s.tasks),
430
+ }));
431
+ const table = renderTable({
432
+ columns,
433
+ rows,
434
+ border: rich ? "unicode" : "ascii",
435
+ padding: 1,
436
+ });
437
+ defaultRuntime.log("");
438
+ defaultRuntime.log(rich ? colorize(rich, theme.heading, "Active Swarms:") : "Active Swarms:");
439
+ defaultRuntime.log(table);
440
+ defaultRuntime.log("");
441
+ }
442
+ catch (err) {
443
+ defaultRuntime.error(danger(String(err)));
444
+ defaultRuntime.exit(1);
445
+ }
446
+ }));
447
+ }
448
+ export function registerSwarmCreateCommand(swarm) {
449
+ addGatewayClientOptions(swarm
450
+ .command("create")
451
+ .description("Create a new agent swarm")
452
+ .requiredOption("--name <name>", "Swarm name")
453
+ .option("--description <text>", "Swarm description")
454
+ .option("--strategy <strategy>", "Task distribution strategy (round_robin|least_busy|capability_match|priority_queue)", "capability_match")
455
+ .option("--orchestrator <agentId>", "Orchestrator agent ID", "main")
456
+ .option("--json", "Output JSON", false)
457
+ .action(async (opts) => {
458
+ try {
459
+ const result = (await callGatewayFromCli("swarm.create", opts, {
460
+ name: opts.name,
461
+ description: opts.description,
462
+ strategy: opts.strategy,
463
+ orchestrator: opts.orchestrator,
464
+ }));
465
+ if (opts.json) {
466
+ defaultRuntime.log(JSON.stringify(result, null, 2));
467
+ return;
468
+ }
469
+ const rich = isRich();
470
+ defaultRuntime.log("");
471
+ defaultRuntime.log(rich
472
+ ? colorize(rich, theme.success, `✓ Swarm "${result.name}" created successfully`)
473
+ : `✓ Swarm "${result.name}" created successfully`);
474
+ defaultRuntime.log(` ID: ${result.id}`);
475
+ defaultRuntime.log(` Strategy: ${result.strategy}`);
476
+ defaultRuntime.log(` Orchestrator: ${result.orchestratorAgentId}`);
477
+ defaultRuntime.log("");
478
+ defaultRuntime.log(rich
479
+ ? colorize(rich, theme.muted, " Use 'poolbot swarm join' to add agents to the swarm.")
480
+ : " Use 'poolbot swarm join' to add agents to the swarm.");
481
+ defaultRuntime.log("");
482
+ }
483
+ catch (err) {
484
+ defaultRuntime.error(danger(String(err)));
485
+ defaultRuntime.exit(1);
486
+ }
487
+ }));
488
+ }
@@ -0,0 +1,10 @@
1
+ import { registerTelemetryStatusCommand } from "./register.telemetry-status.js";
2
+ import { registerTelemetryMetricsCommand } from "./register.telemetry-metrics.js";
3
+ export function registerTelemetryCli(program) {
4
+ const telemetry = program
5
+ .command("telemetry")
6
+ .alias("tel")
7
+ .description("OpenTelemetry observability and metrics");
8
+ registerTelemetryStatusCommand(telemetry);
9
+ registerTelemetryMetricsCommand(telemetry);
10
+ }