Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ All notable changes to DreamCoder will be documented in this file.

- **Sessions can start other sessions and message each other.** The agent can start a new session with `StartSession`, either fresh with a brief or as a fork of its own conversation, optionally in a new git worktree; you approve every new session, whatever the permission mode. Any session can message any other with `SendMessage`, across projects: a message wakes the receiver, and a progress report from a child to its parent waits for the parent's next turn instead of interrupting it (a parent that is already working sees it right away). Reports waiting for the parent are listed above its message box. The server stamps who sent each message, so a session cannot pass itself off as you or as another session. `ListSessions` lists sessions, and `RenameSession` lets the agent rename its own session (#239).
- **Sessions are nested in the sidebar.** Sessions the agent started, and conversations you forked, appear under the session they came from, with an icon for each kind and a count that collapses or expands them. Messages from another session appear in the conversation as a one-line row with the sender, which expands to the full text (#239).
- **Project board.** Each project gets a persistent board of tasks and sub-tasks that you and your sessions share; every worktree of the project uses the same board. Open it from the project in the sidebar. A task records its owner, reviewer and creator, acceptance criteria, priority, dependencies, progress, and the owner's and reviewer's reports. Sessions read and update the board with four tools (`KanbanList`, `KanbanGet`, `KanbanCreate`, `KanbanUpdate`): they split work into sub-tasks, record progress, block a task with a question, submit their work and review it. The board notifies the sessions involved when they are assigned, when work is submitted, blocked, sent back, reset or cancelled, and when you comment. `StartSession` can start a session as a task's owner or reviewer. The board page has a board view and a hierarchy view, opens a task in the side panel, and lists what waits on you under "Needs me": blocked tasks, deliveries to accept and tasks whose owner session is gone. You approve every time a session creates the board, starts a session on a task, cancels a task, changes acceptance criteria it did not set, or makes itself a reviewer; only a task's creator or you choose its reviewer (#242).

### Changed

- **A message you send while the agent is working waits for the next turn.** It used to be slipped into the running turn. Queued messages are listed above the message box, where you can withdraw one or send the queue now, which stops the current turn and starts the next one; Stop does the same while messages are queued. Queued messages survive a model or permission change that restarts the agent at the end of the turn (#239).

### Fixed

- Permission prompts that ask every time, such as starting a session or editing files under `.git/`, no longer offer "Allow for this session", which could not take effect (#242).
- Tools sent to providers through the OpenAI Responses API are no longer in strict mode, so their optional parameters stay optional (#242).
- Confirmation dialogs keep long workspace paths inside their bounds, so Cancel and Enable remain visible when enabling bypass permissions (#226). Thanks @imshah-id.
- Reading environment files, credential files, and SSH private keys now requires explicit approval through both the Read tool and read-only Bash commands. Recursive directory reads, Grep tool glob filters, and files read from Git history are not covered yet (#235). Thanks @AIR-Xie.
- The exact shell no-op `:` is recognized as read-only and no longer requires approval (#235). Thanks @AIR-Xie.
Expand Down
32 changes: 28 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ DreamCoder runs its desktop app and session service locally, bringing model conf
* **Follow the work**: Review sessions, file changes, terminal activity, and tool calls on your desktop.
* **See it, not just read it**: The agent can answer with interactive pages (charts, diagrams, step-by-step walkthroughs) shown right in the conversation, and a built-in browser shows your dev server next to the chat.
* **Design and clone**: Start from 60+ templates and 156+ design systems with `/design`: the agent interviews you first, then builds a web page or app prototype. It can also clone a website. Results are kept in your project's `dc_artifacts/`, ready to export, keep editing, or compare side by side on a canvas.
* **Plan work on a board**: A project board keeps tasks, owners, reviewers and progress for you and your sessions, across sessions and worktrees.
* **Continue on your phone**: Enable H5 Access to reach desktop sessions from a phone browser on the same LAN. Access across networks requires a reverse proxy you configure yourself.
* **Learn how a coding agent works**: A seven-part source code walkthrough follows one code change through the execution loop, tools, permissions, sessions, and desktop integration. See the [Coding Agent Implementation Guide](docs/tutorial/README.en.md).

Expand Down Expand Up @@ -121,7 +122,30 @@ Provider settings and API keys are stored in local files. When you use a cloud m

The templates and most of the design systems are converted from [Open Design](https://github.com/nexu-io/open-design) (Apache-2.0); see [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).

### 4. Multi-Provider Configuration
### 4. Project Board
* **One board for you and your sessions**: Each project gets a persistent board of tasks and sub-tasks. You create and assign tasks there; sessions read the board, split their work into sub-tasks, record progress and submit a report when they finish. The board outlives the sessions, and every worktree of the project shares it.
* **Owner, reviewer and creator**: Each task records who does it, who reviews it and who created it. The reviewer checks the delivery against the acceptance criteria and accepts it or sends it back; without a reviewer, you accept it. The hierarchy view shows the whole task tree, and Needs me collects what waits on you: a blocked task with the session's question, or a delivery to accept.
* **You stay in charge**: The creator sets a task's acceptance criteria. When another session wants to change them, it asks you every time, and the card shows which criteria are added and removed. Sessions also ask before they create the board, start a session on a task, cancel a task or make themselves a reviewer.

<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/dark/kanban.png">
<img src="./assets/kanban.png" alt="The project board with a task open in the side panel: status, owner, reviewer with review instructions, and the delivery report" width="49%">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/dark/kanban-approval.png">
<img src="./assets/kanban-approval.png" alt="A session asks to change a task's acceptance criteria; the card lists the added and removed criteria" width="49%">
</picture>

<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/dark/kanban-tree.png">
<img src="./assets/kanban-tree.png" alt="The hierarchy view: tasks and sub-tasks with status, assignee and dependencies" width="49%">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/dark/kanban-inbox.png">
<img src="./assets/kanban-inbox.png" alt="Needs me: a blocked task with the session's question and a delivery waiting for acceptance" width="49%">
</picture>

### 5. Multi-Provider Configuration
* **Presets and custom endpoints**: Set the API key, endpoint, and model mapping for your chosen provider.
* **Connection check**: Test the availability and latency of configured endpoints in Settings.

Expand All @@ -130,7 +154,7 @@ The templates and most of the design systems are converted from [Open Design](ht
<img src="./assets/setting_provider.png" alt="Adding a provider from a preset">
</picture>

### 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.
Expand All @@ -140,11 +164,11 @@ The templates and most of the design systems are converted from [Open Design](ht
<img src="./assets/setting_computeruse.png" alt="Computer Use settings">
</picture>

### 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.

<picture>
Expand Down
32 changes: 28 additions & 4 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ DreamCoder 在本机运行桌面应用与会话服务,把模型配置、编程
* **看清编程过程**:在桌面查看会话、文件变更、终端和工具调用。
* **不只是文字**:AI 可以直接在对话里给出可交互的页面,如图表、示意图、分步演示;内置浏览器能在对话旁边打开你的开发服务器。
* **设计与复刻**:用 `/design` 从 60+ 个模板和 156+ 套设计系统出发,Agent 先访谈再动手,做出网页或应用原型;也能复刻网站。成果保存在项目的 `dc_artifacts/` 里,可导出、可继续改、可在画布上并排比较。
* **在看板上安排工作**:项目看板为你和会话记录任务、负责人、审核人和进展,跨会话、跨 worktree 保留。
* **从手机接续**:启用 H5 接入后,可在同一局域网内通过手机浏览器访问桌面会话;跨网络访问需要自行配置反向代理。
* **读懂编程智能体**:附带七篇源码导读,沿一次代码修改讲解执行循环、工具、权限、会话与桌面集成,见[《编程智能体实现指南》](docs/tutorial/README.md)。

Expand Down Expand Up @@ -121,7 +122,30 @@ Provider 配置和 API Key 保存在本机文件中。使用云端模型时,

模板和大部分设计系统转换自 [Open Design](https://github.com/nexu-io/open-design)(Apache-2.0),详见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。

### 4. 多模型配置
### 4. 项目看板
* **你和会话共用一块看板**:每个项目一块持久的看板,记录任务和子任务。你在看板上建任务、分配给会话;会话读看板,把工作拆成子任务,记录进展,做完提交交付报告。会话结束了看板还在,同一项目的各个 worktree 共用同一块看板。
* **负责人、审核人和创建者**:每个任务记着谁来做、谁来审、谁建的。审核人对照验收要点检查交付,接受或退回;没有审核人时由你验收。层级视图展示整棵任务树,"待我处理" 汇总等你处理的事:带着会话提问的阻塞任务,和等你验收的交付。
* **由你把关**:验收要点由任务的创建者定。其他会话要改时每次都要你确认,确认卡片列出新增和删除的要点。会话建看板、开新会话做任务、取消任务、把自己设为审核人之前,也都会先问你。

<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/dark/kanban.png">
<img src="./assets/kanban.png" alt="打开任务详情的项目看板:状态、负责人、带审核说明的审核人和交付报告" width="49%">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/dark/kanban-approval.png">
<img src="./assets/kanban-approval.png" alt="会话请求修改任务的验收要点,确认卡片列出新增和删除的要点" width="49%">
</picture>

<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/dark/kanban-tree.png">
<img src="./assets/kanban-tree.png" alt="层级视图:任务和子任务,带状态、负责人和依赖" width="49%">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/dark/kanban-inbox.png">
<img src="./assets/kanban-inbox.png" alt="待我处理:一条带会话提问的阻塞任务,一条等待验收的交付" width="49%">
</picture>

### 5. 多模型配置
* **Provider 预设与自定义端点**:按所选服务商配置 API Key、地址与模型映射。
* **连接检查**:在设置界面测试已配置端点的可用性与延迟。

Expand All @@ -130,7 +154,7 @@ Provider 配置和 API Key 保存在本机文件中。使用云端模型时,
<img src="./assets/setting_provider.png" alt="从预设添加 Provider">
</picture>

### 5. Claude Code 工作流
### 6. Claude Code 工作流
* **Computer Use**:在后台按界面元素操作桌面应用和浏览器,由 [cua-driver](https://github.com/trycua/cua)(MIT)驱动。开启时 DreamCoder 自动下载,不需要 Python。macOS 已验证;Windows 有待社区实测,Linux 为预览。
* **工具调用全程可见**:AI 读写文件、执行终端命令的过程透明呈现,便于理解与审查。
* **MCP 扩展能力**:通过 Model Context Protocol 持续扩展 AI 的上下文与工具能力。
Expand All @@ -140,13 +164,13 @@ Provider 配置和 API Key 保存在本机文件中。使用云端模型时,
<img src="./assets/setting_computeruse.png" alt="Computer Use 设置">
</picture>

### 6. 局域网内手机接续
### 7. 局域网内手机接续
* **H5 接入**:在设置中开启访问、管理 Token,并使用二维码从同一局域网内的手机连接。
* **访问范围**:桌面端需保持运行;跨网络访问需要自行配置反向代理,相关部署指南仍在编写。

---

### 7. MCP 扩展
### 8. MCP 扩展
* **支持 MCP**:通过 Model Context Protocol 接入外部工具。
* **配置过程图形化**:不再手写 JSON,通过界面管理 MCP 服务器。

Expand Down
Binary file added assets/dark/kanban-approval.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/dark/kanban-inbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/dark/kanban-tree.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/dark/kanban.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/kanban-approval.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/kanban-inbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/kanban-tree.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/kanban.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions desktop/src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(method: string, path: string, body?: unknown, options?: { timeout?: number }): Promise<T> {
const url = `${baseUrl}${path}`
const headers = buildHeaders()
Expand Down
32 changes: 32 additions & 0 deletions desktop/src/api/kanban.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { BoardListing, BoardView, KanbanCommand, KanbanEvent } from '@protocol'
import { api } from './client'

export type BoardPoll = { changed: true; view: BoardView } | { changed: false; etag: string }

export type CommandOutcome = { view: BoardView; warnings: string[]; card?: number }

function boardPath(key: string) {
return `/api/kanban/boards/${encodeURIComponent(key)}`
}

export const kanbanApi = {
listBoards() {
return api.get<{ boards: BoardListing[] }>('/api/kanban/boards')
},

createBoard(project: string) {
return api.post<{ view: BoardView }>('/api/kanban/boards', { project })
},

view(key: string, since?: string) {
return api.get<BoardPoll>(since ? `${boardPath(key)}?since=${encodeURIComponent(since)}` : boardPath(key))
},

command(key: string, command: KanbanCommand) {
return api.post<CommandOutcome>(`${boardPath(key)}/commands`, { command })
},

history(key: string, card: number) {
return api.get<{ events: KanbanEvent[] }>(`${boardPath(key)}/cards/${card}/history`)
},
}
1 change: 1 addition & 0 deletions desktop/src/components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ that only renames props or passes them through does not belong here.
| `FormSelect` | Select with labelled triggers and empty application values encoded as nonempty Radix item values |
| `Modal` | Dialog, localized close action and existing modal props |
| `ConfirmDialog` | Alert Dialog with application confirmation callbacks |
| `TreeConnector` | Elbow lines between nested rows, shared by the sidebar session tree and the board's hierarchy view |
| `MobileBottomSheet` | Drawer with localized title and close control |
| `Tooltip` | The tooltip entry point: a Tooltip and content wrapper that keeps the trigger mounted when the content is empty; the single `TooltipProvider` (400 ms delay) is mounted in `App`. `ActivitySettings` and `TerminalSettings` use `ui/tooltip` directly because they need an instant delay, a controlled open state or custom content |
| `ActionMenu` | Shared Dropdown Menu and Context Menu actions/focus handling; the dropdown also takes single-choice submenus (`MenuChoiceGroup`) |
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/components/chat/DesignTemplateChoice.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ describe('DesignTemplateChoice', () => {
'/app/design-templates/saas/index.html',
'/app/design-templates/saas',
))
expect(useWorkspacePanelStore.getState().panelBySession[SESSION]?.tabs[0]).toMatchObject({ kind: 'browser', template: { id: 'saas' } })
expect(useWorkspacePanelStore.getState().panelByTab[SESSION]?.tabs[0]).toMatchObject({ kind: 'browser', template: { id: 'saas' } })
})

it('tells the user when the preview could not be opened', async () => {
Expand Down
7 changes: 4 additions & 3 deletions desktop/src/components/chat/MessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useUIStore } from '../../stores/uiStore'
import { useTranslation } from '../../i18n'
import type { TranslationKey } from '../../i18n/locales/en'
import { UserMessage } from './UserMessage'
import { SessionMessageCard } from './SessionMessageCard'
import { OriginMessageCard } from './OriginMessageCard'
import { AssistantMessage } from './AssistantMessage'
import { StreamingReply } from './StreamingReply'
import { ThinkingBlock } from './ThinkingBlock'
Expand Down Expand Up @@ -2045,8 +2045,8 @@ export const MessageBlock = memo(function MessageBlock({

switch (message.type) {
case 'user_text':
if (message.origin?.kind === 'session') {
return <SessionMessageCard content={message.content} origin={message.origin} timestamp={message.timestamp} />
if (message.origin) {
return <OriginMessageCard content={message.content} origin={message.origin} timestamp={message.timestamp} />
}
return (
<SelectableChatMessage
Expand Down Expand Up @@ -2134,6 +2134,7 @@ export const MessageBlock = memo(function MessageBlock({
toolName={message.toolName}
input={message.input}
description={message.description}
alwaysAsks={message.alwaysAsks}
resolution={message.resolution}
/>
)
Expand Down
Loading
Loading