codex-weixin 0.3.7 → 0.3.8
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/CHANGELOG.md +222 -216
- package/LICENSE +21 -21
- package/NOTICE +5 -5
- package/README.en.md +216 -216
- package/dist/server/index.js +0 -0
- package/dist/server/update-manager.js +1 -0
- package/dist/server/update-manager.js.map +1 -1
- package/dist/web/app.js +1452 -1452
- package/dist/web/favicon.svg +10 -10
- package/dist/web/index.html +390 -390
- package/dist/web/styles.css +418 -418
- package/package.json +62 -62
- package/src/web/favicon.svg +10 -10
package/dist/web/index.html
CHANGED
|
@@ -1,390 +1,390 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<meta name="color-scheme" content="light">
|
|
7
|
-
<title>codex-weixin</title>
|
|
8
|
-
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
|
9
|
-
<link rel="stylesheet" href="/styles.css">
|
|
10
|
-
<script defer src="/vendor/lucide.min.js"></script>
|
|
11
|
-
<script defer src="/vendor/marked.umd.js"></script>
|
|
12
|
-
<script defer src="/vendor/purify.min.js"></script>
|
|
13
|
-
<script defer src="/app.js"></script>
|
|
14
|
-
</head>
|
|
15
|
-
<body>
|
|
16
|
-
<header class="app-header">
|
|
17
|
-
<div class="header-inner">
|
|
18
|
-
<a class="brand" href="#accounts" aria-label="codex-weixin 首页">
|
|
19
|
-
<span class="brand-mark" aria-hidden="true">
|
|
20
|
-
<i data-lucide="terminal-square"></i>
|
|
21
|
-
<i data-lucide="message-circle"></i>
|
|
22
|
-
</span>
|
|
23
|
-
<span class="brand-name">codex-weixin</span>
|
|
24
|
-
<span class="brand-version" id="productVersion" aria-label="codex-weixin 版本" hidden></span>
|
|
25
|
-
</a>
|
|
26
|
-
<nav class="view-tabs" aria-label="管理视图">
|
|
27
|
-
<button class="tab is-active" type="button" data-view="accounts">微信账号</button>
|
|
28
|
-
<button class="tab" type="button" data-view="sessions">会话</button>
|
|
29
|
-
<button class="tab" type="button" data-view="settings">设置</button>
|
|
30
|
-
</nav>
|
|
31
|
-
<div class="header-actions">
|
|
32
|
-
<a class="icon-button github-link" href="https://github.com/XavierJiezou/codex-weixin" target="_blank" rel="noopener noreferrer" title="前往 GitHub" aria-label="前往 codex-weixin GitHub 仓库">
|
|
33
|
-
<i data-lucide="github"></i>
|
|
34
|
-
</a>
|
|
35
|
-
<button class="button button-primary header-action" id="addAccountButton" type="button" title="添加微信" aria-label="添加微信">
|
|
36
|
-
<i data-lucide="scan-line"></i>
|
|
37
|
-
<span>添加微信</span>
|
|
38
|
-
</button>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
</header>
|
|
42
|
-
|
|
43
|
-
<main>
|
|
44
|
-
<section class="status-band" aria-label="服务概览">
|
|
45
|
-
<div class="status-inner">
|
|
46
|
-
<div class="service-state"><span class="pulse-dot" id="serviceDot"></span><span id="serviceStateText">正在检查 Codex</span></div>
|
|
47
|
-
<dl class="metrics">
|
|
48
|
-
<div><dt>运行账号</dt><dd id="runningAccountMetric">0</dd></div>
|
|
49
|
-
<div><dt>受管会话</dt><dd id="sessionMetric">0</dd></div>
|
|
50
|
-
<div class="workspace-metric"><dt>Codex 工作目录</dt><dd id="workspaceMetric">--</dd></div>
|
|
51
|
-
</dl>
|
|
52
|
-
</div>
|
|
53
|
-
</section>
|
|
54
|
-
|
|
55
|
-
<section class="view is-visible" id="accountsView" data-view-panel="accounts">
|
|
56
|
-
<div class="section-heading">
|
|
57
|
-
<div>
|
|
58
|
-
<p class="eyebrow">WECHAT ACCOUNTS</p>
|
|
59
|
-
<h1>微信账号</h1>
|
|
60
|
-
</div>
|
|
61
|
-
<button class="icon-button" id="refreshAccountsButton" type="button" title="刷新账号状态" aria-label="刷新账号状态">
|
|
62
|
-
<i data-lucide="refresh-cw"></i>
|
|
63
|
-
</button>
|
|
64
|
-
</div>
|
|
65
|
-
<div id="accountsList" class="account-list" aria-live="polite"></div>
|
|
66
|
-
</section>
|
|
67
|
-
|
|
68
|
-
<section class="view" id="sessionsView" data-view-panel="sessions" hidden>
|
|
69
|
-
<div class="section-heading">
|
|
70
|
-
<div>
|
|
71
|
-
<p class="eyebrow">CODEX SESSIONS</p>
|
|
72
|
-
<h1>会话</h1>
|
|
73
|
-
</div>
|
|
74
|
-
<button class="button button-secondary" id="newSessionButton" type="button">
|
|
75
|
-
<i data-lucide="plus"></i>
|
|
76
|
-
<span>新建会话</span>
|
|
77
|
-
</button>
|
|
78
|
-
</div>
|
|
79
|
-
<div class="session-account-bar" aria-label="微信账号筛选">
|
|
80
|
-
<span class="session-account-bar-label"><i data-lucide="users"></i><span>微信账号</span></span>
|
|
81
|
-
<div class="session-account-tabs" id="sessionAccountTabs" aria-label="按微信账号筛选会话"></div>
|
|
82
|
-
</div>
|
|
83
|
-
<div class="session-workbench">
|
|
84
|
-
<aside class="session-sidebar" aria-label="Codex 会话列表">
|
|
85
|
-
<div class="session-sidebar-head">
|
|
86
|
-
<span>历史会话</span>
|
|
87
|
-
<span id="sessionListCount">0</span>
|
|
88
|
-
</div>
|
|
89
|
-
<div id="sessionsList" class="session-list" aria-live="polite"></div>
|
|
90
|
-
</aside>
|
|
91
|
-
<section class="chat-panel" id="sessionChatPanel" aria-label="会话消息">
|
|
92
|
-
<header class="chat-header" id="chatHeader">
|
|
93
|
-
<div>
|
|
94
|
-
<p class="eyebrow">THREAD HISTORY</p>
|
|
95
|
-
<h2 id="chatTitle">选择一个会话</h2>
|
|
96
|
-
<p class="chat-context" id="chatContext">查看历史消息并继续聊天</p>
|
|
97
|
-
</div>
|
|
98
|
-
<button class="icon-button" id="refreshMessagesButton" type="button" title="刷新消息" aria-label="刷新消息" disabled>
|
|
99
|
-
<i data-lucide="refresh-cw"></i>
|
|
100
|
-
</button>
|
|
101
|
-
</header>
|
|
102
|
-
<div class="chat-runtime-toolbar" id="sessionRuntimeToolbar" aria-label="当前会话模型设置">
|
|
103
|
-
<span class="chat-runtime-title"><i data-lucide="sliders-horizontal"></i><span>会话设置</span></span>
|
|
104
|
-
<label>
|
|
105
|
-
<span>模型</span>
|
|
106
|
-
<select id="sessionModelInput" disabled><option value="">继承全局设置</option></select>
|
|
107
|
-
</label>
|
|
108
|
-
<label>
|
|
109
|
-
<span>推理强度</span>
|
|
110
|
-
<select id="sessionEffortInput" disabled><option value="">继承全局设置</option></select>
|
|
111
|
-
</label>
|
|
112
|
-
<label>
|
|
113
|
-
<span>过程进度</span>
|
|
114
|
-
<select id="sessionStreamInput" disabled>
|
|
115
|
-
<option value="">继承全局设置</option>
|
|
116
|
-
<option value="on">开启</option>
|
|
117
|
-
<option value="off">关闭</option>
|
|
118
|
-
</select>
|
|
119
|
-
</label>
|
|
120
|
-
</div>
|
|
121
|
-
<div class="chat-messages" id="chatMessages" aria-live="polite"></div>
|
|
122
|
-
<form class="chat-composer" id="chatComposer">
|
|
123
|
-
<div class="composer-files" id="composerFiles" aria-live="polite" hidden></div>
|
|
124
|
-
<div class="composer-controls">
|
|
125
|
-
<button class="icon-button chat-attach" id="chatAttachButton" type="button" title="添加附件" aria-label="添加附件" disabled>
|
|
126
|
-
<i data-lucide="paperclip"></i>
|
|
127
|
-
</button>
|
|
128
|
-
<input id="chatFileInput" type="file" multiple hidden disabled>
|
|
129
|
-
<label class="sr-only" for="chatInput">继续聊天</label>
|
|
130
|
-
<textarea id="chatInput" rows="2" maxlength="100000" placeholder="给 Codex 发送消息…" disabled></textarea>
|
|
131
|
-
<button class="button button-primary chat-send" id="chatSendButton" type="submit" disabled>
|
|
132
|
-
<i data-lucide="send"></i>
|
|
133
|
-
<span>发送</span>
|
|
134
|
-
</button>
|
|
135
|
-
</div>
|
|
136
|
-
<p class="composer-hint">Enter 发送 · Shift + Enter 换行</p>
|
|
137
|
-
</form>
|
|
138
|
-
</section>
|
|
139
|
-
</div>
|
|
140
|
-
</section>
|
|
141
|
-
|
|
142
|
-
<section class="view settings-view" id="settingsView" data-view-panel="settings" hidden>
|
|
143
|
-
<div class="section-heading">
|
|
144
|
-
<div>
|
|
145
|
-
<p class="eyebrow">LOCAL CODEX</p>
|
|
146
|
-
<h1>设置</h1>
|
|
147
|
-
</div>
|
|
148
|
-
</div>
|
|
149
|
-
<form id="settingsForm" class="settings-form">
|
|
150
|
-
<div class="settings-group">
|
|
151
|
-
<h2>工作区</h2>
|
|
152
|
-
<label>
|
|
153
|
-
<span>默认工作目录</span>
|
|
154
|
-
<input id="defaultCwdInput" name="defaultCwd" autocomplete="off" required>
|
|
155
|
-
</label>
|
|
156
|
-
<label>
|
|
157
|
-
<span>允许的工作目录</span>
|
|
158
|
-
<textarea id="allowedWorkspacesInput" name="allowedWorkspaces" rows="5" required></textarea>
|
|
159
|
-
</label>
|
|
160
|
-
</div>
|
|
161
|
-
<div class="settings-group">
|
|
162
|
-
<h2>Codex</h2>
|
|
163
|
-
<div class="field-grid">
|
|
164
|
-
<label>
|
|
165
|
-
<span>后端</span>
|
|
166
|
-
<select id="backendInput" name="codexBackend">
|
|
167
|
-
<option value="auto">自动</option>
|
|
168
|
-
<option value="app-server">App server</option>
|
|
169
|
-
<option value="exec">Exec</option>
|
|
170
|
-
</select>
|
|
171
|
-
</label>
|
|
172
|
-
<label>
|
|
173
|
-
<span>Exec 沙箱</span>
|
|
174
|
-
<select id="sandboxInput" name="codexExecSandbox">
|
|
175
|
-
<option value="">沿用 Codex 设置</option>
|
|
176
|
-
<option value="read-only">只读</option>
|
|
177
|
-
<option value="workspace-write">工作区可写</option>
|
|
178
|
-
<option value="danger-full-access">完整访问</option>
|
|
179
|
-
</select>
|
|
180
|
-
</label>
|
|
181
|
-
<label>
|
|
182
|
-
<span>模型</span>
|
|
183
|
-
<select id="modelInput" name="model">
|
|
184
|
-
<option value="">沿用 Codex 设置</option>
|
|
185
|
-
</select>
|
|
186
|
-
<small class="field-hint effective-setting"><span>当前生效</span><strong id="effectiveModelValue">正在读取</strong></small>
|
|
187
|
-
</label>
|
|
188
|
-
<label>
|
|
189
|
-
<span>推理强度</span>
|
|
190
|
-
<select id="effortInput" name="effort">
|
|
191
|
-
<option value="">沿用模型默认</option>
|
|
192
|
-
</select>
|
|
193
|
-
<small class="field-hint effective-setting"><span>当前生效</span><strong id="effectiveEffortValue">正在读取</strong></small>
|
|
194
|
-
</label>
|
|
195
|
-
<label class="toggle-field" for="streamRepliesInput">
|
|
196
|
-
<span>过程进度</span>
|
|
197
|
-
<span class="toggle-control">
|
|
198
|
-
<input id="streamRepliesInput" name="streamReplies" type="checkbox">
|
|
199
|
-
<span aria-hidden="true"></span>
|
|
200
|
-
</span>
|
|
201
|
-
</label>
|
|
202
|
-
</div>
|
|
203
|
-
</div>
|
|
204
|
-
<div class="settings-group">
|
|
205
|
-
<h2>版本</h2>
|
|
206
|
-
<div class="settings-update">
|
|
207
|
-
<span class="settings-update-version">
|
|
208
|
-
<small>当前版本</small>
|
|
209
|
-
<strong id="settingsVersionValue">--</strong>
|
|
210
|
-
</span>
|
|
211
|
-
<button class="button button-secondary" id="updateCheckButton" type="button">
|
|
212
|
-
<i data-lucide="refresh-cw"></i>
|
|
213
|
-
<span>检查更新</span>
|
|
214
|
-
</button>
|
|
215
|
-
</div>
|
|
216
|
-
</div>
|
|
217
|
-
<div class="form-actions">
|
|
218
|
-
<button class="button button-primary" type="submit">
|
|
219
|
-
<i data-lucide="save"></i>
|
|
220
|
-
<span>保存设置</span>
|
|
221
|
-
</button>
|
|
222
|
-
</div>
|
|
223
|
-
</form>
|
|
224
|
-
</section>
|
|
225
|
-
</main>
|
|
226
|
-
|
|
227
|
-
<dialog class="modal update-modal" id="updateDialog" aria-labelledby="updateDialogTitle">
|
|
228
|
-
<div class="modal-header update-modal-header">
|
|
229
|
-
<div>
|
|
230
|
-
<p class="eyebrow">PRODUCT UPDATE</p>
|
|
231
|
-
<h2 id="updateDialogTitle">发现新版本</h2>
|
|
232
|
-
</div>
|
|
233
|
-
<span class="update-modal-icon" aria-hidden="true"><i data-lucide="package"></i></span>
|
|
234
|
-
</div>
|
|
235
|
-
<div class="modal-body update-modal-body">
|
|
236
|
-
<div class="update-version-flow" aria-label="版本升级">
|
|
237
|
-
<span class="update-version-item"><small>当前版本</small><strong id="updateCurrentVersion">--</strong></span>
|
|
238
|
-
<span class="update-version-divider" aria-hidden="true"></span>
|
|
239
|
-
<span class="update-version-item is-latest"><small>最新版本</small><strong id="updateLatestVersion">--</strong></span>
|
|
240
|
-
</div>
|
|
241
|
-
<p class="update-description">更新期间微信连接会短暂中断,完成后服务将自动重启并恢复连接。</p>
|
|
242
|
-
<div class="update-progress" id="updateProgress" aria-live="polite" hidden>
|
|
243
|
-
<span class="spinner" aria-hidden="true"></span>
|
|
244
|
-
<div><strong id="updateProgressTitle">正在安装更新</strong><span id="updateProgressDetail">请保持此页面打开</span></div>
|
|
245
|
-
</div>
|
|
246
|
-
</div>
|
|
247
|
-
<div class="modal-footer">
|
|
248
|
-
<button class="button button-secondary" id="updateLaterButton" type="button">稍后</button>
|
|
249
|
-
<button class="button button-primary" id="updateNowButton" type="button">
|
|
250
|
-
<i data-lucide="download"></i>
|
|
251
|
-
<span>立即更新</span>
|
|
252
|
-
</button>
|
|
253
|
-
</div>
|
|
254
|
-
</dialog>
|
|
255
|
-
|
|
256
|
-
<dialog class="modal qr-modal" id="qrDialog">
|
|
257
|
-
<div class="modal-header">
|
|
258
|
-
<div>
|
|
259
|
-
<p class="eyebrow">WECHAT LOGIN</p>
|
|
260
|
-
<h2>微信扫码登录</h2>
|
|
261
|
-
</div>
|
|
262
|
-
<button class="icon-button" type="button" data-close-dialog="qrDialog" title="关闭" aria-label="关闭扫码窗口">
|
|
263
|
-
<i data-lucide="x"></i>
|
|
264
|
-
</button>
|
|
265
|
-
</div>
|
|
266
|
-
<div class="qr-stage">
|
|
267
|
-
<div class="qr-frame" id="qrFrame">
|
|
268
|
-
<div class="spinner" aria-label="正在生成二维码"></div>
|
|
269
|
-
</div>
|
|
270
|
-
<p id="qrStatus" class="qr-status">正在生成二维码</p>
|
|
271
|
-
</div>
|
|
272
|
-
<div class="modal-footer">
|
|
273
|
-
<button class="button button-secondary" id="refreshQrButton" type="button">
|
|
274
|
-
<i data-lucide="refresh-cw"></i>
|
|
275
|
-
<span>刷新二维码</span>
|
|
276
|
-
</button>
|
|
277
|
-
</div>
|
|
278
|
-
</dialog>
|
|
279
|
-
|
|
280
|
-
<dialog class="modal" id="accountDialog">
|
|
281
|
-
<form id="accountForm" method="dialog">
|
|
282
|
-
<div class="modal-header">
|
|
283
|
-
<div>
|
|
284
|
-
<p class="eyebrow">ACCOUNT REMARK</p>
|
|
285
|
-
<h2>修改微信账号备注</h2>
|
|
286
|
-
</div>
|
|
287
|
-
<button class="icon-button" type="button" data-close-dialog="accountDialog" title="关闭" aria-label="关闭账号备注窗口">
|
|
288
|
-
<i data-lucide="x"></i>
|
|
289
|
-
</button>
|
|
290
|
-
</div>
|
|
291
|
-
<input id="editingRemarkAccountId" type="hidden">
|
|
292
|
-
<div class="modal-body form-stack">
|
|
293
|
-
<label>
|
|
294
|
-
<span>账号备注</span>
|
|
295
|
-
<input id="accountRemarkInput" maxlength="40" autocomplete="off" placeholder="例如:张三、李四">
|
|
296
|
-
<small class="field-hint">备注只保存在本机;清空后恢复默认名称。</small>
|
|
297
|
-
</label>
|
|
298
|
-
</div>
|
|
299
|
-
<div class="modal-footer">
|
|
300
|
-
<button class="button button-secondary" type="button" data-close-dialog="accountDialog">取消</button>
|
|
301
|
-
<button class="button button-primary" type="submit">
|
|
302
|
-
<i data-lucide="check"></i>
|
|
303
|
-
<span>保存</span>
|
|
304
|
-
</button>
|
|
305
|
-
</div>
|
|
306
|
-
</form>
|
|
307
|
-
</dialog>
|
|
308
|
-
|
|
309
|
-
<dialog class="modal account-removal-modal" id="removeAccountDialog" aria-labelledby="removeAccountDialogTitle">
|
|
310
|
-
<form id="removeAccountForm" method="dialog">
|
|
311
|
-
<div class="modal-header">
|
|
312
|
-
<div>
|
|
313
|
-
<p class="eyebrow">REMOVE ACCOUNT</p>
|
|
314
|
-
<h2 id="removeAccountDialogTitle">移除微信账号</h2>
|
|
315
|
-
</div>
|
|
316
|
-
<button class="icon-button" type="button" data-close-dialog="removeAccountDialog" title="关闭" aria-label="关闭移除账号窗口">
|
|
317
|
-
<i data-lucide="x"></i>
|
|
318
|
-
</button>
|
|
319
|
-
</div>
|
|
320
|
-
<input id="removingAccountId" type="hidden">
|
|
321
|
-
<div class="modal-body account-removal-body">
|
|
322
|
-
<p class="account-removal-lead">选择如何处理 <strong id="removingAccountName">此微信账号</strong> 的会话数据。</p>
|
|
323
|
-
<div class="account-removal-choices" role="radiogroup" aria-label="会话历史处理方式">
|
|
324
|
-
<label class="account-removal-choice">
|
|
325
|
-
<input type="radio" name="retainHistory" value="true" checked>
|
|
326
|
-
<span class="account-removal-option">
|
|
327
|
-
<span class="account-removal-option-icon" aria-hidden="true"><i data-lucide="archive-restore"></i></span>
|
|
328
|
-
<span><strong>保留会话历史</strong><small>账号从页面移除;同一用户重新扫码后恢复备注、授权和历史会话。</small></span>
|
|
329
|
-
</span>
|
|
330
|
-
</label>
|
|
331
|
-
<label class="account-removal-choice is-destructive">
|
|
332
|
-
<input type="radio" name="retainHistory" value="false">
|
|
333
|
-
<span class="account-removal-option">
|
|
334
|
-
<span class="account-removal-option-icon" aria-hidden="true"><i data-lucide="trash-2"></i></span>
|
|
335
|
-
<span><strong>彻底删除历史</strong><small>删除本服务保存的授权和会话状态,重新扫码后不会恢复。</small></span>
|
|
336
|
-
</span>
|
|
337
|
-
</label>
|
|
338
|
-
</div>
|
|
339
|
-
<p class="account-removal-note"><i data-lucide="shield-check"></i><span>登录凭据始终会从本机删除;保留时不会保存 token。</span></p>
|
|
340
|
-
</div>
|
|
341
|
-
<div class="modal-footer">
|
|
342
|
-
<button class="button button-secondary" type="button" data-close-dialog="removeAccountDialog">取消</button>
|
|
343
|
-
<button class="button button-danger" type="submit">
|
|
344
|
-
<i data-lucide="user-minus"></i>
|
|
345
|
-
<span>移除账号</span>
|
|
346
|
-
</button>
|
|
347
|
-
</div>
|
|
348
|
-
</form>
|
|
349
|
-
</dialog>
|
|
350
|
-
|
|
351
|
-
<dialog class="modal session-modal" id="sessionDialog">
|
|
352
|
-
<form id="sessionForm" method="dialog">
|
|
353
|
-
<div class="modal-header">
|
|
354
|
-
<div>
|
|
355
|
-
<p class="eyebrow">MANAGED SESSION</p>
|
|
356
|
-
<h2 id="sessionDialogTitle">新建会话</h2>
|
|
357
|
-
</div>
|
|
358
|
-
<button class="icon-button" type="button" data-close-dialog="sessionDialog" title="关闭" aria-label="关闭会话窗口">
|
|
359
|
-
<i data-lucide="x"></i>
|
|
360
|
-
</button>
|
|
361
|
-
</div>
|
|
362
|
-
<input id="editingSessionId" type="hidden">
|
|
363
|
-
<input id="editingAccountId" type="hidden">
|
|
364
|
-
<div class="modal-body form-stack">
|
|
365
|
-
<label id="senderField">
|
|
366
|
-
<span>微信账号</span>
|
|
367
|
-
<select id="sessionSenderInput" required></select>
|
|
368
|
-
</label>
|
|
369
|
-
<label>
|
|
370
|
-
<span>会话名称</span>
|
|
371
|
-
<input id="sessionTitleInput" maxlength="80" autocomplete="off" required>
|
|
372
|
-
</label>
|
|
373
|
-
<label id="sessionWorkspaceField">
|
|
374
|
-
<span>工作目录</span>
|
|
375
|
-
<input id="sessionWorkspaceInput" autocomplete="off" required>
|
|
376
|
-
</label>
|
|
377
|
-
</div>
|
|
378
|
-
<div class="modal-footer">
|
|
379
|
-
<button class="button button-secondary" type="button" data-close-dialog="sessionDialog">取消</button>
|
|
380
|
-
<button class="button button-primary" type="submit">
|
|
381
|
-
<i data-lucide="check"></i>
|
|
382
|
-
<span>保存</span>
|
|
383
|
-
</button>
|
|
384
|
-
</div>
|
|
385
|
-
</form>
|
|
386
|
-
</dialog>
|
|
387
|
-
|
|
388
|
-
<div class="toast-region" id="toastRegion" aria-live="polite"></div>
|
|
389
|
-
</body>
|
|
390
|
-
</html>
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<meta name="color-scheme" content="light">
|
|
7
|
+
<title>codex-weixin</title>
|
|
8
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
|
9
|
+
<link rel="stylesheet" href="/styles.css">
|
|
10
|
+
<script defer src="/vendor/lucide.min.js"></script>
|
|
11
|
+
<script defer src="/vendor/marked.umd.js"></script>
|
|
12
|
+
<script defer src="/vendor/purify.min.js"></script>
|
|
13
|
+
<script defer src="/app.js"></script>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<header class="app-header">
|
|
17
|
+
<div class="header-inner">
|
|
18
|
+
<a class="brand" href="#accounts" aria-label="codex-weixin 首页">
|
|
19
|
+
<span class="brand-mark" aria-hidden="true">
|
|
20
|
+
<i data-lucide="terminal-square"></i>
|
|
21
|
+
<i data-lucide="message-circle"></i>
|
|
22
|
+
</span>
|
|
23
|
+
<span class="brand-name">codex-weixin</span>
|
|
24
|
+
<span class="brand-version" id="productVersion" aria-label="codex-weixin 版本" hidden></span>
|
|
25
|
+
</a>
|
|
26
|
+
<nav class="view-tabs" aria-label="管理视图">
|
|
27
|
+
<button class="tab is-active" type="button" data-view="accounts">微信账号</button>
|
|
28
|
+
<button class="tab" type="button" data-view="sessions">会话</button>
|
|
29
|
+
<button class="tab" type="button" data-view="settings">设置</button>
|
|
30
|
+
</nav>
|
|
31
|
+
<div class="header-actions">
|
|
32
|
+
<a class="icon-button github-link" href="https://github.com/XavierJiezou/codex-weixin" target="_blank" rel="noopener noreferrer" title="前往 GitHub" aria-label="前往 codex-weixin GitHub 仓库">
|
|
33
|
+
<i data-lucide="github"></i>
|
|
34
|
+
</a>
|
|
35
|
+
<button class="button button-primary header-action" id="addAccountButton" type="button" title="添加微信" aria-label="添加微信">
|
|
36
|
+
<i data-lucide="scan-line"></i>
|
|
37
|
+
<span>添加微信</span>
|
|
38
|
+
</button>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</header>
|
|
42
|
+
|
|
43
|
+
<main>
|
|
44
|
+
<section class="status-band" aria-label="服务概览">
|
|
45
|
+
<div class="status-inner">
|
|
46
|
+
<div class="service-state"><span class="pulse-dot" id="serviceDot"></span><span id="serviceStateText">正在检查 Codex</span></div>
|
|
47
|
+
<dl class="metrics">
|
|
48
|
+
<div><dt>运行账号</dt><dd id="runningAccountMetric">0</dd></div>
|
|
49
|
+
<div><dt>受管会话</dt><dd id="sessionMetric">0</dd></div>
|
|
50
|
+
<div class="workspace-metric"><dt>Codex 工作目录</dt><dd id="workspaceMetric">--</dd></div>
|
|
51
|
+
</dl>
|
|
52
|
+
</div>
|
|
53
|
+
</section>
|
|
54
|
+
|
|
55
|
+
<section class="view is-visible" id="accountsView" data-view-panel="accounts">
|
|
56
|
+
<div class="section-heading">
|
|
57
|
+
<div>
|
|
58
|
+
<p class="eyebrow">WECHAT ACCOUNTS</p>
|
|
59
|
+
<h1>微信账号</h1>
|
|
60
|
+
</div>
|
|
61
|
+
<button class="icon-button" id="refreshAccountsButton" type="button" title="刷新账号状态" aria-label="刷新账号状态">
|
|
62
|
+
<i data-lucide="refresh-cw"></i>
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
<div id="accountsList" class="account-list" aria-live="polite"></div>
|
|
66
|
+
</section>
|
|
67
|
+
|
|
68
|
+
<section class="view" id="sessionsView" data-view-panel="sessions" hidden>
|
|
69
|
+
<div class="section-heading">
|
|
70
|
+
<div>
|
|
71
|
+
<p class="eyebrow">CODEX SESSIONS</p>
|
|
72
|
+
<h1>会话</h1>
|
|
73
|
+
</div>
|
|
74
|
+
<button class="button button-secondary" id="newSessionButton" type="button">
|
|
75
|
+
<i data-lucide="plus"></i>
|
|
76
|
+
<span>新建会话</span>
|
|
77
|
+
</button>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="session-account-bar" aria-label="微信账号筛选">
|
|
80
|
+
<span class="session-account-bar-label"><i data-lucide="users"></i><span>微信账号</span></span>
|
|
81
|
+
<div class="session-account-tabs" id="sessionAccountTabs" aria-label="按微信账号筛选会话"></div>
|
|
82
|
+
</div>
|
|
83
|
+
<div class="session-workbench">
|
|
84
|
+
<aside class="session-sidebar" aria-label="Codex 会话列表">
|
|
85
|
+
<div class="session-sidebar-head">
|
|
86
|
+
<span>历史会话</span>
|
|
87
|
+
<span id="sessionListCount">0</span>
|
|
88
|
+
</div>
|
|
89
|
+
<div id="sessionsList" class="session-list" aria-live="polite"></div>
|
|
90
|
+
</aside>
|
|
91
|
+
<section class="chat-panel" id="sessionChatPanel" aria-label="会话消息">
|
|
92
|
+
<header class="chat-header" id="chatHeader">
|
|
93
|
+
<div>
|
|
94
|
+
<p class="eyebrow">THREAD HISTORY</p>
|
|
95
|
+
<h2 id="chatTitle">选择一个会话</h2>
|
|
96
|
+
<p class="chat-context" id="chatContext">查看历史消息并继续聊天</p>
|
|
97
|
+
</div>
|
|
98
|
+
<button class="icon-button" id="refreshMessagesButton" type="button" title="刷新消息" aria-label="刷新消息" disabled>
|
|
99
|
+
<i data-lucide="refresh-cw"></i>
|
|
100
|
+
</button>
|
|
101
|
+
</header>
|
|
102
|
+
<div class="chat-runtime-toolbar" id="sessionRuntimeToolbar" aria-label="当前会话模型设置">
|
|
103
|
+
<span class="chat-runtime-title"><i data-lucide="sliders-horizontal"></i><span>会话设置</span></span>
|
|
104
|
+
<label>
|
|
105
|
+
<span>模型</span>
|
|
106
|
+
<select id="sessionModelInput" disabled><option value="">继承全局设置</option></select>
|
|
107
|
+
</label>
|
|
108
|
+
<label>
|
|
109
|
+
<span>推理强度</span>
|
|
110
|
+
<select id="sessionEffortInput" disabled><option value="">继承全局设置</option></select>
|
|
111
|
+
</label>
|
|
112
|
+
<label>
|
|
113
|
+
<span>过程进度</span>
|
|
114
|
+
<select id="sessionStreamInput" disabled>
|
|
115
|
+
<option value="">继承全局设置</option>
|
|
116
|
+
<option value="on">开启</option>
|
|
117
|
+
<option value="off">关闭</option>
|
|
118
|
+
</select>
|
|
119
|
+
</label>
|
|
120
|
+
</div>
|
|
121
|
+
<div class="chat-messages" id="chatMessages" aria-live="polite"></div>
|
|
122
|
+
<form class="chat-composer" id="chatComposer">
|
|
123
|
+
<div class="composer-files" id="composerFiles" aria-live="polite" hidden></div>
|
|
124
|
+
<div class="composer-controls">
|
|
125
|
+
<button class="icon-button chat-attach" id="chatAttachButton" type="button" title="添加附件" aria-label="添加附件" disabled>
|
|
126
|
+
<i data-lucide="paperclip"></i>
|
|
127
|
+
</button>
|
|
128
|
+
<input id="chatFileInput" type="file" multiple hidden disabled>
|
|
129
|
+
<label class="sr-only" for="chatInput">继续聊天</label>
|
|
130
|
+
<textarea id="chatInput" rows="2" maxlength="100000" placeholder="给 Codex 发送消息…" disabled></textarea>
|
|
131
|
+
<button class="button button-primary chat-send" id="chatSendButton" type="submit" disabled>
|
|
132
|
+
<i data-lucide="send"></i>
|
|
133
|
+
<span>发送</span>
|
|
134
|
+
</button>
|
|
135
|
+
</div>
|
|
136
|
+
<p class="composer-hint">Enter 发送 · Shift + Enter 换行</p>
|
|
137
|
+
</form>
|
|
138
|
+
</section>
|
|
139
|
+
</div>
|
|
140
|
+
</section>
|
|
141
|
+
|
|
142
|
+
<section class="view settings-view" id="settingsView" data-view-panel="settings" hidden>
|
|
143
|
+
<div class="section-heading">
|
|
144
|
+
<div>
|
|
145
|
+
<p class="eyebrow">LOCAL CODEX</p>
|
|
146
|
+
<h1>设置</h1>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
<form id="settingsForm" class="settings-form">
|
|
150
|
+
<div class="settings-group">
|
|
151
|
+
<h2>工作区</h2>
|
|
152
|
+
<label>
|
|
153
|
+
<span>默认工作目录</span>
|
|
154
|
+
<input id="defaultCwdInput" name="defaultCwd" autocomplete="off" required>
|
|
155
|
+
</label>
|
|
156
|
+
<label>
|
|
157
|
+
<span>允许的工作目录</span>
|
|
158
|
+
<textarea id="allowedWorkspacesInput" name="allowedWorkspaces" rows="5" required></textarea>
|
|
159
|
+
</label>
|
|
160
|
+
</div>
|
|
161
|
+
<div class="settings-group">
|
|
162
|
+
<h2>Codex</h2>
|
|
163
|
+
<div class="field-grid">
|
|
164
|
+
<label>
|
|
165
|
+
<span>后端</span>
|
|
166
|
+
<select id="backendInput" name="codexBackend">
|
|
167
|
+
<option value="auto">自动</option>
|
|
168
|
+
<option value="app-server">App server</option>
|
|
169
|
+
<option value="exec">Exec</option>
|
|
170
|
+
</select>
|
|
171
|
+
</label>
|
|
172
|
+
<label>
|
|
173
|
+
<span>Exec 沙箱</span>
|
|
174
|
+
<select id="sandboxInput" name="codexExecSandbox">
|
|
175
|
+
<option value="">沿用 Codex 设置</option>
|
|
176
|
+
<option value="read-only">只读</option>
|
|
177
|
+
<option value="workspace-write">工作区可写</option>
|
|
178
|
+
<option value="danger-full-access">完整访问</option>
|
|
179
|
+
</select>
|
|
180
|
+
</label>
|
|
181
|
+
<label>
|
|
182
|
+
<span>模型</span>
|
|
183
|
+
<select id="modelInput" name="model">
|
|
184
|
+
<option value="">沿用 Codex 设置</option>
|
|
185
|
+
</select>
|
|
186
|
+
<small class="field-hint effective-setting"><span>当前生效</span><strong id="effectiveModelValue">正在读取</strong></small>
|
|
187
|
+
</label>
|
|
188
|
+
<label>
|
|
189
|
+
<span>推理强度</span>
|
|
190
|
+
<select id="effortInput" name="effort">
|
|
191
|
+
<option value="">沿用模型默认</option>
|
|
192
|
+
</select>
|
|
193
|
+
<small class="field-hint effective-setting"><span>当前生效</span><strong id="effectiveEffortValue">正在读取</strong></small>
|
|
194
|
+
</label>
|
|
195
|
+
<label class="toggle-field" for="streamRepliesInput">
|
|
196
|
+
<span>过程进度</span>
|
|
197
|
+
<span class="toggle-control">
|
|
198
|
+
<input id="streamRepliesInput" name="streamReplies" type="checkbox">
|
|
199
|
+
<span aria-hidden="true"></span>
|
|
200
|
+
</span>
|
|
201
|
+
</label>
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="settings-group">
|
|
205
|
+
<h2>版本</h2>
|
|
206
|
+
<div class="settings-update">
|
|
207
|
+
<span class="settings-update-version">
|
|
208
|
+
<small>当前版本</small>
|
|
209
|
+
<strong id="settingsVersionValue">--</strong>
|
|
210
|
+
</span>
|
|
211
|
+
<button class="button button-secondary" id="updateCheckButton" type="button">
|
|
212
|
+
<i data-lucide="refresh-cw"></i>
|
|
213
|
+
<span>检查更新</span>
|
|
214
|
+
</button>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
<div class="form-actions">
|
|
218
|
+
<button class="button button-primary" type="submit">
|
|
219
|
+
<i data-lucide="save"></i>
|
|
220
|
+
<span>保存设置</span>
|
|
221
|
+
</button>
|
|
222
|
+
</div>
|
|
223
|
+
</form>
|
|
224
|
+
</section>
|
|
225
|
+
</main>
|
|
226
|
+
|
|
227
|
+
<dialog class="modal update-modal" id="updateDialog" aria-labelledby="updateDialogTitle">
|
|
228
|
+
<div class="modal-header update-modal-header">
|
|
229
|
+
<div>
|
|
230
|
+
<p class="eyebrow">PRODUCT UPDATE</p>
|
|
231
|
+
<h2 id="updateDialogTitle">发现新版本</h2>
|
|
232
|
+
</div>
|
|
233
|
+
<span class="update-modal-icon" aria-hidden="true"><i data-lucide="package"></i></span>
|
|
234
|
+
</div>
|
|
235
|
+
<div class="modal-body update-modal-body">
|
|
236
|
+
<div class="update-version-flow" aria-label="版本升级">
|
|
237
|
+
<span class="update-version-item"><small>当前版本</small><strong id="updateCurrentVersion">--</strong></span>
|
|
238
|
+
<span class="update-version-divider" aria-hidden="true"></span>
|
|
239
|
+
<span class="update-version-item is-latest"><small>最新版本</small><strong id="updateLatestVersion">--</strong></span>
|
|
240
|
+
</div>
|
|
241
|
+
<p class="update-description">更新期间微信连接会短暂中断,完成后服务将自动重启并恢复连接。</p>
|
|
242
|
+
<div class="update-progress" id="updateProgress" aria-live="polite" hidden>
|
|
243
|
+
<span class="spinner" aria-hidden="true"></span>
|
|
244
|
+
<div><strong id="updateProgressTitle">正在安装更新</strong><span id="updateProgressDetail">请保持此页面打开</span></div>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
<div class="modal-footer">
|
|
248
|
+
<button class="button button-secondary" id="updateLaterButton" type="button">稍后</button>
|
|
249
|
+
<button class="button button-primary" id="updateNowButton" type="button">
|
|
250
|
+
<i data-lucide="download"></i>
|
|
251
|
+
<span>立即更新</span>
|
|
252
|
+
</button>
|
|
253
|
+
</div>
|
|
254
|
+
</dialog>
|
|
255
|
+
|
|
256
|
+
<dialog class="modal qr-modal" id="qrDialog">
|
|
257
|
+
<div class="modal-header">
|
|
258
|
+
<div>
|
|
259
|
+
<p class="eyebrow">WECHAT LOGIN</p>
|
|
260
|
+
<h2>微信扫码登录</h2>
|
|
261
|
+
</div>
|
|
262
|
+
<button class="icon-button" type="button" data-close-dialog="qrDialog" title="关闭" aria-label="关闭扫码窗口">
|
|
263
|
+
<i data-lucide="x"></i>
|
|
264
|
+
</button>
|
|
265
|
+
</div>
|
|
266
|
+
<div class="qr-stage">
|
|
267
|
+
<div class="qr-frame" id="qrFrame">
|
|
268
|
+
<div class="spinner" aria-label="正在生成二维码"></div>
|
|
269
|
+
</div>
|
|
270
|
+
<p id="qrStatus" class="qr-status">正在生成二维码</p>
|
|
271
|
+
</div>
|
|
272
|
+
<div class="modal-footer">
|
|
273
|
+
<button class="button button-secondary" id="refreshQrButton" type="button">
|
|
274
|
+
<i data-lucide="refresh-cw"></i>
|
|
275
|
+
<span>刷新二维码</span>
|
|
276
|
+
</button>
|
|
277
|
+
</div>
|
|
278
|
+
</dialog>
|
|
279
|
+
|
|
280
|
+
<dialog class="modal" id="accountDialog">
|
|
281
|
+
<form id="accountForm" method="dialog">
|
|
282
|
+
<div class="modal-header">
|
|
283
|
+
<div>
|
|
284
|
+
<p class="eyebrow">ACCOUNT REMARK</p>
|
|
285
|
+
<h2>修改微信账号备注</h2>
|
|
286
|
+
</div>
|
|
287
|
+
<button class="icon-button" type="button" data-close-dialog="accountDialog" title="关闭" aria-label="关闭账号备注窗口">
|
|
288
|
+
<i data-lucide="x"></i>
|
|
289
|
+
</button>
|
|
290
|
+
</div>
|
|
291
|
+
<input id="editingRemarkAccountId" type="hidden">
|
|
292
|
+
<div class="modal-body form-stack">
|
|
293
|
+
<label>
|
|
294
|
+
<span>账号备注</span>
|
|
295
|
+
<input id="accountRemarkInput" maxlength="40" autocomplete="off" placeholder="例如:张三、李四">
|
|
296
|
+
<small class="field-hint">备注只保存在本机;清空后恢复默认名称。</small>
|
|
297
|
+
</label>
|
|
298
|
+
</div>
|
|
299
|
+
<div class="modal-footer">
|
|
300
|
+
<button class="button button-secondary" type="button" data-close-dialog="accountDialog">取消</button>
|
|
301
|
+
<button class="button button-primary" type="submit">
|
|
302
|
+
<i data-lucide="check"></i>
|
|
303
|
+
<span>保存</span>
|
|
304
|
+
</button>
|
|
305
|
+
</div>
|
|
306
|
+
</form>
|
|
307
|
+
</dialog>
|
|
308
|
+
|
|
309
|
+
<dialog class="modal account-removal-modal" id="removeAccountDialog" aria-labelledby="removeAccountDialogTitle">
|
|
310
|
+
<form id="removeAccountForm" method="dialog">
|
|
311
|
+
<div class="modal-header">
|
|
312
|
+
<div>
|
|
313
|
+
<p class="eyebrow">REMOVE ACCOUNT</p>
|
|
314
|
+
<h2 id="removeAccountDialogTitle">移除微信账号</h2>
|
|
315
|
+
</div>
|
|
316
|
+
<button class="icon-button" type="button" data-close-dialog="removeAccountDialog" title="关闭" aria-label="关闭移除账号窗口">
|
|
317
|
+
<i data-lucide="x"></i>
|
|
318
|
+
</button>
|
|
319
|
+
</div>
|
|
320
|
+
<input id="removingAccountId" type="hidden">
|
|
321
|
+
<div class="modal-body account-removal-body">
|
|
322
|
+
<p class="account-removal-lead">选择如何处理 <strong id="removingAccountName">此微信账号</strong> 的会话数据。</p>
|
|
323
|
+
<div class="account-removal-choices" role="radiogroup" aria-label="会话历史处理方式">
|
|
324
|
+
<label class="account-removal-choice">
|
|
325
|
+
<input type="radio" name="retainHistory" value="true" checked>
|
|
326
|
+
<span class="account-removal-option">
|
|
327
|
+
<span class="account-removal-option-icon" aria-hidden="true"><i data-lucide="archive-restore"></i></span>
|
|
328
|
+
<span><strong>保留会话历史</strong><small>账号从页面移除;同一用户重新扫码后恢复备注、授权和历史会话。</small></span>
|
|
329
|
+
</span>
|
|
330
|
+
</label>
|
|
331
|
+
<label class="account-removal-choice is-destructive">
|
|
332
|
+
<input type="radio" name="retainHistory" value="false">
|
|
333
|
+
<span class="account-removal-option">
|
|
334
|
+
<span class="account-removal-option-icon" aria-hidden="true"><i data-lucide="trash-2"></i></span>
|
|
335
|
+
<span><strong>彻底删除历史</strong><small>删除本服务保存的授权和会话状态,重新扫码后不会恢复。</small></span>
|
|
336
|
+
</span>
|
|
337
|
+
</label>
|
|
338
|
+
</div>
|
|
339
|
+
<p class="account-removal-note"><i data-lucide="shield-check"></i><span>登录凭据始终会从本机删除;保留时不会保存 token。</span></p>
|
|
340
|
+
</div>
|
|
341
|
+
<div class="modal-footer">
|
|
342
|
+
<button class="button button-secondary" type="button" data-close-dialog="removeAccountDialog">取消</button>
|
|
343
|
+
<button class="button button-danger" type="submit">
|
|
344
|
+
<i data-lucide="user-minus"></i>
|
|
345
|
+
<span>移除账号</span>
|
|
346
|
+
</button>
|
|
347
|
+
</div>
|
|
348
|
+
</form>
|
|
349
|
+
</dialog>
|
|
350
|
+
|
|
351
|
+
<dialog class="modal session-modal" id="sessionDialog">
|
|
352
|
+
<form id="sessionForm" method="dialog">
|
|
353
|
+
<div class="modal-header">
|
|
354
|
+
<div>
|
|
355
|
+
<p class="eyebrow">MANAGED SESSION</p>
|
|
356
|
+
<h2 id="sessionDialogTitle">新建会话</h2>
|
|
357
|
+
</div>
|
|
358
|
+
<button class="icon-button" type="button" data-close-dialog="sessionDialog" title="关闭" aria-label="关闭会话窗口">
|
|
359
|
+
<i data-lucide="x"></i>
|
|
360
|
+
</button>
|
|
361
|
+
</div>
|
|
362
|
+
<input id="editingSessionId" type="hidden">
|
|
363
|
+
<input id="editingAccountId" type="hidden">
|
|
364
|
+
<div class="modal-body form-stack">
|
|
365
|
+
<label id="senderField">
|
|
366
|
+
<span>微信账号</span>
|
|
367
|
+
<select id="sessionSenderInput" required></select>
|
|
368
|
+
</label>
|
|
369
|
+
<label>
|
|
370
|
+
<span>会话名称</span>
|
|
371
|
+
<input id="sessionTitleInput" maxlength="80" autocomplete="off" required>
|
|
372
|
+
</label>
|
|
373
|
+
<label id="sessionWorkspaceField">
|
|
374
|
+
<span>工作目录</span>
|
|
375
|
+
<input id="sessionWorkspaceInput" autocomplete="off" required>
|
|
376
|
+
</label>
|
|
377
|
+
</div>
|
|
378
|
+
<div class="modal-footer">
|
|
379
|
+
<button class="button button-secondary" type="button" data-close-dialog="sessionDialog">取消</button>
|
|
380
|
+
<button class="button button-primary" type="submit">
|
|
381
|
+
<i data-lucide="check"></i>
|
|
382
|
+
<span>保存</span>
|
|
383
|
+
</button>
|
|
384
|
+
</div>
|
|
385
|
+
</form>
|
|
386
|
+
</dialog>
|
|
387
|
+
|
|
388
|
+
<div class="toast-region" id="toastRegion" aria-live="polite"></div>
|
|
389
|
+
</body>
|
|
390
|
+
</html>
|