opc-agent 4.1.0 → 4.1.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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +20 -20
- package/.github/ISSUE_TEMPLATE/feature_request.md +14 -14
- package/.github/PULL_REQUEST_TEMPLATE.md +13 -13
- package/CHANGELOG.md +48 -48
- package/CONTRIBUTING.md +36 -36
- package/README.zh-CN.md +497 -497
- package/dist/channels/wechat.js +6 -6
- package/dist/deploy/index.js +56 -56
- package/dist/studio/server.js +30 -1
- package/dist/studio-ui/index.html +230 -10
- package/dist/ui/components.js +105 -105
- package/examples/README.md +22 -22
- package/examples/basic-agent.ts +90 -90
- package/examples/brain-integration.ts +71 -71
- package/examples/multi-channel.ts +74 -74
- package/fix-sidebar.mjs +188 -188
- package/install.ps1 +154 -154
- package/install.sh +164 -164
- package/package.json +1 -1
- package/scripts/install.ps1 +31 -31
- package/scripts/install.sh +40 -40
- package/serve-studio.js +13 -13
- package/serve-test.js +25 -25
- package/src/channels/dingtalk.ts +46 -46
- package/src/channels/email.ts +351 -351
- package/src/channels/feishu.ts +349 -349
- package/src/channels/googlechat.ts +42 -42
- package/src/channels/imessage.ts +31 -31
- package/src/channels/irc.ts +82 -82
- package/src/channels/line.ts +32 -32
- package/src/channels/matrix.ts +33 -33
- package/src/channels/mattermost.ts +57 -57
- package/src/channels/msteams.ts +32 -32
- package/src/channels/nostr.ts +32 -32
- package/src/channels/qq.ts +33 -33
- package/src/channels/signal.ts +32 -32
- package/src/channels/sms.ts +33 -33
- package/src/channels/telegram.ts +616 -616
- package/src/channels/twitch.ts +65 -65
- package/src/channels/voice-call.ts +100 -100
- package/src/channels/websocket.ts +399 -399
- package/src/channels/wechat.ts +329 -329
- package/src/channels/whatsapp.ts +32 -32
- package/src/cli/chat.ts +99 -99
- package/src/cli/setup.ts +314 -314
- package/src/core/agent.ts +476 -476
- package/src/core/api-server.ts +277 -277
- package/src/core/audio.ts +98 -98
- package/src/core/collaboration.ts +275 -275
- package/src/core/context-discovery.ts +85 -85
- package/src/core/context-refs.ts +140 -140
- package/src/core/gateway.ts +106 -106
- package/src/core/heartbeat.ts +51 -51
- package/src/core/hooks.ts +105 -105
- package/src/core/ide-bridge.ts +133 -133
- package/src/core/node-network.ts +86 -86
- package/src/core/profiles.ts +122 -122
- package/src/core/scheduler.ts +187 -187
- package/src/core/session-manager.ts +137 -137
- package/src/core/subagent.ts +98 -98
- package/src/core/vision.ts +180 -180
- package/src/core/workflow-graph.ts +365 -365
- package/src/daemon.ts +96 -96
- package/src/deploy/index.ts +255 -255
- package/src/doctor.ts +156 -156
- package/src/eval/index.ts +211 -211
- package/src/eval/suites/basic.json +16 -16
- package/src/eval/suites/memory.json +12 -12
- package/src/eval/suites/safety.json +14 -14
- package/src/hub/brain-seed.ts +54 -54
- package/src/hub/client.ts +60 -60
- package/src/mcp/servers/calculator-mcp.ts +65 -65
- package/src/mcp/servers/crypto-mcp.ts +73 -73
- package/src/mcp/servers/database-mcp.ts +72 -72
- package/src/mcp/servers/datetime-mcp.ts +69 -69
- package/src/mcp/servers/filesystem.ts +66 -66
- package/src/mcp/servers/github-mcp.ts +58 -58
- package/src/mcp/servers/index.ts +63 -63
- package/src/mcp/servers/json-mcp.ts +102 -102
- package/src/mcp/servers/memory-mcp.ts +56 -56
- package/src/mcp/servers/regex-mcp.ts +53 -53
- package/src/mcp/servers/web-mcp.ts +49 -49
- package/src/memory/context-compressor.ts +189 -189
- package/src/memory/seed-loader.ts +212 -212
- package/src/memory/user-profiler.ts +215 -215
- package/src/plugins/content-filter.ts +23 -23
- package/src/plugins/logger.ts +18 -18
- package/src/plugins/rate-limiter.ts +38 -38
- package/src/protocols/a2a/client.ts +132 -132
- package/src/protocols/a2a/index.ts +8 -8
- package/src/protocols/a2a/server.ts +333 -333
- package/src/protocols/a2a/types.ts +88 -88
- package/src/protocols/a2a/utils.ts +50 -50
- package/src/protocols/agui/client.ts +83 -83
- package/src/protocols/agui/index.ts +4 -4
- package/src/protocols/agui/server.ts +218 -218
- package/src/protocols/agui/types.ts +153 -153
- package/src/protocols/index.ts +2 -2
- package/src/protocols/mcp/agent-tools.ts +134 -134
- package/src/protocols/mcp/index.ts +8 -8
- package/src/protocols/mcp/server.ts +262 -262
- package/src/protocols/mcp/types.ts +69 -69
- package/src/providers/index.ts +632 -632
- package/src/publish/index.ts +376 -376
- package/src/scheduler/cron-engine.ts +191 -191
- package/src/scheduler/index.ts +2 -2
- package/src/schema/oad.ts +217 -217
- package/src/security/approval.ts +131 -131
- package/src/security/approvals.ts +143 -143
- package/src/security/elevated.ts +105 -105
- package/src/security/guardrails.ts +248 -248
- package/src/security/index.ts +9 -9
- package/src/security/keys.ts +87 -87
- package/src/security/secrets.ts +129 -129
- package/src/skills/builtin/index.ts +408 -408
- package/src/skills/marketplace.ts +113 -113
- package/src/skills/types.ts +42 -42
- package/src/studio/server.ts +31 -1
- package/src/studio/templates-data.ts +178 -178
- package/src/studio-ui/index.html +230 -10
- package/src/telemetry/index.ts +324 -324
- package/src/tools/builtin/browser.ts +299 -299
- package/src/tools/builtin/datetime.ts +41 -41
- package/src/tools/builtin/file.ts +107 -107
- package/src/tools/builtin/home-assistant.ts +116 -116
- package/src/tools/builtin/rl-tools.ts +243 -243
- package/src/tools/builtin/shell.ts +43 -43
- package/src/tools/builtin/vision.ts +64 -64
- package/src/tools/builtin/web-search.ts +126 -126
- package/src/tools/builtin/web.ts +35 -35
- package/src/tools/document-processor.ts +213 -213
- package/src/tools/image-generator.ts +150 -150
- package/src/tools/integrations/calendar.ts +73 -73
- package/src/tools/integrations/code-exec.ts +39 -39
- package/src/tools/integrations/csv-analyzer.ts +92 -92
- package/src/tools/integrations/database.ts +44 -44
- package/src/tools/integrations/email-send.ts +76 -76
- package/src/tools/integrations/git-tool.ts +42 -42
- package/src/tools/integrations/github-tool.ts +76 -76
- package/src/tools/integrations/image-gen.ts +56 -56
- package/src/tools/integrations/index.ts +92 -92
- package/src/tools/integrations/jira.ts +83 -83
- package/src/tools/integrations/notion.ts +71 -71
- package/src/tools/integrations/npm-tool.ts +48 -48
- package/src/tools/integrations/pdf-reader.ts +58 -58
- package/src/tools/integrations/slack.ts +65 -65
- package/src/tools/integrations/summarizer.ts +49 -49
- package/src/tools/integrations/translator.ts +48 -48
- package/src/tools/integrations/trello.ts +60 -60
- package/src/tools/integrations/vector-search.ts +42 -42
- package/src/tools/integrations/web-scraper.ts +47 -47
- package/src/tools/integrations/web-search.ts +58 -58
- package/src/tools/integrations/webhook.ts +38 -38
- package/src/tools/mcp-client.ts +131 -131
- package/src/tools/web-scraper.ts +179 -179
- package/src/tools/web-search.ts +180 -180
- package/src/ui/components.ts +127 -127
- package/srv-out.txt +1 -1
- package/templates/ecommerce-assistant/README.md +45 -45
- package/templates/ecommerce-assistant/oad.yaml +47 -47
- package/templates/tech-support/README.md +43 -43
- package/templates/tech-support/oad.yaml +45 -45
- package/test-agent/Dockerfile +9 -9
- package/test-agent/README.md +50 -50
- package/test-agent/agent.yaml +23 -23
- package/test-agent/docker-compose.yml +11 -11
- package/test-agent/oad.yaml +31 -31
- package/test-agent/package-lock.json +1492 -1492
- package/test-agent/package.json +17 -17
- package/test-agent/src/index.ts +24 -24
- package/test-agent/src/skills/echo.ts +15 -15
- package/test-agent/tsconfig.json +24 -24
- package/test-full.js +43 -43
- package/test-sidebar.js +22 -22
- package/test-studio3.js +75 -75
- package/test-studio4.js +41 -41
- package/tests/a2a-protocol.test.ts +285 -285
- package/tests/agui-protocol.test.ts +246 -246
- package/tests/api-server.test.ts +148 -148
- package/tests/approvals.test.ts +89 -89
- package/tests/audio.test.ts +40 -40
- package/tests/brain-seed-extended.test.ts +490 -490
- package/tests/brain-seed.test.ts +239 -239
- package/tests/browser.test.ts +179 -179
- package/tests/channels/discord.test.ts +79 -79
- package/tests/channels/email.test.ts +148 -148
- package/tests/channels/feishu.test.ts +123 -123
- package/tests/channels/telegram.test.ts +129 -129
- package/tests/channels/websocket.test.ts +53 -53
- package/tests/channels/wechat.test.ts +170 -170
- package/tests/channels-extra.test.ts +45 -45
- package/tests/chat-cli.test.ts +160 -160
- package/tests/cli.test.ts +46 -46
- package/tests/context-compressor.test.ts +172 -172
- package/tests/context-refs.test.ts +121 -121
- package/tests/cron-engine.test.ts +101 -101
- package/tests/daemon.test.ts +135 -135
- package/tests/deepbrain-wire.test.ts +234 -234
- package/tests/deploy-and-dag.test.ts +196 -196
- package/tests/doctor.test.ts +38 -38
- package/tests/document-processor.test.ts +69 -69
- package/tests/e2e-nocode.test.ts +442 -442
- package/tests/elevated.test.ts +69 -69
- package/tests/eval.test.ts +173 -173
- package/tests/gateway.test.ts +63 -63
- package/tests/guardrails.test.ts +177 -177
- package/tests/home-assistant.test.ts +40 -40
- package/tests/hooks.test.ts +79 -79
- package/tests/ide-bridge.test.ts +38 -38
- package/tests/image-generator.test.ts +84 -84
- package/tests/init-role.test.ts +124 -124
- package/tests/integrations.test.ts +249 -249
- package/tests/mcp-client.test.ts +92 -92
- package/tests/mcp-server.test.ts +178 -178
- package/tests/mcp-servers.test.ts +260 -260
- package/tests/node-network.test.ts +74 -74
- package/tests/plugin-a2a-enhanced.test.ts +230 -230
- package/tests/profiles.test.ts +61 -61
- package/tests/publish.test.ts +231 -231
- package/tests/rl-tools.test.ts +93 -93
- package/tests/sandbox-manager.test.ts +46 -46
- package/tests/scheduler.test.ts +200 -200
- package/tests/secrets.test.ts +107 -107
- package/tests/security-enhanced.test.ts +233 -233
- package/tests/settings-api.test.ts +148 -148
- package/tests/setup.test.ts +73 -73
- package/tests/subagent.test.ts +193 -193
- package/tests/telegram-discord.test.ts +60 -60
- package/tests/telemetry.test.ts +186 -186
- package/tests/user-profiler.test.ts +169 -169
- package/tests/v090-features.test.ts +254 -254
- package/tests/vision.test.ts +61 -61
- package/tests/voice-call.test.ts +47 -47
- package/tests/voice-enhanced.test.ts +169 -169
- package/tests/voice-interaction.test.ts +38 -38
- package/tests/web-search.test.ts +155 -155
- package/tests/workflow-graph.test.ts +279 -279
- package/tutorial/customer-service-agent/README.md +612 -612
- package/tutorial/customer-service-agent/SOUL.md +26 -26
- package/tutorial/customer-service-agent/agent.yaml +63 -63
- package/tutorial/customer-service-agent/package.json +19 -19
- package/tutorial/customer-service-agent/src/index.ts +69 -69
- package/tutorial/customer-service-agent/src/skills/faq.ts +27 -27
- package/tutorial/customer-service-agent/src/skills/ticket.ts +22 -22
- package/tutorial/customer-service-agent/tsconfig.json +14 -14
|
@@ -1,249 +1,249 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
getAllIntegrationTools, getIntegrationTool,
|
|
4
|
-
SlackTool, EmailSendTool, WebhookTool,
|
|
5
|
-
NotionTool, GitHubTool, JiraTool, CalendarTool, TrelloTool,
|
|
6
|
-
WebSearchTool, WebScraperTool, DatabaseTool, VectorSearchTool,
|
|
7
|
-
CodeExecutionTool, GitTool, NpmTool,
|
|
8
|
-
ImageGenerationTool, PDFReaderTool, CSVAnalyzerTool,
|
|
9
|
-
SummarizerTool, TranslatorTool,
|
|
10
|
-
} from '../src/tools/integrations';
|
|
11
|
-
|
|
12
|
-
describe('Integration Tools Registry', () => {
|
|
13
|
-
it('should return all 20 tools', () => {
|
|
14
|
-
const tools = getAllIntegrationTools();
|
|
15
|
-
expect(tools).toHaveLength(20);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should find tools by name', () => {
|
|
19
|
-
expect(getIntegrationTool('slack')).toBe(SlackTool);
|
|
20
|
-
expect(getIntegrationTool('github')).toBe(GitHubTool);
|
|
21
|
-
expect(getIntegrationTool('nonexistent')).toBeUndefined();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('each tool has required properties', () => {
|
|
25
|
-
const tools = getAllIntegrationTools();
|
|
26
|
-
for (const tool of tools) {
|
|
27
|
-
expect(tool.name).toBeTruthy();
|
|
28
|
-
expect(tool.description).toBeTruthy();
|
|
29
|
-
expect(tool.inputSchema).toBeDefined();
|
|
30
|
-
expect(typeof tool.execute).toBe('function');
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('all tool names are unique', () => {
|
|
35
|
-
const tools = getAllIntegrationTools();
|
|
36
|
-
const names = tools.map((t) => t.name);
|
|
37
|
-
expect(new Set(names).size).toBe(names.length);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('SlackTool', () => {
|
|
42
|
-
it('should require action', async () => {
|
|
43
|
-
const r = await SlackTool.execute({});
|
|
44
|
-
expect(r.content).toContain('Unknown action');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should require text for send_message', async () => {
|
|
48
|
-
const r = await SlackTool.execute({ action: 'send_message' });
|
|
49
|
-
expect(r.isError).toBe(true);
|
|
50
|
-
expect(r.content).toContain('text is required');
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe('EmailSendTool', () => {
|
|
55
|
-
it('should require SMTP env vars', async () => {
|
|
56
|
-
const r = await EmailSendTool.execute({ to: 'a@b.com', subject: 'test', body: 'hi' });
|
|
57
|
-
expect(r.isError).toBe(true);
|
|
58
|
-
expect(r.content).toContain('SMTP_HOST');
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
describe('WebhookTool', () => {
|
|
63
|
-
it('should require url', async () => {
|
|
64
|
-
const r = await WebhookTool.execute({});
|
|
65
|
-
expect(r.isError).toBe(true);
|
|
66
|
-
expect(r.content).toContain('url is required');
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('NotionTool', () => {
|
|
71
|
-
it('should require API key', async () => {
|
|
72
|
-
const r = await NotionTool.execute({ action: 'search', query: 'test' });
|
|
73
|
-
expect(r.isError).toBe(true);
|
|
74
|
-
expect(r.content).toContain('NOTION_API_KEY');
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('GitHubTool', () => {
|
|
79
|
-
it('should require GITHUB_TOKEN', async () => {
|
|
80
|
-
const r = await GitHubTool.execute({ action: 'list_issues', owner: 'a', repo: 'b' });
|
|
81
|
-
expect(r.isError).toBe(true);
|
|
82
|
-
expect(r.content).toContain('GITHUB_TOKEN');
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should validate create_issue params', async () => {
|
|
86
|
-
process.env.GITHUB_TOKEN = 'test';
|
|
87
|
-
const r = await GitHubTool.execute({ action: 'create_issue' });
|
|
88
|
-
expect(r.isError).toBe(true);
|
|
89
|
-
expect(r.content).toContain('owner, repo, title required');
|
|
90
|
-
delete process.env.GITHUB_TOKEN;
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
describe('JiraTool', () => {
|
|
95
|
-
it('should require Jira env vars', async () => {
|
|
96
|
-
const r = await JiraTool.execute({ action: 'search', jql: 'test' });
|
|
97
|
-
expect(r.isError).toBe(true);
|
|
98
|
-
expect(r.content).toContain('JIRA_URL');
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('CalendarTool', () => {
|
|
103
|
-
it('should require GOOGLE_ACCESS_TOKEN', async () => {
|
|
104
|
-
const r = await CalendarTool.execute({ action: 'list_events' });
|
|
105
|
-
expect(r.isError).toBe(true);
|
|
106
|
-
expect(r.content).toContain('GOOGLE_ACCESS_TOKEN');
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe('TrelloTool', () => {
|
|
111
|
-
it('should require API key and token', async () => {
|
|
112
|
-
const r = await TrelloTool.execute({ action: 'list_boards' });
|
|
113
|
-
expect(r.isError).toBe(true);
|
|
114
|
-
expect(r.content).toContain('TRELLO_API_KEY');
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
describe('WebSearchTool', () => {
|
|
119
|
-
it('should require query', async () => {
|
|
120
|
-
const r = await WebSearchTool.execute({});
|
|
121
|
-
expect(r.isError).toBe(true);
|
|
122
|
-
expect(r.content).toContain('query required');
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should require API key', async () => {
|
|
126
|
-
const r = await WebSearchTool.execute({ query: 'test' });
|
|
127
|
-
expect(r.isError).toBe(true);
|
|
128
|
-
expect(r.content).toContain('No search API key');
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
describe('WebScraperTool', () => {
|
|
133
|
-
it('should require url', async () => {
|
|
134
|
-
const r = await WebScraperTool.execute({});
|
|
135
|
-
expect(r.isError).toBe(true);
|
|
136
|
-
expect(r.content).toContain('url required');
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
describe('DatabaseTool', () => {
|
|
141
|
-
it('should require connection URL', async () => {
|
|
142
|
-
const r = await DatabaseTool.execute({ query: 'SELECT 1' });
|
|
143
|
-
expect(r.isError).toBe(true);
|
|
144
|
-
expect(r.content).toContain('DATABASE_URL');
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should block destructive queries by default', async () => {
|
|
148
|
-
process.env.DATABASE_URL = 'test.db';
|
|
149
|
-
const r = await DatabaseTool.execute({ query: 'DROP TABLE users' });
|
|
150
|
-
expect(r.isError).toBe(true);
|
|
151
|
-
expect(r.content).toContain('Destructive queries blocked');
|
|
152
|
-
delete process.env.DATABASE_URL;
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
describe('VectorSearchTool', () => {
|
|
157
|
-
it('should require DEEPBRAIN_URL', async () => {
|
|
158
|
-
const r = await VectorSearchTool.execute({ query: 'test' });
|
|
159
|
-
expect(r.isError).toBe(true);
|
|
160
|
-
expect(r.content).toContain('DEEPBRAIN_URL');
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
describe('CodeExecutionTool', () => {
|
|
165
|
-
it('should require code', async () => {
|
|
166
|
-
const r = await CodeExecutionTool.execute({ language: 'javascript', code: '' });
|
|
167
|
-
expect(r.isError).toBe(true);
|
|
168
|
-
expect(r.content).toContain('code required');
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('should reject unknown language', async () => {
|
|
172
|
-
const r = await CodeExecutionTool.execute({ language: 'ruby', code: 'puts 1' });
|
|
173
|
-
expect(r.isError).toBe(true);
|
|
174
|
-
expect(r.content).toContain('Unsupported language');
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
describe('GitTool', () => {
|
|
179
|
-
it('should require message for commit', async () => {
|
|
180
|
-
const r = await GitTool.execute({ action: 'commit' });
|
|
181
|
-
expect(r.isError).toBe(true);
|
|
182
|
-
expect(r.content).toContain('message required');
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
describe('NpmTool', () => {
|
|
187
|
-
it('should reject install action', async () => {
|
|
188
|
-
const r = await NpmTool.execute({ action: 'install', package: 'lodash' });
|
|
189
|
-
expect(r.isError).toBe(true);
|
|
190
|
-
expect(r.content).toContain('not supported');
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
describe('ImageGenerationTool', () => {
|
|
195
|
-
it('should require prompt', async () => {
|
|
196
|
-
const r = await ImageGenerationTool.execute({});
|
|
197
|
-
expect(r.isError).toBe(true);
|
|
198
|
-
expect(r.content).toContain('prompt required');
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
describe('PDFReaderTool', () => {
|
|
203
|
-
it('should require file_path or url', async () => {
|
|
204
|
-
const r = await PDFReaderTool.execute({});
|
|
205
|
-
expect(r.isError).toBe(true);
|
|
206
|
-
expect(r.content).toContain('file_path or url required');
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
describe('CSVAnalyzerTool', () => {
|
|
211
|
-
it('should require file_path or data', async () => {
|
|
212
|
-
const r = await CSVAnalyzerTool.execute({});
|
|
213
|
-
expect(r.isError).toBe(true);
|
|
214
|
-
expect(r.content).toContain('file_path or data required');
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it('should parse inline CSV', async () => {
|
|
218
|
-
const r = await CSVAnalyzerTool.execute({ data: 'name,age\nAlice,30\nBob,25', action: 'parse' });
|
|
219
|
-
expect(r.isError).toBeUndefined();
|
|
220
|
-
expect(r.content).toContain('2 rows');
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('should aggregate CSV', async () => {
|
|
224
|
-
const r = await CSVAnalyzerTool.execute({ data: 'name,score\nA,10\nB,20\nC,30', action: 'aggregate', column: 'score', operation: 'sum' });
|
|
225
|
-
expect(r.content).toContain('60');
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
describe('SummarizerTool', () => {
|
|
230
|
-
it('should require text', async () => {
|
|
231
|
-
const r = await SummarizerTool.execute({});
|
|
232
|
-
expect(r.isError).toBe(true);
|
|
233
|
-
expect(r.content).toContain('text required');
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it('should require API key', async () => {
|
|
237
|
-
const r = await SummarizerTool.execute({ text: 'Hello world' });
|
|
238
|
-
expect(r.isError).toBe(true);
|
|
239
|
-
expect(r.content).toContain('OPENAI_API_KEY');
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
describe('TranslatorTool', () => {
|
|
244
|
-
it('should require text and target language', async () => {
|
|
245
|
-
const r = await TranslatorTool.execute({});
|
|
246
|
-
expect(r.isError).toBe(true);
|
|
247
|
-
expect(r.content).toContain('text and to are required');
|
|
248
|
-
});
|
|
249
|
-
});
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
getAllIntegrationTools, getIntegrationTool,
|
|
4
|
+
SlackTool, EmailSendTool, WebhookTool,
|
|
5
|
+
NotionTool, GitHubTool, JiraTool, CalendarTool, TrelloTool,
|
|
6
|
+
WebSearchTool, WebScraperTool, DatabaseTool, VectorSearchTool,
|
|
7
|
+
CodeExecutionTool, GitTool, NpmTool,
|
|
8
|
+
ImageGenerationTool, PDFReaderTool, CSVAnalyzerTool,
|
|
9
|
+
SummarizerTool, TranslatorTool,
|
|
10
|
+
} from '../src/tools/integrations';
|
|
11
|
+
|
|
12
|
+
describe('Integration Tools Registry', () => {
|
|
13
|
+
it('should return all 20 tools', () => {
|
|
14
|
+
const tools = getAllIntegrationTools();
|
|
15
|
+
expect(tools).toHaveLength(20);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should find tools by name', () => {
|
|
19
|
+
expect(getIntegrationTool('slack')).toBe(SlackTool);
|
|
20
|
+
expect(getIntegrationTool('github')).toBe(GitHubTool);
|
|
21
|
+
expect(getIntegrationTool('nonexistent')).toBeUndefined();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('each tool has required properties', () => {
|
|
25
|
+
const tools = getAllIntegrationTools();
|
|
26
|
+
for (const tool of tools) {
|
|
27
|
+
expect(tool.name).toBeTruthy();
|
|
28
|
+
expect(tool.description).toBeTruthy();
|
|
29
|
+
expect(tool.inputSchema).toBeDefined();
|
|
30
|
+
expect(typeof tool.execute).toBe('function');
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('all tool names are unique', () => {
|
|
35
|
+
const tools = getAllIntegrationTools();
|
|
36
|
+
const names = tools.map((t) => t.name);
|
|
37
|
+
expect(new Set(names).size).toBe(names.length);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('SlackTool', () => {
|
|
42
|
+
it('should require action', async () => {
|
|
43
|
+
const r = await SlackTool.execute({});
|
|
44
|
+
expect(r.content).toContain('Unknown action');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should require text for send_message', async () => {
|
|
48
|
+
const r = await SlackTool.execute({ action: 'send_message' });
|
|
49
|
+
expect(r.isError).toBe(true);
|
|
50
|
+
expect(r.content).toContain('text is required');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('EmailSendTool', () => {
|
|
55
|
+
it('should require SMTP env vars', async () => {
|
|
56
|
+
const r = await EmailSendTool.execute({ to: 'a@b.com', subject: 'test', body: 'hi' });
|
|
57
|
+
expect(r.isError).toBe(true);
|
|
58
|
+
expect(r.content).toContain('SMTP_HOST');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('WebhookTool', () => {
|
|
63
|
+
it('should require url', async () => {
|
|
64
|
+
const r = await WebhookTool.execute({});
|
|
65
|
+
expect(r.isError).toBe(true);
|
|
66
|
+
expect(r.content).toContain('url is required');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('NotionTool', () => {
|
|
71
|
+
it('should require API key', async () => {
|
|
72
|
+
const r = await NotionTool.execute({ action: 'search', query: 'test' });
|
|
73
|
+
expect(r.isError).toBe(true);
|
|
74
|
+
expect(r.content).toContain('NOTION_API_KEY');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('GitHubTool', () => {
|
|
79
|
+
it('should require GITHUB_TOKEN', async () => {
|
|
80
|
+
const r = await GitHubTool.execute({ action: 'list_issues', owner: 'a', repo: 'b' });
|
|
81
|
+
expect(r.isError).toBe(true);
|
|
82
|
+
expect(r.content).toContain('GITHUB_TOKEN');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should validate create_issue params', async () => {
|
|
86
|
+
process.env.GITHUB_TOKEN = 'test';
|
|
87
|
+
const r = await GitHubTool.execute({ action: 'create_issue' });
|
|
88
|
+
expect(r.isError).toBe(true);
|
|
89
|
+
expect(r.content).toContain('owner, repo, title required');
|
|
90
|
+
delete process.env.GITHUB_TOKEN;
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('JiraTool', () => {
|
|
95
|
+
it('should require Jira env vars', async () => {
|
|
96
|
+
const r = await JiraTool.execute({ action: 'search', jql: 'test' });
|
|
97
|
+
expect(r.isError).toBe(true);
|
|
98
|
+
expect(r.content).toContain('JIRA_URL');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('CalendarTool', () => {
|
|
103
|
+
it('should require GOOGLE_ACCESS_TOKEN', async () => {
|
|
104
|
+
const r = await CalendarTool.execute({ action: 'list_events' });
|
|
105
|
+
expect(r.isError).toBe(true);
|
|
106
|
+
expect(r.content).toContain('GOOGLE_ACCESS_TOKEN');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('TrelloTool', () => {
|
|
111
|
+
it('should require API key and token', async () => {
|
|
112
|
+
const r = await TrelloTool.execute({ action: 'list_boards' });
|
|
113
|
+
expect(r.isError).toBe(true);
|
|
114
|
+
expect(r.content).toContain('TRELLO_API_KEY');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('WebSearchTool', () => {
|
|
119
|
+
it('should require query', async () => {
|
|
120
|
+
const r = await WebSearchTool.execute({});
|
|
121
|
+
expect(r.isError).toBe(true);
|
|
122
|
+
expect(r.content).toContain('query required');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should require API key', async () => {
|
|
126
|
+
const r = await WebSearchTool.execute({ query: 'test' });
|
|
127
|
+
expect(r.isError).toBe(true);
|
|
128
|
+
expect(r.content).toContain('No search API key');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe('WebScraperTool', () => {
|
|
133
|
+
it('should require url', async () => {
|
|
134
|
+
const r = await WebScraperTool.execute({});
|
|
135
|
+
expect(r.isError).toBe(true);
|
|
136
|
+
expect(r.content).toContain('url required');
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe('DatabaseTool', () => {
|
|
141
|
+
it('should require connection URL', async () => {
|
|
142
|
+
const r = await DatabaseTool.execute({ query: 'SELECT 1' });
|
|
143
|
+
expect(r.isError).toBe(true);
|
|
144
|
+
expect(r.content).toContain('DATABASE_URL');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should block destructive queries by default', async () => {
|
|
148
|
+
process.env.DATABASE_URL = 'test.db';
|
|
149
|
+
const r = await DatabaseTool.execute({ query: 'DROP TABLE users' });
|
|
150
|
+
expect(r.isError).toBe(true);
|
|
151
|
+
expect(r.content).toContain('Destructive queries blocked');
|
|
152
|
+
delete process.env.DATABASE_URL;
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('VectorSearchTool', () => {
|
|
157
|
+
it('should require DEEPBRAIN_URL', async () => {
|
|
158
|
+
const r = await VectorSearchTool.execute({ query: 'test' });
|
|
159
|
+
expect(r.isError).toBe(true);
|
|
160
|
+
expect(r.content).toContain('DEEPBRAIN_URL');
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe('CodeExecutionTool', () => {
|
|
165
|
+
it('should require code', async () => {
|
|
166
|
+
const r = await CodeExecutionTool.execute({ language: 'javascript', code: '' });
|
|
167
|
+
expect(r.isError).toBe(true);
|
|
168
|
+
expect(r.content).toContain('code required');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should reject unknown language', async () => {
|
|
172
|
+
const r = await CodeExecutionTool.execute({ language: 'ruby', code: 'puts 1' });
|
|
173
|
+
expect(r.isError).toBe(true);
|
|
174
|
+
expect(r.content).toContain('Unsupported language');
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe('GitTool', () => {
|
|
179
|
+
it('should require message for commit', async () => {
|
|
180
|
+
const r = await GitTool.execute({ action: 'commit' });
|
|
181
|
+
expect(r.isError).toBe(true);
|
|
182
|
+
expect(r.content).toContain('message required');
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('NpmTool', () => {
|
|
187
|
+
it('should reject install action', async () => {
|
|
188
|
+
const r = await NpmTool.execute({ action: 'install', package: 'lodash' });
|
|
189
|
+
expect(r.isError).toBe(true);
|
|
190
|
+
expect(r.content).toContain('not supported');
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe('ImageGenerationTool', () => {
|
|
195
|
+
it('should require prompt', async () => {
|
|
196
|
+
const r = await ImageGenerationTool.execute({});
|
|
197
|
+
expect(r.isError).toBe(true);
|
|
198
|
+
expect(r.content).toContain('prompt required');
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe('PDFReaderTool', () => {
|
|
203
|
+
it('should require file_path or url', async () => {
|
|
204
|
+
const r = await PDFReaderTool.execute({});
|
|
205
|
+
expect(r.isError).toBe(true);
|
|
206
|
+
expect(r.content).toContain('file_path or url required');
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe('CSVAnalyzerTool', () => {
|
|
211
|
+
it('should require file_path or data', async () => {
|
|
212
|
+
const r = await CSVAnalyzerTool.execute({});
|
|
213
|
+
expect(r.isError).toBe(true);
|
|
214
|
+
expect(r.content).toContain('file_path or data required');
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should parse inline CSV', async () => {
|
|
218
|
+
const r = await CSVAnalyzerTool.execute({ data: 'name,age\nAlice,30\nBob,25', action: 'parse' });
|
|
219
|
+
expect(r.isError).toBeUndefined();
|
|
220
|
+
expect(r.content).toContain('2 rows');
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('should aggregate CSV', async () => {
|
|
224
|
+
const r = await CSVAnalyzerTool.execute({ data: 'name,score\nA,10\nB,20\nC,30', action: 'aggregate', column: 'score', operation: 'sum' });
|
|
225
|
+
expect(r.content).toContain('60');
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe('SummarizerTool', () => {
|
|
230
|
+
it('should require text', async () => {
|
|
231
|
+
const r = await SummarizerTool.execute({});
|
|
232
|
+
expect(r.isError).toBe(true);
|
|
233
|
+
expect(r.content).toContain('text required');
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('should require API key', async () => {
|
|
237
|
+
const r = await SummarizerTool.execute({ text: 'Hello world' });
|
|
238
|
+
expect(r.isError).toBe(true);
|
|
239
|
+
expect(r.content).toContain('OPENAI_API_KEY');
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
describe('TranslatorTool', () => {
|
|
244
|
+
it('should require text and target language', async () => {
|
|
245
|
+
const r = await TranslatorTool.execute({});
|
|
246
|
+
expect(r.isError).toBe(true);
|
|
247
|
+
expect(r.content).toContain('text and to are required');
|
|
248
|
+
});
|
|
249
|
+
});
|