@raingor/pi-web-switch 0.6.2 → 0.7.1

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.ja.md CHANGED
@@ -167,6 +167,18 @@ pi-web-switch/
167
167
  └── src/ # React フロントエンド
168
168
  ```
169
169
 
170
+ ## 💬 コミュニティ
171
+
172
+ ご質問・ご提案・バグ報告は **Telegram グループ** へどうぞ:
173
+
174
+ 👉 **[pi-web-switch Telegram グループに参加](https://t.me/+ODpy7_7NlOE4NzA1)**
175
+
176
+ 問題を報告する際は以下を添えてください:
177
+
178
+ 1. OS(macOS / Windows / Linux)
179
+ 2. バージョン —— `npm view @raingor/pi-web-switch version`
180
+ 3. 具体的な問題の説明とエラーのスクリーンショットまたはログ
181
+
170
182
  ## 🔗 リンク
171
183
 
172
184
  - **ホームページ:** [raingor.github.io/my-blog](https://raingor.github.io/my-blog/)
package/README.md CHANGED
@@ -330,6 +330,18 @@ pi-web-switch/
330
330
  └── src/ # React frontend
331
331
  ```
332
332
 
333
+ ## 💬 Community
334
+
335
+ Join the **Telegram group** for questions, suggestions, and bug reports:
336
+
337
+ 👉 **[Join the pi-web-switch Telegram group](https://t.me/+ODpy7_7NlOE4NzA1)**
338
+
339
+ When reporting an issue, please include:
340
+
341
+ 1. Your OS (macOS / Windows / Linux)
342
+ 2. Your version — `npm view @raingor/pi-web-switch version`
343
+ 3. A clear description plus any error screenshots or logs
344
+
333
345
  ## 🔗 Links
334
346
 
335
347
  - **Homepage:** [raingor.github.io/my-blog](https://raingor.github.io/my-blog/)
package/README.zh-CN.md CHANGED
@@ -205,6 +205,18 @@ pi-web-switch/
205
205
  └── src/ # React 前端
206
206
  ```
207
207
 
208
+ ## 💬 交流群
209
+
210
+ 有任何疑问、建议或 bug 反馈,欢迎加入 **Telegram 交流群**:
211
+
212
+ 👉 **[加入 pi-web-switch Telegram 交流群](https://t.me/+ODpy7_7NlOE4NzA1)**
213
+
214
+ 提问时请附上:
215
+
216
+ 1. 你的系统(macOS / Windows / Linux)
217
+ 2. 版本号 —— `npm view @raingor/pi-web-switch version`
218
+ 3. 清晰的问题描述,以及报错截图或日志
219
+
208
220
  ## 🔗 相关链接
209
221
 
210
222
  - **个人主页:** [raingor.github.io/my-blog](https://raingor.github.io/my-blog/)
package/dist/index.html CHANGED
@@ -9,8 +9,8 @@
9
9
  <link rel="manifest" href="./manifest.webmanifest" />
10
10
  <meta name="theme-color" content="#05090d" />
11
11
  <meta name="description" content="Web UI for pi coding agent — configuration management, session browser, and usage dashboard" />
12
- <script type="module" crossorigin src="./assets/main-KiBX8nrj.js"></script>
13
- <link rel="stylesheet" crossorigin href="./assets/main-DF0CuClO.css">
12
+ <script type="module" crossorigin src="./assets/main-Bs37wZvZ.js"></script>
13
+ <link rel="stylesheet" crossorigin href="./assets/main-DTnbncES.css">
14
14
  </head>
15
15
  <body>
16
16
  <div id="root"></div>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@raingor/pi-web-switch",
3
3
  "private": false,
4
- "version": "0.6.2",
4
+ "version": "0.7.1",
5
5
  "type": "module",
6
6
  "main": "dist/index.html",
7
7
  "description": "Web UI for pi coding agent — live configuration management, session browser, and memory viewer",
@@ -0,0 +1,53 @@
1
+ import { useState } from "react";
2
+ import { Sparkles } from "lucide-react";
3
+ import { Modal } from "@/components/ui/Modal";
4
+ import { useTranslation } from "@/lib/i18n";
5
+ import { CHANGELOG } from "@/data/changelog";
6
+
7
+ /**
8
+ * "What's new" changelog dialog. Trigger lives in the sidebar footer (version
9
+ * strip). Entries come from src/data/changelog.ts with i18n item keys.
10
+ */
11
+ export function ChangelogButton() {
12
+ const { t } = useTranslation();
13
+ const [open, setOpen] = useState(false);
14
+
15
+ return (
16
+ <>
17
+ <button
18
+ onClick={() => setOpen(true)}
19
+ className="changelog-trigger"
20
+ title={t("changelog.title")}
21
+ >
22
+ <Sparkles className="h-3.5 w-3.5" />
23
+ <span>{t("changelog.button")}</span>
24
+ </button>
25
+
26
+ <Modal open={open} onClose={() => setOpen(false)} title={t("changelog.title")} size="lg">
27
+ <div className="space-y-5">
28
+ {CHANGELOG.map((entry) => (
29
+ <div key={entry.version}>
30
+ <div className="flex items-baseline gap-2">
31
+ <span
32
+ className="rounded-md px-2 py-0.5 text-xs font-semibold"
33
+ style={{ backgroundColor: "color-mix(in srgb, var(--signal-cyan) 16%, transparent)", color: "var(--signal-cyan, #38bdf8)" }}
34
+ >
35
+ v{entry.version}
36
+ </span>
37
+ <span className="text-xs" style={{ color: "var(--subtle-text)" }}>{entry.date}</span>
38
+ </div>
39
+ <ul className="mt-2 space-y-1.5">
40
+ {entry.itemKeys.map((k) => (
41
+ <li key={k} className="flex gap-2 text-sm leading-relaxed" style={{ color: "var(--muted-text)" }}>
42
+ <span style={{ color: "var(--signal-cyan, #38bdf8)" }}>›</span>
43
+ <span>{t(k)}</span>
44
+ </li>
45
+ ))}
46
+ </ul>
47
+ </div>
48
+ ))}
49
+ </div>
50
+ </Modal>
51
+ </>
52
+ );
53
+ }
@@ -0,0 +1,97 @@
1
+ import { useState } from "react";
2
+ import { HelpCircle, Send } from "lucide-react";
3
+ import { Modal } from "@/components/ui/Modal";
4
+ import { useTranslation } from "@/lib/i18n";
5
+
6
+ // Telegram group invite link. Clicking opens the Telegram app (or web) join
7
+ // confirmation — Telegram has no API to add users to a group without their
8
+ // consent, so an invite link is the compliant "one-click join" path.
9
+ const TELEGRAM_GROUP_URL = "https://t.me/+ODpy7_7NlOE4NzA1";
10
+
11
+ /**
12
+ * Floating help button (bottom-right) that opens a usage guide covering the
13
+ * whole app plus a per-module how-to. All copy is i18n-keyed so it tracks the
14
+ * active locale.
15
+ */
16
+
17
+ // Module sections shown in the guide. Order mirrors the sidebar navigation.
18
+ const SECTIONS: { titleKey: string; descKey: string; stepKeys: string[] }[] = [
19
+ { titleKey: "help.dashboard_title", descKey: "help.dashboard_desc", stepKeys: ["help.dashboard_s1", "help.dashboard_s2"] },
20
+ { titleKey: "help.sessions_title", descKey: "help.sessions_desc", stepKeys: ["help.sessions_s1", "help.sessions_s2", "help.sessions_s3"] },
21
+ { titleKey: "help.memory_title", descKey: "help.memory_desc", stepKeys: ["help.memory_s1", "help.memory_s2", "help.memory_s3"] },
22
+ { titleKey: "help.providers_title", descKey: "help.providers_desc", stepKeys: ["help.providers_s1", "help.providers_s2", "help.providers_s3"] },
23
+ { titleKey: "help.subagents_title", descKey: "help.subagents_desc", stepKeys: ["help.subagents_s1", "help.subagents_s2"] },
24
+ { titleKey: "help.settings_title", descKey: "help.settings_desc", stepKeys: ["help.settings_s1", "help.settings_s2"] },
25
+ { titleKey: "help.speedtest_title", descKey: "help.speedtest_desc", stepKeys: ["help.speedtest_s1", "help.speedtest_s2", "help.speedtest_s3"] },
26
+ ];
27
+
28
+ export function HelpButton() {
29
+ const { t } = useTranslation();
30
+ const [open, setOpen] = useState(false);
31
+
32
+ return (
33
+ <>
34
+ <button
35
+ onClick={() => setOpen(true)}
36
+ className="help-fab"
37
+ aria-label={t("help.button")}
38
+ title={t("help.button")}
39
+ >
40
+ <HelpCircle className="h-5 w-5" />
41
+ </button>
42
+
43
+ <Modal open={open} onClose={() => setOpen(false)} title={t("help.title")} size="xl">
44
+ <div className="space-y-6">
45
+ {/* Project overview */}
46
+ <section>
47
+ <h3 className="text-sm font-semibold" style={{ color: "var(--page-text)" }}>{t("help.overview_title")}</h3>
48
+ <p className="mt-1.5 text-sm leading-relaxed" style={{ color: "var(--muted-text)" }}>{t("help.overview_desc")}</p>
49
+ </section>
50
+
51
+ {/* Per-module guide */}
52
+ <section className="space-y-4">
53
+ <h3 className="text-sm font-semibold" style={{ color: "var(--page-text)" }}>{t("help.modules_title")}</h3>
54
+ {SECTIONS.map((s) => (
55
+ <div
56
+ key={s.titleKey}
57
+ className="rounded-lg border px-4 py-3"
58
+ style={{ borderColor: "var(--card-border)", backgroundColor: "var(--card-bg)" }}
59
+ >
60
+ <h4 className="text-sm font-semibold" style={{ color: "var(--page-text)" }}>{t(s.titleKey)}</h4>
61
+ <p className="mt-1 text-xs leading-relaxed" style={{ color: "var(--muted-text)" }}>{t(s.descKey)}</p>
62
+ {s.stepKeys.length > 0 && (
63
+ <ul className="mt-2 space-y-1">
64
+ {s.stepKeys.map((k) => (
65
+ <li key={k} className="flex gap-2 text-xs leading-relaxed" style={{ color: "var(--subtle-text)" }}>
66
+ <span style={{ color: "var(--signal-cyan, #38bdf8)" }}>›</span>
67
+ <span>{t(k)}</span>
68
+ </li>
69
+ ))}
70
+ </ul>
71
+ )}
72
+ </div>
73
+ ))}
74
+ </section>
75
+ {/* Contact / join group */}
76
+ <section
77
+ className="rounded-lg border px-4 py-3"
78
+ style={{ borderColor: "color-mix(in srgb, var(--signal-cyan) 30%, var(--card-border))", backgroundColor: "var(--card-bg)" }}
79
+ >
80
+ <h3 className="text-sm font-semibold" style={{ color: "var(--page-text)" }}>{t("help.contact_title")}</h3>
81
+ <p className="mt-1 text-xs leading-relaxed" style={{ color: "var(--muted-text)" }}>{t("help.contact_desc")}</p>
82
+ <a
83
+ href={TELEGRAM_GROUP_URL}
84
+ target="_blank"
85
+ rel="noreferrer"
86
+ className="mt-3 inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors"
87
+ style={{ backgroundColor: "#229ED9" }}
88
+ >
89
+ <Send className="h-4 w-4" />
90
+ {t("help.contact_join")}
91
+ </a>
92
+ </section>
93
+ </div>
94
+ </Modal>
95
+ </>
96
+ );
97
+ }
@@ -2,6 +2,7 @@ import { useState } from "react";
2
2
  import { Outlet, useLocation } from "react-router-dom";
3
3
  import { Menu, RadioTower } from "lucide-react";
4
4
  import { Sidebar } from "./Sidebar";
5
+ import { HelpButton } from "@/components/help/HelpButton";
5
6
 
6
7
  export function AppShell() {
7
8
  const location = useLocation();
@@ -52,6 +53,8 @@ export function AppShell() {
52
53
  )}
53
54
  </main>
54
55
  </div>
56
+
57
+ <HelpButton />
55
58
  </div>
56
59
  );
57
60
  }
@@ -11,10 +11,15 @@ import {
11
11
  X,
12
12
  Orbit,
13
13
  Gauge,
14
+ Send,
14
15
  } from "lucide-react";
15
16
  import { cn } from "@/lib/utils";
16
17
  import { useTranslation, LANGUAGES } from "@/lib/i18n";
17
18
  import { useState } from "react";
19
+ import { ChangelogButton } from "@/components/help/ChangelogButton";
20
+
21
+ // Telegram group invite link (same as the help dialog).
22
+ const TELEGRAM_GROUP_URL = "https://t.me/+ODpy7_7NlOE4NzA1";
18
23
 
19
24
  const navItems = [
20
25
  { to: "/", icon: LayoutDashboard, key: "nav.dashboard", code: "01" },
@@ -76,6 +81,16 @@ export function Sidebar({ mobileOpen = false, onClose }: SidebarProps) {
76
81
  </nav>
77
82
 
78
83
  <div className="sidebar-footer">
84
+ <a
85
+ href={TELEGRAM_GROUP_URL}
86
+ target="_blank"
87
+ rel="noreferrer"
88
+ className="sidebar-telegram"
89
+ >
90
+ <Send className="h-4 w-4" />
91
+ <span>{t("help.contact_join")}</span>
92
+ </a>
93
+
79
94
  <div className="node-status">
80
95
  <div className="node-status-icon"><Orbit className="h-4 w-4" /></div>
81
96
  <div>
@@ -108,7 +123,7 @@ export function Sidebar({ mobileOpen = false, onClose }: SidebarProps) {
108
123
 
109
124
  <div className="version-strip">
110
125
  <span>{t("app.version")}</span>
111
- <span>BUILD // STABLE</span>
126
+ <ChangelogButton />
112
127
  </div>
113
128
  </div>
114
129
  </aside>
@@ -372,7 +372,7 @@ function MemoryFileSection({
372
372
 
373
373
  export function MemoryPage() {
374
374
  const { t } = useTranslation();
375
- const { initialized, allModels } = useConfigStore();
375
+ const { initialized, allModels, allProviders } = useConfigStore();
376
376
  const [files, setFiles] = useState<MemoryFile[]>([]);
377
377
  const [loading, setLoading] = useState(true);
378
378
  const [refreshing, setRefreshing] = useState(false);
@@ -396,6 +396,16 @@ export function MemoryPage() {
396
396
 
397
397
  // Capacity status (per-target chars vs limit) for progress bars
398
398
  const [status, setStatus] = useState<{ filename: string; target: string; chars: number; limit: number }[]>([]);
399
+
400
+ // Models eligible as the memory-write model: custom providers, plus built-in
401
+ // providers that have an API key actually saved (hasAuth). Built-ins without
402
+ // a key can't run, so they're excluded from the dropdown.
403
+ const eligibleModels = useMemo(() => {
404
+ const usableProviderIds = new Set(
405
+ allProviders.filter((p) => p.type === "custom" || p.hasAuth).map((p) => p.id)
406
+ );
407
+ return allModels.filter((m) => usableProviderIds.has(m.providerId));
408
+ }, [allModels, allProviders]);
399
409
  const loadStatus = useCallback(() => {
400
410
  fetch("/api/pi/memory/status")
401
411
  .then((r) => r.json())
@@ -493,7 +503,11 @@ export function MemoryPage() {
493
503
  });
494
504
  const { success } = (await res.json()) as { success: boolean };
495
505
  setCfgMsg({ ok: !!success, text: success ? t("memory.config_saved") : t("memory.config_save_failed") });
496
- if (success) loadStatus();
506
+ if (success) {
507
+ loadStatus();
508
+ // Close the modal shortly after showing the success message.
509
+ setTimeout(() => setShowConfig(false), 600);
510
+ }
497
511
  } catch {
498
512
  setCfgMsg({ ok: false, text: t("memory.config_save_failed") });
499
513
  } finally {
@@ -724,20 +738,25 @@ export function MemoryPage() {
724
738
  <p className="text-xs" style={{ color: "var(--muted-text)" }}>{t("memory.config_desc")}</p>
725
739
  <div>
726
740
  <label className="mb-1 block text-xs" style={{ color: "var(--muted-text)" }}>{t("memory.config_model")}</label>
727
- <input
728
- type="text"
729
- list="memory-model-options"
741
+ <select
730
742
  value={cfg.llmModelOverride}
731
743
  onChange={(e) => setCfg({ ...cfg, llmModelOverride: e.target.value })}
732
- placeholder={t("memory.config_model_default")}
733
744
  className="w-full rounded-lg border px-3 py-1.5 text-sm outline-none focus:ring-1 focus:ring-blue-500"
734
745
  style={{ backgroundColor: "var(--card-bg)", borderColor: "var(--card-border)", color: "var(--page-text)" }}
735
- />
736
- <datalist id="memory-model-options">
737
- {allModels.map((m) => (
738
- <option key={`${m.providerId}/${m.id}`} value={`${m.providerId}/${m.id}`}>{m.providerName} · {m.name ?? m.id}</option>
746
+ >
747
+ <option value="">{t("memory.config_model_default")}</option>
748
+ {/* If the saved model isn't in the current model list (e.g. a
749
+ provider was removed), still show it so it isn't silently lost. */}
750
+ {cfg.llmModelOverride &&
751
+ !eligibleModels.some((m) => `${m.providerId}/${m.id}` === cfg.llmModelOverride) && (
752
+ <option value={cfg.llmModelOverride}>{cfg.llmModelOverride}</option>
753
+ )}
754
+ {eligibleModels.map((m) => (
755
+ <option key={`${m.providerId}/${m.id}`} value={`${m.providerId}/${m.id}`}>
756
+ {m.providerName} · {m.name ?? m.id}
757
+ </option>
739
758
  ))}
740
- </datalist>
759
+ </select>
741
760
  </div>
742
761
  <div className="flex gap-3">
743
762
  <div className="flex-1">
@@ -0,0 +1,50 @@
1
+ // Version changelog shown in the "What's new" dialog. Newest first.
2
+ // `items` are i18n keys so the entries localize with the active language.
3
+ // When cutting a release, prepend a new entry here.
4
+
5
+ export interface ChangelogEntry {
6
+ version: string;
7
+ date: string; // ISO date
8
+ itemKeys: string[];
9
+ }
10
+
11
+ export const CHANGELOG: ChangelogEntry[] = [
12
+ {
13
+ version: "0.7.0",
14
+ date: "2026-08-27",
15
+ itemKeys: [
16
+ "changelog.0_7_0_1",
17
+ "changelog.0_7_0_2",
18
+ "changelog.0_7_0_3",
19
+ ],
20
+ },
21
+ {
22
+ version: "0.6.2",
23
+ date: "2026-08-26",
24
+ itemKeys: ["changelog.0_6_2_1"],
25
+ },
26
+ {
27
+ version: "0.6.1",
28
+ date: "2026-08-26",
29
+ itemKeys: ["changelog.0_6_1_1"],
30
+ },
31
+ {
32
+ version: "0.6.0",
33
+ date: "2026-08-26",
34
+ itemKeys: [
35
+ "changelog.0_6_0_1",
36
+ "changelog.0_6_0_2",
37
+ "changelog.0_6_0_3",
38
+ "changelog.0_6_0_4",
39
+ ],
40
+ },
41
+ {
42
+ version: "0.5.0",
43
+ date: "2026-08-26",
44
+ itemKeys: [
45
+ "changelog.0_5_0_1",
46
+ "changelog.0_5_0_2",
47
+ "changelog.0_5_0_3",
48
+ ],
49
+ },
50
+ ];
package/src/index.css CHANGED
@@ -657,3 +657,78 @@ table { border-collapse: collapse; }
657
657
  .official-usage-field-wide { grid-column: auto; }
658
658
  .official-usage-cards { grid-template-columns: 1fr; }
659
659
  }
660
+
661
+ /* ─── Help floating action button ───────────────────────── */
662
+ .help-fab {
663
+ position: fixed;
664
+ right: 22px;
665
+ bottom: 22px;
666
+ z-index: 55;
667
+ display: flex;
668
+ align-items: center;
669
+ justify-content: center;
670
+ width: 44px;
671
+ height: 44px;
672
+ border-radius: 50%;
673
+ border: 1px solid color-mix(in srgb, var(--signal-cyan) 40%, var(--card-border));
674
+ background: var(--card-bg-solid);
675
+ color: var(--signal-cyan);
676
+ box-shadow: 0 10px 30px rgba(0,0,0,.28), 0 0 24px color-mix(in srgb, var(--signal-cyan) 14%, transparent);
677
+ cursor: pointer;
678
+ transition: transform 160ms ease, box-shadow 160ms ease, color 160ms ease;
679
+ }
680
+ .help-fab:hover {
681
+ transform: translateY(-2px);
682
+ color: var(--signal-cyan-bright);
683
+ box-shadow: 0 14px 38px rgba(0,0,0,.34), 0 0 34px color-mix(in srgb, var(--signal-cyan) 22%, transparent);
684
+ }
685
+ @media (max-width: 768px) {
686
+ .help-fab { right: 14px; bottom: 14px; width: 40px; height: 40px; }
687
+ }
688
+
689
+ /* ─── Sidebar Telegram join button ──────────────────────── */
690
+ .sidebar-telegram {
691
+ display: flex;
692
+ align-items: center;
693
+ justify-content: center;
694
+ gap: 8px;
695
+ width: 100%;
696
+ margin-bottom: 10px;
697
+ padding: 9px 12px;
698
+ border-radius: 9px;
699
+ border: 1px solid color-mix(in srgb, #229ED9 45%, var(--card-border));
700
+ background: color-mix(in srgb, #229ED9 12%, transparent);
701
+ color: #229ED9;
702
+ font-size: 12px;
703
+ font-weight: 600;
704
+ letter-spacing: .01em;
705
+ cursor: pointer;
706
+ transition: background 160ms ease, transform 160ms ease, box-shadow 160ms ease;
707
+ }
708
+ .sidebar-telegram:hover {
709
+ background: color-mix(in srgb, #229ED9 20%, transparent);
710
+ transform: translateY(-1px);
711
+ box-shadow: 0 8px 22px color-mix(in srgb, #229ED9 22%, transparent);
712
+ }
713
+
714
+ /* ─── Changelog trigger (version strip) ─────────────────── */
715
+ .changelog-trigger {
716
+ display: inline-flex;
717
+ align-items: center;
718
+ gap: 5px;
719
+ padding: 2px 6px;
720
+ border-radius: 6px;
721
+ border: 1px solid transparent;
722
+ color: var(--muted-text);
723
+ font-family: var(--font-mono);
724
+ font-size: 9px;
725
+ letter-spacing: .06em;
726
+ text-transform: uppercase;
727
+ cursor: pointer;
728
+ transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
729
+ }
730
+ .changelog-trigger:hover {
731
+ color: var(--signal-cyan);
732
+ border-color: color-mix(in srgb, var(--signal-cyan) 30%, var(--card-border));
733
+ background: color-mix(in srgb, var(--signal-cyan) 8%, transparent);
734
+ }
@@ -126,7 +126,21 @@ const en: Record<string, string> = {
126
126
  "official_usage.no_result": "No quota result yet",
127
127
  "official_usage.no_result_desc": "Enter an official usage endpoint and API key, then save to test the query and display quota usage.",
128
128
  "app.subtitle": "Configuration Manager",
129
- "app.version": "pi-switch v0.1.0",
129
+ "app.version": "pi-switch v0.7.0",
130
+ "changelog.button": "Changelog",
131
+ "changelog.title": "What's New",
132
+ "changelog.0_7_0_1": "Added a floating \"User Guide\" button (bottom-right) with a project overview and per-module how-to.",
133
+ "changelog.0_7_0_2": "Added \"Join Telegram group\" entry points (sidebar + user guide dialog).",
134
+ "changelog.0_7_0_3": "Added this \"What’s New\" changelog dialog.",
135
+ "changelog.0_6_2_1": "Subagents: edit a custom agent’s model and thinking level directly from the panel.",
136
+ "changelog.0_6_1_1": "Fix: one-click optimize now runs in an async process, no longer freezing the dev server or auto-reloading the page.",
137
+ "changelog.0_6_0_1": "Memory: added \"Optimize Memory\" to consolidate all three memory files at once.",
138
+ "changelog.0_6_0_2": "Memory: added auto-write model config plus capacity limits and overflow strategy.",
139
+ "changelog.0_6_0_3": "Memory: added per-file capacity progress bars and live optimize progress.",
140
+ "changelog.0_6_0_4": "Settings: removed the GitHub Copilot config section.",
141
+ "changelog.0_5_0_1": "Added the \"Model Speed Test\" module, replacing \"Official Usage\".",
142
+ "changelog.0_5_0_2": "Speed test: one-click fetch models (stored separately) and a slow mode to avoid rate limits.",
143
+ "changelog.0_5_0_3": "Providers page hides built-in providers for a cleaner UI.",
130
144
 
131
145
  // Subagents
132
146
  "subagents.summary": "{0} agents · {1} chains",
@@ -483,6 +497,46 @@ const en: Record<string, string> = {
483
497
  "language.zh-CN": "简体中文",
484
498
  "language.zh-TW": "繁體中文",
485
499
  "language.ja": "日本語",
500
+ "help.button": "User Guide",
501
+ "help.title": "User Guide",
502
+ "help.overview_title": "About this project",
503
+ "help.overview_desc": "pi-web-switch is a visual control panel for the pi coding agent: review sessions, manage long-term memory, configure providers and models, edit subagents, benchmark models, and adjust global settings. All changes write directly to the config files under ~/.pi/agent and take effect immediately.",
504
+ "help.modules_title": "Modules",
505
+ "help.dashboard_title": "01 Dashboard",
506
+ "help.dashboard_desc": "Overview of usage and recent activity.",
507
+ "help.dashboard_s1": "See token usage, cost, and per-model stats.",
508
+ "help.dashboard_s2": "Click \"Refresh now\" to rescan session data.",
509
+ "help.sessions_title": "02 Sessions",
510
+ "help.sessions_desc": "Browse, preview, and manage past sessions.",
511
+ "help.sessions_s1": "Sessions are grouped by project; expand/collapse each.",
512
+ "help.sessions_s2": "Deleting a session moves it to Trash — restore or purge.",
513
+ "help.sessions_s3": "In Trash you can select and permanently delete in bulk.",
514
+ "help.memory_title": "03 Memory",
515
+ "help.memory_desc": "View and optimize pi-hermes-memory long-term memory.",
516
+ "help.memory_s1": "Progress bars show each file’s capacity usage (by characters).",
517
+ "help.memory_s2": "\"Optimize Memory\" runs a model to merge duplicates and drop stale entries.",
518
+ "help.memory_s3": "\"Memory Model\" sets the auto-write model, thinking level, and capacity limits.",
519
+ "help.providers_title": "04 Providers & Models",
520
+ "help.providers_desc": "Manage API providers and their models.",
521
+ "help.providers_s1": "Add a custom provider with its baseUrl and API key.",
522
+ "help.providers_s2": "Use \"Fetch models\" to pull and search available models, then enable them.",
523
+ "help.providers_s3": "Adjust per-model params like maxTokens.",
524
+ "help.subagents_title": "05 Subagents",
525
+ "help.subagents_desc": "View and edit subagents, chains, and run history.",
526
+ "help.subagents_s1": "In \"Agents\", select a custom agent and click \"Edit\" to change its model and thinking level.",
527
+ "help.subagents_s2": "The model field has a dropdown of all configured models.",
528
+ "help.settings_title": "06 Settings",
529
+ "help.settings_desc": "Appearance, model defaults, and advanced options.",
530
+ "help.settings_s1": "Switch theme, font size, UI zoom, and language.",
531
+ "help.settings_s2": "Manage pi packages and check for updates.",
532
+ "help.speedtest_title": "07 Model Speed Test",
533
+ "help.speedtest_desc": "Batch-test custom provider models for availability and latency.",
534
+ "help.speedtest_s1": "Pick a provider and use \"Fetch models\" to load the test set (stored separately).",
535
+ "help.speedtest_s2": "Run the test to see success rate, average latency, and latency range.",
536
+ "help.speedtest_s3": "Enable \"Slow mode\" to reduce 429 rate limits.",
537
+ "help.contact_title": "Need help?",
538
+ "help.contact_desc": "For questions, suggestions, or bug reports, join our Telegram group — click the button below to join.",
539
+ "help.contact_join": "Join Telegram group",
486
540
  };
487
541
 
488
542
  export default en;
@@ -124,7 +124,21 @@ const ja: Record<string, string> = {
124
124
  "official_usage.no_result": "利用枠データはまだありません",
125
125
  "official_usage.no_result_desc": "公式使用量 URL と API Key を入力して保存すると、照会テストを行い利用枠を表示します。",
126
126
  "app.subtitle": "設定マネージャー",
127
- "app.version": "pi-switch v0.1.0",
127
+ "app.version": "pi-switch v0.7.0",
128
+ "changelog.button": "変更履歴",
129
+ "changelog.title": "更新情報",
130
+ "changelog.0_7_0_1": "右下にフローティング「使い方」ボタンを追加。プロジェクト概要と各モジュールの使い方を表示。",
131
+ "changelog.0_7_0_2": "「Telegram グループに参加」の入口を追加(サイドバー + 使い方ダイアログ)。",
132
+ "changelog.0_7_0_3": "この「更新情報」ダイアログを追加。",
133
+ "changelog.0_6_2_1": "サブエージェント:カスタムエージェントのモデルと思考レベルをパネルから直接編集可能に。",
134
+ "changelog.0_6_1_1": "修正:メモリ最適化を非同期プロセス化し、開発サーバーの停止やページ自動リロードを解消。",
135
+ "changelog.0_6_0_1": "メモリ:3 つのメモリファイルを一括統合する「メモリを最適化」を追加。",
136
+ "changelog.0_6_0_2": "メモリ:自動書き込みモデル設定、容量上限、上限超過戦略を追加。",
137
+ "changelog.0_6_0_3": "メモリ:ファイル別の容量プログレスバーと最適化のリアルタイム進捗を追加。",
138
+ "changelog.0_6_0_4": "設定:GitHub Copilot 設定セクションを削除。",
139
+ "changelog.0_5_0_1": "「モデル速度計測」モジュールを追加し、「公式使用量」を置き換え。",
140
+ "changelog.0_5_0_2": "計測:モデルのワンクリック取得(別途保存)とレート制限回避の低速モード。",
141
+ "changelog.0_5_0_3": "プロバイダーページで組み込みプロバイダーを非表示にしUIを簡素化。",
128
142
 
129
143
  // Subagents
130
144
  "subagents.summary": "{0} エージェント · {1} チェーン",
@@ -473,6 +487,46 @@ const ja: Record<string, string> = {
473
487
  "language.zh-CN": "简体中文",
474
488
  "language.zh-TW": "繁體中文",
475
489
  "language.ja": "日本語",
490
+ "help.button": "使い方",
491
+ "help.title": "使い方ガイド",
492
+ "help.overview_title": "このプロジェクトについて",
493
+ "help.overview_desc": "pi-web-switch は pi コーディングエージェントのビジュアル設定パネルです。セッション確認、長期メモリ管理、プロバイダーとモデルの設定、サブエージェント編集、モデル速度計測、全体設定の調整ができます。変更は ~/.pi/agent 配下の設定ファイルに直接書き込まれ、即時反映されます。",
494
+ "help.modules_title": "各モジュール",
495
+ "help.dashboard_title": "01 ダッシュボード",
496
+ "help.dashboard_desc": "使用量と最近の活動の概要。",
497
+ "help.dashboard_s1": "トークン使用量、コスト、モデル別統計を確認。",
498
+ "help.dashboard_s2": "「今すぐ更新」でセッションデータを再スキャン。",
499
+ "help.sessions_title": "02 セッション",
500
+ "help.sessions_desc": "過去のセッションを閲覧・プレビュー・管理。",
501
+ "help.sessions_s1": "セッションはプロジェクト別にグループ化、展開/折りたたみ可能。",
502
+ "help.sessions_s2": "削除はゴミ箱へ移動 — 復元または完全削除。",
503
+ "help.sessions_s3": "ゴミ箱で選択して一括完全削除できます。",
504
+ "help.memory_title": "03 メモリ",
505
+ "help.memory_desc": "pi-hermes-memory の長期メモリを表示・最適化。",
506
+ "help.memory_s1": "プログレスバーが各ファイルの容量(文字数)を表示。",
507
+ "help.memory_s2": "「メモリを最適化」でモデルが重複統合と古い項目の削除を実行。",
508
+ "help.memory_s3": "「メモリモデル設定」で自動書き込みモデル、思考レベル、容量上限を設定。",
509
+ "help.providers_title": "04 プロバイダーとモデル",
510
+ "help.providers_desc": "API プロバイダーとそのモデルを管理。",
511
+ "help.providers_s1": "baseUrl と API キーでカスタムプロバイダーを追加。",
512
+ "help.providers_s2": "「モデル取得」で利用可能なモデルを取得・検索し、有効化。",
513
+ "help.providers_s3": "モデルごとの maxTokens などを調整。",
514
+ "help.subagents_title": "05 サブエージェント",
515
+ "help.subagents_desc": "サブエージェント、チェーン、実行履歴を表示・編集。",
516
+ "help.subagents_s1": "「エージェント」でカスタムエージェントを選び「編集」でモデルと思考レベルを変更。",
517
+ "help.subagents_s2": "モデル入力欄に設定済みモデルのドロップダウン候補付き。",
518
+ "help.settings_title": "06 設定",
519
+ "help.settings_desc": "外観、モデル既定値、詳細オプション。",
520
+ "help.settings_s1": "テーマ、フォントサイズ、UI ズーム、言語を切替。",
521
+ "help.settings_s2": "pi パッケージ管理と更新確認。",
522
+ "help.speedtest_title": "07 モデル速度計測",
523
+ "help.speedtest_desc": "カスタムプロバイダーのモデルの可用性と遅延を一括テスト。",
524
+ "help.speedtest_s1": "プロバイダーを選び「モデル取得」でテスト対象を読み込み(別途保存)。",
525
+ "help.speedtest_s2": "テスト実行で成功率、平均遅延、遅延範囲を確認。",
526
+ "help.speedtest_s3": "レート制限時は「低速モード」で 429 を軽減。",
527
+ "help.contact_title": "お困りですか?",
528
+ "help.contact_desc": "ご質問・ご提案・バグ報告は Telegram グループへ。下のボタンから参加できます。",
529
+ "help.contact_join": "Telegram グループに参加",
476
530
  };
477
531
 
478
532
  export default ja;
@@ -124,7 +124,21 @@ const zhCN: Record<string, string> = {
124
124
  "official_usage.no_result": "暂未获取额度数据",
125
125
  "official_usage.no_result_desc": "填写官方用量接口和 API Key,保存后会立即测试查询并显示额度。",
126
126
  "app.subtitle": "配置管理器",
127
- "app.version": "pi-switch v0.1.0",
127
+ "app.version": "pi-switch v0.7.0",
128
+ "changelog.button": "更新日志",
129
+ "changelog.title": "版本更新说明",
130
+ "changelog.0_7_0_1": "新增右下角浮动「使用说明」按钮,弹窗含项目总览与各板块使用指引。",
131
+ "changelog.0_7_0_2": "新增「加入 Telegram 交流群」入口(侧边栏 + 使用说明弹窗)。",
132
+ "changelog.0_7_0_3": "新增本「版本更新说明」弹窗。",
133
+ "changelog.0_6_2_1": "子代理:支持在面板里直接编辑自定义代理的模型和思考级别。",
134
+ "changelog.0_6_1_1": "修复:一键优化改用异步进程,不再导致开发服务器卡顿和页面自动刷新。",
135
+ "changelog.0_6_0_1": "记忆:新增「一键优化记忆」,一次整合三个记忆文件。",
136
+ "changelog.0_6_0_2": "记忆:新增自动写入记忆所用模型的配置,及容量上限与超限策略设置。",
137
+ "changelog.0_6_0_3": "记忆:新增各记忆文件的容量进度条与优化实时进度。",
138
+ "changelog.0_6_0_4": "设置:移除 GitHub Copilot 配置板块。",
139
+ "changelog.0_5_0_1": "新增「模型测速」模块,替代原「官方用量查询」。",
140
+ "changelog.0_5_0_2": "测速支持一键获取模型(独立本地存储)与慢速模式防限流。",
141
+ "changelog.0_5_0_3": "提供商页隐藏内置供应商,精简界面。",
128
142
 
129
143
  // Subagents
130
144
  "subagents.summary": "{0} 个代理 · {1} 个流水线",
@@ -473,6 +487,46 @@ const zhCN: Record<string, string> = {
473
487
  "language.zh-CN": "简体中文",
474
488
  "language.zh-TW": "繁體中文",
475
489
  "language.ja": "日本語",
490
+ "help.button": "使用说明",
491
+ "help.title": "使用说明",
492
+ "help.overview_title": "关于本项目",
493
+ "help.overview_desc": "pi-web-switch 是 pi 编码助手的可视化配置面板:查看会话、管理长期记忆、配置提供商与模型、编辑子代理、测速模型,并调整全局设置。所有改动直接写入 ~/.pi/agent 下的配置文件,实时生效。",
494
+ "help.modules_title": "各板块说明",
495
+ "help.dashboard_title": "01 仪表盘",
496
+ "help.dashboard_desc": "总览用量与近期活动。",
497
+ "help.dashboard_s1": "查看 token 用量、成本和各模型统计。",
498
+ "help.dashboard_s2": "点击「立即刷新」重新扫描会话数据。",
499
+ "help.sessions_title": "02 会话",
500
+ "help.sessions_desc": "浏览、预览和管理历史会话。",
501
+ "help.sessions_s1": "按项目分组查看会话,可展开/折叠。",
502
+ "help.sessions_s2": "删除会话会移入回收站,可恢复或永久删除。",
503
+ "help.sessions_s3": "回收站中可勾选批量永久删除。",
504
+ "help.memory_title": "03 记忆",
505
+ "help.memory_desc": "查看和优化 pi-hermes-memory 长期记忆。",
506
+ "help.memory_s1": "进度条显示三个记忆文件的容量占用(按字符)。",
507
+ "help.memory_s2": "「一键优化记忆」调用模型合并重复、清理过时条目。",
508
+ "help.memory_s3": "「记忆模型配置」设置自动写入所用模型、思考级别和容量上限。",
509
+ "help.providers_title": "04 提供商与模型",
510
+ "help.providers_desc": "管理 API 提供商和它们的模型。",
511
+ "help.providers_s1": "添加自定义提供商,填写 baseUrl 和 API Key。",
512
+ "help.providers_s2": "用「获取模型列表」拉取并搜索可用模型,勾选启用。",
513
+ "help.providers_s3": "可调整每个模型的 maxTokens 等参数。",
514
+ "help.subagents_title": "05 子代理",
515
+ "help.subagents_desc": "查看和编辑子代理、链和运行历史。",
516
+ "help.subagents_s1": "在「代理」选中自定义代理,点「编辑」可改模型和思考级别。",
517
+ "help.subagents_s2": "模型输入框带全部已配置模型的下拉候选。",
518
+ "help.settings_title": "06 设置",
519
+ "help.settings_desc": "外观、模型默认值和高级选项。",
520
+ "help.settings_s1": "切换主题、字体大小、界面缩放和语言。",
521
+ "help.settings_s2": "管理 pi 包并检查更新。",
522
+ "help.speedtest_title": "07 模型测速",
523
+ "help.speedtest_desc": "批量测试自定义提供商模型的可用性与延迟。",
524
+ "help.speedtest_s1": "选择提供商,用「获取模型」拉取待测模型(独立存储)。",
525
+ "help.speedtest_s2": "运行测速,查看成功率、平均延迟和延迟区间。",
526
+ "help.speedtest_s3": "遇限流可开「慢速模式」降低 429。",
527
+ "help.contact_title": "遇到问题?",
528
+ "help.contact_desc": "有任何疑问、建议或 bug 反馈,欢迎加入 Telegram 交流群,点击下方按钮即可加入。",
529
+ "help.contact_join": "加入 Telegram 交流群",
476
530
  };
477
531
 
478
532
  export default zhCN;
@@ -123,7 +123,21 @@ const zhTW: Record<string, string> = {
123
123
  "official_usage.no_result": "尚未取得額度資料",
124
124
  "official_usage.no_result_desc": "填寫官方用量介面與 API Key,儲存後會立即測試查詢並顯示額度。",
125
125
  "app.subtitle": "設定管理器",
126
- "app.version": "pi-switch v0.1.0",
126
+ "app.version": "pi-switch v0.7.0",
127
+ "changelog.button": "更新日誌",
128
+ "changelog.title": "版本更新說明",
129
+ "changelog.0_7_0_1": "新增右下角浮動「使用說明」按鈕,彈窗含專案總覽與各板塊使用指引。",
130
+ "changelog.0_7_0_2": "新增「加入 Telegram 交流群」入口(側邊欄 + 使用說明彈窗)。",
131
+ "changelog.0_7_0_3": "新增本「版本更新說明」彈窗。",
132
+ "changelog.0_6_2_1": "子代理:支援在面板裡直接編輯自訂代理的模型和思考級別。",
133
+ "changelog.0_6_1_1": "修復:一鍵優化改用非同步進程,不再導致開發伺服器卡頓和頁面自動刷新。",
134
+ "changelog.0_6_0_1": "記憶:新增「一鍵優化記憶」,一次整合三個記憶檔。",
135
+ "changelog.0_6_0_2": "記憶:新增自動寫入記憶所用模型的設定,及容量上限與超限策略設置。",
136
+ "changelog.0_6_0_3": "記憶:新增各記憶檔的容量進度條與優化即時進度。",
137
+ "changelog.0_6_0_4": "設定:移除 GitHub Copilot 設定板塊。",
138
+ "changelog.0_5_0_1": "新增「模型測速」模組,替代原「官方用量查詢」。",
139
+ "changelog.0_5_0_2": "測速支援一鍵獲取模型(獨立本地儲存)與慢速模式防限流。",
140
+ "changelog.0_5_0_3": "提供商頁隱藏內建供應商,精簡介面。",
127
141
 
128
142
  // Subagents
129
143
  "subagents.summary": "{0} 個代理 · {1} 個流水線",
@@ -472,6 +486,46 @@ const zhTW: Record<string, string> = {
472
486
  "language.zh-CN": "简体中文",
473
487
  "language.zh-TW": "繁體中文",
474
488
  "language.ja": "日本語",
489
+ "help.button": "使用說明",
490
+ "help.title": "使用說明",
491
+ "help.overview_title": "關於本專案",
492
+ "help.overview_desc": "pi-web-switch 是 pi 編碼助手的可視化配置面板:查看會話、管理長期記憶、配置提供商與模型、編輯子代理、測速模型,並調整全域設定。所有改動直接寫入 ~/.pi/agent 下的配置檔,即時生效。",
493
+ "help.modules_title": "各板塊說明",
494
+ "help.dashboard_title": "01 儀表板",
495
+ "help.dashboard_desc": "總覽用量與近期活動。",
496
+ "help.dashboard_s1": "查看 token 用量、成本和各模型統計。",
497
+ "help.dashboard_s2": "點擊「立即刷新」重新掃描會話資料。",
498
+ "help.sessions_title": "02 會話",
499
+ "help.sessions_desc": "瀏覽、預覽和管理歷史會話。",
500
+ "help.sessions_s1": "按專案分組查看會話,可展開/摺疊。",
501
+ "help.sessions_s2": "刪除會話會移入回收站,可還原或永久刪除。",
502
+ "help.sessions_s3": "回收站中可勾選批次永久刪除。",
503
+ "help.memory_title": "03 記憶",
504
+ "help.memory_desc": "查看和優化 pi-hermes-memory 長期記憶。",
505
+ "help.memory_s1": "進度條顯示三個記憶檔的容量佔用(按字元)。",
506
+ "help.memory_s2": "「一鍵優化記憶」呼叫模型合併重複、清理過時條目。",
507
+ "help.memory_s3": "「記憶模型設定」設定自動寫入所用模型、思考級別和容量上限。",
508
+ "help.providers_title": "04 提供商與模型",
509
+ "help.providers_desc": "管理 API 提供商和它們的模型。",
510
+ "help.providers_s1": "新增自訂提供商,填寫 baseUrl 和 API Key。",
511
+ "help.providers_s2": "用「獲取模型列表」拉取並搜尋可用模型,勾選啟用。",
512
+ "help.providers_s3": "可調整每個模型的 maxTokens 等參數。",
513
+ "help.subagents_title": "05 子代理",
514
+ "help.subagents_desc": "查看和編輯子代理、鏈和執行歷史。",
515
+ "help.subagents_s1": "在「代理」選中自訂代理,點「編輯」可改模型和思考級別。",
516
+ "help.subagents_s2": "模型輸入框帶全部已配置模型的下拉候選。",
517
+ "help.settings_title": "06 設定",
518
+ "help.settings_desc": "外觀、模型預設值和進階選項。",
519
+ "help.settings_s1": "切換主題、字型大小、介面縮放和語言。",
520
+ "help.settings_s2": "管理 pi 套件並檢查更新。",
521
+ "help.speedtest_title": "07 模型測速",
522
+ "help.speedtest_desc": "批次測試自訂提供商模型的可用性與延遲。",
523
+ "help.speedtest_s1": "選擇提供商,用「獲取模型」拉取待測模型(獨立儲存)。",
524
+ "help.speedtest_s2": "執行測速,查看成功率、平均延遲和延遲區間。",
525
+ "help.speedtest_s3": "遇限流可開「慢速模式」降低 429。",
526
+ "help.contact_title": "遇到問題?",
527
+ "help.contact_desc": "有任何疑問、建議或 bug 回報,歡迎加入 Telegram 交流群,點擊下方按鈕即可加入。",
528
+ "help.contact_join": "加入 Telegram 交流群",
475
529
  };
476
530
 
477
531
  export default zhTW;