mu-agent-bridge 1.0.71 → 1.0.78
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/README.md +17 -10
- package/dist/src-ts/agent.js +35 -0
- package/dist/src-ts/channel-sessions.js +3 -2
- package/dist/src-ts/cli.js +67 -37
- package/dist/src-ts/control-server.js +12 -30
- package/dist/src-ts/core-updater.js +141 -33
- package/dist/src-ts/daemon-process.js +2 -1
- package/dist/src-ts/dsh-agent.js +31 -13
- package/dist/src-ts/http-agent.js +36 -0
- package/dist/src-ts/plugin-catalog.js +11 -2
- package/dist/src-ts/plugin-manager.js +351 -50
- package/dist/src-ts/plugins/abweb/index.js +1 -1
- package/dist/src-ts/plugins/abweb/public/app.js +73 -5
- package/dist/src-ts/plugins/abweb/public/index.html +15 -0
- package/dist/src-ts/plugins/abweb/public/style.css +4 -0
- package/dist/src-ts/plugins/aun/attachments.js +3 -21
- package/dist/src-ts/plugins/aun/index.js +155 -21
- package/dist/src-ts/plugins/aun/messages.js +4 -1
- package/dist/src-ts/plugins/aun/public/app.js +2 -1
- package/dist/src-ts/plugins/aun/public/index.html +1 -1
- package/dist/src-ts/plugins/cdp-draft.js +5 -2
- package/dist/src-ts/plugins/chatgpt/cdp-client.js +26 -12
- package/dist/src-ts/plugins/chatgpt/index.js +80 -19
- package/dist/src-ts/plugins/claude-cli/index.js +19 -2
- package/dist/src-ts/plugins/codex-cli/index.js +19 -2
- package/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/dist/src-ts/plugins/doubao/cdp-client.js +234 -45
- package/dist/src-ts/plugins/doubao/index.js +152 -8
- package/dist/src-ts/plugins/doubao/native-task.js +134 -0
- package/dist/src-ts/plugins/dsh/cdp-client.js +334 -0
- package/dist/src-ts/plugins/dsh/index.js +172 -21
- package/dist/src-ts/plugins/dsh/session-history.js +31 -3
- package/dist/src-ts/plugins/feishu/index.js +1 -1
- package/dist/src-ts/plugins/local-cli/agent.js +74 -9
- package/dist/src-ts/plugins/personal-assistant/claude-cli-model.js +30 -0
- package/dist/src-ts/plugins/personal-assistant/coordination.js +57 -0
- package/dist/src-ts/plugins/personal-assistant/index.js +263 -0
- package/dist/src-ts/plugins/personal-assistant/model-client.js +181 -0
- package/dist/src-ts/plugins/personal-assistant/owner-context.js +56 -0
- package/dist/src-ts/plugins/personal-assistant/remote-ability.js +176 -0
- package/dist/src-ts/plugins/personal-assistant/session-memory.js +124 -0
- package/dist/src-ts/plugins/personal-assistant/tools.js +167 -0
- package/dist/src-ts/plugins/qwenwork/cdp-client.js +90 -18
- package/dist/src-ts/plugins/qwenwork/index.js +139 -24
- package/dist/src-ts/plugins/workbuddy/cdp-client.js +353 -82
- package/dist/src-ts/plugins/workbuddy/index.js +124 -41
- package/dist/src-ts/plugins/zcode/cdp-client.js +500 -0
- package/dist/src-ts/plugins/zcode/index.js +97 -0
- package/dist/src-ts/session-management.js +132 -14
- package/dist/src-ts/version-manager.js +6 -3
- package/dist/tests-ts/abweb-cli.test.js +10 -2
- package/dist/tests-ts/abweb-model-config.test.js +73 -0
- package/dist/tests-ts/agent.test.js +27 -0
- package/dist/tests-ts/aun-attachments.test.js +19 -17
- package/dist/tests-ts/aun-default-owner-page.test.js +2 -1
- package/dist/tests-ts/aun-messages.test.js +20 -0
- package/dist/tests-ts/aun-plugin.test.js +292 -19
- package/dist/tests-ts/bundled-package.test.js +12 -2
- package/dist/tests-ts/cdp-draft-recovery.test.js +182 -3
- package/dist/tests-ts/channel-sessions.test.js +27 -0
- package/dist/tests-ts/chatgpt-plugin.test.js +118 -0
- package/dist/tests-ts/control-server.test.js +56 -0
- package/dist/tests-ts/core-updater.test.js +215 -46
- package/dist/tests-ts/daemon-process.test.js +126 -1
- package/dist/tests-ts/desktop-launch.test.js +73 -0
- package/dist/tests-ts/doubao-native-task.test.js +237 -0
- package/dist/tests-ts/doubao-plugin.test.js +773 -12
- package/dist/tests-ts/dsh-agent.test.js +157 -8
- package/dist/tests-ts/dsh-cdp.test.js +148 -0
- package/dist/tests-ts/dsh-history.test.js +37 -0
- package/dist/tests-ts/feishu-plugin.test.js +1 -1
- package/dist/tests-ts/http-agent.test.js +18 -0
- package/dist/tests-ts/installer-assets.test.js +1 -1
- package/dist/tests-ts/local-cli.test.js +146 -1
- package/dist/tests-ts/model-provider-cancellation.test.js +152 -0
- package/dist/tests-ts/native-session-management.test.js +8 -7
- package/dist/tests-ts/personal-assistant-coordination.test.js +92 -0
- package/dist/tests-ts/personal-assistant-extensions.test.js +35 -0
- package/dist/tests-ts/personal-assistant-memory.test.js +117 -0
- package/dist/tests-ts/personal-assistant-owner-context.test.js +107 -0
- package/dist/tests-ts/personal-assistant-remote-ability.test.js +123 -0
- package/dist/tests-ts/personal-assistant.test.js +663 -0
- package/dist/tests-ts/platform-integration.test.js +183 -1
- package/dist/tests-ts/plugin-catalog.test.js +12 -2
- package/dist/tests-ts/plugin-manager.test.js +356 -4
- package/dist/tests-ts/plugin-upgrade-deadline.test.js +354 -0
- package/dist/tests-ts/publish-packages.test.js +42 -0
- package/dist/tests-ts/qwenwork-plugin.test.js +135 -1
- package/dist/tests-ts/qwenwork-reconnect.test.js +195 -0
- package/dist/tests-ts/qwenwork-sse.test.js +33 -0
- package/dist/tests-ts/session-access-defaults.test.js +112 -0
- package/dist/tests-ts/session-management.test.js +159 -4
- package/dist/tests-ts/version-manager.test.js +40 -0
- package/dist/tests-ts/workbuddy-cdp-recovery.test.js +311 -0
- package/dist/tests-ts/workbuddy-plugin.test.js +499 -4
- package/dist/tests-ts/zcode-cdp.test.js +894 -0
- package/dist/tests-ts/zcode-plugin.test.js +396 -0
- package/package.json +1 -1
- package/plugins/abweb/dist/src-ts/agent.js +35 -0
- package/plugins/abweb/dist/src-ts/plugins/abweb/index.js +1 -1
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/app.js +73 -5
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/app.ts +57 -5
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/index.html +15 -0
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/style.css +4 -0
- package/plugins/abweb/package.json +1 -1
- package/plugins/abweb/plugin.json +1 -1
- package/plugins/aun/config.schema.json +1 -1
- package/plugins/aun/dist/src-ts/agent.js +35 -0
- package/plugins/aun/dist/src-ts/plugins/aun/attachments.js +3 -21
- package/plugins/aun/dist/src-ts/plugins/aun/index.js +155 -21
- package/plugins/aun/dist/src-ts/plugins/aun/messages.js +4 -1
- package/plugins/aun/dist/src-ts/plugins/aun/public/app.js +2 -1
- package/plugins/aun/dist/src-ts/plugins/aun/public/index.html +1 -1
- package/plugins/aun/package.json +1 -1
- package/plugins/aun/plugin.json +1 -1
- package/plugins/chatgpt/dist/src-ts/agent.js +35 -0
- package/plugins/chatgpt/dist/src-ts/plugins/cdp-draft.js +5 -2
- package/plugins/chatgpt/dist/src-ts/plugins/chatgpt/cdp-client.js +26 -12
- package/plugins/chatgpt/dist/src-ts/plugins/chatgpt/index.js +80 -19
- package/plugins/chatgpt/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/chatgpt/package.json +1 -1
- package/plugins/chatgpt/plugin.json +1 -1
- package/plugins/claude-cli/dist/src-ts/agent.js +35 -0
- package/plugins/claude-cli/dist/src-ts/plugins/claude-cli/index.js +19 -2
- package/plugins/claude-cli/dist/src-ts/plugins/local-cli/agent.js +74 -9
- package/plugins/claude-cli/package.json +1 -1
- package/plugins/claude-cli/plugin.json +3 -2
- package/plugins/codex-cli/dist/src-ts/agent.js +35 -0
- package/plugins/codex-cli/dist/src-ts/plugins/codex-cli/index.js +19 -2
- package/plugins/codex-cli/dist/src-ts/plugins/local-cli/agent.js +74 -9
- package/plugins/codex-cli/package.json +1 -1
- package/plugins/codex-cli/plugin.json +3 -2
- package/plugins/doubao/config.schema.json +2 -1
- package/plugins/doubao/dist/src-ts/agent.js +35 -0
- package/plugins/doubao/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/doubao/dist/src-ts/plugins/doubao/cdp-client.js +234 -45
- package/plugins/doubao/dist/src-ts/plugins/doubao/index.js +152 -8
- package/plugins/doubao/dist/src-ts/plugins/doubao/native-task.js +134 -0
- package/plugins/doubao/package.json +1 -1
- package/plugins/doubao/plugin.json +3 -2
- package/plugins/dsh/config.schema.json +5 -2
- package/plugins/dsh/dist/src-ts/agent.js +35 -0
- package/plugins/dsh/dist/src-ts/dsh-agent.js +31 -13
- package/plugins/dsh/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/dsh/dist/src-ts/plugins/dsh/cdp-client.js +334 -0
- package/plugins/dsh/dist/src-ts/plugins/dsh/index.js +172 -21
- package/plugins/dsh/dist/src-ts/plugins/dsh/session-history.js +31 -3
- package/plugins/dsh/package.json +1 -1
- package/plugins/dsh/plugin.json +3 -2
- package/plugins/feishu/dist/src-ts/agent.js +35 -0
- package/plugins/feishu/dist/src-ts/plugins/feishu/index.js +1 -1
- package/plugins/feishu/package.json +1 -1
- package/plugins/feishu/plugin.json +1 -1
- package/plugins/personal-assistant/config.schema.json +23 -0
- package/plugins/personal-assistant/dist/src-ts/agent.js +69 -0
- package/plugins/personal-assistant/dist/src-ts/attachments.js +62 -0
- package/plugins/personal-assistant/dist/src-ts/plugin.js +13 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/claude-cli-model.js +30 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/coordination.js +57 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/index.js +263 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/model-client.js +181 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/owner-context.js +56 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/remote-ability.js +176 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/session-memory.js +124 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/tools.js +167 -0
- package/plugins/personal-assistant/package.json +39 -0
- package/plugins/personal-assistant/plugin.json +15 -0
- package/plugins/qwenwork/dist/src-ts/agent.js +35 -0
- package/plugins/qwenwork/dist/src-ts/plugins/cdp-draft.js +5 -2
- package/plugins/qwenwork/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/cdp-client.js +90 -18
- package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/index.js +139 -24
- package/plugins/qwenwork/package.json +1 -1
- package/plugins/qwenwork/plugin.json +3 -2
- package/plugins/workbuddy/config.schema.json +1 -1
- package/plugins/workbuddy/dist/src-ts/agent.js +35 -0
- package/plugins/workbuddy/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/cdp-client.js +353 -82
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/index.js +124 -41
- package/plugins/workbuddy/package.json +1 -1
- package/plugins/workbuddy/plugin.json +3 -2
- package/plugins/zcode/config.schema.json +13 -0
- package/plugins/zcode/dist/src-ts/agent.js +69 -0
- package/plugins/zcode/dist/src-ts/attachments.js +62 -0
- package/plugins/zcode/dist/src-ts/plugin.js +13 -0
- package/plugins/zcode/dist/src-ts/plugins/desktop-launch.js +238 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/cdp-client.js +896 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/cli-client.js +39 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/desktop-launch.js +10 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/index.js +567 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/session-history.js +121 -0
- package/plugins/zcode/dist/src-ts/plugins/zcode/cdp-client.js +500 -0
- package/plugins/zcode/dist/src-ts/plugins/zcode/index.js +97 -0
- package/plugins/zcode/package.json +16 -0
- package/plugins/zcode/plugin.json +11 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
7
|
+
const promises_1 = require("node:fs/promises");
|
|
8
|
+
const node_os_1 = require("node:os");
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const node_test_1 = require("node:test");
|
|
11
|
+
const owner_context_1 = require("../src-ts/plugins/personal-assistant/owner-context");
|
|
12
|
+
async function fixture(responses) {
|
|
13
|
+
const dir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "pa-owner-context-"));
|
|
14
|
+
const logPath = (0, node_path_1.join)(dir, "args.jsonl");
|
|
15
|
+
const ecPath = (0, node_path_1.join)(dir, "ec");
|
|
16
|
+
const responder = `const fs=require('node:fs');const args=process.argv.slice(2);const log=${JSON.stringify(logPath)};const calls=fs.existsSync(log)?fs.readFileSync(log,'utf8').split('\\n').filter(Boolean).length:0;fs.appendFileSync(log,JSON.stringify(args)+'\\n');const value=(${responses.toString()})(args,calls);process.stdout.write(JSON.stringify(value));`;
|
|
17
|
+
await (0, promises_1.writeFile)(ecPath, `#!/usr/bin/env node\n${responder}\n`);
|
|
18
|
+
await (0, promises_1.chmod)(ecPath, 0o755);
|
|
19
|
+
return {
|
|
20
|
+
ecPath,
|
|
21
|
+
args: async () => (await (0, promises_1.readFile)(logPath, "utf8")).trim().split("\n").filter(Boolean).map((line) => JSON.parse(line)),
|
|
22
|
+
cleanup: () => (0, promises_1.rm)(dir, { recursive: true, force: true }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
(0, node_test_1.test)("只用固定 Owner AID 和规范路径经 execFile 读取,内容标记为参考资料", async () => {
|
|
26
|
+
const fake = await fixture(() => ({ command: "cat", binary: false, text: "仅供参考" }));
|
|
27
|
+
try {
|
|
28
|
+
const store = (0, owner_context_1.createOwnerContextStore)({ ownerAid: "owner.agentid.cn", path: "/profile/context.md", ttlMs: 1000, ecPath: fake.ecPath });
|
|
29
|
+
const result = await store.get();
|
|
30
|
+
strict_1.default.equal(result.content, "仅供参考");
|
|
31
|
+
strict_1.default.equal(result.status, "fresh");
|
|
32
|
+
strict_1.default.equal(result.trust, "reference_only");
|
|
33
|
+
strict_1.default.deepEqual(await fake.args(), [["fs", "cat", "owner.agentid.cn:/profile/context.md", "--format", "json"]]);
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
await fake.cleanup();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
(0, node_test_1.test)("TTL 内复用缓存,refresh 强制读取新值", async () => {
|
|
40
|
+
let now = 10_000;
|
|
41
|
+
const fake = await fixture((_args, calls) => ({ command: "cat", binary: false, text: `版本${calls + 1}` }));
|
|
42
|
+
try {
|
|
43
|
+
const store = (0, owner_context_1.createOwnerContextStore)({ ownerAid: "owner.agentid.cn", path: "/profile/context.md", ttlMs: 1000, ecPath: fake.ecPath, now: () => now });
|
|
44
|
+
strict_1.default.equal((await store.get()).content, "版本1");
|
|
45
|
+
now += 500;
|
|
46
|
+
const cached = await store.get();
|
|
47
|
+
strict_1.default.equal(cached.content, "版本1");
|
|
48
|
+
strict_1.default.equal(cached.status, "cached");
|
|
49
|
+
strict_1.default.equal(cached.ageMs, 500);
|
|
50
|
+
strict_1.default.equal((await store.refresh()).content, "版本2");
|
|
51
|
+
strict_1.default.equal((await fake.args()).length, 2);
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
await fake.cleanup();
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
(0, node_test_1.test)("刷新失败保留上次成功值并标记 stale", async () => {
|
|
58
|
+
let now = 10_000;
|
|
59
|
+
const fake = await fixture((_args, calls) => {
|
|
60
|
+
if (calls === 0)
|
|
61
|
+
return { command: "cat", binary: false, text: "最后一次有效资料" };
|
|
62
|
+
throw new Error("读取失败");
|
|
63
|
+
});
|
|
64
|
+
try {
|
|
65
|
+
const store = (0, owner_context_1.createOwnerContextStore)({ ownerAid: "owner.agentid.cn", path: "/profile/context.md", ttlMs: 1000, ecPath: fake.ecPath, now: () => now });
|
|
66
|
+
const first = await store.get();
|
|
67
|
+
now += 1500;
|
|
68
|
+
const stale = await store.get();
|
|
69
|
+
strict_1.default.equal(first.content, stale.content);
|
|
70
|
+
strict_1.default.equal(stale.status, "stale");
|
|
71
|
+
strict_1.default.equal(stale.ageMs, 1500);
|
|
72
|
+
strict_1.default.equal((await fake.args()).length, 2);
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
await fake.cleanup();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
(0, node_test_1.test)("拒绝无效 AID、非绝对或非规范路径及无效 TTL", async () => {
|
|
79
|
+
const fake = await fixture(() => ({ command: "cat", binary: false, text: "unused" }));
|
|
80
|
+
try {
|
|
81
|
+
for (const options of [
|
|
82
|
+
{ ownerAid: "owner; touch /tmp/injected", path: "/profile/context.md", ttlMs: 1000 },
|
|
83
|
+
{ ownerAid: "owner.agentid.cn", path: "profile/context.md", ttlMs: 1000 },
|
|
84
|
+
{ ownerAid: "owner.agentid.cn", path: "/profile/../secret.md", ttlMs: 1000 },
|
|
85
|
+
{ ownerAid: "owner.agentid.cn", path: "/profile/context.md", ttlMs: 0 },
|
|
86
|
+
]) {
|
|
87
|
+
strict_1.default.throws(() => (0, owner_context_1.createOwnerContextStore)({ ...options, ecPath: fake.ecPath }));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
await fake.cleanup();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
(0, node_test_1.test)("拒绝超限文本,且不缓存无效读取", async () => {
|
|
95
|
+
let now = 10_000;
|
|
96
|
+
const fake = await fixture((_args, calls) => ({ command: "cat", binary: false, text: calls === 0 ? "ok" : "过长" }));
|
|
97
|
+
try {
|
|
98
|
+
const store = (0, owner_context_1.createOwnerContextStore)({ ownerAid: "owner.agentid.cn", path: "/profile/context.md", ttlMs: 1000, maxBytes: 3, ecPath: fake.ecPath, now: () => now });
|
|
99
|
+
strict_1.default.equal((await store.get()).content, "ok");
|
|
100
|
+
now += 2000;
|
|
101
|
+
strict_1.default.equal((await store.get()).content, "ok");
|
|
102
|
+
strict_1.default.equal((await fake.args()).length, 2);
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
await fake.cleanup();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
7
|
+
const promises_1 = require("node:fs/promises");
|
|
8
|
+
const node_os_1 = require("node:os");
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const node_test_1 = require("node:test");
|
|
11
|
+
const remote_ability_1 = require("../src-ts/plugins/personal-assistant/remote-ability");
|
|
12
|
+
async function fixture(responses, globals = {}) {
|
|
13
|
+
const dir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "pa-remote-ability-"));
|
|
14
|
+
const logPath = (0, node_path_1.join)(dir, "args.jsonl");
|
|
15
|
+
const ecPath = (0, node_path_1.join)(dir, "ec");
|
|
16
|
+
const defaultIndex = `const fs=require('node:fs');const logPath=${JSON.stringify(logPath)};const index=()=>({abilities:[{path:"status/read",definition_id:"status-v1",detail_ref:"ability/status.json",params_schema:{type:"object",additionalProperties:false,properties:{device:{type:"string"}},required:["device"]},result_schema:{type:"object"},effects:["read"],auth_required:false,require_confirm:false}]});const response=(overrides={})=>({type:"ability",role:"result",call_id:"call-fixed",operation_id:"op-fixed",ability_path:"status/read",definition_id:"status-v1",ok:true,execution_state:"completed",result:{online:true},...overrides});`;
|
|
17
|
+
const declarations = Object.entries(globals).map(([key, value]) => `const ${key}=${JSON.stringify(value)};`).join("");
|
|
18
|
+
const responder = `${defaultIndex}${declarations}globalThis.fs=fs;globalThis.logPath=logPath;const args=process.argv.slice(2);fs.appendFileSync(logPath,JSON.stringify(args)+'\\n');const value=(${responses.toString()})(args);process.stdout.write(JSON.stringify(value));`;
|
|
19
|
+
await (0, promises_1.writeFile)(ecPath, `#!/usr/bin/env node\n${responder}\n`);
|
|
20
|
+
await (0, promises_1.chmod)(ecPath, 0o755);
|
|
21
|
+
return {
|
|
22
|
+
client: new remote_ability_1.RemoteAbilityClient({ selfAid: "self.agentid.cn", ecPath }),
|
|
23
|
+
args: async () => (await (0, promises_1.readFile)(logPath, "utf8")).trim().split("\n").filter(Boolean).map((line) => JSON.parse(line)),
|
|
24
|
+
cleanup: () => (0, promises_1.rm)(dir, { recursive: true, force: true }),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function index(overrides = {}) {
|
|
28
|
+
return {
|
|
29
|
+
abilities: [{ path: "status/read", definition_id: "status-v1", detail_ref: "ability/status.json", params_schema: { type: "object", additionalProperties: false, properties: { device: { type: "string" } }, required: ["device"] }, result_schema: { type: "object" }, effects: ["read"], auth_required: false, require_confirm: false, ...overrides }],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function response(overrides = {}) {
|
|
33
|
+
return { type: "ability", role: "result", call_id: "call-fixed", operation_id: "op-fixed", ability_path: "status/read", definition_id: "status-v1", ok: true, execution_state: "completed", result: { online: true }, ...overrides };
|
|
34
|
+
}
|
|
35
|
+
(0, node_test_1.test)("命令参数经 execFile 直传,远端 schema 和只读契约控制调用", async () => {
|
|
36
|
+
const fixtureValue = await fixture((args) => {
|
|
37
|
+
if (args[0] === "fs")
|
|
38
|
+
return { command: "cat", binary: false, text: JSON.stringify(args[2].endsWith("index.json") ? index() : index().abilities[0]) };
|
|
39
|
+
if (args[0] === "msg" && args[1] === "send") {
|
|
40
|
+
const payload = JSON.parse(args[args.indexOf("--payload") + 1]);
|
|
41
|
+
return { ok: true, request_state: "completed", request_id: payload.call_id, response: response({ call_id: payload.call_id, operation_id: payload.operation_id }) };
|
|
42
|
+
}
|
|
43
|
+
throw new Error("unexpected command");
|
|
44
|
+
});
|
|
45
|
+
try {
|
|
46
|
+
const providerAid = "provider.agentid.cn";
|
|
47
|
+
await fixtureValue.client.discover(providerAid);
|
|
48
|
+
const unsafeText = "x; touch /tmp/remote-ability-injected";
|
|
49
|
+
const result = await fixtureValue.client.call(providerAid, "status/read", { device: unsafeText });
|
|
50
|
+
strict_1.default.equal(result.status, "completed");
|
|
51
|
+
strict_1.default.deepEqual(result.result, { online: true });
|
|
52
|
+
const args = await fixtureValue.args();
|
|
53
|
+
strict_1.default.deepEqual(args[0], ["fs", "cat", `${providerAid}:/ability/index.json`, "--format", "json"]);
|
|
54
|
+
strict_1.default.deepEqual(args[1], ["fs", "cat", `${providerAid}:/ability/status.json`, "--format", "json"]);
|
|
55
|
+
strict_1.default.equal(args[2][0], "msg");
|
|
56
|
+
strict_1.default.equal(args[2][1], "send");
|
|
57
|
+
strict_1.default.ok(args[2].includes("--payload"));
|
|
58
|
+
strict_1.default.ok(args[2].includes("--return"));
|
|
59
|
+
strict_1.default.ok(args[2].includes("required"));
|
|
60
|
+
strict_1.default.equal(args[2].includes("--shell"), false);
|
|
61
|
+
const payload = JSON.parse(args[2][args[2].indexOf("--payload") + 1]);
|
|
62
|
+
strict_1.default.equal(payload.params.device, unsafeText);
|
|
63
|
+
strict_1.default.match(payload.call_id, /^c-/);
|
|
64
|
+
strict_1.default.match(payload.operation_id, /^op-/);
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
await fixtureValue.cleanup();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
(0, node_test_1.test)("拒绝无效 AID、参数 schema 和非只读或需授权契约", async () => {
|
|
71
|
+
const fixtureValue = await fixture((args) => ({ command: "cat", binary: false, text: JSON.stringify(args[2].endsWith("index.json") ? index() : index().abilities[0]) }));
|
|
72
|
+
try {
|
|
73
|
+
await strict_1.default.rejects(fixtureValue.client.discover("bad aid"), /AID/);
|
|
74
|
+
await fixtureValue.client.discover("provider.agentid.cn");
|
|
75
|
+
await strict_1.default.rejects(fixtureValue.client.call("provider.agentid.cn", "status/read", {}), /schema/);
|
|
76
|
+
await strict_1.default.rejects(fixtureValue.client.call("provider.agentid.cn", "other", { device: "x" }), /能力/);
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
await fixtureValue.cleanup();
|
|
80
|
+
}
|
|
81
|
+
for (const denied of [{ effects: ["read", "write"] }, { auth_required: true }, { require_confirm: true }, { detail_ref: "../secret.json" }]) {
|
|
82
|
+
const entry = index(denied).abilities[0];
|
|
83
|
+
const fake = await fixture((args) => args[2].endsWith("index.json") ? { abilities: [entry] } : entry, { entry });
|
|
84
|
+
try {
|
|
85
|
+
await strict_1.default.rejects(fake.client.call("provider.agentid.cn", "status/read", { device: "x" }), /契约|引用|路径/);
|
|
86
|
+
strict_1.default.equal((await fake.args()).filter((args) => args[0] === "msg").length, 0);
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
await fake.cleanup();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
(0, node_test_1.test)("pending 不重发,request get 读取业务结果并校验关联字段", async () => {
|
|
94
|
+
const fixtureValue = await fixture((args) => {
|
|
95
|
+
if (args[0] === "fs")
|
|
96
|
+
return { command: "cat", binary: false, text: JSON.stringify(args[2].endsWith("index.json") ? index() : index().abilities[0]) };
|
|
97
|
+
if (args[1] === "send") {
|
|
98
|
+
const payload = JSON.parse(args[args.indexOf("--payload") + 1]);
|
|
99
|
+
return { ok: true, request_state: "pending", request_id: payload.call_id };
|
|
100
|
+
}
|
|
101
|
+
if (args[1] === "request" && args[2] === "get") {
|
|
102
|
+
const lines = globalThis.fs.readFileSync(globalThis.logPath, "utf8").trim().split(String.fromCharCode(10)).filter(Boolean);
|
|
103
|
+
const sent = JSON.parse(lines.find((line) => JSON.parse(line)[1] === "send"));
|
|
104
|
+
const payload = JSON.parse(sent[sent.indexOf("--payload") + 1]);
|
|
105
|
+
return { ok: true, request: { state: "completed", responsePayload: response({ call_id: payload.call_id, operation_id: payload.operation_id }) } };
|
|
106
|
+
}
|
|
107
|
+
throw new Error("unexpected command");
|
|
108
|
+
});
|
|
109
|
+
try {
|
|
110
|
+
const providerAid = "provider.agentid.cn";
|
|
111
|
+
const pending = await fixtureValue.client.call(providerAid, "status/read", { device: "phone" });
|
|
112
|
+
strict_1.default.equal(pending.status, "pending");
|
|
113
|
+
strict_1.default.equal((await fixtureValue.args()).filter((args) => args[1] === "send").length, 1);
|
|
114
|
+
const completed = await fixtureValue.client.getRequest(providerAid, pending.requestId);
|
|
115
|
+
strict_1.default.equal(completed.status, "completed");
|
|
116
|
+
strict_1.default.deepEqual(completed.result, { online: true });
|
|
117
|
+
strict_1.default.equal((await fixtureValue.args()).filter((args) => args[1] === "send").length, 1);
|
|
118
|
+
await strict_1.default.rejects(fixtureValue.client.getRequest(providerAid, "bad id"), /request_id/);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
await fixtureValue.cleanup();
|
|
122
|
+
}
|
|
123
|
+
});
|