来源:docs/开发运行说明.html

开发运行说明

当前阶段

当前实现范围为 P0+P1+P2,以及 P3 阶段附件离线高保真解析与离线 QA RAG 问答 Prompter:

向量索引、自动文档和 Memos 主库备份恢复属于后续阶段。

环境准备

本项目在 Linux 环境下开发和测试。所有常用开发命令通过 Nx 任务入口执行:

npx nx test sidecar
npx nx run sidecar:compile
npx nx build sidecar

不要直接运行 pip install;Python 包和虚拟环境统一由 uv 管理,并封装在 Nx target、容器构建或后续统一脚本中。开发阶段优先执行本地 Nx 测试,Docker 构建放到阶段末尾验收。

启动 API

npx nx run sidecar:up

默认 Compose 会启动 gatewaymemossidecarsidecar-worker。Caddy 网关只暴露一个宿主机入口:http://localhost:8080/ 进入 Memos,/admin/*/health/webhooks/* 进入 Sidecar。Memos 的 5230 和 Sidecar 容器内部 8080 默认不直接暴露;需要更换宿主机端口时使用 GATEWAY_PORT=8090 npx nx run sidecar:up

Memos 页面:

http://localhost:8080/

健康检查:

curl http://localhost:8080/health

调试管理页面:

http://localhost:8080/admin/ui

页面通过现有管理 API 工作,需要输入 SIDECAR_ADMIN_TOKEN。token 只保存在浏览器 localStorage,不会写入 HTML、日志或仓库。页面也支持查看和保存 AI 调用配置;单条 memo 整理、标签总结和提醒抽取都可以单独选择模型 provider 并编辑提示词。

页面“大模型”区域支持直接切换默认 provider、修改模型名、base URL、响应格式、扩展 JSON 和 key。保存后 config/models.yaml 会记录非机密模型参数,真实 key 写入已忽略的 config/.env.local。API 和 worker 会在后续加载模型配置时读取该文件;备份包不会包含该密钥文件。

Memos 探针

执行 Memos API 探针:

npx nx run sidecar:probe-memos

首次本地联调可创建测试用户、登录并创建 memo:

npx nx run sidecar:probe-memos -- --bootstrap-username test --bootstrap-password testtest --create-memo "探针 memo #系统/原始记录"

创建 Memos Personal Access Token,供 Sidecar/worker 长期读取 Memos API:

npx nx run sidecar:probe-memos -- \
  --bootstrap-username test \
  --bootstrap-password testtest \
  --create-pat \
  --pat-output-env-file /tmp/memosima-pat.env

默认输出会隐藏 PAT 原文;/tmp/memosima-pat.env 仅供本机临时注入容器,不要提交到仓库。

本地部署默认使用 Sidecar 主动轮询 Memos,不需要公网 webhook。config/app.yamlmemos.ingestion_mode: poll 会让 worker 在空闲时读取最近 memo,发现未处理的原始 memo 后自动创建 process_memo 任务。

可选:配置 Memos 内置 webhook:

npx nx run sidecar:probe-memos -- \
  --bootstrap-username test \
  --bootstrap-password testtest \
  --configure-webhook-url "https://your-public-sidecar.example.com/webhooks/memos"

也可以通过 .env 配置 MEMOS_WEBHOOK_URL,然后直接执行探针。Memos 0.28.0 会拒绝 webhook URL 解析到本机、Docker 内网或其他保留/私有 IP,例如 http://sidecar:8080/webhooks/memoshttp://localhost:8080/webhooks/memoshttp://172.x.x.x:8080/webhooks/memos。本地测试不需要绕过该限制,使用默认轮询模式即可;公网部署时把 webhook 指向 Caddy 网关公开入口的 /webhooks/memos

配置 webhook、创建 memo 并轮询 Sidecar 任务状态:

npx nx run sidecar:probe-memos -- \
  --bootstrap-username test \
  --bootstrap-password testtest \
  --configure-webhook-url "$MEMOS_WEBHOOK_URL" \
  --create-memo "自动 webhook 探针 #系统/原始记录" \
  --verify-sidecar-url "http://localhost:8080" \
  --verify-sidecar-token "$SIDECAR_ADMIN_TOKEN"

启动 Worker

持续轮询由 Compose 中的 sidecar-worker 服务负责:

npx nx run sidecar:up

管理接口

调试页面:

http://localhost:8080/admin/ui

页面支持健康状态刷新、任务状态筛选、任务详情查看、失败或待澄清任务重试、候选标签详情查看、候选标签通过/拒绝、按标签生成整体总结、提醒管理、Sidecar 备份恢复,以及 AI 调用配置查看和保存。

worker 维护 #系统/Memosima 管理入口 memo 时,会使用 Memos 0.28 兼容的 content.contains("memosima:admin-entry") filter 表达式查找已有入口,避免把 HTML marker 原文作为 filter 导致 Memos 返回 400。

查询任务:

curl -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  "http://localhost:8080/admin/jobs"

重试失败任务:

curl -X POST -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  "http://localhost:8080/admin/jobs/1/retry"

读取和更新 AI 调用配置。请求体中的 provider 可填写 config/models.yaml 中的 provider 名称;为空时使用默认 provider:

curl -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  "http://localhost:8080/admin/prompts"

curl -X PUT -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"system":"系统提示 {active_tags}","user":"用户提示 {content}"}' \
  "http://localhost:8080/admin/prompts/organize-memo"

临时覆盖某次重试使用的提示词。该覆盖只影响提示词,不会临时改变模型 provider:

curl -X POST -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"prompt_override":{"system":"临时系统 {active_tags}","user":"临时用户 {content}"}}' \
  "http://localhost:8080/admin/jobs/1/retry"

按标签生成整体总结:

curl -X POST -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tag":"#项目/个人AI知识库","limit":50}' \
  "http://localhost:8080/admin/tag-summaries"

该接口会读取最近的 Memos 列表,在 Sidecar 本地按标签路径匹配,排除已有 #系统/AI整理#系统/标签总结 memo,按 config/prompts.yamltag_summary.provider 选择模型生成 Markdown 总结,并在 Memos 中创建带有 #系统/标签总结 和目标标签的新 memo。标签匹配支持高层级路径:请求 #项目 会包含 #项目#项目/... 子标签,但不会包含 #项目管理。如果匹配发生在 AI 整理 memo 上,Sidecar 会用本地 memos.source_memo_uid 反查原始 memo,把原始 memo 纳入总结而不是把 AI 整理 memo 作为来源。创建成功后,Sidecar 会把总结 memo 通过 Memos 原生 REFERENCE relation 引用到每条参与整理的普通来源 memo,便于在 Memos 界面点击回看来源。默认提示词使用 config/prompts.yamltag_summary,支持 {tag}{memo_count}{memos_markdown} 占位符。

查询和管理提醒:

curl -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  "http://localhost:8080/admin/reminders"

curl -X POST -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  "http://localhost:8080/admin/reminders/1/retry"

curl -X POST -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  "http://localhost:8080/admin/reminders/1/cancel"

/admin/reminders 支持 ?status=pending?status=failed?status=sent?status=cancelled 过滤。retry 会把 failedsent 的提醒重新置为 pending,下次 worker 扫描到期提醒时再次发送;cancel 只取消 pendingfailed 的提醒。

下载和恢复 Sidecar 备份:

curl -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  -o memosima-sidecar-backup.zip \
  "http://localhost:8080/admin/backups/download"

curl -X POST -H "Authorization: Bearer<空格>$SIDECAR_ADMIN_TOKEN" \
  -H "Content-Type: application/zip" \
  --data-binary @memosima-sidecar-backup.zip \
  "http://localhost:8080/admin/backups/restore"

备份 ZIP 包含 SQLite 快照、manifest 和非机密配置文件。恢复接口只替换 Sidecar SQLite 数据库,不自动覆盖配置文件,也不包含 Memos 主库或 Memos 附件。恢复前建议先下载当前状态备份。

测试

npx nx test sidecar

当前已通过自动化测试:

npx nx test sidecar
全部测试通过

P2 本地整理草案

worker 处理 memo 时会加载 config/taxonomy.yaml,在 job result.ai_plan 中写入本地整理草案:

该草案用于 P2 早期验证标签治理和任务结构。内容明确时,worker 会创建一条 Markdown AI 整理 memo,内容包含 #系统/AI整理、来源 memo、摘要、标签状态和原文摘录,并在 job result.ai_summary_memo_uid 返回新 memo uid。AI 整理 memo 不再写入业务 #tag,业务标签只在“标签”区域以普通文本展示,避免 AI 生成内容污染 Memos 原生标签筛选。

当所选 provider 对应的 key 存在时,worker 会按 config/models.yaml 调用 OpenAI-compatible /chat/completions,要求模型返回 JSON 对象,并把模型输出的摘要、要点和待办写入 AI 整理 memo。当前默认 provider 为 deepseek,默认模型为 deepseek-v4-flash,需要配置 DEEPSEEK_API_KEY。模型请求中的 base_urldefault_modeltemperaturemax_tokensresponse_formatextra_body 全部由配置文件控制;DeepSeek 模板在 extra_body.thinking.type 中显式配置 disabled,让摘要类任务使用非 thinking 输出。max_tokens 留空时不发送输出 token 限制,Sidecar 不主动截断输入正文。真实 key 只放在本地 .env、部署环境变量

P3 附件解析与 QA 问答

worker 处理 memo 时会读取 memo 中的 resourcesattachments 字段。对于允许扩展名内的 .txt.md 附件,会通过 Memos 资源接口下载并安全解码为 Markdown;对于 .doc.docx.xls.xlsx.ppt.pptx.pdf,会调用可插拔文档解析 provider(默认 MinerU 在线 API)。对于 .drawio(.drawio.svg)与 Mind Elixir .json 脑图,会启动本地 100% 离线的高保真解析器

所有解析结果均写入 Sidecar SQLite 的 artifacts 表,字段包括 memo_uidresource_uidcontent_markdown 等。解析得到的 Markdown 会在调用 LLM 前拼接到原 memo 正文后面参与智能整理。

对于正文为空、只有附件的原 memo,worker 会在 LLM 分析完成后使用 PATCH /api/v1/memos/{memo_uid} 回写一级标题。标题来自 LLM draft 的 title 字段,并会去掉多余的 AI整理 前缀和 Markdown # 符号,避免覆盖已有正文。

解析结果会出现在 job result.attachments 中。若未配置 MINERU_API_TOKEN,Office/PDF 附件会记录为 document_parser_not_configured,而 Draw.io 与思维脑图不受影响,依然可以通过本地离线解析成功。

离线 RAG Prompt 编译器接口:在 API 中新增了 POST /admin/qa/generate-prompt,支持用户通过 active 标签和模糊关键词(通过 Memos API 的 content.contains 召回)获取相关的 Memo 正文及关联的 Artifacts 解析段,组装成系统提示词和用户 Query 合一的超级 Prompt 返给管理页面,便于离线环境一键复制粘贴。

onfig/taxonomy.yaml 或 SQLite business_tags 中的 active 标签时才直接使用;未知标签会降级为候选标签并写入 tag_candidates;禁用标签进入 disabled_tags;系统标签不会由 LLM 创建。业务标签的最后一级名称必须全局唯一,例如已有 #项目/数管 时,后台会把 #数管 归一到该正式标签,并阻止 #其他/数管 成为候选或审核通过。Sidecar 还会按 limits.max_ai_active_tagslimits.max_ai_candidate_tags 限制单条无标签 memo 的 LLM 自动补充数量,默认最多接收 5 个正式标签和 2 个候选标签。

所有 LLM 调用点的默认提示词和模型选择都从 config/prompts.yaml 加载。当前调用点为 organize_memotag_summaryreminder_extractionorganize_memo 支持 {active_tags}{local_plan_json}{content} 占位符;tag_summary 支持 {tag}{memo_count}{memos_markdown} 占位符;reminder_extraction 支持 {trigger_tag}{now}{timezone}{content} 占位符。管理页面保存 AI 调用配置会写回该文件;任务重试时的临时提示词覆盖只写入任务 payload,不会改变默认配置或临时切换模型。

Sidecar 会在本地 memos 表记录两类 memo: