@wu529778790/open-im 1.8.0 → 1.8.1-beta.0

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.
@@ -118,6 +118,14 @@ export declare const PAGE_TEXTS: {
118
118
  readonly saveOk: "Configuration saved.";
119
119
  readonly startOk: "Bridge started.";
120
120
  readonly stopOk: "Bridge stopped.";
121
+ readonly configEditorTitle: "Config Editor";
122
+ readonly configEditorHint: "Edit ~/.open-im/config.json directly";
123
+ readonly configJson: "Configuration (JSON)";
124
+ readonly configJsonHint: "Edit the configuration JSON. Changes will be saved when you click \"Save Config\" in the Service section.";
125
+ readonly formatJson: "Format";
126
+ readonly resetJson: "Reset";
127
+ readonly jsonValid: "Valid JSON";
128
+ readonly jsonInvalid: "Invalid JSON: {error}";
121
129
  };
122
130
  readonly zh: {
123
131
  readonly pageTitle: "open-im 本地控制台";
@@ -232,5 +240,13 @@ export declare const PAGE_TEXTS: {
232
240
  readonly saveOk: "配置已保存。";
233
241
  readonly startOk: "桥接已启动。";
234
242
  readonly stopOk: "桥接已停止。";
243
+ readonly configEditorTitle: "JSON 配置编辑器";
244
+ readonly configEditorHint: "直接编辑 ~/.open-im/config.json";
245
+ readonly configJson: "配置文件 (JSON)";
246
+ readonly configJsonHint: "编辑配置 JSON。点击服务区的“保存配置”按钮后保存更改。";
247
+ readonly formatJson: "格式化";
248
+ readonly resetJson: "重置";
249
+ readonly jsonValid: "JSON 有效";
250
+ readonly jsonInvalid: "JSON 无效:{error}";
235
251
  };
236
252
  };
@@ -118,6 +118,14 @@ export const PAGE_TEXTS = {
118
118
  saveOk: "Configuration saved.",
119
119
  startOk: "Bridge started.",
120
120
  stopOk: "Bridge stopped.",
121
+ configEditorTitle: "Config Editor",
122
+ configEditorHint: "Edit ~/.open-im/config.json directly",
123
+ configJson: "Configuration (JSON)",
124
+ configJsonHint: "Edit the configuration JSON. Changes will be saved when you click \"Save Config\" in the Service section.",
125
+ formatJson: "Format",
126
+ resetJson: "Reset",
127
+ jsonValid: "Valid JSON",
128
+ jsonInvalid: "Invalid JSON: {error}",
121
129
  },
122
130
  zh: {
123
131
  pageTitle: "open-im \u672c\u5730\u63a7\u5236\u53f0",
@@ -232,5 +240,13 @@ export const PAGE_TEXTS = {
232
240
  saveOk: "\u914d\u7f6e\u5df2\u4fdd\u5b58\u3002",
233
241
  startOk: "\u6865\u63a5\u5df2\u542f\u52a8\u3002",
234
242
  stopOk: "\u6865\u63a5\u5df2\u505c\u6b62\u3002",
243
+ configEditorTitle: "JSON \u914d\u7f6e\u7f16\u8f91\u5668",
244
+ configEditorHint: "\u76f4\u63a5\u7f16\u8f91 ~/.open-im/config.json",
245
+ configJson: "\u914d\u7f6e\u6587\u4ef6 (JSON)",
246
+ configJsonHint: "\u7f16\u8f91\u914d\u7f6e JSON\u3002\u70b9\u51fb\u670d\u52a1\u533a\u7684\u201c\u4fdd\u5b58\u914d\u7f6e\u201d\u6309\u94ae\u540e\u4fdd\u5b58\u66f4\u6539\u3002",
247
+ formatJson: "\u683c\u5f0f\u5316",
248
+ resetJson: "\u91cd\u7f6e",
249
+ jsonValid: "JSON \u6709\u6548",
250
+ jsonInvalid: "JSON \u65e0\u6548\uff1a{error}",
235
251
  }
236
252
  };
@@ -380,7 +380,7 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
380
380
 
381
381
  // Navigation
382
382
  function setActiveNav(targetId) {
383
- ["navOverviewBtn","navPlatformsBtn","navAiBtn","navServiceBtn"].forEach((id) => {
383
+ ["navOverviewBtn","navPlatformsBtn","navAiBtn","navServiceBtn","navConfigEditorBtn"].forEach((id) => {
384
384
  const btn = el(id);
385
385
  if (btn) btn.classList.toggle("active", id === targetId);
386
386
  });
@@ -445,6 +445,70 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
445
445
  }
446
446
  }
447
447
 
448
+ // Open-im Config Editor functions
449
+ let originalConfigJson = "";
450
+
451
+ async function loadOpenImConfig() {
452
+ const textarea = document.getElementById("configJson");
453
+ if (!(textarea instanceof HTMLTextAreaElement)) return;
454
+ try {
455
+ const data = await request("/api/config/file");
456
+ const raw = (data.contents || "").trim();
457
+ originalConfigJson = raw;
458
+ try {
459
+ const parsed = JSON.parse(raw);
460
+ textarea.value = JSON.stringify(parsed, null, 2) + "\n";
461
+ } catch {
462
+ textarea.value = raw;
463
+ }
464
+ validateJson();
465
+ } catch (error) {
466
+ showJsonValidationMessage(error.message || String(error), "error");
467
+ }
468
+ }
469
+
470
+ function validateJson() {
471
+ const textarea = document.getElementById("configJson");
472
+ const message = document.getElementById("jsonValidationMessage");
473
+ if (!(textarea instanceof HTMLTextAreaElement) || !message) return;
474
+
475
+ const json = textarea.value;
476
+ try {
477
+ JSON.parse(json);
478
+ showJsonValidationMessage("Valid JSON", "success");
479
+ } catch (err) {
480
+ showJsonValidationMessage("Invalid JSON: " + (err.message || String(err)), "error");
481
+ }
482
+ }
483
+
484
+ function showJsonValidationMessage(text, type) {
485
+ const message = document.getElementById("jsonValidationMessage");
486
+ if (!message) return;
487
+ message.textContent = text;
488
+ message.className = "message";
489
+ if (type) message.classList.add("message-" + type);
490
+ message.classList.remove("hidden");
491
+ }
492
+
493
+ function formatJson() {
494
+ const textarea = document.getElementById("configJson");
495
+ if (!(textarea instanceof HTMLTextAreaElement)) return;
496
+ try {
497
+ const parsed = JSON.parse(textarea.value);
498
+ textarea.value = JSON.stringify(parsed, null, 2) + "\n";
499
+ validateJson();
500
+ } catch (err) {
501
+ showJsonValidationMessage("Cannot format: Invalid JSON", "error");
502
+ }
503
+ }
504
+
505
+ function resetJson() {
506
+ const textarea = document.getElementById("configJson");
507
+ if (!(textarea instanceof HTMLTextAreaElement)) return;
508
+ textarea.value = originalConfigJson;
509
+ validateJson();
510
+ }
511
+
448
512
  // Fill form with data
449
513
  const AI_FIELD_MAPPINGS = [
450
514
  { id: "ai-aiCommand", key: "aiCommand" },
@@ -475,6 +539,9 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
475
539
  }
476
540
  });
477
541
 
542
+ // Load JSON editor content
543
+ void loadOpenImConfig();
544
+
478
545
  updateVisualState();
479
546
  }
480
547
 
@@ -558,11 +625,30 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
558
625
  });
559
626
  });
560
627
 
628
+ // Config editor JSON textarea
629
+ const configJsonTextarea = document.getElementById("configJson");
630
+ if (configJsonTextarea) {
631
+ configJsonTextarea.addEventListener("input", validateJson);
632
+ }
633
+
634
+ // Config editor buttons
635
+ const formatJsonButton = document.getElementById("formatJsonButton");
636
+ if (formatJsonButton) {
637
+ formatJsonButton.addEventListener("click", formatJson);
638
+ }
639
+
640
+ const resetJsonButton = document.getElementById("resetJsonButton");
641
+ if (resetJsonButton) {
642
+ resetJsonButton.addEventListener("click", resetJson);
643
+ }
644
+
645
+
561
646
  // Navigation
562
647
  el("navOverviewBtn").onclick = () => scrollToSection("dashboardSection", "navOverviewBtn");
563
648
  el("navPlatformsBtn").onclick = () => scrollToSection("configSection", "navPlatformsBtn");
564
649
  el("navAiBtn").onclick = () => scrollToSection("aiSection", "navAiBtn");
565
650
  el("navServiceBtn").onclick = () => scrollToSection("serviceSection", "navServiceBtn");
651
+ el("navConfigEditorBtn").onclick = () => scrollToSection("configEditorSection", "navConfigEditorBtn");
566
652
 
567
653
  // Language toggle
568
654
  el("langButton").onclick = () => {
@@ -617,6 +703,9 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
617
703
  async function save() {
618
704
  setBusy(true);
619
705
  try {
706
+ // First save JSON editor content if changed
707
+ await saveOpenImConfig();
708
+ // Then save form data
620
709
  await request("/api/config/save?final=1", { method: "POST", body: JSON.stringify(payload()) });
621
710
  setMessage(t("saveOk"), "success");
622
711
  } catch (error) {
@@ -626,6 +715,31 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
626
715
  }
627
716
  }
628
717
 
718
+ async function saveOpenImConfig() {
719
+ const textarea = document.getElementById("configJson");
720
+ if (!(textarea instanceof HTMLTextAreaElement)) return;
721
+ const json = textarea.value;
722
+
723
+ // Validate JSON
724
+ try {
725
+ JSON.parse(json);
726
+ } catch (err) {
727
+ showJsonValidationMessage("Invalid JSON: " + (err.message || String(err)), "error");
728
+ throw new Error("Invalid JSON: " + (err.message || String(err)));
729
+ }
730
+
731
+ try {
732
+ await request("/api/config/file", {
733
+ method: "POST",
734
+ body: JSON.stringify({ contents: json }),
735
+ });
736
+ originalConfigJson = json;
737
+ } catch (error) {
738
+ showJsonValidationMessage(error.message || String(error), "error");
739
+ throw error;
740
+ }
741
+ }
742
+
629
743
  async function startService() {
630
744
  setBusy(true);
631
745
  try {
@@ -781,6 +781,16 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
781
781
  </svg>
782
782
  <span id="navServiceText">Service</span>
783
783
  </button>
784
+ <button class="nav-item" id="navConfigEditorBtn">
785
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
786
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
787
+ <polyline points="14 2 14 8 20 8"/>
788
+ <line x1="16" y1="13" x2="8" y2="13"/>
789
+ <line x1="16" y1="17" x2="8" y2="17"/>
790
+ <polyline points="10 9 9 9 8 9"/>
791
+ </svg>
792
+ <span id="navConfigEditorText">Config Editor</span>
793
+ </button>
784
794
  </nav>
785
795
  </aside>
786
796
 
@@ -1196,6 +1206,33 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
1196
1206
  </div>
1197
1207
  </div>
1198
1208
  </section>
1209
+
1210
+ <!-- Config Editor Section -->
1211
+ <section class="section" id="configEditorSection" style="display:none">
1212
+ <div class="section-header">
1213
+ <h2 class="section-title" id="configEditorTitle">Config Editor</h2>
1214
+ <p class="section-description" id="configEditorHint">Edit ~/.open-im/config.json directly</p>
1215
+ </div>
1216
+
1217
+ <div class="card">
1218
+ <div class="card-body">
1219
+ <div class="form-group">
1220
+ <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
1221
+ <label class="form-label" id="configJson-label">Configuration (JSON)</label>
1222
+ <div style="display:flex; gap:8px;">
1223
+ <button id="formatJsonButton" class="btn btn-sm btn-ghost">Format</button>
1224
+ <button id="resetJsonButton" class="btn btn-sm btn-ghost">Reset</button>
1225
+ </div>
1226
+ </div>
1227
+ <textarea id="configJson" class="form-input mono" rows="20" style="font-family:monospace; font-size:13px; line-height:1.5; min-height:400px; resize:vertical;" spellcheck="false"></textarea>
1228
+ <p class="form-hint" id="configJson-hint">Edit the configuration JSON. Changes will be saved when you click "Save Config" in the Service section.</p>
1229
+ </div>
1230
+ <div class="form-group">
1231
+ <div id="jsonValidationMessage" class="message hidden" aria-live="polite"></div>
1232
+ </div>
1233
+ </div>
1234
+ </div>
1235
+ </section>
1199
1236
  </div>
1200
1237
  </main>
1201
1238
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.8.0",
3
+ "version": "1.8.1-beta.0",
4
4
  "description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, CodeBuddy)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",