opc-agent 1.1.3 → 1.2.1

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 (156) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/CONTRIBUTING.md +75 -75
  3. package/README.md +429 -429
  4. package/README.zh-CN.md +415 -415
  5. package/dist/channels/web.js +256 -256
  6. package/dist/core/streaming.d.ts +56 -0
  7. package/dist/core/streaming.js +160 -0
  8. package/dist/deploy/hermes.js +22 -22
  9. package/dist/deploy/openclaw.js +31 -31
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.js +7 -1
  12. package/dist/providers/index.d.ts +1 -1
  13. package/dist/providers/index.js +13 -148
  14. package/dist/schema/oad.d.ts +3 -3
  15. package/dist/templates/code-reviewer.js +5 -5
  16. package/dist/templates/customer-service.js +2 -2
  17. package/dist/templates/data-analyst.js +5 -5
  18. package/dist/templates/knowledge-base.js +2 -2
  19. package/dist/templates/sales-assistant.js +4 -4
  20. package/dist/templates/teacher.js +6 -6
  21. package/dist/tools/gateway.d.ts +28 -0
  22. package/dist/tools/gateway.js +177 -0
  23. package/docs/.vitepress/config.ts +103 -103
  24. package/docs/api/cli.md +48 -48
  25. package/docs/api/oad-schema.md +64 -64
  26. package/docs/api/sdk.md +80 -80
  27. package/docs/guide/concepts.md +51 -51
  28. package/docs/guide/configuration.md +79 -79
  29. package/docs/guide/deployment.md +42 -42
  30. package/docs/guide/getting-started.md +44 -44
  31. package/docs/guide/templates.md +28 -28
  32. package/docs/guide/testing.md +84 -84
  33. package/docs/index.md +27 -27
  34. package/docs/zh/api/cli.md +54 -54
  35. package/docs/zh/api/oad-schema.md +87 -87
  36. package/docs/zh/api/sdk.md +102 -102
  37. package/docs/zh/guide/concepts.md +104 -104
  38. package/docs/zh/guide/configuration.md +135 -135
  39. package/docs/zh/guide/deployment.md +81 -81
  40. package/docs/zh/guide/getting-started.md +82 -82
  41. package/docs/zh/guide/templates.md +84 -84
  42. package/docs/zh/guide/testing.md +88 -88
  43. package/docs/zh/index.md +27 -27
  44. package/examples/customer-service-demo/README.md +90 -90
  45. package/examples/customer-service-demo/oad.yaml +107 -107
  46. package/package.json +1 -1
  47. package/src/analytics/index.ts +66 -66
  48. package/src/channels/discord.ts +192 -192
  49. package/src/channels/email.ts +177 -177
  50. package/src/channels/feishu.ts +236 -236
  51. package/src/channels/index.ts +15 -15
  52. package/src/channels/slack.ts +160 -160
  53. package/src/channels/telegram.ts +90 -90
  54. package/src/channels/voice.ts +106 -106
  55. package/src/channels/web.ts +17 -17
  56. package/src/channels/webhook.ts +199 -199
  57. package/src/channels/websocket.ts +87 -87
  58. package/src/channels/wechat.ts +149 -149
  59. package/src/core/a2a.ts +143 -143
  60. package/src/core/agent.ts +152 -152
  61. package/src/core/analytics-engine.ts +186 -186
  62. package/src/core/auth.ts +57 -57
  63. package/src/core/cache.ts +141 -141
  64. package/src/core/compose.ts +77 -77
  65. package/src/core/config.ts +14 -14
  66. package/src/core/errors.ts +148 -148
  67. package/src/core/hitl.ts +138 -138
  68. package/src/core/knowledge.ts +49 -4
  69. package/src/core/logger.ts +57 -57
  70. package/src/core/orchestrator.ts +215 -215
  71. package/src/core/performance.ts +187 -187
  72. package/src/core/rate-limiter.ts +128 -128
  73. package/src/core/room.ts +109 -109
  74. package/src/core/runtime.ts +152 -152
  75. package/src/core/sandbox.ts +101 -101
  76. package/src/core/security.ts +171 -171
  77. package/src/core/streaming.ts +195 -0
  78. package/src/core/types.ts +68 -68
  79. package/src/core/versioning.ts +106 -106
  80. package/src/core/watch.ts +178 -178
  81. package/src/core/workflow.ts +235 -235
  82. package/src/deploy/hermes.ts +156 -156
  83. package/src/deploy/openclaw.ts +200 -200
  84. package/src/dtv/data.ts +29 -29
  85. package/src/dtv/trust.ts +43 -43
  86. package/src/dtv/value.ts +47 -47
  87. package/src/i18n/index.ts +216 -216
  88. package/src/index.ts +6 -0
  89. package/src/marketplace/index.ts +223 -223
  90. package/src/memory/deepbrain.ts +108 -108
  91. package/src/memory/index.ts +34 -34
  92. package/src/plugins/index.ts +208 -208
  93. package/src/providers/index.ts +12 -3
  94. package/src/schema/oad.ts +155 -155
  95. package/src/skills/base.ts +16 -16
  96. package/src/skills/document.ts +100 -100
  97. package/src/skills/http.ts +35 -35
  98. package/src/skills/index.ts +27 -27
  99. package/src/skills/scheduler.ts +80 -80
  100. package/src/skills/webhook-trigger.ts +59 -59
  101. package/src/templates/code-reviewer.ts +34 -34
  102. package/src/templates/customer-service.ts +80 -80
  103. package/src/templates/data-analyst.ts +70 -70
  104. package/src/templates/executive-assistant.ts +71 -71
  105. package/src/templates/financial-advisor.ts +60 -60
  106. package/src/templates/knowledge-base.ts +31 -31
  107. package/src/templates/legal-assistant.ts +71 -71
  108. package/src/templates/sales-assistant.ts +79 -79
  109. package/src/templates/teacher.ts +79 -79
  110. package/src/testing/index.ts +181 -181
  111. package/src/tools/calculator.ts +73 -73
  112. package/src/tools/datetime.ts +149 -149
  113. package/src/tools/gateway.ts +220 -0
  114. package/src/tools/json-transform.ts +187 -187
  115. package/src/tools/mcp.ts +76 -76
  116. package/src/tools/text-analysis.ts +116 -116
  117. package/templates/Dockerfile +15 -15
  118. package/templates/code-reviewer/README.md +27 -27
  119. package/templates/code-reviewer/oad.yaml +41 -41
  120. package/templates/customer-service/README.md +22 -22
  121. package/templates/customer-service/oad.yaml +36 -36
  122. package/templates/docker-compose.yml +21 -21
  123. package/templates/ecommerce-assistant/README.md +45 -0
  124. package/templates/ecommerce-assistant/oad.yaml +47 -0
  125. package/templates/knowledge-base/README.md +28 -28
  126. package/templates/knowledge-base/oad.yaml +38 -38
  127. package/templates/sales-assistant/README.md +26 -26
  128. package/templates/sales-assistant/oad.yaml +43 -43
  129. package/templates/tech-support/README.md +43 -0
  130. package/templates/tech-support/oad.yaml +45 -0
  131. package/tests/a2a.test.ts +66 -66
  132. package/tests/agent.test.ts +72 -72
  133. package/tests/analytics.test.ts +50 -50
  134. package/tests/channel.test.ts +39 -39
  135. package/tests/e2e.test.ts +134 -134
  136. package/tests/errors.test.ts +83 -83
  137. package/tests/gateway.test.ts +71 -0
  138. package/tests/hitl.test.ts +71 -71
  139. package/tests/i18n.test.ts +41 -41
  140. package/tests/mcp.test.ts +54 -54
  141. package/tests/oad.test.ts +68 -68
  142. package/tests/performance.test.ts +115 -115
  143. package/tests/plugin.test.ts +74 -74
  144. package/tests/room.test.ts +106 -106
  145. package/tests/runtime.test.ts +42 -42
  146. package/tests/sandbox.test.ts +46 -46
  147. package/tests/security.test.ts +60 -60
  148. package/tests/streaming.test.ts +109 -0
  149. package/tests/templates.test.ts +77 -77
  150. package/tests/v070.test.ts +76 -76
  151. package/tests/versioning.test.ts +75 -75
  152. package/tests/voice.test.ts +61 -61
  153. package/tests/webhook.test.ts +29 -29
  154. package/tests/workflow.test.ts +143 -143
  155. package/tsconfig.json +19 -19
  156. package/vitest.config.ts +9 -9
@@ -1,28 +1,28 @@
1
- # Knowledge Base Template
2
-
3
- RAG-powered knowledge base agent that answers questions from your company docs.
4
-
5
- ## Features
6
- - **Semantic Search**: Uses DeepBrain for intelligent document retrieval
7
- - **Document Ingestion**: Add docs to build your knowledge base
8
- - **Source Citations**: Cites sources in answers
9
-
10
- ## Quick Start
11
- ```bash
12
- opc init my-kb --template knowledge-base
13
- cd my-kb
14
- # Optional: install deepbrain for full RAG support
15
- npm install deepbrain
16
- opc run
17
- ```
18
-
19
- ## How It Works
20
- 1. Ingest company documents into DeepBrain
21
- 2. User asks a question
22
- 3. Agent searches for relevant document chunks
23
- 4. LLM generates answer based on retrieved context
24
-
25
- ## Configuration
26
- - `memory.longTerm.provider: deepbrain` — enables semantic memory
27
- - `memory.longTerm.collection` — DeepBrain collection name
28
- - Falls back to in-memory if deepbrain is not installed
1
+ # Knowledge Base Template
2
+
3
+ RAG-powered knowledge base agent that answers questions from your company docs.
4
+
5
+ ## Features
6
+ - **Semantic Search**: Uses DeepBrain for intelligent document retrieval
7
+ - **Document Ingestion**: Add docs to build your knowledge base
8
+ - **Source Citations**: Cites sources in answers
9
+
10
+ ## Quick Start
11
+ ```bash
12
+ opc init my-kb --template knowledge-base
13
+ cd my-kb
14
+ # Optional: install deepbrain for full RAG support
15
+ npm install deepbrain
16
+ opc run
17
+ ```
18
+
19
+ ## How It Works
20
+ 1. Ingest company documents into DeepBrain
21
+ 2. User asks a question
22
+ 3. Agent searches for relevant document chunks
23
+ 4. LLM generates answer based on retrieved context
24
+
25
+ ## Configuration
26
+ - `memory.longTerm.provider: deepbrain` — enables semantic memory
27
+ - `memory.longTerm.collection` — DeepBrain collection name
28
+ - Falls back to in-memory if deepbrain is not installed
@@ -1,38 +1,38 @@
1
- apiVersion: opc/v1
2
- kind: Agent
3
- metadata:
4
- name: knowledge-base
5
- version: 1.0.0
6
- description: "RAG-powered knowledge base agent using DeepBrain for semantic search"
7
- author: Deepleaper
8
- license: Apache-2.0
9
- marketplace:
10
- certified: false
11
- category: knowledge
12
- spec:
13
- provider:
14
- default: deepseek
15
- allowed: [openai, deepseek, qwen]
16
- model: deepseek-chat
17
- systemPrompt: |
18
- You are a knowledge base assistant. Answer questions using the company documents
19
- and knowledge provided to you. If you don't have enough information, say so honestly.
20
- Always cite sources when possible. Be accurate and concise.
21
- skills:
22
- - name: doc-search
23
- description: "Search company documents using semantic search"
24
- - name: doc-ingest
25
- description: "Ingest new documents into the knowledge base"
26
- channels:
27
- - type: web
28
- port: 3000
29
- memory:
30
- shortTerm: true
31
- longTerm:
32
- provider: deepbrain
33
- collection: company-knowledge
34
- dtv:
35
- trust:
36
- level: sandbox
37
- value:
38
- metrics: [queries_answered, accuracy_score, docs_indexed]
1
+ apiVersion: opc/v1
2
+ kind: Agent
3
+ metadata:
4
+ name: knowledge-base
5
+ version: 1.0.0
6
+ description: "RAG-powered knowledge base agent using DeepBrain for semantic search"
7
+ author: Deepleaper
8
+ license: Apache-2.0
9
+ marketplace:
10
+ certified: false
11
+ category: knowledge
12
+ spec:
13
+ provider:
14
+ default: deepseek
15
+ allowed: [openai, deepseek, qwen]
16
+ model: deepseek-chat
17
+ systemPrompt: |
18
+ You are a knowledge base assistant. Answer questions using the company documents
19
+ and knowledge provided to you. If you don't have enough information, say so honestly.
20
+ Always cite sources when possible. Be accurate and concise.
21
+ skills:
22
+ - name: doc-search
23
+ description: "Search company documents using semantic search"
24
+ - name: doc-ingest
25
+ description: "Ingest new documents into the knowledge base"
26
+ channels:
27
+ - type: web
28
+ port: 3000
29
+ memory:
30
+ shortTerm: true
31
+ longTerm:
32
+ provider: deepbrain
33
+ collection: company-knowledge
34
+ dtv:
35
+ trust:
36
+ level: sandbox
37
+ value:
38
+ metrics: [queries_answered, accuracy_score, docs_indexed]
@@ -1,26 +1,26 @@
1
- # Sales Assistant Template
2
-
3
- AI-powered sales assistant for product Q&A, lead capture, and appointment booking.
4
-
5
- ## Features
6
- - **Product Q&A**: Answers questions about your products/services
7
- - **Lead Capture**: Collects prospect information (name, email, company)
8
- - **Appointment Booking**: Schedules demos and meetings
9
-
10
- ## Quick Start
11
- ```bash
12
- opc init my-sales-bot --template sales-assistant
13
- cd my-sales-bot
14
- opc run
15
- ```
16
-
17
- ## Configuration
18
- Edit `oad.yaml` to customize:
19
- - System prompt with your product details
20
- - Add your product FAQ data
21
- - Configure appointment scheduling rules
22
-
23
- ## Value Metrics
24
- - `leads_captured` — Number of leads collected
25
- - `appointments_booked` — Demos/meetings scheduled
26
- - `conversion_rate` — Lead to appointment ratio
1
+ # Sales Assistant Template
2
+
3
+ AI-powered sales assistant for product Q&A, lead capture, and appointment booking.
4
+
5
+ ## Features
6
+ - **Product Q&A**: Answers questions about your products/services
7
+ - **Lead Capture**: Collects prospect information (name, email, company)
8
+ - **Appointment Booking**: Schedules demos and meetings
9
+
10
+ ## Quick Start
11
+ ```bash
12
+ opc init my-sales-bot --template sales-assistant
13
+ cd my-sales-bot
14
+ opc run
15
+ ```
16
+
17
+ ## Configuration
18
+ Edit `oad.yaml` to customize:
19
+ - System prompt with your product details
20
+ - Add your product FAQ data
21
+ - Configure appointment scheduling rules
22
+
23
+ ## Value Metrics
24
+ - `leads_captured` — Number of leads collected
25
+ - `appointments_booked` — Demos/meetings scheduled
26
+ - `conversion_rate` — Lead to appointment ratio
@@ -1,43 +1,43 @@
1
- apiVersion: opc/v1
2
- kind: Agent
3
- metadata:
4
- name: sales-assistant
5
- version: 1.0.0
6
- description: "AI sales assistant with product Q&A, lead capture, and appointment booking"
7
- author: Deepleaper
8
- license: Apache-2.0
9
- marketplace:
10
- certified: false
11
- category: sales
12
- spec:
13
- provider:
14
- default: deepseek
15
- allowed: [openai, deepseek, qwen]
16
- model: deepseek-chat
17
- systemPrompt: |
18
- You are a professional sales assistant. Your goals:
19
- 1. Answer product questions accurately and enthusiastically
20
- 2. Capture leads by collecting name, email, and company info
21
- 3. Book appointments when prospects are ready
22
- Be friendly, persuasive but not pushy. Always provide value first.
23
- skills:
24
- - name: product-qa
25
- description: "Answer product-related questions"
26
- - name: lead-capture
27
- description: "Capture prospect information"
28
- - name: appointment-booking
29
- description: "Schedule meetings and demos"
30
- channels:
31
- - type: web
32
- port: 3000
33
- - type: websocket
34
- port: 3002
35
- memory:
36
- shortTerm: true
37
- longTerm:
38
- provider: in-memory
39
- dtv:
40
- trust:
41
- level: sandbox
42
- value:
43
- metrics: [leads_captured, appointments_booked, conversion_rate]
1
+ apiVersion: opc/v1
2
+ kind: Agent
3
+ metadata:
4
+ name: sales-assistant
5
+ version: 1.0.0
6
+ description: "AI sales assistant with product Q&A, lead capture, and appointment booking"
7
+ author: Deepleaper
8
+ license: Apache-2.0
9
+ marketplace:
10
+ certified: false
11
+ category: sales
12
+ spec:
13
+ provider:
14
+ default: deepseek
15
+ allowed: [openai, deepseek, qwen]
16
+ model: deepseek-chat
17
+ systemPrompt: |
18
+ You are a professional sales assistant. Your goals:
19
+ 1. Answer product questions accurately and enthusiastically
20
+ 2. Capture leads by collecting name, email, and company info
21
+ 3. Book appointments when prospects are ready
22
+ Be friendly, persuasive but not pushy. Always provide value first.
23
+ skills:
24
+ - name: product-qa
25
+ description: "Answer product-related questions"
26
+ - name: lead-capture
27
+ description: "Capture prospect information"
28
+ - name: appointment-booking
29
+ description: "Schedule meetings and demos"
30
+ channels:
31
+ - type: web
32
+ port: 3000
33
+ - type: websocket
34
+ port: 3002
35
+ memory:
36
+ shortTerm: true
37
+ longTerm:
38
+ provider: in-memory
39
+ dtv:
40
+ trust:
41
+ level: sandbox
42
+ value:
43
+ metrics: [leads_captured, appointments_booked, conversion_rate]
@@ -0,0 +1,43 @@
1
+ # Tech Support Agent — 技术支持工位
2
+
3
+ 专为 IT 支持团队设计的 AI 工位,覆盖软件故障、系统配置、网络问题等场景。
4
+
5
+ ## 快速开始
6
+
7
+ ```bash
8
+ opc init --template tech-support
9
+ opc start
10
+ ```
11
+
12
+ 访问 http://localhost:3000 即可使用技术支持聊天界面。
13
+
14
+ ## 功能
15
+
16
+ | 技能 | 说明 |
17
+ |------|------|
18
+ | troubleshoot | 分步骤诊断和解决技术问题 |
19
+ | knowledge-lookup | 查询技术文档与历史解决方案 |
20
+ | ticket-create | 创建并跟踪技术支持工单 |
21
+ | escalate | 升级复杂问题至专项团队 |
22
+
23
+ ## 配置
24
+
25
+ 在 `oad.yaml` 中修改以下参数:
26
+
27
+ - `spec.provider.default` — 切换 LLM 提供商(deepseek / openai / qwen)
28
+ - `spec.model` — 指定模型版本
29
+ - `spec.systemPrompt` — 定制支持范围和话术风格
30
+
31
+ ### 环境变量
32
+
33
+ ```bash
34
+ OPC_LLM_API_KEY=your_key
35
+ OPC_LLM_MODEL=deepseek-chat # 可选,覆盖 oad.yaml 中的 model
36
+ OPC_DEEPBRAIN_ENABLED=true # 启用 DeepBrain 知识库增强(需全局安装 deepbrain)
37
+ ```
38
+
39
+ ## 推荐搭配
40
+
41
+ - 将内部技术文档、SOP、FAQ 上传至知识库(`/api/kb/upload`)
42
+ - 开启 `OPC_DEEPBRAIN_ENABLED=true` 获得更精准的语义检索
43
+ - 通过 Dashboard(`/dashboard`)监控首次解决率和平均响应时间
@@ -0,0 +1,45 @@
1
+ apiVersion: opc/v1
2
+ kind: Agent
3
+ metadata:
4
+ name: tech-support
5
+ version: 1.0.0
6
+ description: "技术支持工位 - 处理用户技术问题、故障排查和解决方案推荐"
7
+ author: Deepleaper
8
+ license: Apache-2.0
9
+ marketplace:
10
+ certified: false
11
+ category: it-support
12
+ spec:
13
+ provider:
14
+ default: deepseek
15
+ allowed: [openai, deepseek, qwen, gemini]
16
+ model: deepseek-chat
17
+ systemPrompt: |
18
+ 你是一名专业的技术支持工程师。
19
+ 你帮助用户解决技术问题,包括软件故障、系统配置、网络问题、硬件故障等。
20
+ 回答时请保持专业、耐心,并提供清晰的步骤指引。
21
+ 优先使用知识库中的已知解决方案。
22
+ 如果问题无法远程解决,请指导用户联系线下支持或提交工单。
23
+ skills:
24
+ - name: troubleshoot
25
+ description: "诊断和解决技术问题,提供分步骤操作指南"
26
+ - name: knowledge-lookup
27
+ description: "查询技术文档、FAQ 和历史解决方案库"
28
+ - name: ticket-create
29
+ description: "为复杂问题创建技术支持工单并跟踪进展"
30
+ - name: escalate
31
+ description: "将高优先级问题升级到高级工程师或专项团队"
32
+ channels:
33
+ - type: web
34
+ port: 3000
35
+ memory:
36
+ shortTerm: true
37
+ longTerm: true
38
+ knowledge:
39
+ enabled: true
40
+ deepbrain: auto
41
+ dtv:
42
+ trust:
43
+ level: internal
44
+ value:
45
+ metrics: [resolution_time, first_contact_resolution, customer_satisfaction]
package/tests/a2a.test.ts CHANGED
@@ -1,66 +1,66 @@
1
- import { describe, it, expect, beforeEach } from 'vitest';
2
- import { AgentRegistry } from '../src/core/a2a';
3
- import { BaseAgent } from '../src/core/agent';
4
- import { InMemoryStore } from '../src/memory';
5
-
6
- function createTestAgent(name: string): BaseAgent {
7
- const agent = new BaseAgent({ name, model: 'test', systemPrompt: `I am ${name}` }, new InMemoryStore());
8
- return agent;
9
- }
10
-
11
- describe('AgentRegistry (A2A)', () => {
12
- let registry: AgentRegistry;
13
-
14
- beforeEach(() => {
15
- registry = new AgentRegistry();
16
- });
17
-
18
- it('should register and discover agents', () => {
19
- const agent = createTestAgent('agent-1');
20
- registry.register(agent, [{ name: 'summarize', description: 'Summarize text' }]);
21
-
22
- const all = registry.discover();
23
- expect(all).toHaveLength(1);
24
- expect(all[0].agentName).toBe('agent-1');
25
- });
26
-
27
- it('should discover by capability', () => {
28
- const a1 = createTestAgent('a1');
29
- const a2 = createTestAgent('a2');
30
- registry.register(a1, [{ name: 'summarize', description: 'Summarize' }]);
31
- registry.register(a2, [{ name: 'translate', description: 'Translate' }]);
32
-
33
- const found = registry.discover('translate');
34
- expect(found).toHaveLength(1);
35
- expect(found[0].agentName).toBe('a2');
36
- });
37
-
38
- it('should unregister agents', () => {
39
- const agent = createTestAgent('temp');
40
- registry.register(agent, []);
41
- registry.unregister('temp');
42
- expect(registry.discover()).toHaveLength(0);
43
- });
44
-
45
- it('should handle request to unknown agent', async () => {
46
- const response = await registry.call('a1', 'unknown', 'test', 'hello');
47
- expect(response.status).toBe('error');
48
- });
49
-
50
- it('should send A2A request and get response', async () => {
51
- const agent = createTestAgent('responder');
52
- await agent.init();
53
- registry.register(agent, [{ name: 'chat', description: 'Chat' }]);
54
-
55
- const response = await registry.call('caller', 'responder', 'chat', 'hello');
56
- expect(response.status).toBe('success');
57
- expect(response.payload).toBeDefined();
58
- });
59
-
60
- it('should get agent by name', () => {
61
- const agent = createTestAgent('finder');
62
- registry.register(agent, []);
63
- expect(registry.getAgent('finder')).toBeDefined();
64
- expect(registry.getAgent('none')).toBeUndefined();
65
- });
66
- });
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { AgentRegistry } from '../src/core/a2a';
3
+ import { BaseAgent } from '../src/core/agent';
4
+ import { InMemoryStore } from '../src/memory';
5
+
6
+ function createTestAgent(name: string): BaseAgent {
7
+ const agent = new BaseAgent({ name, model: 'test', systemPrompt: `I am ${name}` }, new InMemoryStore());
8
+ return agent;
9
+ }
10
+
11
+ describe('AgentRegistry (A2A)', () => {
12
+ let registry: AgentRegistry;
13
+
14
+ beforeEach(() => {
15
+ registry = new AgentRegistry();
16
+ });
17
+
18
+ it('should register and discover agents', () => {
19
+ const agent = createTestAgent('agent-1');
20
+ registry.register(agent, [{ name: 'summarize', description: 'Summarize text' }]);
21
+
22
+ const all = registry.discover();
23
+ expect(all).toHaveLength(1);
24
+ expect(all[0].agentName).toBe('agent-1');
25
+ });
26
+
27
+ it('should discover by capability', () => {
28
+ const a1 = createTestAgent('a1');
29
+ const a2 = createTestAgent('a2');
30
+ registry.register(a1, [{ name: 'summarize', description: 'Summarize' }]);
31
+ registry.register(a2, [{ name: 'translate', description: 'Translate' }]);
32
+
33
+ const found = registry.discover('translate');
34
+ expect(found).toHaveLength(1);
35
+ expect(found[0].agentName).toBe('a2');
36
+ });
37
+
38
+ it('should unregister agents', () => {
39
+ const agent = createTestAgent('temp');
40
+ registry.register(agent, []);
41
+ registry.unregister('temp');
42
+ expect(registry.discover()).toHaveLength(0);
43
+ });
44
+
45
+ it('should handle request to unknown agent', async () => {
46
+ const response = await registry.call('a1', 'unknown', 'test', 'hello');
47
+ expect(response.status).toBe('error');
48
+ });
49
+
50
+ it('should send A2A request and get response', async () => {
51
+ const agent = createTestAgent('responder');
52
+ await agent.init();
53
+ registry.register(agent, [{ name: 'chat', description: 'Chat' }]);
54
+
55
+ const response = await registry.call('caller', 'responder', 'chat', 'hello');
56
+ expect(response.status).toBe('success');
57
+ expect(response.payload).toBeDefined();
58
+ });
59
+
60
+ it('should get agent by name', () => {
61
+ const agent = createTestAgent('finder');
62
+ registry.register(agent, []);
63
+ expect(registry.getAgent('finder')).toBeDefined();
64
+ expect(registry.getAgent('none')).toBeUndefined();
65
+ });
66
+ });
@@ -1,72 +1,72 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { BaseAgent } from '../src/core/agent';
3
-
4
- describe('BaseAgent', () => {
5
- it('should start in init state', () => {
6
- const agent = new BaseAgent({ name: 'test' });
7
- expect(agent.state).toBe('init');
8
- expect(agent.name).toBe('test');
9
- });
10
-
11
- it('should transition through lifecycle', async () => {
12
- const agent = new BaseAgent({ name: 'test' });
13
- const states: string[] = [];
14
- agent.on('state:change', (_from, to) => states.push(to));
15
-
16
- await agent.init();
17
- expect(agent.state).toBe('ready');
18
-
19
- await agent.start();
20
- expect(agent.state).toBe('running');
21
-
22
- await agent.stop();
23
- expect(agent.state).toBe('stopped');
24
-
25
- expect(states).toEqual(['ready', 'running', 'stopped']);
26
- });
27
-
28
- it('should not start if not ready', async () => {
29
- const agent = new BaseAgent({ name: 'test' });
30
- await expect(agent.start()).rejects.toThrow('Cannot start agent in state: init');
31
- });
32
-
33
- it('should handle messages with stub provider', async () => {
34
- const agent = new BaseAgent({ name: 'test', systemPrompt: 'Be helpful' });
35
- await agent.init();
36
-
37
- const response = await agent.handleMessage({
38
- id: 'msg_1',
39
- role: 'user',
40
- content: 'Hello',
41
- timestamp: Date.now(),
42
- });
43
-
44
- expect(response.role).toBe('assistant');
45
- expect(response.content).toContain('Hello');
46
- });
47
-
48
- it('should use skills before LLM fallback', async () => {
49
- const agent = new BaseAgent({ name: 'test' });
50
- await agent.init();
51
-
52
- agent.registerSkill({
53
- name: 'greeter',
54
- description: 'Greets users',
55
- execute: async (_ctx, msg) => {
56
- if (msg.content.toLowerCase().includes('hello')) {
57
- return { handled: true, response: 'Hi there!', confidence: 1.0 };
58
- }
59
- return { handled: false, confidence: 0 };
60
- },
61
- });
62
-
63
- const response = await agent.handleMessage({
64
- id: 'msg_1',
65
- role: 'user',
66
- content: 'Hello!',
67
- timestamp: Date.now(),
68
- });
69
-
70
- expect(response.content).toBe('Hi there!');
71
- });
72
- });
1
+ import { describe, it, expect } from 'vitest';
2
+ import { BaseAgent } from '../src/core/agent';
3
+
4
+ describe('BaseAgent', () => {
5
+ it('should start in init state', () => {
6
+ const agent = new BaseAgent({ name: 'test' });
7
+ expect(agent.state).toBe('init');
8
+ expect(agent.name).toBe('test');
9
+ });
10
+
11
+ it('should transition through lifecycle', async () => {
12
+ const agent = new BaseAgent({ name: 'test' });
13
+ const states: string[] = [];
14
+ agent.on('state:change', (_from, to) => states.push(to));
15
+
16
+ await agent.init();
17
+ expect(agent.state).toBe('ready');
18
+
19
+ await agent.start();
20
+ expect(agent.state).toBe('running');
21
+
22
+ await agent.stop();
23
+ expect(agent.state).toBe('stopped');
24
+
25
+ expect(states).toEqual(['ready', 'running', 'stopped']);
26
+ });
27
+
28
+ it('should not start if not ready', async () => {
29
+ const agent = new BaseAgent({ name: 'test' });
30
+ await expect(agent.start()).rejects.toThrow('Cannot start agent in state: init');
31
+ });
32
+
33
+ it('should handle messages with stub provider', async () => {
34
+ const agent = new BaseAgent({ name: 'test', systemPrompt: 'Be helpful' });
35
+ await agent.init();
36
+
37
+ const response = await agent.handleMessage({
38
+ id: 'msg_1',
39
+ role: 'user',
40
+ content: 'Hello',
41
+ timestamp: Date.now(),
42
+ });
43
+
44
+ expect(response.role).toBe('assistant');
45
+ expect(response.content).toContain('Hello');
46
+ });
47
+
48
+ it('should use skills before LLM fallback', async () => {
49
+ const agent = new BaseAgent({ name: 'test' });
50
+ await agent.init();
51
+
52
+ agent.registerSkill({
53
+ name: 'greeter',
54
+ description: 'Greets users',
55
+ execute: async (_ctx, msg) => {
56
+ if (msg.content.toLowerCase().includes('hello')) {
57
+ return { handled: true, response: 'Hi there!', confidence: 1.0 };
58
+ }
59
+ return { handled: false, confidence: 0 };
60
+ },
61
+ });
62
+
63
+ const response = await agent.handleMessage({
64
+ id: 'msg_1',
65
+ role: 'user',
66
+ content: 'Hello!',
67
+ timestamp: Date.now(),
68
+ });
69
+
70
+ expect(response.content).toBe('Hi there!');
71
+ });
72
+ });