personal-bot 0.2.6 → 0.2.8

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.
Files changed (69) hide show
  1. package/README.md +47 -13
  2. package/README.zh-CN.md +46 -12
  3. package/docs/README.md +4 -2
  4. package/docs/agent-collaboration.md +4 -4
  5. package/docs/capability-design.md +12 -6
  6. package/docs/dsh-implementation-plan.md +9 -7
  7. package/docs/dsh-support-proposal.md +6 -22
  8. package/docs/dsh.en.md +333 -0
  9. package/docs/dsh.md +346 -48
  10. package/docs/file-storage.md +1 -1
  11. package/docs/history.md +2 -0
  12. package/docs/installation-design.md +7 -4
  13. package/docs/model-context.md +60 -0
  14. package/docs/model-instruction-guidelines.md +51 -0
  15. package/docs/release.md +10 -6
  16. package/docs/subagent-upgrade-proposal.md +1 -1
  17. package/docs/technical-design.md +21 -15
  18. package/docs/validation.md +64 -7
  19. package/lib/dsh.js +4 -0
  20. package/lib/extension/dsh/agent-events.js +1 -1
  21. package/lib/extension/dsh/agent-runtime.js +8 -5
  22. package/lib/integrations/dsh/resources.d.ts +1 -1
  23. package/lib/integrations/dsh/resources.js +14 -14
  24. package/lib/integrations/dsh/session.js +1 -0
  25. package/lib/integrations/installation/pi-bridge.js +9 -9
  26. package/lib/integrations/team-context.js +7 -3
  27. package/lib/services/agents/agent-notices.js +2 -2
  28. package/lib/services/agents/team-service.js +1 -1
  29. package/lib/tools/agents/contract.d.ts +1 -1
  30. package/lib/tools/agents/contract.js +7 -7
  31. package/lib/tools/agents/dsh-contract.js +4 -4
  32. package/lib/tools/history/contract.d.ts +1 -1
  33. package/lib/tools/history/contract.js +2 -2
  34. package/lib/tools/teams/contract.d.ts +2 -2
  35. package/lib/tools/teams/contract.js +11 -11
  36. package/npm-shrinkwrap.json +30 -25
  37. package/package.json +28 -25
  38. package/python/README.md +1 -1
  39. package/resources/agents/coordinator.md +5 -33
  40. package/resources/agents/general-purpose.md +3 -15
  41. package/resources/prompts/history-summary.md +1 -1
  42. package/resources/prompts/team-member.md +7 -0
  43. package/resources/prompts/workspace.md +13 -24
  44. package/resources/references/compute-finance.md +22 -0
  45. package/resources/references/compute.md +11 -88
  46. package/resources/references/task-conductor.md +20 -15
  47. package/resources/skills/project-maintenance/SKILL.md +9 -11
  48. package/resources/skills/provider-connections/SKILL.md +7 -7
  49. package/scripts/README.md +1 -1
  50. package/src/dsh.ts +4 -0
  51. package/src/extension/agent-events.ts +17 -4
  52. package/src/extension/command.ts +1 -1
  53. package/src/extension/dsh/agent-events.ts +1 -1
  54. package/src/extension/dsh/agent-runtime.ts +7 -6
  55. package/src/extension/events.ts +14 -9
  56. package/src/extension/subagent-entry.ts +24 -16
  57. package/src/integrations/dsh/resources.ts +17 -14
  58. package/src/integrations/dsh/session.ts +2 -0
  59. package/src/integrations/installation/pi-bridge.ts +9 -7
  60. package/src/integrations/pi/agent-context.ts +1 -1
  61. package/src/integrations/team-context.ts +7 -3
  62. package/src/services/agents/agent-notices.ts +2 -2
  63. package/src/services/agents/team-service.ts +1 -1
  64. package/src/tools/agents/contract.ts +7 -7
  65. package/src/tools/agents/dsh-contract.ts +4 -4
  66. package/src/tools/history/contract.ts +2 -2
  67. package/src/tools/register.ts +1 -7
  68. package/src/tools/teams/contract.ts +11 -11
  69. package/resources/prompts/tool-guidelines.md +0 -3
@@ -0,0 +1,51 @@
1
+ # 模型指令编写原则
2
+
3
+ 修改 Agent 实际可见的内容及其加载方式时遵循本文。范围包括 Pi 与 dsh 的主会话、专家、历史摘要,以及公共提示、角色、动态环境、团队消息、通知、工具说明、技能、参考资料和模板。当前加载方式见[模型上下文](model-context.md)。
4
+
5
+ ## 从实际上下文出发
6
+
7
+ 以宿主实际组装的内容判断取舍,尤其检查新会话第一次任务。同时考虑宿主提示、用户资料、工具声明和技能目录,避免只看某个 Markdown 文件。
8
+
9
+ 每段指令应有具体用途:它帮助模型作什么决定、执行什么操作,或者避免什么已知错误。根据用途保留、合并、删除、条件加载或按需读取,不以字数最少为目标。没有明确需求的规则不要因为“看起来更严谨”而加入。
10
+
11
+ ## 直接说明要做什么
12
+
13
+ 使用自然、直接的语言,写清职责、操作入口、参数含义和下一步。内部架构与执行机制只在改变实际操作时说明,其余留在开发文档。
14
+
15
+ 例如,委派时说明目标、相关资料、约束和交付要求即可,不需要再向模型解释“不继承父聊天历史”。状态、分页、通知领取和异步完成等含义会影响工具调用,应保留必要细节。
16
+
17
+ ## 不增加泛化流程
18
+
19
+ 按用户请求和已有约定推进,不自行补入通用的证据收集、授权核对、审批、独立复核或业务验收流程。不在公共提示、角色、工具和通知中反复写“不扩大授权”“不等于成功”等提醒,也不为普通交付固定证据报告或复核结论格式。
20
+
21
+ 具体任务需要查来源、复核计算或检查结果时,写明实际要检查什么。专业方法可以保留影响结果的口径、假设、数据处理和适用条件;常规操作不因此变成逐项审批或留证任务。独立复核按用户需求或具体问题安排,不设为默认必经步骤。
22
+
23
+ 权限和确认机制沿用宿主、凭据、外部服务及用户约定。不要为假设风险新增提示门槛,也不要通过提示掩盖或绕过实际执行限制。保留直接影响操作的事项,如配置作用域、凭据引用、内容公开范围,以及结果未知时先查状态、避免重复执行。
24
+
25
+ ## 保留实用细节,按用途放置
26
+
27
+ | 内容 | 放置要求 |
28
+ | --- | --- |
29
+ | 首次任务就需要的职责与资料位置 | 放在公共提示或对应角色中 |
30
+ | 工作区目录用途与组织规范 | 保留首轮可见的目录说明和模板导航;不能只藏在尚未选择的维护技能里,已有用户布局与约定优先 |
31
+ | 工具参数、分页、状态和结果入口 | 放在工具契约中,避免其他提示重复完整说明 |
32
+ | 团队等特定任务说明 | 仅在相应任务或状态下加入 |
33
+ | 维护、接入、计算及调度方法 | 通过技能或参考资料按需读取,正文包含能实际执行的方法和必要细节 |
34
+ | 动态环境与错误 | 提供当前操作需要的字段;详细诊断留在状态或日志入口 |
35
+ | 历史摘要 | 使用专用提示与待总结资料,不混入普通工作角色和无关技能 |
36
+
37
+ 优先使用宿主已有的资源发现、技能、工具、配置和上下文去重机制。检查同一要求是否已由宿主或其他已加载内容提供;专用说明不要无条件叠加到所有会话。
38
+
39
+ ## 在正确位置修复
40
+
41
+ 先区分提示内容、上下文组装、功能实现和测试问题。加载缺失、时序错误、重复注入或错误处理问题应修代码;不要增加提示规则来补偿。
42
+
43
+ 发现一类问题后,检查两个宿主及其他相关入口,包括代码生成的任务、通知和工具结果。复查既有处理是否过度定制,不为单个案例继续叠加规则。
44
+
45
+ 修改插件自身的内容与加载逻辑,保留用户资料、角色补充、历史和备份。不要为了整理提示而迁移用户布局、覆盖用户约定或改变既有执行合同。
46
+
47
+ ## 验证与记录
48
+
49
+ 加载行为用真实宿主 SDK、本地文件和进程检查来源、首轮出现时机、后续更新、条件加载及去重。测试应覆盖具体行为,不能断言提示句子、标签或全文快照;不能为了满足文案断言反向修改提示,也不为纯文案调整新增此类测试。
50
+
51
+ 运行适用的仓库检查,并在设计文档说明当前行为。字符数只能说明文本长度变化;本地加载检查不证明模型理解、专业结果或费用改善。真实模型效果按实际验收范围记录。
package/docs/release.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # npm 发布
2
2
 
3
- 发布配置以 package.json 为准:包名 personal-bot,registry 为 npmjs,稳定版本使用 latest。包包含 Pi 扩展源码、资源和预构建的安装 CLI。扩展由 Pi 加载;npx 与全局 pbot 命令由 Node 直接运行。
3
+ 发布配置以 package.json 为准:包名 personal-bot,registry 为 npmjs,稳定版本使用 latest。包包含 Pi 扩展源码、共享资源、预构建的安装 CLI 和 dsh Host/Web 产物。Pi 加载源码入口,dsh 通过原生包根 Loader 加载 Host 与 Web 客户端;npx 与全局 pbot 命令由 Node 直接运行。
4
4
 
5
5
  ## 首次配置
6
6
 
@@ -38,13 +38,15 @@ npm pack --dry-run
38
38
  npm pack
39
39
  ```
40
40
 
41
- prepack 先检查再构建 CLI。核对包清单包含 bin、lib、src、resources、Python 锁文件、setup 脚本和 npm-shrinkwrap.json,排除 dist、node_modules、凭据与运行数据。Pi 宿主包保持 optional peerDependencies,避免 npx 安装入口隐式下载宿主。另在独立 npm cache/prefix 中验证 tarball 的 npm exec 与全局 pbot --version,检查未额外安装 Pi SDK。
41
+ prepack 依次执行 `npm run check`、`npm run build:cli`、`npm run build:dsh`。核对包清单包含 bin、lib(含 dsh Host/Web 产物)、src、resources(含 dsh bundle patch)、Python 锁文件、setup 脚本和 npm-shrinkwrap.json,排除 dist、node_modules、凭据与运行数据。核对包根与 `./dsh` 导出指向 `./lib/dsh.js`、`./client` 指向 `./lib/client.js`,以及 dsh bundle/client 元数据完整。
42
42
 
43
- 在独立 Pi 配置和临时工作区验收安装;加载扩展会准备用户级 Python 环境,因此验收同时使用独立用户数据目录。
43
+ Pi/dsh 宿主包保持 optional peerDependencies,避免独立 CLI 安装时隐式下载宿主 SDK。dsh SDK peer 范围为 `"*"`,最低宿主要求由 `engines.dsh` 声明;用户安装跟随 `latest`,开发依赖及锁文件保留精确版本。发布验收记录实际 dsh/pnpm 版本,不把最低版本声明视为未来版本已验收。共享契约库 TypeBox 是范围为 `"*"` 的必需 peer,开发依赖锁定版本;Pi 原生加载器提供它,dsh 安装时由包管理器补齐。另在独立 npm cache/prefix 中验证 tarball 的 npm exec 与全局 pbot --version,检查未额外安装 Pi/dsh SDK。
44
+
45
+ 在独立 Pi 配置和临时工作区验收安装;加载扩展会准备用户级 Python 环境,因此验收同时使用独立用户数据目录。再按[dsh 使用说明](dsh.md),在当前 dsh `latest` 的隔离 Web profile 中通过原生插件命令安装同一 tarball,并记录实际宿主版本,核对 Host 启用、包根 Web 客户端加载、`/pbot` 四页签及原生 Remote 查询。验证范围与剩余缺口见[验证](validation.md)。
44
46
 
45
47
  ## GitHub 发布
46
48
 
47
- [CI](../.github/workflows/ci.yml) 在 Node 24.x 安装完整开发依赖、执行检查和测试,再生成候选 tarball;独立 Node 22.19.0 作业安装同一 tarball,检查 CLI 不隐式安装宿主 SDK,再显式安装锁定的 Pi SDK,验证扩展、工具、技能和资料初始化。消费者检查不安装 dsh 开发依赖,不调用模型。[发布工作流](../.github/workflows/publish.yml)要求:
49
+ [CI](../.github/workflows/ci.yml) 在 Node 24.x 安装完整开发依赖、执行检查和测试,再生成候选 tarball;独立 Node 22.19.0 作业安装同一 tarball,检查 CLI 不隐式安装宿主 SDK,再显式安装锁定的 Pi SDK,验证扩展、工具、技能和资料初始化。独立消费者作业仅验证 Pi/CLI,不安装 dsh 开发依赖,不调用模型;全量测试中的 dsh 本地 SDK 测试不代表候选包的包根 Web 加载和 Remote 传输已自动验收。dsh 原生安装与界面按上述步骤单独验证。[发布工作流](../.github/workflows/publish.yml)要求:
48
50
 
49
51
  - tag 为 v<稳定版本>,包与锁文件版本一致。
50
52
  - 提交已进入远端默认分支。
@@ -89,8 +91,10 @@ npm view "personal-bot@$VERSION" version --registry=https://registry.npmjs.org
89
91
  npm view personal-bot dist-tags --json --registry=https://registry.npmjs.org
90
92
  ```
91
93
 
92
- 在独立 Pi 配置和临时工作区执行 `pi install --local npm:personal-bot`,核对安装版本、扩展加载、技能发现和 /pbot status。
94
+ 在独立 npm cache/prefix 中从公开 registry 全新安装发布版本,验证 npx 入口与全局 pbot 命令。再在独立 Pi 配置和临时工作区执行 `pi install --local npm:personal-bot`,核对安装版本、扩展加载、技能发现和 /pbot status。
95
+
96
+ 按[dsh 使用说明](dsh.md),使用当前 dsh 和 pnpm,在独立 profile 中通过原生插件命令安装公开 registry 的目标版本,记录实际宿主与插件版本,核对 Host 启用、包根 Web 客户端加载、`/pbot` 管理页及 Remote 查询。安装与无模型检查不代表成功模型工作流已验收,结果记录在[验证](validation.md)。
93
97
 
94
98
  上传结果不明时先查询 registry。若上传完成但后续查询失败,手动运行 Publish npm,选择原版本 tag 并保持 verify_only=true。该模式重新执行检查与 registry 查询,不上传;目标版本已不是 latest 时会失败。不要直接重跑原上传作业,也不要移动已发布 tag。
95
99
 
96
- 已发布版本不可覆盖。问题修复由维护者选择新版本、弃用说明或 dist-tag 调整。当前远端发布和全新安装仍待验收,范围见[验证](validation.md)。
100
+ 已发布版本不可覆盖。问题修复由维护者选择新版本、弃用说明或 dist-tag 调整。2026-11-06,提交 `1625a78af324de412ba12b0689de6c9ebde61698` 的 0.2.6 已通过 OIDC 发布及公开版本/latest 查询;公开 registry 只读核对确认该版本存在、latest 为 0.2.6,且包含 dsh Host/Web 入口。0.2.6 从公开 registry 全新安装的 npx、Pi 与 dsh 验收仍待完成,证据及范围见[CI 与发布记录](validation.md#ci-与发布2026-11-06)。
@@ -6,7 +6,7 @@
6
6
 
7
7
  保留两种工作方式:独立委派与持续对话;成员直接交换原文的团队协作。仍由 tmux 和独立 Pi 进程运行成员,不增加协调者模型或后台服务。
8
8
 
9
- 团队增量最初采用 **0.1.3**,未更改原有控制字段。随后按用户要求取消旧会话位置兼容,改由 Pi 管理对话文件,因此当前版本为 **0.2.0**。这只改变会话定位与恢复契约,不引入先前被删去的统一队列、事件日志或执行器重构。
9
+ 团队增量最初采用 **0.1.3**,未更改原有控制字段。随后在 **0.2.0** 中取消旧会话位置兼容,改由 Pi 管理对话文件。该次变更只改变会话定位与恢复契约,不引入先前被删去的统一队列、事件日志或执行器重构;当前发布版本以 package.json 为准。
10
10
 
11
11
  | 上一版的复杂点 | 本版处理 |
12
12
  | --- | --- |
@@ -1,6 +1,6 @@
1
1
  # 技术设计
2
2
 
3
- Personal Bot 提供按工作区加载的 Pi 扩展和固定版 dsh Host/Web 接入。模型负责分析、协调和工具使用;扩展负责资料准备、专家会话和共享 Python 环境。安装与命令见[项目 README](../README.md)。
3
+ Personal Bot 提供按工作区加载的 Pi 扩展和原生 dsh Host/Web 接入。模型负责分析、协调和工具使用;扩展负责资料准备、专家会话和共享 Python 环境。安装与命令见[项目 README](../README.md)。
4
4
 
5
5
  ## 模块与依赖
6
6
 
@@ -21,8 +21,8 @@ src/pbot.ts 装配 Pi 入口,src/dsh.ts 装配 dsh Host,src/ui/dsh/index.ts
21
21
  | 目录 | 责任 |
22
22
  | --- | --- |
23
23
  | src/tools/ | 输入、输出、schema、执行适配和工具列表 |
24
- | src/services/ | 业务规则、状态变更和操作顺序,按 agents、workspace 聚合 |
25
- | src/model/ | 数据类 |
24
+ | src/services/ | 业务规则、状态变更和操作顺序,按 agents、workspace、history、installation 聚合 |
25
+ | src/model/ | 业务数据类型与窄能力约定,不包含业务实现或宿主 SDK 类型 |
26
26
  | src/integrations/ | Pi/dsh 原生会话、Python 环境激活与进程执行 |
27
27
  | src/storage/ | 原子 JSON、子会话与团队文件 |
28
28
  | src/extension/ | 命令、事件和资源生命周期 |
@@ -30,7 +30,7 @@ src/pbot.ts 装配 Pi 入口,src/dsh.ts 装配 dsh Host,src/ui/dsh/index.ts
30
30
  | src/common/ | JSON、校验、文件、包路径和版本辅助逻辑 |
31
31
  | resources/ | 角色、技能、提示词、模板和参考资料 |
32
32
 
33
- 服务不依赖 Pi/dsh SDK、工具或 UI。共享进程执行可直接使用,其他宿主能力通过窄接口传入。接入层可引用服务类型;命令和工具通过服务执行状态变更。数据类在进入 JSON、存储和工具结果前转为普通数据。
33
+ 服务不依赖 Pi/dsh SDK、工具或 UI。共享进程执行可直接使用,其他宿主能力通过窄接口传入。接入层可引用服务类型;命令和工具通过服务执行状态变更。模型层用 interface/type 描述普通数据和窄能力契约;数据以普通对象进入 JSON、存储和工具结果。
34
34
 
35
35
  | 主体 | 管理内容 |
36
36
  | --- | --- |
@@ -47,7 +47,7 @@ Pi 原生配置决定扩展加载范围,启动目录作为工作区根目录
47
47
 
48
48
  Pi 的 `/pbot` 打开原生菜单,状态与长记录使用只读阅读页;dsh 使用独立工作台。见[界面设计](interaction-design.md)。
49
49
 
50
- `/pbot init` 可选地补建资料,已有文件保持不变。`/pbot status` 展示路径、版本和 Python 状态;模型通过每轮 pbot_environment 取得工作区、cwd、资源根目录和进程环境信息。
50
+ `/pbot init` 可选地补建资料,已有文件保持不变。Pi 的新建根 AGENTS.md 在原生 `/reload` 或下次启动后加载,命令完成时提示这一点,不另行拼接或自动重载活动会话。`/pbot status` 展示路径、版本和完整 Python 状态;模型环境只保留工作区、资源根目录及 Python 状态与就绪目录。实际 cwd 由宿主提供,准备错误日志保留在状态入口。
51
51
 
52
52
  主 reload 保留子进程并重新关联,但暂停团队,不继续安排旧批次;退出或切换会话时清理子进程、取消环境准备并恢复本实例持有的环境变量。关闭操作幂等。子会话的分支归属、通知和恢复规则见[专家协作](agent-collaboration.md)。
53
53
 
@@ -57,15 +57,21 @@ dsh 只为原生 registry 中的根 Agent 建立协调者工作区,绑定其
57
57
 
58
58
  | 资源 | 用途与加载方式 |
59
59
  | --- | --- |
60
- | resources/prompts/workspace.md | 主会话与专家的公共约定 |
61
- | resources/agents/、工作区 agents/ | coordinator、general-purpose 及同名工作区补充 |
62
- | resources/skills/ | 通过 resources_discover 提供;专家同时发现工作区技能 |
63
- | resources/references/ | 按需读取的操作参考 |
64
- | resources/templates/workspace-agents.md | 补建根资料入口的模板 |
60
+ | resources/prompts/workspace.md | 主会话与专家的公共操作约定、目录用途与异常重试说明 |
61
+ | resources/agents/、工作区 agents/ | coordinator、general-purpose 职责及同名工作区补充 |
62
+ | resources/prompts/team-member.md | 仅在专家处理团队任务时随团队目标与职责加载 |
63
+ | resources/prompts/history-summary.md | 两种宿主的独立历史摘要调用,不带主/专家上下文 |
64
+ | resources/skills/ | 原生技能目录只展示元数据,正文按需读取 |
65
+ | resources/references/ | 按任务读取;普通计算与指标/回测分开 |
66
+ | resources/templates/workspace-agents.md | 补建根资料入口的模板,不覆盖现有文件 |
65
67
 
66
- 主会话通过 before_agent_start 增加提示词 section,同时保留 Pi 原生 AGENTS.md 加载。资源在使用时读取,缺失时报错;提示词更新后按宿主原生机制重载。dsh 使用原生 systemPrompt 与 FileSystemSkillProvider,发现包内技能及工作区 `.agents/skills`,不增加另一套工具或技能注册平台。
68
+ Pi 主会话通过包清单发现技能,遵守原生 `--no-skills` 与包级资源过滤;专家按自己的 noSkills 选择发现包内及原工作区技能。before_agent_start 读取公共约定和角色补充,完整读取后更新 section;读取失败显式取消本轮,避免宿主只报告 hook 错误后继续。原生 AGENTS、技能元数据和提示模板由 Pi 自己加载、重载与去重;pbot 不另拼根 AGENTS,工具也不重复附加公共指南。
67
69
 
68
- 公共约定负责工作区与执行边界,角色负责职责与验收,技能提供专业方法与必要的本地操作约定,工具定义参数与结果语义。委派资料修改依据原任务授权及明确的文件责任,诊断环境问题不要求再次授权。工具按 action 校验必填与允许字段,返回具体参数错误;status 不读取报告正文。Pi 附件组装保留绝对来源及原生读取结果;dsh 使用原生文件存储与图片准入,Web 通用文件走原生 Session 上传凭证,命令图片使用原生编码图片输入。资料保存由模型按公共约定与维护技能处理,沉淀方法、口径与结论,可再次查询的数据按需获取。布局见[文件存储](file-storage.md)。
70
+ dsh 专家通过原生 composeFrom 应用父会话 preset,再限制其工具。包内技能在 Host 层注册一次,项目/用户技能与更新监听交给原生 provider;公共约定和角色在 system-prompt/assemble 当次刷新,遵守宿主 complete persona 覆盖。团队简报随首个已接纳团队上下文提供,不放在先于 pre-step 求值的动态 system section。
71
+
72
+ 同一会话中不变的 section 由宿主沿用;这不代表后续模型请求不再携带有效系统提示。团队公共消息按结构化来源与序号去重,压缩后需要的原文通过 read 续取。目录用途常驻,维护方法、接入、计算和调度细节按需读取。具体入口与审查取舍见[模型上下文](model-context.md)。
73
+
74
+ 公共约定说明工作方式与资料位置,角色说明分工与交付,技能提供专业方法与必要的本地操作约定,工具定义参数与结果语义。委派包含文件修改时说明范围和责任;不重复加入通用授权、证据或验收要求。工具按 action 校验必填与允许字段,返回具体参数错误;status 不读取报告正文。Pi 附件组装保留绝对来源及原生读取结果;dsh 使用原生文件存储与图片准入,Web 通用文件走原生 Session 上传凭证,命令图片使用原生编码图片输入。资料保存由模型按公共约定与维护技能处理,沉淀方法、口径与结论,可再次查询的数据按需获取。布局见[文件存储](file-storage.md)。
69
75
 
70
76
  ## 历史查询
71
77
 
@@ -81,7 +87,7 @@ PiAgents 使用 `--session-id <agentId>` 启动新的原生会话,让 Pi 按
81
87
 
82
88
  恢复使用已绑定的绝对路径,不查找最近会话,也不因配置变化转用其他文件。AgentService 在更换 generation 和入队前要求 Pi 接入层验证文件、session ID 与 cwd。引用绑定后文件不可读取时保守失败,不将未知历史当作空白待命。父侧报告读取使用原生解析器和内存 SessionManager,不改写或迁移原生文件。
83
89
 
84
- 会话文件移出控制目录改变恢复契约,因此版本为 0.2.0,旧兼容线不进入当前列表或后台调度;不导入、迁移或删除旧记录。既有控制字段、团队调度及完成叶节点关联保持不变。
90
+ 会话文件移出控制目录的恢复契约在 0.2.0 引入。旧兼容线不进入当前列表或后台调度;不导入、迁移或删除旧记录。既有控制字段、团队调度及完成叶节点关联保持不变。
85
91
 
86
92
  dsh 的 `native-session.json` 只保存原生 Session ID,不把它写入 Pi 路径字段。先持久化父会话,再创建并持久化空专家;冷读、恢复校验和固定 `dsh:<turn/end seq>` 报告均使用公开 Session API。恢复保留原生模型选择,清除旧 inbox,只接纳新代次的新请求。双方不接管对方的会话。
87
93
 
@@ -111,8 +117,8 @@ Web 拥有草稿、上传和查询;接纳后的命令归服务端。命令不
111
117
 
112
118
  ## 工具与分发
113
119
 
114
- Pi 将工具纳入 pbot namespace,codemode 按契约组合;dsh 注册原生工具,并在固定版可表达的 schema 之外继续校验完整领域契约。原生 CLI/MCP 与可选 Task Conductor 的接入和授权见[工具与执行](capability-design.md)。
120
+ Pi 将工具纳入 pbot namespace,codemode 按契约组合;dsh 注册原生工具,并在宿主可表达的 schema 之外继续校验完整领域契约。原生 CLI/MCP 与可选 Task Conductor 的接入和授权见[工具与执行](capability-design.md)。
115
121
 
116
- 扩展以 TypeScript 源码分发,由 Pi 加载;dist 仅供测试导入。安装 CLI 使用现有 TypeScript 工具链单独生成 lib,由 bin/pbot.mjs 启动,消费者无需编译或预装 Pi。dsh Host 与 Web 也编译到 lib,客户端由原生包根 Loader 发现;Pi 的入口仍由包清单明确指向 src。宿主 SDK 均为 optional peer,不捆绑另一份运行时;TypeBox 声明为范围为 `"*"` 的必需 peer:Pi 通过原生加载器提供;dsh 安装时由包管理器补齐。开发依赖锁定 TypeBox 版本,不随包捆绑。Pi/CLI 保持 Node.js 22.19+,dsh 与完整开发使用 Node.js 24.9+。安装检查子进程在发现真实宿主后使用该宿主的 SDK 读取配置和切换来源声明。发布版本以 package.json 为准,包内组件共用该版本。子会话兼容线在 1.0 前按次版本、1.0 起按主版本判断,跨线会话不能直接恢复。
122
+ 扩展以 TypeScript 源码分发,由 Pi 加载;dist 仅供测试导入。安装 CLI 使用现有 TypeScript 工具链单独生成 lib,由 bin/pbot.mjs 启动,消费者无需编译或预装 Pi。dsh Host 与 Web 也编译到 lib,客户端由原生包根 Loader 发现;Pi 的入口仍由包清单明确指向 src。宿主 SDK 均为 optional peer,不捆绑另一份运行时。dsh 用户安装跟随 `latest`,`engines.dsh` 声明最低版本 `>=0.2.2-rc.1`,dsh SDK peer 范围为 `"*"`;开发依赖和锁文件仍保留精确版本,验收只证明记录中的实际版本。TypeBox 声明为范围为 `"*"` 的必需 peer:Pi 通过原生加载器提供;dsh 安装时由包管理器补齐。开发依赖锁定 TypeBox 版本,不随包捆绑。Pi/CLI 保持 Node.js 22.19+,dsh 与完整开发使用 Node.js 24.9+。安装检查子进程在发现真实宿主后使用该宿主的 SDK 读取配置和切换来源声明。发布版本以 package.json 为准,包内组件共用该版本。子会话兼容线在 1.0 前按次版本、1.0 起按主版本判断,跨线会话不能直接恢复。
117
123
 
118
124
  开发验证见[验证](validation.md),分发流程见[npm 发布](release.md)。
@@ -9,7 +9,7 @@ git diff --check
9
9
  npm pack --dry-run
10
10
  ```
11
11
 
12
- 完整开发与验收使用 Linux、Node.js 24.9+;Pi 与独立 CLI 消费路径保留 Node.js 22.19+。CI 使用 Node 24.x 安装完整开发依赖、执行全量检查并构建候选包,再由独立 Node 22.19.0 作业安装同一 tarball,检查无宿主 SDK 的 CLI 与显式安装 Pi SDK 后的扩展、工具、技能及资料初始化。消费者检查不安装 dsh 开发依赖,也不调用模型。npm test 先构建 dist 和 CLI、dsh Host/Web 的 lib,再串行执行 Node 测试。测试使用真实本地文件、进程、计算、Pi 1.5.0 与固定版 dsh 0.2.2-rc.1 SDK。Pi 开发依赖与相关传递组件统一锁定 1.5.0;宿主提供的包声明为 optional peer,不增加运行时副本。发布包包含 bin/lib,扩展仍由 Pi 加载 src,dist 不进入发布包。
12
+ 完整开发与验收使用 Linux、Node.js 24.9+;Pi 与独立 CLI 消费路径保留 Node.js 22.19+。CI 使用 Node 24.x 安装完整开发依赖、执行全量检查并构建候选包,再由独立 Node 22.19.0 作业安装同一 tarball,检查无宿主 SDK 的 CLI 与显式安装 Pi SDK 后的扩展、工具、技能及资料初始化。消费者检查不安装 dsh 开发依赖,也不调用模型。npm test 先构建 dist 和 CLI、dsh Host/Web 的 lib,再串行执行 Node 测试。测试使用真实本地文件、进程、计算、Pi 1.5.0 与开发基线 dsh 0.2.2-rc.1 SDK。Pi 开发依赖与相关传递组件统一锁定 1.5.0;宿主提供的包声明为 optional peer,不增加运行时副本。发布包包含 bin/lib,扩展仍由 Pi 加载 src,dist 不进入发布包。
13
13
 
14
14
  | 范围 | 检查内容 |
15
15
  | --- | --- |
@@ -17,7 +17,8 @@ npm pack --dry-run
17
17
  | tests/installation/ | 真实子进程、Pi 原生配置、来源与资源过滤保留、过期计划、CLI 打包入口、无模型认证时的初始化分发与拦截 |
18
18
  | tests/smoke/ | 实际 tarball 加载、资料准备、独立 Python setup 脚本 |
19
19
  | tests/e2e/ | Pi SDK/RPC 命令与工具、确认、持久化、重启和 Bash 环境继承 |
20
- | tests/dsh/ | 真实 Agent/Session、代次与占用、附件、文件规则、团队、通知、双来源 history、原生 Remote、资源可见性与生命周期 |
20
+ | tests/integration/ | Pi 首轮上下文、原生差量、技能禁用与包过滤、init 后的原生 reload、必需资料读取失败时取消 |
21
+ | tests/dsh/ | 真实 Agent/Session、代次与占用、附件、文件规则、团队、通知、双来源 history、原生 Remote、preset 继承、资源可见性与生命周期 |
21
22
  | 历史并发 | 真实多进程与来源短锁,拒绝过期扫描和摘要覆盖,损坏来源隔离与独立取消 |
22
23
  | 专家协作 | 真实 tmux/Pi 进程、无任务待命、原 inbox、消息顺序、分支归属、通知领取和异常退出 |
23
24
  | 历史查询 | 真实 SDK 保存的问答、补充输入、工具过滤、分支隔离、四叉分组、原文与摘要搜索、正文分页、重载复用、空会话不误报、旧目录复制、跨目录读取、缺失原文时保留存档、旧路径清理、按会话 ID 重新关联与工具契约 |
@@ -43,13 +44,69 @@ Node 测试不下载第三方 Python 依赖;原生库集成验证见 [Python
43
44
 
44
45
  实际 tarball 在隔离消费者目录通过 `scripts/check-consumer.mjs` 验证:独立 CLI 无需 Pi/dsh SDK,显式安装 Pi 1.5.0 后扩展加载无错误或包警告,四个工具、技能和 `/pbot init` 均通过,不发起模型请求。
45
46
 
46
- 本轮未调用真实模型,也未重新执行 Linux、Node.js 22.19.0 或人工 TUI 验收。
47
+ 上述 Pi 1.5 本地批次未调用真实模型,也未重新执行 Linux、Node.js 22.19.0 或人工 TUI 验收。后续 CI 结果单独记录如下,不改写本地批次的范围。
48
+
49
+ ## CI 与发布(2026-11-06)
50
+
51
+ 以下记录限定为提交 `1625a78af324de412ba12b0689de6c9ebde61698`、`personal-bot@0.2.6`,Pi SDK 为 1.5.0,dsh 为 0.2.2-rc.1。
52
+
53
+ - [CI 运行 42242658306](https://github.com/realqiyan/personal-bot/actions/runs/42242658306):Ubuntu、Node.js 24.22.2、npm 11.19.1 下,`npm ci --ignore-scripts`、`npm run check`、`npm test`、`git diff --check` 均通过。125 项测试全部通过,无失败或跳过;依赖边界为 135 个模块、554 条依赖。package 作业正常执行 `npm pack`,包括 prepack 的检查、CLI 构建和 dsh Host/Web 构建。
54
+ - 同次 CI 的 pi-consumer 作业使用 Node.js 22.19.0、npm 10.9.3,安装同一候选 tarball。独立 CLI 与显式安装 Pi 1.5.0 后的扩展加载、四个工具、技能、`/pbot init` 均通过,不调用模型。
55
+ - [发布运行 42242680832](https://github.com/realqiyan/personal-bot/actions/runs/42242680832):同一提交的 OIDC 发布及 `Verify public version and latest` 成功。公开 npm registry 的只读核对确认 `personal-bot@0.2.6` 存在、`latest=0.2.6`,导出包含 `./lib/dsh.js` 与 `./lib/client.js`,dsh 元数据包含 Host/Web 所需的 bundle/client 声明。
56
+
57
+ 这些结果补齐了该提交的 Linux 全量、Node.js 22.19.0 Pi/CLI 消费者和远端发布检查。独立消费者作业仅覆盖 Pi/CLI;dsh 本地 SDK 测试不代表候选包的包根 Web 加载及 Remote 传输已自动验收。下文保留此前 tarball 的 Web/桌面人工验证;公开版本和元数据核对不代表 0.2.6 已从 registry 完成全新 npx、Pi 或 dsh 安装,也不证明完整桌面模型流程。人工 TUI、成功模型调用、摘要取消和长运行缺口仍保留。
58
+
59
+ ## 文档校正与安装来源回归(2026-11-07)
60
+
61
+ 本次记录针对基于 `1625a78` 的文档校正及安装来源检查修复,不属于已发布 0.2.6 的验收记录。macOS、Node.js 24.22.2、npm 11.19.1 下,`npm run check`、`npm test`、`git diff --check` 与正常执行 prepack 的 `npm pack --dry-run --json` 均通过;127 项测试全部通过,无失败或跳过。
62
+
63
+ 新增两项回归使用隔离的用户/项目配置、真实文件、子进程和 Pi SDK,检查缺失本地目录、未安装 Git 来源及无有效包名目录在计划前被拒绝,原配置保持不变;来源修复后能识别为保留项,独立单文件扩展与未安装 npm 声明仍可识别。测试没有执行联网安装或调用模型。本次改动未重新执行 Linux、Node.js 22.19.0、人工 TUI 或 dsh Web/桌面验收;前节 CI 结果仅适用于其记录的提交。
64
+
65
+ ## dsh 命令与版本策略(2026-11-07)
66
+
67
+ 当前源码的 dsh 安装示例改为 `latest`,`engines.dsh` 改为最低版本 `>=0.2.2-rc.1`,dsh SDK 保持 optional peer、范围为 `"*"`;开发依赖及解析版本仍为 0.2.2-rc.1。已同步中英文 README,并提供内容对应的[中文](dsh.md)和[英文](dsh.en.md)完整指南。已发布的 0.2.6 元数据没有被改写,本次范围放宽需后续发布才作用于 registry 安装。
68
+
69
+ npm 只读查询确认当时 `latest=0.2.2-rc.1`、Node.js 要求为 `>=24.9.0`。实际运行原生 CLI 版本与帮助,在临时 DSH_HOME、HOME 和工作目录创建独立 Web profile、导出配置及读取 Web 帮助;未启动个人 profile 或调用模型。插件命令参数对照原生转发实现与 pnpm 文档核对,本机 PATH 没有 pnpm,因此本轮没有实际安装、更新或移除 profile 插件。
70
+
71
+ 使用真实 dsh `evaluatePluginCompatibility` 检查最低版本、后续版本和预发布版本字符串,并核对 package.json 与 shrinkwrap 的范围一致;这只验证范围语义,不代表那些后续版本的运行验收。macOS、Node.js 24.22.2、npm 11.19.1 下再次执行 `npm run check` 与 `npm test`,127/127 通过,无失败、取消或跳过,依赖边界为 135 个模块、554 条依赖。`git diff --check` 及正常执行 prepack 的 `npm pack --dry-run --json` 通过;267 个包条目包含两份 README、中英文 dsh 指南、Host/Web 产物和包/锁文件。
72
+
73
+ 同日此前的全量复测还在已准备的用户级 Python 3.12.16 venv 中执行隔离模式的 `pip check` 与 `python/tests` 原生库测试,依赖检查和 5/5 测试通过;未安装或升级依赖。本轮文档和包声明修改后未重复计算库测试。Linux、Node.js 22.19.0、真实 Web/桌面插件安装及成功模型工作流的范围仍以上述既有记录为限。
74
+
75
+ ## 模型上下文审查(2026-11-07)
76
+
77
+ 本次针对基于 `1625a78` 的未发布工作区修改,覆盖 Pi/dsh 主会话、专家、团队任务及两种历史摘要入口,内容取舍与加载方式见[模型上下文](model-context.md)。macOS、Node.js 24.22.2、npm 11.19.1、Pi 1.5.0、dsh 0.2.2-rc.1 下,`npm run check`、`npm test`、`git diff --check` 均通过;135 项测试全部通过,无失败、取消或跳过,依赖边界为 137 个模块、558 条依赖。该总数包含当前工作区的安装与通知回归,不全是本次新增测试。
78
+
79
+ - Pi 使用真实资源加载器和 `_prepareRun` 观察认证前的主会话、专家首轮及后续差量,核对原生 AGENTS、用户职责补充、工具声明、技能目录、精简环境和条件性团队内容。主会话 no-skills、包级 `skills: []` 过滤均生效;未变化的 section 不追加,角色修改在下次准备时可见。新建 AGENTS 在原生 reload 后加载,已有内容保持原样。
80
+ - Pi 主会话与真实专家入口分别用不可读取的职责文件触发加载失败,实际 custom-message run 的原生 abort 信号已设置,未进入 provider 请求,tokens 为零。此处检查取消与调用时序,不以错误文案或唯一 stopReason 判断成功。
81
+ - dsh 使用真实 preset、Agent/Session 和原生文件/技能工具,核对专家 create/resume 的 preset 继承、首轮 AGENTS 和工具可见性、角色当次刷新、原文保真,以及项目/用户/包技能的优先级、文件更新监听和卸载生命周期。complete persona 保留宿主覆盖规则;noSkills 隐藏模型技能目录和工具,用户显式技能手势保留原生行为。
82
+ - dsh 团队首轮在实际 request/header 前收到共同目标、成员职责和公共原文;简报每次团队发言一次,公共序号按实际消费确认。回归覆盖无公共消息、准入拒绝后重新发言、后续批次去重及人工输入不追加团队内容。最终快照另保存主会话连续两次输入、普通专家、noSkills 专家和团队首轮;各请求在原生上下文组装后因缺少 provider adapter 失败,没有生成模型响应。
83
+ - 两个历史摘要入口通过源码核对:只提供专用提示与本次历史文本,不提供工具或普通会话上下文。现有历史测试继续验证分组、分页、持久化和并发;没有通过替代模型证明摘要质量。
84
+
85
+ 首轮全量检查曾有一项真实 tmux/Pi 待命测试超时。隔离观察确认 Pi 联网元数据查询使子进程停留在 starting;在该离线 fixture 补齐其他原生进程测试已有的 `PI_OFFLINE=1` 后,单项与最终全量均通过。没有延长超时、修改生产启动规则或调整提示来迁就断言。
86
+
87
+ 正常执行 prepack 的 `npm pack --dry-run --json` 通过,共 269 个包条目;包含 CLI、dsh Host/Web、team-member、compute-finance 和本文引用的上下文设计文档,已删除的 tool-guidelines 不再进入包。未发布。
88
+
89
+ 证据目录:`/tmp/pbot-pi-context-audit-8UHhUu/` 保存 Pi 原始观察及最终六种加载场景;`/tmp/pbot-dsh-context-review-pn3D9O/` 保存修改前的 dsh 发现;`/var/folders/tg/_ll136tn58387kdsr5vxzzwr0000gn/T/pbot-dsh-final-context-3tSpqi/` 保存最终 dsh 原生请求和事件;`/var/folders/tg/_ll136tn58387kdsr5vxzzwr0000gn/T/pbot-context-review-RJEmho/` 保存修改前资源、Pi 汇总、待命诊断脚本及最终打包结果。临时文件可能被系统清理,行为回归保留在仓库测试中。
90
+
91
+ 本次使用临时工作区及隔离的用户、认证和 Python 故障目录,不使用个人凭据,不修改用户资料、历史或备份。本地结果只证明上下文的来源、内容保真、出现时机及去重,不证明模型理解、专业判断、实际 token/费用或成功的外部服务工作流。没有重新验收 Linux、Node.js 22.19.0、完整 Web/桌面或成功模型调用;前述旧版本与已发布提交的验收范围保持不变。
92
+
93
+ ## 模型指令通用提醒清理(2026-11-07)
94
+
95
+ 在 `3d48fdd` 之后,清理公共提示、角色、团队消息、通知、工具说明及技能中的重复证据、权限和验收引导,保留目录用途、分页、配置作用域、计算方法与防重复执行说明;后续要求写入 AGENTS.md 及[模型指令编写原则](model-instruction-guidelines.md)。本轮不修改加载机制、状态规则或审批实现,不新增文案断言。
96
+
97
+ 同一 macOS、Node.js 24.22.2、npm 11.19.1、Pi 1.5.0、dsh 0.2.2-rc.1 环境下,`npm run check`、`npm test`、`git diff --check` 通过;135/135 测试通过,无失败、取消或跳过,依赖边界仍为 137 个模块、558 条依赖。测试总数包含工作区已有的安装与通知回归。未调用真实模型;此前上下文快照对应上一轮措辞,本次通过现有行为回归检查加载、分页与通知,不将旧快照当作新文案实测。
98
+
99
+ ## 0.2.8 本地候选检查(2026-11-07)
100
+
101
+ 本次候选在 0.2.7 的安装、恢复和双宿主基础上,同步 Task Conductor 0.1.6 的 Pi/dsh 安装、原生 MCP、会话通知和自定义 ACP 使用指引。package.json、shrinkwrap 与两份 README 的当前版本同步为 0.2.8,子会话兼容线仍为 0.2。
102
+
103
+ macOS、Node.js 24.22.2、npm 11.19.1、Pi 1.5.0、dsh 0.2.2-rc.1 下,`npm run check`、`npm test`、`git diff --check` 全部通过;135/135 测试通过,无失败、取消或跳过,依赖边界为 137 个模块、558 条依赖。正常执行 prepack 的 `npm pack --dry-run --json` 通过,270 个包条目包含 CLI、dsh Host/Web、Pi 源码、提示与技能、编写原则和中英文 dsh 指南,不包含 dist 或 node_modules。此记录为本地候选检查,未执行本版本的远端 CI、npm 发布或真实模型验收。
47
104
 
48
105
  ## 双宿主接入验收
49
106
 
50
- 已完成固定版 dsh 的 Host/Web、专家与团队、附件、通知、双来源 history 和人工管理。当前结果与证据位置持续记录在[实施记录](dsh-implementation-plan.md),使用入口见[dsh 使用](dsh.md)。
107
+ 已完成 dsh 0.2.2-rc.1 基线的 Host/Web、专家与团队、附件、通知、双来源 history 和人工管理。当前结果与证据位置持续记录在[实施记录](dsh-implementation-plan.md),使用入口见[dsh 使用](dsh.md)。
51
108
 
52
- - 最新源码在 macOS、Node.js 24.22.2、npm 11.19.1 下完成 `npm run check`、`npm test`、`git diff --check`,125/125 通过,无跳过;依赖边界为 135 个模块、554 条依赖。正常 `npm pack --dry-run` 与 prepack 打包通过。最新 Linux 回归未完成。
109
+ - Pi 1.5 本地回归在 macOS、Node.js 24.22.2、npm 11.19.1 下完成 `npm run check`、`npm test`、`git diff --check`,125/125 通过,无跳过;依赖边界为 135 个模块、554 条依赖。正常 `npm pack --dry-run` 与 prepack 打包通过。2026-11-06 对提交 `1625a78` 的 Linux 全量检查也已通过,见上节 CI 记录。
53
110
  - 正常 tarball 在独立消费者目录安装后没有安装 Pi/dsh SDK 副本;Node.js 22.19.0 下独立 CLI 返回版本,Pi 实际加载四个工具与技能、执行资料初始化和空专家查询通过。固定版 dsh 原生安装最终运行代码后,完整 Web 流程再次通过。
54
111
  - 正常执行 prepack 的 tarball 经原生插件命令安装后,真实 Chrome 验证四个 Remote、资料准备、文件与图片上传、长原生记录分页、私人草稿、公共消息分页、停止后冷读、显式恢复、history 查询与页面刷新。缺 provider 的批次真实失败并暂停,没有生成模拟响应。
55
112
  - 原生 Web 审批验证单次允许、真实取消以及等待期间符号链接变化;使用原生 Session 审计和真实 write 工具,不生成模型响应。
@@ -124,8 +181,8 @@ Python 测试已同时隔离 HOME 与 XDG_DATA_HOME,并用真实准备脚本
124
181
  | Task Conductor | 实际多节点产物、至少两轮周期任务、Pi 关闭或重载后的查询与防重复提交 |
125
182
  | CLI/MCP | 认证、发现、重连、动态工具、取消与业务结果 |
126
183
  | TUI/RPC | 人工 attach、焦点、批准、查看器、长时间运行和会话导航 |
127
- | npm 分发 | 包含安装器的新版本 OIDC 发布、公开 registry 的 npx 入口与用户环境反馈 |
128
- | 平台与存储 | 最新源码的 Linux 全量、macOS 独立安装器的完整交互、断电持久性及文件系统差异 |
184
+ | npm 分发 | 0.2.6 从公开 registry 全新安装的 npx 入口、Pi 与 dsh 原生安装及 Host/Web/Remote 检查、用户环境反馈;该版本 OIDC 发布与公开版本/latest 查询已于 2026-11-06 完成 |
185
+ | 平台与存储 | macOS 独立安装器的完整交互、断电持久性及文件系统差异;提交 `1625a78` 的 Linux 全量检查已于 2026-11-06 完成 |
129
186
 
130
187
  研究与资料方法使用真实任务资料验收,重点检查来源追溯、口径一致、缺失数据处理、历史前提复核、产物引用和结项依据。知识沉淀需检查是否提炼方法与口径,以及后续任务能否据此重新取数。探索任务应区分实验失败与假设被否定。
131
188
 
package/lib/dsh.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { join } from "node:path";
2
+ import * as SkillFilesystem from "@deepseek-ai/dsh-skill-filesystem";
3
+ import { resourceRoot } from "./common/paths.js";
1
4
  import { registerDshCommand } from "./extension/dsh/command.js";
2
5
  import { registerDshManagement } from "./extension/dsh/management.js";
3
6
  import { DshWorkspaces, dshDependencies } from "./extension/dsh/workspace.js";
@@ -7,6 +10,7 @@ export const inject = ["commands", "typert", ...dshDependencies];
7
10
  export async function apply(ctx) {
8
11
  const [major, minor] = process.versions.node.split(".").map(Number);
9
12
  requireThat(major > 24 || (major === 24 && minor >= 9), "dsh 接入需要 Node.js 24.9.0 或更新版本。");
13
+ await ctx.plugin(SkillFilesystem, { providerName: "pbot", includeDefaultRoots: false, bundledSkillDir: join(resourceRoot, "skills") });
10
14
  const workspaces = new DshWorkspaces(ctx);
11
15
  ctx.effect(() => () => workspaces.close());
12
16
  const management = registerDshManagement(ctx, workspaces);
@@ -144,7 +144,7 @@ export class DshAgentEvents {
144
144
  if (this.#error && this.#errorKey) {
145
145
  if (!known.has(this.#errorKey))
146
146
  value = { keys: [this.#errorKey], content: "# 协作扫描故障\n\n" + this.#error +
147
- "\n\n先核对控制记录和原生报告;结果未知不是重跑许可。" +
147
+ "\n\n先查看控制记录和原生报告,再决定是否重试,避免重复执行。" +
148
148
  (this.#recovery === "reload" ? "团队服务已停用;修复文件后还需重载服务端 personal-bot 插件。" :
149
149
  this.#recovery === "retry" ? "控制锁持续占用,后台会继续重试;不会自动删除锁或重新提交任务。" : "报告或控制记录读取失败,修复后后台会重试扫描。") +
150
150
  (this.#pausePending ? "\n\n团队暂停尚未确认,不能据此开始成员私人任务。" : "") };
@@ -25,6 +25,7 @@ export class DshAgentRuntime {
25
25
  #answer = "";
26
26
  #hasAnswer = false;
27
27
  #activeTeam;
28
+ #teamBriefed = false;
28
29
  #pendingPause;
29
30
  #pump;
30
31
  #timer;
@@ -127,13 +128,12 @@ export class DshAgentRuntime {
127
128
  requireThat(link, "团队关联不可读取。");
128
129
  const seen = this.#seen.get(link.team.teamId) ?? new Set();
129
130
  const context = createTeamContext(link, seen);
130
- if (!context)
131
+ if (this.#teamBriefed && !context)
131
132
  return decision;
132
- return { ...decision, messages: [...decision.messages, createUserMessage({ content: [{ type: "text", text: context.content }],
133
- source: { kind: "pbot-team-context", form: "relay", teamId: link.team.teamId, seqs: context.seqs } })] };
133
+ const text = [...(this.#teamBriefed ? [] : [teamBrief(link)]), ...(context ? [context.content] : [])].join("\n\n");
134
+ return { ...decision, messages: [...decision.messages, createUserMessage({ content: [{ type: "text", text }],
135
+ source: { kind: "pbot-team-context", form: "relay", teamId: link.team.teamId, seqs: context?.seqs ?? [] } })] };
134
136
  });
135
- this.ctx.systemPrompt.section({ name: "pbot:team", order: 600, interpolate: false,
136
- text: () => this.#activeTeam && !this.humanPending() && this.execution.current?.source === "parent" ? teamBrief(this.#activeTeam) : "" });
137
137
  this.execution.save({ state: "idle", activity: "空闲" });
138
138
  this.ctx.effect(() => () => this.stop());
139
139
  }
@@ -167,6 +167,7 @@ export class DshAgentRuntime {
167
167
  this.#turnEvents = [];
168
168
  this.#answer = "";
169
169
  this.#hasAnswer = false;
170
+ this.#teamBriefed = false;
170
171
  this.execution.begin();
171
172
  }
172
173
  if (this.execution.current)
@@ -199,6 +200,8 @@ export class DshAgentRuntime {
199
200
  this.execution.humanInput();
200
201
  if (event.data.source.kind === "pbot-team-context") {
201
202
  const { teamId, seqs } = event.data.source, seen = this.#seen.get(teamId) ?? new Set();
203
+ if (this.#activeTeam?.team.teamId === teamId)
204
+ this.#teamBriefed = true;
202
205
  for (const seq of seqs)
203
206
  seen.add(seq);
204
207
  this.#seen.set(teamId, seen);
@@ -1,7 +1,7 @@
1
1
  import type { Context } from "@deepseek-ai/cordis";
2
2
  import type { Agent } from "@deepseek-ai/dsh-agent";
3
3
  import type { AgentOptions } from "../../model/agent.js";
4
- export declare function dshResources(ctx: Context, agent: Agent, root: string, role: "coordinator" | "general-purpose", python: () => {
4
+ export declare function dshResources(ctx: Context, _agent: Agent, root: string, role: "coordinator" | "general-purpose", python: () => {
5
5
  state: string;
6
6
  directory?: string;
7
7
  error?: string;
@@ -1,32 +1,32 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { FileSystemSkillProvider } from "@deepseek-ai/dsh-skill-filesystem";
4
3
  import { agentText } from "../agent-resources.js";
5
4
  import { resourceRoot } from "../../common/paths.js";
6
5
  import { requireThat } from "../../common/validation.js";
7
- export async function dshResources(ctx, agent, root, role, python, check) {
8
- let text = await agentText(role, root);
9
- const workspace = await readFile(join(resourceRoot, "prompts/workspace.md"), "utf8");
6
+ export async function dshResources(ctx, _agent, root, role, python, check) {
7
+ const read = () => Promise.all([agentText(role, root), readFile(join(resourceRoot, "prompts/workspace.md"), "utf8")]);
8
+ const [text, workspace] = await read();
10
9
  check();
11
- ctx.systemPrompt.section({ name: "pbot:role", order: 1, text: () => text, interpolate: false });
10
+ ctx.systemPrompt.section({ name: "pbot:role", order: 1, text, interpolate: false });
12
11
  ctx.systemPrompt.section({ name: "pbot:workspace", order: 2, text: workspace, interpolate: false });
13
12
  ctx.systemPrompt.context({ name: "pbot:environment", order: 300, required: true, interpolate: false,
14
- text: () => JSON.stringify({ host: "dsh", workspaceRoot: root, cwd: ctx.workingDirectory.get(agent.session), resourceRoot, python: python() }) });
15
- ctx.skills.registerProvider(control => new FileSystemSkillProvider(ctx, control, {
16
- providerName: "pbot", includeDefaultRoots: false, customSkillDirs: [join(root, ".agents/skills")],
17
- bundledSkillDir: join(resourceRoot, "skills"), watch: false,
18
- }));
19
- ctx.on("agent/pre-step", async (_payload, next) => {
13
+ text: () => {
14
+ const { state, directory } = python();
15
+ return JSON.stringify({ workspaceRoot: root, resourceRoot, python: { state, ...(directory ? { directory } : {}) } });
16
+ } });
17
+ ctx.on("system-prompt/assemble", async (_assembly, _context, next) => {
20
18
  check();
21
- text = await agentText(role, root);
19
+ const [roleText, workspaceText] = await read();
22
20
  check();
23
- return next();
21
+ const assembly = await next();
22
+ return { ...assembly, sections: assembly.sections.map(section => section.name === "pbot:role" ? { ...section, text: roleText }
23
+ : section.name === "pbot:workspace" ? { ...section, text: workspaceText } : section) };
24
24
  });
25
25
  }
26
26
  /** Map the expert's native loadout; this is not isolation from Bash, CLI, or MCP. */
27
27
  export function dshExpertTools(ctx, agent, options) {
28
28
  const names = new Set(ctx.tools.definitions(agent).map(tool => tool.name));
29
- const forbidden = new Set(["pbot_agent", "pbot_team", "pbot_history", "subagent", "list_subagent_models", "list_agents", "send_message", "interrupt_agent"]);
29
+ const forbidden = new Set(["pbot_agent", "pbot_team", "pbot_history", "subagent", "subagent_fork", "list_subagent_models", "list_agents", "send_message", "interrupt_agent"]);
30
30
  if (options.noSkills)
31
31
  forbidden.add("skill");
32
32
  if (options.tools) {
@@ -29,6 +29,7 @@ export async function openDshAgent(ctx, d, parent, resume, setup, signal) {
29
29
  signal.throwIfAborted();
30
30
  const compose = async (agentCtx, agent) => {
31
31
  validateHeader(d, agent.session.header);
32
+ agentCtx.get("agentPresets")?.composeFrom(agentCtx, parent.ctx);
32
33
  if (resume)
33
34
  agent.inbox.clear();
34
35
  const commit = await setup(agentCtx, agent);
@@ -52,19 +52,16 @@ export async function inspectPackages(root, workspace) {
52
52
  for (const pkg of manager.listConfiguredPackages()) {
53
53
  const entries = (pkg.scope === "project" ? settings.getProjectSettings() : settings.getGlobalSettings()).packages ?? [];
54
54
  const entry = entries.find(item => sourceOf(item) === pkg.source);
55
- let name = npmName(pkg.source), version;
55
+ let name = npmName(pkg.source), version, singleFile = false;
56
56
  if (pkg.installedPath) {
57
- let file = pkg.installedPath;
58
- if ((await stat(file)).isDirectory())
59
- file = join(file, "package.json");
60
- else
61
- file = ""; // Single-file extensions have no npm identity.
62
- if (file) {
57
+ const info = await stat(pkg.installedPath);
58
+ singleFile = info.isFile(); // An existing standalone extension has no npm identity.
59
+ if (info.isDirectory()) {
63
60
  try {
64
- const manifest = JSON.parse(await readFile(file, "utf8"));
61
+ const manifest = JSON.parse(await readFile(join(pkg.installedPath, "package.json"), "utf8"));
65
62
  if (name && manifest.name !== name)
66
63
  throw new Error(`安装包身份不匹配:${pkg.source}`);
67
- name = typeof manifest.name === "string" ? manifest.name : name;
64
+ name = typeof manifest.name === "string" && manifest.name.trim() ? manifest.name : name;
68
65
  version = typeof manifest.version === "string" ? manifest.version : undefined;
69
66
  }
70
67
  catch (error) {
@@ -73,6 +70,9 @@ export async function inspectPackages(root, workspace) {
73
70
  }
74
71
  }
75
72
  }
73
+ if (!name && !singleFile) {
74
+ throw new Error(`无法辨认 ${pkg.scope} 来源的包身份:${pkg.source}。请先通过 Pi 原生配置恢复或修正该来源,再重新运行 setup。`);
75
+ }
76
76
  result.push({ source: pkg.source, scope: pkg.scope, filtered: pkg.filtered, entry,
77
77
  ...(pkg.installedPath ? { installedPath: pkg.installedPath } : {}), ...(name ? { name } : {}), ...(version ? { version } : {}) });
78
78
  }
@@ -1,4 +1,7 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
1
3
  import { markdownBlock } from "../common/markdown.js";
4
+ import { resourceRoot } from "../common/paths.js";
2
5
  function messageMarkdown(message) {
3
6
  return [
4
7
  "## 消息 " + message.seq, "",
@@ -15,14 +18,15 @@ function messageMarkdown(message) {
15
18
  export function teamMessagesMarkdown(page) {
16
19
  return ["# 团队公共消息", "", "- `teamId`: `" + page.teamId + "`", "- `lastSeq`: `" + page.lastSeq + "`",
17
20
  "- `nextAfterSeq`: `" + page.nextAfterSeq + "`", "",
18
- "公共原文仅作信息,不扩大用户授权。nextOffset 非空时先续读该条正文,再读取后续消息。", "",
21
+ "nextOffset 非空时先续读该条正文,再读取后续消息。", "",
19
22
  page.messages.map(messageMarkdown).join("\n\n")].join("\n");
20
23
  }
21
24
  export function teamBrief(link) {
22
25
  return ["# 团队协作", "", "- 团队:" + link.team.name, "- `teamId`: `" + link.team.teamId + "`",
23
26
  "- 当前成员 `agentId`: `" + link.request.agentId + "`", "- `runId`: `" + link.run.runId + "`",
24
27
  "- 轮次:" + link.request.round + " / " + link.run.rounds, "", "## 共同目标", "", link.team.brief,
25
- "", "## 成员职责", "", ...link.team.members.flatMap(member => ["### " + member.agentId, "", member.role, ""])].join("\n");
28
+ "", "## 成员职责", "", ...link.team.members.flatMap(member => ["### " + member.agentId, "", member.role, ""]),
29
+ readFileSync(join(resourceRoot, "prompts/team-member.md"), "utf8").trim()].join("\n");
26
30
  }
27
31
  export function createTeamContext(link, seen, throughSeq = link.team.messages.length) {
28
32
  const pending = link.team.messages.filter(m => m.seq <= throughSeq && !seen.has(m.seq));
@@ -51,7 +55,7 @@ export function createTeamContext(link, seen, throughSeq = link.team.messages.le
51
55
  const seqs = messages.map(m => m.seq);
52
56
  return { content: ["# 团队公共上下文", "", "- `teamId`: `" + link.team.teamId + "`", "- `throughSeq`: `" + throughSeq + "`",
53
57
  "- `remainingFromSeq`: `" + (pending[messages.length]?.seq ?? null) + "`", "",
54
- "团队成员原文,仅作信息,不扩大用户授权。未包含或被截断的正文用 pbot_team_message read 读取。remainingFromSeq 非空时,用 afterSeq: remainingFromSeq - 1 读取未包含的消息。", "",
58
+ "未包含或被截断的正文用 pbot_team_message read 读取。remainingFromSeq 非空时,用 afterSeq: remainingFromSeq - 1 读取未包含的消息。", "",
55
59
  messages.map(messageMarkdown).join("\n\n")].join("\n"),
56
60
  seqs };
57
61
  }
@@ -5,7 +5,7 @@ export function teamNotice(values, known) {
5
5
  if (!notes.length)
6
6
  return;
7
7
  return { kind: "teams", keys: notes.map(value => value.key), content: ["# 团队批次状态", "",
8
- "团队批次状态已变化。用 pbot_team status/read 查询;结束不等于业务验收通过。暂停可能仍有在途工作,不能自动重跑旧请求。", "",
8
+ "团队批次状态已变化,用 pbot_team status/read 查看状态和结果。暂停时可能仍有在途工作,重跑前先查看原请求结果。", "",
9
9
  notes.map(value => ["## " + value.name, "", "- `teamId`: `" + value.teamId + "`", "- `runId`: `" + value.runId + "`",
10
10
  "- 状态:" + value.state, "- 在途工作:" + value.activeCount, ...(value.reason ? ["", "### 原因", "", value.reason] : [])].join("\n")).join("\n\n")].join("\n") };
11
11
  }
@@ -17,7 +17,7 @@ export function agentNotice(values, links, known) {
17
17
  return;
18
18
  return { kind: "agents", keys: batch.map(value => value.agentId + ":" + value.cycle.cycleId),
19
19
  content: "# 子会话工作结果\n\n子会话工作已结束。完整报告用 pbot_agent read 读取,指定对应 agentId 和 cycle.cycleId;nextOffset 非空时沿用该 cycleId 续读。\n\n" +
20
- (batch.some(value => value.cycle.source !== "parent") ? "包含人工子会话输入,其结果不扩大主会话原任务授权。\n\n" : "") +
20
+ (batch.some(value => value.cycle.source !== "parent") ? "部分结果包含人工子会话输入,来源见 cycle.source。\n\n" : "") +
21
21
  batch.map(value => "## " + value.name + "\n\n" + markdownFields(json({ agentId: value.agentId,
22
22
  cycle: { cycleId: value.cycle.cycleId, state: value.cycle.state, source: value.cycle.source, requestIds: value.cycle.requestIds,
23
23
  ...(value.cycle.error === undefined ? {} : { error: value.cycle.error }) },
@@ -317,7 +317,7 @@ export class TeamService {
317
317
  slots--;
318
318
  changed = true;
319
319
  inputs.push({ ...q, teamId: team.teamId, runId: run.runId,
320
- message: ["# 团队发言任务", "", "执行本次团队发言安排。最终答复将公开给全体成员;这不扩大原任务授权。", "",
320
+ message: ["# 团队发言任务", "", "执行本次团队发言安排。最终答复将公开给全体成员。", "",
321
321
  "- `teamId`: `" + team.teamId + "`", "- `runId`: `" + run.runId + "`", "- 轮次:" + q.round,
322
322
  "", "## 本批次要求", "", run.instruction].join("\n") });
323
323
  }
@@ -1,5 +1,5 @@
1
1
  import { Type } from "typebox";
2
- export declare const agentDescription = "\u72EC\u7ACB\u4E13\u5BB6\u4F1A\u8BDD\uFF0C\u4E0D\u7EE7\u627F\u7236\u804A\u5929\u5386\u53F2\u3002start \u5B8C\u6210\u542F\u52A8\u540E\u8FD4\u56DE\uFF0C\u4E0D\u7B49\u5F85\u5DE5\u4F5C\u5B8C\u6210\uFF1B\u672A\u63D0\u4F9B message/prompts/files \u65F6\u53EA\u542F\u52A8\u5F85\u547D\u4F1A\u8BDD\uFF0C\u4E0D\u8C03\u7528\u6A21\u578B\u3002\u5B8C\u6210\u81EA\u52A8\u901A\u77E5\uFF0C\u65E0\u9700\u8F6E\u8BE2\u3002\u56E2\u961F\u5360\u7528\u671F\u95F4\u4E0D\u80FD\u79C1\u4EBA send\u3002send \u7EE7\u7EED\u5BF9\u8BDD\uFF0Crename \u6539\u540D\uFF0Cstatus/list \u67E5\u770B\u72B6\u6001\uFF0Cstatus \u8FD4\u56DE\u6700\u8FD1\u5468\u671F\u4E14\u4E0D\u8BFB\u53D6\u62A5\u544A\u6B63\u6587\u3002read \u975E\u963B\u585E\u8BFB\u53D6\u62A5\u544A\uFF1B\u8BFB\u53D6\u5DF2\u7ED3\u675F\u5468\u671F\u4F1A\u9886\u53D6\u8BE5\u5468\u671F\u7684\u5B8C\u6210\u901A\u77E5\uFF08\u5305\u62EC\u90E8\u5206\u8BFB\u53D6\uFF09\uFF0C\u540E\u7EED\u4E0D\u518D\u91CD\u590D\u901A\u77E5\u3002nextOffset \u975E\u7A7A\u65F6\u4EE5\u8FD4\u56DE\u7684 cycle.cycleId \u56FA\u5B9A\u5468\u671F\u7EED\u8BFB\u3002state \u662F\u6267\u884C\u72B6\u6001\uFF0Ccycle.state \u662F\u5DE5\u4F5C\u7ED3\u679C\uFF0Cqueued \u4EC5\u8868\u793A\u5165\u961F\u3002stop \u505C\u6B62\u5E76\u4FDD\u7559\u5386\u53F2\uFF0Cresume \u643A\u65B0 message \u6062\u590D\uFF0C\u4E0D\u91CD\u653E\u65E7\u5DE5\u4F5C\u3002\u72EC\u7ACB\u590D\u6838\u987B start \u65B0\u4E0A\u4E0B\u6587\u3002\u5B50\u4F1A\u8BDD\u4F7F\u7528\u539F\u751F CLI/MCP\uFF0C\u6309\u59D4\u6D3E\u8303\u56F4\u5DE5\u4F5C\uFF0C\u4E0D\u9012\u5F52\u59D4\u6D3E\u3002\u6BCF\u4E2A\u7236\u4F1A\u8BDD\u6700\u591A 50 \u4E2A\u5B58\u6D3B\u5B50\u4F1A\u8BDD\uFF0C\u7A7A\u95F2\u4E5F\u8BA1\u5165\u3002";
2
+ export declare const agentDescription = "\u59D4\u6D3E\u4E13\u5BB6\u5E76\u7EE7\u7EED\u5BF9\u8BDD\u3002start \u542F\u52A8\u540E\u5373\u8FD4\u56DE\uFF0C\u5B8C\u6210\u81EA\u52A8\u901A\u77E5\uFF0C\u65E0\u9700\u8F6E\u8BE2\uFF1B\u7701\u7565\u521D\u59CB\u8F93\u5165\u65F6\u5F85\u547D\u3002send \u7EE7\u7EED\u5BF9\u8BDD\uFF0C\u56E2\u961F\u5360\u7528\u671F\u95F4\u4E0D\u53EF\u79C1\u4EBA send\u3002status \u67E5\u770B\u72B6\u6001\uFF0Cread \u8BFB\u53D6\u62A5\u544A\uFF1B\u8BFB\u53D6\u5DF2\u7ED3\u675F\u5468\u671F\u5373\u9886\u53D6\u5176\u901A\u77E5\uFF0C\u5305\u62EC\u90E8\u5206\u8BFB\u53D6\u3002\u7EED\u8BFB\u56FA\u5B9A cycle.cycleId \u5E76\u4F7F\u7528 nextOffset\u3002state \u8868\u793A\u6267\u884C\u72B6\u6001\uFF0Ccycle.state \u8868\u793A\u5DE5\u4F5C\u7ED3\u679C\uFF0Cqueued \u53EA\u8868\u793A\u5165\u961F\u3002stop \u4FDD\u7559\u5386\u53F2\uFF0Cresume \u643A\u65B0 message \u7EE7\u7EED\u3002\u6BCF\u4E2A\u7236\u4F1A\u8BDD\u6700\u591A 50 \u4E2A\u5B58\u6D3B\u4E13\u5BB6\uFF0C\u7A7A\u95F2\u4E5F\u8BA1\u5165\u3002";
3
3
  export declare const agentStartOptions: {
4
4
  name: Type.TOptional<Type.TString>;
5
5
  message: Type.TOptional<Type.TString>;