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
@@ -1,9 +1,35 @@
1
1
  import { createServer, IncomingMessage, ServerResponse, request as httpRequest } from 'http';
2
- import { readFileSync, existsSync } from 'fs';
2
+ import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';
3
3
  import { join, extname } from 'path';
4
4
  import * as net from 'net';
5
5
  import { Tracer } from '../telemetry';
6
6
 
7
+ export interface WorkflowNode {
8
+ id: string;
9
+ type: 'agent' | 'tool' | 'condition' | 'loop' | 'parallel' | 'input' | 'output';
10
+ name: string;
11
+ x: number;
12
+ y: number;
13
+ config: Record<string, any>;
14
+ }
15
+
16
+ export interface WorkflowEdge {
17
+ id: string;
18
+ from: string;
19
+ to: string;
20
+ fromPort: string;
21
+ toPort: string;
22
+ }
23
+
24
+ export interface WorkflowDefinition {
25
+ id: string;
26
+ name: string;
27
+ nodes: WorkflowNode[];
28
+ edges: WorkflowEdge[];
29
+ created: string;
30
+ updated: string;
31
+ }
32
+
7
33
  interface StudioConfig {
8
34
  port: number;
9
35
  agentDir: string;
@@ -100,6 +126,29 @@ class StudioServer {
100
126
  try {
101
127
  let data: any;
102
128
 
129
+ // Dynamic workflow routes (parameterized)
130
+ if (route.match(/^workflows\/[^/]+\/run$/) && req.method === 'POST') {
131
+ const wfId = route.split('/')[1];
132
+ data = await this.runWorkflow(wfId);
133
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
134
+ res.end(JSON.stringify(data));
135
+ return;
136
+ }
137
+ if (route.match(/^workflows\/[^/]+$/) && req.method === 'GET') {
138
+ const wfId = route.split('/')[1];
139
+ data = this.getWorkflowById(wfId);
140
+ res.writeHead(data.error ? 404 : 200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
141
+ res.end(JSON.stringify(data));
142
+ return;
143
+ }
144
+ if (route.match(/^workflows\/[^/]+$/) && req.method === 'DELETE') {
145
+ const wfId = route.split('/')[1];
146
+ data = this.deleteWorkflow(wfId);
147
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
148
+ res.end(JSON.stringify(data));
149
+ return;
150
+ }
151
+
103
152
  switch (route) {
104
153
  case 'modules':
105
154
  data = await this.getModulesStatus();
@@ -130,7 +179,12 @@ class StudioServer {
130
179
  data = await this.getTools();
131
180
  break;
132
181
  case 'workflows/list':
133
- data = await this.getWorkflows();
182
+ data = this.listWorkflows();
183
+ break;
184
+ case 'workflows':
185
+ if (req.method === 'POST') data = await this.saveWorkflow(req);
186
+ else if (req.method === 'GET') data = this.listWorkflows();
187
+ else { res.writeHead(405); res.end(); return; }
134
188
  break;
135
189
  case 'jobs/list':
136
190
  data = await this.getJobs();
@@ -188,6 +242,14 @@ class StudioServer {
188
242
  case 'telemetry/metrics':
189
243
  data = this.tracer ? this.tracer.getMetrics() : [];
190
244
  break;
245
+ case 'playground/chat':
246
+ if (req.method === 'POST') {
247
+ return this.handlePlaygroundChat(req, res);
248
+ }
249
+ res.writeHead(405); res.end(); return;
250
+ case 'playground/models':
251
+ data = { models: ['gpt-4o', 'gpt-4o-mini', 'claude-sonnet-4', 'claude-haiku', 'gemini-2.0-flash', 'deepseek-v3'] };
252
+ break;
191
253
  default:
192
254
  res.writeHead(404, { 'Content-Type': 'application/json' });
193
255
  res.end(JSON.stringify({ error: 'Not found' }));
@@ -333,9 +395,84 @@ class StudioServer {
333
395
  }
334
396
  }
335
397
 
336
- private async getWorkflows() {
398
+ private getWorkflowsDir(): string {
399
+ const dir = join(this.config.agentDir, '.opc', 'workflows');
400
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
401
+ return dir;
402
+ }
403
+
404
+ private listWorkflows(): { workflows: WorkflowDefinition[] } {
405
+ const dir = this.getWorkflowsDir();
406
+ const files = require('fs').readdirSync(dir).filter((f: string) => f.endsWith('.json'));
407
+ const workflows = files.map((f: string) => {
408
+ try { return JSON.parse(readFileSync(join(dir, f), 'utf-8')); } catch { return null; }
409
+ }).filter(Boolean);
410
+ // Also include OAD-defined workflows
337
411
  const oad = this.loadOAD();
338
- return { workflows: oad?.spec?.workflows || [] };
412
+ const oadWorkflows = (oad?.spec?.workflows || []).map((w: any, i: number) => ({
413
+ id: `oad-${i}`,
414
+ name: w.name || `Workflow ${i + 1}`,
415
+ nodes: [],
416
+ edges: [],
417
+ steps: w.steps,
418
+ source: 'oad',
419
+ }));
420
+ return { workflows: [...workflows, ...oadWorkflows] };
421
+ }
422
+
423
+ private getWorkflowById(id: string): WorkflowDefinition | { error: string } {
424
+ const filePath = join(this.getWorkflowsDir(), `${id}.json`);
425
+ if (!existsSync(filePath)) return { error: 'Workflow not found' };
426
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
427
+ }
428
+
429
+ private async saveWorkflow(req: IncomingMessage): Promise<{ success: boolean; id: string }> {
430
+ const body = await this.readBody(req);
431
+ const workflow = JSON.parse(body) as WorkflowDefinition;
432
+ if (!workflow.id) workflow.id = `wf-${Date.now()}`;
433
+ workflow.updated = new Date().toISOString();
434
+ if (!workflow.created) workflow.created = workflow.updated;
435
+ const filePath = join(this.getWorkflowsDir(), `${workflow.id}.json`);
436
+ writeFileSync(filePath, JSON.stringify(workflow, null, 2));
437
+ return { success: true, id: workflow.id };
438
+ }
439
+
440
+ private deleteWorkflow(id: string): { success: boolean } {
441
+ const filePath = join(this.getWorkflowsDir(), `${id}.json`);
442
+ if (existsSync(filePath)) require('fs').unlinkSync(filePath);
443
+ return { success: true };
444
+ }
445
+
446
+ private async runWorkflow(id: string): Promise<any> {
447
+ const wf = this.getWorkflowById(id);
448
+ if ('error' in wf) return wf;
449
+ // Basic topological execution simulation
450
+ const results: Record<string, any> = {};
451
+ const sorted = this.topoSort(wf.nodes, wf.edges);
452
+ for (const node of sorted) {
453
+ results[node.id] = { type: node.type, name: node.name, status: 'completed', output: `[simulated output for ${node.name}]` };
454
+ }
455
+ return { workflowId: id, status: 'completed', results };
456
+ }
457
+
458
+ private topoSort(nodes: WorkflowNode[], edges: WorkflowEdge[]): WorkflowNode[] {
459
+ const nodeMap = new Map(nodes.map(n => [n.id, n]));
460
+ const inDegree = new Map<string, number>();
461
+ const adj = new Map<string, string[]>();
462
+ for (const n of nodes) { inDegree.set(n.id, 0); adj.set(n.id, []); }
463
+ for (const e of edges) { adj.get(e.from)?.push(e.to); inDegree.set(e.to, (inDegree.get(e.to) || 0) + 1); }
464
+ const queue = nodes.filter(n => (inDegree.get(n.id) || 0) === 0);
465
+ const result: WorkflowNode[] = [];
466
+ while (queue.length > 0) {
467
+ const node = queue.shift()!;
468
+ result.push(node);
469
+ for (const next of (adj.get(node.id) || [])) {
470
+ const d = (inDegree.get(next) || 1) - 1;
471
+ inDegree.set(next, d);
472
+ if (d === 0) queue.push(nodeMap.get(next)!);
473
+ }
474
+ }
475
+ return result;
339
476
  }
340
477
 
341
478
  private async getJobs() {
@@ -616,6 +753,31 @@ class StudioServer {
616
753
  res.end(content);
617
754
  }
618
755
 
756
+ private async handlePlaygroundChat(req: IncomingMessage, res: ServerResponse): Promise<void> {
757
+ const body = JSON.parse(await this.readBody(req));
758
+ const { messages = [], model = 'gpt-4o', temperature = 0.7, systemPrompt } = body;
759
+
760
+ res.writeHead(200, {
761
+ 'Content-Type': 'text/event-stream',
762
+ 'Cache-Control': 'no-cache',
763
+ 'Connection': 'keep-alive',
764
+ 'Access-Control-Allow-Origin': '*',
765
+ });
766
+
767
+ // Simulated streaming response for playground demo
768
+ const allMsgs = systemPrompt ? [{ role: 'system', content: systemPrompt }, ...messages] : messages;
769
+ const lastMsg = allMsgs[allMsgs.length - 1]?.content || '';
770
+ const response = `This is a playground demo response to: "${lastMsg}"\n\nModel: ${model}, Temperature: ${temperature}\nMessages in context: ${allMsgs.length}`;
771
+
772
+ const words = response.split(' ');
773
+ for (let i = 0; i < words.length; i++) {
774
+ const chunk = (i === 0 ? '' : ' ') + words[i];
775
+ res.write(`data: ${JSON.stringify({ content: chunk })}\n\n`);
776
+ }
777
+ res.write('data: [DONE]\n\n');
778
+ res.end();
779
+ }
780
+
619
781
  private readBody(req: IncomingMessage): Promise<string> {
620
782
  return new Promise((resolve, reject) => {
621
783
  let body = '';