@poolzin/pool-bot 2026.3.9 → 2026.3.11

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 (128) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +147 -69
  3. package/dist/.buildstamp +1 -1
  4. package/dist/agents/error-classifier.js +26 -77
  5. package/dist/agents/skills/security.js +1 -7
  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/program/command-registry.js +13 -0
  11. package/dist/cli/program/register.maintenance.js +21 -0
  12. package/dist/cli/program/register.subclis.js +9 -0
  13. package/dist/cli/swarm-cli/register.js +8 -0
  14. package/dist/cli/swarm-cli/register.swarm-status.js +488 -0
  15. package/dist/cli/telemetry-cli/register.js +10 -0
  16. package/dist/cli/telemetry-cli/register.telemetry-alerts.js +176 -0
  17. package/dist/cli/telemetry-cli/register.telemetry-metrics.js +323 -0
  18. package/dist/cli/telemetry-cli/register.telemetry-status.js +179 -0
  19. package/dist/commands/doctor-checks.js +498 -0
  20. package/dist/context-engine/index.js +1 -1
  21. package/dist/context-engine/legacy.js +1 -3
  22. package/dist/context-engine/summarizing.js +5 -8
  23. package/dist/cron/service/timer.js +18 -0
  24. package/dist/gateway/protocol/index.js +5 -2
  25. package/dist/gateway/protocol/schema/error-codes.js +1 -0
  26. package/dist/gateway/protocol/schema/swarm.js +80 -0
  27. package/dist/gateway/protocol/schema.js +1 -0
  28. package/dist/gateway/server-close.js +4 -0
  29. package/dist/gateway/server-constants.js +1 -0
  30. package/dist/gateway/server-cron.js +29 -0
  31. package/dist/gateway/server-maintenance.js +35 -2
  32. package/dist/gateway/server-methods/swarm.js +58 -0
  33. package/dist/gateway/server-methods/telemetry.js +71 -0
  34. package/dist/gateway/server-methods-list.js +8 -0
  35. package/dist/gateway/server-methods.js +9 -2
  36. package/dist/gateway/server.impl.js +33 -16
  37. package/dist/infra/abort-pattern.js +4 -4
  38. package/dist/infra/retry.js +3 -1
  39. package/dist/skills/commands.js +7 -25
  40. package/dist/skills/index.js +14 -17
  41. package/dist/skills/parser.js +12 -27
  42. package/dist/skills/registry.js +3 -6
  43. package/dist/skills/security.js +2 -8
  44. package/dist/swarm/service.js +247 -0
  45. package/dist/telemetry/alert-engine.js +258 -0
  46. package/dist/telemetry/cron-instrumentation.js +49 -0
  47. package/dist/telemetry/gateway-instrumentation.js +80 -0
  48. package/dist/telemetry/instrumentation.js +66 -0
  49. package/dist/telemetry/service.js +345 -0
  50. package/dist/tui/components/assistant-message.js +6 -2
  51. package/dist/tui/components/hyperlink-markdown.js +32 -0
  52. package/dist/tui/components/searchable-select-list.js +12 -1
  53. package/dist/tui/components/user-message.js +6 -2
  54. package/dist/tui/index.js +22 -6
  55. package/dist/tui/theme/theme-detection.js +226 -0
  56. package/dist/tui/tui-command-handlers.js +20 -0
  57. package/dist/tui/tui-formatters.js +4 -3
  58. package/dist/tui/utils/ctrl-c-handler.js +67 -0
  59. package/dist/tui/utils/osc8-hyperlinks.js +208 -0
  60. package/dist/tui/utils/safe-stop.js +180 -0
  61. package/dist/tui/utils/session-key-utils.js +81 -0
  62. package/dist/tui/utils/text-sanitization.js +284 -0
  63. package/dist/utils/lru-cache.js +116 -0
  64. package/dist/utils/performance.js +199 -0
  65. package/dist/utils/retry.js +240 -0
  66. package/docs/MELHORIAS_IMPLEMENTADAS.md +228 -0
  67. package/docs/MELHORIAS_PROFISSIONAIS.md +282 -0
  68. package/docs/PLANO_ACAO_TUI.md +357 -0
  69. package/docs/PROGRESSO_TUI.md +66 -0
  70. package/docs/RELATORIO_FINAL.md +217 -0
  71. package/docs/diagnostico-shell-completion.md +265 -0
  72. package/docs/features/advanced-memory.md +585 -0
  73. package/docs/features/discord-components-v2.md +277 -0
  74. package/docs/features/swarm.md +100 -0
  75. package/docs/features/telemetry.md +284 -0
  76. package/docs/integrations/INTEGRATION_PLAN.md +665 -345
  77. package/docs/models/provider-infrastructure.md +400 -0
  78. package/docs/security/exec-approvals.md +294 -0
  79. package/extensions/bluebubbles/package.json +1 -1
  80. package/extensions/copilot-proxy/package.json +1 -1
  81. package/extensions/diagnostics-otel/package.json +1 -1
  82. package/extensions/discord/package.json +1 -1
  83. package/extensions/feishu/package.json +1 -1
  84. package/extensions/google-antigravity-auth/package.json +1 -1
  85. package/extensions/google-gemini-cli-auth/package.json +1 -1
  86. package/extensions/googlechat/package.json +1 -1
  87. package/extensions/hexstrike-bridge/README.md +119 -0
  88. package/extensions/hexstrike-bridge/index.test.ts +247 -0
  89. package/extensions/hexstrike-bridge/index.ts +487 -0
  90. package/extensions/hexstrike-bridge/package.json +17 -0
  91. package/extensions/imessage/package.json +1 -1
  92. package/extensions/irc/package.json +1 -1
  93. package/extensions/line/package.json +1 -1
  94. package/extensions/llm-task/package.json +1 -1
  95. package/extensions/lobster/package.json +1 -1
  96. package/extensions/matrix/CHANGELOG.md +10 -0
  97. package/extensions/matrix/package.json +1 -1
  98. package/extensions/mattermost/package.json +1 -1
  99. package/extensions/mavalie/README.md +97 -0
  100. package/extensions/mavalie/package.json +15 -0
  101. package/extensions/mavalie/src/index.ts +62 -0
  102. package/extensions/mcp-server/index.ts +14 -0
  103. package/extensions/mcp-server/package.json +11 -0
  104. package/extensions/mcp-server/src/service.ts +540 -0
  105. package/extensions/memory-core/package.json +1 -1
  106. package/extensions/memory-lancedb/package.json +1 -1
  107. package/extensions/minimax-portal-auth/package.json +1 -1
  108. package/extensions/msteams/CHANGELOG.md +10 -0
  109. package/extensions/msteams/package.json +1 -1
  110. package/extensions/nextcloud-talk/package.json +1 -1
  111. package/extensions/nostr/CHANGELOG.md +10 -0
  112. package/extensions/nostr/package.json +1 -1
  113. package/extensions/open-prose/package.json +1 -1
  114. package/extensions/openai-codex-auth/package.json +1 -1
  115. package/extensions/signal/package.json +1 -1
  116. package/extensions/slack/package.json +1 -1
  117. package/extensions/telegram/package.json +1 -1
  118. package/extensions/tlon/package.json +1 -1
  119. package/extensions/twitch/CHANGELOG.md +10 -0
  120. package/extensions/twitch/package.json +1 -1
  121. package/extensions/voice-call/CHANGELOG.md +10 -0
  122. package/extensions/voice-call/package.json +1 -1
  123. package/extensions/whatsapp/package.json +1 -1
  124. package/extensions/zalo/CHANGELOG.md +10 -0
  125. package/extensions/zalo/package.json +1 -1
  126. package/extensions/zalouser/CHANGELOG.md +10 -0
  127. package/extensions/zalouser/package.json +1 -1
  128. package/package.json +8 -1
@@ -27,27 +27,27 @@
27
27
  // ============================================================================
28
28
  export {
29
29
  // Errors
30
- SkillError, } from './types.js';
30
+ SkillError, } from "./types.js";
31
31
  // ============================================================================
32
32
  // Parser
33
33
  // ============================================================================
34
- export { parseSkill, parseSkillFile, parseSkills, isSkillFile, extractSkillId, parseYaml, parseSections, validateMetadata, extractContent, } from './parser.js';
34
+ export { parseSkill, parseSkillFile, parseSkills, isSkillFile, extractSkillId, parseYaml, parseSections, validateMetadata, extractContent, } from "./parser.js";
35
35
  // ============================================================================
36
36
  // Registry
37
37
  // ============================================================================
38
- export { SkillsRegistry, getRegistry, resetRegistry, } from './registry.js';
38
+ export { SkillsRegistry, getRegistry, resetRegistry } from "./registry.js";
39
39
  // ============================================================================
40
40
  // Loader
41
41
  // ============================================================================
42
- export { SkillLoader, getLoader, resetLoader, } from './loader.js';
42
+ export { SkillLoader, getLoader, resetLoader } from "./loader.js";
43
43
  // ============================================================================
44
44
  // Security
45
45
  // ============================================================================
46
- export { scanSkill, quickSecurityCheck, getSecuritySummary, formatFindings, PATTERNS, } from './security.js';
46
+ export { scanSkill, quickSecurityCheck, getSecuritySummary, formatFindings, PATTERNS, } from "./security.js";
47
47
  // ============================================================================
48
48
  // Commands
49
49
  // ============================================================================
50
- export { registerSkillsCommands, listCommand, viewCommand, searchCommand, enableCommand, disableCommand, scanCommand, statsCommand, } from './commands.js';
50
+ export { registerSkillsCommands, listCommand, viewCommand, searchCommand, enableCommand, disableCommand, scanCommand, statsCommand, } from "./commands.js";
51
51
  // ============================================================================
52
52
  // Context Integration (Future Enhancement)
53
53
  // ============================================================================
@@ -59,20 +59,17 @@ export { registerSkillsCommands, listCommand, viewCommand, searchCommand, enable
59
59
  /**
60
60
  * Current skills system version
61
61
  */
62
- export const SKILLS_VERSION = '1.0.0';
62
+ export const SKILLS_VERSION = "1.0.0";
63
63
  /**
64
64
  * Default skill directories
65
65
  */
66
- export const DEFAULT_SKILL_PATHS = [
67
- './skills',
68
- '~/.poolbot/skills',
69
- ];
66
+ export const DEFAULT_SKILL_PATHS = ["./skills", "~/.poolbot/skills"];
70
67
  // ============================================================================
71
68
  // Convenience Functions
72
69
  // ============================================================================
73
- import { getRegistry } from './registry.js';
74
- import { getLoader } from './loader.js';
75
- import { scanSkill } from './security.js';
70
+ import { getRegistry } from "./registry.js";
71
+ import { getLoader } from "./loader.js";
72
+ import { scanSkill } from "./security.js";
76
73
  /**
77
74
  * Quick skill lookup by ID
78
75
  */
@@ -115,7 +112,7 @@ export async function getSkillForContext(skillId, config = {}) {
115
112
  const fullConfig = {
116
113
  skillIds: [skillId],
117
114
  maxTokens: 4000,
118
- disclosureLevel: 'summary',
115
+ disclosureLevel: "summary",
119
116
  includeLinkedFiles: false,
120
117
  ...config,
121
118
  };
@@ -160,8 +157,8 @@ export async function initSkills(config) {
160
157
  * Reset the skills system (useful for testing)
161
158
  */
162
159
  export function resetSkills() {
163
- const { resetRegistry } = require('./registry.js');
164
- const { resetLoader } = require('./loader.js');
160
+ const { resetRegistry } = require("./registry.js");
161
+ const { resetLoader } = require("./loader.js");
165
162
  resetRegistry();
166
163
  resetLoader();
167
164
  }
@@ -52,7 +52,8 @@ function parseYaml(yaml) {
52
52
  continue;
53
53
  }
54
54
  // Check for multiline value start (pipe | or greater-than >)
55
- if (currentKey && (trimmed === "|" || trimmed === ">" || trimmed.startsWith("|-") || trimmed.startsWith(">-"))) {
55
+ if (currentKey &&
56
+ (trimmed === "|" || trimmed === ">" || trimmed.startsWith("|-") || trimmed.startsWith(">-"))) {
56
57
  multilineValue = [];
57
58
  continue;
58
59
  }
@@ -60,7 +61,8 @@ function parseYaml(yaml) {
60
61
  if (currentKey && multilineValue.length > 0) {
61
62
  // Check if next line is still part of multiline (indented or empty)
62
63
  const nextLine = lines[i + 1];
63
- if (nextLine !== undefined && (nextLine.startsWith(" ") || nextLine.startsWith("\t") || nextLine.trim() === "")) {
64
+ if (nextLine !== undefined &&
65
+ (nextLine.startsWith(" ") || nextLine.startsWith("\t") || nextLine.trim() === "")) {
64
66
  multilineValue.push(line);
65
67
  continue;
66
68
  }
@@ -271,12 +273,8 @@ function validateMetadata(frontmatter, options = {}) {
271
273
  createdAt,
272
274
  updatedAt,
273
275
  license: frontmatter.license ? String(frontmatter.license) : undefined,
274
- repository: frontmatter.repository
275
- ? String(frontmatter.repository)
276
- : undefined,
277
- documentation: frontmatter.documentation
278
- ? String(frontmatter.documentation)
279
- : undefined,
276
+ repository: frontmatter.repository ? String(frontmatter.repository) : undefined,
277
+ documentation: frontmatter.documentation ? String(frontmatter.documentation) : undefined,
280
278
  enabledByDefault: frontmatter.enabledByDefault === true,
281
279
  };
282
280
  }
@@ -288,25 +286,12 @@ function validateMetadata(frontmatter, options = {}) {
288
286
  */
289
287
  function extractContent(sections) {
290
288
  // Map section aliases
291
- const quickstart = sections.get("quick start") ??
292
- sections.get("quickstart") ??
293
- sections.get("getting started");
294
- const usage = sections.get("usage") ??
295
- sections.get("how to use") ??
296
- sections.get("using this skill") ??
297
- "";
298
- const configuration = sections.get("configuration") ??
299
- sections.get("config") ??
300
- sections.get("setup");
301
- const environment = sections.get("environment") ??
302
- sections.get("env") ??
303
- sections.get("environment variables");
304
- const examples = sections.get("examples") ??
305
- sections.get("example") ??
306
- sections.get("example usage");
307
- const api = sections.get("api") ??
308
- sections.get("api reference") ??
309
- sections.get("reference");
289
+ const quickstart = sections.get("quick start") ?? sections.get("quickstart") ?? sections.get("getting started");
290
+ const usage = sections.get("usage") ?? sections.get("how to use") ?? sections.get("using this skill") ?? "";
291
+ const configuration = sections.get("configuration") ?? sections.get("config") ?? sections.get("setup");
292
+ const environment = sections.get("environment") ?? sections.get("env") ?? sections.get("environment variables");
293
+ const examples = sections.get("examples") ?? sections.get("example") ?? sections.get("example usage");
294
+ const api = sections.get("api") ?? sections.get("api reference") ?? sections.get("reference");
310
295
  const troubleshooting = sections.get("troubleshooting") ??
311
296
  sections.get("troubleshoot") ??
312
297
  sections.get("common issues");
@@ -86,8 +86,7 @@ export class SkillsRegistry extends EventEmitter {
86
86
  skill.securityReport = await scanSkill(skill);
87
87
  skill.verification = skill.securityReport.result;
88
88
  // Auto-disable if strict security and failed
89
- if (this.config.strictSecurity &&
90
- skill.verification === "failed") {
89
+ if (this.config.strictSecurity && skill.verification === "failed") {
91
90
  skill.enabled = false;
92
91
  skill.status = "disabled";
93
92
  }
@@ -303,11 +302,9 @@ export class SkillsRegistry extends EventEmitter {
303
302
  const byVerification = {};
304
303
  for (const skill of skills) {
305
304
  // Count by category
306
- byCategory[skill.metadata.category] =
307
- (byCategory[skill.metadata.category] || 0) + 1;
305
+ byCategory[skill.metadata.category] = (byCategory[skill.metadata.category] || 0) + 1;
308
306
  // Count by verification
309
- byVerification[skill.verification] =
310
- (byVerification[skill.verification] || 0) + 1;
307
+ byVerification[skill.verification] = (byVerification[skill.verification] || 0) + 1;
311
308
  }
312
309
  return {
313
310
  total: skills.length,
@@ -147,7 +147,7 @@ export async function scanSkill(skill) {
147
147
  });
148
148
  }
149
149
  // Check against patterns
150
- for (const { type, severity, pattern, description, remediation, } of PATTERNS) {
150
+ for (const { type, severity, pattern, description, remediation } of PATTERNS) {
151
151
  if (pattern.test(line)) {
152
152
  findings.push({
153
153
  type,
@@ -288,13 +288,7 @@ export function formatFindings(findings) {
288
288
  for (const finding of findings) {
289
289
  bySeverity[finding.severity].push(finding);
290
290
  }
291
- for (const severity of [
292
- "critical",
293
- "high",
294
- "medium",
295
- "low",
296
- "info",
297
- ]) {
291
+ for (const severity of ["critical", "high", "medium", "low", "info"]) {
298
292
  const group = bySeverity[severity];
299
293
  if (group.length === 0)
300
294
  continue;
@@ -0,0 +1,247 @@
1
+ // Agent Swarm Service - Multi-agent coordination and task distribution
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { createSubsystemLogger } from "../logging/subsystem.js";
5
+ const log = createSubsystemLogger("swarm");
6
+ const POOLBOT_DIR = join(process.env.HOME ?? "/tmp", ".poolbot");
7
+ const SWARM_STATE_FILE = join(POOLBOT_DIR, "swarm-state.json");
8
+ export class SwarmService {
9
+ swarms;
10
+ persistEnabled;
11
+ constructor(persistEnabled = true) {
12
+ this.swarms = new Map();
13
+ this.persistEnabled = persistEnabled;
14
+ this.loadFromDisk();
15
+ }
16
+ ensureDir() {
17
+ if (!existsSync(POOLBOT_DIR)) {
18
+ mkdirSync(POOLBOT_DIR, { recursive: true });
19
+ }
20
+ }
21
+ loadFromDisk() {
22
+ if (!this.persistEnabled)
23
+ return;
24
+ try {
25
+ this.ensureDir();
26
+ if (existsSync(SWARM_STATE_FILE)) {
27
+ const data = readFileSync(SWARM_STATE_FILE, "utf-8");
28
+ const parsed = JSON.parse(data);
29
+ for (const [id, swarm] of Object.entries(parsed)) {
30
+ this.swarms.set(id, swarm);
31
+ }
32
+ log.info(`Loaded ${this.swarms.size} swarms from disk`);
33
+ }
34
+ }
35
+ catch (error) {
36
+ log.error(`Failed to load swarm state: ${String(error)}`);
37
+ }
38
+ }
39
+ saveToDisk() {
40
+ if (!this.persistEnabled)
41
+ return;
42
+ try {
43
+ this.ensureDir();
44
+ const data = {};
45
+ for (const [id, swarm] of this.swarms) {
46
+ data[id] = swarm;
47
+ }
48
+ writeFileSync(SWARM_STATE_FILE, JSON.stringify(data, null, 2));
49
+ }
50
+ catch (error) {
51
+ log.error(`Failed to save swarm state: ${String(error)}`);
52
+ }
53
+ }
54
+ async list() {
55
+ const swarmList = Array.from(this.swarms.values()).map((swarm) => ({
56
+ id: swarm.id,
57
+ name: swarm.name,
58
+ status: swarm.status,
59
+ members: swarm.members.length,
60
+ tasks: swarm.tasks.length,
61
+ }));
62
+ return { swarms: swarmList };
63
+ }
64
+ async getStatus(swarmId) {
65
+ const swarm = this.swarms.get(swarmId);
66
+ return { swarm: swarm ?? null };
67
+ }
68
+ async create(params) {
69
+ const id = `swarm-${Date.now()}`;
70
+ const now = Date.now();
71
+ const swarm = {
72
+ id,
73
+ name: params.name,
74
+ description: params.description,
75
+ createdAt: now,
76
+ orchestratorAgentId: params.orchestratorAgentId,
77
+ members: [],
78
+ tasks: [],
79
+ strategy: params.strategy,
80
+ status: "active",
81
+ };
82
+ this.swarms.set(id, swarm);
83
+ this.saveToDisk();
84
+ log.info(`Created swarm: ${id} (${params.name})`);
85
+ return {
86
+ id,
87
+ name: params.name,
88
+ description: params.description,
89
+ strategy: params.strategy,
90
+ orchestratorAgentId: params.orchestratorAgentId,
91
+ createdAt: now,
92
+ status: "active",
93
+ };
94
+ }
95
+ async delete(swarmId) {
96
+ const deleted = this.swarms.delete(swarmId);
97
+ if (deleted) {
98
+ this.saveToDisk();
99
+ log.info(`Deleted swarm: ${swarmId}`);
100
+ }
101
+ return deleted;
102
+ }
103
+ async addMember(swarmId, member) {
104
+ const swarm = this.swarms.get(swarmId);
105
+ if (!swarm)
106
+ return false;
107
+ // Check if member already exists
108
+ const existingIndex = swarm.members.findIndex((m) => m.agentId === member.agentId);
109
+ if (existingIndex >= 0) {
110
+ swarm.members[existingIndex] = member;
111
+ }
112
+ else {
113
+ swarm.members.push(member);
114
+ }
115
+ this.saveToDisk();
116
+ return true;
117
+ }
118
+ async removeMember(swarmId, agentId) {
119
+ const swarm = this.swarms.get(swarmId);
120
+ if (!swarm)
121
+ return false;
122
+ const initialLength = swarm.members.length;
123
+ swarm.members = swarm.members.filter((m) => m.agentId !== agentId);
124
+ const removed = swarm.members.length < initialLength;
125
+ if (removed) {
126
+ this.saveToDisk();
127
+ }
128
+ return removed;
129
+ }
130
+ async addTask(swarmId, task) {
131
+ const swarm = this.swarms.get(swarmId);
132
+ if (!swarm)
133
+ return false;
134
+ swarm.tasks.push(task);
135
+ this.saveToDisk();
136
+ return true;
137
+ }
138
+ async removeTask(swarmId, taskId) {
139
+ const swarm = this.swarms.get(swarmId);
140
+ if (!swarm)
141
+ return false;
142
+ const initialLength = swarm.tasks.length;
143
+ swarm.tasks = swarm.tasks.filter((t) => t.id !== taskId);
144
+ const removed = swarm.tasks.length < initialLength;
145
+ if (removed) {
146
+ this.saveToDisk();
147
+ }
148
+ return removed;
149
+ }
150
+ async updateTaskStatus(swarmId, taskId, status, assignedTo) {
151
+ const swarm = this.swarms.get(swarmId);
152
+ if (!swarm)
153
+ return false;
154
+ const task = swarm.tasks.find((t) => t.id === taskId);
155
+ if (!task)
156
+ return false;
157
+ task.status = status;
158
+ if (assignedTo)
159
+ task.assignedTo = assignedTo;
160
+ if (status === "in_progress" && !task.startedAt)
161
+ task.startedAt = Date.now();
162
+ if (status === "completed" && !task.completedAt)
163
+ task.completedAt = Date.now();
164
+ this.saveToDisk();
165
+ return true;
166
+ }
167
+ async updateMemberStatus(swarmId, agentId, status, currentTaskId) {
168
+ const swarm = this.swarms.get(swarmId);
169
+ if (!swarm)
170
+ return false;
171
+ const member = swarm.members.find((m) => m.agentId === agentId);
172
+ if (!member)
173
+ return false;
174
+ member.status = status;
175
+ member.lastHeartbeatAt = Date.now();
176
+ if (currentTaskId !== undefined)
177
+ member.currentTaskId = currentTaskId;
178
+ if (status === "working" && currentTaskId) {
179
+ member.completedTasks++;
180
+ }
181
+ this.saveToDisk();
182
+ return true;
183
+ }
184
+ async updateSwarmStatus(swarmId, status) {
185
+ const swarm = this.swarms.get(swarmId);
186
+ if (!swarm)
187
+ return false;
188
+ swarm.status = status;
189
+ this.saveToDisk();
190
+ return true;
191
+ }
192
+ // Get or create default swarm for demo purposes
193
+ async getOrCreateDefaultSwarm() {
194
+ const defaultId = "swarm-default";
195
+ let swarm = this.swarms.get(defaultId);
196
+ if (!swarm) {
197
+ const now = Date.now();
198
+ swarm = {
199
+ id: defaultId,
200
+ name: "Default Swarm",
201
+ description: "Default agent swarm for task coordination",
202
+ createdAt: now,
203
+ orchestratorAgentId: "main",
204
+ members: [
205
+ {
206
+ agentId: "agent-1",
207
+ sessionKey: "swarm/agent-1",
208
+ status: "idle",
209
+ capabilities: ["typescript", "review", "coding"],
210
+ joinedAt: now,
211
+ lastHeartbeatAt: now,
212
+ completedTasks: 0,
213
+ failedTasks: 0,
214
+ },
215
+ ],
216
+ tasks: [],
217
+ strategy: "capability_match",
218
+ status: "active",
219
+ };
220
+ this.swarms.set(defaultId, swarm);
221
+ this.saveToDisk();
222
+ }
223
+ return swarm;
224
+ }
225
+ // Get swarm statistics
226
+ async getStats(swarmId) {
227
+ const swarm = this.swarms.get(swarmId);
228
+ if (!swarm)
229
+ return null;
230
+ const activeMembers = swarm.members.filter((m) => m.status === "idle" || m.status === "working").length;
231
+ const completedTasks = swarm.tasks.filter((t) => t.status === "completed").length;
232
+ const failedTasks = swarm.tasks.filter((t) => t.status === "failed").length;
233
+ const pendingTasks = swarm.tasks.filter((t) => t.status === "pending").length;
234
+ const inProgressTasks = swarm.tasks.filter((t) => t.status === "in_progress").length;
235
+ return {
236
+ totalMembers: swarm.members.length,
237
+ activeMembers,
238
+ totalTasks: swarm.tasks.length,
239
+ completedTasks,
240
+ failedTasks,
241
+ pendingTasks,
242
+ inProgressTasks,
243
+ };
244
+ }
245
+ }
246
+ // Singleton instance
247
+ export const swarmService = new SwarmService();