pi-courier 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -124,16 +124,23 @@ Startup success looks like:
124
124
  **First contact (one-time pairing):**
125
125
 
126
126
  1. **DM the bot** from your account and send any message
127
- 2. The bot is not yet a trusted user, so the bridge prints a challenge code in its log (`pi-courier logs` or `journalctl --user -u pi-courier -f`):
127
+ 2. You are not a trusted user yet (e.g. you pressed Enter on the trusted-user prompt in setup, leaving only the bot itself trusted), so the bridge prints a challenge code in its log (`pi-courier logs` or `journalctl --user -u pi-courier -f`):
128
128
 
129
129
  ```
130
- 🔐 Challenge code for @barry: 138949
130
+ [2026-08-06T02:38:34.833Z] [INFO] 🔐 Challenge code for @barry: 529311
131
131
  ```
132
132
 
133
133
  3. **Reply with that code** in the chat (just the digits) — the log confirms the pairing:
134
134
 
135
135
  ```
136
- [auth:info] ✅ barry authenticated
136
+ [2026-08-06T02:38:44.487Z] [INFO] [auth:info] ✅ barry authenticated
137
+ ```
138
+
139
+ You can chat normally right away:
140
+
141
+ ```
142
+ [2026-08-06T02:38:55.685Z] [INFO] 📥 [matrix] @barry: 你好,收到请回复!
143
+ [2026-08-06T02:38:57.884Z] [INFO] [agent] 回复 @barry: 你好!收到,我在线。...
137
144
  ```
138
145
 
139
146
  You are now a trusted user (the first trusted user also becomes admin). Any user not in `auth.trustedUsers` goes through this flow once; pre-listed users skip it entirely.
@@ -213,7 +220,10 @@ A: Historical events that can't be decrypted (new device without old keys). Norm
213
220
  A: The bot's new device never received the room keys. The bot account has no cross-signing, so the most reliable fix is to **use a non-encrypted room** (create a room without encryption and invite the bot) — the bridge handles plain rooms fine even with `encryption: true`.
214
221
 
215
222
  **Q: `M_BAD_JSON: Provided device_id in device_keys does not match...`?**
216
- A: The crypto store holds an old device identity but the token belongs to a newer device (re-logged). Delete and restart: `rm -rf ~/.pi/msg-bridge-matrix-crypto && pi-courier restart`. Do this whenever you re-run setup / change the token.
223
+ A: The crypto store holds an old device identity but the token belongs to a newer device (re-logged). Delete and restart: `rm -rf ~/.pi/pi-courier-matrix-crypto && pi-courier restart`. Do this whenever you re-run setup / change the token.
224
+
225
+ **Q: `One time key signed_curve25519:... already exists` (M_UNKNOWN)?**
226
+ A: The token is bound to an old device on the server and the local OTK bookkeeping is out of sync — **deleting the local crypto store does NOT help** (the server assigns the device ID from the token, so a rebuilt store uses the same device). **You must get a new token**: re-run `pi-courier setup` and answer `n` to "keep the existing token?" (or log in with the password); a new token = a new device = clean server state. Pair with a crypto-store delete if device residue persists.
217
227
 
218
228
  **Q: First message asks for a 6-digit code?**
219
229
  A: That's the challenge auth — reply with the code to become a trusted user.
package/README.zh-CN.md CHANGED
@@ -124,16 +124,23 @@ pi-courier enable # 安装 systemd 服务:开机自启 + 立即启动
124
124
  **首次接触(一次性配对):**
125
125
 
126
126
  1. 用你的账号**给 bot 发私聊消息**(随便发什么都行)
127
- 2. 此时你还不是 trusted user,bridge 会在日志里打印验证码(`pi-courier logs` 或 `journalctl --user -u pi-courier -f`):
127
+ 2. 此时你还不是 trusted user(比如 setup 时信任用户回车用了默认的 bot 自己),bridge 会在日志里打印验证码(`pi-courier logs` 或 `journalctl --user -u pi-courier -f`):
128
128
 
129
129
  ```
130
- 🔐 Challenge code for @barry: 138949
130
+ [2026-08-06T02:38:34.833Z] [INFO] 🔐 Challenge code for @barry: 529311
131
131
  ```
132
132
 
133
133
  3. **在聊天里回复这串数字**(只发数字),日志确认配对成功:
134
134
 
135
135
  ```
136
- [auth:info] ✅ barry authenticated
136
+ [2026-08-06T02:38:44.487Z] [INFO] [auth:info] ✅ barry authenticated
137
+ ```
138
+
139
+ 配对成功后立刻可以正常对话:
140
+
141
+ ```
142
+ [2026-08-06T02:38:55.685Z] [INFO] 📥 [matrix] @barry: 你好,收到请回复!
143
+ [2026-08-06T02:38:57.884Z] [INFO] [agent] 回复 @barry: 你好!收到,我在线。...
137
144
  ```
138
145
 
139
146
  你就成为 trusted user(第一个 trusted 用户自动成为管理员)。不在 `auth.trustedUsers` 里的用户都会走一次这个流程;预信任用户完全跳过。
@@ -210,7 +217,10 @@ A: 历史消息无法解密(新设备没有旧密钥)。**正常**,新消息不
210
217
  A: bot 的新设备没拿到房间密钥。bot 账号没有交叉签名,最可靠的解法是**用非加密房间**(新建房间时不勾选加密,把 bot 拉进来)—— 配置 `encryption: true` 也照常处理非加密房间。
211
218
 
212
219
  **Q: 报 `M_BAD_JSON: Provided device_id in device_keys does not match...`?**
213
- A: 加密存储里是旧设备身份,而 token 属于新设备(重新登录过)。删除重启:`rm -rf ~/.pi/msg-bridge-matrix-crypto && pi-courier restart`。**每次重跑 setup / 换 token 都顺手删一次。**
220
+ A: 加密存储里是旧设备身份,而 token 属于新设备(重新登录过)。删除重启:`rm -rf ~/.pi/pi-courier-matrix-crypto && pi-courier restart`。**每次重跑 setup / 换 token 都顺手删一次。**
221
+
222
+ **Q: 报 `One time key signed_curve25519:... already exists`(M_UNKNOWN)?**
223
+ A: token 在服务器上已绑定旧设备,但本地与服务器的 OTK 记账错位 —— **删本地 crypto store 无效**(device ID 由服务器按 token 指定,删了重建还是同一个)。**必须换 token**:重跑 `pi-courier setup`,在"保留现有 token?"处输 `n` 重新获取(或直接密码登录),新 token = 新设备 = 服务器干净。换 token 后如遇 device 残留问题再配合删 crypto store。
214
224
 
215
225
  **Q: 第一次发消息要 6 位验证码?**
216
226
  A: 这是挑战认证 —— 把验证码回复给 bot 即成为 trusted user。
@@ -0,0 +1,29 @@
1
+ # pi-courier 一键部署配置示例
2
+ # 复制为 .env 并填入真实值: cp .env.example .env
3
+ # 注意:.env 包含敏感信息(token/key),已被 gitignore,不要提交!
4
+
5
+ # ---- Matrix(必须)----
6
+ PI_MATRIX_HOMESERVER=https://matrix.purplelin.com
7
+ PI_MATRIX_ACCESS_TOKEN=syt_你的token
8
+
9
+ # ---- 信任用户(可选,逗号分隔;不设则走验证码配对)----
10
+ PI_MATRIX_TRUSTED_USERS=@barry:matrix.purplelin.com
11
+
12
+ # ---- 加密(可选,默认 true)----
13
+ PI_MATRIX_ENCRYPTION=true
14
+
15
+ # ---- 工作目录(可选,容器内路径)----
16
+ PI_WORKDIR=/root/Projects
17
+
18
+ # ---- LLM(必须)----
19
+ PI_LLM_API_KEY=sk-你的key
20
+
21
+ # ---- 默认 provider/模型(可选)----
22
+ PI_DEFAULT_PROVIDER=opencode-go
23
+ PI_DEFAULT_MODEL=deepseek-v4-flash
24
+
25
+ # ---- 日志级别(可选:debug/info/warn/error)----
26
+ # PI_LOG_LEVEL=info
27
+
28
+ # ---- GitHub CLI(可选)----
29
+ # GH_TOKEN=ghp_xxx
@@ -22,7 +22,7 @@ ENV https_proxy=${HTTPS_PROXY} \
22
22
 
23
23
  # pi-courier 版本:发新版本后更新此值 —— RUN 层指令文本随之变化,
24
24
  # docker 缓存自动失效,不会装到旧版(避免"升级了但镜像还是旧代码"的坑)
25
- ARG PI_COURIER_VERSION=0.1.14
25
+ ARG PI_COURIER_VERSION=0.1.16
26
26
 
27
27
  # 仅需要 ca-certificates(npm install 走 https;git 由 runtime 层负责)
28
28
  RUN apt-get update \
@@ -46,11 +46,29 @@ ENV https_proxy=${HTTPS_PROXY} \
46
46
  # 系统依赖:
47
47
  # - git:pi 的 bash 工具 / `pi install` 需要(slim 基础镜像没有)
48
48
  # - ca-certificates:HTTPS 证书
49
- # - curl:排查网络问题用(可选)
49
+ # - curl:下载/排查
50
+ # - jq:JSON 处理(API 调试/日志分析)
51
+ # - wget/unzip:下载与解压(项目包/发布物)
52
+ # - openssl:证书/密钥操作
53
+ # - procps:ps/pgrep 排查进程
54
+ # - python3:脚本/数据处理(node:slim 默认没有 python)
55
+ # (apt 请求也走上面的代理 ENV,受限网络下可代理)
50
56
  RUN apt-get update \
51
- && apt-get install -y --no-install-recommends git ca-certificates curl \
57
+ && apt-get install -y --no-install-recommends \
58
+ git ca-certificates curl jq wget unzip openssl procps python3 \
52
59
  && rm -rf /var/lib/apt/lists/*
53
60
 
61
+ # GitHub CLI(gh):Debian 官方源没有,从 GitHub Releases 下载二进制。
62
+ # 动态取 latest 版本;amd64 为主流 VPS 架构(TARGETARCH 可覆盖 arm64)。
63
+ ARG TARGETARCH
64
+ RUN GH_TAG=$(curl -fsSL https://api.github.com/repos/cli/cli/releases/latest | jq -r .tag_name) \
65
+ && ARCH=$(case "${TARGETARCH}" in arm64) echo arm64 ;; *) echo amd64 ;; esac) \
66
+ && curl -fsSL "https://github.com/cli/cli/releases/download/${GH_TAG}/gh_${GH_TAG#v}_linux_${ARCH}.tar.gz" -o /tmp/gh.tgz \
67
+ && tar xzf /tmp/gh.tgz -C /tmp \
68
+ && cp /tmp/gh_*/bin/gh /usr/local/bin/gh \
69
+ && gh --version \
70
+ && rm -rf /tmp/gh*
71
+
54
72
  # 从 builder 只带 node_modules,然后在 runtime 重建 bin 符号链接
55
73
  # (docker COPY 会把符号链接解引用成普通文件,导致相对 import 解析错误,
56
74
  # 所以不能直接 COPY /usr/local/bin/pi)
@@ -12,13 +12,13 @@ deploy/docker/
12
12
  ├── defaults/ # 模板源(构建进镜像 /opt/pi-courier/defaults/)
13
13
  │ └── agent/
14
14
  │ ├── models.json # 完整模型数据(24 模型,开箱即用)
15
- │ ├── auth.json # API key 占位(唯一需要你填的文件)
15
+ │ ├── auth.json # API key 占位(也可用 pi TUI 配置)
16
16
  │ └── settings.json # 默认 provider + 模型
17
17
  └── data/ # 运行时数据(自动创建;含 key/token,已 gitignore)
18
18
  └── agent/ # 首次启动自动从模板填充
19
19
  ```
20
20
 
21
- ## 部署步骤
21
+ ## 部署步骤(实测流程)
22
22
 
23
23
  ### 1. 准备
24
24
 
@@ -34,7 +34,7 @@ sudo apt-get install -y docker-compose-plugin
34
34
  git clone https://github.com/Hi-Barry/pi-courier.git && cd pi-courier/deploy/docker
35
35
  ```
36
36
 
37
- ### 2. 构建(只构建,不运行)
37
+ ### 2. 构建
38
38
 
39
39
  ```bash
40
40
  # 如果 VPS 需要代理访问外网(GitHub 下载 21MB E2EE 库),先导出:
@@ -44,45 +44,91 @@ git clone https://github.com/Hi-Barry/pi-courier.git && cd pi-courier/deploy/doc
44
44
  docker compose build
45
45
  ```
46
46
 
47
- ### 3. 配置(只需填 API key)
48
-
49
- 首次启动会自动把模板拷入 `./data/agent/`。先启动一次容器完成初始化,再填 key:
47
+ ### 3. 启动容器
50
48
 
51
49
  ```bash
52
- docker compose up -d # 启动(entrypoint 自动初始化 ./data/agent/)
53
- docker exec pi-courier ls /root/.pi/agent # 确认模板已拷入
50
+ docker compose up -d
51
+ ```
52
+
53
+ 首次启动 entrypoint 会自动把 LLM 配置模板拷入 `./data/agent/`(models.json / auth.json / settings.json)。此时容器处于"等待配置"状态,日志会提示(属正常):
54
+
55
+ ```
56
+ [pi-courier] first run: initializing /root/.pi/agent from template
57
+ [WARN] ⚠️ 未配置 Matrix 连接(缺少 homeserver 或 access token)。
58
+ [WARN] 请运行 `pi-courier setup` 完成配置,然后重启服务。
59
+ [WARN] 等待配置中… (Ctrl+C / SIGTERM 退出)
54
60
  ```
55
61
 
56
- 然后编辑宿主 `./data/agent/auth.json`,把占位的 `sk-你的key` 换成真实 API key:
62
+ > **也可以完全跳过 4-5 步**:用环境变量一键配置(见文末"环境变量一键部署"),`up -d` 后直接就是就绪状态。
63
+
64
+ ### 4. 配置 LLM 模型(pi TUI,推荐)
57
65
 
58
66
  ```bash
59
- # data/agent/auth.json
60
- { "opencode-go": { "type": "api_key", "key": "sk-真实key" } }
67
+ docker exec -it pi-courier bash
68
+ pi # 进入 pi 交互界面
69
+ /login # 登录/配置 provider(填 API key)
70
+ /model # 选择模型(如 deepseek-v4-flash)
71
+ exit # 退出
61
72
  ```
62
73
 
63
- > 默认 provider `opencode-go` / `deepseek-v4-flash`(settings.json)。用其他 provider 的话,改 settings.json 并确认 models.json 里有对应模型。
74
+ > 也可以不用 TUI:直接编辑宿主 `./data/agent/auth.json`(把占位的 `sk-你的key` 换成真实 key),settings.json 里确认默认模型。entrypoint 已把模板拷好,只需填 key。
64
75
 
65
- ### 4. Matrix 配置(向导)
76
+ ### 5. 配置 Matrix
66
77
 
67
78
  ```bash
68
- docker exec -it pi-courier pi-courier setup
79
+ docker exec -it pi-courier bash
80
+ pi-courier setup # 交互向导:服务器地址 → token(密码登录或粘贴)→ 信任用户 → E2EE → workdir
81
+ exit
69
82
  ```
70
83
 
71
- 按提示输入:homeserver token(密码登录或粘贴)→ 信任用户 → E2EE → workdir。写入容器内 `/root/.pi/pi-courier.json`(宿主 `./data/pi-courier.json`)
84
+ - **信任用户**:可以直接回车默认(bot 自己),之后第一个给你发消息的人通过验证码自动配对(见第 7 )
85
+ - 向导写入容器内 `/root/.pi/pi-courier.json`(宿主 `./data/pi-courier.json`)
86
+
87
+ ### 6. 重启生效 + 查看日志
72
88
 
73
89
  ```bash
74
- docker compose restart # 让 Matrix 配置生效
75
- docker logs pi-courier # 应看到 ✅ Matrix connected + ✅ pi RPC connected (model: deepseek-v4-flash)
90
+ docker compose restart
91
+ docker logs -f pi-courier
92
+ ```
93
+
94
+ 看到如下输出即部署成功:
95
+
96
+ ```
97
+ ✅ Matrix connected as @dockerpicourier1:matrix.purplelin.com (0 rooms, E2EE enabled)
98
+ ✅ transports connected: matrix=up
99
+ ✅ pi RPC connected (model: deepseek-v4-flash, session: 019f...)
100
+ 🚀 pi-courier ready. Waiting for messages...
101
+ ```
102
+
103
+ ### 7. 首次配对(6 位验证码)
104
+
105
+ 如果 setup 时信任用户用了默认(bot 自己),用你的账号给 bot 发第一条消息,日志会打印验证码:
106
+
107
+ ```
108
+ [INFO] 🔐 Challenge code for @barry: 529311
109
+ ```
110
+
111
+ **在 Matrix 客户端把这 6 位数字回复给 bot**,配对成功:
112
+
113
+ ```
114
+ [INFO] [auth:info] ✅ barry authenticated
115
+ ```
116
+
117
+ 之后就能正常对话了:
118
+
119
+ ```
120
+ [INFO] 📥 [matrix] @barry: 你好,收到请回复!
121
+ [INFO] [agent] 回复 @barry: 你好!收到,我在线。...
76
122
  ```
77
123
 
78
- ### 5. 使用
124
+ ### 8. 使用
79
125
 
80
- - 给 bot 发消息 → 查看验证码: `docker logs pi-courier` → 回复验证码配对
81
126
  - 查看日志: `docker logs -f pi-courier`(或 `docker exec pi-courier pi-courier logs --level debug`)
82
127
  - 重启: `docker compose restart`
83
128
  - 停止: `docker compose down`(数据保留在 ./data)
129
+ - **GitHub CLI(gh)**:镜像内置。交互登录:`docker exec -it pi-courier bash` → `gh auth login`(device flow);或注入 token(compose environment 加 `GH_TOKEN: ghp_xxx`,适合自动化)
84
130
 
85
- ### 6. 升级
131
+ ### 9. 升级
86
132
 
87
133
  ```bash
88
134
  # 方式 A:容器内自更新(npm 全局方式)
@@ -97,22 +143,61 @@ git pull && docker compose build && docker compose up -d
97
143
  # docker compose build --no-cache
98
144
  ```
99
145
 
100
- ### 7. 映射宿主机项目目录(可选)
146
+ ### 10. 映射宿主机项目目录(可选)
101
147
 
102
148
  让 pi 在容器里直接操作宿主机上的代码:
103
149
 
104
150
  1. compose 里取消注释 `- ./projects:/root/Projects`
105
- 2. 配置 `workdir` 指向容器内路径(`docker exec -it pi-courier pi-courier setup` 的 workdir 填 `/root/Projects/<你的项目>`)
106
- 3. 宿主机代码放 `./projects/<你的项目>`
151
+ 2. 配置 `workdir` 指向容器内路径(`pi-courier setup` 的 workdir 填 `/root/Projects/<你的项目>`)
152
+ 3. 宿主机代码放 `./projects/<你的项目>`,pi 的工作目录就是 `/root/Projects/<你的项目>`。
153
+
154
+ ## 环境变量一键部署(推荐)
155
+
156
+ 不碰 TUI、不 exec setup —— 所有配置走环境变量,`up -d` 后直接就绪。
157
+
158
+ ### 1. 创建 .env(复制模板填真实值)
159
+
160
+ ```bash
161
+ cp .env.example .env
162
+ nano .env # 填:PI_MATRIX_HOMESERVER / PI_MATRIX_ACCESS_TOKEN / PI_LLM_API_KEY 等
163
+ ```
164
+
165
+ > `.env` 含敏感信息(token/key),已被 gitignore,不要提交。
166
+
167
+ ### 2. 启动即就绪
168
+
169
+ ```bash
170
+ docker compose up -d
171
+ docker logs -f pi-courier
172
+ # 直接看到:✅ Matrix connected + ✅ pi RPC connected (model: ...) + 🚀 ready
173
+ ```
174
+
175
+ ### 支持的变量
176
+
177
+ | 变量 | 作用 | 必填 |
178
+ |---|---|---|
179
+ | `PI_MATRIX_HOMESERVER` | Matrix 服务器地址 | ✅(与 token 成对) |
180
+ | `PI_MATRIX_ACCESS_TOKEN` | Matrix bot token | ✅ |
181
+ | `PI_MATRIX_TRUSTED_USERS` | 预信任用户(逗号分隔 MXID,如 `@barry:matrix.purplelin.com`);不设则走验证码配对 | 可选 |
182
+ | `PI_MATRIX_ENCRYPTION` | E2EE 开关(`true`/`false`,默认 true) | 可选 |
183
+ | `PI_WORKDIR` | 工作目录(容器内路径,默认 /root/Projects) | 可选 |
184
+ | `PI_LLM_API_KEY` | LLM API key(auth.json 模板引用此变量) | ✅ |
185
+ | `PI_DEFAULT_PROVIDER` / `PI_DEFAULT_MODEL` | 默认 provider/模型(entrypoint 写入 settings.json) | 可选 |
186
+ | `PI_LOG_LEVEL` | 日志级别(debug/info/warn/error) | 可选 |
187
+ | `GH_TOKEN` | GitHub CLI token | 可选 |
188
+
189
+ **优先级**:环境变量 > 配置文件 > 交互向导。env 未设置时走原有流程(setup 向导),完全兼容。
107
190
 
108
191
  ## 常见问题
109
192
 
110
193
  | 问题 | 解决 |
111
194
  |---|---|
112
195
  | 构建很慢 / 卡在下载 | 构建期网络问题,设 `export HTTPS_PROXY` 再 build |
113
- | 启动显示 `model: unknown` | `./data/agent/auth.json` 没填 key,或 settings.json 的模型不在 models.json |
196
+ | 启动显示 `model: unknown` | `./data/agent/auth.json` 没填 key,或用 pi TUI `/login` 配置 |
114
197
  | 发消息没有回复 | 按顺序查:`docker logs` 看 Matrix 连接、pi RPC 连接、模型是否 unknown |
115
- | `M_BAD_JSON: device_id does not match` | 重登录过,删 `./data/msg-bridge-matrix-crypto` 重启 |
198
+ | 发消息后日志只有 `Challenge code`,没有回复 | 这是首次配对 —— 6 位验证码回复给 bot |
199
+ | `M_BAD_JSON: device_id does not match` | 重登录过,删 `./data/pi-courier-matrix-crypto` 重启 |
200
+ | `One time key ... already exists`(M_UNKNOWN) | token 绑定旧设备且服务器 OTK 记账错位,删 store 无效 → **换 token**(setup 时"保留现有 token?"输 n 重新获取) |
116
201
  | 加密房间解不开新消息 | bot 无交叉签名,改用非加密房间 |
117
202
  | 会话重启丢失 | 0.1.1+ 自动 `--continue`,确认 `./data` 卷没被删 |
118
203
  | 想用新配置 | 改 `./data/pi-courier.json` → `docker compose restart` |
@@ -1 +1,6 @@
1
- { "opencode-go": { "type": "api_key", "key": "sk-你的key" } }
1
+ {
2
+ "opencode-go": {
3
+ "type": "api_key",
4
+ "key": "${PI_LLM_API_KEY}"
5
+ }
6
+ }
@@ -17,6 +17,25 @@ services:
17
17
  # - ./projects:/root/Projects
18
18
  environment:
19
19
  - TZ=Asia/Shanghai
20
+ # ---- 一键配置(推荐):设置这些变量后,无需 exec setup/编辑文件 ----
21
+ # Matrix(必须:PI_MATRIX_HOMESERVER + PI_MATRIX_ACCESS_TOKEN 同时设置)
22
+ - PI_MATRIX_HOMESERVER=${PI_MATRIX_HOMESERVER:-}
23
+ - PI_MATRIX_ACCESS_TOKEN=${PI_MATRIX_ACCESS_TOKEN:-}
24
+ # 信任用户(逗号分隔 MXID,预信任可跳过验证码;不设则走验证码配对)
25
+ - PI_MATRIX_TRUSTED_USERS=${PI_MATRIX_TRUSTED_USERS:-}
26
+ # 加密开关(true/false,默认 true)
27
+ - PI_MATRIX_ENCRYPTION=${PI_MATRIX_ENCRYPTION:-}
28
+ # 工作目录(容器内路径,默认 /root/Projects)
29
+ - PI_WORKDIR=${PI_WORKDIR:-}
30
+ # LLM API key(auth.json 模板已引用此变量)
31
+ - PI_LLM_API_KEY=${PI_LLM_API_KEY:-}
32
+ # 默认 provider/模型(可选,entrypoint 写入 settings.json)
33
+ - PI_DEFAULT_PROVIDER=${PI_DEFAULT_PROVIDER:-}
34
+ - PI_DEFAULT_MODEL=${PI_DEFAULT_MODEL:-}
35
+ # 日志级别(debug/info/warn/error,可选)
36
+ - PI_LOG_LEVEL=${PI_LOG_LEVEL:-}
37
+ # GitHub CLI token(可选,gh auth 用)
38
+ - GH_TOKEN=${GH_TOKEN:-}
20
39
  # 运行时代理(可选,仅当 Matrix / LLM provider 需要代理访问时)
21
40
  # - https_proxy=http://<host>:<port>
22
41
  # - http_proxy=http://<host>:<port>
@@ -18,4 +18,19 @@ if [ ! -d "$CONFIG_DIR/agent" ] || [ -z "$(ls -A "$CONFIG_DIR/agent" 2>/dev/null
18
18
  cp -rn "$DEFAULTS/agent/." "$CONFIG_DIR/agent/" || echo "[pi-courier] WARN: template copy failed"
19
19
  fi
20
20
 
21
+ # env-driven defaults for pi settings (pi itself has no env support for
22
+ # defaultProvider/defaultModel, so render them into settings.json).
23
+ # env wins over whatever is in the file (idempotent on every start).
24
+ if [ -n "$PI_DEFAULT_PROVIDER" ] || [ -n "$PI_DEFAULT_MODEL" ]; then
25
+ node -e '
26
+ const fs = require("fs");
27
+ const p = "/root/.pi/agent/settings.json";
28
+ const s = JSON.parse(fs.readFileSync(p, "utf8"));
29
+ if (process.env.PI_DEFAULT_PROVIDER) s.defaultProvider = process.env.PI_DEFAULT_PROVIDER;
30
+ if (process.env.PI_DEFAULT_MODEL) s.defaultModel = process.env.PI_DEFAULT_MODEL;
31
+ fs.writeFileSync(p, JSON.stringify(s, null, 2));
32
+ console.log("[pi-courier] settings.json updated from env");
33
+ '
34
+ fi
35
+
21
36
  exec "$@"
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD;;GAEG;AACH,wBAAgB,UAAU,IAAI,eAAe,CA2B5C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAUxD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD;;GAEG;AACH,wBAAgB,UAAU,IAAI,eAAe,CA4D5C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAUxD"}
package/dist/config.js CHANGED
@@ -22,13 +22,44 @@ export function loadConfig() {
22
22
  console.error("Failed to load config file:", err);
23
23
  }
24
24
  }
25
- // Environment variables override file config (higher priority)
25
+ // Environment variables override file config (higher priority).
26
+ // Matrix connection requires both PI_MATRIX_HOMESERVER and
27
+ // PI_MATRIX_ACCESS_TOKEN to be set; the other PI_* vars apply individually.
26
28
  if (process.env.PI_MATRIX_HOMESERVER && process.env.PI_MATRIX_ACCESS_TOKEN) {
27
29
  config.matrix = {
28
30
  homeserverUrl: process.env.PI_MATRIX_HOMESERVER,
29
31
  accessToken: process.env.PI_MATRIX_ACCESS_TOKEN,
32
+ ...(process.env.PI_MATRIX_ENCRYPTION !== undefined
33
+ ? { encryption: process.env.PI_MATRIX_ENCRYPTION === "true" }
34
+ : {}),
30
35
  };
31
36
  }
37
+ else if (process.env.PI_MATRIX_ENCRYPTION !== undefined && config.matrix) {
38
+ config.matrix.encryption = process.env.PI_MATRIX_ENCRYPTION === "true";
39
+ }
40
+ // Trusted users via env: comma-separated MXIDs, e.g.
41
+ // "PI_MATRIX_TRUSTED_USERS=@barry:matrix.purplelin.com,@alice:matrix.purplelin.com"
42
+ if (process.env.PI_MATRIX_TRUSTED_USERS) {
43
+ const users = process.env.PI_MATRIX_TRUSTED_USERS.split(",")
44
+ .map((u) => u.trim())
45
+ .filter(Boolean)
46
+ .map((u) => (u.startsWith("matrix:") ? u : `matrix:${u}`));
47
+ if (users.length > 0) {
48
+ config.auth = {
49
+ ...(config.auth ?? {}),
50
+ trustedUsers: users,
51
+ adminUserId: config.auth?.adminUserId ?? users[0],
52
+ };
53
+ }
54
+ }
55
+ // Working directory via env (container deployments: /root/Projects etc.)
56
+ if (process.env.PI_WORKDIR) {
57
+ config.workdir = process.env.PI_WORKDIR;
58
+ }
59
+ // Log level via env (debug/info/warn/error)
60
+ if (process.env.PI_LOG_LEVEL) {
61
+ config.logLevel = process.env.PI_LOG_LEVEL;
62
+ }
32
63
  return config;
33
64
  }
34
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;AAClD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAE7D;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAoB,EAAE,CAAC;IAEnC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;YAChC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,mBAAmB,WAAW,8BAA8B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;YACjH,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;YACrE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QAC3E,MAAM,CAAC,MAAM,GAAG;YACd,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB;YAC/C,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;SAChD,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAAuB;IAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -42,7 +42,7 @@ export class MatrixProvider {
42
42
  let cryptoProvider;
43
43
  if (this.config.encryption !== false) {
44
44
  try {
45
- const cryptoStorePath = path.join(os.homedir(), ".pi", "msg-bridge-matrix-crypto");
45
+ const cryptoStorePath = path.join(os.homedir(), ".pi", "pi-courier-matrix-crypto");
46
46
  cryptoProvider = new RustSdkCryptoStorageProvider(cryptoStorePath, 0 /* RustSdkCryptoStoreType.Sqlite */);
47
47
  console.log("[Matrix] E2EE crypto storage enabled (Rust/SQLite)");
48
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-courier",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Run pi coding agent from Matrix. Slash commands, skills and prompts fully work from messengers via the RPC protocol.",
5
5
  "type": "module",
6
6
  "main": "dist/standalone.js",