@wu529778790/open-im 1.7.1-beta.4 → 1.7.1-beta.6
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/dist/cli.js
CHANGED
|
@@ -120,11 +120,11 @@ async function cmdDev() {
|
|
|
120
120
|
}
|
|
121
121
|
async function cmdDashboard() {
|
|
122
122
|
// Start web config server in persistent mode (no timeout)
|
|
123
|
-
const { startWebConfigServer
|
|
123
|
+
const { startWebConfigServer } = await import("./config-web.js");
|
|
124
124
|
const server = await startWebConfigServer({ mode: "dev", cwd: process.cwd(), persistent: true });
|
|
125
|
-
|
|
125
|
+
const url = server.loginUrl ?? server.url;
|
|
126
|
+
console.log(`\nDashboard: ${url}`);
|
|
126
127
|
console.log("Press Ctrl+C to close.\n");
|
|
127
|
-
openWebConfigUrl();
|
|
128
128
|
await server.waitForResult;
|
|
129
129
|
}
|
|
130
130
|
function showHelp(exitCode = 0) {
|
|
@@ -207,9 +207,6 @@ export declare const PAGE_TEXTS: {
|
|
|
207
207
|
readonly codexProxy: "Codex 代理";
|
|
208
208
|
readonly claudeTimeout: "Claude 超时(毫秒)";
|
|
209
209
|
readonly claudeConfigPath: "配置文件位置";
|
|
210
|
-
readonly claudeAuthToken: "ANTHROPIC_AUTH_TOKEN";
|
|
211
|
-
readonly claudeBaseUrl: "ANTHROPIC_BASE_URL";
|
|
212
|
-
readonly claudeModel: "ANTHROPIC_MODEL";
|
|
213
210
|
readonly claudeProxy: "代理(可选)";
|
|
214
211
|
readonly codexTimeout: "Codex 超时(毫秒)";
|
|
215
212
|
readonly codebuddyTimeout: "CodeBuddy 超时(毫秒)";
|
|
@@ -207,9 +207,6 @@ export const PAGE_TEXTS = {
|
|
|
207
207
|
codexProxy: "Codex \u4ee3\u7406",
|
|
208
208
|
claudeTimeout: "Claude \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
|
|
209
209
|
claudeConfigPath: "\u914d\u7f6e\u6587\u4ef6\u4f4d\u7f6e",
|
|
210
|
-
claudeAuthToken: "ANTHROPIC_AUTH_TOKEN",
|
|
211
|
-
claudeBaseUrl: "ANTHROPIC_BASE_URL",
|
|
212
|
-
claudeModel: "ANTHROPIC_MODEL",
|
|
213
210
|
claudeProxy: "\u4ee3\u7406\uff08\u53ef\u9009\uff09",
|
|
214
211
|
codexTimeout: "Codex \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
|
|
215
212
|
codebuddyTimeout: "CodeBuddy \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
|
|
@@ -201,9 +201,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
|
|
|
201
201
|
{ id: "ai-claudeWorkDir-label", key: "workDir" },
|
|
202
202
|
{ id: "ai-claudeTimeoutMs-label", key: "claudeTimeout" },
|
|
203
203
|
{ id: "ai-claudeConfigPath-label", key: "claudeConfigPath" },
|
|
204
|
-
{ id: "ai-claudeAuthToken-label", key: "claudeAuthToken" },
|
|
205
|
-
{ id: "ai-claudeBaseUrl-label", key: "claudeBaseUrl" },
|
|
206
|
-
{ id: "ai-claudeModel-label", key: "claudeModel" },
|
|
207
204
|
{ id: "ai-claudeProxy-label", key: "claudeProxy" },
|
|
208
205
|
{ id: "ai-codexCliPath-label", key: "codexCli" },
|
|
209
206
|
{ id: "ai-codexTimeoutMs-label", key: "codexTimeout" },
|
|
@@ -405,15 +402,55 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
|
|
|
405
402
|
return body;
|
|
406
403
|
}
|
|
407
404
|
|
|
405
|
+
async function loadClaudeSettings() {
|
|
406
|
+
const textarea = document.getElementById("claudeSettingsEditor");
|
|
407
|
+
if (!(textarea instanceof HTMLTextAreaElement)) return;
|
|
408
|
+
try {
|
|
409
|
+
const data = await request("/api/claude/settings");
|
|
410
|
+
const raw = (data.contents || "").trim();
|
|
411
|
+
const target = raw || "{\n}\n";
|
|
412
|
+
try {
|
|
413
|
+
const parsed = JSON.parse(target);
|
|
414
|
+
textarea.value = JSON.stringify(parsed, null, 2) + "\n";
|
|
415
|
+
} catch {
|
|
416
|
+
// 如果后端返回的不是合法 JSON,就原样展示,方便用户手动修
|
|
417
|
+
textarea.value = target;
|
|
418
|
+
}
|
|
419
|
+
} catch (error) {
|
|
420
|
+
setMessage(error.message || String(error), "error");
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
async function saveClaudeSettings() {
|
|
425
|
+
const textarea = document.getElementById("claudeSettingsEditor");
|
|
426
|
+
if (!(textarea instanceof HTMLTextAreaElement)) return;
|
|
427
|
+
const edited = textarea.value;
|
|
428
|
+
// Validate JSON before sending
|
|
429
|
+
try {
|
|
430
|
+
const parsed = JSON.parse(edited);
|
|
431
|
+
textarea.value = JSON.stringify(parsed, null, 2) + "\n";
|
|
432
|
+
} catch (err) {
|
|
433
|
+
setMessage("Invalid JSON: " + (err && err.message ? err.message : String(err)), "error");
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
await request("/api/claude/settings", {
|
|
439
|
+
method: "POST",
|
|
440
|
+
body: JSON.stringify({ contents: edited }),
|
|
441
|
+
});
|
|
442
|
+
setMessage("Claude settings.json saved.", "success");
|
|
443
|
+
} catch (error) {
|
|
444
|
+
setMessage(error.message || String(error), "error");
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
408
448
|
// Fill form with data
|
|
409
449
|
const AI_FIELD_MAPPINGS = [
|
|
410
450
|
{ id: "ai-aiCommand", key: "aiCommand" },
|
|
411
451
|
{ id: "ai-claudeWorkDir", key: "claudeWorkDir" },
|
|
412
452
|
{ id: "ai-claudeTimeoutMs", key: "claudeTimeoutMs" },
|
|
413
453
|
{ id: "ai-claudeConfigPath", key: "claudeConfigPath" },
|
|
414
|
-
{ id: "ai-claudeAuthToken", key: "claudeAuthToken" },
|
|
415
|
-
{ id: "ai-claudeBaseUrl", key: "claudeBaseUrl" },
|
|
416
|
-
{ id: "ai-claudeModel", key: "claudeModel" },
|
|
417
454
|
{ id: "ai-claudeProxy", key: "claudeProxy" },
|
|
418
455
|
{ id: "ai-codexCliPath", key: "codexCliPath" },
|
|
419
456
|
{ id: "ai-codexTimeoutMs", key: "codexTimeoutMs" },
|
|
@@ -460,6 +497,7 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
|
|
|
460
497
|
applyLanguage();
|
|
461
498
|
const data = await request("/api/config");
|
|
462
499
|
fill(data.payload, data.meta);
|
|
500
|
+
await loadClaudeSettings();
|
|
463
501
|
// Initialize current AI tool panel from dropdown value
|
|
464
502
|
currentAiToolPanel = el("ai-aiCommand")?.value || "claude";
|
|
465
503
|
await refreshStatus();
|
|
@@ -499,6 +537,16 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
|
|
|
499
537
|
}
|
|
500
538
|
});
|
|
501
539
|
|
|
540
|
+
// Claude settings.json editor (advanced, inline & collapsible)
|
|
541
|
+
const claudeSettingsContainer = document.getElementById("claudeSettingsContainer");
|
|
542
|
+
if (claudeSettingsContainer && claudeSettingsContainer instanceof HTMLDetailsElement) {
|
|
543
|
+
claudeSettingsContainer.addEventListener("toggle", () => {
|
|
544
|
+
if (claudeSettingsContainer.open) {
|
|
545
|
+
void loadClaudeSettings();
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
502
550
|
// AI tool switcher
|
|
503
551
|
document.querySelectorAll(".tab[data-tool]").forEach((tab) => {
|
|
504
552
|
tab.addEventListener("click", () => {
|
|
@@ -652,9 +700,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
|
|
|
652
700
|
claudeWorkDir: getValue("ai-claudeWorkDir"),
|
|
653
701
|
claudeTimeoutMs: getNumber("ai-claudeTimeoutMs"),
|
|
654
702
|
claudeConfigPath: getValue("ai-claudeConfigPath"),
|
|
655
|
-
claudeAuthToken: getValue("ai-claudeAuthToken"),
|
|
656
|
-
claudeBaseUrl: getValue("ai-claudeBaseUrl"),
|
|
657
|
-
claudeModel: getValue("ai-claudeModel"),
|
|
658
703
|
claudeProxy: getValue("ai-claudeProxy"),
|
|
659
704
|
codexTimeoutMs: getNumber("ai-codexTimeoutMs"),
|
|
660
705
|
codebuddyTimeoutMs: getNumber("ai-codebuddyTimeoutMs"),
|
|
@@ -1128,19 +1128,20 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
|
|
|
1128
1128
|
<div class="form-hint" id="ai-claudeConfigPath-hint">Environment variables are saved to ~/.claude/settings.json</div>
|
|
1129
1129
|
</div>
|
|
1130
1130
|
<div class="form-group">
|
|
1131
|
-
<
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1131
|
+
<details id="claudeSettingsContainer">
|
|
1132
|
+
<summary class="form-label" style="cursor: pointer;">Edit ~/.claude/settings.json (advanced)</summary>
|
|
1133
|
+
<div class="form-hint" style="margin-top: 8px; margin-bottom: 8px;">
|
|
1134
|
+
JSON will be auto-formatted; invalid JSON 会提示错误。
|
|
1135
|
+
</div>
|
|
1136
|
+
<textarea
|
|
1137
|
+
id="claudeSettingsEditor"
|
|
1138
|
+
class="form-input mono"
|
|
1139
|
+
style="min-height: 200px; white-space: pre; font-family: var(--font-mono);"
|
|
1140
|
+
></textarea>
|
|
1141
|
+
<div class="form-hint" style="margin-top: 4px;">
|
|
1142
|
+
折叠/展开以隐藏或查看完整配置。
|
|
1143
|
+
</div>
|
|
1144
|
+
</details>
|
|
1144
1145
|
</div>
|
|
1145
1146
|
</div>
|
|
1146
1147
|
|
package/dist/config-web.js
CHANGED
|
@@ -2,6 +2,8 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { createServer } from "node:http";
|
|
3
3
|
import { URL } from "node:url";
|
|
4
4
|
import { randomBytes } from "node:crypto";
|
|
5
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
6
|
+
import { join, dirname } from "node:path";
|
|
5
7
|
import { DWClient } from "dingtalk-stream";
|
|
6
8
|
import { WEB_CONFIG_PORT } from "./constants.js";
|
|
7
9
|
import { CONFIG_PATH, getClaudeConfigHome, loadClaudeSettingsEnv, saveClaudeSettingsEnv, loadConfig, loadFileConfig, saveFileConfig } from "./config.js";
|
|
@@ -11,6 +13,11 @@ import { initWeWork, stopWeWork } from "./wework/client.js";
|
|
|
11
13
|
import { createLogger } from "./logger.js";
|
|
12
14
|
const log = createLogger("ConfigWeb");
|
|
13
15
|
const TEST_TIMEOUT_MS = 10000;
|
|
16
|
+
function getClaudeSettingsPath() {
|
|
17
|
+
const home = getClaudeConfigHome();
|
|
18
|
+
const baseDir = join(home, ".claude");
|
|
19
|
+
return join(baseDir, "settings.json");
|
|
20
|
+
}
|
|
14
21
|
const pendingLogins = new Map();
|
|
15
22
|
const activeSessions = new Map();
|
|
16
23
|
function getWebConfigHost() {
|
|
@@ -705,6 +712,57 @@ export async function startWebConfigServer(options) {
|
|
|
705
712
|
json(response, 200, getServiceStatus());
|
|
706
713
|
return;
|
|
707
714
|
}
|
|
715
|
+
if (request.method === "GET" && requestUrl.pathname === "/api/claude/settings") {
|
|
716
|
+
try {
|
|
717
|
+
const settingsPath = getClaudeSettingsPath();
|
|
718
|
+
let contents = "{}";
|
|
719
|
+
if (existsSync(settingsPath)) {
|
|
720
|
+
contents = readFileSync(settingsPath, "utf-8");
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
// Try to synthesize from env if file doesn't exist yet
|
|
724
|
+
const env = loadClaudeSettingsEnv();
|
|
725
|
+
if (Object.keys(env).length > 0) {
|
|
726
|
+
contents = JSON.stringify({ env }, null, 2);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
json(response, 200, { path: settingsPath, contents });
|
|
730
|
+
}
|
|
731
|
+
catch (error) {
|
|
732
|
+
json(response, 500, { error: error instanceof Error ? error.message : String(error) });
|
|
733
|
+
}
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
if (request.method === "POST" && requestUrl.pathname === "/api/claude/settings") {
|
|
737
|
+
try {
|
|
738
|
+
const body = await readJson(request);
|
|
739
|
+
const raw = body.contents ?? "";
|
|
740
|
+
if (!raw.trim()) {
|
|
741
|
+
json(response, 400, { error: "contents is required" });
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
let parsed;
|
|
745
|
+
try {
|
|
746
|
+
parsed = JSON.parse(raw);
|
|
747
|
+
}
|
|
748
|
+
catch (err) {
|
|
749
|
+
json(response, 400, { error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` });
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const pretty = JSON.stringify(parsed, null, 2);
|
|
753
|
+
const settingsPath = getClaudeSettingsPath();
|
|
754
|
+
const dir = dirname(settingsPath);
|
|
755
|
+
if (!existsSync(dir)) {
|
|
756
|
+
mkdirSync(dir, { recursive: true });
|
|
757
|
+
}
|
|
758
|
+
writeFileSync(settingsPath, pretty, "utf-8");
|
|
759
|
+
json(response, 200, { message: "Claude settings.json saved.", path: settingsPath });
|
|
760
|
+
}
|
|
761
|
+
catch (error) {
|
|
762
|
+
json(response, 500, { error: error instanceof Error ? error.message : String(error) });
|
|
763
|
+
}
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
708
766
|
if (request.method === "GET" && requestUrl.pathname === "/api/health") {
|
|
709
767
|
const file = loadFileConfig();
|
|
710
768
|
const fileTelegram = file.platforms?.telegram;
|