Skip to content

feat(desktop): bundle ApeMind MCP placeholder + seed default recipes on first launch#19

Merged
earayu merged 2 commits into
mainfrom
chore/bundle-apemind-mcp-and-recipes
May 25, 2026
Merged

feat(desktop): bundle ApeMind MCP placeholder + seed default recipes on first launch#19
earayu merged 2 commits into
mainfrom
chore/bundle-apemind-mcp-and-recipes

Conversation

@earayu
Copy link
Copy Markdown
Collaborator

@earayu earayu commented May 25, 2026

现状

apecloud/apemind-agent fork 已经把品牌 / Logo / repo / Docker / 工作流命名调通,但还没把 ApeMind 自家的 MCP 扩展和工作流(recipes)作为分发资源内置进来。每次新装的 ApeMind Agent 需要用户手动配置 ApeMind MCP + 没有任何预置工作流。

@梅西 在 PR #18 已经把 3 个 ApeMind 工作流 YAML 放到 ui/desktop/default-recipes/

  • apemind-knowledge-qa.yaml(知识库问答)
  • apemind-deep-research.yaml(深度研究报告)
  • apemind-table-summary.yaml(表格总结)

现象

不做接线的话,PR #18 的模板源文件只是仓库里的资源,没人读,不会出现在 Desktop 用户的 Recipe 列表。ApeMind MCP 扩展也不会出现在 bundled-extensions 列表里。

影响

  • 用户装完 Agent 后默认 Recipe 列表是空的,看不到 ApeMind 工作流
  • 用户需要手动从 0 开始添加 ApeMind MCP 扩展,体验差
  • 客户/试用者看不到"开箱即用"的 ApeCloud 品牌 + ApeMind 集成

期望结果

三处变更:

  1. ui/desktop/forge.config.ts:把 default-recipes 加到 extraResource,让 Electron Forge 打包时把 YAML 目录复制到 app 的 Resources/default-recipes/ 路径。

  2. ui/desktop/src/main.ts 新增 seedDefaultRecipes()

    • 启动早期调用(在 appMain() 顶部,包在 try/catch 里)
    • process.resourcesPath/default-recipes/(packaged) 或 __dirname/../default-recipes/(dev)
    • 拷贝所有 .yaml / .yml 文件到 ~/.config/goose/recipes/
    • 同名文件已存在则跳过(不覆盖用户改过的版本,对齐 @冯诺伊曼 + @梅西 之前的设计)
    • 失败不阻塞启动,仅 log warn
    • 这条路径与 goose-rs / Desktop UI 已有的 recipe 读取逻辑兼容(~/.config/goose/recipes/ 是 goose 自家的用户 recipe 目录),零改动到核心 recipe runner
  3. bundled-extensions.json 增加 apemind 条目

    • type: streamable_http
    • enabled: falseuri: "":在扩展列表里出现一行 "ApeMind" + description 提示用户填写 URL/token 后启用
    • URL / token 不硬编码,由用户在 UI 配置或环境变量注入

不解决什么

  • 不引入 init-config.yaml(按当前 Recipe 是"复制到用户目录"的方案,可以不靠 init-config;后续如果还要预设 provider/model 默认值再加)
  • 不在代码里写死 ApeMind MCP 的 URL / token(由用户配置或 env var 控制)
  • 不动 goose-rs core / recipe runner / extension runtime
  • 不改 recipe-list 读取逻辑(用 goose 已有的 ~/.config/goose/recipes/ 读取路径)
  • 不做 manifest 版本化("新增不覆盖"靠同名文件判定即可;正式版本化 -v2 后缀的更新策略留给后续)

验证

  • 静态 diff:git diff main...HEAD 只动 3 个文件(forge.config.ts + main.ts + bundled-extensions.json)
  • 计划:merge 后 @冯诺伊曼 在 3F 本机:
    1. 清理本地状态(删 /Applications/ApeMind Agent.app + ~/Library/Application Support/ApeMind Agent/ + ~/.config/goose/
    2. 拉最新 main,pnpm -C ui/desktop run package
    3. 打开新 app,确认 Recipe 列表里出现 3 个 ApeMind workflow
    4. 确认扩展列表里出现 ApeMind 条目(disabled 状态)
    5. 给 @earayu2 试装

关联

  • 模板源文件 PR:feat: add ApeMind default workflows #18(@梅西)
  • 上游友好原则:见 feedback_goose_upstream_minimal_diff.md(5-cat 第 3 类默认配置 + 第 5 类打包分发)
  • 触发对话:#鹅岛 msg 250a69aa(earayu2 拍板 B 混合方案)+ cb109985(earayu2 提问怎么内置)

earayu added 2 commits May 25, 2026 12:49
…on first launch

Three pieces for the ApeCloud distribution layer:

1. forge.config.ts: add `default-recipes` to extraResource so the
   directory ships inside the packaged app's Resources path.

2. main.ts seedDefaultRecipes(): on app startup, read recipe YAMLs from
   the bundled `default-recipes/` directory (packaged: process.resourcesPath;
   dev: relative to __dirname) and copy them to ~/.config/goose/recipes/.
   Same-name files are skipped (never overwrite user edits). This
   intentionally uses goose's existing user-recipe directory so the
   reader logic in goose-rs and the Desktop UI need no changes —
   upstream-merge-friendly.

3. bundled-extensions.json: add an `apemind` entry of type
   streamable_http, enabled=false, uri="" — appears in the extensions
   list with description prompting the user to configure URL + token
   before enabling. URL/token intentionally not hardcoded.

Recipe YAML content authored separately in #18 (placed at
ui/desktop/default-recipes/).

5-cat compliance: category 3 (默认配置 / bundled extension config) +
category 5 (打包分发 / forge extraResource + first-copy logic). Zero
changes to Rust crates or recipe reader logic.

Signed-off-by: earayu <earayu@163.com>
…peMind MCP

Per earayu2 #鹅岛 msg 792dda6a:
- ApeMind MCP placeholder URL: `https://your-apemind.example.com/mcp`
- Auth header placeholder: `Authorization: Bearer your-api-key-here`

Two pieces:

1. `bundled-extensions.json` apemind entry: add `uri` + `headers.Authorization`
   placeholder values so the user only has to swap `your-api-key-here` (and
   adjust the URL if needed) when enabling.

2. `bundled-extensions.ts` BundledExtension type + streamable_http loader case:
   extend to propagate `headers` (and `envs`/`env_keys`) into the actual
   extension config. Without this, the JSON `headers` field is silently
   dropped during sync, so the auth would never reach the runtime.

5-cat compliance: still category 3 (默认配置 / bundled extension config). The
loader extension is a 1-line TS plumbing pass-through, not a change to the
goose-rs extension runtime — minimal rebase surface upstream-side.

Signed-off-by: earayu <earayu@163.com>
@earayu earayu merged commit 8d57f76 into main May 25, 2026
21 checks passed
earayu added a commit that referenced this pull request May 25, 2026
…on first launch (#19)

* feat(desktop): bundle ApeMind MCP placeholder + seed default recipes on first launch

Three pieces for the ApeCloud distribution layer:

1. forge.config.ts: add `default-recipes` to extraResource so the
   directory ships inside the packaged app's Resources path.

2. main.ts seedDefaultRecipes(): on app startup, read recipe YAMLs from
   the bundled `default-recipes/` directory (packaged: process.resourcesPath;
   dev: relative to __dirname) and copy them to ~/.config/goose/recipes/.
   Same-name files are skipped (never overwrite user edits). This
   intentionally uses goose's existing user-recipe directory so the
   reader logic in goose-rs and the Desktop UI need no changes —
   upstream-merge-friendly.

3. bundled-extensions.json: add an `apemind` entry of type
   streamable_http, enabled=false, uri="" — appears in the extensions
   list with description prompting the user to configure URL + token
   before enabling. URL/token intentionally not hardcoded.

Recipe YAML content authored separately in #18 (placed at
ui/desktop/default-recipes/).

5-cat compliance: category 3 (默认配置 / bundled extension config) +
category 5 (打包分发 / forge extraResource + first-copy logic). Zero
changes to Rust crates or recipe reader logic.

Signed-off-by: earayu <earayu@163.com>

* fix(desktop): wire Authorization header for bundled streamable_http ApeMind MCP

Per earayu2 #鹅岛 msg 792dda6a:
- ApeMind MCP placeholder URL: `https://your-apemind.example.com/mcp`
- Auth header placeholder: `Authorization: Bearer your-api-key-here`

Two pieces:

1. `bundled-extensions.json` apemind entry: add `uri` + `headers.Authorization`
   placeholder values so the user only has to swap `your-api-key-here` (and
   adjust the URL if needed) when enabling.

2. `bundled-extensions.ts` BundledExtension type + streamable_http loader case:
   extend to propagate `headers` (and `envs`/`env_keys`) into the actual
   extension config. Without this, the JSON `headers` field is silently
   dropped during sync, so the auth would never reach the runtime.

5-cat compliance: still category 3 (默认配置 / bundled extension config). The
loader extension is a 1-line TS plumbing pass-through, not a change to the
goose-rs extension runtime — minimal rebase surface upstream-side.

Signed-off-by: earayu <earayu@163.com>

---------

Signed-off-by: earayu <earayu@163.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant