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 .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

set -e

echo "▎ pre-commit: format check"
pnpm format:check

echo "▎ pre-commit: lint"
pnpm lint

Expand Down
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ coverage
pnpm-lock.yaml
docs/VISUAL_DESIGN.html
reference
.claude
release-artifacts
target
15 changes: 13 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.1.6] — 2026-05-28

### 🐛 Critical fix — Bash tool calls were always reporting "error"

The Rust output structs (`ReadOk`, `EditOk`, `BashOk`) returned fields
in snake_case (`exit_code`, `lines_total`, `diff_preview`) while the
TS wrappers read them in camelCase. Result: `r.exitCode` was always
Expand All @@ -21,6 +22,7 @@ output structs. Glob and Grep were already single-word fields, no
change needed.

### Polish carry-over

- **Keyboard shortcuts**: ⌘N starts a new session, ⌘, opens Settings,
⌘/ opens About. New `src/lib/keyboard.ts` helper.
- **Switching project now clears chat history** so the next message
Expand All @@ -30,6 +32,7 @@ change needed.
## [0.1.5] — 2026-05-28

### Polish + dead-code removal

- **Composer `+` menu wired**. Click `+` → popover with three actions:
Attach file (opens native file picker, inserts `@<absolute-path>`
into the textarea), Slash command (prepends `/`), Memory note
Expand All @@ -51,6 +54,7 @@ change needed.
## [0.1.4] — 2026-05-28

### Robustness + polish

- **React error boundary** wraps the entire app. Uncaught render errors
now show a recoverable error panel ("DeepCode crashed") with the
stack trace + reload button, instead of leaving the user with a
Expand All @@ -64,12 +68,13 @@ change needed.
## [0.1.3] — 2026-05-28

### Visual redesign — phase 2

- **All 7 utility screens** (Sessions / Plugins / Skills / Permissions /
MCP / Settings / About) redesigned to match `docs/VISUAL_DESIGN.html`.
New shared `Screen` + `Card` + `Row` primitives.
- **About** is now a proper hero card with brand mark + gradient text
+ status diagnostics + docs links (replacing the boxed table layout
the user shared as visually off-spec).
- status diagnostics + docs links (replacing the boxed table layout
the user shared as visually off-spec).
- **Settings** has a GUI/JSON segmented toggle: GUI shows a quick
reference + filterable flat table; JSON shows a live-validated
textarea. Save persists to ~/.deepcode/settings.json (was
Expand All @@ -81,13 +86,15 @@ change needed.
- **MCP** uses status badges + tool count + inline error tail.

### Release pipeline (M9)

- `release.yml` rewritten for Tauri (was Electron-era). Tag → CI
→ npm publish + signed/notarized DMG + GitHub Release with notes.
- `docs/RELEASING.md` explains the 6 secrets needed and step-by-step.

## [0.1.2] — 2026-05-28

### Fixes — caught from user playtest of 0.1.1

- **Tool input field-name fix.** `tool_write` (and read / edit / bash /
glob / grep) were failing with `missing required key filePath` when
DeepSeek emitted snake_case keys but the wrapper expected camelCase.
Expand All @@ -109,6 +116,7 @@ change needed.
Skills, MCP, About, Settings). Expand-chevron ‹ still deferred.

### UX improvements

- **Proper dropdowns** for mode / model / effort — click-popover with
inline descriptions and meta annotations, replacing the brittle
click-to-cycle pattern.
Expand All @@ -120,6 +128,7 @@ change needed.
## [0.1.1] — 2026-05-28

### Visual redesign — phase 1

Major UI overhaul aligning the desktop client to `docs/VISUAL_DESIGN.html`.
Phase 1 covers the three highest-traffic surfaces: Onboarding, Sessions
sidebar, and the main Chat / REPL view. Other six screens land in 0.1.2.
Expand All @@ -143,6 +152,7 @@ sidebar, and the main Chat / REPL view. Other six screens land in 0.1.2.
text headline matching the design spec.

### Conversation flow

- Carries over the `dangerouslyAllowBrowser: true` fix from 0.1.0 so the
OpenAI SDK's browser-environment guard doesn't trip in the Tauri webview
- Surfaces full error stack traces in the chat stream when the agent
Expand All @@ -152,6 +162,7 @@ sidebar, and the main Chat / REPL view. Other six screens land in 0.1.2.
## [0.1.0] — 2026-05-28

### Mac client + CLI baseline

- **CLI:** agent loop, 30+ slash commands, MCP support, plugin system,
sandbox, hooks, modes, skills, sub-agents, output styles, effort
levels, headless `-p` mode
Expand Down
27 changes: 14 additions & 13 deletions MORNING_REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
本轮 (v6 → v7) 又推了 3 个 feature PR + 这个汇报。重点是为 v1.1 开了头:
VS Code 扩展 + LSP bridge,让 DeepCode 进入 IDE 生态。

| # | 主题 | 主要内容 |
| --- | --- | --- |
| #55 | v1.1 入口 — VS Code + LSP | `apps/vscode` 扩展骨架(commands + Chat 视图 + 配置) · `apps/lsp` stdio LSP 服务器 + JSON-RPC handler + 3 个 custom commands + 8 个单元测试 + Neovim/Emacs/Sublime 配置示例 |
| #56 | schema + image + migration | `packages/core/schemas/settings.schema.json` (draft-07 全覆盖) + `validateSettingsShallow` + Vision 接口(Stub + OpenAICompat with 14 tests)+ `docs/MIGRATION_FROM_CLAUDE_CODE.md` 5 分钟切换指南 |
| 本 PR | README 完善 + 报告 | 重写 README.md:状态从 "M0 设计阶段" 改为生产级 progress bar / 文档地图 / 项目结构表 · 本汇报 v7 |
| # | 主题 | 主要内容 |
| ----- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| #55 | v1.1 入口 — VS Code + LSP | `apps/vscode` 扩展骨架(commands + Chat 视图 + 配置) · `apps/lsp` stdio LSP 服务器 + JSON-RPC handler + 3 个 custom commands + 8 个单元测试 + Neovim/Emacs/Sublime 配置示例 |
| #56 | schema + image + migration | `packages/core/schemas/settings.schema.json` (draft-07 全覆盖) + `validateSettingsShallow` + Vision 接口(Stub + OpenAICompat with 14 tests)+ `docs/MIGRATION_FROM_CLAUDE_CODE.md` 5 分钟切换指南 |
| 本 PR | README 完善 + 报告 | 重写 README.md:状态从 "M0 设计阶段" 改为生产级 progress bar / 文档地图 / 项目结构表 · 本汇报 v7 |

## 状态对照

Expand Down Expand Up @@ -75,14 +75,14 @@ Marketplace 上线 ████████░░░░░

## 6 个包的最终矩阵

| 包 | 状态 | 测试 | 备注 |
| --- | --- | --- | --- |
| `@deepcode/core` | ✅ ship-ready | 478 | 内核,UI-agnostic,npm 可发 |
| `@deepcode/shared-ui` | ✅ ship-ready | 0 (types-only) | 共享类型 |
| `deepcode-cli` | ✅ ship-ready | 47 | npm 可发,npx 可跑 |
| `@deepcode/desktop` | 🟡 等装 Electron | 0 (TBD) | UI/IPC/build 配置全在 |
| `@deepcode/vscode` | 🟡 v1.1 骨架 | 0 (TBD) | manifest + extension.ts 骨架 |
| `@deepcode/lsp` | 🟡 v1.1 骨架 | 8 | stdio server + handler 完整 |
| 包 | 状态 | 测试 | 备注 |
| --------------------- | ---------------- | -------------- | ---------------------------- |
| `@deepcode/core` | ✅ ship-ready | 478 | 内核,UI-agnostic,npm 可发 |
| `@deepcode/shared-ui` | ✅ ship-ready | 0 (types-only) | 共享类型 |
| `deepcode-cli` | ✅ ship-ready | 47 | npm 可发,npx 可跑 |
| `@deepcode/desktop` | 🟡 等装 Electron | 0 (TBD) | UI/IPC/build 配置全在 |
| `@deepcode/vscode` | 🟡 v1.1 骨架 | 0 (TBD) | manifest + extension.ts 骨架 |
| `@deepcode/lsp` | 🟡 v1.1 骨架 | 8 | stdio server + handler 完整 |

## 总结

Expand All @@ -97,6 +97,7 @@ Claude session 能做的代码工作已经穷尽。
- 文档(28 个 .md)100%

剩下的全部需要用户层动作或外部资源:

- Apple Developer ID($99/yr + Xcode)
- Electron binary 装包(~250MB CI 时间)
- 真录 demo 视频(人 + mic + iMovie)
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,25 @@ v1.1 VS Code/JetBrains █████░░░░░░░░░░░░░

### 用户文档

| 文件 | 内容 |
| --- | --- |
| [docs/MIGRATION_FROM_CLAUDE_CODE.md](docs/MIGRATION_FROM_CLAUDE_CODE.md) | 从 Claude Code 5 分钟迁移指南 + 字段映射 |
| [docs/BEHAVIOR_PARITY.md](docs/BEHAVIOR_PARITY.md) | 与 Claude Code 的逐项行为对比 |
| [docs/SHIPPING_MAC.md](docs/SHIPPING_MAC.md) | 给 maintainer:Apple Dev ID + 签名 + 公证全流程 |
| [docs/VOICE_INPUT.md](docs/VOICE_INPUT.md) | 装 whisper.cpp 本地语音输入 |
| [docs/DEMO_SCRIPT.md](docs/DEMO_SCRIPT.md) | 5 分钟 launch 视频逐段录制脚本 |
| 文件 | 内容 |
| ------------------------------------------------------------------------ | ----------------------------------------------- |
| [docs/MIGRATION_FROM_CLAUDE_CODE.md](docs/MIGRATION_FROM_CLAUDE_CODE.md) | 从 Claude Code 5 分钟迁移指南 + 字段映射 |
| [docs/BEHAVIOR_PARITY.md](docs/BEHAVIOR_PARITY.md) | 与 Claude Code 的逐项行为对比 |
| [docs/SHIPPING_MAC.md](docs/SHIPPING_MAC.md) | 给 maintainer:Apple Dev ID + 签名 + 公证全流程 |
| [docs/VOICE_INPUT.md](docs/VOICE_INPUT.md) | 装 whisper.cpp 本地语音输入 |
| [docs/DEMO_SCRIPT.md](docs/DEMO_SCRIPT.md) | 5 分钟 launch 视频逐段录制脚本 |

### 设计文档

| 文件 | 内容 |
| --- | --- |
| [docs/DEVELOPMENT_PLAN.md](docs/DEVELOPMENT_PLAN.md) | 整体开发方案 v0.5(1500+ 行 / §3 模块 / §6 里程碑) |
| [docs/VISUAL_DESIGN.html](docs/VISUAL_DESIGN.html) | 视觉设计 v0.4(11 屏 mockup) |
| [docs/security-model.md](docs/security-model.md) | 威胁模型 + 防御层 + 攻击向量测试 + 已知缺口 |
| [docs/design/sandbox-plan-worktree.md](docs/design/sandbox-plan-worktree.md) | sandbox × plan mode × worktree 关系矩阵 |
| [docs/design/plugin-security.md](docs/design/plugin-security.md) | plugin 信任 ladder + sandbox 子进程 |
| [docs/design/effort-levels.md](docs/design/effort-levels.md) | 5 档 effort 到 DeepSeek API 参数映射 |
| [docs/m1-validation.md](docs/m1-validation.md) | M1 用真 DeepSeek API 验证记录 |
| 文件 | 内容 |
| ---------------------------------------------------------------------------- | --------------------------------------------------- |
| [docs/DEVELOPMENT_PLAN.md](docs/DEVELOPMENT_PLAN.md) | 整体开发方案 v0.5(1500+ 行 / §3 模块 / §6 里程碑) |
| [docs/VISUAL_DESIGN.html](docs/VISUAL_DESIGN.html) | 视觉设计 v0.4(11 屏 mockup) |
| [docs/security-model.md](docs/security-model.md) | 威胁模型 + 防御层 + 攻击向量测试 + 已知缺口 |
| [docs/design/sandbox-plan-worktree.md](docs/design/sandbox-plan-worktree.md) | sandbox × plan mode × worktree 关系矩阵 |
| [docs/design/plugin-security.md](docs/design/plugin-security.md) | plugin 信任 ladder + sandbox 子进程 |
| [docs/design/effort-levels.md](docs/design/effort-levels.md) | 5 档 effort 到 DeepSeek API 参数映射 |
| [docs/m1-validation.md](docs/m1-validation.md) | M1 用真 DeepSeek API 验证记录 |

## 项目结构

Expand Down
14 changes: 6 additions & 8 deletions apps/cli/src/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,9 @@ describe('built-in command behavior', () => {
// Modify the file after snapshot
await fs.writeFile(file, 'changed');
const ctx = makeContext({ sessions: sm, sessionId: meta.id });
const out = await reg.match(`/rewind ${snap!.seq} code`)!.cmd.run(
[String(snap!.seq), 'code'],
ctx,
);
const out = await reg
.match(`/rewind ${snap!.seq} code`)!
.cmd.run([String(snap!.seq), 'code'], ctx);
expect(out.join('\n')).toMatch(/Restored/);
const after = await fs.readFile(file, 'utf8');
expect(after).toBe('original');
Expand Down Expand Up @@ -306,10 +305,9 @@ describe('built-in command behavior', () => {
sessionId: meta.id,
history: [before, after],
});
const out = await reg.match(`/rewind ${snap!.seq} conversation`)!.cmd.run(
[String(snap!.seq), 'conversation'],
ctx,
);
const out = await reg
.match(`/rewind ${snap!.seq} conversation`)!
.cmd.run([String(snap!.seq), 'conversation'], ctx);
expect(out.join('\n')).toMatch(/kept 1 of 2 messages/);
expect(ctx.newHistory).toEqual([before]);
});
Expand Down
16 changes: 8 additions & 8 deletions apps/cli/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ const EFFORT_TIERS: Array<{

export const EffortCommand: SlashCommand = {
name: '/effort',
description: 'Set effort tier (interactive picker if no arg): /effort [low|medium|high|xhigh|max]',
description:
'Set effort tier (interactive picker if no arg): /effort [low|medium|high|xhigh|max]',
run(args, ctx) {
if (args.length === 0) {
// Selector UI — show the table; user picks via `/effort <name>` next turn.
Expand All @@ -183,9 +184,7 @@ export const EffortCommand: SlashCommand = {
const next = args[0]!;
const tier = EFFORT_TIERS.find((t) => t.name === next);
if (!tier) {
return [
`Unknown effort "${next}". Valid: ${EFFORT_TIERS.map((t) => t.name).join(' | ')}`,
];
return [`Unknown effort "${next}". Valid: ${EFFORT_TIERS.map((t) => t.name).join(' | ')}`];
}
ctx.effort = next;
return [
Expand Down Expand Up @@ -328,8 +327,7 @@ export const TodosCommand: SlashCommand = {
if (todos.length === 0) return ['No active todos.'];
const lines = [`Todos (${todos.length}):`];
for (const t of todos) {
const marker =
t.status === 'completed' ? '✓' : t.status === 'in_progress' ? '●' : '○';
const marker = t.status === 'completed' ? '✓' : t.status === 'in_progress' ? '●' : '○';
const text = t.status === 'in_progress' ? t.activeForm : t.content;
lines.push(` ${marker} ${text}`);
}
Expand Down Expand Up @@ -492,7 +490,8 @@ export const RewindCommand: SlashCommand = {
];
}
case 'summarize-from': {
if (!ctx.provider) return ['(/rewind summarize-from requires a provider — none configured.)'];
if (!ctx.provider)
return ['(/rewind summarize-from requires a provider — none configured.)'];
const kept = trimHistoryBefore(currentHistory, cutoffMs);
const tail = currentHistory.slice(kept.length);
if (tail.length === 0) {
Expand All @@ -506,7 +505,8 @@ export const RewindCommand: SlashCommand = {
];
}
case 'summarize-up-to': {
if (!ctx.provider) return ['(/rewind summarize-up-to requires a provider — none configured.)'];
if (!ctx.provider)
return ['(/rewind summarize-up-to requires a provider — none configured.)'];
const head = trimHistoryBefore(currentHistory, cutoffMs);
const tail = currentHistory.slice(head.length);
if (head.length === 0) {
Expand Down
12 changes: 3 additions & 9 deletions apps/cli/src/parse-args.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,11 @@ describe('parseArgs', () => {

describe('resolveEffort (precedence)', () => {
it('cli flag wins over env and settings', () => {
expect(
resolveEffort({ cliFlag: 'high', envVar: 'low', settingsLevel: 'max' }),
).toBe('high');
expect(resolveEffort({ cliFlag: 'high', envVar: 'low', settingsLevel: 'max' })).toBe('high');
});

it('env var wins when no cli flag', () => {
expect(resolveEffort({ envVar: 'xhigh', settingsLevel: 'low' })).toBe(
'xhigh',
);
expect(resolveEffort({ envVar: 'xhigh', settingsLevel: 'low' })).toBe('xhigh');
});

it('settings wins when no cli flag and no env', () => {
Expand All @@ -152,9 +148,7 @@ describe('resolveEffort (precedence)', () => {
});

it('ignores invalid env var', () => {
expect(resolveEffort({ envVar: 'ultra', settingsLevel: 'low' })).toBe(
'low',
);
expect(resolveEffort({ envVar: 'ultra', settingsLevel: 'low' })).toBe('low');
});

it('trims whitespace in env var', () => {
Expand Down
4 changes: 1 addition & 3 deletions apps/cli/src/repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,7 @@ export async function startRepl(opts: ReplOpts): Promise<number> {
sandboxConfig: settings.sandbox,
approval: async (toolName, _input, verdict) => {
output.write(`\n ⏸ Approve ${toolName}? Reason: ${verdict.reason}\n`);
const answer = (
await rl.question(' [y]es / [n]o / [a]lways: ')
).trim().toLowerCase();
const answer = (await rl.question(' [y]es / [n]o / [a]lways: ')).trim().toLowerCase();
if (answer === 'a' || answer === 'always') {
// Persist a bare-tool matcher to project-local settings so the next
// run of this tool from this project skips the prompt.
Expand Down
12 changes: 6 additions & 6 deletions apps/desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ mv apps/desktop/postcss.config.template.js apps/desktop/postcss.config.js

之后:

| 命令 | 作用 |
| ------------------ | --------------------------------------------------- |
| `pnpm dev` | Vite dev server + electron 自动重载 |
| `pnpm build:all` | 构建 renderer (dist/) + main process (dist-electron/) |
| `pnpm pack` | 打包未签名 .app(本地测试) |
| `pnpm dist` | 完整签名 + 公证 + .dmg(需要 Apple Developer ID) |
| 命令 | 作用 |
| ---------------- | ----------------------------------------------------- |
| `pnpm dev` | Vite dev server + electron 自动重载 |
| `pnpm build:all` | 构建 renderer (dist/) + main process (dist-electron/) |
| `pnpm pack` | 打包未签名 .app(本地测试) |
| `pnpm dist` | 完整签名 + 公证 + .dmg(需要 Apple Developer ID) |

## 还没做(M6-rest 余下任务)

Expand Down
11 changes: 2 additions & 9 deletions apps/desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,7 @@
"shortDescription": "DeepSeek-powered coding agent",
"longDescription": "DeepCode is a Claude-Code-parity coding agent powered by DeepSeek — chat, plan mode, tool use, sandboxed bash, MCP, plugins.",
"copyright": "Copyright © 2026 DeepCode",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns"
],
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns"],
"macOS": {
"minimumSystemVersion": "11.0",
"frameworks": [],
Expand All @@ -56,9 +51,7 @@
"plugins": {
"updater": {
"active": true,
"endpoints": [
"https://github.com/oratis/deepcode/releases/latest/download/latest.json"
],
"endpoints": ["https://github.com/oratis/deepcode/releases/latest/download/latest.json"],
"dialog": false,
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDk0MDMzRUQ0RkVFNUREODUKUldTRjNlWCsxRDREbEttVHEwUEplK1FKbnRCakpGb3dVWTYveFdxSmxwK2ZROWFZcW1kYzZMSGcK"
}
Expand Down
Loading
Loading