personal-bot 0.2.3 → 0.2.5
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/CONTEXT.md +13 -7
- package/README.md +46 -9
- package/README.zh-CN.md +46 -9
- package/bin/pbot.mjs +3 -0
- package/docs/README.md +4 -1
- package/docs/agent-collaboration.md +26 -12
- package/docs/architecture-guidelines.md +2 -2
- package/docs/capability-design.md +6 -4
- package/docs/dsh-implementation-plan.md +158 -0
- package/docs/dsh-support-proposal.md +314 -0
- package/docs/dsh.md +103 -0
- package/docs/file-storage.md +14 -9
- package/docs/history.md +29 -18
- package/docs/installation-design.md +226 -0
- package/docs/interaction-design.md +13 -0
- package/docs/release.md +5 -5
- package/docs/technical-design.md +29 -15
- package/docs/validation.md +53 -3
- package/lib/client.js +1071 -0
- package/lib/common/files.d.ts +2 -0
- package/lib/common/files.js +44 -0
- package/lib/common/json.d.ts +6 -0
- package/lib/common/json.js +16 -0
- package/lib/common/markdown.d.ts +5 -0
- package/lib/common/markdown.js +26 -0
- package/lib/common/package-source.js +16 -0
- package/lib/common/paths.d.ts +1 -0
- package/lib/common/paths.js +2 -0
- package/lib/common/validation.d.ts +3 -0
- package/lib/common/validation.js +14 -0
- package/lib/common/version.d.ts +3 -0
- package/lib/common/version.js +13 -0
- package/lib/dsh.d.ts +4 -0
- package/lib/dsh.js +22 -0
- package/lib/extension/dsh/agent-events.d.ts +24 -0
- package/lib/extension/dsh/agent-events.js +242 -0
- package/lib/extension/dsh/agent-runtime.d.ts +49 -0
- package/lib/extension/dsh/agent-runtime.js +348 -0
- package/lib/extension/dsh/command.d.ts +4 -0
- package/lib/extension/dsh/command.js +83 -0
- package/lib/extension/dsh/files.d.ts +5 -0
- package/lib/extension/dsh/files.js +67 -0
- package/lib/extension/dsh/history.d.ts +15 -0
- package/lib/extension/dsh/history.js +88 -0
- package/lib/extension/dsh/management.d.ts +21 -0
- package/lib/extension/dsh/management.js +217 -0
- package/lib/extension/dsh/workspace.d.ts +48 -0
- package/lib/extension/dsh/workspace.js +290 -0
- package/lib/extension/setup-cli.js +136 -0
- package/lib/extension/setup-guard.js +11 -0
- package/lib/integrations/agent-resources.d.ts +1 -0
- package/lib/integrations/agent-resources.js +18 -0
- package/lib/integrations/dsh/dsh-agents.d.ts +30 -0
- package/lib/integrations/dsh/dsh-agents.js +104 -0
- package/lib/integrations/dsh/history-summary.d.ts +11 -0
- package/lib/integrations/dsh/history-summary.js +40 -0
- package/lib/integrations/dsh/history.d.ts +16 -0
- package/lib/integrations/dsh/history.js +156 -0
- package/lib/integrations/dsh/input.d.ts +21 -0
- package/lib/integrations/dsh/input.js +62 -0
- package/lib/integrations/dsh/messages.d.ts +36 -0
- package/lib/integrations/dsh/messages.js +11 -0
- package/lib/integrations/dsh/notifications.d.ts +8 -0
- package/lib/integrations/dsh/notifications.js +55 -0
- package/lib/integrations/dsh/resources.d.ts +10 -0
- package/lib/integrations/dsh/resources.js +41 -0
- package/lib/integrations/dsh/schema.d.ts +7 -0
- package/lib/integrations/dsh/schema.js +28 -0
- package/lib/integrations/dsh/session.d.ts +14 -0
- package/lib/integrations/dsh/session.js +59 -0
- package/lib/integrations/history-summary.d.ts +2 -0
- package/lib/integrations/history-summary.js +21 -0
- package/lib/integrations/installation/pi-bridge.js +131 -0
- package/lib/integrations/installation/pi-setup.js +193 -0
- package/lib/integrations/installation/processes.js +155 -0
- package/lib/integrations/installation/workspace.js +21 -0
- package/lib/integrations/process.d.ts +14 -0
- package/lib/integrations/process.js +48 -0
- package/lib/integrations/python-activation.d.ts +2 -0
- package/lib/integrations/python-activation.js +29 -0
- package/lib/integrations/team-context.d.ts +18 -0
- package/lib/integrations/team-context.js +57 -0
- package/lib/model/agent.d.ts +92 -0
- package/lib/model/agent.js +1 -0
- package/lib/model/history.d.ts +43 -0
- package/lib/model/history.js +1 -0
- package/lib/model/team.d.ts +85 -0
- package/lib/model/team.js +1 -0
- package/lib/services/agents/agent-notices.d.ts +13 -0
- package/lib/services/agents/agent-notices.js +25 -0
- package/lib/services/agents/agent-run.d.ts +39 -0
- package/lib/services/agents/agent-run.js +138 -0
- package/lib/services/agents/agent-service.d.ts +166 -0
- package/lib/services/agents/agent-service.js +325 -0
- package/lib/services/agents/team-service.d.ts +168 -0
- package/lib/services/agents/team-service.js +343 -0
- package/lib/services/history/history-service.d.ts +103 -0
- package/lib/services/history/history-service.js +269 -0
- package/lib/services/installation/setup-service.js +121 -0
- package/lib/services/workspace/python-environment-service.d.ts +15 -0
- package/lib/services/workspace/python-environment-service.js +50 -0
- package/lib/services/workspace/workspace-files.d.ts +2 -0
- package/lib/services/workspace/workspace-files.js +17 -0
- package/lib/services/workspace/workspace-preparation.d.ts +2 -0
- package/lib/services/workspace/workspace-preparation.js +18 -0
- package/lib/storage/agent-files.d.ts +30 -0
- package/lib/storage/agent-files.js +166 -0
- package/lib/storage/atomic-json.d.ts +11 -0
- package/lib/storage/atomic-json.js +101 -0
- package/lib/storage/file-access.d.ts +2 -0
- package/lib/storage/file-access.js +26 -0
- package/lib/storage/history-files.d.ts +10 -0
- package/lib/storage/history-files.js +63 -0
- package/lib/storage/team-files.d.ts +16 -0
- package/lib/storage/team-files.js +111 -0
- package/lib/tools/agents/actions.d.ts +52 -0
- package/lib/tools/agents/actions.js +49 -0
- package/lib/tools/agents/contract.d.ts +163 -0
- package/lib/tools/agents/contract.js +56 -0
- package/lib/tools/agents/dsh-contract.d.ts +52 -0
- package/lib/tools/agents/dsh-contract.js +15 -0
- package/lib/tools/agents/dsh-tool.d.ts +5 -0
- package/lib/tools/agents/dsh-tool.js +38 -0
- package/lib/tools/history/actions.d.ts +70 -0
- package/lib/tools/history/actions.js +7 -0
- package/lib/tools/history/contract.d.ts +81 -0
- package/lib/tools/history/contract.js +32 -0
- package/lib/tools/history/dsh-tool.d.ts +4 -0
- package/lib/tools/history/dsh-tool.js +22 -0
- package/lib/tools/result.d.ts +18 -0
- package/lib/tools/result.js +10 -0
- package/lib/tools/teams/actions.d.ts +24 -0
- package/lib/tools/teams/actions.js +38 -0
- package/lib/tools/teams/contract.d.ts +232 -0
- package/lib/tools/teams/contract.js +67 -0
- package/lib/tools/teams/dsh-tool.d.ts +8 -0
- package/lib/tools/teams/dsh-tool.js +49 -0
- package/lib/ui/dsh/attachments.d.ts +5 -0
- package/lib/ui/dsh/attachments.js +39 -0
- package/lib/ui/dsh/elements.d.ts +17 -0
- package/lib/ui/dsh/elements.js +79 -0
- package/lib/ui/dsh/index.d.ts +4 -0
- package/lib/ui/dsh/index.js +13 -0
- package/lib/ui/dsh/management.d.ts +4 -0
- package/lib/ui/dsh/management.js +711 -0
- package/lib/ui/dsh/remote.d.ts +15 -0
- package/lib/ui/dsh/remote.js +11 -0
- package/lib/ui/dsh/styles.d.ts +1 -0
- package/lib/ui/dsh/styles.js +132 -0
- package/lib/ui/presentation.d.ts +3 -0
- package/lib/ui/presentation.js +12 -0
- package/lib/ui/setup.js +52 -0
- package/npm-shrinkwrap.json +11118 -783
- package/package.json +113 -9
- package/python/README.md +6 -6
- package/resources/agents/coordinator.md +1 -1
- package/resources/dsh/cordis.patch.yml +3 -0
- package/resources/installer/plugins.json +16 -0
- package/resources/prompts/workspace.md +1 -1
- package/resources/references/compute.md +1 -1
- package/resources/references/task-conductor.md +6 -4
- package/resources/skills/provider-connections/SKILL.md +10 -0
- package/scripts/README.md +13 -1
- package/src/common/package-source.ts +16 -0
- package/src/dsh.ts +22 -0
- package/src/extension/agent-events.ts +51 -46
- package/src/extension/agents-command.ts +48 -34
- package/src/extension/command.ts +42 -23
- package/src/extension/dsh/agent-events.ts +148 -0
- package/src/extension/dsh/agent-runtime.ts +251 -0
- package/src/extension/dsh/command.ts +78 -0
- package/src/extension/dsh/files.ts +61 -0
- package/src/extension/dsh/history.ts +69 -0
- package/src/extension/dsh/management.ts +108 -0
- package/src/extension/dsh/workspace.ts +206 -0
- package/src/extension/events.ts +6 -4
- package/src/extension/history.ts +15 -12
- package/src/extension/setup-cli.ts +109 -0
- package/src/extension/setup-guard.ts +12 -0
- package/src/extension/subagent-entry.ts +34 -63
- package/src/extension/teams-command.ts +53 -46
- package/src/integrations/{pi/agent-resources.ts → agent-resources.ts} +2 -2
- package/src/integrations/dsh/dsh-agents.ts +97 -0
- package/src/integrations/dsh/history-summary.ts +43 -0
- package/src/integrations/dsh/history.ts +76 -0
- package/src/integrations/dsh/input.ts +66 -0
- package/src/integrations/dsh/messages.ts +22 -0
- package/src/integrations/dsh/notifications.ts +46 -0
- package/src/integrations/dsh/resources.ts +44 -0
- package/src/integrations/dsh/schema.ts +26 -0
- package/src/integrations/dsh/session.ts +67 -0
- package/src/integrations/history-summary.ts +20 -0
- package/src/integrations/installation/pi-bridge.ts +107 -0
- package/src/integrations/installation/pi-setup.ts +162 -0
- package/src/integrations/installation/processes.ts +124 -0
- package/src/integrations/installation/workspace.ts +18 -0
- package/src/integrations/pi/history.ts +4 -14
- package/src/integrations/pi/pi-agents.ts +17 -6
- package/src/integrations/pi/team-context.ts +6 -58
- package/src/integrations/team-context.ts +60 -0
- package/src/model/agent.ts +2 -0
- package/src/model/history.ts +3 -1
- package/src/pbot.ts +1 -1
- package/src/services/agents/agent-notices.ts +28 -0
- package/src/services/agents/agent-run.ts +114 -0
- package/src/services/agents/agent-service.ts +127 -64
- package/src/services/history/history-service.ts +120 -59
- package/src/services/installation/setup-service.ts +145 -0
- package/src/storage/agent-files.ts +17 -4
- package/src/storage/history-files.ts +30 -5
- package/src/tools/agents/actions.ts +47 -0
- package/src/tools/agents/contract.ts +8 -5
- package/src/tools/agents/dsh-contract.ts +16 -0
- package/src/tools/agents/dsh-tool.ts +41 -0
- package/src/tools/agents/tool.ts +7 -43
- package/src/tools/history/actions.ts +9 -0
- package/src/tools/history/contract.ts +34 -0
- package/src/tools/history/dsh-tool.ts +22 -0
- package/src/tools/history/tool.ts +7 -30
- package/src/tools/teams/actions.ts +38 -0
- package/src/tools/teams/contract.ts +7 -3
- package/src/tools/teams/dsh-tool.ts +55 -0
- package/src/tools/teams/tool.ts +6 -31
- package/src/ui/agent-display.ts +7 -4
- package/src/ui/dsh/attachments.ts +42 -0
- package/src/ui/dsh/elements.ts +50 -0
- package/src/ui/dsh/index.ts +18 -0
- package/src/ui/dsh/management.ts +412 -0
- package/src/ui/dsh/remote.ts +20 -0
- package/src/ui/dsh/styles.ts +132 -0
- package/src/ui/pi/menu.ts +37 -0
- package/src/ui/pi/reader.ts +46 -0
- package/src/ui/presentation.ts +12 -0
- package/src/ui/setup.ts +40 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { teamMessagesMarkdown } from "../../integrations/team-context.js";
|
|
2
|
+
import { markdownResult, result } from "../result.js";
|
|
3
|
+
export function executeTeam(service, agents, input, owner) {
|
|
4
|
+
const views = agents.list(owner);
|
|
5
|
+
service.recover(owner);
|
|
6
|
+
let id = input.teamId;
|
|
7
|
+
switch (input.action) {
|
|
8
|
+
case "create":
|
|
9
|
+
id = service.create(owner, { name: input.name, brief: input.brief, members: input.members }, views).teamId;
|
|
10
|
+
break;
|
|
11
|
+
case "list": return markdownResult({ teams: service.list(owner, views) }, "团队列表");
|
|
12
|
+
case "read": {
|
|
13
|
+
const page = service.read(id, { kind: "coordinator", owner }, input);
|
|
14
|
+
return result(page, false, teamMessagesMarkdown(page));
|
|
15
|
+
}
|
|
16
|
+
case "run":
|
|
17
|
+
service.run(id, owner, { instruction: input.instruction, mode: input.mode,
|
|
18
|
+
...(input.rounds === undefined ? {} : { rounds: input.rounds }),
|
|
19
|
+
...(input.maxConcurrent === undefined ? {} : { maxConcurrent: input.maxConcurrent }),
|
|
20
|
+
...(input.timeoutSeconds === undefined ? {} : { timeoutSeconds: input.timeoutSeconds }) }, views);
|
|
21
|
+
break;
|
|
22
|
+
case "pause":
|
|
23
|
+
service.pause(id, owner);
|
|
24
|
+
break;
|
|
25
|
+
case "close":
|
|
26
|
+
service.close(id, owner, views);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
return markdownResult(service.status(id, owner, views), "团队状态");
|
|
30
|
+
}
|
|
31
|
+
export function executeTeamMessage(service, input, actor, requestId) {
|
|
32
|
+
if (input.action === "read") {
|
|
33
|
+
const page = service.read(input.teamId, actor, input);
|
|
34
|
+
return result(page, false, teamMessagesMarkdown(page));
|
|
35
|
+
}
|
|
36
|
+
const message = service.post(input.teamId, actor, requestId, input.text, input.replyTo);
|
|
37
|
+
return markdownResult({ teamId: input.teamId, seq: message.seq, status: "stored" }, "团队消息已保存");
|
|
38
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
export declare const teamDescription = "\u4E3B\u4F1A\u8BDD\u7BA1\u7406\u56FA\u5B9A\u6210\u5458\u56E2\u961F\u3002create \u4E0D\u542F\u52A8\u6A21\u578B\uFF1Brun \u5F00\u5C55\u6709\u9650 roundRobin \u8F6E\u6D41\u8BA8\u8BBA\u6216 parallel \u5E76\u884C\u8F6E\u6B21\uFF0C\u9ED8\u8BA4 2 \u8F6E\u3001\u6574\u6279 15 \u5206\u949F\uFF0C\u6210\u5458\u76F4\u63A5\u53D6\u5F97\u516C\u5171\u539F\u6587\u3002\u56E2\u961F\u8FD0\u884C\u65F6\u5360\u7528\u6210\u5458\uFF1Bpause \u505C\u6B62\u65B0\u5B89\u6392\u548C\u9886\u53D6\uFF0C\u5141\u8BB8\u5728\u9014\u5DE5\u4F5C\u6536\u5C3E\uFF0C\u4E4B\u540E\u53EF\u79C1\u4EBA send\uFF1B\u9700\u8981\u4E2D\u6B62\u6210\u5458\u7528 pbot_agent stop\u3002\u5230\u671F\u65F6\u5B50\u5165\u53E3\u5C3D\u529B\u4E2D\u6B62\u672A\u88AB\u4EBA\u5DE5\u63A5\u7BA1\u7684\u56E2\u961F\u5DE5\u4F5C\u3002close \u4FDD\u7559\u6210\u5458\u4F1A\u8BDD\u548C\u5386\u53F2\uFF1B\u6362\u6210\u5458\u987B\u5173\u95ED\u65E7\u56E2\u961F\u518D\u521B\u5EFA\u3002\u7EE7\u7EED\u987B\u660E\u786E run \u65B0\u6279\u6B21\uFF0C\u4E0D\u91CD\u653E\u65E7\u8BF7\u6C42\u3002\u5B8C\u6210\u4ECD\u9700\u4E1A\u52A1\u9A8C\u6536\u3002";
|
|
3
|
+
export declare const teamMessageDescription = "\u76F4\u63A5\u8BFB\u53D6/\u53D1\u5E03\u56E2\u961F\u516C\u5171\u539F\u6587\u3002post \u4E0D\u5524\u9192\u6A21\u578B\u3001\u4E0D\u589E\u52A0\u8F6E\u6B21\uFF0C\u6240\u6709\u6210\u5458\u53EF\u89C1\uFF0C\u4E0D\u63D0\u4F9B\u79C1\u4FE1\u6216\u9012\u5F52\u59D4\u6D3E\u3002\u6210\u5458\u53EA\u80FD\u5728\u81EA\u5DF1\u7684\u56E2\u961F\u5DE5\u4F5C\u4E2D post\u3002read \u7528 afterSeq \u5206\u9875\uFF1B\u957F\u6D88\u606F\u7528 seq/offset/limit \u7EE7\u7EED\uFF0CnextOffset \u975E\u7A7A\u8868\u793A\u8BE5\u6761\u6B63\u6587\u4E0D\u5B8C\u6574\u3002\u4FDD\u5B58\u6210\u529F\u4E0D\u662F\u6A21\u578B\u5DF2\u8BFB\u6216\u4E1A\u52A1\u5B8C\u6210\u3002";
|
|
4
|
+
export declare const teamParametersSchema: Type.TObject<{
|
|
5
|
+
afterSeq: Type.TOptional<Type.TInteger>;
|
|
6
|
+
seq: Type.TOptional<Type.TInteger>;
|
|
7
|
+
offset: Type.TOptional<Type.TInteger>;
|
|
8
|
+
limit: Type.TOptional<Type.TInteger>;
|
|
9
|
+
action: Type.TUnion<Type.TLiteral<string>[]>;
|
|
10
|
+
teamId: Type.TOptional<Type.TString>;
|
|
11
|
+
name: Type.TOptional<Type.TString>;
|
|
12
|
+
brief: Type.TOptional<Type.TString>;
|
|
13
|
+
members: Type.TOptional<Type.TArray<Type.TObject<{
|
|
14
|
+
agentId: Type.TString;
|
|
15
|
+
role: Type.TString;
|
|
16
|
+
}>>>;
|
|
17
|
+
instruction: Type.TOptional<Type.TString>;
|
|
18
|
+
mode: Type.TOptional<Type.TUnion<[Type.TLiteral<"roundRobin">, Type.TLiteral<"parallel">]>>;
|
|
19
|
+
rounds: Type.TOptional<Type.TInteger>;
|
|
20
|
+
maxConcurrent: Type.TOptional<Type.TInteger>;
|
|
21
|
+
timeoutSeconds: Type.TOptional<Type.TInteger>;
|
|
22
|
+
}>;
|
|
23
|
+
export declare const teamActionSchema: Type.TUnion<[Type.TObject<{
|
|
24
|
+
action: Type.TLiteral<"create">;
|
|
25
|
+
name: Type.TString;
|
|
26
|
+
brief: Type.TString;
|
|
27
|
+
members: Type.TArray<Type.TObject<{
|
|
28
|
+
agentId: Type.TString;
|
|
29
|
+
role: Type.TString;
|
|
30
|
+
}>>;
|
|
31
|
+
}>, Type.TObject<{
|
|
32
|
+
action: Type.TLiteral<"list">;
|
|
33
|
+
}>, ...Type.TObject<{
|
|
34
|
+
action: Type.TLiteral<string>;
|
|
35
|
+
teamId: Type.TString;
|
|
36
|
+
}>[], Type.TObject<{
|
|
37
|
+
instruction: Type.TString;
|
|
38
|
+
mode: Type.TUnion<[Type.TLiteral<"roundRobin">, Type.TLiteral<"parallel">]>;
|
|
39
|
+
rounds: Type.TOptional<Type.TInteger>;
|
|
40
|
+
maxConcurrent: Type.TOptional<Type.TInteger>;
|
|
41
|
+
timeoutSeconds: Type.TOptional<Type.TInteger>;
|
|
42
|
+
action: Type.TLiteral<"run">;
|
|
43
|
+
teamId: Type.TString;
|
|
44
|
+
}>, Type.TObject<{
|
|
45
|
+
afterSeq: Type.TOptional<Type.TInteger>;
|
|
46
|
+
seq: Type.TOptional<Type.TInteger>;
|
|
47
|
+
offset: Type.TOptional<Type.TInteger>;
|
|
48
|
+
limit: Type.TOptional<Type.TInteger>;
|
|
49
|
+
action: Type.TLiteral<"read">;
|
|
50
|
+
teamId: Type.TString;
|
|
51
|
+
}>]>;
|
|
52
|
+
export declare const teamMessageParametersSchema: Type.TObject<{
|
|
53
|
+
afterSeq: Type.TOptional<Type.TInteger>;
|
|
54
|
+
seq: Type.TOptional<Type.TInteger>;
|
|
55
|
+
offset: Type.TOptional<Type.TInteger>;
|
|
56
|
+
limit: Type.TOptional<Type.TInteger>;
|
|
57
|
+
action: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"post">]>;
|
|
58
|
+
teamId: Type.TString;
|
|
59
|
+
text: Type.TOptional<Type.TString>;
|
|
60
|
+
replyTo: Type.TOptional<Type.TInteger>;
|
|
61
|
+
}>;
|
|
62
|
+
export declare const teamMessageActionSchema: Type.TUnion<[Type.TObject<{
|
|
63
|
+
afterSeq: Type.TOptional<Type.TInteger>;
|
|
64
|
+
seq: Type.TOptional<Type.TInteger>;
|
|
65
|
+
offset: Type.TOptional<Type.TInteger>;
|
|
66
|
+
limit: Type.TOptional<Type.TInteger>;
|
|
67
|
+
action: Type.TLiteral<"read">;
|
|
68
|
+
teamId: Type.TString;
|
|
69
|
+
}>, Type.TObject<{
|
|
70
|
+
action: Type.TLiteral<"post">;
|
|
71
|
+
teamId: Type.TString;
|
|
72
|
+
text: Type.TString;
|
|
73
|
+
replyTo: Type.TOptional<Type.TInteger>;
|
|
74
|
+
}>]>;
|
|
75
|
+
export declare const teamPageSchema: Type.TObject<{
|
|
76
|
+
teamId: Type.TString;
|
|
77
|
+
messages: Type.TArray<Type.TObject<{
|
|
78
|
+
seq: Type.TInteger;
|
|
79
|
+
operationId: Type.TString;
|
|
80
|
+
author: Type.TObject<{
|
|
81
|
+
kind: Type.TUnion<[Type.TLiteral<"user">, Type.TLiteral<"coordinator">, Type.TLiteral<"member">]>;
|
|
82
|
+
agentId: Type.TOptional<Type.TString>;
|
|
83
|
+
name: Type.TString;
|
|
84
|
+
}>;
|
|
85
|
+
text: Type.TString;
|
|
86
|
+
replyTo: Type.TOptional<Type.TInteger>;
|
|
87
|
+
runId: Type.TOptional<Type.TString>;
|
|
88
|
+
source: Type.TOptional<Type.TObject<{
|
|
89
|
+
requestId: Type.TString;
|
|
90
|
+
cycleId: Type.TString;
|
|
91
|
+
}>>;
|
|
92
|
+
offset: Type.TInteger;
|
|
93
|
+
totalLength: Type.TInteger;
|
|
94
|
+
nextOffset: Type.TUnion<[Type.TInteger, Type.TNull]>;
|
|
95
|
+
}>>;
|
|
96
|
+
lastSeq: Type.TInteger;
|
|
97
|
+
nextAfterSeq: Type.TUnion<[Type.TInteger, Type.TNull]>;
|
|
98
|
+
}>;
|
|
99
|
+
export declare const teamResultSchema: Type.TUnion<[Type.TUnion<[Type.TObject<{
|
|
100
|
+
teamId: Type.TString;
|
|
101
|
+
name: Type.TString;
|
|
102
|
+
brief: Type.TString;
|
|
103
|
+
closed: Type.TBoolean;
|
|
104
|
+
owned: Type.TLiteral<true>;
|
|
105
|
+
members: Type.TArray<Type.TObject<{
|
|
106
|
+
agentId: Type.TString;
|
|
107
|
+
role: Type.TString;
|
|
108
|
+
name: Type.TString;
|
|
109
|
+
state: Type.TString;
|
|
110
|
+
}>>;
|
|
111
|
+
lastSeq: Type.TInteger;
|
|
112
|
+
activeCount: Type.TInteger;
|
|
113
|
+
unresolved: Type.TArray<Type.TObject<{
|
|
114
|
+
requestId: Type.TString;
|
|
115
|
+
agentId: Type.TString;
|
|
116
|
+
runId: Type.TString;
|
|
117
|
+
round: Type.TInteger;
|
|
118
|
+
active: Type.TBoolean;
|
|
119
|
+
state: Type.TString;
|
|
120
|
+
cycleId: Type.TOptional<Type.TString>;
|
|
121
|
+
}>>;
|
|
122
|
+
run: Type.TOptional<Type.TObject<{
|
|
123
|
+
runId: Type.TString;
|
|
124
|
+
instruction: Type.TString;
|
|
125
|
+
mode: Type.TUnion<[Type.TLiteral<"roundRobin">, Type.TLiteral<"parallel">]>;
|
|
126
|
+
state: Type.TUnion<[Type.TLiteral<"running">, Type.TLiteral<"paused">, Type.TLiteral<"finished">]>;
|
|
127
|
+
rounds: Type.TInteger;
|
|
128
|
+
maxConcurrent: Type.TInteger;
|
|
129
|
+
deadlineAt: Type.TNumber;
|
|
130
|
+
scheduled: Type.TInteger;
|
|
131
|
+
published: Type.TInteger;
|
|
132
|
+
reason: Type.TOptional<Type.TString>;
|
|
133
|
+
}>>;
|
|
134
|
+
}>, Type.TObject<{
|
|
135
|
+
teamId: Type.TString;
|
|
136
|
+
name: Type.TString;
|
|
137
|
+
closed: Type.TBoolean;
|
|
138
|
+
owned: Type.TLiteral<false>;
|
|
139
|
+
}>]>, Type.TObject<{
|
|
140
|
+
teams: Type.TArray<Type.TUnion<[Type.TObject<{
|
|
141
|
+
teamId: Type.TString;
|
|
142
|
+
name: Type.TString;
|
|
143
|
+
brief: Type.TString;
|
|
144
|
+
closed: Type.TBoolean;
|
|
145
|
+
owned: Type.TLiteral<true>;
|
|
146
|
+
members: Type.TArray<Type.TObject<{
|
|
147
|
+
agentId: Type.TString;
|
|
148
|
+
role: Type.TString;
|
|
149
|
+
name: Type.TString;
|
|
150
|
+
state: Type.TString;
|
|
151
|
+
}>>;
|
|
152
|
+
lastSeq: Type.TInteger;
|
|
153
|
+
activeCount: Type.TInteger;
|
|
154
|
+
unresolved: Type.TArray<Type.TObject<{
|
|
155
|
+
requestId: Type.TString;
|
|
156
|
+
agentId: Type.TString;
|
|
157
|
+
runId: Type.TString;
|
|
158
|
+
round: Type.TInteger;
|
|
159
|
+
active: Type.TBoolean;
|
|
160
|
+
state: Type.TString;
|
|
161
|
+
cycleId: Type.TOptional<Type.TString>;
|
|
162
|
+
}>>;
|
|
163
|
+
run: Type.TOptional<Type.TObject<{
|
|
164
|
+
runId: Type.TString;
|
|
165
|
+
instruction: Type.TString;
|
|
166
|
+
mode: Type.TUnion<[Type.TLiteral<"roundRobin">, Type.TLiteral<"parallel">]>;
|
|
167
|
+
state: Type.TUnion<[Type.TLiteral<"running">, Type.TLiteral<"paused">, Type.TLiteral<"finished">]>;
|
|
168
|
+
rounds: Type.TInteger;
|
|
169
|
+
maxConcurrent: Type.TInteger;
|
|
170
|
+
deadlineAt: Type.TNumber;
|
|
171
|
+
scheduled: Type.TInteger;
|
|
172
|
+
published: Type.TInteger;
|
|
173
|
+
reason: Type.TOptional<Type.TString>;
|
|
174
|
+
}>>;
|
|
175
|
+
}>, Type.TObject<{
|
|
176
|
+
teamId: Type.TString;
|
|
177
|
+
name: Type.TString;
|
|
178
|
+
closed: Type.TBoolean;
|
|
179
|
+
owned: Type.TLiteral<false>;
|
|
180
|
+
}>]>>;
|
|
181
|
+
}>, Type.TObject<{
|
|
182
|
+
teamId: Type.TString;
|
|
183
|
+
messages: Type.TArray<Type.TObject<{
|
|
184
|
+
seq: Type.TInteger;
|
|
185
|
+
operationId: Type.TString;
|
|
186
|
+
author: Type.TObject<{
|
|
187
|
+
kind: Type.TUnion<[Type.TLiteral<"user">, Type.TLiteral<"coordinator">, Type.TLiteral<"member">]>;
|
|
188
|
+
agentId: Type.TOptional<Type.TString>;
|
|
189
|
+
name: Type.TString;
|
|
190
|
+
}>;
|
|
191
|
+
text: Type.TString;
|
|
192
|
+
replyTo: Type.TOptional<Type.TInteger>;
|
|
193
|
+
runId: Type.TOptional<Type.TString>;
|
|
194
|
+
source: Type.TOptional<Type.TObject<{
|
|
195
|
+
requestId: Type.TString;
|
|
196
|
+
cycleId: Type.TString;
|
|
197
|
+
}>>;
|
|
198
|
+
offset: Type.TInteger;
|
|
199
|
+
totalLength: Type.TInteger;
|
|
200
|
+
nextOffset: Type.TUnion<[Type.TInteger, Type.TNull]>;
|
|
201
|
+
}>>;
|
|
202
|
+
lastSeq: Type.TInteger;
|
|
203
|
+
nextAfterSeq: Type.TUnion<[Type.TInteger, Type.TNull]>;
|
|
204
|
+
}>]>;
|
|
205
|
+
export declare const teamMessageResultSchema: Type.TUnion<[Type.TObject<{
|
|
206
|
+
teamId: Type.TString;
|
|
207
|
+
messages: Type.TArray<Type.TObject<{
|
|
208
|
+
seq: Type.TInteger;
|
|
209
|
+
operationId: Type.TString;
|
|
210
|
+
author: Type.TObject<{
|
|
211
|
+
kind: Type.TUnion<[Type.TLiteral<"user">, Type.TLiteral<"coordinator">, Type.TLiteral<"member">]>;
|
|
212
|
+
agentId: Type.TOptional<Type.TString>;
|
|
213
|
+
name: Type.TString;
|
|
214
|
+
}>;
|
|
215
|
+
text: Type.TString;
|
|
216
|
+
replyTo: Type.TOptional<Type.TInteger>;
|
|
217
|
+
runId: Type.TOptional<Type.TString>;
|
|
218
|
+
source: Type.TOptional<Type.TObject<{
|
|
219
|
+
requestId: Type.TString;
|
|
220
|
+
cycleId: Type.TString;
|
|
221
|
+
}>>;
|
|
222
|
+
offset: Type.TInteger;
|
|
223
|
+
totalLength: Type.TInteger;
|
|
224
|
+
nextOffset: Type.TUnion<[Type.TInteger, Type.TNull]>;
|
|
225
|
+
}>>;
|
|
226
|
+
lastSeq: Type.TInteger;
|
|
227
|
+
nextAfterSeq: Type.TUnion<[Type.TInteger, Type.TNull]>;
|
|
228
|
+
}>, Type.TObject<{
|
|
229
|
+
teamId: Type.TString;
|
|
230
|
+
seq: Type.TInteger;
|
|
231
|
+
status: Type.TLiteral<"stored">;
|
|
232
|
+
}>]>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
export const teamDescription = "主会话管理固定成员团队。create 不启动模型;run 开展有限 roundRobin 轮流讨论或 parallel 并行轮次,默认 2 轮、整批 15 分钟,成员直接取得公共原文。团队运行时占用成员;pause 停止新安排和领取,允许在途工作收尾,之后可私人 send;需要中止成员用 pbot_agent stop。到期时子入口尽力中止未被人工接管的团队工作。close 保留成员会话和历史;换成员须关闭旧团队再创建。继续须明确 run 新批次,不重放旧请求。完成仍需业务验收。";
|
|
3
|
+
export const teamMessageDescription = "直接读取/发布团队公共原文。post 不唤醒模型、不增加轮次,所有成员可见,不提供私信或递归委派。成员只能在自己的团队工作中 post。read 用 afterSeq 分页;长消息用 seq/offset/limit 继续,nextOffset 非空表示该条正文不完整。保存成功不是模型已读或业务完成。";
|
|
4
|
+
const id = Type.String({ minLength: 1, maxLength: 128 });
|
|
5
|
+
const text = Type.String({ minLength: 1, maxLength: 24000 });
|
|
6
|
+
const name = Type.String({ minLength: 1, maxLength: 64, pattern: "^[^\\r\\n\\x00-\\x1f]+$" });
|
|
7
|
+
const mode = Type.Union([Type.Literal("roundRobin"), Type.Literal("parallel")], { description: "run 必填:roundRobin 按成员顺序轮流发言;parallel 在并发上限内发言,全员本轮完成后才进入下一轮。" });
|
|
8
|
+
const members = Type.Array(Type.Object({ agentId: id, role: Type.String({ minLength: 1, maxLength: 4000 }) }, { additionalProperties: false }), {
|
|
9
|
+
minItems: 1, maxItems: 50, description: "仅 create,必填:固定成员及职责。成员须属于当前父会话分支、版本兼容且未加入其他未关闭团队。create 不启动模型,也不等待成员就绪。",
|
|
10
|
+
});
|
|
11
|
+
const run = {
|
|
12
|
+
instruction: Type.String({ ...text, description: "仅 run,必填:本次新批次的明确任务与交付要求;不恢复或重放旧批次。" }), mode,
|
|
13
|
+
rounds: Type.Optional(Type.Integer({ minimum: 1, maximum: 10, description: "仅 run:每位成员的轮数,默认 2。" })),
|
|
14
|
+
maxConcurrent: Type.Optional(Type.Integer({ minimum: 1, maximum: 50, description: "仅 run:roundRobin 默认且只允许 1;parallel 默认 min(2, 成员数)。不得超过成员数;已排队但未完成的请求也占用并发名额。" })),
|
|
15
|
+
timeoutSeconds: Type.Optional(Type.Integer({ minimum: 1, maximum: 86400, description: "仅 run:整批期限,默认 900 秒,包含所有轮次和等待。到期停止新安排和领取,子入口尽力中止未被人工接管的在途工作;pause 则允许在途工作收尾。" })),
|
|
16
|
+
};
|
|
17
|
+
const page = {
|
|
18
|
+
afterSeq: Type.Optional(Type.Integer({ minimum: 0, description: "仅 read:读取序号大于此值的消息,默认 0,不得超过 lastSeq。返回 nextAfterSeq 用于继续消息列表;单条续读使用 seq/offset,省略 afterSeq。先补完被截断的正文,再继续列表。" })),
|
|
19
|
+
seq: Type.Optional(Type.Integer({ minimum: 1, description: "仅 read:指定一条消息,配合该消息的 nextOffset 续读。未指定时从 afterSeq 后顺序读取。" })),
|
|
20
|
+
offset: Type.Optional(Type.Integer({ minimum: 0, description: "仅 read:指定 seq 的正文 UTF-16 字符偏移,默认 0;非零时必须同时提供 seq。" })),
|
|
21
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 16000, description: "仅 read:本页所有消息正文合计的 UTF-16 字符上限,默认 16000,不是消息条数或 token 数;不含元数据和 Markdown 格式开销。" })),
|
|
22
|
+
};
|
|
23
|
+
const object = (fields) => Type.Object(fields, { additionalProperties: false });
|
|
24
|
+
export const teamParametersSchema = object({
|
|
25
|
+
action: Type.Union(["create", "list", "status", "read", "run", "pause", "close"].map(v => Type.Literal(v)), {
|
|
26
|
+
description: "create 只接受并必填 name/brief/members;list 只接受 action;status/pause/close 只接受并必填 teamId;read 必填 teamId,可选 afterSeq/seq/offset/limit;run 必填 teamId/instruction/mode,可选 rounds/maxConcurrent/timeoutSeconds。禁止携带其他 action 的字段。run 要求所有成员存活、idle、当前代次团队接入就绪、无待处理私人输入,且团队未关闭、无运行批次或在途工作。pause 仅停止新安排和未领取请求;close 要求先暂停并等待在途工作结束,不停止成员会话。",
|
|
27
|
+
}),
|
|
28
|
+
teamId: Type.Optional(id), name: Type.Optional(name), brief: Type.Optional(text), members: Type.Optional(members),
|
|
29
|
+
instruction: Type.Optional(run.instruction), mode: Type.Optional(mode), rounds: run.rounds, maxConcurrent: run.maxConcurrent, timeoutSeconds: run.timeoutSeconds, ...page,
|
|
30
|
+
});
|
|
31
|
+
export const teamActionSchema = Type.Union([
|
|
32
|
+
object({ action: Type.Literal("create"), name, brief: text, members }),
|
|
33
|
+
object({ action: Type.Literal("list") }),
|
|
34
|
+
...["status", "pause", "close"].map(v => object({ action: Type.Literal(v), teamId: id })),
|
|
35
|
+
object({ action: Type.Literal("run"), teamId: id, ...run }),
|
|
36
|
+
object({ action: Type.Literal("read"), teamId: id, ...page }),
|
|
37
|
+
]);
|
|
38
|
+
export const teamMessageParametersSchema = object({
|
|
39
|
+
action: Type.Union([Type.Literal("read"), Type.Literal("post")], {
|
|
40
|
+
description: "read 必填 teamId,只可选 afterSeq/seq/offset/limit,禁止 text/replyTo;post 必填 teamId/text,只可选 replyTo,禁止所有分页字段。",
|
|
41
|
+
}), teamId: id, text: Type.Optional(Type.String({ ...text, description: "仅 post,必填:向全体成员公开的原文,不扩大任务授权。" })),
|
|
42
|
+
replyTo: Type.Optional(Type.Integer({ minimum: 1, description: "仅 post:回复已有消息的 seq。" })), ...page,
|
|
43
|
+
});
|
|
44
|
+
export const teamMessageActionSchema = Type.Union([
|
|
45
|
+
object({ action: Type.Literal("read"), teamId: id, ...page }),
|
|
46
|
+
object({ action: Type.Literal("post"), teamId: id, text, replyTo: Type.Optional(Type.Integer({ minimum: 1 })) }),
|
|
47
|
+
]);
|
|
48
|
+
const message = object({ seq: Type.Integer(), operationId: Type.String(),
|
|
49
|
+
author: object({ kind: Type.Union([Type.Literal("user"), Type.Literal("coordinator"), Type.Literal("member")]), agentId: Type.Optional(id), name: Type.String() }),
|
|
50
|
+
text: Type.String(), replyTo: Type.Optional(Type.Integer()), runId: Type.Optional(id),
|
|
51
|
+
source: Type.Optional(object({ requestId: id, cycleId: id })),
|
|
52
|
+
offset: Type.Integer(), totalLength: Type.Integer({ description: "完整正文的 UTF-16 字符数。" }),
|
|
53
|
+
nextOffset: Type.Union([Type.Integer(), Type.Null()], { description: "非 null 表示本条正文尚未读完;使用相同 teamId、seq 和此 offset 续读。" }) });
|
|
54
|
+
export const teamPageSchema = object({ teamId: id, messages: Type.Array(message), lastSeq: Type.Integer(),
|
|
55
|
+
nextAfterSeq: Type.Union([Type.Integer(), Type.Null()], { description: "后续消息列表的 afterSeq;null 只表示列表已到末尾,仍须检查每条消息的 nextOffset。指定 seq 时始终为 null。" }) });
|
|
56
|
+
const ownedView = object({ teamId: id, name: Type.String(), brief: Type.String(), closed: Type.Boolean(), owned: Type.Literal(true),
|
|
57
|
+
members: Type.Array(object({ agentId: id, role: Type.String(), name: Type.String(), state: Type.String() })),
|
|
58
|
+
lastSeq: Type.Integer(), activeCount: Type.Integer({ description: "所有批次中已领取、执行实例仍存活且尚无完成记录的请求数;paused 仍可能大于 0。" }),
|
|
59
|
+
unresolved: Type.Array(object({ requestId: id, agentId: id, runId: id, round: Type.Integer(), active: Type.Boolean(),
|
|
60
|
+
state: Type.String({ description: "queued=运行批次中尚未领取;accepted=已领取且仍在途;uncertain=已领取但执行实例/代次不再匹配、无完成记录;cancelled=批次已停止且未领取,或周期取消;unpublished=已完成但尚未公开有效原文;mixed/interactive=含人工或私人工作,不自动公开;failed/interrupted=失败或中断。不能将 unresolved 当作成功或自动重试许可。" }), cycleId: Type.Optional(id) }), {
|
|
61
|
+
description: "所有批次中尚未确认完成且公开的请求,包含排队、在途、失败、结果不明和不宜公开的工作;不是仅列出运行中的请求。先核对原请求和业务结果,避免重复执行。",
|
|
62
|
+
}),
|
|
63
|
+
run: Type.Optional(object({ runId: id, instruction: Type.String(), mode, state: Type.Union([Type.Literal("running"), Type.Literal("paused"), Type.Literal("finished")]),
|
|
64
|
+
rounds: Type.Integer(), maxConcurrent: Type.Integer(), deadlineAt: Type.Number(), scheduled: Type.Integer(), published: Type.Integer(), reason: Type.Optional(Type.String()) })) });
|
|
65
|
+
const view = Type.Union([ownedView, object({ teamId: id, name: Type.String(), closed: Type.Boolean(), owned: Type.Literal(false) })]);
|
|
66
|
+
export const teamResultSchema = Type.Union([view, object({ teams: Type.Array(view) }), teamPageSchema]);
|
|
67
|
+
export const teamMessageResultSchema = Type.Union([teamPageSchema, object({ teamId: id, seq: Type.Integer(), status: Type.Literal("stored") })]);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { Agent } from "@deepseek-ai/dsh-agent";
|
|
3
|
+
import type { TeamService } from "../../services/agents/team-service.js";
|
|
4
|
+
import type { AgentService } from "../../services/agents/agent-service.js";
|
|
5
|
+
import type { AgentOwner } from "../../model/agent.js";
|
|
6
|
+
import type { TeamActor } from "../../model/team.js";
|
|
7
|
+
export declare function registerDshTeamTool(ctx: Context, agent: Agent, service: TeamService, agents: AgentService, owner: AgentOwner, check: () => void): void;
|
|
8
|
+
export declare function registerDshTeamMessageTool(ctx: Context, agent: Agent, service: TeamService, actor: () => TeamActor, check: () => void): void;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { dshParameters, dshOutputSchema } from "../../integrations/dsh/schema.js";
|
|
2
|
+
import { object } from "../../common/json.js";
|
|
3
|
+
import { requireThat, schema } from "../../common/validation.js";
|
|
4
|
+
import { markdownFields } from "../../common/markdown.js";
|
|
5
|
+
import { teamMessagesMarkdown } from "../../integrations/team-context.js";
|
|
6
|
+
import { executeTeam, executeTeamMessage } from "./actions.js";
|
|
7
|
+
import { teamDescription, teamMessageDescription, teamParametersSchema, teamActionSchema, teamResultSchema, teamMessageParametersSchema, teamMessageActionSchema, teamMessageResultSchema } from "./contract.js";
|
|
8
|
+
export function registerDshTeamTool(ctx, agent, service, agents, owner, check) {
|
|
9
|
+
const validators = new Map(teamActionSchema.anyOf.map(row => [row.properties.action.const, schema(row)]));
|
|
10
|
+
const validOutput = schema(teamResultSchema);
|
|
11
|
+
ctx.tools.register({ name: "pbot_team", description: teamDescription, parameters: dshParameters(teamParametersSchema),
|
|
12
|
+
output: {
|
|
13
|
+
schema: dshOutputSchema(teamResultSchema),
|
|
14
|
+
render: (args, value) => [{ type: "text", text: object(args) && args.action === "read"
|
|
15
|
+
? teamMessagesMarkdown(value) : "# 团队\n\n" + markdownFields(value) }],
|
|
16
|
+
},
|
|
17
|
+
async execute(args, exec) {
|
|
18
|
+
check();
|
|
19
|
+
exec.signal.throwIfAborted();
|
|
20
|
+
requireThat(exec.agent === agent && object(args) && typeof args.action === "string", "团队工具会话或参数无效。");
|
|
21
|
+
const valid = validators.get(args.action);
|
|
22
|
+
requireThat(valid && valid(args), "团队参数无效。");
|
|
23
|
+
const value = executeTeam(service, agents, args, owner).structuredContent;
|
|
24
|
+
requireThat(validOutput(value), "团队输出不符合契约。");
|
|
25
|
+
return value;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function registerDshTeamMessageTool(ctx, agent, service, actor, check) {
|
|
30
|
+
const validators = new Map(teamMessageActionSchema.anyOf.map(row => [row.properties.action.const, schema(row)]));
|
|
31
|
+
const validOutput = schema(teamMessageResultSchema);
|
|
32
|
+
ctx.tools.register({ name: "pbot_team_message", description: teamMessageDescription, parameters: dshParameters(teamMessageParametersSchema),
|
|
33
|
+
output: {
|
|
34
|
+
schema: dshOutputSchema(teamMessageResultSchema),
|
|
35
|
+
render: (args, value) => [{ type: "text", text: object(args) && args.action === "read"
|
|
36
|
+
? teamMessagesMarkdown(value) : "# 团队消息\n\n" + markdownFields(value) }],
|
|
37
|
+
},
|
|
38
|
+
async execute(args, exec) {
|
|
39
|
+
check();
|
|
40
|
+
exec.signal.throwIfAborted();
|
|
41
|
+
requireThat(exec.agent === agent && object(args) && typeof args.action === "string", "团队消息会话或参数无效。");
|
|
42
|
+
const valid = validators.get(args.action);
|
|
43
|
+
requireThat(valid && valid(args), "团队消息参数无效。");
|
|
44
|
+
const value = executeTeamMessage(service, args, actor(), exec.callId).structuredContent;
|
|
45
|
+
requireThat(validOutput(value), "团队消息输出不符合契约。");
|
|
46
|
+
return value;
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { CommandSubmitAttachment } from "@deepseek-ai/dsh-commands/types";
|
|
3
|
+
import type { SessionId } from "@deepseek-ai/dsh-session/types";
|
|
4
|
+
/** Native commands admit encoded images and resolve session-owned file receipts. */
|
|
5
|
+
export declare function commandAttachments(ctx: Context, sessionId: SessionId, files: readonly File[], signal: AbortSignal, progress: (message: string) => void): Promise<CommandSubmitAttachment[]>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const images = new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
|
|
2
|
+
function encodedImage(file, signal) {
|
|
3
|
+
signal.throwIfAborted();
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const reader = new FileReader(), abort = () => reader.abort();
|
|
6
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
7
|
+
reader.onloadend = () => signal.removeEventListener("abort", abort);
|
|
8
|
+
reader.onerror = () => reject(reader.error ?? new Error("图片读取失败。"));
|
|
9
|
+
reader.onabort = () => reject(signal.reason ?? new DOMException("图片读取已取消。", "AbortError"));
|
|
10
|
+
reader.onload = () => {
|
|
11
|
+
if (typeof reader.result !== "string")
|
|
12
|
+
reject(new Error("图片读取失败。"));
|
|
13
|
+
else
|
|
14
|
+
resolve(reader.result.slice(reader.result.indexOf(",") + 1));
|
|
15
|
+
};
|
|
16
|
+
reader.readAsDataURL(file);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/** Native commands admit encoded images and resolve session-owned file receipts. */
|
|
20
|
+
export async function commandAttachments(ctx, sessionId, files, signal, progress) {
|
|
21
|
+
if (files.length > 32)
|
|
22
|
+
throw new Error("一次最多附加 32 个文件。");
|
|
23
|
+
const attachments = [];
|
|
24
|
+
for (const file of files) {
|
|
25
|
+
signal.throwIfAborted();
|
|
26
|
+
progress("正在准备附件:" + file.name);
|
|
27
|
+
if (images.has(file.type)) {
|
|
28
|
+
attachments.push({ type: "image", mediaType: file.type, name: file.name, data: await encodedImage(file, signal) });
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
const result = await ctx.fileUpload.upload(sessionId, file, file.name, signal, value => progress(`正在上传 ${file.name}:${value.loaded} / ${value.total ?? file.size} 字节`));
|
|
32
|
+
if (!result.ok)
|
|
33
|
+
throw new Error(result.error.message);
|
|
34
|
+
attachments.push({ type: "file", receiptId: result.value.receiptId });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
signal.throwIfAborted();
|
|
38
|
+
return attachments;
|
|
39
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const record: (value: unknown) => Record<string, unknown>;
|
|
2
|
+
export declare const rows: (value: unknown) => Record<string, unknown>[];
|
|
3
|
+
export declare const text: (value: unknown) => string;
|
|
4
|
+
export declare const objectInput: (value: string) => Record<string, unknown>;
|
|
5
|
+
export declare const lines: (value: string) => string[];
|
|
6
|
+
export declare function element<K extends keyof HTMLElementTagNameMap>(tag: K, content?: string, className?: string): HTMLElementTagNameMap[K];
|
|
7
|
+
export declare function block(value: unknown): HTMLPreElement;
|
|
8
|
+
export declare function note(value: string): HTMLParagraphElement;
|
|
9
|
+
export declare function group(parent: HTMLElement, className?: string): HTMLDivElement;
|
|
10
|
+
export declare function details(parent: HTMLElement, title: string): HTMLDetailsElement;
|
|
11
|
+
export declare function field(parent: HTMLElement, label: string, multiline?: boolean, value?: string): HTMLInputElement | HTMLTextAreaElement;
|
|
12
|
+
export declare function select(parent: HTMLElement, label: string, values: [string, string][]): HTMLSelectElement;
|
|
13
|
+
export declare function badge(state: unknown): HTMLSpanElement;
|
|
14
|
+
export declare function facts(values: [string, unknown][]): HTMLDListElement;
|
|
15
|
+
export declare function empty(title: string, description: string): HTMLDivElement;
|
|
16
|
+
export declare function pageTitle(parent: HTMLElement, title: string, description: string): HTMLElement;
|
|
17
|
+
export declare function time(value: unknown): string;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { object } from "../../common/json.js";
|
|
2
|
+
import { stateLabel } from "../presentation.js";
|
|
3
|
+
export const record = (value) => { if (!object(value))
|
|
4
|
+
throw new Error("管理数据无效。"); return value; };
|
|
5
|
+
export const rows = (value) => Array.isArray(value) ? value.map(record) : [];
|
|
6
|
+
export const text = (value) => value === null || value === undefined ? "" : String(value);
|
|
7
|
+
export const objectInput = (value) => record(JSON.parse(value || "{}"));
|
|
8
|
+
export const lines = (value) => value.split(/\r?\n/).map(item => item.trim()).filter(Boolean);
|
|
9
|
+
export function element(tag, content = "", className = "") {
|
|
10
|
+
const node = document.createElement(tag);
|
|
11
|
+
node.textContent = content;
|
|
12
|
+
node.className = className;
|
|
13
|
+
return node;
|
|
14
|
+
}
|
|
15
|
+
export function block(value) { return element("pre", typeof value === "string" ? value : JSON.stringify(value, null, 2), "pbot-prose"); }
|
|
16
|
+
export function note(value) { return element("p", value, "pbot-muted"); }
|
|
17
|
+
export function group(parent, className = "pbot-stack") {
|
|
18
|
+
const node = element("div", "", className);
|
|
19
|
+
parent.append(node);
|
|
20
|
+
return node;
|
|
21
|
+
}
|
|
22
|
+
export function details(parent, title) {
|
|
23
|
+
const node = element("details", "", "pbot-disclosure");
|
|
24
|
+
node.append(element("summary", title));
|
|
25
|
+
parent.append(node);
|
|
26
|
+
return node;
|
|
27
|
+
}
|
|
28
|
+
export function field(parent, label, multiline = false, value = "") {
|
|
29
|
+
const wrapper = element("label", "", "pbot-field"), input = multiline ? element("textarea") : element("input");
|
|
30
|
+
wrapper.append(element("span", label));
|
|
31
|
+
input.value = value;
|
|
32
|
+
input.setAttribute("aria-label", label);
|
|
33
|
+
if (input instanceof HTMLTextAreaElement)
|
|
34
|
+
input.rows = 3;
|
|
35
|
+
wrapper.append(input);
|
|
36
|
+
parent.append(wrapper);
|
|
37
|
+
return input;
|
|
38
|
+
}
|
|
39
|
+
export function select(parent, label, values) {
|
|
40
|
+
const wrapper = element("label", "", "pbot-field"), input = element("select");
|
|
41
|
+
wrapper.append(element("span", label));
|
|
42
|
+
input.setAttribute("aria-label", label);
|
|
43
|
+
for (const [value, title] of values) {
|
|
44
|
+
const option = element("option", title);
|
|
45
|
+
option.value = value;
|
|
46
|
+
input.append(option);
|
|
47
|
+
}
|
|
48
|
+
wrapper.append(input);
|
|
49
|
+
parent.append(wrapper);
|
|
50
|
+
return input;
|
|
51
|
+
}
|
|
52
|
+
export function badge(state) {
|
|
53
|
+
const node = element("span", stateLabel(state), "pbot-badge");
|
|
54
|
+
node.dataset.state = text(state);
|
|
55
|
+
return node;
|
|
56
|
+
}
|
|
57
|
+
export function facts(values) {
|
|
58
|
+
const node = element("dl", "", "pbot-facts");
|
|
59
|
+
for (const [label, value] of values)
|
|
60
|
+
node.append(element("dt", label), element("dd", text(value) || "—"));
|
|
61
|
+
return node;
|
|
62
|
+
}
|
|
63
|
+
export function empty(title, description) {
|
|
64
|
+
const node = element("div", "", "pbot-empty");
|
|
65
|
+
node.append(element("h3", title), note(description));
|
|
66
|
+
return node;
|
|
67
|
+
}
|
|
68
|
+
export function pageTitle(parent, title, description) {
|
|
69
|
+
const node = element("header", "", "pbot-page-title");
|
|
70
|
+
node.append(element("h2", title));
|
|
71
|
+
if (description)
|
|
72
|
+
node.append(note(description));
|
|
73
|
+
parent.append(node);
|
|
74
|
+
return node;
|
|
75
|
+
}
|
|
76
|
+
export function time(value) {
|
|
77
|
+
const date = new Date(typeof value === "number" ? value : text(value));
|
|
78
|
+
return Number.isNaN(date.getTime()) ? "" : date.toLocaleString(undefined, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
79
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { pbotReadRemote } from "./remote.js";
|
|
2
|
+
import { showManagement } from "./management.js";
|
|
3
|
+
export const name = "personal-bot";
|
|
4
|
+
export const inject = ["remote"];
|
|
5
|
+
export async function apply(ctx) {
|
|
6
|
+
ctx.remote.$mount(pbotReadRemote);
|
|
7
|
+
await ctx.plugin({ name: "pbot-management-view", inject: ["commandUi", "remote", "remote.commands", "remote.pbot", "fileUpload"],
|
|
8
|
+
apply(view) {
|
|
9
|
+
view.commandUi.decorate({ name: "pbot", available: () => true,
|
|
10
|
+
ui: { kind: "action", run: session => { showManagement(view, session.sessionId); } } });
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { SessionId } from "@deepseek-ai/dsh-session/types";
|
|
3
|
+
/** The view owns drafts, uploads and queries. Accepted commands belong to the server workspace. */
|
|
4
|
+
export declare function showManagement(ctx: Context, parentSessionId: SessionId): void;
|