MiniHarness 架构说明¶
本页是
miniharness/代码自身的"建筑图纸":目录怎么组织、每个文件对应上游什么、依赖方向规则、公共 API 边界。 读者是改代码的人,以及想理解仓库布局的学习者。 与其它文档的分工:docs/report/解读上游系统"是什么、为什么";docs/chapters/教你怎么从 0 到 1 实现;本页回答"仓库里的代码本身怎么摆、凭什么这么摆"。
1. 目录组织¶
1.1 原则:目录按上游包家族镜像¶
代码目录镜像上游的包族结构(packages/ 下的 core/、llm/、boot/、sandbox/……),镜像到家族这一级(两级子包),不镜像到每个包,也不按主题平铺:
- 家族级镜像:约 20 个子包,维护成本低,"去哪个目录找什么"与上游一致;
- 文件级镜像:只做约定密集处(session、llm、agent-loop),这几处上游"一个文件一个职责"本身就是知识点;
- 为什么不是 1:1 镜像全部近 50 个包?Python 一个仓库分成 50 个目录,光
__init__.py就有 50 个,对教学项目是过度工程; - 为什么不是主题平铺?平铺表达不了模块边界:无法声明"哪些是约定、哪些是实现细节",依赖方向无法用测试约束,环压力只能靠延迟导入绕。
1.2 目录树¶
miniharness/
├── __init__.py # 教学面再导出,只含约定层(__all__ == 28,见 §4)
├── core/ # packages/core
│ ├── session/ # Session 本体 + types/invariant/json/message/repair/surface/projections,__init__.py 聚合
│ │ │ # message.py 上游在 llm/llm/src/message.ts,mini 保留会话域(L0 不依赖 llm,简化标注)
│ │ ├── projections.py # message 投影(SessionMessageProjection):image/offload 的拆分校验 + 图片卸载覆盖表(对应 session/surface.ts + compaction-image-offload/projection.ts)
│ │ ├── zstd_frames.py # zstd 拼接帧容器扫描/解码/截断前缀恢复(python-zstandard)
│ │ ├── persistence.py # JSONL(zstd 帧容器/明文) / SQLite 持久化(上游独立包组 packages/session;V2 一行一事件)+ _find/list_headers 走多代解析
│ │ ├── generation.py # generation 读侧:canonical 文件名/目录多代选择/migrate-on-open(对应 session-persistence-jsonl/src/generation.ts)
│ │ └── released/ # released 只读词表 + v0/v1 codec + 相邻迁移链迁移器(不对应 packages/session/session-format-*/)
│ ├── session_store.py # SessionStore(ctx.sessions 服务:create/prepare/enter/announce + fork + flush)
│ ├── scope.py # Context + RegistryService(vendor/cordis 语义)
│ ├── dsh_scope.py # dsh-scope 原语(scopeParents 图 + scopeTarget 载波 + createScope,对应 packages/core/scope)
│ ├── hmr.py # Cordis HMR 服务(vendor/hmr:register_config watch + 单飞刷新 + config-update-failed 外泄)
│ ├── schema.py # schemastery 配置引擎全量移植(vendor/schemastery)
│ ├── home_paths.py # harness 根解析($DSH_HOME > ~/.dsh;packages/util/home-paths)
│ ├── tool_timeout.py # 工具调用超时约定常量(TOOL_TIMEOUT / timeout_error_message,L0,packages/guard 的超时执行器共享面)
│ ├── tools.py # 工具注册表 + 执行管线
│ ├── system_prompt.py # SystemPromptService(分节渲染,systemPrompt 服务)
│ └── agent_loop/ # agent.py(turn/step 状态机,V2 内嵌流写入磁盘)+ assistant_stream.py(AssistantStreamAttempt)+ resident_loop.py(常驻单循环)+ tool_calls.py(并行调度)+ inbox.py(双队列收件箱)+ projections.py(turnBoundary/inbox 会话投影单元)
├── llm/ # packages/llm
│ ├── protocol.py # StreamChunk / LlmAdapter / LlmFailure / BlockAssembler(协议层)
│ │ + 图像定价/模态/发现类型(LlmImageRequestPrice/Pricing 等)
│ ├── assistant_stream.py # AssistantStreamRecord codec:Accumulator 压缩 / expand 解码 / validate 校验(V2 流内嵌)
│ ├── deepseek.py # DeepSeek Messages API 适配器(httpx + 图片/Files 路径)
│ ├── deepseek_messages.py # Messages wire 序列化 + SSE 事件派发/翻译 + 错误映射
│ ├── fake.py # FakeLlmAdapter(教学扩展)
│ ├── retry_policy.py # retry policy 解析(normal/always)
│ ├── retry.py # agent/request-error 恢复 + 退避
│ ├── token_meter.py # TokenMeter 增量 fold + usage 折入锚
│ └── deepseek_files/ # DeepSeek Files API 执行簇(file-id/defaults/models/types/model-info/
│ # image-tokens/request-pricing/files-api/upload-index/file-store/request-files)
├── ptc_runtime/ # packages/ptc-runtime(seam + Python 后端,L1)
│ ├── types.py # PtcRunRequest/Spec/Result/Failure + 绑定契约(PtcBindingNamespace)
│ ├── service.py # PtcRuntime Service Definition + 保留名常量 + 绑定校验
│ └── runtime.py # PythonPtcRuntime(CPython 子进程 + 行 JSON 绑定协议)
├── ptc/ # packages/core/tools/src/ptc.ts(L2,tools-presentation seam)
│ └── run_code.py # run_code 工具(子派发 tool/ptc-dispatch* 事件 + 精心挑选外层结果)
├── attachment/ # packages/attachment(attachment + attachment-local)
│ ├── types.py # ImageAttachmentRef(含 originalDimensions)/ FileAttachmentRef / SaveImage·SaveFile·SaveFileStreamAttachment / ImageAttachmentLimits / ImageRequestTarget / RequestImageAttachment
│ ├── error.py # AttachmentError + 17 错误码(含 INVALID_FILE_BASE64 / ATTACHMENT_FILES_UNSUPPORTED)+ is_attachment_error
│ ├── encoding.py # 共享质量阶梯 [85,75,60] + encodeFirstWithinLimit 惰性候选执行
│ ├── normalization.py # provider 无关规范化管线(直通/总像素预算+长边封顶/按 alpha 分流编码)
│ ├── projection.py # requestImageDimensions 纯请求投影几何(alpha.1 抽到 seam 包)
│ ├── request_image.py # variantId 确定身份的请求图缓存版本(request-image-v6,按路由目标)
│ ├── admission.py # canonical base64 wire 受理入口(图片批次 + 文件单个)
│ ├── file_store.py # verbatim 文件内容寻址存储(files/<sha2>/<sha>/<name> 别名 + file-objects 规范对象)
│ └── store.py # LocalAttachmentStore(规范化字节 sha256 内容寻址 + 完整性复验 + verbatim 文件族 + admit_prompt_content)
├── seams/session_checkpoint.py # 语义持久化检查点策略(packages/session/session-checkpoint-policy)
├── storage/ # packages/storage(storage hub + storage-domain + storage-json)
│ ├── hub.py # Storage hub(ctx.storage:backend 注册表 + 可挂载数据形态,不碰 IO)
│ ├── registry.py # BackendRegistry(具名 backend 表 + stale disposer 守卫)
│ ├── spec.py # 域声明(define_domain / domain_table / DomainSpec / descriptor_of)
│ ├── domain.py # DomainImpl + KvTable + DomainGlobal(单写链 + domain/changed 发射)
│ ├── facility.py # DomainFacility(route 解析 + open 校验 + backup-and-skip 政策)
│ ├── events.py # DomainChanged(put 带新值 / delete 无值)
│ ├── error.py # StorageError / DomainError 错误码闭集
│ └── jsonbackend/ # JSON 持久 medium:atomic.py / format.py / single_unit.py / per_record_unit.py
├── compaction/ # packages/compaction
│ ├── config.py # 压缩规格解析(threshold / headroom / reserved output / retain / retries)
│ ├── region.py # selectCompactableRange + 压缩事务(surface replace 检查点)
│ ├── summarizer.py # 前缀重放摘要 + 检查点框架
│ ├── tool_result_pruner.py # 可选 tool-result 裁剪阶段(ctx.toolResultPruner 消费者)
│ └── engine.py # BasicCompactionEngine(pre-step 压力 / request-error overflow 接线)
├── jobs/ # packages/jobs(seam + jobs-local + tool-jobs)
│ ├── types.py # 类型/常量 / JobDoneBox(done 的 Promise 替身)/ JobHandle
│ ├── view.py # JobView / JobChunk / JobChannel 投影(view.ts 等价)
│ ├── ring.py # OutputRing(绝对偏移 + 头部驱逐 + UTF-8 安全超块尾部)
│ ├── pump.py # 注册表自有 pull 泵(150ms cadence + 结算末次排干 + spill)
│ ├── events.py # JobEventHub / JobLayer(scope 分层路由 + 包含投递)
│ ├── archive_admission.py # job 家族并入 workspace session-activity/stop
│ ├── render.py # public_job / status_line / render_model_delta
│ ├── registry.py # LocalJobRegistry(ctx.jobs 服务 + owner 会话栅栏 + 结算/上限/teardown + events)
│ └── tools.py # job_output / job_list / job_kill + 完成 notice 投递 + 可见输出封顶(finalizeContent)
├── plan/ # packages/plan/plan-mode(状态机 + 审查 UI + 投影)
│ ├── config.py # plan-mode 规格解析(section 校验,fail loud)
│ ├── mode.py # PlanModeController(log-only plan/mode + plan:policy 节 + pre-step 提交)
│ ├── review.py # exit_plan_mode 工具 + /plan 命令 + userQuestions 审查通道
│ └── projection.py # plan 投影单元(command/run ↔ plan/mode 双事件折叠)
├── commands/ # packages/interaction/commands(命令约定)
│ └── __init__.py # CommandRegistry + command/run|done 配对 + parse/route
├── goal/ # packages/goal(goal + goal-round-driver + tool-goal + command-goal)
│ ├── domain.py # goal/change 事件严格重放 fold + GoalError
│ ├── service.py # GoalService(ctx.goals:compare-and-set 变更 + 激活)
│ ├── prompt.py # goal round 提示词
│ ├── driver.py # GoalDriver(pre-step reservation 校验 + continue_rounds + driver 模式事件驱动续跑)
│ ├── tools.py # get_goal / create_goal / update_goal + tool:goal 节
│ └── commands.py # /goal 命令表面
├── skills/ # packages/skill(skill + skill-filesystem + tool-skill + skill-office + tool-workspace-dependencies)
│ ├── registry.py # SkillRegistry(ctx.skills 服务 + 分层注册 + 渲染/digest)
│ ├── filesystem.py # FileSystemSkillProvider(六类根 + frontmatter)
│ └── tool_skill.py # skill 工具 + /名字 手势 + durable catalog 注入
├── guard/ # packages/guard(循环卫生守卫:超时执行器 + 重复调用提醒)
│ ├── timeout_policy.py # TimeoutPolicy 插件(上游 timeout-policy,仅注册超时执行器约定面)
│ └── repeat_tool_reminder.py # RepeatToolReminder(重复工具调用提醒:预拒绝计数 + 决策折叠)
├── identity/ # packages/identity/anonymous-user-id(harness-home 匿名用户 id)
├── telemetry/ # packages/session/{session-stats,session-telemetry,session-telemetry-otel} + packages/llm/token-meter
│ ├── folds.py # fold_session_stats / fold_token_usage / derive_turn_token_usage(纯 fold)
│ ├── service.py # UsageStatsService(ctx.usageStats)+ projection_values 自由函数
│ ├── session_telemetry.py # SessionTelemetryBackend + Coordinator(live/on-demand 采集 + 脱敏 waterfall)
│ └── session_telemetry_otel.py # OTel 后端(LoggerProvider + OTLP 导出;FEEDBACK_ONLY/DISABLED)
├── session_query/ # packages/session-query(session-query + session-query-sqlite + tool-session-query)
│ ├── config.py # 配置常量 + SessionQueryError 错误码闭集
│ ├── extraction.py # 一方事件语义文本抽取
│ ├── documents.py # 事件记录 + 语义文档投影(surface 分类)
│ ├── sqlite.py # FTS5 检索索引(bm25 + snippet)
│ ├── service.py # SessionQuery(ctx.sessionQuery:search/search_events/read_event/trace_event/lineage)
│ └── tool.py # 模型侧五工具(session_search/event_search/trace/event_trace/event_read)
├── session_projection/ # packages/session/session-projection(投影注册 API v2,L1)
│ └── __init__.py # ProjectionDefinition + SessionProjectionRegistry(ctx.sessionProjections)
├── session_turn_outline/ # packages/session/session-turn-outline(M18,L2)
│ └── __init__.py # turnOutline 投影单元(turn/start 锚定 + 首人类 prompt + 落定回复)
├── session_title/ # packages/session/session-title + session-title-first-prompt-llm(M10,L2)
│ └── __init__.py # SessionTitleService + title/titleInput 投影 + fallback + first-prompt LLM 提供者
├── session_projection_cache/ # packages/session/session-projection-cache(M14,L2)
│ └── __init__.py # SessionProjectionCache(写后节流 + 身份匹配 + 冷读播种,storage domain)
├── workflow/ # packages/workflow/workflow(M13,L2)
│ └── __init__.py # WorkflowEngine 服务定义 + WorkflowError 码 + validate_meta + 六事件
├── workflow_ptc/ # packages/workflow/workflow-ptc(M13,L3)
│ ├── __init__.py # PtcWorkflowEngine:Python 工作流脚本经 PythonPtcRuntime 绑定面执行
│ └── meta.py # META_STATEMENT / assert_body_parses / resolve_subagent_provider
├── tool_workflow/ # packages/workflow/tool-workflow(M13,L3)
│ └── __init__.py # workflow 模型工具 + durable run-start/agent-start/agent-end/run-end 记录
├── subprocess/ # packages/subprocess(M17,L3)
│ └── __init__.py # ctx.subprocess 接缝服务(resolve_executable/terminal_environment/env 清洗收编)
├── deepseek_account/ # packages/credentials/deepseek-account(P1-21,L3)
│ └── __init__.py # ctx.deepseekAccount 服务定义 + 本地落空实现(恒 signed-out)
├── terminal/ # packages/terminal/terminal 服务域(L1,仅依赖 core.scope)
│ ├── types.py # TerminalError 8 码闭集 + TerminalBackend/TerminalSession Protocol + _utf8_bytes(代理对感知)
│ ├── sanitize.py # TerminalSanitizer + normalize_terminal_text(terminal-bash/src/sanitize.ts)
│ ├── bounded_buffer.py # BoundedTextBuffer(双限链式 chunk,session.ts:44-156)+ read_scrollback + utf8_tail
│ ├── operation.py # LocalSendOperation(单飞 + owner 栅栏 + cancel 结算)
│ └── service.py # TerminalSessionService(ctx.terminals:spawn/kill/read/signal/start_send/list)+ install_terminals
├── terminal_bash/ # packages/terminal/terminal-bash(terminal 后端 P2,层 3 登记,拓扑同 shell)
│ ├── config.py # resolve_config 缺省(rows=40/cols=160)+ shell 探测
│ ├── environment.py # child_environment(owner.id+sessionId+UTF-8 preamble)+ bash/pwsh prompt 复盘(133;D marker / dsh> )
│ ├── emulator.py # 终端仿真器(CPR/DA2/DA1/DECRQM 应答 + 光标定位 + scrollback 视图/翻页)
│ ├── provider.py # TerminalHandle 契约(inspect_foreground/inspect_activity + write/signal/terminate 生命周期)+ 平台拆三(_posix.py / _winpty.py:pywinpty PtyProcess + reader 线程 + SubprocessOutcome)
│ ├── shell_activity.py # ShellActivity + prepare_shell_activity(bash --rcfile / zsh ZDOTDIR 私有状态文件,subprocess-local shell-activity.ts)
│ ├── session.py # LocalPtySession(poll_readiness 五判据 settle + interrupt + 增量 UTF-8 解码)
│ └── index.py # install_terminal_bash(幂等)+ apply(依赖 terminals 先装)
├── tool_terminal/ # packages/terminal/tool-terminal(六模型工具 P3,层 3 登记,消费 terminal + jobs)
│ ├── render.py # render_spawn/send/send_read/read/list + bound_terminal_text(逐字对齐 render.ts)
│ ├── tools.py # 六工具(terminal_open/send/read/signal/close/list)+ resolve_config + install_tool_terminal
│ └── __init__.py # 导出 + 上游插件形状常量 name/inject
├── terminal_controller/ # packages/api/terminal-controller(浏览器终端 P4,层 3 登记)
│ ├── types.py # 两错误码 + TerminalControlUnavailable/LimitReached + resolve_config + frame_bytes
│ ├── stream.py # TerminalFollower(JSON 帧 UTF-8 字节预算 + 排空/分离)
│ ├── terminal.py # BrowserTerminal(pyte HistoryScreen 恢复屏 + Follow)+ require_controller 分支
│ ├── shells.py # resolve_executable/shell + discover_shells + terminal_environment(subprocess-local 等价)
│ └── index.py # TerminalController(ctx.terminalController:environment/shells/list/create/follow/write/resize/rename/close)
├── workspace_controller/ # packages/api/workspace-controller(工作区控制,层 3 登记)
│ └── __init__.py # WorkspaceController(ctx.workspaceController:十命令 + follow 代次)
├── workspace_files/ # packages/api/workspace-files(文件预览,层 3 登记)
│ └── __init__.py # WorkspaceFiles(ctx.workspaceFiles:read/readBytes(options)/stat/list + target-scoped changes)
├── settings_controller/ # packages/api/settings-controller(设置/凭据,层 3 登记)
│ └── __init__.py # SettingsController + CredentialsController(ctx.settingsController / credentialsController)
├── context/ # packages/context(请求上下文插件,层 2 登记)
│ ├── time_context.py # 每步时钟读数 + 浏览器时区策略 + timeContext 投影
│ ├── tmux_context.py # tmux 方位查询/变化抑制 + tmuxContext 投影
│ ├── file_reference.py # @file 词法 + FileReferenceService(ctx.fileReferences)
│ ├── file_reference_local.py # WorkspaceFileSearch 模糊索引 + 本地服务 + 提示节
│ ├── session_reference.py # dsh-session URI/提及 + 跨会话快照准备 + candidates
│ └── agent_instructions.py # AGENTS.md 发现/预算渲染/reconcile + pre-step/touch driver
├── boot/ # packages/boot
│ ├── boot.py # 启动 + patch overlay
│ ├── composition.py # YAML 配置 / !!js 插值 / dump 渲染
│ └── dotenv.py # .env 解析(parse_dotenv)
├── loader/ # vendor/loader + vendor/include(cordis 组件系统,L0)
│ ├── model.py # ENTRY_KEY / GROUP_KEY / SEP 载波键
│ ├── utils.py # !!js 求值 + baseUrl 上溯 + 瞬态事件循环结算
│ ├── patch.py # apply_entry_patches(replace / insert / name 门)
│ ├── entry.py # Entry(update / disabled / init)+ module 旧方言桥
│ ├── group.py # EntryGroup(一级子列表宿主)+ Group 插件
│ ├── tree.py # EntryTree(扁平 store + resolve / import_ / write)
│ ├── loader.py # Loader 服务(internal/config|update|plugin 钩子)
│ └── include.py # Include 子树(文件读写 + initial + !!js 原样回写)
├── fs/ # packages/fs(文件系统 seam + 本地/沙箱后端 + 模型侧工具)
│ ├── types.py # 目标/版本标识、元数据、写/编辑意图与结果、FsErrorCode 闭集
│ ├── service.py # FileSystem(ctx.fs 抽象契约,含 watch 默认拒绝)
│ ├── local.py # LocalFileSystem(realpath 身份 / 原子写 / 字面编辑 / watchdog watch)
│ ├── sandbox.py # SandboxedFileSystem(每次调用沙箱围栏)
│ ├── observation_policy.py # 观测态策略(fs/write-intent、fs/edit-intent、fs/observed)
│ ├── diff.py # write/edit 结果态 hunk diff + FsDiffMeta(operation)
│ ├── tools.py # read / write / edit 工具(tool-fs)
│ ├── str_replace_editor.py # str_replace_editor 工具
│ └── search.py # glob / grep 工具(stdlib 承载)
├── lsp/ # packages/lsp/lsp(LSP 能力 seam,L1)
│ └── __init__.py # Lsp(ctx.lsp:provider 注册原子预留 id+扩展名 + 每查询扩展名路由)+ LspError + final_extension
├── lsp_stdio/ # packages/lsp/lsp-stdio(通用 stdio 语言服务器后端,L2)
│ ├── framing.py # Content-Length JSON-RPC 编解码(头部/消息大小有界)
│ ├── abort.py # 信号鸭子类型(.aborted/.is_set)+ abortable(不取消底层 work)
│ ├── protocol.py # LSP wire 类型面(dict 承载,登记)
│ ├── translate.py # 纯协议翻译:能力判定 / Location/LocationLink/Hover 归一
│ ├── host.py # 经 ctx.fs 规范工作区 + 约束读源(完整文档字节上限)
│ ├── connection.py # 子进程上的 JSON-RPC 端点(server 请求应答 / stderr 有界尾 / 增级终止)
│ ├── instance.py # 一个服务端实例:握手 + 串行可取消查询队列 + 瞬态 open + 有界拆除
│ └── __init__.py # LocalLspProvider(按工作区池化)+ install_lsp_stdio(server 表)
├── tool_lsp/ # packages/lsp/tool-lsp(模型可见 lsp 工具,L2)
│ ├── render.py # 一基↔零基光标转换 / 位置渲染 / file:URI 解析 / UI 呈现
│ └── __init__.py # create_lsp_tool / install_tool_lsp(四操作只读工具 + tool:lsp prompt 节)
├── todo/ # packages/todo
│ └── __init__.py # to_todo_list / fold_todos / install_todo_tool(模型侧 todo_write)
├── spill/ # packages/spill(spill + spill-local + spill-policy)
│ ├── __init__.py # SpillStore seam + LocalSpillStore + 大结果落盘策略(tools/post-execute)
│ └── retention.py # retain_content:text/image 有序 head/tail 保留(token 预算、整图不可切)
├── workspace/ # packages/workspace/workspace(工作区实体 + 注册表服务)
│ └── __init__.py # Workspace / WorkspaceService(ctx.workspaces)+ paths 规范化 + 归档准入/置顶/默认登记
├── settings/ # packages/settings(settings + settings-file)
│ └── __init__.py # SettingsProvider + SettingsScope + redact_secrets + 文件 provider
├── cli/ # apps/cli
│ ├── main.py # launcher 选项(profile / patch / dump)+ _web_main(boot/profile 驱动装配)
│ ├── headless.py # 一次性任务入口
│ ├── default_tools.py # headless 默认工具集(教学扩展)
│ ├── session_cmds.py # 会话 list / resume / delete / stats(教学扩展;stats 为遥测可视化终端)
│ ├── preset_cmds.py # presets list / show / select / delete(教学扩展,web Remote 等价本地入口)
│ ├── web_profile.yml # 默认 web 组合模板(种子进 profile include;Loader 不写此资产)
│ └── plugins/ # web 组合条目插件(loader 插件模块 apply(ctx, **config),每条目安装一服务)
│ ├── system_prompt.py / web.py / user_questions.py / sandbox_policy.py
│ ├── terminal_controller.py / fs.py / credentials.py / workspaces.py
│ ├── workspace_controller.py / workspace_files.py / session_projections.py
│ ├── usage_stats.py / turn_outline.py / command_feedback.py / message_feedback.py
│ ├── approval.py / permission_presets.py
│ ├── session_title.py / session_title_first_prompt_llm.py / deepseek_account.py
├── preset/ # packages/preset + apps/cli/config/agent-presets
│ ├── presets.py # shipped root / 分层 roster / 投影 / 锁 / cordis 翻译(数据目录 preset/{minimal,standard} 随迁)
├── extensions/ # packages/extensions
│ └── dynamic.py # 动态插件生命周期
├── interaction/ # packages/interaction
│ ├── approval.py # 审批服务(+ approval:policy 上下文 + setPolicy 通知)
│ ├── permission_presets.py # 权限预设(PermissionPresetService:预设表 + derive + 写路径 + /permission)
│ ├── user_questions.py # user-questions 服务(模型澄清 seam:UserQuestionError + ask 派发 + restore)
│ └── tool_ask_user.py # ask_user_question 工具(schema/execute/render,同 tool-ask-user)
├── feedback/ # packages/feedback(M12,L3)
│ ├── command_feedback.py # FEEDBACK_CATEGORIES + record_feedback + /feedback 命令 + sessionFeedback Remote
│ └── message_feedback.py # messageFeedback Remote(list/put/delete + 版本 CAS + 活/冷会话)
├── protocol/ # packages/{acp, sdk, hooks}
│ ├── acp.py # ACP 服务器子集
│ ├── sdk.py # JSON-RPC 信封 + 最小运行服务
│ └── hooks.py # hooks 桥(CC 配置 → 拦截决策)
├── seams/ # packages/{sandbox, credentials, authorization, subprocess, subagent}
│ ├── sandbox_local.py # 真沙箱后端(平台链探测 / 失败即拒绝)
│ ├── sandbox_policy.py # 沙箱策略服务(部署缺省 + 会话日志覆盖决议)
│ ├── landlock_run.py # Landlock 自限制执行器(native/landlock-run 的 ctypes 载体)
│ ├── sandbox_windows_acl/ # Windows ACL 写限制沙箱(ctypes FFI 物化上游 windows-acl-restrict-poc;非 win32 import 即抛 OSError)
│ ├── credentials_local.py # 凭据四层 + CredentialsService(provide="credentials",发 credentials/record-updated)
│ ├── authorization.py # 授权服务(install_authorization opt-in;registerFlow/list/describe/cancel/begin + authorization/settled)
│ ├── subprocess_env.py # 子进程环境清洗切片(凭据形 + DSH_* 名剔除,packages/subprocess)
│ └── subagent/ # __init__ + descriptor + providers(三通道)+ worker(子进程)+ continuation(续跑管理)+ archive_admission(归档准入)+ tool(模型侧委托工具)
├── shell/ # packages/shell/{shell, bash-local, bash-sandbox, pwsh-local, pwsh-sandbox, shell-env}
│ ├── types.py # ShellExecution 句柄 / ShellExpiryPolicy / observed 偏移读 / settled_execution
│ ├── bash_local.py # 本地 bash 执行器(execute→ShellExecution,缺省 provider)
│ ├── bash_sandbox.py # 沙箱消费执行器(confine 包裹 + 三路归因 + result 装饰)
│ ├── pwsh_local.py # 本地 pwsh 执行器(-NoLogo -NoProfile -NonInteractive -Command + 编码前导 + 路径解析)
│ ├── pwsh_sandbox.py # 沙箱消费 pwsh 执行器(M16)
│ ├── env.py # ctx.shellEnv 注册表(DSH_* 内置 + 保留键 DSH_PROFILE[_DIR])
│ └── helpers.py # spawn 归因 / denial / runner 失败分类(helpers.ts)
├── tool_bash/ # packages/shell/tool-bash(模型面 bash 工具)
│ ├── index.py # bash 工具(前台/提升/后台三态 + jobs 集成 + stopped)
│ ├── background.py # process_outcome / process_sources / ring_delta
│ └── render.py # parse_exit_status / render_result / render_promoted / render_job_read
├── tool_pwsh/ # packages/shell/tool-pwsh(模型面 pwsh 工具,M16)
│ ├── index.py # pwsh 工具(三态 + jobs 集成 + kind:'pwsh')
│ └── render.py # render_pwsh_result / render_promoted / render_job_read
├── mcp/ # packages/mcp/{mcp-client, mcp-resources}(mini 子集)
│ ├── types.py # Config schema / ReconnectConfig / RECONNECT_DEFAULTS / 常量
│ ├── client.py # apply(ctx, config) 同步门面:resolve 配置 → 链接生成
│ ├── connection.py # 代连接 supervisor(stdio / streamable-http)+ 重连 + 工具归属注册 + 生命线 ping
│ ├── transport.py # 传输工厂(stdio_client / streamable_http_client)
│ ├── server_context.py # MCP server 挂载(静态 server / CLI 定位 / 配置解析 → 联系请求)
│ ├── tools.py # sync_tools(公共工具名 hash / bridge 定义 / output 投影 / 图片受理)
│ ├── fixture_server.py # stdio 夹具(教学扩展,tests 用)
│ └── resources/ # packages/mcp/mcp-resources
│ ├── render.py # output render(手动 JSON 序列化的紧凑 JSON 投影)
│ ├── tools.py # list/read 三个共享资源工具(register_resource_tools)
│ └── runtime.py # ResourceRuntime(createResource → 生命周期 + disposer)
├── client/ # packages/client
│ └── trajectory.py # Trajectory 折叠引擎
├── web/ # packages/api/gateway + packages/client/connection + session-controller + remotes + host/frontend-static + host/webserver(mini 子集)
│ ├── envelope.py # 两信封 RPC(client-request / server-response,rpc-schema.ts:connection 层错误闭集 + transport_error 折叠)
│ ├── attachments.py # unary 结果的二进制附件(bytes 叶子投影为 null 占位 + multipart 分帧 metadata + bytes-<i>)
│ ├── api.py # WebApi 会话服务(unary 方法 + 路由表)
│ ├── stream_protocol.py # Remote 流 wire 语法(open/cancel/item/end/error 帧 exactKeys 闭合 + $events/result payload)
│ ├── uplink.py # 单流有界上行 inbox(字节上限 / end 半关 / end 后 item 与超限两违例)+ 方法侧 UplinkItems(逐项 codec 解码 + 失败折 gateway/input-invalid)
│ ├── mux.py # WS /api/remote.mux 单路径承载全部 Remote 流(RemoteStreamMuxConnection)
│ ├── events.py # $events 注册表(api-session/* 转发源 + waterfall + $events/result 结算)
│ ├── streams.py # GatewayStreams($events 装配 + session/terminal/workspace/files 流分发表)
│ ├── approvals.py # 审批桥(async tools/ask 闸门 ↔ approval/request waterfall + $events/result)
│ ├── questions.py # user-questions 桥(user-questions/request waterfall ↔ $events/result 结算)
│ ├── downloads.py # GET /api/session.export 会话日志导出(zip 打包 root + 后代 + 媒体)
│ ├── frontend.py # 静态服务约定(遍历 403 / SPA 回退 200 / MIME)
│ ├── inventory.py # pluginInventory/list 投影(Loader 条目四字段 + preset 组合行 flatten)
│ ├── static/ # vanilla SPA 教学参照前端(index.html / app.js / style.css,无构建步;消费旧 SSE wire,对新后端不工作——真实对接见仓库顶层 `webui/`)
│ ├── server.py # FastAPI 载体(unary {args} 解包 + $events/result 特判 + WS + 静态,stream-server.ts / handler.ts)
│ └── launcher.py # web profile 启动器(build_app / run_web)
├── web_tools/ # packages/web/{web,web-search-deepseek,web-fetch-http}+tool-web(模型可见 web 功能族,默认组合 dsh-base 挂载)
│ ├── runtime.py # WebRuntime(ctx.web:URL 策略 + 双 provider 注册表 + 执行期选择六分支 + 配置回落)
│ ├── network.py # 整址公网策略(答案集先整体校验再钉桩,防 DNS 重绑定)+ is_public_ip_address
│ ├── policy.py # 字节帽(声明超限拒绝/流式截断)+ 字符帽 + redirect 跟随/跨源拒绝
│ ├── fetch_http.py # 匿名公共抓取 provider(HttpFetchProvider + build_http_limits)
│ ├── search_deepseek.py # DeepSeek 搜索 provider(Anthropic /messages 协议 + citation_snippets + 3xx 拒绝)
│ ├── search_tool.py # web_search 工具(web_search_section_text + run_search_queries + round-robin 去重 merge)
│ ├── fetch_tool.py # web_fetch 工具(web_fetch_section_text + format_fetch_output 三段截断 + MAX_CONVERSION_DEPTH)
│ ├── trust.py # 信任域/信任来源判定
│ └── types.py # 契约类型(WebSearchResult/WebFetchResult + run_deadlined/is_set_signal)
├── demo.py # 端到端演示(教学入口,python -m miniharness.demo)
└── example_plugins.py # boot 演示插件(教学示例)
1.3 顶层再导出策略¶
miniharness/__init__.py保留"教学再导出":from miniharness import Session对学习者成立;- 子包
__init__.py做族内再导出:from miniharness.llm import StreamChunk与from miniharness.llm.protocol import StreamChunk等价。文档与示例写浅路径,业务代码写深路径(可被依赖方向测试检查); - 聚合器必须显式
__all__:无__all__时from .x import *会把子模块命名空间的所有公开名复制进包——包括与子模块同名的属性(子模块属性遮蔽包引用),也包括子模块内部导入的 stdlib 名(如json.py里的import json)。星号导入只应复制约定名,因此子包与其子模块各写显式__all__; - 命名沿用上游:
sdk.py与上游包名一致;session_cmds.py与sessions.py单复数混淆消除。
2. 模块 ↔ 上游映射¶
行级对照账本:每一行是"mini 路径 ↔ 上游对应"的权威归属。简化标注以各模块 docstring 为准,本表只列归属;改公共代码时先查本表。
| mini 路径 | 上游对应(唯一权威) | 备注 |
|---|---|---|
core/session/(session/types/invariant/json/message/repair/surface/seq_ranges + generation/persistence/zstd_frames 等) |
packages/core/session/src/(types/invariant/surface/repair/seq-ranges/preparation/request-header/known-event-types/index 9 文件)+ packages/llm/llm/src/message.ts + packages/session/session-format/src/json.ts |
message 构造保留在会话域(L0 不依赖 llm,简化标注);上游 json.ts 在独立的 session-format 包(JSON 规范化/roundtrip),mini 并入会话域 |
core/session/persistence.py |
packages/session/session-persistence-jsonl(+ session-format* 相邻迁移链) |
上游是独立包组,mini 并入会话域(简化标注);目录布局与上游 session-persistence-jsonl/src/format.ts 一致:root/--<projectKey(cwd)>--/<encodeSegment(id)>/session.v4.jsonl[.zstd](generation 版本化文件名,v0 旧名 session.jsonl 保留拒读;~XXXX 段转义、projectKey 分隔符折叠+251 截断、cwd 缺省 _no-cwd);默认载体 zstd 拼接帧容器(zstd_frames.py,一帧一记录,torn 末帧前缀恢复;可选明文 .jsonl),编码互斥、遗留平铺、重复 id、未知版本都直接拒绝读取(released 旧版本由上游相邻迁移链处理);V4 一行一事件(上游仅 v0→v1 迁移 codec 保留打包,assistant/message 内嵌流;V4 tool 角色平铺结果);头行与目录同源(header.cwd 回写);崩溃修复 closers 经 commit_repair 写入磁盘(与上游 commitRepair 一致),恢复构造 mode="restore";多代读侧:_find/list_headers 经 core/session/generation.py 解析 canonical 名、取最高代、migrate-on-open(确保代当前才回写,_ensure_generation_current)——v0/v1 released 旧制品读入时被相邻迁移(v0→v1→v2→v3→v4)转成 v3 后继发布,源文件不可变保留(os.replace 原子发布,.zstd 后缀=mini 载体约定,上游 .zst) |
core/session/released/(helpers/dispositions/codec/validate/validate_v2/validate_v3/validate_v4/payload_validation/relationships/migrate_v0_v1/migrate_v1_to_v2/migrate_v2_to_v3/migrate_v3_to_v4/catalog,共 15 文件) |
packages/session/session-format-catalog + session-format-v0-to-v1 + session-format-v1-to-v2 + session-format-v2-to-v3 + session-format-v3-to-v4;词表 packages/core/session/src/known-event-types.ts(54 类型闭集);格式类型 packages/session/session-format/src/types.ts |
相邻迁移链整件纯函数移植(含 v2→v3、v3→v4);migrate_released_artifact 按版本选边 v0→v1→v2→v3→v4;载体差异(登记):v1 物理头 seedLength→isSeeded(seedLength:0 = seeded 零切割)、v1 user/message flat、chunk 流内嵌(assistant/message stream records / assistant/attempt);fork 切点重导出为 {inherited:true} marker(空种子合成 createdAt 时间);密集重映射拒绝指向已消费 chunk 的引用(绝不重定向,逐字文案);迁移不写任意目标(组装完整 AFTER + staged 校验 + 原子替换);深度校验层:54 类型逐字段 payload 语义(payload_validation.py,上游 payload-validation.ts ~1028 行)+ 跨事件关系状态机(relationships.py,上游 relationships.ts ~475 行,v2 assistant/attempt step 门经 (set,frozenset) 修复)+ artifact 编排(validate.py/validate_v2.py/validate_v3.py:内嵌流三事实 cross-check、marker/cut 双向、restore=信封级装载、v2 field 无引号方言);迁移链已切真实校验器(v0→v1 逐事件门 + 终态 artifact 双重门,v1→v2 目标门,v2→v3 目标 assertV3Event 全量校验);仅令牌/自性能隔离不随行移植 |
core/session_store.py |
packages/core/session/src/index.ts(SessionStore 部分) |
内存会话服务:create/prepare/enter/announce 生命周期 + get/list/fork(五错误码)+ flush 检查点 + session/created|disposed|event|flush 四事件;create 与上游 generator effect 一致(enter 先 yield、announce 抛错自动回滚);事件派发经 scope_target 载波(carrier=scope_target(session, scope_of(owner_ctx or self.ctx)),与上游 enter 的 scopeTarget(session, scopeOf(store.ctx)) 一致);结构一致:SessionStore(Service),构造 super(ctx, "sessions") 即经 ctx.provide 自动登记、随拥有 fiber 自动注销(与上游 index.ts:790 extends Service + super(ctx, 'sessions') 一致),install_sessions/web/api 手工 provide 已简化移除;无 typert lookup、flush 为同步近似(简化标注见模块 docstring) |
core/agents.py |
packages/core/agent/src/index.ts(AgentRegistry)+ archive-admission.ts |
进程内 live 代理实例注册表(ctx.agents,L1):AgentRegistry(Service) 构造即 super(ctx, "agents") 登记、随拥有 fiber 注销;register(agent, owner=None)(id 与会话不符 / 同 id 已登记 fail-loud)、查询面 get/list/roots/is_owned_by、agent/created/agent/disposed(agent 自有载波,非会话日志事件;与上游 publish 时 enter+announce 公告一致,mini 单同步进程一键发布);install_agents(ctx) 幂等装配(生产 6 处 root 组合均接在 install_sessions 旁);模块级 assert_live_agent(agent)——装配即强制(无 agents 服务的裸装配 no-op)。另含 install_turn_archive_admission(ctx, lookup)(对齐上游 archive-admission.ts):注册表构造点安装 turn 归档准入家族——会话 Agent 运行中答 workspace/session-activity 的 {kind:'turn'}、workspace/session-stop 以 cancel('user')(不带 keep_inbox,排队输入随取消丢弃)停止该回合;家族键并入 workspace 的 SessionActivityKindMap。注册点 = AgentLoop.publish();goal _prepare_mutation 前置 assertLive 边界(陈旧/重复实例拒绝),jobs 访问面按 owner 会话 id 栅栏(rc.1 起不再断言 live 实例,owner 仅在 start 时解析为 live Agent,见 jobs 行)。载体差异:上游 initiator 用 AsyncLocalStorage 承载身份,走 enter+announce 两步;subagent 运行时 owner 链不承载(本节只登记 root/父子全部 live 实例) |
storage/(hub/registry/spec/domain/facility/events/error + jsonbackend/) |
packages/storage/storage(index.ts:Storage 插件 + storageBackendServiceKey) + packages/storage/storage-domain(domain.ts/index.ts) + packages/storage/storage-json(single-unit/per-record-unit/format/atomic) |
非会话 KV 存储中心(ctx.storage,L1,不承载 storage-sqlite):hub 不碰 IO(backend 注册表 + 可挂载数据形态,storage.backend.<name> 生命周期服务键);domain 数据形态带 schema 校验(open 逐记录 validate_schema_value,invalid-record 带 fail-closed detail(table/key);invalid_records='backup-and-skip' 时坏记录 backup_record 移开 + 日志 + 跳过)、单写链(写先持久后改内存再发 domain/changed,put 带新值 / delete 无值;update 在链槽读改写 + missing-key 拒绝;close 排空已排队写照发事件、以 DomainError('closed') 拒绝新写);每域单开(already-open / reserved 释放);JSON backend:single 整文档 / per-record 一记录一文档(path-safe key、foreign 坏/过期文档读缺位、legacy 整文档 bootstrap 经版本接受集栅、.bak.<YYYYMMDDHHmm> 备份文件) |
core/scope.py |
vendor/cordis + packages/core/scope |
Context(服务仓库 + 事件总线 + 四种派发 + asyncio 变体)+ fiber 生命周期(对应 fiber.ts:状态机 PENDING/LOADING/ACTIVE/FAILED/UNLOADING/DISPOSED + internal/status;effect(execute, label) 上游形态——execute 立即执行、返回值按 None/callable/awaitable/生成器收集为 disposer;单发 + 可 await;注册先于执行 + setup barrier 重入保护;dispose 幂等 join 在途;同步立即逆序、异步并发 unload、错误 contained;装载半边 + 注册表——RegistryService(ctx.plugin 缩写 + 插件形态归一 + 运行记录按 callback 键控)、fiber 携带 inject 依赖 + epoch 重载(依赖变化卸载→重装)、restart()/update()(internal/update waterfall)、internal/config waterfall + schema 校验(resolve_config,core/schema.py)、internal/plugin 每次装载/卸载派发)+ create_scope fiber-backed 作用域(父销毁收回子 fiber)+ 服务仓库(reflect.ts 对应:按隔离标签键控的全局 store,ctx.get strict 缺省返回 None,ctx.isolate(name) 换标签,per-agent 的 tools/systemPrompt 经隔离不冲撞 root realm,重复提供同一标签 fail loud);另含 Service 基类(service.ts 对应:构造即经 ctx.provide 自动登记、随 fiber 注销、_invoke 可调用、_check/_init)、ctx.extend(meta)/ctx.intercept(name, config)(intercept 配置经 Service._resolve_config 沿祖先链近根优先合并)、内建 LoggerService(logger.ts 对应:ctx.logger(name) 铸具名 Logger 门面 + printf 格式 + exporter 注册/级别过滤/默认缓冲导出器,ctx.logger 属性为绑定访问方 ctx 的视图);dsh-scope 对应:事件派发模型改上游形态——on 双写 root _flat_hooks(全局 Hook 表)+ 祖先链 _listeners,dispatch 系加 this_arg 载波参数(有载波走扁平表按载波键过滤,无载波保留祖先链);create_scope 返回 Scope 包装 + 自动绑父 scope;scope_key = scope_of(self)(scopeParents 图);残余简化标注见模块 docstring |
core/schema.py |
vendor/schemastery/src/index.ts(902 行单文件) |
schemastery 引擎全量移植:可调用 Schema 节点 + resolve 分发 + 17 类 resolver(any/never/const/string/number/boolean/function/is/bitset/array/dict/tuple/object/union/intersect/transform/lazy + date/regExp/arrayBuffer 复合体)+ meta 克隆语义 + from/extend + ValidationError($path 前缀) + Options(autofix/ignore/path/strict) + toString 全 formatter + toJSON(uid+refs 共享序列化) + i18n(mergeDesc) + simplify(deepEqual dict-aware);S.from_/is_/reg_exp/array_buffer 等 pythonic 命名(上游名映射进 docstring);cordis fiber 适配层(resolve_config/ValidationError 聚合消息)保留文件尾部;L0 叶零内部依赖,cosmokit 助手(deepEqual/isNullable/isPlainObject/clone/valueMap/pick/Binary)内联;callback 不做字符串求值、date/regExp/arrayBuffer 锚定 Python 对应物(载体差异标注) |
core/dsh_scope.py |
packages/core/scope/src/index.ts + store.ts |
dsh-scope 协议本尊(纯库,L0):ScopeKey 弱引用身份键、scopeParents 图(bind/link/rebind + 环检测)、scope_parent_of/scope_chain_of(nearest-first)、scope_target/_ScopeCarrier/is_scope_carrier/carrier_key_of、scope_of(parent 链)、NamedEntries/AnonymousEntries/ScopedLayers 对应 store.ts;Context.create_scope 返回 Scope 包装(delegation 包装,__slots__ 无 __dict__) |
core/hmr.py |
vendor/hmr/src/index.ts + packages/boot/hmr/src/index.ts |
Cordis HMR 服务:Hmr(Service) provide="hmr";register_config(filename, refresh)——findWatchRoot walk-up 根定位(realpath+depth+缺盘拒绝)、重复注册拒绝、初扫已存在目标即刷(chokidar ignoreInitial=false 语义:缺文件无初扫)、disposer 注销+关 watcher+join 在飞刷新;refresh_config(key) 单飞+dirty 合并循环、失败 logger.warn + hmr/config-update-failed 并行事件外泄不毒化循环;run_exclusive(operation) 串行事务队列(对齐 packages/boot/hmr runExclusive:嵌套拒绝 'HMR transactions cannot be nested'、关闭拒绝 'HMR is disposed';config-editor/plugin-manager 类宿主写路径与自动重载共用锚);销毁期注册归一 CordisError(INACTIVE_EFFECT)。载体 watchdog(上游 chokidar);Node ESM 模块图热重载(ModuleLoader/externals/accepted)不适用 Python 载体;Windows 短路径两侧 normcase+realpath 归一 |
core/tools.py |
packages/core/tools |
作用域化注册表(ScopedLayers/NamedEntries 存储:注册即 effect 归目标 fiber、fiber 销毁即自动注销;resolve/names 缺省取注册表 root 的 scope 键,显式 scope 沿键父链最近者胜 + 全局层兜底)+ 守卫执行管线(pre/execute/post waterfall + schema 校验 + 超时);schema_of/schemas 白名单投影 name/description/parameters +(存在时)deferLoading 标记;执行管线的规范化结果在 tools/post-execute 政策前经 project_content(上游 projectContent)安装内容,finalize_content 在结算前收口 |
core/tool_timeout.py |
packages/util(超时常量)→ 被 packages/guard/timeout-policy 消费 |
工具调用超时约定叶(L0,零内部依赖):TOOL_TIMEOUT = "TOOL_TIMEOUT"、timeout_error_message(timeout_ms);被 core/tools.py(管线超时替换 error_info={name:'ToolTimeoutError', code:TOOL_TIMEOUT})与 guard/timeout_policy.py 两侧共享——guard 超时执行器是 packages/core/tools 超时语义的消费方 |
guard/ |
packages/guard(timeout-policy + repeat-tool-reminder) |
循环卫生守卫:repeat_tool_reminder.py —— 重复工具调用提醒:Config(thresholds: [3,5,8] fail-loud 校验、include/exclude 通配符、argumentsPreviewChars 默认 500);per-agent WeakKeyDictionary 链,agent/pre-step 任一 user 消息清链;pre-execute 监听器对下行 {kind:'deny'} 决策计数并把提醒挂到 exec_.additional_contexts(mini deny 短路 post-execute);post-execute observe() 在委派前执行,提醒 prepend 到下游决策 additionalContexts(accept 路径 {kind:'accept', additionalContexts:[reminder]},block 路径保留 kind:'block');提醒消息 source {kind:'plugin', plugin:'repeat-tool-reminder', form:'notice', summary:'{tool} × {count}'};timeout_policy.py —— 只 import L0 core.tool_timeout 再导出 TOOL_TIMEOUT(超时执行器本体在 core/tools.py 管线,timer-wins),装配面 opt-in install_timeout_policy/install_repeat_tool_reminder。载体差异登记:上游 post-execute 决策 PostToolDecision {kind, feedback?, additionalContexts?}(tools/src/index.ts:599-602)——mini 管线读取 kind(旧 action 别名已统一);上游 pre 侧 deny-vote 计数在 post-execute 决策里反馈,mini 因 deny 短路改为挂 exec |
core/agent_loop/agent.py |
packages/core/agent-loop/src/agent.ts + index.ts |
单一 async 泵(_pump_async/_run_step_async)+ followup/steer 同步门面(经常驻单事件循环驱动,见下行 resident_loop)+ 协作式取消(_cancel_event 每轮新建 + call_soon_threadsafe 跨线程置位——对应上游 agent.ts:325 每 phase 新建 AbortController);aborted_cancel_cause 裁剪 abort 原因(对齐 agent.ts:79-94:只保留 {kind},hook 类另带 reason),cancel 与 _close_turn 落 turn/end 前经它过滤,杜绝 live fetch/AbortSignal 的额外字段(如 stack)进入日志;max_parallel_tool_calls 为经校验的普通配置值(对齐上游 Volatile 配置 + getter 读取,非 settings 服务);agent/pre-step 决策经 awaterfall;publish/dispose 生命周期(enter+announce+agent/session-start / cancel(disposed)+scope.dispose+detach,会话店成员资格归 loop)+ agent/* 事件载波派发(scopeTarget(agent, loop scope 键),兄弟作用域隔离)+ turn/step 编号 1 起经 _replayed_next_turn 从会话日志续号(对应 invariant.ts nextTurn:turn/end 闭合后 +1、尾部未闭合停在当前号;resume 冷重建 loop 不重置回合号);V2 流结算(agent.ts:375-458):正常完成 settle assistant/message(内嵌 stream、content=原始 assembler 块)、finish error/aborted 与异常先 settle assistant/attempt 再走 request-error waterfall、取消定稿 interruptedBlocks 前缀(空则 attempt) |
core/agent_loop/resident_loop.py |
(无独立文件:Node 进程固有单事件循环) | 教学扩展:进程级懒加载单例循环(守护线程 run_forever);run_on_resident 阻塞提交协程、异常冒泡、主线程 Ctrl+C 协作取消在途泵;同步门面由此驱动后跨调用共享同一循环,与上游形态一致 |
core/agent_loop/tool_calls.py |
packages/core/agent-loop/src/tool-calls.ts |
工具调用调度器(真并行):exclusive 单元素屏障 + parallel 有界滚动池(max_parallel 上限,读取经 AgentLoop.max_parallel_tool_calls getter;上游读 config.maxParallelToolCalls.get())、pre-execute 按模型序有序 await、execute 体真并行、结果按模型序提交;abort 时未启动调用按模型序补 TOOL_ABORTED_BEFORE_DISPATCH 合成错误 |
core/agent_loop/inbox.py |
packages/core/agent-loop/src/inbox.ts |
双队列(followup→next-turn / steer→next-step)+ agent/inbox/spliced 持久化 |
core/agent_loop/projections.py |
packages/core/agent-loop/src/index.ts(turnBoundaryProjectionDefinition)+ inbox.ts(inboxProjectionDefinition) |
AgentLoop 拥有的会话投影单元:turnBoundary(host-only,stateVersion 2,消费 turn/start·end、step/start·end)+ inbox(wire,stateVersion 1,从 agent/inbox/spliced fold 双队列,wire 值即 fold 状态);AgentLoop 构造在有 sessionProjections(M7)时注册,dispose 随作用域回滚——session/projections 暴露 inbox 单元,host-only 的 turnBoundary 不进客户端 cut(对齐上游 session-projection snapshot 的 wire 门) |
core/agent_loop/assistant_stream.py |
packages/core/agent-loop/src/assistant-stream.ts |
AssistantStreamAttempt:一次模型 attempt 的压缩 + 组装 + 终态结算封装(attemptId/revision/start/push/settle/abandon;settle 在持久事件 append 成功后发 committed、失败 abandon;push 同时喂 Accumulator 与 BlockAssembler);V2 assistant/message.stream 内嵌与 assistant/attempt 的生产端 |
llm/assistant_stream.py |
packages/llm/llm/src/assistant-stream.ts |
AssistantStreamRecord codec:AssistantStreamAccumulator 游程压缩(text/reasoning/tool-call delta 连续段 + 不可压缩原样 chunk,dt 硬性规定)、expand_assistant_stream 逐 delta 边界还原、validate_record exactKeys fail-closed;V2 seed 边界展开验证(_assert_current_assistant_stream)消费同 codec |
core/agent_loop/runtime_context.py |
packages/core/agent-loop/src/runtime-context.ts |
loop 侧运行时上下文投影:retained 三态(undefined/null/{seq,text})restore(倒序找最近一条仍在 surface 的 owned 快照)+ 按追加序惰性消化新事件;project(current, sections) 文本相等去重、变化铸快照 user 消息(sections 非空带 form:'snapshot' 归因,空即 CLEARED 哨兵不带归因);SOURCE/CLEARED 逐字一致;接线在 _run_step_async pre-step waterfall 前(默认进入把快照追加在 claimed 之后,显式 enter 决策整体接管) |
core/system_prompt.py |
packages/core/system-prompt/src/ |
assemble waterfall + contexts/tools/variables 提供器 + {{variable}} 严格插值 + render_context_sections/join_context_sections 节渲染面(上游 renderContextSections/joinContextSections);scope 层叠、assembly.tools→请求工具集成未复现(简化标注见模块 docstring) |
llm/protocol.py |
packages/llm/llm/src/ |
stream(messages, tools, signal) async 约定 + StreamAborted + _aiter_raced(异步迭代与 abort 事件竞速,asyncio 原生载体) |
llm/deepseek.py |
packages/llm/llm-deepseek/src/{adapter,config,defaults,models}.ts |
DeepSeek 官方 Anthropic 兼容 Messages 适配器:httpx 异步传输(原生 asyncio,abort 置位即关闭连接、真取消)+ per-read idle 300s watchdog(与上游 fetch 一致)+ catalog 能力解析 + image-capable 请求路径(Files API file-id 优先 → inline base64 回退 → stale-id 有界重试);base 缺省 https://api.deepseek.com/anthropic,POST messagesApiRoot(base)/messages |
llm/deepseek_messages.py |
packages/llm/llm-deepseek/src/{serialize,translate,sse,messages-api,transport}.ts |
Messages wire 层:harness 消息 → Anthropic content blocks(text/image/thinking/tool_use/tool_result)+ 请求体 {model,max_tokens,system?,messages,tools?,stream,thinking,output_config?,…} + SSE 事件派发(message_start/content_block_*/message_delta/message_stop/ping/error,message_stop 为完成点)+ 响应翻译(tool_use→tool-call、thinking→reasoning、stop_reason/usage 映射)+ HTTP/带内错误码映射 |
llm/deepseek_files/ |
packages/llm/llm-deepseek/src/{common,file-store,files-api,upload-index}.ts |
Files API 执行簇:file-id/defaults/models/types/model-info(能力解析)+ image-tokens(vision-token 计算器)+ request-pricing(路由目标 ImageRequestTarget + 请求图定价)+ files-api(Messages /v1/files httpx 传输)+ upload-index(files-v3.json + filelock)+ file-store(单飞共享上传 + 配额恢复)+ request-files(解析 + stale-id 重试 + 规范化图片诊断) |
llm/fake.py |
无 | 教学扩展 |
attachment/(types + error + image + encoding + normalization + projection + request_image + admission + file_store + store) |
packages/attachment/attachment(seam + types + error + admission + request-projection)+ packages/attachment/attachment-local(store + image + encoding + normalization + request-image + file-store) |
sharp→Pillow(权威全量解码/EXIF 定向/重编码);规范化管线(总像素预算 + 长边封顶 + 共享质量阶梯按 alpha 分流)与 variantId 请求图缓存(request-image-v6,路由目标 ImageRequestTarget)与 alpha.1 一致;verbatim 文件族与 alpha.1 一致(file_store.py:file_leaf_name 清洗 / files/<sha2>/<sha>/<name> 别名 + file-objects 规范对象 / save·save_stream·read_stream 摘要验证;AttachmentStore 七方法含 admit_prompt_content 实例方法);CompressionLimiter 并发闸与 SharedRequest 单飞登记架构不适用(同步载体天然串行);显式 root(上游 DSH_HOME/attachments/v1) |
llm/retry_policy.py |
packages/llm/llm/src/retry-policy.ts |
|
llm/retry.py |
packages/llm/llm-retry/src/ |
async 恢复决策(派发前熔合信号检查 + always 派发后复查中止胜过决策)+ 事件驱动多信号竞速可取消等待(等价 AbortSignal.any;裸测试替身信号回退轮询)+ 插件 effect teardown(注销监听器 + lifetime.abort + 排干在途恢复) |
llm/token_meter.py |
packages/llm/token-meter/src/ |
|
compaction/(config + region + summarizer + engine + tool_result_pruner + image_offload) |
packages/compaction/compaction-basic/src/ + compaction-tool-result-pruner/src/ + compaction-image-offload/src/(config / region / summarizer / index.ts / projection.ts) |
前缀重放无 KV cache 语义;toolResultPruner 可选阶段已与上游一致(compaction/tool_result_pruner.py,上游注入 ctx.toolResultPruner,mini 经 ctx.get('toolResultPruner') 取用);image_offload.py 镜像 compaction-image-offload——offload_oldest_images + agent/request-error 上的 IMAGE_OFFLOAD_REQUIRED surface 修复(install_compaction 一并安装),投影经 core/session/projections.py。配置对齐上游:headroomTokens 缺省 65536,maxTokens 缺省取 headroomTokens(不再固定 8192);resolve_spec(policy, contextWindow, reservedCompletionTokens) 压力预算 = 窗口 − 预留输出 − headroom,保留预算按「窗口 − 预留输出」缩放;reservedCompletionTokens 取请求信封 maxTokens 或适配器 defaultMaxTokens。摘要指令消息为无 source 的原始 user 请求消息(深冻结) |
jobs/(types + view + ring + pump + events + archive_admission + render + registry + tools) |
packages/jobs/(seam + jobs-local + tool-jobs) |
rc.1 重写:JobSpec.run(JobHandle)(append/updateProgress)+ pull 源(JobOutputSource)按 cadence 泵入 ring + JobOutcome.result;read 消费模型游标 / readAt 非消耗;JobEvents.subscribe(filter,listener)({owner}/{owners:'all'\|'scope'})替代 onJobDone/onJobsChanged;限界 OutputRing(绝对偏移 + 头部驱逐 + UTF-8 安全超块尾部);controller/订阅按注册 scope 分层;canonical value + render 分离;finalizeContent 可见输出二次封顶;owner 是 SessionId(经 ctx.agents 解析 live Agent;assert_live_agent 台账面已随 rc.1 移除);run_in_background 触发入口经模型侧 subagent 工具复现(简化标注见模块 docstring 与 verified-diffs §2.67/§3.44) |
plan/(config + mode + review + projection) |
packages/plan/plan-mode/src/ |
状态机 + plan:policy 节 + 审查 UI(exit_plan_mode / /plan / userQuestions)+ plan 投影;canonical value + Tool.render 已与上游一致(简化标注见模块 docstring) |
commands/ |
packages/interaction/commands/src/ |
命令注册/派发 + command/run|done 配对 + commands/change 通知 + normalizeResult fail-loud;handler 签名 (agent, raw) 为教学扩展(简化标注见模块 docstring) |
goal/(domain + service + prompt + driver + tools + commands) |
packages/goal/(goal + goal-round-driver + tool-goal + command-goal) |
Typert remote(上游命令由 human UI 表面派发,mini 用 /goal 命令承载);_prepare_mutation 前置 assert_live_agent(R4 agent registry);driver 模式事件驱动续跑(同步门面保留 continue_rounds);权威判定近似;三工具 canonical value + render 已与上游一致(简化标注见模块 docstring) |
skills/(registry + filesystem + tool_skill) |
packages/skill/(skill + skill-filesystem + tool-skill) |
无 chokidar watch、无 ctx.fs 适配;skill 工具 canonical value + render 已与上游一致(简化标注见模块 docstring) |
skills/office.py + skills/assets/ |
packages/skill/skill-office |
内置 dsh-office provider:office-docx/pptx/xlsx 三技能(assets 逐字节复用上游 SKILL.md + scripts/check_office.py 纯 stdlib 只读检查器);get() 正文追加 "LibreOffice Kit is disabled in this deployment."(上游 cli:false 降级分支)。载体差异:无 @deepseek-ai/libreoffice-kit(Node CLI + LibreOffice 二进制)——渲染/PDF/公式重算登记触发条件;装配 sdk-app 门控(DSH_PRIMARY_RUNTIME),install_office_skills 幂等 |
skills/workspace_dependencies.py |
packages/skill/tool-workspace-dependencies |
load_workspace_dependencies 工具:读 runtime.json(PrimaryRuntimeManifest 校验:platform/arch/python/node/pnpm/pythonPackages)+ dependencies/ 路径推导 + payload 原位校验/安装(staging cp → 原子 swap + .previous 树)。载体差异:mini 无捆绑运行时,未配置 payload 时回落运行中 Python(sys.executable + site-packages + 已安装分布);sdk-app 门控装配 |
telemetry/(folds + service) |
packages/session/session-stats/src/(projection)+ packages/llm/token-meter/src/(usage-projection + turn-usage) |
sessionStats/tokenUsage 投影 fold + derive_turn_token_usage(fail-closed)+ opt-in UsageStatsService(ctx.usageStats);register_telemetry_projections 把两单元注册进 ctx.sessionProjections(M7),projection_values 优先读注册表快照、否则服务镜像/现场折叠;contextPressure 与 telemetry-capture 不承载 |
telemetry/session_telemetry.py + telemetry/session_telemetry_otel.py |
packages/session/session-telemetry + session-telemetry-otel |
会话遥测(L2):SessionTelemetryBackend(ctx.sessionTelemetry)seam + SessionTelemetryCoordinator(live 订阅 session/created|event|disposed|flush + agent/error 并清扫在世会话 / on-demand 读 canonical log;每条事件经 session-telemetry/record waterfall 脱敏,本包无规则;模块级 handoff cursor 防重放;contain 单步异常)+ OTel 后端(LoggerProvider+BatchLogRecordProcessor+OTLP/HTTP;FEEDBACK_ONLY 按反馈 on-demand 采集、DISABLED 仅告警;sharing 模式;shutdown 期限)。载体差异:Node @opentelemetry/sdk-logs → Python opentelemetry-sdk;匿名 user.id 经 identity;feedback/committed 面板与 Session.fromRestore 采集路径不承载(mini 无 feedback 提交面板) |
session_projection/__init__.py |
packages/session/session-projection/src/{types,index}.ts |
会话投影注册 API v2(L1):ProjectionDefinition(key / init(header, inherited_event_count) / apply(state, event) / 可选 view + state_version)+ SessionProjectionRegistry(ctx.sessionProjections):订阅 session/created(新会话初始化 cell)与 session/event(eager drive),cell 惰性构建 + 按 is 变更门通知 on_changed;读面 state_of/snapshot/cached_snapshot/checkpoint/restore_floor/view_checkpoint/restore/hydrate。载体差异:merge-extensible 类型表 + zod schema → 运行时可选 state_schema/view_schema 可调用对象;上游 session.header → mini session.meta;WeakMap → WeakKeyDictionary。telemetry 经 register_telemetry_projections 把 sessionStats/tokenUsage 注册为单元,projection_values 返回注册表快照全部 wire 单元(含 inbox/title/turnOutline/permissions 等) |
session_turn_outline/__init__.py |
packages/session/session-turn-outline/src/{projection,types}.ts |
turnOutline 投影单元(M18,L2):preview 文本块 space-join + 空白折叠 + 预算截断省略号(50/120)+ turnOutlineProjectionDefinition(stateVersion 2,fold turn/start 锚定 + 人类 prompt 首块即胜 + draft 缓冲到 turn/end,wire view = turns 数组,state_schema 严格递增 turn) |
session_title/__init__.py |
packages/session/session-title/src/{index,normalize,types}.ts + session-title-first-prompt-llm |
会话标题(M10,L2):clean_title_text/truncate_title_utf8/normalize_title/fallback_title + fold_session_title + SessionTitleService(get/rename 用户钉扎/refresh 取消钉扎/register 提供者;自动 first-prompt 调度——fallback 先落、request/header 后执行提供者)+ titleInput(stateVersion 3)/title(stateVersion 1)投影 + register_first_prompt_llm_provider(系统提示词 framing + 输入字节上限 + max-tokens/error 映射)。载体差异:上游 llm/stream 事件与 async 微任务/AbortSignal 竞争 → mini 同步门面在 request/header 后触发;LLM 调用经 run_on_resident 驱动适配器流 |
session_projection_cache/__init__.py |
packages/session/session-projection-cache/src/{index,spec}.ts |
持久投影缓存(M14,L2):SessionProjectionCache(ctx.sessionProjectionCache)——写后节流(turn/end/create/dispose 强制 + count threshold + interval 惰性定时)落盘 session_projcache domain(per-record、version 7、backup-and-skip)+ 身份匹配(lifecycle + formatVersion + unseeded cut 守卫)+ 零 I/O cached_snapshot/跨格式边 cached_predecessor_title/hydrate_prepared/cold_snapshot 写回 + 无损 JSON 校验。载体差异:上游 async 持久化 + handle 级逐条读回验证 → mini 经 run_on_resident 同步驱动 storage domain 单写链 |
workflow/__init__.py |
packages/workflow/workflow/src/{index,types,runtime-types}.ts |
工作流接缝(M13,L2):WorkflowEngine(ctx.workflowEngine)服务定义 + WorkflowError 11 码闭集(缺省 fatal)+ validate_meta(违规聚合 META_INVALID)+ 六事件(workflow/start、phase、log、agent-start、agent-end、end)+ WorkflowRunId 品牌 |
workflow_ptc/__init__.py |
packages/workflow/workflow-ptc/src/{index,host,guest,runtime,realm,meta}.ts |
Python 工作流引擎(M13,L3):PtcWorkflowEngine.start(meta/脚本解析/provider/maxTotalAgents 前置校验)→ PtcWorkflowRun(host 侧:guest 程序经 PythonPtcRuntime 绑定面执行,workflowHost 绑定 begin/startChild/childResult/disposeChild/progress;六脚本全局 agent/parallel/pipeline/phase/log/args;FIFO 并发槽 + 总 agent/items caps + schema 子集选项 + 结果物化 + 取消/拆解)。载体差异:脚本语言 JS→Python(同 run_code flavor);子代理 structured 输出无载体(schema 子代理按上游「缺 structured = 失败 → null」语义);子代理经 continuation manager 启动 |
tool_workflow/__init__.py |
packages/workflow/tool-workflow/src/{index,record,types}.ts |
workflow 模型工具(M13,L3):workflow 工具(script/meta/args/run_in_background 参数、前台/后台结局、渲染)+ durable 记录(tool-workflow/run-start/agent-start/agent-end/run-end)顶层传输执行 + 后台作业集成 |
subprocess/__init__.py |
packages/subprocess/subprocess/src/index.ts |
subprocess 接缝服务(M17,L3):ctx.subprocess(resolve_executable/terminal_environment/scrubbed_parent_env 收编既有实现,无复制)。载体差异:Windows Job/systemd scope/execve runner 平台专属 containment 无 Python 等价(Popen 近似);spill 收集器以内存缓冲承载 |
deepseek_account/__init__.py |
packages/credentials/deepseek-account/src/{index,types}.ts |
账户服务定义(P1-21,L3):ctx.deepseekAccount 抽象 + LocalAccountService(恒 signed-out、getProfile/Balance → null、startSignIn 因无浏览器 fail loud)+ account/* Remote wire(getState/getProfile/getBalance/signOut)。载体差异:浏览器 PKCE + Platform HTTP 是浏览器宿主载体(触发条件:引入浏览器客户端时实现平台域) |
session_query/(config/extraction/documents/sqlite/service/tool) |
packages/session-query/{session-query,session-query-sqlite,tool-session-query} |
会话检索(L2):extract_event_text(一方事件语义文本)+ build_search_documents(surface 分类 current/shadowed/log-only)+ SqliteSearchIndex(FTS5 bm25 + snippet;查询当数据)+ SessionQuery(ctx.sessionQuery:search 跨会话最佳命中 / search_events 会话内 / read_event 原始窗口 / trace_event 替换来源 / lineage 世系;活会话经 ctx.sessions、持久化经注入 persistence)+ 五模型工具。载体差异:上游 tracing 提供方分层与 observation/lease 不承载(现场解析日志);授权/workpace 作用域(workspace-access + sessionProjections)不承载(无 workspace 实体,M5);session-log-export 由 web/downloads.py 承载 |
todo/__init__.py |
packages/todo |
待办清单(L2):to_todo_list(工具入参校验,措辞逐字对齐)+ fold_todos(todo/write 最新胜出、turn/start 清空)+ install_todo_tool(模型侧 todo_write;事件 todo/write 为 log-only,已入 core/session/types.py KNOWN_TYPES)。载体差异:上游投影单元经 ctx.sessionProjections 注册,mini 无投影注册表(随 M7),当前以纯函数 fold + 工具结果承载 |
spill/(__init__.py + retention.py) |
packages/spill/{spill,spill-local,spill-policy}(spill-policy/notice.ts / retention.ts) |
大结果落盘(L2):SpillStore(ctx.spillStore)seam + LocalSpillStore(每会话私有目录、0600 文件、注入式根)+ install_spill_policy(tools/post-execute prepend:可保留内容(text/image)的估算 token 超 maxInlineTokens 时把完整文本(图片位置写成可读附件地址)落盘、替换为有界 head/tail 预览 + 取回提示;图片整块保留或省略,提示报告 Omitted N images.;嵌套 PTC 复合结果省略整图时经 source {kind:'ptc-mode'} 的 user 消息重注 additionalContexts(ptc/run_code.py 转发);best-effort,失败绝不改写成功结果)。载体差异:上游策略依赖 dsh-output-retention(TextRetainer/describeOmitted),mini 内联预览与 describeOmitted 文案;上游按 UTF-16 码元切分并在代理对中间回退,Python str 以码点为原子单位,天然不在代理对中间切分,retention.ts 的代理保护不承载;上游 tools/ptc-dispatch-log 次臂不承载(mini 由 run_code 的 tool/ptc-dispatch 承载,post-execute 对嵌套结果照常保留) |
workspace/__init__.py |
packages/workspace/workspace |
工作区实体(L2):fully_qualified_workspace_path/default_workspace_title/realpath_normalize(realpath 为唯一性 canon)+ Workspace(稳定 uuid、目录路径、标题、有序会话账户:setTitle/attachSession/insertSessionBefore/detachSession/status)+ WorkspaceService(ctx.workspaces:create/create_now/initialize_default/resolve_by_path/list/get/remove/delete/insert_before + 全局归档会话集 archive_session/unarchive_session/workspace/session-activity waterfall 准入(活跃则 WorkspaceActiveSessionError)+stopActivity 写后派发 workspace/session-stop/归档丢 pin + 全局置顶会话集 pinnedSessionIds/pin_session/unpin_session(WorkspaceArchivedSessionPinError,pin 顺序最近在前)+ SessionActivity/SessionActivityItem/SessionActivityKind(Map) 类型 + 首用默认登记 initializeDefault/defaultWorkspaceId + workspace/changed 变更通知)。载体差异:上游经 ctx.storage.domain(storage-domain 表 + 双写恢复标记 + 单写链)持久化并做 header-validated 账户过滤/归档集,mini 以 JSON 注册表(含 order/archivedSessionIds/pinnedSessionIds/defaultWorkspaceId 字段,缺省回填空)+ os.replace 原子发布承载(无显式 domain version;无 pendingMutation 恢复标记;change 通知以自有 workspace/changed 承载;SessionActivityKindMap 以 {"turn": object, "job": object} 承载上游可合并类型表——本包声明随默认组合装载的 turn/job 家族,其余由各自 provider 合并;typert RPC 视图未承载)。详见 verified-diffs §2.63/§2.65/§3.40 |
settings/__init__.py |
packages/settings/{settings,settings-file} |
用户设置(L2):SettingsProvider(ctx.settings:命名空间注册 + 解析值 = schema 默认 → composition base → 用户文档 section)+ SettingsScope(get/watch/update/replace/mutate)+ 写路径 monotonic revision(陈旧写 SettingsConflictError/SETTINGS_CONFLICT)+ settings/updated(深度相等门控)与 settings/document-updated + redact_secrets(schema 声明 secret 位置只报 set 状态)+ SettingsFileProvider(JSON 文档原子写 + document_path/prepare_document + watchdog 外部改动重载,provider 源提交)。载体差异:上游 schema 用 schemastery(role('secret') + toJSON 线视图),mini 以纯 dict 默认值 + 显式 secret 路径集承载;typert RPC 描述视图未承载(settings-controller 以 schema:{} 占位)。rc.1 核心(settings/forms.py,步骤 182):SettingsForms(无注册机制、命名空间 = configEditor.entries() 唯一 profile entry id、读 configuration() 三层 value/base/user、写经 configEditor.edit 持久化 cordis.patch.yml、revision 追踪、configure({auto}) 页面策略、legacy settings.yaml 导入)+ install_settings_forms(幂等装配,要求 ctx.configEditor 在场);生产装配(步骤 184):web profile 已迁 boot/profile 驱动——cli/plugins/* 组合条目 + install_config_editor + install_settings_forms 装配,SettingsForms 成为 web profile 的 ctx.settings(命名空间 = web 组合条目 id,写经 config-editor 持久化 profile cordis.patch.yml);headless 手写装配仍维持 SettingsFileProvider 既有载体 |
boot/boot.py |
packages/boot/app-boot |
mount_root_include(Loader 服务 + 根 Include 条目,并登记 _BOOTSTRAP_INCLUDES WeakMap)+ boot()(装载根配置→依序补丁→审计未激活条目 fail loud,ACTIVE/FAILED/PENDING 三态对齐 auditStartupEntries)+ load_optional_patches(缺文件→空层、坏文件 fail loud)+ reconcile_profile_patches(对齐 app-boot reconcileProfilePatches:快照 previousFailures 四元 → entry.update 应用补丁世代 → 等旧 fiber 结算 + await_all → introduced 判定(requiredIds 点名或与 previous 不一致的新失败)→ 抛 / 旧 fiber 被拒未失败原样重抛 → emit app-boot/config-reload)+ watch_user_patches(经 HMR watch 用户补丁层 → reconcile 对账重挂)。载体:旧 {replace|insert} 叠层补丁在 boot 侧转成 applyEntryPatches 形态(_overlay_to_entry_patches,不做表达式求值);对账的 fiber 结算为同步等价(internal/update waterfall 内完成卸载/重装,无 Promise.allSettled) |
boot/composition.py |
packages/boot/app-boot + apps/cli/src/args.ts |
load_dotenv_file 与上游 readEnvLayer 一致:ENOENT 静默/其它 warn/已存在不覆盖/bootstrap-only 物化前整体拒绝;home= 为 harness-home 时 HOME_LAYER_PROXY_NAMES(HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY)豁免、代理名错误文案明说 home .env 第二条出路(index.ts:174-177) |
boot/dotenv.py |
packages/boot/app-boot(loadEnv) |
bootstrap-only 名单/前缀与 BOOTSTRAP_NAMES/PREFIXES 一致;HOME_LAYER_PROXY_NAMES 同款;豁免判定在 load_dotenv_file(同上游 readEnvLayer) |
boot/profile.py |
packages/boot/app-boot/src/{profile,profile-context}.ts |
profile 目录机制:resolve_profile_dir(名字校验 + $MINIHARNESS_HOME/profiles/<name>)+ init_profile(manifest + 空 cordis.patch.yml 模板)+ load_profile_directory(读 dsh.profile.bundles + 用户补丁层)+ bundle_patch_files(dsh.bundle.patch 单文件/列表)+ compose_entries(空根或 base 单次 applyEntryPatches)+ read_profile_patches(层序:bundle → profile cordis.patch.yml → home 级 → overlays,后压先)。载体差异:mini 无 npm bundle 包(dsh-base/web-app)与 pnpm 安装面——bundle 层解析与 plugin-manager 子进程族登记架构不适用/触发条件;headless/web 是 Python 组合入口(非 bundle 装载插件树),用户自定义 profile 的 CLI 全接线随该差异登记 |
boot/config_editor.py |
packages/boot/config-editor/src/index.ts |
ConfigEditor(ctx.configEditor):profile 活动条目的配置编辑持久化到 cordis.patch.yml——documentPath/entries()(根 Include 树唯一 id)/configuration()(inherited + override)/edit(entry, change)(filelock 锁锚 profile package.json → reconcile 磁盘现状 → Fiber._resolve_config 验证 → ruamel round-trip 注释保留改写 → effective 验证 → 原子写 → reconcile requiredIds,失败写回旧文本再 reconcile 回滚;全程 hmr.run_exclusive)。载体差异:schemastery Config 校验经 _resolve_config(有 schema 时);filelock + 本地原子写 |
boot/config_schema.py |
packages/boot/app-boot/src/config-schema/ |
profile 配置 schema 导出(步骤 182):generate_config_schema(compose 条目 → 逐插件 Config 投影 → JSON Schema 2020-12 文档 ConfigSchemaDump,含 $defs loaderExpression/entryMetadata/entry/entryList/patchList/patch/unknownConfig/includeConfig/includePatch/configN + x-cordis 注解 profile/complete/entries/diagnostics/patchSchema)+ collect_config_schemas(boot-free 走行、模块导入读 Config、group/include 子树递归)+ project_native_schema(schemastery → JSON Schema 投影器:object/dict/array/tuple/union/intersect/transform/string/number/boolean/const/any/never + 值位置 !!js 包裹 + x-cordis 注解 + partial limitation)。消费面:CLI --dump-config-schema(cli/main.py)。载体差异:mini 插件 config 多无 schemastery Config 声明 → 条目投影 unknownConfig(对齐上游无 schema 行为);lazy builder 执行一次;无法静态投影标 partial |
loader/(model/utils/patch/entry/group/tree/loader/isolate/include) |
vendor/loader/src/{index,internal,config/{entry,group,isolate,tree,utils}}.ts + vendor/include/src/index.ts |
cordis 组件系统活树:EntryTree 扁平 store + entries()/resolve()/import_()/write();Entry 生命周期(update/disabled/init、loader/partial-dispose、internal/plugin 归属)+ module 旧方言 apply 桥;EntryGroup 一级子列表宿主(create/remove/update/stop)+ Group 插件;Loader 服务(internal/config 树载体字面/普通条目 interpolate、internal/update 写回 + 重载日志、internal/plugin 自销毁回写 disabled、[Service.check] 的 intercept.await 门控、envData/exit)+ apply_entry_patches + isolate/intercept 条目选项(isolate.py:Local/Global realm + loader/patch-context waterfall 迁实现 + loader/partial-dispose realm GC)+ Include(文件读写/initial/dump !!js 原样、rename 重试)。方言:条目 YAML 用上游 entryListSchema(JSON_SCHEMA + !!js)。载体/适配(登记 §3):同步门面 + ctx.plugin(parent=) 显式归属、baseUrl 沿 ctx 父链上溯、settle_gathered 瞬态 loop 结算、getOuterStack 数据面。不适用:internal.ts(Node ESM 内部加载器) |
fs/(types/service/local/sandbox/observation_policy/diff/tools/str_replace_editor/search) |
packages/fs/fs + fs-local + fs-sandbox + fs-observation-policy + tool-fs + tool-str-replace-editor + tool-fs-search |
文件系统域(L1):FileSystem(ctx.fs)seam(含 watch 抽象契约,基类默认拒绝 FS_IO_ERROR)+ LocalFileSystem(realpath 身份、严格 UTF-8 + NUL 二进制拒绝、原子 staging、createIfAbsent 硬链接 no-replace、replaceIfVersion 陈旧守卫、字面编辑 LF/CRLF、watch 经 watchdog)+ SandboxedFileSystem(每次调用 read-only/workspace-write/danger-full-access 围栏)+ ObservedStateGate(fs/write-intent/fs/edit-intent/fs/observed)+ 模型侧 read/write/edit、str_replace_editor、glob/grep;write 落盘 meta(FsDiffMeta)带 operation 区分 create 空 hunk 与内容未变的不变覆盖。上游 tool-present 已删除,mini 同步移除 present 工具与注册。载体差异:AbortSignal→取消句柄;win32 DACL 复制/替换不承载;glob/grep 以 stdlib os.walk+re 替代打包 ripgrep(tool-fs-search);watch 以 watchdog 承载、无 chokidar ready 事件(observer 启动即返回,signal 只在 stat 前后检查);read_image 未承载(依赖图片/附件渲染)。详见 verified-diffs §2.45/§2.46/§2.64/§3.41 |
lsp/ |
packages/lsp/lsp |
LSP 能力 seam(L1,步骤 185):ctx.lsp 提供语言服务 provider 注册表 + 按文件末段扩展名的每查询、顺序无关选择,暴露四语义操作(goToDefinition/findReferences/goToImplementation/hover)无 JSON-RPC 逃生口;register_provider 原子预留 id+扩展名(非法/冲突不发布,fail-loud)+ 返回 disposer;LspError 稳定码闭集 + final_extension。载体差异:上游 provider id 是品牌类型,mini 以 str 承载 |
lsp_stdio/ |
packages/lsp/lsp-stdio |
通用 stdio 语言服务器后端(L2,步骤 185):framing(Content-Length JSON-RPC 编解码,头部/消息大小有界)+ translate(能力判定/Location/LocationLink/Hover 归一,纯函数)+ host(经 ctx.fs 规范工作区 + 约束读源)+ connection(子进程上的 JSON-RPC 端点:server→client 请求应答 + stderr 有界尾 + 增级终止)+ instance(握手 + 串行可取消查询队列 + 瞬态 didOpen→request→didClose + 有界拆除)+ LocalLspProvider(按规范工作区池化惰性单飞,传输失败透明重试一次)+ install_lsp_stdio(server 表)。载体差异:ctx.subprocess.spawn→asyncio.create_subprocess_exec(无 OS 级受管范围/进程树 containment);Web AbortSignal→鸭子类型信号 + 短轮询(abortable 不取消底层 work);AggregateError→单失败重抛/RuntimeError |
tool_lsp/ |
packages/lsp/tool-lsp |
模型可见 lsp 只读工具(L2,步骤 185):四操作;一基 UTF-16 光标→seam 零基位置;要求会话工作区 cwd(否则 LSP_WORKSPACE_REQUIRED);位置渲染(按文件分组、file: URI→工作区相对/绝对、maxLocations 省略标记、完整结果 maxResultChars 封顶)+ hover 渲染;tool:lsp prompt 节(order 2200,文本逐字)。载体差异:上游 apply(ctx,config) 经 ctx.tools.register + inject tools/lsp/systemPrompt;mini 以 install_tool_lsp(ctx, registry, config) 由 default_tools 在 ctx.lsp 在场时条件注册 |
cli/main.py |
apps/cli/src/args.ts |
launcher 选项解析 + 组合验证/dump/--dump-config-schema;_web_main(--profile web)为 boot/profile 驱动装配(步骤 184):首次把默认 web 组合模板(cli/web_profile.yml)种子进 $DSH_HOME/profiles/web/cordis.yml → 读 profile/home/overlay 补丁层 → boot 组合(条目 = cli/plugins/* 插件)→ 装配 config-editor + SettingsForms + settings-controller → default_tools + agentPreset 投影 → web/launcher.run_web。对齐上游 web-app bundle 的插件组合面 |
cli/plugins/* |
packages/bundle/web-app(插件条目) |
web 组合条目插件(步骤 184):每条目 apply(ctx, **config) 安装一个 web 服务(install_* 既有函数);permission-presets/session-title-first-prompt-llm 声明 inject 依赖(approval/sessionTitle),session-title 读 boot env ctx.adapter |
cli/headless.py |
packages/bundle/headless + apps/cli |
|
cli/default_tools.py |
无 | 教学扩展(上游是工具插件注册) |
cli/session_cmds.py |
无 | 教学扩展(上游会话管理在 web 表层) |
cli/preset_cmds.py |
无 | 教学扩展(上游 preset 管理是 web 表层 Remote:list/read/deletePreset/selectPreset)——miniharness presets 子命令,投影/锁/删除语义一致,不写 agent-preset/selected |
preset/presets.py |
packages/preset + apps/cli/config/agent-presets |
shipped root(system) + 多根 first-root-wins roster、project_preset/project_session_agent_preset 投影、PresetLockedError、PresetNotWritableError、mount 作用域审计;YAML 翻译(agent.cordis.yml → Preset);数据目录 preset/{minimal,standard};rc.1 声明式 registry 面——make_agent_preset_projection/register_agent_preset_projection(agentPreset 会话投影单元,stateVersion 1)+ roster rows()(AgentPresetRow 形态含 isDefault/broken)供 agentPresets Remote list/read/select 消费 |
preset/registry.py |
packages/preset/agent-preset-registry/src/{index,definition,composition-inventory}.ts |
声明式载体(步骤 182):AgentPresetRegistry(register(definition) 幂等 + 重复拒绝 + unregister disposer、composition_inventory() 声明态行投影 AgentPresetComposition)+ definition_composition/entry_list_problem/flatten_rows(声明行 flatten:组行跳过、组 disabled 继承、!!js 求值被拒→'conditional')+ install_agent_preset_registry(幂等装配 ctx.agentPresets)。组合行 flat 工具与 web/inventory.py 共享(单一实现,web→preset 显式例外)。载体差异:无 live fiber 常驻挂载(PresetTree/EntryTree 激活态行),mini 只提供声明态行(挂载树载体差异延续 §2.77) |
extensions/dynamic.py |
packages/extensions/* |
|
interaction/approval.py |
packages/interaction/user-approval |
审批服务(ApprovalService):策略两档 + 审计对 + approval:policy 系统提示词上下文 + set_policy(agent, policy) 注入模型可见变更通知 |
interaction/permission_presets.py |
packages/interaction/permission-presets |
权限预设(M11):PermissionPresetService(预设表捆绑 sandbox 模式 + 审批策略、derive/current/resolve/option_of、set 写 permission/preset 在前 + 只写变更旋钮、pin_initial_permission 会话钉扎、Auto 集成、permissions 投影 stateVersion 2、/permission 命令、catalog Remote);组合缺省读 ctx.shell.sandbox_mode/sandboxPolicy + approval 配置 |
interaction/user_questions.py |
packages/interaction/user-questions/src/index.ts |
UserQuestionError(name + 稳定 code)、ask() 校验序逐字(aborted → ASK_ABORTED / EMPTY_QUESTIONS / CALLER_NOT_LIVE / DELEGATED_CALLER / BAD_INTENT)、waterfall 派发(user-questions/request + no-answerer fail-loud → NO_PROVIDER)、restore_user_question_error 传输恢复、取消归一(航 signal aborted → ASK_ABORTED)。载体差异:waterfall base 经 core/scope.py awaterfall 扩展形参承载(见 §3.36) |
interaction/tool_ask_user.py |
packages/interaction/tool-ask-user/src/index.ts |
ask_user_question 工具(schema properties id/question/header/options/multi_select 逐字 + required 数组;execute 投影 + canonical {"answers":[...]};UQE → ToolResult(error="Error: {message}", error_info={name, code}));render 直接返回紧凑 JSON 字符串(mini 全局工具 content 载体使列表渲染会包 repr,载体等价见 §3.36)。仅装配 userQuestions 服务后注册 |
feedback/command_feedback.py |
packages/feedback/command-feedback |
会话级人工反馈(M12):FEEDBACK_CATEGORIES + record_feedback(feedback/record log-only 事件,trim/省略空 text/无 category)+ /feedback 命令(recordInput:false,空输入拒绝,成功两行 ack 含匿名用户 id)+ sessionFeedback Remote(record,session-not-found)。载体差异:Remote 经 Service + web/api.py 代理(上游 TypertRemoteService) |
feedback/message_feedback.py |
packages/feedback/message-feedback |
消息级反馈(M12):MessageFeedbackService(list/put/delete)——note 校验先于一切(note-blank/note-too-large)、目标校验(append-origin 非空 assistant/message)、版本 CAS(version-conflict + ifVersion)、无操作不追加事件、note/category 省略丢键、delete 幂等恒 {absent:true}、活/冷会话路径(live flush 参与 / persistence load+append+flush)。载体差异:上游 open/stat/read 句柄与逐条持久化验证不承载 |
client/trajectory.py |
packages/client/ui-trajectory |
|
mcp/types.py |
packages/mcp/mcp-client/src/{connection,index}.ts |
ReconnectConfig / RECONNECT_DEFAULTS / Config schema 默认值(serverName 模式 [A-Za-z0-9_-]{1,32}、toolCallTimeoutMs 60000、maxInstructionBytes 32768、GENERATION_CLOSE_TIMEOUT_MS 5000);resolve_reconnect_policy / resolve_mcp_config 以显式解析承载上游 Schemastery loader 的 fail-loud 归一校验 |
mcp/client.py |
packages/mcp/mcp-client/src/index.ts |
apply(ctx, config):scope-session 化 serverName 保留集 + resolve → 链接生成;McpServerConnection 同步门面 |
mcp/connection.py |
packages/mcp/mcp-client/src/connection.ts |
代连接 supervisor:stdio / streamable-http 统一,简历过期扫描 + 重连(初始/上限延迟、预算耗尽即停),工具归属注册(_RESOURCE_KEY / _TOOLS_OFFSET 预算集)与 sync_tools 换代、tools/list_changed 重同步、server instructions 字节上限 fail-loud、失败即拒绝(failOnStartupError 直抛);载体差异(SDK 2.2):SDK stdio 传输在子进程退出时不投递 EOF/异常(_drain_stdout 永久阻塞、read_stream 不关闭)——mini 以「握手/工具 RPC 有界竞速(_run_rpc,5s,对 generation.lost 中止)+ 常驻生命线 ping(watchdog,15s 心跳 / 3s 超时)」替代上游 within 取消令牌,杜绝子进程退出后握手流程阻塞挂起;代关闭屏障(GENERATION_CLOSE_TIMEOUT_MS)超时 fail-closed 防重叠子进程 |
mcp/transport.py |
packages/mcp/mcp-client/src/transport.ts |
传输工厂 + stdio 子进程 env 组装(复用 seams.subprocess_env 净身切片的 L3 例外,见 §3 规则 1) |
mcp/server_context.py |
packages/mcp/mcp-client/src/{server-context,mcp-servers.ts} |
server 挂载点 / CLI 定位(-m module、script、绝对路径)/ MCP_SERVERS_ORDER |
mcp/tools.py |
packages/mcp/mcp-client/src/tools.ts |
sync_tools:${server}.${name}#${hash} 公共工具名(stringHash32 → base36 → MCP 前缀截断)、darkfrozen 手写 JSON 序列化等价(frost_equal / create_output)、LLM 输入/输出/图片受理投影(admit 门 + variantId 请求图缓存);图片投影经 project_content 政策前安装(对齐上游 projectContent:三条件一致才返回,post-execute 政策仍可替换/阻止) |
mcp/resources/render.py |
packages/mcp/mcp-resources/src/render.ts |
render_resource_result:手动 JSON 序列化紧凑 JSON + blob 掩码(8 base64 字符不泄漏原文) |
mcp/resources/tools.py |
packages/mcp/mcp-resources/src/tools.ts |
list_mcp_resources / list_mcp_resource_templates / read_mcp_resource 三工具定义(server/cursor/uri 参数约定 + Render 双参) |
mcp/resources/runtime.py |
packages/mcp/mcp-resources/src/index.ts |
McpResourceRuntime(createResource 生命周期、资源请求经关联连接、disposer 注销)+ install_mcp_resources(ctx) 装配 |
mcp/fixture_server.py |
无 | 教学扩展(tests 的 stdio/HTTP 夹具,--die-after 自毁模拟崩溃) |
web/envelope.py |
packages/client/connection/src/{rpc-schema,rpc}.ts |
两信封消息联合(client-request / server-response)+ 连接层错误闭集(含 R3 新增 gateway/input-invalid);transport_error 折叠兜底码 ‘internal’ |
web/attachments.py |
packages/api/gateway/src/index.ts(encodeRpcResult / encodeRuntimeResult)+ packages/client/connection/src/rpc-host.ts(fullResponse)+ client/rpc.ts(parseBinaryResponse) |
unary 结果的二进制附件:bytes 叶子投影为 null 占位 + {path, codec:'bytes', part} 描述(循环引用 → gateway: circular RPC result)、result_response 分帧(失败/纯 JSON → application/json;有附件 → multipart/form-data 的 metadata + bytes-<i> 流式出体)、dumps 解冻后 wire 序列化;客户端重组在 webui/src/wire/rpc.ts |
web/api.py |
packages/api/session-controller/src/index.ts(session 域辅助入口)+ packages/preset/agent-preset-registry/src/index.ts(agentPresets Remote 面)+ packages/api/job-controller/src/index.ts(job/kill) |
WebApi unary 方法(list/search/create/selectModel/modelCatalog/canOpenWorkspacePath/openWorkspacePath/rename/fork/prompt/attachment/updateQueue/cancel/page)+ 路由表;session/queue placement 三态经 session/control 投影;agentPresets list/read/select(声明式 roster + turnBoundary 首回合锁 + durable agent-preset/selected);job/kill(栅栏折 job/not-found) |
web/args.py |
packages/api/gateway/src/index.ts(assertExactArguments:1112 / decode:1140)+ remote-error-codes.ts |
路由层 {args} 边界校验:每方法字段集合精确匹配(missing/unexpected → gateway/arguments-invalid)+ 顶层 JSON 类型(错型 → gateway/input-invalid);TypertGatewayFaultDetails{endpoint, field?};枚举/范围/非空/跨字段语义留 handler(业务码) |
web/stream_protocol.py |
packages/api/gateway/src/stream-protocol.ts |
Remote 流 wire 语法:open/cancel/item/end/error 帧(客户端四型与宿主三型都 exactKeys 闭合,多一个键即拒)、$events 打开与 $events/result payload 解析、无损 JSON 判定(dict 键须 str、float 有限非 -0) |
web/uplink.py |
packages/api/gateway/src/stream-server.ts(UplinkInbox)+ index.ts(GatewayInvocation.uplink 的 UplinkDecoder:1214-1285 / decode:1493-1514 / streamInboxBytes @default 262144) |
单条逻辑流的有界单消费者上行 inbox:整帧 UTF-8 字节记账、end 半关、end 后 item → gateway/protocol、超限 → gateway/uplink-overflow(违例带 {endpoint} details 并中止该流)、fail 先到先得、释放后丢帧;方法侧 UplinkItems 逐项过该 endpoint 声明的 codec(未声明走无损 JSON 校验 + 解码结果复校),被拒项折 gateway/input-invalid(消息 wire field "uplink" failed boundary validation,details {endpoint, field})并中止整条逻辑流 |
web/mux.py |
packages/api/gateway/src/create-mux-websocket.ts(RemoteStreamMuxConnection)+ stream-server.ts |
单条 /api/remote.mux WebSocket 承载全部 Remote 流;open/cancel/item/end/error 帧往返,二进制 1003/非法 1008/重复 open 1008 关闭码,隔离单流失败;每条 open 先建自己的 inbox(紧跟 open 的 item 排队不丢),item 违例以 Remote failure 中止该流并发终态 error 帧,$events 网关自有流 open 即释放 inbox |
webui/src/wire/mux.ts + webui/src/wire/json-value.ts |
packages/typert/protocol/src/types.ts(RemoteStreamHandle:93-121)+ packages/api/gateway/src/client/{stream-client,index}.ts(ClientStreamHandle / pump / failAll)+ packages/typert/protocol/src/json-value.ts(isRemoteUplinkItem) |
客户端一条逻辑流:openStream 拿到的 StreamHandle 发上行 item(先过无损 JSON 校验)、endUplink 半关、close 取消、next() 取下行帧;终态帧或断连(failAll)后 send() 抛错并让挂起的 next() 失败 |
web/events.py |
packages/api/gateway/src/index.ts(remote-event)+ packages/api/session-controller(api-session/*)+ packages/api/remotes |
$events 注册表:open 首帧 ready → 转发 emit/waterfall/cancel;api-session/* 转发源(created/disposed/status/error/activity)+ settings/document-updated(emit,转发 {ns, revision},对齐 remote-events.ts:40);waterfall 经 $events/result 结算(result/next/rejected/cancelled),未知 clientId fail-closed |
web/streams.py |
packages/api/session-controller/src/{index,remote-events}.ts + packages/api/terminal-controller/src/{index,retention}.ts + packages/api/workspace-controller/src/feed.ts + packages/api/workspace-files/src/index.ts + packages/api/job-controller/src/{rows,observe}.ts + packages/api/gateway/src/index.ts(GatewayInvocation:1287-1335) |
GatewayStreams Remote 方法面:session/follow(快照 snapshot{header,cursor,records,hasMore,projections} + 逐条 event)+ session/control(baseline{projections} + 实时 projection 替换帧;rc.1 已去 queues/jobs)+ terminal/retain(一帧 retained 后保持到取消/身份关闭)+ terminal/follow(snapshot{sequence,screen,info} + 有序 output/state)+ workspace/follow(baseline{items,archivedSessionIds,pinnedSessionIds} + upsert/remove/order/archived/pinned)+ workspaceFiles/changes(ready + change)+ job/list({type:'rows', jobs} 整集替换,纯 output 追加不刷新)+ job/follow(opened → output{chunks,next,lossy?} 按 64 KiB 软预算切帧 → 终态 status 后关流)+ $events 装配;每个流方法收一个 StreamInvocation(uplink() 一次 + 下行结束 close() 释放上行 + signal),声明的 codec 走 uplink_codecs()(rc.1 全为 In = never,故出厂空表);跨堆非阻塞唤醒线程安全。活体 event 载体 = ≤50ms 短轮询批量提取(_poll_new_events,seq >= cursor,0 基 seq 不吞首帧);terminal/workspace/files/job 四条流 = 控制器同步对象的非阻塞 pop 经 10ms 短轮询桥接;wire 无 since(重连=重开全量) |
web/approvals.py |
packages/interaction/user-approval + packages/api/remotes(last-resort approval 转发) |
审批桥:async tools/ask 闸门 → approval/request waterfall($events)+ $events/result 结算; outcome 映射 result∈APPROVAL_OUTCOMES(否则 unavailable fail-closed)/rejected→unavailable/next→nxt()/cancelled;审计对 approval/asked+decided;接线点在工具闸门(上游在 approval/request,教学简化) |
web/questions.py |
packages/bundle/client-ui-user-questions(应答面)+ packages/api/remotes(waterfall) |
user-questions 桥:install 挂 async answerer 到会话 loop.ctx 的 user-questions/request;wire {questions, agent: agent.id}(agent 投影为 id,上游 ui-user-questions 只消费会话上下文中的 agent);kind result 原样 value / next→await nxt() / rejected→_restore_wire_error(dict name/message/code 均有 str → UQE,否则 RuntimeError)/ cancelled→aborted_question() |
web/server.py |
packages/api/gateway/src/{stream-server,index}.ts(WS mux + 升级拒绝)+ packages/client/connection/src/{rpc.ts,rpc-host.ts}(unary 载体语义 + 响应分帧) |
FastAPI 载体:unary POST {args} 严格解包(/api/<endpoint>)+ $events/result 特判;载体状态码 404/415/400(token 门配置时 /api/* 另有 401,web/auth.py——上游 requestRejection 等价物),业务错误恒 200 + result.ok=false + server-response 信封(含二进制的结果经 web/attachments.py 分帧);WS /api/remote.mux;GET /api/session.export 载体(query 校验→400、调 build_session_export);SPA 静态 fallback;无 CORS(上游同款:靠 415 状态码挡跨站写入) |
web/downloads.py |
packages/session-query/session-log-export/src/{archive,index}.ts(导出域)+ api/session-controller(下载端点约定面) |
会话日志导出:parse_export_query(sessionId/includeDescendants)、SessionLogExportDeps、safe_session_id_segment、session_log_zip_filename、build_session_export(zip 条目序:根制品逐字原始文件名→后代 BFS+seen-set 去重→媒体、压缩等级缺省 6、私有错误安全壳);测试 tests/test_web_export.py |
web/frontend.py |
packages/host/frontend-static |
静态服务约定:遍历 403 / SPA 回退 200 / MIME 按扩展 / 未知扩展 octet-stream;index taps 恒 identity(无 boot-manifest);DIST_ROOT 默认 web/static/,经 MINIHARNESS_WEBUI_DIST 可指向产品化前端构建产物(webui/dist/),约定不变 |
web/inventory.py |
packages/host/plugin-inventory/src/{index,types}.ts + packages/preset/agent-presets/src/composition-inventory.ts + discovery.ts(entryListProblem) |
pluginInventory/list 投影:entries_snapshot(Loader 非 group 条目四字段 {entryId,moduleName,enabled,fiberPhase},无 loader 服务→空)、file_composition/composition_inventory/build_inventory(preset 组合行 flatten 经 preset/registry.py 单一实现:组行跳过、组 disabled 继承、!!js 求值被拒→'conditional' + condition 原文、无 roster→省略 agentPresets 键)、PluginInventoryService(ctx.pluginInventory);JSON-schema 方言与 !!js 求值子集同 loader。载体差异:preset.json 载体无插件行→rows: [] |
web/static/(index.html + app.js + style.css) |
packages/bundle/web-app + packages/client |
教学参照 vanilla SPA(无构建步):消费旧 SSE wire(events.mux/respond/host.describe),alpha.1 后端已删这些端点,故不对新后端工作,仅作历史/教学说明;产品化前端 = 仓库顶层 webui/ 独立 React 工程(只依赖新 wire 约定,见 §3 三层边界) |
web/launcher.py |
packages/host/webserver(Config:host 两值 + port 0)+ api/gateway heartbeat |
host/port 优先级「CLI --host/--port(经 cli/main 传入)> env MINIHARNESS_WEB_HOST/PORT > 缺省 127.0.0.1/0」;0.0.0.0 无 token fail-loud;心跳与上游 gateway 约定一致:uvicorn_options() 设 ws_ping_interval=2 / ws_ping_timeout=4(transport 级 Ping 2s + 连续 2 周期无 Pong 判定断开 ≈ 上游 websocketHeartbeatIntervalMs @default 2000 + MAX_MISSED_HEARTBEATS=2 terminate) |
web_tools/(runtime + network + policy + fetch_http + search_deepseek + search_tool + fetch_tool + trust + types) |
packages/web/web + web-search-deepseek + web-fetch-http + web/tool-web |
模型可见 web 功能族(L2,默认组合 dsh-base 挂载;install_web(ctx) 经 ctx.provide("web", ...) 暴露,四个 CLI 入口同挂,cli/default_tools.py 按 ctx.get("web") 条件注册工具):WebRuntime(URL 策略 + 凭据检查、双 provider 注册表重复 id → WEB_DUPLICATE_PROVIDER、执行期选择六分支、search 按 request.maxResults 封顶置 truncated、配置 id 回落 DSH_WEB_SEARCH_PROVIDER/DSH_WEB_FETCH_PROVIDER)+ fetch_http(匿名公共抓取恒可用 + 整址公网策略防 DNS 重绑定 + 字节帽/字符帽 + 同源重定向跟随 ≤maxRedirects、跨源拒绝)+ search_deepseek(Anthropic /messages 协议 + redirect:'error' 手动 3xx 拒绝 + citation_snippets + 归一 WebSearchResult)+ 两工具 web_search/web_fetch(schema/描述/输出必需字段逐字 + 节 order 2000/2100 + format_*_output 截断规则)。载体差异(见 verified-diffs §3.35):turndown→markdownify+bs4(GFM 表头/colspan 差异如实登记)、AbortSignal→threading.Event/FusedSignal 轮询、代理面简化恒直连、无 present 卡片、WebConfig searchTimeoutMs 烘焙 base 补丁 60000。测试:tests/test_web_tools.py 75 测(本地钉桩不触公网);全量 3048 绿。详见 verified-diffs §2.58 |
protocol/acp.py |
packages/acp/acp |
自动化专用 JSON-RPC 服务:initialize(sessionCapabilities:{close,list,resume})、会话生命周期 new/resume/list/close(校验序逐字、keyset 分页 page.at(-1) 游标、selectionFor 恢复已提交路由)、模型选择标准配置 set()(model/reasoning_effort 逐字文案、切 model 复位 reasoning;目录经可选 adapter.models_catalog/resolve_model_info()['reasoning'] 教学扩展承载;provider/model 变化时 agent/pre-step 追加 durable modelSwitchNotice user 消息——source {kind:'model-selection', form:'notice', summary≤120 字符},对齐 packages/core/agent/src/model-selection.ts)、prompt 同步完整回合(snapshot+pin、turnless/max-tokens/error 结算逐字)+ 更新流投影(agent_message_chunk 带 messageId、agent_thought_chunk、tool_call/_update completed/failed)+ 富媒体受理 + 一次性审批桥 + usage_update 发射(request/context 带 contextWindow + Session.request_context() + _emit_usage_update,assistant/message 带 usage 时发射)+ session/update 并发逐块流式通知(_install_update_stream 订阅 session/event 逐事件实时投影、update_sink 即时外发;in-process 载体收敛 server.updates 批量)+ 可写入磁盘归档:AcpServer(persistence=...) 可选 JsonlPersistence 后端——new_session declare + _install_persistence_hook(session/event append / session/flush flush)、close_session flush、list_sessions 合并磁盘 headers、resume_session 非 live 经 repair_and_replay 物化;磁盘写默认关闭(宿主装配持久化);简化标注见模块 docstring(磁盘会话仅事件日志重建、不给 live turn 后台执行) |
protocol/sdk.py |
packages/sdk/protocol + sdk/server |
messageId 为真实消息 id(与 inbox 回执一致,官方 SDK 依赖);互操作测试 tests/test_upstream_sdk_interop.py(需 pydantic + 上游 SDK 源码,缺则 skip) |
protocol/hooks.py |
packages/hooks/hook-protocol + hooks-claude-code |
默认 runner 与 runner.ts 一致:stdin JSON payload + trailing newline、cwd、CLAUDE_PROJECT_DIR env、缺省 600000ms 超时;保留"异步 + signal"同步近似(subprocess);source kind:PostToolUse 的 additionalContext 铸 hooks-claude-code source user 消息 prepend 进 additionalContexts(对齐 index.ts:199-201/258/265/269),Stop 阻塞时同 source steer(index.ts:281) |
seams/sandbox_local.py |
packages/sandbox/sandbox-local + sandbox-windows-acl |
landlock 后端经 seams/landlock_run.py ctypes 自限制执行器真执行(CLI 约定与 native/landlock-run/docs/cli-contract.md 一致:--ro/--rw/--/--probe、exit 125、报告行逐字);Windows ACL 写限制由 seams/sandbox_windows_acl/ 物化(见下行) |
seams/sandbox_windows_acl/(12 模块) |
sandbox/windows-acl-restrict-poc(单文件 index.ts 分区) |
ctypes FFI 物化 WRITE_RESTRICTED 写入限制:win32_abi / ffi(替上游 koffi)/ errors / acl / token / workspace_sid / path_boundary / grant / spawn / index / runner 一一对应上游分区;runner 为 python -m CLI(exit 127 失败签名);非 win32 平台 import 即抛 OSError;门控 e2e 见 tests/test_windows_acl_e2e.py |
seams/landlock_run.py |
native/landlock-run(C11 launcher) |
ctypes 复刻同一 CLI 约定与 Landlock UAPI 语义(ABI 协商 / PATH_BENEATH 规则 / PR_SET_NO_NEW_PRIVS → restrict_self → execvp;full ⟺ 内核 ABI ≥ 5,否则 partial 但仍受限;非 Linux 宿主干净退出 125) |
seams/sandbox_policy.py |
packages/sandbox/sandbox-policy |
ctx.sandboxPolicy:Config {mode 缺省 read-only, workspaceRoot} fail-loud 校验;resolve() = 显式 mode > 会话日志最后一条 sandbox/mode(session-mode.ts 的 effectiveSandboxMode fold)> 部署缺省,workspace 根先 canonical 后词法规范化、会话 cwd 即边界;三档策略上下文经 systemPrompt .context('sandbox:policy', order=110) 注册,loop 侧投影在变化时把快照注入对话消息流(core/agent_loop/runtime_context.py);模式变更围栏 add_mode_fence(fence) + set_mode(session, mode)(唯一写路径前逐个拒绝)——上游 terminal-controller 经 internal/dispatch 拦截 sandbox/mode 的同步等价面(mini 的 session/event 监听异常被存储层 contained,无法拒绝写入) |
shell/(types/bash_local/bash_sandbox/pwsh_local/pwsh_sandbox/helpers/env) |
packages/shell/{shell, bash-local, bash-sandbox, pwsh-local, pwsh-sandbox, shell-env} |
ctx.shell 执行器族:execute(spec) -> ShellExecution(句柄含 status/exitCode/signal/done/observed 非消耗偏移读/read_output() 消费读/kill() 与 result() 前台投影);resolve 补齐 workdir/timeoutMs/onExpiry(kill|none)/stdoutMaxBytes;已 aborted signal 视为已触发。本地直跑 / 经 ctx.sandbox confine 包裹并报告 {mode, denied, enforcement};三路归因与 helpers.ts 一致——runner 启动失败(ENOENT/EACCES 且 argv[0] 证据 + cwd 可用性独立校验)与 runner 失败规则命中经 result 装饰抛 SandboxUnavailableError 且优先于 denial,denial = 非零退出 + stderr 大小写不敏感签名;danger-full-access 直通不包裹。pwsh 变体(M16):PwshLocalExecutor(pwsh -NoLogo -NoProfile -NonInteractive -Command + UTF-8 编码前导 + PATH/ProgramFiles 解析、Windows PowerShell 5.1 兜底)+ SandboxPwshExecutor(confine + 三路归因),install_pwsh_executor/install_bash_executor 幂等。env.py 的 ctx.shellEnv 收集内置 DSH_* 并在 profileContext 在场时填充保留键 DSH_PROFILE/DSH_PROFILE_DIR。载体差异:无 ctx.subprocess 托管范围/spill 收集器,进程经 subprocess.Popen + 读/监视线程、内存增长缓冲(UTF-8 安全裁头)承载,observed 无 spillPath;SIGTERM→SIGKILL 宽限期近似。详见 verified-diffs §2.68/§3.45 |
tool_bash/(index/background/render) |
packages/shell/tool-bash/src/{index,background,render}.ts |
模型面 bash 工具(层 3 登记,消费 ctx.shell + ctx.jobs + ctx.shellEnv):Config {enableRunInBackground?, promoteOnTimeout?}(缺省皆 true);前台超时不再杀——提升为后台作业返回 {kind:'promoted', jobId, timeoutMs, output},run_in_background 返回 {kind:'background', jobId},纯前台投影 {kind:'foreground', …, stopped?};process_outcome(killed/completed + detail,runner 失败/denial 追加)、process_sources(observed 非消耗流作 pull 源)、ring_delta;parse_exit_status/render_result/render_promoted/render_job_read 逐字对齐 shell+tool-bash render.ts。载体差异:无 schemastery/沙箱升级审批面;一次装配——jobs 在注册时在场即用作业尾巴,foreground→job-backed 换装未承载;作业 owner=agent id。详见 verified-diffs §2.68/§3.45 |
tool_pwsh/(index/render) |
packages/shell/tool-pwsh/src/{index,render}.ts |
模型面 pwsh 工具(M16,层 3 登记,消费 ctx.shell + ctx.jobs + ctx.shellEnv):与 tool-bash 同构(三态 + jobs 集成 + stopped),差异在 pwsh 方言——描述文本(pwsh -Command/原生 Windows 路径/$env:)、作业 kind 'pwsh'、前台 canonical 恒带 kind:'foreground'、render_pwsh_result/render_promoted/render_job_read |
terminal/(types/sanitize/bounded_buffer/operation/service/__init__) |
packages/terminal/terminal/src/index.ts + terminal-bash/src/{session,sanitize}.ts(P1 核心契约,P2 由 terminal_bash 域承接) |
终端服务域(L1,仅依赖 core.scope):TerminalSessionService(ctx.terminals:spawn/kill/read/signal/start_send/list/get_owner_sessions/has_owner_activity/register_backend)+ TerminalError 8 码闭集(TERMINAL_ERROR_CODES)+ BoundedTextBuffer(bytes+maxLines 双限、consume()={delta,truncated}、首块永不增长、代理对感知记账与拼接修正、淘汰端逐单元出队)+ TerminalSanitizer(CSI/OSC/short 转义 + 跨块 pending + 二进制拒绝)+ LocalSendOperation(单飞 + owner 栅栏)。对齐证据:service.ts:160 名校验(仅空串拒绝,PTY session name must be non-empty)、session.ts:44-156 缓冲语义、service.spec.ts 拒绝面(OWNER_NOT_LIVE/NO_BACKEND/DUPLICATE_NAME/SEND_ACTIVE/FOREIGN_SESSION)。详见 verified-diffs §2.52/§3.29 |
terminal_bash/(config/environment/emulator/provider/shell_activity/session/index) |
packages/terminal/terminal-bash/src/{index,config,environment,session}.ts + packages/shell/pwsh-local/src/index.ts(P2 后端)+ packages/subprocess/subprocess-local/src/{terminal,shell-activity}.ts(subprocess PTY 面) |
真实 PTY 后端(层 3 登记,拓扑同 shell):resolve_config(rows=40/cols=160 缺省)+ child_environment(owner.id/DSH_SESSION_ID/DSH_PTY_SESSION_ID + UTF-8 preamble + NO_COLOR/TERM=dumb)+ bash CONTROLLED_PROMPT 与 pwsh 133;D 标记 prompt 复盘 + LocalPtySession(poll_readiness 五判据兜底结算 stdin_read/inferred_idle/timeout/session_exit、interrupt:posix 前台组 SIGINT / win sendintr、增量 UTF-8 解码)+ TerminalHandle 契约(SubprocessForeground/SubprocessOutcome/SubprocessTerminalActivity + inspect_foreground/inspect_activity;write/signal 前作废 shell-activity、terminate 置静默并释放)+ 平台拆三 provider(_posix.py pty;_winpty.py pywinpty PtyProcess + reader 线程 + SubprocessOutcome 退出封装)+ shell_activity.py(仅非 win32 纯 bash|zsh -i 注入私有 --rcfile/ZDOTDIR,状态文件 pid:seq:idle|busy,inspect_activity 据 prompt 证据 + 前台进程组判读)+ install_terminal_bash(幂等)/apply(依赖 terminals 先装,镜像上游 install/apply 分离)。载体差异:pyte 不含 ? 私有前缀 CSI(扫描层剥离)、pyte LF 无 CR、Windows 无前台组/无 termios(sendintr,activity 恒 unknown)、winpty write 收 str / read 回 str;inspect_activity 无进程表 inspect(descendants/完整快照/会话存活)与 managed task count,只凭 shell-activity + 前台组。详见 verified-diffs §2.53/§2.66/§3.30/§3.43 |
tool_terminal/(render/tools/__init__) |
packages/terminal/tool-terminal/src/{index,render}.ts(P3 六工具) |
终端模型工具族(层 3 登记,消费 terminal P1 + jobs L2 + core.system_prompt):六工具 terminal_open/terminal_send/terminal_read/terminal_signal/terminal_close/terminal_list(schema/description/output/render/present_call/present_result/finalize_content 全量)+ render_spawn/send/send_read/read/list 与 bound_terminal_text 逐字对齐 render.ts(fitWithPrefix/boundBodyWithSuffix)+ resolve_config(DEFAULT_MAX_RESULT_BYTES=256*1024、MIN_MAX_RESULT_BYTES=64 fail loud)+ register_terminal_tools + install_tool_terminal(幂等,缺服务即建:systemPrompt tool:pty/order 1700 + terminals + tools 注册)/apply;后台 terminal_send 经 jobs.start(kind='pty-send', label='<id>: <text|(input)>', owner=owner.id, outputLimitBytes=maxResultBytes) 装配(惰性 pull 源 _send_source 消费 operation 增量并渲染 render_send_read,对齐 background.ts sendSource;JobDoneBox + _await_settle 轮询结算 → completed/killed/failed)。载体差异:无 presentationMeta 通道、无 tools/execute 中间件(finalize_content 施加在五类 ToolResult 路径)、同步轮询桥接替代 Promise、tool:pty order 用字面量 1700、_SignalAdapter 映射 ToolExec.signal→terminal Cancellation。详见 verified-diffs §2.54/§3.31 |
terminal_controller/(types/stream/terminal/shells/index) |
packages/api/terminal-controller/src/{index,terminal,stream,shells,types}.ts(P4 浏览器终端域) |
Session 作用域浏览器终端(层 3 登记,消费 terminal P1 + terminal_bash.provider PTY seam + core.scope):TerminalController(ctx.terminalController:environment/shells/list/create/follow/write/resize/rename/close;owner 作用域 + 服务拆解 + install_terminal_controller 幂等)+ BrowserTerminal(pyte HistoryScreen 有界恢复屏、follow 独占输入并降级旧附加为只读、require_controller 精确 not-running/read-only、close 先 terminate→drain→finish)+ TerminalFollower(JSON.stringify(frame) UTF-8 字节预算、超额显式失败 reconnect to recover)+ shells.py(terminal_environment/resolve_executable 对齐 subprocess-local resolveExecutable:空拒/相对路径拒/绝对 stat+X_OK/PATH×PATHEXT;profile cmd=[]、pwsh=-NoLogo、其余=-i)。消费面:web/args.py 十条 terminal/* 边界规格(agent wire=agentId、list/retain=sessionId)+ web/api.py 九 handler + web/streams.py terminal/retain(一帧 retained 后保持到取消/身份关闭)/terminal/follow 流 + envelope.RPC_ERROR_CODES 两码;cli/plugins/terminal_controller.py(web profile 组合条目,boot/profile 驱动装配 sandbox+sandboxPolicy+terminalController)。载体差异:同步单线程无 pending 窗口、pyte 纯文本恢复屏、沙箱模式围栏挂在 sandboxPolicy.add_mode_fence(上游 internal/dispatch 拦截的等价面)。详见 verified-diffs §2.55/§3.32 |
workspace_controller/(index) |
packages/api/workspace-controller/src/{index,commands,feed,types}.ts |
工作区 Remote(层 3 登记,消费 ctx.workspaces):WorkspaceController(ctx.workspaceController:create/initializeDefault/rename/delete/insertBefore/insertSessionBefore/archiveSession/unarchiveSession/pinSession/unpinSession + follow 代次;命令经锁串行化 + WorkspaceFault 稳定 workspace/* 码,归档活跃折 workspace/session-active 带 activity)+ WorkspaceFollow(订阅 workspace/changed 投影 baseline/upsert/remove/order/archived/pinned)。依赖扩展:workspace 注册表新增 order/归档集/置顶集/默认登记/resolve_by_path/insert_before/delete/变更通知。载体差异:变更事件以自有 workspace/changed 承载(上游 storage-domain domain/changed);首用目录经配置 documentsDirectory(缺省 ~/Documents)而非原生命令查系统 Documents;initializeDefault 无 AbortSignal(无原生命令面);directoryPicker namespace 因无后端缺席。详见 verified-diffs §2.63/§3.40 |
workspace_files/(__init__) |
packages/api/workspace-files/src/{index,changes,types}.ts |
工作区文件预览(层 3 登记,消费 ctx.fs):WorkspaceFiles(ctx.workspaceFiles:read 按行分页 bounded 切页、readBytes 原生字节(options.range 窗口 / 省略读整文件受 maxFileBytes cap / options.baseFile 基目录解析,rc.1 折入 readAll/readRelated)、stat、工作区限定 list + 目标级 changes 流);WorkspaceChanges(ctx.fs.watch OS 监听 + fs/observed 过滤到解析目标,命中后重 stat 产出 version/absent);FsError 折 workspace-file/* 七码(含 watch-unsupported);fs 异步面经 run_on_resident 同步驱动。详见 verified-diffs §2.56/§3.33、§2.70/§3.47 |
settings_controller/(__init__) |
packages/api/settings-controller/src/{index,credentials,types}.ts |
设置/凭据 Remote(层 3 登记):SettingsController(ctx.settingsController:脱敏 describe + update/replace/mutate + openSettingsDocument/openAgentPresetDirectory)+ CredentialsController(ctx.credentialsController:describe ≤64 refs / set / unset);settings/conflict/settings/rejected/credential/rejected/agent-preset/read-only。依赖扩展:settings 新增 document_path/prepare_document、credentials 服务新增 describe/set/unset。载体差异:无原生打开器(canOpen 恒 False)、schema 以 {} 占位;autoGenerate 缺省 true(上游 presentations.get(fiber)?.auto ?? true,mini 无 configure 面恒缺省)。详见 verified-diffs §2.56/§3.33 |
context/(time_context/tmux_context/file_reference/file_reference_local/session_reference/agent_instructions) |
packages/context/{time-context,tmux-context,file-reference,file-reference-local,session-reference,agent-instructions} |
请求上下文插件(层 2 登记,消费 ctx.sessionProjections/ctx.shell/ctx.sessionQuery/ctx.spillStore):time_context(每步时钟读数 + 浏览器时区策略 + timeContext 投影)、tmux_context(tmux 方位查询/变化抑制 + tmuxContext 投影)、file_reference+file_reference_local(@file 词法 + WorkspaceFileSearch 模糊索引 + ctx.fileReferences)、session_reference(dsh-session: URI/提及 + 跨会话有界快照 + ctx.sessionReferenceResolver candidates)、agent_instructions(AGENTS.md 发现/去重/预算渲染/基线/reconcile + pre-step 注入与 tools/post-execute touch)。载体差异:time-context zoneinfo、tmux 同步 shell、file-reference-local 同步索引、session-reference 标签回退 id、agent-instructions 无 turnBoundary 投影。详见 verified-diffs §2.57/§3.34 |
seams/credentials_local.py |
packages/credentials/credentials-local |
文档为 version-1 JSON 布局 {version:1, refs, records}(上游 YAML):fail-closed 解析 + 可识别 flat 文档启动自动迁移;记录服务侧五件套(read/describe/list/modify/delete_record + .records 只读视图,键语法 [a-z][a-z0-9-]*、写锁 DOCUMENT_LOCK_WAIT_SECONDS=30、modifyRecord 唯一写路径——锁内 reconcile + mutate + 写前准入 = 读路径选择);CredentialsService 桥接:CredentialsService(Service) provide="credentials" 包装 LocalCredentialProvider,modify_record/delete_record 成功后发 credentials/record-updated(key)(无 carrier ancestor 路由);install_credentials(ctx, provider) 装配;引用半边:describe(ref)/set(ref,value)/unset(ref) 委托 provider(settings-controller 的 credentials namespace,值只进不出);读侧热重载:读入口 _refresh_if_changed() 先 os.stat 比对 mtime/size、变了才整表重解析(外部编辑/删除即时生效),写路径 _reconcile_from_disk 折叠不变,原子写无撕裂读侧不需锁 |
seams/authorization.py |
packages/credentials/authorization(src/{index,types,invariant}.ts,全套 437 行) |
AuthorizationService(Service) provide="authorization" + install_authorization(ctx)(显式 opt-in,依赖 ctx.credentials 缺失 fail-loud)。错误码闭集 DUPLICATE_FLOW/NO_FLOW/UNKNOWN_METHOD/ALREADY_IN_FLIGHT/NOT_COMMITTED/DECLINED/CANCELLED;registerFlow effect 登记(disposer 注销,二次 DUPLICATE_FLOW)+ begin 复核 ALREADY_IN_FLIGHT;list/describe;begin 校验序 NO_FLOW→UNKNOWN_METHOD→ALREADY_IN_FLIGHT→pre-aborted(返回 cancelled 不占槽不 settle)→ 占槽(同步 AbortSignal)→ _attempt(AuthorizationSession.commit 对齐上游 index.ts:400-408:signal.throwIfAborted + attempt 活跃检查 + committing 置位 + modifyRecord 写记录;cancel 在 committing 后不取消——"Once admitted, cancellation waits for completion";credentials/record-updated 记账兜底 + describe_record 二次确认、declined/pre-aborted → cancelled 不核 commit、未提交 → NOT_COMMITTED)→ _settle 发 authorization/settled(payload (key, settlement) 元组、listener 异常 contained);简化标注:async→sync(begin 同步返回)、AbortSignal 无事件机、interaction 回调参数化 |
seams/subprocess_env.py |
packages/subprocess/subprocess/src/index.ts + types.ts |
环境清洗切片:SENSITIVE_ENV_PATTERN 凭据形启发式 + DSH_ENV_PREFIX 大小写不敏感剔除;显式 env 在 scrub 之后合并(providers spawn 层叠)。subprocess 的终端 process 契约(SubprocessTerminalActivity/inspect_activity/shellActivity)由载体 terminal_bash.provider 承载(seams 层不得反向 import terminal_bash,§依赖方向):inspect_activity 见 verified-diffs §2.66 |
seams/subagent/(__init__.py + descriptor.py + providers.py + worker.py + continuation.py + archive_admission.py + tool.py) |
packages/subagent/subagent + subagent-fork-in-process + -acp + -dsh-sdk + subagent-spawn-in-process + subagent-in-process-driver + tool-subagent-control + tool-subagent-report |
续跑 A8 为异步事件驱动(双路径:父有 driver → 投递即返回 + watchSettlement 结算 + steer 批内合并;无 driver → 回退同步 pump)。生命周期 scoped dispatch(委托父 scope 载体过滤,无标号退化祖先链)+ provider 注册表(register_provider → 注销发布 subagent/provider-removed)+ DRAINING 拒绝面(drain/drain_descendants/drain_children + assert_admitting 准入边界)+ report 工具逐字约定(output 参数、部署级 reportDelivery 'quiet'|'next-step'、{messageId} 返回与 render)+ childId 预留 DUPLICATE_CHILD 断言已与上游一致;prompt 内容受理与上游一致:文本穿透、图片经父作用域 attachments store 受理为 durable 引用(子适配器须声明 image 输入模态,否则 reason=MODEL_DOES_NOT_SUPPORT_IMAGES;store 缺席/受理失败折 subagent/attachment-invalid,reason=底层 code),file 在宿主边界拒收(reason=SUBAGENT_FILE_UNSUPPORTED,镜像上游浏览器客户端路由前拒绝);rc.1 增量:archive_admission.py 归档准入(running 后代 workspace/session-activity 的 {kind:'subagent'} + session-stop parent 取消,runtime 构造点注册根上下文)+ ActivationPool 进程内容量(经不间断 continuable 父链共享,maxActiveSubagents 默认 8 / maxDepth 默认 1 / resolve_max_depth,满额抛 ACTIVATION_LIMIT_REACHED)+ list_agents status running|inactive + scope(children 默认 / descendants);catalog 事件/投影、sessionQuery.observeSession、Remote subagent.list、model-selection settings 链为 mini 无载体(架构不适用,见 verified-diffs §2.69/§3.46);invariant 运行时校验架构不适用;同步模式结算投递走非唤醒 next-step |
seams/agent_team/(13 模块) |
packages/experimental/agent-team + tool-agent-team(src/index.ts) |
Agent Teams 实验族:implicit-root roster + durable peer mailbox + shared task DAG。types/validation/error/journal/projection(team/member(v2)/team/task/team/message/queued/team/message/delivered 四事件全 log-only、payload 逐字段 zod-strict fail-closed、task revision 从 1 连续、图成环拒、写域 advisory 重叠校验);roster(spawn/stop/interrupt/reconcile/live_children_by_root;成员以 start_continuable(agent_options={provider}) 子会话承载,descriptor agentProvider 承载请求方 provider);mailbox(Team authority queue → steer_host_subagent 冷/热三态路由);task_board(8 动作 CAS 转移矩阵);activity(with观测窗口 wait_for);lifecycle(admit/JOINED 窗);service(同步门面);tools(9 工具 + team:policy 提示节,canonical value 全 fixed record)。sync/async 双投递载体:同步 _spawn_admitted(harness/CLI 无循环态)+ 事件循环内 start_continuable_async/spawn_async/_checkpoint_initial_prompt_async(await 让出控制,驱动载体不被 time.sleep 阻塞)。简化:wire/Remote 端点不承载(错误语义走 TeamError.code 闭集)、上游 todo 事件与 client-ui-agent-team/web-profile 前端 wire 面由 webui/ 自行选择 |
seams/session_checkpoint.py |
packages/session/session-checkpoint-policy/src/index.ts |
语义持久化检查点(三屏障):模型请求(agent/checkpoint boundary='request',请求信封落日志后、adapter 派发前)+ 顶层工具(tools/pre-execute,exec_.agent 有且 exec_.parent 为空;取消折叠为 canonical ABORTED_BEFORE_DISPATCH)+ 步边界(agent/pre-step);经 SessionStore.checkpoint(无持久化参与者 fail-closed)。载体差异:上游经 llm/stream 服务 waterfall 延迟适配器构造,mini 单一 adapter 直接调用故改用 agent/checkpoint waterfall。install_checkpoint_policy(ctx) opt-in |
ptc_runtime/(types + service + runtime) |
packages/ptc-runtime/ptc-runtime/src/{index,types}.ts + ptc-runtime-node + packages/experimental/ptc-runtime-python |
PTC(programmatic tool calls,程序化工具调用)执行 seam:PtcRuntime Service Definition(ctx.ptcRuntime)+ 保留名常量(RESERVED_BINDING_GLOBALS/RESERVED_ERROR_MEMBERS/PORTABLE_RESERVED_WORDS/DUNDER_MEMBER)+ 绑定校验;PythonPtcRuntime 每请求在全新 CPython 子进程跑模型 Python(顶层 await/return),绑定经 stdin/stdout 行 JSON 协议桥接,墙钟预算/中止/输出上限 + 正交失败分类(exception/timeout/abort/worker-exit/invalid-output/output-limit/protocol)。载体差异:上游 Node 后端 worker/subprocess + fd-3 wire,mini CPython 子进程 + 行 JSON;子进程非安全边界(上游同款声明)。install_ptc_runtime(ctx) |
ptc/run_code.py |
packages/core/tools/src/ptc.ts |
PTC 模式 run_code 工具(上游 createRunCodeTool):程序经 tools.<name> 调用 agent 可见工具(嵌套子派发);每次子派发落 tool/ptc-dispatch-start / tool/ptc-dispatch(rootCallId/parentCallId/subCallId=<parent>:ptc:<n>/name/arguments/isError/content);只有外层精心挑选的结果进模型历史。describe/parameters 按 runtime 语言取 flavor(typescript/python)。载体差异:上游用 registry 分阶段调度接口(prepare/dispatch/finalize/finish)+ 并发池,mini 经 run_pipeline 顺序执行(事件序与 payload 形状对齐,并发上限简化登记) |
demo.py |
packages/examples/agent-spine-demo |
教学入口,保留顶层(python -m miniharness.demo) |
example_plugins.py |
examples/ |
教学示例,保留顶层 |
3. 依赖方向规则¶
分层如下(Python 没有编译期模块边界,规则由 tests/test_dependencies.py 的 import 方向断言固定,违反即测试失败):
| 层 | 内容 | 允许依赖 |
|---|---|---|
| L0 地基 | core/session、core/scope、core/dsh_scope、core/schema、core/hmr、core/home_paths、core/tool_timeout、loader |
无(互不依赖;core.scope ↔ core.dsh_scope / core.schema / core.hmr→core.scope / loader→core.scope 经 §3 例外豁免;core.tool_timeout 是超时约定常量叶,被 core.tools 与 guard 两侧共享) |
| L1 领域 | llm/*、core/tools、core/system_prompt、core/session_store、core/agents、attachment、ptc_runtime、identity、storage、fs/*、lsp、boot/*、guard、session_projection、terminal |
仅 L0(fs 单元还注册模型侧工具进 core.tools——§3 规则 1 显式例外;terminal 仅依赖 core.scope) |
| L2 编排 | core/agent_loop、compaction、jobs、plan、commands、goal、skills、telemetry、session_query、todo、spill、workspace、settings、context、web_tools、lsp_stdio、tool_lsp、session_turn_outline、session_title、session_projection_cache、workflow |
L0 + L1 |
| L3 应用与入口 | cli/*、protocol/*、seams/*、preset、extensions、interaction、feedback、client、mcp、web、shell、tool_bash、tool_pwsh、terminal_bash、tool_terminal、terminal_controller、workspace_controller、workspace_files、settings_controller、workflow_ptc、tool_workflow、subprocess、deepseek_account |
L0 ~ L2(tool_bash/tool_pwsh 消费 shell seam / cli 组装 tool_bash、tool_pwsh 复用 tool_bash background 助手 / workflow_ptc 消费 seams subagent / subprocess 收编 seams+terminal_controller / cli 组装 tool_workflow+deepseek_account / web 投影复用 preset/registry 组合行工具,见 §3 依赖例外) |
| 教学层 | demo.py、example_plugins.py |
任意层,但不得被业务模块依赖 |
三层组织边界(代码与结构上清晰分离、解耦):
| 边界 | 内容 | 耦合面 |
|---|---|---|
| core 核心能力 | miniharness/core/ 等(L0~L2 纯领域逻辑) |
不感知 web/CLI 传输载体 |
| 后端 web 服务 | miniharness/web/ + protocol/ 等(L3 传输层) |
消费 core 能力;对外发布 HTTP/WS wire 约定(信封/帧/错误语义) |
| 前端工程 | 独立工程形态:webui/(React+TS+Vite,产品化)走新 wire;web/static/ vanilla SPA 降为教学参照(旧 wire,不实跑) |
只依赖后端发布的 wire 约定,禁止 import/hack Python 内部 |
前端唯一的耦合面是 web/ 层发布的 wire 约定,不是 Python 内部 API——这保证前端可独立选用现代化的技术组合(如 React)而无需改造内核。
webui/(仓库顶层独立工程,React+TS+Vite):产品化浏览器前端,只消费 web/ 发布的 alpha.1 wire 约定(两信封 RPC /api/<endpoint> + /api/remote.mux WS 帧 + $events/$events/result + session/follow/control),零 Python import。三层结构:src/wire/(约定客户端层,纯 TS 可单测)、src/app/(React 编排 hooks)、src/ui/(无状态展示组件);测试用 vitest(mock fetch/WS)。构建/运行手册见 webui/README.md:开发期 Vite dev server 把 /api 与 /api/remote.mux 代理到本地 Python 后端(vite.config.ts,目标经 MINIHARNESS_WEBUI_PROXY 覆盖);生产期 vite build 产出 webui/dist/,后端 web/frontend.py 经 MINIHARNESS_WEBUI_DIST 指向该产物即可承载(serve_static 约定不变)。覆盖范围与教学 SPA 功能面一致(会话列表/新建、Trajectory(虚拟化窗口 + Overview 折叠跳转 + 全文搜索)、审批瀑布、队列/作业),不整体移植上游 packages/client 40 模块。
规则:
- L_n 只依赖 L_{<n},禁止依赖同层或上层。十二条显式例外:
seams/subagent/worker.py依赖protocol/*(同层):worker 是 ACP / SDK 线协议的服务端载体,复用协议层的帧与信封实现;core/hmr.py依赖core/scope(同层):HMR 是 cordis 家族的 vendored 部件(上游 vendor/hmr 直接建在 cordis 之上),复用 Service/fiber 基座,与 core.dsh_scope 同理归属 L0;loader/*依赖core/scope(同层):loader 是 cordis 家族的 vendored 部件(上游 vendor/loader 直接建在 cordis 之上),复用 Service/fiber/Inject 基座,与 core.hmr 同理归属 L0;fs/*依赖core.tools(同层,单方向):fs 单元承载模型侧文件工具(上游 tool-fs 等是 fs 域的消费面,register 进 core.tools);core.tools 不得反向 import fs;cli/main.py依赖web(同层,单方向):launcher 组装 web profile——cli 把 ctx/adapter/tools 交给 web 层运行时,web 层不得反向 import cli;cli/headless.py依赖seams与shell(同层,单方向):run_headless 组装沙箱后端链路与 bash 执行器装进 ctx——同上游 bundle/headless 依赖 dsh-sandbox / sandbox-policy / bash-sandbox 的包拓扑;seams/shell 层不得反向 import cli;shell/bash_sandbox.py依赖seams/sandbox_local(同层,单方向):bash-sandbox 是 ctx.sandbox 的消费者——上游 bash-sandbox 同样依赖 dsh-sandbox,拓扑一致而非分层倒挂;seams 层不得反向 import shell;tool_bash/*依赖shell(同层,单方向):tool-bash 是 ctx.shell + ctx.shellEnv 的模型面消费者——上游 tool-bash 依赖 dsh-shell / dsh-shell-env,拓扑一致;shell 层不得反向 import tool_bash;cli/default_tools.py依赖tool_bash(同层,单方向):default_tools 组装真实 bash 工具(上游 bundle/base compose tool-bash),同 cli→shell 先例;tool_bash 层不得反向 import cli;
mcp/connection.py依赖seams/subprocess_env(同层,单方向):stdio 子进程 env 组装复用 seam 的净身切片(上游 mcp-client spawn 透传 env),同 cli→seams 先例;seams 层不得反向 import mcp;cli/main.py依赖demo(教学层):无 profile 时以demo兜底(教学扩展入口)。plan/*依赖interaction(同层,单方向):plan-mode 审查经 userQuestions 通道(interaction.ask,上游 plan-mode peerDep@deepseek-ai/dsh-user-questions),interaction 不得反向 import plan;web/questions.py依赖interaction(同层,单方向):user-questions 桥消费 UserQuestionsService(上游 web-app 组合 dsh-client-ui-user-questions),interaction 不得反向 import web;cli/*依赖interaction(同层,单方向):四个入口安装 userQuestions 服务 seam(上游 base bundle 依赖 dsh-user-questions,同 cli→web 先例),interaction 不得反向 import cli。protocol/内三个模块互不依赖(acp、sdk、hooks 各自独立)。seams/内 sandbox(sandbox_local + sandbox_policy)、credentials、subagent 互不依赖;policy 与 local 同属沙箱子域——上游 dsh-sandbox-policy 同样依赖 dsh-sandbox。seams/credentials_local.py从boot/dotenv.py导入parse_dotenv(L3 → L1):凭据文档解析复用 boot 层的.env解析器,方向合法。
4. 公共 API 面¶
白名单(约定层,改它需要对照上游 + 更新差异清单):Session、Context、RegistryService、Tool、ToolRegistry、AgentLoop、StreamChunk、LlmAdapter、DeepSeekAdapter、LlmFailure、SessionPersistence/JsonlPersistence/SqlitePersistence、apply_patch、boot、run_headless、create_message 与四个 block 构造、derive_messages、turn_balance、repair_interrupted_turn、SESSION_FORMAT_VERSION、TOOL_NOT_STARTED、TOOL_OUTCOME_UNKNOWN。
黑名单(内部工具,不在顶层 __all__,只允许深路径 import):deep_freeze、thaw、is_json_safe、now_ms、_http_error_code、_map_finish_reason、load_events_checked、repair_and_replay、balanced_after_replay。
教学扩展(上游无对应,标注于此):cli/default_tools.py、cli/session_cmds.py(会话管理子命令;--config 属 cli/main.py 启动器标志,同为教学扩展)、llm/fake.py、demo.py、example_plugins.py。
顶层 __all__ 收敛至 28 项(白名单 + FakeLlmAdapter),由 tests/test_dependencies.py 断言固定;白名单每一项都能在 §2 映射表里找到上游对应。
深路径约定(不在顶层 __all__,仅经子包深路径暴露,由 tests/test_token_meter.py、tests/test_compaction.py、tests/test_jobs.py、tests/test_plan.py、tests/test_skills.py、tests/test_session_store.py 固定行为):TokenMeter、install_compaction、CompactionEngine、compact_surface_region、select_compactable_range、inspect_compaction_entry_state、frame_summary、install_jobs、register_job_tools、LocalJobRegistry、JobDoneBox、fit_with_suffix、fit_completion_notice、install_system_prompt、SystemPromptService、install_plan_mode、PlanModeController、fold_plan_mode、resolve_config、install_skills、register_skill_tools、SkillRegistry、FileSystemSkillProvider、SkillTool、SKILL_GESTURE、render_skill_content、parse_skill_file、digest_catalog_entries、install_sessions、SessionStore、SessionForkError、SESSION_NOT_FOUND、SESSION_NOT_LIVE、SESSION_ALREADY_EXISTS、INVALID_BOUNDARY、OPEN_TURN、LocalAttachmentStore、AttachmentStore、ImageAttachmentRef、SaveImageAttachment、ImageAttachmentLimits、AttachmentError、is_image_admission_error、detect_image、probe_image、supports_acp_image_prompts、admit_acp_prompt、assistant_block_to_acp。装配约定:apply_retry_planner(ctx) → install_compaction(ctx) → install_jobs(ctx) → install_system_prompt(ctx) →(可选)install_plan_mode(ctx, config) →(可选)install_skills(ctx) →(可选)install_sessions(ctx)(均幂等;CONTEXT_WINDOW_EXCEEDED 不在重试白名单,由压缩接管;作业工具注册经 register_job_tools(reg, ctx.get("jobs")),default_tools 在 ctx.jobs 存在时自动收编;skill 工具注册经 register_skill_tools(reg, ctx.get("skills")),default_tools 在 ctx.skills 存在时自动收编;plan 依赖 systemPrompt 服务,缺失 fail loud;会话经 install_sessions(ctx) 提供 ctx.sessions,headless / demo / resume 入口已接入)。