feat(chat): work-status panel, and MCP auth and settings fixes (#2776)

Adds a work-status panel beside the transcript. Context fill, model and
cost, todos, running subagents and the permission requests blocking
them, branch and working-tree state, MCP servers, pinned messages and
context sources were scattered across the header, the composer and the
context panel — a blocked subagent was reported nowhere at all. The
panel reads them from live channels rather than persisted history, and
becomes an overlay where the chat is too narrow to seat a column.

It is on by default, including for existing installs. Because it now
carries these readouts, the desktop header and composer drop the ones it
duplicates: todo and changed-files chips, usage and MCP tabs. VS Code
and mobile keep theirs — neither hosts the panel.

Fixes MCP authorization, which was broken from the panel, invalidated by
a directory switch through a redirect URI that encoded the working
directory, and left the desktop app in the background because browsers
will not follow a custom-protocol link without a user gesture. The
settings page no longer asks the user to understand the MCP spec before
adding a server: one field takes the command or the link, with the kind
inferred and a visible override, and client-registration fields appear
only when a server actually asks for its own credentials.

Also: skills load from the panel instead of only when the composer's
slash autocomplete opens; the header button names the current instance
rather than falling through to the word "Instance" for relay hosts.

Three new optional UI settings keys, all migrated. No change to stored
MCP server configuration.
This commit is contained in:
Bohdan Triapitsyn
2026-08-09 19:30:25 +03:00
parent 493a618efc
commit f4743ea060
69 changed files with 5777 additions and 894 deletions
+89 -3
View File
@@ -1541,8 +1541,6 @@ export const dict: Record<I18nKey, string> = {
'header.github.accountSource.cli': 'CLI',
'header.services.openWithCurrent': 'インスタンス、使用量、MCPを開く(現在: {current})',
'header.services.open': 'サービス、使用量、MCPを開く',
'header.services.tooltip.currentInstanceWithShortcuts': '現在のインスタンス: {current}({toggle}、次のタブ {nextTab})',
'header.services.tooltip.servicesWithShortcuts': 'サービス({toggle}、次のタブ {nextTab})',
'header.services.title': 'サービス',
'header.services.viewAria': 'サービスを表示',
'header.services.closeAria': 'サービスを閉じる',
@@ -1559,7 +1557,6 @@ export const dict: Record<I18nKey, string> = {
'header.services.used': '使用済み',
'header.services.remaining': '残り',
'header.services.modelFamily.other': 'その他',
'header.services.shutdownDev': 'OpenChamberを停止',
'header.actions.openPlanAria': '計画を開く',
'header.actions.toggleChangesPanel': '変更パネル',
'header.actions.toggleChangesPanelAria': '変更パネルの切り替え',
@@ -2942,4 +2939,93 @@ export const dict: Record<I18nKey, string> = {
'updateDialog.changelog.title': '新機能',
'quota.window.premiumInteractions': 'プレミアムインタラクション',
'chat.workStatus.ariaLabel': '作業状況',
'chat.workStatus.context.label': 'コンテキスト',
'chat.workStatus.git.changedFileSingle': '{count} 件のファイルを変更',
'chat.workStatus.git.changedFilePlural': '{count} 件のファイルを変更',
'chat.workStatus.pr.untitled': 'タイトルなしのプルリクエスト',
'chat.workStatus.pr.draft': 'ドラフト',
'chat.workStatus.pr.checks': 'チェック',
'chat.workStatus.pr.checksFailed': '{count} 件失敗',
'chat.workStatus.pr.checksPending': '{count} 件実行中',
'chat.workStatus.pr.checksPassed': '{count} 件成功',
'chat.workStatus.attention.merge': 'マージ実行中',
'chat.workStatus.attention.rebase': 'リベース実行中',
'chat.workStatus.attention.cherryPick': 'チェリーピック実行中',
'chat.workStatus.attention.revert': 'リバート実行中',
'chat.workStatus.attention.bisect': '二分探索実行中',
'chat.workStatus.subagent.done': '完了',
'chat.workStatus.subagent.untitled': 'サブエージェント',
'chat.workStatus.mcp.toggle': '{name} を切り替え',
'chat.workStatus.mcp.needsAuth': 'サインイン',
'chat.workStatus.mcp.failed': '失敗',
'chat.workStatus.pinned.unavailable': 'ピン留めしたメッセージ',
'chat.workStatus.section.session': 'セッション',
'chat.workStatus.section.repository': 'リポジトリ',
'chat.workStatus.section.subagents': 'サブエージェント',
'chat.workStatus.section.mcp': 'MCP',
'chat.workStatus.section.pinned': 'ピン留めしたメッセージ',
'chat.workStatus.section.tasks': 'タスク',
'chat.workStatus.subagent.working': '作業中',
'chat.workStatus.subagent.needsPermission': '許可が必要',
'chat.workStatus.subagent.askedQuestion': '質問があります',
'chat.workStatus.section.contextBreakdown': 'コンテキストソース',
'chat.workStatus.breakdown.skills': 'スキル',
'chat.workStatus.breakdown.mcp': 'MCP サーバー',
'chat.workStatus.action.openChanges': '変更を開く',
'chat.workStatus.action.openGit': 'Git パネルを開く',
'chat.workStatus.action.openPr': 'プルリクエストを開く',
'chat.workStatus.action.openSubagent': '{name} を開く',
'chat.workStatus.section.usage': '使用量',
'chat.workStatus.goal.open': '目標を管理',
'chat.workStatus.goal.pause': '一時停止',
'chat.workStatus.goal.resume': '再開',
'chat.workStatus.goal.updateFailed': '目標を更新できませんでした',
'chat.workStatus.pinned.unpin': 'ピン留めを解除',
'chat.workStatus.pinned.reveal': 'メッセージへ移動',
'chat.workStatus.pinned.unpinFailed': 'ピン留めを解除できませんでした',
'chat.workStatus.action.openContext': 'コンテキストパネルを開く',
'chat.workStatus.section.linkedIssues': 'リンク済み',
'chat.workStatus.linkedIssues.open': 'GitHub で #{number} を開く',
'chat.workStatus.linkedIssues.unlink': 'リンクを解除',
'chat.workStatus.linkedIssues.unlinkFailed': 'リンクを解除できませんでした',
'chat.workStatus.linkedIssues.link': 'セッションにリンク',
'chat.workStatus.linkedIssues.linkFailed': 'リンクできませんでした',
'chat.workStatus.breakdown.issueCountSingle': 'Issue {count} 件',
'chat.workStatus.breakdown.issueCountPlural': 'Issue {count} 件',
'chat.workStatus.breakdown.prCountSingle': 'PR {count} 件',
'chat.workStatus.breakdown.prCountPlural': 'PR {count} 件',
'chat.workStatus.breakdown.skillCountSingle': 'スキル {count} 個',
'chat.workStatus.breakdown.skillCountPlural': 'スキル {count} 個',
'chat.workStatus.breakdown.mcpCountSingle': 'MCP {count} 個',
'chat.workStatus.breakdown.mcpCountPlural': 'MCP {count} 個',
'chat.workStatus.sections.open': 'セクションを選択',
'chat.workStatus.sections.dialogTitle': 'パネルのセクション',
'chat.workStatus.sections.dialogDescription': '作業状況パネルに表示する内容を選びます。非表示のセクションもデータは保持され、表示されないだけです。',
'header.workStatusPanel.toggleAria': '作業状況パネルを切り替え',
'header.workStatusPanel.hide': '作業状況を非表示',
'header.workStatusPanel.show': '作業状況を表示',
'chat.workStatus.mcp.authorizeOpenFailed': '認証ページを開けませんでした',
'chat.workStatus.mcp.authorizeFailed': '認証に失敗しました',
'mcpDropdown.toast.authorizeOpenFailed': '認証ページを開けませんでした',
'mcpDropdown.toast.authorizeFailed': '認証に失敗しました',
'header.services.tooltip.currentInstance': '現在のインスタンス: {current}({toggle})',
'header.workStatusPanel.showOverlay': 'チャットの上に作業状況を表示',
'settings.mcp.page.connection.title': '接続方法',
'settings.mcp.page.connection.description': '起動コマンド、またはホスト型サーバーのリンクを貼り付けます。',
'settings.mcp.page.registration.title': 'このサーバーには専用アプリが必要です',
'settings.mcp.page.registration.description': '認証情報を自動発行しません。サービス側の設定でアプリを作成し、その情報をここに貼り付けてサインインしてください。',
'settings.mcp.page.registration.callbackLabel': 'この住所をサービスに登録してください',
'settings.mcp.page.registration.clientId': 'アプリ ID',
'settings.mcp.page.registration.clientSecret': 'アプリシークレット',
'settings.mcp.page.registration.afterSaving': '保存してから「認証」を押してください。',
'settings.mcp.page.toast.copiedCallbackUrl': '住所をコピーしました',
'settings.mcp.page.toast.clipboardWriteFailed': 'クリップボードにコピーできませんでした',
'settings.mcp.page.scope.everywhere': 'すべてのプロジェクトで利用可能',
'settings.mcp.page.scope.thisProject': 'このプロジェクトのみ',
'settings.mcp.page.env.description': 'API キーなど、サーバーが必要とする値。',
'settings.mcp.page.connection.kindCommand': 'コマンド',
'settings.mcp.page.connection.kindLink': 'リンク',
'settings.mcp.page.connection.hintCommand': 'このマシンで実行します。コマンド全体を貼り付けると、1 行に 1 引数へ分割されます。',
'settings.mcp.page.connection.hintLink': '他者がホストするサーバーに接続します。その https アドレスを貼り付けてください。',
};