@raingor/pi-web-switch 0.4.0 → 0.4.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/package.json +5 -1
- package/public/sw.js +28 -5
- package/server/agent-session-manager.ts +827 -0
- package/server/chat-api-plugin.ts +488 -0
- package/server/pi-reader.ts +242 -1
- package/src/App.tsx +2 -0
- package/src/components/chat/ChatInput.tsx +863 -0
- package/src/components/chat/ChatPage.tsx +617 -0
- package/src/components/chat/ChatWindow.tsx +338 -0
- package/src/components/chat/MessageView.tsx +595 -0
- package/src/components/dashboard/DashboardPage.tsx +45 -5
- package/src/components/layout/AppShell.tsx +12 -5
- package/src/components/layout/Sidebar.tsx +2 -0
- package/src/components/providers/ProvidersModelsPage.tsx +28 -10
- package/src/components/sessions/SessionsPage.tsx +466 -148
- package/src/hooks/useAgentSession.ts +1104 -0
- package/src/index.css +24 -0
- package/src/lib/translations/en.ts +69 -0
- package/src/lib/translations/ja.ts +69 -0
- package/src/lib/translations/zh-CN.ts +69 -0
- package/src/lib/translations/zh-TW.ts +69 -0
- package/src/main.tsx +4 -2
- package/src/store/config-store.ts +41 -0
- package/src/types/chat.ts +217 -0
- package/vite.config.ts +141 -0
package/src/index.css
CHANGED
|
@@ -28,6 +28,18 @@
|
|
|
28
28
|
--sidebar-hover-text: #374151;
|
|
29
29
|
--scrollbar-thumb: #d1d5db;
|
|
30
30
|
--scrollbar-thumb-hover: #9ca3af;
|
|
31
|
+
|
|
32
|
+
/* Chat component variables */
|
|
33
|
+
--bg: #ffffff;
|
|
34
|
+
--bg-panel: #f9fafb;
|
|
35
|
+
--bg-hover: #f3f4f6;
|
|
36
|
+
--bg-selected: #eff6ff;
|
|
37
|
+
--border: #e5e7eb;
|
|
38
|
+
--text: #111827;
|
|
39
|
+
--text-muted: #6b7280;
|
|
40
|
+
--text-dim: #9ca3af;
|
|
41
|
+
--accent: #2563eb;
|
|
42
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
31
43
|
}
|
|
32
44
|
|
|
33
45
|
.dark {
|
|
@@ -55,6 +67,18 @@
|
|
|
55
67
|
--sidebar-hover-text: #e5e7eb;
|
|
56
68
|
--scrollbar-thumb: #4b5563;
|
|
57
69
|
--scrollbar-thumb-hover: #6b7280;
|
|
70
|
+
|
|
71
|
+
/* Chat component variables */
|
|
72
|
+
--bg: #030712;
|
|
73
|
+
--bg-panel: rgba(17, 24, 39, 0.5);
|
|
74
|
+
--bg-hover: rgba(31, 41, 55, 0.5);
|
|
75
|
+
--bg-selected: rgba(37, 99, 235, 0.1);
|
|
76
|
+
--border: #1f2937;
|
|
77
|
+
--text: #f3f4f6;
|
|
78
|
+
--text-muted: #9ca3af;
|
|
79
|
+
--text-dim: #6b7280;
|
|
80
|
+
--accent: #2563eb;
|
|
81
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
58
82
|
}
|
|
59
83
|
|
|
60
84
|
:root {
|
|
@@ -64,6 +64,7 @@ const en: Record<string, string> = {
|
|
|
64
64
|
|
|
65
65
|
"nav.sessions": "Sessions",
|
|
66
66
|
"nav.memory": "Memory",
|
|
67
|
+
"nav.chat": "Chat",
|
|
67
68
|
"nav.settings": "Settings",
|
|
68
69
|
"app.subtitle": "Configuration Manager",
|
|
69
70
|
"app.version": "pi-switch v0.1.0",
|
|
@@ -101,6 +102,14 @@ const en: Record<string, string> = {
|
|
|
101
102
|
|
|
102
103
|
// Dashboard
|
|
103
104
|
"dashboard.title": "Usage Statistics",
|
|
105
|
+
"dashboard.source_pi": "Pi",
|
|
106
|
+
"dashboard.source_cindy_pi": "Cindy-Pi",
|
|
107
|
+
"dashboard.source_claude": "Claude",
|
|
108
|
+
"dashboard.source_codex": "Codex",
|
|
109
|
+
"dashboard.source_all": "All",
|
|
110
|
+
"dashboard.source_opencode": "OpenCode",
|
|
111
|
+
"dashboard.source_gemini": "Gemini",
|
|
112
|
+
"dashboard.source_grok": "Grok",
|
|
104
113
|
"dashboard.requests_count": "{0} requests · {1} total cost",
|
|
105
114
|
"dashboard.range.today": "Today",
|
|
106
115
|
"dashboard.range.7d": "7 Days",
|
|
@@ -213,6 +222,7 @@ const en: Record<string, string> = {
|
|
|
213
222
|
"sessions.summary": "{0} sessions across {1} projects",
|
|
214
223
|
"sessions.filter_placeholder": "Search projects or sessions...",
|
|
215
224
|
"sessions.no_sessions": "No sessions found",
|
|
225
|
+
"sessions.no_search_results": "No sessions match your search",
|
|
216
226
|
"sessions.last_active": "Last active {0}",
|
|
217
227
|
"sessions.sessions_count": "{0} sessions",
|
|
218
228
|
"sessions.messages": "{0} messages",
|
|
@@ -227,6 +237,8 @@ const en: Record<string, string> = {
|
|
|
227
237
|
"sessions.delete_error": "Error deleting session",
|
|
228
238
|
"sessions.load_failed": "Failed to load sessions",
|
|
229
239
|
"sessions.refresh": "Refresh",
|
|
240
|
+
"sessions.expand_all": "Expand All",
|
|
241
|
+
"sessions.collapse_all": "Collapse All",
|
|
230
242
|
"sessions.more_count": "{0} more",
|
|
231
243
|
"sessions.tab_sessions": "Sessions",
|
|
232
244
|
"sessions.tab_trash": "Trash",
|
|
@@ -338,6 +350,63 @@ const en: Record<string, string> = {
|
|
|
338
350
|
"loading.error_title": "Failed to Load Configuration",
|
|
339
351
|
"loading.retry": "Retry",
|
|
340
352
|
|
|
353
|
+
// Chat
|
|
354
|
+
"chat.sessions": "Sessions",
|
|
355
|
+
"chat.new_session": "New session",
|
|
356
|
+
"chat.loading": "Loading...",
|
|
357
|
+
"chat.no_sessions": "No sessions yet. Click + to start a new chat.",
|
|
358
|
+
"chat.welcome_title": "Welcome to Pi Chat",
|
|
359
|
+
"chat.welcome_desc": "Select a session from the sidebar, or click + to start a new chat session in a project directory.",
|
|
360
|
+
"chat.select_cwd": "Select Working Directory",
|
|
361
|
+
"chat.cancel": "Cancel",
|
|
362
|
+
"chat.start_chat": "Start Chat",
|
|
363
|
+
"chat.delete_confirm": "Delete this session? This cannot be undone.",
|
|
364
|
+
"chat.delete": "Delete",
|
|
365
|
+
"chat.loading_session": "Loading session...",
|
|
366
|
+
"chat.thinking": "Thinking...",
|
|
367
|
+
"chat.running_tool": "Running tool...",
|
|
368
|
+
"chat.running_command": "Running command...",
|
|
369
|
+
"chat.send_message": "Send a message... (/ for commands, ! for bash)",
|
|
370
|
+
"chat.type_to_steer": "Type to steer...",
|
|
371
|
+
"chat.compacting": "Compacting context...",
|
|
372
|
+
"chat.compaction_failed": "Compaction failed: {0}",
|
|
373
|
+
"chat.retrying": "Retrying ({0}/{1}){2}",
|
|
374
|
+
"chat.steering_queued": "{0} steering, {1} follow-up queued",
|
|
375
|
+
"chat.recall": "Recall",
|
|
376
|
+
"chat.default_tools": "Default tools",
|
|
377
|
+
"chat.all_tools": "All tools",
|
|
378
|
+
"chat.no_tools": "No tools",
|
|
379
|
+
"chat.auto": "Auto",
|
|
380
|
+
"chat.no_model": "No model",
|
|
381
|
+
"chat.no_models_available": "No models available. Check your model configuration.",
|
|
382
|
+
"chat.search_models": "Search models...",
|
|
383
|
+
"chat.no_models_found": "No models found",
|
|
384
|
+
"chat.models_count": "{0} models",
|
|
385
|
+
"chat.models_filtered": "{0} of {1} models",
|
|
386
|
+
"chat.attach_image": "Attach image",
|
|
387
|
+
"chat.tool_preset": "Tool preset",
|
|
388
|
+
"chat.compact_context": "Compact context",
|
|
389
|
+
"chat.stop": "Stop",
|
|
390
|
+
"chat.send": "Send",
|
|
391
|
+
"chat.fork_from_here": "Fork from here",
|
|
392
|
+
"chat.show_less": "Show less",
|
|
393
|
+
"chat.show_more": "Show {0} more characters",
|
|
394
|
+
"chat.tool_call": "tool call",
|
|
395
|
+
"chat.thinking_collapsed": "Thinking (collapsed)",
|
|
396
|
+
"chat.thinking_label": "Thinking",
|
|
397
|
+
"chat.result": "result",
|
|
398
|
+
"chat.error_label": "(error)",
|
|
399
|
+
"chat.exit_code": "exit",
|
|
400
|
+
"chat.msg_count": "{0} msg",
|
|
401
|
+
"chat.untitled": "Untitled",
|
|
402
|
+
"chat.just_now": "just now",
|
|
403
|
+
"chat.min_ago": "{0}m ago",
|
|
404
|
+
"chat.hr_ago": "{0}h ago",
|
|
405
|
+
"chat.day_ago": "{0}d ago",
|
|
406
|
+
"chat.invalid_directory": "Invalid directory",
|
|
407
|
+
"chat.expand_all": "Expand all",
|
|
408
|
+
"chat.collapse_all": "Collapse all",
|
|
409
|
+
|
|
341
410
|
// Language Switcher
|
|
342
411
|
"language.label": "Language",
|
|
343
412
|
"language.en": "English",
|
|
@@ -62,6 +62,7 @@ const ja: Record<string, string> = {
|
|
|
62
62
|
|
|
63
63
|
"nav.sessions": "セッション",
|
|
64
64
|
"nav.memory": "メモリ",
|
|
65
|
+
"nav.chat": "チャット",
|
|
65
66
|
"nav.settings": "設定",
|
|
66
67
|
"app.subtitle": "設定マネージャー",
|
|
67
68
|
"app.version": "pi-switch v0.1.0",
|
|
@@ -98,6 +99,14 @@ const ja: Record<string, string> = {
|
|
|
98
99
|
"subagents.showing_recent": "最新 100 件を表示",
|
|
99
100
|
|
|
100
101
|
"dashboard.title": "使用統計",
|
|
102
|
+
"dashboard.source_pi": "Pi",
|
|
103
|
+
"dashboard.source_cindy_pi": "Cindy-Pi",
|
|
104
|
+
"dashboard.source_claude": "Claude",
|
|
105
|
+
"dashboard.source_codex": "Codex",
|
|
106
|
+
"dashboard.source_all": "すべて",
|
|
107
|
+
"dashboard.source_opencode": "OpenCode",
|
|
108
|
+
"dashboard.source_gemini": "Gemini",
|
|
109
|
+
"dashboard.source_grok": "Grok",
|
|
101
110
|
"dashboard.requests_count": "{0} リクエスト · 総コスト {1}",
|
|
102
111
|
"dashboard.range.today": "今日",
|
|
103
112
|
"dashboard.range.7d": "7日",
|
|
@@ -207,6 +216,7 @@ const ja: Record<string, string> = {
|
|
|
207
216
|
"sessions.summary": "合計 {0} セッション、{1} プロジェクト",
|
|
208
217
|
"sessions.filter_placeholder": "プロジェクトまたはセッションを検索...",
|
|
209
218
|
"sessions.no_sessions": "セッションが見つかりません",
|
|
219
|
+
"sessions.no_search_results": "検索条件に一致するセッションが見つかりません",
|
|
210
220
|
"sessions.last_active": "最終アクティブ {0}",
|
|
211
221
|
"sessions.sessions_count": "{0} セッション",
|
|
212
222
|
"sessions.messages": "{0} メッセージ",
|
|
@@ -221,6 +231,8 @@ const ja: Record<string, string> = {
|
|
|
221
231
|
"sessions.delete_error": "削除中にエラーが発生しました",
|
|
222
232
|
"sessions.load_failed": "セッションの読み込みに失敗しました",
|
|
223
233
|
"sessions.refresh": "更新",
|
|
234
|
+
"sessions.expand_all": "すべて展開",
|
|
235
|
+
"sessions.collapse_all": "すべて折りたたむ",
|
|
224
236
|
"sessions.more_count": "あと {0} 件",
|
|
225
237
|
"sessions.tab_sessions": "セッション",
|
|
226
238
|
"sessions.tab_trash": "ゴミ箱",
|
|
@@ -329,6 +341,63 @@ const ja: Record<string, string> = {
|
|
|
329
341
|
"loading.error_title": "設定の読み込みに失敗しました",
|
|
330
342
|
"loading.retry": "再試行",
|
|
331
343
|
|
|
344
|
+
// Chat
|
|
345
|
+
"chat.sessions": "セッション",
|
|
346
|
+
"chat.new_session": "新規セッション",
|
|
347
|
+
"chat.loading": "読み込み中...",
|
|
348
|
+
"chat.no_sessions": "セッションがありません。+ をクリックして新しいチャットを開始してください。",
|
|
349
|
+
"chat.welcome_title": "Pi Chat へようこそ",
|
|
350
|
+
"chat.welcome_desc": "サイドバーからセッションを選択するか、+ をクリックしてプロジェクトディレクトリで新しいチャットを開始します。",
|
|
351
|
+
"chat.select_cwd": "作業ディレクトリを選択",
|
|
352
|
+
"chat.cancel": "キャンセル",
|
|
353
|
+
"chat.start_chat": "チャット開始",
|
|
354
|
+
"chat.delete_confirm": "このセッションを削除しますか?この操作は元に戻せません。",
|
|
355
|
+
"chat.delete": "削除",
|
|
356
|
+
"chat.loading_session": "セッションを読み込み中...",
|
|
357
|
+
"chat.thinking": "考え中...",
|
|
358
|
+
"chat.running_tool": "ツールを実行中...",
|
|
359
|
+
"chat.running_command": "コマンドを実行中...",
|
|
360
|
+
"chat.send_message": "メッセージを送信...(/ でコマンド、! で bash)",
|
|
361
|
+
"chat.type_to_steer": "入力して誘導...",
|
|
362
|
+
"chat.compacting": "コンテキストを圧縮中...",
|
|
363
|
+
"chat.compaction_failed": "圧縮失敗:{0}",
|
|
364
|
+
"chat.retrying": "再試行中 ({0}/{1}){2}",
|
|
365
|
+
"chat.steering_queued": "{0} 件の誘導、{1} 件のフォローアップがキューにあります",
|
|
366
|
+
"chat.recall": "取り消す",
|
|
367
|
+
"chat.default_tools": "デフォルトツール",
|
|
368
|
+
"chat.all_tools": "すべてのツール",
|
|
369
|
+
"chat.no_tools": "ツールなし",
|
|
370
|
+
"chat.auto": "自動",
|
|
371
|
+
"chat.no_model": "モデルなし",
|
|
372
|
+
"chat.no_models_available": "利用可能なモデルがありません。モデル設定を確認してください。",
|
|
373
|
+
"chat.search_models": "モデルを検索...",
|
|
374
|
+
"chat.no_models_found": "モデルが見つかりません",
|
|
375
|
+
"chat.models_count": "{0} モデル",
|
|
376
|
+
"chat.models_filtered": "{0} / {1} モデル",
|
|
377
|
+
"chat.attach_image": "画像を添付",
|
|
378
|
+
"chat.tool_preset": "ツールプリセット",
|
|
379
|
+
"chat.compact_context": "コンテキストを圧縮",
|
|
380
|
+
"chat.stop": "停止",
|
|
381
|
+
"chat.send": "送信",
|
|
382
|
+
"chat.fork_from_here": "ここから分岐",
|
|
383
|
+
"chat.show_less": "折りたたむ",
|
|
384
|
+
"chat.show_more": "残り {0} 文字を表示",
|
|
385
|
+
"chat.tool_call": "ツール呼び出し",
|
|
386
|
+
"chat.thinking_collapsed": "思考(折りたたみ)",
|
|
387
|
+
"chat.thinking_label": "思考",
|
|
388
|
+
"chat.result": "結果",
|
|
389
|
+
"chat.error_label": "(エラー)",
|
|
390
|
+
"chat.exit_code": "終了コード",
|
|
391
|
+
"chat.msg_count": "{0} 件",
|
|
392
|
+
"chat.untitled": "無題",
|
|
393
|
+
"chat.just_now": "たった今",
|
|
394
|
+
"chat.min_ago": "{0} 分前",
|
|
395
|
+
"chat.hr_ago": "{0} 時間前",
|
|
396
|
+
"chat.day_ago": "{0} 日前",
|
|
397
|
+
"chat.invalid_directory": "無効なディレクトリ",
|
|
398
|
+
"chat.expand_all": "すべて展開",
|
|
399
|
+
"chat.collapse_all": "すべて折りたたむ",
|
|
400
|
+
|
|
332
401
|
"language.label": "言語",
|
|
333
402
|
"language.en": "English",
|
|
334
403
|
"language.zh-CN": "简体中文",
|
|
@@ -62,6 +62,7 @@ const zhCN: Record<string, string> = {
|
|
|
62
62
|
|
|
63
63
|
"nav.sessions": "会话",
|
|
64
64
|
"nav.memory": "记忆",
|
|
65
|
+
"nav.chat": "聊天",
|
|
65
66
|
"nav.settings": "设置",
|
|
66
67
|
"app.subtitle": "配置管理器",
|
|
67
68
|
"app.version": "pi-switch v0.1.0",
|
|
@@ -98,6 +99,14 @@ const zhCN: Record<string, string> = {
|
|
|
98
99
|
"subagents.showing_recent": "显示最近 100 条记录",
|
|
99
100
|
|
|
100
101
|
"dashboard.title": "使用统计",
|
|
102
|
+
"dashboard.source_pi": "Pi 程序",
|
|
103
|
+
"dashboard.source_cindy_pi": "Cindy-Pi",
|
|
104
|
+
"dashboard.source_claude": "Claude",
|
|
105
|
+
"dashboard.source_codex": "Codex",
|
|
106
|
+
"dashboard.source_all": "全部",
|
|
107
|
+
"dashboard.source_opencode": "OpenCode",
|
|
108
|
+
"dashboard.source_gemini": "Gemini",
|
|
109
|
+
"dashboard.source_grok": "Grok",
|
|
101
110
|
"dashboard.requests_count": "{0} 次请求 · 总成本 {1}",
|
|
102
111
|
"dashboard.range.today": "当天",
|
|
103
112
|
"dashboard.range.7d": "7天",
|
|
@@ -207,6 +216,7 @@ const zhCN: Record<string, string> = {
|
|
|
207
216
|
"sessions.summary": "共 {0} 个会话,分布在 {1} 个项目",
|
|
208
217
|
"sessions.filter_placeholder": "搜索项目或会话...",
|
|
209
218
|
"sessions.no_sessions": "未找到会话",
|
|
219
|
+
"sessions.no_search_results": "没有找到匹配的会话",
|
|
210
220
|
"sessions.last_active": "最近活跃 {0}",
|
|
211
221
|
"sessions.sessions_count": "{0} 个会话",
|
|
212
222
|
"sessions.messages": "{0} 条消息",
|
|
@@ -221,6 +231,8 @@ const zhCN: Record<string, string> = {
|
|
|
221
231
|
"sessions.delete_error": "删除时发生错误",
|
|
222
232
|
"sessions.load_failed": "加载会话失败",
|
|
223
233
|
"sessions.refresh": "刷新",
|
|
234
|
+
"sessions.expand_all": "全部展开",
|
|
235
|
+
"sessions.collapse_all": "全部折叠",
|
|
224
236
|
"sessions.more_count": "还有 {0} 条",
|
|
225
237
|
"sessions.tab_sessions": "会话",
|
|
226
238
|
"sessions.tab_trash": "回收站",
|
|
@@ -329,6 +341,63 @@ const zhCN: Record<string, string> = {
|
|
|
329
341
|
"loading.error_title": "加载配置失败",
|
|
330
342
|
"loading.retry": "重试",
|
|
331
343
|
|
|
344
|
+
// Chat
|
|
345
|
+
"chat.sessions": "会话",
|
|
346
|
+
"chat.new_session": "新建会话",
|
|
347
|
+
"chat.loading": "加载中...",
|
|
348
|
+
"chat.no_sessions": "暂无会话。点击 + 开始新对话。",
|
|
349
|
+
"chat.welcome_title": "欢迎使用 Pi Chat",
|
|
350
|
+
"chat.welcome_desc": "从侧栏选择一个会话,或点击 + 在项目目录中开始新的对话。",
|
|
351
|
+
"chat.select_cwd": "选择工作目录",
|
|
352
|
+
"chat.cancel": "取消",
|
|
353
|
+
"chat.start_chat": "开始对话",
|
|
354
|
+
"chat.delete_confirm": "确定删除此会话?此操作无法撤销。",
|
|
355
|
+
"chat.delete": "删除",
|
|
356
|
+
"chat.loading_session": "正在加载会话...",
|
|
357
|
+
"chat.thinking": "思考中...",
|
|
358
|
+
"chat.running_tool": "正在运行工具...",
|
|
359
|
+
"chat.running_command": "正在执行命令...",
|
|
360
|
+
"chat.send_message": "发送消息...(/ 选择命令,! 执行命令)",
|
|
361
|
+
"chat.type_to_steer": "输入以引导...",
|
|
362
|
+
"chat.compacting": "正在压缩上下文...",
|
|
363
|
+
"chat.compaction_failed": "压缩失败:{0}",
|
|
364
|
+
"chat.retrying": "重试中 ({0}/{1}){2}",
|
|
365
|
+
"chat.steering_queued": "{0} 条引导,{1} 条跟进已排队",
|
|
366
|
+
"chat.recall": "撤回",
|
|
367
|
+
"chat.default_tools": "默认工具",
|
|
368
|
+
"chat.all_tools": "全部工具",
|
|
369
|
+
"chat.no_tools": "无工具",
|
|
370
|
+
"chat.auto": "自动",
|
|
371
|
+
"chat.no_model": "无模型",
|
|
372
|
+
"chat.no_models_available": "暂无可用模型,请检查模型配置。",
|
|
373
|
+
"chat.search_models": "搜索模型...",
|
|
374
|
+
"chat.no_models_found": "未找到模型",
|
|
375
|
+
"chat.models_count": "{0} 个模型",
|
|
376
|
+
"chat.models_filtered": "{0} / {1} 个模型",
|
|
377
|
+
"chat.attach_image": "附加图片",
|
|
378
|
+
"chat.tool_preset": "工具预设",
|
|
379
|
+
"chat.compact_context": "压缩上下文",
|
|
380
|
+
"chat.stop": "停止",
|
|
381
|
+
"chat.send": "发送",
|
|
382
|
+
"chat.fork_from_here": "从此处分叉",
|
|
383
|
+
"chat.show_less": "收起",
|
|
384
|
+
"chat.show_more": "展开剩余 {0} 个字符",
|
|
385
|
+
"chat.tool_call": "工具调用",
|
|
386
|
+
"chat.thinking_collapsed": "思考(已折叠)",
|
|
387
|
+
"chat.thinking_label": "思考",
|
|
388
|
+
"chat.result": "结果",
|
|
389
|
+
"chat.error_label": "(错误)",
|
|
390
|
+
"chat.exit_code": "退出码",
|
|
391
|
+
"chat.msg_count": "{0} 条消息",
|
|
392
|
+
"chat.untitled": "未命名",
|
|
393
|
+
"chat.just_now": "刚刚",
|
|
394
|
+
"chat.min_ago": "{0} 分钟前",
|
|
395
|
+
"chat.hr_ago": "{0} 小时前",
|
|
396
|
+
"chat.day_ago": "{0} 天前",
|
|
397
|
+
"chat.invalid_directory": "无效目录",
|
|
398
|
+
"chat.expand_all": "全部展开",
|
|
399
|
+
"chat.collapse_all": "全部折叠",
|
|
400
|
+
|
|
332
401
|
"language.label": "语言",
|
|
333
402
|
"language.en": "English",
|
|
334
403
|
"language.zh-CN": "简体中文",
|
|
@@ -62,6 +62,7 @@ const zhTW: Record<string, string> = {
|
|
|
62
62
|
|
|
63
63
|
"nav.sessions": "會話",
|
|
64
64
|
"nav.memory": "記憶",
|
|
65
|
+
"nav.chat": "聊天",
|
|
65
66
|
"nav.settings": "設定",
|
|
66
67
|
"app.subtitle": "設定管理器",
|
|
67
68
|
"app.version": "pi-switch v0.1.0",
|
|
@@ -98,6 +99,14 @@ const zhTW: Record<string, string> = {
|
|
|
98
99
|
"subagents.showing_recent": "顯示最近 100 條記錄",
|
|
99
100
|
|
|
100
101
|
"dashboard.title": "使用統計",
|
|
102
|
+
"dashboard.source_pi": "Pi 程式",
|
|
103
|
+
"dashboard.source_cindy_pi": "Cindy-Pi",
|
|
104
|
+
"dashboard.source_claude": "Claude",
|
|
105
|
+
"dashboard.source_codex": "Codex",
|
|
106
|
+
"dashboard.source_all": "全部",
|
|
107
|
+
"dashboard.source_opencode": "OpenCode",
|
|
108
|
+
"dashboard.source_gemini": "Gemini",
|
|
109
|
+
"dashboard.source_grok": "Grok",
|
|
101
110
|
"dashboard.requests_count": "{0} 次請求 · 總成本 {1}",
|
|
102
111
|
"dashboard.range.today": "當天",
|
|
103
112
|
"dashboard.range.7d": "7天",
|
|
@@ -207,6 +216,7 @@ const zhTW: Record<string, string> = {
|
|
|
207
216
|
"sessions.summary": "共 {0} 個會話,分佈在 {1} 個專案",
|
|
208
217
|
"sessions.filter_placeholder": "搜尋專案或會話...",
|
|
209
218
|
"sessions.no_sessions": "未找到會話",
|
|
219
|
+
"sessions.no_search_results": "沒有找到符合的會話",
|
|
210
220
|
"sessions.last_active": "最近活躍 {0}",
|
|
211
221
|
"sessions.sessions_count": "{0} 個會話",
|
|
212
222
|
"sessions.messages": "{0} 條訊息",
|
|
@@ -221,6 +231,8 @@ const zhTW: Record<string, string> = {
|
|
|
221
231
|
"sessions.delete_error": "刪除時發生錯誤",
|
|
222
232
|
"sessions.load_failed": "載入會話失敗",
|
|
223
233
|
"sessions.refresh": "重新整理",
|
|
234
|
+
"sessions.expand_all": "全部展開",
|
|
235
|
+
"sessions.collapse_all": "全部收合",
|
|
224
236
|
"sessions.more_count": "還有 {0} 條",
|
|
225
237
|
"sessions.tab_sessions": "會話",
|
|
226
238
|
"sessions.tab_trash": "回收筒",
|
|
@@ -329,6 +341,63 @@ const zhTW: Record<string, string> = {
|
|
|
329
341
|
"loading.error_title": "載入設定失敗",
|
|
330
342
|
"loading.retry": "重試",
|
|
331
343
|
|
|
344
|
+
// Chat
|
|
345
|
+
"chat.sessions": "會話",
|
|
346
|
+
"chat.new_session": "新建會話",
|
|
347
|
+
"chat.loading": "載入中...",
|
|
348
|
+
"chat.no_sessions": "尚無會話。點擊 + 開始新對話。",
|
|
349
|
+
"chat.welcome_title": "歡迎使用 Pi Chat",
|
|
350
|
+
"chat.welcome_desc": "從側欄選擇一個會話,或點擊 + 在專案目錄中開始新的對話。",
|
|
351
|
+
"chat.select_cwd": "選擇工作目錄",
|
|
352
|
+
"chat.cancel": "取消",
|
|
353
|
+
"chat.start_chat": "開始對話",
|
|
354
|
+
"chat.delete_confirm": "確定刪除此會話?此操作無法復原。",
|
|
355
|
+
"chat.delete": "刪除",
|
|
356
|
+
"chat.loading_session": "正在載入會話...",
|
|
357
|
+
"chat.thinking": "思考中...",
|
|
358
|
+
"chat.running_tool": "正在執行工具...",
|
|
359
|
+
"chat.running_command": "正在執行指令...",
|
|
360
|
+
"chat.send_message": "發送訊息…(/ 選擇指令,! 執行指令)",
|
|
361
|
+
"chat.type_to_steer": "輸入以引導...",
|
|
362
|
+
"chat.compacting": "正在壓縮上下文...",
|
|
363
|
+
"chat.compaction_failed": "壓縮失敗:{0}",
|
|
364
|
+
"chat.retrying": "重試中 ({0}/{1}){2}",
|
|
365
|
+
"chat.steering_queued": "{0} 條引導,{1} 條跟進已排隊",
|
|
366
|
+
"chat.recall": "撤回",
|
|
367
|
+
"chat.default_tools": "預設工具",
|
|
368
|
+
"chat.all_tools": "全部工具",
|
|
369
|
+
"chat.no_tools": "無工具",
|
|
370
|
+
"chat.auto": "自動",
|
|
371
|
+
"chat.no_model": "無模型",
|
|
372
|
+
"chat.no_models_available": "暫無可用模型,請檢查模型配置。",
|
|
373
|
+
"chat.search_models": "搜尋模型...",
|
|
374
|
+
"chat.no_models_found": "未找到模型",
|
|
375
|
+
"chat.models_count": "{0} 個模型",
|
|
376
|
+
"chat.models_filtered": "{0} / {1} 個模型",
|
|
377
|
+
"chat.attach_image": "附加圖片",
|
|
378
|
+
"chat.tool_preset": "工具預設",
|
|
379
|
+
"chat.compact_context": "壓縮上下文",
|
|
380
|
+
"chat.stop": "停止",
|
|
381
|
+
"chat.send": "發送",
|
|
382
|
+
"chat.fork_from_here": "從此分叉",
|
|
383
|
+
"chat.show_less": "收起",
|
|
384
|
+
"chat.show_more": "展開剩餘 {0} 個字元",
|
|
385
|
+
"chat.tool_call": "工具呼叫",
|
|
386
|
+
"chat.thinking_collapsed": "思考(已摺疊)",
|
|
387
|
+
"chat.thinking_label": "思考",
|
|
388
|
+
"chat.result": "結果",
|
|
389
|
+
"chat.error_label": "(錯誤)",
|
|
390
|
+
"chat.exit_code": "退出碼",
|
|
391
|
+
"chat.msg_count": "{0} 條訊息",
|
|
392
|
+
"chat.untitled": "未命名",
|
|
393
|
+
"chat.just_now": "剛剛",
|
|
394
|
+
"chat.min_ago": "{0} 分鐘前",
|
|
395
|
+
"chat.hr_ago": "{0} 小時前",
|
|
396
|
+
"chat.day_ago": "{0} 天前",
|
|
397
|
+
"chat.invalid_directory": "無效目錄",
|
|
398
|
+
"chat.expand_all": "全部展開",
|
|
399
|
+
"chat.collapse_all": "全部摺疊",
|
|
400
|
+
|
|
332
401
|
"language.label": "語言",
|
|
333
402
|
"language.en": "English",
|
|
334
403
|
"language.zh-CN": "简体中文",
|
package/src/main.tsx
CHANGED
|
@@ -123,8 +123,10 @@ createRoot(document.getElementById("root")!).render(
|
|
|
123
123
|
</StrictMode>
|
|
124
124
|
);
|
|
125
125
|
|
|
126
|
-
// ─── PWA: register service worker
|
|
127
|
-
|
|
126
|
+
// ─── PWA: register service worker (production only — dev must not
|
|
127
|
+
// cache HTML pages, or SPA routes like /providers can return stale HTML
|
|
128
|
+
// to API fetches and break JSON parsing) ─────────────────────
|
|
129
|
+
if ("serviceWorker" in navigator && import.meta.env.PROD) {
|
|
128
130
|
window.addEventListener("load", () => {
|
|
129
131
|
navigator.serviceWorker.register("/sw.js").catch((err) => {
|
|
130
132
|
console.warn("SW registration failed:", err);
|
|
@@ -180,6 +180,7 @@ interface ConfigState {
|
|
|
180
180
|
// Custom provider CRUD
|
|
181
181
|
addCustomProvider: (id: string, cfg: CustomProviderConfig) => Promise<boolean>;
|
|
182
182
|
updateCustomProvider: (id: string, cfg: Partial<CustomProviderConfig>) => Promise<boolean>;
|
|
183
|
+
renameCustomProvider: (oldId: string, newId: string, cfg?: Partial<CustomProviderConfig>) => Promise<boolean>;
|
|
183
184
|
removeCustomProvider: (id: string) => Promise<boolean>;
|
|
184
185
|
|
|
185
186
|
// Import/Export (to localStorage for backup, writes back to pi files)
|
|
@@ -464,6 +465,46 @@ export const useConfigStore = create<ConfigState>((set, get) => ({
|
|
|
464
465
|
return ok;
|
|
465
466
|
},
|
|
466
467
|
|
|
468
|
+
renameCustomProvider: async (oldId, newId, cfg) => {
|
|
469
|
+
const { modelsJson, settings } = get();
|
|
470
|
+
if (!modelsJson || oldId === newId) return false;
|
|
471
|
+
const existing = modelsJson.providers[oldId];
|
|
472
|
+
if (!existing || modelsJson.providers[newId]) return false;
|
|
473
|
+
// Re-key in place, preserving provider order in models.json
|
|
474
|
+
const newProviders: PiModelsJson["providers"] = {};
|
|
475
|
+
for (const [k, v] of Object.entries(modelsJson.providers)) {
|
|
476
|
+
newProviders[k === oldId ? newId : k] = k === oldId ? { ...existing, ...cfg } : v;
|
|
477
|
+
}
|
|
478
|
+
const updated = { providers: newProviders };
|
|
479
|
+
const ok = await apiPost("/models", updated);
|
|
480
|
+
if (!ok) return false;
|
|
481
|
+
set({ modelsJson: updated });
|
|
482
|
+
// Rewrite provider references in settings (defaultProvider, defaultModel,
|
|
483
|
+
// enabledModels entries are "providerId/modelId" strings)
|
|
484
|
+
if (settings) {
|
|
485
|
+
const prefix = `${oldId}/`;
|
|
486
|
+
const patch: Partial<PiSettings> = {};
|
|
487
|
+
if (settings.defaultProvider === oldId) patch.defaultProvider = newId;
|
|
488
|
+
if (settings.defaultModel?.startsWith(prefix))
|
|
489
|
+
patch.defaultModel = `${newId}/${settings.defaultModel.slice(prefix.length)}`;
|
|
490
|
+
if (settings.enabledModels?.some((r) => r.startsWith(prefix)))
|
|
491
|
+
patch.enabledModels = settings.enabledModels.map((r) =>
|
|
492
|
+
r.startsWith(prefix) ? `${newId}/${r.slice(prefix.length)}` : r
|
|
493
|
+
);
|
|
494
|
+
if (Object.keys(patch).length > 0) {
|
|
495
|
+
const updatedSettings = { ...settings, ...patch };
|
|
496
|
+
if (await apiPost("/settings", updatedSettings)) set({ settings: updatedSettings });
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
const { auth, builtinProviders } = get();
|
|
500
|
+
const newAllProviders = mergeProviders(builtinProviders, auth ?? {}, updated);
|
|
501
|
+
const newAllModels = newAllProviders.flatMap((p) =>
|
|
502
|
+
p.models.map((m) => ({ ...m, providerId: p.id, providerName: p.name }))
|
|
503
|
+
);
|
|
504
|
+
set({ allProviders: newAllProviders, allModels: newAllModels });
|
|
505
|
+
return true;
|
|
506
|
+
},
|
|
507
|
+
|
|
467
508
|
removeCustomProvider: async (id) => {
|
|
468
509
|
const { modelsJson } = get();
|
|
469
510
|
if (!modelsJson) return false;
|