personal-bot 0.2.4 → 0.2.6
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 +9 -7
- package/README.md +15 -8
- package/README.zh-CN.md +15 -8
- package/docs/README.md +3 -1
- package/docs/agent-collaboration.md +27 -13
- 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 +3 -1
- package/docs/interaction-design.md +13 -0
- package/docs/release.md +3 -3
- package/docs/subagent-upgrade-proposal.md +3 -3
- package/docs/technical-design.md +29 -15
- package/docs/validation.md +49 -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/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/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/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/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/npm-shrinkwrap.json +11123 -793
- package/package.json +94 -11
- package/python/README.md +6 -6
- package/resources/agents/coordinator.md +1 -1
- package/resources/dsh/cordis.patch.yml +3 -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 +9 -1
- 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/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/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/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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "personal-bot",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/realqiyan/personal-bot.git"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"registry": "https://registry.npmjs.org/",
|
|
11
11
|
"tag": "latest"
|
|
12
12
|
},
|
|
13
|
-
"description": "A personal assistant connecting knowledge, research, and action
|
|
13
|
+
"description": "A personal assistant connecting knowledge, research, and action for Pi and DeepSeek Harness.",
|
|
14
14
|
"type": "module",
|
|
15
15
|
"bin": {
|
|
16
16
|
"pbot": "./bin/pbot.mjs"
|
|
@@ -26,6 +26,19 @@
|
|
|
26
26
|
"prompts": [],
|
|
27
27
|
"themes": []
|
|
28
28
|
},
|
|
29
|
+
"dsh": {
|
|
30
|
+
"bundle": { "patch": "./resources/dsh/cordis.patch.yml" },
|
|
31
|
+
"client": {
|
|
32
|
+
"platform": "web",
|
|
33
|
+
"inject": ["@deepseek-ai/dsh-api-remotes", "@deepseek-ai/dsh-client-ui-commands", "@deepseek-ai/dsh-client-file-upload"]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"exports": {
|
|
37
|
+
".": { "types": "./lib/dsh.d.ts", "default": "./lib/dsh.js" },
|
|
38
|
+
"./dsh": { "types": "./lib/dsh.d.ts", "default": "./lib/dsh.js" },
|
|
39
|
+
"./client": { "types": "./lib/ui/dsh/index.d.ts", "default": "./lib/client.js" },
|
|
40
|
+
"./*": "./*"
|
|
41
|
+
},
|
|
29
42
|
"files": [
|
|
30
43
|
"npm-shrinkwrap.json",
|
|
31
44
|
"bin",
|
|
@@ -42,25 +55,73 @@
|
|
|
42
55
|
"docs"
|
|
43
56
|
],
|
|
44
57
|
"engines": {
|
|
45
|
-
"node": ">=22.19.0"
|
|
58
|
+
"node": ">=22.19.0",
|
|
59
|
+
"dsh": "0.2.2-rc.1"
|
|
46
60
|
},
|
|
47
61
|
"scripts": {
|
|
48
62
|
"check": "tsc --noEmit && npm run check:dependencies",
|
|
49
63
|
"check:dependencies": "depcruise --config .dependency-cruiser.cjs src",
|
|
50
|
-
"build": "node scripts/clean-dist.mjs && tsc && npm run build:cli",
|
|
64
|
+
"build": "node scripts/clean-dist.mjs && tsc && npm run build:cli && npm run build:dsh",
|
|
51
65
|
"build:cli": "node scripts/build-cli.mjs",
|
|
66
|
+
"build:dsh": "node scripts/build-dsh.mjs",
|
|
52
67
|
"test": "npm run build && node --test --test-concurrency=1 tests/*/*.test.mjs",
|
|
53
68
|
"test:smoke": "npm run build && node --test --test-concurrency=1 tests/smoke/*.test.mjs",
|
|
54
69
|
"test:e2e": "npm run build && node --test --test-concurrency=1 tests/e2e/*.test.mjs",
|
|
55
|
-
"prepack": "npm run check && npm run build:cli"
|
|
70
|
+
"prepack": "npm run check && npm run build:cli && npm run build:dsh"
|
|
56
71
|
},
|
|
57
72
|
"peerDependencies": {
|
|
73
|
+
"@deepseek-ai/cordis": "~4.1.0",
|
|
74
|
+
"@deepseek-ai/dsh-agent": "0.2.2-rc.1",
|
|
75
|
+
"@deepseek-ai/dsh-session": "0.2.2-rc.1",
|
|
76
|
+
"@deepseek-ai/dsh-session-persistence": "0.2.2-rc.1",
|
|
77
|
+
"@deepseek-ai/dsh-session-query": "0.2.2-rc.1",
|
|
78
|
+
"@deepseek-ai/dsh-llm": "0.2.2-rc.1",
|
|
79
|
+
"@deepseek-ai/dsh-commands": "0.2.2-rc.1",
|
|
80
|
+
"@deepseek-ai/dsh-api-remotes": "0.2.2-rc.1",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-commands": "0.2.2-rc.1",
|
|
82
|
+
"@deepseek-ai/dsh-client-file-upload": "0.2.2-rc.1",
|
|
83
|
+
"@deepseek-ai/dsh-tools": "0.2.2-rc.1",
|
|
84
|
+
"@deepseek-ai/dsh-home-paths": "0.2.2-rc.1",
|
|
85
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.2-rc.1",
|
|
86
|
+
"@deepseek-ai/dsh-skill": "0.2.2-rc.1",
|
|
87
|
+
"@deepseek-ai/dsh-skill-filesystem": "0.2.2-rc.1",
|
|
88
|
+
"@deepseek-ai/dsh-working-directory": "0.2.2-rc.1",
|
|
89
|
+
"@deepseek-ai/dsh-fs": "0.2.2-rc.1",
|
|
90
|
+
"@deepseek-ai/dsh-attachment": "0.2.2-rc.1",
|
|
91
|
+
"@deepseek-ai/dsh-fs-patch": "0.2.2-rc.1",
|
|
92
|
+
"@deepseek-ai/dsh-user-approval": "0.2.2-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-tool-executor-ptc": "0.2.2-rc.1",
|
|
94
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.2-rc.1",
|
|
95
|
+
"@deepseek-ai/dsh-typert-registry": "0.2.2-rc.1",
|
|
58
96
|
"@earendil-works/pi-ai": "*",
|
|
59
97
|
"@earendil-works/pi-coding-agent": "*",
|
|
60
98
|
"@earendil-works/pi-tui": "*",
|
|
61
99
|
"typebox": "*"
|
|
62
100
|
},
|
|
63
101
|
"peerDependenciesMeta": {
|
|
102
|
+
"@deepseek-ai/cordis": { "optional": true },
|
|
103
|
+
"@deepseek-ai/dsh-agent": { "optional": true },
|
|
104
|
+
"@deepseek-ai/dsh-session": { "optional": true },
|
|
105
|
+
"@deepseek-ai/dsh-session-persistence": { "optional": true },
|
|
106
|
+
"@deepseek-ai/dsh-session-query": { "optional": true },
|
|
107
|
+
"@deepseek-ai/dsh-llm": { "optional": true },
|
|
108
|
+
"@deepseek-ai/dsh-commands": { "optional": true },
|
|
109
|
+
"@deepseek-ai/dsh-api-remotes": { "optional": true },
|
|
110
|
+
"@deepseek-ai/dsh-client-ui-commands": { "optional": true },
|
|
111
|
+
"@deepseek-ai/dsh-client-file-upload": { "optional": true },
|
|
112
|
+
"@deepseek-ai/dsh-tools": { "optional": true },
|
|
113
|
+
"@deepseek-ai/dsh-home-paths": { "optional": true },
|
|
114
|
+
"@deepseek-ai/dsh-system-prompt": { "optional": true },
|
|
115
|
+
"@deepseek-ai/dsh-skill": { "optional": true },
|
|
116
|
+
"@deepseek-ai/dsh-skill-filesystem": { "optional": true },
|
|
117
|
+
"@deepseek-ai/dsh-working-directory": { "optional": true },
|
|
118
|
+
"@deepseek-ai/dsh-fs": { "optional": true },
|
|
119
|
+
"@deepseek-ai/dsh-attachment": { "optional": true },
|
|
120
|
+
"@deepseek-ai/dsh-fs-patch": { "optional": true },
|
|
121
|
+
"@deepseek-ai/dsh-user-approval": { "optional": true },
|
|
122
|
+
"@deepseek-ai/dsh-tool-executor-ptc": { "optional": true },
|
|
123
|
+
"@deepseek-ai/dsh-typert-protocol": { "optional": true },
|
|
124
|
+
"@deepseek-ai/dsh-typert-registry": { "optional": true },
|
|
64
125
|
"@earendil-works/pi-ai": {
|
|
65
126
|
"optional": true
|
|
66
127
|
},
|
|
@@ -69,9 +130,6 @@
|
|
|
69
130
|
},
|
|
70
131
|
"@earendil-works/pi-tui": {
|
|
71
132
|
"optional": true
|
|
72
|
-
},
|
|
73
|
-
"typebox": {
|
|
74
|
-
"optional": true
|
|
75
133
|
}
|
|
76
134
|
},
|
|
77
135
|
"dependencies": {
|
|
@@ -80,12 +138,37 @@
|
|
|
80
138
|
"semver": "7.8.5"
|
|
81
139
|
},
|
|
82
140
|
"devDependencies": {
|
|
83
|
-
"@
|
|
84
|
-
"@
|
|
85
|
-
"@
|
|
141
|
+
"@deepseek-ai/cordis": "4.1.0",
|
|
142
|
+
"@deepseek-ai/dsh": "0.2.2-rc.1",
|
|
143
|
+
"@deepseek-ai/dsh-agent": "0.2.2-rc.1",
|
|
144
|
+
"@deepseek-ai/dsh-api-remotes": "0.2.2-rc.1",
|
|
145
|
+
"@deepseek-ai/dsh-client-ui-commands": "0.2.2-rc.1",
|
|
146
|
+
"@deepseek-ai/dsh-client-file-upload": "0.2.2-rc.1",
|
|
147
|
+
"@deepseek-ai/dsh-commands": "0.2.2-rc.1",
|
|
148
|
+
"@deepseek-ai/dsh-llm": "0.2.2-rc.1",
|
|
149
|
+
"@deepseek-ai/dsh-session": "0.2.2-rc.1",
|
|
150
|
+
"@deepseek-ai/dsh-session-persistence": "0.2.2-rc.1",
|
|
151
|
+
"@deepseek-ai/dsh-session-query": "0.2.2-rc.1",
|
|
152
|
+
"@deepseek-ai/dsh-tools": "0.2.2-rc.1",
|
|
153
|
+
"@deepseek-ai/dsh-home-paths": "0.2.2-rc.1",
|
|
154
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.2-rc.1",
|
|
155
|
+
"@deepseek-ai/dsh-skill": "0.2.2-rc.1",
|
|
156
|
+
"@deepseek-ai/dsh-skill-filesystem": "0.2.2-rc.1",
|
|
157
|
+
"@deepseek-ai/dsh-working-directory": "0.2.2-rc.1",
|
|
158
|
+
"@deepseek-ai/dsh-fs": "0.2.2-rc.1",
|
|
159
|
+
"@deepseek-ai/dsh-attachment": "0.2.2-rc.1",
|
|
160
|
+
"@deepseek-ai/dsh-fs-patch": "0.2.2-rc.1",
|
|
161
|
+
"@deepseek-ai/dsh-user-approval": "0.2.2-rc.1",
|
|
162
|
+
"@deepseek-ai/dsh-tool-executor-ptc": "0.2.2-rc.1",
|
|
163
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.2-rc.1",
|
|
164
|
+
"@deepseek-ai/dsh-typert-registry": "0.2.2-rc.1",
|
|
165
|
+
"@earendil-works/pi-ai": "1.5.0",
|
|
166
|
+
"@earendil-works/pi-coding-agent": "1.5.0",
|
|
167
|
+
"@earendil-works/pi-tui": "1.5.0",
|
|
86
168
|
"@types/node": "24.10.1",
|
|
87
169
|
"@types/semver": "7.7.1",
|
|
88
170
|
"dependency-cruiser": "18.5.0",
|
|
171
|
+
"esbuild": "0.25.12",
|
|
89
172
|
"typebox": "1.3.27",
|
|
90
173
|
"typescript": "5.9.3"
|
|
91
174
|
}
|
package/python/README.md
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
## 自动准备与激活
|
|
6
6
|
|
|
7
|
-
Pi 加载 Personal Bot
|
|
7
|
+
Pi 加载 Personal Bot、原生 `/reload`,或 dsh 加载 pbot Host 组件时自动执行 setup,无需另行确认或指定路径。同一系统用户的两种宿主共用该环境:
|
|
8
8
|
|
|
9
9
|
1. 共享 venv 不存在时创建,不使用系统 site-packages。
|
|
10
10
|
2. 按 `requirements.lock` 补齐或对齐依赖,允许升级或降级;已匹配时不重新安装。
|
|
11
11
|
3. 检查依赖关系、全部预装库导入和简单 TA-Lib 计算。
|
|
12
|
-
4. 成功后将 venv 的 `bin`
|
|
12
|
+
4. 成功后将 venv 的 `bin` 放到当前宿主进程 PATH 前端,设置 `VIRTUAL_ENV`,移除 `PYTHONHOME`、`PYTHONPATH` 并禁用用户 site-packages。主会话与专家的原生 Bash 继承该环境。
|
|
13
13
|
|
|
14
14
|
| 系统 | 共享环境 |
|
|
15
15
|
| --- | --- |
|
|
@@ -18,7 +18,7 @@ Pi 加载 Personal Bot 或原生 `/reload` 后自动执行 setup,无需另行
|
|
|
18
18
|
|
|
19
19
|
首次准备从当前 PATH 选择 python3,无该命令时使用 python;需要 Python 3.11+ 和 venv/ensurepip。系统 Python 只用于创建独立 venv,不在系统环境中安装依赖。现有环境不自动替换基础解释器,也不删除额外安装的包。
|
|
20
20
|
|
|
21
|
-
首次安装可能需要数分钟和网络。环境准备不依赖 `/pbot init` 或工作区资料;不需要 Personal Bot
|
|
21
|
+
首次安装可能需要数分钟和网络。环境准备不依赖 `/pbot init` 或工作区资料;不需要 Personal Bot 时通过所属宿主的原生配置取消加载。`/pbot status` 显示环境状态。所属激活生命周期关闭时恢复本扩展修改的进程环境变量;dsh 按整个 pbot 组件共享激活,不随某个浏览器页面或单个工作区关闭而恢复,不覆盖期间其他代码对变量的新修改。外部终端和 shell 配置不变。
|
|
22
22
|
|
|
23
23
|
## 失败与手工重试
|
|
24
24
|
|
|
@@ -45,7 +45,7 @@ python3 scripts/setup-python.py
|
|
|
45
45
|
python3 scripts/setup-python.py --check # 只检查,不创建或安装
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
脚本不接受解释器或目标路径参数。独立脚本不能激活其父终端;自动激活由 pbot 完成。不修改工作区设置、脚本、历史运行记录或结果。准备脚本支持 Linux/macOS
|
|
48
|
+
脚本不接受解释器或目标路径参数。独立脚本不能激活其父终端;自动激活由 pbot 完成。不修改工作区设置、脚本、历史运行记录或结果。准备脚本支持 Linux/macOS;插件其他宿主依赖仍须满足。dsh 桌面应用从登录 Shell 读取环境,Python 3.11+ 必须在该环境的 PATH 中可见。
|
|
49
49
|
|
|
50
50
|
## 使用与验证
|
|
51
51
|
|
|
@@ -60,10 +60,10 @@ python -m pip check
|
|
|
60
60
|
python -B -m unittest discover -s python/tests -v
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
Node 测试使用真实本地文件、进程、临时 venv 与 Pi 原生 Bash,验证检查、错误、取消和激活恢复;不下载依赖。完整安装与库测试使用准备好的真实环境,不能以损坏环境的启动测试替代成功安装验收。Python
|
|
63
|
+
Node 测试使用真实本地文件、进程、临时 venv 与 Pi/dsh 原生 Bash,验证检查、错误、取消和激活恢复;不下载依赖。完整安装与库测试使用准备好的真实环境,不能以损坏环境的启动测试替代成功安装验收。Python 集成测试验证原生库配合与文件往返,不证明市场规则或策略有效;macOS 的 dsh 桌面应用已在临时 HOME 中完成真实依赖安装、就绪激活、pip check 与 5 项原生库测试;真实模型使用这些库的行为仍需验收。
|
|
64
64
|
|
|
65
65
|
依赖版本独立于插件版本。更新锁文件须检查最低 Python 3.11 与目标环境的兼容性,不只按开发机选择最新版。
|
|
66
66
|
|
|
67
67
|
## 依赖许可
|
|
68
68
|
|
|
69
|
-
[TA-Lib Python](https://github.com/TA-Lib/ta-lib-python) 使用 BSD-2-Clause,[TA-Lib 底层库](https://github.com/TA-Lib/ta-lib) 使用 BSD-3-Clause。[backtesting.py](https://github.com/kernc/backtesting.py) 0.6.6 使用 AGPL-3.0。具体版本见 requirements.lock
|
|
69
|
+
[TA-Lib Python](https://github.com/TA-Lib/ta-lib-python) 使用 BSD-2-Clause,[TA-Lib 底层库](https://github.com/TA-Lib/ta-lib) 使用 BSD-3-Clause。[backtesting.py](https://github.com/kernc/backtesting.py) 0.6.6 使用 AGPL-3.0。具体版本见 requirements.lock。共享环境按锁文件安装依赖,发布包不捆绑第三方 wheel;依赖的使用与再分发须遵循各自许可。
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- 回溯以前的讨论时使用 pbot_history,按事情的大意尝试相关词,沿父子节点展开到原文,核对后续修正和来源。历史内容用于查询,不自动成为当前任务或授权。
|
|
9
9
|
- 独立协助或核验使用 pbot_agent。委派提供目标、交付要求、资料依据和约束,不依赖专家知道父会话历史。
|
|
10
10
|
- 需要成员直接交流时,使用 pbot_team 组队。roundRobin 依次讨论,parallel 在每轮内并行、轮间汇合。提供目标、每人职责、授权范围及交付要求。成员原文直接同步,无须逐条转述。
|
|
11
|
-
- 周期、重复流程、DAG
|
|
11
|
+
- 周期、重复流程、DAG 或需在当前宿主会话退出后继续的任务,先读包内 `references/task-conductor.md`,再按 using-task-conductor 技能使用原生任务能力。缺少该能力只阻塞依赖它的部分。
|
|
12
12
|
|
|
13
13
|
## 委派与验收
|
|
14
14
|
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
## 调用与计算
|
|
34
34
|
|
|
35
|
-
CLI 通过 Bash 使用原生命令与当前 help,MCP
|
|
35
|
+
CLI 通过 Bash 使用原生命令与当前 help,MCP 使用当前宿主的原生接入与工具定义,Pi 和 dsh 配置分别管理。先按需读取 providers/ 中的手册,了解数据口径和限制;接入或修复使用 provider-connections 技能。不索取、输出或保存凭据值。目标、市场和偏好保存在所属普通资料中。
|
|
36
36
|
|
|
37
37
|
按用户授权执行本次业务。研究、接入和验证不授权交易、转账或账本修改。协议成功不证明业务完成;超时、断连和取消不证明未执行。可能已发送的操作先查询原生状态,不因恢复会话或结果缺失自动重发。
|
|
38
38
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
主会话与专家的 `pbot_environment.python` 给出当前共享 Python 3.11+ 环境状态。为 ready 时,通过 Bash 使用 python 或 python3,按任务导入第三方库原生 API。项目构建和测试遵循项目声明的环境,在对应命令中使用。
|
|
6
6
|
|
|
7
|
-
状态未就绪或依赖异常时,可自主诊断,只暂停依赖该环境的计算,不自动退回系统 Python,不删除或重建共享环境。额外依赖或共享环境变更先核对已有授权及影响范围;未获授权时说明所需变更并询问。需要重试 setup
|
|
7
|
+
状态未就绪或依赖异常时,可自主诊断,只暂停依赖该环境的计算,不自动退回系统 Python,不删除或重建共享环境。额外依赖或共享环境变更先核对已有授权及影响范围;未获授权时说明所需变更并询问。需要重试 setup 时,使用当前宿主的 `/pbot python setup` 原生入口;需要用户执行会话操作时说明该入口;专家将所需会话操作或补充授权交回主会话。
|
|
8
8
|
|
|
9
9
|
所有 pbot 工作区共用当前用户的环境。更新依赖前停止相关计算,避免影响其他工作区;不同插件版本的依赖要求可能冲突。库清单说明可用方法,不代替本次环境状态检查。
|
|
10
10
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# 原生 Task Conductor
|
|
2
2
|
|
|
3
|
-
主会话需要周期、重复流程、DAG
|
|
3
|
+
主会话需要周期、重复流程、DAG 或离开当前宿主会话后继续执行时使用本文。普通独立协助使用 pbot_agent。
|
|
4
4
|
|
|
5
5
|
## 准备能力
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
先通过当前宿主的原生工具发现查找 Task Conductor,并加载 using-task-conductor 技能,以实际 MCP schema 为准。工具未直接显示不等于未安装;技能可用时,按技能处理连接或排障。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
以下安装命令只适用于 Pi。技能缺失时,用 `pi list` 检查插件及资源启用状态。已有旧版接入包时,先审阅官方升级说明,确认来源和作用域后显式替换旧包声明,不同时加载两份;服务更新与 MCP 配置另行核对,保留任务历史。确未安装则按本项目基线使用 Pi 1.5.0,核对已有安装授权,已覆盖时直接使用工作区安装命令,未覆盖时再请求授权:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
pi install --local npm:task-conductor-plugin
|
|
@@ -14,6 +14,8 @@ pi install --local npm:task-conductor-plugin
|
|
|
14
14
|
|
|
15
15
|
需要重载及通过技能交互安装时,请用户在当前 Pi 会话执行 `/reload`,再执行 `/skill:using-task-conductor` 处理服务安装、setup 与原生 MCP 接入;这些斜杠命令不能通过 Bash 代执行。可直接读取已发现的技能继续可执行的步骤。复用已有原生连接,不在聊天中索取凭据值;CLI 配置查询不等价于当前会话的临时连接状态。插件可见不证明服务已连接,执行器 ready 不证明模型认证和执行成功。
|
|
16
16
|
|
|
17
|
+
在 dsh 中,按上游适用于当前版本的方式加载技能,并通过 dsh 原生 MCP 连接已有服务;不把 Pi 插件声明、`pi install` 或 `/reload` 用作 dsh 接入。服务端节点的执行器、认证与环境仍按其自身配置核对,不假定与当前 dsh 会话相同。
|
|
18
|
+
|
|
17
19
|
能力不可用时说明依赖它的工作受阻,继续其他已授权工作;不以循环等待或后台子会话替代持久调度。
|
|
18
20
|
|
|
19
21
|
## 委派与许可
|
|
@@ -28,4 +30,4 @@ pi install --local npm:task-conductor-plugin
|
|
|
28
30
|
|
|
29
31
|
任务定义、执行和节点分别用 taskId、runId 和节点 ID 标识。提交响应不明时先查已有标识;未取得 ID 时,按接口可用的请求关联、任务列表、提交时间或任务特征查找并核对。未能确认是否已创建时保留未知状态,不重复提交。实时状态查询 Task Conductor;项目资料只保存必要定义、标识和有时点的结果依据。
|
|
30
32
|
|
|
31
|
-
取消当前执行与停止未来周期分别操作,并查询确认。pbot_agent stop
|
|
33
|
+
取消当前执行与停止未来周期分别操作,并查询确认。pbot_agent stop 或当前宿主关闭不停止 Task Conductor。报告已设置调度须有实际提交结果;报告本轮成功须核对本轮产物与完成条件。
|
|
@@ -13,6 +13,10 @@ description: 接入或修复原生 CLI/MCP,核对认证与可用性,维护
|
|
|
13
13
|
|
|
14
14
|
## MCP
|
|
15
15
|
|
|
16
|
+
先核对当前宿主、连接来源与实际配置范围。Pi 和 dsh 分别管理原生配置,不自动同步模型、认证或 MCP。
|
|
17
|
+
|
|
18
|
+
### Pi
|
|
19
|
+
|
|
16
20
|
可先用当前可见工具及 CLI 自主诊断。需要查看当前会话的连接、认证、工具与配置来源时,请用户在该 Pi 会话执行 `/mcp`;这是会话操作,不能通过 Bash 代执行。Bash 中使用 `pi mcp --help` 及相关子命令查询或配置;CLI 查询不等价于当前会话状态,尤其不能据此判断会话内临时连接。
|
|
17
21
|
|
|
18
22
|
新增连接默认只接入当前项目。从工作区根目录执行 `pi mcp add --local <server> ...`,写入 `.pi/mcp.json`;删除项目连接使用 `pi mcp remove --local <server>`。add/remove 未指定 `--local` 时修改当前 Pi agent dir 的 `mcp.json`,仅在用户明确要求跨项目使用时选择该范围。第三方 setup 同样采用项目配置;无法指定范围时,改用 Pi 原生项目配置。
|
|
@@ -21,6 +25,12 @@ description: 接入或修复原生 CLI/MCP,核对认证与可用性,维护
|
|
|
21
25
|
|
|
22
26
|
外部修改配置后,请用户在当前 Pi 会话执行 `/reload`,再用 `/mcp` 核对实际配置来源和连接状态;不要声称已代用户完成会话操作。当前工具 schema 通过原生工具搜索或 codemode 按需取得。新增权限、安装或共享配置变更先核对已有授权,已授权的操作不重复询问。
|
|
23
27
|
|
|
28
|
+
### dsh
|
|
29
|
+
|
|
30
|
+
使用当前固定版本的原生 MCP 组件、profile 设置、认证与工具发现。按其公开文档或当前 help 核对参数,不使用 Pi 的命令和 `.pi/mcp.json` 配置方式。连接可能服务于同一 profile 的多个工作区,修改前核对实际作用域及已有授权,不把 profile 配置称为工作区隔离。
|
|
31
|
+
|
|
32
|
+
优先复用已有连接,保留无关条目与其他工作区配置。用原生界面或可用管理能力完成已授权操作,再从当前会话核对工具、认证与连接状态;确需用户执行原生操作时,明确对应入口。工具可见不代表连接或业务调用成功,不为验证连接擅自执行写操作。
|
|
33
|
+
|
|
24
34
|
## 验证与手册
|
|
25
35
|
|
|
26
36
|
用本次获准的查询验证所需能力,将实际接口、时间、覆盖范围与结果依据保存在所属项目。区分配置已保存、连接可用和业务已验证。
|
package/scripts/README.md
CHANGED
|
@@ -10,8 +10,16 @@
|
|
|
10
10
|
|
|
11
11
|
`npm run build:cli` 调用 `build-cli.mjs`,清理生成目录 lib,再按 tsconfig.cli.json 编译独立 CLI、Pi 检查桥接和启动保护。bin/pbot.mjs 转交已生成的入口。npm test 的构建与 prepack 都执行此步骤;扩展运行仍由 Pi 加载 src 源码。消费者直接使用发布包中的 lib,无需安装开发依赖。
|
|
12
12
|
|
|
13
|
+
## dsh 构建
|
|
14
|
+
|
|
15
|
+
`npm run build:dsh` 调用 `build-dsh.mjs`,由 tsconfig.dsh.json 编译 Host 与浏览器入口,再用 esbuild 将 Web 代码包装为固定版原生包根 Loader 模块。宿主 SDK 保持 external;完整 build 和 prepack 先构建 CLI、再构建 dsh,统一输出到 lib。
|
|
16
|
+
|
|
17
|
+
## 发布包消费者检查
|
|
18
|
+
|
|
19
|
+
`node scripts/check-consumer.mjs <tarball>` 在临时目录安装实际发布包,先检查独立 CLI 与宿主 SDK 缺省状态,再安装 package.json 中锁定的 Pi SDK,验证扩展、工具、技能和资料初始化。CI 使用 Node.js 22.19.0 执行,完整开发依赖、dsh 构建和全量测试仍使用 Node.js 24.9+。检查使用独立用户目录与损坏 Python 目标,不下载计算依赖或调用模型;结束后删除本次临时目录。
|
|
20
|
+
|
|
13
21
|
## 构建清理
|
|
14
22
|
|
|
15
23
|
`clean-dist.mjs` 由 npm run build 调用,仅清理仓库内生成的 dist/,供 TypeScript 重新编译测试导入。
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
本包不提供工作区升级命令或历史转换脚本。插件安装和更新由对应宿主的原生包管理或用户维护的源码目录负责。
|
package/src/dsh.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import { registerDshCommand } from "./extension/dsh/command.js";
|
|
3
|
+
import { registerDshManagement } from "./extension/dsh/management.js";
|
|
4
|
+
import { DshWorkspaces, dshDependencies } from "./extension/dsh/workspace.js";
|
|
5
|
+
import { requireThat } from "./common/validation.js";
|
|
6
|
+
|
|
7
|
+
export const name = "personal-bot";
|
|
8
|
+
export const inject = ["commands", "typert", ...dshDependencies];
|
|
9
|
+
|
|
10
|
+
export async function apply(ctx: Context) {
|
|
11
|
+
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
12
|
+
requireThat(major! > 24 || (major === 24 && minor! >= 9), "dsh 接入需要 Node.js 24.9.0 或更新版本。");
|
|
13
|
+
const workspaces = new DshWorkspaces(ctx);
|
|
14
|
+
ctx.effect(() => () => workspaces.close());
|
|
15
|
+
const management = registerDshManagement(ctx, workspaces);
|
|
16
|
+
registerDshCommand(ctx, workspaces, management);
|
|
17
|
+
ctx.on("agent/created", async ({ agent }) => {
|
|
18
|
+
if (ctx.agents.roots().includes(agent) && agent.session.header.origin !== "subagent") await workspaces.open(agent);
|
|
19
|
+
});
|
|
20
|
+
for (const agent of ctx.agents.roots()) if (agent.session.header.origin !== "subagent") await workspaces.open(agent);
|
|
21
|
+
void workspaces.preparePython().catch(error => ctx.logger.warn(String(error)));
|
|
22
|
+
}
|
|
@@ -6,12 +6,13 @@ import { agentOwner, deliveredCycles } from "../integrations/pi/agent-context.js
|
|
|
6
6
|
import { agentBoard } from "../ui/agent-display.js";
|
|
7
7
|
import { deliveredTeams } from "../integrations/pi/team-context.js";
|
|
8
8
|
import type { TeamInput } from "../model/team.js";
|
|
9
|
-
import {
|
|
9
|
+
import { agentNotice, teamNotice } from "../services/agents/agent-notices.js";
|
|
10
10
|
import { markdownFields } from "../common/markdown.js";
|
|
11
11
|
|
|
12
12
|
export function registerAgentEvents(pi: ExtensionAPI, lifecycle: Lifecycle, confirmations: Confirmations) {
|
|
13
13
|
let ctx: ExtensionContext | undefined, timer: ReturnType<typeof setInterval> | undefined;
|
|
14
|
-
let paused = false;
|
|
14
|
+
let paused = false, epoch = 0, refreshEpoch = 0;
|
|
15
|
+
let refreshing: Promise<void> | undefined;
|
|
15
16
|
let controlBusySince: number | undefined;
|
|
16
17
|
let failure: { key: string; error: string; recovery: "retry" | "repair" | "reload" } | undefined;
|
|
17
18
|
const recordFailure = (error: unknown) => {
|
|
@@ -44,45 +45,32 @@ export function registerAgentEvents(pi: ExtensionAPI, lifecycle: Lifecycle, conf
|
|
|
44
45
|
if (!busy) throw error;
|
|
45
46
|
}
|
|
46
47
|
};
|
|
47
|
-
const collectNotification = (): CustomMessageEntryDraft | undefined => {
|
|
48
|
-
const instance = lifecycle.active;
|
|
48
|
+
const collectNotification = async (): Promise<CustomMessageEntryDraft | undefined> => {
|
|
49
|
+
const instance = lifecycle.active, revision = epoch;
|
|
49
50
|
if (!ctx || !instance || paused || ctx.signal?.aborted) return;
|
|
50
51
|
const delivered = new Set([...deliveredCycles(ctx), ...deliveredTeams(ctx)]), now = Date.now();
|
|
51
52
|
for (const [key, at] of submitting) if (delivered.has(key) || now - at > 5000) submitting.delete(key);
|
|
52
|
-
const owner = agentOwner(ctx)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
notes.map(v => ["## " + v.name, "", "- `teamId`: `" + v.teamId + "`", "- `runId`: `" + v.runId + "`",
|
|
60
|
-
"- 状态:" + v.state, "- 在途工作:" + v.activeCount, ...(v.reason ? ["", "### 原因", "", v.reason] : [])].join("\n")).join("\n\n")].join("\n"),
|
|
61
|
-
details: { keys } };
|
|
53
|
+
const owner = agentOwner(ctx);
|
|
54
|
+
let note: ReturnType<typeof teamNotice> | ReturnType<typeof agentNotice> = teamNotice(
|
|
55
|
+
instance.teams.notifications(owner, instance.agents.list(owner)), new Set([...delivered, ...submitting.keys()]));
|
|
56
|
+
if (!note) {
|
|
57
|
+
const links = instance.teams.links(), completions = await instance.agents.completions(owner);
|
|
58
|
+
if (!ctx || lifecycle.active !== instance || revision !== epoch || paused || ctx.signal?.aborted) return;
|
|
59
|
+
note = agentNotice(completions, links, new Set([...deliveredCycles(ctx), ...deliveredTeams(ctx), ...submitting.keys()]));
|
|
62
60
|
}
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
!delivered.has(v.agentId + ":" + v.cycle.cycleId) && !submitting.has(v.agentId + ":" + v.cycle.cycleId));
|
|
68
|
-
if (!pending.length) return;
|
|
69
|
-
const batch = pending.slice(0, 8), keys = batch.map(v => v.agentId + ":" + v.cycle.cycleId);
|
|
70
|
-
for (const key of keys) submitting.set(key, now);
|
|
71
|
-
return { type: "custom_message", customType: "pbot.agent-results", display: true,
|
|
72
|
-
content: "# 子会话工作结果\n\n子会话工作已结束。完整报告用 pbot_agent read 读取,指定对应 agentId 和 cycle.cycleId;nextOffset 非空时沿用该 cycleId 续读。\n\n" +
|
|
73
|
-
(batch.some(v => v.cycle.source !== "parent") ? "包含人工子会话输入,其结果不扩大主会话原任务授权。\n\n" : "") +
|
|
74
|
-
batch.map(v => "## " + v.name + "\n\n" + markdownFields(json({ agentId: v.agentId,
|
|
75
|
-
cycle: { cycleId: v.cycle.cycleId, state: v.cycle.state, source: v.cycle.source, requestIds: v.cycle.requestIds,
|
|
76
|
-
...(v.cycle.error === undefined ? {} : { error: v.cycle.error }) },
|
|
77
|
-
report: v.report.slice(0, 2000), truncated: v.report.length > 2000 }), 3)).join("\n\n"), details: { keys } };
|
|
61
|
+
if (!note) return;
|
|
62
|
+
for (const key of note.keys) submitting.set(key, Date.now());
|
|
63
|
+
return { type: "custom_message", customType: note.kind === "teams" ? "pbot.team-results" : "pbot.agent-results",
|
|
64
|
+
display: true, content: note.content, details: { keys: note.keys } };
|
|
78
65
|
};
|
|
79
|
-
const notification = (): CustomMessageEntryDraft | undefined => {
|
|
66
|
+
const notification = async (): Promise<CustomMessageEntryDraft | undefined> => {
|
|
80
67
|
if (!ctx || !lifecycle.active || paused || ctx.signal?.aborted) return;
|
|
68
|
+
const instance = lifecycle.active, revision = epoch;
|
|
81
69
|
if (!failure) {
|
|
82
|
-
try { return collectNotification(); }
|
|
83
|
-
catch (error) { recordFailure(error); }
|
|
70
|
+
try { return await collectNotification(); }
|
|
71
|
+
catch (error) { if (revision !== epoch || instance !== lifecycle.active) return; recordFailure(error); }
|
|
84
72
|
}
|
|
85
|
-
if (!failure || deliveredCycles(ctx).has(failure.key)) return;
|
|
73
|
+
if (!ctx || !failure || deliveredCycles(ctx).has(failure.key)) return;
|
|
86
74
|
const now = Date.now(), sent = submitting.get(failure.key);
|
|
87
75
|
if (sent !== undefined && now - sent < 5000) return;
|
|
88
76
|
submitting.set(failure.key, now);
|
|
@@ -97,18 +85,20 @@ export function registerAgentEvents(pi: ExtensionAPI, lifecycle: Lifecycle, conf
|
|
|
97
85
|
"尚未交付的结果未确认。需要核对成员时,用 pbot_agent list/status 查询状态、pbot_agent read 读取可用报告;结果未知不构成重新提交的依据。", "",
|
|
98
86
|
markdownFields({ error: failure.error })].join("\n"), details: { keys: [failure.key] } };
|
|
99
87
|
};
|
|
100
|
-
const
|
|
101
|
-
const instance = lifecycle.active;
|
|
88
|
+
const refreshWork = async () => {
|
|
89
|
+
const instance = lifecycle.active, revision = epoch;
|
|
102
90
|
if (!ctx || !instance) return;
|
|
103
91
|
try {
|
|
104
92
|
instance.agentOwner = agentOwner(ctx);
|
|
105
|
-
instance.agents.refresh(instance.agentOwner);
|
|
93
|
+
await instance.agents.refresh(instance.agentOwner);
|
|
94
|
+
const completed = await instance.agents.completions(instance.agentOwner);
|
|
95
|
+
if (!ctx || lifecycle.active !== instance || revision !== epoch) return;
|
|
106
96
|
const values = instance.agents.list(instance.agentOwner);
|
|
107
97
|
try {
|
|
108
98
|
instance.teams.recover(instance.agentOwner);
|
|
109
99
|
if (pausePending) pauseTeams();
|
|
110
100
|
if (!pausePending) {
|
|
111
|
-
for (const input of instance.teams.advance(instance.agentOwner, values,
|
|
101
|
+
for (const input of instance.teams.advance(instance.agentOwner, values, completed)) dispatching.set(input.requestId, input);
|
|
112
102
|
for (const [id, input] of dispatching) {
|
|
113
103
|
try { instance.agents.enqueueTeam(input, instance.agentOwner); dispatching.delete(id); }
|
|
114
104
|
catch (error) {
|
|
@@ -133,26 +123,41 @@ export function registerAgentEvents(pi: ExtensionAPI, lifecycle: Lifecycle, conf
|
|
|
133
123
|
if (ctx.hasUI) ctx.ui.setStatus("pbot-agents-error", undefined);
|
|
134
124
|
}
|
|
135
125
|
} catch (error) {
|
|
126
|
+
if (revision !== epoch || instance !== lifecycle.active) return;
|
|
136
127
|
recordFailure(error);
|
|
137
128
|
}
|
|
138
|
-
if (ctx
|
|
129
|
+
if (ctx?.isIdle() && !paused) {
|
|
130
|
+
const message = await notification();
|
|
131
|
+
if (message && revision === epoch && instance === lifecycle.active && ctx?.isIdle() && !paused) pi.sendMessage(message, { triggerTurn: true, deliverAs: "steer" });
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const refresh = (): Promise<void> => {
|
|
135
|
+
if (refreshing) return refreshEpoch === epoch ? refreshing : refreshing.then(() => refresh());
|
|
136
|
+
refreshEpoch = epoch;
|
|
137
|
+
const revision = epoch;
|
|
138
|
+
const pending = refreshWork().catch(error => { if (revision === epoch) recordFailure(error); }).finally(() => {
|
|
139
|
+
if (refreshing === pending) refreshing = undefined;
|
|
140
|
+
});
|
|
141
|
+
refreshing = pending;
|
|
142
|
+
return pending;
|
|
139
143
|
};
|
|
140
|
-
const boundary = (outcome: string, entries: SessionBoundaryDraft[], context: ExtensionContext) => {
|
|
144
|
+
const boundary = async (outcome: string, entries: SessionBoundaryDraft[], context: ExtensionContext) => {
|
|
141
145
|
ctx = context;
|
|
142
146
|
if (outcome === "aborted" || ctx.signal?.aborted) { paused = true; confirmations.pause(); pauseTeams(); return; }
|
|
143
|
-
const
|
|
144
|
-
|
|
147
|
+
const revision = epoch, instance = lifecycle.active;
|
|
148
|
+
const message = await notification();
|
|
149
|
+
if (message && revision === epoch && instance === lifecycle.active && !paused && !ctx?.signal?.aborted) return { entries: [...entries, message], continue: true };
|
|
145
150
|
return;
|
|
146
151
|
};
|
|
147
152
|
pi.on("session_start", (_event, context) => {
|
|
148
|
-
ctx = context; paused = false; pausePending = false; controlBusySince = undefined; failure = undefined; confirmations.resume(); submitting.clear(); dispatching.clear();
|
|
153
|
+
epoch++; ctx = context; paused = false; pausePending = false; controlBusySince = undefined; failure = undefined; confirmations.resume(); submitting.clear(); dispatching.clear();
|
|
149
154
|
if (timer) clearInterval(timer);
|
|
150
|
-
if (lifecycle.active) { lifecycle.active.agentOwner = agentOwner(ctx); timer = setInterval(refresh, 1000); timer.unref(); }
|
|
151
|
-
refresh();
|
|
155
|
+
if (lifecycle.active) { lifecycle.active.agentOwner = agentOwner(ctx); timer = setInterval(() => { void refresh(); }, 1000); timer.unref(); }
|
|
156
|
+
return refresh();
|
|
152
157
|
});
|
|
153
158
|
pi.on("input", (_event, context) => { ctx = context; paused = false; confirmations.resume(); });
|
|
154
159
|
pi.on("before_agent_start", (_event, context) => { ctx = context; });
|
|
155
|
-
pi.on("session_tree", (_event, context) => { ctx = context; submitting.clear(); refresh(); });
|
|
160
|
+
pi.on("session_tree", (_event, context) => { epoch++; ctx = context; submitting.clear(); return refresh(); });
|
|
156
161
|
pi.on("turn_end", (event, context) => boundary(event.outcome, event.entries, context));
|
|
157
162
|
pi.on("agent_before_settle", (event, context) => boundary(event.outcome, event.entries, context));
|
|
158
163
|
pi.on("agent_settled", (event, context) => {
|
|
@@ -163,5 +168,5 @@ export function registerAgentEvents(pi: ExtensionAPI, lifecycle: Lifecycle, conf
|
|
|
163
168
|
const keys = (event.details as { agentReadKeys?: string[] } | undefined)?.agentReadKeys;
|
|
164
169
|
if (keys?.length) pi.appendEntry("pbot.agent-read", { keys, toolCallId: event.parentToolCallId ?? event.toolCallId });
|
|
165
170
|
});
|
|
166
|
-
pi.on("session_shutdown", () => { if (timer) clearInterval(timer); timer = undefined; submitting.clear(); dispatching.clear(); pausePending = false; ctx = undefined; });
|
|
171
|
+
pi.on("session_shutdown", () => { epoch++; if (timer) clearInterval(timer); timer = undefined; submitting.clear(); dispatching.clear(); pausePending = false; ctx = undefined; });
|
|
167
172
|
}
|
|
@@ -5,43 +5,57 @@ import type { WorkspaceInstance } from "./lifecycle.js";
|
|
|
5
5
|
import { agentOwner } from "../integrations/pi/agent-context.js";
|
|
6
6
|
import { tmuxName } from "../integrations/pi/pi-agents.js";
|
|
7
7
|
import { agentSummary } from "../ui/agent-display.js";
|
|
8
|
+
import { readPage } from "../ui/pi/reader.js";
|
|
9
|
+
import { choose } from "../ui/pi/menu.js";
|
|
10
|
+
import { stateLabel } from "../ui/presentation.js";
|
|
8
11
|
import type { Confirmations } from "../ui/confirmation.js";
|
|
9
12
|
|
|
10
13
|
export async function showAgents(_pi: ExtensionAPI, instance: WorkspaceInstance, ctx: ExtensionCommandContext, confirmations: Confirmations, agentIds?: string[]) {
|
|
11
14
|
instance.check();
|
|
12
|
-
const owner = () => agentOwner(ctx),
|
|
13
|
-
if (ctx.mode !== "tui") { ctx.ui.notify(JSON.stringify(
|
|
14
|
-
if (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
15
|
+
const owner = () => agentOwner(ctx), views = () => instance.agents.list(owner()).filter(v => !agentIds || agentIds.includes(v.agentId));
|
|
16
|
+
if (ctx.mode !== "tui") { ctx.ui.notify(JSON.stringify(views()), "info"); return; }
|
|
17
|
+
if (confirmations.presenting) { ctx.ui.notify("请先处理待确认操作。", "info"); return; }
|
|
18
|
+
for (;;) {
|
|
19
|
+
instance.check(); const values = views();
|
|
20
|
+
if (!values.length) { ctx.ui.notify("还没有专家。告诉主助手需要什么专家即可创建。", "info"); return; }
|
|
21
|
+
const options = values.map(v => agentSummary(v) + (v.owned ? "" : " · 其他分支"));
|
|
22
|
+
const selected = await choose(ctx, "专家", options), picked = values[options.indexOf(selected ?? "")]; if (!picked) return;
|
|
23
|
+
if (!picked.owned) { ctx.ui.notify("请返回所属分支操作。", "info"); continue; }
|
|
24
|
+
for (;;) {
|
|
25
|
+
instance.check(); const value = instance.agents.status(picked.agentId, owner()), inTmux = Boolean(process.env.TMUX);
|
|
26
|
+
const enterTui = value.alive ? "进入会话" : "打开原会话(待命)";
|
|
27
|
+
const action = await choose(ctx, `${value.name} · ${stateLabel(value.state)}`, [enterTui, "详情", ...(value.alive ? ["补充要求"] : []), "重命名", ...(value.alive ? ["停止"] : [])]);
|
|
28
|
+
if (!action) break;
|
|
29
|
+
instance.check();
|
|
30
|
+
try {
|
|
31
|
+
if (action === "详情") {
|
|
32
|
+
await readPage(ctx, value.name, [`状态 ${stateLabel(value.state)}`, `活动 ${value.activity}`, `模型 ${value.options.provider}/${value.options.model}`,
|
|
33
|
+
`目录 ${value.cwd}`, `ID ${value.agentId}`, ...(value.error ? ["", value.error] : []), "", `返回主会话:Ctrl+B → ${inTmux ? "l" : "d"}`].join("\n")); continue;
|
|
34
|
+
}
|
|
35
|
+
if (action === "停止") { instance.agents.stop(value.agentId, owner()); ctx.ui.notify("已请求停止。", "info"); continue; }
|
|
36
|
+
if (action === "重命名") {
|
|
37
|
+
const name = await ctx.ui.input("新名称", value.name); instance.check();
|
|
38
|
+
if (name?.trim()) { instance.agents.rename(value.agentId, name.trim(), owner()); ctx.ui.notify("名称已更新。", "info"); } continue;
|
|
39
|
+
}
|
|
40
|
+
if (action === "补充要求") {
|
|
41
|
+
const message = await ctx.ui.editor("补充要求"); instance.check();
|
|
42
|
+
if (message?.trim()) { instance.agents.send(value.agentId, message, "steer", owner()); ctx.ui.notify("要求已排队。", "info"); } continue;
|
|
43
|
+
}
|
|
44
|
+
if (action !== enterTui) continue;
|
|
45
|
+
ctx.ui.notify(`返回主会话:Ctrl+B → ${inTmux ? "l" : "d"}`, "info");
|
|
46
|
+
let tui: TUI | undefined;
|
|
47
|
+
await ctx.ui.custom<void>((terminal, _theme, _keys, done) => { tui = terminal; queueMicrotask(() => done()); return new Text("", 0, 0); });
|
|
48
|
+
if (!tui) return;
|
|
49
|
+
instance.check(); await instance.agents.enter(value.agentId, owner()); const terminal = tui; terminal.stop();
|
|
50
|
+
try {
|
|
51
|
+
const code = await new Promise<number | null>(resolve => {
|
|
52
|
+
const child = spawn("tmux", [inTmux ? "switch-client" : "attach-session", "-t", "=" + tmuxName(value.agentId)], { stdio: "inherit" });
|
|
53
|
+
child.on("error", () => resolve(null)); child.on("close", resolve);
|
|
54
|
+
});
|
|
55
|
+
if (code !== 0) ctx.ui.notify("无法进入专家会话。", "error");
|
|
56
|
+
} finally { terminal.start(); terminal.requestRender(true); }
|
|
57
|
+
return;
|
|
58
|
+
} catch (error) { ctx.ui.notify(error instanceof Error ? error.message : String(error), "error"); }
|
|
59
|
+
}
|
|
31
60
|
}
|
|
32
|
-
if (action !== enterTui) return;
|
|
33
|
-
let tui: TUI | undefined;
|
|
34
|
-
await ctx.ui.custom<void>((terminal, _theme, _keys, done) => { tui = terminal; queueMicrotask(() => done()); return new Text("", 0, 0); });
|
|
35
|
-
if (!tui) return;
|
|
36
|
-
instance.check();
|
|
37
|
-
instance.agents.enter(value.agentId, owner());
|
|
38
|
-
const terminal = tui;
|
|
39
|
-
terminal.stop();
|
|
40
|
-
try {
|
|
41
|
-
const code = await new Promise<number | null>(resolve => {
|
|
42
|
-
const child = spawn("tmux", [inTmux ? "switch-client" : "attach-session", "-t", "=" + tmuxName(value.agentId)], { stdio: "inherit" });
|
|
43
|
-
child.on("error", () => resolve(null)); child.on("close", resolve);
|
|
44
|
-
});
|
|
45
|
-
if (code !== 0) ctx.ui.notify("无法进入子会话。", "error");
|
|
46
|
-
} finally { terminal.start(); terminal.requestRender(true); }
|
|
47
61
|
}
|