chatccc 0.2.188 → 0.2.190
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/agent-prompts/claude_specific.md +45 -45
- package/agent-prompts/codex_specific.md +2 -2
- package/agent-prompts/cursor_specific.md +13 -13
- package/config.sample.json +14 -14
- package/im-skills/feishu-skill/receive-send-file.md +63 -63
- package/im-skills/feishu-skill/receive-send-image.md +24 -24
- package/im-skills/feishu-skill/skill.md +3 -3
- package/im-skills/wechat-file-skill/receive-send-file.md +38 -38
- package/im-skills/wechat-file-skill/send-file.mjs +83 -83
- package/im-skills/wechat-file-skill/skill.md +10 -10
- package/im-skills/wechat-image-skill/skill.md +10 -10
- package/im-skills/wechat-video-skill/receive-send-video.md +38 -38
- package/im-skills/wechat-video-skill/send-video.mjs +79 -79
- package/im-skills/wechat-video-skill/skill.md +10 -10
- package/package.json +1 -1
- package/scripts/postinstall-sharp-check.mjs +58 -58
- package/src/__tests__/agent-delegate-task-rpc.test.ts +165 -165
- package/src/__tests__/builtin-config.test.ts +33 -33
- package/src/__tests__/card-plain-text.test.ts +5 -5
- package/src/__tests__/cardkit.test.ts +60 -60
- package/src/__tests__/cards.test.ts +77 -77
- package/src/__tests__/chatgpt-subscription-rpc.test.ts +89 -89
- package/src/__tests__/chatgpt-subscription.test.ts +135 -135
- package/src/__tests__/chrome-devtools-guard.test.ts +165 -165
- package/src/__tests__/claude-adapter.test.ts +592 -592
- package/src/__tests__/codex-reset-actions.test.ts +146 -146
- package/src/__tests__/config-reload.test.ts +4 -4
- package/src/__tests__/config-sample.test.ts +17 -17
- package/src/__tests__/feishu-api.test.ts +60 -60
- package/src/__tests__/feishu-platform.test.ts +22 -22
- package/src/__tests__/format-message.test.ts +47 -47
- package/src/__tests__/orchestrator.test.ts +116 -112
- package/src/__tests__/privacy.test.ts +198 -198
- package/src/__tests__/raw-stream-log.test.ts +106 -106
- package/src/__tests__/session.test.ts +17 -17
- package/src/__tests__/shared-prefix.test.ts +36 -36
- package/src/__tests__/stream-state.test.ts +42 -42
- package/src/__tests__/web-ui.test.ts +209 -130
- package/src/adapters/claude-adapter.ts +566 -566
- package/src/adapters/claude-session-meta-store.ts +120 -120
- package/src/adapters/codex-adapter.ts +27 -28
- package/src/adapters/cursor-adapter.ts +46 -46
- package/src/adapters/raw-stream-log.ts +124 -124
- package/src/adapters/resource-monitor.ts +140 -140
- package/src/agent-delegate-task-rpc.ts +153 -153
- package/src/agent-delegate-task.ts +81 -81
- package/src/agent-stop-stuck.ts +129 -129
- package/src/builtin/cli.ts +189 -189
- package/src/builtin/index.ts +170 -168
- package/src/cards.ts +137 -137
- package/src/chatgpt-subscription-rpc.ts +27 -27
- package/src/chatgpt-subscription.ts +299 -299
- package/src/chrome-devtools-guard.ts +318 -318
- package/src/codex-reset-actions.ts +184 -184
- package/src/config.ts +86 -86
- package/src/feishu-platform.ts +20 -20
- package/src/format-message.ts +293 -293
- package/src/litellm-proxy.ts +374 -374
- package/src/orchestrator.ts +143 -143
- package/src/privacy.ts +118 -118
- package/src/session-chat-binding.ts +6 -6
- package/src/session-name.ts +8 -8
- package/src/session.ts +98 -98
- package/src/shared-prefix.ts +29 -29
- package/src/sim-platform.ts +20 -20
- package/src/turn-cards.ts +117 -117
- package/src/web-ui.ts +142 -24
package/src/web-ui.ts
CHANGED
|
@@ -28,7 +28,10 @@ const ILINK_AUTH_PATH = join(USER_DATA_DIR, "state", "ilink-auth.json");
|
|
|
28
28
|
|
|
29
29
|
interface AppConfig {
|
|
30
30
|
feishu?: { appId?: string; appSecret?: string };
|
|
31
|
-
platforms?: {
|
|
31
|
+
platforms?: {
|
|
32
|
+
feishu?: { enabled?: boolean; platformType?: string };
|
|
33
|
+
ilink?: { enabled?: boolean; reuseTokenOnStart?: boolean };
|
|
34
|
+
};
|
|
32
35
|
chromeDevtools?: { enabled?: boolean; port?: number; chromePath?: string };
|
|
33
36
|
port?: number;
|
|
34
37
|
gitTimeoutSeconds?: number;
|
|
@@ -105,6 +108,73 @@ function saveConfig(cfg: AppConfig): void {
|
|
|
105
108
|
writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2), "utf8");
|
|
106
109
|
}
|
|
107
110
|
|
|
111
|
+
type ConfigApplyMode = "saved" | "reload" | "restart-required";
|
|
112
|
+
|
|
113
|
+
interface ConfigApplyResult {
|
|
114
|
+
mode: ConfigApplyMode;
|
|
115
|
+
restartRequired: boolean;
|
|
116
|
+
restartReasons: string[];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function stringValue(value: unknown): string {
|
|
120
|
+
return typeof value === "string" ? value.trim() : "";
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function portValue(cfg: AppConfig): number {
|
|
124
|
+
return Number.isInteger(cfg.port) && cfg.port! >= 1 && cfg.port! <= 65535 ? cfg.port! : 18080;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function platformEnabled(cfg: AppConfig, platform: "feishu" | "ilink"): boolean {
|
|
128
|
+
return cfg.platforms?.[platform]?.enabled !== false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function feishuPlatformType(cfg: AppConfig): string {
|
|
132
|
+
return cfg.platforms?.feishu?.platformType === "lark" ? "lark" : "feishu";
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function ilinkReuseTokenOnStart(cfg: AppConfig): boolean {
|
|
136
|
+
return cfg.platforms?.ilink?.reuseTokenOnStart !== false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function getRestartRequiredReasons(before: AppConfig, after: AppConfig): string[] {
|
|
140
|
+
const reasons: string[] = [];
|
|
141
|
+
|
|
142
|
+
if (portValue(before) !== portValue(after)) reasons.push("port");
|
|
143
|
+
if (stringValue(before.feishu?.appId) !== stringValue(after.feishu?.appId)) reasons.push("feishu.appId");
|
|
144
|
+
if (stringValue(before.feishu?.appSecret) !== stringValue(after.feishu?.appSecret)) reasons.push("feishu.appSecret");
|
|
145
|
+
if (feishuPlatformType(before) !== feishuPlatformType(after)) reasons.push("platforms.feishu.platformType");
|
|
146
|
+
if (platformEnabled(before, "feishu") !== platformEnabled(after, "feishu")) reasons.push("platforms.feishu.enabled");
|
|
147
|
+
if (platformEnabled(before, "ilink") !== platformEnabled(after, "ilink")) reasons.push("platforms.ilink.enabled");
|
|
148
|
+
if (ilinkReuseTokenOnStart(before) !== ilinkReuseTokenOnStart(after)) {
|
|
149
|
+
reasons.push("platforms.ilink.reuseTokenOnStart");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return reasons;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function applySavedConfigIfPossible(before: AppConfig, after: AppConfig): Promise<ConfigApplyResult> {
|
|
156
|
+
const setupMode = Boolean(setupActivateHook && setupHttpServer);
|
|
157
|
+
if (setupMode) {
|
|
158
|
+
return { mode: "saved", restartRequired: false, restartReasons: [] };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const running = isServiceRunning();
|
|
162
|
+
if (!running) {
|
|
163
|
+
return { mode: "saved", restartRequired: false, restartReasons: [] };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const restartReasons = getRestartRequiredReasons(before, after);
|
|
167
|
+
if (restartReasons.length > 0) {
|
|
168
|
+
return { mode: "restart-required", restartRequired: true, restartReasons };
|
|
169
|
+
}
|
|
170
|
+
if (!reloadConfigHook) {
|
|
171
|
+
return { mode: "saved", restartRequired: false, restartReasons: [] };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
await reloadConfigHook();
|
|
175
|
+
return { mode: "reload", restartRequired: false, restartReasons: [] };
|
|
176
|
+
}
|
|
177
|
+
|
|
108
178
|
function maskSecret(value: string | undefined): string {
|
|
109
179
|
if (!value) return "(未设置)";
|
|
110
180
|
if (value.length <= 8) return "***";
|
|
@@ -298,9 +368,10 @@ async function handlePostConfig(req: IncomingMessage, res: ServerResponse): Prom
|
|
|
298
368
|
) as AppConfig;
|
|
299
369
|
try {
|
|
300
370
|
saveConfig(merged);
|
|
301
|
-
|
|
371
|
+
const applyResult = await applySavedConfigIfPossible(existing, merged);
|
|
372
|
+
jsonReply(res, 200, { ok: true, ...applyResult });
|
|
302
373
|
} catch (err) {
|
|
303
|
-
jsonReply(res, 500, { ok: false, error: (err as Error).message });
|
|
374
|
+
jsonReply(res, 500, { ok: false, saved: true, error: (err as Error).message });
|
|
304
375
|
}
|
|
305
376
|
}
|
|
306
377
|
|
|
@@ -451,10 +522,17 @@ async function handleStartService(_req: IncomingMessage, res: ServerResponse): P
|
|
|
451
522
|
}
|
|
452
523
|
|
|
453
524
|
if (path === "reload") {
|
|
454
|
-
// service
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
525
|
+
// service 已经在跑:只刷新进程内配置,让后续消息/新会话使用新值。
|
|
526
|
+
if (!reloadConfigHook) {
|
|
527
|
+
jsonReply(res, 200, { ok: true, pid: process.pid, mode: "saved" });
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
try {
|
|
531
|
+
await reloadConfigHook();
|
|
532
|
+
jsonReply(res, 200, { ok: true, pid: process.pid, mode: "reload" });
|
|
533
|
+
} catch (err) {
|
|
534
|
+
jsonReply(res, 500, { ok: false, error: (err as Error).message });
|
|
535
|
+
}
|
|
458
536
|
return;
|
|
459
537
|
}
|
|
460
538
|
|
|
@@ -855,6 +933,7 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
855
933
|
<div class="config-row"><span class="key">App ID</span><span class="val" id="cfg-APP_ID">-</span></div>
|
|
856
934
|
<div class="config-row"><span class="key">App Secret</span><span class="val" id="cfg-APP_SECRET">-</span></div>
|
|
857
935
|
<div class="config-row"><span class="key">平台类型</span><span class="val" id="cfg-FEISHU_PLATFORM_TYPE">-</span></div>
|
|
936
|
+
<div class="hint" style="margin-top:6px;line-height:1.6">生效范围:飞书开关、App ID、App Secret 或平台类型变更需要重启 ChatCCC。</div>
|
|
858
937
|
<button class="btn btn-outline" style="margin-top:8px" onclick="editSection('feishu')">编辑</button>
|
|
859
938
|
</div>
|
|
860
939
|
</details>
|
|
@@ -873,6 +952,7 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
873
952
|
<button class="btn btn-outline" style="font-size:12px" onclick="forgetIlink()">忘记扫码</button>
|
|
874
953
|
<span style="font-size:11px;color:#94a3b8;margin-left:8px">清除登录状态,重启后重新扫码</span>
|
|
875
954
|
</div>
|
|
955
|
+
<div class="hint" style="margin-top:6px;line-height:1.6">生效范围:微信 iLink 开关变更需要重启 ChatCCC。</div>
|
|
876
956
|
</div>
|
|
877
957
|
</details>
|
|
878
958
|
|
|
@@ -882,7 +962,7 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
882
962
|
<div class="config-row"><span class="key">状态</span><span class="val" id="cfg-CHROME_DEVTOOLS_ENABLED">-</span></div>
|
|
883
963
|
<div class="config-row" id="cfg-CHROME_DEVTOOLS_PORT_ROW"><span class="key">CDP 端口</span><span class="val" id="cfg-CHROME_DEVTOOLS_PORT">-</span></div>
|
|
884
964
|
<div class="config-row" id="cfg-CHROME_DEVTOOLS_PATH_ROW"><span class="key">Chrome 路径</span><span class="val" id="cfg-CHROME_DEVTOOLS_PATH">-</span></div>
|
|
885
|
-
<div class="hint" style="margin-top:6px;line-height:1.6"
|
|
965
|
+
<div class="hint" style="margin-top:6px;line-height:1.6">生效范围:保存后立即应用到 Chrome CDP 守护进程。依赖:本机 Google Chrome;ChatGPT 订阅到期查询需要在该 CDP Chrome 中登录 ChatGPT。</div>
|
|
886
966
|
<button class="btn btn-outline" style="margin-top:8px" onclick="editSection('chromeDevtools')">编辑</button>
|
|
887
967
|
</div>
|
|
888
968
|
</details>
|
|
@@ -897,6 +977,7 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
897
977
|
<div class="config-row"><span class="key">Base URL</span><span class="val" id="cfg-ANTHROPIC_BASE_URL">-</span></div>
|
|
898
978
|
<div class="config-row"><span class="key">Max Turns</span><span class="val" id="cfg-ANTHROPIC_MAX_TURN">-</span><span class="hint">(0=无限制)</span></div>
|
|
899
979
|
<label class="agent-default-row" style="margin-top:10px"><input type="checkbox" id="dash-default-claude" onchange="setDashboardDefaultAgent('claude', this.checked)"> 设为默认 Agent</label>
|
|
980
|
+
<div class="hint" style="margin-top:6px;line-height:1.6">生效范围:保存后下一条消息或下个新会话生效,当前生成不中断。</div>
|
|
900
981
|
<button class="btn btn-outline" style="margin-top:8px" onclick="editSection('claude')">编辑</button>
|
|
901
982
|
</div>
|
|
902
983
|
</details>
|
|
@@ -910,6 +991,7 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
910
991
|
<div class="config-row"><span class="key">头像电池电量</span><span class="val" id="cfg-CURSOR_AVATAR_BATTERY_MODE">-</span></div>
|
|
911
992
|
<div class="config-row" id="cfg-CURSOR_ON_DEMAND_MONTHLY_BUDGET_ROW"><span class="key">每月On demand use预算</span><span class="val" id="cfg-CURSOR_ON_DEMAND_MONTHLY_BUDGET">-</span></div>
|
|
912
993
|
<label class="agent-default-row" style="margin-top:10px"><input type="checkbox" id="dash-default-cursor" onchange="setDashboardDefaultAgent('cursor', this.checked)"> 设为默认 Agent</label>
|
|
994
|
+
<div class="hint" style="margin-top:6px;line-height:1.6">生效范围:保存后下一条消息或下个新会话生效,当前生成不中断。</div>
|
|
913
995
|
<button class="btn btn-outline" style="margin-top:8px" onclick="editSection('cursor')">编辑</button>
|
|
914
996
|
</div>
|
|
915
997
|
</details>
|
|
@@ -922,6 +1004,7 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
922
1004
|
<div class="config-row"><span class="key">备选模型</span><span class="val" id="cfg-CODEX_ALTERNATIVE_MODEL">-</span></div>
|
|
923
1005
|
<div class="config-row"><span class="key">Effort</span><span class="val" id="cfg-CODEX_EFFORT">-</span></div>
|
|
924
1006
|
<label class="agent-default-row" style="margin-top:10px"><input type="checkbox" id="dash-default-codex" onchange="setDashboardDefaultAgent('codex', this.checked)"> 设为默认 Agent</label>
|
|
1007
|
+
<div class="hint" style="margin-top:6px;line-height:1.6">生效范围:保存后下一条消息或下个新会话生效,当前生成不中断。</div>
|
|
925
1008
|
<button class="btn btn-outline" style="margin-top:8px" onclick="editSection('codex')">编辑</button>
|
|
926
1009
|
</div>
|
|
927
1010
|
</details>
|
|
@@ -938,6 +1021,7 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
938
1021
|
<!-- Edit Modal -->
|
|
939
1022
|
<div id="edit-modal" class="card hidden" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:90%;max-width:480px;z-index:200;max-height:80vh;overflow-y:auto">
|
|
940
1023
|
<h2 id="edit-modal-title">编辑配置</h2>
|
|
1024
|
+
<div id="edit-modal-effect" class="hint" style="margin-bottom:12px;line-height:1.6"></div>
|
|
941
1025
|
<div id="edit-modal-fields"></div>
|
|
942
1026
|
<div class="btn-group" style="justify-content:flex-end;margin-top:16px">
|
|
943
1027
|
<button class="btn btn-outline" onclick="closeEditModal()">取消</button>
|
|
@@ -977,6 +1061,26 @@ function cursorBatteryModeLabel(value) {
|
|
|
977
1061
|
return value === 'onDemandUse' ? 'On demand use 金额' : 'API 使用比例';
|
|
978
1062
|
}
|
|
979
1063
|
|
|
1064
|
+
function configEffectHint(section) {
|
|
1065
|
+
if (section === 'feishu') return '生效范围:App ID、App Secret、平台类型或飞书开关变更需要重启 ChatCCC;其它未变更项仅保存。';
|
|
1066
|
+
if (section === 'chromeDevtools') return '生效范围:保存后立即应用到 Chrome CDP 守护进程。';
|
|
1067
|
+
if (section === 'claude') return '生效范围:保存后下一条消息或下个新会话生效,当前生成不中断。';
|
|
1068
|
+
if (section === 'cursor') return '生效范围:保存后下一条消息或下个新会话生效,当前生成不中断。';
|
|
1069
|
+
if (section === 'codex') return '生效范围:保存后下一条消息或下个新会话生效,当前生成不中断。';
|
|
1070
|
+
return '生效范围:保存后按配置类型应用。';
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
function toastConfigApplyResult(result, savedText) {
|
|
1074
|
+
var text = savedText || '配置已保存';
|
|
1075
|
+
if (result && result.mode === 'reload') {
|
|
1076
|
+
toast(text + ',后续消息/新会话已生效。');
|
|
1077
|
+
} else if (result && result.mode === 'restart-required') {
|
|
1078
|
+
toast(text + ',需重启服务生效。');
|
|
1079
|
+
} else {
|
|
1080
|
+
toast(text);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
980
1084
|
function onCursorBatteryModeChange(prefix, value) {
|
|
981
1085
|
var rowId = prefix === 'edit-' ? 'edit-cursor-on-demand-budget-row' : 'field-cursor-on-demand-budget-row';
|
|
982
1086
|
var row = document.getElementById(rowId);
|
|
@@ -1014,7 +1118,7 @@ async function onPlatformToggle(platform, enabled) {
|
|
|
1014
1118
|
state.config.platforms[platform].enabled = enabled;
|
|
1015
1119
|
var label = document.getElementById('dash-platform-' + platform + '-label');
|
|
1016
1120
|
if (label) label.textContent = enabled ? '已启用' : '未启用';
|
|
1017
|
-
|
|
1121
|
+
toastConfigApplyResult(result, (platform === 'feishu' ? '飞书' : '微信 iLink') + (enabled ? ' 已启用' : ' 已禁用'));
|
|
1018
1122
|
} else {
|
|
1019
1123
|
toast('保存失败: ' + (result.error || '未知错误'), 'error');
|
|
1020
1124
|
// 还原 toggle
|
|
@@ -1420,15 +1524,16 @@ function renderStep3() {
|
|
|
1420
1524
|
document.getElementById('review-content').innerHTML = lines.join('');
|
|
1421
1525
|
}
|
|
1422
1526
|
|
|
1423
|
-
async function saveConfig(vars) {
|
|
1527
|
+
async function saveConfig(vars, options) {
|
|
1528
|
+
options = options || {};
|
|
1424
1529
|
var result = await api('/api/config', 'POST', { vars: vars });
|
|
1425
1530
|
if (result.ok) {
|
|
1426
1531
|
state.config = Object.assign({}, state.config, vars);
|
|
1427
|
-
|
|
1532
|
+
if (!options.quiet) toastConfigApplyResult(result, '配置已保存');
|
|
1428
1533
|
} else {
|
|
1429
1534
|
toast('保存失败: ' + (result.error || '未知错误'), 'error');
|
|
1430
1535
|
}
|
|
1431
|
-
return result
|
|
1536
|
+
return result;
|
|
1432
1537
|
}
|
|
1433
1538
|
|
|
1434
1539
|
async function setDashboardDefaultAgent(agent, enabled) {
|
|
@@ -1451,7 +1556,7 @@ async function setDashboardDefaultAgent(agent, enabled) {
|
|
|
1451
1556
|
state.config.cursor.defaultAgent = agent === 'cursor';
|
|
1452
1557
|
state.config.codex.defaultAgent = agent === 'codex';
|
|
1453
1558
|
updateDefaultAgentToggles();
|
|
1454
|
-
|
|
1559
|
+
toastConfigApplyResult(result, '默认 Agent 已更新');
|
|
1455
1560
|
} else {
|
|
1456
1561
|
toast('保存失败: ' + (result.error || '未知错误'), 'error');
|
|
1457
1562
|
updateDefaultAgentToggles();
|
|
@@ -1464,26 +1569,36 @@ async function saveAndStart() {
|
|
|
1464
1569
|
toast('飞书已启用,请先填写 App ID 和 App Secret', 'error');
|
|
1465
1570
|
return;
|
|
1466
1571
|
}
|
|
1467
|
-
var
|
|
1468
|
-
if (
|
|
1572
|
+
var saved = await saveConfig(vars, { quiet: true });
|
|
1573
|
+
if (saved.ok !== true) return;
|
|
1469
1574
|
document.getElementById('btn-save-start').disabled = true;
|
|
1470
1575
|
document.getElementById('btn-save-start').innerHTML = '<span class="spinner"></span> 应用中...';
|
|
1576
|
+
|
|
1577
|
+
if (state.running && saved.restartRequired === true) {
|
|
1578
|
+
await api('/api/restart', 'POST');
|
|
1579
|
+
toast('配置已保存,服务正在重启…');
|
|
1580
|
+
pollUntilRunning();
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
if (state.running && saved.mode === 'reload') {
|
|
1585
|
+
toastConfigApplyResult(saved, '配置已保存');
|
|
1586
|
+
setTimeout(function(){ location.reload(); }, 1000);
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1471
1590
|
var result = await api('/api/start', 'POST');
|
|
1472
1591
|
if (result.ok) {
|
|
1473
1592
|
var msg;
|
|
1474
|
-
if (result.mode === '
|
|
1475
|
-
msg = '
|
|
1593
|
+
if (result.mode === 'reload') {
|
|
1594
|
+
msg = '配置已保存,后续消息/新会话已生效。';
|
|
1476
1595
|
} else if (result.mode === 'inplace') {
|
|
1477
1596
|
msg = '服务已启动! PID: ' + result.pid;
|
|
1478
1597
|
} else {
|
|
1479
1598
|
msg = '服务已启动! PID: ' + (result.pid || '?');
|
|
1480
1599
|
}
|
|
1481
1600
|
toast(msg);
|
|
1482
|
-
|
|
1483
|
-
pollUntilRunning();
|
|
1484
|
-
} else {
|
|
1485
|
-
setTimeout(function(){ location.reload(); }, 1500);
|
|
1486
|
-
}
|
|
1601
|
+
setTimeout(function(){ location.reload(); }, 1500);
|
|
1487
1602
|
} else {
|
|
1488
1603
|
toast('保存失败: ' + (result.error || '未知错误'), 'error');
|
|
1489
1604
|
document.getElementById('btn-save-start').disabled = false;
|
|
@@ -1666,6 +1781,8 @@ function editSection(section) {
|
|
|
1666
1781
|
var titleMap = { feishu: '飞书', chromeDevtools: 'Chrome CDP', claude: 'Claude Agent', cursor: 'Cursor Agent', codex: 'Codex Agent' };
|
|
1667
1782
|
document.getElementById('edit-modal-title').textContent = '编辑 ' + (titleMap[section] || section);
|
|
1668
1783
|
|
|
1784
|
+
document.getElementById('edit-modal-effect').textContent = configEffectHint(section);
|
|
1785
|
+
|
|
1669
1786
|
var html = '';
|
|
1670
1787
|
var labelMap = {
|
|
1671
1788
|
'CHATCCC_APP_ID': 'App ID', 'CHATCCC_APP_SECRET': 'App Secret',
|
|
@@ -1801,14 +1918,15 @@ async function saveEdit() {
|
|
|
1801
1918
|
var ptEl = document.getElementById('edit-CHATCCC_FEISHU_PLATFORM_TYPE');
|
|
1802
1919
|
if (ptEl && ptEl.value.trim()) vars['CHATCCC_FEISHU_PLATFORM_TYPE'] = ptEl.value.trim();
|
|
1803
1920
|
}
|
|
1804
|
-
await saveConfig(vars);
|
|
1921
|
+
var result = await saveConfig(vars, { quiet: true });
|
|
1922
|
+
if (result.ok !== true) return;
|
|
1805
1923
|
try {
|
|
1806
1924
|
var fresh = await api('/api/config');
|
|
1807
1925
|
state.config = fresh.vars || state.config;
|
|
1808
1926
|
} catch(e) {}
|
|
1809
1927
|
closeEditModal();
|
|
1810
1928
|
updateDashboardUI();
|
|
1811
|
-
|
|
1929
|
+
toastConfigApplyResult(result, '修改已保存');
|
|
1812
1930
|
}
|
|
1813
1931
|
|
|
1814
1932
|
// ---- Other actions ----
|