ResearchOS 是一个把“问题”研究成“观点”的个人深度研究工作台。
当前实现为 R1 持久化研究核心的首个可用迭代:
登录 → 工作台 → 选题池 → 创建研究项目 → 问题定义 → 研究假设 → 研究地图 → 资料搜集
- 复制
.env.example为.env,按需修改POSTGRES_DB、POSTGRES_USER和POSTGRES_PASSWORD;同时保持DATABASE_URL、DIRECT_DATABASE_URL中的连接信息一致。 - 启动 PostgreSQL 并初始化数据库:
npm install
npm run db:up
npm run db:deploy
npm run db:seed
npm run dev打开 http://localhost:3000。
研究假设、研究地图和资料搜集支持“AI 生成初稿 + 用户审核确认 + 手动编辑”的混合交互。资料搜集 Agent 只生成检索计划,不会静默执行外部搜索;搜索结果默认是待审核资料,不会自动成为事实或证据。未配置 Provider 或 Connector 时,页面保留完整的手动新增、编辑、删除和保存路径。
在 .env 中配置任意 OpenAI-compatible 服务:
AI_BASE_URL="https://api.openai.com/v1"
AI_API_KEY="your-api-key"
AI_MODEL="gpt-4o-mini"
# 可选;默认 60000,模型响应较慢时可提高到 90000
AI_TIMEOUT_MS="60000"更新 Prisma Schema 后执行 npx prisma generate,数据库执行 npm run db:deploy;如果正在运行 Next.js 开发服务,重启 npm run dev 以加载新的 Prisma Client 和环境变量。
在“研究假设”“研究地图”或“资料搜集”页面底部点击 查看执行日志,可以查看当前阶段最近 20 次运行;点击某次运行的详情,可以看到 RUN_STARTED、PROVIDER_REQUEST、RUN_COMPLETED 或 PROVIDER_FAILED 等事件、错误信息、耗时和脱敏元数据。
页面会持续轮询 GENERATING 运行,直到 Agent 完成或失败;连续 2 分钟没有收敛会自动回到手动模式。服务端会将超过 5 分钟仍为 GENERATING 的孤立运行标记为失败,下一次生成请求会创建新运行。
也可以直接通过接口查询,projectId 替换为当前研究项目 ID:
curl -b "<登录 Cookie>" "http://localhost:3000/api/projects/<projectId>/agent-runs?stage=MAP&limit=20"
curl -b "<登录 Cookie>" "http://localhost:3000/api/projects/<projectId>/agent-runs/<runId>"开发服务终端会同步输出不含 API Key 的结构化日志,前缀为 [agent-run]。常见故障码:
AGENT_NOT_CONFIGURED:检查AI_BASE_URL、AI_API_KEY、AI_MODEL,修改.env后重启npm run dev。AGENT_TIMEOUT:检查上游网络、代理和模型响应时间。AGENT_RATE_LIMITED:检查模型配额、调用频率或切换模型。AGENT_INVALID_OUTPUT:上游没有返回合法 JSON,检查 OpenAI-compatible 服务是否支持response_format: { type: "json_object" }。AGENT_UPSTREAM_ERROR:查看运行详情中的 HTTP 错误和终端日志,确认AI_BASE_URL是否应包含/v1。P2021或agent_run_logs/agent_runs表不存在:先执行npm run db:deploy,再重启开发服务。
不要在终端命令或日志中打印 AI_API_KEY。项目提供了一个复用真实 Provider 请求格式的验证教本:
# 验证研究假设请求
npm run verify:ai
# 验证研究地图请求
npm run verify:ai -- map输出含义:
PASS:网络、鉴权、模型名和 JSON 结构均可用。HTTP 401/403:API Key 或上游权限不对。HTTP 404:AI_BASE_URL路径不对,通常检查是否应包含/v1。HTTP 400:模型或response_format: { type: "json_object" }不被上游兼容接口支持。TIMEOUT:请求超过AI_TIMEOUT_MS;先看实际耗时,再检查上游网络、代理、模型负载或提高超时。UPSTREAM_ERROR且没有 HTTP 状态:通常是 DNS、TLS、代理或网络不可达。
日志迁移文件为 prisma/migrations/20260824100000_add_agent_run_logs/migration.sql。日志只保存运行状态、错误、事件和脱敏元数据,不保存 API Key。
如果 .env 已经配置了 OpenAI 官方 API,资料搜集会优先自动使用模型内置网页搜索,不需要填写 SOURCE_WEB_SEARCH_MCP_ENDPOINT 和 SOURCE_WEB_SEARCH_MCP_TOKEN。当前默认规则是:
AI_BASE_URL是https://api.openai.com/v1:自动启用内置网页搜索。- 其他 OpenAI-compatible 服务:默认不假设支持网页搜索;如果该服务确实兼容 Responses Web Search,可以设置
SOURCE_BUILTIN_WEB_SEARCH="true"。 - 如果配置了
SOURCE_WEB_SEARCH_MCP_ENDPOINT:优先使用 MCP,MCP 优先级高于内置搜索。 SOURCE_PAGE_FETCH_MCP_ENDPOINT仍然只负责网页正文抓取;没有抓取 MCP 时,可以手工粘贴正文。
因此,最简单的配置只需要已有的 AI 配置:
AI_BASE_URL="https://api.openai.com/v1"
AI_API_KEY="your-openai-api-key"
AI_MODEL="gpt-4.1-mini"
SOURCE_BUILTIN_WEB_SEARCH="auto"如果你使用的是兼容 OpenAI 的其他服务,并确认它提供 Responses API 网页搜索,再显式打开:
AI_BASE_URL="https://your-provider.example.com/v1"
AI_API_KEY="your-provider-key"
AI_MODEL="your-search-capable-model"
SOURCE_BUILTIN_WEB_SEARCH="true"资料搜集阶段也支持通过标准 Connector 接口调用远程 Streamable HTTP MCP。搜索和抓取独立配置,后续可以分别替换为学术搜索、新闻搜索或内部知识库 Connector:
SOURCE_WEB_SEARCH_CONNECTOR_ID="web-search"
SOURCE_WEB_SEARCH_MCP_ENDPOINT="https://your-mcp.example.com/mcp"
SOURCE_WEB_SEARCH_MCP_TOOL="web_search"
SOURCE_WEB_SEARCH_MCP_TOKEN=""
SOURCE_PAGE_FETCH_CONNECTOR_ID="page-fetch"
SOURCE_PAGE_FETCH_MCP_ENDPOINT="https://your-fetch-mcp.example.com/mcp"
SOURCE_PAGE_FETCH_MCP_TOOL="fetch_page"
SOURCE_PAGE_FETCH_MCP_TOKEN=""
SOURCE_CONNECTOR_TIMEOUT_MS="30000"
SOURCE_SEARCH_RESULT_LIMIT="4"
SOURCE_FETCH_MAX_BYTES="1000000"修改 .env 后重启开发服务。Connector 只接受远程 HTTP MCP,不会在 Web 服务器内启动任意本地 stdio 进程。网页抓取会拒绝 localhost、内网地址、链路本地地址和非 HTTP(S) URL。
验证配置:
npm run verify:sources
npm run verify:sources -- "自定义安全测试搜索词"脚本会打印 Connector ID、搜索模式、工具名、能力、健康状态和最多 3 条结果标题/URL,不会打印 Token 或网页正文。未配置 MCP 但配置了 OpenAI 官方 AI 时,应看到 search mode=OPENAI_WEB_SEARCH;完全没有搜索能力时才会返回 SOURCE_CONNECTOR_NOT_CONFIGURED。
常见资料 Connector 错误:
SOURCE_CONNECTOR_NOT_CONFIGURED:缺少对应 endpoint,或检索任务引用了未注册的 Connector ID。SOURCE_CONNECTOR_RATE_LIMITED:内置网页搜索达到调用限制,请稍后重试或切换 MCP。SOURCE_CONNECTOR_UNAUTHORIZED:Bearer Token 无效或 MCP 服务拒绝访问。SOURCE_CONNECTOR_TIMEOUT:远程 MCP 超过SOURCE_CONNECTOR_TIMEOUT_MS。SOURCE_INVALID_RESULT:MCP 工具没有返回标准results或contentTextJSON。SOURCE_URL_BLOCKED:抓取 URL 指向 localhost、内网或云元数据地址。
搜索或抓取失败不会阻塞研究流程。用户可以直接添加 URL、创建无 URL 的手工笔记,或在资料卡片中粘贴正文。
本地容器运行依赖 Podman 与 podman compose。项目使用 .podman-compose/config.json 隔离 Compose 凭据配置,避免读取已卸载 Docker Desktop 遗留的 credsStore;启动脚本设置 PODMAN_COMPOSE_WARNING_LOGS=false,不再输出外部 Compose provider 提示;PostgreSQL 镜像通过 mirror.gcr.io 获取,避免部分网络环境访问 Docker Hub 时出现 EOF。若本机没有 Podman,也可以使用 npx prisma dev --name researchos --detach。该命令返回代理连接串时,应用侧 DATABASE_URL 需要追加 &pgbouncer=true,迁移使用的 DIRECT_DATABASE_URL 保持原连接串。
npm run typecheck
npm test
npm run test:e2e
npm run buildsrc/app/:Next.js 页面和 API Route Handlers。src/app/(app)/:受会话保护的工作台、选题池和研究项目真实路由。src/server/modules/:按工作空间过滤的 Prisma 仓储。src/lib/domain.ts:研究领域类型和状态。src/server/auth/:数据库会话和当前工作空间边界。prisma/schema.prisma:PostgreSQL 核心对象模型。docs/20260812-researchos-prd.md:产品需求文档。docs/20260812-researchos-tech-design.md:技术方案文档。
按照技术方案继续实现:
- 证据核验与事实提取。
- 学术搜索、新闻搜索和内部知识库 Connector。
- 研究地图父子关系、拖拽排序和画布视图。
- Red Team、结论版本和 Markdown 文章生成。