下述内容借助Cursor的Composor 2生成。
Dr. Claw 是一个面向科研全流程的 AI 研究助手 / 研究工作区:把「调研 → 想法 → 实验 → 写作 → 展示」尽量放在同一个应用里完成,减少在多种工具之间来回切换。官方中文描述是「面向科研全流程的通用 AI 研究助手」;package.json 里也写明它同时是 Claude Code、Cursor CLI、Codex、OpenRouter 等能力的桌面与移动端 UI,并带 Research Lab(研究实验室)。
参见“附录”了解陌生技术名词。
| 层级 | 技术 | 作用 |
|---|---|---|
| 前端 | React 18 + Vite + Tailwind 等 | 浏览器 UI;开发时通常 5173 端口,通过代理连后端 |
| 后端 | Node.js + Express | REST API、项目/会话等业务 |
| 实时通信 | ws(WebSocket) |
与前端保持连接(例如会话、终端等实时能力) |
| 终端 | node-pty |
在 UI 里嵌入类终端体验 |
| 数据 | SQLite(如 better-sqlite3) |
本地持久化(用户、会话等,具体表结构在 server/database/) |
| 认证 | JWT 等(见 middleware/auth.js) |
保护 API;CLI 另有 cli-auth 等路由 |
sequenceDiagram
participant UI as Chat UI
participant WS as WebSocket /ws
participant S as server/index.js
participant Q as openai-codex.js
participant SDK as @openai/codex-sdk
UI->>WS: codex-command + options
WS->>S: JSON message
S->>Q: queryCodex(command, options, WebSocketWriter)
Q->>SDK: new Codex / startThread or resumeThread
Q->>SDK: thread.runStreamed (stream)
SDK-->>Q: events
Q-->>WS: session-created (once id known)
Q-->>WS: codex-response (many)
Q-->>WS: token-budget (optional)
Q-->>WS: codex-complete
WS-->>UI: latestMessage
UI->>UI: useChatRealtimeHandlers 更新消息列表
Dr. Claw为“前端-后端”架构,后端会进一步通过@openai/codex-sdk请求codex中配置的、可访问的模型。
WebSocketContext 里 socket.send(JSON.stringify(message))
} else if (provider === 'codex') {
console.log('[DEBUG] Sending codex-command');
sendMessage({
type: 'codex-command',
command: messageContent,
sessionId: effectiveSessionId,
options: {
cwd: resolvedProjectPath,
projectPath: resolvedProjectPath,
sessionId: effectiveSessionId,
resume: Boolean(effectiveSessionId),
model: codexModel,
permissionMode: permissionMode === 'plan' ? 'default' : permissionMode,
modelReasoningEffort: codexReasoningEffort === 'default' ? undefined : codexReasoningEffort,
attachments: codexAttachmentPayload,
images: uploadedImages,
telemetryEnabled,
sessionMode: isNewSession ? newSessionMode : selectedSession?.mode,
stageTagKeys: pendingStageTagKeys,
stageTagSource: 'task_context',
},
});
server/index.js 里用 WebSocketServer 的 verifyClient 鉴权,pathname === '/ws' 时进入 handleChatConnection,在里面解析 JSON 并分发给 Claude / Codex / Cursor 等 const preparedInput = await prepareCodexInput(command, images, workingDirectory);
tempImagePaths = preparedInput.tempImagePaths;
tempDir = preparedInput.tempDir;
// Execute with streaming
// Prefer pre-uploaded attachments (buildCodexInput) over base64 temp images (prepareCodexInput)
const codexInput = attachments
? buildCodexInput(command, attachments)
: preparedInput.input;