@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
@@ -0,0 +1,498 @@
1
+ /**
2
+ * Helper to safely get config
3
+ */
4
+ async function safeLoadConfig() {
5
+ try {
6
+ const { loadConfig } = await import("../config/config.js");
7
+ return (await loadConfig());
8
+ }
9
+ catch {
10
+ return null;
11
+ }
12
+ }
13
+ /**
14
+ * Registry of all doctor checks
15
+ */
16
+ export const doctorCheckRegistry = {
17
+ config: async () => {
18
+ const start = Date.now();
19
+ try {
20
+ const { readConfigFileSnapshot } = await import("../config/config.js");
21
+ const snapshot = await readConfigFileSnapshot();
22
+ if (!snapshot.exists) {
23
+ return {
24
+ name: "config",
25
+ status: "error",
26
+ message: "Configuration file not found",
27
+ durationMs: Date.now() - start,
28
+ suggestions: ["Run `poolbot setup` to create initial configuration"],
29
+ };
30
+ }
31
+ if (!snapshot.valid) {
32
+ const issues = snapshot.issues?.map((i) => i.message).join("; ") ?? "Unknown issues";
33
+ return {
34
+ name: "config",
35
+ status: "error",
36
+ message: `Configuration invalid: ${issues}`,
37
+ durationMs: Date.now() - start,
38
+ suggestions: ["Run `poolbot doctor --fix` to auto-repair configuration"],
39
+ details: { issues: snapshot.issues },
40
+ };
41
+ }
42
+ return {
43
+ name: "config",
44
+ status: "ok",
45
+ message: "Configuration is valid",
46
+ durationMs: Date.now() - start,
47
+ details: { path: snapshot.path },
48
+ };
49
+ }
50
+ catch (err) {
51
+ return {
52
+ name: "config",
53
+ status: "error",
54
+ message: `Failed to check config: ${String(err)}`,
55
+ durationMs: Date.now() - start,
56
+ };
57
+ }
58
+ },
59
+ auth: async () => {
60
+ const start = Date.now();
61
+ try {
62
+ const cfg = await safeLoadConfig();
63
+ if (!cfg) {
64
+ return {
65
+ name: "auth",
66
+ status: "skipped",
67
+ message: "Could not load configuration",
68
+ durationMs: Date.now() - start,
69
+ };
70
+ }
71
+ // Check auth profiles
72
+ const authProfiles = cfg.authProfiles;
73
+ if (!authProfiles || authProfiles.length === 0) {
74
+ return {
75
+ name: "auth",
76
+ status: "warning",
77
+ message: "No authentication profiles configured",
78
+ durationMs: Date.now() - start,
79
+ suggestions: ["Run `poolbot configure` to set up authentication"],
80
+ };
81
+ }
82
+ const validProfiles = authProfiles.filter((p) => p?.credential);
83
+ if (validProfiles.length === 0) {
84
+ return {
85
+ name: "auth",
86
+ status: "error",
87
+ message: "Auth profiles exist but none have valid credentials",
88
+ durationMs: Date.now() - start,
89
+ suggestions: ["Run `poolbot configure` to re-authenticate"],
90
+ };
91
+ }
92
+ return {
93
+ name: "auth",
94
+ status: "ok",
95
+ message: `${validProfiles.length} authentication profile(s) configured`,
96
+ durationMs: Date.now() - start,
97
+ details: { profileCount: validProfiles.length },
98
+ };
99
+ }
100
+ catch (err) {
101
+ return {
102
+ name: "auth",
103
+ status: "error",
104
+ message: `Failed to check auth: ${String(err)}`,
105
+ durationMs: Date.now() - start,
106
+ };
107
+ }
108
+ },
109
+ completion: async () => {
110
+ const start = Date.now();
111
+ try {
112
+ const { checkShellCompletionStatus } = await import("./doctor-completion.js");
113
+ const status = await checkShellCompletionStatus();
114
+ if (!status.cacheExists) {
115
+ return {
116
+ name: "completion",
117
+ status: "warning",
118
+ message: "Completion cache not found",
119
+ durationMs: Date.now() - start,
120
+ suggestions: [
121
+ "Run `poolbot completion --write-state` to generate cache",
122
+ "Run `poolbot completion --install` to install to shell profile",
123
+ ],
124
+ details: { shell: status.shell },
125
+ };
126
+ }
127
+ if (!status.profileInstalled) {
128
+ return {
129
+ name: "completion",
130
+ status: "warning",
131
+ message: `Completion cache exists but not installed in ${status.shell} profile`,
132
+ durationMs: Date.now() - start,
133
+ suggestions: ["Run `poolbot completion --install` to enable completion"],
134
+ details: { shell: status.shell, cachePath: status.cachePath },
135
+ };
136
+ }
137
+ if (status.usesSlowPattern) {
138
+ return {
139
+ name: "completion",
140
+ status: "warning",
141
+ message: "Using slow dynamic completion pattern",
142
+ durationMs: Date.now() - start,
143
+ suggestions: ["Run `poolbot doctor --fix` to upgrade to cached completion"],
144
+ details: { shell: status.shell },
145
+ };
146
+ }
147
+ return {
148
+ name: "completion",
149
+ status: "ok",
150
+ message: `Shell completion installed and cached for ${status.shell}`,
151
+ durationMs: Date.now() - start,
152
+ details: { shell: status.shell, cachePath: status.cachePath },
153
+ };
154
+ }
155
+ catch (err) {
156
+ return {
157
+ name: "completion",
158
+ status: "error",
159
+ message: `Failed to check completion: ${String(err)}`,
160
+ durationMs: Date.now() - start,
161
+ };
162
+ }
163
+ },
164
+ gateway: async ({ runtime, options }) => {
165
+ const start = Date.now();
166
+ try {
167
+ const cfg = await safeLoadConfig();
168
+ if (!cfg) {
169
+ return {
170
+ name: "gateway",
171
+ status: "skipped",
172
+ message: "Could not load configuration",
173
+ durationMs: Date.now() - start,
174
+ };
175
+ }
176
+ const { checkGatewayHealth } = await import("./doctor-gateway-health.js");
177
+ const result = await checkGatewayHealth({
178
+ runtime,
179
+ cfg: cfg,
180
+ timeoutMs: options.nonInteractive ? 3000 : 10_000,
181
+ });
182
+ if (!result.healthOk) {
183
+ return {
184
+ name: "gateway",
185
+ status: "error",
186
+ message: "Gateway health check failed",
187
+ durationMs: Date.now() - start,
188
+ suggestions: [
189
+ "Run `poolbot gateway status` for detailed status",
190
+ "Run `poolbot gateway restart` to restart the gateway",
191
+ ],
192
+ };
193
+ }
194
+ return {
195
+ name: "gateway",
196
+ status: "ok",
197
+ message: "Gateway is healthy",
198
+ durationMs: Date.now() - start,
199
+ };
200
+ }
201
+ catch (err) {
202
+ return {
203
+ name: "gateway",
204
+ status: "error",
205
+ message: `Failed to check gateway: ${String(err)}`,
206
+ durationMs: Date.now() - start,
207
+ };
208
+ }
209
+ },
210
+ security: async () => {
211
+ const start = Date.now();
212
+ try {
213
+ const cfg = await safeLoadConfig();
214
+ if (!cfg) {
215
+ return {
216
+ name: "security",
217
+ status: "skipped",
218
+ message: "Could not load configuration",
219
+ durationMs: Date.now() - start,
220
+ };
221
+ }
222
+ // Check for security warnings
223
+ const warnings = [];
224
+ const suggestions = [];
225
+ // Check gateway auth
226
+ const gateway = cfg.gateway;
227
+ const auth = gateway?.auth;
228
+ const authMode = auth?.mode;
229
+ if (authMode === "off") {
230
+ warnings.push("Gateway authentication is disabled");
231
+ suggestions.push("Enable token auth: poolbot config set gateway.auth.mode token");
232
+ }
233
+ // Check channel allowlists
234
+ const channels = cfg.channels;
235
+ if (channels) {
236
+ for (const [name, channel] of Object.entries(channels)) {
237
+ if (channel && typeof channel === "object") {
238
+ const ch = channel;
239
+ if (!ch.allowFrom || ch.allowFrom.length === 0) {
240
+ warnings.push(`Channel ${name} has no allowlist configured`);
241
+ }
242
+ }
243
+ }
244
+ }
245
+ if (warnings.length > 0) {
246
+ return {
247
+ name: "security",
248
+ status: "warning",
249
+ message: `${warnings.length} security warning(s) found`,
250
+ durationMs: Date.now() - start,
251
+ suggestions,
252
+ details: { warnings },
253
+ };
254
+ }
255
+ return {
256
+ name: "security",
257
+ status: "ok",
258
+ message: "No security warnings detected",
259
+ durationMs: Date.now() - start,
260
+ };
261
+ }
262
+ catch (err) {
263
+ return {
264
+ name: "security",
265
+ status: "error",
266
+ message: `Failed to check security: ${String(err)}`,
267
+ durationMs: Date.now() - start,
268
+ };
269
+ }
270
+ },
271
+ plugins: async () => {
272
+ const start = Date.now();
273
+ // This is a simplified check - real implementation would load plugin registry
274
+ return {
275
+ name: "plugins",
276
+ status: "ok",
277
+ message: "Plugin check not yet implemented",
278
+ durationMs: Date.now() - start,
279
+ };
280
+ },
281
+ memory: async () => {
282
+ const start = Date.now();
283
+ try {
284
+ const cfg = await safeLoadConfig();
285
+ if (!cfg) {
286
+ return {
287
+ name: "memory",
288
+ status: "skipped",
289
+ message: "Could not load configuration",
290
+ durationMs: Date.now() - start,
291
+ };
292
+ }
293
+ const agents = cfg.agents;
294
+ const defaults = agents?.defaults;
295
+ const memorySearch = defaults?.memorySearch;
296
+ const memoryEnabled = memorySearch?.enabled ?? false;
297
+ if (!memoryEnabled) {
298
+ return {
299
+ name: "memory",
300
+ status: "warning",
301
+ message: "Memory search is disabled",
302
+ durationMs: Date.now() - start,
303
+ suggestions: [
304
+ "Enable memory: poolbot config set agents.defaults.memorySearch.enabled true",
305
+ ],
306
+ };
307
+ }
308
+ return {
309
+ name: "memory",
310
+ status: "ok",
311
+ message: "Memory search is enabled",
312
+ durationMs: Date.now() - start,
313
+ };
314
+ }
315
+ catch (err) {
316
+ return {
317
+ name: "memory",
318
+ status: "error",
319
+ message: `Failed to check memory: ${String(err)}`,
320
+ durationMs: Date.now() - start,
321
+ };
322
+ }
323
+ },
324
+ workspace: async () => {
325
+ const start = Date.now();
326
+ try {
327
+ const agentScope = await import("../agents/agent-scope.js");
328
+ const cfg = await safeLoadConfig();
329
+ if (!cfg) {
330
+ return {
331
+ name: "workspace",
332
+ status: "skipped",
333
+ message: "Could not load configuration",
334
+ durationMs: Date.now() - start,
335
+ };
336
+ }
337
+ const agentId = agentScope.resolveDefaultAgentId(cfg);
338
+ const workspaceDir = agentScope.resolveAgentWorkspaceDir(cfg, agentId);
339
+ // Check if workspace exists
340
+ const fs = await import("node:fs");
341
+ if (!fs.existsSync(workspaceDir)) {
342
+ return {
343
+ name: "workspace",
344
+ status: "warning",
345
+ message: `Workspace directory does not exist`,
346
+ durationMs: Date.now() - start,
347
+ suggestions: ["The workspace will be created on first agent run"],
348
+ details: { path: workspaceDir },
349
+ };
350
+ }
351
+ return {
352
+ name: "workspace",
353
+ status: "ok",
354
+ message: `Workspace ready`,
355
+ durationMs: Date.now() - start,
356
+ details: { path: workspaceDir },
357
+ };
358
+ }
359
+ catch (err) {
360
+ return {
361
+ name: "workspace",
362
+ status: "error",
363
+ message: `Failed to check workspace: ${String(err)}`,
364
+ durationMs: Date.now() - start,
365
+ };
366
+ }
367
+ },
368
+ state: async () => {
369
+ const start = Date.now();
370
+ try {
371
+ const { resolveStateDir } = await import("../config/paths.js");
372
+ const path = await import("node:path");
373
+ const fs = await import("node:fs");
374
+ const stateDir = resolveStateDir();
375
+ const checks = {
376
+ stateDir: fs.existsSync(stateDir),
377
+ completions: fs.existsSync(path.join(stateDir, "completions")),
378
+ sessions: fs.existsSync(path.join(stateDir, "sessions")),
379
+ };
380
+ const missing = Object.entries(checks)
381
+ .filter(([, exists]) => !exists)
382
+ .map(([name]) => name);
383
+ if (missing.length > 0) {
384
+ return {
385
+ name: "state",
386
+ status: "warning",
387
+ message: `Missing state directories: ${missing.join(", ")}`,
388
+ durationMs: Date.now() - start,
389
+ suggestions: ["Run `poolbot doctor --fix` to create missing directories"],
390
+ details: { checks },
391
+ };
392
+ }
393
+ return {
394
+ name: "state",
395
+ status: "ok",
396
+ message: "All state directories present",
397
+ durationMs: Date.now() - start,
398
+ details: { checks },
399
+ };
400
+ }
401
+ catch (err) {
402
+ return {
403
+ name: "state",
404
+ status: "error",
405
+ message: `Failed to check state: ${String(err)}`,
406
+ durationMs: Date.now() - start,
407
+ };
408
+ }
409
+ },
410
+ };
411
+ /**
412
+ * Run a specific check by name
413
+ */
414
+ export async function runDoctorCheck(name, params) {
415
+ const checkFn = doctorCheckRegistry[name];
416
+ if (!checkFn) {
417
+ return {
418
+ name,
419
+ status: "error",
420
+ message: `Unknown check: ${name}`,
421
+ durationMs: 0,
422
+ };
423
+ }
424
+ return checkFn(params);
425
+ }
426
+ /**
427
+ * Run all checks and generate report
428
+ */
429
+ export async function runAllDoctorChecks(params) {
430
+ const checks = [
431
+ "config",
432
+ "auth",
433
+ "completion",
434
+ "gateway",
435
+ "security",
436
+ "memory",
437
+ "workspace",
438
+ "state",
439
+ ];
440
+ const results = [];
441
+ for (const checkName of checks) {
442
+ const result = await runDoctorCheck(checkName, params);
443
+ results.push(result);
444
+ }
445
+ // Calculate health score
446
+ const weights = { ok: 1, warning: 0.5, error: 0, skipped: 0.75 };
447
+ const totalWeight = results.reduce((sum, r) => sum + weights[r.status], 0);
448
+ const healthScore = Math.round((totalWeight / results.length) * 100);
449
+ return {
450
+ timestamp: new Date().toISOString(),
451
+ version: "2026.3.9", // Should be dynamic
452
+ checks: results,
453
+ summary: {
454
+ total: results.length,
455
+ ok: results.filter((r) => r.status === "ok").length,
456
+ warning: results.filter((r) => r.status === "warning").length,
457
+ error: results.filter((r) => r.status === "error").length,
458
+ skipped: results.filter((r) => r.status === "skipped").length,
459
+ autoFixed: results.filter((r) => r.autoFixed).length,
460
+ },
461
+ healthScore,
462
+ };
463
+ }
464
+ /**
465
+ * Format report for console output
466
+ */
467
+ export function formatDoctorReport(report) {
468
+ const lines = [];
469
+ // Header
470
+ lines.push("╔════════════════════════════════════════════════════════╗");
471
+ lines.push("║ 🏥 PoolBot Doctor Report ║");
472
+ lines.push("╚════════════════════════════════════════════════════════╝");
473
+ lines.push("");
474
+ // Health score
475
+ const scoreColor = report.healthScore >= 80 ? "🟢" : report.healthScore >= 50 ? "🟡" : "🔴";
476
+ lines.push(`Health Score: ${scoreColor} ${report.healthScore}/100`);
477
+ lines.push("");
478
+ // Summary
479
+ lines.push("Summary:");
480
+ lines.push(` ✅ OK: ${report.summary.ok}/${report.summary.total}`);
481
+ lines.push(` ⚠️ Warning: ${report.summary.warning}/${report.summary.total}`);
482
+ lines.push(` ❌ Error: ${report.summary.error}/${report.summary.total}`);
483
+ if (report.summary.autoFixed > 0) {
484
+ lines.push(` 🔧 Auto-fixed: ${report.summary.autoFixed}`);
485
+ }
486
+ lines.push("");
487
+ // Individual checks
488
+ for (const check of report.checks) {
489
+ const icon = check.status === "ok" ? "✅" : check.status === "warning" ? "⚠️" : "❌";
490
+ lines.push(`${icon} ${check.name.padEnd(12)} ${check.message}`);
491
+ if (check.suggestions && check.suggestions.length > 0) {
492
+ for (const suggestion of check.suggestions) {
493
+ lines.push(` 💡 ${suggestion}`);
494
+ }
495
+ }
496
+ }
497
+ return lines.join("\n");
498
+ }
@@ -2,6 +2,7 @@ export { createConfigIO, loadConfig, parseConfigJson5, readConfigFileSnapshot, r
2
2
  export { migrateLegacyConfig } from "./legacy-migrate.js";
3
3
  export * from "./paths.js";
4
4
  export * from "./runtime-overrides.js";
5
+ export * from "./secrets-integration.js";
5
6
  export * from "./types.js";
6
7
  export { validateConfigObject, validateConfigObjectWithPlugins } from "./validation.js";
7
8
  export { PoolBotSchema } from "./zod-schema.js";
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Config Secrets Integration
3
+ *
4
+ * Integrates the secrets management system with config loading.
5
+ * Resolves SecretRefs in config values at runtime.
6
+ */
7
+ import { SecretsRuntime } from "../secrets/index.js";
8
+ const SECRET_PATHS = [
9
+ "agent.model",
10
+ "agent.apiKey",
11
+ "channels.telegram.botToken",
12
+ "channels.discord.token",
13
+ "channels.slack.botToken",
14
+ "channels.slack.appToken",
15
+ "gateway.auth.token",
16
+ "gateway.auth.password",
17
+ "memory.apiKey",
18
+ "tools.browser.apiKey",
19
+ ];
20
+ /**
21
+ * Deeply traverse config and resolve secret references
22
+ */
23
+ export function resolveConfigSecrets(config, secretsRuntime) {
24
+ const resolved = { ...config };
25
+ // Resolve specific known secret paths
26
+ for (const path of SECRET_PATHS) {
27
+ resolvePath(resolved, path.split("."), secretsRuntime);
28
+ }
29
+ // Also scan for any string values that look like secret refs
30
+ scanAndResolveSecrets(resolved, "", secretsRuntime);
31
+ return resolved;
32
+ }
33
+ function resolvePath(obj, path, runtime) {
34
+ if (path.length === 0)
35
+ return;
36
+ const [head, ...tail] = path;
37
+ if (!(head in obj))
38
+ return;
39
+ if (tail.length === 0) {
40
+ // Leaf node - resolve if it's a string
41
+ const value = obj[head];
42
+ if (typeof value === "string") {
43
+ const result = runtime.resolve(head, value);
44
+ if (result.value !== undefined) {
45
+ obj[head] = result.value;
46
+ }
47
+ }
48
+ }
49
+ else {
50
+ // Traverse deeper
51
+ const child = obj[head];
52
+ if (typeof child === "object" && child !== null && !Array.isArray(child)) {
53
+ resolvePath(child, tail, runtime);
54
+ }
55
+ }
56
+ }
57
+ function scanAndResolveSecrets(obj, path, runtime) {
58
+ if (typeof obj === "string") {
59
+ // Check if it looks like a secret ref
60
+ if (obj.startsWith("env:") || obj.startsWith("file:")) {
61
+ runtime.resolve(path || "unknown", obj);
62
+ }
63
+ return;
64
+ }
65
+ if (Array.isArray(obj)) {
66
+ obj.forEach((item, index) => {
67
+ scanAndResolveSecrets(item, `${path}[${index}]`, runtime);
68
+ });
69
+ return;
70
+ }
71
+ if (typeof obj === "object" && obj !== null) {
72
+ for (const [key, value] of Object.entries(obj)) {
73
+ const newPath = path ? `${path}.${key}` : key;
74
+ scanAndResolveSecrets(value, newPath, runtime);
75
+ }
76
+ }
77
+ }
78
+ /**
79
+ * Create a secrets runtime from config
80
+ */
81
+ export function createSecretsRuntimeFromConfig(_config, secretsConfig) {
82
+ return new SecretsRuntime({
83
+ allowDirectValues: true,
84
+ warnOnDirectValues: true,
85
+ failOnUnresolved: false,
86
+ ...secretsConfig,
87
+ });
88
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Context Engine - Pluggable conversation context management
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { LegacyContextEngine, globalContextEngineRegistry } from './context-engine/index.js';
7
+ *
8
+ * // Register the legacy engine
9
+ * globalContextEngineRegistry.register('legacy', LegacyContextEngine);
10
+ *
11
+ * // Get engine instance
12
+ * const engine = globalContextEngineRegistry.getEngine('legacy');
13
+ *
14
+ * // Bootstrap for a session
15
+ * await engine.bootstrap({ sessionId: 'session-123' });
16
+ *
17
+ * // Ingest a message
18
+ * await engine.ingest({
19
+ * sessionId: 'session-123',
20
+ * message: { role: 'user', content: 'Hello!' }
21
+ * });
22
+ *
23
+ * // Assemble context
24
+ * const result = await engine.assemble({
25
+ * sessionId: 'session-123',
26
+ * messages: []
27
+ * });
28
+ * ```
29
+ */
30
+ // Registry
31
+ export { ContextEngineRegistry, globalContextEngineRegistry, resolveContextEngine, } from "./registry.js";
32
+ // Legacy Engine
33
+ export { LegacyContextEngine, createLegacyContextEngine } from "./legacy.js";