codex-to-im 0.1.0 → 0.1.2
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 +35 -1
- package/README_CN.md +35 -1
- package/config.env.example +12 -15
- package/dist/cli.mjs +114 -1
- package/dist/daemon.mjs +7118 -6870
- package/dist/ui-server.mjs +1430 -353
- package/docs/install-windows.md +40 -3
- package/package.json +9 -12
package/dist/ui-server.mjs
CHANGED
|
@@ -4616,16 +4616,16 @@ function parsePositiveInt(value) {
|
|
|
4616
4616
|
}
|
|
4617
4617
|
function loadConfig() {
|
|
4618
4618
|
const env = loadRawConfigEnv();
|
|
4619
|
-
const rawRuntime = env.get("CTI_RUNTIME") || "
|
|
4620
|
-
const runtime = ["claude", "codex", "auto"].includes(rawRuntime) ? rawRuntime : "
|
|
4619
|
+
const rawRuntime = env.get("CTI_RUNTIME") || "codex";
|
|
4620
|
+
const runtime = ["claude", "codex", "auto"].includes(rawRuntime) ? rawRuntime : "codex";
|
|
4621
4621
|
return {
|
|
4622
4622
|
runtime,
|
|
4623
|
-
enabledChannels: splitCsv(env.get("CTI_ENABLED_CHANNELS")) ?? [],
|
|
4623
|
+
enabledChannels: splitCsv(env.get("CTI_ENABLED_CHANNELS")) ?? ["feishu"],
|
|
4624
4624
|
defaultWorkDir: env.get("CTI_DEFAULT_WORKDIR") || process.cwd(),
|
|
4625
4625
|
defaultModel: env.get("CTI_DEFAULT_MODEL") || void 0,
|
|
4626
4626
|
defaultMode: env.get("CTI_DEFAULT_MODE") || "code",
|
|
4627
4627
|
historyMessageLimit: parsePositiveInt(env.get("CTI_HISTORY_MESSAGE_LIMIT")) ?? 8,
|
|
4628
|
-
codexSkipGitRepoCheck: env.has("CTI_CODEX_SKIP_GIT_REPO_CHECK") ? env.get("CTI_CODEX_SKIP_GIT_REPO_CHECK") === "true" :
|
|
4628
|
+
codexSkipGitRepoCheck: env.has("CTI_CODEX_SKIP_GIT_REPO_CHECK") ? env.get("CTI_CODEX_SKIP_GIT_REPO_CHECK") === "true" : true,
|
|
4629
4629
|
tgBotToken: env.get("CTI_TG_BOT_TOKEN") || void 0,
|
|
4630
4630
|
tgChatId: env.get("CTI_TG_CHAT_ID") || void 0,
|
|
4631
4631
|
tgAllowedUsers: splitCsv(env.get("CTI_TG_ALLOWED_USERS")),
|
|
@@ -4891,7 +4891,7 @@ var CodexProvider = class {
|
|
|
4891
4891
|
/** Maps session IDs to Codex thread IDs for resume. */
|
|
4892
4892
|
threadIds = /* @__PURE__ */ new Map();
|
|
4893
4893
|
/**
|
|
4894
|
-
* Lazily load the Codex SDK. Throws a clear error if
|
|
4894
|
+
* Lazily load the Codex SDK. Throws a clear error if the installation is incomplete.
|
|
4895
4895
|
*/
|
|
4896
4896
|
async ensureSDK() {
|
|
4897
4897
|
if (this.sdk && this.codex) {
|
|
@@ -4901,7 +4901,7 @@ var CodexProvider = class {
|
|
|
4901
4901
|
this.sdk = await Function('return import("@openai/codex-sdk")')();
|
|
4902
4902
|
} catch {
|
|
4903
4903
|
throw new Error(
|
|
4904
|
-
"[CodexProvider] @openai/codex-sdk is
|
|
4904
|
+
"[CodexProvider] @openai/codex-sdk is missing from this codex-to-im installation. Reinstall codex-to-im or run npm install in the project root."
|
|
4905
4905
|
);
|
|
4906
4906
|
}
|
|
4907
4907
|
const apiKey = process.env.CTI_CODEX_API_KEY || process.env.CODEX_API_KEY || process.env.OPENAI_API_KEY || void 0;
|
|
@@ -4940,6 +4940,10 @@ var CodexProvider = class {
|
|
|
4940
4940
|
{ type: "text", text: params.prompt }
|
|
4941
4941
|
];
|
|
4942
4942
|
for (const file of imageFiles) {
|
|
4943
|
+
if (file.filePath && fs2.existsSync(file.filePath)) {
|
|
4944
|
+
parts.push({ type: "local_image", path: file.filePath });
|
|
4945
|
+
continue;
|
|
4946
|
+
}
|
|
4943
4947
|
const ext = MIME_EXT[file.type] || ".png";
|
|
4944
4948
|
const tmpPath = path2.join(os2.tmpdir(), `cti-img-${Date.now()}-${Math.random().toString(36).slice(2)}${ext}`);
|
|
4945
4949
|
fs2.writeFileSync(tmpPath, Buffer.from(file.data, "base64"));
|
|
@@ -5128,9 +5132,39 @@ import os3 from "node:os";
|
|
|
5128
5132
|
import path3 from "node:path";
|
|
5129
5133
|
var ACTIVE_WINDOW_MS = 15 * 60 * 1e3;
|
|
5130
5134
|
var MAX_SESSION_META_BYTES = 4 * 1024 * 1024;
|
|
5135
|
+
var TITLE_MAX_CHARS = 72;
|
|
5136
|
+
function getCodexHome() {
|
|
5137
|
+
return process.env.CODEX_HOME || path3.join(os3.homedir(), ".codex");
|
|
5138
|
+
}
|
|
5131
5139
|
function getCodexSessionsRoot() {
|
|
5132
|
-
|
|
5133
|
-
|
|
5140
|
+
return path3.join(getCodexHome(), "sessions");
|
|
5141
|
+
}
|
|
5142
|
+
function getArchivedSessionsRoot() {
|
|
5143
|
+
return path3.join(getCodexHome(), "archived_sessions");
|
|
5144
|
+
}
|
|
5145
|
+
function getSessionIndexPath() {
|
|
5146
|
+
return path3.join(getCodexHome(), "session_index.jsonl");
|
|
5147
|
+
}
|
|
5148
|
+
function extractThreadIdFromRolloutName(name) {
|
|
5149
|
+
const match = name.match(/-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i);
|
|
5150
|
+
return match?.[1] || null;
|
|
5151
|
+
}
|
|
5152
|
+
function loadArchivedThreadIds() {
|
|
5153
|
+
const archivedRoot = getArchivedSessionsRoot();
|
|
5154
|
+
if (!fs3.existsSync(archivedRoot)) return /* @__PURE__ */ new Set();
|
|
5155
|
+
let entries;
|
|
5156
|
+
try {
|
|
5157
|
+
entries = fs3.readdirSync(archivedRoot, { withFileTypes: true });
|
|
5158
|
+
} catch {
|
|
5159
|
+
return /* @__PURE__ */ new Set();
|
|
5160
|
+
}
|
|
5161
|
+
const ids = /* @__PURE__ */ new Set();
|
|
5162
|
+
for (const entry of entries) {
|
|
5163
|
+
if (!entry.isFile()) continue;
|
|
5164
|
+
const threadId = extractThreadIdFromRolloutName(entry.name);
|
|
5165
|
+
if (threadId) ids.add(threadId);
|
|
5166
|
+
}
|
|
5167
|
+
return ids;
|
|
5134
5168
|
}
|
|
5135
5169
|
function readFirstLine(filePath, maxBytes = MAX_SESSION_META_BYTES) {
|
|
5136
5170
|
const fd = fs3.openSync(filePath, "r");
|
|
@@ -5178,7 +5212,36 @@ function isDesktopLike(meta) {
|
|
|
5178
5212
|
const source = meta?.source?.toLowerCase() || "";
|
|
5179
5213
|
return originator.includes("desktop") || source === "vscode" || source === "desktop";
|
|
5180
5214
|
}
|
|
5181
|
-
function
|
|
5215
|
+
function loadThreadNameIndex(archivedThreadIds) {
|
|
5216
|
+
const indexPath = getSessionIndexPath();
|
|
5217
|
+
if (!fs3.existsSync(indexPath)) return /* @__PURE__ */ new Map();
|
|
5218
|
+
let content = "";
|
|
5219
|
+
try {
|
|
5220
|
+
content = fs3.readFileSync(indexPath, "utf-8");
|
|
5221
|
+
} catch {
|
|
5222
|
+
return /* @__PURE__ */ new Map();
|
|
5223
|
+
}
|
|
5224
|
+
const titles = /* @__PURE__ */ new Map();
|
|
5225
|
+
for (const line of content.split(/\r?\n/)) {
|
|
5226
|
+
if (!line.trim()) continue;
|
|
5227
|
+
let parsed;
|
|
5228
|
+
try {
|
|
5229
|
+
parsed = JSON.parse(line);
|
|
5230
|
+
} catch {
|
|
5231
|
+
continue;
|
|
5232
|
+
}
|
|
5233
|
+
const threadId = parsed.id?.trim();
|
|
5234
|
+
const title = trimTitle(parsed.thread_name || "");
|
|
5235
|
+
if (!threadId || !title || archivedThreadIds.has(threadId)) continue;
|
|
5236
|
+
const updatedAt = parsed.updated_at || "";
|
|
5237
|
+
const existing = titles.get(threadId);
|
|
5238
|
+
if (!existing || updatedAt >= existing.updatedAt) {
|
|
5239
|
+
titles.set(threadId, { title, updatedAt });
|
|
5240
|
+
}
|
|
5241
|
+
}
|
|
5242
|
+
return new Map(Array.from(titles.entries()).map(([threadId, entry]) => [threadId, entry.title]));
|
|
5243
|
+
}
|
|
5244
|
+
function parseDesktopSession(filePath, threadNames, archivedThreadIds) {
|
|
5182
5245
|
const firstLine = readFirstLine(filePath);
|
|
5183
5246
|
if (!firstLine) return null;
|
|
5184
5247
|
let parsed;
|
|
@@ -5190,6 +5253,9 @@ function parseDesktopSession(filePath) {
|
|
|
5190
5253
|
if (parsed.type !== "session_meta" || !parsed.payload?.id || !isDesktopLike(parsed.payload)) {
|
|
5191
5254
|
return null;
|
|
5192
5255
|
}
|
|
5256
|
+
if (archivedThreadIds.has(parsed.payload.id)) {
|
|
5257
|
+
return null;
|
|
5258
|
+
}
|
|
5193
5259
|
let stat;
|
|
5194
5260
|
try {
|
|
5195
5261
|
stat = fs3.statSync(filePath);
|
|
@@ -5200,6 +5266,8 @@ function parseDesktopSession(filePath) {
|
|
|
5200
5266
|
const lastEventAt = stat.mtime.toISOString();
|
|
5201
5267
|
const firstSeenAt = parsed.payload.timestamp || parsed.timestamp || stat.birthtime.toISOString();
|
|
5202
5268
|
const threadId = parsed.payload.id;
|
|
5269
|
+
const title = threadNames.get(threadId);
|
|
5270
|
+
if (!title) return null;
|
|
5203
5271
|
return {
|
|
5204
5272
|
threadId,
|
|
5205
5273
|
filePath,
|
|
@@ -5209,18 +5277,27 @@ function parseDesktopSession(filePath) {
|
|
|
5209
5277
|
cliVersion: parsed.payload.cli_version || void 0,
|
|
5210
5278
|
firstSeenAt,
|
|
5211
5279
|
lastEventAt,
|
|
5212
|
-
title
|
|
5280
|
+
title,
|
|
5213
5281
|
activeEstimate: Date.now() - stat.mtimeMs < ACTIVE_WINDOW_MS
|
|
5214
5282
|
};
|
|
5215
5283
|
}
|
|
5284
|
+
function trimTitle(text2) {
|
|
5285
|
+
const normalized = text2.replace(/\s+/g, " ").trim();
|
|
5286
|
+
if (!normalized) return "";
|
|
5287
|
+
if (normalized.length <= TITLE_MAX_CHARS) return normalized;
|
|
5288
|
+
return `${normalized.slice(0, TITLE_MAX_CHARS - 3).trimEnd()}...`;
|
|
5289
|
+
}
|
|
5216
5290
|
function listDesktopSessions(limit = 12) {
|
|
5217
5291
|
const root = getCodexSessionsRoot();
|
|
5218
5292
|
if (!fs3.existsSync(root)) return [];
|
|
5293
|
+
const archivedThreadIds = loadArchivedThreadIds();
|
|
5294
|
+
const threadNames = loadThreadNameIndex(archivedThreadIds);
|
|
5295
|
+
if (threadNames.size === 0) return [];
|
|
5219
5296
|
const files = [];
|
|
5220
5297
|
walkSessionFiles(root, files);
|
|
5221
5298
|
const sessions = [];
|
|
5222
5299
|
for (const filePath of files) {
|
|
5223
|
-
const session = parseDesktopSession(filePath);
|
|
5300
|
+
const session = parseDesktopSession(filePath, threadNames, archivedThreadIds);
|
|
5224
5301
|
if (session) sessions.push(session);
|
|
5225
5302
|
}
|
|
5226
5303
|
return sessions.sort((a, b) => b.lastEventAt.localeCompare(a.lastEventAt)).slice(0, Math.max(1, limit));
|
|
@@ -5229,6 +5306,9 @@ function getDesktopSessionByThreadId(threadId) {
|
|
|
5229
5306
|
const sessions = listDesktopSessions(200);
|
|
5230
5307
|
return sessions.find((session) => session.threadId === threadId) || null;
|
|
5231
5308
|
}
|
|
5309
|
+
function isArchivedDesktopThread(threadId) {
|
|
5310
|
+
return loadArchivedThreadIds().has(threadId);
|
|
5311
|
+
}
|
|
5232
5312
|
|
|
5233
5313
|
// src/session-bindings.ts
|
|
5234
5314
|
import path4 from "node:path";
|
|
@@ -5237,9 +5317,6 @@ function getSessionName(session) {
|
|
|
5237
5317
|
if (session.working_directory) return path4.basename(session.working_directory);
|
|
5238
5318
|
return session.id.slice(0, 8);
|
|
5239
5319
|
}
|
|
5240
|
-
function getSessionDescription(session) {
|
|
5241
|
-
return session.working_directory || "(no working directory)";
|
|
5242
|
-
}
|
|
5243
5320
|
function bindStoreToSession(store, channelType, chatId, sessionId) {
|
|
5244
5321
|
const session = store.getSession(sessionId);
|
|
5245
5322
|
if (!session) return null;
|
|
@@ -5284,29 +5361,29 @@ function bindStoreToSdkSession(store, channelType, chatId, sdkSessionId, opts) {
|
|
|
5284
5361
|
model: model || session.model
|
|
5285
5362
|
});
|
|
5286
5363
|
}
|
|
5287
|
-
function listBindingTargetOptions(
|
|
5288
|
-
|
|
5364
|
+
function listBindingTargetOptions(_store, desktopLimit = 12) {
|
|
5365
|
+
return listDesktopSessions(desktopLimit).map((session) => ({
|
|
5289
5366
|
key: `desktop:${session.threadId}`,
|
|
5290
5367
|
kind: "desktop",
|
|
5291
5368
|
id: session.threadId,
|
|
5292
|
-
label:
|
|
5293
|
-
description: `${session.threadId.slice(0, 8)}... \xB7 ${session.cwd || "(no cwd)"}
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
key: `session:${session.id}`,
|
|
5297
|
-
kind: "session",
|
|
5298
|
-
id: session.id,
|
|
5299
|
-
label: `[Internal] ${getSessionName(session)}`,
|
|
5300
|
-
description: `${session.id.slice(0, 8)}... \xB7 ${getSessionDescription(session)}${session.sdk_session_id ? ` \xB7 thread ${session.sdk_session_id.slice(0, 8)}...` : ""}`
|
|
5369
|
+
label: session.title,
|
|
5370
|
+
description: `${session.threadId.slice(0, 8)}... \xB7 ${session.cwd || "(no cwd)"}`,
|
|
5371
|
+
cwd: session.cwd,
|
|
5372
|
+
threadId: session.threadId
|
|
5301
5373
|
}));
|
|
5302
|
-
return [...desktopOptions, ...sessionOptions];
|
|
5303
5374
|
}
|
|
5304
5375
|
function listBindingSummaries(store) {
|
|
5305
5376
|
return store.listChannelBindings().map((binding) => {
|
|
5306
5377
|
const session = store.getSession(binding.codepilotSessionId);
|
|
5307
5378
|
const currentThreadId = binding.sdkSessionId || session?.sdk_session_id || void 0;
|
|
5379
|
+
const desktop = currentThreadId ? getDesktopSessionByThreadId(currentThreadId) : null;
|
|
5380
|
+
const archived = currentThreadId ? isArchivedDesktopThread(currentThreadId) : false;
|
|
5308
5381
|
const currentTargetKey = currentThreadId ? `desktop:${currentThreadId}` : `session:${binding.codepilotSessionId}`;
|
|
5309
|
-
const currentTargetLabel = currentThreadId ?
|
|
5382
|
+
const currentTargetLabel = currentThreadId ? desktop?.title || (archived ? `\u5DF2\u5F52\u6863\u684C\u9762\u7EBF\u7A0B ${currentThreadId.slice(0, 8)}...` : `Desktop thread ${currentThreadId.slice(0, 8)}...`) : getSessionName(session || {
|
|
5383
|
+
id: binding.codepilotSessionId,
|
|
5384
|
+
working_directory: binding.workingDirectory,
|
|
5385
|
+
model: binding.model
|
|
5386
|
+
});
|
|
5310
5387
|
return {
|
|
5311
5388
|
id: binding.id,
|
|
5312
5389
|
channelType: binding.channelType,
|
|
@@ -5509,6 +5586,10 @@ async function stopBridge() {
|
|
|
5509
5586
|
}
|
|
5510
5587
|
return getBridgeStatus();
|
|
5511
5588
|
}
|
|
5589
|
+
async function restartBridge() {
|
|
5590
|
+
await stopBridge();
|
|
5591
|
+
return await startBridge();
|
|
5592
|
+
}
|
|
5512
5593
|
function getBridgeLogs(lines = 200) {
|
|
5513
5594
|
ensureDirs();
|
|
5514
5595
|
const filePath = path5.join(logsDir, "bridge.log");
|
|
@@ -6483,6 +6564,18 @@ function mergeConfig(payload) {
|
|
|
6483
6564
|
weixinMediaEnabled: payload.weixinMediaEnabled === true
|
|
6484
6565
|
};
|
|
6485
6566
|
}
|
|
6567
|
+
function getWeixinAccountsPayload() {
|
|
6568
|
+
return listWeixinAccounts().map((account) => ({
|
|
6569
|
+
accountId: account.accountId,
|
|
6570
|
+
name: account.name,
|
|
6571
|
+
userId: account.userId,
|
|
6572
|
+
enabled: account.enabled,
|
|
6573
|
+
baseUrl: account.baseUrl,
|
|
6574
|
+
cdnBaseUrl: account.cdnBaseUrl,
|
|
6575
|
+
lastLoginAt: account.lastLoginAt,
|
|
6576
|
+
updatedAt: account.updatedAt
|
|
6577
|
+
}));
|
|
6578
|
+
}
|
|
6486
6579
|
async function validateFeishuCredentials(config) {
|
|
6487
6580
|
if (!config.feishuAppId || !config.feishuAppSecret) {
|
|
6488
6581
|
return { ok: false, message: "Feishu App ID / App Secret \u4E0D\u80FD\u4E3A\u7A7A\u3002" };
|
|
@@ -6559,155 +6652,253 @@ function renderHtml() {
|
|
|
6559
6652
|
<title>Codex to IM</title>
|
|
6560
6653
|
<style>
|
|
6561
6654
|
:root {
|
|
6562
|
-
--bg: #
|
|
6655
|
+
--bg: #f5f7fa;
|
|
6563
6656
|
--surface: #ffffff;
|
|
6564
|
-
--
|
|
6565
|
-
--border: #
|
|
6566
|
-
--
|
|
6567
|
-
--
|
|
6568
|
-
--
|
|
6569
|
-
--primary
|
|
6570
|
-
--
|
|
6571
|
-
--
|
|
6572
|
-
--
|
|
6657
|
+
--surface-soft: #fafafa;
|
|
6658
|
+
--border: #e5e7eb;
|
|
6659
|
+
--border-strong: #d0d7e2;
|
|
6660
|
+
--text: #111827;
|
|
6661
|
+
--muted: #667085;
|
|
6662
|
+
--primary: #1677ff;
|
|
6663
|
+
--primary-strong: #0958d9;
|
|
6664
|
+
--success: #15803d;
|
|
6665
|
+
--danger: #dc2626;
|
|
6666
|
+
--sidebar: #001529;
|
|
6667
|
+
--sidebar-border: #0f2b46;
|
|
6668
|
+
--sidebar-text: #c7d2e0;
|
|
6669
|
+
--sidebar-active: #1677ff;
|
|
6670
|
+
--code-bg: #0f172a;
|
|
6573
6671
|
}
|
|
6574
6672
|
|
|
6575
6673
|
* { box-sizing: border-box; }
|
|
6576
6674
|
html, body { height: 100%; }
|
|
6577
6675
|
body {
|
|
6578
6676
|
margin: 0;
|
|
6579
|
-
font: 14px/1.5 "
|
|
6677
|
+
font: 14px/1.5 "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
|
|
6580
6678
|
color: var(--text);
|
|
6581
6679
|
background: var(--bg);
|
|
6582
6680
|
}
|
|
6583
6681
|
|
|
6682
|
+
button, input, select, textarea {
|
|
6683
|
+
font: inherit;
|
|
6684
|
+
}
|
|
6685
|
+
|
|
6584
6686
|
.shell {
|
|
6585
6687
|
min-height: 100vh;
|
|
6586
6688
|
display: grid;
|
|
6587
|
-
grid-template-columns:
|
|
6689
|
+
grid-template-columns: 232px minmax(0, 1fr);
|
|
6588
6690
|
}
|
|
6589
6691
|
|
|
6590
6692
|
.sidebar {
|
|
6591
6693
|
background: var(--sidebar);
|
|
6592
|
-
|
|
6593
|
-
padding:
|
|
6694
|
+
color: var(--sidebar-text);
|
|
6695
|
+
padding: 20px 16px;
|
|
6696
|
+
border-right: 1px solid var(--sidebar-border);
|
|
6697
|
+
}
|
|
6698
|
+
|
|
6699
|
+
.brand {
|
|
6700
|
+
padding: 10px 12px 18px;
|
|
6701
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
6702
|
+
margin-bottom: 18px;
|
|
6594
6703
|
}
|
|
6595
6704
|
|
|
6596
|
-
.
|
|
6597
|
-
|
|
6705
|
+
.brand-title {
|
|
6706
|
+
margin: 0;
|
|
6707
|
+
color: #ffffff;
|
|
6708
|
+
font-size: 16px;
|
|
6598
6709
|
font-weight: 700;
|
|
6599
|
-
margin: 0 0 6px;
|
|
6600
6710
|
}
|
|
6601
6711
|
|
|
6602
|
-
.
|
|
6603
|
-
margin: 0 0
|
|
6604
|
-
color: var(--
|
|
6712
|
+
.brand-copy {
|
|
6713
|
+
margin: 6px 0 0;
|
|
6714
|
+
color: var(--sidebar-text);
|
|
6715
|
+
font-size: 13px;
|
|
6605
6716
|
}
|
|
6606
6717
|
|
|
6607
6718
|
.nav {
|
|
6608
6719
|
display: grid;
|
|
6609
|
-
gap:
|
|
6720
|
+
gap: 4px;
|
|
6610
6721
|
}
|
|
6611
6722
|
|
|
6612
|
-
.nav
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6723
|
+
.nav-link {
|
|
6724
|
+
width: 100%;
|
|
6725
|
+
border: 0;
|
|
6726
|
+
background: transparent;
|
|
6727
|
+
color: var(--sidebar-text);
|
|
6728
|
+
text-align: left;
|
|
6729
|
+
padding: 10px 12px;
|
|
6616
6730
|
border-radius: 8px;
|
|
6731
|
+
cursor: pointer;
|
|
6732
|
+
}
|
|
6733
|
+
|
|
6734
|
+
.nav-link:hover {
|
|
6735
|
+
background: rgba(255, 255, 255, 0.08);
|
|
6736
|
+
color: #ffffff;
|
|
6617
6737
|
}
|
|
6618
6738
|
|
|
6619
|
-
.nav
|
|
6620
|
-
background:
|
|
6739
|
+
.nav-link.active {
|
|
6740
|
+
background: var(--sidebar-active);
|
|
6741
|
+
color: #ffffff;
|
|
6621
6742
|
}
|
|
6622
6743
|
|
|
6623
6744
|
.main {
|
|
6624
|
-
padding: 28px 32px
|
|
6745
|
+
padding: 28px 32px 36px;
|
|
6625
6746
|
}
|
|
6626
6747
|
|
|
6627
|
-
.
|
|
6748
|
+
.page {
|
|
6749
|
+
display: none;
|
|
6750
|
+
}
|
|
6751
|
+
|
|
6752
|
+
.page.active {
|
|
6753
|
+
display: block;
|
|
6754
|
+
}
|
|
6755
|
+
|
|
6756
|
+
.page-header {
|
|
6628
6757
|
display: flex;
|
|
6629
6758
|
justify-content: space-between;
|
|
6630
6759
|
align-items: flex-start;
|
|
6631
|
-
gap:
|
|
6632
|
-
margin-bottom:
|
|
6760
|
+
gap: 16px;
|
|
6761
|
+
margin-bottom: 20px;
|
|
6633
6762
|
}
|
|
6634
6763
|
|
|
6635
|
-
.
|
|
6636
|
-
margin: 0
|
|
6764
|
+
.page-title {
|
|
6765
|
+
margin: 0;
|
|
6637
6766
|
font-size: 28px;
|
|
6638
6767
|
line-height: 1.2;
|
|
6639
6768
|
}
|
|
6640
6769
|
|
|
6641
|
-
.
|
|
6642
|
-
margin: 0;
|
|
6770
|
+
.page-copy {
|
|
6771
|
+
margin: 6px 0 0;
|
|
6643
6772
|
color: var(--muted);
|
|
6644
6773
|
}
|
|
6645
6774
|
|
|
6646
6775
|
.status-grid {
|
|
6647
6776
|
display: grid;
|
|
6648
|
-
grid-template-columns: repeat(auto-fit, minmax(
|
|
6649
|
-
gap:
|
|
6650
|
-
margin-bottom:
|
|
6777
|
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
6778
|
+
gap: 16px;
|
|
6779
|
+
margin-bottom: 20px;
|
|
6651
6780
|
}
|
|
6652
6781
|
|
|
6653
|
-
.status-card,
|
|
6782
|
+
.status-card,
|
|
6783
|
+
.panel {
|
|
6654
6784
|
background: var(--surface);
|
|
6655
6785
|
border: 1px solid var(--border);
|
|
6656
6786
|
border-radius: 10px;
|
|
6657
6787
|
}
|
|
6658
6788
|
|
|
6659
6789
|
.status-card {
|
|
6660
|
-
padding:
|
|
6790
|
+
padding: 16px 18px;
|
|
6661
6791
|
}
|
|
6662
6792
|
|
|
6663
6793
|
.status-card strong {
|
|
6664
6794
|
display: block;
|
|
6665
6795
|
font-size: 12px;
|
|
6666
6796
|
color: var(--muted);
|
|
6667
|
-
margin-bottom: 8px;
|
|
6668
6797
|
font-weight: 600;
|
|
6798
|
+
margin-bottom: 8px;
|
|
6669
6799
|
}
|
|
6670
6800
|
|
|
6671
6801
|
.status-value {
|
|
6672
|
-
font-size:
|
|
6802
|
+
font-size: 22px;
|
|
6803
|
+
line-height: 1.2;
|
|
6673
6804
|
font-weight: 700;
|
|
6805
|
+
word-break: break-word;
|
|
6674
6806
|
}
|
|
6675
6807
|
|
|
6676
|
-
.
|
|
6677
|
-
|
|
6678
|
-
gap: 20px;
|
|
6808
|
+
.panel {
|
|
6809
|
+
padding: 20px;
|
|
6679
6810
|
}
|
|
6680
6811
|
|
|
6681
6812
|
.section-grid {
|
|
6682
6813
|
display: grid;
|
|
6683
6814
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
6684
|
-
gap:
|
|
6815
|
+
gap: 20px;
|
|
6685
6816
|
}
|
|
6686
6817
|
|
|
6687
|
-
.
|
|
6818
|
+
.overview-grid {
|
|
6688
6819
|
display: grid;
|
|
6689
|
-
grid-template-columns:
|
|
6690
|
-
gap:
|
|
6820
|
+
grid-template-columns: minmax(0, 1.35fr) minmax(320px, 0.9fr);
|
|
6821
|
+
gap: 20px;
|
|
6691
6822
|
}
|
|
6692
6823
|
|
|
6693
|
-
.panel {
|
|
6694
|
-
|
|
6824
|
+
.panel-header {
|
|
6825
|
+
display: flex;
|
|
6826
|
+
justify-content: space-between;
|
|
6827
|
+
align-items: flex-start;
|
|
6828
|
+
gap: 12px;
|
|
6829
|
+
margin-bottom: 16px;
|
|
6695
6830
|
}
|
|
6696
6831
|
|
|
6697
|
-
.panel h2
|
|
6698
|
-
|
|
6832
|
+
.panel-header h2,
|
|
6833
|
+
.panel-header h3 {
|
|
6834
|
+
margin: 0;
|
|
6699
6835
|
font-size: 18px;
|
|
6700
6836
|
}
|
|
6701
6837
|
|
|
6838
|
+
.panel-header p {
|
|
6839
|
+
margin: 6px 0 0;
|
|
6840
|
+
color: var(--muted);
|
|
6841
|
+
}
|
|
6842
|
+
|
|
6843
|
+
.toolbar,
|
|
6844
|
+
.actions,
|
|
6845
|
+
.session-actions {
|
|
6846
|
+
display: flex;
|
|
6847
|
+
gap: 10px;
|
|
6848
|
+
flex-wrap: wrap;
|
|
6849
|
+
}
|
|
6850
|
+
|
|
6851
|
+
button {
|
|
6852
|
+
border: 1px solid var(--border-strong);
|
|
6853
|
+
background: #ffffff;
|
|
6854
|
+
color: var(--text);
|
|
6855
|
+
border-radius: 8px;
|
|
6856
|
+
padding: 9px 14px;
|
|
6857
|
+
cursor: pointer;
|
|
6858
|
+
}
|
|
6859
|
+
|
|
6860
|
+
button:hover {
|
|
6861
|
+
border-color: var(--primary);
|
|
6862
|
+
color: var(--primary);
|
|
6863
|
+
}
|
|
6864
|
+
|
|
6865
|
+
button.primary {
|
|
6866
|
+
background: var(--primary);
|
|
6867
|
+
border-color: var(--primary);
|
|
6868
|
+
color: #ffffff;
|
|
6869
|
+
}
|
|
6870
|
+
|
|
6871
|
+
button.primary:hover {
|
|
6872
|
+
background: var(--primary-strong);
|
|
6873
|
+
border-color: var(--primary-strong);
|
|
6874
|
+
color: #ffffff;
|
|
6875
|
+
}
|
|
6876
|
+
|
|
6877
|
+
button[disabled] {
|
|
6878
|
+
border-color: var(--border);
|
|
6879
|
+
color: #9ca3af;
|
|
6880
|
+
background: #f3f4f6;
|
|
6881
|
+
cursor: not-allowed;
|
|
6882
|
+
}
|
|
6883
|
+
|
|
6884
|
+
button[disabled]:hover {
|
|
6885
|
+
border-color: var(--border);
|
|
6886
|
+
color: #9ca3af;
|
|
6887
|
+
}
|
|
6888
|
+
|
|
6702
6889
|
.fields {
|
|
6703
6890
|
display: grid;
|
|
6704
|
-
gap:
|
|
6891
|
+
gap: 16px;
|
|
6705
6892
|
}
|
|
6706
6893
|
|
|
6707
6894
|
.field-row {
|
|
6708
6895
|
display: grid;
|
|
6709
6896
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
6710
|
-
gap:
|
|
6897
|
+
gap: 16px;
|
|
6898
|
+
}
|
|
6899
|
+
|
|
6900
|
+
.field-row.triple {
|
|
6901
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
6711
6902
|
}
|
|
6712
6903
|
|
|
6713
6904
|
label {
|
|
@@ -6719,16 +6910,15 @@ function renderHtml() {
|
|
|
6719
6910
|
|
|
6720
6911
|
input, select, textarea {
|
|
6721
6912
|
width: 100%;
|
|
6722
|
-
border: 1px solid var(--border);
|
|
6723
|
-
background: #
|
|
6913
|
+
border: 1px solid var(--border-strong);
|
|
6914
|
+
background: #ffffff;
|
|
6724
6915
|
color: var(--text);
|
|
6725
6916
|
border-radius: 8px;
|
|
6726
6917
|
padding: 10px 12px;
|
|
6727
|
-
font: inherit;
|
|
6728
6918
|
}
|
|
6729
6919
|
|
|
6730
6920
|
input:focus, select:focus, textarea:focus {
|
|
6731
|
-
outline: 2px solid rgba(
|
|
6921
|
+
outline: 2px solid rgba(22, 119, 255, 0.14);
|
|
6732
6922
|
border-color: var(--primary);
|
|
6733
6923
|
}
|
|
6734
6924
|
|
|
@@ -6739,7 +6929,7 @@ function renderHtml() {
|
|
|
6739
6929
|
|
|
6740
6930
|
.checkbox-row {
|
|
6741
6931
|
display: flex;
|
|
6742
|
-
gap:
|
|
6932
|
+
gap: 16px;
|
|
6743
6933
|
flex-wrap: wrap;
|
|
6744
6934
|
}
|
|
6745
6935
|
|
|
@@ -6748,7 +6938,6 @@ function renderHtml() {
|
|
|
6748
6938
|
align-items: center;
|
|
6749
6939
|
gap: 8px;
|
|
6750
6940
|
color: var(--text);
|
|
6751
|
-
font-weight: 500;
|
|
6752
6941
|
}
|
|
6753
6942
|
|
|
6754
6943
|
.checkbox input {
|
|
@@ -6757,129 +6946,217 @@ function renderHtml() {
|
|
|
6757
6946
|
margin: 0;
|
|
6758
6947
|
}
|
|
6759
6948
|
|
|
6760
|
-
.
|
|
6761
|
-
|
|
6949
|
+
.notice {
|
|
6950
|
+
padding: 12px 14px;
|
|
6951
|
+
background: #f8fafc;
|
|
6952
|
+
border: 1px solid #e2e8f0;
|
|
6953
|
+
border-radius: 8px;
|
|
6954
|
+
color: var(--muted);
|
|
6955
|
+
}
|
|
6956
|
+
|
|
6957
|
+
.message {
|
|
6958
|
+
display: none;
|
|
6959
|
+
margin-top: 14px;
|
|
6960
|
+
padding: 10px 12px;
|
|
6961
|
+
border-radius: 8px;
|
|
6962
|
+
}
|
|
6963
|
+
|
|
6964
|
+
.message.show { display: block; }
|
|
6965
|
+
.message.success { background: rgba(21, 128, 61, 0.10); color: var(--success); }
|
|
6966
|
+
.message.error { background: rgba(220, 38, 38, 0.10); color: var(--danger); }
|
|
6967
|
+
|
|
6968
|
+
.global-message-host {
|
|
6969
|
+
position: fixed;
|
|
6970
|
+
top: 20px;
|
|
6971
|
+
left: 50%;
|
|
6972
|
+
transform: translateX(-50%);
|
|
6973
|
+
display: grid;
|
|
6762
6974
|
gap: 10px;
|
|
6763
|
-
|
|
6975
|
+
z-index: 2000;
|
|
6976
|
+
pointer-events: none;
|
|
6764
6977
|
}
|
|
6765
6978
|
|
|
6766
|
-
|
|
6979
|
+
.global-message {
|
|
6980
|
+
min-width: 240px;
|
|
6981
|
+
max-width: min(560px, calc(100vw - 32px));
|
|
6982
|
+
padding: 10px 14px;
|
|
6983
|
+
border-radius: 8px;
|
|
6767
6984
|
border: 1px solid var(--border);
|
|
6768
|
-
background:
|
|
6985
|
+
background: rgba(255, 255, 255, 0.96);
|
|
6986
|
+
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
|
|
6769
6987
|
color: var(--text);
|
|
6770
|
-
border-radius: 8px;
|
|
6771
|
-
padding: 10px 14px;
|
|
6772
|
-
font: inherit;
|
|
6773
|
-
cursor: pointer;
|
|
6774
6988
|
}
|
|
6775
6989
|
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
border-color: var(--primary);
|
|
6779
|
-
color: #fff;
|
|
6990
|
+
.global-message.success {
|
|
6991
|
+
border-color: rgba(21, 128, 61, 0.16);
|
|
6780
6992
|
}
|
|
6781
6993
|
|
|
6782
|
-
|
|
6783
|
-
|
|
6994
|
+
.global-message.error {
|
|
6995
|
+
border-color: rgba(220, 38, 38, 0.16);
|
|
6784
6996
|
}
|
|
6785
6997
|
|
|
6786
|
-
|
|
6787
|
-
|
|
6998
|
+
.info-list {
|
|
6999
|
+
display: grid;
|
|
7000
|
+
gap: 12px;
|
|
6788
7001
|
}
|
|
6789
7002
|
|
|
6790
|
-
.
|
|
7003
|
+
.info-item {
|
|
6791
7004
|
padding: 12px 14px;
|
|
7005
|
+
border: 1px solid var(--border);
|
|
6792
7006
|
border-radius: 8px;
|
|
6793
|
-
background: var(--
|
|
7007
|
+
background: var(--surface-soft);
|
|
7008
|
+
}
|
|
7009
|
+
|
|
7010
|
+
.info-item strong {
|
|
7011
|
+
display: block;
|
|
7012
|
+
margin-bottom: 4px;
|
|
7013
|
+
font-size: 12px;
|
|
6794
7014
|
color: var(--muted);
|
|
6795
7015
|
}
|
|
6796
7016
|
|
|
6797
|
-
.
|
|
6798
|
-
|
|
7017
|
+
.mono,
|
|
7018
|
+
.project-group-path,
|
|
7019
|
+
.session-path,
|
|
7020
|
+
.binding-detail code {
|
|
7021
|
+
font-family: "Cascadia Code", Consolas, "SF Mono", monospace;
|
|
6799
7022
|
}
|
|
6800
7023
|
|
|
6801
|
-
.
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
7024
|
+
.session-list {
|
|
7025
|
+
display: grid;
|
|
7026
|
+
gap: 16px;
|
|
7027
|
+
}
|
|
7028
|
+
|
|
7029
|
+
.project-group {
|
|
7030
|
+
border: 1px solid var(--border);
|
|
6806
7031
|
border-radius: 10px;
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
7032
|
+
background: var(--surface);
|
|
7033
|
+
padding: 16px;
|
|
7034
|
+
display: grid;
|
|
7035
|
+
gap: 14px;
|
|
6810
7036
|
}
|
|
6811
7037
|
|
|
6812
|
-
.
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
7038
|
+
.project-group-head {
|
|
7039
|
+
display: flex;
|
|
7040
|
+
justify-content: space-between;
|
|
7041
|
+
align-items: flex-start;
|
|
7042
|
+
gap: 16px;
|
|
6817
7043
|
}
|
|
6818
7044
|
|
|
6819
|
-
.
|
|
6820
|
-
|
|
6821
|
-
|
|
7045
|
+
.project-group-title {
|
|
7046
|
+
font-size: 16px;
|
|
7047
|
+
font-weight: 700;
|
|
7048
|
+
}
|
|
6822
7049
|
|
|
6823
|
-
.
|
|
7050
|
+
.project-group-path {
|
|
7051
|
+
color: var(--muted);
|
|
7052
|
+
font-size: 12px;
|
|
7053
|
+
margin-top: 4px;
|
|
7054
|
+
word-break: break-all;
|
|
7055
|
+
}
|
|
7056
|
+
|
|
7057
|
+
.project-group-count {
|
|
7058
|
+
color: var(--muted);
|
|
7059
|
+
font-size: 12px;
|
|
7060
|
+
white-space: nowrap;
|
|
7061
|
+
}
|
|
7062
|
+
|
|
7063
|
+
.project-session-list {
|
|
6824
7064
|
display: grid;
|
|
6825
|
-
gap:
|
|
7065
|
+
gap: 12px;
|
|
6826
7066
|
}
|
|
6827
7067
|
|
|
6828
7068
|
.session-card {
|
|
6829
7069
|
border: 1px solid var(--border);
|
|
6830
7070
|
border-radius: 10px;
|
|
6831
|
-
padding:
|
|
6832
|
-
background:
|
|
7071
|
+
padding: 14px;
|
|
7072
|
+
background: var(--surface-soft);
|
|
7073
|
+
}
|
|
7074
|
+
|
|
7075
|
+
.session-card.current-thread {
|
|
7076
|
+
border-color: rgba(22, 119, 255, 0.32);
|
|
7077
|
+
background: rgba(22, 119, 255, 0.03);
|
|
6833
7078
|
}
|
|
6834
7079
|
|
|
6835
7080
|
.session-head {
|
|
6836
|
-
display:
|
|
6837
|
-
|
|
6838
|
-
gap:
|
|
7081
|
+
display: grid;
|
|
7082
|
+
grid-template-columns: minmax(0, 1.9fr) 150px minmax(220px, 1fr) auto;
|
|
7083
|
+
gap: 16px;
|
|
6839
7084
|
align-items: center;
|
|
6840
|
-
|
|
7085
|
+
}
|
|
7086
|
+
|
|
7087
|
+
.session-main {
|
|
7088
|
+
min-width: 0;
|
|
7089
|
+
display: grid;
|
|
7090
|
+
gap: 4px;
|
|
6841
7091
|
}
|
|
6842
7092
|
|
|
6843
7093
|
.session-title {
|
|
6844
7094
|
font-weight: 700;
|
|
6845
7095
|
}
|
|
6846
7096
|
|
|
6847
|
-
.session-
|
|
7097
|
+
.session-title-row {
|
|
6848
7098
|
display: flex;
|
|
7099
|
+
align-items: center;
|
|
6849
7100
|
gap: 8px;
|
|
6850
7101
|
flex-wrap: wrap;
|
|
6851
|
-
margin: 8px 0;
|
|
6852
7102
|
}
|
|
6853
7103
|
|
|
6854
|
-
.session-
|
|
7104
|
+
.session-mark {
|
|
6855
7105
|
display: inline-flex;
|
|
6856
7106
|
align-items: center;
|
|
6857
|
-
padding:
|
|
7107
|
+
padding: 1px 8px;
|
|
6858
7108
|
border-radius: 999px;
|
|
6859
|
-
|
|
7109
|
+
background: rgba(22, 119, 255, 0.10);
|
|
7110
|
+
color: var(--primary);
|
|
7111
|
+
font-size: 12px;
|
|
7112
|
+
border: 1px solid rgba(22, 119, 255, 0.16);
|
|
7113
|
+
}
|
|
7114
|
+
|
|
7115
|
+
.session-thread {
|
|
6860
7116
|
color: var(--muted);
|
|
6861
|
-
background: #fff;
|
|
6862
7117
|
font-size: 12px;
|
|
6863
7118
|
}
|
|
6864
7119
|
|
|
6865
|
-
.session-
|
|
6866
|
-
|
|
6867
|
-
border-color: rgba(22, 101, 52, 0.26);
|
|
6868
|
-
background: rgba(22, 101, 52, 0.08);
|
|
7120
|
+
.session-thread code {
|
|
7121
|
+
word-break: break-all;
|
|
6869
7122
|
}
|
|
6870
7123
|
|
|
6871
|
-
.session-
|
|
6872
|
-
|
|
7124
|
+
.session-inline-action {
|
|
7125
|
+
border: 0;
|
|
7126
|
+
background: transparent;
|
|
7127
|
+
color: var(--primary);
|
|
7128
|
+
padding: 0;
|
|
7129
|
+
margin-left: 8px;
|
|
7130
|
+
font-size: 12px;
|
|
7131
|
+
}
|
|
7132
|
+
|
|
7133
|
+
.session-inline-action:hover {
|
|
7134
|
+
color: var(--primary-strong);
|
|
7135
|
+
text-decoration: underline;
|
|
7136
|
+
}
|
|
7137
|
+
|
|
7138
|
+
.session-cell {
|
|
7139
|
+
min-width: 0;
|
|
7140
|
+
display: grid;
|
|
7141
|
+
gap: 4px;
|
|
7142
|
+
}
|
|
7143
|
+
|
|
7144
|
+
.session-label {
|
|
7145
|
+
color: var(--muted);
|
|
6873
7146
|
font-size: 12px;
|
|
7147
|
+
}
|
|
7148
|
+
|
|
7149
|
+
.session-value,
|
|
7150
|
+
.session-path {
|
|
6874
7151
|
color: var(--muted);
|
|
7152
|
+
font-size: 12px;
|
|
6875
7153
|
word-break: break-all;
|
|
6876
7154
|
}
|
|
6877
7155
|
|
|
6878
7156
|
.session-actions {
|
|
6879
|
-
|
|
6880
|
-
|
|
7157
|
+
justify-content: flex-end;
|
|
7158
|
+
align-items: center;
|
|
6881
7159
|
flex-wrap: wrap;
|
|
6882
|
-
margin-top: 10px;
|
|
6883
7160
|
}
|
|
6884
7161
|
|
|
6885
7162
|
.panel-block {
|
|
@@ -6894,217 +7171,535 @@ function renderHtml() {
|
|
|
6894
7171
|
font-weight: 700;
|
|
6895
7172
|
}
|
|
6896
7173
|
|
|
6897
|
-
.
|
|
6898
|
-
|
|
6899
|
-
|
|
7174
|
+
.channel-shell {
|
|
7175
|
+
padding: 0;
|
|
7176
|
+
overflow: hidden;
|
|
6900
7177
|
}
|
|
6901
7178
|
|
|
6902
|
-
.
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
padding:
|
|
7179
|
+
.channel-tabs {
|
|
7180
|
+
display: flex;
|
|
7181
|
+
align-items: flex-end;
|
|
7182
|
+
gap: 0;
|
|
7183
|
+
padding: 0 20px;
|
|
7184
|
+
border-bottom: 1px solid var(--border);
|
|
7185
|
+
background: #ffffff;
|
|
6907
7186
|
}
|
|
6908
7187
|
|
|
6909
|
-
.
|
|
6910
|
-
display:
|
|
6911
|
-
|
|
6912
|
-
align-items: baseline;
|
|
6913
|
-
gap: 10px;
|
|
6914
|
-
margin-bottom: 6px;
|
|
7188
|
+
.command-sections {
|
|
7189
|
+
display: grid;
|
|
7190
|
+
gap: 14px;
|
|
6915
7191
|
}
|
|
6916
7192
|
|
|
6917
|
-
.
|
|
6918
|
-
|
|
7193
|
+
.command-section {
|
|
7194
|
+
border: 1px solid var(--border);
|
|
7195
|
+
border-radius: 8px;
|
|
7196
|
+
background: var(--surface-soft);
|
|
7197
|
+
overflow: hidden;
|
|
6919
7198
|
}
|
|
6920
7199
|
|
|
6921
|
-
.
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
7200
|
+
.command-section-title {
|
|
7201
|
+
margin: 0;
|
|
7202
|
+
padding: 10px 14px;
|
|
7203
|
+
font-size: 14px;
|
|
7204
|
+
font-weight: 700;
|
|
7205
|
+
border-bottom: 1px solid var(--border);
|
|
7206
|
+
background: #ffffff;
|
|
6926
7207
|
}
|
|
6927
7208
|
|
|
6928
|
-
.
|
|
7209
|
+
.command-list {
|
|
7210
|
+
display: grid;
|
|
7211
|
+
}
|
|
7212
|
+
|
|
7213
|
+
.command-item {
|
|
7214
|
+
display: grid;
|
|
7215
|
+
grid-template-columns: 280px minmax(0, 1fr);
|
|
7216
|
+
gap: 16px;
|
|
7217
|
+
padding: 10px 14px;
|
|
7218
|
+
border-top: 1px solid var(--border);
|
|
7219
|
+
}
|
|
7220
|
+
|
|
7221
|
+
.command-item:first-child {
|
|
7222
|
+
border-top: 0;
|
|
7223
|
+
}
|
|
7224
|
+
|
|
7225
|
+
.command-item code {
|
|
7226
|
+
word-break: break-all;
|
|
7227
|
+
}
|
|
7228
|
+
|
|
7229
|
+
.channel-tab {
|
|
7230
|
+
border: 0;
|
|
7231
|
+
border-bottom: 2px solid transparent;
|
|
7232
|
+
border-radius: 0;
|
|
7233
|
+
padding: 14px 18px 12px;
|
|
7234
|
+
background: transparent;
|
|
7235
|
+
color: var(--muted);
|
|
7236
|
+
margin-bottom: -1px;
|
|
7237
|
+
}
|
|
7238
|
+
|
|
7239
|
+
.channel-tab.active {
|
|
7240
|
+
color: var(--primary);
|
|
7241
|
+
border-bottom-color: var(--primary);
|
|
7242
|
+
background: transparent;
|
|
7243
|
+
}
|
|
7244
|
+
|
|
7245
|
+
.channel-view {
|
|
7246
|
+
display: none;
|
|
7247
|
+
padding: 20px;
|
|
7248
|
+
}
|
|
7249
|
+
|
|
7250
|
+
.channel-view.active {
|
|
7251
|
+
display: block;
|
|
7252
|
+
}
|
|
7253
|
+
|
|
7254
|
+
.binding-list {
|
|
7255
|
+
display: grid;
|
|
7256
|
+
gap: 10px;
|
|
7257
|
+
}
|
|
7258
|
+
|
|
7259
|
+
.binding-item {
|
|
7260
|
+
border: 1px solid var(--border);
|
|
7261
|
+
border-radius: 10px;
|
|
7262
|
+
background: var(--surface-soft);
|
|
7263
|
+
padding: 12px 14px;
|
|
7264
|
+
}
|
|
7265
|
+
|
|
7266
|
+
.binding-head {
|
|
7267
|
+
display: flex;
|
|
7268
|
+
justify-content: space-between;
|
|
7269
|
+
align-items: baseline;
|
|
7270
|
+
gap: 10px;
|
|
7271
|
+
margin-bottom: 6px;
|
|
7272
|
+
}
|
|
7273
|
+
|
|
7274
|
+
.binding-title {
|
|
7275
|
+
font-weight: 700;
|
|
7276
|
+
}
|
|
7277
|
+
|
|
7278
|
+
.binding-detail {
|
|
7279
|
+
color: var(--muted);
|
|
7280
|
+
font-size: 12px;
|
|
7281
|
+
margin-top: 4px;
|
|
7282
|
+
word-break: break-all;
|
|
7283
|
+
}
|
|
7284
|
+
|
|
7285
|
+
.binding-controls {
|
|
6929
7286
|
display: grid;
|
|
6930
7287
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
6931
7288
|
gap: 10px;
|
|
6932
7289
|
margin-top: 12px;
|
|
6933
7290
|
}
|
|
6934
7291
|
|
|
6935
|
-
.binding-
|
|
6936
|
-
|
|
6937
|
-
border: 1px
|
|
7292
|
+
.binding-table-wrap {
|
|
7293
|
+
margin-top: 12px;
|
|
7294
|
+
border: 1px solid var(--border);
|
|
6938
7295
|
border-radius: 10px;
|
|
7296
|
+
background: #ffffff;
|
|
7297
|
+
overflow: hidden;
|
|
7298
|
+
}
|
|
7299
|
+
|
|
7300
|
+
.binding-table {
|
|
7301
|
+
width: 100%;
|
|
7302
|
+
border-collapse: collapse;
|
|
7303
|
+
}
|
|
7304
|
+
|
|
7305
|
+
.binding-table th,
|
|
7306
|
+
.binding-table td {
|
|
7307
|
+
padding: 10px 12px;
|
|
7308
|
+
border-top: 1px solid var(--border);
|
|
7309
|
+
text-align: left;
|
|
7310
|
+
vertical-align: top;
|
|
7311
|
+
}
|
|
7312
|
+
|
|
7313
|
+
.binding-table thead th {
|
|
7314
|
+
border-top: 0;
|
|
7315
|
+
background: #f8fafc;
|
|
7316
|
+
color: var(--muted);
|
|
7317
|
+
font-size: 12px;
|
|
7318
|
+
font-weight: 700;
|
|
7319
|
+
}
|
|
7320
|
+
|
|
7321
|
+
.binding-table tbody tr.current {
|
|
7322
|
+
background: rgba(22, 119, 255, 0.04);
|
|
7323
|
+
}
|
|
7324
|
+
|
|
7325
|
+
.binding-table-title {
|
|
7326
|
+
font-weight: 700;
|
|
7327
|
+
word-break: break-word;
|
|
7328
|
+
}
|
|
7329
|
+
|
|
7330
|
+
.binding-table-thread,
|
|
7331
|
+
.binding-table-path {
|
|
7332
|
+
font-size: 12px;
|
|
6939
7333
|
color: var(--muted);
|
|
6940
|
-
|
|
7334
|
+
word-break: break-all;
|
|
7335
|
+
}
|
|
7336
|
+
|
|
7337
|
+
.binding-table-mark {
|
|
7338
|
+
display: inline-flex;
|
|
7339
|
+
align-items: center;
|
|
7340
|
+
margin-left: 8px;
|
|
7341
|
+
padding: 1px 8px;
|
|
7342
|
+
border-radius: 999px;
|
|
7343
|
+
background: rgba(22, 119, 255, 0.10);
|
|
7344
|
+
color: var(--primary);
|
|
7345
|
+
font-size: 12px;
|
|
7346
|
+
}
|
|
7347
|
+
|
|
7348
|
+
.binding-target-btn {
|
|
7349
|
+
border: 1px solid var(--border);
|
|
7350
|
+
border-radius: 8px;
|
|
7351
|
+
background: #ffffff;
|
|
7352
|
+
white-space: nowrap;
|
|
7353
|
+
}
|
|
7354
|
+
|
|
7355
|
+
.binding-target-btn.current {
|
|
7356
|
+
border-color: rgba(22, 119, 255, 0.30);
|
|
7357
|
+
background: rgba(22, 119, 255, 0.08);
|
|
7358
|
+
color: var(--primary);
|
|
6941
7359
|
}
|
|
6942
7360
|
|
|
6943
|
-
.
|
|
7361
|
+
.binding-empty {
|
|
7362
|
+
padding: 12px 14px;
|
|
7363
|
+
border: 1px dashed var(--border-strong);
|
|
7364
|
+
border-radius: 8px;
|
|
6944
7365
|
color: var(--muted);
|
|
7366
|
+
background: var(--surface-soft);
|
|
6945
7367
|
}
|
|
6946
7368
|
|
|
7369
|
+
.logs {
|
|
7370
|
+
white-space: pre-wrap;
|
|
7371
|
+
word-break: break-word;
|
|
7372
|
+
background: var(--code-bg);
|
|
7373
|
+
color: #e2e8f0;
|
|
7374
|
+
border-radius: 10px;
|
|
7375
|
+
padding: 16px;
|
|
7376
|
+
min-height: 420px;
|
|
7377
|
+
overflow: auto;
|
|
7378
|
+
}
|
|
7379
|
+
|
|
7380
|
+
.ghost,
|
|
6947
7381
|
.small {
|
|
6948
7382
|
color: var(--muted);
|
|
6949
7383
|
font-size: 12px;
|
|
6950
7384
|
}
|
|
6951
7385
|
|
|
6952
|
-
@media (max-width:
|
|
7386
|
+
@media (max-width: 1180px) {
|
|
7387
|
+
.overview-grid,
|
|
7388
|
+
.section-grid {
|
|
7389
|
+
grid-template-columns: 1fr;
|
|
7390
|
+
}
|
|
7391
|
+
}
|
|
7392
|
+
|
|
7393
|
+
@media (max-width: 980px) {
|
|
6953
7394
|
.shell { grid-template-columns: 1fr; }
|
|
6954
|
-
.sidebar { border-right: 0; border-bottom: 1px solid var(--border); }
|
|
6955
|
-
.
|
|
6956
|
-
.
|
|
6957
|
-
.
|
|
7395
|
+
.sidebar { border-right: 0; border-bottom: 1px solid var(--sidebar-border); }
|
|
7396
|
+
.nav { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
|
7397
|
+
.main { padding: 20px 20px 28px; }
|
|
7398
|
+
.field-row,
|
|
7399
|
+
.field-row.triple,
|
|
7400
|
+
.command-item,
|
|
6958
7401
|
.binding-controls { grid-template-columns: 1fr; }
|
|
7402
|
+
.status-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
7403
|
+
}
|
|
7404
|
+
|
|
7405
|
+
@media (max-width: 720px) {
|
|
7406
|
+
.nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
7407
|
+
.status-grid { grid-template-columns: 1fr; }
|
|
7408
|
+
.page-header,
|
|
7409
|
+
.panel-header,
|
|
7410
|
+
.project-group-head,
|
|
7411
|
+
.binding-head { flex-direction: column; align-items: stretch; }
|
|
7412
|
+
.session-head { grid-template-columns: 1fr; }
|
|
7413
|
+
.session-actions { justify-content: flex-start; }
|
|
6959
7414
|
}
|
|
6960
7415
|
</style>
|
|
6961
7416
|
</head>
|
|
6962
7417
|
<body>
|
|
6963
7418
|
<div class="shell">
|
|
6964
7419
|
<aside class="sidebar">
|
|
6965
|
-
<
|
|
6966
|
-
|
|
7420
|
+
<div class="brand">
|
|
7421
|
+
<p class="brand-title">Codex to IM</p>
|
|
7422
|
+
<p class="brand-copy">\u672C\u5730\u540E\u53F0\u3001\u4F1A\u8BDD\u5171\u4EAB\u3001\u901A\u9053\u7ED1\u5B9A\u548C\u8C03\u8BD5\u90FD\u8D70\u8FD9\u91CC\u3002</p>
|
|
7423
|
+
</div>
|
|
6967
7424
|
<nav class="nav">
|
|
6968
|
-
<
|
|
6969
|
-
<
|
|
6970
|
-
<
|
|
6971
|
-
<
|
|
6972
|
-
<
|
|
6973
|
-
<
|
|
6974
|
-
<a href="#logs">\u65E5\u5FD7</a>
|
|
7425
|
+
<button type="button" class="nav-link active" data-page="overview">\u6982\u89C8</button>
|
|
7426
|
+
<button type="button" class="nav-link" data-page="sessions">\u4F1A\u8BDD</button>
|
|
7427
|
+
<button type="button" class="nav-link" data-page="config">\u914D\u7F6E</button>
|
|
7428
|
+
<button type="button" class="nav-link" data-page="channels">\u901A\u9053</button>
|
|
7429
|
+
<button type="button" class="nav-link" data-page="logs">\u65E5\u5FD7</button>
|
|
7430
|
+
<button type="button" class="nav-link" data-page="commands">\u547D\u4EE4\u8BF4\u660E</button>
|
|
6975
7431
|
</nav>
|
|
6976
7432
|
</aside>
|
|
6977
7433
|
<main class="main">
|
|
6978
|
-
<section class="
|
|
6979
|
-
<div>
|
|
6980
|
-
<
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
<section class="status-grid">
|
|
6986
|
-
<div class="status-card">
|
|
6987
|
-
<strong>Bridge</strong>
|
|
6988
|
-
<div class="status-value" id="bridgeStatus">-</div>
|
|
6989
|
-
</div>
|
|
6990
|
-
<div class="status-card">
|
|
6991
|
-
<strong>Codex \u96C6\u6210</strong>
|
|
6992
|
-
<div class="status-value" id="integrationStatus">-</div>
|
|
6993
|
-
</div>
|
|
6994
|
-
<div class="status-card">
|
|
6995
|
-
<strong>Runtime</strong>
|
|
6996
|
-
<div class="status-value" id="runtimeStatus">-</div>
|
|
6997
|
-
</div>
|
|
6998
|
-
<div class="status-card">
|
|
6999
|
-
<strong>Desktop Sessions</strong>
|
|
7000
|
-
<div class="status-value" id="desktopSessionCount">-</div>
|
|
7001
|
-
</div>
|
|
7002
|
-
<div class="status-card">
|
|
7003
|
-
<strong>IM Bindings</strong>
|
|
7004
|
-
<div class="status-value" id="bindingCount">-</div>
|
|
7005
|
-
</div>
|
|
7006
|
-
<div class="status-card">
|
|
7007
|
-
<strong>Config Home</strong>
|
|
7008
|
-
<div class="status-value" id="homeStatus" style="font-size:14px;">-</div>
|
|
7434
|
+
<section class="page active" data-page="overview">
|
|
7435
|
+
<div class="page-header">
|
|
7436
|
+
<div>
|
|
7437
|
+
<h1 class="page-title">\u6982\u89C8</h1>
|
|
7438
|
+
<p class="page-copy">\u8FD0\u884C\u72B6\u6001\u3001\u540E\u53F0\u63A7\u5236\u548C\u5F53\u524D\u73AF\u5883\u96C6\u4E2D\u5728\u8FD9\u4E00\u9875\u3002</p>
|
|
7439
|
+
</div>
|
|
7009
7440
|
</div>
|
|
7010
|
-
</section>
|
|
7011
7441
|
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
\u8FD9\u91CC\u5217\u51FA\u6700\u8FD1\u5728 <code>Codex Windows App</code> \u4E2D\u6D3B\u8DC3\u8FC7\u7684\u672C\u5730\u4F1A\u8BDD\uFF0C\u4F5C\u4E3A\u63A5\u7BA1\u5230\u98DE\u4E66\u6216\u5FAE\u4FE1\u7684\u5019\u9009\u5165\u53E3\u3002
|
|
7442
|
+
<section class="status-grid">
|
|
7443
|
+
<div class="status-card">
|
|
7444
|
+
<strong>Bridge</strong>
|
|
7445
|
+
<div class="status-value" id="bridgeStatus">-</div>
|
|
7017
7446
|
</div>
|
|
7018
|
-
<div class="
|
|
7019
|
-
|
|
7447
|
+
<div class="status-card">
|
|
7448
|
+
<strong>Codex \u96C6\u6210</strong>
|
|
7449
|
+
<div class="status-value" id="integrationStatus">-</div>
|
|
7020
7450
|
</div>
|
|
7021
|
-
<div class="
|
|
7022
|
-
<
|
|
7451
|
+
<div class="status-card">
|
|
7452
|
+
<strong>Runtime</strong>
|
|
7453
|
+
<div class="status-value" id="runtimeStatus">-</div>
|
|
7454
|
+
</div>
|
|
7455
|
+
<div class="status-card">
|
|
7456
|
+
<strong>Desktop Sessions</strong>
|
|
7457
|
+
<div class="status-value" id="desktopSessionCount">-</div>
|
|
7458
|
+
</div>
|
|
7459
|
+
<div class="status-card">
|
|
7460
|
+
<strong>IM Bindings</strong>
|
|
7461
|
+
<div class="status-value" id="bindingCount">-</div>
|
|
7462
|
+
</div>
|
|
7463
|
+
<div class="status-card">
|
|
7464
|
+
<strong>Config Home</strong>
|
|
7465
|
+
<div class="status-value" id="homeStatus" style="font-size: 14px;">-</div>
|
|
7023
7466
|
</div>
|
|
7024
|
-
<div class="small" id="desktopSessionMeta" style="margin: 12px 0 14px;">\u6B63\u5728\u52A0\u8F7D\u2026</div>
|
|
7025
|
-
<div class="session-list" id="desktopSessionsList"></div>
|
|
7026
|
-
<div class="message" id="desktopMessage"></div>
|
|
7027
7467
|
</section>
|
|
7028
7468
|
|
|
7029
|
-
<div class="
|
|
7030
|
-
<section class="panel"
|
|
7031
|
-
<
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
<
|
|
7035
|
-
Runtime
|
|
7036
|
-
<select id="runtime">
|
|
7037
|
-
<option value="codex">codex</option>
|
|
7038
|
-
<option value="auto">auto</option>
|
|
7039
|
-
<option value="claude">claude</option>
|
|
7040
|
-
</select>
|
|
7041
|
-
</label>
|
|
7042
|
-
<label>
|
|
7043
|
-
\u9ED8\u8BA4\u6A21\u5F0F
|
|
7044
|
-
<select id="defaultMode">
|
|
7045
|
-
<option value="code">code</option>
|
|
7046
|
-
<option value="plan">plan</option>
|
|
7047
|
-
<option value="ask">ask</option>
|
|
7048
|
-
</select>
|
|
7049
|
-
</label>
|
|
7050
|
-
<label>
|
|
7051
|
-
/history \u8FD4\u56DE\u6761\u6570
|
|
7052
|
-
<input id="historyMessageLimit" type="number" min="1" max="20" value="8" />
|
|
7053
|
-
</label>
|
|
7054
|
-
</div>
|
|
7055
|
-
<label>
|
|
7056
|
-
\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55
|
|
7057
|
-
<input id="defaultWorkDir" placeholder="D:\\workspace\\project" />
|
|
7058
|
-
</label>
|
|
7059
|
-
<label>
|
|
7060
|
-
\u9ED8\u8BA4\u6A21\u578B
|
|
7061
|
-
<input id="defaultModel" placeholder="\u7559\u7A7A\u5219\u4F7F\u7528 runtime \u9ED8\u8BA4\u6A21\u578B" />
|
|
7062
|
-
</label>
|
|
7063
|
-
<div class="checkbox-row">
|
|
7064
|
-
<label class="checkbox"><input id="channelFeishu" type="checkbox" /> \u542F\u7528\u98DE\u4E66</label>
|
|
7065
|
-
<label class="checkbox"><input id="channelWeixin" type="checkbox" /> \u542F\u7528\u5FAE\u4FE1</label>
|
|
7066
|
-
<label class="checkbox"><input id="autoApprove" type="checkbox" /> \u81EA\u52A8\u6279\u51C6\u5DE5\u5177\u6743\u9650</label>
|
|
7067
|
-
</div>
|
|
7068
|
-
<div class="checkbox-row">
|
|
7069
|
-
<label class="checkbox"><input id="codexSkipGitRepoCheck" type="checkbox" /> \u5141\u8BB8\u5728\u672A\u4FE1\u4EFB Git \u76EE\u5F55\u8FD0\u884C Codex</label>
|
|
7469
|
+
<div class="overview-grid">
|
|
7470
|
+
<section class="panel">
|
|
7471
|
+
<div class="panel-header">
|
|
7472
|
+
<div>
|
|
7473
|
+
<h2>\u8FD0\u884C\u63A7\u5236</h2>
|
|
7474
|
+
<p>\u4FDD\u5B58\u914D\u7F6E\u540E\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5728\u8FD9\u91CC\u542F\u505C bridge\u3001\u6D4B\u8BD5 Codex \u6216\u5237\u65B0\u6574\u4F53\u72B6\u6001\u3002</p>
|
|
7070
7475
|
</div>
|
|
7071
|
-
<div class="small">\u5982\u679C\u65B0\u5EFA\u4F1A\u8BDD\u62A5 \u201CNot inside a trusted directory\u201D\uFF0C\u53EF\u4EE5\u6253\u5F00\u8FD9\u4E2A\u9009\u9879\u3002\u4FEE\u6539\u540E\u9700\u8981\u91CD\u542F Bridge \u624D\u4F1A\u751F\u6548\u3002</div>
|
|
7072
7476
|
</div>
|
|
7073
|
-
</section>
|
|
7074
|
-
|
|
7075
|
-
<section class="panel" id="ops">
|
|
7076
|
-
<h2>\u8FD0\u884C\u63A7\u5236</h2>
|
|
7077
7477
|
<div class="actions">
|
|
7078
7478
|
<button class="primary" id="startBridgeBtn">\u542F\u52A8 Bridge</button>
|
|
7079
7479
|
<button id="stopBridgeBtn">\u505C\u6B62 Bridge</button>
|
|
7480
|
+
<button id="restartBridgeBtn">\u91CD\u542F Bridge</button>
|
|
7080
7481
|
<button id="testCodexBtn">\u6D4B\u8BD5 Codex</button>
|
|
7081
7482
|
<button id="refreshBtn">\u5237\u65B0\u72B6\u6001</button>
|
|
7082
7483
|
</div>
|
|
7484
|
+
|
|
7083
7485
|
<div class="panel-block">
|
|
7084
7486
|
<p class="panel-subtitle">\u5F53\u524D\u80FD\u529B</p>
|
|
7085
|
-
<div class="notice">
|
|
7086
|
-
\u5DF2\u63A5\u901A\uFF1A\u4FDD\u5B58\u914D\u7F6E\u3001\u540E\u53F0\u542F\u505C\u3001\u98DE\u4E66\u51ED\u636E\u6D4B\u8BD5\u3001\u5FAE\u4FE1\u626B\u7801\u3001Codex \u8FDE\u63A5\u6D4B\u8BD5\u3001\u684C\u9762\u4F1A\u8BDD\u53D1\u73B0\u3001IM \u7ED1\u5B9A\u67E5\u770B\u4E0E\u7F51\u9875\u4FA7\u5207\u6362\u3002
|
|
7087
|
-
</div>
|
|
7487
|
+
<div class="notice">\u5DF2\u63A5\u901A\uFF1A\u4FDD\u5B58\u914D\u7F6E\u3001\u540E\u53F0\u542F\u505C\u3001\u98DE\u4E66\u51ED\u636E\u6D4B\u8BD5\u3001\u5FAE\u4FE1\u626B\u7801\u3001Codex \u8FDE\u63A5\u6D4B\u8BD5\u3001\u684C\u9762\u4F1A\u8BDD\u53D1\u73B0\u3001IM \u7ED1\u5B9A\u67E5\u770B\u4E0E\u7F51\u9875\u4FA7\u5207\u6362\u3002</div>
|
|
7088
7488
|
</div>
|
|
7489
|
+
|
|
7089
7490
|
<div class="panel-block">
|
|
7090
7491
|
<p class="panel-subtitle">\u53EF\u9009 Codex \u96C6\u6210</p>
|
|
7091
|
-
<div class="notice">
|
|
7092
|
-
\u4E3B\u6D41\u7A0B\u4E0D\u4F9D\u8D56\u8FD9\u5C42\u96C6\u6210\u3002\u53EA\u6709\u5F53\u4F60\u60F3\u5728 Codex \u91CC\u76F4\u63A5\u6253\u5F00 <code>codex-to-im</code>\uFF0C\u6216\u8005\u4FDD\u7559\u4E00\u4E2A\u201C\u5171\u4EAB\u5F53\u524D\u4F1A\u8BDD\u5230\u98DE\u4E66\u201D\u7684\u8F7B\u5165\u53E3\u65F6\uFF0C\u624D\u9700\u8981\u5B89\u88C5\u5B83\u3002
|
|
7093
|
-
</div>
|
|
7492
|
+
<div class="notice">\u4E3B\u6D41\u7A0B\u4E0D\u4F9D\u8D56\u8FD9\u5C42\u96C6\u6210\u3002\u53EA\u6709\u5F53\u4F60\u60F3\u5728 Codex \u91CC\u76F4\u63A5\u6253\u5F00 codex-to-im\uFF0C\u6216\u8005\u4FDD\u7559\u4E00\u4E2A\u201C\u5171\u4EAB\u5F53\u524D\u4F1A\u8BDD\u5230\u98DE\u4E66\u201D\u7684\u8F7B\u5165\u53E3\u65F6\uFF0C\u624D\u9700\u8981\u5B89\u88C5\u5B83\u3002</div>
|
|
7094
7493
|
<div class="actions" style="margin-top: 12px;">
|
|
7095
7494
|
<button id="installIntegrationBtn">\u5B89\u88C5\u53EF\u9009 Codex \u96C6\u6210</button>
|
|
7096
7495
|
</div>
|
|
7097
7496
|
</div>
|
|
7098
|
-
|
|
7099
|
-
\u5305\u6839\u76EE\u5F55\uFF1A<span id="packageRoot">-</span>
|
|
7100
|
-
</div>
|
|
7497
|
+
|
|
7101
7498
|
<div class="message" id="opsMessage"></div>
|
|
7102
7499
|
</section>
|
|
7500
|
+
|
|
7501
|
+
<section class="panel">
|
|
7502
|
+
<div class="panel-header">
|
|
7503
|
+
<div>
|
|
7504
|
+
<h2>\u5F53\u524D\u73AF\u5883</h2>
|
|
7505
|
+
<p>\u8FD9\u91CC\u663E\u793A\u672C\u673A\u8FD0\u884C\u65F6\u548C\u5173\u952E\u76EE\u5F55\uFF0C\u4FBF\u4E8E\u6392\u67E5\u90E8\u7F72\u95EE\u9898\u3002</p>
|
|
7506
|
+
</div>
|
|
7507
|
+
</div>
|
|
7508
|
+
<div class="info-list">
|
|
7509
|
+
<div class="info-item">
|
|
7510
|
+
<strong>\u5305\u6839\u76EE\u5F55</strong>
|
|
7511
|
+
<div class="mono" id="packageRoot">-</div>
|
|
7512
|
+
</div>
|
|
7513
|
+
<div class="info-item">
|
|
7514
|
+
<strong>\u914D\u7F6E\u76EE\u5F55</strong>
|
|
7515
|
+
<div class="mono" id="overviewHomeStatus">-</div>
|
|
7516
|
+
</div>
|
|
7517
|
+
<div class="info-item">
|
|
7518
|
+
<strong>\u684C\u9762\u4F1A\u8BDD\u6839\u76EE\u5F55</strong>
|
|
7519
|
+
<div class="mono" id="desktopRootStatus">-</div>
|
|
7520
|
+
</div>
|
|
7521
|
+
<div class="info-item">
|
|
7522
|
+
<strong>\u754C\u9762\u8BF4\u660E</strong>
|
|
7523
|
+
<div>\u5DE6\u4FA7\u5207\u6362\u9875\u9762\uFF1B\u201C\u4F1A\u8BDD\u201D\u7BA1\u7406\u684C\u9762 thread\uFF1B\u201C\u901A\u9053\u201D\u91CC\u67E5\u770B\u98DE\u4E66/\u5FAE\u4FE1\u5F53\u524D\u7ED1\u5B9A\u5E76\u76F4\u63A5\u5207\u6362\u3002</div>
|
|
7524
|
+
</div>
|
|
7525
|
+
</div>
|
|
7526
|
+
</section>
|
|
7527
|
+
</div>
|
|
7528
|
+
</section>
|
|
7529
|
+
|
|
7530
|
+
<section class="page" data-page="sessions">
|
|
7531
|
+
<div class="page-header">
|
|
7532
|
+
<div>
|
|
7533
|
+
<h1 class="page-title">\u4F1A\u8BDD</h1>
|
|
7534
|
+
<p class="page-copy">\u6309\u5DE5\u7A0B\u76EE\u5F55\u67E5\u770B\u6700\u8FD1\u684C\u9762\u4F1A\u8BDD\uFF0C\u5E76\u590D\u5236 thread \u6216\u63A5\u7BA1\u547D\u4EE4\u3002</p>
|
|
7535
|
+
</div>
|
|
7536
|
+
<div class="toolbar">
|
|
7537
|
+
<button id="refreshDesktopBtn">\u5237\u65B0\u684C\u9762\u4F1A\u8BDD</button>
|
|
7538
|
+
</div>
|
|
7539
|
+
</div>
|
|
7540
|
+
|
|
7541
|
+
<section class="panel" id="desktop">
|
|
7542
|
+
<div class="notice">\u8FD9\u91CC\u53EA\u5C55\u793A\u5728 Codex \u684C\u9762\u7D22\u5F15\u91CC\u6709\u540D\u5B57\u7684\u7EBF\u7A0B\uFF0C\u548C Windows App \u5DE6\u4FA7\u5217\u8868\u4FDD\u6301\u4E00\u81F4\u3002</div>
|
|
7543
|
+
<div class="notice" style="margin-top: 12px;">\u6700\u77ED\u8DEF\u5F84\uFF1A\u627E\u5230\u76EE\u6807 thread\uFF0C\u7136\u540E\u628A <code>/thread 019d1da4</code> \u8FD9\u6837\u7684\u547D\u4EE4\u53D1\u7ED9\u98DE\u4E66\u673A\u5668\u4EBA\uFF0C\u6216\u76F4\u63A5\u5230\u201C\u901A\u9053\u201D\u9875\u5207\u6362\u7ED1\u5B9A\u3002</div>
|
|
7544
|
+
<div class="small" id="desktopSessionMeta" style="margin: 14px 0 16px;">\u6B63\u5728\u52A0\u8F7D\u2026</div>
|
|
7545
|
+
<div class="session-list" id="desktopSessionsList"></div>
|
|
7546
|
+
<div class="message" id="desktopMessage"></div>
|
|
7547
|
+
</section>
|
|
7548
|
+
</section>
|
|
7549
|
+
|
|
7550
|
+
<section class="page" data-page="config">
|
|
7551
|
+
<div class="page-header">
|
|
7552
|
+
<div>
|
|
7553
|
+
<h1 class="page-title">\u914D\u7F6E</h1>
|
|
7554
|
+
<p class="page-copy">\u8FD9\u91CC\u7EF4\u62A4\u672C\u5730\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55\u3001\u8FD0\u884C\u6A21\u5F0F\u548C\u5168\u5C40\u884C\u4E3A\u5F00\u5173\u3002</p>
|
|
7555
|
+
</div>
|
|
7556
|
+
</div>
|
|
7557
|
+
|
|
7558
|
+
<section class="panel" id="config">
|
|
7559
|
+
<div class="panel-header">
|
|
7560
|
+
<div>
|
|
7561
|
+
<h2>\u57FA\u7840\u914D\u7F6E</h2>
|
|
7562
|
+
<p>\u4FDD\u5B58\u540E\u4F1A\u5199\u5165\u672C\u5730\u914D\u7F6E\u76EE\u5F55\uFF1B\u6D89\u53CA\u8FD0\u884C\u65F6\u7684\u9009\u9879\u901A\u5E38\u9700\u8981\u91CD\u542F Bridge \u624D\u751F\u6548\u3002</p>
|
|
7563
|
+
</div>
|
|
7564
|
+
<div class="toolbar">
|
|
7565
|
+
<button class="primary" id="saveConfigBtn">\u4FDD\u5B58\u914D\u7F6E</button>
|
|
7566
|
+
</div>
|
|
7567
|
+
</div>
|
|
7568
|
+
|
|
7569
|
+
<div class="fields">
|
|
7570
|
+
<div class="field-row triple">
|
|
7571
|
+
<label>
|
|
7572
|
+
Runtime
|
|
7573
|
+
<select id="runtime">
|
|
7574
|
+
<option value="codex" selected>codex</option>
|
|
7575
|
+
<option value="auto">auto</option>
|
|
7576
|
+
<option value="claude">claude</option>
|
|
7577
|
+
</select>
|
|
7578
|
+
</label>
|
|
7579
|
+
<label>
|
|
7580
|
+
\u9ED8\u8BA4\u6A21\u5F0F
|
|
7581
|
+
<select id="defaultMode">
|
|
7582
|
+
<option value="code">code</option>
|
|
7583
|
+
<option value="plan">plan</option>
|
|
7584
|
+
<option value="ask">ask</option>
|
|
7585
|
+
</select>
|
|
7586
|
+
</label>
|
|
7587
|
+
<label>
|
|
7588
|
+
/history \u8FD4\u56DE\u6761\u6570
|
|
7589
|
+
<input id="historyMessageLimit" type="number" min="1" max="20" value="8" />
|
|
7590
|
+
</label>
|
|
7591
|
+
</div>
|
|
7592
|
+
<label>
|
|
7593
|
+
\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55
|
|
7594
|
+
<input id="defaultWorkDir" placeholder="D:\\workspace\\project" />
|
|
7595
|
+
</label>
|
|
7596
|
+
<label>
|
|
7597
|
+
\u9ED8\u8BA4\u6A21\u578B
|
|
7598
|
+
<input id="defaultModel" placeholder="\u7559\u7A7A\u5219\u4F7F\u7528 runtime \u9ED8\u8BA4\u6A21\u578B" />
|
|
7599
|
+
</label>
|
|
7600
|
+
<div class="checkbox-row">
|
|
7601
|
+
<label class="checkbox"><input id="channelFeishu" type="checkbox" checked /> \u542F\u7528\u98DE\u4E66</label>
|
|
7602
|
+
<label class="checkbox"><input id="channelWeixin" type="checkbox" /> \u542F\u7528\u5FAE\u4FE1</label>
|
|
7603
|
+
<label class="checkbox"><input id="autoApprove" type="checkbox" /> \u81EA\u52A8\u6279\u51C6\u5DE5\u5177\u6743\u9650</label>
|
|
7604
|
+
</div>
|
|
7605
|
+
<div class="checkbox-row">
|
|
7606
|
+
<label class="checkbox"><input id="codexSkipGitRepoCheck" type="checkbox" checked /> \u5141\u8BB8\u5728\u672A\u4FE1\u4EFB Git \u76EE\u5F55\u8FD0\u884C Codex</label>
|
|
7607
|
+
</div>
|
|
7608
|
+
<div class="small">\u5982\u679C\u65B0\u5EFA\u4F1A\u8BDD\u62A5 \u201CNot inside a trusted directory\u201D\uFF0C\u53EF\u4EE5\u6253\u5F00\u8FD9\u4E2A\u9009\u9879\u3002\u4FEE\u6539\u540E\u9700\u8981\u91CD\u542F Bridge \u624D\u4F1A\u751F\u6548\u3002</div>
|
|
7609
|
+
</div>
|
|
7610
|
+
|
|
7611
|
+
<div class="message" id="configMessage"></div>
|
|
7612
|
+
</section>
|
|
7613
|
+
</section>
|
|
7614
|
+
|
|
7615
|
+
<section class="page" data-page="commands">
|
|
7616
|
+
<div class="page-header">
|
|
7617
|
+
<div>
|
|
7618
|
+
<h1 class="page-title">\u547D\u4EE4\u8BF4\u660E</h1>
|
|
7619
|
+
<p class="page-copy">\u8FD9\u91CC\u5217\u51FA\u5F53\u524D\u6865\u63A5\u804A\u5929\u91CC\u53EF\u7528\u7684\u547D\u4EE4\uFF0C\u98DE\u4E66\u548C\u5FAE\u4FE1\u5171\u7528\u540C\u4E00\u5957\u8BED\u4E49\u3002</p>
|
|
7620
|
+
</div>
|
|
7621
|
+
</div>
|
|
7622
|
+
|
|
7623
|
+
<section class="panel">
|
|
7624
|
+
<div class="panel-header">
|
|
7625
|
+
<div>
|
|
7626
|
+
<h2>\u547D\u4EE4\u4F7F\u7528\u8BF4\u660E</h2>
|
|
7627
|
+
<p>\u4E0B\u9762\u8FD9\u4E9B\u547D\u4EE4\u9002\u7528\u4E8E\u5F53\u524D\u6865\u63A5\u5230\u7684\u804A\u5929\u901A\u9053\uFF0C\u98DE\u4E66\u548C\u5FAE\u4FE1\u5171\u7528\u540C\u4E00\u5957\u547D\u4EE4\u8BED\u4E49\u3002</p>
|
|
7628
|
+
</div>
|
|
7629
|
+
</div>
|
|
7630
|
+
|
|
7631
|
+
<div class="notice" style="margin-bottom: 16px;">\u6700\u77ED\u4F7F\u7528\u8DEF\u5F84\uFF1A\u5148\u53D1 <code>/threads</code> \u67E5\u770B\u6700\u8FD1\u684C\u9762\u4F1A\u8BDD\uFF0C\u518D\u53D1 <code>/thread 1</code> \u63A5\u7BA1\uFF1B\u4E4B\u540E\u76F4\u63A5\u53D1\u9001\u6587\u672C\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002</div>
|
|
7632
|
+
|
|
7633
|
+
<div class="command-sections">
|
|
7634
|
+
<section class="command-section">
|
|
7635
|
+
<h3 class="command-section-title">\u6700\u5E38\u7528</h3>
|
|
7636
|
+
<div class="command-list">
|
|
7637
|
+
<div class="command-item"><code>/help</code><div>\u67E5\u770B\u5B8C\u6574\u547D\u4EE4\u8BF4\u660E\u3002</div></div>
|
|
7638
|
+
<div class="command-item"><code>/threads</code><div>\u5217\u51FA\u6700\u8FD1\u684C\u9762\u4F1A\u8BDD\u3002</div></div>
|
|
7639
|
+
<div class="command-item"><code>/thread <thread-id | \u5E8F\u53F7></code><div>\u7ED1\u5B9A\u684C\u9762 thread\uFF0C\u63A5\u7BA1\u684C\u9762\u4F1A\u8BDD\u3002</div></div>
|
|
7640
|
+
<div class="command-item"><code>\u76F4\u63A5\u53D1\u9001\u6587\u672C</code><div>\u7EE7\u7EED\u5F53\u524D\u5DF2\u7ED1\u5B9A\u4F1A\u8BDD\u3002</div></div>
|
|
7641
|
+
<div class="command-item"><code>/status</code><div>\u67E5\u770B\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u4E86\u54EA\u6761\u4F1A\u8BDD\u3001thread\u3001\u76EE\u5F55\u548C\u6A21\u5F0F\u3002</div></div>
|
|
7642
|
+
<div class="command-item"><code>/history</code><div>\u67E5\u770B\u5F53\u524D\u4F1A\u8BDD\u6700\u8FD1 N \u6761\u6D88\u606F\u3002</div></div>
|
|
7643
|
+
</div>
|
|
7644
|
+
</section>
|
|
7645
|
+
|
|
7646
|
+
<section class="command-section">
|
|
7647
|
+
<h3 class="command-section-title">\u5207\u6362\u4E0E\u7ED1\u5B9A</h3>
|
|
7648
|
+
<div class="command-list">
|
|
7649
|
+
<div class="command-item"><code>/sessions</code><div>\u5217\u51FA\u5185\u90E8\u4F1A\u8BDD\u3002</div></div>
|
|
7650
|
+
<div class="command-item"><code>/use <session-id | \u5E8F\u53F7></code><div>\u5207\u6362\u5230\u5DF2\u6709\u5185\u90E8\u4F1A\u8BDD\u3002</div></div>
|
|
7651
|
+
<div class="command-item"><code>/bind <session-id | thread-id | \u5E8F\u53F7></code><div>\u667A\u80FD\u7ED1\u5B9A\uFF0C\u517C\u5BB9\u65E7\u7528\u6CD5\uFF1B\u53EF\u7ED1\u5B9A\u5185\u90E8\u4F1A\u8BDD\u6216\u684C\u9762 thread\u3002</div></div>
|
|
7652
|
+
</div>
|
|
7653
|
+
</section>
|
|
7654
|
+
|
|
7655
|
+
<section class="command-section">
|
|
7656
|
+
<h3 class="command-section-title">\u4F1A\u8BDD\u8BBE\u7F6E</h3>
|
|
7657
|
+
<div class="command-list">
|
|
7658
|
+
<div class="command-item"><code>/new [\u7EDD\u5BF9\u8DEF\u5F84]</code><div>\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u53EF\u9009\u5730\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55\u3002</div></div>
|
|
7659
|
+
<div class="command-item"><code>/cwd /path/to/project</code><div>\u4FEE\u6539\u5F53\u524D\u4F1A\u8BDD\u5DE5\u4F5C\u76EE\u5F55\u3002</div></div>
|
|
7660
|
+
<div class="command-item"><code>/mode plan|code|ask</code><div>\u4FEE\u6539\u5F53\u524D\u4F1A\u8BDD\u6A21\u5F0F\u3002</div></div>
|
|
7661
|
+
<div class="command-item"><code>/stop</code><div>\u505C\u6B62\u5F53\u524D\u4EFB\u52A1\u3002</div></div>
|
|
7662
|
+
</div>
|
|
7663
|
+
</section>
|
|
7664
|
+
|
|
7665
|
+
<section class="command-section">
|
|
7666
|
+
<h3 class="command-section-title">\u6743\u9650</h3>
|
|
7667
|
+
<div class="command-list">
|
|
7668
|
+
<div class="command-item"><code>/perm allow|allow_session|deny <id></code><div>\u6587\u672C\u65B9\u5F0F\u5904\u7406\u4E00\u4E2A\u5F85\u6279\u51C6\u6743\u9650\u3002</div></div>
|
|
7669
|
+
<div class="command-item"><code>1 / 2 / 3</code><div>\u5FEB\u901F\u5904\u7406\u5355\u4E2A\u5F85\u6279\u51C6\u6743\u9650\u3002</div></div>
|
|
7670
|
+
</div>
|
|
7671
|
+
</section>
|
|
7672
|
+
</div>
|
|
7673
|
+
</section>
|
|
7674
|
+
</section>
|
|
7675
|
+
|
|
7676
|
+
<section class="page" data-page="channels">
|
|
7677
|
+
<div class="page-header">
|
|
7678
|
+
<div>
|
|
7679
|
+
<h1 class="page-title">\u901A\u9053</h1>
|
|
7680
|
+
<p class="page-copy">\u6BCF\u4E2A\u901A\u9053\u90FD\u663E\u793A\u5F53\u524D\u7ED1\u5B9A\u7684\u4F1A\u8BDD\uFF0C\u5E76\u652F\u6301\u5728\u7F51\u9875\u91CC\u76F4\u63A5\u6539\u7ED1\u3002</p>
|
|
7681
|
+
</div>
|
|
7103
7682
|
</div>
|
|
7104
7683
|
|
|
7105
|
-
<
|
|
7106
|
-
<
|
|
7107
|
-
<
|
|
7684
|
+
<section class="panel channel-shell">
|
|
7685
|
+
<div class="channel-tabs" role="tablist" aria-label="\u901A\u9053\u914D\u7F6E">
|
|
7686
|
+
<button type="button" class="channel-tab active" data-channel="feishu" role="tab" aria-selected="true">\u98DE\u4E66</button>
|
|
7687
|
+
<button type="button" class="channel-tab" data-channel="weixin" role="tab" aria-selected="false">\u5FAE\u4FE1</button>
|
|
7688
|
+
</div>
|
|
7689
|
+
|
|
7690
|
+
<div class="channel-view active" data-channel="feishu" role="tabpanel">
|
|
7691
|
+
<section id="feishu">
|
|
7692
|
+
<div class="panel-header">
|
|
7693
|
+
<div>
|
|
7694
|
+
<h2>\u98DE\u4E66 / Lark</h2>
|
|
7695
|
+
<p>\u586B\u5199\u51ED\u636E\u3001\u6D4B\u8BD5\u53EF\u7528\u6027\uFF0C\u5E76\u67E5\u770B\u5F53\u524D\u98DE\u4E66\u804A\u5929\u7ED1\u5B9A\u5230\u54EA\u6761\u4F1A\u8BDD\u3002</p>
|
|
7696
|
+
</div>
|
|
7697
|
+
<div class="toolbar">
|
|
7698
|
+
<button id="saveFeishuChannelBtn">\u4FDD\u5B58\u901A\u9053\u914D\u7F6E</button>
|
|
7699
|
+
<button id="testFeishuBtn">\u6D4B\u8BD5\u98DE\u4E66\u51ED\u636E</button>
|
|
7700
|
+
</div>
|
|
7701
|
+
</div>
|
|
7702
|
+
|
|
7108
7703
|
<div class="fields">
|
|
7109
7704
|
<div class="field-row">
|
|
7110
7705
|
<label>
|
|
@@ -7130,28 +7725,48 @@ function renderHtml() {
|
|
|
7130
7725
|
<label class="checkbox"><input id="feishuStreamingEnabled" type="checkbox" checked /> \u542F\u7528\u98DE\u4E66\u6D41\u5F0F\u54CD\u5E94\u5361\u7247</label>
|
|
7131
7726
|
</div>
|
|
7132
7727
|
<div class="small">\u9700\u8981\u98DE\u4E66\u4FA7\u5DF2\u5F00\u901A\u53EF\u66F4\u65B0\u5361\u7247\u7684\u76F8\u5173\u80FD\u529B\uFF1B\u5982\u679C\u6743\u9650\u4E0D\u8DB3\uFF0C\u4F1A\u81EA\u52A8\u56DE\u9000\u4E3A\u6700\u7EC8\u7ED3\u679C\u6D88\u606F\u3002</div>
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
</
|
|
7728
|
+
</div>
|
|
7729
|
+
|
|
7730
|
+
<div class="panel-block">
|
|
7731
|
+
<p class="panel-subtitle">\u901A\u9053\u72B6\u6001</p>
|
|
7732
|
+
<div class="small" id="feishuRuntimeMeta">\u6B63\u5728\u52A0\u8F7D\u2026</div>
|
|
7137
7733
|
</div>
|
|
7138
7734
|
<div class="panel-block">
|
|
7139
7735
|
<p class="panel-subtitle">\u5F53\u524D\u98DE\u4E66\u7ED1\u5B9A</p>
|
|
7140
7736
|
<div class="small" id="feishuBindingMeta">\u6B63\u5728\u52A0\u8F7D\u2026</div>
|
|
7141
7737
|
<div class="binding-list" id="feishuBindings" style="margin-top: 12px;"></div>
|
|
7142
7738
|
</div>
|
|
7739
|
+
|
|
7143
7740
|
<div class="message" id="feishuMessage"></div>
|
|
7144
|
-
|
|
7741
|
+
</section>
|
|
7742
|
+
</div>
|
|
7743
|
+
|
|
7744
|
+
<div class="channel-view" data-channel="weixin" role="tabpanel">
|
|
7745
|
+
<section id="wechat">
|
|
7746
|
+
<div class="panel-header">
|
|
7747
|
+
<div>
|
|
7748
|
+
<h2>\u5FAE\u4FE1</h2>
|
|
7749
|
+
<p>\u626B\u7801\u767B\u5F55\u5FAE\u4FE1\u5E76\u67E5\u770B\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u7684\u4F1A\u8BDD\u3002</p>
|
|
7750
|
+
</div>
|
|
7751
|
+
<div class="toolbar">
|
|
7752
|
+
<button id="saveWeixinChannelBtn">\u4FDD\u5B58\u901A\u9053\u914D\u7F6E</button>
|
|
7753
|
+
<button id="weixinLoginBtn">\u5F00\u59CB\u5FAE\u4FE1\u626B\u7801</button>
|
|
7754
|
+
</div>
|
|
7755
|
+
</div>
|
|
7145
7756
|
|
|
7146
|
-
<section class="panel" id="wechat">
|
|
7147
|
-
<h2>\u5FAE\u4FE1</h2>
|
|
7148
7757
|
<div class="fields">
|
|
7149
7758
|
<div class="checkbox-row">
|
|
7150
7759
|
<label class="checkbox"><input id="weixinMediaEnabled" type="checkbox" /> \u542F\u7528\u56FE\u7247 / \u6587\u4EF6 / \u89C6\u9891\u5165\u7AD9\u4E0B\u8F7D</label>
|
|
7151
7760
|
</div>
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
</
|
|
7761
|
+
</div>
|
|
7762
|
+
<div class="panel-block">
|
|
7763
|
+
<p class="panel-subtitle">\u901A\u9053\u72B6\u6001</p>
|
|
7764
|
+
<div class="small" id="weixinRuntimeMeta">\u6B63\u5728\u52A0\u8F7D\u2026</div>
|
|
7765
|
+
</div>
|
|
7766
|
+
<div class="panel-block">
|
|
7767
|
+
<p class="panel-subtitle">\u5DF2\u767B\u5F55\u5FAE\u4FE1\u8D26\u53F7</p>
|
|
7768
|
+
<div class="small" id="weixinAccountMeta">\u6B63\u5728\u52A0\u8F7D\u2026</div>
|
|
7769
|
+
<div class="binding-list" id="weixinAccounts" style="margin-top: 12px;"></div>
|
|
7155
7770
|
</div>
|
|
7156
7771
|
<div class="panel-block">
|
|
7157
7772
|
<p class="panel-subtitle">\u5F53\u524D\u5FAE\u4FE1\u7ED1\u5B9A</p>
|
|
@@ -7159,23 +7774,41 @@ function renderHtml() {
|
|
|
7159
7774
|
<div class="binding-list" id="weixinBindings" style="margin-top: 12px;"></div>
|
|
7160
7775
|
</div>
|
|
7161
7776
|
<div class="message" id="weixinMessage"></div>
|
|
7162
|
-
|
|
7777
|
+
</section>
|
|
7778
|
+
</div>
|
|
7779
|
+
</section>
|
|
7780
|
+
</section>
|
|
7781
|
+
|
|
7782
|
+
<section class="page" data-page="logs">
|
|
7783
|
+
<div class="page-header">
|
|
7784
|
+
<div>
|
|
7785
|
+
<h1 class="page-title">\u65E5\u5FD7</h1>
|
|
7786
|
+
<p class="page-copy">\u65E5\u5FD7\u9875\u53EA\u8D1F\u8D23\u67E5\u770B bridge \u65E5\u5FD7\uFF0C\u4FBF\u4E8E\u6392\u67E5\u8FD0\u884C\u548C\u901A\u9053\u95EE\u9898\u3002</p>
|
|
7787
|
+
</div>
|
|
7788
|
+
<div class="toolbar">
|
|
7789
|
+
<button id="refreshLogsBtn">\u5237\u65B0\u65E5\u5FD7</button>
|
|
7790
|
+
</div>
|
|
7163
7791
|
</div>
|
|
7164
7792
|
|
|
7165
7793
|
<section class="panel" id="logs">
|
|
7166
|
-
<h2>\u65E5\u5FD7</h2>
|
|
7167
7794
|
<div class="logs" id="logsOutput">\u7B49\u5F85\u52A0\u8F7D\u65E5\u5FD7\u2026</div>
|
|
7168
7795
|
</section>
|
|
7169
|
-
</
|
|
7796
|
+
</section>
|
|
7170
7797
|
</main>
|
|
7171
7798
|
</div>
|
|
7799
|
+
<div id="globalMessageHost" class="global-message-host" aria-live="polite"></div>
|
|
7172
7800
|
|
|
7173
7801
|
<script>
|
|
7174
7802
|
const state = {
|
|
7175
7803
|
config: null,
|
|
7804
|
+
bridgeStatus: null,
|
|
7176
7805
|
desktopSessions: [],
|
|
7177
7806
|
bindings: [],
|
|
7178
7807
|
bindingOptions: [],
|
|
7808
|
+
weixinAccounts: [],
|
|
7809
|
+
desktopRoot: '',
|
|
7810
|
+
activePage: 'overview',
|
|
7811
|
+
activeChannel: 'feishu',
|
|
7179
7812
|
};
|
|
7180
7813
|
|
|
7181
7814
|
function escapeHtml(value) {
|
|
@@ -7196,6 +7829,16 @@ function renderHtml() {
|
|
|
7196
7829
|
return '/thread ' + value.slice(0, 12);
|
|
7197
7830
|
}
|
|
7198
7831
|
|
|
7832
|
+
function pathSegments(value) {
|
|
7833
|
+
const normalized = String(value || '').split('/').join('\\\\');
|
|
7834
|
+
return normalized.split('\\\\').filter(Boolean);
|
|
7835
|
+
}
|
|
7836
|
+
|
|
7837
|
+
function baseName(value) {
|
|
7838
|
+
const segments = pathSegments(value);
|
|
7839
|
+
return segments[segments.length - 1] || value || '(no cwd)';
|
|
7840
|
+
}
|
|
7841
|
+
|
|
7199
7842
|
function formatTime(value) {
|
|
7200
7843
|
if (!value) return '-';
|
|
7201
7844
|
const date = new Date(value);
|
|
@@ -7207,6 +7850,33 @@ function renderHtml() {
|
|
|
7207
7850
|
return option.label + ' \xB7 ' + option.description;
|
|
7208
7851
|
}
|
|
7209
7852
|
|
|
7853
|
+
function renderBindingTable(binding) {
|
|
7854
|
+
const sessions = state.desktopSessions || [];
|
|
7855
|
+
if (!sessions.length) {
|
|
7856
|
+
return '<div class="binding-empty">\u5F53\u524D\u8FD8\u6CA1\u6709\u548C\u4F1A\u8BDD\u9875\u4E00\u81F4\u7684\u547D\u540D\u684C\u9762\u7EBF\u7A0B\u3002</div>';
|
|
7857
|
+
}
|
|
7858
|
+
|
|
7859
|
+
return ''
|
|
7860
|
+
+ '<div class="binding-table-wrap">'
|
|
7861
|
+
+ '<table class="binding-table">'
|
|
7862
|
+
+ '<thead><tr><th>\u6807\u9898</th><th>Thread</th><th>\u76EE\u5F55</th><th>\u64CD\u4F5C</th></tr></thead>'
|
|
7863
|
+
+ '<tbody>'
|
|
7864
|
+
+ sessions.map((session) => {
|
|
7865
|
+
const targetKey = 'desktop:' + session.threadId;
|
|
7866
|
+
const active = targetKey === binding.currentTargetKey;
|
|
7867
|
+
return ''
|
|
7868
|
+
+ '<tr class="' + (active ? 'current' : '') + '">'
|
|
7869
|
+
+ '<td><div class="binding-table-title">' + escapeHtml(session.title || 'Untitled Session') + (active ? '<span class="binding-table-mark">\u5F53\u524D</span>' : '') + '</div></td>'
|
|
7870
|
+
+ '<td><div class="binding-table-thread"><code>' + escapeHtml(session.threadId) + '</code></div></td>'
|
|
7871
|
+
+ '<td><div class="binding-table-path">' + escapeHtml(session.cwd || '(no cwd)') + '</div></td>'
|
|
7872
|
+
+ '<td><button type="button" class="binding-target-btn' + (active ? ' current' : '') + '" data-action="switch-binding-target" data-binding-id="' + escapeHtml(binding.id) + '" data-target-key="' + escapeHtml(targetKey) + '"' + (active ? ' disabled' : '') + '>' + (active ? '\u5F53\u524D\u4F1A\u8BDD' : '\u5207\u6362\u5230\u5F53\u524D\u4F1A\u8BDD') + '</button></td>'
|
|
7873
|
+
+ '</tr>';
|
|
7874
|
+
}).join('')
|
|
7875
|
+
+ '</tbody>'
|
|
7876
|
+
+ '</table>'
|
|
7877
|
+
+ '</div>';
|
|
7878
|
+
}
|
|
7879
|
+
|
|
7210
7880
|
function enabledChannelsFromForm() {
|
|
7211
7881
|
const channels = [];
|
|
7212
7882
|
if (document.getElementById('channelFeishu').checked) channels.push('feishu');
|
|
@@ -7235,53 +7905,316 @@ function renderHtml() {
|
|
|
7235
7905
|
|
|
7236
7906
|
function showMessage(id, type, message) {
|
|
7237
7907
|
const node = document.getElementById(id);
|
|
7908
|
+
if (!node) return;
|
|
7238
7909
|
node.className = 'message show ' + type;
|
|
7239
7910
|
node.textContent = message;
|
|
7240
7911
|
}
|
|
7241
7912
|
|
|
7913
|
+
function showGlobalMessage(type, message) {
|
|
7914
|
+
const host = document.getElementById('globalMessageHost');
|
|
7915
|
+
if (!host) return;
|
|
7916
|
+
|
|
7917
|
+
const item = document.createElement('div');
|
|
7918
|
+
item.className = 'global-message ' + (type || 'success');
|
|
7919
|
+
item.textContent = message;
|
|
7920
|
+
host.appendChild(item);
|
|
7921
|
+
|
|
7922
|
+
window.setTimeout(() => {
|
|
7923
|
+
item.remove();
|
|
7924
|
+
}, 2200);
|
|
7925
|
+
}
|
|
7926
|
+
|
|
7927
|
+
function setActivePage(page, syncHash) {
|
|
7928
|
+
const nextPage = ['overview', 'sessions', 'config', 'commands', 'channels', 'logs'].includes(page) ? page : 'overview';
|
|
7929
|
+
state.activePage = nextPage;
|
|
7930
|
+
|
|
7931
|
+
document.querySelectorAll('.nav-link').forEach((element) => {
|
|
7932
|
+
const node = element;
|
|
7933
|
+
node.classList.toggle('active', node.dataset.page === nextPage);
|
|
7934
|
+
});
|
|
7935
|
+
|
|
7936
|
+
document.querySelectorAll('.page').forEach((element) => {
|
|
7937
|
+
const node = element;
|
|
7938
|
+
node.classList.toggle('active', node.dataset.page === nextPage);
|
|
7939
|
+
});
|
|
7940
|
+
|
|
7941
|
+
if (syncHash !== false) {
|
|
7942
|
+
const hash = nextPage === 'channels'
|
|
7943
|
+
? '#channels/' + state.activeChannel
|
|
7944
|
+
: '#' + nextPage;
|
|
7945
|
+
if (window.location.hash !== hash) {
|
|
7946
|
+
history.replaceState(null, '', hash);
|
|
7947
|
+
}
|
|
7948
|
+
}
|
|
7949
|
+
}
|
|
7950
|
+
|
|
7951
|
+
function setActiveChannel(channel, syncHash) {
|
|
7952
|
+
const nextChannel = channel === 'weixin' ? 'weixin' : 'feishu';
|
|
7953
|
+
state.activeChannel = nextChannel;
|
|
7954
|
+
|
|
7955
|
+
document.querySelectorAll('.channel-tab').forEach((element) => {
|
|
7956
|
+
const node = element;
|
|
7957
|
+
const active = node.dataset.channel === nextChannel;
|
|
7958
|
+
node.classList.toggle('active', active);
|
|
7959
|
+
node.setAttribute('aria-selected', active ? 'true' : 'false');
|
|
7960
|
+
});
|
|
7961
|
+
|
|
7962
|
+
document.querySelectorAll('.channel-view').forEach((element) => {
|
|
7963
|
+
const node = element;
|
|
7964
|
+
const active = node.dataset.channel === nextChannel;
|
|
7965
|
+
node.classList.toggle('active', active);
|
|
7966
|
+
node.hidden = !active;
|
|
7967
|
+
});
|
|
7968
|
+
|
|
7969
|
+
if (syncHash !== false && state.activePage === 'channels') {
|
|
7970
|
+
const hash = '#channels/' + nextChannel;
|
|
7971
|
+
if (window.location.hash !== hash) {
|
|
7972
|
+
history.replaceState(null, '', hash);
|
|
7973
|
+
}
|
|
7974
|
+
}
|
|
7975
|
+
}
|
|
7976
|
+
|
|
7977
|
+
function syncPageFromHash() {
|
|
7978
|
+
const raw = String(window.location.hash || '').replace(/^#/, '');
|
|
7979
|
+
if (!raw) {
|
|
7980
|
+
setActivePage('overview', false);
|
|
7981
|
+
setActiveChannel('feishu', false);
|
|
7982
|
+
return;
|
|
7983
|
+
}
|
|
7984
|
+
|
|
7985
|
+
if (raw.startsWith('channels/')) {
|
|
7986
|
+
setActivePage('channels', false);
|
|
7987
|
+
setActiveChannel(raw.split('/')[1] || 'feishu', false);
|
|
7988
|
+
return;
|
|
7989
|
+
}
|
|
7990
|
+
|
|
7991
|
+
setActivePage(raw, false);
|
|
7992
|
+
}
|
|
7993
|
+
|
|
7242
7994
|
async function copyText(value, successMessage) {
|
|
7243
7995
|
if (!navigator.clipboard || !value) {
|
|
7244
7996
|
throw new Error('\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u590D\u5236\uFF0C\u6216\u6CA1\u6709\u53EF\u590D\u5236\u7684\u5185\u5BB9\u3002');
|
|
7245
7997
|
}
|
|
7246
7998
|
await navigator.clipboard.writeText(value);
|
|
7247
|
-
|
|
7999
|
+
showGlobalMessage('success', successMessage);
|
|
8000
|
+
}
|
|
8001
|
+
|
|
8002
|
+
function groupDesktopSessions(sessions) {
|
|
8003
|
+
const groups = new Map();
|
|
8004
|
+
for (const session of sessions || []) {
|
|
8005
|
+
const key = session.cwd || '(no cwd)';
|
|
8006
|
+
if (!groups.has(key)) {
|
|
8007
|
+
groups.set(key, {
|
|
8008
|
+
key,
|
|
8009
|
+
name: baseName(key),
|
|
8010
|
+
cwd: key,
|
|
8011
|
+
latest: session.lastEventAt || '',
|
|
8012
|
+
sessions: [],
|
|
8013
|
+
});
|
|
8014
|
+
}
|
|
8015
|
+
const group = groups.get(key);
|
|
8016
|
+
group.sessions.push(session);
|
|
8017
|
+
if ((session.lastEventAt || '') > group.latest) {
|
|
8018
|
+
group.latest = session.lastEventAt || '';
|
|
8019
|
+
}
|
|
8020
|
+
}
|
|
8021
|
+
|
|
8022
|
+
return Array.from(groups.values())
|
|
8023
|
+
.map((group) => ({
|
|
8024
|
+
...group,
|
|
8025
|
+
sessions: group.sessions.sort((left, right) => (right.lastEventAt || '').localeCompare(left.lastEventAt || '')),
|
|
8026
|
+
}))
|
|
8027
|
+
.sort((left, right) => {
|
|
8028
|
+
const timeOrder = (right.latest || '').localeCompare(left.latest || '');
|
|
8029
|
+
if (timeOrder !== 0) return timeOrder;
|
|
8030
|
+
return left.name.localeCompare(right.name, 'zh-CN');
|
|
8031
|
+
});
|
|
8032
|
+
}
|
|
8033
|
+
|
|
8034
|
+
function isChannelEnabled(channelType) {
|
|
8035
|
+
return Boolean(state.config && (state.config.enabledChannels || []).includes(channelType));
|
|
8036
|
+
}
|
|
8037
|
+
|
|
8038
|
+
function runningChannels() {
|
|
8039
|
+
return state.bridgeStatus && Array.isArray(state.bridgeStatus.channels) ? state.bridgeStatus.channels : [];
|
|
8040
|
+
}
|
|
8041
|
+
|
|
8042
|
+
function isChannelRunning(channelType) {
|
|
8043
|
+
return Boolean(state.bridgeStatus && state.bridgeStatus.running && runningChannels().includes(channelType));
|
|
8044
|
+
}
|
|
8045
|
+
|
|
8046
|
+
function bridgeNeedsRestart() {
|
|
8047
|
+
if (!state.config || !state.bridgeStatus || !state.bridgeStatus.running) return false;
|
|
8048
|
+
const configured = (state.config.enabledChannels || []).slice().sort().join(',');
|
|
8049
|
+
const running = runningChannels().slice().sort().join(',');
|
|
8050
|
+
return configured !== running;
|
|
8051
|
+
}
|
|
8052
|
+
|
|
8053
|
+
function channelLabel(channelType) {
|
|
8054
|
+
return channelType === 'weixin' ? '\u5FAE\u4FE1' : '\u98DE\u4E66';
|
|
8055
|
+
}
|
|
8056
|
+
|
|
8057
|
+
function channelRuntimeText(channelType) {
|
|
8058
|
+
const label = channelLabel(channelType);
|
|
8059
|
+
if (!isChannelEnabled(channelType)) {
|
|
8060
|
+
return label + '\u5728\u914D\u7F6E\u4E2D\u672A\u542F\u7528\u3002';
|
|
8061
|
+
}
|
|
8062
|
+
if (!state.bridgeStatus || !state.bridgeStatus.running) {
|
|
8063
|
+
return label + '\u5DF2\u542F\u7528\uFF0C\u4F46 Bridge \u8FD8\u6CA1\u542F\u52A8\u3002\u542F\u52A8 Bridge \u540E\u624D\u4F1A\u771F\u6B63\u63A5\u901A\u3002';
|
|
8064
|
+
}
|
|
8065
|
+
if (!isChannelRunning(channelType)) {
|
|
8066
|
+
return label + '\u5DF2\u5199\u5165\u914D\u7F6E\uFF0C\u4F46\u5F53\u524D\u8FD0\u884C\u4E2D\u7684 Bridge \u8FD8\u6CA1\u52A0\u8F7D\u8FD9\u4E2A\u901A\u9053\u3002\u70B9\u51FB\u201C\u91CD\u542F Bridge\u201D\u540E\u751F\u6548\u3002';
|
|
8067
|
+
}
|
|
8068
|
+
return label + '\u5DF2\u63A5\u901A\u5230\u5F53\u524D\u8FD0\u884C\u4E2D\u7684 Bridge\u3002';
|
|
8069
|
+
}
|
|
8070
|
+
|
|
8071
|
+
function emptyBindingText(channelType) {
|
|
8072
|
+
const label = channelLabel(channelType);
|
|
8073
|
+
if (!isChannelEnabled(channelType)) {
|
|
8074
|
+
return label + '\u672A\u542F\u7528\u3002\u5148\u5728\u201C\u914D\u7F6E\u201D\u91CC\u52FE\u9009\u540E\u4FDD\u5B58\u3002';
|
|
8075
|
+
}
|
|
8076
|
+
if (!state.bridgeStatus || !state.bridgeStatus.running) {
|
|
8077
|
+
return label + '\u5DF2\u542F\u7528\uFF0C\u4F46 Bridge \u8FD8\u6CA1\u542F\u52A8\u3002\u542F\u52A8\u540E\u624D\u4F1A\u521B\u5EFA\u7ED1\u5B9A\u3002';
|
|
8078
|
+
}
|
|
8079
|
+
if (!isChannelRunning(channelType)) {
|
|
8080
|
+
return label + '\u5DF2\u542F\u7528\uFF0C\u4F46\u5F53\u524D\u8FD0\u884C\u4E2D\u7684 Bridge \u8FD8\u6CA1\u52A0\u8F7D\u8FD9\u4E2A\u901A\u9053\u3002\u70B9\u51FB\u201C\u91CD\u542F Bridge\u201D\u540E\u751F\u6548\u3002';
|
|
8081
|
+
}
|
|
8082
|
+
return label + '\u5F53\u524D\u8FD8\u6CA1\u6709\u804A\u5929\u63A5\u5165\u3002\u5148\u4ECE' + label + '\u53D1\u4E00\u6761\u6D88\u606F\uFF0Cbridge \u624D\u4F1A\u521B\u5EFA\u7ED1\u5B9A\u3002';
|
|
8083
|
+
}
|
|
8084
|
+
|
|
8085
|
+
function quickSwitchState(channelType) {
|
|
8086
|
+
const label = channelLabel(channelType);
|
|
8087
|
+
if (!isChannelEnabled(channelType)) {
|
|
8088
|
+
return { disabled: true, title: label + '\u672A\u542F\u7528\u3002' };
|
|
8089
|
+
}
|
|
8090
|
+
if (!state.bridgeStatus || !state.bridgeStatus.running) {
|
|
8091
|
+
return { disabled: true, title: 'Bridge \u8FD8\u6CA1\u542F\u52A8\u3002\u542F\u52A8\u540E\u518D\u5207\u6362' + label + '\u4F1A\u8BDD\u3002' };
|
|
8092
|
+
}
|
|
8093
|
+
if (!isChannelRunning(channelType)) {
|
|
8094
|
+
return { disabled: true, title: label + '\u5DF2\u5199\u5165\u914D\u7F6E\uFF0C\u4F46\u5F53\u524D\u8FD0\u884C\u4E2D\u7684 Bridge \u8FD8\u6CA1\u52A0\u8F7D\u3002\u8BF7\u5148\u91CD\u542F Bridge\u3002' };
|
|
8095
|
+
}
|
|
8096
|
+
|
|
8097
|
+
const bindings = state.bindings.filter((item) => item.channelType === channelType);
|
|
8098
|
+
if (bindings.length === 0) {
|
|
8099
|
+
return { disabled: true, title: '\u5F53\u524D\u8FD8\u6CA1\u6709' + label + '\u804A\u5929\u7ED1\u5B9A\u3002\u5148\u8BA9' + label + '\u53D1\u6765\u4E00\u6761\u6D88\u606F\u3002' };
|
|
8100
|
+
}
|
|
8101
|
+
if (bindings.length > 1) {
|
|
8102
|
+
return { disabled: true, title: label + '\u6709\u591A\u4E2A\u7ED1\u5B9A\uFF0C\u8BF7\u5230\u901A\u9053\u9875\u5207\u6362\u3002' };
|
|
8103
|
+
}
|
|
8104
|
+
|
|
8105
|
+
return {
|
|
8106
|
+
disabled: false,
|
|
8107
|
+
title: '\u5207\u6362' + label + '\u5230\u5F53\u524D\u4F1A\u8BDD',
|
|
8108
|
+
bindingId: bindings[0].id,
|
|
8109
|
+
};
|
|
8110
|
+
}
|
|
8111
|
+
|
|
8112
|
+
function currentThreadMarks(threadId) {
|
|
8113
|
+
const marks = [];
|
|
8114
|
+
const currentTargetKey = 'desktop:' + threadId;
|
|
8115
|
+
const counts = new Map();
|
|
8116
|
+
|
|
8117
|
+
for (const binding of state.bindings || []) {
|
|
8118
|
+
const matchesThread = binding.currentThreadId === threadId || binding.currentTargetKey === currentTargetKey;
|
|
8119
|
+
if (!matchesThread) continue;
|
|
8120
|
+
counts.set(binding.channelType, (counts.get(binding.channelType) || 0) + 1);
|
|
8121
|
+
}
|
|
8122
|
+
|
|
8123
|
+
for (const [channelType, count] of counts.entries()) {
|
|
8124
|
+
const label = channelType === 'weixin' ? '\u5FAE\u4FE1\u5F53\u524D' : '\u98DE\u4E66\u5F53\u524D';
|
|
8125
|
+
marks.push(count > 1 ? label + ' x' + count : label);
|
|
8126
|
+
}
|
|
8127
|
+
|
|
8128
|
+
return marks;
|
|
8129
|
+
}
|
|
8130
|
+
|
|
8131
|
+
function renderDesktopSessionCard(session) {
|
|
8132
|
+
const feishuSwitch = quickSwitchState('feishu');
|
|
8133
|
+
const weixinSwitch = quickSwitchState('weixin');
|
|
8134
|
+
const targetKey = 'desktop:' + session.threadId;
|
|
8135
|
+
const originator = session.originator || 'Codex Desktop';
|
|
8136
|
+
const marks = currentThreadMarks(session.threadId);
|
|
8137
|
+
const markHtml = marks.map((mark) => '<span class="session-mark">' + escapeHtml(mark) + '</span>').join('');
|
|
8138
|
+
|
|
8139
|
+
return ''
|
|
8140
|
+
+ '<article class="session-card' + (marks.length ? ' current-thread' : '') + '">'
|
|
8141
|
+
+ '<div class="session-head">'
|
|
8142
|
+
+ '<div class="session-main">'
|
|
8143
|
+
+ '<div class="session-title-row"><div class="session-title">' + escapeHtml(session.title || 'Untitled Session') + '</div>' + markHtml + '</div>'
|
|
8144
|
+
+ '<div class="session-thread">Thread: <code>' + escapeHtml(session.threadId) + '</code><button type="button" class="session-inline-action" data-action="copy-thread" data-thread-id="' + escapeHtml(session.threadId) + '">\u590D\u5236</button></div>'
|
|
8145
|
+
+ '</div>'
|
|
8146
|
+
+ '<div class="session-cell">'
|
|
8147
|
+
+ '<div class="session-label">\u6765\u6E90</div>'
|
|
8148
|
+
+ '<div class="session-value">' + escapeHtml(originator) + '</div>'
|
|
8149
|
+
+ '</div>'
|
|
8150
|
+
+ '<div class="session-cell">'
|
|
8151
|
+
+ '<div class="session-label">\u76EE\u5F55</div>'
|
|
8152
|
+
+ '<div class="session-path">' + escapeHtml(session.cwd || '(no cwd)') + '</div>'
|
|
8153
|
+
+ '</div>'
|
|
8154
|
+
+ '<div class="session-actions">'
|
|
8155
|
+
+ '<button type="button" data-action="bind-channel" data-channel="feishu" data-binding-id="' + escapeHtml(feishuSwitch.bindingId || '') + '" data-target-key="' + escapeHtml(targetKey) + '" title="' + escapeHtml(feishuSwitch.title) + '"' + (feishuSwitch.disabled ? ' disabled' : '') + '>\u98DE\u4E66\u5207\u5230\u6B64\u4F1A\u8BDD</button>'
|
|
8156
|
+
+ '<button type="button" data-action="bind-channel" data-channel="weixin" data-binding-id="' + escapeHtml(weixinSwitch.bindingId || '') + '" data-target-key="' + escapeHtml(targetKey) + '" title="' + escapeHtml(weixinSwitch.title) + '"' + (weixinSwitch.disabled ? ' disabled' : '') + '>\u5FAE\u4FE1\u5207\u5230\u6B64\u4F1A\u8BDD</button>'
|
|
8157
|
+
+ '<button type="button" data-action="copy-bind-command" data-thread-id="' + escapeHtml(session.threadId) + '">\u590D\u5236\u547D\u4EE4</button>'
|
|
8158
|
+
+ '</div>'
|
|
8159
|
+
+ '</div>'
|
|
8160
|
+
+ '</article>';
|
|
7248
8161
|
}
|
|
7249
8162
|
|
|
7250
8163
|
function renderDesktopSessions(result) {
|
|
7251
8164
|
state.desktopSessions = result.sessions || [];
|
|
8165
|
+
state.desktopRoot = result.root || '-';
|
|
8166
|
+
const groups = groupDesktopSessions(state.desktopSessions);
|
|
7252
8167
|
document.getElementById('desktopSessionCount').textContent = String(state.desktopSessions.length);
|
|
7253
8168
|
document.getElementById('desktopSessionMeta').textContent =
|
|
7254
|
-
'\u626B\u63CF\u76EE\u5F55\uFF1A' +
|
|
8169
|
+
'\u626B\u63CF\u76EE\u5F55\uFF1A' + state.desktopRoot + ' \xB7 ' + groups.length + ' \u4E2A\u5DE5\u7A0B \xB7 ' + state.desktopSessions.length + ' \u6761\u684C\u9762\u4F1A\u8BDD';
|
|
8170
|
+
document.getElementById('desktopRootStatus').textContent = state.desktopRoot;
|
|
7255
8171
|
|
|
7256
8172
|
const list = document.getElementById('desktopSessionsList');
|
|
7257
8173
|
if (state.desktopSessions.length === 0) {
|
|
7258
8174
|
list.innerHTML = '<div class="notice ghost">\u5F53\u524D\u6CA1\u6709\u53D1\u73B0\u684C\u9762\u7AEF\u4F1A\u8BDD\u3002\u5148\u5728 Codex Windows App \u4E2D\u6253\u5F00\u6216\u8FD0\u884C\u4E00\u4E2A\u4F1A\u8BDD\uFF0C\u518D\u56DE\u5230\u8FD9\u91CC\u5237\u65B0\u3002</div>';
|
|
8175
|
+
rerenderBindingPanels();
|
|
7259
8176
|
return;
|
|
7260
8177
|
}
|
|
7261
8178
|
|
|
7262
|
-
list.innerHTML =
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
8179
|
+
list.innerHTML = groups.map((group) => ''
|
|
8180
|
+
+ '<section class="project-group">'
|
|
8181
|
+
+ '<div class="project-group-head">'
|
|
8182
|
+
+ '<div>'
|
|
8183
|
+
+ '<div class="project-group-title">' + escapeHtml(group.name) + '</div>'
|
|
8184
|
+
+ '<div class="project-group-path">' + escapeHtml(group.cwd || '(no cwd)') + '</div>'
|
|
8185
|
+
+ '</div>'
|
|
8186
|
+
+ '<div class="project-group-count">' + group.sessions.length + ' \u4E2A\u7EBF\u7A0B</div>'
|
|
8187
|
+
+ '</div>'
|
|
8188
|
+
+ '<div class="project-session-list">'
|
|
8189
|
+
+ group.sessions.map((session) => renderDesktopSessionCard(session)).join('')
|
|
8190
|
+
+ '</div>'
|
|
8191
|
+
+ '</section>'
|
|
8192
|
+
).join('');
|
|
8193
|
+
|
|
8194
|
+
rerenderBindingPanels();
|
|
8195
|
+
}
|
|
8196
|
+
|
|
8197
|
+
function rerenderDesktopSessions() {
|
|
8198
|
+
if (!state.desktopSessions.length && !state.desktopRoot) return;
|
|
8199
|
+
renderDesktopSessions({
|
|
8200
|
+
root: state.desktopRoot,
|
|
8201
|
+
sessions: state.desktopSessions,
|
|
8202
|
+
});
|
|
8203
|
+
}
|
|
7268
8204
|
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
+ '</div>'
|
|
7283
|
-
+ '</article>';
|
|
7284
|
-
}).join('');
|
|
8205
|
+
function rerenderBindingPanels() {
|
|
8206
|
+
renderChannelBindings(
|
|
8207
|
+
'feishu',
|
|
8208
|
+
'feishuBindings',
|
|
8209
|
+
'feishuBindingMeta',
|
|
8210
|
+
emptyBindingText('feishu')
|
|
8211
|
+
);
|
|
8212
|
+
renderChannelBindings(
|
|
8213
|
+
'weixin',
|
|
8214
|
+
'weixinBindings',
|
|
8215
|
+
'weixinBindingMeta',
|
|
8216
|
+
emptyBindingText('weixin')
|
|
8217
|
+
);
|
|
7285
8218
|
}
|
|
7286
8219
|
|
|
7287
8220
|
function renderChannelBindings(channelType, listId, metaId, emptyText) {
|
|
@@ -7289,7 +8222,7 @@ function renderHtml() {
|
|
|
7289
8222
|
const list = document.getElementById(listId);
|
|
7290
8223
|
const meta = document.getElementById(metaId);
|
|
7291
8224
|
meta.textContent = bindings.length > 0
|
|
7292
|
-
? '\u5F53\u524D\u5DF2\u53D1\u73B0 ' + bindings.length + ' \u4E2A\u804A\u5929\u7ED1\u5B9A\
|
|
8225
|
+
? '\u5F53\u524D\u5DF2\u53D1\u73B0 ' + bindings.length + ' \u4E2A\u804A\u5929\u7ED1\u5B9A\u3002\u8FD9\u91CC\u53EA\u663E\u793A\u548C\u4F1A\u8BDD\u9875\u4E00\u81F4\u7684\u547D\u540D\u684C\u9762\u7EBF\u7A0B\u3002'
|
|
7293
8226
|
: emptyText;
|
|
7294
8227
|
|
|
7295
8228
|
if (bindings.length === 0) {
|
|
@@ -7298,11 +8231,6 @@ function renderHtml() {
|
|
|
7298
8231
|
}
|
|
7299
8232
|
|
|
7300
8233
|
list.innerHTML = bindings.map((binding) => {
|
|
7301
|
-
const options = state.bindingOptions.map((option) => {
|
|
7302
|
-
const selected = option.key === binding.currentTargetKey ? ' selected' : '';
|
|
7303
|
-
return '<option value="' + escapeHtml(option.key) + '"' + selected + '>' + escapeHtml(optionLabel(option)) + '</option>';
|
|
7304
|
-
}).join('');
|
|
7305
|
-
|
|
7306
8234
|
return ''
|
|
7307
8235
|
+ '<article class="binding-item" data-binding-id="' + escapeHtml(binding.id) + '">'
|
|
7308
8236
|
+ '<div class="binding-head">'
|
|
@@ -7310,16 +8238,40 @@ function renderHtml() {
|
|
|
7310
8238
|
+ '<div class="small">' + escapeHtml(binding.mode) + '</div>'
|
|
7311
8239
|
+ '</div>'
|
|
7312
8240
|
+ '<div class="binding-detail">\u5F53\u524D\u4F1A\u8BDD\uFF1A<code>' + escapeHtml(binding.currentSessionId.slice(0, 8)) + '...</code> \xB7 ' + escapeHtml(binding.currentSessionName) + '</div>'
|
|
8241
|
+
+ '<div class="binding-detail">\u5F53\u524D\u76EE\u6807\uFF1A' + escapeHtml(binding.currentTargetLabel || '\u672A\u7ED1\u5B9A') + '</div>'
|
|
7313
8242
|
+ '<div class="binding-detail">\u5F53\u524D thread\uFF1A<code>' + escapeHtml(binding.currentThreadId || 'not-shared') + '</code></div>'
|
|
7314
8243
|
+ '<div class="binding-detail">\u76EE\u5F55\uFF1A' + escapeHtml(binding.workingDirectory || '~') + '</div>'
|
|
7315
|
-
+
|
|
7316
|
-
+ '<select data-role="target">' + options + '</select>'
|
|
7317
|
-
+ '<button type="button" data-action="save-binding">\u5207\u6362\u7ED1\u5B9A</button>'
|
|
7318
|
-
+ '</div>'
|
|
8244
|
+
+ renderBindingTable(binding)
|
|
7319
8245
|
+ '</article>';
|
|
7320
8246
|
}).join('');
|
|
7321
8247
|
}
|
|
7322
8248
|
|
|
8249
|
+
function renderWeixinAccounts() {
|
|
8250
|
+
const meta = document.getElementById('weixinAccountMeta');
|
|
8251
|
+
const list = document.getElementById('weixinAccounts');
|
|
8252
|
+
const accounts = state.weixinAccounts || [];
|
|
8253
|
+
|
|
8254
|
+
if (accounts.length === 0) {
|
|
8255
|
+
meta.textContent = '\u5F53\u524D\u8FD8\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u5FAE\u4FE1\u8D26\u53F7\u3002\u5148\u70B9\u51FB\u201C\u5F00\u59CB\u5FAE\u4FE1\u626B\u7801\u201D\uFF0C\u7136\u540E\u5728\u624B\u673A\u4E0A\u786E\u8BA4\u3002';
|
|
8256
|
+
list.innerHTML = '<div class="binding-empty">\u626B\u7801\u6210\u529F\u540E\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u5F53\u524D\u5DF2\u4FDD\u5B58\u7684\u5FAE\u4FE1\u8D26\u53F7\u3002</div>';
|
|
8257
|
+
return;
|
|
8258
|
+
}
|
|
8259
|
+
|
|
8260
|
+
meta.textContent = '\u5F53\u524D\u5DF2\u4FDD\u5B58 ' + accounts.length + ' \u4E2A\u5FAE\u4FE1\u8D26\u53F7\u3002\u5FAE\u4FE1\u6865\u63A5\u662F\u5355\u8D26\u53F7\u6A21\u5F0F\uFF0C\u6700\u65B0\u542F\u7528\u7684\u8D26\u53F7\u4F1A\u751F\u6548\u3002';
|
|
8261
|
+
list.innerHTML = accounts.map((account) => ''
|
|
8262
|
+
+ '<article class="binding-item">'
|
|
8263
|
+
+ '<div class="binding-head">'
|
|
8264
|
+
+ '<div class="binding-title">' + escapeHtml(account.name || account.accountId) + '</div>'
|
|
8265
|
+
+ '<div class="small">' + (account.enabled ? '\u5DF2\u542F\u7528' : '\u5DF2\u505C\u7528') + '</div>'
|
|
8266
|
+
+ '</div>'
|
|
8267
|
+
+ '<div class="binding-detail">\u8D26\u53F7 ID\uFF1A<code>' + escapeHtml(account.accountId) + '</code></div>'
|
|
8268
|
+
+ '<div class="binding-detail">\u7528\u6237 ID\uFF1A<code>' + escapeHtml(account.userId || '-') + '</code></div>'
|
|
8269
|
+
+ '<div class="binding-detail">Base URL\uFF1A' + escapeHtml(account.baseUrl || '-') + '</div>'
|
|
8270
|
+
+ '<div class="binding-detail">\u6700\u8FD1\u767B\u5F55\uFF1A' + escapeHtml(formatTime(account.lastLoginAt || account.updatedAt)) + '</div>'
|
|
8271
|
+
+ '</article>'
|
|
8272
|
+
).join('');
|
|
8273
|
+
}
|
|
8274
|
+
|
|
7323
8275
|
function renderBindings(result) {
|
|
7324
8276
|
state.bindings = result.bindings || [];
|
|
7325
8277
|
state.bindingOptions = result.options || [];
|
|
@@ -7328,14 +8280,15 @@ function renderHtml() {
|
|
|
7328
8280
|
'feishu',
|
|
7329
8281
|
'feishuBindings',
|
|
7330
8282
|
'feishuBindingMeta',
|
|
7331
|
-
'
|
|
8283
|
+
emptyBindingText('feishu')
|
|
7332
8284
|
);
|
|
7333
8285
|
renderChannelBindings(
|
|
7334
8286
|
'weixin',
|
|
7335
8287
|
'weixinBindings',
|
|
7336
8288
|
'weixinBindingMeta',
|
|
7337
|
-
'
|
|
8289
|
+
emptyBindingText('weixin')
|
|
7338
8290
|
);
|
|
8291
|
+
rerenderDesktopSessions();
|
|
7339
8292
|
}
|
|
7340
8293
|
|
|
7341
8294
|
function fillForm(config) {
|
|
@@ -7355,6 +8308,7 @@ function renderHtml() {
|
|
|
7355
8308
|
document.getElementById('feishuAllowedUsers').value = config.feishuAllowedUsers || '';
|
|
7356
8309
|
document.getElementById('feishuStreamingEnabled').checked = config.feishuStreamingEnabled !== false;
|
|
7357
8310
|
document.getElementById('weixinMediaEnabled').checked = config.weixinMediaEnabled === true;
|
|
8311
|
+
rerenderDesktopSessions();
|
|
7358
8312
|
}
|
|
7359
8313
|
|
|
7360
8314
|
async function api(path, options) {
|
|
@@ -7372,12 +8326,23 @@ function renderHtml() {
|
|
|
7372
8326
|
async function loadStatus() {
|
|
7373
8327
|
const status = await api('/api/status');
|
|
7374
8328
|
const config = await api('/api/config');
|
|
8329
|
+
state.bridgeStatus = status.bridge || null;
|
|
8330
|
+
state.weixinAccounts = status.weixin && Array.isArray(status.weixin.linkedAccounts) ? status.weixin.linkedAccounts : [];
|
|
7375
8331
|
fillForm(config);
|
|
7376
|
-
|
|
8332
|
+
const runningChannelText = runningChannels().length ? ' \xB7 ' + runningChannels().join(', ') : '';
|
|
8333
|
+
document.getElementById('bridgeStatus').textContent = status.bridge.running ? 'Running' + runningChannelText : 'Stopped';
|
|
7377
8334
|
document.getElementById('integrationStatus').textContent = status.codexIntegrationInstalled ? '\u5DF2\u5B89\u88C5' : '\u672A\u5B89\u88C5';
|
|
7378
8335
|
document.getElementById('runtimeStatus').textContent = config.runtime || 'codex';
|
|
7379
8336
|
document.getElementById('homeStatus').textContent = status.home;
|
|
8337
|
+
document.getElementById('overviewHomeStatus').textContent = status.home;
|
|
7380
8338
|
document.getElementById('packageRoot').textContent = status.packageRoot;
|
|
8339
|
+
document.getElementById('feishuRuntimeMeta').textContent = channelRuntimeText('feishu');
|
|
8340
|
+
document.getElementById('weixinRuntimeMeta').textContent = channelRuntimeText('weixin');
|
|
8341
|
+
renderWeixinAccounts();
|
|
8342
|
+
renderBindings({
|
|
8343
|
+
bindings: state.bindings,
|
|
8344
|
+
options: state.bindingOptions,
|
|
8345
|
+
});
|
|
7381
8346
|
}
|
|
7382
8347
|
|
|
7383
8348
|
async function loadLogs() {
|
|
@@ -7386,7 +8351,7 @@ function renderHtml() {
|
|
|
7386
8351
|
}
|
|
7387
8352
|
|
|
7388
8353
|
async function loadDesktopSessions() {
|
|
7389
|
-
const result = await api('/api/desktop-sessions?limit=
|
|
8354
|
+
const result = await api('/api/desktop-sessions?limit=36');
|
|
7390
8355
|
renderDesktopSessions(result);
|
|
7391
8356
|
}
|
|
7392
8357
|
|
|
@@ -7401,14 +8366,53 @@ function renderHtml() {
|
|
|
7401
8366
|
body: JSON.stringify(formPayload()),
|
|
7402
8367
|
});
|
|
7403
8368
|
fillForm(saved.config);
|
|
7404
|
-
showMessage(
|
|
8369
|
+
showMessage(
|
|
8370
|
+
'configMessage',
|
|
8371
|
+
'success',
|
|
8372
|
+
bridgeNeedsRestart()
|
|
8373
|
+
? '\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002\u5F53\u524D Bridge \u8FD8\u5728\u4F7F\u7528\u65E7\u901A\u9053\u914D\u7F6E\uFF0C\u70B9\u51FB\u201C\u91CD\u542F Bridge\u201D\u540E\u751F\u6548\u3002'
|
|
8374
|
+
: '\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002'
|
|
8375
|
+
);
|
|
7405
8376
|
return saved;
|
|
7406
8377
|
}
|
|
7407
8378
|
|
|
8379
|
+
document.querySelectorAll('.nav-link').forEach((element) => {
|
|
8380
|
+
element.addEventListener('click', () => {
|
|
8381
|
+
setActivePage(element.dataset.page || 'overview', true);
|
|
8382
|
+
});
|
|
8383
|
+
});
|
|
8384
|
+
|
|
8385
|
+
document.querySelectorAll('.channel-tab').forEach((element) => {
|
|
8386
|
+
element.addEventListener('click', () => {
|
|
8387
|
+
setActivePage('channels', false);
|
|
8388
|
+
setActiveChannel(element.dataset.channel || 'feishu', true);
|
|
8389
|
+
});
|
|
8390
|
+
});
|
|
8391
|
+
|
|
8392
|
+
window.addEventListener('hashchange', syncPageFromHash);
|
|
8393
|
+
|
|
7408
8394
|
document.getElementById('saveConfigBtn').addEventListener('click', async () => {
|
|
7409
8395
|
try {
|
|
7410
8396
|
await saveConfig();
|
|
7411
8397
|
await loadStatus();
|
|
8398
|
+
await loadBindings();
|
|
8399
|
+
} catch (error) {
|
|
8400
|
+
showMessage('configMessage', 'error', error.message);
|
|
8401
|
+
}
|
|
8402
|
+
});
|
|
8403
|
+
|
|
8404
|
+
document.getElementById('saveFeishuChannelBtn').addEventListener('click', async () => {
|
|
8405
|
+
try {
|
|
8406
|
+
await saveConfig();
|
|
8407
|
+
await loadStatus();
|
|
8408
|
+
await loadBindings();
|
|
8409
|
+
showMessage(
|
|
8410
|
+
'feishuMessage',
|
|
8411
|
+
'success',
|
|
8412
|
+
bridgeNeedsRestart()
|
|
8413
|
+
? '\u98DE\u4E66\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002\u5F53\u524D Bridge \u8FD8\u5728\u4F7F\u7528\u65E7\u901A\u9053\u914D\u7F6E\uFF0C\u70B9\u51FB\u201C\u91CD\u542F Bridge\u201D\u540E\u751F\u6548\u3002'
|
|
8414
|
+
: '\u98DE\u4E66\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002'
|
|
8415
|
+
);
|
|
7412
8416
|
} catch (error) {
|
|
7413
8417
|
showMessage('feishuMessage', 'error', error.message);
|
|
7414
8418
|
}
|
|
@@ -7417,6 +8421,8 @@ function renderHtml() {
|
|
|
7417
8421
|
document.getElementById('testFeishuBtn').addEventListener('click', async () => {
|
|
7418
8422
|
try {
|
|
7419
8423
|
await saveConfig();
|
|
8424
|
+
await loadStatus();
|
|
8425
|
+
await loadBindings();
|
|
7420
8426
|
const result = await api('/api/test/feishu', { method: 'POST' });
|
|
7421
8427
|
showMessage('feishuMessage', result.ok ? 'success' : 'error', result.message);
|
|
7422
8428
|
} catch (error) {
|
|
@@ -7424,12 +8430,34 @@ function renderHtml() {
|
|
|
7424
8430
|
}
|
|
7425
8431
|
});
|
|
7426
8432
|
|
|
8433
|
+
document.getElementById('saveWeixinChannelBtn').addEventListener('click', async () => {
|
|
8434
|
+
try {
|
|
8435
|
+
await saveConfig();
|
|
8436
|
+
await loadStatus();
|
|
8437
|
+
await loadBindings();
|
|
8438
|
+
showMessage(
|
|
8439
|
+
'weixinMessage',
|
|
8440
|
+
'success',
|
|
8441
|
+
bridgeNeedsRestart()
|
|
8442
|
+
? '\u5FAE\u4FE1\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002\u5F53\u524D Bridge \u8FD8\u5728\u4F7F\u7528\u65E7\u901A\u9053\u914D\u7F6E\uFF0C\u70B9\u51FB\u201C\u91CD\u542F Bridge\u201D\u540E\u751F\u6548\u3002'
|
|
8443
|
+
: '\u5FAE\u4FE1\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002'
|
|
8444
|
+
);
|
|
8445
|
+
} catch (error) {
|
|
8446
|
+
showMessage('weixinMessage', 'error', error.message);
|
|
8447
|
+
}
|
|
8448
|
+
});
|
|
8449
|
+
|
|
7427
8450
|
document.getElementById('weixinLoginBtn').addEventListener('click', async () => {
|
|
7428
8451
|
try {
|
|
7429
8452
|
await saveConfig();
|
|
7430
8453
|
showMessage('weixinMessage', 'success', '\u5FAE\u4FE1\u626B\u7801\u6D41\u7A0B\u5DF2\u542F\u52A8\uFF0C\u6D4F\u89C8\u5668\u4F1A\u6253\u5F00\u4E8C\u7EF4\u7801\u9875\u9762\u3002');
|
|
7431
8454
|
const result = await api('/api/test/weixin', { method: 'POST' });
|
|
7432
|
-
|
|
8455
|
+
await loadStatus();
|
|
8456
|
+
await loadBindings();
|
|
8457
|
+
const followup = isChannelRunning('weixin')
|
|
8458
|
+
? '\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u4FDD\u5B58\u3002\u5F53\u524D Bridge \u5DF2\u52A0\u8F7D\u5FAE\u4FE1\u901A\u9053\uFF0C\u51E0\u79D2\u540E\u4F1A\u81EA\u52A8\u63A5\u5165\u65B0\u8D26\u53F7\u3002'
|
|
8459
|
+
: '\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u4FDD\u5B58\u3002\u5F53\u524D\u8FD0\u884C\u4E2D\u7684 Bridge \u8FD8\u6CA1\u52A0\u8F7D\u5FAE\u4FE1\u901A\u9053\uFF0C\u70B9\u51FB\u201C\u91CD\u542F Bridge\u201D\u540E\u751F\u6548\u3002';
|
|
8460
|
+
showMessage('weixinMessage', result.ok ? 'success' : 'error', followup);
|
|
7433
8461
|
} catch (error) {
|
|
7434
8462
|
showMessage('weixinMessage', 'error', error.message);
|
|
7435
8463
|
}
|
|
@@ -7460,6 +8488,20 @@ function renderHtml() {
|
|
|
7460
8488
|
}
|
|
7461
8489
|
});
|
|
7462
8490
|
|
|
8491
|
+
document.getElementById('restartBridgeBtn').addEventListener('click', async () => {
|
|
8492
|
+
try {
|
|
8493
|
+
await saveConfig();
|
|
8494
|
+
const result = await api('/api/bridge/restart', { method: 'POST' });
|
|
8495
|
+
showMessage('opsMessage', 'success', 'Bridge \u5DF2\u91CD\u542F\u3002PID: ' + (result.status.pid || '-'));
|
|
8496
|
+
await loadStatus();
|
|
8497
|
+
await loadBindings();
|
|
8498
|
+
await loadLogs();
|
|
8499
|
+
} catch (error) {
|
|
8500
|
+
showMessage('opsMessage', 'error', error.message);
|
|
8501
|
+
await loadLogs();
|
|
8502
|
+
}
|
|
8503
|
+
});
|
|
8504
|
+
|
|
7463
8505
|
document.getElementById('installIntegrationBtn').addEventListener('click', async () => {
|
|
7464
8506
|
try {
|
|
7465
8507
|
const result = await api('/api/install-codex-integration', { method: 'POST' });
|
|
@@ -7492,12 +8534,20 @@ function renderHtml() {
|
|
|
7492
8534
|
}
|
|
7493
8535
|
});
|
|
7494
8536
|
|
|
8537
|
+
document.getElementById('refreshLogsBtn').addEventListener('click', async () => {
|
|
8538
|
+
try {
|
|
8539
|
+
await loadLogs();
|
|
8540
|
+
} catch (error) {
|
|
8541
|
+
showMessage('opsMessage', 'error', error.message);
|
|
8542
|
+
}
|
|
8543
|
+
});
|
|
8544
|
+
|
|
7495
8545
|
document.getElementById('refreshDesktopBtn').addEventListener('click', async () => {
|
|
7496
8546
|
try {
|
|
7497
8547
|
await loadDesktopSessions();
|
|
7498
8548
|
showMessage('desktopMessage', 'success', '\u684C\u9762\u4F1A\u8BDD\u5217\u8868\u5DF2\u5237\u65B0\u3002');
|
|
7499
8549
|
} catch (error) {
|
|
7500
|
-
|
|
8550
|
+
showGlobalMessage('error', error.message);
|
|
7501
8551
|
}
|
|
7502
8552
|
});
|
|
7503
8553
|
|
|
@@ -7507,6 +8557,28 @@ function renderHtml() {
|
|
|
7507
8557
|
if (!target) return;
|
|
7508
8558
|
|
|
7509
8559
|
try {
|
|
8560
|
+
if (target.dataset.action === 'bind-channel') {
|
|
8561
|
+
const bindingId = target.dataset.bindingId || '';
|
|
8562
|
+
const targetKey = target.dataset.targetKey || '';
|
|
8563
|
+
const channelType = target.dataset.channel || '';
|
|
8564
|
+
if (!bindingId || !targetKey) {
|
|
8565
|
+
throw new Error('\u5F53\u524D\u901A\u9053\u6CA1\u6709\u53EF\u5207\u6362\u7684\u7ED1\u5B9A\uFF0C\u8BF7\u5148\u5728\u901A\u9053\u9875\u5B8C\u6210\u63A5\u5165\u3002');
|
|
8566
|
+
}
|
|
8567
|
+
const result = await api('/api/bindings/update', {
|
|
8568
|
+
method: 'POST',
|
|
8569
|
+
body: JSON.stringify({
|
|
8570
|
+
bindingId,
|
|
8571
|
+
targetKey,
|
|
8572
|
+
}),
|
|
8573
|
+
});
|
|
8574
|
+
renderBindings(result);
|
|
8575
|
+
showMessage(
|
|
8576
|
+
'desktopMessage',
|
|
8577
|
+
'success',
|
|
8578
|
+
(channelType === 'weixin' ? '\u5FAE\u4FE1' : '\u98DE\u4E66') + '\u5DF2\u5207\u6362\u5230\u5F53\u524D\u4F1A\u8BDD\u3002'
|
|
8579
|
+
);
|
|
8580
|
+
return;
|
|
8581
|
+
}
|
|
7510
8582
|
if (target.dataset.action === 'copy-thread') {
|
|
7511
8583
|
await copyText(target.dataset.threadId || '', 'Thread ID \u5DF2\u590D\u5236\u3002');
|
|
7512
8584
|
return;
|
|
@@ -7525,20 +8597,15 @@ function renderHtml() {
|
|
|
7525
8597
|
|
|
7526
8598
|
async function handleBindingAction(event, channelType, messageId) {
|
|
7527
8599
|
const source = event.target instanceof Element ? event.target : null;
|
|
7528
|
-
const target = source ? source.closest('button[data-action="
|
|
8600
|
+
const target = source ? source.closest('button[data-action="switch-binding-target"]') : null;
|
|
7529
8601
|
if (!target) return;
|
|
7530
8602
|
|
|
7531
|
-
const item = target.closest('[data-binding-id]');
|
|
7532
|
-
if (!item) return;
|
|
7533
|
-
const select = item.querySelector('select[data-role="target"]');
|
|
7534
|
-
if (!select) return;
|
|
7535
|
-
|
|
7536
8603
|
try {
|
|
7537
8604
|
const result = await api('/api/bindings/update', {
|
|
7538
8605
|
method: 'POST',
|
|
7539
8606
|
body: JSON.stringify({
|
|
7540
|
-
bindingId:
|
|
7541
|
-
targetKey:
|
|
8607
|
+
bindingId: target.dataset.bindingId,
|
|
8608
|
+
targetKey: target.dataset.targetKey,
|
|
7542
8609
|
}),
|
|
7543
8610
|
});
|
|
7544
8611
|
renderBindings(result);
|
|
@@ -7556,6 +8623,8 @@ function renderHtml() {
|
|
|
7556
8623
|
handleBindingAction(event, 'weixin', 'weixinMessage');
|
|
7557
8624
|
});
|
|
7558
8625
|
|
|
8626
|
+
syncPageFromHash();
|
|
8627
|
+
|
|
7559
8628
|
Promise.all([loadStatus(), loadBindings(), loadDesktopSessions(), loadLogs()]).catch((error) => {
|
|
7560
8629
|
showMessage('opsMessage', 'error', error.message);
|
|
7561
8630
|
});
|
|
@@ -7581,6 +8650,9 @@ var server = http.createServer(async (request, response) => {
|
|
|
7581
8650
|
home: CTI_HOME,
|
|
7582
8651
|
packageRoot: getPackageRoot(),
|
|
7583
8652
|
codexIntegrationInstalled: isCodexIntegrationInstalled(),
|
|
8653
|
+
weixin: {
|
|
8654
|
+
linkedAccounts: getWeixinAccountsPayload()
|
|
8655
|
+
},
|
|
7584
8656
|
startedAt: serverStartTime
|
|
7585
8657
|
});
|
|
7586
8658
|
return;
|
|
@@ -7645,6 +8717,11 @@ var server = http.createServer(async (request, response) => {
|
|
|
7645
8717
|
json(response, 200, { ok: true, status });
|
|
7646
8718
|
return;
|
|
7647
8719
|
}
|
|
8720
|
+
if (request.method === "POST" && url.pathname === "/api/bridge/restart") {
|
|
8721
|
+
const status = await restartBridge();
|
|
8722
|
+
json(response, 200, { ok: true, status });
|
|
8723
|
+
return;
|
|
8724
|
+
}
|
|
7648
8725
|
if (request.method === "POST" && url.pathname === "/api/bindings/update") {
|
|
7649
8726
|
const payload = await readJsonBody(request);
|
|
7650
8727
|
const bindingId = asString(payload.bindingId);
|