@researai/deepscientist 1.5.1 → 1.5.3
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 +69 -1
- package/bin/ds.js +2239 -153
- package/docs/en/00_QUICK_START.md +60 -20
- package/docs/en/01_SETTINGS_REFERENCE.md +20 -20
- package/docs/en/02_START_RESEARCH_GUIDE.md +11 -11
- package/docs/en/03_QQ_CONNECTOR_GUIDE.md +10 -10
- package/docs/en/05_TUI_GUIDE.md +1 -1
- package/docs/en/09_DOCTOR.md +48 -4
- package/docs/en/90_ARCHITECTURE.md +4 -2
- package/docs/zh/00_QUICK_START.md +60 -20
- package/docs/zh/01_SETTINGS_REFERENCE.md +21 -21
- package/docs/zh/02_START_RESEARCH_GUIDE.md +19 -19
- package/docs/zh/03_QQ_CONNECTOR_GUIDE.md +10 -10
- package/docs/zh/05_TUI_GUIDE.md +1 -1
- package/docs/zh/09_DOCTOR.md +46 -4
- package/install.sh +125 -8
- package/package.json +2 -1
- package/pyproject.toml +1 -1
- package/src/deepscientist/__init__.py +6 -1
- package/src/deepscientist/artifact/service.py +553 -26
- package/src/deepscientist/bash_exec/monitor.py +23 -4
- package/src/deepscientist/bash_exec/runtime.py +3 -0
- package/src/deepscientist/bash_exec/service.py +132 -4
- package/src/deepscientist/bridges/base.py +10 -19
- package/src/deepscientist/channels/discord_gateway.py +25 -2
- package/src/deepscientist/channels/feishu_long_connection.py +41 -3
- package/src/deepscientist/channels/qq.py +524 -64
- package/src/deepscientist/channels/qq_gateway.py +22 -3
- package/src/deepscientist/channels/relay.py +429 -90
- package/src/deepscientist/channels/slack_socket.py +29 -5
- package/src/deepscientist/channels/telegram_polling.py +25 -2
- package/src/deepscientist/channels/whatsapp_local_session.py +32 -4
- package/src/deepscientist/cli.py +27 -0
- package/src/deepscientist/config/models.py +6 -40
- package/src/deepscientist/config/service.py +165 -156
- package/src/deepscientist/connector_profiles.py +346 -0
- package/src/deepscientist/connector_runtime.py +88 -43
- package/src/deepscientist/daemon/api/handlers.py +65 -11
- package/src/deepscientist/daemon/api/router.py +4 -2
- package/src/deepscientist/daemon/app.py +772 -219
- package/src/deepscientist/doctor.py +69 -2
- package/src/deepscientist/gitops/diff.py +3 -0
- package/src/deepscientist/home.py +25 -2
- package/src/deepscientist/mcp/context.py +3 -1
- package/src/deepscientist/mcp/server.py +66 -7
- package/src/deepscientist/migration.py +114 -0
- package/src/deepscientist/prompts/builder.py +71 -3
- package/src/deepscientist/qq_profiles.py +186 -0
- package/src/deepscientist/quest/layout.py +1 -0
- package/src/deepscientist/quest/service.py +70 -12
- package/src/deepscientist/quest/stage_views.py +46 -0
- package/src/deepscientist/runners/codex.py +2 -0
- package/src/deepscientist/shared.py +44 -17
- package/src/prompts/connectors/lingzhu.md +3 -0
- package/src/prompts/connectors/qq.md +42 -2
- package/src/prompts/system.md +123 -10
- package/src/skills/analysis-campaign/SKILL.md +35 -6
- package/src/skills/baseline/SKILL.md +73 -32
- package/src/skills/decision/SKILL.md +4 -3
- package/src/skills/experiment/SKILL.md +28 -6
- package/src/skills/finalize/SKILL.md +5 -2
- package/src/skills/idea/SKILL.md +2 -2
- package/src/skills/intake-audit/SKILL.md +2 -2
- package/src/skills/rebuttal/SKILL.md +4 -2
- package/src/skills/review/SKILL.md +4 -2
- package/src/skills/scout/SKILL.md +2 -2
- package/src/skills/write/SKILL.md +2 -2
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/{AiManusChatView-w5lF2Ttt.js → AiManusChatView-qzChi9uh.js} +67 -94
- package/src/ui/dist/assets/{AnalysisPlugin-DJOED79I.js → AnalysisPlugin-CcC_-UqN.js} +1 -1
- package/src/ui/dist/assets/{AutoFigurePlugin-DaG61Y0M.js → AutoFigurePlugin-DD8LkJLe.js} +5 -5
- package/src/ui/dist/assets/{CliPlugin-CV4LqUB_.js → CliPlugin-DJJFfVmW.js} +17 -110
- package/src/ui/dist/assets/{CodeEditorPlugin-DylfAea4.js → CodeEditorPlugin-CrjkHNLh.js} +8 -8
- package/src/ui/dist/assets/{CodeViewerPlugin-F7saY0LM.js → CodeViewerPlugin-obnD6G5R.js} +5 -5
- package/src/ui/dist/assets/{DocViewerPlugin-COP0c7jf.js → DocViewerPlugin-DB9SUQVd.js} +3 -3
- package/src/ui/dist/assets/{GitDiffViewerPlugin-CAS05pT9.js → GitDiffViewerPlugin-DZLlNlD2.js} +1 -1
- package/src/ui/dist/assets/{ImageViewerPlugin-Bco1CN_w.js → ImageViewerPlugin-BGwfDZ0Y.js} +5 -5
- package/src/ui/dist/assets/{LabCopilotPanel-CvMlCD99.js → LabCopilotPanel-dfLptQcR.js} +10 -10
- package/src/ui/dist/assets/{LabPlugin-BYankkE4.js → LabPlugin-CeGjAl3A.js} +1 -1
- package/src/ui/dist/assets/{LatexPlugin-LDSMR-t-.js → LatexPlugin-BBJ7kd1V.js} +7 -7
- package/src/ui/dist/assets/{MarkdownViewerPlugin-B7o80jgm.js → MarkdownViewerPlugin-DKZi7BcB.js} +4 -4
- package/src/ui/dist/assets/{MarketplacePlugin-CM6ZOcpC.js → MarketplacePlugin-C_k-9jD0.js} +3 -3
- package/src/ui/dist/assets/{NotebookEditor-Dc61cXmK.js → NotebookEditor-4R88_BMO.js} +1 -1
- package/src/ui/dist/assets/{PdfLoader-DWowuQwx.js → PdfLoader-DwEFQLrw.js} +1 -1
- package/src/ui/dist/assets/{PdfMarkdownPlugin-BsJM1q_a.js → PdfMarkdownPlugin-D-jdsqF8.js} +3 -3
- package/src/ui/dist/assets/{PdfViewerPlugin-DB2eEEFQ.js → PdfViewerPlugin-CmeBGDY0.js} +10 -10
- package/src/ui/dist/assets/{SearchPlugin-CraThSvt.js → SearchPlugin-Dlz2WKJ4.js} +1 -1
- package/src/ui/dist/assets/{Stepper-CgocRTPq.js → Stepper-ClOgzWM3.js} +1 -1
- package/src/ui/dist/assets/{TextViewerPlugin-B1JGhKtd.js → TextViewerPlugin-DDQWxibk.js} +4 -4
- package/src/ui/dist/assets/{VNCViewer-CclFC7FM.js → VNCViewer-CJXT0Nm8.js} +9 -9
- package/src/ui/dist/assets/{bibtex-D3IKsMl7.js → bibtex-DLr4Rtk4.js} +1 -1
- package/src/ui/dist/assets/{code-BP37Xx0p.js → code-DgKK408Y.js} +1 -1
- package/src/ui/dist/assets/{file-content-BAJSu-9r.js → file-content-6HBqQnvQ.js} +1 -1
- package/src/ui/dist/assets/{file-diff-panel-DUGeCTuy.js → file-diff-panel-Dhu0TbBM.js} +1 -1
- package/src/ui/dist/assets/{file-socket-CXc1Ojf7.js → file-socket-CP3iwVZG.js} +1 -1
- package/src/ui/dist/assets/{file-utils-2J21jt7M.js → file-utils-BsS-Aw68.js} +1 -1
- package/src/ui/dist/assets/{image-CMMmgvcn.js → image-ByeK-Zcv.js} +1 -1
- package/src/ui/dist/assets/{index-DmwmJmbW.js → index-BLjo5--a.js} +33610 -31016
- package/src/ui/dist/assets/{index-CWgMgpow.js → index-BdsE0uRz.js} +11 -11
- package/src/ui/dist/assets/{index-s7aHnNQ4.js → index-C-eX-N6A.js} +1 -1
- package/src/ui/dist/assets/{index-KGt-z-dD.css → index-CuQhlrR-.css} +2747 -2
- package/src/ui/dist/assets/{index-BaVumsQT.js → index-DyremSIv.js} +2 -2
- package/src/ui/dist/assets/{message-square-CQRfX0Am.js → message-square-DnagiLnc.js} +1 -1
- package/src/ui/dist/assets/{monaco-B4TbdsrF.js → monaco-4kBFeprs.js} +1 -1
- package/src/ui/dist/assets/{popover-B8Rokodk.js → popover-hRCXZzs2.js} +1 -1
- package/src/ui/dist/assets/{project-sync-D_i96KH4.js → project-sync-O_85YuP6.js} +1 -1
- package/src/ui/dist/assets/{sigma-D12PnzCN.js → sigma-DvKopSnL.js} +1 -1
- package/src/ui/dist/assets/{tooltip-B6YrI4aJ.js → tooltip-BmlPc6kc.js} +1 -1
- package/src/ui/dist/assets/{trash-Bc8jGp0V.js → trash-n-UvdZFR.js} +1 -1
- package/src/ui/dist/assets/{useCliAccess-mXVCYSZ-.js → useCliAccess-WDd3_wIh.js} +1 -1
- package/src/ui/dist/assets/{useFileDiffOverlay-Bg6b9H9K.js → useFileDiffOverlay-rXLIL2NF.js} +1 -1
- package/src/ui/dist/assets/{wrap-text-Drh5GEnL.js → wrap-text-qIYQ4a_W.js} +1 -1
- package/src/ui/dist/assets/{zoom-out-CJj9DZLn.js → zoom-out-fZXCEFsy.js} +1 -1
- package/src/ui/dist/index.html +2 -2
- package/uv.lock +1155 -0
- package/src/ui/dist/assets/LabPlugin-D9jVIo0A.css +0 -2698
|
@@ -92,9 +92,9 @@ acp:
|
|
|
92
92
|
- 类型:`string`
|
|
93
93
|
- 默认值:安装时的 DeepScientist 主目录,通常为 `~/DeepScientist`
|
|
94
94
|
- 页面标签:`Home path`
|
|
95
|
-
-
|
|
95
|
+
- 作用:这是配置、项目、memory、plugins、logs、cache 的根路径。
|
|
96
96
|
- 何时修改:仅在你明确使用自定义安装目录时修改。
|
|
97
|
-
-
|
|
97
|
+
- 注意事项:这不是单个项目路径,而是整个 DeepScientist 的运行时根目录。
|
|
98
98
|
|
|
99
99
|
**`default_runner`**
|
|
100
100
|
|
|
@@ -102,7 +102,7 @@ acp:
|
|
|
102
102
|
- 默认值:`codex`
|
|
103
103
|
- 允许值:当前页面预设为 `codex`、`claude`
|
|
104
104
|
- 页面标签:`Default runner`
|
|
105
|
-
-
|
|
105
|
+
- 作用:当项目没有单独覆盖 runner 时,默认走这里指定的 runner。
|
|
106
106
|
- 何时修改:只有在你真的接通并启用了其他 runner 时才需要改。
|
|
107
107
|
- 注意事项:当前仓库的真实主路径仍然是 `codex`;`claude` 仍是预留位。
|
|
108
108
|
|
|
@@ -122,17 +122,17 @@ acp:
|
|
|
122
122
|
- 类型:`boolean`
|
|
123
123
|
- 默认值:`true`
|
|
124
124
|
- 页面标签:`Restore sessions on start`
|
|
125
|
-
- 作用:daemon
|
|
125
|
+
- 作用:daemon 启动时尝试恢复之前的项目会话状态。
|
|
126
126
|
- 何时关闭:你希望每次启动都从干净的运行时状态进入。
|
|
127
127
|
|
|
128
128
|
**`daemon.max_concurrent_quests`**
|
|
129
129
|
|
|
130
130
|
- 类型:`number`
|
|
131
131
|
- 默认值:`1`
|
|
132
|
-
- 页面标签:`Max concurrent
|
|
133
|
-
-
|
|
132
|
+
- 页面标签:`Max concurrent projects`
|
|
133
|
+
- 作用:限制同时活跃的项目数量。
|
|
134
134
|
- 推荐值:大多数情况下保持 `1`。
|
|
135
|
-
-
|
|
135
|
+
- 风险:并发项目越多,资源竞争、连接器串扰和观察复杂度越高。
|
|
136
136
|
|
|
137
137
|
**`daemon.ack_timeout_ms`**
|
|
138
138
|
|
|
@@ -212,7 +212,7 @@ acp:
|
|
|
212
212
|
- 类型:`boolean`
|
|
213
213
|
- 默认值:`true`
|
|
214
214
|
- 页面标签:`Auto-checkpoint`
|
|
215
|
-
-
|
|
215
|
+
- 作用:项目过程中自动做 Git 检查点。
|
|
216
216
|
- 何时关闭:你完全希望手动控制提交节奏。
|
|
217
217
|
|
|
218
218
|
**`git.auto_push`**
|
|
@@ -263,15 +263,15 @@ acp:
|
|
|
263
263
|
|
|
264
264
|
- 类型:`boolean`
|
|
265
265
|
- 默认值:`true`
|
|
266
|
-
- 页面标签:`Sync
|
|
267
|
-
-
|
|
266
|
+
- 页面标签:`Sync project skills on create`
|
|
267
|
+
- 作用:创建项目时,把技能镜像到项目本地 `.codex/skills` / `.claude/agents`。
|
|
268
268
|
|
|
269
269
|
**`skills.sync_quest_on_open`**
|
|
270
270
|
|
|
271
271
|
- 类型:`boolean`
|
|
272
272
|
- 默认值:`true`
|
|
273
|
-
- 页面标签:`Sync
|
|
274
|
-
-
|
|
273
|
+
- 页面标签:`Sync project skills on open`
|
|
274
|
+
- 作用:打开已有项目时刷新本地技能镜像。
|
|
275
275
|
|
|
276
276
|
### Connector policy
|
|
277
277
|
|
|
@@ -296,7 +296,7 @@ acp:
|
|
|
296
296
|
- 类型:`boolean`
|
|
297
297
|
- 默认值:`true`
|
|
298
298
|
- 页面标签:`Enable direct chat`
|
|
299
|
-
- 作用:允许 connector
|
|
299
|
+
- 作用:允许 connector 私聊直接驱动项目。
|
|
300
300
|
|
|
301
301
|
### Cloud link
|
|
302
302
|
|
|
@@ -385,7 +385,7 @@ acp:
|
|
|
385
385
|
|
|
386
386
|
### 摘要
|
|
387
387
|
|
|
388
|
-
`runners.yaml`
|
|
388
|
+
`runners.yaml` 定义项目实际由哪个 runner 执行,以及 runner 的模型默认值、审批策略、沙箱策略和失败重试策略。在当前开源版本中:
|
|
389
389
|
|
|
390
390
|
- `codex`:主路径,默认启用。
|
|
391
391
|
- `claude`:TODO / 预留条目,默认禁用,暂时不能运行。
|
|
@@ -447,7 +447,7 @@ claude:
|
|
|
447
447
|
- 类型:`string`
|
|
448
448
|
- 默认值:`codex=gpt-5.4`,`claude=inherit`
|
|
449
449
|
- 页面标签:`Default model`
|
|
450
|
-
-
|
|
450
|
+
- 作用:项目和单次请求没有覆盖时的默认模型。
|
|
451
451
|
|
|
452
452
|
**`model_reasoning_effort`**
|
|
453
453
|
|
|
@@ -539,7 +539,7 @@ claude:
|
|
|
539
539
|
- 第一版部署一般保持 `codex.enabled: true`、`claude.enabled: false`。
|
|
540
540
|
- 当前版本不要把 `default_runner` 从 `codex` 改走。
|
|
541
541
|
- 如果你不希望任何自动审批,才把 `approval_policy` 调成更严格模式。
|
|
542
|
-
-
|
|
542
|
+
- 如果项目经常需要长时间工具调用,不要随意把 `mcp_tool_timeout_sec` 改小。
|
|
543
543
|
|
|
544
544
|
## `connectors.yaml`
|
|
545
545
|
|
|
@@ -549,7 +549,7 @@ claude:
|
|
|
549
549
|
|
|
550
550
|
- 优先使用无需公网回调的原生传输路径。
|
|
551
551
|
- legacy webhook / relay 字段只作为兼容或兜底。
|
|
552
|
-
-
|
|
552
|
+
- 所有连接器最终都属于同一个项目交互系统,而不是各自独立的一套消息逻辑。
|
|
553
553
|
|
|
554
554
|
### 顶层路由字段
|
|
555
555
|
|
|
@@ -602,7 +602,7 @@ claude:
|
|
|
602
602
|
|
|
603
603
|
- 类型:`boolean`
|
|
604
604
|
- 默认值:大多数 connector 为 `true`
|
|
605
|
-
-
|
|
605
|
+
- 作用:私聊默认自动跟随当前活跃项目。
|
|
606
606
|
|
|
607
607
|
### `telegram`
|
|
608
608
|
|
|
@@ -902,7 +902,7 @@ legacy Meta Cloud 字段:
|
|
|
902
902
|
|
|
903
903
|
- 类型:`boolean`
|
|
904
904
|
- 默认值:`true`
|
|
905
|
-
- 作用:QQ
|
|
905
|
+
- 作用:QQ 私聊默认跟随最新活跃项目。
|
|
906
906
|
|
|
907
907
|
### QQ 里程碑媒体策略
|
|
908
908
|
|
|
@@ -1000,7 +1000,7 @@ allow_unsigned: false
|
|
|
1000
1000
|
|
|
1001
1001
|
### 摘要
|
|
1002
1002
|
|
|
1003
|
-
这个文件管理外部 MCP 服务。它不控制内置 `memory`、`artifact`、`bash_exec
|
|
1003
|
+
这个文件管理外部 MCP 服务。它不控制内置 `memory`、`artifact`、`bash_exec`,也不保存项目内部工具调用历史。
|
|
1004
1004
|
|
|
1005
1005
|
### 结构
|
|
1006
1006
|
|
|
@@ -1023,7 +1023,7 @@ servers:
|
|
|
1023
1023
|
|
|
1024
1024
|
- 类型:`boolean`
|
|
1025
1025
|
- 默认值:新卡片默认为 `false`
|
|
1026
|
-
- 作用:只有启用的外部 MCP
|
|
1026
|
+
- 作用:只有启用的外部 MCP 才会暴露给项目或 runner。
|
|
1027
1027
|
|
|
1028
1028
|
**`servers.<server_id>.transport`**
|
|
1029
1029
|
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
## 这个弹窗实际做什么
|
|
11
11
|
|
|
12
|
-
`Start Research`
|
|
12
|
+
`Start Research` 不只是“新建项目表单”,它同时完成四件事:
|
|
13
13
|
|
|
14
14
|
1. 收集结构化启动上下文
|
|
15
|
-
2.
|
|
15
|
+
2. 把这些上下文编译成项目的第一条 kickoff prompt
|
|
16
16
|
3. 绑定一个可选的可复用 baseline
|
|
17
17
|
4. 持久化 `startup_contract`,供后续 prompt builder 持续读取
|
|
18
18
|
|
|
@@ -113,17 +113,17 @@ type StartResearchContractFields = {
|
|
|
113
113
|
|
|
114
114
|
## 字段说明
|
|
115
115
|
|
|
116
|
-
###
|
|
116
|
+
### 项目基本身份
|
|
117
117
|
|
|
118
118
|
**`title`**
|
|
119
119
|
|
|
120
|
-
-
|
|
120
|
+
- 项目的人类可读标题。
|
|
121
121
|
- 用于卡片和工作区标题。
|
|
122
122
|
- 不要求与 `quest_id` 一致。
|
|
123
123
|
|
|
124
124
|
**`quest_id`**
|
|
125
125
|
|
|
126
|
-
-
|
|
126
|
+
- 项目的稳定标识,保存在 `quest_id` 中,同时也是目录名。
|
|
127
127
|
- 默认由 runtime 提供下一个顺序编号。
|
|
128
128
|
- 允许用户手动覆盖。
|
|
129
129
|
|
|
@@ -256,17 +256,17 @@ type StartResearchContractFields = {
|
|
|
256
256
|
|
|
257
257
|
`compileStartResearchPrompt(...)` 会生成一段可读 kickoff prompt,包含:
|
|
258
258
|
|
|
259
|
-
-
|
|
260
|
-
-
|
|
261
|
-
-
|
|
262
|
-
- baseline
|
|
263
|
-
-
|
|
264
|
-
-
|
|
265
|
-
-
|
|
266
|
-
-
|
|
267
|
-
-
|
|
268
|
-
-
|
|
269
|
-
-
|
|
259
|
+
- 项目启动上下文
|
|
260
|
+
- 核心研究请求
|
|
261
|
+
- 研究目标
|
|
262
|
+
- baseline 上下文
|
|
263
|
+
- 参考论文 / 仓库
|
|
264
|
+
- 运行约束
|
|
265
|
+
- 研究交付模式
|
|
266
|
+
- 决策处理模式
|
|
267
|
+
- 启动模式
|
|
268
|
+
- 研究合同
|
|
269
|
+
- 必须遵守的工作规则
|
|
270
270
|
|
|
271
271
|
其中自定义启动会被明确写出来:
|
|
272
272
|
|
|
@@ -327,8 +327,8 @@ type StartResearchContractFields = {
|
|
|
327
327
|
|
|
328
328
|
```json
|
|
329
329
|
{
|
|
330
|
-
"title": "Continue retrieval
|
|
331
|
-
"goal": "Continue the existing retrieval
|
|
330
|
+
"title": "Continue retrieval project",
|
|
331
|
+
"goal": "Continue the existing retrieval project and decide whether a fresh main run is still needed.",
|
|
332
332
|
"quest_id": "013",
|
|
333
333
|
"requested_baseline_ref": null,
|
|
334
334
|
"startup_contract": {
|
|
@@ -396,7 +396,7 @@ type StartResearchContractFields = {
|
|
|
396
396
|
|
|
397
397
|
## 运行时意义
|
|
398
398
|
|
|
399
|
-
- `startup_contract`
|
|
399
|
+
- `startup_contract` 是项目的持久状态,不只是 UI 临时字段。
|
|
400
400
|
- 后续 prompt builder 还会继续读取 `launch_mode`、`custom_profile`、`entry_state_summary`、`review_summary`、`custom_brief`。
|
|
401
401
|
- 所以 `Start Research` 不只影响第一轮,还会影响后续路由判断。
|
|
402
402
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
完成本文档后,你应该可以做到:
|
|
17
17
|
|
|
18
18
|
- 用 QQ 私聊 DeepScientist
|
|
19
|
-
- 让 QQ
|
|
19
|
+
- 让 QQ 自动绑定到当前最新项目
|
|
20
20
|
- 在 QQ 中使用 `/new`、`/use latest`、`/status` 等命令
|
|
21
21
|
- 在 `Settings` 页面看到自动检测到的 `openid`
|
|
22
22
|
- 从 `Settings` 页面执行非破坏性的连接测试
|
|
@@ -219,7 +219,7 @@ QQ readiness is healthy, but no OpenID has been learned yet. Save credentials, t
|
|
|
219
219
|
- `Settings > Connectors > QQ` 中的 `Detected OpenID` 不再为空
|
|
220
220
|
- `Snapshot` 里出现已经发现的目标会话,且绑定目标不是空
|
|
221
221
|
- 再次点击“发送测试消息”时,不再提示 target 为空
|
|
222
|
-
-
|
|
222
|
+
- 如果当前已经有最新项目,普通文本会自动进入该项目;如果还没有项目,则优先返回帮助信息
|
|
223
223
|
|
|
224
224
|
### 5.2 报错提示速查
|
|
225
225
|
|
|
@@ -239,17 +239,17 @@ QQ readiness is healthy, but no OpenID has been learned yet. Save credentials, t
|
|
|
239
239
|
| 命令 | 作用 |
|
|
240
240
|
| --- | --- |
|
|
241
241
|
| `/help` | 查看帮助 |
|
|
242
|
-
| `/projects` 或 `/list` |
|
|
243
|
-
| `/use <quest_id>` |
|
|
244
|
-
| `/use latest` |
|
|
245
|
-
| `/new <goal>` |
|
|
246
|
-
| `/status` |
|
|
242
|
+
| `/projects` 或 `/list` | 查看项目列表 |
|
|
243
|
+
| `/use <quest_id>` | 绑定指定项目 |
|
|
244
|
+
| `/use latest` | 绑定最新项目 |
|
|
245
|
+
| `/new <goal>` | 新建项目并把当前 QQ 会话绑定过去 |
|
|
246
|
+
| `/status` | 查看当前项目状态 |
|
|
247
247
|
|
|
248
248
|
日常沟通建议:
|
|
249
249
|
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
-
|
|
250
|
+
- 如果已经有最新项目,普通文本通常会继续那个项目
|
|
251
|
+
- 如果还没有项目,优先发送 `/new <goal>`
|
|
252
|
+
- 如果你想切换到另一个项目,显式发送 `/use <quest_id>`
|
|
253
253
|
|
|
254
254
|
## 7. 最容易踩坑的地方
|
|
255
255
|
|
package/docs/zh/05_TUI_GUIDE.md
CHANGED
package/docs/zh/09_DOCTOR.md
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
## 推荐使用流程
|
|
6
6
|
|
|
7
|
-
1. 先安装 DeepScientist
|
|
7
|
+
1. 先安装 DeepScientist:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install -g @
|
|
10
|
+
npm install -g @researai/deepscientist
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
2. 先直接尝试启动:
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
- 本地 Python 运行时是否健康
|
|
32
32
|
- `~/DeepScientist` 是否存在且可写
|
|
33
|
+
- `uv` 是否可用,以便管理本地 Python 运行时
|
|
33
34
|
- `git` 是否安装并完成基本配置
|
|
34
35
|
- 必需配置文件是否有效
|
|
35
36
|
- 当前开源版本是否仍然使用 `codex` 作为可运行 runner
|
|
@@ -42,10 +43,10 @@
|
|
|
42
43
|
|
|
43
44
|
### 没有安装 Codex
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
重新安装 DeepScientist,让随包的 Codex 依赖一起装好:
|
|
46
47
|
|
|
47
48
|
```bash
|
|
48
|
-
npm install -g @
|
|
49
|
+
npm install -g @researai/deepscientist
|
|
49
50
|
```
|
|
50
51
|
|
|
51
52
|
### 已安装 Codex,但还没有登录
|
|
@@ -58,6 +59,20 @@ codex
|
|
|
58
59
|
|
|
59
60
|
先完成一次登录,再重新执行 `ds doctor`。
|
|
60
61
|
|
|
62
|
+
### 没有安装 `uv`
|
|
63
|
+
|
|
64
|
+
正常情况下,第一次运行 `ds` 会自动在本地安装 `uv`。如果自动安装失败,再手动执行:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
如果你在 Windows PowerShell:
|
|
71
|
+
|
|
72
|
+
```powershell
|
|
73
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
74
|
+
```
|
|
75
|
+
|
|
61
76
|
### 本地论文 PDF 编译暂时不可用
|
|
62
77
|
|
|
63
78
|
如果你希望直接在 DeepScientist 里本地编译论文,可以安装一个轻量级 TinyTeX `pdflatex` 运行时:
|
|
@@ -86,6 +101,33 @@ ds --stop
|
|
|
86
101
|
|
|
87
102
|
里的 `ui.port`。
|
|
88
103
|
|
|
104
|
+
也可以直接临时换一个端口启动:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
ds --port 21000
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 当前激活的是 Python `3.10` 或更低版本
|
|
111
|
+
|
|
112
|
+
如果你已经在使用 conda,而当前环境过旧,请先激活正确环境:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
conda activate ds311
|
|
116
|
+
python3 --version
|
|
117
|
+
which python3
|
|
118
|
+
ds
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
或者新建一个可用环境:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
conda create -n ds311 python=3.11 -y
|
|
125
|
+
conda activate ds311
|
|
126
|
+
ds
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
如果你不手动切换,`ds` 也可以在 DeepScientist home 下自动准备受管的 `uv` + Python 运行时。
|
|
130
|
+
|
|
89
131
|
### Git 用户身份没有配置
|
|
90
132
|
|
|
91
133
|
运行:
|
package/install.sh
CHANGED
|
@@ -233,10 +233,8 @@ copy_source_tree() {
|
|
|
233
233
|
--exclude='./node_modules' \
|
|
234
234
|
--exclude='./ui' \
|
|
235
235
|
--exclude='./src/ui/node_modules' \
|
|
236
|
-
--exclude='./src/ui/dist' \
|
|
237
236
|
--exclude='./src/ui/lib/node_modules' \
|
|
238
237
|
--exclude='./src/tui/node_modules' \
|
|
239
|
-
--exclude='./src/tui/dist' \
|
|
240
238
|
--exclude='./src/deepscientist.egg-info' \
|
|
241
239
|
. | tar -C "$target" -xf -
|
|
242
240
|
else
|
|
@@ -252,16 +250,18 @@ prune_tree() {
|
|
|
252
250
|
"$target/node_modules" \
|
|
253
251
|
"$target/ui" \
|
|
254
252
|
"$target/src/ui/node_modules" \
|
|
255
|
-
"$target/src/ui/dist" \
|
|
256
253
|
"$target/src/ui/lib/node_modules" \
|
|
257
254
|
"$target/src/tui/node_modules" \
|
|
258
|
-
"$target/src/tui/dist" \
|
|
259
255
|
"$target/src/deepscientist.egg-info"
|
|
260
256
|
find "$target" -type d -name '__pycache__' -prune -exec rm -rf {} +
|
|
261
257
|
find "$target" -type f \( -name '*.pyc' -o -name '*.pyo' \) -delete
|
|
262
258
|
}
|
|
263
259
|
|
|
264
260
|
build_ui() {
|
|
261
|
+
if should_use_prebuilt_bundle "$1/src/ui" "$1/src/ui/dist" "index.html" "${DEEPSCIENTIST_FORCE_UI_BUILD:-}"; then
|
|
262
|
+
print_step "Using up-to-date web UI bundle from source tree"
|
|
263
|
+
return
|
|
264
|
+
fi
|
|
265
265
|
print_step "Building web UI in install tree"
|
|
266
266
|
npm --prefix "$1/src/ui" install --include=dev --no-audit --no-fund
|
|
267
267
|
npm --prefix "$1/src/ui" run build
|
|
@@ -274,12 +274,125 @@ install_root_runtime() {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
build_tui() {
|
|
277
|
+
local tui_entry=""
|
|
278
|
+
if [ -f "$1/src/tui/dist/index.js" ]; then
|
|
279
|
+
tui_entry="index.js"
|
|
280
|
+
elif [ -f "$1/src/tui/dist/index.cjs" ]; then
|
|
281
|
+
tui_entry="index.cjs"
|
|
282
|
+
elif [ -d "$1/src/tui/dist/components" ]; then
|
|
283
|
+
tui_entry="components"
|
|
284
|
+
fi
|
|
285
|
+
if [ -n "$tui_entry" ] && should_use_prebuilt_bundle "$1/src/tui" "$1/src/tui/dist" "$tui_entry" "${DEEPSCIENTIST_FORCE_TUI_BUILD:-}"; then
|
|
286
|
+
print_step "Using up-to-date TUI bundle from source tree"
|
|
287
|
+
return
|
|
288
|
+
fi
|
|
277
289
|
print_step "Building TUI in install tree"
|
|
278
290
|
npm --prefix "$1/src/tui" install --include=dev --no-audit --no-fund
|
|
279
291
|
npm --prefix "$1/src/tui" run build
|
|
280
292
|
npm --prefix "$1/src/tui" prune --omit=dev --no-audit --no-fund
|
|
281
293
|
}
|
|
282
294
|
|
|
295
|
+
truthy_env() {
|
|
296
|
+
case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in
|
|
297
|
+
1|true|yes|on)
|
|
298
|
+
return 0
|
|
299
|
+
;;
|
|
300
|
+
*)
|
|
301
|
+
return 1
|
|
302
|
+
;;
|
|
303
|
+
esac
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
should_use_prebuilt_bundle() {
|
|
307
|
+
local source_root="$1"
|
|
308
|
+
local dist_root="$2"
|
|
309
|
+
local dist_entry="$3"
|
|
310
|
+
local force_value="${4:-}"
|
|
311
|
+
|
|
312
|
+
if truthy_env "$force_value"; then
|
|
313
|
+
return 1
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
if [ ! -e "$dist_root/$dist_entry" ]; then
|
|
317
|
+
return 1
|
|
318
|
+
fi
|
|
319
|
+
|
|
320
|
+
local freshness_output=""
|
|
321
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
322
|
+
freshness_output="$(python3 - "$source_root" "$dist_root" <<'PY'
|
|
323
|
+
from pathlib import Path
|
|
324
|
+
import sys
|
|
325
|
+
|
|
326
|
+
source_root = Path(sys.argv[1])
|
|
327
|
+
dist_root = Path(sys.argv[2])
|
|
328
|
+
ignore_names = {"dist", "node_modules", ".git", "__pycache__"}
|
|
329
|
+
|
|
330
|
+
if not source_root.exists() or not dist_root.exists():
|
|
331
|
+
print("stale")
|
|
332
|
+
raise SystemExit(0)
|
|
333
|
+
|
|
334
|
+
def iter_files(root: Path):
|
|
335
|
+
for path in root.rglob("*"):
|
|
336
|
+
if not path.is_file():
|
|
337
|
+
continue
|
|
338
|
+
if any(part in ignore_names for part in path.relative_to(root).parts):
|
|
339
|
+
continue
|
|
340
|
+
yield path
|
|
341
|
+
|
|
342
|
+
source_mtime = 0.0
|
|
343
|
+
for path in iter_files(source_root):
|
|
344
|
+
source_mtime = max(source_mtime, path.stat().st_mtime)
|
|
345
|
+
|
|
346
|
+
dist_mtime = 0.0
|
|
347
|
+
for path in dist_root.rglob("*"):
|
|
348
|
+
if not path.is_file():
|
|
349
|
+
continue
|
|
350
|
+
dist_mtime = max(dist_mtime, path.stat().st_mtime)
|
|
351
|
+
|
|
352
|
+
print("fresh" if dist_mtime >= source_mtime else "stale")
|
|
353
|
+
PY
|
|
354
|
+
)"
|
|
355
|
+
elif command -v python >/dev/null 2>&1; then
|
|
356
|
+
freshness_output="$(python - "$source_root" "$dist_root" <<'PY'
|
|
357
|
+
from pathlib import Path
|
|
358
|
+
import sys
|
|
359
|
+
|
|
360
|
+
source_root = Path(sys.argv[1])
|
|
361
|
+
dist_root = Path(sys.argv[2])
|
|
362
|
+
ignore_names = {"dist", "node_modules", ".git", "__pycache__"}
|
|
363
|
+
|
|
364
|
+
if not source_root.exists() or not dist_root.exists():
|
|
365
|
+
print("stale")
|
|
366
|
+
raise SystemExit(0)
|
|
367
|
+
|
|
368
|
+
def iter_files(root: Path):
|
|
369
|
+
for path in root.rglob("*"):
|
|
370
|
+
if not path.is_file():
|
|
371
|
+
continue
|
|
372
|
+
if any(part in ignore_names for part in path.relative_to(root).parts):
|
|
373
|
+
continue
|
|
374
|
+
yield path
|
|
375
|
+
|
|
376
|
+
source_mtime = 0.0
|
|
377
|
+
for path in iter_files(source_root):
|
|
378
|
+
source_mtime = max(source_mtime, path.stat().st_mtime)
|
|
379
|
+
|
|
380
|
+
dist_mtime = 0.0
|
|
381
|
+
for path in dist_root.rglob("*"):
|
|
382
|
+
if not path.is_file():
|
|
383
|
+
continue
|
|
384
|
+
dist_mtime = max(dist_mtime, path.stat().st_mtime)
|
|
385
|
+
|
|
386
|
+
print("fresh" if dist_mtime >= source_mtime else "stale")
|
|
387
|
+
PY
|
|
388
|
+
)"
|
|
389
|
+
else
|
|
390
|
+
return 1
|
|
391
|
+
fi
|
|
392
|
+
|
|
393
|
+
[ "$freshness_output" = "fresh" ]
|
|
394
|
+
}
|
|
395
|
+
|
|
283
396
|
write_install_wrappers() {
|
|
284
397
|
local target="$1"
|
|
285
398
|
mkdir -p "$target/bin"
|
|
@@ -288,6 +401,10 @@ write_install_wrappers() {
|
|
|
288
401
|
#!/usr/bin/env bash
|
|
289
402
|
set -euo pipefail
|
|
290
403
|
SCRIPT_DIR="\$(cd "\$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
|
404
|
+
HOME_DIR="\$(cd "\$SCRIPT_DIR/../.." && pwd)"
|
|
405
|
+
if [ -z "\${DEEPSCIENTIST_HOME:-}" ]; then
|
|
406
|
+
export DEEPSCIENTIST_HOME="\$HOME_DIR"
|
|
407
|
+
fi
|
|
291
408
|
NODE_BIN="\${DEEPSCIENTIST_NODE:-node}"
|
|
292
409
|
exec "\$NODE_BIN" "\$SCRIPT_DIR/ds.js" "\$@"
|
|
293
410
|
EOF
|
|
@@ -304,6 +421,9 @@ write_global_wrapper() {
|
|
|
304
421
|
cat >"$target_path" <<EOF
|
|
305
422
|
#!/usr/bin/env bash
|
|
306
423
|
set -euo pipefail
|
|
424
|
+
if [ -z "\${DEEPSCIENTIST_HOME:-}" ]; then
|
|
425
|
+
export DEEPSCIENTIST_HOME="$BASE_DIR"
|
|
426
|
+
fi
|
|
307
427
|
exec "$INSTALL_DIR/bin/$command_name" "\$@"
|
|
308
428
|
EOF
|
|
309
429
|
chmod +x "$target_path"
|
|
@@ -311,10 +431,6 @@ EOF
|
|
|
311
431
|
|
|
312
432
|
require_command node
|
|
313
433
|
require_command npm
|
|
314
|
-
if ! command -v python3 >/dev/null 2>&1 && ! command -v python >/dev/null 2>&1; then
|
|
315
|
-
echo "Python 3 is required to run DeepScientist." >&2
|
|
316
|
-
exit 1
|
|
317
|
-
fi
|
|
318
434
|
|
|
319
435
|
SOURCE_ROOT_RESOLVED="$(resolve_path "$SOURCE_ROOT")"
|
|
320
436
|
INSTALL_DIR_RESOLVED="$(resolve_path "$INSTALL_DIR")"
|
|
@@ -356,6 +472,7 @@ printf 'Run: %s\n' "$BIN_DIR/ds"
|
|
|
356
472
|
printf 'Start web workspace: %s\n' "$BIN_DIR/ds --web"
|
|
357
473
|
printf 'Default start: %s\n' "$BIN_DIR/ds"
|
|
358
474
|
printf 'When `ds` starts, it prints the local Web URL and opens it automatically when supported.\n'
|
|
475
|
+
printf 'If `uv` is missing, the first `ds` start will bootstrap a local copy automatically under the DeepScientist home.\n'
|
|
359
476
|
if [ "$WITH_TINYTEX" -eq 1 ]; then
|
|
360
477
|
print_step "Installing TinyTeX pdflatex runtime"
|
|
361
478
|
"$INSTALL_DIR/bin/ds" latex install-runtime
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@researai/deepscientist",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"description": "Local-first research operating system with a Python runtime and npm launcher",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"docs/en/",
|
|
10
10
|
"docs/zh/",
|
|
11
11
|
"install.sh",
|
|
12
|
+
"uv.lock",
|
|
12
13
|
"assets/branding/",
|
|
13
14
|
"assets/connectors/",
|
|
14
15
|
"bin/",
|
package/pyproject.toml
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version as _package_version
|
|
2
|
+
|
|
1
3
|
__all__ = ["__version__"]
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
try:
|
|
6
|
+
__version__ = _package_version("deepscientist")
|
|
7
|
+
except PackageNotFoundError: # pragma: no cover - source checkout fallback
|
|
8
|
+
__version__ = "1.5.3"
|