@researai/deepscientist 1.5.0 → 1.5.1
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/AGENTS.md +26 -0
- package/README.md +19 -179
- package/assets/connectors/lingzhu/openclaw-bridge/README.md +124 -0
- package/assets/connectors/lingzhu/openclaw-bridge/index.ts +162 -0
- package/assets/connectors/lingzhu/openclaw-bridge/openclaw.plugin.json +145 -0
- package/assets/connectors/lingzhu/openclaw-bridge/package.json +35 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/cli.ts +180 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/config.ts +196 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/debug-log.ts +111 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/events.ts +4 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/http-handler.ts +1133 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/image-cache.ts +75 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/lingzhu-tools.ts +246 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/transform.ts +541 -0
- package/assets/connectors/lingzhu/openclaw-bridge/src/types.ts +131 -0
- package/assets/connectors/lingzhu/openclaw-bridge/tsconfig.json +14 -0
- package/assets/connectors/lingzhu/openclaw.lingzhu.config.template.json +39 -0
- package/bin/ds.js +233 -53
- package/docs/en/00_QUICK_START.md +134 -0
- package/docs/en/01_SETTINGS_REFERENCE.md +1104 -0
- package/docs/en/02_START_RESEARCH_GUIDE.md +404 -0
- package/docs/en/03_QQ_CONNECTOR_GUIDE.md +325 -0
- package/docs/en/04_LINGZHU_CONNECTOR_GUIDE.md +216 -0
- package/docs/en/05_TUI_GUIDE.md +141 -0
- package/docs/en/06_RUNTIME_AND_CANVAS.md +679 -0
- package/docs/en/07_MEMORY_AND_MCP.md +253 -0
- package/docs/en/08_FIGURE_STYLE_GUIDE.md +97 -0
- package/docs/en/09_DOCTOR.md +108 -0
- package/docs/en/90_ARCHITECTURE.md +245 -0
- package/docs/en/91_DEVELOPMENT.md +195 -0
- package/docs/en/99_ACKNOWLEDGEMENTS.md +29 -0
- package/docs/zh/00_QUICK_START.md +134 -0
- package/docs/zh/01_SETTINGS_REFERENCE.md +1137 -0
- package/docs/zh/02_START_RESEARCH_GUIDE.md +414 -0
- package/docs/zh/03_QQ_CONNECTOR_GUIDE.md +324 -0
- package/docs/zh/04_LINGZHU_CONNECTOR_GUIDE.md +230 -0
- package/docs/zh/05_TUI_GUIDE.md +128 -0
- package/docs/zh/06_RUNTIME_AND_CANVAS.md +271 -0
- package/docs/zh/07_MEMORY_AND_MCP.md +235 -0
- package/docs/zh/08_FIGURE_STYLE_GUIDE.md +97 -0
- package/docs/zh/09_DOCTOR.md +112 -0
- package/docs/zh/99_ACKNOWLEDGEMENTS.md +29 -0
- package/install.sh +32 -8
- package/package.json +4 -2
- package/pyproject.toml +1 -1
- package/src/deepscientist/artifact/guidance.py +9 -2
- package/src/deepscientist/artifact/service.py +482 -22
- package/src/deepscientist/bash_exec/monitor.py +27 -5
- package/src/deepscientist/bash_exec/runtime.py +639 -0
- package/src/deepscientist/bash_exec/service.py +99 -16
- package/src/deepscientist/bridges/base.py +3 -0
- package/src/deepscientist/bridges/connectors.py +292 -13
- package/src/deepscientist/channels/qq.py +19 -2
- package/src/deepscientist/channels/relay.py +1 -0
- package/src/deepscientist/cli.py +32 -25
- package/src/deepscientist/config/models.py +28 -2
- package/src/deepscientist/config/service.py +201 -6
- package/src/deepscientist/connector_runtime.py +2 -0
- package/src/deepscientist/daemon/api/handlers.py +50 -5
- package/src/deepscientist/daemon/api/router.py +1 -0
- package/src/deepscientist/daemon/app.py +442 -15
- package/src/deepscientist/doctor.py +444 -0
- package/src/deepscientist/home.py +1 -0
- package/src/deepscientist/latex_runtime.py +17 -4
- package/src/deepscientist/lingzhu_support.py +182 -0
- package/src/deepscientist/mcp/server.py +49 -2
- package/src/deepscientist/prompts/builder.py +181 -58
- package/src/deepscientist/quest/layout.py +1 -0
- package/src/deepscientist/quest/service.py +63 -2
- package/src/deepscientist/quest/stage_views.py +19 -1
- package/src/deepscientist/runtime_tools/__init__.py +16 -0
- package/src/deepscientist/runtime_tools/builtins.py +19 -0
- package/src/deepscientist/runtime_tools/models.py +29 -0
- package/src/deepscientist/runtime_tools/registry.py +40 -0
- package/src/deepscientist/runtime_tools/service.py +59 -0
- package/src/deepscientist/runtime_tools/tinytex.py +25 -0
- package/src/deepscientist/tinytex.py +276 -0
- package/src/prompts/connectors/lingzhu.md +12 -0
- package/src/prompts/connectors/qq.md +121 -0
- package/src/prompts/system.md +177 -33
- package/src/skills/analysis-campaign/SKILL.md +22 -6
- package/src/skills/baseline/SKILL.md +5 -4
- package/src/skills/decision/SKILL.md +4 -3
- package/src/skills/experiment/SKILL.md +5 -4
- package/src/skills/finalize/SKILL.md +5 -4
- package/src/skills/idea/SKILL.md +5 -4
- package/src/skills/intake-audit/SKILL.md +277 -0
- package/src/skills/intake-audit/references/state-audit-template.md +41 -0
- package/src/skills/rebuttal/SKILL.md +407 -0
- package/src/skills/rebuttal/references/action-plan-template.md +63 -0
- package/src/skills/rebuttal/references/evidence-update-template.md +30 -0
- package/src/skills/rebuttal/references/response-letter-template.md +113 -0
- package/src/skills/rebuttal/references/review-matrix-template.md +55 -0
- package/src/skills/review/SKILL.md +293 -0
- package/src/skills/review/references/experiment-todo-template.md +29 -0
- package/src/skills/review/references/review-report-template.md +83 -0
- package/src/skills/review/references/revision-log-template.md +40 -0
- package/src/skills/scout/SKILL.md +5 -4
- package/src/skills/write/SKILL.md +7 -3
- package/src/tui/dist/components/WelcomePanel.js +17 -43
- package/src/tui/dist/components/messages/BashExecOperationMessage.js +3 -2
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/{AiManusChatView-7v-dHngU.js → AiManusChatView-w5lF2Ttt.js} +109 -575
- package/src/ui/dist/assets/{AnalysisPlugin-B_Xmz-KE.js → AnalysisPlugin-DJOED79I.js} +1 -1
- package/src/ui/dist/assets/{AutoFigurePlugin-Cko-0tm1.js → AutoFigurePlugin-DaG61Y0M.js} +63 -8
- package/src/ui/dist/assets/{CliPlugin-BsU0ht7q.js → CliPlugin-CV4LqUB_.js} +43 -609
- package/src/ui/dist/assets/{CodeEditorPlugin-DcMMP0Rt.js → CodeEditorPlugin-DylfAea4.js} +8 -8
- package/src/ui/dist/assets/{CodeViewerPlugin-BqoQ5QyY.js → CodeViewerPlugin-F7saY0LM.js} +5 -5
- package/src/ui/dist/assets/{DocViewerPlugin-D7eHNhU6.js → DocViewerPlugin-COP0c7jf.js} +3 -3
- package/src/ui/dist/assets/{GitDiffViewerPlugin-DLJN42T5.js → GitDiffViewerPlugin-CAS05pT9.js} +1 -1
- package/src/ui/dist/assets/{ImageViewerPlugin-gJMV7MOu.js → ImageViewerPlugin-Bco1CN_w.js} +5 -6
- package/src/ui/dist/assets/{LabCopilotPanel-B857sfxP.js → LabCopilotPanel-CvMlCD99.js} +12 -15
- package/src/ui/dist/assets/LabPlugin-BYankkE4.js +2676 -0
- package/src/ui/dist/assets/LabPlugin-D9jVIo0A.css +2698 -0
- package/src/ui/dist/assets/{LatexPlugin-DWKEo-Wj.js → LatexPlugin-LDSMR-t-.js} +16 -16
- package/src/ui/dist/assets/{MarkdownViewerPlugin-DBzoEmhv.js → MarkdownViewerPlugin-B7o80jgm.js} +4 -4
- package/src/ui/dist/assets/{MarketplacePlugin-DoHc-8vo.js → MarketplacePlugin-CM6ZOcpC.js} +3 -3
- package/src/ui/dist/assets/{NotebookEditor-CKjKH-yS.js → NotebookEditor-Dc61cXmK.js} +3 -3
- package/src/ui/dist/assets/{PdfLoader-zFoL0VPo.js → PdfLoader-DWowuQwx.js} +1 -1
- package/src/ui/dist/assets/{PdfMarkdownPlugin-DXPaL9Nt.js → PdfMarkdownPlugin-BsJM1q_a.js} +3 -3
- package/src/ui/dist/assets/{PdfViewerPlugin-DhK8qCFp.js → PdfViewerPlugin-DB2eEEFQ.js} +10 -10
- package/src/ui/dist/assets/{SearchPlugin-CdSi6krf.js → SearchPlugin-CraThSvt.js} +1 -1
- package/src/ui/dist/assets/{Stepper-V-WiDQJl.js → Stepper-CgocRTPq.js} +1 -1
- package/src/ui/dist/assets/{TextViewerPlugin-hIs1Efiu.js → TextViewerPlugin-B1JGhKtd.js} +4 -4
- package/src/ui/dist/assets/{VNCViewer-DG8b0q2X.js → VNCViewer-CclFC7FM.js} +9 -10
- package/src/ui/dist/assets/{bibtex-HDac6fVW.js → bibtex-D3IKsMl7.js} +1 -1
- package/src/ui/dist/assets/{code-BnBeNxBc.js → code-BP37Xx0p.js} +1 -1
- package/src/ui/dist/assets/{file-content-IRQ3jHb8.js → file-content-BAJSu-9r.js} +1 -1
- package/src/ui/dist/assets/{file-diff-panel-DZoQ9I6r.js → file-diff-panel-DUGeCTuy.js} +1 -1
- package/src/ui/dist/assets/{file-socket-BMCdLc-P.js → file-socket-CXc1Ojf7.js} +1 -1
- package/src/ui/dist/assets/{file-utils-CltILB3w.js → file-utils-2J21jt7M.js} +1 -1
- package/src/ui/dist/assets/{image-Boe6ffhu.js → image-CMMmgvcn.js} +1 -1
- package/src/ui/dist/assets/{index-BlplpvE1.js → index-BaVumsQT.js} +2 -2
- package/src/ui/dist/assets/{index-DZqJ-qAM.js → index-CWgMgpow.js} +60 -2154
- package/src/ui/dist/assets/{index-DO43pFZP.js → index-DmwmJmbW.js} +6372 -8434
- package/src/ui/dist/assets/{index-Bq2bvfkl.css → index-KGt-z-dD.css} +225 -2920
- package/src/ui/dist/assets/{index-2Zf65FZt.js → index-s7aHnNQ4.js} +1 -1
- package/src/ui/dist/assets/{message-square-mUHn_Ssb.js → message-square-CQRfX0Am.js} +1 -1
- package/src/ui/dist/assets/{monaco-fe0arNEU.js → monaco-B4TbdsrF.js} +1 -1
- package/src/ui/dist/assets/{popover-D_7i19qU.js → popover-B8Rokodk.js} +1 -1
- package/src/ui/dist/assets/{project-sync-DyVGrU7H.js → project-sync-D_i96KH4.js} +2 -8
- package/src/ui/dist/assets/{sigma-BzazRyxQ.js → sigma-D12PnzCN.js} +1 -1
- package/src/ui/dist/assets/{tooltip-DN_yjHFH.js → tooltip-B6YrI4aJ.js} +1 -1
- package/src/ui/dist/assets/trash-Bc8jGp0V.js +32 -0
- package/src/ui/dist/assets/{useCliAccess-DV2L2Qxy.js → useCliAccess-mXVCYSZ-.js} +12 -42
- package/src/ui/dist/assets/{useFileDiffOverlay-DyTj-p_V.js → useFileDiffOverlay-Bg6b9H9K.js} +1 -1
- package/src/ui/dist/assets/{wrap-text-ozYHtUwq.js → wrap-text-Drh5GEnL.js} +1 -1
- package/src/ui/dist/assets/{zoom-out-BN9MUyCQ.js → zoom-out-CJj9DZLn.js} +1 -1
- package/src/ui/dist/index.html +2 -2
- package/assets/fonts/Inter-Variable.ttf +0 -0
- package/assets/fonts/NotoSerifSC-Regular-C94HN_ZN.ttf +0 -0
- package/assets/fonts/NunitoSans-Variable.ttf +0 -0
- package/assets/fonts/Satoshi-Medium-ByP-Zb-9.woff2 +0 -0
- package/assets/fonts/SourceSans3-Variable.ttf +0 -0
- package/assets/fonts/ds-fonts.css +0 -83
- package/src/ui/dist/assets/Inter-Variable-VF2RPR_K.ttf +0 -0
- package/src/ui/dist/assets/LabPlugin-bL7rpic8.js +0 -43
- package/src/ui/dist/assets/NotoSerifSC-Regular-C94HN_ZN-C94HN_ZN.ttf +0 -0
- package/src/ui/dist/assets/NunitoSans-Variable-B_ZymHAd.ttf +0 -0
- package/src/ui/dist/assets/Satoshi-Medium-ByP-Zb-9-GkA34YXu.woff2 +0 -0
- package/src/ui/dist/assets/SourceSans3-Variable-CD-WOsSK.ttf +0 -0
- package/src/ui/dist/assets/info-CcsK_htA.js +0 -18
- package/src/ui/dist/assets/user-plus-BusDx-hF.js +0 -79
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"gateway": {
|
|
3
|
+
"port": 18789,
|
|
4
|
+
"http": {
|
|
5
|
+
"endpoints": {
|
|
6
|
+
"chatCompletions": {
|
|
7
|
+
"enabled": true
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"plugins": {
|
|
13
|
+
"entries": {
|
|
14
|
+
"lingzhu": {
|
|
15
|
+
"enabled": true,
|
|
16
|
+
"config": {
|
|
17
|
+
"authAk": "",
|
|
18
|
+
"agentId": "main",
|
|
19
|
+
"includeMetadata": true,
|
|
20
|
+
"requestTimeoutMs": 60000,
|
|
21
|
+
"systemPrompt": "",
|
|
22
|
+
"defaultNavigationMode": "0",
|
|
23
|
+
"enableFollowUp": true,
|
|
24
|
+
"followUpMaxCount": 3,
|
|
25
|
+
"maxImageBytes": 5242880,
|
|
26
|
+
"sessionMode": "per_user",
|
|
27
|
+
"sessionNamespace": "lingzhu",
|
|
28
|
+
"autoReceiptAck": true,
|
|
29
|
+
"visibleProgressHeartbeat": true,
|
|
30
|
+
"visibleProgressHeartbeatSec": 10,
|
|
31
|
+
"debugLogging": false,
|
|
32
|
+
"debugLogPayloads": false,
|
|
33
|
+
"debugLogDir": "",
|
|
34
|
+
"enableExperimentalNativeActions": false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
package/bin/ds.js
CHANGED
|
@@ -21,10 +21,12 @@ const pythonCommands = new Set([
|
|
|
21
21
|
'note',
|
|
22
22
|
'approve',
|
|
23
23
|
'graph',
|
|
24
|
-
'
|
|
24
|
+
'doctor',
|
|
25
|
+
'docker',
|
|
25
26
|
'push',
|
|
26
27
|
'memory',
|
|
27
28
|
'baseline',
|
|
29
|
+
'latex',
|
|
28
30
|
'config',
|
|
29
31
|
]);
|
|
30
32
|
|
|
@@ -34,17 +36,21 @@ function printLauncherHelp() {
|
|
|
34
36
|
console.log(`DeepScientist launcher
|
|
35
37
|
|
|
36
38
|
Usage:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
ds
|
|
40
|
+
ds --tui
|
|
41
|
+
ds --both
|
|
42
|
+
ds --stop
|
|
43
|
+
ds --restart
|
|
44
|
+
ds doctor
|
|
45
|
+
ds latex status
|
|
46
|
+
ds --home ~/DeepScientist --port 20999
|
|
43
47
|
|
|
44
48
|
Advanced Python CLI:
|
|
45
49
|
ds init
|
|
46
|
-
ds new "reproduce baseline and test idea"
|
|
47
|
-
ds
|
|
50
|
+
ds new "reproduce baseline and test one stronger idea"
|
|
51
|
+
ds doctor
|
|
52
|
+
ds latex install-runtime
|
|
53
|
+
ds run decision --quest-id 001 --message "review current state"
|
|
48
54
|
`);
|
|
49
55
|
}
|
|
50
56
|
|
|
@@ -88,6 +94,146 @@ function bindUiUrl(host, port) {
|
|
|
88
94
|
return `http://${formatHttpHost(normalized)}:${port}`;
|
|
89
95
|
}
|
|
90
96
|
|
|
97
|
+
function normalizeMode(value) {
|
|
98
|
+
const normalized = String(value || '')
|
|
99
|
+
.trim()
|
|
100
|
+
.toLowerCase();
|
|
101
|
+
if (normalized === 'tui' || normalized === 'both' || normalized === 'web') {
|
|
102
|
+
return normalized;
|
|
103
|
+
}
|
|
104
|
+
return 'web';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function parseBooleanSetting(rawValue, fallback = false) {
|
|
108
|
+
if (typeof rawValue === 'boolean') {
|
|
109
|
+
return rawValue;
|
|
110
|
+
}
|
|
111
|
+
const normalized = String(rawValue || '')
|
|
112
|
+
.trim()
|
|
113
|
+
.toLowerCase();
|
|
114
|
+
if (['true', 'yes', 'on', '1'].includes(normalized)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
if (['false', 'no', 'off', '0'].includes(normalized)) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return fallback;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function supportsAnsi() {
|
|
124
|
+
return Boolean(process.stdout.isTTY && process.env.TERM !== 'dumb');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function stripAnsi(text) {
|
|
128
|
+
return String(text || '')
|
|
129
|
+
.replace(/\u001B]8;;[^\u0007]*\u0007/g, '')
|
|
130
|
+
.replace(/\u001B]8;;\u0007/g, '')
|
|
131
|
+
.replace(/\u001B\[[0-9;]*m/g, '');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function visibleWidth(text) {
|
|
135
|
+
return stripAnsi(text).length;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function centerText(text, width) {
|
|
139
|
+
const targetWidth = Math.max(visibleWidth(text), width || 0);
|
|
140
|
+
const padding = Math.max(0, Math.floor((targetWidth - visibleWidth(text)) / 2));
|
|
141
|
+
return `${' '.repeat(padding)}${text}`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function hyperlink(url, label = url) {
|
|
145
|
+
if (!supportsAnsi()) {
|
|
146
|
+
return label;
|
|
147
|
+
}
|
|
148
|
+
return `\u001B]8;;${url}\u0007${label}\u001B]8;;\u0007`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function colorize(code, text) {
|
|
152
|
+
if (!supportsAnsi()) {
|
|
153
|
+
return text;
|
|
154
|
+
}
|
|
155
|
+
return `${code}${text}\u001B[0m`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function renderBrandArtwork() {
|
|
159
|
+
const brandPath = path.join(repoRoot, 'assets', 'branding', 'deepscientist-mark.png');
|
|
160
|
+
const chafa = resolveExecutableOnPath('chafa');
|
|
161
|
+
if (!supportsAnsi() || !chafa || !fs.existsSync(brandPath)) {
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
const width = Math.max(18, Math.min(30, Math.floor((process.stdout.columns || 100) / 3)));
|
|
165
|
+
const height = Math.max(8, Math.floor(width / 2));
|
|
166
|
+
try {
|
|
167
|
+
const result = spawnSync(
|
|
168
|
+
chafa,
|
|
169
|
+
['--size', `${width}x${height}`, '--format', 'symbols', '--colors', '16', brandPath],
|
|
170
|
+
{ encoding: 'utf8' }
|
|
171
|
+
);
|
|
172
|
+
if (result.status === 0 && result.stdout && result.stdout.trim()) {
|
|
173
|
+
return result.stdout.replace(/\s+$/, '').split(/\r?\n/);
|
|
174
|
+
}
|
|
175
|
+
} catch {}
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function printLaunchCard({ url, bindUrl, mode, autoOpenRequested, browserOpened, daemonOnly }) {
|
|
180
|
+
const width = Math.max(72, Math.min(process.stdout.columns || 100, 108));
|
|
181
|
+
const divider = colorize('\u001B[38;5;245m', '─'.repeat(Math.max(36, width - 6)));
|
|
182
|
+
const title = colorize('\u001B[1;38;5;39m', 'ResearAI');
|
|
183
|
+
const subtitle = colorize('\u001B[38;5;110m', 'Local-first research operating system');
|
|
184
|
+
const urlLabel = colorize('\u001B[1;38;5;45m', hyperlink(url, url));
|
|
185
|
+
const workspaceMode =
|
|
186
|
+
mode === 'both'
|
|
187
|
+
? 'Web workspace + terminal workspace'
|
|
188
|
+
: mode === 'tui'
|
|
189
|
+
? 'Terminal workspace'
|
|
190
|
+
: 'Web workspace';
|
|
191
|
+
const browserLine = autoOpenRequested
|
|
192
|
+
? browserOpened
|
|
193
|
+
? 'Browser launch requested successfully.'
|
|
194
|
+
: 'Browser auto-open was requested but is not available in this terminal session.'
|
|
195
|
+
: 'Browser auto-open is disabled. Open the URL manually if needed.';
|
|
196
|
+
const nextStep = daemonOnly
|
|
197
|
+
? 'Use ds --tui to enter the terminal workspace.'
|
|
198
|
+
: mode === 'web'
|
|
199
|
+
? 'Use ds --tui to enter the terminal workspace.'
|
|
200
|
+
: mode === 'both'
|
|
201
|
+
? 'The terminal workspace starts below.'
|
|
202
|
+
: 'Use Ctrl+O inside TUI to reopen the web workspace.';
|
|
203
|
+
|
|
204
|
+
console.log('');
|
|
205
|
+
const artwork = renderBrandArtwork();
|
|
206
|
+
for (const line of artwork) {
|
|
207
|
+
console.log(centerText(line, width));
|
|
208
|
+
}
|
|
209
|
+
if (artwork.length === 0) {
|
|
210
|
+
console.log(centerText(colorize('\u001B[1;38;5;39m', '⛰'), width));
|
|
211
|
+
}
|
|
212
|
+
const wordmark = [
|
|
213
|
+
' ____ ____ _ _ _ _ ',
|
|
214
|
+
' | _ \\ ___ ___ _ __ / ___| ___(_) ___ _ __ | |_(_)___| |_ ',
|
|
215
|
+
" | | | |/ _ \\/ _ \\ '_ \\\\___ \\ / __| |/ _ \\ '_ \\| __| / __| __|",
|
|
216
|
+
' | |_| | __/ __/ |_) |___) | (__| | __/ | | | |_| \\__ \\ |_ ',
|
|
217
|
+
' |____/ \\___|\\___| .__/|____/ \\___|_|\\___|_| |_|\\__|_|___/\\__|',
|
|
218
|
+
' |_| ',
|
|
219
|
+
];
|
|
220
|
+
console.log(centerText(title, width));
|
|
221
|
+
for (const line of wordmark) {
|
|
222
|
+
console.log(centerText(colorize('\u001B[1;38;5;39m', line), width));
|
|
223
|
+
}
|
|
224
|
+
console.log(centerText(subtitle, width));
|
|
225
|
+
console.log('');
|
|
226
|
+
console.log(centerText(divider, width));
|
|
227
|
+
console.log(centerText(colorize('\u001B[1m', workspaceMode), width));
|
|
228
|
+
console.log(centerText(urlLabel, width));
|
|
229
|
+
console.log(centerText(divider, width));
|
|
230
|
+
console.log(centerText(browserLine, width));
|
|
231
|
+
console.log(centerText(`Daemon bind: ${bindUrl}`, width));
|
|
232
|
+
console.log(centerText(nextStep, width));
|
|
233
|
+
console.log(centerText('Run ds --stop to stop the managed daemon.', width));
|
|
234
|
+
console.log('');
|
|
235
|
+
}
|
|
236
|
+
|
|
91
237
|
function escapeHtml(value) {
|
|
92
238
|
return String(value ?? '')
|
|
93
239
|
.replaceAll('&', '&')
|
|
@@ -274,13 +420,13 @@ function createCodexPreflightError(home, probe) {
|
|
|
274
420
|
|
|
275
421
|
function parseLauncherArgs(argv) {
|
|
276
422
|
const args = [...argv];
|
|
277
|
-
let mode =
|
|
423
|
+
let mode = null;
|
|
278
424
|
let host = null;
|
|
279
425
|
let port = null;
|
|
280
426
|
let home = null;
|
|
281
427
|
let stop = false;
|
|
282
428
|
let restart = false;
|
|
283
|
-
let openBrowser =
|
|
429
|
+
let openBrowser = null;
|
|
284
430
|
let questId = null;
|
|
285
431
|
let status = false;
|
|
286
432
|
let daemonOnly = false;
|
|
@@ -305,7 +451,7 @@ function parseLauncherArgs(argv) {
|
|
|
305
451
|
else if (arg === '--port' && args[index + 1]) port = Number(args[++index]);
|
|
306
452
|
else if (arg === '--home' && args[index + 1]) home = path.resolve(args[++index]);
|
|
307
453
|
else if (arg === '--quest-id' && args[index + 1]) questId = args[++index];
|
|
308
|
-
else if (arg === '--mode' && args[index + 1]) mode = args[++index];
|
|
454
|
+
else if (arg === '--mode' && args[index + 1]) mode = normalizeMode(args[++index]);
|
|
309
455
|
else if (arg === '--help' || arg === '-h') return { help: true };
|
|
310
456
|
else if (!arg.startsWith('--')) return null;
|
|
311
457
|
}
|
|
@@ -962,30 +1108,53 @@ async function readConfiguredUiAddress(home, venvPython, fallbackHost, fallbackP
|
|
|
962
1108
|
const text = result.stdout || '';
|
|
963
1109
|
const hostMatch = text.match(/^\s*host:\s*["']?([^"'\n]+)["']?\s*$/m);
|
|
964
1110
|
const portMatch = text.match(/^\s*port:\s*(\d+)\s*$/m);
|
|
1111
|
+
const modeMatch = text.match(/^\s*default_mode:\s*["']?([^"'\n]+)["']?\s*$/m);
|
|
1112
|
+
const autoOpenMatch = text.match(/^\s*auto_open_browser:\s*([^\n]+)\s*$/m);
|
|
965
1113
|
return {
|
|
966
1114
|
host: fallbackHost || (hostMatch ? hostMatch[1].trim() : '0.0.0.0'),
|
|
967
1115
|
port: fallbackPort || (portMatch ? Number(portMatch[1]) : 20999),
|
|
1116
|
+
defaultMode: normalizeMode(modeMatch ? modeMatch[1].trim() : 'web'),
|
|
1117
|
+
autoOpenBrowser: parseBooleanSetting(autoOpenMatch ? autoOpenMatch[1].trim() : true, true),
|
|
968
1118
|
};
|
|
969
1119
|
} catch {
|
|
970
|
-
return {
|
|
1120
|
+
return {
|
|
1121
|
+
host: fallbackHost || '0.0.0.0',
|
|
1122
|
+
port: fallbackPort || 20999,
|
|
1123
|
+
defaultMode: 'web',
|
|
1124
|
+
autoOpenBrowser: true,
|
|
1125
|
+
};
|
|
971
1126
|
}
|
|
972
1127
|
}
|
|
973
1128
|
|
|
974
1129
|
function readConfiguredUiAddressFromFile(home, fallbackHost, fallbackPort) {
|
|
975
1130
|
const configPath = path.join(home, 'config', 'config.yaml');
|
|
976
1131
|
if (!fs.existsSync(configPath)) {
|
|
977
|
-
return {
|
|
1132
|
+
return {
|
|
1133
|
+
host: fallbackHost || '0.0.0.0',
|
|
1134
|
+
port: fallbackPort || 20999,
|
|
1135
|
+
defaultMode: 'web',
|
|
1136
|
+
autoOpenBrowser: true,
|
|
1137
|
+
};
|
|
978
1138
|
}
|
|
979
1139
|
try {
|
|
980
1140
|
const text = fs.readFileSync(configPath, 'utf8');
|
|
981
1141
|
const hostMatch = text.match(/^\s*host:\s*["']?([^"'\n]+)["']?\s*$/m);
|
|
982
1142
|
const portMatch = text.match(/^\s*port:\s*(\d+)\s*$/m);
|
|
1143
|
+
const modeMatch = text.match(/^\s*default_mode:\s*["']?([^"'\n]+)["']?\s*$/m);
|
|
1144
|
+
const autoOpenMatch = text.match(/^\s*auto_open_browser:\s*([^\n]+)\s*$/m);
|
|
983
1145
|
return {
|
|
984
1146
|
host: fallbackHost || (hostMatch ? hostMatch[1].trim() : '0.0.0.0'),
|
|
985
1147
|
port: fallbackPort || (portMatch ? Number(portMatch[1]) : 20999),
|
|
1148
|
+
defaultMode: normalizeMode(modeMatch ? modeMatch[1].trim() : 'web'),
|
|
1149
|
+
autoOpenBrowser: parseBooleanSetting(autoOpenMatch ? autoOpenMatch[1].trim() : true, true),
|
|
986
1150
|
};
|
|
987
1151
|
} catch {
|
|
988
|
-
return {
|
|
1152
|
+
return {
|
|
1153
|
+
host: fallbackHost || '0.0.0.0',
|
|
1154
|
+
port: fallbackPort || 20999,
|
|
1155
|
+
defaultMode: 'web',
|
|
1156
|
+
autoOpenBrowser: true,
|
|
1157
|
+
};
|
|
989
1158
|
}
|
|
990
1159
|
}
|
|
991
1160
|
|
|
@@ -1080,38 +1249,42 @@ async function startDaemon(home, venvPython, host, port) {
|
|
|
1080
1249
|
}
|
|
1081
1250
|
|
|
1082
1251
|
function openBrowser(url) {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
const child = spawn(
|
|
1086
|
-
child.on('error', () => {
|
|
1087
|
-
console.log(`Open this URL in your browser: ${url}`);
|
|
1088
|
-
});
|
|
1252
|
+
const spawnDetached = (command, args) => {
|
|
1253
|
+
try {
|
|
1254
|
+
const child = spawn(command, args, { detached: true, stdio: 'ignore' });
|
|
1089
1255
|
child.unref();
|
|
1090
1256
|
return true;
|
|
1257
|
+
} catch {
|
|
1258
|
+
return false;
|
|
1091
1259
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1260
|
+
};
|
|
1261
|
+
|
|
1262
|
+
if (process.platform === 'darwin') {
|
|
1263
|
+
const opener = resolveExecutableOnPath('open');
|
|
1264
|
+
return opener ? spawnDetached(opener, [url]) : false;
|
|
1265
|
+
}
|
|
1266
|
+
if (process.platform === 'win32') {
|
|
1267
|
+
return spawnDetached('cmd', ['/c', 'start', '', url]);
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
const commands = [
|
|
1271
|
+
{ command: 'xdg-open', args: [url] },
|
|
1272
|
+
{ command: 'gio', args: ['open', url] },
|
|
1273
|
+
{ command: 'sensible-browser', args: [url] },
|
|
1274
|
+
{ command: 'gnome-open', args: [url] },
|
|
1275
|
+
{ command: 'kde-open', args: [url] },
|
|
1276
|
+
{ command: 'kde-open5', args: [url] },
|
|
1277
|
+
];
|
|
1278
|
+
for (const candidate of commands) {
|
|
1279
|
+
const resolved = resolveExecutableOnPath(candidate.command);
|
|
1280
|
+
if (!resolved) {
|
|
1281
|
+
continue;
|
|
1099
1282
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
console.log(`Open this URL in your browser: ${url}`);
|
|
1103
|
-
return false;
|
|
1283
|
+
if (spawnDetached(resolved, candidate.args)) {
|
|
1284
|
+
return true;
|
|
1104
1285
|
}
|
|
1105
|
-
const child = spawn('xdg-open', [url], { detached: true, stdio: 'ignore' });
|
|
1106
|
-
child.on('error', () => {
|
|
1107
|
-
console.log(`Open this URL in your browser: ${url}`);
|
|
1108
|
-
});
|
|
1109
|
-
child.unref();
|
|
1110
|
-
return true;
|
|
1111
|
-
} catch {
|
|
1112
|
-
console.log(`Open this URL in your browser: ${url}`);
|
|
1113
|
-
return false;
|
|
1114
1286
|
}
|
|
1287
|
+
return false;
|
|
1115
1288
|
}
|
|
1116
1289
|
|
|
1117
1290
|
function handleCodexPreflightFailure(error) {
|
|
@@ -1199,7 +1372,15 @@ async function launcherMain(rawArgs) {
|
|
|
1199
1372
|
ensureInitialized(home, venvPython);
|
|
1200
1373
|
maybePrintOptionalLatexNotice(home);
|
|
1201
1374
|
|
|
1202
|
-
const
|
|
1375
|
+
const configuredUi = await readConfiguredUiAddress(home, venvPython, options.host, options.port);
|
|
1376
|
+
const host = configuredUi.host;
|
|
1377
|
+
const port = configuredUi.port;
|
|
1378
|
+
const mode = normalizeMode(options.mode ?? 'web');
|
|
1379
|
+
const shouldOpenBrowser = options.daemonOnly
|
|
1380
|
+
? false
|
|
1381
|
+
: options.openBrowser === null
|
|
1382
|
+
? configuredUi.autoOpenBrowser !== false && mode !== 'tui'
|
|
1383
|
+
: options.openBrowser;
|
|
1203
1384
|
if (options.restart) {
|
|
1204
1385
|
await stopDaemon(home);
|
|
1205
1386
|
}
|
|
@@ -1212,21 +1393,20 @@ async function launcherMain(rawArgs) {
|
|
|
1212
1393
|
if (handleCodexPreflightFailure(error)) return true;
|
|
1213
1394
|
throw error;
|
|
1214
1395
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1396
|
+
const browserOpened = shouldOpenBrowser ? openBrowser(started.url) : false;
|
|
1397
|
+
printLaunchCard({
|
|
1398
|
+
url: started.url,
|
|
1399
|
+
bindUrl: started.bindUrl,
|
|
1400
|
+
mode,
|
|
1401
|
+
autoOpenRequested: shouldOpenBrowser,
|
|
1402
|
+
browserOpened,
|
|
1403
|
+
daemonOnly: options.daemonOnly,
|
|
1404
|
+
});
|
|
1222
1405
|
|
|
1223
|
-
if (options.mode === 'web' || options.mode === 'both' || options.openBrowser) {
|
|
1224
|
-
openBrowser(started.url);
|
|
1225
|
-
}
|
|
1226
1406
|
if (options.daemonOnly) {
|
|
1227
1407
|
process.exit(0);
|
|
1228
1408
|
}
|
|
1229
|
-
if (
|
|
1409
|
+
if (mode === 'web') {
|
|
1230
1410
|
process.exit(0);
|
|
1231
1411
|
}
|
|
1232
1412
|
launchTui(started.url, options.questId, home, venvPython);
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# 00 Quick Start: Launch DeepScientist and Run Your First Quest
|
|
2
|
+
|
|
3
|
+
This is the fastest way to go from installation to a running quest.
|
|
4
|
+
|
|
5
|
+
You will do four things:
|
|
6
|
+
|
|
7
|
+
1. install DeepScientist
|
|
8
|
+
2. start the local runtime
|
|
9
|
+
3. create a new quest from the home page
|
|
10
|
+
4. reopen old quests from the quest list
|
|
11
|
+
|
|
12
|
+
The screenshots in this guide use the current live web UI at `deepscientist.cc:20999` as an example. Your local UI at `127.0.0.1:20999` should look the same or very close.
|
|
13
|
+
|
|
14
|
+
## 1. Install
|
|
15
|
+
|
|
16
|
+
Install Codex and DeepScientist globally:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @openai/codex @researai/deepscientist
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If you plan to compile LaTeX locally later, you can also install the lightweight PDF runtime:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
ds latex install-runtime
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 2. Start DeepScientist
|
|
29
|
+
|
|
30
|
+
Start the local daemon and web workspace:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
ds
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
By default, the web UI is served at:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
http://127.0.0.1:20999
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
If the browser does not open automatically, paste that address into your browser manually.
|
|
43
|
+
|
|
44
|
+
## 3. Understand the Home Page
|
|
45
|
+
|
|
46
|
+
When DeepScientist starts, open the home page at `/`.
|
|
47
|
+
|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
The home page is intentionally simple. The two main entry buttons are:
|
|
51
|
+
|
|
52
|
+
- `Start Research`: create a new quest and launch a new research run
|
|
53
|
+
- `List Quest`: reopen an existing quest
|
|
54
|
+
|
|
55
|
+
If you are using DeepScientist for the first time, start with `Start Research`.
|
|
56
|
+
|
|
57
|
+
## 4. Create a New Quest With Start Research
|
|
58
|
+
|
|
59
|
+
Click `Start Research` to open the launch dialog.
|
|
60
|
+
|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
This dialog creates a new quest repository and writes the startup contract for the agent.
|
|
64
|
+
|
|
65
|
+
The most important fields are:
|
|
66
|
+
|
|
67
|
+
- `Quest ID`: usually auto-generated in sequence such as `00`, `01`, `02`
|
|
68
|
+
- `Primary request` / research goal: the actual scientific task you want the agent to work on
|
|
69
|
+
- `Reuse Baseline`: optional; choose an existing baseline if you want to continue from an earlier result
|
|
70
|
+
- `Research intensity`: how aggressive the run should be
|
|
71
|
+
- `Decision mode`: `Autonomous` means the agent should keep going by itself unless a true approval is needed
|
|
72
|
+
- `Research paper`: choose whether the run should also aim to produce paper-style output
|
|
73
|
+
- `Language`: choose the user-facing language for the run
|
|
74
|
+
|
|
75
|
+
For a first test, keep it simple:
|
|
76
|
+
|
|
77
|
+
- write one clear research question
|
|
78
|
+
- leave baseline empty unless you already have one
|
|
79
|
+
- use `Balanced` or `Sprint`
|
|
80
|
+
- keep decision mode on `Autonomous`
|
|
81
|
+
|
|
82
|
+
Then click the final `Start Research` action in the dialog.
|
|
83
|
+
|
|
84
|
+
## 5. Reopen an Existing Quest With List Quest
|
|
85
|
+
|
|
86
|
+
Click `List Quest` on the home page to open the existing quest list.
|
|
87
|
+
|
|
88
|
+

|
|
89
|
+
|
|
90
|
+
Use this dialog when you want to:
|
|
91
|
+
|
|
92
|
+
- reopen a quest that is already running or already finished
|
|
93
|
+
- search by quest title or quest id
|
|
94
|
+
- jump back into a previous workspace quickly
|
|
95
|
+
|
|
96
|
+
Each row corresponds to one quest repository. Click a quest card to open it.
|
|
97
|
+
|
|
98
|
+
## 6. What Happens After Opening a Quest
|
|
99
|
+
|
|
100
|
+
After you create or open a quest, DeepScientist takes you to the workspace page for that quest.
|
|
101
|
+
|
|
102
|
+
Inside the workspace, the usual flow is:
|
|
103
|
+
|
|
104
|
+
1. watch agent progress in Copilot / Studio
|
|
105
|
+
2. inspect files, notes, and generated artifacts
|
|
106
|
+
3. use Canvas to understand the current quest graph and stage progress
|
|
107
|
+
4. stop the run only when you intentionally want to interrupt it
|
|
108
|
+
|
|
109
|
+
## 7. Useful Runtime Commands
|
|
110
|
+
|
|
111
|
+
Check status:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
ds --status
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Stop the current local daemon:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
ds --stop
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Run diagnostics if something looks broken:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
ds doctor
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 8. What To Read Next
|
|
130
|
+
|
|
131
|
+
- [01 Settings Reference: Configure DeepScientist](./01_SETTINGS_REFERENCE.md)
|
|
132
|
+
- [02 Start Research Guide: Fill the Start Research Contract](./02_START_RESEARCH_GUIDE.md)
|
|
133
|
+
- [03 QQ Connector Guide: Use QQ With DeepScientist](./03_QQ_CONNECTOR_GUIDE.md)
|
|
134
|
+
- [05 TUI Guide: Use the Terminal Interface](./05_TUI_GUIDE.md)
|