opc-agent 2.0.2 → 3.0.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 (151) hide show
  1. package/README.md +603 -545
  2. package/dist/channels/voice.d.ts +59 -0
  3. package/dist/channels/voice.js +351 -1
  4. package/dist/cli.js +284 -5
  5. package/dist/core/agent.d.ts +9 -0
  6. package/dist/core/agent.js +49 -0
  7. package/dist/core/collaboration.d.ts +89 -0
  8. package/dist/core/collaboration.js +201 -0
  9. package/dist/deploy/index.d.ts +40 -0
  10. package/dist/deploy/index.js +261 -0
  11. package/dist/index.d.ts +7 -1
  12. package/dist/index.js +47 -3
  13. package/dist/mcp/servers/calculator-mcp.d.ts +3 -0
  14. package/dist/mcp/servers/calculator-mcp.js +65 -0
  15. package/dist/mcp/servers/crypto-mcp.d.ts +3 -0
  16. package/dist/mcp/servers/crypto-mcp.js +108 -0
  17. package/dist/mcp/servers/database-mcp.d.ts +3 -0
  18. package/dist/mcp/servers/database-mcp.js +73 -0
  19. package/dist/mcp/servers/datetime-mcp.d.ts +3 -0
  20. package/dist/mcp/servers/datetime-mcp.js +71 -0
  21. package/dist/mcp/servers/filesystem.d.ts +3 -0
  22. package/dist/mcp/servers/filesystem.js +101 -0
  23. package/dist/mcp/servers/github-mcp.d.ts +3 -0
  24. package/dist/mcp/servers/github-mcp.js +60 -0
  25. package/dist/mcp/servers/index.d.ts +21 -0
  26. package/dist/mcp/servers/index.js +50 -0
  27. package/dist/mcp/servers/json-mcp.d.ts +3 -0
  28. package/dist/mcp/servers/json-mcp.js +126 -0
  29. package/dist/mcp/servers/memory-mcp.d.ts +3 -0
  30. package/dist/mcp/servers/memory-mcp.js +60 -0
  31. package/dist/mcp/servers/regex-mcp.d.ts +3 -0
  32. package/dist/mcp/servers/regex-mcp.js +56 -0
  33. package/dist/mcp/servers/web-mcp.d.ts +3 -0
  34. package/dist/mcp/servers/web-mcp.js +51 -0
  35. package/dist/memory/index.d.ts +2 -0
  36. package/dist/memory/index.js +4 -1
  37. package/dist/memory/seed-loader.d.ts +51 -0
  38. package/dist/memory/seed-loader.js +200 -0
  39. package/dist/schema/oad.d.ts +292 -12
  40. package/dist/schema/oad.js +12 -1
  41. package/dist/security/guardrails.d.ts +50 -0
  42. package/dist/security/guardrails.js +197 -0
  43. package/dist/studio/server.d.ts +31 -1
  44. package/dist/studio/server.js +154 -3
  45. package/dist/studio-ui/index.html +1278 -662
  46. package/dist/tools/integrations/calendar.d.ts +3 -0
  47. package/dist/tools/integrations/calendar.js +73 -0
  48. package/dist/tools/integrations/code-exec.d.ts +3 -0
  49. package/dist/tools/integrations/code-exec.js +42 -0
  50. package/dist/tools/integrations/csv-analyzer.d.ts +3 -0
  51. package/dist/tools/integrations/csv-analyzer.js +142 -0
  52. package/dist/tools/integrations/database.d.ts +3 -0
  53. package/dist/tools/integrations/database.js +44 -0
  54. package/dist/tools/integrations/email-send.d.ts +3 -0
  55. package/dist/tools/integrations/email-send.js +104 -0
  56. package/dist/tools/integrations/git-tool.d.ts +3 -0
  57. package/dist/tools/integrations/git-tool.js +49 -0
  58. package/dist/tools/integrations/github-tool.d.ts +3 -0
  59. package/dist/tools/integrations/github-tool.js +77 -0
  60. package/dist/tools/integrations/image-gen.d.ts +3 -0
  61. package/dist/tools/integrations/image-gen.js +58 -0
  62. package/dist/tools/integrations/index.d.ts +30 -0
  63. package/dist/tools/integrations/index.js +107 -0
  64. package/dist/tools/integrations/jira.d.ts +3 -0
  65. package/dist/tools/integrations/jira.js +85 -0
  66. package/dist/tools/integrations/notion.d.ts +3 -0
  67. package/dist/tools/integrations/notion.js +71 -0
  68. package/dist/tools/integrations/npm-tool.d.ts +3 -0
  69. package/dist/tools/integrations/npm-tool.js +49 -0
  70. package/dist/tools/integrations/pdf-reader.d.ts +3 -0
  71. package/dist/tools/integrations/pdf-reader.js +91 -0
  72. package/dist/tools/integrations/slack.d.ts +3 -0
  73. package/dist/tools/integrations/slack.js +67 -0
  74. package/dist/tools/integrations/summarizer.d.ts +3 -0
  75. package/dist/tools/integrations/summarizer.js +49 -0
  76. package/dist/tools/integrations/translator.d.ts +3 -0
  77. package/dist/tools/integrations/translator.js +48 -0
  78. package/dist/tools/integrations/trello.d.ts +3 -0
  79. package/dist/tools/integrations/trello.js +60 -0
  80. package/dist/tools/integrations/vector-search.d.ts +3 -0
  81. package/dist/tools/integrations/vector-search.js +44 -0
  82. package/dist/tools/integrations/web-scraper.d.ts +3 -0
  83. package/dist/tools/integrations/web-scraper.js +48 -0
  84. package/dist/tools/integrations/web-search.d.ts +3 -0
  85. package/dist/tools/integrations/web-search.js +60 -0
  86. package/dist/tools/integrations/webhook.d.ts +3 -0
  87. package/dist/tools/integrations/webhook.js +39 -0
  88. package/dist/ui/components.d.ts +10 -0
  89. package/dist/ui/components.js +123 -0
  90. package/package.json +1 -1
  91. package/src/channels/voice.ts +365 -0
  92. package/src/cli.ts +294 -6
  93. package/src/core/agent.ts +56 -0
  94. package/src/core/collaboration.ts +275 -0
  95. package/src/deploy/index.ts +255 -0
  96. package/src/index.ts +21 -1
  97. package/src/mcp/servers/calculator-mcp.ts +65 -0
  98. package/src/mcp/servers/crypto-mcp.ts +73 -0
  99. package/src/mcp/servers/database-mcp.ts +72 -0
  100. package/src/mcp/servers/datetime-mcp.ts +69 -0
  101. package/src/mcp/servers/filesystem.ts +66 -0
  102. package/src/mcp/servers/github-mcp.ts +58 -0
  103. package/src/mcp/servers/index.ts +63 -0
  104. package/src/mcp/servers/json-mcp.ts +102 -0
  105. package/src/mcp/servers/memory-mcp.ts +56 -0
  106. package/src/mcp/servers/regex-mcp.ts +53 -0
  107. package/src/mcp/servers/web-mcp.ts +49 -0
  108. package/src/memory/index.ts +3 -0
  109. package/src/memory/seed-loader.ts +212 -0
  110. package/src/schema/oad.ts +13 -0
  111. package/src/security/guardrails.ts +248 -0
  112. package/src/studio/server.ts +166 -4
  113. package/src/studio-ui/index.html +1278 -662
  114. package/src/tools/integrations/calendar.ts +73 -0
  115. package/src/tools/integrations/code-exec.ts +39 -0
  116. package/src/tools/integrations/csv-analyzer.ts +92 -0
  117. package/src/tools/integrations/database.ts +44 -0
  118. package/src/tools/integrations/email-send.ts +76 -0
  119. package/src/tools/integrations/git-tool.ts +42 -0
  120. package/src/tools/integrations/github-tool.ts +76 -0
  121. package/src/tools/integrations/image-gen.ts +56 -0
  122. package/src/tools/integrations/index.ts +92 -0
  123. package/src/tools/integrations/jira.ts +83 -0
  124. package/src/tools/integrations/notion.ts +71 -0
  125. package/src/tools/integrations/npm-tool.ts +48 -0
  126. package/src/tools/integrations/pdf-reader.ts +58 -0
  127. package/src/tools/integrations/slack.ts +65 -0
  128. package/src/tools/integrations/summarizer.ts +49 -0
  129. package/src/tools/integrations/translator.ts +48 -0
  130. package/src/tools/integrations/trello.ts +60 -0
  131. package/src/tools/integrations/vector-search.ts +42 -0
  132. package/src/tools/integrations/web-scraper.ts +47 -0
  133. package/src/tools/integrations/web-search.ts +58 -0
  134. package/src/tools/integrations/webhook.ts +38 -0
  135. package/src/ui/components.ts +127 -0
  136. package/tests/brain-seed-extended.test.ts +490 -0
  137. package/tests/brain-seed.test.ts +239 -0
  138. package/tests/collaboration.test.ts +319 -0
  139. package/tests/deploy-and-dag.test.ts +196 -0
  140. package/tests/guardrails.test.ts +177 -0
  141. package/tests/integrations.test.ts +249 -0
  142. package/tests/mcp-servers.test.ts +260 -0
  143. package/tests/voice-enhanced.test.ts +169 -0
  144. package/dist/dtv/data.d.ts +0 -18
  145. package/dist/dtv/data.js +0 -25
  146. package/dist/dtv/trust.d.ts +0 -19
  147. package/dist/dtv/trust.js +0 -40
  148. package/dist/dtv/value.d.ts +0 -23
  149. package/dist/dtv/value.js +0 -38
  150. package/dist/marketplace/index.d.ts +0 -34
  151. package/dist/marketplace/index.js +0 -202
package/dist/cli.js CHANGED
@@ -57,6 +57,7 @@ const analytics_engine_1 = require("./core/analytics-engine");
57
57
  const testing_1 = require("./testing");
58
58
  const openclaw_1 = require("./deploy/openclaw");
59
59
  const hermes_1 = require("./deploy/hermes");
60
+ const index_1 = require("./deploy/index");
60
61
  const workflow_1 = require("./core/workflow");
61
62
  const versioning_1 = require("./core/versioning");
62
63
  const providers_1 = require("./providers");
@@ -188,9 +189,21 @@ program
188
189
  fs.mkdirSync(dir, { recursive: true });
189
190
  fs.mkdirSync(path.join(dir, 'src', 'skills'), { recursive: true });
190
191
  fs.mkdirSync(path.join(dir, 'data'), { recursive: true });
192
+ fs.mkdirSync(path.join(dir, 'brain-seeds'), { recursive: true });
191
193
  // Get system prompt content
192
194
  const systemPromptContent = roleData.files['system-prompt.md'] || roleData.files['prompts/system.md'] || '';
193
- // agent.yaml with role system prompt
195
+ // Generate brain-seeds/ files from role data
196
+ const brainSeedContent = roleData.files['brain-seed.md'] || '';
197
+ const industryMatch = brainSeedContent ? brainSeedContent.match(/# Industry Knowledge[\s\S]*?(?=# Job Knowledge|# Workstation Knowledge|$)/i) : null;
198
+ const jobMatch = brainSeedContent ? brainSeedContent.match(/# Job Knowledge[\s\S]*?(?=# Industry Knowledge|# Workstation Knowledge|$)/i) : null;
199
+ const workstationMatch = brainSeedContent ? brainSeedContent.match(/# Workstation Knowledge[\s\S]*?(?=# Industry Knowledge|# Job Knowledge|$)/i) : null;
200
+ fs.writeFileSync(path.join(dir, 'brain-seeds', 'industry.md'), industryMatch?.[0]?.trim() || `# Industry Knowledge\n\n## Overview\n\nAdd industry-specific knowledge for your domain.\n`);
201
+ fs.writeFileSync(path.join(dir, 'brain-seeds', 'job.md'), jobMatch?.[0]?.trim() || `# Job Knowledge\n\n## Core Skills\n\nAdd role-specific knowledge for ${roleDisplayName}.\n`);
202
+ // workstation.md: public workstation knowledge (tools, workflows, best practices)
203
+ // Company-specific knowledge belongs to Desk (closed-source), not here.
204
+ const workstationSeedFromRole = workstationMatch?.[0]?.trim() || '';
205
+ fs.writeFileSync(path.join(dir, 'brain-seeds', 'workstation.md'), workstationSeedFromRole || `# Workstation Knowledge\n\n## Tools & Environment\n\nCommon tools and setup for this workstation role.\n\n## Workflows\n\nStandard operating procedures and workflows.\n\n## Best Practices\n\nIndustry best practices for this role.\n`);
206
+ // agent.yaml with role system prompt and brain seeds
194
207
  const firstLine = systemPromptContent.split('\n').find((l) => l.trim() && !l.startsWith('#'))?.trim() || 'You are a helpful AI assistant.';
195
208
  fs.writeFileSync(path.join(dir, 'agent.yaml'), `apiVersion: opc/v1
196
209
  kind: Agent
@@ -212,6 +225,15 @@ spec:
212
225
  longTerm:
213
226
  provider: deepbrain
214
227
  database: ./data/brain.db
228
+ brain:
229
+ seeds:
230
+ - brain-seeds/industry.md
231
+ - brain-seeds/job.md
232
+ - brain-seeds/workstation.md
233
+ autoSeed: true
234
+ evolve:
235
+ enabled: true
236
+ direction: bottom-up
215
237
  skills: []
216
238
  `);
217
239
  // SOUL.md from system-prompt.md
@@ -292,8 +314,12 @@ export class EchoSkill extends BaseSkill {
292
314
  console.log(` ${icon.file} agent.yaml - Agent definition with role system prompt`);
293
315
  console.log(` ${icon.file} SOUL.md - Role personality (${systemPromptContent.split('\n').length} lines)`);
294
316
  console.log(` ${icon.file} CONTEXT.md - Role context & documentation`);
317
+ console.log(` ${icon.file} brain-seeds/ - 3-tier brain seed knowledge`);
318
+ console.log(` ${color.dim('├')} industry.md - Industry knowledge`);
319
+ console.log(` ${color.dim('├')} job.md - Job/role knowledge`);
320
+ console.log(` ${color.dim('└')} workstation.md - Workstation knowledge`);
295
321
  if (roleData.files['brain-seed.md']) {
296
- console.log(` ${icon.file} data/brain-seed.md - Role brain seed knowledge`);
322
+ console.log(` ${icon.file} data/brain-seed.md - Role brain seed knowledge (legacy)`);
297
323
  }
298
324
  console.log(` ${icon.file} src/index.ts - Entry point`);
299
325
  console.log(` ${icon.file} package.json - Dependencies`);
@@ -952,9 +978,70 @@ program
952
978
  .option('-t, --target <target>', 'Deploy target', 'openclaw')
953
979
  .option('-o, --output <dir>', 'Output directory')
954
980
  .option('--install', 'Also register in OpenClaw config')
981
+ .option('--docker', 'Generate Dockerfile + docker-compose.yml')
982
+ .option('--railway', 'Deploy to Railway')
983
+ .option('--fly', 'Deploy to Fly.io')
984
+ .option('--local', 'Deploy locally via Docker Compose')
985
+ .option('-p, --port <port>', 'Port number', '3000')
986
+ .option('--replicas <n>', 'Number of replicas', '1')
955
987
  .action(async (opts) => {
988
+ const deployer = new index_1.AgentDeployer();
989
+ const agentDir = path.resolve(opts.output || '.');
990
+ // New deploy modes
991
+ if (opts.docker) {
992
+ console.log(`\n${icon.rocket} ${color.bold('Generating Docker deployment files')}\n`);
993
+ const result = await deployer.generateFiles(agentDir, { port: parseInt(opts.port), replicas: parseInt(opts.replicas) });
994
+ console.log(`${icon.success} ${result.message}`);
995
+ for (const f of (result.files || []))
996
+ console.log(` ${icon.file} ${f}`);
997
+ console.log();
998
+ return;
999
+ }
1000
+ if (opts.railway) {
1001
+ console.log(`\n${icon.rocket} ${color.bold('Deploying to Railway')}\n`);
1002
+ const result = await deployer.deployRailway(agentDir);
1003
+ if (result.success) {
1004
+ console.log(`${icon.success} ${result.message}`);
1005
+ if (result.url)
1006
+ console.log(` URL: ${color.cyan(result.url)}`);
1007
+ }
1008
+ else {
1009
+ console.error(`${icon.error} ${result.message}`);
1010
+ process.exit(1);
1011
+ }
1012
+ return;
1013
+ }
1014
+ if (opts.fly) {
1015
+ console.log(`\n${icon.rocket} ${color.bold('Deploying to Fly.io')}\n`);
1016
+ const result = await deployer.deployFly(agentDir);
1017
+ if (result.success) {
1018
+ console.log(`${icon.success} ${result.message}`);
1019
+ if (result.url)
1020
+ console.log(` URL: ${color.cyan(result.url)}`);
1021
+ }
1022
+ else {
1023
+ console.error(`${icon.error} ${result.message}`);
1024
+ process.exit(1);
1025
+ }
1026
+ return;
1027
+ }
1028
+ if (opts.local) {
1029
+ console.log(`\n${icon.rocket} ${color.bold('Deploying locally via Docker')}\n`);
1030
+ const result = await deployer.deployLocal(agentDir, { port: parseInt(opts.port), replicas: parseInt(opts.replicas) });
1031
+ if (result.success) {
1032
+ console.log(`${icon.success} ${result.message}`);
1033
+ if (result.url)
1034
+ console.log(` URL: ${color.cyan(result.url)}`);
1035
+ }
1036
+ else {
1037
+ console.error(`${icon.error} ${result.message}`);
1038
+ process.exit(1);
1039
+ }
1040
+ return;
1041
+ }
1042
+ // Legacy deploy modes
956
1043
  if (opts.target !== 'openclaw' && opts.target !== 'hermes') {
957
- console.error(`${icon.error} Unknown target: ${color.bold(opts.target)}. Supported: openclaw, hermes`);
1044
+ console.error(`${icon.error} Unknown target: ${color.bold(opts.target)}. Supported: openclaw, hermes, --docker, --railway, --fly, --local`);
958
1045
  process.exit(1);
959
1046
  }
960
1047
  try {
@@ -1403,9 +1490,12 @@ program
1403
1490
  }
1404
1491
  });
1405
1492
  // ── Brain command ────────────────────────────────────────────
1406
- program
1493
+ const brainCmd = program
1407
1494
  .command('brain')
1408
- .description('Show agent memory/brain status from DeepBrain')
1495
+ .description('Manage agent brain (memory, seeds, evolve)');
1496
+ brainCmd
1497
+ .command('status')
1498
+ .description('Show brain stats (pages, tiers, last evolve)')
1409
1499
  .option('--url <url>', 'DeepBrain server URL', 'http://localhost:3333')
1410
1500
  .action(async (opts) => {
1411
1501
  console.log(`\n${icon.gear} ${color.bold('DeepBrain Status')} — ${color.dim(opts.url)}\n`);
@@ -1438,6 +1528,86 @@ program
1438
1528
  }
1439
1529
  }
1440
1530
  });
1531
+ brainCmd
1532
+ .command('seed')
1533
+ .description('Import brain seed files into memory')
1534
+ .option('-f, --file <file>', 'OAD file', 'agent.yaml')
1535
+ .option('--status', 'Check if seeds have been imported')
1536
+ .option('--reset', 'Re-import seeds (clear marker and re-seed)')
1537
+ .action(async (opts) => {
1538
+ const { BrainSeedLoader } = require('./memory/seed-loader');
1539
+ let config = {};
1540
+ try {
1541
+ config = yaml.load(fs.readFileSync(opts.file, 'utf-8'));
1542
+ }
1543
+ catch { /* ignore */ }
1544
+ const brainConfig = config?.spec?.brain;
1545
+ if (!brainConfig?.seeds?.length) {
1546
+ console.log(`${icon.info} No brain seeds configured in ${opts.file}.`);
1547
+ console.log(` Add spec.brain.seeds to your agent.yaml.`);
1548
+ return;
1549
+ }
1550
+ const loader = new BrainSeedLoader(process.cwd(), {
1551
+ seeds: brainConfig.seeds,
1552
+ autoSeed: brainConfig.autoSeed !== false,
1553
+ });
1554
+ if (opts.status) {
1555
+ const seeded = await loader.isSeeded();
1556
+ console.log(`\n Brain seed status: ${seeded ? color.green('seeded ✔') : color.yellow('not seeded')}`);
1557
+ console.log(` Seeds configured: ${brainConfig.seeds.map((s) => color.cyan(s)).join(', ')}\n`);
1558
+ return;
1559
+ }
1560
+ if (opts.reset) {
1561
+ const markerPath = path.resolve(process.cwd(), '.brain-seeded');
1562
+ if (fs.existsSync(markerPath)) {
1563
+ fs.unlinkSync(markerPath);
1564
+ console.log(` ${icon.success} Cleared seed marker.`);
1565
+ }
1566
+ }
1567
+ if (await loader.isSeeded() && !opts.reset) {
1568
+ console.log(`${icon.info} Brain already seeded. Use --reset to re-import.`);
1569
+ return;
1570
+ }
1571
+ console.log(`\n${icon.gear} Importing brain seeds...\n`);
1572
+ // Use a simple mock brain that logs imports (real usage would connect to DeepBrain)
1573
+ const pages = [];
1574
+ const mockBrain = {
1575
+ learn: async (content, meta) => { pages.push(meta?.slug || 'unknown'); },
1576
+ };
1577
+ const result = await loader.seedBrain(mockBrain);
1578
+ await loader.markSeeded();
1579
+ console.log(` ${icon.success} Imported ${color.bold(String(result.imported))} pages from ${brainConfig.seeds.length} seed files.`);
1580
+ for (const p of result.pages) {
1581
+ console.log(` ${color.dim('•')} ${p}`);
1582
+ }
1583
+ console.log();
1584
+ });
1585
+ brainCmd
1586
+ .command('evolve')
1587
+ .description('Trigger manual knowledge evolution cycle')
1588
+ .option('--dry-run', 'Show what would be promoted without doing it')
1589
+ .action(async (opts) => {
1590
+ const { KnowledgeEvolver } = require('./memory/seed-loader');
1591
+ const evolver = new KnowledgeEvolver();
1592
+ console.log(`\n${icon.gear} ${color.bold('Knowledge Evolution')}\n`);
1593
+ console.log(` ${icon.info} Checking for promotion candidates...`);
1594
+ // Would connect to real brain in production
1595
+ const result = await evolver.checkPromotion(null);
1596
+ if (result.candidates.length === 0) {
1597
+ console.log(` ${icon.info} No knowledge ready for promotion yet.\n`);
1598
+ }
1599
+ else {
1600
+ for (const c of result.candidates) {
1601
+ console.log(` ${color.cyan(c.slug)} → ${c.fromTier} → ${c.toTier} (confidence: ${(c.confidence * 100).toFixed(0)}%)`);
1602
+ }
1603
+ if (opts.dryRun) {
1604
+ console.log(`\n ${icon.info} Dry run — no changes made.\n`);
1605
+ }
1606
+ else {
1607
+ console.log(`\n ${icon.success} Promoted ${result.promoted} knowledge entries.\n`);
1608
+ }
1609
+ }
1610
+ });
1441
1611
  // ── Logs command ─────────────────────────────────────────────
1442
1612
  program
1443
1613
  .command('logs')
@@ -1866,6 +2036,82 @@ program
1866
2036
  }
1867
2037
  console.log(`\n${color.bold('Summary:')} ${allPassed}/${allTotal} passed (${allTotal ? Math.round(allPassed / allTotal * 100) : 0}%)`);
1868
2038
  });
2039
+ // ── Guardrails command ────────────────────────────────────────
2040
+ const guardrailsCmd = program.command('guardrails').description('Guardrail utilities');
2041
+ guardrailsCmd
2042
+ .command('test <message>')
2043
+ .description('Test guardrails against a message')
2044
+ .option('-c, --config <file>', 'OAD config file with guardrails')
2045
+ .action(async (message, opts) => {
2046
+ const { GuardrailManager, createGuardrailsFromConfig } = await Promise.resolve().then(() => __importStar(require('./security/guardrails')));
2047
+ let manager;
2048
+ if (opts.config) {
2049
+ const raw = fs.readFileSync(opts.config, 'utf-8');
2050
+ const doc = yaml.load(raw);
2051
+ manager = createGuardrailsFromConfig(doc.spec?.guardrails ?? {});
2052
+ }
2053
+ else {
2054
+ // Default: all built-in rules
2055
+ manager = new GuardrailManager({
2056
+ input: [
2057
+ { name: 'pii-detector', type: 'regex', action: 'redact' },
2058
+ { name: 'prompt-injection', type: 'keyword', action: 'block' },
2059
+ { name: 'toxicity', type: 'keyword', action: 'block' },
2060
+ { name: 'compliance-filter', type: 'keyword', action: 'block' },
2061
+ ],
2062
+ output: [],
2063
+ });
2064
+ }
2065
+ console.log(color.bold('Testing guardrails against:'), message);
2066
+ console.log();
2067
+ const result = await manager.checkInput(message);
2068
+ if (result.passed) {
2069
+ console.log(color.green('✓ PASSED — no violations'));
2070
+ }
2071
+ else {
2072
+ if (result.blocked)
2073
+ console.log(color.red('✗ BLOCKED'));
2074
+ if (result.warned)
2075
+ console.log(color.yellow('⚠ WARNING'));
2076
+ if (result.redacted) {
2077
+ console.log(color.yellow('✎ REDACTED'));
2078
+ console.log(' Redacted text:', result.redactedText);
2079
+ }
2080
+ for (const v of result.violations) {
2081
+ console.log(` [${v.action}] ${v.rule}: ${v.detail}`);
2082
+ }
2083
+ }
2084
+ });
2085
+ // ── Voice command ─────────────────────────────────────────────
2086
+ program
2087
+ .command('voice')
2088
+ .description('Voice conversation utilities')
2089
+ .command('start')
2090
+ .description('Start voice conversation (requires STT/TTS providers)')
2091
+ .option('--stt <provider>', 'STT provider: whisper, deepgram', 'whisper')
2092
+ .option('--tts <provider>', 'TTS provider: edge-tts, openai-tts, elevenlabs', 'edge-tts')
2093
+ .option('--voice <name>', 'Voice name/id')
2094
+ .option('--language <lang>', 'Language code', 'en')
2095
+ .action(async (opts) => {
2096
+ console.log(color.bold('🎤 Voice Conversation Mode'));
2097
+ console.log(` STT: ${opts.stt} | TTS: ${opts.tts} | Voice: ${opts.voice ?? 'default'} | Language: ${opts.language}`);
2098
+ console.log(color.dim(' (Voice conversation requires audio input integration — use as library)'));
2099
+ console.log();
2100
+ console.log('To use voice in your agent:');
2101
+ console.log(color.cyan(`
2102
+ import { VoiceChannel, createVoiceProviders } from 'opc-agent';
2103
+
2104
+ const { stt, tts } = createVoiceProviders({
2105
+ sttProvider: '${opts.stt}',
2106
+ ttsProvider: '${opts.tts}',
2107
+ voice: '${opts.voice ?? 'en-US-AriaNeural'}',
2108
+ language: '${opts.language}',
2109
+ });
2110
+
2111
+ const voice = new VoiceChannel({ sttProvider: stt, ttsProvider: tts });
2112
+ await voice.start();
2113
+ `));
2114
+ });
1869
2115
  program.parse();
1870
2116
  // ── Keys command ──────────────────────────────────────────────
1871
2117
  const keys_1 = require("./security/keys");
@@ -2142,4 +2388,37 @@ mcpCmd
2142
2388
  }
2143
2389
  console.log();
2144
2390
  });
2391
+ mcpCmd
2392
+ .command('list')
2393
+ .description('List available pre-built MCP servers')
2394
+ .action(() => {
2395
+ const { listMCPServers } = require('./mcp/servers');
2396
+ const servers = listMCPServers();
2397
+ console.log(`\n${icon.gear} Available MCP Servers:\n`);
2398
+ for (const s of servers) {
2399
+ console.log(` ${color.green(s.name.padEnd(14))} ${s.description} ${color.dim(`(${s.toolCount} tools, v${s.version})`)}`);
2400
+ }
2401
+ console.log(`\n Total: ${servers.length} servers\n`);
2402
+ });
2403
+ mcpCmd
2404
+ .command('start')
2405
+ .argument('<name>', 'Server name (e.g. filesystem, github, calculator)')
2406
+ .option('--port <port>', 'Start in HTTP+SSE mode on given port')
2407
+ .description('Start a pre-built MCP server (stdio by default)')
2408
+ .action(async (name, opts) => {
2409
+ const { getMCPServer } = require('./mcp/servers');
2410
+ const { MCPServer } = require('./protocols/mcp');
2411
+ const config = getMCPServer(name);
2412
+ const server = new MCPServer(config);
2413
+ if (opts.port) {
2414
+ const port = parseInt(opts.port) || 3100;
2415
+ await server.serveHTTP(port);
2416
+ console.log(`${icon.success} MCP server ${color.cyan(name)} running on http://localhost:${port}`);
2417
+ console.log(`${icon.info} Tools: ${server.getToolCount()}`);
2418
+ }
2419
+ else {
2420
+ console.error(`${icon.success} MCP server ${color.cyan(name)} (stdio) — ${server.getToolCount()} tools`);
2421
+ await server.serveStdio();
2422
+ }
2423
+ });
2145
2424
  //# sourceMappingURL=cli.js.map
@@ -6,6 +6,8 @@ import type { MCPTool } from '../tools/mcp';
6
6
  import { MCPToolRegistry } from '../tools/mcp';
7
7
  import { type SubAgentConfig, type SubAgentResult } from './subagent';
8
8
  import { Tracer } from '../telemetry';
9
+ import { type BrainSeedConfig } from '../memory/seed-loader';
10
+ import { GuardrailManager, type GuardrailConfig } from '../security/guardrails';
9
11
  export declare class BaseAgent extends EventEmitter implements IAgent {
10
12
  readonly name: string;
11
13
  private _state;
@@ -23,6 +25,9 @@ export declare class BaseAgent extends EventEmitter implements IAgent {
23
25
  private longTermMemory?;
24
26
  private longTermMemoryConfig;
25
27
  private tracer?;
28
+ private brainSeedConfig?;
29
+ private agentDir;
30
+ private guardrails?;
26
31
  constructor(options: {
27
32
  name: string;
28
33
  systemPrompt?: string;
@@ -38,11 +43,15 @@ export declare class BaseAgent extends EventEmitter implements IAgent {
38
43
  };
39
44
  maxToolRounds?: number;
40
45
  tracer?: Tracer;
46
+ agentDir?: string;
47
+ brainSeedConfig?: BrainSeedConfig;
41
48
  });
42
49
  setLongTermMemory(brain: any, config?: {
43
50
  autoLearn?: boolean;
44
51
  autoRecall?: boolean;
45
52
  }): void;
53
+ setGuardrails(config: GuardrailConfig): void;
54
+ getGuardrails(): GuardrailManager | undefined;
46
55
  getLongTermMemory(): any;
47
56
  getLongTermMemoryConfig(): {
48
57
  autoLearn: boolean;
@@ -7,6 +7,8 @@ const providers_1 = require("../providers");
7
7
  const auto_learn_1 = require("../skills/auto-learn");
8
8
  const mcp_1 = require("../tools/mcp");
9
9
  const subagent_1 = require("./subagent");
10
+ const seed_loader_1 = require("../memory/seed-loader");
11
+ const guardrails_1 = require("../security/guardrails");
10
12
  class BaseAgent extends events_1.EventEmitter {
11
13
  name;
12
14
  _state = 'init';
@@ -24,6 +26,9 @@ class BaseAgent extends events_1.EventEmitter {
24
26
  longTermMemory;
25
27
  longTermMemoryConfig = { autoLearn: true, autoRecall: true };
26
28
  tracer;
29
+ brainSeedConfig;
30
+ agentDir;
31
+ guardrails;
27
32
  constructor(options) {
28
33
  super();
29
34
  this.name = options.name;
@@ -41,6 +46,8 @@ class BaseAgent extends events_1.EventEmitter {
41
46
  this.skillLearner = new auto_learn_1.SkillLearner(options.skillsDir);
42
47
  }
43
48
  this.tracer = options.tracer;
49
+ this.agentDir = options.agentDir ?? process.cwd();
50
+ this.brainSeedConfig = options.brainSeedConfig;
44
51
  }
45
52
  setLongTermMemory(brain, config) {
46
53
  this.longTermMemory = brain;
@@ -51,6 +58,12 @@ class BaseAgent extends events_1.EventEmitter {
51
58
  };
52
59
  }
53
60
  }
61
+ setGuardrails(config) {
62
+ this.guardrails = new guardrails_1.GuardrailManager(config);
63
+ }
64
+ getGuardrails() {
65
+ return this.guardrails;
66
+ }
54
67
  getLongTermMemory() {
55
68
  return this.longTermMemory;
56
69
  }
@@ -93,6 +106,15 @@ class BaseAgent extends events_1.EventEmitter {
93
106
  if (this.skillLearner) {
94
107
  await this.skillLearner.loadLearnedSkills();
95
108
  }
109
+ // Auto-seed brain if configured
110
+ if (this.brainSeedConfig?.autoSeed && this.longTermMemory) {
111
+ const loader = new seed_loader_1.BrainSeedLoader(this.agentDir, this.brainSeedConfig);
112
+ if (!await loader.isSeeded()) {
113
+ const result = await loader.seedBrain(this.longTermMemory);
114
+ this.emit('brain:seeded', result);
115
+ await loader.markSeeded();
116
+ }
117
+ }
96
118
  this.transition('ready');
97
119
  }
98
120
  async start() {
@@ -149,6 +171,23 @@ class BaseAgent extends events_1.EventEmitter {
149
171
  }
150
172
  const sessionId = message.metadata?.sessionId ?? 'default';
151
173
  await this.memory.addMessage(sessionId, message);
174
+ // === Guardrails: check input ===
175
+ if (this.guardrails) {
176
+ const inputCheck = await this.guardrails.checkInput(message.content);
177
+ if (inputCheck.blocked) {
178
+ const blockedResponse = this.createResponse(inputCheck.message ?? 'Message blocked by guardrails.', message);
179
+ await this.memory.addMessage(sessionId, blockedResponse);
180
+ this.emit('message:out', blockedResponse);
181
+ if (rootSpan && this.tracer) {
182
+ this.tracer.addEvent(rootSpan, 'guardrail.blocked', { rule: inputCheck.violations[0]?.rule ?? 'unknown' });
183
+ this.tracer.endSpan(rootSpan, 'ok');
184
+ }
185
+ return blockedResponse;
186
+ }
187
+ if (inputCheck.redacted && inputCheck.redactedText) {
188
+ message = { ...message, content: inputCheck.redactedText };
189
+ }
190
+ }
152
191
  // === Recall from long-term memory ===
153
192
  let memoryContext = '';
154
193
  if (this.longTermMemory && this.longTermMemoryConfig.autoRecall) {
@@ -264,6 +303,16 @@ class BaseAgent extends events_1.EventEmitter {
264
303
  timestamp: Date.now(),
265
304
  });
266
305
  }
306
+ // === Guardrails: check output ===
307
+ if (this.guardrails) {
308
+ const outputCheck = await this.guardrails.checkOutput(finalResponse);
309
+ if (outputCheck.blocked) {
310
+ finalResponse = outputCheck.message ?? 'Response blocked by guardrails.';
311
+ }
312
+ else if (outputCheck.redacted && outputCheck.redactedText) {
313
+ finalResponse = outputCheck.redactedText;
314
+ }
315
+ }
267
316
  const response = this.createResponse(finalResponse, message);
268
317
  await this.memory.addMessage(sessionId, response);
269
318
  this.emit('message:out', response);
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Multi-agent collaboration patterns
3
+ * @module core/collaboration
4
+ */
5
+ import type { BaseAgent } from './agent';
6
+ import type { Message } from './types';
7
+ export interface DebateArgument {
8
+ agent: string;
9
+ round: number;
10
+ argument: string;
11
+ }
12
+ export interface DebateResult {
13
+ topic: string;
14
+ rounds: DebateArgument[];
15
+ summary: string;
16
+ judge?: string;
17
+ }
18
+ export interface VoteEntry {
19
+ agent: string;
20
+ choice: string;
21
+ confidence: number;
22
+ }
23
+ export interface VoteResult {
24
+ question: string;
25
+ votes: VoteEntry[];
26
+ winner: string;
27
+ tally: Record<string, number>;
28
+ }
29
+ export interface PipelineStageResult {
30
+ agent: string;
31
+ input: string;
32
+ output: string;
33
+ durationMs: number;
34
+ }
35
+ export interface PipelineResult {
36
+ stages: PipelineStageResult[];
37
+ finalOutput: string;
38
+ totalDurationMs: number;
39
+ }
40
+ export interface WorkerResult {
41
+ agent: string;
42
+ subtask: string;
43
+ result: string;
44
+ }
45
+ export interface HierarchyResult {
46
+ task: string;
47
+ subtasks: WorkerResult[];
48
+ synthesis: string;
49
+ }
50
+ export declare class DebatePattern {
51
+ private agents;
52
+ private rounds;
53
+ constructor(agents: BaseAgent[], rounds?: number);
54
+ debate(topic: string, judgeAgent?: BaseAgent): Promise<DebateResult>;
55
+ }
56
+ export declare class VotingPattern {
57
+ private agents;
58
+ constructor(agents: BaseAgent[]);
59
+ vote(question: string, options: string[]): Promise<VoteResult>;
60
+ weightedVote(question: string, options: string[]): Promise<VoteResult>;
61
+ private tallyVotes;
62
+ }
63
+ export declare class PipelinePattern {
64
+ private stages;
65
+ constructor(stages: {
66
+ agent: BaseAgent;
67
+ transform?: (input: string) => string;
68
+ }[]);
69
+ process(input: string): Promise<PipelineResult>;
70
+ }
71
+ export declare class HierarchyPattern {
72
+ private leader;
73
+ private workers;
74
+ constructor(leader: BaseAgent, workers: BaseAgent[]);
75
+ execute(task: string): Promise<HierarchyResult>;
76
+ }
77
+ export declare class SharedContext {
78
+ private store;
79
+ private listeners;
80
+ set(key: string, value: any): void;
81
+ get<T>(key: string): T | undefined;
82
+ getAll(): Record<string, any>;
83
+ onChange(key: string, callback: (value: any) => void): void;
84
+ }
85
+ export declare class ConversationProtocol {
86
+ roundRobin(agents: BaseAgent[], topic: string, rounds: number): Promise<Message[]>;
87
+ moderated(agents: BaseAgent[], moderator: BaseAgent, topic: string): Promise<Message[]>;
88
+ }
89
+ //# sourceMappingURL=collaboration.d.ts.map