psyclaw 0.28.0 → 0.28.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/agents/recommended/catalog.json +99 -0
- package/dist/apps/panel/index.html +5 -5
- package/dist/src/adapters/pi/extension.js +164 -18
- package/dist/src/adapters/pi/extension.js.map +1 -1
- package/dist/src/adapters/pi/rpc.d.ts +2 -0
- package/dist/src/adapters/pi/rpc.js +9 -2
- package/dist/src/adapters/pi/rpc.js.map +1 -1
- package/dist/src/agents/recommended-personas.d.ts +42 -0
- package/dist/src/agents/recommended-personas.js +135 -0
- package/dist/src/agents/recommended-personas.js.map +1 -0
- package/dist/src/ars/mode-editor.d.ts +20 -0
- package/dist/src/ars/mode-editor.js +57 -0
- package/dist/src/ars/mode-editor.js.map +1 -0
- package/dist/src/ars/profile.d.ts +4 -1
- package/dist/src/ars/profile.js +23 -6
- package/dist/src/ars/profile.js.map +1 -1
- package/dist/src/cli.js +6 -3
- package/dist/src/cli.js.map +1 -1
- package/dist/src/creation/contracts.d.ts +3 -0
- package/dist/src/creation/service.js +17 -5
- package/dist/src/creation/service.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/orchestration/bundled-personas.d.ts +16 -0
- package/dist/src/orchestration/bundled-personas.js +101 -0
- package/dist/src/orchestration/bundled-personas.js.map +1 -0
- package/dist/src/orchestration/effects.d.ts +8 -0
- package/dist/src/orchestration/effects.js +39 -0
- package/dist/src/orchestration/effects.js.map +1 -0
- package/dist/src/orchestration/personas.d.ts +2 -1
- package/dist/src/orchestration/personas.js +20 -7
- package/dist/src/orchestration/personas.js.map +1 -1
- package/dist/src/orchestration/pi-executor.d.ts +9 -5
- package/dist/src/orchestration/pi-executor.js +55 -22
- package/dist/src/orchestration/pi-executor.js.map +1 -1
- package/dist/src/orchestration/research-agents.d.ts +3 -7
- package/dist/src/orchestration/research-agents.js +5 -69
- package/dist/src/orchestration/research-agents.js.map +1 -1
- package/dist/src/panel/server.js +6 -0
- package/dist/src/panel/server.js.map +1 -1
- package/dist/src/style/cli-ui.d.ts +14 -0
- package/dist/src/style/cli-ui.js +45 -0
- package/dist/src/style/cli-ui.js.map +1 -1
- package/dist/src/tui/skill-manager.js +1 -1
- package/dist/src/tui/skill-manager.js.map +1 -1
- package/dist/src/updates/update.js +9 -3
- package/dist/src/updates/update.js.map +1 -1
- package/package.json +11 -3
- package/vendor/academic-paper-skills/LICENSE +21 -0
- package/vendor/academic-paper-skills/NOTICE.md +7 -0
- package/vendor/academic-paper-skills/PSYCLAW_SOURCE.json +14 -0
- package/vendor/academic-paper-skills/academic-paper-composer/SKILL.md +840 -0
- package/vendor/academic-paper-skills/academic-paper-composer/references/section_guides.md +675 -0
- package/vendor/academic-paper-skills/academic-paper-composer/references/writing_standards.md +629 -0
- package/vendor/academic-paper-skills/academic-paper-composer/scripts/chapter_quality_check.py +470 -0
- package/vendor/academic-paper-skills/academic-paper-composer/scripts/final_evaluation.py +550 -0
- package/vendor/academic-paper-skills/academic-paper-strategist/SKILL.md +670 -0
- package/vendor/academic-paper-skills/academic-paper-strategist/references/quality_standards.md +336 -0
- package/vendor/academic-paper-skills/academic-paper-strategist/references/search_strategy.md +459 -0
- package/vendor/academic-paper-skills/academic-paper-strategist/scripts/evaluate_samples.py +300 -0
- package/vendor/academic-paper-skills/academic-paper-strategist/scripts/gap_analysis.py +399 -0
- package/vendor/ars/pi/wrapper.js +9 -0
- package/vendor/nature-skills/LICENSE +201 -0
- package/vendor/nature-skills/NOTICE.md +7 -0
- package/vendor/nature-skills/PSYCLAW_SOURCE.json +19 -0
- package/vendor/nature-skills/skills/nature-figure/README.md +107 -0
- package/vendor/nature-skills/skills/nature-figure/README_EN.md +107 -0
- package/vendor/nature-skills/skills/nature-figure/SKILL.md +154 -0
- package/vendor/nature-skills/skills/nature-figure/agents/openai.yaml +4 -0
- package/vendor/nature-skills/skills/nature-figure/evals/evals.json +325 -0
- package/vendor/nature-skills/skills/nature-figure/manifest.yaml +103 -0
- package/vendor/nature-skills/skills/nature-figure/references/ai-graphical-abstract-workflow.md +129 -0
- package/vendor/nature-skills/skills/nature-figure/references/api.md +576 -0
- package/vendor/nature-skills/skills/nature-figure/references/asset-adaptation.md +72 -0
- package/vendor/nature-skills/skills/nature-figure/references/backend-selection.md +118 -0
- package/vendor/nature-skills/skills/nature-figure/references/chart-types.md +348 -0
- package/vendor/nature-skills/skills/nature-figure/references/common-patterns.md +371 -0
- package/vendor/nature-skills/skills/nature-figure/references/demos.md +58 -0
- package/vendor/nature-skills/skills/nature-figure/references/design-theory.md +467 -0
- package/vendor/nature-skills/skills/nature-figure/references/figure-contract.md +122 -0
- package/vendor/nature-skills/skills/nature-figure/references/figure-legend-conventions.md +90 -0
- package/vendor/nature-skills/skills/nature-figure/references/multipanel-evidence-architecture.md +268 -0
- package/vendor/nature-skills/skills/nature-figure/references/nature-2026-observations.md +124 -0
- package/vendor/nature-skills/skills/nature-figure/references/nature-article-requirements.md +149 -0
- package/vendor/nature-skills/skills/nature-figure/references/openrouter-image-generation.md +141 -0
- package/vendor/nature-skills/skills/nature-figure/references/qa-contract.md +344 -0
- package/vendor/nature-skills/skills/nature-figure/references/r-template-index.md +66 -0
- package/vendor/nature-skills/skills/nature-figure/references/r-workflow.md +234 -0
- package/vendor/nature-skills/skills/nature-figure/references/template-catalog.md +33 -0
- package/vendor/nature-skills/skills/nature-figure/references/tutorials.md +260 -0
- package/vendor/nature-skills/skills/nature-figure/requirements.txt +1 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/audit_figure_collisions.py +742 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/audit_panel_alignment.py +933 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/audit_pdf_text.py +152 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/figure_safety.py +50 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/generate_openrouter_schematic.py +260 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/nature_figure_backend.py +93 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/panel_alignment.R +188 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/plot_templates.py +604 -0
- package/vendor/nature-skills/skills/nature-figure/scripts/validate_figure.py +835 -0
- package/vendor/nature-skills/skills/nature-figure/static/core/contract.md +55 -0
- package/vendor/nature-skills/skills/nature-figure/static/core/stance.md +41 -0
- package/vendor/nature-skills/skills/nature-figure/static/fragments/backend/python.md +56 -0
- package/vendor/nature-skills/skills/nature-figure/static/fragments/backend/r.md +63 -0
- package/vendor/nature-skills/skills/nature-figure/tests/test_figure_safety.py +209 -0
- package/vendor/nature-skills/skills/nature-polishing/README.md +58 -0
- package/vendor/nature-skills/skills/nature-polishing/README_EN.md +58 -0
- package/vendor/nature-skills/skills/nature-polishing/SKILL.md +111 -0
- package/vendor/nature-skills/skills/nature-polishing/agents/openai.yaml +4 -0
- package/vendor/nature-skills/skills/nature-polishing/manifest.yaml +101 -0
- package/vendor/nature-skills/skills/nature-polishing/references/latex-layout.md +211 -0
- package/vendor/nature-skills/skills/nature-polishing/references/nat-comms-2025-diction.md +73 -0
- package/vendor/nature-skills/skills/nature-polishing/references/phrasebank-playbook.md +175 -0
- package/vendor/nature-skills/skills/nature-polishing/references/published-article-patterns.md +126 -0
- package/vendor/nature-skills/skills/nature-polishing/references/section-moves.md +252 -0
- package/vendor/nature-skills/skills/nature-polishing/references/style-guardrails.md +94 -0
- package/vendor/nature-skills/skills/nature-polishing/references/writing-strategy.md +160 -0
- package/vendor/nature-skills/skills/nature-polishing/static/core/failure-modes.md +29 -0
- package/vendor/nature-skills/skills/nature-polishing/static/core/output-format.md +21 -0
- package/vendor/nature-skills/skills/nature-polishing/static/core/stance.md +26 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/generic.md +17 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nat-comms.md +38 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nat-mach-intell.md +102 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nature.md +19 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/language/en.md +19 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/language/zh-to-en.md +19 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/algorithmic.md +18 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/hypothesis.md +17 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/methods.md +35 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/research.md +29 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/review.md +17 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/abstract.md +26 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/conclusion.md +15 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/discussion.md +48 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/intro.md +33 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/methods.md +26 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/results.md +61 -0
- package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/title.md +17 -0
- package/vendor/nature-skills/skills/nature-ref-verifier/README.md +44 -0
- package/vendor/nature-skills/skills/nature-ref-verifier/README_EN.md +44 -0
- package/vendor/nature-skills/skills/nature-ref-verifier/SKILL.md +196 -0
- package/vendor/nature-skills/skills/nature-ref-verifier/agents/openai.yaml +4 -0
- package/vendor/nature-skills/skills/nature-ref-verifier/manifest.yaml +19 -0
- package/vendor/nature-skills/skills/nature-ref-verifier/references/common-patterns.md +96 -0
- package/vendor/nature-skills/skills/nature-shared/README.md +43 -0
- package/vendor/nature-skills/skills/nature-shared/README_EN.md +43 -0
- package/vendor/nature-skills/skills/nature-shared/SKILL.md +33 -0
- package/vendor/nature-skills/skills/nature-shared/agents/openai.yaml +6 -0
- package/vendor/nature-skills/skills/nature-shared/core/consistency-sweep.md +122 -0
- package/vendor/nature-skills/skills/nature-shared/core/discussion-argument-language.md +192 -0
- package/vendor/nature-skills/skills/nature-shared/core/ethics.md +88 -0
- package/vendor/nature-skills/skills/nature-shared/core/main-text-discipline.md +179 -0
- package/vendor/nature-skills/skills/nature-shared/core/nature-abstract.md +171 -0
- package/vendor/nature-skills/skills/nature-shared/core/nature-introduction.md +164 -0
- package/vendor/nature-skills/skills/nature-shared/core/nature-results-discussion.md +215 -0
- package/vendor/nature-skills/skills/nature-shared/core/paper-type-taxonomy.md +41 -0
- package/vendor/nature-skills/skills/nature-shared/core/reader-workflow.md +21 -0
- package/vendor/nature-skills/skills/nature-shared/core/research-compliance.md +192 -0
- package/vendor/nature-skills/skills/nature-shared/core/terminology-ledger.md +58 -0
- package/vendor/nature-skills/skills/nature-shared/journal-formats/nat-comms.md +139 -0
- package/vendor/nature-skills/skills/nature-shared/journal-formats/nature-machine-intelligence.md +431 -0
- package/vendor/nature-skills/skills/nature-shared/journal-formats/nature.md +313 -0
- package/vendor/nature-skills/skills/nature-shared/manifest.yaml +52 -0
- package/vendor/nature-skills/skills/nature-shared/scripts/check_consistency.py +273 -0
- package/vendor/nature-skills/skills/nature-shared/tests/test_check_consistency.py +63 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ PsyClaw 是面向社会科学研究的智能体工作台。它把研究项目、
|
|
|
4
4
|
|
|
5
5
|
PsyClaw 自有代码使用 MIT 许可证;随 npm 包内置的 Academic Research Skills 位于 `vendor/ars`,保持上游署名并单独遵循 CC BY-NC 4.0,仅限非商业用途。
|
|
6
6
|
|
|
7
|
-
当前版本:`0.28.
|
|
7
|
+
当前版本:`0.28.2`。正式命令、用户配置目录和后续发布统一使用 `psyclaw`。
|
|
8
8
|
|
|
9
9
|
## 发布流程
|
|
10
10
|
|
|
@@ -21,19 +21,19 @@ RELEASE_MESSAGE="release: describe the change" pnpm release:push
|
|
|
21
21
|
需要 Node.js `>=22.19.0`。官方 npm 源:
|
|
22
22
|
|
|
23
23
|
```powershell
|
|
24
|
-
npm install -g psyclaw@0.28.
|
|
24
|
+
npm install -g psyclaw@0.28.2
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
如果本机 npm 配置把 registry 误写成带有 `~/` 的地址,请显式指定官方源:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
npm install -g psyclaw@0.28.
|
|
30
|
+
npm install -g psyclaw@0.28.2 --registry=https://registry.npmjs.org/
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
中国大陆网络较慢或无法访问官方源时:
|
|
34
34
|
|
|
35
35
|
```powershell
|
|
36
|
-
npm install -g psyclaw@0.28.
|
|
36
|
+
npm install -g psyclaw@0.28.2 --registry=https://registry.npmmirror.com
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
PsyClaw 的 npm 发布包直接携带 Windows x64/arm64 版 `ripgrep` 和 `fd`,Windows 启动时直接使用包内可执行文件,不再联网下载。其他平台缺少这两个工具时仍由锁定的 Pi 原生工具管理器处理:代理环境走 GitHub 官方 API 与 Release,国内 npm registry 环境统一走国内镜像。
|
|
@@ -92,7 +92,7 @@ psyclaw brief
|
|
|
92
92
|
| 创建项目能力 | `/create-skill`、`/create-hook`、`/create-rule`、`/create-subagent`(均先预览并确认) |
|
|
93
93
|
| 运行自定义只读角色 | `/agents --agent <id> <task>` 或 `/agents --agents <id,...> <task>`(最多四个隔离 worker) |
|
|
94
94
|
| 调用已加载 Skill | `/skill:<name>` |
|
|
95
|
-
| 使用 PsyClaw ARS | `/ars doctor
|
|
95
|
+
| 使用 PsyClaw ARS | 输入 `ars` 后按 Tab(或 `ars: <task>`);也可用 `/ars doctor` / `/ars full <task>` |
|
|
96
96
|
| 管理 Plugin | `/plugin`;终端使用 `psyclaw plugin install|remove|list` |
|
|
97
97
|
| 调用已配置 MCP | 模型通过 `psyclaw_mcp` 自动发现并调用 `.psyclaw/mcp/*.json` 中启用的服务器 |
|
|
98
98
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "psyclaw/recommended-agents/v1",
|
|
3
|
+
"documentVersion": "0.28.2",
|
|
4
|
+
"syncedAt": "2026-09-06",
|
|
5
|
+
"sourceDocument": "bundled literature/review subagents",
|
|
6
|
+
"sourceRef": "bundled",
|
|
7
|
+
"repositoryHint": "对齐 Claude Code:Subagent = md 提示合订本。外仓可后续以 GitHub 源加入 installPrep;当前内置 8 个无需安装。",
|
|
8
|
+
"items": [
|
|
9
|
+
{
|
|
10
|
+
"id": "landscape-mapper",
|
|
11
|
+
"name": "研究版图分析者",
|
|
12
|
+
"kind": "agent",
|
|
13
|
+
"pack": "literature",
|
|
14
|
+
"role": "researcher",
|
|
15
|
+
"stage": "文献多智能体",
|
|
16
|
+
"description": "梳理研究主题、年代分布、代表性论文和研究方向。",
|
|
17
|
+
"sourceRef": "bundled",
|
|
18
|
+
"bundled": true
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "methods-scout",
|
|
22
|
+
"name": "方法学分析者",
|
|
23
|
+
"kind": "agent",
|
|
24
|
+
"pack": "literature",
|
|
25
|
+
"role": "analyst",
|
|
26
|
+
"stage": "文献多智能体",
|
|
27
|
+
"description": "识别研究设计、测量与分析线索,区分元数据可判断与不可判断之处。",
|
|
28
|
+
"sourceRef": "bundled",
|
|
29
|
+
"bundled": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "evidence-critic",
|
|
33
|
+
"name": "证据批判者",
|
|
34
|
+
"kind": "agent",
|
|
35
|
+
"pack": "literature",
|
|
36
|
+
"role": "critic",
|
|
37
|
+
"stage": "文献多智能体",
|
|
38
|
+
"description": "检查证据强弱、偏倚、冲突与因果边界。",
|
|
39
|
+
"sourceRef": "bundled",
|
|
40
|
+
"bundled": true
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "gap-finder",
|
|
44
|
+
"name": "研究缺口分析者",
|
|
45
|
+
"kind": "agent",
|
|
46
|
+
"pack": "literature",
|
|
47
|
+
"role": "verifier",
|
|
48
|
+
"stage": "文献多智能体",
|
|
49
|
+
"description": "寻找尚未充分覆盖的问题、对象、情境和方法。",
|
|
50
|
+
"sourceRef": "bundled",
|
|
51
|
+
"bundled": true
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "theory-reviewer",
|
|
55
|
+
"name": "理论与贡献审稿人",
|
|
56
|
+
"kind": "agent",
|
|
57
|
+
"pack": "review",
|
|
58
|
+
"role": "critic",
|
|
59
|
+
"stage": "同行评审多智能体",
|
|
60
|
+
"description": "检查问题重要性、理论定位、创新性与主张—证据一致性。",
|
|
61
|
+
"sourceRef": "bundled",
|
|
62
|
+
"bundled": true
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "methods-reviewer",
|
|
66
|
+
"name": "研究设计审稿人",
|
|
67
|
+
"kind": "agent",
|
|
68
|
+
"pack": "review",
|
|
69
|
+
"role": "analyst",
|
|
70
|
+
"stage": "同行评审多智能体",
|
|
71
|
+
"description": "检查抽样、设计、测量、效度与因果推断边界。",
|
|
72
|
+
"sourceRef": "bundled",
|
|
73
|
+
"bundled": true
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "statistics-reviewer",
|
|
77
|
+
"name": "统计与可复现性审稿人",
|
|
78
|
+
"kind": "agent",
|
|
79
|
+
"pack": "review",
|
|
80
|
+
"role": "verifier",
|
|
81
|
+
"stage": "同行评审多智能体",
|
|
82
|
+
"description": "检查分析策略、效应量、置信区间与可复现信息(不重算统计)。",
|
|
83
|
+
"sourceRef": "bundled",
|
|
84
|
+
"bundled": true
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "ethics-editorial-reviewer",
|
|
88
|
+
"name": "伦理与编辑审稿人",
|
|
89
|
+
"kind": "agent",
|
|
90
|
+
"pack": "review",
|
|
91
|
+
"role": "writer",
|
|
92
|
+
"stage": "同行评审多智能体",
|
|
93
|
+
"description": "检查伦理、透明报告、引用表达与可读性。",
|
|
94
|
+
"sourceRef": "bundled",
|
|
95
|
+
"bundled": true
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"installPrep": []
|
|
99
|
+
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div class="layout">
|
|
18
18
|
<nav class="nav" aria-label="Panel 导航">
|
|
19
19
|
<button class="active" data-view="project">项目文件</button>
|
|
20
|
-
<button data-view="ecosystem">Skill / Plugin / MCP</button>
|
|
20
|
+
<button data-view="ecosystem">Skill / Plugin / MCP / Agent</button>
|
|
21
21
|
<button data-view="provider">Provider 与成本</button>
|
|
22
22
|
</nav>
|
|
23
23
|
<main class="main">
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
</section>
|
|
34
34
|
|
|
35
35
|
<section id="view-ecosystem" class="view">
|
|
36
|
-
<div class="page-head"><div><h1>Skill / Plugin / MCP 生态</h1><p>在同一页面管理研究 Skill、Pi Plugin 与
|
|
37
|
-
<div class="controls" style="margin-bottom:12px"><input id="eco-search" placeholder="搜索名称或描述"><div class="segmented" aria-label="能力类型"><button class="active" data-eco-kind="all">全部</button><button data-eco-kind="skill">Skill</button><button data-eco-kind="plugin">Plugin</button><button data-eco-kind="mcp">MCP</button></div><select id="eco-kind" aria-label="更多类型"><option value="all">全部来源</option><option value="local">用户 Skill</option><option value="external">外部工具</option></select><select id="eco-status"><option value="all">全部状态</option><option value="enabled">已启用</option><option value="available">未启用</option></select></div>
|
|
36
|
+
<div class="page-head"><div><h1>Skill / Plugin / MCP / Agent 生态</h1><p>在同一页面管理研究 Skill、Pi Plugin、MCP 与 Subagent(对齐 Claude Code)。配置变更后使用 <code>/reload</code>。</p></div><button id="refresh-ecosystem" class="button">刷新</button></div>
|
|
37
|
+
<div class="controls" style="margin-bottom:12px"><input id="eco-search" placeholder="搜索名称或描述"><div class="segmented" aria-label="能力类型"><button class="active" data-eco-kind="all">全部</button><button data-eco-kind="skill">Skill</button><button data-eco-kind="plugin">Plugin</button><button data-eco-kind="mcp">MCP</button><button data-eco-kind="agent">Agent</button></div><select id="eco-kind" aria-label="更多类型"><option value="all">全部来源</option><option value="local">用户 Skill</option><option value="external">外部工具</option></select><select id="eco-status"><option value="all">全部状态</option><option value="enabled">已启用</option><option value="available">未启用</option></select></div>
|
|
38
38
|
<div class="table-wrap"><table class="data"><thead><tr><th>名称</th><th>类型</th><th>来源</th><th>状态</th><th>操作</th></tr></thead><tbody id="ecosystem-body"><tr><td colspan="5">读取中...</td></tr></tbody></table></div>
|
|
39
39
|
</section>
|
|
40
40
|
|
|
@@ -65,8 +65,8 @@ function selectTree(button){document.querySelectorAll(".tree-item").forEach(item
|
|
|
65
65
|
async function openFile(path,button){selectTree(button);$("viewer-path").textContent=path;$("viewer-kind").textContent="读取中";$("viewer-body").className="viewer-body empty";$("viewer-body").textContent="读取中...";try{const file=await json(`/api/project-file?path=${encodeURIComponent(path)}`);$("viewer-kind").textContent=file.format;$("viewer-body").className="viewer-body";$("viewer-body").innerHTML=file.format==="markdown"?`<article class="markdown">${renderMarkdown(file.content)}</article>`:`<pre class="raw">${esc(file.format==="json"?JSON.stringify(JSON.parse(file.content),null,2):file.content)}</pre>`}catch(error){$("viewer-body").className="viewer-body empty";$("viewer-body").textContent=error.message}}
|
|
66
66
|
async function loadProject(){const files=await json("/api/project-files");state.files=files.files||[];renderTree();const goal=document.querySelector('[data-file="notes/goal.md"]')||document.querySelector("[data-file]");if(goal)goal.click()}
|
|
67
67
|
|
|
68
|
-
async function loadEcosystem(){try{const[skills,plugins,mcps,enabled]=await Promise.all([json("/api/recommended-skills"),json("/api/recommended-plugins"),json("/api/recommended-mcps"),json("/api/enabled-capabilities")]);const skillSet=new Set((enabled.skills||[]).map(item=>item.id)),mcpSet=new Set((enabled.mcp||[]).map(item=>item.id));state.eco=[...(enabled.coreSkills||[]).map(item=>({...item,kind:"core",description:item.description||"PsyClaw 内置 Skill",sourceRef:"bundled",enabled:item.enabled,installed:true})),...(skills.items||[]).map(item=>({...item,kind:"skill",enabled:skillSet.has(item.id),installed:skillSet.has(item.id)})),...(plugins.items||[]).map(item=>({...item,kind:"plugin",enabled:Boolean(item.enabled),installed:Boolean(item.installed)})),...(enabled.localSkills||[]).map(item=>({...item,kind:"local",sourceRef:item.path||"用户目录",installed:true})),...(mcps.items||[]).map(item=>({...item,kind:"mcp",enabled:mcpSet.has(item.id),installed:mcpSet.has(item.id)})),...(skills.externalTools||[]).map(item=>({...item,kind:"external",enabled:false,installed:false}))];renderEcosystem()}catch(error){$("ecosystem-body").innerHTML=`<tr><td colspan="5">${esc(error.message)}</td></tr>`}}
|
|
69
|
-
function renderEcosystem(){const query=$("eco-search").value.trim().toLowerCase(),sourceKind=$("eco-kind").value,status=$("eco-status").value,primaryKind=state.ecoKind;const primaryMatches=item=>primaryKind==="all"||(primaryKind==="skill"?(item.kind==="skill"||item.kind==="core"||item.kind==="local"):item.kind===primaryKind);const items=state.eco.filter(item=>primaryMatches(item)&&(sourceKind==="all"||item.kind===sourceKind)&&(status==="all"||(status==="enabled"?item.enabled:!item.enabled))&&`${item.name} ${item.description||""}`.toLowerCase().includes(query));$("ecosystem-body").innerHTML=items.map(item=>`<tr><td><div class="name">${esc(item.name)}</div><div class="subtle">${esc(item.description||"")}${item.kind==="plugin"&&item.scope?` · ${item.scope==="project"?"当前项目":"所有项目"}${item.filtered?" · 已限定资源范围":""}`:""}</div></td><td>${esc(item.kind==="core"?"Core Skill":item.kind==="local"?"用户 Skill":item.kind.toUpperCase())}</td><td>${/^https?:/.test(item.sourceRef||"")?`<a href="${esc(item.sourceRef)}" target="_blank" rel="noreferrer">来源</a>`:esc(item.sourceRef||"bundled")}</td><td><span class="tag ${item.enabled?"ok":item.configured?"warn":""}">${item.locked?"
|
|
68
|
+
async function loadEcosystem(){try{const[skills,plugins,mcps,agents,enabled]=await Promise.all([json("/api/recommended-skills"),json("/api/recommended-plugins"),json("/api/recommended-mcps"),json("/api/recommended-agents"),json("/api/enabled-capabilities")]);const skillSet=new Set((enabled.skills||[]).map(item=>item.id)),mcpSet=new Set((enabled.mcp||[]).map(item=>item.id));state.eco=[...(enabled.coreSkills||[]).map(item=>({...item,kind:"core",description:item.description||"PsyClaw 内置 Skill",sourceRef:"bundled",enabled:item.enabled,installed:true})),...(skills.items||[]).map(item=>({...item,kind:"skill",enabled:skillSet.has(item.id),installed:skillSet.has(item.id)})),...(plugins.items||[]).map(item=>({...item,kind:"plugin",enabled:Boolean(item.enabled),installed:Boolean(item.installed)})),...(enabled.localSkills||[]).map(item=>({...item,kind:"local",sourceRef:item.path||"用户目录",installed:true})),...(mcps.items||[]).map(item=>({...item,kind:"mcp",enabled:mcpSet.has(item.id),installed:mcpSet.has(item.id)})),...(agents.items||[]).map(item=>({...item,kind:"agent",enabled:Boolean(item.enabled),installed:Boolean(item.installed),locked:Boolean(item.locked)})),...(skills.externalTools||[]).map(item=>({...item,kind:"external",enabled:false,installed:false}))];renderEcosystem()}catch(error){$("ecosystem-body").innerHTML=`<tr><td colspan="5">${esc(error.message)}</td></tr>`}}
|
|
69
|
+
function renderEcosystem(){const query=$("eco-search").value.trim().toLowerCase(),sourceKind=$("eco-kind").value,status=$("eco-status").value,primaryKind=state.ecoKind;const primaryMatches=item=>primaryKind==="all"||(primaryKind==="skill"?(item.kind==="skill"||item.kind==="core"||item.kind==="local"):item.kind===primaryKind);const items=state.eco.filter(item=>primaryMatches(item)&&(sourceKind==="all"||item.kind===sourceKind)&&(status==="all"||(status==="enabled"?item.enabled:!item.enabled))&&`${item.name} ${item.description||""}`.toLowerCase().includes(query));$("ecosystem-body").innerHTML=items.map(item=>`<tr><td><div class="name">${esc(item.name)}</div><div class="subtle">${esc(item.description||"")}${item.kind==="plugin"&&item.scope?` · ${item.scope==="project"?"当前项目":"所有项目"}${item.filtered?" · 已限定资源范围":""}`:""}${item.kind==="agent"&&item.slashCommand?` · ${esc(item.slashCommand)}`:""}</div></td><td>${esc(item.kind==="core"?"Core Skill":item.kind==="local"?"用户 Skill":item.kind==="agent"?"Agent":item.kind.toUpperCase())}</td><td>${/^https?:/.test(item.sourceRef||"")?`<a href="${esc(item.sourceRef)}" target="_blank" rel="noreferrer">来源</a>`:esc(item.sourceRef||"bundled")}</td><td><span class="tag ${item.enabled?"ok":item.configured?"warn":""}">${item.locked?"内置可用":item.enabled?(item.kind==="plugin"?"已安装":"已启用"):item.kind==="plugin"&&item.configured?"配置存在,文件缺失":item.kind==="external"?"可安装外部工具":"未启用"}</span></td><td>${item.locked||item.kind==="agent"?"—":item.kind==="plugin"&&item.local?"—":item.kind==="plugin"?`<button class="button small ${item.installed?"":"primary"}" onclick="installCapability('plugin','${esc(item.id)}')">${item.installed?"重新安装":"安装"}</button>`:item.kind==="external"?`<button class="button small primary" onclick="installCapability('external','${esc(item.id)}')">安装</button>`:item.enabled?`<button class="button small" onclick="toggleCapability('${item.kind}','${esc(item.id)}',false)">停用</button>`:item.kind==="local"?`<button class="button small primary" onclick="toggleCapability('local','${esc(item.id)}',true)">启用</button>`:`<button class="button small primary" onclick="installCapability('${item.kind}','${esc(item.id)}')">${item.kind==="core"?"启用":"安装"}</button>`}</td></tr>`).join("")||'<tr><td colspan="5">没有匹配项</td></tr>'}
|
|
70
70
|
async function toggleCapability(kind,id,enabled){await json("/api/recommendation-state",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({kind:kind==="core"?"core-skill":kind==="skill"?"skills":kind==="local"?"local-skill":kind,id,enabled})});await loadEcosystem()}
|
|
71
71
|
async function installCapability(kind,id){if(kind==="core"){await toggleCapability(kind,id,true);return}const scope=kind==="skill"||kind==="plugin"?(confirm("安装到系统目录?\n确定:所有项目使用;取消:仅当前项目使用。")?"user":"project"):undefined;if(!confirm(`确认安装 ${id}?${kind==="external"?"模型将按官方来源安装并验证。":"安装完成后需要 /reload。"}`))return;const result=await json("/api/install/execute",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({kind,id,scope,approved:true,actor:"researcher"})});alert(result.message||(result.ok?"安装任务已处理。":"安装未完成"));await loadEcosystem()}
|
|
72
72
|
[$("eco-search"),$("eco-kind"),$("eco-status")].forEach(control=>control.addEventListener("input",renderEcosystem));
|
|
@@ -2,7 +2,9 @@ import { DefaultPackageManager, getAgentDir, SettingsManager } from "@earendil-w
|
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
import { appendApproval, approvalInputDigest, asProject, assertResearchDecision, bootstrapProject, projectPaths, readApprovals, resolveResearchDecision, runOfflineBrief, runInstitutionalFulltext, runLiteratureReview, runExpertReview, runAnalysisDelegation, runWritingReview, runMetaAnalysis, createStageRunner, exportAcademicDocument, recordCitationUse, runParallelPeerReview, writeHandoff } from "../../index.js";
|
|
4
4
|
import { runPlanWithPi } from "../../orchestration/pi-executor.js";
|
|
5
|
-
import { customPersonaPlan,
|
|
5
|
+
import { customPersonaPlan, parseAgentsRequest } from "../../orchestration/personas.js";
|
|
6
|
+
import { elevatedEffects, formatEffects, hasElevatedEffects, normalizeEffects, toolsForEffects } from "../../orchestration/effects.js";
|
|
7
|
+
import { agentManagerRows, loadSelectablePersonas } from "../../agents/recommended-personas.js";
|
|
6
8
|
import { atomicWriteFile } from "../../project/jsonl.js";
|
|
7
9
|
import { applyCreation, previewCreation, runArsMultiAgentBridge } from "../../index.js";
|
|
8
10
|
import { loadUserRules, userRulesPrompt } from "../../rules/user-rules.js";
|
|
@@ -19,6 +21,7 @@ import { enabledLocalSkillPaths, enabledLocalPromptPaths, readUserSkillState, sc
|
|
|
19
21
|
import { RuntimeMcpRegistry, setUserMcpConfigEnabled, } from "../../integrations/mcp-runtime.js";
|
|
20
22
|
import { SecretInputComponent, ProviderPickerComponent, } from "../../tui/provider-picker.js";
|
|
21
23
|
import { ARS_REPOSITORY_URL, ARS_UPSTREAM_COMMIT, ARS_UPSTREAM_REF, PSYCLAW_ARS_PROFILE_VERSION, detectNatureArsFillers, formatNatureArsFillerStatus, isArsPiActive, isArsPiTurn, psyclawArsPatch, } from "../../ars/profile.js";
|
|
24
|
+
import { ArsModeEditor, enterArsModeEditorText, isArsModeEditorText } from "../../ars/mode-editor.js";
|
|
22
25
|
const PARADIGMS = new Set([
|
|
23
26
|
"survey-observational",
|
|
24
27
|
"qualitative-thematic",
|
|
@@ -643,6 +646,46 @@ async function openPluginManager(ctx, rows) {
|
|
|
643
646
|
missingMessage: "按 Enter 安装到当前项目。",
|
|
644
647
|
})));
|
|
645
648
|
}
|
|
649
|
+
function agentManagerItems(rows) {
|
|
650
|
+
return rows.map((row) => ({
|
|
651
|
+
id: row.id,
|
|
652
|
+
name: row.name,
|
|
653
|
+
description: row.description,
|
|
654
|
+
status: row.status,
|
|
655
|
+
sourceRef: row.sourceRef,
|
|
656
|
+
details: [
|
|
657
|
+
`类别:${row.stage}`,
|
|
658
|
+
`角色:${row.role}`,
|
|
659
|
+
`来源:${row.source === "bundled" ? "内置 Subagent(类似 Claude Explore/Plan)" : "项目 .psyclaw/agents/custom"}`,
|
|
660
|
+
`运行:/agents --agent ${row.id} <只读研究任务>`,
|
|
661
|
+
],
|
|
662
|
+
}));
|
|
663
|
+
}
|
|
664
|
+
async function openAgentManager(ctx, rows) {
|
|
665
|
+
return ctx.ui.custom((tui, theme, keybindings, done) => (new SkillManagerComponent(agentManagerItems(rows), tui, theme, keybindings, done, {
|
|
666
|
+
title: "Subagent(对齐 Claude Code)",
|
|
667
|
+
itemLabel: "Subagent",
|
|
668
|
+
footer: "↑/↓ 移动 · Enter 查看用法 · Esc 关闭 · 运行: /agents --agent <id> <任务>",
|
|
669
|
+
enterAction: "details",
|
|
670
|
+
toggleEnabled: false,
|
|
671
|
+
enabledText: "已可选用",
|
|
672
|
+
lockedMessage: "内置 Subagent 始终可用。运行:/agents --agent <id> <只读研究任务>",
|
|
673
|
+
})));
|
|
674
|
+
}
|
|
675
|
+
async function showAgentManager(ctx, statusOnly = false) {
|
|
676
|
+
const rows = await agentManagerRows(ctx.cwd);
|
|
677
|
+
if (!ctx.hasUI || typeof ctx.ui.custom !== "function" || statusOnly) {
|
|
678
|
+
ctx.ui.notify(rows.map((row) => `${row.status === "core" ? "◆" : "●"} ${row.id} — ${row.name}(${row.stage})`).join("\n")
|
|
679
|
+
|| "暂无 Subagent。可用 /create-subagent 创建(类似 Claude Code)。", "info");
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
while (true) {
|
|
683
|
+
const action = await openAgentManager(ctx, await agentManagerRows(ctx.cwd));
|
|
684
|
+
if (action.type === "close")
|
|
685
|
+
return;
|
|
686
|
+
// Enter/Space only show inline notices; keep the manager open.
|
|
687
|
+
}
|
|
688
|
+
}
|
|
646
689
|
async function installRecommendedPlugin(ctx, row) {
|
|
647
690
|
if (!row.installable)
|
|
648
691
|
throw new Error(row.reason ?? `${row.name} 尚未提供可安装的 Plugin package`);
|
|
@@ -1110,6 +1153,18 @@ export default function psyclawExtension(pi) {
|
|
|
1110
1153
|
})}`,
|
|
1111
1154
|
};
|
|
1112
1155
|
});
|
|
1156
|
+
if (!legacyTestApi && typeof pi.on === "function")
|
|
1157
|
+
pi.on("session_start", (_event, ctx) => {
|
|
1158
|
+
if (!ctx.hasUI || typeof ctx.ui.setEditorComponent !== "function")
|
|
1159
|
+
return;
|
|
1160
|
+
ctx.ui.setEditorComponent((tui, theme, keybindings) => {
|
|
1161
|
+
const editor = new ArsModeEditor(tui, theme, keybindings);
|
|
1162
|
+
editor.onArsModeChange = (active) => {
|
|
1163
|
+
ctx.ui.setStatus("ars", active ? "ARS" : undefined);
|
|
1164
|
+
};
|
|
1165
|
+
return editor;
|
|
1166
|
+
});
|
|
1167
|
+
});
|
|
1113
1168
|
if (!legacyTestApi && typeof pi.on === "function")
|
|
1114
1169
|
pi.on("input", (event, ctx) => {
|
|
1115
1170
|
if (event.source === "extension")
|
|
@@ -1123,7 +1178,10 @@ export default function psyclawExtension(pi) {
|
|
|
1123
1178
|
pi.on("input", async (event, ctx) => {
|
|
1124
1179
|
if (event.source === "extension" || isArsPiActive(ctx.sessionManager))
|
|
1125
1180
|
return;
|
|
1126
|
-
|
|
1181
|
+
const text = event.text.trim();
|
|
1182
|
+
const entersArs = isArsModeEditorText(text)
|
|
1183
|
+
|| /^\/(?:ars-[a-z0-9-]+|skill:(?:deep-research|academic-paper|academic-paper-reviewer|academic-pipeline))(?:\s|$)/i.test(text);
|
|
1184
|
+
if (!entersArs)
|
|
1127
1185
|
return;
|
|
1128
1186
|
if (!ctx.hasUI)
|
|
1129
1187
|
return { action: "handled" };
|
|
@@ -1409,22 +1467,37 @@ export default function psyclawExtension(pi) {
|
|
|
1409
1467
|
});
|
|
1410
1468
|
if (!legacyTestApi)
|
|
1411
1469
|
pi.registerCommand("ars", {
|
|
1412
|
-
description: "
|
|
1470
|
+
description: "进入 ARS 对话模式,或管理 doctor/start/full/stop",
|
|
1413
1471
|
handler: async (args, ctx) => {
|
|
1414
1472
|
try {
|
|
1415
|
-
const [action
|
|
1473
|
+
const [action, ...rest] = args.trim().split(/\s+/).filter(Boolean);
|
|
1474
|
+
// Bare /ars → conversation mode (ars: + tint). No profile popup.
|
|
1475
|
+
if (!action) {
|
|
1476
|
+
if (!ctx.hasUI) {
|
|
1477
|
+
ctx.ui.notify("当前环境无编辑器;请改用 /ars start 或发送 ars: <任务>。", "info");
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
if (!isArsPiActive(ctx.sessionManager)) {
|
|
1481
|
+
const approved = await ctx.ui.confirm("启用 ARS?", `来源:${ARS_REPOSITORY_URL} @ ${ARS_UPSTREAM_REF}\n许可:CC BY-NC 4.0,仅限非商业用途。关键研究阶段仍会请求确认。`);
|
|
1482
|
+
if (!approved)
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
ctx.ui.setEditorText(enterArsModeEditorText(ctx.ui.getEditorText?.() ?? ""));
|
|
1486
|
+
ctx.ui.setStatus("ars", "ARS");
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1416
1489
|
if (action === "status") {
|
|
1417
1490
|
ctx.ui.notify([
|
|
1418
1491
|
`PsyClaw ARS profile v${PSYCLAW_ARS_PROFILE_VERSION}`,
|
|
1419
|
-
"模式:轻量 ARS
|
|
1492
|
+
"模式:轻量 ARS(输入 ars 后按 Tab,或以 ars: 前缀对话)",
|
|
1420
1493
|
`来源:${ARS_REPOSITORY_URL} @ ${ARS_UPSTREAM_REF} (${ARS_UPSTREAM_COMMIT.slice(0, 12)})`,
|
|
1421
|
-
"
|
|
1494
|
+
"入口:ars: <task>,/ars doctor,/ars start,/ars full <task>,/ars stop",
|
|
1422
1495
|
formatNatureArsFillerStatus(natureFillersFromCommandContext(ctx)),
|
|
1423
1496
|
].join("\n"), "info");
|
|
1424
1497
|
return;
|
|
1425
1498
|
}
|
|
1426
1499
|
if (action === "install") {
|
|
1427
|
-
ctx.ui.notify("ARS
|
|
1500
|
+
ctx.ui.notify("ARS 与 Nature/compose 技能已内置:输入 ars 后按 Tab,或以 /ars start、/ars full <task> 使用。", "info");
|
|
1428
1501
|
return;
|
|
1429
1502
|
}
|
|
1430
1503
|
if ((action === "start" || action === "full") && !isArsPiActive(ctx.sessionManager)) {
|
|
@@ -1442,11 +1515,14 @@ export default function psyclawExtension(pi) {
|
|
|
1442
1515
|
? `/ars-full${rest.length > 0 ? ` ${rest.join(" ")}` : ""}`
|
|
1443
1516
|
: undefined;
|
|
1444
1517
|
if (!upstreamCommand) {
|
|
1445
|
-
ctx.ui.notify("Usage: /ars [status|doctor|start|full <task>|stop]", "info");
|
|
1518
|
+
ctx.ui.notify("Usage: /ars [status|doctor|start|full <task>|stop] 或直接输入 ars 后按 Tab", "info");
|
|
1446
1519
|
return;
|
|
1447
1520
|
}
|
|
1448
|
-
if (action === "
|
|
1449
|
-
ctx.ui.
|
|
1521
|
+
if (action === "stop") {
|
|
1522
|
+
ctx.ui.setStatus("ars", undefined);
|
|
1523
|
+
if (ctx.hasUI && isArsModeEditorText(ctx.ui.getEditorText?.() ?? "")) {
|
|
1524
|
+
ctx.ui.setEditorText("");
|
|
1525
|
+
}
|
|
1450
1526
|
}
|
|
1451
1527
|
// A queued prompt does not get a fresh system prompt in Pi. Wait so the
|
|
1452
1528
|
// upstream wrapper can activate ARS and inject its compatibility note.
|
|
@@ -1848,7 +1924,7 @@ export default function psyclawExtension(pi) {
|
|
|
1848
1924
|
pi.registerTool({
|
|
1849
1925
|
name: "psyclaw_create",
|
|
1850
1926
|
label: "Create project capability",
|
|
1851
|
-
description: "Preview and, after an explicit UI confirmation, create one PsyClaw-native project Skill, declarative analysis Hook, additive Rule, or
|
|
1927
|
+
description: "Preview and, after an explicit UI confirmation, create one PsyClaw-native project Skill, declarative analysis Hook, additive Rule, or Subagent (Claude-style). Elevated subagent effects require confirmation at create and again at each /agents run.",
|
|
1852
1928
|
parameters: Type.Object({
|
|
1853
1929
|
kind: Type.Union([Type.Literal("skill"), Type.Literal("hook"), Type.Literal("rule"), Type.Literal("subagent")]),
|
|
1854
1930
|
id: Type.String({ minLength: 1, maxLength: 64 }),
|
|
@@ -1859,6 +1935,12 @@ export default function psyclawExtension(pi) {
|
|
|
1859
1935
|
pattern: Type.Optional(Type.String({ maxLength: 500 })),
|
|
1860
1936
|
pathPrefix: Type.Optional(Type.String({ maxLength: 200 })),
|
|
1861
1937
|
role: Type.Optional(Type.Union([Type.Literal("planner"), Type.Literal("researcher"), Type.Literal("analyst"), Type.Literal("critic"), Type.Literal("writer"), Type.Literal("verifier")])),
|
|
1938
|
+
allowedEffects: Type.Optional(Type.Array(Type.Union([
|
|
1939
|
+
Type.Literal("read"),
|
|
1940
|
+
Type.Literal("write"),
|
|
1941
|
+
Type.Literal("network"),
|
|
1942
|
+
Type.Literal("destructive"),
|
|
1943
|
+
]), { maxItems: 4 })),
|
|
1862
1944
|
}),
|
|
1863
1945
|
executionMode: "sequential",
|
|
1864
1946
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -1870,7 +1952,15 @@ export default function psyclawExtension(pi) {
|
|
|
1870
1952
|
if (!ctx.hasUI || typeof ctx.ui?.confirm !== "function") {
|
|
1871
1953
|
return { content: [{ type: "text", text: JSON.stringify({ ...preview, status: "preview-only", reason: "interactive confirmation unavailable" }, null, 2) }], details: preview };
|
|
1872
1954
|
}
|
|
1873
|
-
const
|
|
1955
|
+
const effects = request.kind === "subagent" ? normalizeEffects(request.allowedEffects) : ["read"];
|
|
1956
|
+
const elevated = request.kind === "subagent" && hasElevatedEffects(effects);
|
|
1957
|
+
const title = elevated
|
|
1958
|
+
? `创建 Subagent “${preview.id}”(含提升权限)?`
|
|
1959
|
+
: `创建 ${params.kind} “${preview.id}”?`;
|
|
1960
|
+
const body = elevated
|
|
1961
|
+
? `目标:${preview.path}\n声明 effects:${formatEffects(effects)}\n将开放工具:${toolsForEffects(effects).join(", ")}\nSHA-256:${preview.sha256}\n\n每次 /agents 运行仍会再次确认。凭据读取与绕过门禁仍被禁止。\n\n${preview.contents}`
|
|
1962
|
+
: `目标:${preview.path}\nSHA-256:${preview.sha256}\n\n${preview.contents}`;
|
|
1963
|
+
const approved = await ctx.ui.confirm(title, body);
|
|
1874
1964
|
if (!approved)
|
|
1875
1965
|
return { content: [{ type: "text", text: "Creation cancelled; no file was written." }], details: { status: "cancelled", preview } };
|
|
1876
1966
|
const result = await applyCreation(ctx.cwd, request, preview.sha256, true);
|
|
@@ -2121,12 +2211,22 @@ export default function psyclawExtension(pi) {
|
|
|
2121
2211
|
// runner behind PSYCLAW_DEVELOPER_COMMANDS in published builds.
|
|
2122
2212
|
if (!legacyTestApi)
|
|
2123
2213
|
pi.registerCommand("agents", {
|
|
2124
|
-
description: "
|
|
2214
|
+
description: "浏览或运行 Subagent(对齐 Claude Code)",
|
|
2125
2215
|
handler: async (args, ctx) => {
|
|
2216
|
+
const trimmed = args.trim();
|
|
2217
|
+
if (!trimmed || trimmed === "status" || trimmed === "list") {
|
|
2218
|
+
try {
|
|
2219
|
+
await showAgentManager(ctx, trimmed === "status" || trimmed === "list");
|
|
2220
|
+
}
|
|
2221
|
+
catch (error) {
|
|
2222
|
+
await notifyError(ctx, error);
|
|
2223
|
+
}
|
|
2224
|
+
return;
|
|
2225
|
+
}
|
|
2126
2226
|
const requested = parseAgentsRequest(args);
|
|
2127
2227
|
const objective = requested.objective;
|
|
2128
2228
|
if (!objective) {
|
|
2129
|
-
ctx.ui.notify("Usage: /agents [--agent <id>|--agents <id,...>] <
|
|
2229
|
+
ctx.ui.notify("Usage: /agents [--agent <id>|--agents <id,...>] <task>\n无任务时直接运行 /agents 打开 Subagent 管理页。", "info");
|
|
2130
2230
|
return;
|
|
2131
2231
|
}
|
|
2132
2232
|
if (objective.length > 4_000) {
|
|
@@ -2151,13 +2251,60 @@ export default function psyclawExtension(pi) {
|
|
|
2151
2251
|
const runId = `pi_agent_${Date.now()}`;
|
|
2152
2252
|
let plan = researchTaskPlan(runId, objective);
|
|
2153
2253
|
if (requested.ids.length > 0) {
|
|
2154
|
-
const available = await
|
|
2254
|
+
const available = await loadSelectablePersonas(ctx.cwd);
|
|
2155
2255
|
const byId = new Map(available.map((persona) => [persona.id, persona]));
|
|
2156
2256
|
const selected = requested.ids.map((id) => byId.get(id));
|
|
2157
2257
|
const missing = requested.ids.filter((_id, index) => !selected[index]);
|
|
2158
2258
|
if (missing.length > 0)
|
|
2159
|
-
throw new Error(`Unknown or invalid
|
|
2160
|
-
|
|
2259
|
+
throw new Error(`Unknown or invalid subagent: ${missing.join(", ")}. Run /agents to list bundled and custom subagents.`);
|
|
2260
|
+
const personas = selected.filter((persona) => persona !== undefined);
|
|
2261
|
+
const unionEffects = normalizeEffects(personas.flatMap((persona) => persona.allowedEffects));
|
|
2262
|
+
const elevated = elevatedEffects(unionEffects);
|
|
2263
|
+
if (elevated.length > 0) {
|
|
2264
|
+
if (!ctx.hasUI || typeof ctx.ui.confirm !== "function") {
|
|
2265
|
+
throw new Error(`Subagent effects [${formatEffects(elevated)}] require interactive confirmation`);
|
|
2266
|
+
}
|
|
2267
|
+
const approved = await ctx.ui.confirm("批准 Subagent 提升权限?", `将启用:${formatEffects(elevated)}\n对应工具:${toolsForEffects(unionEffects).join(", ")}\n任务:${objective.slice(0, 400)}\n\n凭据读取、绕过门禁与外部发布仍被禁止。`);
|
|
2268
|
+
if (!approved) {
|
|
2269
|
+
ctx.ui.notify("已取消:未批准提升权限,未启动 Subagent。", "warning");
|
|
2270
|
+
return;
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
plan = customPersonaPlan(runId, objective, personas);
|
|
2274
|
+
await mkdir(join(ctx.cwd, ".psyclaw", "plans"), { recursive: true });
|
|
2275
|
+
await atomicWriteFile(join(ctx.cwd, ".psyclaw", "plans", `${runId}.json`), `${JSON.stringify(plan, null, 2)}\n`);
|
|
2276
|
+
const eventLog = new RunEventLog(ctx.cwd, runId);
|
|
2277
|
+
const result = await runPlanWithPi(plan, {
|
|
2278
|
+
cwd: ctx.cwd,
|
|
2279
|
+
agentDir: join(ctx.cwd, ".psyclaw", "pi-agent"),
|
|
2280
|
+
...(ctx.model?.provider === undefined ? {} : { provider: ctx.model.provider }),
|
|
2281
|
+
...(ctx.model?.id === undefined ? {} : { model: ctx.model.id }),
|
|
2282
|
+
env: providerEnvironment(ctx.model?.provider),
|
|
2283
|
+
...(elevated.length === 0 ? { tools: [] } : {}),
|
|
2284
|
+
allowWrites: unionEffects.includes("write"),
|
|
2285
|
+
allowNetwork: unionEffects.includes("network"),
|
|
2286
|
+
allowDestructive: unionEffects.includes("destructive"),
|
|
2287
|
+
root: ctx.cwd,
|
|
2288
|
+
pauseRequested: async () => {
|
|
2289
|
+
try {
|
|
2290
|
+
await import("node:fs/promises").then(({ access }) => access(join(ctx.cwd, ".psyclaw", "runs", `${runId}.pause`)));
|
|
2291
|
+
return true;
|
|
2292
|
+
}
|
|
2293
|
+
catch {
|
|
2294
|
+
return false;
|
|
2295
|
+
}
|
|
2296
|
+
},
|
|
2297
|
+
onEvent: async (event) => { await eventLog.append(event); },
|
|
2298
|
+
});
|
|
2299
|
+
pi.appendEntry("psyclaw:agent-run", {
|
|
2300
|
+
runId,
|
|
2301
|
+
status: result.status,
|
|
2302
|
+
diagnostics: result.diagnostics,
|
|
2303
|
+
effects: unionEffects,
|
|
2304
|
+
recordedAt: new Date().toISOString(),
|
|
2305
|
+
});
|
|
2306
|
+
ctx.ui.notify(`Agent run ${result.status}: ${result.diagnostics.join("; ") || "verified"}`, result.status === "completed" ? "info" : "warning");
|
|
2307
|
+
return;
|
|
2161
2308
|
}
|
|
2162
2309
|
await mkdir(join(ctx.cwd, ".psyclaw", "plans"), { recursive: true });
|
|
2163
2310
|
await atomicWriteFile(join(ctx.cwd, ".psyclaw", "plans", `${runId}.json`), `${JSON.stringify(plan, null, 2)}\n`);
|
|
@@ -2168,7 +2315,6 @@ export default function psyclawExtension(pi) {
|
|
|
2168
2315
|
...(ctx.model?.provider === undefined ? {} : { provider: ctx.model.provider }),
|
|
2169
2316
|
...(ctx.model?.id === undefined ? {} : { model: ctx.model.id }),
|
|
2170
2317
|
env: providerEnvironment(ctx.model?.provider),
|
|
2171
|
-
...(requested.ids.length > 0 ? { tools: [] } : {}),
|
|
2172
2318
|
root: ctx.cwd,
|
|
2173
2319
|
pauseRequested: async () => {
|
|
2174
2320
|
try {
|