跳到主要内容

数据截至 (上游 commit 7538cc96774b)

Kun — 架构与原理

30 秒导读: Kun 是一个 Electron 桌面 coding 工作台。它不让你「一句话让 AI 直接改代码」,而是先把需求写清楚、落成文件,再生成计划、再让 agent 编码、最后回到验收。工程上它把整个 agent 循环塞进一个独立的 kun serve 子进程,只通过 127.0.0.1 上的 HTTP/SSE 跟界面说话;循环内部所有省钱手段都围绕一件事——让上游模型的 prompt 缓存尽可能命中


1. 这是什么(零基础也能懂)

一句话定义: Kun = 一个桌面 GUI(Electron + React)+ 一个本地 agent 运行时(kun serve),两者用本地 HTTP/SSE 连接。

解决什么问题 / 给谁用。 假设你要给一个真实项目加功能。常见 AI coding 工具的做法是:你在聊天框敲一句话,它立刻开始改文件。问题是需求没说清、计划没对齐,改完你才发现方向错了。

Kun 的赌注是:把需求这一步显式做出来,并且落成仓库里的文件。需求草稿写进 .kunsdd/requirements/<uuid>/requirement.md,计划写进 .kunsdd/plan/*.md,两边靠一份 trace.json 对账(src/shared/sdd.ts:1src/shared/gui-plan.ts:1)。

它能做什么(功能):

能力落到哪
需求澄清 → 需求文档 → 设计稿/交互原型.kunsdd/requirements/<uuid>/(requirement.mdimg/proto/chat/)
实施计划 + Todo + 需求覆盖率对账.kunsdd/plan/*.md + trace.json
Agent 编码(读文件、跑命令、改文件、LSP、MCP、Skills)工作区本身
变更审查(/review)、内联 diff、工具审批GUI 面板 + POST /v1/threads/{id}/review
独立 Write 写作工作区、定时任务、IM 接入、可视化工作流桌面端各视图

用起来什么样。 运行时本身是个普通的本地 HTTP 服务,不依赖 GUI 也能跑:

# 起运行时(默认端口 18899,见 kun/src/cli/cli-options.ts:40)
kun serve --host 127.0.0.1 --port 18899 --data-dir ~/.kun \
--runtime-token "$KUN_RUNTIME_TOKEN"

# /health 免鉴权;/v1/* 一律要 Bearer(--insecure 才跳过,见 kun/src/server/auth.ts:8)
curl -H "Authorization: Bearer $KUN_RUNTIME_TOKEN" \
http://127.0.0.1:18899/v1/threads

这里有一条必须先说清的 caveat:鉴权默认是开着的,--insecure 是显式的本地开发开关。 0.3.0 起 insecure 是设置里一个独立的布尔位,默认 false(defaultKunRuntimeSettings,「When true, the runtime skips bearer-token auth. Local dev only.」,src/shared/app-settings-kun-defaults.ts:195),isKunRuntimeInsecure 只看这个布尔、不再由空 token 推导(src/shared/app-settings-kun-migration.ts:327)。服务端的 isAuthorized 要求 token 非空且匹配,否则一律 401(kun/src/server/auth.ts:8);空 token + 非 insecure 时连 GUI 自己也进不来。真正兜底的仍是绑定地址——只听 127.0.0.1。完整讨论见 第 1 章 §3.3 与 §7

桌面端做的事,本质就是把这套 HTTP 调用包成界面:新建 thread → 发起 turn → 订阅 SSE 事件流 → 把 item 渲染成气泡、diff 和审批弹窗。

一句话直觉。 把 Kun 想成一台带门禁的车间:GUI 是接待前台(只递单子、只看电视墙),kun serve 是车间本身(工具、机器、原料都在里面),两者之间只有一个窗口(本地 HTTP)和一条传送带(SSE)。整条流水线的成本控制,则是「别让上一批工装白摆」——也就是 prompt 缓存。


2. 顶层全景(它大概怎么转)

2.1 三段式进程边界

先看物理边界。整个系统是三个进程,渲染进程连 HTTP 都发不出去,必须借道主进程。

┌───────────────────────────────────────┐
│ 1. Electron 渲染进程 │
│ React UI: 需求 / 计划 / 聊天 │
└───────────────────┬───────────────────┘
│ window.kunGui.runtimeRequest(...)
│ (preload contextBridge -> IPC)
┌───────────────────▼───────────────────┐
│ 2. Electron 主进程 │
│ 起停子进程 / 转发 HTTP / 中转 SSE │
└───────────────────┬───────────────────┘
│ http://127.0.0.1:18899
│ Authorization: Bearer <token>
┌───────────────────▼───────────────────┐
│ 3. kun serve 子进程(独立) │
│ Router -> AgentLoop -> 模型 / 工具 │
└───────────────────────────────────────┘

怎么读:从上到下是一次请求的方向,SSE 事件沿同一条路反向回流。

主进程用 startKunChild 拉起子进程,并且硬编码把它绑在 127.0.0.1(src/main/kun-process.ts:298:489);URL 拼装函数 normalizeLocalKunHost 干脆拒绝除 localhost / 127.0.0.1 / ::1 之外的任何 host(src/main/kun-base-url.ts:11)。渲染进程只拿到 window.kunGui(src/preload/index.ts:700),真正发 HTTP 的是主进程。

2.2 部件一句话职责

部件干什么在哪个文件
Router极简路由,支持 :param,注册顺序优先kun/src/server/router.ts:15
buildRouter全部 /v1/* 路由表 + 逐条鉴权kun/src/server/routes/index.ts:8
buildEventStreamResponseSSE:先补发历史事件、再订阅实时事件kun/src/server/routes/events.ts:40
createKunServeRuntime组装机:把 store / 工具 / 模型 / loop 全部接线kun/src/server/runtime-composition.ts:15
AgentLoop中央循环:一个 turn 从装配到收尾kun/src/loop/agent-loop.ts:26
LocalToolHost工具执行 + 多道闸门(沙箱 / 钩子 / 审批)kun/src/adapters/tool/local-tool-host-core.ts:21
CompatModelClient一个客户端打三种上游协议kun/src/adapters/model/compat-model-client.ts:33
KunRuntimeProvider渲染侧的运行时客户端(经 IPC)src/renderer/src/agent/kun-runtime.ts:187

2.3 主线:一个 turn 走一遍

POST /v1/threads/{id}/turns 落地后,AgentLoop.runTurn 起一个循环,每转一圈叫一个 step(kun/src/loop/agent-loop-turn-lifecycle.ts:29kun/src/loop/agent-loop-execution.ts:20)。

POST /v1/threads/:id/turns


① 装配上下文
读盘历史 → 治愈畸形历史 → 判断是否压缩
→ 注入 skill / memory / goal / todo 指令


② 组装请求
不可变前缀(系统提示 + 工具表)+ 动态历史(发送前瘦身)


③ 流式解码
文本 / 推理 / 工具调用增量 → 落库 + SSE 推给 GUI

├── 本轮没有工具调用 ─────────────► 收尾:completed


④ 执行工具
多道闸门(沙箱 / 钩子 / 读后写 / 审批)→ 串行或并发执行 → 结果落库

└────────────────────────────────► 回到 ①,step + 1

几个值得先记住的点:

  • 历史只在 step 0 治愈一次。治愈要做两次全量 stringify,循环内自己追加的 item 本来就合法,所以只在进入 turn 时做(kun/src/loop/model-step-preparation-service.ts:151)。
  • 压缩发生在组装请求之前,而不是事后补救(compactIfNeeded,kun/src/loop/history-compaction-service.ts:63)。
  • 闸门不止三道,且都在 LocalToolHost.execute 里按固定顺序过:沙箱拦截 → pre-hooks → 读后写校验 → 运行时策略 → 显式审批 → 执行 → post-hooks(kun/src/adapters/tool/local-tool-host-core.ts:74)。目录层还有一道“广告过滤”(工具自己的 shouldAdvertise),但那决定的是“模型能不能看见”,不是执行闸门——两者不要混称,详见第 4 章。
  • 并发是有限且同质的:只读内建工具最多 3 个一批,委派子 agent 才允许整批扇出(PARALLEL_READ_ONLY_TOOL_NAMESDEFAULT_MAX_PARALLEL_READ_ONLY_TOOL_CALLS,kun/src/loop/tool-dispatch-policy.ts:4:9)。
  • 订阅制模型走岔路:如果这个 thread 的 provider 能被 sdkRuntime 接管,整个 turn 直接交给内嵌的 Claude Agent SDK 跑,不进原生 loop(kun/src/loop/agent-loop-turn-lifecycle.ts:91-99)。

3. 阅读地图

按下面顺序读,是从「边界 → 循环 → 上下文 → 工具 → 模型 → 产品」由外向内、再由内向外的一圈。

顺序章节你会学到
0Kun — 这是什么 / 全景 / 阅读地图本页:它是什么、大盘怎么转
1进程与协议边界:GUI 怎么把 agent 关在门外三进程分工、Bearer 鉴权(及显式 insecure 开关这条 caveat)、SSE 断线续传与去重、子进程监管与重启预算
2Agent Loop:一个 turn 从出生到收尾step 循环、流式 item 落库、并发调度、goal/todo 续跑、交互式提问熔断、预算闸门、失败诊断
3缓存优先:上下文工程与省钱三件套不可变前缀与指纹、发送前历史瘦身、上下文压缩、token economy、provider 计数不可信
4工具面:能力目录、执行与多道闸门能力注册表、内建工具族、多道闸门(沙箱 / 钩子 / 读后写 / 审批)、MCP 与 Skills、委派子 agent
5模型接入层:一个请求怎么发出去,以及订阅引擎这条岔路三种上游协议的统一封装、SSE 解码、重试与错误分类、Claude 订阅引擎
6GUI 产品层:需求先行流水线与自动化编排.kunsdd/ 目录契约、需求→计划→Todo 追溯、审查面板、定时任务与工作流画布

只想快速判断相关性的 agent: 读完 §2 和 §4 就够决定要不要下钻;要抄「怎么保住 prompt 缓存」直接去第 3 章,要抄「怎么把 agent 关进独立进程」直接去第 1 章。


4. 巧妙之处(可借鉴的技术)

这一节是精华浓缩版,每条在对应章节还会展开。共同的主题:Kun 把「省 token」当成架构约束,而不是事后优化

4.1 前缀是一个带指纹和版本号的对象,不是一段字符串

大多数项目的系统提示就是一个字符串,谁都能拼。Kun 把它建模成 ImmutablePrefix:系统提示、工具表、pinned 约束、few-shot,外加 fingerprintrevision(kun/src/cache/immutable-prefix.ts:9)。

改前缀只能走 setSystemPrompt / setTools 这类显式 mutator,每次改都会 bump revision 并重算指纹(kun/src/cache/immutable-prefix.ts:151:155)。工具表在算指纹前会先按名字排序、schema 递归按 key 排序,所以工具顺序抖动不会误伤缓存(normalizeTools,kun/src/cache/immutable-prefix.ts:44)。

系统提示自己也知道这件事——它开头就写着「这份契约故意保持稳定,放在每个请求最前面是为了让 provider 的 prompt 缓存能复用」(kun/src/prompt/kun-system-prompt.ts:1)。

4.2 主动体检:前缀里混进 UUID / 时间戳,直接报警

缓存被打碎最常见的原因是有人往系统提示里塞了「当前时间」或者一个随机 id。Kun 干脆写了个探测器,扫前缀里的 UUID、ISO8601 时间、十六进制哈希、JWT 四类易变内容(detectVolatilePrefixContent,kun/src/cache/prefix-volatility.ts:24),并把结果作为流水线阶段 input_cached 的诊断字段发出去(kun/src/loop/model-step-preparation-service.ts:189-194)。

4.3 工具目录按 turn 冻结:破坏性漂移延迟到下一轮生效

每个 turn 开始时给当时的工具目录拍快照并冻结(TurnToolCatalogFreezer.resolve,kun/src/loop/turn-tool-catalog.ts:22)。turn 中途目录变了怎么办?分两种:

  • 新增工具 → 判为 additive,提示一句,下一 turn 生效。
  • 改了、删了、重排了 schema → 判为 breaking,当前 turn 继续用冻结的旧目录,变更同样延迟到下一 turn(kun/src/loop/turn-tool-catalog.ts:44-47,提示语见 buildToolCatalogDriftMessage,kun/src/loop/model-step-preparation-helpers.ts:173)。

跨 turn 的漂移由遥测层的指纹比对发现(recordToolCatalogFingerprint,kun/src/loop/loop-telemetry.ts:66),并作为 tool_catalog_changed 事件记录(kun/src/loop/agent-loop-base.ts:447)。

这是 0.3.0 的新取舍:早期版本遇到破坏性漂移会直接中止本轮;现在改为冻结 + 延迟生效,既保住了「同一轮内发给模型的工具表字节不变」(缓存友好),又不再打断用户正在跑的任务。

4.4 发送前瘦身,但不改硬盘上的历史

applyRequestHistoryHygiene 在发请求那一刻裁剪工具输出:超长结果按行/字节/token 截断,保留含 error|failed|timeout 等关键词的信号行,还有一个累计 token 预算——从新到旧保留完整结果,预算耗尽后的老结果压成一行摘要,最近 4 条永远保全(kun/src/loop/request-history-hygiene.ts:81)。

关键在于它只作用于出站请求,持久化的 session log 一个字都不动。所以 GUI 上你还能看到完整的工具输出,模型看到的却是瘦身版。

4.5 不相信 provider 报的 prompt_tokens

压缩的触发依据本该是 provider 返回的 prompt token 数。但 Kun 发现有的上游会把累计缓存读取折进这个数字——注释里点名 MiniMax-M3 被观测到虚报约 25 倍,导致上下文条一直卡在 100%、压缩空转。

于是有了 PROMPT_TOKEN_TRUST_FACTOR = 6:provider 报的数超过本地估算的 6 倍就判为记账噪音,退回自己的估算(kun/src/loop/context-compactor-types.ts:12,应用点 trustworthyPromptTokens 调用在 kun/src/loop/context-compactor.ts:114)。同时估算里会加上 overheadTokens(系统提示 + 工具 schema + few-shot),避免只数 item 时系统性低估(kun/src/loop/history-compaction-service.ts:104)。

这是一条很实用的工程直觉:外部计数器是输入,不是真理。

4.6 交互式提问熔断器:turn 级、只管「问用户」的工具

user_input / request_user_input 这类交互式工具在一个 turn 内最多问 3 次,超过就直接抑制,并回一段解释性文本让模型改走普通文本或收尾(ToolStormBreaker,kun/src/loop/tool-storm-breaker.ts:20,阈值常量在同文件 :7)。

先澄清两点:

  • 它是 loop 层的守卫,不是工具宿主那几道执行闸门之一。走读在第 2 章。
  • 普通工具永不被它抑制——注释里写明「identical calls may be retried freely after a failure」,失败重试同一个工具是合法的;0.3.0 之前的「相同参数重复调用即熔断」逻辑已删除,现在只防「反复骚扰用户」。熔断器随 turn 一起创建和销毁(kun/src/loop/agent-loop-turn-lifecycle.ts:160-162:321)。

4.7 SSE 的 seq 去重与心跳不占号

事件流先补发 since_seq 之后的持久化事件,再挂上实时订阅。因为「先落库再广播」,同一事件会在两条路各来一次,所以连接内维护一个高水位 seq 做去重(kun/src/server/routes/events.ts:40,去重判定在 :110)。

心跳则复用当前高水位 seq,不申请新号。原因写在注释里:运行时重启后内存里的 seq 计数器从头开始,心跳如果盖上这些小号,会把客户端游标倒退,下次订阅就会把整条历史重放进实时时间线。

4.8 需求与计划靠文件对账,不靠对话记忆

需求文档里用结构化块写验收标准,计划文档里写 covers 声明,两边由 parseSddRequirementBlocks / parseSddPlanCovers 解析,computeSddCoverage 算覆盖率,deriveSddStatuses 反推每条需求的状态(src/shared/sdd-trace.ts:92:177:201:232)。

结果就是「做完了吗」这个问题有一个可计算的答案,而不是让模型回忆。

4.9 一个 loop 两台引擎

AgentLoop.runTurn 开头有一个分叉:如果 thread 的 provider 能被 sdkRuntime 接管(resolveProvider / handlesProvider),整个 turn 交给 AgentSdkRuntime,由官方 Claude Agent SDK 驱动、走用户自己的 Claude 订阅计费;Kun 只负责「注入大脑」——人格、独占工具、权限、历史 transcript(kun/src/loop/agent-loop-turn-lifecycle.ts:91-99kun/src/runtime/agent-sdk/agent-sdk-runtime-core.ts:56)。

编排逻辑只依赖注入的 SdkRuntimeDeps 接缝(kun/src/runtime/agent-sdk/agent-sdk-runtime-contracts.ts:128),跟真实 SDK 包和 Kun 具体服务的绑定全部收在工厂里(createAgentSdkRuntime,kun/src/runtime/agent-sdk/agent-sdk-runtime-factory.ts:32),所以这条岔路是可单测的。

4.10 computer-use 从「进程内输入库」变成「独立桥接宿主」

早期版本有个平台妥协:macOS 上 libnut(computer-use 用的输入库)第一次调用会把纯 Node 子进程提升成 Cocoa 应用,Dock 里冒出第二个图标,于是只有用户开了 computer-use 才把子进程换成真 Electron 实例。

0.3.0 把这个难题整个拆掉了:kun serve 子进程永远以 Node 模式运行(ELECTRON_RUN_AS_NODE='1',src/main/kun-process.ts:503-507),computer-use 的输入动作改由主进程里一个独立的桥接宿主承担,运行时只拿 KUN_COMPUTER_USE_BRIDGE_URL/TOKEN 两个环境变量去连它(src/main/kun-process.ts:463-465,宿主在 src/main/computer-use/computer-use-host.ts:30)。

值得记的是这个形状的演变:副作用被挪出主循环进程,进程内就不再有「可选的重依赖」。


5. 代码地图(导航索引)

按符号名 grep 比按行号更抗漂移。行号 as-of 7538cc9

同名文件提醒: gui-plan.ts 有两份——GUI 侧 src/shared/gui-plan.ts 与运行时侧 kun/src/shared/gui-plan.ts,内容相近但行号完全不同。全篇引用一律写全路径前缀,别只写 shared/gui-plan.ts

5.1 进程与协议边界

主题文件路径符号名
CLI 参数/配置合并kun/src/cli/serve.ts:29parseServeOptions
默认端口 18899kun/src/cli/cli-options.ts:40DEFAULT_SERVE_PORT
Node HTTP 服务启动kun/src/server/node-http-server.ts:14startNodeHttpServer
路由匹配kun/src/server/router.ts:15Router
全量路由表kun/src/server/routes/index.ts:8buildRouter
Bearer 鉴权kun/src/server/auth.ts:8isAuthorized
SSE 流(补发 + 去重 + 心跳)kun/src/server/routes/events.ts:40buildEventStreamResponse
SSE 编码kun/src/server/sse.ts:3encodeSseEvent
运行时总装kun/src/server/runtime-composition.ts:15createKunServeRuntime
GUI 侧拉起子进程src/main/kun-process.ts:298startKunChild
本地 host 白名单src/main/kun-base-url.ts:11normalizeLocalKunHost
鉴权开关判定(显式 insecure)src/shared/app-settings-kun-migration.ts:327isKunRuntimeInsecure
SSE 经 IPC 中转src/main/runtime-sse-ipc.ts:178registerRuntimeSseIpc
重启预算src/main/kun-runtime-supervisor.ts:38RestartBudget
渲染侧运行时客户端src/renderer/src/agent/kun-runtime.ts:187KunRuntimeProvider

5.2 Agent Loop

主题文件路径符号名
循环主体(空壳继承链顶端)kun/src/loop/agent-loop.ts:26AgentLoop
一个 turn 的生命周期kun/src/loop/agent-loop-turn-lifecycle.ts:29AgentLoopTurnLifecycle.runTurn
step 循环kun/src/loop/agent-loop-execution.ts:20AgentLoopExecution.loop
单步:装配→发送→解码kun/src/loop/agent-loop-base.ts:349AgentLoopBase.modelStep
工具调度(串/并)kun/src/loop/agent-loop-base.ts:359AgentLoopBase.dispatchToolCalls
并发白名单与上限kun/src/loop/tool-dispatch-policy.ts:4:9PARALLEL_READ_ONLY_TOOL_NAMES / DEFAULT_MAX_PARALLEL_READ_ONLY_TOOL_CALLS
交互式提问熔断(turn 级守卫)kun/src/loop/tool-storm-breaker.ts:20ToolStormBreaker
成本预算闸门kun/src/loop/turn-budget-gate.ts:96TurnBudgetGate
goal 续跑kun/src/loop/goal-resume-coordinator.ts:70GoalResumeCoordinator
用户插话队列kun/src/loop/steering-queue.ts:20SteeringQueue
追加式会话日志kun/src/loop/append-only-session-log.ts:11AppendOnlySessionLog
事件记录器kun/src/services/runtime-event-recorder.ts:45RuntimeEventRecorder
turn 编排服务kun/src/services/turn-service-core.ts:218TurnService

5.3 缓存与上下文

主题文件路径符号名
不可变前缀模型kun/src/cache/immutable-prefix.ts:9ImmutablePrefix
前缀显式变更kun/src/cache/immutable-prefix.ts:151setSystemPrompt / setTools
前缀自检kun/src/cache/immutable-prefix.ts:170verifyImmutablePrefix
易变内容探测kun/src/cache/prefix-volatility.ts:24detectVolatilePrefixContent
工具目录指纹kun/src/cache/tool-catalog-fingerprint.ts:11buildToolCatalogFingerprint
turn 内目录冻结kun/src/loop/turn-tool-catalog.ts:22TurnToolCatalogFreezer.resolve
缓存诊断kun/src/cache/cache-diagnostics.ts:36diagnoseCacheUsage
缓存命中率统计kun/src/telemetry/cache-telemetry.ts:9CacheTelemetry
发送前历史瘦身kun/src/loop/request-history-hygiene.ts:81applyRequestHistoryHygiene
上下文压缩kun/src/loop/context-compactor.ts:48ContextCompactor
provider 计数信任因子kun/src/loop/context-compactor-types.ts:12PROMPT_TOKEN_TRUST_FACTOR
压缩编排(含 overhead)kun/src/loop/history-compaction-service.ts:63HistoryCompactionService.compactIfNeeded
token economykun/src/loop/token-economy.ts:85-86applyTokenEconomyToRequest
历史治愈(读盘时)kun/src/loop/history-healing.ts:9healLoadedHistoryItems
历史修复(发送前)kun/src/domain/model-history-repair.ts:13repairModelHistoryItems
自动模型路由kun/src/loop/auto-model-router.ts:27resolveAutoModelRoute
系统提示(缓存前缀本体)kun/src/prompt/kun-system-prompt.ts:1KUN_SYSTEM_PROMPT

5.4 工具与闸门

主题文件路径符号名
能力注册表kun/src/adapters/tool/capability-registry.ts:46CapabilityRegistry
工具执行宿主kun/src/adapters/tool/local-tool-host-core.ts:21LocalToolHost
执行 + 多道闸门kun/src/adapters/tool/local-tool-host-core.ts:74LocalToolHost.execute
闸门一:沙箱拦截kun/src/adapters/tool/sandbox-policy.ts:128sandboxBlockForTool
闸门一:写路径校验kun/src/adapters/tool/sandbox-policy.ts:177canWritePath
闸门:审批kun/src/adapters/in-memory-approval-gate.ts:20InMemoryApprovalGate
闸门:hooks 引擎kun/src/hooks/hook-engine.ts:162:199runPreToolUseHooks / runPostToolUseHooks
工具参数修复kun/src/adapters/model/tool-argument-repair.ts:6repairToolArguments
Skills 运行时kun/src/skills/skill-runtime-engine.ts:51SkillRuntime
MCP 工具提供者kun/src/adapters/tool/mcp-tool-provider.ts:186buildMcpToolProviders
子 agent 委派kun/src/delegation/delegation-runtime-lifecycle.ts:80DelegationRuntime
变更审查kun/src/services/review-service.ts:69ReviewService

5.5 模型接入层

主题文件路径符号名
兼容型模型客户端kun/src/adapters/model/compat-model-client.ts:33CompatModelClient
流式入口kun/src/adapters/model/compat-model-client.ts:34CompatModelClient.stream
三种协议请求体kun/src/adapters/model/compat-model-client-base.ts:249buildRequestBody
协议枚举(含 custom_endpoint 旁路)kun/src/contracts/model-endpoint-format.ts:1MODEL_ENDPOINT_FORMATS
Anthropic 流解码kun/src/adapters/model/compat-model-client-stream.ts:630consumeAnthropicMessagesStreamPayload
多 provider 分发kun/src/adapters/model/multi-provider-model-client.ts:16MultiProviderModelClient
订阅引擎kun/src/runtime/agent-sdk/agent-sdk-runtime-core.ts:56AgentSdkRuntime
SDK 绑定工厂kun/src/runtime/agent-sdk/agent-sdk-runtime-factory.ts:32createAgentSdkRuntime
SDK 事件映射kun/src/runtime/agent-sdk/sdk-event-mapper.ts:157SdkEventMapper
工具桥接kun/src/runtime/agent-sdk/sdk-tool-bridge.ts:118buildBridgedToolSpecs

5.6 GUI 产品层

主题文件路径符号名
.kunsdd 目录契约src/shared/sdd.ts:1SDD_RELATIVE_DIR
需求文档路径src/shared/sdd.ts:19buildSddDraftRelativePath
计划目录与工具名(GUI 侧)src/shared/gui-plan.ts:1:89GUI_PLAN_RELATIVE_DIR / GUI_PLAN_CREATE_PLAN_TOOL_NAME
计划路径判定(运行时侧同名文件)kun/src/shared/gui-plan.ts:34isGuiPlanCurrentRelativePath
需求块解析src/shared/sdd-trace.ts:92parseSddRequirementBlocks
计划覆盖声明src/shared/sdd-trace.ts:177parseSddPlanCovers
覆盖率计算src/shared/sdd-trace.ts:201computeSddCoverage
需求草稿状态src/renderer/src/sdd/sdd-draft-store.ts:205createSddDraft
计划工具结果解析(渲染侧)src/renderer/src/plan/plan-tool.ts:46extractPlanMetadataFromBlock
工作流引擎src/main/workflow-runtime.ts:57WorkflowRuntime
工作流 DSLsrc/shared/workflow-dsl.ts:25exportWorkflowDsl
定时任务src/main/schedule-runtime.ts:64ScheduleRuntime

6. 边界与局限(诚实说明)

  • 它是本地单机的。 运行时只绑 127.0.0.1,normalizeLocalKunHost 会对任何外部 host 直接抛错(src/main/kun-base-url.ts:11)。没有多用户、没有服务端部署形态。
  • 鉴权默认开启,--insecure 是显式的本地开发开关。 insecure 默认 false(src/shared/app-settings-kun-defaults.ts:195),isKunRuntimeInsecure 只看这个布尔(src/shared/app-settings-kun-migration.ts:327),isAuthorized 在非 insecure 时要求 token 非空且匹配(kun/src/server/auth.ts:8)。安全性由"token + 只绑本机"双层提供;显式打开 insecure 后同机其它进程可以直调全部 /v1/*
  • 工具目录不能在一轮内热改。 破坏性变更会被 TurnToolCatalogFreezer 冻结到下一 turn 才生效(kun/src/loop/turn-tool-catalog.ts:22)——这是为缓存做的取舍,代价是插拔 MCP / Skills 后当前轮看不到新 schema。
  • .kunsdd/ 是产品约定,不是通用标准。 需求-计划追溯完全建立在这套目录和 markdown 块格式上,换工具就没了。
  • 许可证是 PolyForm Noncommercial 1.0.0(package.json),不是常见的 MIT/Apache。
  • 本页刻意不进代码细节。 每一条机制的真实走读在对应章节;本页只保证你知道「有这么回事、该去哪看」。