opc-agent 4.1.0 → 4.1.2
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/USABILITY-ISSUES.md +73 -0
- package/dist/channels/web.js +8 -2
- package/dist/channels/wechat.js +6 -6
- package/dist/cli.js +200 -85
- package/dist/core/runtime.js +37 -15
- package/dist/deploy/index.js +56 -56
- package/dist/doctor.d.ts +1 -0
- package/dist/doctor.js +105 -10
- package/dist/memory/deepbrain.d.ts +1 -1
- package/dist/memory/deepbrain.js +95 -4
- package/dist/scheduler/cron-engine.js +3 -36
- 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/web.ts +8 -2
- 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/cli.ts +195 -92
- 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/runtime.ts +25 -0
- 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 +98 -11
- 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/deepbrain.ts +99 -5
- 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
package/tests/chat-cli.test.ts
CHANGED
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Tests for CLI chat slash command handling logic.
|
|
5
|
-
* We test the command parsing logic directly since the chat command
|
|
6
|
-
* is tightly coupled to readline/process.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// Extract the slash command logic for testing
|
|
10
|
-
function createSlashHandler(options: {
|
|
11
|
-
agentName?: string;
|
|
12
|
-
agentVersion?: string;
|
|
13
|
-
providerName?: string;
|
|
14
|
-
model?: string;
|
|
15
|
-
skillNames?: string[];
|
|
16
|
-
history?: { role: string; content: string }[];
|
|
17
|
-
}) {
|
|
18
|
-
const {
|
|
19
|
-
agentName = 'test-agent',
|
|
20
|
-
agentVersion = '1.0.0',
|
|
21
|
-
providerName = 'openai',
|
|
22
|
-
model = 'gpt-4',
|
|
23
|
-
skillNames = [],
|
|
24
|
-
history = [],
|
|
25
|
-
} = options;
|
|
26
|
-
|
|
27
|
-
const output: string[] = [];
|
|
28
|
-
const log = (msg: string) => output.push(msg);
|
|
29
|
-
|
|
30
|
-
const handleSlashCommand = (cmd: string): boolean => {
|
|
31
|
-
const lower = cmd.toLowerCase().trim();
|
|
32
|
-
if (lower === '/quit' || lower === '/exit') {
|
|
33
|
-
output.push('QUIT');
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
if (lower === '/help') {
|
|
37
|
-
log('Available commands:');
|
|
38
|
-
log('/help /quit /clear /skills /memory /info');
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
if (lower === '/clear') {
|
|
42
|
-
history.length = 0;
|
|
43
|
-
log('Conversation history cleared.');
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
|
-
if (lower === '/skills') {
|
|
47
|
-
if (skillNames.length === 0) {
|
|
48
|
-
log('No skills registered.');
|
|
49
|
-
} else {
|
|
50
|
-
log('Registered skills:');
|
|
51
|
-
skillNames.forEach(s => log(`• ${s}`));
|
|
52
|
-
}
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
if (lower === '/info') {
|
|
56
|
-
log(`Name: ${agentName}`);
|
|
57
|
-
log(`Version: ${agentVersion}`);
|
|
58
|
-
log(`Provider: ${providerName}`);
|
|
59
|
-
log(`Model: ${model}`);
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
return false;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
return { handleSlashCommand, output, history };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
describe('Chat CLI slash commands', () => {
|
|
69
|
-
it('/help returns command list', () => {
|
|
70
|
-
const { handleSlashCommand, output } = createSlashHandler({});
|
|
71
|
-
const handled = handleSlashCommand('/help');
|
|
72
|
-
expect(handled).toBe(true);
|
|
73
|
-
expect(output.some(l => l.includes('commands'))).toBe(true);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('/clear resets history', () => {
|
|
77
|
-
const history = [{ role: 'user', content: 'hi' }, { role: 'assistant', content: 'hello' }];
|
|
78
|
-
const { handleSlashCommand } = createSlashHandler({ history });
|
|
79
|
-
handleSlashCommand('/clear');
|
|
80
|
-
expect(history).toHaveLength(0);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('/skills lists skills', () => {
|
|
84
|
-
const { handleSlashCommand, output } = createSlashHandler({ skillNames: ['echo', 'search'] });
|
|
85
|
-
handleSlashCommand('/skills');
|
|
86
|
-
expect(output.some(l => l.includes('echo'))).toBe(true);
|
|
87
|
-
expect(output.some(l => l.includes('search'))).toBe(true);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('/skills with no skills shows empty message', () => {
|
|
91
|
-
const { handleSlashCommand, output } = createSlashHandler({ skillNames: [] });
|
|
92
|
-
handleSlashCommand('/skills');
|
|
93
|
-
expect(output.some(l => l.includes('No skills'))).toBe(true);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('/info shows agent info', () => {
|
|
97
|
-
const { handleSlashCommand, output } = createSlashHandler({ agentName: 'MyBot', model: 'gpt-4o' });
|
|
98
|
-
handleSlashCommand('/info');
|
|
99
|
-
expect(output.some(l => l.includes('MyBot'))).toBe(true);
|
|
100
|
-
expect(output.some(l => l.includes('gpt-4o'))).toBe(true);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('/quit sets quit flag', () => {
|
|
104
|
-
const { handleSlashCommand, output } = createSlashHandler({});
|
|
105
|
-
handleSlashCommand('/quit');
|
|
106
|
-
expect(output).toContain('QUIT');
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('/exit also works as quit', () => {
|
|
110
|
-
const { handleSlashCommand, output } = createSlashHandler({});
|
|
111
|
-
handleSlashCommand('/exit');
|
|
112
|
-
expect(output).toContain('QUIT');
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('unknown slash command returns false', () => {
|
|
116
|
-
const { handleSlashCommand } = createSlashHandler({});
|
|
117
|
-
expect(handleSlashCommand('/unknown')).toBe(false);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('non-slash text returns false', () => {
|
|
121
|
-
const { handleSlashCommand } = createSlashHandler({});
|
|
122
|
-
expect(handleSlashCommand('hello world')).toBe(false);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('case insensitive: /HELP works', () => {
|
|
126
|
-
const { handleSlashCommand, output } = createSlashHandler({});
|
|
127
|
-
expect(handleSlashCommand('/HELP')).toBe(true);
|
|
128
|
-
expect(output.length).toBeGreaterThan(0);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('whitespace trimmed: " /help " works', () => {
|
|
132
|
-
const { handleSlashCommand, output } = createSlashHandler({});
|
|
133
|
-
expect(handleSlashCommand(' /help ')).toBe(true);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('empty input handling', () => {
|
|
137
|
-
const text = ' '.trim();
|
|
138
|
-
expect(text).toBe('');
|
|
139
|
-
// Empty input should be skipped (no slash command)
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('banner would contain agent name', () => {
|
|
143
|
-
const agentName = 'MyTestAgent';
|
|
144
|
-
const banner = `OPC Agent - Interactive Chat - ${agentName}`;
|
|
145
|
-
expect(banner).toContain(agentName);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it('/clear then history is empty', () => {
|
|
149
|
-
const history = [{ role: 'user', content: 'msg1' }];
|
|
150
|
-
const { handleSlashCommand } = createSlashHandler({ history });
|
|
151
|
-
expect(history).toHaveLength(1);
|
|
152
|
-
handleSlashCommand('/clear');
|
|
153
|
-
expect(history).toHaveLength(0);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('message without slash goes to agent (not handled by slash handler)', () => {
|
|
157
|
-
const { handleSlashCommand } = createSlashHandler({});
|
|
158
|
-
expect(handleSlashCommand('tell me a joke')).toBe(false);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tests for CLI chat slash command handling logic.
|
|
5
|
+
* We test the command parsing logic directly since the chat command
|
|
6
|
+
* is tightly coupled to readline/process.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Extract the slash command logic for testing
|
|
10
|
+
function createSlashHandler(options: {
|
|
11
|
+
agentName?: string;
|
|
12
|
+
agentVersion?: string;
|
|
13
|
+
providerName?: string;
|
|
14
|
+
model?: string;
|
|
15
|
+
skillNames?: string[];
|
|
16
|
+
history?: { role: string; content: string }[];
|
|
17
|
+
}) {
|
|
18
|
+
const {
|
|
19
|
+
agentName = 'test-agent',
|
|
20
|
+
agentVersion = '1.0.0',
|
|
21
|
+
providerName = 'openai',
|
|
22
|
+
model = 'gpt-4',
|
|
23
|
+
skillNames = [],
|
|
24
|
+
history = [],
|
|
25
|
+
} = options;
|
|
26
|
+
|
|
27
|
+
const output: string[] = [];
|
|
28
|
+
const log = (msg: string) => output.push(msg);
|
|
29
|
+
|
|
30
|
+
const handleSlashCommand = (cmd: string): boolean => {
|
|
31
|
+
const lower = cmd.toLowerCase().trim();
|
|
32
|
+
if (lower === '/quit' || lower === '/exit') {
|
|
33
|
+
output.push('QUIT');
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
if (lower === '/help') {
|
|
37
|
+
log('Available commands:');
|
|
38
|
+
log('/help /quit /clear /skills /memory /info');
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
if (lower === '/clear') {
|
|
42
|
+
history.length = 0;
|
|
43
|
+
log('Conversation history cleared.');
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
if (lower === '/skills') {
|
|
47
|
+
if (skillNames.length === 0) {
|
|
48
|
+
log('No skills registered.');
|
|
49
|
+
} else {
|
|
50
|
+
log('Registered skills:');
|
|
51
|
+
skillNames.forEach(s => log(`• ${s}`));
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (lower === '/info') {
|
|
56
|
+
log(`Name: ${agentName}`);
|
|
57
|
+
log(`Version: ${agentVersion}`);
|
|
58
|
+
log(`Provider: ${providerName}`);
|
|
59
|
+
log(`Model: ${model}`);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return { handleSlashCommand, output, history };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
describe('Chat CLI slash commands', () => {
|
|
69
|
+
it('/help returns command list', () => {
|
|
70
|
+
const { handleSlashCommand, output } = createSlashHandler({});
|
|
71
|
+
const handled = handleSlashCommand('/help');
|
|
72
|
+
expect(handled).toBe(true);
|
|
73
|
+
expect(output.some(l => l.includes('commands'))).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('/clear resets history', () => {
|
|
77
|
+
const history = [{ role: 'user', content: 'hi' }, { role: 'assistant', content: 'hello' }];
|
|
78
|
+
const { handleSlashCommand } = createSlashHandler({ history });
|
|
79
|
+
handleSlashCommand('/clear');
|
|
80
|
+
expect(history).toHaveLength(0);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('/skills lists skills', () => {
|
|
84
|
+
const { handleSlashCommand, output } = createSlashHandler({ skillNames: ['echo', 'search'] });
|
|
85
|
+
handleSlashCommand('/skills');
|
|
86
|
+
expect(output.some(l => l.includes('echo'))).toBe(true);
|
|
87
|
+
expect(output.some(l => l.includes('search'))).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('/skills with no skills shows empty message', () => {
|
|
91
|
+
const { handleSlashCommand, output } = createSlashHandler({ skillNames: [] });
|
|
92
|
+
handleSlashCommand('/skills');
|
|
93
|
+
expect(output.some(l => l.includes('No skills'))).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('/info shows agent info', () => {
|
|
97
|
+
const { handleSlashCommand, output } = createSlashHandler({ agentName: 'MyBot', model: 'gpt-4o' });
|
|
98
|
+
handleSlashCommand('/info');
|
|
99
|
+
expect(output.some(l => l.includes('MyBot'))).toBe(true);
|
|
100
|
+
expect(output.some(l => l.includes('gpt-4o'))).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('/quit sets quit flag', () => {
|
|
104
|
+
const { handleSlashCommand, output } = createSlashHandler({});
|
|
105
|
+
handleSlashCommand('/quit');
|
|
106
|
+
expect(output).toContain('QUIT');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('/exit also works as quit', () => {
|
|
110
|
+
const { handleSlashCommand, output } = createSlashHandler({});
|
|
111
|
+
handleSlashCommand('/exit');
|
|
112
|
+
expect(output).toContain('QUIT');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('unknown slash command returns false', () => {
|
|
116
|
+
const { handleSlashCommand } = createSlashHandler({});
|
|
117
|
+
expect(handleSlashCommand('/unknown')).toBe(false);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('non-slash text returns false', () => {
|
|
121
|
+
const { handleSlashCommand } = createSlashHandler({});
|
|
122
|
+
expect(handleSlashCommand('hello world')).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('case insensitive: /HELP works', () => {
|
|
126
|
+
const { handleSlashCommand, output } = createSlashHandler({});
|
|
127
|
+
expect(handleSlashCommand('/HELP')).toBe(true);
|
|
128
|
+
expect(output.length).toBeGreaterThan(0);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('whitespace trimmed: " /help " works', () => {
|
|
132
|
+
const { handleSlashCommand, output } = createSlashHandler({});
|
|
133
|
+
expect(handleSlashCommand(' /help ')).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('empty input handling', () => {
|
|
137
|
+
const text = ' '.trim();
|
|
138
|
+
expect(text).toBe('');
|
|
139
|
+
// Empty input should be skipped (no slash command)
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('banner would contain agent name', () => {
|
|
143
|
+
const agentName = 'MyTestAgent';
|
|
144
|
+
const banner = `OPC Agent - Interactive Chat - ${agentName}`;
|
|
145
|
+
expect(banner).toContain(agentName);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('/clear then history is empty', () => {
|
|
149
|
+
const history = [{ role: 'user', content: 'msg1' }];
|
|
150
|
+
const { handleSlashCommand } = createSlashHandler({ history });
|
|
151
|
+
expect(history).toHaveLength(1);
|
|
152
|
+
handleSlashCommand('/clear');
|
|
153
|
+
expect(history).toHaveLength(0);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('message without slash goes to agent (not handled by slash handler)', () => {
|
|
157
|
+
const { handleSlashCommand } = createSlashHandler({});
|
|
158
|
+
expect(handleSlashCommand('tell me a joke')).toBe(false);
|
|
159
|
+
});
|
|
160
|
+
});
|
package/tests/cli.test.ts
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import * as fs from 'fs';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
|
|
5
|
-
describe('CLI: opc chat slash commands', () => {
|
|
6
|
-
// Test that slash commands are recognized patterns
|
|
7
|
-
const slashCommands = ['/help', '/quit', '/exit', '/clear', '/skills', '/memory', '/info'];
|
|
8
|
-
|
|
9
|
-
it('should define all expected slash commands', () => {
|
|
10
|
-
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
11
|
-
for (const cmd of slashCommands) {
|
|
12
|
-
expect(cliSource).toContain(`'${cmd}'`);
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('chat command should be registered', () => {
|
|
17
|
-
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
18
|
-
expect(cliSource).toContain(".command('chat')");
|
|
19
|
-
expect(cliSource).toContain('Interactive CLI chat with the agent');
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('init command should generate SOUL.md and CONTEXT.md', () => {
|
|
23
|
-
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
24
|
-
expect(cliSource).toContain("'SOUL.md'");
|
|
25
|
-
expect(cliSource).toContain("'CONTEXT.md'");
|
|
26
|
-
expect(cliSource).toContain('# Project Context');
|
|
27
|
-
expect(cliSource).toContain('Personality');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('chat banner should include expected elements', () => {
|
|
31
|
-
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
32
|
-
expect(cliSource).toContain('OPC Agent — Interactive Chat');
|
|
33
|
-
expect(cliSource).toContain('/help for commands');
|
|
34
|
-
expect(cliSource).toContain('╔');
|
|
35
|
-
expect(cliSource).toContain('╚');
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('chat should load SOUL.md and CONTEXT.md', () => {
|
|
39
|
-
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
40
|
-
expect(cliSource).toContain("'SOUL.md'");
|
|
41
|
-
expect(cliSource).toContain("'CONTEXT.md'");
|
|
42
|
-
// Should prepend to system prompt
|
|
43
|
-
expect(cliSource).toContain('soulContent');
|
|
44
|
-
expect(cliSource).toContain('contextContent');
|
|
45
|
-
});
|
|
46
|
-
});
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
describe('CLI: opc chat slash commands', () => {
|
|
6
|
+
// Test that slash commands are recognized patterns
|
|
7
|
+
const slashCommands = ['/help', '/quit', '/exit', '/clear', '/skills', '/memory', '/info'];
|
|
8
|
+
|
|
9
|
+
it('should define all expected slash commands', () => {
|
|
10
|
+
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
11
|
+
for (const cmd of slashCommands) {
|
|
12
|
+
expect(cliSource).toContain(`'${cmd}'`);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('chat command should be registered', () => {
|
|
17
|
+
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
18
|
+
expect(cliSource).toContain(".command('chat')");
|
|
19
|
+
expect(cliSource).toContain('Interactive CLI chat with the agent');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('init command should generate SOUL.md and CONTEXT.md', () => {
|
|
23
|
+
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
24
|
+
expect(cliSource).toContain("'SOUL.md'");
|
|
25
|
+
expect(cliSource).toContain("'CONTEXT.md'");
|
|
26
|
+
expect(cliSource).toContain('# Project Context');
|
|
27
|
+
expect(cliSource).toContain('Personality');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('chat banner should include expected elements', () => {
|
|
31
|
+
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
32
|
+
expect(cliSource).toContain('OPC Agent — Interactive Chat');
|
|
33
|
+
expect(cliSource).toContain('/help for commands');
|
|
34
|
+
expect(cliSource).toContain('╔');
|
|
35
|
+
expect(cliSource).toContain('╚');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('chat should load SOUL.md and CONTEXT.md', () => {
|
|
39
|
+
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'src', 'cli.ts'), 'utf-8');
|
|
40
|
+
expect(cliSource).toContain("'SOUL.md'");
|
|
41
|
+
expect(cliSource).toContain("'CONTEXT.md'");
|
|
42
|
+
// Should prepend to system prompt
|
|
43
|
+
expect(cliSource).toContain('soulContent');
|
|
44
|
+
expect(cliSource).toContain('contextContent');
|
|
45
|
+
});
|
|
46
|
+
});
|