opc-agent 1.3.2 → 2.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 (226) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  4. package/.github/workflows/ci.yml +24 -0
  5. package/CHANGELOG.md +48 -63
  6. package/CONTRIBUTING.md +21 -60
  7. package/README.md +284 -348
  8. package/README.zh-CN.md +415 -415
  9. package/dist/channels/slack.js +93 -10
  10. package/dist/channels/telegram.d.ts +30 -9
  11. package/dist/channels/telegram.js +125 -33
  12. package/dist/channels/web.d.ts +10 -0
  13. package/dist/channels/web.js +33 -2
  14. package/dist/cli.js +667 -65
  15. package/dist/core/agent.d.ts +23 -0
  16. package/dist/core/agent.js +120 -3
  17. package/dist/core/runtime.d.ts +5 -0
  18. package/dist/core/runtime.js +71 -0
  19. package/dist/core/scheduler.d.ts +52 -0
  20. package/dist/core/scheduler.js +168 -0
  21. package/dist/core/subagent.d.ts +28 -0
  22. package/dist/core/subagent.js +65 -0
  23. package/dist/daemon.d.ts +3 -0
  24. package/dist/daemon.js +134 -0
  25. package/dist/deploy/hermes.js +22 -22
  26. package/dist/deploy/openclaw.js +31 -40
  27. package/dist/index.d.ts +10 -10
  28. package/dist/index.js +22 -15
  29. package/dist/providers/index.d.ts +6 -2
  30. package/dist/providers/index.js +22 -9
  31. package/dist/schema/oad.d.ts +180 -6
  32. package/dist/schema/oad.js +12 -1
  33. package/dist/skills/auto-learn.d.ts +28 -0
  34. package/dist/skills/auto-learn.js +257 -0
  35. package/dist/templates/code-reviewer.d.ts +0 -8
  36. package/dist/templates/code-reviewer.js +5 -9
  37. package/dist/templates/customer-service.d.ts +0 -8
  38. package/dist/templates/customer-service.js +2 -6
  39. package/dist/templates/data-analyst.d.ts +0 -8
  40. package/dist/templates/data-analyst.js +5 -9
  41. package/dist/templates/knowledge-base.d.ts +0 -8
  42. package/dist/templates/knowledge-base.js +2 -6
  43. package/dist/templates/sales-assistant.d.ts +0 -8
  44. package/dist/templates/sales-assistant.js +4 -8
  45. package/dist/templates/teacher.d.ts +0 -8
  46. package/dist/templates/teacher.js +6 -10
  47. package/dist/tools/builtin/datetime.d.ts +3 -0
  48. package/dist/tools/builtin/datetime.js +44 -0
  49. package/dist/tools/builtin/file.d.ts +3 -0
  50. package/dist/tools/builtin/file.js +151 -0
  51. package/dist/tools/builtin/index.d.ts +15 -0
  52. package/dist/tools/builtin/index.js +30 -0
  53. package/dist/tools/builtin/shell.d.ts +3 -0
  54. package/dist/tools/builtin/shell.js +43 -0
  55. package/dist/tools/builtin/web.d.ts +3 -0
  56. package/dist/tools/builtin/web.js +37 -0
  57. package/dist/tools/mcp-client.d.ts +24 -0
  58. package/dist/tools/mcp-client.js +119 -0
  59. package/dist/traces/index.d.ts +49 -0
  60. package/dist/traces/index.js +102 -0
  61. package/docs/.vitepress/config.ts +103 -103
  62. package/docs/api/cli.md +48 -48
  63. package/docs/api/oad-schema.md +64 -64
  64. package/docs/api/sdk.md +80 -80
  65. package/docs/guide/concepts.md +51 -51
  66. package/docs/guide/configuration.md +79 -79
  67. package/docs/guide/deployment.md +42 -42
  68. package/docs/guide/getting-started.md +44 -44
  69. package/docs/guide/templates.md +28 -28
  70. package/docs/guide/testing.md +84 -84
  71. package/docs/index.md +27 -27
  72. package/docs/zh/api/cli.md +54 -54
  73. package/docs/zh/api/oad-schema.md +87 -87
  74. package/docs/zh/api/sdk.md +102 -102
  75. package/docs/zh/guide/concepts.md +104 -104
  76. package/docs/zh/guide/configuration.md +135 -135
  77. package/docs/zh/guide/deployment.md +81 -81
  78. package/docs/zh/guide/getting-started.md +82 -82
  79. package/docs/zh/guide/templates.md +84 -84
  80. package/docs/zh/guide/testing.md +88 -88
  81. package/docs/zh/index.md +27 -27
  82. package/examples/README.md +22 -0
  83. package/examples/basic-agent.ts +90 -0
  84. package/examples/brain-integration.ts +71 -0
  85. package/examples/customer-service-demo/README.md +90 -90
  86. package/examples/customer-service-demo/oad.yaml +107 -107
  87. package/examples/multi-channel.ts +74 -0
  88. package/package.json +1 -1
  89. package/src/analytics/index.ts +66 -66
  90. package/src/channels/discord.ts +192 -192
  91. package/src/channels/email.ts +177 -177
  92. package/src/channels/feishu.ts +236 -236
  93. package/src/channels/index.ts +15 -15
  94. package/src/channels/slack.ts +217 -160
  95. package/src/channels/telegram.ts +155 -33
  96. package/src/channels/voice.ts +106 -106
  97. package/src/channels/web.ts +38 -2
  98. package/src/channels/webhook.ts +199 -199
  99. package/src/channels/websocket.ts +87 -87
  100. package/src/channels/wechat.ts +149 -149
  101. package/src/cli.ts +697 -63
  102. package/src/core/a2a.ts +143 -143
  103. package/src/core/agent.ts +146 -3
  104. package/src/core/analytics-engine.ts +186 -186
  105. package/src/core/auth.ts +57 -57
  106. package/src/core/cache.ts +141 -141
  107. package/src/core/compose.ts +77 -77
  108. package/src/core/config.ts +14 -14
  109. package/src/core/errors.ts +148 -148
  110. package/src/core/hitl.ts +138 -138
  111. package/src/core/logger.ts +57 -57
  112. package/src/core/orchestrator.ts +215 -215
  113. package/src/core/performance.ts +187 -187
  114. package/src/core/rate-limiter.ts +128 -128
  115. package/src/core/room.ts +109 -109
  116. package/src/core/runtime.ts +230 -152
  117. package/src/core/sandbox.ts +101 -101
  118. package/src/core/scheduler.ts +187 -0
  119. package/src/core/security.ts +171 -171
  120. package/src/core/subagent.ts +98 -0
  121. package/src/core/types.ts +68 -68
  122. package/src/core/versioning.ts +106 -106
  123. package/src/core/watch.ts +178 -178
  124. package/src/core/workflow.ts +235 -235
  125. package/src/daemon.ts +96 -0
  126. package/src/deploy/hermes.ts +156 -156
  127. package/src/deploy/openclaw.ts +190 -200
  128. package/src/i18n/index.ts +216 -216
  129. package/src/index.ts +14 -10
  130. package/src/memory/deepbrain.ts +108 -108
  131. package/src/memory/index.ts +34 -34
  132. package/src/plugins/index.ts +208 -208
  133. package/src/providers/index.ts +354 -331
  134. package/src/schema/oad.ts +14 -2
  135. package/src/skills/auto-learn.ts +262 -0
  136. package/src/skills/base.ts +16 -16
  137. package/src/skills/document.ts +100 -100
  138. package/src/skills/http.ts +35 -35
  139. package/src/skills/index.ts +27 -27
  140. package/src/skills/scheduler.ts +80 -80
  141. package/src/skills/webhook-trigger.ts +59 -59
  142. package/src/templates/code-reviewer.ts +30 -34
  143. package/src/templates/customer-service.ts +76 -80
  144. package/src/templates/data-analyst.ts +66 -70
  145. package/src/templates/executive-assistant.ts +71 -71
  146. package/src/templates/financial-advisor.ts +60 -60
  147. package/src/templates/knowledge-base.ts +27 -31
  148. package/src/templates/legal-assistant.ts +71 -71
  149. package/src/templates/sales-assistant.ts +75 -79
  150. package/src/templates/teacher.ts +75 -79
  151. package/src/testing/index.ts +181 -181
  152. package/src/tools/builtin/datetime.ts +41 -0
  153. package/src/tools/builtin/file.ts +107 -0
  154. package/src/tools/builtin/index.ts +28 -0
  155. package/src/tools/builtin/shell.ts +43 -0
  156. package/src/tools/builtin/web.ts +35 -0
  157. package/src/tools/calculator.ts +73 -73
  158. package/src/tools/datetime.ts +149 -149
  159. package/src/tools/json-transform.ts +187 -187
  160. package/src/tools/mcp-client.ts +131 -0
  161. package/src/tools/mcp.ts +76 -76
  162. package/src/tools/text-analysis.ts +116 -116
  163. package/src/traces/index.ts +132 -0
  164. package/templates/Dockerfile +15 -15
  165. package/templates/code-reviewer/README.md +27 -27
  166. package/templates/code-reviewer/oad.yaml +41 -41
  167. package/templates/customer-service/README.md +22 -22
  168. package/templates/customer-service/oad.yaml +36 -36
  169. package/templates/docker-compose.yml +21 -21
  170. package/templates/ecommerce-assistant/README.md +45 -45
  171. package/templates/ecommerce-assistant/oad.yaml +47 -47
  172. package/templates/knowledge-base/README.md +28 -28
  173. package/templates/knowledge-base/oad.yaml +38 -38
  174. package/templates/sales-assistant/README.md +26 -26
  175. package/templates/sales-assistant/oad.yaml +43 -43
  176. package/templates/tech-support/README.md +43 -43
  177. package/templates/tech-support/oad.yaml +45 -45
  178. package/test-agent/Dockerfile +9 -0
  179. package/test-agent/README.md +50 -0
  180. package/test-agent/agent.yaml +23 -0
  181. package/test-agent/docker-compose.yml +11 -0
  182. package/test-agent/oad.yaml +31 -0
  183. package/test-agent/package-lock.json +1492 -0
  184. package/test-agent/package.json +18 -0
  185. package/test-agent/src/index.ts +24 -0
  186. package/test-agent/src/skills/echo.ts +15 -0
  187. package/test-agent/tsconfig.json +25 -0
  188. package/tests/a2a.test.ts +66 -66
  189. package/tests/agent.test.ts +72 -72
  190. package/tests/analytics.test.ts +50 -50
  191. package/tests/auto-learn.test.ts +105 -0
  192. package/tests/builtin-tools.test.ts +83 -0
  193. package/tests/channel.test.ts +39 -39
  194. package/tests/cli.test.ts +46 -0
  195. package/tests/e2e.test.ts +134 -134
  196. package/tests/errors.test.ts +83 -83
  197. package/tests/hitl.test.ts +71 -71
  198. package/tests/i18n.test.ts +41 -41
  199. package/tests/mcp.test.ts +54 -54
  200. package/tests/oad.test.ts +68 -68
  201. package/tests/performance.test.ts +115 -115
  202. package/tests/plugin.test.ts +74 -74
  203. package/tests/room.test.ts +106 -106
  204. package/tests/runtime.test.ts +42 -42
  205. package/tests/sandbox.test.ts +46 -46
  206. package/tests/security.test.ts +60 -60
  207. package/tests/subagent.test.ts +130 -0
  208. package/tests/telegram-discord.test.ts +60 -0
  209. package/tests/templates.test.ts +77 -77
  210. package/tests/v070.test.ts +76 -76
  211. package/tests/versioning.test.ts +75 -75
  212. package/tests/voice.test.ts +61 -61
  213. package/tests/webhook.test.ts +29 -29
  214. package/tests/workflow.test.ts +143 -143
  215. package/tsconfig.json +19 -19
  216. package/vitest.config.ts +9 -9
  217. package/dist/core/dashboard.d.ts +0 -35
  218. package/dist/core/dashboard.js +0 -157
  219. package/dist/core/priority.d.ts +0 -52
  220. package/dist/core/priority.js +0 -102
  221. package/src/core/dashboard.ts +0 -219
  222. package/src/core/priority.ts +0 -140
  223. package/src/dtv/data.ts +0 -29
  224. package/src/dtv/trust.ts +0 -43
  225. package/src/dtv/value.ts +0 -47
  226. package/src/marketplace/index.ts +0 -223
@@ -1,116 +1,116 @@
1
- import type { MCPTool, MCPToolResult } from './mcp';
2
-
3
- /**
4
- * Text Analysis Tool — v0.8.0
5
- * Summarize, translate (stub), sentiment analysis as an LLM function tool.
6
- * Note: For production, connect to actual LLM/NLP APIs. This provides basic built-in analysis.
7
- */
8
- export const TextAnalysisTool: MCPTool = {
9
- name: 'text_analysis',
10
- description: 'Analyze text: word count, character count, reading time, keyword extraction, basic sentiment, and language detection.',
11
- inputSchema: {
12
- type: 'object',
13
- properties: {
14
- operation: {
15
- type: 'string',
16
- enum: ['stats', 'keywords', 'sentiment', 'detect_language', 'truncate', 'split_sentences'],
17
- description: 'Analysis operation to perform',
18
- },
19
- text: {
20
- type: 'string',
21
- description: 'Text to analyze',
22
- },
23
- maxLength: {
24
- type: 'number',
25
- description: 'Max length for truncate operation',
26
- },
27
- topN: {
28
- type: 'number',
29
- description: 'Number of top keywords to extract (default: 10)',
30
- },
31
- },
32
- required: ['operation', 'text'],
33
- },
34
-
35
- async execute(input: Record<string, unknown>): Promise<MCPToolResult> {
36
- try {
37
- const op = String(input.operation);
38
- const text = String(input.text ?? '');
39
-
40
- switch (op) {
41
- case 'stats': {
42
- const words = text.split(/\s+/).filter(Boolean);
43
- const sentences = text.split(/[.!?。!?]+/).filter(Boolean);
44
- const readingTimeMin = Math.ceil(words.length / 200);
45
- return {
46
- content: JSON.stringify({
47
- characters: text.length,
48
- words: words.length,
49
- sentences: sentences.length,
50
- paragraphs: text.split(/\n\s*\n/).filter(Boolean).length,
51
- readingTimeMinutes: readingTimeMin,
52
- }, null, 2),
53
- };
54
- }
55
-
56
- case 'keywords': {
57
- const topN = Number(input.topN ?? 10);
58
- const words = text.toLowerCase().replace(/[^\w\s\u4e00-\u9fff]/g, '').split(/\s+/).filter(Boolean);
59
- const stopWords = new Set(['the', 'a', 'an', 'is', 'are', 'was', 'were', 'in', 'on', 'at', 'to', 'for', 'of', 'and', 'or', 'but', 'not', 'with', 'this', 'that', 'it', 'be', 'has', 'have', 'had', 'do', 'does', 'did', 'will', 'would', 'can', 'could', 'should', 'may', 'might', 'from', 'by', 'as', 'if', 'so', 'than']);
60
- const freq: Record<string, number> = {};
61
- for (const w of words) {
62
- if (w.length < 2 || stopWords.has(w)) continue;
63
- freq[w] = (freq[w] ?? 0) + 1;
64
- }
65
- const sorted = Object.entries(freq).sort((a, b) => b[1] - a[1]).slice(0, topN);
66
- return { content: JSON.stringify(sorted.map(([word, count]) => ({ word, count })), null, 2) };
67
- }
68
-
69
- case 'sentiment': {
70
- // Basic lexicon-based sentiment
71
- const positiveWords = new Set(['good', 'great', 'excellent', 'amazing', 'wonderful', 'fantastic', 'love', 'happy', 'best', 'awesome', 'perfect', 'brilliant', 'outstanding', 'superb', 'beautiful', 'nice', 'enjoy', 'like', 'positive', 'success']);
72
- const negativeWords = new Set(['bad', 'terrible', 'awful', 'horrible', 'hate', 'worst', 'poor', 'ugly', 'fail', 'wrong', 'sad', 'angry', 'frustrating', 'disappointing', 'negative', 'annoying', 'broken', 'useless', 'boring', 'painful']);
73
-
74
- const words = text.toLowerCase().split(/\s+/);
75
- let pos = 0, neg = 0;
76
- for (const w of words) {
77
- if (positiveWords.has(w)) pos++;
78
- if (negativeWords.has(w)) neg++;
79
- }
80
- const total = pos + neg || 1;
81
- const score = (pos - neg) / total; // -1 to 1
82
- const label = score > 0.1 ? 'positive' : score < -0.1 ? 'negative' : 'neutral';
83
- return {
84
- content: JSON.stringify({ score: Math.round(score * 100) / 100, label, positive: pos, negative: neg }, null, 2),
85
- };
86
- }
87
-
88
- case 'detect_language': {
89
- // Simple heuristic
90
- const hasChinese = /[\u4e00-\u9fff]/.test(text);
91
- const hasJapanese = /[\u3040-\u309f\u30a0-\u30ff]/.test(text);
92
- const hasKorean = /[\uac00-\ud7af]/.test(text);
93
- const hasArabic = /[\u0600-\u06ff]/.test(text);
94
- const lang = hasChinese ? 'zh' : hasJapanese ? 'ja' : hasKorean ? 'ko' : hasArabic ? 'ar' : 'en';
95
- return { content: JSON.stringify({ detected: lang, confidence: 'heuristic' }) };
96
- }
97
-
98
- case 'truncate': {
99
- const maxLen = Number(input.maxLength ?? 100);
100
- const truncated = text.length > maxLen ? text.slice(0, maxLen) + '...' : text;
101
- return { content: truncated };
102
- }
103
-
104
- case 'split_sentences': {
105
- const sentences = text.match(/[^.!?。!?]+[.!?。!?]+/g) ?? [text];
106
- return { content: JSON.stringify(sentences.map((s) => s.trim()), null, 2) };
107
- }
108
-
109
- default:
110
- return { content: `Unknown operation: ${op}`, isError: true };
111
- }
112
- } catch (err) {
113
- return { content: `Error: ${(err as Error).message}`, isError: true };
114
- }
115
- },
116
- };
1
+ import type { MCPTool, MCPToolResult } from './mcp';
2
+
3
+ /**
4
+ * Text Analysis Tool — v0.8.0
5
+ * Summarize, translate (stub), sentiment analysis as an LLM function tool.
6
+ * Note: For production, connect to actual LLM/NLP APIs. This provides basic built-in analysis.
7
+ */
8
+ export const TextAnalysisTool: MCPTool = {
9
+ name: 'text_analysis',
10
+ description: 'Analyze text: word count, character count, reading time, keyword extraction, basic sentiment, and language detection.',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {
14
+ operation: {
15
+ type: 'string',
16
+ enum: ['stats', 'keywords', 'sentiment', 'detect_language', 'truncate', 'split_sentences'],
17
+ description: 'Analysis operation to perform',
18
+ },
19
+ text: {
20
+ type: 'string',
21
+ description: 'Text to analyze',
22
+ },
23
+ maxLength: {
24
+ type: 'number',
25
+ description: 'Max length for truncate operation',
26
+ },
27
+ topN: {
28
+ type: 'number',
29
+ description: 'Number of top keywords to extract (default: 10)',
30
+ },
31
+ },
32
+ required: ['operation', 'text'],
33
+ },
34
+
35
+ async execute(input: Record<string, unknown>): Promise<MCPToolResult> {
36
+ try {
37
+ const op = String(input.operation);
38
+ const text = String(input.text ?? '');
39
+
40
+ switch (op) {
41
+ case 'stats': {
42
+ const words = text.split(/\s+/).filter(Boolean);
43
+ const sentences = text.split(/[.!?。!?]+/).filter(Boolean);
44
+ const readingTimeMin = Math.ceil(words.length / 200);
45
+ return {
46
+ content: JSON.stringify({
47
+ characters: text.length,
48
+ words: words.length,
49
+ sentences: sentences.length,
50
+ paragraphs: text.split(/\n\s*\n/).filter(Boolean).length,
51
+ readingTimeMinutes: readingTimeMin,
52
+ }, null, 2),
53
+ };
54
+ }
55
+
56
+ case 'keywords': {
57
+ const topN = Number(input.topN ?? 10);
58
+ const words = text.toLowerCase().replace(/[^\w\s\u4e00-\u9fff]/g, '').split(/\s+/).filter(Boolean);
59
+ const stopWords = new Set(['the', 'a', 'an', 'is', 'are', 'was', 'were', 'in', 'on', 'at', 'to', 'for', 'of', 'and', 'or', 'but', 'not', 'with', 'this', 'that', 'it', 'be', 'has', 'have', 'had', 'do', 'does', 'did', 'will', 'would', 'can', 'could', 'should', 'may', 'might', 'from', 'by', 'as', 'if', 'so', 'than']);
60
+ const freq: Record<string, number> = {};
61
+ for (const w of words) {
62
+ if (w.length < 2 || stopWords.has(w)) continue;
63
+ freq[w] = (freq[w] ?? 0) + 1;
64
+ }
65
+ const sorted = Object.entries(freq).sort((a, b) => b[1] - a[1]).slice(0, topN);
66
+ return { content: JSON.stringify(sorted.map(([word, count]) => ({ word, count })), null, 2) };
67
+ }
68
+
69
+ case 'sentiment': {
70
+ // Basic lexicon-based sentiment
71
+ const positiveWords = new Set(['good', 'great', 'excellent', 'amazing', 'wonderful', 'fantastic', 'love', 'happy', 'best', 'awesome', 'perfect', 'brilliant', 'outstanding', 'superb', 'beautiful', 'nice', 'enjoy', 'like', 'positive', 'success']);
72
+ const negativeWords = new Set(['bad', 'terrible', 'awful', 'horrible', 'hate', 'worst', 'poor', 'ugly', 'fail', 'wrong', 'sad', 'angry', 'frustrating', 'disappointing', 'negative', 'annoying', 'broken', 'useless', 'boring', 'painful']);
73
+
74
+ const words = text.toLowerCase().split(/\s+/);
75
+ let pos = 0, neg = 0;
76
+ for (const w of words) {
77
+ if (positiveWords.has(w)) pos++;
78
+ if (negativeWords.has(w)) neg++;
79
+ }
80
+ const total = pos + neg || 1;
81
+ const score = (pos - neg) / total; // -1 to 1
82
+ const label = score > 0.1 ? 'positive' : score < -0.1 ? 'negative' : 'neutral';
83
+ return {
84
+ content: JSON.stringify({ score: Math.round(score * 100) / 100, label, positive: pos, negative: neg }, null, 2),
85
+ };
86
+ }
87
+
88
+ case 'detect_language': {
89
+ // Simple heuristic
90
+ const hasChinese = /[\u4e00-\u9fff]/.test(text);
91
+ const hasJapanese = /[\u3040-\u309f\u30a0-\u30ff]/.test(text);
92
+ const hasKorean = /[\uac00-\ud7af]/.test(text);
93
+ const hasArabic = /[\u0600-\u06ff]/.test(text);
94
+ const lang = hasChinese ? 'zh' : hasJapanese ? 'ja' : hasKorean ? 'ko' : hasArabic ? 'ar' : 'en';
95
+ return { content: JSON.stringify({ detected: lang, confidence: 'heuristic' }) };
96
+ }
97
+
98
+ case 'truncate': {
99
+ const maxLen = Number(input.maxLength ?? 100);
100
+ const truncated = text.length > maxLen ? text.slice(0, maxLen) + '...' : text;
101
+ return { content: truncated };
102
+ }
103
+
104
+ case 'split_sentences': {
105
+ const sentences = text.match(/[^.!?。!?]+[.!?。!?]+/g) ?? [text];
106
+ return { content: JSON.stringify(sentences.map((s) => s.trim()), null, 2) };
107
+ }
108
+
109
+ default:
110
+ return { content: `Unknown operation: ${op}`, isError: true };
111
+ }
112
+ } catch (err) {
113
+ return { content: `Error: ${(err as Error).message}`, isError: true };
114
+ }
115
+ },
116
+ };
@@ -0,0 +1,132 @@
1
+ /**
2
+ * OPC Agent Traces — Structured logging for agent actions.
3
+ *
4
+ * Collects traces that can be fed to DeepBrain's learn() API.
5
+ * Inspired by OpenTelemetry spans.
6
+ */
7
+
8
+ export interface Span {
9
+ traceId: string;
10
+ spanId: string;
11
+ name: string;
12
+ startTime: Date;
13
+ endTime?: Date;
14
+ attributes: Record<string, string | number | boolean>;
15
+ events: SpanEvent[];
16
+ status: 'ok' | 'error' | 'unset';
17
+ }
18
+
19
+ export interface SpanEvent {
20
+ name: string;
21
+ timestamp: Date;
22
+ attributes?: Record<string, string | number | boolean>;
23
+ }
24
+
25
+ export interface TraceExporter {
26
+ export(spans: Span[]): Promise<void>;
27
+ }
28
+
29
+ /** In-memory buffer that holds spans until flushed */
30
+ export class TraceCollector {
31
+ private spans: Span[] = [];
32
+ private exporters: TraceExporter[] = [];
33
+ private maxBufferSize: number;
34
+
35
+ constructor(maxBufferSize = 100) {
36
+ this.maxBufferSize = maxBufferSize;
37
+ }
38
+
39
+ addExporter(exporter: TraceExporter): void {
40
+ this.exporters.push(exporter);
41
+ }
42
+
43
+ startSpan(name: string, attributes: Record<string, string | number | boolean> = {}): Span {
44
+ const span: Span = {
45
+ traceId: crypto.randomUUID(),
46
+ spanId: crypto.randomUUID().slice(0, 16),
47
+ name,
48
+ startTime: new Date(),
49
+ attributes,
50
+ events: [],
51
+ status: 'unset',
52
+ };
53
+ this.spans.push(span);
54
+
55
+ if (this.spans.length >= this.maxBufferSize) {
56
+ this.flush().catch(() => {}); // Best effort
57
+ }
58
+
59
+ return span;
60
+ }
61
+
62
+ endSpan(span: Span, status: 'ok' | 'error' = 'ok'): void {
63
+ span.endTime = new Date();
64
+ span.status = status;
65
+ }
66
+
67
+ addEvent(span: Span, name: string, attributes?: Record<string, string | number | boolean>): void {
68
+ span.events.push({ name, timestamp: new Date(), attributes });
69
+ }
70
+
71
+ async flush(): Promise<number> {
72
+ const toExport = [...this.spans];
73
+ this.spans = [];
74
+
75
+ for (const exporter of this.exporters) {
76
+ await exporter.export(toExport);
77
+ }
78
+
79
+ return toExport.length;
80
+ }
81
+
82
+ getBufferedSpans(): readonly Span[] {
83
+ return this.spans;
84
+ }
85
+
86
+ get bufferedCount(): number {
87
+ return this.spans.length;
88
+ }
89
+ }
90
+
91
+ /** Console exporter for development */
92
+ export class ConsoleExporter implements TraceExporter {
93
+ async export(spans: Span[]): Promise<void> {
94
+ for (const span of spans) {
95
+ const duration = span.endTime
96
+ ? `${span.endTime.getTime() - span.startTime.getTime()}ms`
97
+ : 'ongoing';
98
+ console.log(`[TRACE] ${span.name} (${duration}) [${span.status}]`);
99
+ }
100
+ }
101
+ }
102
+
103
+ /** DeepBrain exporter — sends traces to DeepBrain learn() */
104
+ export class DeepBrainExporter implements TraceExporter {
105
+ private learnEndpoint: string;
106
+
107
+ constructor(deepbrainUrl: string = 'http://localhost:3333') {
108
+ this.learnEndpoint = `${deepbrainUrl}/api/learn`;
109
+ }
110
+
111
+ async export(spans: Span[]): Promise<void> {
112
+ for (const span of spans) {
113
+ try {
114
+ await fetch(this.learnEndpoint, {
115
+ method: 'POST',
116
+ headers: { 'Content-Type': 'application/json' },
117
+ body: JSON.stringify({
118
+ action: span.name,
119
+ result: span.status === 'ok' ? 'success' : 'error',
120
+ context: {
121
+ ...span.attributes,
122
+ duration: span.endTime ? span.endTime.getTime() - span.startTime.getTime() : null,
123
+ events: span.events.map(e => e.name),
124
+ },
125
+ }),
126
+ });
127
+ } catch {
128
+ // Best effort — don't break agent if brain is down
129
+ }
130
+ }
131
+ }
132
+ }
@@ -1,15 +1,15 @@
1
- FROM node:22-alpine AS base
2
- WORKDIR /app
3
-
4
- # Install dependencies
5
- COPY package.json package-lock.json* ./
6
- RUN npm ci --production 2>/dev/null || npm install --production
7
-
8
- # Copy agent files
9
- COPY oad.yaml ./
10
- COPY .env* ./
11
- COPY prompts/ ./prompts/ 2>/dev/null || true
12
-
13
- EXPOSE 3000
14
-
15
- CMD ["npx", "opc", "run"]
1
+ FROM node:22-alpine AS base
2
+ WORKDIR /app
3
+
4
+ # Install dependencies
5
+ COPY package.json package-lock.json* ./
6
+ RUN npm ci --production 2>/dev/null || npm install --production
7
+
8
+ # Copy agent files
9
+ COPY oad.yaml ./
10
+ COPY .env* ./
11
+ COPY prompts/ ./prompts/ 2>/dev/null || true
12
+
13
+ EXPOSE 3000
14
+
15
+ CMD ["npx", "opc", "run"]
@@ -1,27 +1,27 @@
1
- # Code Reviewer Template
2
-
3
- AI-powered code reviewer that catches bugs and suggests improvements.
4
-
5
- ## Features
6
- - **Bug Detection**: Finds potential bugs and security issues
7
- - **Style Checks**: Enforces coding best practices
8
- - **Improvement Suggestions**: Actionable refactoring advice
9
- - **Severity Ratings**: 🔴 Critical | 🟡 Warning | 🔵 Info
10
-
11
- ## Quick Start
12
- ```bash
13
- opc init my-reviewer --template code-reviewer
14
- cd my-reviewer
15
- opc run
16
- ```
17
-
18
- ## Usage
19
- Send code via the web or WebSocket channel:
20
- ```json
21
- {
22
- "message": "Review this:\n```python\ndef calc(x):\n return eval(x)\n```"
23
- }
24
- ```
25
-
26
- ## Configuration
27
- Customize the system prompt in `oad.yaml` to focus on specific languages or coding standards.
1
+ # Code Reviewer Template
2
+
3
+ AI-powered code reviewer that catches bugs and suggests improvements.
4
+
5
+ ## Features
6
+ - **Bug Detection**: Finds potential bugs and security issues
7
+ - **Style Checks**: Enforces coding best practices
8
+ - **Improvement Suggestions**: Actionable refactoring advice
9
+ - **Severity Ratings**: 🔴 Critical | 🟡 Warning | 🔵 Info
10
+
11
+ ## Quick Start
12
+ ```bash
13
+ opc init my-reviewer --template code-reviewer
14
+ cd my-reviewer
15
+ opc run
16
+ ```
17
+
18
+ ## Usage
19
+ Send code via the web or WebSocket channel:
20
+ ```json
21
+ {
22
+ "message": "Review this:\n```python\ndef calc(x):\n return eval(x)\n```"
23
+ }
24
+ ```
25
+
26
+ ## Configuration
27
+ Customize the system prompt in `oad.yaml` to focus on specific languages or coding standards.
@@ -1,41 +1,41 @@
1
- apiVersion: opc/v1
2
- kind: Agent
3
- metadata:
4
- name: code-reviewer
5
- version: 1.0.0
6
- description: "AI code reviewer that reviews code and suggests improvements"
7
- author: Deepleaper
8
- license: Apache-2.0
9
- marketplace:
10
- certified: false
11
- category: developer-tools
12
- spec:
13
- provider:
14
- default: deepseek
15
- allowed: [openai, deepseek, qwen]
16
- model: deepseek-chat
17
- systemPrompt: |
18
- You are an expert code reviewer. When given code:
19
- 1. Check for bugs, security issues, and performance problems
20
- 2. Suggest improvements for readability and maintainability
21
- 3. Follow language-specific best practices
22
- 4. Be constructive and explain your reasoning
23
- Rate severity: 🔴 Critical | 🟡 Warning | 🔵 Info
24
- skills:
25
- - name: code-analysis
26
- description: "Analyze code for bugs and improvements"
27
- - name: style-check
28
- description: "Check coding style and best practices"
29
- channels:
30
- - type: web
31
- port: 3000
32
- - type: websocket
33
- port: 3002
34
- memory:
35
- shortTerm: true
36
- longTerm: false
37
- dtv:
38
- trust:
39
- level: sandbox
40
- value:
41
- metrics: [reviews_completed, issues_found, suggestions_accepted]
1
+ apiVersion: opc/v1
2
+ kind: Agent
3
+ metadata:
4
+ name: code-reviewer
5
+ version: 1.0.0
6
+ description: "AI code reviewer that reviews code and suggests improvements"
7
+ author: Deepleaper
8
+ license: Apache-2.0
9
+ marketplace:
10
+ certified: false
11
+ category: developer-tools
12
+ spec:
13
+ provider:
14
+ default: deepseek
15
+ allowed: [openai, deepseek, qwen]
16
+ model: deepseek-chat
17
+ systemPrompt: |
18
+ You are an expert code reviewer. When given code:
19
+ 1. Check for bugs, security issues, and performance problems
20
+ 2. Suggest improvements for readability and maintainability
21
+ 3. Follow language-specific best practices
22
+ 4. Be constructive and explain your reasoning
23
+ Rate severity: 🔴 Critical | 🟡 Warning | 🔵 Info
24
+ skills:
25
+ - name: code-analysis
26
+ description: "Analyze code for bugs and improvements"
27
+ - name: style-check
28
+ description: "Check coding style and best practices"
29
+ channels:
30
+ - type: web
31
+ port: 3000
32
+ - type: websocket
33
+ port: 3002
34
+ memory:
35
+ shortTerm: true
36
+ longTerm: false
37
+ dtv:
38
+ trust:
39
+ level: sandbox
40
+ value:
41
+ metrics: [reviews_completed, issues_found, suggestions_accepted]
@@ -1,22 +1,22 @@
1
- # Customer Service Agent Template
2
-
3
- A ready-to-use customer service agent with:
4
- - **FAQ Lookup** — Matches common questions to predefined answers
5
- - **Human Handoff** — Detects when a customer wants a real person
6
- - **Web Channel** — HTTP API for chat integration
7
-
8
- ## Quick Start
9
-
10
- ```bash
11
- opc init my-service --template customer-service
12
- cd my-service
13
- opc run
14
- ```
15
-
16
- ## Customization
17
-
18
- Edit `oad.yaml` to:
19
- - Change the system prompt
20
- - Add custom FAQ entries
21
- - Switch LLM provider
22
- - Adjust trust level
1
+ # Customer Service Agent Template
2
+
3
+ A ready-to-use customer service agent with:
4
+ - **FAQ Lookup** — Matches common questions to predefined answers
5
+ - **Human Handoff** — Detects when a customer wants a real person
6
+ - **Web Channel** — HTTP API for chat integration
7
+
8
+ ## Quick Start
9
+
10
+ ```bash
11
+ opc init my-service --template customer-service
12
+ cd my-service
13
+ opc run
14
+ ```
15
+
16
+ ## Customization
17
+
18
+ Edit `oad.yaml` to:
19
+ - Change the system prompt
20
+ - Add custom FAQ entries
21
+ - Switch LLM provider
22
+ - Adjust trust level
@@ -1,36 +1,36 @@
1
- apiVersion: opc/v1
2
- kind: Agent
3
- metadata:
4
- name: customer-service
5
- version: 1.0.0
6
- description: "A customer service agent with FAQ lookup and human handoff"
7
- author: Deepleaper
8
- license: Apache-2.0
9
- marketplace:
10
- certified: false
11
- category: customer-service
12
- spec:
13
- provider:
14
- default: deepseek
15
- allowed: [openai, deepseek, qwen]
16
- model: deepseek-chat
17
- systemPrompt: |
18
- You are a friendly and professional customer service agent.
19
- You help customers with their questions about products, orders, shipping, and returns.
20
- Be concise, helpful, and empathetic.
21
- skills:
22
- - name: faq-lookup
23
- description: "Look up FAQ answers"
24
- - name: human-handoff
25
- description: "Hand off to human agent when needed"
26
- channels:
27
- - type: web
28
- port: 3000
29
- memory:
30
- shortTerm: true
31
- longTerm: false
32
- dtv:
33
- trust:
34
- level: sandbox
35
- value:
36
- metrics: [response_time, satisfaction_score]
1
+ apiVersion: opc/v1
2
+ kind: Agent
3
+ metadata:
4
+ name: customer-service
5
+ version: 1.0.0
6
+ description: "A customer service agent with FAQ lookup and human handoff"
7
+ author: Deepleaper
8
+ license: Apache-2.0
9
+ marketplace:
10
+ certified: false
11
+ category: customer-service
12
+ spec:
13
+ provider:
14
+ default: deepseek
15
+ allowed: [openai, deepseek, qwen]
16
+ model: deepseek-chat
17
+ systemPrompt: |
18
+ You are a friendly and professional customer service agent.
19
+ You help customers with their questions about products, orders, shipping, and returns.
20
+ Be concise, helpful, and empathetic.
21
+ skills:
22
+ - name: faq-lookup
23
+ description: "Look up FAQ answers"
24
+ - name: human-handoff
25
+ description: "Hand off to human agent when needed"
26
+ channels:
27
+ - type: web
28
+ port: 3000
29
+ memory:
30
+ shortTerm: true
31
+ longTerm: false
32
+ dtv:
33
+ trust:
34
+ level: sandbox
35
+ value:
36
+ metrics: [response_time, satisfaction_score]