先说个结论:WorkDSH 是我个人折腾了大半年、反复推倒重来后开源的一个 AI 编程工作台。它的定位很清楚——做一个 WorkBuddy 这类闭源 AI 编程 IDE 的可私有化、可扩展、完全开源的同思路实现。代码已经放在 GitHub 上,License 用的是 MIT,想拿去商用、二次开发或者嵌入到自己的工具链都没问题。这篇文章把整个项目的思路、架构、搭建过程和踩过的坑都摊开讲一遍,希望对正在调研同类方案、想自己搓一个私有化 AI 助手的同学有帮助。文章不会很长篇幅讨论某个具体商业产品的优劣,重点在痛点和解决方案本身。
1. 为什么做 WorkDSH:我给 AI 编程工作台列了一份"开源需求清单"
1.1 AI 编程工作台到底解决了什么痛点
先把这个话题拉回到一个基础问题上:为什么现在大家不满足于在网页聊天框里问大模型,反而转向 WorkBuddy 这类"AI 编程工作台"?我自己用下来的感受是,关键差异不在"能聊",而在"能做"。
你在网页对话里问"帮我看看这段代码哪里有问题",大模型只能基于你贴给它的片段做推断,它看不到整个工程的结构,不知道常量定义在哪里,不清楚构建脚本怎么写的。而一个工作台形态的 AI 工具会把整个项目目录暴露给模型,让模型能读文件、检索符号、执行命令、查看报错日志,甚至根据你的指令直接修改多个文件。这个东西的本质,是把"对话式问答"升级成了"可执行的工程协作"。
WorkBuddy 这类工具把 IDE、终端、对话面板揉在一起,本质上解决的是"模型怎么理解一个真实项目"的问题。它通过项目索引、文件读取、工具调用(function calling)让模型从"聊天助手"变成一个"能动手的驻场工程师"。这个方向是对的,也正是我觉得值得做一个开源版本的原因。
1.2 闭源工具让我下决心自研的三个理由
市面上成熟产品虽然好用,但我在实际使用中遇到了几个绕不过去的坎,这也是 WorkDSH 诞生的直接原因。
第一个是数据边界问题。项目代码、私有依赖、内部规范这类东西,很多是没法随便传到云端处理的。我在帮朋友处理一个嵌入式控制器的代码审查时,客户明确要求所有分析必须在本地完成,不能把代码片段上传到任何第三方服务。闭源工具在企业内部选型时很容易在这一步被一票否决。
第二个是成本模型问题。订阅制工具的计费方式通常是按席位加调用量,个人开发者和多项目并行的时候,账单非常不可控。我高峰期一天可能触发几百次复杂调用,月末对账单时的心疼程度,懂的都懂。开源项目至少给了你"接本地模型"这个选项,把边际成本打到接近零。
第三个是扩展自由度问题。闭源工具的 Skill(技能)和自定义指令体系再强大,也是按官方思路设计的。我想实现"提交代码前自动按团队规范做变更影响分析"这种内部流程,闭源工具很难做到让我把规则写在 Git 仓库里、跟着分支走、多人共享。这个需求看起来简单,但在闭源生态里就是很别扭。
1.3 WorkDSH 的定位:不是替代品,而是"可私有化的同思路实现"
需要先划清一个边界:WorkDSH 不是号称"干掉 WorkBuddy"的替代品,而是把这类 AI 编程工作台的核心交互模式重新实现了一遍,并且把数据、配置、模型选择权全部交还给使用者。
WorkDSH 的核心理念可以概括为三句话:
- 一切皆文件:会话、技能、指令、模型配置都是本地文件,方便 Git 管理和团队共享;
- 模型无侵入:向上层提供统一的 Agent 接口,底层可以自由切换 Ollama、OpenAI 兼容 API、本地推理框架;
- 扩展靠技能:复杂的工程流程封装成 Skill,用 Markdown 或 JSON 编写,不需要改主程序代码。
这个定位决定了 WorkDSH 的使用场景非常聚焦——需要私有化部署、看重数据安全、愿意花一点时间配置自己工作流的开发者,使用体验和价值会远高于通用闭源工具。如果你只是想开箱即用、不想折腾配置,那闭源产品确实省心,这一点我不回避。
2. 整体架构设计:WorkDSH 的技术选型和模块拆解
2.1 技术栈:Tauri + React + Go 网关,为什么这么选
技术选型是我在这个项目上纠结最久的部分。最初的原型用的是 Electron + Python FastAPI,功能没问题,但打包体积和内存占用实在劝退。一个常驻后台的 AI 工作台如果吃掉 1GB 内存,在嵌入式开发机上跑起来会非常影响并行编译的速度。
后来我把桌面壳换成了 Tauri。Tauri 调用系统自带的 WebView 渲染前端,Rust 充当后端,打包体积从 Electron 动辄一两百 MB 降到了二十 MB 左右,运行时内存也降到了原来的四分之一。这对需要常驻的开发工具来说体感差异很大。
但纯 Tauri 也有一个尴尬点:AI 工作台涉及大量流式请求、进程管理、网络代理,这些逻辑塞进 Rust 前端命令里会让主进程又重又难调试。所以我额外加了一个 Go 编写的本地网关进程(workdsh-gateway),负责统一处理模型 API 请求、SSE 流解析、工具调用转发和命令白名单过滤。
选 Go 而不是 Python 做网关,主要考虑三点:编译产物是单一二进制文件,部署简单;并发模型天生适合处理大量流式连接;内存占用稳定,适合长期驻留。最终整套技术栈是:
- 桌面壳与本地存储:Tauri(Rust)
- 前端界面:React + TypeScript + TailwindCSS
- 本地网关:Go + chi 路由 + SSE 流处理
- 模型协议:OpenAI 兼容接口 + Ollama HTTP API
- 技能运行时:JSON Schema 定义 + Go 模板引擎
这个组合的优点是每个组件边界清晰,哪一环出问题都可以单独排查,不互相牵连。
2.2 五个核心模块与各自职责
WorkDSH 内部拆成五个模块,每个模块解决一类问题。我在设计时参考了很多同类开源项目的做法,但做了一些更"工程向"的取舍。
会话管理模块负责对话记录的存储与恢复。所有会话默认以 JSONL 格式保存在本地目录,每条消息记录角色、内容、时间戳、引用文件和 token 用量。这样有两个好处:一是会话可以像代码一样提交到 Git,方便回溯;二是解析成本低,后续做自动化分析很容易。
项目感知模块负责把当前工程文件变成模型可理解的上下文。它不会盲目把整个仓库塞给模型,而是先做目录结构扫描,生成项目地图,再根据用户指令按需读取文件。读取时会过滤二进制文件、node_modules、.git 这类目录,并且对单个文件做截断上限管理。
工具调用模块是让模型"能动手"的关键。WorkDSH 目前内置了 read_file、write_file、list_dir、run_command、grep_search 五个基础工具。run_command 默认所有命令都要经过用户确认,并且配置了危险命令黑名单,比如rm -rf /、git push --force这类操作会强制拦截。
技能系统模块是 WorkDSH 扩展性的核心。一个技能就是一个包含指令模板、参数定义、触发方式的文件夹。模型在回答时会先根据用户意图匹配技能,命中后加载技能模板作为系统提示词的一部分。这有点像给模型"装插件",但实现上完全靠文件驱动,不用改主逻辑。
模型网关模块封装了所有模型提供方。无论你用的是云端 API 还是本地 Ollama,在 WorkDSH 里看到的都是同一套chat/completions内部接口。网关侧负责做模型路由、失败重试、超时控制和预算统计,日志里可以实时看到每次调用的 token 消耗和成本估算。
2.3 和 WorkBuddy 的体验异同对比
很多人会直接问我:WorkDSH 用起来和 WorkBuddy 差多少?我从实际体验角度做一个坦诚对比。
| 维度 | WorkBuddy 类闭源产品 | WorkDSH 开源方案 |
|---|---|---|
| 开箱即用程度 | 安装后基本零配置 | 需要手动配置模型、技能和规则 |
| 数据归属 | 默认云端,部分支持本地 | 默认完全本地,可自主决定 |
| 模型选择 | 自带模型,可选型号有限 | 任意 OpenAI 兼容模型或 Ollama 本地模型 |
| 技能扩展 | 官方提供技能市场 | 技能即文件,自己编写、团队共享 |
| 团队协作 | 云端协作方便 | 靠 Git 分发配置和技能 |
| 成本 | 订阅制 + 调用量 | 软件免费,只付模型调用成本 |
| 定制能力 | 受官方边界限制 | 全源码开放,随意改 |
单论对话流畅度和 UI 打磨度,闭源商业产品绝对更成熟,这点不需要嘴硬。但 WorkDSH 赢在"可解释、可控制、可私有化"。对我来说,一个能看清每一行上下文的工具,比一个黑盒但顺滑的工具更重要。毕竟 AI 编程工作台处理的是工程代码,安全性和可追溯性优先级很高。
3. 从零搭建本地环境,把 WorkDSH 跑起来
3.1 环境准备与依赖安装
WorkDSH 对运行环境的要求不苛刻,但为了少踩坑,我建议按下面的方式来装。我本人在 Windows 11、Ubuntu 22.04 和 macOS 14 上都跑通过,这里以 Ubuntu 为主做演示。
基础依赖有四个:Node.js 20 以上、Rust 工具链、Go 1.22 以上、pnpm 包管理器。Tauri 在 Linux 上还需要系统 WebView 依赖,安装命令是:
sudo apt update sudo apt install libwebkit2gtk-4.1-dev build-essential \ libssl-dev libayatana-appindicator3-dev librsvg2-dev然后拉取代码并安装依赖:
git clone https://github.com/workdsh/workdsh.git cd workdsh pnpm install cargo build --release cd gateway && go build -o workdsh-gateway .前端、桌面壳、网关三个部分分别构建后,启动入口在src-tauri的 dev 模式里。如果你想本地跑通全流程,建议先启动网关再启动桌面应用,顺序反了可能导致模型请求的连接被拒。
提示:在 Ubuntu 上如果启动时白屏,大概率是 WebView 依赖没装全,检查
libwebkit2gtk-4.1-dev是否真的是 4.1 版本。装成 4.0 会在运行时静默失败,界面起不来但没有任何报错。
3.2 模型接入:一套配置兼容 Ollama 与远端 API
WorkDSH 的模型配置全部集中在根目录的workdsh.config.json里。它的设计原则是"本地模型和远端 API 用同一套配置结构",切换成本很低。
先看最简单的情况:接入 Ollama 上的本地模型。比如我想用qwen2.5-coder:14b这个模型做日常辅助,配置就是这样的:
{ "models": [ { "id": "local-qwen", "name": "Qwen2.5 Coder 14B", "type": "ollama", "endpoint": "http://127.0.0.1:11434", "model": "qwen2.5-coder:14b", "contextWindow": 32768, "maxTokens": 4096 } ], "defaultModel": "local-qwen" }想接 OpenAI 兼容的远端 API 时,只需要把type改成openai,加上apiKey字段,其他结构完全一致。网关在启动时会读取所有模型配置,并做一次连通性探测,在界面上显示每个模型的延迟状态。这个设计可以让你在同一个界面里混合使用本地模型和云端模型,按任务复杂度手动切换。
我自己实测下来的经验是:日常聊天、快速答疑用 7B 到 14B 的本地模型完全够用,响应速度快,还不用担心数据出去;但涉及跨文件重构、复杂调试、代码评审这类高难度任务时,本地模型质量确实拼不过大参数云端模型。所以 WorkDSH 的"多模型并存"不是摆设,是实际省钱又保质量的关键。
3.3 项目目录结构与关键配置解析
WorkDSH 使用一个独立的配置目录来管理所有用户数据。在 Linux 下默认位置是~/.workdsh/,Windows 下是%USERPROFILE%\.workdsh\。目录结构如下:
.workdsh/ ├── config.json # 全局配置:模型、默认代理、主题 ├── skills/ # 技能目录,每个技能一个子文件夹 │ ├── code-review/ │ │ ├── SKILL.md # 技能说明与指令模板 │ │ └── schema.json # 技能参数定义 │ └── commit-message/ ├── sessions/ # 会话记录,JSONL 格式 ├── rules/ # 自定义全局指令 │ └── global.md └── logs/ # 网关运行日志这里重点说rules/global.md,它对应的工作方式和你给 AI 助手设置"自定义指令"类似。文件里的内容会作为系统提示词的一部分,在每次会话开始时自动注入。Git 仓库里也可以放一个.workdsh/rules.md,这个文件的作用域是当前项目,适合写项目专属规范,比如"所有 Rust 错误处理必须返回 Result,不允许 unwrap"这种。
注意:全局规则和项目规则的注入顺序是先全局后项目。如果两者内容有冲突,项目规则会覆盖全局规则。这个优先级设计是为了适配"不同项目有不同规范"的现实场景。
3.4 写一个自定义技能:代码 Review 示例
技能系统是 WorkDSH 里最值得玩的部分。我拿团队里最常用的"代码 Review 技能"来演示怎么定义一个技能。
在~/.workdsh/skills/code-review/下建两个文件。首先是SKILL.md,它负责告诉模型"这个技能干什么、怎么用、按什么步骤执行":
--- name: code-review description: 审查当前 Git 工作区的变更内容,输出结构化的评审报告。 trigger: 审查代码 / review changes / 看看这次改动 version: 1.0.0 --- 当你收到与代码审查相关的请求时,按照以下步骤执行: 1. 执行 `git diff --cached` 获取暂存区变更,如果没有暂存内容再执行 `git diff`; 2. 对每个变更文件执行 `read_file` 读取完整内容; 3. 检查以下方面:边界条件处理、错误处理路径、安全风险、性能隐患、代码规范; 4. 输出报告,格式按 "严重问题 / 建议优化 / 非阻塞评论" 分类。 报告结尾必须附带一行文件级修改建议,用 Markdown 列表列出。然后是schema.json,它定义技能的可填参数,比如审查深度、是否检查安全项等:
{ "name": "code-review", "arguments": [ { "name": "depth", "type": "string", "enum": ["quick", "standard", "deep"], "default": "standard", "description": "审查深度,quick 只看 diff,deep 会检查上下游调用链" }, { "name": "focus_security", "type": "boolean", "default": true, "description": "是否重点检查安全漏洞" } ] }定义好之后,不需要重启应用,直接在会话里说"帮我审查一下暂存区的代码",模型会自动匹配到这个技能并按照流程执行。类似地,你可以写提交信息生成技能、接口文档生成技能、Changelog 聚合技能等等。这个过程全部用文件驱动,意味着你可以把整个 skills 目录交给 Git 管理,团队里所有人都共享同一套技能定义。
4. 实操过程的坑与排查实录
4.1 SSE 流式输出解析问题
第一版网关在对接远端 API 的流式输出时,我遇到过一个非常隐蔽的 bug:当返回内容里包含中文字符时,SSE 流会出现阶段性的解析错乱。具体表现是流式文本中间偶尔混入一行原始的 JSON 数据,界面上的回复会突然跳出一段机器码一样的内容。
排查过程花了两个晚上。最后发现是 Go 的bufio.Scanner默认的 Buffer 大小是 64KB,当单次 SSE 数据块超过这个限制时,Scanner 会返回错误,而我的代码忽略了这部分错误,导致数据流错位。
解决方案是显式调大缓冲区并处理错误:
scanner := bufio.NewScanner(resp.Body) scanner.Buffer(make([]byte, 1024*1024), 1024*1024) for scanner.Scan() { line := scanner.Text() if !strings.HasPrefix(line, "data:") { continue } // 解析 JSON 并推送到前端 }这个问题的教训是:做流式请求处理时,永远不要假设网络返回的数据块大小是合理的。生产环境里模型厂商的返回内容不受你控制,缓冲区必须按最坏情况设计。
4.2 function calling 格式不兼容问题
WorkDSH 的工具调用最初是严格按 OpenAI 的 function calling 规范设计的,但实测下来发现很多开源模型的 function calling 输出并不标准。有的模型会输出 XML 格式的工具调用,有的会直接把工具名和参数放在纯文本的 Markdown 代码块里。
经过实测,最简单的兼容方案是在网关层加一个"格式归一化"步骤。收到模型输出后,先尝试按标准 JSON 解析;如果失败,再用正则从文本中提取可能的 JSON 片段;如果还失败,就把整段文本作为普通消息传给前端渲染,而不是直接报错。这样用户在遇到模型输出异常时,至少能看到模型"想做什么",而不是看到一段冷冰冰的错误提示。
4.3 上下文管理与截断策略
长会话是每个 AI 工作台的痛点。项目早期,我经常遇到会话进行到一半时模型开始"失忆",早期定过的变量名和约定全部忘记,回答质量断崖式下降。
排查后发现根因是 contextWindow 和 maxTokens 配置不合理——模型上下文窗口虽然标称 32K,但 WorkDSH 默认会往系统提示词里塞项目地图、技能模板和全局规则,这些固定上下文大约占掉 6K 到 8K token,剩下可用空间就变少了。
我现在采用三级处理策略:
- 对话轮次超过 20 轮时,自动启用摘要模式,把早期对话压缩成要点;
- 单次工具调用返回结果超过 4000 token 时,不再直接注入上下文,而是先存到临时文件,让模型按需读取;
- 关键信息(用户明确指定的常量名、路径、约束条件)提取到"持久记忆区",不参与滚动淘汰。
这个策略实施后,长会话的稳定性提升非常明显。代价是实现复杂度高了不少,但 AI 工作台如果连基本的长对话一致性都保证不了,其他功能再花哨也没用。
4.4 并行任务导致本地模型显存溢出
我在一台 24GB 显存的机器上做多项目并行测试时,遇到了一个实际问题:连续触发多个本地模型推理任务,显存直接溢出,界面卡死,网关进程也崩溃了。
排查后发现,WorkDSH 内置的"自动规划模式"会把一个大型任务拆成多个子任务并发执行,每个子任务都会往 Ollama 发送推理请求。Ollama 本身有并发处理能力,但它允许多个模型同时驻留显存,于是多个模型实例把显存挤爆了。
解决方案是在网关层加了一个并发信号量,全局限制同时进行的推理请求数,默认设为 2。对于 14B 这类模型,建议按显存大小调整:每 8GB 显存对应约 1 个并发推理任务。如果你需要跑大批量任务,宁可排队,也不能并发拉满,否则一个崩溃就可能损失整个会话上下文。
4.5 自定义指令不生效的排查思路
这是一个非常高频率的问题,几乎每周都有人来问"为什么我写了 rules 文件但模型不听"。我排查过很多次后总结出三个常见原因:
第一是文件位置不对。全局规则必须放在配置目录的rules/global.md,项目规则必须放在当前工作目录的.workdsh/rules.md。放错位置不会报错,但也不会生效。
第二是编码问题。如果文件里有 BOM 头,部分模型会把它当成正文的一部分,导致系统提示词解析异常。建议统一用 UTF-8 无 BOM 保存。
第三是冲突覆盖。如果全局规则和技能定义都对同一件事做了约束,技能的优先级更高,全局规则里的同主题约束会被覆盖。排查时可以用网关日志里的"prompt inspector"功能查看最终注入的系统提示词,确认你的规则是否真的进入了模型上下文。
4.6 常见问题速查表
| 问题现象 | 可能原因 | 解决方式 |
|---|---|---|
| 启动后白屏 | Linux 系统 WebView 版本不对 | 安装 libwebkit2gtk-4.1-dev 并确认版本 |
| 模型请求超时 | 网关未启动或模型地址不可达 | 先启动 workdsh-gateway,再检查模型端点 |
| 流式输出乱码 | SSE 缓冲区溢出 | 调大 bufio.Scanner 缓冲至 1MB |
| 工具调用不执行 | 模型 function calling 格式非标准 | 检查网关日志,确认是格式问题还是拦截图问题 |
| 长会话模型失忆 | 固定上下文占用过多 | 启用摘要模式,降低项目地图注入量 |
| 自定义指令不生效 | 规则文件位置或编码错误 | 按 4.5 节的三步排查 |
| 并行任务崩显存 | 推理并发数过高 | 调整网关并发信号量上限 |
| 中文输出截断 | maxTokens 设置偏小 | 按输出长度需求提升 maxTokens 并降低预留空洞 |
5. 拓展场景与个人体会
5.1 不止写代码:技能系统带来的可能性
我在设计 WorkDSH 的过程中发现,技能系统一旦跑通,它的适用范围远不止代码生成。因为技能本质上是"给模型套一层可复用的执行流程模板",所以很多重复性的智力劳动都能封装成技能。
举个例子,我给一个做文档的同学写过一个"会议纪要转待办事项"的技能:模型先读取会议记录文件,提取参会人和时间点,再按"负责人 + 截止时间 + 交付物"的格式输出待办清单,最后调用 write_file 写入项目的 TODO.md。整个流程完全自动,和代码审查技能的工作方式一模一样。
另一个例子是"数据库表结构文档生成"技能:输入一个 SQL 文件,模型自动分析每张表的字段、索引、外键关系,输出 Markdown 格式的数据库说明文档。过去人工写这份文档可能要半天,现在一分钟内基本能出初稿,人工只需要校核关键字段的说明是否准确。这些技能让我强烈感觉到,AI 工作台的形态其实非常适合各类"文件输入 + 规则处理 + 文件输出"的知识工作。
5.2 把 WorkDSH 接入嵌入式 / C++ / STM32 这类工程
可能有读者觉得 AI 编程工作台只适合 Web 前端或 Python 项目,实际上 WorkDSH 在设计时特意考虑了嵌入式这类传统工程场景。
嵌入式项目的特殊性在于:编译环境高度依赖交叉工具链,工程里经常混着 C、C++、汇编、链接脚本和厂家 SDK,模型很难靠猜测搞清楚构建逻辑。我的做法是通过项目规则把构建命令、目标芯片型号、SDK 路径这些信息显式写进.workdsh/rules.md,然后让模型在动代码之前先执行read_file读取 CMakeLists 或 Makefile,确认自己对构建系统的理解是正确的。
我在一个 STM32 项目上实测过几次:让 WorkDSH 辅助排查外设初始化顺序的问题,它通过阅读启动文件和时钟配置,能给出比较靠谱的排查方向,虽然不能完全替代示波器和硬件调试,但至少省掉了一大半翻手册的时间。对 C# 开发者来说,如果是处理 USB 摄像头 SDK 集成这类偏设备的场景,同样可以把 SDK 文档喂给项目规则,让模型基于真实的 API 约束来分析调用链。
这个方向目前做得还比较基础,但我认为"传统软件工程 + 本地模型 + 项目规则"的组合,可能是未来 AI 编程工具最有价值的落地领域之一。
5.3 我踩过几次坑之后的几点心得
项目从第一个原型到现在,踩过的坑远比文章里写到的多。有几点心得,我认为比任何功能清单都值得分享。
第一,AI 编程工作台最核心的竞争力不是模型多强,而是"上下文组织能力"。同样的模型,你给它塞一万行垃圾代码和给它配置好的项目地图、技能模板、规则系统,最终输出质量天差地别。所以 WorkDSH 的大量工作其实是围绕上下文管理做的:什么东西该进上下文,什么东西不该进,什么时候该摘要,什么时候该直接读文件。这个方向看似不性感,但决定了工具的上限。
第二,开源项目一定要把"可复现的示例"放在第一位。我自己在用很多开源工具时,最头疼的就是文档写得云里雾里、配置项全靠猜。所以 WorkDSH 里我把示例技能、示例规则、示例模型配置都放在仓库的 examples 目录里,新用户 clone 下来之后照着改就能跑起来。这个习惯也大大降低了社区反馈的沟通成本。
第三,不要试图和小团队比拼全功能。WorkDSH 有的功能闭源产品早就有了,而且打磨得更好,这不需要不服气。我的策略是聚焦"数据可控"和"技能文件化"这两个点,把它们做到足够好用,剩下的事情交给社区和插件生态。目前已经有人把 WorkDSH 的技能系统接到内部的代码审计流程里,也有人用它做私有文档问答,这些都是我一开始没想到的用法。
如果让我重新选择一次,我依然会走 "Tauri + Go 网关 + 文件化技能" 这条路,虽然过程折腾,但得到的是一个完全透明的、可以自己掌控每一个环节的 AI 工作台。接下来我打算重点完善技能市场机制,让社区贡献的技能可以像 npm 包一样一键安装。项目的所有问题都可以在 GitHub 仓库的 Issues 区讨论,感兴趣的读者不妨 clone 下来改一版适合自己的工作流。