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/rl-tools.test.ts
CHANGED
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
rlRecordTrajectory, rlEvaluateOutcome, rlGetBestStrategy, rlCompareStrategies,
|
|
4
|
-
rlGenerateTrainingData, rlRewardSignal, rlExplorationSuggest, rlUpdatePolicy,
|
|
5
|
-
rlGetStatistics, rlResetEpisode,
|
|
6
|
-
} from '../src/tools/builtin/rl-tools';
|
|
7
|
-
|
|
8
|
-
describe('RL Tools', () => {
|
|
9
|
-
beforeEach(async () => { await rlResetEpisode.execute({}); });
|
|
10
|
-
|
|
11
|
-
it('rl_record_trajectory records actions', async () => {
|
|
12
|
-
const r = await rlRecordTrajectory.execute({ taskType: 'search', action: 'web_search' });
|
|
13
|
-
const data = JSON.parse(r.content);
|
|
14
|
-
expect(data.episodeId).toBeTruthy();
|
|
15
|
-
expect(data.actionsRecorded).toBe(1);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('rl_evaluate_outcome scores episode', async () => {
|
|
19
|
-
await rlRecordTrajectory.execute({ taskType: 'search', action: 'web_search' });
|
|
20
|
-
const r = await rlEvaluateOutcome.execute({ outcome: 'success' });
|
|
21
|
-
const data = JSON.parse(r.content);
|
|
22
|
-
expect(data.score).toBe(1);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('rl_get_best_strategy returns null when no data', async () => {
|
|
26
|
-
const r = await rlGetBestStrategy.execute({ taskType: 'nonexistent_xyz' });
|
|
27
|
-
expect(JSON.parse(r.content).strategy).toBeNull();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('rl_compare_strategies returns breakdown', async () => {
|
|
31
|
-
await rlRecordTrajectory.execute({ taskType: 'coding', action: 'write', outcome: 'success' });
|
|
32
|
-
await rlResetEpisode.execute({});
|
|
33
|
-
await rlRecordTrajectory.execute({ taskType: 'coding', action: 'debug', outcome: 'failure' });
|
|
34
|
-
const r = await rlCompareStrategies.execute({ taskType: 'coding' });
|
|
35
|
-
const data = JSON.parse(r.content);
|
|
36
|
-
expect(data.total).toBe(2);
|
|
37
|
-
expect(data.breakdown.successes).toBe(1);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('rl_generate_training_data exports JSONL', async () => {
|
|
41
|
-
await rlRecordTrajectory.execute({ taskType: 'test', action: 'action1', outcome: 'success' });
|
|
42
|
-
const r = await rlGenerateTrainingData.execute({ taskType: 'test' });
|
|
43
|
-
expect(r.content).toContain('action1');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('rl_reward_signal records reward', async () => {
|
|
47
|
-
await rlRecordTrajectory.execute({ taskType: 'test', action: 'act' });
|
|
48
|
-
const r = await rlRewardSignal.execute({ reward: 1.5 });
|
|
49
|
-
const data = JSON.parse(r.content);
|
|
50
|
-
expect(data.reward).toBe(1.5);
|
|
51
|
-
expect(data.totalReward).toBe(1.5);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('rl_reward_signal fails without episode', async () => {
|
|
55
|
-
const r = await rlRewardSignal.execute({ reward: 1 });
|
|
56
|
-
expect(r.isError).toBe(true);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('rl_exploration_suggest returns suggestions', async () => {
|
|
60
|
-
await rlRecordTrajectory.execute({ taskType: 'explore', action: 'a' });
|
|
61
|
-
await rlResetEpisode.execute({});
|
|
62
|
-
await rlRecordTrajectory.execute({ taskType: 'explore', action: 'b' });
|
|
63
|
-
const r = await rlExplorationSuggest.execute({ taskType: 'explore', currentAction: 'a' });
|
|
64
|
-
const data = JSON.parse(r.content);
|
|
65
|
-
expect(data.suggestions).toContain('b');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('rl_update_policy updates weights', async () => {
|
|
69
|
-
const r = await rlUpdatePolicy.execute({ taskType: 'code', action: 'refactor', weight: 2 });
|
|
70
|
-
const data = JSON.parse(r.content);
|
|
71
|
-
expect(data.weights.refactor).toBe(2);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('rl_get_statistics returns stats', async () => {
|
|
75
|
-
await rlRecordTrajectory.execute({ taskType: 'stats_test', action: 'a', outcome: 'success' });
|
|
76
|
-
const r = await rlGetStatistics.execute({ taskType: 'stats_test' });
|
|
77
|
-
const data = JSON.parse(r.content);
|
|
78
|
-
expect(data.stats_test.total).toBe(1);
|
|
79
|
-
expect(data.stats_test.success).toBe(1);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('rl_reset_episode clears state', async () => {
|
|
83
|
-
await rlRecordTrajectory.execute({ taskType: 'test', action: 'a' });
|
|
84
|
-
const r = await rlResetEpisode.execute({});
|
|
85
|
-
expect(JSON.parse(r.content).hadActiveEpisode).toBe(true);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('trajectory recording accumulates actions', async () => {
|
|
89
|
-
await rlRecordTrajectory.execute({ taskType: 'multi', action: 'step1' });
|
|
90
|
-
const r = await rlRecordTrajectory.execute({ taskType: 'multi', action: 'step2' });
|
|
91
|
-
expect(JSON.parse(r.content).actionsRecorded).toBe(2);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
rlRecordTrajectory, rlEvaluateOutcome, rlGetBestStrategy, rlCompareStrategies,
|
|
4
|
+
rlGenerateTrainingData, rlRewardSignal, rlExplorationSuggest, rlUpdatePolicy,
|
|
5
|
+
rlGetStatistics, rlResetEpisode,
|
|
6
|
+
} from '../src/tools/builtin/rl-tools';
|
|
7
|
+
|
|
8
|
+
describe('RL Tools', () => {
|
|
9
|
+
beforeEach(async () => { await rlResetEpisode.execute({}); });
|
|
10
|
+
|
|
11
|
+
it('rl_record_trajectory records actions', async () => {
|
|
12
|
+
const r = await rlRecordTrajectory.execute({ taskType: 'search', action: 'web_search' });
|
|
13
|
+
const data = JSON.parse(r.content);
|
|
14
|
+
expect(data.episodeId).toBeTruthy();
|
|
15
|
+
expect(data.actionsRecorded).toBe(1);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('rl_evaluate_outcome scores episode', async () => {
|
|
19
|
+
await rlRecordTrajectory.execute({ taskType: 'search', action: 'web_search' });
|
|
20
|
+
const r = await rlEvaluateOutcome.execute({ outcome: 'success' });
|
|
21
|
+
const data = JSON.parse(r.content);
|
|
22
|
+
expect(data.score).toBe(1);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('rl_get_best_strategy returns null when no data', async () => {
|
|
26
|
+
const r = await rlGetBestStrategy.execute({ taskType: 'nonexistent_xyz' });
|
|
27
|
+
expect(JSON.parse(r.content).strategy).toBeNull();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('rl_compare_strategies returns breakdown', async () => {
|
|
31
|
+
await rlRecordTrajectory.execute({ taskType: 'coding', action: 'write', outcome: 'success' });
|
|
32
|
+
await rlResetEpisode.execute({});
|
|
33
|
+
await rlRecordTrajectory.execute({ taskType: 'coding', action: 'debug', outcome: 'failure' });
|
|
34
|
+
const r = await rlCompareStrategies.execute({ taskType: 'coding' });
|
|
35
|
+
const data = JSON.parse(r.content);
|
|
36
|
+
expect(data.total).toBe(2);
|
|
37
|
+
expect(data.breakdown.successes).toBe(1);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('rl_generate_training_data exports JSONL', async () => {
|
|
41
|
+
await rlRecordTrajectory.execute({ taskType: 'test', action: 'action1', outcome: 'success' });
|
|
42
|
+
const r = await rlGenerateTrainingData.execute({ taskType: 'test' });
|
|
43
|
+
expect(r.content).toContain('action1');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('rl_reward_signal records reward', async () => {
|
|
47
|
+
await rlRecordTrajectory.execute({ taskType: 'test', action: 'act' });
|
|
48
|
+
const r = await rlRewardSignal.execute({ reward: 1.5 });
|
|
49
|
+
const data = JSON.parse(r.content);
|
|
50
|
+
expect(data.reward).toBe(1.5);
|
|
51
|
+
expect(data.totalReward).toBe(1.5);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('rl_reward_signal fails without episode', async () => {
|
|
55
|
+
const r = await rlRewardSignal.execute({ reward: 1 });
|
|
56
|
+
expect(r.isError).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('rl_exploration_suggest returns suggestions', async () => {
|
|
60
|
+
await rlRecordTrajectory.execute({ taskType: 'explore', action: 'a' });
|
|
61
|
+
await rlResetEpisode.execute({});
|
|
62
|
+
await rlRecordTrajectory.execute({ taskType: 'explore', action: 'b' });
|
|
63
|
+
const r = await rlExplorationSuggest.execute({ taskType: 'explore', currentAction: 'a' });
|
|
64
|
+
const data = JSON.parse(r.content);
|
|
65
|
+
expect(data.suggestions).toContain('b');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('rl_update_policy updates weights', async () => {
|
|
69
|
+
const r = await rlUpdatePolicy.execute({ taskType: 'code', action: 'refactor', weight: 2 });
|
|
70
|
+
const data = JSON.parse(r.content);
|
|
71
|
+
expect(data.weights.refactor).toBe(2);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('rl_get_statistics returns stats', async () => {
|
|
75
|
+
await rlRecordTrajectory.execute({ taskType: 'stats_test', action: 'a', outcome: 'success' });
|
|
76
|
+
const r = await rlGetStatistics.execute({ taskType: 'stats_test' });
|
|
77
|
+
const data = JSON.parse(r.content);
|
|
78
|
+
expect(data.stats_test.total).toBe(1);
|
|
79
|
+
expect(data.stats_test.success).toBe(1);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('rl_reset_episode clears state', async () => {
|
|
83
|
+
await rlRecordTrajectory.execute({ taskType: 'test', action: 'a' });
|
|
84
|
+
const r = await rlResetEpisode.execute({});
|
|
85
|
+
expect(JSON.parse(r.content).hadActiveEpisode).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('trajectory recording accumulates actions', async () => {
|
|
89
|
+
await rlRecordTrajectory.execute({ taskType: 'multi', action: 'step1' });
|
|
90
|
+
const r = await rlRecordTrajectory.execute({ taskType: 'multi', action: 'step2' });
|
|
91
|
+
expect(JSON.parse(r.content).actionsRecorded).toBe(2);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { SandboxManager } from '../src/core/sandbox';
|
|
3
|
-
|
|
4
|
-
describe('SandboxManager (Remote)', () => {
|
|
5
|
-
it('should create with default local backend', () => {
|
|
6
|
-
const sm = new SandboxManager();
|
|
7
|
-
expect(sm).toBeDefined();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('should exec local command', async () => {
|
|
11
|
-
const sm = new SandboxManager({ backend: 'local' });
|
|
12
|
-
const result = await sm.exec('echo hello');
|
|
13
|
-
expect(result.exitCode).toBe(0);
|
|
14
|
-
expect(result.stdout).toContain('hello');
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('should return non-zero exit code on failure', async () => {
|
|
18
|
-
const sm = new SandboxManager({ backend: 'local' });
|
|
19
|
-
const result = await sm.exec('exit 1');
|
|
20
|
-
expect(result.exitCode).not.toBe(0);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should throw on docker without image', async () => {
|
|
24
|
-
const sm = new SandboxManager({ backend: 'docker' });
|
|
25
|
-
await expect(sm.exec('echo hi')).rejects.toThrow('Docker image is required');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should throw on ssh without host', async () => {
|
|
29
|
-
const sm = new SandboxManager({ backend: 'ssh' });
|
|
30
|
-
await expect(sm.exec('echo hi')).rejects.toThrow('SSH host and user are required');
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should upload locally (copy)', async () => {
|
|
34
|
-
const sm = new SandboxManager({ backend: 'local' });
|
|
35
|
-
const fs = await import('fs');
|
|
36
|
-
const path = await import('path');
|
|
37
|
-
const os = await import('os');
|
|
38
|
-
const src = path.join(os.tmpdir(), 'sandbox-test-src.txt');
|
|
39
|
-
const dst = path.join(os.tmpdir(), 'sandbox-test-dst.txt');
|
|
40
|
-
fs.writeFileSync(src, 'test content');
|
|
41
|
-
await sm.upload(src, dst);
|
|
42
|
-
expect(fs.readFileSync(dst, 'utf-8')).toBe('test content');
|
|
43
|
-
fs.unlinkSync(src);
|
|
44
|
-
fs.unlinkSync(dst);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { SandboxManager } from '../src/core/sandbox';
|
|
3
|
+
|
|
4
|
+
describe('SandboxManager (Remote)', () => {
|
|
5
|
+
it('should create with default local backend', () => {
|
|
6
|
+
const sm = new SandboxManager();
|
|
7
|
+
expect(sm).toBeDefined();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should exec local command', async () => {
|
|
11
|
+
const sm = new SandboxManager({ backend: 'local' });
|
|
12
|
+
const result = await sm.exec('echo hello');
|
|
13
|
+
expect(result.exitCode).toBe(0);
|
|
14
|
+
expect(result.stdout).toContain('hello');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should return non-zero exit code on failure', async () => {
|
|
18
|
+
const sm = new SandboxManager({ backend: 'local' });
|
|
19
|
+
const result = await sm.exec('exit 1');
|
|
20
|
+
expect(result.exitCode).not.toBe(0);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should throw on docker without image', async () => {
|
|
24
|
+
const sm = new SandboxManager({ backend: 'docker' });
|
|
25
|
+
await expect(sm.exec('echo hi')).rejects.toThrow('Docker image is required');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should throw on ssh without host', async () => {
|
|
29
|
+
const sm = new SandboxManager({ backend: 'ssh' });
|
|
30
|
+
await expect(sm.exec('echo hi')).rejects.toThrow('SSH host and user are required');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should upload locally (copy)', async () => {
|
|
34
|
+
const sm = new SandboxManager({ backend: 'local' });
|
|
35
|
+
const fs = await import('fs');
|
|
36
|
+
const path = await import('path');
|
|
37
|
+
const os = await import('os');
|
|
38
|
+
const src = path.join(os.tmpdir(), 'sandbox-test-src.txt');
|
|
39
|
+
const dst = path.join(os.tmpdir(), 'sandbox-test-dst.txt');
|
|
40
|
+
fs.writeFileSync(src, 'test content');
|
|
41
|
+
await sm.upload(src, dst);
|
|
42
|
+
expect(fs.readFileSync(dst, 'utf-8')).toBe('test content');
|
|
43
|
+
fs.unlinkSync(src);
|
|
44
|
+
fs.unlinkSync(dst);
|
|
45
|
+
});
|
|
46
|
+
});
|