feat(chat): terminal chat parity for every tool; Desktop-like artifacts

- The chat over a terminal pane now covers Claude, Codex, omp, Cursor and
  Antigravity: Cursor's agent transcript and agy's step log
  (brain/<id>/.system_generated/logs/transcript_full.jsonl) are read as
  conversations; Cursor sessions are claimed by their workspace
- Replies appear as soon as they are written: the projects-tree watcher
  broadcasts `transcript_changed` (at most every 250 ms per session) and the
  chat re-reads the transcript while the terminal underneath draws
- Stop shows from the pane's own busy line (Claude/Codex `esc to interrupt`,
  agy `… esc to cancel`), or fresh output for omp/Cursor — no hooks needed
- Permission prompts read off the terminal become a card with the tool, its
  command and "Deny with a note"; Codex gets Permission mode / Model buttons
  that open its own numbered pickers, answered from the menu card
- Artifacts: cards for pages/documents/diagrams/tables/React components, a
  Preview | Code panel with versions, copy, download, save to the Artifacts
  Hub, full screen; sandboxed iframes without allow-same-origin
- Claude panes get CLAUDE_CODE_ENABLE_TODO_TOOLS=1 so the Progress panel has a
  plan; multi-question pane menus read their Next row and question tabs
- The realtime chat bridge (structured stdio, /api/chat-bridge, /ws-chat)
  from the unreleased ad9d475 is not kept
This commit is contained in:
2026-10-21 15:44:17 +07:00
parent aee4fc190e
commit 383b9ae231
41 changed files with 2582 additions and 426 deletions
+23 -1
View File
@@ -89,6 +89,7 @@
"findClose": "Close find"
},
"chat": {
"codexPicker": "Opens Codex's own picker — answer it in the chat",
"placeholder": "Write a message…",
"send": "Send",
"notSent": "The terminal is not connected — the message was not sent.",
@@ -139,7 +140,28 @@
},
"menu": {
"placeholder": "Type your answer…",
"cancel": "Cancel (Esc)"
"cancel": "Cancel (Esc)",
"prev": "Previous question",
"next": "Next question"
},
"request": {
"notePlaceholder": "Tell the model what to do instead…",
"send": "Send",
"denyWithNote": "Deny with a note"
},
"artifact": {
"preview": "Preview",
"code": "Code",
"copy": "Copy",
"download": "Download",
"share": "Save to Artifacts",
"shared": "Saved to your Artifacts library — share it from the Artifacts page.",
"cannotShare": "This file cannot be saved to Artifacts.",
"expand": "Full screen",
"collapse": "Exit full screen",
"older": "Older version",
"newer": "Newer version",
"version": "Version {{n}} of {{total}}"
}
},
"interrupted": {
+9
View File
@@ -230,6 +230,15 @@
"stopped": "stopped"
},
"hide": "Hide conversation"
},
"artifact": {
"html": "Web page",
"svg": "Image · SVG",
"markdown": "Document",
"mermaid": "Diagram",
"react": "React component",
"csv": "Table",
"open": "Click to open"
}
},
"overview": {
+2 -2
View File
@@ -1302,9 +1302,9 @@
},
"chatUi": {
"title": "Chat UI",
"description": "How a new Claude or Codex session opens in its workspace. Saved for your account only.",
"description": "How a new Claude, Codex, omp, Cursor or Antigravity session opens in its workspace. Saved for your account only.",
"label": "Open new sessions as a chat",
"labelDesc": "A Claude or Codex session first shows its conversation like Claude Desktop, with a message box, instead of its terminal. Each session then keeps its own view: the chat/terminal button beside a pane's split buttons switches it. Permission prompts and menus still need the terminal.",
"labelDesc": "A new session first shows its conversation like Claude Desktop, with a message box, instead of its terminal (the terminal stays underneath). Each session then keeps its own view: the chat/terminal button beside a pane's split buttons switches it. Permission prompts and questions are answered from cards in the chat.",
"saveFailed": "Could not save: {{message}}"
},
"sessionDefaults": {
+23 -1
View File
@@ -89,6 +89,7 @@
"findClose": "Đóng tìm kiếm"
},
"chat": {
"codexPicker": "Mở bộ chọn của chính Codex — trả lời ngay trong chat",
"placeholder": "Viết tin nhắn…",
"send": "Gửi",
"notSent": "Terminal chưa kết nối — tin nhắn chưa được gửi.",
@@ -139,7 +140,28 @@
},
"menu": {
"placeholder": "Nhập câu trả lời của bạn…",
"cancel": "Huỷ (Esc)"
"cancel": "Huỷ (Esc)",
"prev": "Câu trước",
"next": "Câu tiếp"
},
"request": {
"notePlaceholder": "Nói cho model biết nên làm gì thay vào đó…",
"send": "Gửi",
"denyWithNote": "Từ chối kèm lời nhắn"
},
"artifact": {
"preview": "Xem trước",
"code": "Mã",
"copy": "Sao chép",
"download": "Tải xuống",
"share": "Lưu vào Artifacts",
"shared": "Đã lưu vào thư viện Artifacts của bạn — chia sẻ từ trang Artifacts.",
"cannotShare": "Không lưu được file này vào Artifacts.",
"expand": "Toàn màn hình",
"collapse": "Thoát toàn màn hình",
"older": "Phiên bản cũ hơn",
"newer": "Phiên bản mới hơn",
"version": "Phiên bản {{n}}/{{total}}"
}
},
"interrupted": {
+9
View File
@@ -230,6 +230,15 @@
"stopped": "đã dừng"
},
"hide": "Ẩn hội thoại"
},
"artifact": {
"html": "Trang web",
"svg": "Ảnh · SVG",
"markdown": "Tài liệu",
"mermaid": "Sơ đồ",
"react": "Component React",
"csv": "Bảng",
"open": "Bấm để mở"
}
},
"overview": {
+2 -2
View File
@@ -1302,9 +1302,9 @@
},
"chatUi": {
"title": "Giao diện chat",
"description": "Cách một session Claude hoặc Codex mới mở trong workspace. Chỉ lưu cho tài khoản của bạn.",
"description": "Cách một session Claude, Codex, omp, Cursor hoặc Antigravity mới mở trong workspace. Chỉ lưu cho tài khoản của bạn.",
"label": "Mở session mới dạng chat",
"labelDesc": "Session Claude hoặc Codex sẽ mở hội thoại như Claude Desktop, kèm ô nhập tin, thay cho terminal. Sau đó mỗi session giữ dạng xem riêng: nút chat/terminal cạnh nút split của pane để chuyển. Hỏi quyền và menu vẫn cần terminal.",
"labelDesc": "Session mới sẽ mở hội thoại như Claude Desktop, kèm ô nhập tin, thay cho terminal (terminal vẫn chạy bên dưới). Sau đó mỗi session giữ dạng xem riêng: nút chat/terminal cạnh nút split của pane để chuyển. Hỏi quyền và câu hỏi được trả lời bằng thẻ ngay trong chat.",
"saveFailed": "Không lưu được: {{message}}"
},
"sessionDefaults": {