codex-weixin 0.2.1

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.
Files changed (93) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +5 -0
  4. package/README.en.md +200 -0
  5. package/README.md +210 -0
  6. package/dist/bridge/access.d.ts +21 -0
  7. package/dist/bridge/access.js +31 -0
  8. package/dist/bridge/access.js.map +1 -0
  9. package/dist/bridge/actions.d.ts +21 -0
  10. package/dist/bridge/actions.js +120 -0
  11. package/dist/bridge/actions.js.map +1 -0
  12. package/dist/bridge/errors.d.ts +1 -0
  13. package/dist/bridge/errors.js +15 -0
  14. package/dist/bridge/errors.js.map +1 -0
  15. package/dist/bridge/format.d.ts +14 -0
  16. package/dist/bridge/format.js +62 -0
  17. package/dist/bridge/format.js.map +1 -0
  18. package/dist/bridge/prompt-buffer.d.ts +45 -0
  19. package/dist/bridge/prompt-buffer.js +56 -0
  20. package/dist/bridge/prompt-buffer.js.map +1 -0
  21. package/dist/bridge/service.d.ts +38 -0
  22. package/dist/bridge/service.js +292 -0
  23. package/dist/bridge/service.js.map +1 -0
  24. package/dist/codex/app-server-runner.d.ts +74 -0
  25. package/dist/codex/app-server-runner.js +514 -0
  26. package/dist/codex/app-server-runner.js.map +1 -0
  27. package/dist/codex/exec-runner.d.ts +36 -0
  28. package/dist/codex/exec-runner.js +153 -0
  29. package/dist/codex/exec-runner.js.map +1 -0
  30. package/dist/codex/runner.d.ts +22 -0
  31. package/dist/codex/runner.js +57 -0
  32. package/dist/codex/runner.js.map +1 -0
  33. package/dist/codex/sandbox.d.ts +3 -0
  34. package/dist/codex/sandbox.js +15 -0
  35. package/dist/codex/sandbox.js.map +1 -0
  36. package/dist/index.d.ts +15 -0
  37. package/dist/index.js +16 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/server/account-manager.d.ts +94 -0
  40. package/dist/server/account-manager.js +468 -0
  41. package/dist/server/account-manager.js.map +1 -0
  42. package/dist/server/arguments.d.ts +3 -0
  43. package/dist/server/arguments.js +25 -0
  44. package/dist/server/arguments.js.map +1 -0
  45. package/dist/server/http-server.d.ts +23 -0
  46. package/dist/server/http-server.js +481 -0
  47. package/dist/server/http-server.js.map +1 -0
  48. package/dist/server/index.d.ts +2 -0
  49. package/dist/server/index.js +69 -0
  50. package/dist/server/index.js.map +1 -0
  51. package/dist/server/login-manager.d.ts +27 -0
  52. package/dist/server/login-manager.js +49 -0
  53. package/dist/server/login-manager.js.map +1 -0
  54. package/dist/server/process-lock.d.ts +5 -0
  55. package/dist/server/process-lock.js +63 -0
  56. package/dist/server/process-lock.js.map +1 -0
  57. package/dist/state/config.d.ts +19 -0
  58. package/dist/state/config.js +41 -0
  59. package/dist/state/config.js.map +1 -0
  60. package/dist/state/json-store.d.ts +3 -0
  61. package/dist/state/json-store.js +23 -0
  62. package/dist/state/json-store.js.map +1 -0
  63. package/dist/state/paths.d.ts +12 -0
  64. package/dist/state/paths.js +28 -0
  65. package/dist/state/paths.js.map +1 -0
  66. package/dist/state/runtime-state.d.ts +57 -0
  67. package/dist/state/runtime-state.js +212 -0
  68. package/dist/state/runtime-state.js.map +1 -0
  69. package/dist/web/app.js +958 -0
  70. package/dist/web/index.html +273 -0
  71. package/dist/web/styles.css +324 -0
  72. package/dist/web/vendor/lucide.min.js +12 -0
  73. package/dist/web/vendor/marked.umd.js +79 -0
  74. package/dist/web/vendor/purify.min.js +3 -0
  75. package/dist/weixin/accounts.d.ts +22 -0
  76. package/dist/weixin/accounts.js +66 -0
  77. package/dist/weixin/accounts.js.map +1 -0
  78. package/dist/weixin/api.d.ts +75 -0
  79. package/dist/weixin/api.js +191 -0
  80. package/dist/weixin/api.js.map +1 -0
  81. package/dist/weixin/login.d.ts +29 -0
  82. package/dist/weixin/login.js +100 -0
  83. package/dist/weixin/login.js.map +1 -0
  84. package/dist/weixin/media.d.ts +32 -0
  85. package/dist/weixin/media.js +266 -0
  86. package/dist/weixin/media.js.map +1 -0
  87. package/dist/weixin/messages.d.ts +24 -0
  88. package/dist/weixin/messages.js +87 -0
  89. package/dist/weixin/messages.js.map +1 -0
  90. package/dist/weixin/monitor.d.ts +22 -0
  91. package/dist/weixin/monitor.js +110 -0
  92. package/dist/weixin/monitor.js.map +1 -0
  93. package/package.json +61 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,45 @@
1
+ # Changelog
2
+
3
+ All notable changes to `codex-weixin` are documented in this file.
4
+
5
+ ## [0.2.1] - 2026-07-14
6
+
7
+ ### Changed
8
+
9
+ - Restored the README logo, feature-status tables, and screenshot locations for phone-based WeChat examples.
10
+ - Added a sanitized Web session-management preview generated from the actual local management page.
11
+
12
+ ### Fixed
13
+
14
+ - Marked the built server entry point executable so npm keeps the `codex-weixin` command in the published package.
15
+
16
+ ## [0.2.0] - 2026-07-14
17
+
18
+ ### Added
19
+
20
+ - Local-only Web management page for account, session, workspace, model, and reasoning-effort settings.
21
+ - Concurrent multi-account WeChat login and monitoring with local account remarks and sender authorization.
22
+ - Managed Codex sessions grouped by WeChat account, including history, Markdown rendering, continued chat, and create, rename, activate, reset, and delete actions.
23
+ - Web prompt attachments and history playback, preview, or download for images, videos, and files.
24
+ - WeChat inbound and outbound image, audio, video, and file handling.
25
+ - Codex app-server V2 support with dynamic model metadata and `codex exec` fallback.
26
+ - GPT-5.6 Sol, Terra, and Luna model options for the IkunCoding provider.
27
+ - Web typing state and `/status` output for the effective model and reasoning effort.
28
+
29
+ ### Changed
30
+
31
+ - Replaced the command-oriented CLI with the `codex-weixin` local server entry point.
32
+ - Unified service state and the default Codex workspace under `~/.codex-weixin`.
33
+ - Made app-server the preferred backend for both new and resumed sessions.
34
+
35
+ ### Fixed
36
+
37
+ - Prevented duplicate WeChat deliveries from producing duplicate Codex replies.
38
+ - Preserved session ownership and numbering per WeChat account when creating sessions from the Web page.
39
+ - Restored connection and history continuation for newly created Web sessions.
40
+ - Displayed Codex-generated media in Web session history.
41
+ - Kept GPT-5.6 options available after selecting a different model.
42
+ - Removed extra message spacing and hid internal WeChat and Codex routing identifiers from the normal UI.
43
+
44
+ [0.2.1]: https://github.com/XavierJiezou/codex-weixin/releases/tag/v0.2.1
45
+ [0.2.0]: https://github.com/XavierJiezou/codex-weixin/releases/tag/v0.2.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Xuechao Zou
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,5 @@
1
+ codex-weixin is a clean-room independent WeChat bridge for OpenAI Codex.
2
+
3
+ The project structure and protocol boundaries were informed by the MIT-licensed
4
+ Tencent/openclaw-weixin package and by public documentation in the WeChat/Codex
5
+ bridge ecosystem. Source code from AGPL-licensed projects is not copied.
package/README.en.md ADDED
@@ -0,0 +1,200 @@
1
+ <h1 align="center">codex-weixin</h1>
2
+
3
+ <p align="center">
4
+ <img src="docs/images/codex-weixin-logo.png" alt="codex-weixin logo" width="480" />
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="./README.md">中文</a> | <strong>English</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <strong>Connect multiple personal WeChat accounts to a local OpenAI Codex installation.</strong>
13
+ </p>
14
+
15
+ `codex-weixin` is a cross-platform, local-only WeChat service dedicated to Codex. Starting it opens a Web management page where users scan a WeChat QR code, manage accounts and workspaces, and switch Codex sessions.
16
+
17
+ ```text
18
+ Multiple WeChat accounts <-> codex-weixin <-> local Codex <-> allowed workspaces
19
+ ```
20
+
21
+ It is not a general messaging gateway. The management page is never exposed to the LAN or public Internet.
22
+
23
+ ## Feature status
24
+
25
+ Screenshots live under `docs/images/screenshots/`. The Web management screenshot is included; rows that require a phone view reserve stable filenames for later WeChat captures.
26
+
27
+ | Status | Feature | Details | Screenshot |
28
+ | --- | --- | --- | --- |
29
+ | ✅ | Local Web management | A `127.0.0.1`-only page manages WeChat accounts, sessions, workspaces, and Codex settings. | [Web sessions](docs/images/screenshots/web-session-management.png) |
30
+ | ✅ | Multiple WeChat accounts | One service runs multiple accounts with local remarks and isolated authorization, attachments, and sessions. | [Web sessions](docs/images/screenshots/web-session-management.png) |
31
+ | ✅ | Browser QR connection | Shows waiting, scanned, connected, and expired QR states. | Pending: `docs/images/screenshots/wechat-qr-login.png` |
32
+ | ✅ | Session management | Grouped account tabs, Markdown history, continued Codex threads, and create, rename, activate, reset, and delete actions. | [Web sessions](docs/images/screenshots/web-session-management.png) |
33
+ | ✅ | Web text and attachments | Send text with up to 10 files (50 MB total), with media playback, preview, and download in history. | Pending: `docs/images/screenshots/web-attachments.png` |
34
+ | ✅ | WeChat private-chat control | Supports regular messages plus `/status`, `/new`, `/bind`, `/prompt start`, `/prompt done`, and `/stop`. | Pending: `docs/images/screenshots/wechat-chat.png` |
35
+ | ✅ | WeChat media input | Accepts transcribed voice, images, audio, video, and files as local Codex attachments. | Pending: `docs/images/screenshots/wechat-media-input.png` |
36
+ | ✅ | File delivery to WeChat | Codex can return local images, videos, and files as native WeChat messages. | Pending: `docs/images/screenshots/wechat-media-output.png` |
37
+ | ✅ | Models and reasoning effort | Model-aware dropdowns loaded from app-server, including GPT-5.6 Sol, Terra, and Luna for IkunCoding. | Pending: `docs/images/screenshots/web-model-settings.png` |
38
+ | ✅ | Typing state and deduplication | Web typing state plus persistent sync cursors and message IDs prevent duplicate replies. | Pending: `docs/images/screenshots/wechat-typing.png` |
39
+ | ✅ | App-server first | New and resumed sessions prefer Codex app-server V2 and fall back to `codex exec` when unavailable. | Pending: `docs/images/screenshots/wechat-status.png` |
40
+
41
+ ## Web management preview
42
+
43
+ <p align="center">
44
+ <img src="docs/images/screenshots/web-session-management.png" alt="codex-weixin Web session management" width="100%" />
45
+ </p>
46
+
47
+ ## Requirements
48
+
49
+ - Node.js `>=22`
50
+ - Git
51
+ - An installed and authenticated Codex CLI
52
+
53
+ ```bash
54
+ npm install -g @openai/codex
55
+ codex --version
56
+ codex
57
+ ```
58
+
59
+ ## Install and start
60
+
61
+ Install globally from npm:
62
+
63
+ ```bash
64
+ npm install -g codex-weixin
65
+ codex-weixin
66
+ ```
67
+
68
+ Or install from source:
69
+
70
+ ```bash
71
+ git clone https://github.com/XavierJiezou/codex-weixin.git
72
+ cd codex-weixin
73
+ npm install
74
+ npm run build
75
+ npm install -g .
76
+ codex-weixin
77
+ ```
78
+
79
+ The service opens [http://127.0.0.1:8787](http://127.0.0.1:8787). To run without a global install:
80
+
81
+ ```bash
82
+ npm start
83
+ ```
84
+
85
+ ## First connection
86
+
87
+ 1. Open Settings and confirm the default and allowed Codex workspaces.
88
+ 2. Select Add WeChat, scan the QR code, and confirm in WeChat.
89
+ 3. Send any message to the connected account.
90
+ 4. Return to WeChat Accounts and allow the pending sender.
91
+ 5. Send the message again to start a Codex turn.
92
+
93
+ Repeat the QR flow to add more accounts. Every account has its own monitor, sender authorization, inbound directory, and managed-session state. A failed account does not stop the others.
94
+
95
+ ## Session management
96
+
97
+ The Sessions page manages conversations created and used by this server. It does not scan or take ownership of every Codex conversation created in other terminals.
98
+
99
+ Selecting a session reads its user messages and final replies from Codex's own persisted thread. The Web composer can submit text and multiple files as one turn and continues that same thread, so context remains shared with later WeChat messages. Uploads are isolated by account and session under `~/.codex-weixin/inbound/`, with at most 10 files and 50 MB total per turn.
100
+
101
+ The UI does not display `@im.bot`, `@im.wechat`, or Codex thread IDs. The first two are internal iLink routing identifiers, not profile names. Each account can have a local remark edited from the WeChat Accounts page; the remark is reused by session tabs, with `WeChat Account 1` used only as a fallback. The current QR and messaging APIs do not expose WeChat nicknames, avatars, or a profile lookup endpoint, so the page uses a default icon while retaining those identifiers only in local state for correct routing.
102
+
103
+ - Each authorized WeChat account has one active session and may own multiple named sessions.
104
+ - Activate chooses which Codex thread receives the sender's next message.
105
+ - Reset clears the recorded thread so the next message starts fresh context.
106
+ - Delete removes only the bridge record, not Codex's own history files.
107
+ - `/new` creates a new managed session for the current sender.
108
+
109
+ ## WeChat commands
110
+
111
+ ```text
112
+ /help Show commands
113
+ /status Show session, workspace, thread, backend, effective model, and reasoning effort
114
+ /bind <absolute-path> Bind to an allowed workspace
115
+ /new Create a new managed Codex session
116
+ /prompt start Buffer multiple WeChat messages
117
+ /prompt done Submit the buffer as one Codex turn
118
+ /stop Interrupt the current Codex task
119
+ ```
120
+
121
+ Regular messages enter the active session. Images, files, videos, and voice/audio without transcription are saved under the account's inbound directory and added to the prompt by local path. WeChat voice transcription is preferred when available.
122
+
123
+ ## Sending local files
124
+
125
+ Codex can request local-file delivery in its final response:
126
+
127
+ ````text
128
+ ```codex-weixin-actions
129
+ {
130
+ "send": [
131
+ { "type": "image", "path": "/absolute/path/chart.png" },
132
+ { "type": "video", "path": "/absolute/path/demo.mp4" },
133
+ { "type": "file", "path": "/absolute/path/report.pdf" }
134
+ ]
135
+ }
136
+ ```
137
+ ````
138
+
139
+ Only absolute local paths are accepted. Native outbound types are `image`, `video`, and `file`; audio is sent as a regular file. Remote URLs are not uploaded as local files.
140
+
141
+ ## Codex backend
142
+
143
+ The default `codexBackend` is `auto`. On the first Codex message, the service starts one persistent `codex app-server --stdio` process and uses the current `initialize`, `thread/*`, and `turn/*` protocol. New and resumed conversations prefer app-server; startup, handshake, or request failures automatically fall back to `codex exec` or `codex exec resume`.
144
+
145
+ WeChat does not currently expose Codex approval prompts, so app-server uses `approvalPolicy: "never"` and operates only within the configured Codex sandbox instead of waiting for an approval that cannot be answered in WeChat. The management page can still pin the backend to `app-server` or `exec` for diagnostics.
146
+
147
+ ## Models and reasoning effort
148
+
149
+ The Settings page loads available models and model-specific reasoning efforts from Codex app-server. Leaving a field on "Use Codex settings" preserves the Codex configuration; choosing and saving an explicit value applies it to later Web and WeChat turns.
150
+
151
+ The IkunCoding provider also exposes `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna`. These options remain available after switching to another model. Send `/status` in WeChat to inspect the effective model and reasoning effort.
152
+
153
+ ## Local data
154
+
155
+ Service state and the default Codex workspace share this directory:
156
+
157
+ ```text
158
+ ~/.codex-weixin/
159
+ accounts/ One credential file per WeChat account
160
+ runtime/<account-id>/ Sender authorization and managed sessions
161
+ inbound/<account-id>/ Inbound WeChat attachments
162
+ config.json Codex and workspace configuration
163
+ logs/
164
+ ```
165
+
166
+ Do not commit or share this directory. The management API never returns WeChat tokens to the browser.
167
+
168
+ ## Startup settings
169
+
170
+ The server always binds to `127.0.0.1`. Environment variables can change its port and state directory or disable automatic browser opening:
171
+
172
+ ```text
173
+ CODEX_WEIXIN_PORT=8787
174
+ CODEX_WEIXIN_STATE_DIR=/absolute/private/path
175
+ CODEX_WEIXIN_OPEN=0
176
+ ```
177
+
178
+ ## Security model
179
+
180
+ - Non-local Host and Origin values are rejected.
181
+ - Every mutating API call requires an in-memory page token.
182
+ - WeChat credentials never reach the management page.
183
+ - Unknown senders are denied until explicitly allowed.
184
+ - `/bind` accepts only absolute paths under the workspace allowlist.
185
+ - `danger-full-access` bypasses the Codex filesystem sandbox and must be enabled only when full-machine access is acceptable.
186
+ - Concurrent accounts share local compute resources and Codex quotas.
187
+
188
+ ## Development
189
+
190
+ ```bash
191
+ npm install
192
+ npm run dev
193
+ npm test
194
+ npm run typecheck
195
+ npm run build
196
+ ```
197
+
198
+ The project is a clean-room independent implementation under the MIT License. Its iLink integration shape references `Tencent/openclaw-weixin`, along with public Codex/WeChat projects for app-server, media-transfer, and security-boundary practices. No AGPL source code was copied.
199
+
200
+ See [CHANGELOG.md](./CHANGELOG.md) for release history.
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ <h1 align="center">codex-weixin</h1>
2
+
3
+ <p align="center">
4
+ <img src="docs/images/codex-weixin-logo.png" alt="codex-weixin logo" width="480" />
5
+ </p>
6
+
7
+ <p align="center">
8
+ <strong>中文</strong> | <a href="./README.en.md">English</a>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <strong>把多个个人微信账号接入本机 OpenAI Codex。</strong>
13
+ </p>
14
+
15
+ `codex-weixin` 是一个跨平台、本机运行的微信到 Codex 专用服务。启动后会打开 Web 管理页;用户在页面扫码登录微信,即可从微信私聊控制本机 Codex、管理工作目录和切换会话。
16
+
17
+ ```text
18
+ 多个微信账号 <-> codex-weixin <-> 本机 Codex <-> 允许的工作目录
19
+ ```
20
+
21
+ 它不是通用消息网关,不接入其他聊天平台,也不把管理页面开放到局域网或公网。
22
+
23
+ ## 功能状态
24
+
25
+ 截图统一放在 `docs/images/screenshots/`。Web 管理页截图已补齐;需要手机微信画面的功能保留了固定文件名,后续可直接补图。
26
+
27
+ | 状态 | 功能 | 说明 | 截图 |
28
+ | --- | --- | --- | --- |
29
+ | ✅ | 本机 Web 管理 | 页面只监听 `127.0.0.1`,集中管理微信账号、会话、工作目录和 Codex 设置。 | [Web 会话管理](docs/images/screenshots/web-session-management.png) |
30
+ | ✅ | 多微信账号 | 一个服务并行运行多个微信账号,支持本机备注、独立授权、独立附件与会话状态。 | [Web 会话管理](docs/images/screenshots/web-session-management.png) |
31
+ | ✅ | 网页扫码接入 | 显示等待扫码、已扫码、已连接和二维码过期状态。 | 待补:`docs/images/screenshots/wechat-qr-login.png` |
32
+ | ✅ | 会话管理 | 按微信账号分类,查看 Markdown 历史并继续同一 Codex thread;支持新建、重命名、切换、重置和删除。 | [Web 会话管理](docs/images/screenshots/web-session-management.png) |
33
+ | ✅ | Web 文本与附件 | 一次发送文本和最多 10 个文件(合计 50 MB),历史中可播放、预览或下载媒体。 | 待补:`docs/images/screenshots/web-attachments.png` |
34
+ | ✅ | 微信私聊控制 | 支持普通消息和 `/status`、`/new`、`/bind`、`/prompt start`、`/prompt done`、`/stop`。 | 待补:`docs/images/screenshots/wechat-chat.png` |
35
+ | ✅ | 微信多媒体输入 | 接收语音转写、图片、音频、视频和文件,并以本机附件交给 Codex。 | 待补:`docs/images/screenshots/wechat-media-input.png` |
36
+ | ✅ | 文件回传微信 | Codex 可把本机图片、视频和文件作为微信原生消息发回。 | 待补:`docs/images/screenshots/wechat-media-output.png` |
37
+ | ✅ | 模型和推理强度 | 从 app-server 读取模型能力并通过下拉列表切换;IkunCoding 支持 GPT-5.6 Sol、Terra 和 Luna。 | 待补:`docs/images/screenshots/web-model-settings.png` |
38
+ | ✅ | 输入状态与去重 | Web 显示“对方正在输入…”,并持久记录同步游标和消息 ID,防止重复回复。 | 待补:`docs/images/screenshots/wechat-typing.png` |
39
+ | ✅ | App-server 优先 | 新旧会话优先使用 Codex app-server V2;不可用时自动回退到 `codex exec`。 | 待补:`docs/images/screenshots/wechat-status.png` |
40
+
41
+ ## Web 管理页预览
42
+
43
+ <p align="center">
44
+ <img src="docs/images/screenshots/web-session-management.png" alt="codex-weixin Web 会话管理页面" width="100%" />
45
+ </p>
46
+
47
+ ## 环境要求
48
+
49
+ - Node.js `>=22`
50
+ - Git
51
+ - 已安装并登录 Codex CLI
52
+
53
+ ```bash
54
+ npm install -g @openai/codex
55
+ codex --version
56
+ codex
57
+ ```
58
+
59
+ ## 安装
60
+
61
+ 推荐从 npm 全局安装:
62
+
63
+ ```bash
64
+ npm install -g codex-weixin
65
+ codex-weixin
66
+ ```
67
+
68
+ 也可以从源码安装:
69
+
70
+ ```bash
71
+ git clone https://github.com/XavierJiezou/codex-weixin.git
72
+ cd codex-weixin
73
+ npm install
74
+ npm run build
75
+ npm install -g .
76
+ ```
77
+
78
+ 服务会自动打开 [http://127.0.0.1:8787](http://127.0.0.1:8787)。如果不希望全局安装,也可以在项目目录运行:
79
+
80
+ ```bash
81
+ npm start
82
+ ```
83
+
84
+ ## 第一次接入微信
85
+
86
+ 1. 打开管理页,在“设置”中确认 Codex 默认工作目录和允许的工作目录。
87
+ 2. 点击“添加微信”,使用微信扫描页面二维码并确认登录。
88
+ 3. 在微信中给新接入的账号发送任意消息。
89
+ 4. 回到“微信账号”,允许页面中出现的待授权联系人。
90
+ 5. 再次从微信发送消息,Codex 会在默认工作目录中开始处理。
91
+
92
+ 继续添加账号时重复扫码即可。每个账号都有独立的轮询任务、联系人授权、入站文件和会话状态;单个账号发生错误不会停止其他账号。
93
+
94
+ ## 会话管理
95
+
96
+ “会话”页面只管理由本服务创建和使用的 Codex 会话,不扫描或接管其他终端产生的全部 Codex 历史记录。
97
+
98
+ 选择一个会话后,右侧会从 Codex 自身保存的 thread 中读取历史用户消息和最终回复。可以直接在页面底部继续聊天,并通过回形针按钮将文本提示词和多个文件作为同一个 turn 发送;Web 和微信共用同一个 thread,上下文会保持连续。上传文件按微信账号和会话隔离保存在 `~/.codex-weixin/inbound/`,每次最多 10 个、合计不超过 50 MB。
99
+
100
+ 页面不显示 `@im.bot`、`@im.wechat` 和 Codex thread id。前两者是微信 iLink 用于账号、联系人路由的内部标识,并不是昵称。可以在“微信账号”页面给账号设置只保存在本机的备注;备注会同步用于会话标签。未设置备注时才使用“微信账号 1”这类默认名称。当前扫码和消息接口没有提供微信昵称、头像或个人资料查询能力,因此页面使用默认图标;这些内部标识仍只在本机状态文件中保存,以保证消息能投递到正确账号和联系人。
101
+
102
+ - 每个已授权微信账号有一个当前活动会话,也可以拥有多个命名会话。
103
+ - “切换”决定该联系人下一条微信消息继续哪个 Codex thread。
104
+ - “重置”清空本服务记录的 thread,下一条消息创建新上下文。
105
+ - “删除”只删除本服务中的会话记录,不删除 Codex 自身保存的历史文件。
106
+ - 微信中的 `/new` 会立即为当前联系人创建新的受管会话。
107
+
108
+ ## 微信内命令
109
+
110
+ ```text
111
+ /help 查看命令
112
+ /status 查看当前会话、工作目录、thread、backend、实际模型和推理强度
113
+ /bind <absolute-path> 绑定到允许列表内的工作目录
114
+ /new 创建新的受管 Codex 会话
115
+ /prompt start 开始缓冲多条微信消息
116
+ /prompt done 将缓冲内容作为一次 Codex turn 提交
117
+ /stop 中断当前 Codex 任务
118
+ ```
119
+
120
+ 普通消息直接进入当前活动会话。图片、文件、视频和无转写语音会先保存到账号独立的入站目录,再以本地路径加入 prompt;有微信转写文本的语音优先使用转写文本。
121
+
122
+ ## 文件回传
123
+
124
+ Codex 可以在最终回复中声明需要发送的本机文件:
125
+
126
+ ````text
127
+ ```codex-weixin-actions
128
+ {
129
+ "send": [
130
+ { "type": "image", "path": "/absolute/path/chart.png" },
131
+ { "type": "video", "path": "/absolute/path/demo.mp4" },
132
+ { "type": "file", "path": "/absolute/path/report.pdf" }
133
+ ]
134
+ }
135
+ ```
136
+ ````
137
+
138
+ 只接受本机绝对路径。原生出站类型为 `image`、`video` 和 `file`;音频按普通文件发送。远程 URL 不会被当作本机文件上传。
139
+
140
+ ## Codex 后端
141
+
142
+ 默认的 `codexBackend` 是 `auto`。第一次收到 Codex 消息时,服务会启动一个持久的 `codex app-server --stdio` 进程,并使用新版 `initialize`、`thread/*` 和 `turn/*` 协议。新会话和已有会话都优先通过 app-server 运行;如果 app-server 无法启动、握手或处理请求,会自动回退到 `codex exec` 或 `codex exec resume`。
143
+
144
+ 微信端目前没有 Codex 审批弹窗,因此 app-server 使用 `approvalPolicy: "never"`,只在现有 Codex sandbox 权限内执行,不会等待一个无法在微信中回答的本机审批请求。管理页仍可把后端固定为 `app-server` 或 `exec`,用于排查问题。
145
+
146
+ ## 模型和推理强度
147
+
148
+ “设置”页面会从 Codex app-server 读取可用模型和各模型支持的推理强度。选择“沿用 Codex 设置”时使用 Codex 自身配置;选择具体模型或推理强度并保存后,后续 Web 和微信消息都会使用该配置。
149
+
150
+ IkunCoding 提供方会额外显示 `gpt-5.6-sol`、`gpt-5.6-terra` 和 `gpt-5.6-luna`。切换到其他模型后,这三项仍会保留在下拉列表中。微信发送 `/status` 可以查看当前生效的模型和推理强度。
151
+
152
+ ## 本地数据
153
+
154
+ 服务状态和默认 Codex 工作目录统一放在:
155
+
156
+ ```text
157
+ ~/.codex-weixin/
158
+ accounts/ 微信账号凭据,每个账号一个文件
159
+ runtime/<account-id>/ 联系人授权和受管会话状态
160
+ inbound/<account-id>/ 微信入站附件
161
+ config.json Codex 和工作区配置
162
+ logs/
163
+ ```
164
+
165
+ 不要提交或分享该目录。管理 API 不会把微信 token 返回给浏览器。
166
+
167
+ ## 启动设置
168
+
169
+ 服务始终只绑定 `127.0.0.1`。可以通过环境变量改变端口、状态目录或关闭自动打开浏览器:
170
+
171
+ ```text
172
+ CODEX_WEIXIN_PORT=8787
173
+ CODEX_WEIXIN_STATE_DIR=/absolute/private/path
174
+ CODEX_WEIXIN_OPEN=0
175
+ ```
176
+
177
+ Windows PowerShell 示例:
178
+
179
+ ```powershell
180
+ $env:CODEX_WEIXIN_OPEN="0"
181
+ codex-weixin
182
+ ```
183
+
184
+ ## 安全边界
185
+
186
+ - Web 服务只监听本机,拒绝非本机 Host 和 Origin。
187
+ - 所有修改 API 都需要页面运行时临时令牌。
188
+ - 微信凭据永远不返回管理页面。
189
+ - 未知联系人默认拒绝,必须在管理页明确允许。
190
+ - `/bind` 只能选择允许列表内的绝对工作目录。
191
+ - `danger-full-access` 会绕过 Codex 文件系统 sandbox;只有接受整机访问风险时才启用。
192
+ - 多账号可以并行触发 Codex,会共同占用本机 CPU、内存和 Codex 配额。
193
+
194
+ ## 开发
195
+
196
+ ```bash
197
+ npm install
198
+ npm run dev
199
+ npm test
200
+ npm run typecheck
201
+ npm run build
202
+ ```
203
+
204
+ 开发入口同样只启动本机 Web 服务。浏览器页面、JSON API、多账号运行时、扫码状态机和受管会话都有自动化测试。
205
+
206
+ ## 参考与许可
207
+
208
+ 项目是独立实现,微信 iLink 接入形态参考 `Tencent/openclaw-weixin`,并参考了公开的 Codex/微信桥接项目在 Codex app-server、媒体传输和安全边界方面的实践。项目未复制 AGPL 项目源码,使用 MIT License。
209
+
210
+ 版本变更见 [CHANGELOG.md](./CHANGELOG.md)。
@@ -0,0 +1,21 @@
1
+ export type AccessDecision = {
2
+ allowed: true;
3
+ message: string;
4
+ } | {
5
+ allowed: false;
6
+ message: string;
7
+ };
8
+ export type AccessControllerOptions = {
9
+ allowedSenderIds?: string[];
10
+ pairedSenderIds?: string[];
11
+ };
12
+ export declare class AccessController {
13
+ private readonly configuredAllowlist;
14
+ private readonly pairedSenderIds;
15
+ constructor(options?: AccessControllerOptions);
16
+ isAllowed(senderId: string): boolean;
17
+ requireAccess(senderId: string): AccessDecision;
18
+ allow(senderId: string): void;
19
+ remove(senderId: string): void;
20
+ listPairedSenderIds(): string[];
21
+ }
@@ -0,0 +1,31 @@
1
+ export class AccessController {
2
+ configuredAllowlist;
3
+ pairedSenderIds;
4
+ constructor(options = {}) {
5
+ this.configuredAllowlist = new Set(options.allowedSenderIds ?? []);
6
+ this.pairedSenderIds = new Set(options.pairedSenderIds ?? []);
7
+ }
8
+ isAllowed(senderId) {
9
+ return this.configuredAllowlist.has(senderId) || this.pairedSenderIds.has(senderId);
10
+ }
11
+ requireAccess(senderId) {
12
+ if (this.isAllowed(senderId)) {
13
+ return { allowed: true, message: "sender is allowed" };
14
+ }
15
+ return {
16
+ allowed: false,
17
+ message: `Access denied. Open the codex-weixin management page and allow sender: ${senderId}`
18
+ };
19
+ }
20
+ allow(senderId) {
21
+ this.pairedSenderIds.add(senderId);
22
+ }
23
+ remove(senderId) {
24
+ this.pairedSenderIds.delete(senderId);
25
+ this.configuredAllowlist.delete(senderId);
26
+ }
27
+ listPairedSenderIds() {
28
+ return [...this.pairedSenderIds].sort();
29
+ }
30
+ }
31
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../../src/bridge/access.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,gBAAgB;IACV,mBAAmB,CAAc;IACjC,eAAe,CAAc;IAE9C,YAAY,UAAmC,EAAE;QAC/C,IAAI,CAAC,mBAAmB,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,SAAS,CAAC,QAAgB;QACxB,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtF,CAAC;IAED,aAAa,CAAC,QAAgB;QAC5B,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;QACzD,CAAC;QAED,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,0EAA0E,QAAQ,EAAE;SAC9F,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAgB;QACpB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,QAAgB;QACrB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,mBAAmB;QACjB,OAAO,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ export type SendAction = {
2
+ type: "image" | "file" | "video";
3
+ path: string;
4
+ };
5
+ export type ControlAction = {
6
+ type: "workspace.set";
7
+ path: string;
8
+ } | {
9
+ type: "workspace.reset";
10
+ } | {
11
+ type: "thread.reset";
12
+ };
13
+ export type BridgeActions = {
14
+ send: SendAction[];
15
+ control: ControlAction[];
16
+ };
17
+ export type ParsedActionBlocks = {
18
+ visibleText: string;
19
+ actions: BridgeActions;
20
+ };
21
+ export declare function parseActionBlocks(text: string): ParsedActionBlocks;