@lobehub/lobehub 2.0.0-next.252 → 2.0.0-next.254
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/CHANGELOG.md +58 -0
- package/apps/desktop/build/entitlements.mac.plist +9 -0
- package/apps/desktop/resources/locales/zh-CN/dialog.json +5 -1
- package/apps/desktop/resources/locales/zh-CN/menu.json +7 -0
- package/apps/desktop/src/main/controllers/SystemCtr.ts +186 -94
- package/apps/desktop/src/main/controllers/__tests__/SystemCtr.test.ts +200 -31
- package/apps/desktop/src/main/core/browser/Browser.ts +9 -0
- package/apps/desktop/src/main/locales/default/dialog.ts +7 -2
- package/apps/desktop/src/main/locales/default/menu.ts +7 -0
- package/apps/desktop/src/main/menus/impls/macOS.ts +44 -1
- package/apps/desktop/src/main/utils/fullDiskAccess.ts +121 -0
- package/changelog/v1.json +14 -0
- package/locales/ar/discover.json +3 -0
- package/locales/ar/file.json +2 -0
- package/locales/ar/models.json +38 -10
- package/locales/ar/providers.json +0 -1
- package/locales/ar/setting.json +42 -0
- package/locales/bg-BG/discover.json +3 -0
- package/locales/bg-BG/file.json +2 -0
- package/locales/bg-BG/models.json +36 -7
- package/locales/bg-BG/providers.json +0 -1
- package/locales/bg-BG/setting.json +43 -1
- package/locales/de-DE/discover.json +3 -0
- package/locales/de-DE/file.json +2 -0
- package/locales/de-DE/models.json +45 -10
- package/locales/de-DE/providers.json +0 -1
- package/locales/de-DE/setting.json +43 -1
- package/locales/en-US/discover.json +3 -0
- package/locales/en-US/models.json +10 -10
- package/locales/en-US/providers.json +0 -1
- package/locales/en-US/setting.json +43 -1
- package/locales/es-ES/discover.json +3 -0
- package/locales/es-ES/file.json +2 -0
- package/locales/es-ES/models.json +49 -10
- package/locales/es-ES/providers.json +0 -1
- package/locales/es-ES/setting.json +43 -1
- package/locales/fa-IR/discover.json +3 -0
- package/locales/fa-IR/file.json +2 -0
- package/locales/fa-IR/models.json +39 -10
- package/locales/fa-IR/providers.json +0 -1
- package/locales/fa-IR/setting.json +43 -1
- package/locales/fr-FR/discover.json +3 -0
- package/locales/fr-FR/file.json +2 -0
- package/locales/fr-FR/models.json +36 -7
- package/locales/fr-FR/providers.json +0 -1
- package/locales/fr-FR/setting.json +42 -0
- package/locales/it-IT/discover.json +3 -0
- package/locales/it-IT/file.json +2 -0
- package/locales/it-IT/models.json +45 -10
- package/locales/it-IT/providers.json +0 -1
- package/locales/it-IT/setting.json +42 -0
- package/locales/ja-JP/discover.json +3 -0
- package/locales/ja-JP/file.json +2 -0
- package/locales/ja-JP/models.json +42 -7
- package/locales/ja-JP/providers.json +0 -1
- package/locales/ja-JP/setting.json +42 -0
- package/locales/ko-KR/discover.json +3 -0
- package/locales/ko-KR/file.json +2 -0
- package/locales/ko-KR/models.json +48 -7
- package/locales/ko-KR/providers.json +0 -1
- package/locales/ko-KR/setting.json +42 -0
- package/locales/nl-NL/discover.json +3 -0
- package/locales/nl-NL/file.json +2 -0
- package/locales/nl-NL/models.json +4 -6
- package/locales/nl-NL/providers.json +0 -1
- package/locales/nl-NL/setting.json +42 -0
- package/locales/pl-PL/discover.json +3 -0
- package/locales/pl-PL/file.json +2 -0
- package/locales/pl-PL/models.json +36 -7
- package/locales/pl-PL/providers.json +0 -1
- package/locales/pl-PL/setting.json +43 -1
- package/locales/pt-BR/discover.json +3 -0
- package/locales/pt-BR/file.json +2 -0
- package/locales/pt-BR/models.json +47 -6
- package/locales/pt-BR/providers.json +0 -1
- package/locales/pt-BR/setting.json +42 -0
- package/locales/ru-RU/discover.json +3 -0
- package/locales/ru-RU/file.json +2 -0
- package/locales/ru-RU/models.json +36 -7
- package/locales/ru-RU/providers.json +0 -1
- package/locales/ru-RU/setting.json +42 -0
- package/locales/tr-TR/discover.json +3 -0
- package/locales/tr-TR/file.json +2 -0
- package/locales/tr-TR/models.json +36 -5
- package/locales/tr-TR/providers.json +0 -1
- package/locales/tr-TR/setting.json +43 -1
- package/locales/vi-VN/discover.json +3 -0
- package/locales/vi-VN/file.json +2 -0
- package/locales/vi-VN/models.json +5 -5
- package/locales/vi-VN/providers.json +0 -1
- package/locales/vi-VN/setting.json +42 -0
- package/locales/zh-CN/discover.json +3 -3
- package/locales/zh-CN/models.json +38 -9
- package/locales/zh-CN/providers.json +0 -1
- package/locales/zh-CN/setting.json +42 -0
- package/locales/zh-TW/discover.json +3 -0
- package/locales/zh-TW/file.json +2 -0
- package/locales/zh-TW/models.json +54 -10
- package/locales/zh-TW/providers.json +0 -1
- package/locales/zh-TW/setting.json +42 -0
- package/package.json +1 -1
- package/packages/electron-client-ipc/src/events/system.ts +1 -0
- package/src/app/[variants]/(desktop)/desktop-onboarding/features/PermissionsStep.tsx +16 -30
- package/src/app/[variants]/(desktop)/desktop-onboarding/index.tsx +19 -9
- package/src/app/[variants]/(desktop)/desktop-onboarding/storage.ts +49 -0
- package/src/features/ChatInput/ActionBar/Params/Controls.tsx +7 -6
- package/apps/desktop/src/main/controllers/scripts/full-disk-access.applescript +0 -85
package/locales/zh-TW/file.json
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"empty": "暫無已上傳文件/文件夾",
|
|
19
19
|
"header.actions.builtInBlockList.filtered": "已過濾 {{ignored}} 個檔案(共 {{total}} 個檔案)",
|
|
20
20
|
"header.actions.connect": "連接...",
|
|
21
|
+
"header.actions.createFolderError": "無法建立資料夾",
|
|
22
|
+
"header.actions.creatingFolder": "正在建立資料夾...",
|
|
21
23
|
"header.actions.gitignore.apply": "套用規則",
|
|
22
24
|
"header.actions.gitignore.cancel": "忽略規則",
|
|
23
25
|
"header.actions.gitignore.content": "偵測到 .gitignore 檔案(共 {{count}} 個檔案),是否套用忽略規則?",
|
|
@@ -271,20 +271,20 @@
|
|
|
271
271
|
"chatgpt-4o-latest.description": "ChatGPT-4o 是一款即時更新的動態模型,結合強大的理解與生成能力,適用於客服、教育與技術支援等大規模應用場景。",
|
|
272
272
|
"claude-2.0.description": "Claude 2 提供企業級關鍵改進,包括領先的 20 萬 token 上下文、降低幻覺、系統提示與新測試功能:工具調用。",
|
|
273
273
|
"claude-2.1.description": "Claude 2 提供企業級關鍵改進,包括領先的 20 萬 token 上下文、降低幻覺、系統提示與新測試功能:工具調用。",
|
|
274
|
-
"claude-3-5-haiku-20241022.description": "Claude 3.5 Haiku 是 Anthropic
|
|
274
|
+
"claude-3-5-haiku-20241022.description": "Claude 3.5 Haiku 是 Anthropic 推出的次世代最快模型。相較於 Claude 3 Haiku,其在多項技能上皆有提升,並在多項智能基準測試中超越先前最大模型 Claude 3 Opus。",
|
|
275
275
|
"claude-3-5-haiku-latest.description": "Claude 3.5 Haiku 提供快速回應,適用於輕量任務。",
|
|
276
|
-
"claude-3-7-sonnet-20250219.description": "Claude
|
|
276
|
+
"claude-3-7-sonnet-20250219.description": "Claude 3.7 Sonnet 是 Anthropic 最具智慧的模型,也是市場上首個混合推理模型。它能夠即時回應,或進行可視化的逐步推理。Sonnet 尤其擅長程式設計、資料科學、視覺處理與智能體任務。",
|
|
277
277
|
"claude-3-7-sonnet-latest.description": "Claude 3.7 Sonnet 是 Anthropic 最新且最強大的模型,適用於高度複雜任務,具備卓越的效能、智慧、流暢度與理解力。",
|
|
278
278
|
"claude-3-haiku-20240307.description": "Claude 3 Haiku 是 Anthropic 推出的最快速且最精簡的模型,設計用於即時回應,具備快速且準確的表現。",
|
|
279
279
|
"claude-3-opus-20240229.description": "Claude 3 Opus 是 Anthropic 最強大的模型,適用於高度複雜任務,具備卓越的效能、智慧、流暢度與理解力。",
|
|
280
280
|
"claude-3-sonnet-20240229.description": "Claude 3 Sonnet 在智慧與速度之間取得平衡,適合企業工作負載,提供高效能與低成本的大規模部署。",
|
|
281
|
-
"claude-haiku-4-5-20251001.description": "Claude Haiku 4.5 是 Anthropic
|
|
281
|
+
"claude-haiku-4-5-20251001.description": "Claude Haiku 4.5 是 Anthropic 最快且最聰明的 Haiku 模型,具備閃電般的速度與延伸推理能力。",
|
|
282
282
|
"claude-opus-4-1-20250805-thinking.description": "Claude Opus 4.1 Thinking 是一個進階版本,能夠揭示其推理過程。",
|
|
283
283
|
"claude-opus-4-1-20250805.description": "Claude Opus 4.1 是 Anthropic 最新且最強大的模型,適用於高度複雜任務,具備卓越的效能、智慧、流暢度與理解力。",
|
|
284
|
-
"claude-opus-4-20250514.description": "Claude Opus 4 是 Anthropic
|
|
284
|
+
"claude-opus-4-20250514.description": "Claude Opus 4 是 Anthropic 為高度複雜任務打造的最強大模型,於效能、智能、流暢度與理解力方面皆表現卓越。",
|
|
285
285
|
"claude-opus-4-5-20251101.description": "Claude Opus 4.5 是 Anthropic 的旗艦模型,結合卓越智慧與可擴展效能,適合需要最高品質回應與推理的複雜任務。",
|
|
286
286
|
"claude-sonnet-4-20250514-thinking.description": "Claude Sonnet 4 Thinking 可產生即時回應或延伸的逐步思考,並顯示其推理過程。",
|
|
287
|
-
"claude-sonnet-4-20250514.description": "Claude Sonnet 4
|
|
287
|
+
"claude-sonnet-4-20250514.description": "Claude Sonnet 4 能夠即時回應,或進行可視化的逐步思考過程。",
|
|
288
288
|
"claude-sonnet-4-5-20250929.description": "Claude Sonnet 4.5 是 Anthropic 迄今最智慧的模型。",
|
|
289
289
|
"codegeex-4.description": "CodeGeeX-4 是一款強大的 AI 程式輔助工具,支援多語言問答與程式碼補全,能有效提升開發者的生產力。",
|
|
290
290
|
"codegeex4-all-9b.description": "CodeGeeX4-ALL-9B 是一個多語言程式碼生成模型,支援程式碼補全與生成、程式碼解釋器、網頁搜尋、函式呼叫與倉庫層級的程式碼問答,涵蓋多種軟體開發場景。它是參數數量低於 100 億的頂尖程式碼模型之一。",
|
|
@@ -355,7 +355,7 @@
|
|
|
355
355
|
"deepseek-ai/deepseek-v3.1-terminus.description": "DeepSeek V3.1 是新一代推理模型,具備更強的複雜推理與思維鏈能力,適用於深度分析任務。",
|
|
356
356
|
"deepseek-ai/deepseek-v3.1.description": "DeepSeek V3.1 是新一代推理模型,具備更強的複雜推理與思維鏈能力,適用於深度分析任務。",
|
|
357
357
|
"deepseek-ai/deepseek-vl2.description": "DeepSeek-VL2 是一款基於 DeepSeekMoE-27B 的 MoE 視覺語言模型,採用稀疏激活,僅使用 4.5B 活躍參數即可達到強大表現。擅長視覺問答、OCR、文件/表格/圖表理解與視覺對齊。",
|
|
358
|
-
"deepseek-chat.description": "DeepSeek
|
|
358
|
+
"deepseek-chat.description": "一款結合通用與程式能力的開源模型。保留聊天模型的對話能力與程式模型的強大編碼能力,並提升偏好對齊。DeepSeek-V2.5 也在寫作與指令遵循方面有所進步。",
|
|
359
359
|
"deepseek-coder-33B-instruct.description": "DeepSeek Coder 33B 是一款程式語言模型,訓練於 2T token(87% 程式碼,13% 中英文文本),支援 16K 上下文視窗與中間填充任務,提供專案級程式補全與片段填充功能。",
|
|
360
360
|
"deepseek-coder-v2.description": "DeepSeek Coder V2 是一款開源 MoE 程式模型,在程式任務中表現強勁,媲美 GPT-4 Turbo。",
|
|
361
361
|
"deepseek-coder-v2:236b.description": "DeepSeek Coder V2 是一款開源 MoE 程式模型,在程式任務中表現強勁,媲美 GPT-4 Turbo。",
|
|
@@ -378,7 +378,7 @@
|
|
|
378
378
|
"deepseek-r1-fast-online.description": "DeepSeek R1 快速全量版,支援即時網頁搜尋,結合 671B 規模能力與快速回應。",
|
|
379
379
|
"deepseek-r1-online.description": "DeepSeek R1 全量版擁有 671B 參數與即時網頁搜尋功能,提供更強的理解與生成能力。",
|
|
380
380
|
"deepseek-r1.description": "DeepSeek-R1 在強化學習前使用冷啟動資料,於數學、程式碼與推理任務中表現可媲美 OpenAI-o1。",
|
|
381
|
-
"deepseek-reasoner.description": "DeepSeek V3.2
|
|
381
|
+
"deepseek-reasoner.description": "DeepSeek V3.2 推理模式會在最終答案前輸出思考鏈,以提升準確性。",
|
|
382
382
|
"deepseek-v2.description": "DeepSeek V2 是一款高效的 MoE 模型,適用於具成本效益的處理任務。",
|
|
383
383
|
"deepseek-v2:236b.description": "DeepSeek V2 236B 是 DeepSeek 專注於程式碼生成的模型,具備強大能力。",
|
|
384
384
|
"deepseek-v3-0324.description": "DeepSeek-V3-0324 是一款擁有 671B 參數的 MoE 模型,在程式設計、技術能力、語境理解與長文本處理方面表現出色。",
|
|
@@ -471,7 +471,7 @@
|
|
|
471
471
|
"ernie-tiny-8k.description": "ERNIE Tiny 8K 是一款超輕量模型,適合簡單問答、分類與低成本推理。",
|
|
472
472
|
"ernie-x1-turbo-32k.description": "ERNIE X1 Turbo 32K 是一款快速思考模型,具備 32K 上下文,適合複雜推理與多輪對話。",
|
|
473
473
|
"ernie-x1.1-preview.description": "ERNIE X1.1 預覽版是一款思考模型預覽,用於評估與測試。",
|
|
474
|
-
"fal-ai/bytedance/seedream/v4.description": "Seedream 4.0
|
|
474
|
+
"fal-ai/bytedance/seedream/v4.description": "Seedream 4.0 是來自字節跳動 Seed 團隊的圖像生成模型,支援文字與圖像輸入,能夠高品質且高度可控地生成圖像,從文字提示中創建圖像。",
|
|
475
475
|
"fal-ai/flux-kontext/dev.description": "FLUX.1 模型專注於圖像編輯,支援文字與圖像輸入。",
|
|
476
476
|
"fal-ai/flux-pro/kontext.description": "FLUX.1 Kontext [pro] 接受文字與參考圖像輸入,實現目標區域編輯與複雜場景轉換。",
|
|
477
477
|
"fal-ai/flux/krea.description": "Flux Krea [dev] 是一款圖像生成模型,偏好更真實自然的美學風格。",
|
|
@@ -479,8 +479,8 @@
|
|
|
479
479
|
"fal-ai/hunyuan-image/v3.description": "一款強大的原生多模態圖像生成模型。",
|
|
480
480
|
"fal-ai/imagen4/preview.description": "來自 Google 的高品質圖像生成模型。",
|
|
481
481
|
"fal-ai/nano-banana.description": "Nano Banana 是 Google 最新、最快且最高效的原生多模態模型,支援透過對話進行圖像生成與編輯。",
|
|
482
|
-
"fal-ai/qwen-image-edit.description": "來自 Qwen
|
|
483
|
-
"fal-ai/qwen-image.description": "Qwen
|
|
482
|
+
"fal-ai/qwen-image-edit.description": "來自 Qwen 團隊的專業圖像編輯模型,支援語義與外觀編輯,能精確處理中英文文字,並實現風格轉換、物體旋轉等高品質編輯。",
|
|
483
|
+
"fal-ai/qwen-image.description": "來自 Qwen 團隊的強大圖像生成模型,具備優異的中文文字渲染能力與多樣化視覺風格。",
|
|
484
484
|
"flux-1-schnell.description": "來自黑森林實驗室的 12B 參數文字轉圖像模型,透過潛在對抗擴散蒸餾技術,在 1 至 4 步內生成高品質圖像。其表現媲美封閉式替代方案,並以 Apache-2.0 授權釋出,供個人、研究與商業用途。",
|
|
485
485
|
"flux-dev.description": "FLUX.1 [dev] 是一款開放權重的蒸餾模型,僅限非商業用途。它保有接近專業水準的圖像品質與指令遵循能力,同時運行更高效,資源使用優於同等大小的標準模型。",
|
|
486
486
|
"flux-kontext-max.description": "最先進的語境圖像生成與編輯技術,結合文字與圖像輸入,實現精準且一致的結果。",
|
|
@@ -526,9 +526,53 @@
|
|
|
526
526
|
"gemini-2.5-pro-preview-05-06.description": "Gemini 2.5 Pro Preview 是 Google 最先進的推理模型,能處理程式碼、數學與 STEM 問題,並分析大型資料集、程式碼庫與長篇文件。",
|
|
527
527
|
"gemini-2.5-pro-preview-06-05.description": "Gemini 2.5 Pro Preview 是 Google 最先進的推理模型,能處理程式碼、數學與 STEM 問題,並分析大型資料集、程式碼庫與長篇文件。",
|
|
528
528
|
"gemini-2.5-pro.description": "Gemini 2.5 Pro 是 Google 的旗艦推理模型,支援長上下文,適用於處理複雜任務。",
|
|
529
|
+
"gemini-3-flash-preview.description": "Gemini 3 Flash 是為速度而生的智慧模型,結合前沿智能與卓越的搜尋接地能力。",
|
|
530
|
+
"gemini-3-pro-image-preview.description": "Gemini 3 Pro Image(Nano Banana Pro)是 Google 的圖像生成模型,支援多模態對話。",
|
|
531
|
+
"gemini-3-pro-image-preview:image.description": "Gemini 3 Pro Image(Nano Banana Pro)是 Google 的圖像生成模型,並支援多模態聊天。",
|
|
532
|
+
"gemini-3-pro-preview.description": "Gemini 3 Pro 是 Google 最強大的智能代理與情境編碼模型,具備頂尖推理能力、豐富視覺表現與深度互動。",
|
|
529
533
|
"gemini-flash-latest.description": "Gemini Flash 最新版本",
|
|
530
534
|
"gemini-flash-lite-latest.description": "Gemini Flash-Lite 最新版本",
|
|
531
535
|
"gemini-pro-latest.description": "Gemini Pro 最新版本",
|
|
536
|
+
"gemma-7b-it.description": "Gemma 7B 是一款適合中小型任務的高性價比模型。",
|
|
537
|
+
"gemma2-9b-it.description": "Gemma 2 9B 專為特定任務與工具整合進行優化。",
|
|
538
|
+
"gemma2.description": "Gemma 2 是 Google 的高效模型,涵蓋從小型應用到複雜資料處理的多種場景。",
|
|
539
|
+
"gemma2:27b.description": "Gemma 2 是 Google 的高效模型,涵蓋從小型應用到複雜資料處理的多種場景。",
|
|
540
|
+
"gemma2:2b.description": "Gemma 2 是 Google 的高效模型,涵蓋從小型應用到複雜資料處理的多種場景。",
|
|
541
|
+
"generalv3.5.description": "Spark Max 是功能最完整的版本,支援網頁搜尋與多種內建插件。其核心能力、系統角色與函數調用皆經過全面優化,能在複雜應用場景中展現卓越表現。",
|
|
542
|
+
"generalv3.description": "Spark Pro 是一款針對專業領域優化的高效能大型語言模型,專注於數學、程式設計、醫療與教育,支援網頁搜尋與天氣、日期等內建插件。其在複雜知識問答、語言理解與高階文本創作方面表現出色,是專業應用的理想選擇。",
|
|
543
|
+
"glm-4-0520.description": "GLM-4-0520 是最新版本模型,專為高度複雜與多樣化任務設計,具備卓越效能。",
|
|
544
|
+
"glm-4-32b-0414.description": "GLM-4 32B 0414 是一款通用 GLM 模型,支援多任務文本生成與理解。",
|
|
545
|
+
"glm-4-9b-chat.description": "GLM-4-9B-Chat 在語義、數學、推理、程式與知識方面表現優異,並支援網頁瀏覽、程式執行、自訂工具調用與長文本推理,支援包括日語、韓語、德語在內的 26 種語言。",
|
|
546
|
+
"glm-4-air-250414.description": "GLM-4-Air 是一款高性價比選擇,效能接近 GLM-4,速度快且成本低。",
|
|
547
|
+
"glm-4-air.description": "GLM-4-Air 是一款高性價比選擇,效能接近 GLM-4,速度快且成本低。",
|
|
548
|
+
"glm-4-airx.description": "GLM-4-AirX 是 GLM-4-Air 的高效版本,推理速度提升至 2.6 倍。",
|
|
549
|
+
"glm-4-alltools.description": "GLM-4-AllTools 是一款多功能智能體模型,針對複雜指令規劃與工具使用(如網頁瀏覽、程式解釋、文本生成)進行優化,適合多任務執行。",
|
|
550
|
+
"glm-4-flash-250414.description": "GLM-4-Flash 適合簡單任務:速度最快且免費。",
|
|
551
|
+
"glm-4-flash.description": "GLM-4-Flash 適合簡單任務:速度最快且免費。",
|
|
552
|
+
"glm-4-flashx.description": "GLM-4-FlashX 是 Flash 的增強版,具備超快推理能力。",
|
|
553
|
+
"glm-4-long.description": "GLM-4-Long 支援超長輸入,適用於記憶型任務與大規模文件處理。",
|
|
554
|
+
"glm-4-plus.description": "GLM-4-Plus 是高智能旗艦模型,擅長處理長文本與複雜任務,整體效能全面升級。",
|
|
555
|
+
"glm-4.1v-thinking-flash.description": "GLM-4.1V-Thinking 是目前已知最強的約 10B 視覺語言模型,涵蓋影片理解、圖像問答、學科解題、OCR、文件與圖表閱讀、GUI 智能體、前端編碼與語義對齊等 SOTA 任務。透過先進強化學習與思考鏈推理,提升準確性與豐富度,超越傳統非思考模型的結果與可解釋性。",
|
|
556
|
+
"glm-4.1v-thinking-flashx.description": "GLM-4.1V-Thinking 是目前已知最強的約 10B 視覺語言模型,涵蓋影片理解、圖像問答、學科解題、OCR、文件與圖表閱讀、GUI 智能體、前端編碼與語義對齊等 SOTA 任務。透過先進強化學習與思考鏈推理,提升準確性與豐富度,超越傳統非思考模型的結果與可解釋性。",
|
|
557
|
+
"glm-4.5-air.description": "GLM-4.5 輕量版,兼顧效能與成本,支援靈活的混合思考模式。",
|
|
558
|
+
"glm-4.5-airx.description": "GLM-4.5-Air 快速版,回應更迅速,適用於大規模高速應用。",
|
|
559
|
+
"glm-4.5-flash.description": "免費的 GLM-4.5 版本,在推理、程式與智能體任務中表現強勁。",
|
|
560
|
+
"glm-4.5-x.description": "GLM-4.5 快速版,生成速度高達每秒 100 個 token,效能出色。",
|
|
561
|
+
"glm-4.5.description": "智譜旗艦模型,支援可切換思考模式,整體表現達開源 SOTA,支援最多 128K 上下文。",
|
|
562
|
+
"glm-4.5v.description": "智譜新一代 MoE 視覺推理模型,總參數 106B,啟用 12B,於圖像、影片、文件理解與 GUI 任務中,在同級開源多模態模型中達到 SOTA 水準。",
|
|
563
|
+
"glm-4.6.description": "智譜最新旗艦模型 GLM-4.6(355B)在高階編碼、長文本處理、推理與智能體能力上全面超越前代,特別在程式能力上對齊 Claude Sonnet 4,成為國內頂尖的 Coding 模型。",
|
|
564
|
+
"glm-4.7.description": "GLM-4.7 是智譜最新旗艦模型,針對 Agentic Coding 場景強化了編碼能力、長程任務規劃與工具協同,並在多個公開基準榜單中取得開源模型領先表現。通用能力提升,回應更簡潔自然,寫作更具沉浸感。執行複雜智能體任務與工具調用時,指令遵循更強,Artifacts 與 Agentic Coding 的前端美感與長程任務完成效率進一步提升。",
|
|
565
|
+
"glm-4.description": "GLM-4 是 2024 年 1 月推出的舊版旗艦模型,現已由更強的 GLM-4-0520 取代。",
|
|
566
|
+
"glm-4v-flash.description": "GLM-4V-Flash 專注於單張圖像的高效理解,適用於即時或批次圖像處理等快速分析場景。",
|
|
567
|
+
"glm-4v-plus-0111.description": "GLM-4V-Plus 能理解影片與多張圖像,適合多模態任務。",
|
|
568
|
+
"glm-4v-plus.description": "GLM-4V-Plus 能理解影片與多張圖像,適合多模態任務。",
|
|
569
|
+
"glm-4v.description": "GLM-4V 在各類視覺任務中展現強大的圖像理解與推理能力。",
|
|
570
|
+
"glm-z1-air.description": "具備強大推理能力的模型,適用於需要深度推理的任務。",
|
|
571
|
+
"glm-z1-airx.description": "超高速推理,兼具高品質推理表現。",
|
|
572
|
+
"glm-z1-flash.description": "GLM-Z1 系列具備強大的複雜推理能力,擅長邏輯、數學與程式任務。",
|
|
573
|
+
"glm-z1-flashx.description": "快速且低成本:Flash 增強版,具備超快推理與高併發能力。",
|
|
574
|
+
"glm-zero-preview.description": "GLM-Zero-Preview 具備強大的複雜推理能力,擅長邏輯、數學與程式任務。",
|
|
575
|
+
"global.anthropic.claude-opus-4-5-20251101-v1:0.description": "Claude Opus 4.5 是 Anthropic 的旗艦模型,結合卓越智慧與可擴展效能,適用於需要最高品質回應與推理的複雜任務。",
|
|
532
576
|
"meta/Llama-3.2-90B-Vision-Instruct.description": "先進的圖像推理能力,適用於視覺理解代理應用。",
|
|
533
577
|
"meta/Llama-3.3-70B-Instruct.description": "Llama 3.3 是最先進的多語言開源 Llama 模型,以極低成本提供接近 405B 的效能。該模型基於 Transformer 架構,並透過 SFT 與 RLHF 提升實用性與安全性。經指令微調版本針對多語言對話進行最佳化,在業界基準測試中超越多數開放與封閉模型。知識截止時間:2023 年 12 月。",
|
|
534
578
|
"meta/Meta-Llama-3-70B-Instruct.description": "一款功能強大的 70B 參數模型,擅長推理、程式編寫與廣泛語言任務。",
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"internlm.description": "一個專注於大型模型研究與工具的開源組織,提供高效、易用的平台,讓尖端模型與演算法更易於取得。",
|
|
30
30
|
"jina.description": "Jina AI 成立於 2020 年,是領先的搜尋 AI 公司。其搜尋技術堆疊包含向量模型、重排序器與小型語言模型,打造可靠且高品質的生成式與多模態搜尋應用。",
|
|
31
31
|
"lmstudio.description": "LM Studio 是一款桌面應用程式,可在本機開發與實驗大型語言模型。",
|
|
32
|
-
"lobehub.description": "LobeHub Cloud 使用官方 API 存取 AI 模型,並以與模型代幣相關的點數(Credits)來計算使用量。",
|
|
33
32
|
"minimax.description": "MiniMax 成立於 2021 年,致力於打造通用 AI,擁有多模態基礎模型,包括兆級參數的 MoE 文本模型、語音模型與視覺模型,並推出如海螺 AI 等應用。",
|
|
34
33
|
"mistral.description": "Mistral 提供先進的通用、專業與研究模型,支援複雜推理、多語言任務與程式碼生成,並支援函式呼叫以實現自訂整合。",
|
|
35
34
|
"modelscope.description": "ModelScope 是阿里雲的模型即服務平台,提供多樣化的 AI 模型與推理服務。",
|
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
"_cloud.officialProvider": "{{name}} 官方模型服務",
|
|
3
3
|
"about.title": "關於",
|
|
4
4
|
"advancedSettings": "進階設定",
|
|
5
|
+
"agentCronJobs.addJob": "新增排程任務",
|
|
6
|
+
"agentCronJobs.confirmDelete": "您確定要刪除此排程任務嗎?",
|
|
7
|
+
"agentCronJobs.content": "任務內容",
|
|
8
|
+
"agentCronJobs.create": "建立",
|
|
9
|
+
"agentCronJobs.createSuccess": "排程任務建立成功",
|
|
10
|
+
"agentCronJobs.deleteJob": "刪除任務",
|
|
11
|
+
"agentCronJobs.deleteSuccess": "排程任務刪除成功",
|
|
12
|
+
"agentCronJobs.description": "透過排程執行自動化您的代理程式",
|
|
13
|
+
"agentCronJobs.disable": "停用",
|
|
14
|
+
"agentCronJobs.editJob": "編輯排程任務",
|
|
15
|
+
"agentCronJobs.empty.description": "建立您的第一個排程任務以自動化代理程式",
|
|
16
|
+
"agentCronJobs.empty.title": "尚無排程任務",
|
|
17
|
+
"agentCronJobs.enable": "啟用",
|
|
18
|
+
"agentCronJobs.form.content.placeholder": "輸入給代理程式的提示或指令",
|
|
19
|
+
"agentCronJobs.form.maxExecutions.placeholder": "留空表示無限制",
|
|
20
|
+
"agentCronJobs.form.name.placeholder": "輸入任務名稱",
|
|
21
|
+
"agentCronJobs.form.timeRange.end": "結束時間",
|
|
22
|
+
"agentCronJobs.form.timeRange.start": "開始時間",
|
|
23
|
+
"agentCronJobs.form.validation.contentRequired": "任務內容為必填",
|
|
24
|
+
"agentCronJobs.form.validation.invalidTimeRange": "開始時間必須早於結束時間",
|
|
25
|
+
"agentCronJobs.form.validation.nameRequired": "任務名稱為必填",
|
|
26
|
+
"agentCronJobs.interval.12hours": "每 12 小時",
|
|
27
|
+
"agentCronJobs.interval.1hour": "每小時",
|
|
28
|
+
"agentCronJobs.interval.30min": "每 30 分鐘",
|
|
29
|
+
"agentCronJobs.interval.6hours": "每 6 小時",
|
|
30
|
+
"agentCronJobs.interval.daily": "每日",
|
|
31
|
+
"agentCronJobs.interval.weekly": "每週",
|
|
32
|
+
"agentCronJobs.lastExecuted": "上次執行時間",
|
|
33
|
+
"agentCronJobs.maxExecutions": "最大執行次數",
|
|
34
|
+
"agentCronJobs.name": "任務名稱",
|
|
35
|
+
"agentCronJobs.never": "從未",
|
|
36
|
+
"agentCronJobs.remainingExecutions": "剩餘:{{count}}",
|
|
37
|
+
"agentCronJobs.save": "儲存",
|
|
38
|
+
"agentCronJobs.schedule": "排程",
|
|
39
|
+
"agentCronJobs.status.depleted": "已耗盡",
|
|
40
|
+
"agentCronJobs.status.disabled": "已停用",
|
|
41
|
+
"agentCronJobs.status.enabled": "已啟用",
|
|
42
|
+
"agentCronJobs.timeRange": "時間範圍",
|
|
43
|
+
"agentCronJobs.title": "排程任務",
|
|
44
|
+
"agentCronJobs.unlimited": "無限制",
|
|
45
|
+
"agentCronJobs.updateSuccess": "排程任務更新成功",
|
|
46
|
+
"agentCronJobs.weekdays": "平日",
|
|
5
47
|
"agentInfoDescription.basic.avatar": "頭像",
|
|
6
48
|
"agentInfoDescription.basic.description": "描述",
|
|
7
49
|
"agentInfoDescription.basic.name": "名稱",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.254",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { useWatchBroadcast } from '@lobechat/electron-client-ipc';
|
|
3
4
|
import { Block, Button, Flexbox, Icon, Text } from '@lobehub/ui';
|
|
4
5
|
import { cssVar } from 'antd-style';
|
|
5
6
|
import {
|
|
@@ -93,12 +94,15 @@ const PermissionsStep = memo<PermissionsStepProps>(({ onBack, onNext }) => {
|
|
|
93
94
|
const micStatus = await ipc.system.getMediaAccessStatus('microphone');
|
|
94
95
|
const screenStatus = await ipc.system.getMediaAccessStatus('screen');
|
|
95
96
|
const accessibilityStatus = await ipc.system.getAccessibilityStatus();
|
|
97
|
+
// Full Disk Access can now be checked by attempting to read protected directories
|
|
98
|
+
const fullDiskStatus = await ipc.system.getFullDiskAccessStatus();
|
|
96
99
|
|
|
97
100
|
setPermissions((prev) =>
|
|
98
101
|
prev.map((p) => {
|
|
99
102
|
if (p.id === 1) return { ...p, granted: notifStatus === 'authorized' };
|
|
100
|
-
// Full Disk Access
|
|
101
|
-
if (p.id === 2)
|
|
103
|
+
// Full Disk Access status is detected by reading protected directories
|
|
104
|
+
if (p.id === 2)
|
|
105
|
+
return { ...p, buttonKey: 'screen3.actions.openSettings', granted: fullDiskStatus };
|
|
102
106
|
if (p.id === 3)
|
|
103
107
|
return { ...p, granted: micStatus === 'granted' && screenStatus === 'granted' };
|
|
104
108
|
if (p.id === 4) return { ...p, granted: accessibilityStatus };
|
|
@@ -111,28 +115,11 @@ const PermissionsStep = memo<PermissionsStepProps>(({ onBack, onNext }) => {
|
|
|
111
115
|
checkAllPermissions();
|
|
112
116
|
}, [checkAllPermissions]);
|
|
113
117
|
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
checkAllPermissions();
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const handleVisibilityChange = () => {
|
|
123
|
-
if (document.visibilityState === 'visible') {
|
|
124
|
-
checkAllPermissions();
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
window.addEventListener('focus', handleFocus);
|
|
129
|
-
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
130
|
-
|
|
131
|
-
return () => {
|
|
132
|
-
window.removeEventListener('focus', handleFocus);
|
|
133
|
-
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
134
|
-
};
|
|
135
|
-
}, [checkAllPermissions]);
|
|
118
|
+
// Listen for window focus event from Electron main process
|
|
119
|
+
// This is more reliable than browser focus events in Electron environment
|
|
120
|
+
useWatchBroadcast('windowFocused', () => {
|
|
121
|
+
checkAllPermissions();
|
|
122
|
+
});
|
|
136
123
|
|
|
137
124
|
const handlePermissionRequest = async (permissionId: number) => {
|
|
138
125
|
const ipc = ensureElectronIpc();
|
|
@@ -143,7 +130,8 @@ const PermissionsStep = memo<PermissionsStepProps>(({ onBack, onNext }) => {
|
|
|
143
130
|
break;
|
|
144
131
|
}
|
|
145
132
|
case 2: {
|
|
146
|
-
|
|
133
|
+
// Use native prompt dialog for Full Disk Access
|
|
134
|
+
await ipc.system.promptFullDiskAccessIfNotGranted();
|
|
147
135
|
break;
|
|
148
136
|
}
|
|
149
137
|
case 3: {
|
|
@@ -175,7 +163,7 @@ const PermissionsStep = memo<PermissionsStepProps>(({ onBack, onNext }) => {
|
|
|
175
163
|
{permissions.map((permission) => (
|
|
176
164
|
<Block
|
|
177
165
|
align={'center'}
|
|
178
|
-
clickable={!permission.granted
|
|
166
|
+
clickable={!permission.granted}
|
|
179
167
|
gap={16}
|
|
180
168
|
horizontal
|
|
181
169
|
key={permission.id}
|
|
@@ -197,7 +185,7 @@ const PermissionsStep = memo<PermissionsStepProps>(({ onBack, onNext }) => {
|
|
|
197
185
|
{t(permission.descriptionKey as any)}
|
|
198
186
|
</Text>
|
|
199
187
|
</Flexbox>
|
|
200
|
-
{permission.granted
|
|
188
|
+
{permission.granted ? (
|
|
201
189
|
<Icon color={cssVar.colorSuccess} icon={Check} size={20} />
|
|
202
190
|
) : (
|
|
203
191
|
<Button
|
|
@@ -213,9 +201,7 @@ const PermissionsStep = memo<PermissionsStepProps>(({ onBack, onNext }) => {
|
|
|
213
201
|
}}
|
|
214
202
|
type={'text'}
|
|
215
203
|
>
|
|
216
|
-
{permission.
|
|
217
|
-
? t('screen3.actions.granted')
|
|
218
|
-
: t(permission.buttonKey)}
|
|
204
|
+
{t(permission.buttonKey)}
|
|
219
205
|
</Button>
|
|
220
206
|
)}
|
|
221
207
|
</Block>
|
|
@@ -2,27 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
import { Flexbox, Skeleton } from '@lobehub/ui';
|
|
4
4
|
import { Suspense, memo, useCallback, useEffect, useState } from 'react';
|
|
5
|
-
import {
|
|
5
|
+
import { useSearchParams } from 'react-router-dom';
|
|
6
6
|
|
|
7
7
|
import Loading from '@/components/Loading/BrandTextLoading';
|
|
8
8
|
import { electronSystemService } from '@/services/electron/system';
|
|
9
|
-
import { isDev } from '@/utils/env';
|
|
10
9
|
|
|
11
10
|
import OnboardingContainer from './_layout';
|
|
12
11
|
import DataModeStep from './features/DataModeStep';
|
|
13
12
|
import LoginStep from './features/LoginStep';
|
|
14
13
|
import PermissionsStep from './features/PermissionsStep';
|
|
15
14
|
import WelcomeStep from './features/WelcomeStep';
|
|
16
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
clearDesktopOnboardingStep,
|
|
17
|
+
getDesktopOnboardingStep,
|
|
18
|
+
setDesktopOnboardingCompleted,
|
|
19
|
+
setDesktopOnboardingStep,
|
|
20
|
+
} from './storage';
|
|
17
21
|
|
|
18
22
|
const DesktopOnboardingPage = memo(() => {
|
|
19
|
-
const navigate = useNavigate();
|
|
20
23
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
21
24
|
const [isMac, setIsMac] = useState(true);
|
|
22
25
|
const [isLoading, setIsLoading] = useState(true);
|
|
23
26
|
|
|
24
|
-
// 从 URL query
|
|
27
|
+
// 从 localStorage 或 URL query 参数获取初始步骤
|
|
28
|
+
// 优先使用 localStorage 以支持重启后恢复
|
|
25
29
|
const getInitialStep = useCallback(() => {
|
|
30
|
+
// First try localStorage (for app restart scenario)
|
|
31
|
+
const savedStep = getDesktopOnboardingStep();
|
|
32
|
+
if (savedStep !== null) {
|
|
33
|
+
return savedStep;
|
|
34
|
+
}
|
|
35
|
+
// Then try URL params
|
|
26
36
|
const stepParam = searchParams.get('step');
|
|
27
37
|
if (stepParam) {
|
|
28
38
|
const step = parseInt(stepParam, 10);
|
|
@@ -33,11 +43,10 @@ const DesktopOnboardingPage = memo(() => {
|
|
|
33
43
|
|
|
34
44
|
const [currentStep, setCurrentStep] = useState(getInitialStep);
|
|
35
45
|
|
|
36
|
-
//
|
|
46
|
+
// 持久化当前步骤到 localStorage
|
|
37
47
|
useEffect(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}, [navigate]);
|
|
48
|
+
setDesktopOnboardingStep(currentStep);
|
|
49
|
+
}, [currentStep]);
|
|
41
50
|
|
|
42
51
|
// 设置窗口大小和可调整性
|
|
43
52
|
useEffect(() => {
|
|
@@ -117,6 +126,7 @@ const DesktopOnboardingPage = memo(() => {
|
|
|
117
126
|
case 4: {
|
|
118
127
|
// 如果是第4步(LoginStep),完成 onboarding
|
|
119
128
|
setDesktopOnboardingCompleted();
|
|
129
|
+
clearDesktopOnboardingStep(); // Clear persisted step since onboarding is complete
|
|
120
130
|
// Restore window resizable before hard reload (cleanup won't run due to hard navigation)
|
|
121
131
|
electronSystemService
|
|
122
132
|
.setWindowResizable({ resizable: true })
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export const DESKTOP_ONBOARDING_STORAGE_KEY = 'lobechat:desktop:onboarding:completed:v1';
|
|
2
|
+
export const DESKTOP_ONBOARDING_STEP_KEY = 'lobechat:desktop:onboarding:step:v1';
|
|
2
3
|
|
|
3
4
|
export const getDesktopOnboardingCompleted = () => {
|
|
4
5
|
if (typeof window === 'undefined') return true;
|
|
@@ -32,3 +33,51 @@ export const clearDesktopOnboardingCompleted = () => {
|
|
|
32
33
|
return false;
|
|
33
34
|
}
|
|
34
35
|
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get the persisted onboarding step (for restoring after app restart)
|
|
39
|
+
*/
|
|
40
|
+
export const getDesktopOnboardingStep = (): number | null => {
|
|
41
|
+
if (typeof window === 'undefined') return null;
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const step = window.localStorage.getItem(DESKTOP_ONBOARDING_STEP_KEY);
|
|
45
|
+
if (step) {
|
|
46
|
+
const parsedStep = Number.parseInt(step, 10);
|
|
47
|
+
if (parsedStep >= 1 && parsedStep <= 4) {
|
|
48
|
+
return parsedStep;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Persist the current onboarding step
|
|
59
|
+
*/
|
|
60
|
+
export const setDesktopOnboardingStep = (step: number) => {
|
|
61
|
+
if (typeof window === 'undefined') return false;
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
window.localStorage.setItem(DESKTOP_ONBOARDING_STEP_KEY, step.toString());
|
|
65
|
+
return true;
|
|
66
|
+
} catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Clear the persisted onboarding step (called when onboarding completes)
|
|
73
|
+
*/
|
|
74
|
+
export const clearDesktopOnboardingStep = () => {
|
|
75
|
+
if (typeof window === 'undefined') return false;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
window.localStorage.removeItem(DESKTOP_ONBOARDING_STEP_KEY);
|
|
79
|
+
return true;
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
@@ -80,10 +80,10 @@ const ParamControlWrapper = memo<ParamControlWrapperProps>(
|
|
|
80
80
|
<Checkbox
|
|
81
81
|
checked={checked}
|
|
82
82
|
className={styles.checkbox}
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
onClick={(e) => {
|
|
84
|
+
e.stopPropagation();
|
|
85
|
+
onToggle(!checked);
|
|
85
86
|
}}
|
|
86
|
-
onClick={(e) => e.stopPropagation()}
|
|
87
87
|
/>
|
|
88
88
|
<div style={{ flex: 1 }}>
|
|
89
89
|
<Component disabled={disabled} onChange={onChange} value={value} />
|
|
@@ -275,6 +275,7 @@ const Controls = memo<ControlsProps>(({ setUpdating }) => {
|
|
|
275
275
|
disabled={!enabled}
|
|
276
276
|
onToggle={(checked) => handleToggle(key, checked)}
|
|
277
277
|
styles={styles}
|
|
278
|
+
value={form.getFieldValue(PARAM_NAME_MAP[key])}
|
|
278
279
|
/>
|
|
279
280
|
),
|
|
280
281
|
label: (
|
|
@@ -297,9 +298,9 @@ const Controls = memo<ControlsProps>(({ setUpdating }) => {
|
|
|
297
298
|
mobile
|
|
298
299
|
? baseItems
|
|
299
300
|
: baseItems.map(({ tag, ...item }) => ({
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
301
|
+
...item,
|
|
302
|
+
desc: <Tag size={'small'}>{tag}</Tag>,
|
|
303
|
+
}))
|
|
303
304
|
}
|
|
304
305
|
itemsType={'flat'}
|
|
305
306
|
onValuesChange={handleValuesChange}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
on run argv
|
|
2
|
-
set appBundlePath to item 1 of argv
|
|
3
|
-
|
|
4
|
-
set settingsBundleIds to {"com.apple.SystemSettings", "com.apple.systempreferences"}
|
|
5
|
-
|
|
6
|
-
-- Bring System Settings/Preferences to front (Ventura+ / older). If it doesn't exist, ignore.
|
|
7
|
-
repeat with bundleId in settingsBundleIds
|
|
8
|
-
try
|
|
9
|
-
tell application id bundleId to activate
|
|
10
|
-
exit repeat
|
|
11
|
-
end try
|
|
12
|
-
end repeat
|
|
13
|
-
|
|
14
|
-
tell application "System Events"
|
|
15
|
-
set settingsProcess to missing value
|
|
16
|
-
repeat 30 times
|
|
17
|
-
repeat with bundleId in settingsBundleIds
|
|
18
|
-
try
|
|
19
|
-
if exists (first process whose bundle identifier is bundleId) then
|
|
20
|
-
set settingsProcess to first process whose bundle identifier is bundleId
|
|
21
|
-
exit repeat
|
|
22
|
-
end if
|
|
23
|
-
end try
|
|
24
|
-
end repeat
|
|
25
|
-
|
|
26
|
-
if settingsProcess is not missing value then exit repeat
|
|
27
|
-
delay 0.2
|
|
28
|
-
end repeat
|
|
29
|
-
|
|
30
|
-
if settingsProcess is missing value then return "no-settings-process"
|
|
31
|
-
|
|
32
|
-
tell settingsProcess
|
|
33
|
-
set frontmost to true
|
|
34
|
-
|
|
35
|
-
repeat 30 times
|
|
36
|
-
if exists window 1 then exit repeat
|
|
37
|
-
delay 0.2
|
|
38
|
-
end repeat
|
|
39
|
-
if not (exists window 1) then return "no-window"
|
|
40
|
-
|
|
41
|
-
-- Best-effort: find an "add" button in the front window and click it.
|
|
42
|
-
set clickedAdd to false
|
|
43
|
-
repeat 30 times
|
|
44
|
-
try
|
|
45
|
-
repeat with b in (buttons of window 1)
|
|
46
|
-
set bDesc to ""
|
|
47
|
-
set bName to ""
|
|
48
|
-
set bTitle to ""
|
|
49
|
-
try set bDesc to description of b end try
|
|
50
|
-
try set bName to name of b end try
|
|
51
|
-
try set bTitle to title of b end try
|
|
52
|
-
|
|
53
|
-
if (bDesc is "Add") or (bTitle is "Add") or (bName is "+") or (bTitle is "+") then
|
|
54
|
-
click b
|
|
55
|
-
set clickedAdd to true
|
|
56
|
-
exit repeat
|
|
57
|
-
end if
|
|
58
|
-
end repeat
|
|
59
|
-
end try
|
|
60
|
-
|
|
61
|
-
if clickedAdd is true then exit repeat
|
|
62
|
-
delay 0.2
|
|
63
|
-
end repeat
|
|
64
|
-
|
|
65
|
-
if clickedAdd is false then return "no-add-button"
|
|
66
|
-
|
|
67
|
-
-- Wait for open panel / sheet
|
|
68
|
-
repeat 30 times
|
|
69
|
-
if exists sheet 1 of window 1 then exit repeat
|
|
70
|
-
delay 0.2
|
|
71
|
-
end repeat
|
|
72
|
-
if not (exists sheet 1 of window 1) then return "no-sheet"
|
|
73
|
-
|
|
74
|
-
-- Open "Go to the folder" and input the app bundle path, then confirm.
|
|
75
|
-
keystroke "G" using {command down, shift down}
|
|
76
|
-
delay 0.3
|
|
77
|
-
keystroke appBundlePath
|
|
78
|
-
key code 36
|
|
79
|
-
delay 0.6
|
|
80
|
-
-- Confirm "Open" in the panel (Enter usually triggers default)
|
|
81
|
-
key code 36
|
|
82
|
-
return "ok"
|
|
83
|
-
end tell
|
|
84
|
-
end tell
|
|
85
|
-
end run
|