feat: AI Router per session; Settings at the sidebar's foot; shipped tool icons
AI Router is a session's choice, not a workspace's: - an AI Router select beside the model picker in the workspace home and a pane's run form (RouterPicker.tsx; hidden off Claude/Codex or with only Native; last pick remembered in agenthub.session.router) - `router` on POST /api/lanes/:id/start and POST /api/run; Claude gets --settings=<data dir>/router-settings/<name>.json (0600, outranks project and user settings, key never in argv), Codex -p <name> + key via tmux -e - dashboard_runs.router; a resume naming none goes back to it - profile PATCH rewrites the session files, DELETE removes them - gone: POST /api/lanes/:id/router/apply, LaneRouterRow, the Add-workspace router radio, the claude-/codex-home `routers` answers; clearLaneRouters takes the old keys out of each workspace's settings.local.json at start Sidebar: Settings pinned to the foot, the collapse toggle beside it (stacked on the rail) instead of in the brand's corner. Icons: shipped SVG marks for claude, codex, openclaw and hermes (a black/white pair swapped by theme) in client/public/ai-tools/, used by AiToolIcon before the server's favicon.
This commit is contained in:
@@ -40,23 +40,15 @@
|
||||
"addLaneRepoHintAdopt": "An existing directory. The dashboard tracks it as-is — no worktree, no new branch.",
|
||||
"addLaneRepoLabel": "Source repository",
|
||||
"addLaneRepoLabelAdopt": "Directory",
|
||||
"addLaneRouterCustom": "AI Router",
|
||||
"addLaneRouterEmptyHint": "No router profile saved yet — add one under Settings › AI Router.",
|
||||
"addLaneRouterHint": "Native talks to the vendor's own API. An AI Router profile is written into this workspace's own config when it is created.",
|
||||
"addLaneRouterLabel": "Model endpoint",
|
||||
"addLaneRouterLoading": "Loading router profiles…",
|
||||
"addLaneRouterProfileLabel": "Router profile",
|
||||
"addLaneSetupClose": "Close",
|
||||
"addLaneSetupMcp": "MCP servers",
|
||||
"addLaneSetupProfile": "Profile",
|
||||
"addLaneSetupRouter": "Model endpoint",
|
||||
"addLaneSetupTitle": "Setup",
|
||||
"addLaneTitleLabel": "Title",
|
||||
"addLaneTitlePlaceholder": "Optional",
|
||||
"addLaneToolDefaultBadge": "Default",
|
||||
"addLaneNoTools": "No AI tool is installed and enabled.",
|
||||
"addLaneNoToolsLink": "Open Settings → AI Tools",
|
||||
"addLaneRouterNativeTool": "Native ({{tool}})",
|
||||
"addLaneToolHint": "Which CLI drives this workspace. Cannot be changed later.",
|
||||
"addLaneWorktreeDetached": "(detached)",
|
||||
"addLaneWorktreesMore": "+{{count}} more",
|
||||
@@ -222,13 +214,8 @@
|
||||
"proof.ticketReport": "Task report",
|
||||
"renameLabel": "Rename this workspace",
|
||||
"reorderHint": "Drag to reorder · Alt+←/→",
|
||||
"router.applied": "Applied.",
|
||||
"router.native": "Native ({{tool}})",
|
||||
"router.nativeOnly": "{{tool}} runs on its own settings — AI Router profiles work with Claude Code and Codex only.",
|
||||
"router.appliedRestart": "Applied, but the session running in this workspace still uses the old models — restart it to take effect.",
|
||||
"router.label": "Model",
|
||||
"router.restart": "Restart",
|
||||
"router.restarted": "Session restarted with the new router.",
|
||||
"router.label": "AI Router",
|
||||
"runtime.boot": "▶ up",
|
||||
"runtime.busy.down": "stopping…",
|
||||
"runtime.busy.up": "booting…",
|
||||
|
||||
@@ -67,8 +67,7 @@
|
||||
"claudeHome": {
|
||||
"title": "CLAUDE_HOME",
|
||||
"description": "Root directory for Claude Code session data. Changing this updates the scan path for transcripts and imports immediately.",
|
||||
"placeholder": "/path/to/claude-home",
|
||||
"routersMissing": "Saved. These workspaces name an AI Router profile the new home does not have, and start on Native until it is added there or they are re-pointed: {{lanes}}"
|
||||
"placeholder": "/path/to/claude-home"
|
||||
},
|
||||
"hooks": {
|
||||
"title": "Hook Configuration",
|
||||
@@ -510,7 +509,6 @@
|
||||
"cancel": "Cancel",
|
||||
"removeConfirm": "Remove the profile \"{{label}}\"? Every workspace using it is reset to the vendor's own API right away — on disk and in the dashboard.",
|
||||
"loading": "Loading profiles…",
|
||||
"lanesFailed": "Saved, but {{count}} workspace could not be updated and still carries the old endpoint: {{lanes}}",
|
||||
"test": "Test",
|
||||
"testing": "Testing…",
|
||||
"testOk": "The endpoint answered — {{model}} is reachable with this key.",
|
||||
@@ -589,8 +587,7 @@
|
||||
"title": "CODEX_HOME",
|
||||
"description": "Root directory for Codex config and session journals. The dashboard reads it, writes AI Router layers into it, and starts every codex workspace with it.",
|
||||
"restartNote": "A codex workspace already running keeps the home it started with, and shows as idle, until it is restarted.",
|
||||
"placeholder": "/path/to/codex-home",
|
||||
"routersFailed": "Saved, but the AI Router layer could not be re-written for: {{lanes}}"
|
||||
"placeholder": "/path/to/codex-home"
|
||||
},
|
||||
"codexHooks": {
|
||||
"title": "Codex hooks",
|
||||
|
||||
@@ -40,23 +40,15 @@
|
||||
"addLaneRepoHintAdopt": "Một thư mục có sẵn. Dashboard theo dõi nguyên trạng — không tạo worktree, không tạo nhánh mới.",
|
||||
"addLaneRepoLabel": "Repo nguồn",
|
||||
"addLaneRepoLabelAdopt": "Thư mục",
|
||||
"addLaneRouterCustom": "AI Router",
|
||||
"addLaneRouterEmptyHint": "Chưa lưu profile router nào — thêm ở Settings › AI Router.",
|
||||
"addLaneRouterHint": "Native là gọi thẳng API của hãng. Chọn profile AI Router thì cấu hình được ghi vào config riêng của workspace này lúc tạo.",
|
||||
"addLaneRouterLabel": "Endpoint model",
|
||||
"addLaneRouterLoading": "Đang tải danh sách router…",
|
||||
"addLaneRouterProfileLabel": "Profile router",
|
||||
"addLaneSetupClose": "Đóng",
|
||||
"addLaneSetupMcp": "MCP server",
|
||||
"addLaneSetupProfile": "Profile",
|
||||
"addLaneSetupRouter": "Endpoint model",
|
||||
"addLaneSetupTitle": "Thiết lập",
|
||||
"addLaneTitleLabel": "Tiêu đề",
|
||||
"addLaneTitlePlaceholder": "Không bắt buộc",
|
||||
"addLaneToolDefaultBadge": "Mặc định",
|
||||
"addLaneNoTools": "Chưa có AI tool nào được cài và bật.",
|
||||
"addLaneNoToolsLink": "Mở Cài đặt → AI Tools",
|
||||
"addLaneRouterNativeTool": "Native ({{tool}})",
|
||||
"addLaneToolHint": "CLI nào điều khiển workspace này. Không thể thay đổi sau này.",
|
||||
"addLaneWorktreeDetached": "(detached)",
|
||||
"addLaneWorktreesMore": "+{{count}} nữa",
|
||||
@@ -222,13 +214,8 @@
|
||||
"proof.ticketReport": "Báo cáo nhiệm vụ",
|
||||
"renameLabel": "Đổi tên workspace này",
|
||||
"reorderHint": "Kéo để sắp xếp · Alt+←/→",
|
||||
"router.applied": "Đã áp dụng.",
|
||||
"router.native": "Native ({{tool}})",
|
||||
"router.nativeOnly": "{{tool}} chạy bằng cấu hình riêng — hồ sơ AI Router chỉ dùng được với Claude Code và Codex.",
|
||||
"router.appliedRestart": "Đã áp dụng, nhưng phiên đang chạy trong workspace này vẫn dùng model cũ — khởi động lại phiên để có hiệu lực.",
|
||||
"router.label": "Model",
|
||||
"router.restart": "Khởi động lại",
|
||||
"router.restarted": "Đã khởi động lại phiên với router mới.",
|
||||
"router.label": "AI Router",
|
||||
"runtime.boot": "▶ chạy",
|
||||
"runtime.busy.down": "đang dừng…",
|
||||
"runtime.busy.up": "đang khởi động…",
|
||||
|
||||
@@ -67,8 +67,7 @@
|
||||
"claudeHome": {
|
||||
"title": "CLAUDE_HOME",
|
||||
"description": "Thư mục gốc chứa dữ liệu phiên Claude Code. Thay đổi sẽ cập nhật ngay đường dẫn quét cho transcript và import.",
|
||||
"placeholder": "/đường-dẫn/tới/claude-home",
|
||||
"routersMissing": "Đã lưu. Các workspace này dùng một hồ sơ AI Router mà thư mục mới không có, nên sẽ chạy Native cho đến khi bạn thêm hồ sơ đó ở đây hoặc chọn lại router cho workspace: {{lanes}}"
|
||||
"placeholder": "/đường-dẫn/tới/claude-home"
|
||||
},
|
||||
"hooks": {
|
||||
"title": "Cấu hình hook",
|
||||
@@ -510,7 +509,6 @@
|
||||
"cancel": "Huỷ",
|
||||
"removeConfirm": "Xoá profile \"{{label}}\"? Mọi workspace đang dùng nó sẽ được đưa về API gốc của hãng ngay lập tức — cả trên đĩa lẫn trong dashboard.",
|
||||
"loading": "Đang tải danh sách profile…",
|
||||
"lanesFailed": "Đã lưu, nhưng {{count}} workspace không cập nhật được và vẫn đang giữ endpoint cũ: {{lanes}}",
|
||||
"test": "Kiểm tra",
|
||||
"testing": "Đang kiểm tra…",
|
||||
"testOk": "Endpoint đã trả lời — {{model}} dùng được với key này.",
|
||||
@@ -589,8 +587,7 @@
|
||||
"title": "CODEX_HOME",
|
||||
"description": "Thư mục gốc chứa config và nhật ký phiên của Codex. Dashboard đọc từ đây, ghi layer AI Router vào đây, và mở mọi workspace codex với thư mục này.",
|
||||
"restartNote": "Workspace codex đang chạy vẫn dùng thư mục cũ, và hiện là idle, cho tới khi được khởi động lại.",
|
||||
"placeholder": "/đường-dẫn/tới/codex-home",
|
||||
"routersFailed": "Đã lưu, nhưng không ghi lại được layer AI Router cho: {{lanes}}"
|
||||
"placeholder": "/đường-dẫn/tới/codex-home"
|
||||
},
|
||||
"codexHooks": {
|
||||
"title": "Hook của Codex",
|
||||
|
||||
Reference in New Issue
Block a user