Pi agent-core harness 与 Claude Code 的 Session 和上下文管理
对比 Pi agent-core harness 与 Claude Code 如何保存会话记录、恢复运行时状态、构造模型上下文、压缩历史和处理工具输出,说明两套 Agent Runtime 在状态与资源管理上的实现差异。
共 83 篇文章
对比 Pi agent-core harness 与 Claude Code 如何保存会话记录、恢复运行时状态、构造模型上下文、压缩历史和处理工具输出,说明两套 Agent Runtime 在状态与资源管理上的实现差异。
拆 pi-ai 多 provider 适配层:约 10 个线缆协议实现如何覆盖 37 家 provider,compat 标志矩阵如何抹平 OpenAI 兼容生态,重试判定为什么是带 issue 编号的正则库,上下文溢出的三种检测路径,以及模型 catalog 为什么走构建期生成与手工 override。
分析 pi-tui 如何将组件输出约束为字符串行数组,比较相邻两帧以重绘变化区间,并处理滚动区、终端尺寸、内联图片和 IME 光标等差分渲染的正确性条件。
拆 pi 正在进行的客户端/服务端拆分:为什么先重构出 repository 接缝再沿接缝拆进程,CBOR 协议为什么传输中立且快照权威,attach 与会话租约如何建模多前端共享,以及双栈并存的过渡工程。
拆 pi 的会话与上下文层:为什么会话建模成 entry 树而不是消息数组,模型切换和 compaction 如何成为持久化的一等条目,树结构如何支持分支导航与分支摘要,compaction 的安全切割点、文件账本与缓存隔离怎么做。
拆 pi 的 agent 主循环:为什么 StreamFn 契约禁止抛异常、失败如何编码成 stopReason=error 的 assistant 消息进入会话历史、截断的 tool call 为什么整批拒绝执行、并行工具调度如何保证 transcript 确定性,以及工具输出截断的工程细节。
通读 pi(Mario Zechner 的 coding agent harness)源码:四层包结构如何划分关注点与策略归属,为什么它不内置权限弹窗、MCP、子代理和 plan mode,以及 Extensions、Skills 与本地文档按需加载如何构成其扩展机制。
OffscreenComponent 的渲染与提交逻辑、可见性切换时 layout effect 的卸载与重挂、四个关键 commit 的演进线,以及系列四个月的回顾。
8 月 28 日到 9 月 21 日,master 上完成了 useSyncExternalStore 对 useMutableSource 的替换,中间还有一次删 除后第二天加回的反复,这篇按 commit 顺序讲清过程和背后的 tearing 问题。
9 月 14 日合入的 useInsertionEffect 在 commit 阶段的执行位置与 CSS-in-JS 场景,以及 react-server-dom-webpack 里 Flight(Server Components)协议的当前完成度。
选择性注水的完整链路:点击落在未注水的 Suspense 边界上时,事件如何被挂起入队、边界如何被提升到高优先级 lane 抢先注水,以及提交后队列如何按序重放。
Fizz 的数据结构与工作流程:Request、Task、Segment、SuspenseBoundary 四类对象,挂起后如何分段补发,以及与 ReactPartialRenderer 旧实现的对比。
一次 click 如何经事件优先级决定更新的 lane,以及 Provider 变更如何沿 dependencies 链表与 childLanes 冒泡送到每个 consumer。
useOpaqueIdentifier 在服务器和客户端各自的发号方式,以及 hydration 时用不透明对象延迟物化 id、绕开两端计数器对不上问题的完整设计。
startTransition、useTransition、useDeferredValue 三个用户 API 在源码里的实现形态,以及它们如何通过 ReactCurrentBatchConfig 接到 Lane 模型上。
组件 throw 出 thenable 之后的完整链路:throwException 捕获边界、pingCache 与 retryCache 两层去重、挂起 lane 的节流提交、ping 之后的 RetryLane 重试。
setTimeout 里连续两次 setState 在 17 渲染两次、在 18 alpha 的 createRoot 下只渲染一次,这篇从源码核实这个差异在当时的代码里如何成立,以及渲染进行中收到更新时交错更新队列的入队与转移 。
7 月第一周 master 上围绕 flushSync 的一合一滚:unbatchedUpdates 和 flushDiscreteUpdates 被并进 flushSync,六天后又整体回滚,这篇把重构前后两个形态拆开看。
createRoot 转正的三个 commit、RootTag 从三种收编成两种的过程,以及换了入口之后首挂载、批处理、回调参数这些具体行为差在哪。
ensureRootIsScheduled 如何在 Sync 与 Concurrent 两条路径间做选择,Scheduler 的 5ms 时间切片、MessageChannel 调度与任务续体机制,收束 Fiber 与 Lane 三篇。
接上篇读 ReactFiberLane.new.js:getNextLanes 的分支决策、computeExpirationTime 的过期时间数值、transition lane 的轮转分配。
Lane 模型的静态结构:31 个二进制位的分组、getHighestPriorityLane 等位运算函数,以及 expirationTime 单值模型被放弃的原因。
系列开篇。递归的 Stack Reconciler 为什么撑不起可中断渲染,Fiber 的字段分组、双缓冲与 .new/.old 双 fork 的现状。
60 篇的收官篇:不可变文档与显式映射的更 新模型、核心薄扩展厚的边界、插件系统的能力分层,每个设计论断都指回具体篇目,附全系列地图与完整索引。
从文档模型、更新模型、合法性校验、扩展机制四层对比 ProseMirror 与 Draft.js、Slate、Quill 的结构差异,ProseMirror 侧逐条对应本系列前 58 篇拆过的机制。
meta 仓库 bin/pm.js 的命令面、buildhelper 的构建测试约定,以及 changelog 驱动的 release 管线如何统一管理 20 个仓库的版本与依赖。
prosemirror-test-builder 的两个源文件:block/mark builder 的生成与默认 attrs、字符串里 标签的位置记账、flatten 的嵌套 tag 平移,以及它在 prosemirror-transform 测试里同时充当操作参数和映射断言锚点的用法。
prosemirror-example-setup 的装配逻辑:七个插件按固定顺序拼装,顺序决定按键与输入的分发优先级,三个 build 函数按 schema 按需生成绑定,以及它离生产级编辑器差什么。
prosemirror-tables 的 columnresizing 插件与 TableView:widget 装饰生成拖拽手柄,mousemove/mousedown 的事件链,拖拽期间只改 DOM 的实时反馈,松手时 colwidth attr 一次写回,以及 handleWidth 等配置与插件拼装顺序。
prosemirror-tables 的命令层:selectedRect 把选区翻译成 TableRect,addColumn/addRow 在格网定位后改 span 或插新格,mergeCells/splitCell 重算 span 与 colwidth,goToNextCell 按文档顺序导航。
prosemirror-tables 的 CellSelection:用 anchorCell/headCell 两个位置表达矩形选区,isRowSelection/isColSelection 的判定与扩展,选区可视化的装饰方案,以及跨表格时的边界处理。
prosemirror-tables 的地基:tableNodes 工厂生成的四个节点 spec、colspan/rowspan/colwidth 三个 attr,TableMap 的扁平格网与 problems 诊断,以及 findTable、cellAround 等定位函数。
prosemirror-search 的两个文件:SearchQuery 的文本块扫描与正则匹配、range 随文档变化的 Mapping 维护、getReplacements 的 skip/copy 区间,以及命令与装饰的组合。
prosemirror-markdown 的双向转换机制:MarkdownSerializer 的渲染表与状态机,markdown-it token 流接入 MarkdownParseState 的栈,以及与 DOM 通路的对照。
prosemirror-changeset 的 span 表示:Change 的 A/B 双坐标、Change.merge 在中间坐标系上的归并、addSteps 之后用 Myers diff 最小化,以及 simplifyChanges 的按词化简。
prosemirror-collab 的 API 面与使用方分工:unconfirmed 的三类变动、history 在 rebase 后的 Branch.rebased 重建、preserveItems 的两处作用,以及官网 demo 里收发循环的完整时序。
prosemirror-collab 的集中式权威模型:version 与 unconfirmed 两个字段怎么记账,远端 step 到达时本地未确认 step 如何经 rebaseSteps 撤销、追赶、映射重做。
prosemirror-menu 的 MenuElement 协议、MenuItem 的 run/select/enable/active 四件套、Dropdown 组合、menubar 插件的 floating 模式,以及这套 UI 层为什么留在核心之外。
dropcursor 在 dragover 事件里算出落点,用一个绝对定位的 div 画指示线;块级位置画横线、行内位置画竖线,内部拖拽经过 dropPoint 的 schema 校验。
两个块级节点之间的文档位置没有文本容器,TextSelection 与 NodeSelection 都落不进去;gapcursor 用一种选区类型加一个 widget 假光标补上这类缝隙。
prosemirror-schema-list 全文件解读:list_item 内容表达式的设计,wrapInList、splitListItem 、liftListItem、sinkListItem 四条命令的逐步推导,以及列表为什么是全库边界情况最密集的代码。
prosemirror-schema-basic 全文件解读:九个节点与四个 mark 的 spec 逐一定义,marks 排除规则的三层实例,以及列表节点为什么留给 schema-list。
prosemirror-inputrules 全文件解读:InputRule 的 match 与 handler、正则 $ 结尾匹配的语义,handleTextInput 挂载点,wrappingInputRule 与 textblockTypeInputRule 两个构造器,以及 undoInputRule 怎么把规则效果和输入文本分开撤销。
prosemirror-history 全文件解读:Branch/Item 双栈结构,逆步与选区书签组成的事件,时间阈值加位置相邻的分组启发式,以及协作 rebase 对历史栈的重写。
prosemirror-commands 全文件解读:Command 的 (state, dispatch, view) 签名与 dry-run 惯例,chainCommands 的短路语义,baseKeymap 逐条拆解,以及内置命令对 structure.ts 判断函数的消费方式。
prosemirror-keymap 全文件解读:handleKeyDown 挂载方式、Mod-/Shift- 键名规格的归一化、一次按键最多三次查表的兜底逻辑,以及多 keymap 组合时的顺序语义。
只用 model、transform、state、view 四个核心包手写一个支持输入、删除、加粗的最小编辑器,每个行为对应到前面各篇讲的机制,并用一张 API 表收束核心层。
browser.ts 的 UA 嗅探与能力探测、补丁在 view 各模块的具体分布、dom.ts 的 DOM 工具函数族,以及编辑器为什么需要集中的一层浏览器差异补丁。
posAtCoords 与 coordsAtPos 的双向换算实现:相邻字符矩形压扁的定位策略、caretFromPoint 的逐层下钻与浏览器补丁、endOfTextblock 用 Selection.modify 实测边界,以及 scrollRectIntoView 的逐层滚动。
serializeForClipboard 与 parseFromClipboard 的实现:data-pm-slice 元数据的往返、text/html 与 text/plain 的取舍、外来 HTML 的 sibling 归一与 doPaste 的插入逻辑。
prosemirror-view 的 Decoration 体系:widget/inline/node 三种类型、DecorationSet 的局部数组加子树三元组结构、map 跟随文档的映射规则,以及 viewDecorations 的生成与渲染消费。
NodeView 接口的七个委托方法、CustomNodeViewDesc 接入 ViewDesc 树的方式、contentDOM 的内容托管约定,以及 MarkView 与 NodeView 的差异。
compositionstart/update/end 在 prosemirror-view 里的完整处理:组合期间的 DOM 写入保护、endComposition 的读回收尾、compositionID 的撤销分组,以及移动端和 Safari 的补丁分布。
selectionToDOM 怎么把 state 选区写进 DOM,selectionchange 怎么被读回 state,syncNodeSelection 与一批边界工具函数如何兜住浏览器的选区怪癖。
事件注册表 handlers 与 editHandlers 的分工、someProp 的统一入口、keydown 的完整处理路径、captureKeys 的兜底过滤,以及 beforeinput 的降级补丁。
浏览器直接改 DOM 之后,MutationObserver 怎么攒记录、flush 怎么聚合成文档区间,readDOMChange 又如何用 diff 把变化反推成一次 transaction。
ViewDesc 的增量更新机制:matchesNode/matchesMark/matchesHack 的复用判定、dirty 四级标记、iterDeco 的装饰注入位置,以及文本节点的就地更新。
ViewDesc 描述树的静态结构:类族分工、children 与文档树的对应、docViewDesc 的构建路径,以及 dom、contentDOM、nodeDOM 三个引用的关系。
EditorView 总览:构造顺序、props 与 DirectEditorProps、dispatchTransaction 惯例、updateState 的完整路径、pluginViews 的挂载与 destroy 的清理面。
用三个完整可运行的小插件(字符统计、只读开关、选区上报)把 prosemirror-state 插件系统的 StateField、filterTransaction 与 view 规格串起来用一遍。
插件规格的另外三个接口:filterTransaction 的否决权、appendTransaction 的链式修正与收敛约定、view 与 props 如何把插件接到 EditorView 上。
prosemirror-state 的插件系统上半部分:PluginSpec、Plugin、PluginKey 三件套的分工,StateField 的 init/apply 签名与纯函数约束,插件顺序对字段初始化的影响,以及 key.getState 的取数路径。
Transaction 对 Transform 的四项扩展:惰性映射的选区、storedMarks 的失效规则、meta 的插件通信惯例,以及 scrollIntoView 与 time 字段的消费方。
prosemirror-state 的选区体系:TextSelection、NodeSelection、AllSelection 的 anchor/head 语义,SelectionBookmark 的 map 与恢复,replace 的落点计算,以及 $cursor 与 inline 位置的边界处理。
EditorState 的字段分层、create 的插件初始化流程、applyTransaction 的两阶段应用过程,以及 reconfigure 换插件时的字段保留规则。
Transform 类如何用 steps/docs/mapping 三个数组组织一次修改,replace/delete/insert 便捷方法的分层,以及 addMark/removeMark 的范围处理。
structure.ts 里 canSplit、canJoin、liftTarget、findWrapping 四个纯判断函数的校验逻辑,以及 prosemirror-commands 对它们的消费方式。
Mapping 类的 maps/mirror 双数组、多步链式映射的删除信息累计、镜像步跳转与 recover 找回机制,以及它给 rebase 打下的地基。
StepMap 的区间段编码、map 的 assoc 方向偏好、MapResult 的删除标记位,以及 recover 值的设计与用途。
ReplaceStep 与 ReplaceAroundStep 的字段、映射与合并规则,以及 Fitter 如何用 frontier、placed、unplaced 三块状态为 slice 寻找闭合节点序列。
Step 抽象基类的接口划分、StepResult 的失败语义、AddMarkStep/RemoveMarkStep 与 AttrStep 的实现,以及可逆性对 undo 的意义。
model 阶段收官:Node 上遍历、校验、定位三族辅助方法的实现与边界行为,以及 model 层 API 的心智模型总结。
diff.ts 两个函数如何从两端扫描定位差异区间:引用相等与 sameMarkup 的 分层判定、compareDeep 的 attrs 深比较,以及 view 层 readDOMChange 对 diff 结果的消费。
parseDOM 规则的 priority 排序与 tag/style 匹配过程,ParseContext 的节点栈状态机(findPlace、findWrapping、closeExtra、sync),context 上下文限定与空白符处理策略。
DOMOutputSpec 三种形态与 0 号洞的约束,renderSpec 的递归与 XSS 防护,serializeFragment 用 active 栈合并相邻 mark 的过程,以及纯文本输出走 leafText 的约定。
Slice 用 openStart 与 openEnd 记录切片两端被切开的层数,replace 用两路与三路合并把切片接回文档,沿途用 close 做 schema 校验。
pos 的扁平编号约定、ResolvedPos 的 path 结构与 depth/parent/index/offset 字段族、start/end/before/after 的边界语义,以及 resolve 的成本与缓存策略。
NodeSpec 各字段的含义,content expression 从字符串编译成 DFA 的过程,createChecked 的校验路径,以及 Schema 构造器在 compile 阶段做的全部工作。
Mark 与 Node 的不对称设计:Mark 不进文档树,以排序数组挂在节点上。addToSet、removeFromSet、sameSet 的实现,excludes 的单向互斥语义,以及为什么粗体斜体不做成嵌套节点。
Node 的四个字段与不可变约定,Fragment 的 size 缓存与位置换算,nodeSize 与 childCount 两套计数,以及叶节点和文本节点的特例。
用 prosemirror-example-setup 几十行代码搭出编辑 器,在控制台里看文档的 JSON 结构和一次输入产生的 Transaction,为后续读源码建立直观模型。
ProseMirror 工作区根目录布局与 22 个包的 dependencies 逐层梳理:核心四层单向依赖、扩展只朝下依赖核心、拆成多包的工程理由。
从 contenteditable 的浏览器差异与 HTML 即模型的混乱讲起,说明「文档即数据」的思路和 ProseMirror 的四条设计原则,并交代整个源码分析系列的读法与规划。