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.
- package/README.md +603 -545
- package/dist/channels/voice.d.ts +59 -0
- package/dist/channels/voice.js +351 -1
- package/dist/cli.js +284 -5
- package/dist/core/agent.d.ts +9 -0
- package/dist/core/agent.js +49 -0
- package/dist/core/collaboration.d.ts +89 -0
- package/dist/core/collaboration.js +201 -0
- package/dist/deploy/index.d.ts +40 -0
- package/dist/deploy/index.js +261 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +47 -3
- package/dist/mcp/servers/calculator-mcp.d.ts +3 -0
- package/dist/mcp/servers/calculator-mcp.js +65 -0
- package/dist/mcp/servers/crypto-mcp.d.ts +3 -0
- package/dist/mcp/servers/crypto-mcp.js +108 -0
- package/dist/mcp/servers/database-mcp.d.ts +3 -0
- package/dist/mcp/servers/database-mcp.js +73 -0
- package/dist/mcp/servers/datetime-mcp.d.ts +3 -0
- package/dist/mcp/servers/datetime-mcp.js +71 -0
- package/dist/mcp/servers/filesystem.d.ts +3 -0
- package/dist/mcp/servers/filesystem.js +101 -0
- package/dist/mcp/servers/github-mcp.d.ts +3 -0
- package/dist/mcp/servers/github-mcp.js +60 -0
- package/dist/mcp/servers/index.d.ts +21 -0
- package/dist/mcp/servers/index.js +50 -0
- package/dist/mcp/servers/json-mcp.d.ts +3 -0
- package/dist/mcp/servers/json-mcp.js +126 -0
- package/dist/mcp/servers/memory-mcp.d.ts +3 -0
- package/dist/mcp/servers/memory-mcp.js +60 -0
- package/dist/mcp/servers/regex-mcp.d.ts +3 -0
- package/dist/mcp/servers/regex-mcp.js +56 -0
- package/dist/mcp/servers/web-mcp.d.ts +3 -0
- package/dist/mcp/servers/web-mcp.js +51 -0
- package/dist/memory/index.d.ts +2 -0
- package/dist/memory/index.js +4 -1
- package/dist/memory/seed-loader.d.ts +51 -0
- package/dist/memory/seed-loader.js +200 -0
- package/dist/schema/oad.d.ts +292 -12
- package/dist/schema/oad.js +12 -1
- package/dist/security/guardrails.d.ts +50 -0
- package/dist/security/guardrails.js +197 -0
- package/dist/studio/server.d.ts +31 -1
- package/dist/studio/server.js +154 -3
- package/dist/studio-ui/index.html +1278 -662
- package/dist/tools/integrations/calendar.d.ts +3 -0
- package/dist/tools/integrations/calendar.js +73 -0
- package/dist/tools/integrations/code-exec.d.ts +3 -0
- package/dist/tools/integrations/code-exec.js +42 -0
- package/dist/tools/integrations/csv-analyzer.d.ts +3 -0
- package/dist/tools/integrations/csv-analyzer.js +142 -0
- package/dist/tools/integrations/database.d.ts +3 -0
- package/dist/tools/integrations/database.js +44 -0
- package/dist/tools/integrations/email-send.d.ts +3 -0
- package/dist/tools/integrations/email-send.js +104 -0
- package/dist/tools/integrations/git-tool.d.ts +3 -0
- package/dist/tools/integrations/git-tool.js +49 -0
- package/dist/tools/integrations/github-tool.d.ts +3 -0
- package/dist/tools/integrations/github-tool.js +77 -0
- package/dist/tools/integrations/image-gen.d.ts +3 -0
- package/dist/tools/integrations/image-gen.js +58 -0
- package/dist/tools/integrations/index.d.ts +30 -0
- package/dist/tools/integrations/index.js +107 -0
- package/dist/tools/integrations/jira.d.ts +3 -0
- package/dist/tools/integrations/jira.js +85 -0
- package/dist/tools/integrations/notion.d.ts +3 -0
- package/dist/tools/integrations/notion.js +71 -0
- package/dist/tools/integrations/npm-tool.d.ts +3 -0
- package/dist/tools/integrations/npm-tool.js +49 -0
- package/dist/tools/integrations/pdf-reader.d.ts +3 -0
- package/dist/tools/integrations/pdf-reader.js +91 -0
- package/dist/tools/integrations/slack.d.ts +3 -0
- package/dist/tools/integrations/slack.js +67 -0
- package/dist/tools/integrations/summarizer.d.ts +3 -0
- package/dist/tools/integrations/summarizer.js +49 -0
- package/dist/tools/integrations/translator.d.ts +3 -0
- package/dist/tools/integrations/translator.js +48 -0
- package/dist/tools/integrations/trello.d.ts +3 -0
- package/dist/tools/integrations/trello.js +60 -0
- package/dist/tools/integrations/vector-search.d.ts +3 -0
- package/dist/tools/integrations/vector-search.js +44 -0
- package/dist/tools/integrations/web-scraper.d.ts +3 -0
- package/dist/tools/integrations/web-scraper.js +48 -0
- package/dist/tools/integrations/web-search.d.ts +3 -0
- package/dist/tools/integrations/web-search.js +60 -0
- package/dist/tools/integrations/webhook.d.ts +3 -0
- package/dist/tools/integrations/webhook.js +39 -0
- package/dist/ui/components.d.ts +10 -0
- package/dist/ui/components.js +123 -0
- package/package.json +1 -1
- package/src/channels/voice.ts +365 -0
- package/src/cli.ts +294 -6
- package/src/core/agent.ts +56 -0
- package/src/core/collaboration.ts +275 -0
- package/src/deploy/index.ts +255 -0
- package/src/index.ts +21 -1
- package/src/mcp/servers/calculator-mcp.ts +65 -0
- package/src/mcp/servers/crypto-mcp.ts +73 -0
- package/src/mcp/servers/database-mcp.ts +72 -0
- package/src/mcp/servers/datetime-mcp.ts +69 -0
- package/src/mcp/servers/filesystem.ts +66 -0
- package/src/mcp/servers/github-mcp.ts +58 -0
- package/src/mcp/servers/index.ts +63 -0
- package/src/mcp/servers/json-mcp.ts +102 -0
- package/src/mcp/servers/memory-mcp.ts +56 -0
- package/src/mcp/servers/regex-mcp.ts +53 -0
- package/src/mcp/servers/web-mcp.ts +49 -0
- package/src/memory/index.ts +3 -0
- package/src/memory/seed-loader.ts +212 -0
- package/src/schema/oad.ts +13 -0
- package/src/security/guardrails.ts +248 -0
- package/src/studio/server.ts +166 -4
- package/src/studio-ui/index.html +1278 -662
- package/src/tools/integrations/calendar.ts +73 -0
- package/src/tools/integrations/code-exec.ts +39 -0
- package/src/tools/integrations/csv-analyzer.ts +92 -0
- package/src/tools/integrations/database.ts +44 -0
- package/src/tools/integrations/email-send.ts +76 -0
- package/src/tools/integrations/git-tool.ts +42 -0
- package/src/tools/integrations/github-tool.ts +76 -0
- package/src/tools/integrations/image-gen.ts +56 -0
- package/src/tools/integrations/index.ts +92 -0
- package/src/tools/integrations/jira.ts +83 -0
- package/src/tools/integrations/notion.ts +71 -0
- package/src/tools/integrations/npm-tool.ts +48 -0
- package/src/tools/integrations/pdf-reader.ts +58 -0
- package/src/tools/integrations/slack.ts +65 -0
- package/src/tools/integrations/summarizer.ts +49 -0
- package/src/tools/integrations/translator.ts +48 -0
- package/src/tools/integrations/trello.ts +60 -0
- package/src/tools/integrations/vector-search.ts +42 -0
- package/src/tools/integrations/web-scraper.ts +47 -0
- package/src/tools/integrations/web-search.ts +58 -0
- package/src/tools/integrations/webhook.ts +38 -0
- package/src/ui/components.ts +127 -0
- package/tests/brain-seed-extended.test.ts +490 -0
- package/tests/brain-seed.test.ts +239 -0
- package/tests/collaboration.test.ts +319 -0
- package/tests/deploy-and-dag.test.ts +196 -0
- package/tests/guardrails.test.ts +177 -0
- package/tests/integrations.test.ts +249 -0
- package/tests/mcp-servers.test.ts +260 -0
- package/tests/voice-enhanced.test.ts +169 -0
- package/dist/dtv/data.d.ts +0 -18
- package/dist/dtv/data.js +0 -25
- package/dist/dtv/trust.d.ts +0 -19
- package/dist/dtv/trust.js +0 -40
- package/dist/dtv/value.d.ts +0 -23
- package/dist/dtv/value.js +0 -38
- package/dist/marketplace/index.d.ts +0 -34
- 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
|
-
//
|
|
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('
|
|
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
|
package/dist/core/agent.d.ts
CHANGED
|
@@ -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;
|
package/dist/core/agent.js
CHANGED
|
@@ -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
|