+
+
+
+
-### 5. Claude Code Workflows
+### 6. Claude Code Workflows
* **Computer Use**: operates desktop apps and browsers in the background through UI elements, powered by [cua-driver](https://github.com/trycua/cua) (MIT). DreamCoder downloads it when you turn Computer Use on; no Python needed. Verified on macOS; Windows needs community testing, Linux is a preview.
* **Transparent tool execution**: File edits and terminal commands are surfaced clearly, so it's easy to understand and review what the agent is doing.
* **MCP extensibility**: Expand context and tooling through the Model Context Protocol.
@@ -140,11 +164,11 @@ The templates and most of the design systems are converted from [Open Design](ht
-### 6. Continue on Your Phone over LAN
+### 7. Continue on Your Phone over LAN
* **H5 Access**: Enable access in Settings, manage the token, and use the QR code to connect a phone on the same LAN.
* **Access scope**: Keep the desktop app running. Cross-network access requires your own reverse proxy; the deployment guide is still in progress.
-### 7. MCP Extensions
+### 8. MCP Extensions
* **Visual configuration**: Manage MCP servers in the UI instead of editing JSON by hand.
+
+
+
+
-### 6. 局域网内手机接续
+### 7. 局域网内手机接续
* **H5 接入**:在设置中开启访问、管理 Token,并使用二维码从同一局域网内的手机连接。
* **访问范围**:桌面端需保持运行;跨网络访问需要自行配置反向代理,相关部署指南仍在编写。
---
-### 7. MCP 扩展
+### 8. MCP 扩展
* **支持 MCP**:通过 Model Context Protocol 接入外部工具。
* **配置过程图形化**:不再手写 JSON,通过界面管理 MCP 服务器。
diff --git a/assets/dark/kanban-approval.png b/assets/dark/kanban-approval.png
new file mode 100644
index 00000000..f20fa59b
Binary files /dev/null and b/assets/dark/kanban-approval.png differ
diff --git a/assets/dark/kanban-inbox.png b/assets/dark/kanban-inbox.png
new file mode 100644
index 00000000..519e2af7
Binary files /dev/null and b/assets/dark/kanban-inbox.png differ
diff --git a/assets/dark/kanban-tree.png b/assets/dark/kanban-tree.png
new file mode 100644
index 00000000..742a8d23
Binary files /dev/null and b/assets/dark/kanban-tree.png differ
diff --git a/assets/dark/kanban.png b/assets/dark/kanban.png
new file mode 100644
index 00000000..68623750
Binary files /dev/null and b/assets/dark/kanban.png differ
diff --git a/assets/kanban-approval.png b/assets/kanban-approval.png
new file mode 100644
index 00000000..d6c3e58c
Binary files /dev/null and b/assets/kanban-approval.png differ
diff --git a/assets/kanban-inbox.png b/assets/kanban-inbox.png
new file mode 100644
index 00000000..e846268a
Binary files /dev/null and b/assets/kanban-inbox.png differ
diff --git a/assets/kanban-tree.png b/assets/kanban-tree.png
new file mode 100644
index 00000000..96997c8a
Binary files /dev/null and b/assets/kanban-tree.png differ
diff --git a/assets/kanban.png b/assets/kanban.png
new file mode 100644
index 00000000..b2294804
Binary files /dev/null and b/assets/kanban.png differ
diff --git a/desktop/src/api/client.ts b/desktop/src/api/client.ts
index 1ec3f4e0..824cee3d 100644
--- a/desktop/src/api/client.ts
+++ b/desktop/src/api/client.ts
@@ -69,6 +69,13 @@ export class ApiError extends Error {
}
}
+export function apiErrorCode(error: unknown): string | null {
+ if (!(error instanceof ApiError)) return null
+ const body = error.body
+ if (!body || typeof body !== 'object' || !('error' in body)) return null
+ return typeof body.error === 'string' ? body.error : null
+}
+
async function request{loadError}
:{t('kanban.detail.notFound', { card: `#${id}` })}
+ ) : ( +{t('kanban.detail.ownerMissing')}
} + +{error}
+ if (!events) return{t('common.loading')}
+ const now = Date.now() + const entries = entriesFor(t, view, card, events).reverse() + + return ( +{note}
+ ))} + +{listError}
+ :+ {projectName(project)} +
+{loadError}
+ :+ {t('kanban.error.refreshFailed', { message: loadError })} +
+ )} +