Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ Catalog lookup: `--apps <file>` if given, else `~/.octosense/apps.json` if it ex
```

- `"source": "makepad"` resolves through Cargo to the same Makepad checkout as the host; such builds go to `~/.octosense/build/makepad`.
- Step-by-step guides (Chinese): [open a hosted app](docs/open-apps.md), including the fix for an empty catalog when `cargo metadata --offline` fails, and [open the full Makepad catalog](docs/add-all-makepad-apps.md).
- Relative paths resolve from the catalog's directory. Arguments are passed literally, without a shell.
- `policy`: `"new"` opens another instance; `"focus"` (default) focuses a running one.
- Do not add `--stdin-loop` or Studio variables; the shell adds them. Restart after editing.
Expand Down
191 changes: 191 additions & 0 deletions docs/add-all-makepad-apps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# 把 Makepad 全家桶应用到 OctoSense

本文说明如何把 Makepad 仓库里的全部应用(浏览器、文件、终端、天气、金融、邮件、笔记、日历、提醒、计算器、Fabric、Score、视频、导航、VJ、Fab、Director、Image、PDF、AI 等)一次性加进 OctoSense 桌面,让它们全部出现在 **⌘Space** 应用菜单里并可随时打开。

---

## 一、前提条件

1. **Makepad 同级框架仓库就位**

```sh
cd /path/to/OctoSense
python3 tools/setup-native.py --update
```

把 `../makepad`、`../octoscript`、`../octoscript-makepad` 检出到锁定版本。
目录里 `"source": "makepad"` 的行要靠 `cargo metadata --offline` 解析出
这个 checkout 才能生效。

2. **Cargo 缓存完整**(离线 metadata 能成功)

第一次构建宿主后,跑一次联网 `cargo metadata` 把缺失依赖补进缓存:

```sh
cargo metadata --format-version 1 --manifest-path Cargo.toml > /dev/null
```

之后 `cargo metadata --offline` 正常,目录解析出 Makepad 根。
(缓存不全时所有 `source: makepad` 行会被静默跳过,日志只显示
`no app 'X' in the registry`。)

3. **编译宿主**

```sh
cargo build --release
```

---

## 二、两个应用目录

| 文件 | 内容 |
|---|---|
| `config/apps.json`(默认) | Reference + Makepad 全家桶(20+ 个应用),桌面默认就读它 |
| `config/apps.makepad.json` | 与 `config/apps.json` 相同的副本,供 `--apps` 显式指定 |

默认目录已经包含所有 Makepad 应用,你**不需要手写**,直接 `cargo run --release` 即可。
也可以显式指定副本:

```sh
cargo run --release -- --apps config/apps.makepad.json
```

想换成自己的目录,建 `~/.octosense/apps.json` 个人目录覆盖默认目录,重启即可。

> 注意:Makepad 自带的 Photos 和 Mail 已从目录中移除,由 OctoSense 的系统应用(News、Photos、Maps、Camera、Mail、AI providers,经 App Hub 打包进 Shell)取代,它们不在开发者程序目录里。

---

## 三、目录里 Makepad 全家桶的完整条目

`config/apps.makepad.json` 的 `source: makepad` 行(每行 3 要素:
`package` = Makepad 的 Cargo 包名,`bin` = 可执行文件名,`policy` = 多实例策略):

| id | label | package | bin | policy |
|---|---|---|---|---|
| `browser` | Browser | makepad-browser | browser | focus |
| `files` | Files | makepad-files | files | focus (args: `--demo`) |
| `terminal` | Terminal | makepad-terminal | terminal | new |
| `mixer` | Mixer | makepad-mixer | makepad-mixer | focus |
| `task` | Task Manager | makepad-task | task | focus |
| `sheets` | Sheets | makepad-sheets | sheets | focus |
| `clock` | Clock | makepad-clock | clock | focus |
| **`weather`** | **Weather** | **makepad-weather** | **weather** | **focus** |
| `finance` | Finance | makepad-finance | finance | focus |
| `notes` | Notes | makepad-notes | notes | focus |
| `calendar` | Calendar | makepad-calendar | calendar | focus |
| `reminders` | Reminders | makepad-reminders | reminders | focus |
| `calculator` | Calculator | makepad-calculator | calculator | focus |
| `fabric` | Fabric | makepad-fabric | makepad-fabric | focus |
| `score` | Score | makepad-app-score | makepad-app-score | focus |
| `video` | Video Player | makepad-video | video | new |
| `route` | Route | makepad-app-route | route | focus |
| `vj` | VJ | makepad-vj | makepad-vj | focus |
| `fab` | Fab | makepad-fab | makepad-fab | focus |
| `studio` | Director | makepad-director | director | focus |
| `image` | Image Viewer | makepad-image | image | new |
| `pdf` | PDF Viewer | makepad-pdf | pdf | new |
| `aichat` | AI | makepad-aichat | aichat | new |

`policy: focus` = 已有实例就聚焦,`policy: new` = 每次开新实例。

---

## 四、启动并打开全家桶

```sh
# 1. 启动桌面,加载 Makepad 全家桶目录
cargo run --release -- --apps config/apps.makepad.json
```

启动后用任一方式打开应用:

**脚本化**(每个应用独立一行,适合自动化):

```sh
# 在启动参数里同时开多个(可叠加)
cargo run --release -- \
--apps config/apps.makepad.json \
--test-action launch-weather \
--test-action launch-browser

# 或者在桌面已运行时,另开一个 shell 发 test-action
# (test-action 只在启动时执行一次,所以每次要新起进程)
```

**手动**(在桌面里操作,最常用):

- **⌘Space** → 应用菜单,搜索并点击任意应用名
- 或 **⌘1…0** 切工作区,**⌘W** 关 tile,**⌘F** 当前 tile 全屏

每个应用首次打开会现场 `cargo run` 编译(进度显示在 tile 里,
首次冷构建约 90 秒);之后复用 Cargo 缓存,秒开。

---

## 五、验证

启动后在桌面主日志(重定向 stdout 可得)里找:

```
wm: desktop style octosense applied to N clients and 0 modules
# N = 已打开的应用 tile 数

# 对每个打开的应用:
wm: --test-action launch weather
wm: launched weather as client 1
wm: weather client 1 first frame in NNN ms (cold) ← 出画面

# 打开多个应用:
wm: launched browser as client 2
wm: launched terminal as client 3
...
```

`first frame in NNN ms (cold)` 表示该应用的首帧已渲染,tile 里能看到画面。
每个应用自己的日志在 `~/.octosense/wm/logs/<app>.log`。

---

## 六、常见问题

**打开应用时报 `no app 'X' in the registry`**

Cargo 离线缓存不全。联网跑一次:

```sh
cargo metadata --format-version 1 --manifest-path Cargo.toml > /dev/null
```

再重启 OctoSense。

**应用 tile 里一直显示 "building…" 不出画面**

首次冷构建,进度正常。等 90 秒左右出首帧。之后秒开。

**应用打不开(构建失败)**

看 `~/.octosense/wm/logs/<app>.log` 里的编译错误。
Makepad 全家桶应用都依赖同一个 Makepad checkout,版本不匹配会失败。

**某个应用不想要,隐藏它的启动器图标**

在 `~/.octosense/wm/launcher.hides` 里加一行应用 id,例如:

```json
["image", "pdf", "aichat"]
```

Image/PDF/AI 这三个 helper 应用默认出现在启动器里(除非被隐藏)。

---

## 相关

- 单个应用目录格式:README「Add an app」章节
- 目录解析原理与离线 metadata 踩坑:[open-apps.md](open-apps.md) 第四、五章
- Makepad 全家桶目录是生成物:由上游 `scripts/upstream.py catalog`(读
Makepad checkout 的依赖图生成)产出,本地在 `config/apps.overlay.json`
叠加适配。检查漂移或重新生成:
`python3 scripts/upstream.py catalog`(加 `--apply` 写回)。
147 changes: 147 additions & 0 deletions docs/open-apps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# 在 OctoSense 中打开托管应用(操作记录 + 参考)

这份文档整理了在 OctoSense 桌面中打开托管应用的步骤(2026-09-26 实测)。

OctoSense 桌面能把 Makepad 应用作为独立子进程托管在自己的窗口(tile)里。
下面先按时间顺序记录当时怎么做的,再给可照抄的命令。

## 一、当时是怎么操作的(按时间)

1. **准备同级框架仓库**:`python3 tools/setup-native.py --update`
—— 把 `../makepad`、`../octoscript`、`../octoscript-makepad` 检出到锁定版本。
2. **编译宿主**:`cargo build`(debug 或 release),产物在 `CARGO_TARGET_DIR`
指定的 target 目录下(默认 `target/`)。
3. **启动桌面**:跑编译出的 `octosense` 可执行文件。
第一次用 `--test-action launch-weather` 打 weather,日志报
`no app 'weather' in the registry` —— 应用目录里查不到 weather。
4. **查原因**:目录的 `"source": "makepad"` 行要靠
`cargo metadata --offline` 解析出 Makepad checkout;
而离线 metadata 因为缓存缺依赖(`agent-client-protocol` 1.3.0)而失败,
导致所有 makepad 应用行被静默跳过。
5. **修复**:联网跑一次 `cargo metadata` 把缺的依赖补进缓存;
之后离线 metadata 正常,目录解析出同级的 `../makepad` checkout。
6. **再开 weather**:桌面把 weather 作为 **client 1** 托管,现场
`cargo run` 编译;首次冷构建 91 秒出首帧(`first frame in 91473 ms (cold)`),
天气应用成功渲染进桌面 tile。

## 二、可照抄的命令

### 启动并打开天气

```sh
# 启动桌面(用 Makepad 全家桶目录)
cargo run --release -- --apps config/apps.makepad.json

# 在另一个 shell 里,或直接加在启动参数上:
cargo run --release -- --test-action launch-weather
```

`--test-action launch-<app-id>` 是脚本化打开应用的方式,
app-id 就是目录里的 `id`(weather、browser、files、terminal、aichat……)。
首次启动会现场 `cargo run` 编译应用,进度显示在 tile 里;
之后复用 Cargo 缓存,秒开。

### 手动操作(不用 test-action)

- **⌘Space** 打开应用菜单/搜索,直接搜 "Weather"
- **⌘W** 关 tile,**⌘F** 当前 tile 全屏,**⌘1…0** 切工作区
- 菜单里 Learn → Keybindings 列全部快捷键

### 验证日志

启动后在桌面主日志(重定向 stdout 可得)里找这几行:

```
wm: --test-action launch weather
wm: launched weather as client 1
wm: weather client 1 first frame in NNN ms (cold) ← 应用已出画面
```

## 三、两个应用目录

| 文件 | 内容 | 何时用 |
|---|---|---|
| `config/apps.json`(默认) | Reference + Makepad 全家桶(Browser、Files、Terminal、Weather、Finance、Notes、Calendar、Reminders、Calculator、Fabric、Score、Video、Route、VJ、Fab、Director、Image、PDF、AI 等) | 默认桌面 |
| `config/apps.makepad.json` | 与默认目录相同的副本 | 用 `--apps` 显式指定时 |

用 `--apps` 选目录:

```sh
cargo run --release -- --apps config/apps.makepad.json
```

个人目录 `~/.octosense/apps.json` 优先级高于项目默认;`--apps` 永远指向你点名的文件。

## 四、目录里为什么应用会"缺席"

`"source": "makepad"` 的行不是按路径找,而是让 Cargo 报告它用哪个 Makepad checkout
来编译本宿主,然后去那个 checkout 里找应用。

1. 宿主启动时跑一次 `cargo metadata --offline --locked`,
在依赖图里找带 `apps/wm/Cargo.toml` 标记的 Makepad 仓库根。
(见 `src/octosense/makepad_source.rs`、`src/octosense/catalog.rs`。)
2. 找不到 checkout(比如离线依赖不全),这些行会被**静默跳过**,
不会报错 —— 日志里只会看到 `no app 'X' in the registry`。

症状:启动后用 `--test-action launch-weather` 打开应用,
日志打 `octosense: no app 'weather' in the registry`,目录里却没有 weather。

原因:Cargo 缓存里缺少 lock 文件锁定的依赖版本(本次是
`agent-client-protocol` 要 1.3.0,缓存只有 1.2.0),
`cargo metadata --offline` 直接失败 → 解析不出 Makepad 根 →
所有 `source: makepad` 行被丢弃。

修复(联网跑一次 metadata 把依赖补进缓存):

```sh
cd OctoSense
cargo metadata --format-version 1 --manifest-path Cargo.toml > /dev/null
```

之后离线 metadata 正常,目录解析出同级的 `../makepad` checkout。
(前提:同级框架仓库已经用 `python3 tools/setup-native.py` 准备好。)

## 五、往目录里加一个新应用

目录是一组 JSON 数组,每行三选一:

- `"manifest"` + `"package"` + `"bin"` —— 指到某个 Cargo 工程(相对目录所在目录)
- `"executable"` —— 指到已安装的可执行文件
- `"source": "makepad"` + `"package"` + `"bin"` —— 让宿主按本构建的 Makepad checkout 解析

```json
{
"id": "notes",
"label": "Notes",
"manifest": "../notes/Cargo.toml",
"package": "my-notes",
"bin": "notes",
"policy": "new",
"args": []
}
```

规则(与 `src/octosense/catalog.rs` 校验一致):

- `id` 只允许小写字母、数字、`-`、`_`;目录内不允许重复
- `label` 必填;`policy` 缺省是 `focus`(已有实例就聚焦),`new` 强制开新实例
- `args` 是字符串数组,原样传给子进程(不经 shell)
- 应用必须支持 `--stdin-loop` 托管协议,且与本宿主同一 Makepad 版本
- 可执行文件托管的条目不要写 `package` / `bin`

放哪:

```sh
# 项目默认目录:改 config/apps.json,重启 OctoSense
# 个人目录(优先于项目默认):~/.octosense/apps.json
# 临时选目录:--apps /path/to/your.json
```

写完之后,应用就会出现在 **⌘Space** 应用菜单里;也可以 `--test-action launch-<id>` 直接打开。
不可用(找不到 manifest / 构建失败)的应用会在桌面日志里报原因,不会崩溃。

## 相关

- 应用目录格式:README「Add an app」章节
- 每个应用托管时自己的日志:`~/.octosense/wm/logs/<app>.log`
- 目录里不存在的 app 快捷键会提示「unavailable」,不会崩溃