chatccc 0.2.184 → 0.2.185
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 +88 -69
- package/config.sample.json +5 -0
- package/im-skills/feishu-skill/skill.md +3 -3
- package/package.json +1 -1
- package/src/__tests__/agent-delegate-task-rpc.test.ts +165 -165
- package/src/__tests__/chatgpt-subscription-rpc.test.ts +89 -0
- package/src/__tests__/chatgpt-subscription.test.ts +135 -0
- package/src/__tests__/chrome-devtools-guard.test.ts +125 -0
- package/src/__tests__/config-reload.test.ts +13 -0
- package/src/__tests__/config-sample.test.ts +11 -0
- package/src/__tests__/orchestrator.test.ts +162 -117
- package/src/__tests__/web-ui.test.ts +16 -0
- package/src/agent-delegate-task-rpc.ts +153 -153
- package/src/agent-delegate-task.ts +81 -81
- package/src/chatgpt-subscription-rpc.ts +27 -0
- package/src/chatgpt-subscription.ts +299 -0
- package/src/chrome-devtools-guard.ts +242 -0
- package/src/config.ts +21 -0
- package/src/index.ts +12 -4
- package/src/orchestrator.ts +41 -4
- package/src/session-name.ts +8 -8
- package/src/session.ts +6 -6
- package/src/web-ui.ts +136 -6
package/src/orchestrator.ts
CHANGED
|
@@ -81,6 +81,7 @@ import {
|
|
|
81
81
|
} from "./session-chat-binding.ts";
|
|
82
82
|
import { getCodexUsageSummary, getTenantAccessToken, sendPostMessage } from "./feishu-platform.ts";
|
|
83
83
|
import { getCursorUsageSummary, type CursorUsageSummary } from "./cursor-usage.ts";
|
|
84
|
+
import { getChatGptSubscriptionStatus, type ChatGptSubscriptionResult } from "./chatgpt-subscription.ts";
|
|
84
85
|
import { delegateAgentTask } from "./agent-delegate-task.ts";
|
|
85
86
|
import { applySharedPrefix } from "./shared-prefix.ts";
|
|
86
87
|
import { cwdDisplayName, sessionChatName } from "./session-name.ts";
|
|
@@ -107,7 +108,7 @@ function findModelMatch(input: string, models: string[]): string | null {
|
|
|
107
108
|
return candidates[0] ?? null;
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
function formatCodexUsageSummary(usage: CodexUsageSummary): string {
|
|
111
|
+
function formatCodexUsageSummary(usage: CodexUsageSummary, chatGptSubscription: ChatGptSubscriptionResult | null = null): string {
|
|
111
112
|
const progressBar = (usedPercent: number) => {
|
|
112
113
|
const width = 20;
|
|
113
114
|
const usedBlocks = Math.max(0, Math.min(width, Math.round((usedPercent / 100) * width)));
|
|
@@ -185,14 +186,47 @@ function formatCodexUsageSummary(usage: CodexUsageSummary): string {
|
|
|
185
186
|
return lines.join("\n");
|
|
186
187
|
};
|
|
187
188
|
|
|
189
|
+
const formatChatGptSubscription = () => {
|
|
190
|
+
if (!chatGptSubscription?.ok || !chatGptSubscription.subscription) return "";
|
|
191
|
+
const subscription = chatGptSubscription.subscription;
|
|
192
|
+
const pad = (value: number) => String(value).padStart(2, "0");
|
|
193
|
+
const formatExpiresAt = (value: string | null) => {
|
|
194
|
+
if (!value) return "暂无数据";
|
|
195
|
+
const date = new Date(value);
|
|
196
|
+
if (!Number.isFinite(date.getTime())) return value;
|
|
197
|
+
return [
|
|
198
|
+
date.getFullYear(),
|
|
199
|
+
"-",
|
|
200
|
+
pad(date.getMonth() + 1),
|
|
201
|
+
"-",
|
|
202
|
+
pad(date.getDate()),
|
|
203
|
+
" ",
|
|
204
|
+
pad(date.getHours()),
|
|
205
|
+
":",
|
|
206
|
+
pad(date.getMinutes()),
|
|
207
|
+
].join("");
|
|
208
|
+
};
|
|
209
|
+
const remaining = typeof subscription.remainingDays === "number"
|
|
210
|
+
? `(剩余 ${subscription.remainingDays} 天)`
|
|
211
|
+
: "";
|
|
212
|
+
return [
|
|
213
|
+
"**ChatGPT 订阅:**",
|
|
214
|
+
`- 套餐: ${subscription.plan ?? "暂无数据"}`,
|
|
215
|
+
`- 到期: ${formatExpiresAt(subscription.expiresAt)}${remaining}`,
|
|
216
|
+
`- 自动续费: ${subscription.willRenew === null ? "暂无数据" : subscription.willRenew ? "是" : "否"}`,
|
|
217
|
+
].join("\n");
|
|
218
|
+
};
|
|
219
|
+
|
|
188
220
|
return [
|
|
189
221
|
"Codex 用量:",
|
|
190
222
|
"",
|
|
223
|
+
formatChatGptSubscription(),
|
|
224
|
+
chatGptSubscription?.ok ? "" : "",
|
|
191
225
|
formatResetCredits(),
|
|
192
226
|
"",
|
|
193
227
|
formatWindow("5h", usage.fiveHour),
|
|
194
228
|
formatWindow("周", usage.weekly),
|
|
195
|
-
].join("\n");
|
|
229
|
+
].filter((line, index, arr) => line !== "" || (index > 0 && arr[index - 1] !== "")).join("\n");
|
|
196
230
|
}
|
|
197
231
|
|
|
198
232
|
function formatCursorUsageSummary(usage: CursorUsageSummary): string {
|
|
@@ -277,8 +311,11 @@ async function sendUsageSummary(platform: PlatformAdapter, chatId: string, tool:
|
|
|
277
311
|
return;
|
|
278
312
|
}
|
|
279
313
|
|
|
280
|
-
const usage = await
|
|
281
|
-
|
|
314
|
+
const [usage, chatGptSubscription] = await Promise.all([
|
|
315
|
+
getCodexUsageSummary(),
|
|
316
|
+
getChatGptSubscriptionStatus().catch(() => null),
|
|
317
|
+
]);
|
|
318
|
+
const content = formatCodexUsageSummary(usage, chatGptSubscription);
|
|
282
319
|
if (platform.kind === "wechat") {
|
|
283
320
|
await platform.sendText(chatId, content).catch(() => {});
|
|
284
321
|
} else if (platform.kind === "feishu") {
|
package/src/session-name.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export function cwdDisplayName(cwd: string): string {
|
|
2
|
-
const trimmed = cwd.trim().replace(/[\\/]+$/, "");
|
|
3
|
-
return trimmed.split(/[\\/]/).filter(Boolean).pop() || trimmed || "cwd";
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function sessionChatName(left: string, cwd: string): string {
|
|
7
|
-
return `${left}-${cwdDisplayName(cwd)}`;
|
|
8
|
-
}
|
|
1
|
+
export function cwdDisplayName(cwd: string): string {
|
|
2
|
+
const trimmed = cwd.trim().replace(/[\\/]+$/, "");
|
|
3
|
+
return trimmed.split(/[\\/]/).filter(Boolean).pop() || trimmed || "cwd";
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function sessionChatName(left: string, cwd: string): string {
|
|
7
|
+
return `${left}-${cwdDisplayName(cwd)}`;
|
|
8
|
+
}
|
package/src/session.ts
CHANGED
|
@@ -955,12 +955,12 @@ export async function runAgentSession(
|
|
|
955
955
|
const imSkillsCacheDir = join(USER_DATA_DIR, "im-skills");
|
|
956
956
|
const skillVariables = {
|
|
957
957
|
cwd,
|
|
958
|
-
session_id: sessionId,
|
|
959
|
-
im_skills_cache_dir: imSkillsCacheDir,
|
|
960
|
-
delegate_task_url: `http://127.0.0.1:${CHATCCC_PORT}/api/agent/delegate-task`,
|
|
961
|
-
send_image_url: `http://127.0.0.1:${CHATCCC_PORT}/api/agent/send-image`,
|
|
962
|
-
send_file_url: `http://127.0.0.1:${CHATCCC_PORT}/api/agent/send-file`,
|
|
963
|
-
send_image_script: join(feishuSkillDir, "send-image.mjs"),
|
|
958
|
+
session_id: sessionId,
|
|
959
|
+
im_skills_cache_dir: imSkillsCacheDir,
|
|
960
|
+
delegate_task_url: `http://127.0.0.1:${CHATCCC_PORT}/api/agent/delegate-task`,
|
|
961
|
+
send_image_url: `http://127.0.0.1:${CHATCCC_PORT}/api/agent/send-image`,
|
|
962
|
+
send_file_url: `http://127.0.0.1:${CHATCCC_PORT}/api/agent/send-file`,
|
|
963
|
+
send_image_script: join(feishuSkillDir, "send-image.mjs"),
|
|
964
964
|
send_file_script: join(feishuSkillDir, "send-file.mjs"),
|
|
965
965
|
download_video_script: join(feishuSkillDir, "download-video.mjs"),
|
|
966
966
|
wechat_send_image_script: join(wechatImageSkillDir, "send-image.mjs"),
|
package/src/web-ui.ts
CHANGED
|
@@ -29,6 +29,7 @@ const ILINK_AUTH_PATH = join(USER_DATA_DIR, "state", "ilink-auth.json");
|
|
|
29
29
|
interface AppConfig {
|
|
30
30
|
feishu?: { appId?: string; appSecret?: string };
|
|
31
31
|
platforms?: { feishu?: { enabled?: boolean }; ilink?: { enabled?: boolean } };
|
|
32
|
+
chromeDevtools?: { enabled?: boolean; port?: number; chromePath?: string };
|
|
32
33
|
port?: number;
|
|
33
34
|
gitTimeoutSeconds?: number;
|
|
34
35
|
claude?: { enabled?: boolean; defaultAgent?: boolean; model?: string; subagentModel?: string; effort?: string; apiKey?: string; baseUrl?: string; maxTurn?: number };
|
|
@@ -336,6 +337,15 @@ export function unflattenConfig(flat: Record<string, unknown>): Record<string, u
|
|
|
336
337
|
result.platforms = result.platforms || {};
|
|
337
338
|
(result.platforms as Record<string, unknown>).ilink = (result.platforms as Record<string, unknown>).ilink || {};
|
|
338
339
|
((result.platforms as Record<string, unknown>).ilink as Record<string, unknown>).enabled = val === true || val === "true";
|
|
340
|
+
} else if (key === "CHATCCC_CHROME_DEVTOOLS_ENABLED") {
|
|
341
|
+
result.chromeDevtools = result.chromeDevtools || {};
|
|
342
|
+
(result.chromeDevtools as Record<string, unknown>).enabled = val === true || val === "true";
|
|
343
|
+
} else if (key === "CHATCCC_CHROME_DEVTOOLS_PORT") {
|
|
344
|
+
result.chromeDevtools = result.chromeDevtools || {};
|
|
345
|
+
(result.chromeDevtools as Record<string, unknown>).port = parseInt(val as string, 10) || 15166;
|
|
346
|
+
} else if (key === "CHATCCC_CHROME_DEVTOOLS_PATH") {
|
|
347
|
+
result.chromeDevtools = result.chromeDevtools || {};
|
|
348
|
+
(result.chromeDevtools as Record<string, unknown>).chromePath = val;
|
|
339
349
|
} else if (key === "CHATCCC_PORT") {
|
|
340
350
|
result.port = parseInt(val as string, 10) || 18080;
|
|
341
351
|
} else if (key === "CHATCCC_GIT_TIMEOUT_SECONDS") {
|
|
@@ -639,6 +649,32 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
639
649
|
</div>
|
|
640
650
|
</div>
|
|
641
651
|
|
|
652
|
+
<!-- Chrome CDP -->
|
|
653
|
+
<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:14px;margin-bottom:12px" id="chrome-devtools-block">
|
|
654
|
+
<div style="display:flex;align-items:center;justify-content:space-between">
|
|
655
|
+
<div>
|
|
656
|
+
<div style="font-weight:600;font-size:14px">常驻 Chrome CDP(选填)</div>
|
|
657
|
+
<div style="font-size:12px;color:#64748b">维护本机 Chrome DevTools Protocol 端口,用于 ChatGPT 订阅到期查询</div>
|
|
658
|
+
</div>
|
|
659
|
+
<input type="checkbox" class="agent-toggle" id="field-CHATCCC_CHROME_DEVTOOLS_ENABLED" onchange="toggleWizardChromeDevtoolsFields(this.checked)">
|
|
660
|
+
</div>
|
|
661
|
+
<div id="chrome-devtools-settings" style="margin-top:12px;padding-top:12px;border-top:1px solid #e2e8f0">
|
|
662
|
+
<div class="hint" style="margin-bottom:10px;line-height:1.6">
|
|
663
|
+
依赖:本机已安装 Google Chrome;查询 ChatGPT 订阅到期时间时,需要在这个 CDP 专用 Chrome 窗口中登录 ChatGPT。
|
|
664
|
+
</div>
|
|
665
|
+
<div class="form-group" style="margin-bottom:10px">
|
|
666
|
+
<label>CDP 端口</label>
|
|
667
|
+
<input type="number" id="field-CHATCCC_CHROME_DEVTOOLS_PORT" min="1" max="65535" step="1" placeholder="15166">
|
|
668
|
+
<div class="hint">默认 15166;健康检查端点:http://127.0.0.1:15166/json/version</div>
|
|
669
|
+
</div>
|
|
670
|
+
<div class="form-group">
|
|
671
|
+
<label>Chrome 路径(选填)</label>
|
|
672
|
+
<input type="text" id="field-CHATCCC_CHROME_DEVTOOLS_PATH" placeholder="留空自动探测 chrome.exe">
|
|
673
|
+
<div class="hint">选填;留空时自动探测 Google Chrome。</div>
|
|
674
|
+
</div>
|
|
675
|
+
</div>
|
|
676
|
+
</div>
|
|
677
|
+
|
|
642
678
|
<div class="btn-group" style="justify-content:flex-end">
|
|
643
679
|
<button class="btn btn-primary" id="btn-step1-next" onclick="goStep1Next()">下一步</button>
|
|
644
680
|
</div>
|
|
@@ -825,6 +861,17 @@ header .badge{font-size:13px;padding:4px 12px;border-radius:12px;font-weight:500
|
|
|
825
861
|
</div>
|
|
826
862
|
</details>
|
|
827
863
|
|
|
864
|
+
<details class="card config-section">
|
|
865
|
+
<summary>Chrome CDP(选填)</summary>
|
|
866
|
+
<div class="section-detail">
|
|
867
|
+
<div class="config-row"><span class="key">状态</span><span class="val" id="cfg-CHROME_DEVTOOLS_ENABLED">-</span></div>
|
|
868
|
+
<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>
|
|
869
|
+
<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>
|
|
870
|
+
<div class="hint" style="margin-top:6px;line-height:1.6">依赖:本机 Google Chrome;ChatGPT 订阅到期查询需要在该 CDP Chrome 中登录 ChatGPT。</div>
|
|
871
|
+
<button class="btn btn-outline" style="margin-top:8px" onclick="editSection('chromeDevtools')">编辑</button>
|
|
872
|
+
</div>
|
|
873
|
+
</details>
|
|
874
|
+
|
|
828
875
|
<details class="card config-section" id="dash-claude">
|
|
829
876
|
<summary>Claude Agent</summary>
|
|
830
877
|
<div class="section-detail">
|
|
@@ -907,6 +954,7 @@ const AGENT_FIELDS = {
|
|
|
907
954
|
codex: ['CHATCCC_CODEX_PATH','CHATCCC_CODEX_MODEL','CHATCCC_CODEX_EFFORT']
|
|
908
955
|
};
|
|
909
956
|
const FEISHU_FIELDS = ['CHATCCC_APP_ID','CHATCCC_APP_SECRET'];
|
|
957
|
+
const CHROME_DEVTOOLS_FIELDS = ['CHATCCC_CHROME_DEVTOOLS_ENABLED','CHATCCC_CHROME_DEVTOOLS_PORT','CHATCCC_CHROME_DEVTOOLS_PATH'];
|
|
910
958
|
|
|
911
959
|
function cursorBatteryModeLabel(value) {
|
|
912
960
|
return value === 'onDemandUse' ? 'On demand use 金额' : 'API 使用比例';
|
|
@@ -918,6 +966,18 @@ function onCursorBatteryModeChange(prefix, value) {
|
|
|
918
966
|
if (row) row.style.display = value === 'onDemandUse' ? '' : 'none';
|
|
919
967
|
}
|
|
920
968
|
|
|
969
|
+
function toggleWizardChromeDevtoolsFields(enabled) {
|
|
970
|
+
var settings = document.getElementById('chrome-devtools-settings');
|
|
971
|
+
if (settings) settings.style.display = enabled ? '' : 'none';
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
function toggleEditChromeDevtoolsFields(enabled) {
|
|
975
|
+
['CHATCCC_CHROME_DEVTOOLS_PORT', 'CHATCCC_CHROME_DEVTOOLS_PATH'].forEach(function(key){
|
|
976
|
+
var row = document.getElementById('edit-row-' + key);
|
|
977
|
+
if (row) row.style.display = enabled ? '' : 'none';
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
|
|
921
981
|
function onWizardPlatformToggle(platform, enabled) {
|
|
922
982
|
state.platformsEnabled[platform] = enabled;
|
|
923
983
|
// 飞书凭证字段跟随开关显示/隐藏
|
|
@@ -1133,6 +1193,12 @@ function renderStep1() {
|
|
|
1133
1193
|
if (credFields) credFields.style.display = feishuEnabled ? '' : 'none';
|
|
1134
1194
|
var ilToggle = document.getElementById('platform-enable-ilink');
|
|
1135
1195
|
if (ilToggle) ilToggle.checked = ilinkEnabled;
|
|
1196
|
+
var cd = c.chromeDevtools || {};
|
|
1197
|
+
var cdpEnabled = document.getElementById('field-CHATCCC_CHROME_DEVTOOLS_ENABLED');
|
|
1198
|
+
if (cdpEnabled) cdpEnabled.checked = cd.enabled === true;
|
|
1199
|
+
prefillNested('field-CHATCCC_CHROME_DEVTOOLS_PORT', cd.port || 15166);
|
|
1200
|
+
prefillNested('field-CHATCCC_CHROME_DEVTOOLS_PATH', cd.chromePath);
|
|
1201
|
+
toggleWizardChromeDevtoolsFields(cd.enabled === true);
|
|
1136
1202
|
}
|
|
1137
1203
|
|
|
1138
1204
|
/**
|
|
@@ -1231,6 +1297,12 @@ function collectAllFields() {
|
|
|
1231
1297
|
if (ptEl && ptEl.value.trim()) vars['CHATCCC_FEISHU_PLATFORM_TYPE'] = ptEl.value.trim();
|
|
1232
1298
|
vars.CHATCCC_FEISHU_ENABLED = !!state.platformsEnabled.feishu;
|
|
1233
1299
|
vars.CHATCCC_ILINK_ENABLED = !!state.platformsEnabled.ilink;
|
|
1300
|
+
var cdpEnabledEl = document.getElementById('field-CHATCCC_CHROME_DEVTOOLS_ENABLED');
|
|
1301
|
+
vars.CHATCCC_CHROME_DEVTOOLS_ENABLED = !!(cdpEnabledEl && cdpEnabledEl.checked);
|
|
1302
|
+
var cdpPortEl = document.getElementById('field-CHATCCC_CHROME_DEVTOOLS_PORT');
|
|
1303
|
+
vars.CHATCCC_CHROME_DEVTOOLS_PORT = (cdpPortEl && cdpPortEl.value.trim()) ? cdpPortEl.value.trim() : '15166';
|
|
1304
|
+
var cdpPathEl = document.getElementById('field-CHATCCC_CHROME_DEVTOOLS_PATH');
|
|
1305
|
+
if (cdpPathEl && cdpPathEl.value.trim()) vars.CHATCCC_CHROME_DEVTOOLS_PATH = cdpPathEl.value.trim();
|
|
1234
1306
|
vars.CHATCCC_CLAUDE_ENABLED = !!state.agentsEnabled.claude;
|
|
1235
1307
|
vars.CHATCCC_CURSOR_ENABLED = !!state.agentsEnabled.cursor;
|
|
1236
1308
|
vars.CHATCCC_CODEX_ENABLED = !!state.agentsEnabled.codex;
|
|
@@ -1281,6 +1353,15 @@ function renderStep3() {
|
|
|
1281
1353
|
lines.push('<div style="color:#ef4444;margin-top:8px">未启用任何平台</div>');
|
|
1282
1354
|
}
|
|
1283
1355
|
|
|
1356
|
+
lines.push('<h3 style="margin:16px 0 8px">Chrome CDP</h3>');
|
|
1357
|
+
lines.push('<div class="config-row"><span class="key">状态</span><span class="val">' + (vars.CHATCCC_CHROME_DEVTOOLS_ENABLED ? '已启用' : '已禁用') + '</span></div>');
|
|
1358
|
+
if (vars.CHATCCC_CHROME_DEVTOOLS_ENABLED) {
|
|
1359
|
+
lines.push('<div class="config-row"><span class="key">CDP 端口</span><span class="val">' + (vars.CHATCCC_CHROME_DEVTOOLS_PORT || '15166') + '</span></div>');
|
|
1360
|
+
if (vars.CHATCCC_CHROME_DEVTOOLS_PATH) {
|
|
1361
|
+
lines.push('<div class="config-row"><span class="key">Chrome 路径</span><span class="val">' + vars.CHATCCC_CHROME_DEVTOOLS_PATH + '</span></div>');
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1284
1365
|
lines.push('<h3 style="margin:16px 0 8px">已启用的 AI Agent</h3>');
|
|
1285
1366
|
var enabledList = [];
|
|
1286
1367
|
if (state.agentsEnabled.claude) enabledList.push('claude');
|
|
@@ -1471,6 +1552,16 @@ function updateDashboardUI() {
|
|
|
1471
1552
|
ilinkForgetRow.style.display = (ilinkEnabled && state.ilinkAuthExists) ? '' : 'none';
|
|
1472
1553
|
}
|
|
1473
1554
|
|
|
1555
|
+
var chromeDevtools = c.chromeDevtools || {};
|
|
1556
|
+
var cdpPort = chromeDevtools.port || 15166;
|
|
1557
|
+
document.getElementById('cfg-CHROME_DEVTOOLS_ENABLED').textContent = chromeDevtools.enabled ? '已启用' : '已禁用';
|
|
1558
|
+
document.getElementById('cfg-CHROME_DEVTOOLS_PORT').textContent = String(cdpPort);
|
|
1559
|
+
document.getElementById('cfg-CHROME_DEVTOOLS_PATH').textContent = chromeDevtools.chromePath || '(自动探测)';
|
|
1560
|
+
var cdpPortRow = document.getElementById('cfg-CHROME_DEVTOOLS_PORT_ROW');
|
|
1561
|
+
var cdpPathRow = document.getElementById('cfg-CHROME_DEVTOOLS_PATH_ROW');
|
|
1562
|
+
if (cdpPortRow) cdpPortRow.style.display = chromeDevtools.enabled ? '' : 'none';
|
|
1563
|
+
if (cdpPathRow) cdpPathRow.style.display = chromeDevtools.enabled ? '' : 'none';
|
|
1564
|
+
|
|
1474
1565
|
document.getElementById('dash-claude').style.display = claudeOn ? '' : 'none';
|
|
1475
1566
|
document.getElementById('dash-cursor').style.display = cursorOn ? '' : 'none';
|
|
1476
1567
|
document.getElementById('dash-codex').style.display = codexOn ? '' : 'none';
|
|
@@ -1546,14 +1637,18 @@ function editSection(section) {
|
|
|
1546
1637
|
editSectionType = section;
|
|
1547
1638
|
var fields;
|
|
1548
1639
|
if (section === 'feishu') fields = FEISHU_FIELDS;
|
|
1640
|
+
else if (section === 'chromeDevtools') fields = CHROME_DEVTOOLS_FIELDS;
|
|
1549
1641
|
else fields = AGENT_FIELDS[section] || [];
|
|
1550
1642
|
|
|
1551
|
-
var titleMap = { feishu: '飞书', claude: 'Claude Agent', cursor: 'Cursor Agent', codex: 'Codex Agent' };
|
|
1643
|
+
var titleMap = { feishu: '飞书', chromeDevtools: 'Chrome CDP', claude: 'Claude Agent', cursor: 'Cursor Agent', codex: 'Codex Agent' };
|
|
1552
1644
|
document.getElementById('edit-modal-title').textContent = '编辑 ' + (titleMap[section] || section);
|
|
1553
1645
|
|
|
1554
1646
|
var html = '';
|
|
1555
1647
|
var labelMap = {
|
|
1556
1648
|
'CHATCCC_APP_ID': 'App ID', 'CHATCCC_APP_SECRET': 'App Secret',
|
|
1649
|
+
'CHATCCC_CHROME_DEVTOOLS_ENABLED': '启用常驻 Chrome CDP(选填)',
|
|
1650
|
+
'CHATCCC_CHROME_DEVTOOLS_PORT': 'CDP 端口',
|
|
1651
|
+
'CHATCCC_CHROME_DEVTOOLS_PATH': 'Chrome 路径(选填)',
|
|
1557
1652
|
'CHATCCC_ANTHROPIC_MODEL': '模型', 'CHATCCC_ANTHROPIC_SUBAGENT_MODEL': 'Subagent 模型', 'CHATCCC_ANTHROPIC_EFFORT': 'Effort',
|
|
1558
1653
|
'CHATCCC_ANTHROPIC_API_KEY': 'API Key', 'CHATCCC_ANTHROPIC_BASE_URL': 'Base URL', 'CHATCCC_ANTHROPIC_MAX_TURN': 'Max Turns (0=无限制)',
|
|
1559
1654
|
'CHATCCC_CURSOR_PATH': 'CLI 路径', 'CHATCCC_CURSOR_MODEL': '模型',
|
|
@@ -1561,6 +1656,15 @@ function editSection(section) {
|
|
|
1561
1656
|
'CHATCCC_CURSOR_ON_DEMAND_MONTHLY_BUDGET': '每月On demand use预算',
|
|
1562
1657
|
'CHATCCC_CODEX_PATH': 'CLI 路径', 'CHATCCC_CODEX_MODEL': '模型', 'CHATCCC_CODEX_EFFORT': 'Effort'
|
|
1563
1658
|
};
|
|
1659
|
+
var hintMap = {
|
|
1660
|
+
'CHATCCC_CHROME_DEVTOOLS_ENABLED': '依赖:本机 Google Chrome;ChatGPT 订阅到期查询需要在该 CDP Chrome 中登录 ChatGPT。',
|
|
1661
|
+
'CHATCCC_CHROME_DEVTOOLS_PORT': '默认 15166,健康检查端点为 http://127.0.0.1:15166/json/version。',
|
|
1662
|
+
'CHATCCC_CHROME_DEVTOOLS_PATH': '选填。留空时自动探测 Google Chrome。'
|
|
1663
|
+
};
|
|
1664
|
+
|
|
1665
|
+
if (section === 'chromeDevtools') {
|
|
1666
|
+
html += '<div class="hint" style="margin-bottom:12px;line-height:1.6">常驻 Chrome CDP 用于维护本机 Chrome DevTools Protocol 端口。依赖:本机 Google Chrome;ChatGPT 订阅到期查询需要在该 CDP Chrome 中登录 ChatGPT。</div>';
|
|
1667
|
+
}
|
|
1564
1668
|
|
|
1565
1669
|
fields.forEach(function(key){
|
|
1566
1670
|
var val = state.config[key] || '';
|
|
@@ -1569,6 +1673,10 @@ function editSection(section) {
|
|
|
1569
1673
|
if (section === 'feishu') {
|
|
1570
1674
|
if (key === 'CHATCCC_APP_ID' && state.config.feishu) val = state.config.feishu.appId || '';
|
|
1571
1675
|
else if (key === 'CHATCCC_APP_SECRET' && state.config.feishu) val = state.config.feishu.appSecret || '';
|
|
1676
|
+
} else if (section === 'chromeDevtools' && state.config.chromeDevtools) {
|
|
1677
|
+
if (key === 'CHATCCC_CHROME_DEVTOOLS_ENABLED') val = state.config.chromeDevtools.enabled === true ? 'true' : 'false';
|
|
1678
|
+
else if (key === 'CHATCCC_CHROME_DEVTOOLS_PORT') val = state.config.chromeDevtools.port != null ? String(state.config.chromeDevtools.port) : '15166';
|
|
1679
|
+
else if (key === 'CHATCCC_CHROME_DEVTOOLS_PATH') val = state.config.chromeDevtools.chromePath || '';
|
|
1572
1680
|
} else if (section === 'claude' && state.config.claude) {
|
|
1573
1681
|
if (key === 'CHATCCC_ANTHROPIC_MODEL') val = state.config.claude.model || '';
|
|
1574
1682
|
else if (key === 'CHATCCC_ANTHROPIC_SUBAGENT_MODEL') val = state.config.claude.subagentModel || '';
|
|
@@ -1588,7 +1696,12 @@ function editSection(section) {
|
|
|
1588
1696
|
}
|
|
1589
1697
|
}
|
|
1590
1698
|
var isSecret = key.includes('SECRET') || key.includes('API_KEY');
|
|
1591
|
-
if (key === '
|
|
1699
|
+
if (key === 'CHATCCC_CHROME_DEVTOOLS_ENABLED') {
|
|
1700
|
+
var checked = val === true || val === 'true';
|
|
1701
|
+
html += '<div class="form-group"><label style="display:flex;align-items:center;gap:8px"><input type="checkbox" id="edit-' + key + '"' + (checked ? ' checked' : '') + ' onchange="toggleEditChromeDevtoolsFields(this.checked)"> ' + (labelMap[key] || key) + '</label>';
|
|
1702
|
+
if (hintMap[key]) html += '<div class="hint" style="margin-top:6px;line-height:1.5">' + hintMap[key] + '</div>';
|
|
1703
|
+
html += '</div>';
|
|
1704
|
+
} else if (key === 'CHATCCC_CURSOR_AVATAR_BATTERY_MODE') {
|
|
1592
1705
|
var modeVal = val || 'apiPercent';
|
|
1593
1706
|
html += '<div class="form-group"><label>' + (labelMap[key] || key) + '</label>';
|
|
1594
1707
|
html += '<select id="edit-' + key + '" onchange="onCursorBatteryModeChange(\\'edit-\\', this.value)" style="width:100%;padding:8px 12px;border:1px solid #cbd5e1;border-radius:8px;font-size:14px;outline:none">';
|
|
@@ -1596,11 +1709,19 @@ function editSection(section) {
|
|
|
1596
1709
|
html += '<option value="onDemandUse"' + (modeVal === 'onDemandUse' ? ' selected' : '') + '>On demand use 金额</option>';
|
|
1597
1710
|
html += '</select></div>';
|
|
1598
1711
|
} else {
|
|
1599
|
-
var rowId = key === 'CHATCCC_CURSOR_ON_DEMAND_MONTHLY_BUDGET'
|
|
1600
|
-
|
|
1601
|
-
|
|
1712
|
+
var rowId = key === 'CHATCCC_CURSOR_ON_DEMAND_MONTHLY_BUDGET'
|
|
1713
|
+
? ' id="edit-cursor-on-demand-budget-row"'
|
|
1714
|
+
: (section === 'chromeDevtools' && key !== 'CHATCCC_CHROME_DEVTOOLS_ENABLED' ? ' id="edit-row-' + key + '"' : '');
|
|
1715
|
+
var isNumber = key === 'CHATCCC_CURSOR_ON_DEMAND_MONTHLY_BUDGET' || key === 'CHATCCC_CHROME_DEVTOOLS_PORT';
|
|
1716
|
+
var inputType = isNumber ? 'number' : (isSecret ? 'password' : 'text');
|
|
1717
|
+
var attrs = key === 'CHATCCC_CURSOR_ON_DEMAND_MONTHLY_BUDGET'
|
|
1718
|
+
? ' min="1" step="1"'
|
|
1719
|
+
: key === 'CHATCCC_CHROME_DEVTOOLS_PORT'
|
|
1720
|
+
? ' min="1" max="65535" step="1" placeholder="15166"'
|
|
1721
|
+
: '';
|
|
1602
1722
|
html += '<div class="form-group"' + rowId + '><label>' + (labelMap[key] || key) + '</label>';
|
|
1603
1723
|
html += '<input type="' + inputType + '" id="edit-' + key + '"' + attrs + ' value="' + String(val).replace(/"/g,'"') + '">';
|
|
1724
|
+
if (hintMap[key]) html += '<div class="hint" style="margin-top:6px;line-height:1.5">' + hintMap[key] + '</div>';
|
|
1604
1725
|
html += '</div>';
|
|
1605
1726
|
}
|
|
1606
1727
|
});
|
|
@@ -1617,6 +1738,9 @@ function editSection(section) {
|
|
|
1617
1738
|
if (section === 'cursor') {
|
|
1618
1739
|
var editModeEl = document.getElementById('edit-CHATCCC_CURSOR_AVATAR_BATTERY_MODE');
|
|
1619
1740
|
onCursorBatteryModeChange('edit-', editModeEl ? editModeEl.value : 'apiPercent');
|
|
1741
|
+
} else if (section === 'chromeDevtools') {
|
|
1742
|
+
var editChromeDevtoolsEnabledEl = document.getElementById('edit-CHATCCC_CHROME_DEVTOOLS_ENABLED');
|
|
1743
|
+
toggleEditChromeDevtoolsFields(!!(editChromeDevtoolsEnabledEl && editChromeDevtoolsEnabledEl.checked));
|
|
1620
1744
|
}
|
|
1621
1745
|
document.getElementById('edit-modal').classList.remove('hidden');
|
|
1622
1746
|
document.getElementById('edit-overlay').classList.remove('hidden');
|
|
@@ -1631,13 +1755,19 @@ function closeEditModal() {
|
|
|
1631
1755
|
async function saveEdit() {
|
|
1632
1756
|
var fields;
|
|
1633
1757
|
if (editSectionType === 'feishu') fields = FEISHU_FIELDS;
|
|
1758
|
+
else if (editSectionType === 'chromeDevtools') fields = CHROME_DEVTOOLS_FIELDS;
|
|
1634
1759
|
else fields = AGENT_FIELDS[editSectionType] || [];
|
|
1635
1760
|
|
|
1636
1761
|
var vars = {};
|
|
1637
1762
|
fields.forEach(function(key){
|
|
1638
1763
|
var el = document.getElementById('edit-' + key);
|
|
1639
|
-
if (el)
|
|
1764
|
+
if (!el) return;
|
|
1765
|
+
if (key === 'CHATCCC_CHROME_DEVTOOLS_ENABLED') vars[key] = !!el.checked;
|
|
1766
|
+
else vars[key] = el.value.trim();
|
|
1640
1767
|
});
|
|
1768
|
+
if (editSectionType === 'chromeDevtools' && !vars.CHATCCC_CHROME_DEVTOOLS_PORT) {
|
|
1769
|
+
vars.CHATCCC_CHROME_DEVTOOLS_PORT = '15166';
|
|
1770
|
+
}
|
|
1641
1771
|
if (editSectionType === 'cursor' && vars.CHATCCC_CURSOR_AVATAR_BATTERY_MODE === 'onDemandUse' && !vars.CHATCCC_CURSOR_ON_DEMAND_MONTHLY_BUDGET) {
|
|
1642
1772
|
vars.CHATCCC_CURSOR_ON_DEMAND_MONTHLY_BUDGET = '1000';
|
|
1643
1773
|
}
|