open-multi-agent-kit 0.95.0 → 0.95.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +1 -1
  3. package/dist/approvals/approval-receipt-store.d.ts +18 -0
  4. package/dist/approvals/approval-receipt-store.d.ts.map +1 -0
  5. package/dist/approvals/approval-receipt-store.js +169 -0
  6. package/dist/approvals/approval-receipt-store.js.map +1 -0
  7. package/dist/approvals/approval-receipt.d.ts +43 -0
  8. package/dist/approvals/approval-receipt.d.ts.map +1 -0
  9. package/dist/approvals/approval-receipt.js +208 -0
  10. package/dist/approvals/approval-receipt.js.map +1 -0
  11. package/dist/approvals/approval-verifier.d.ts +17 -0
  12. package/dist/approvals/approval-verifier.d.ts.map +1 -0
  13. package/dist/approvals/approval-verifier.js +23 -0
  14. package/dist/approvals/approval-verifier.js.map +1 -0
  15. package/dist/approvals/plannotator-approval-bridge.d.ts +58 -0
  16. package/dist/approvals/plannotator-approval-bridge.d.ts.map +1 -0
  17. package/dist/approvals/plannotator-approval-bridge.js +169 -0
  18. package/dist/approvals/plannotator-approval-bridge.js.map +1 -0
  19. package/dist/cli/args.d.ts.map +1 -1
  20. package/dist/cli/args.js +2 -0
  21. package/dist/cli/args.js.map +1 -1
  22. package/dist/commands/package-doctor-cli.d.ts +13 -0
  23. package/dist/commands/package-doctor-cli.d.ts.map +1 -0
  24. package/dist/commands/package-doctor-cli.js +80 -0
  25. package/dist/commands/package-doctor-cli.js.map +1 -0
  26. package/dist/commands/router-feedback-cli.d.ts +11 -0
  27. package/dist/commands/router-feedback-cli.d.ts.map +1 -0
  28. package/dist/commands/router-feedback-cli.js +99 -0
  29. package/dist/commands/router-feedback-cli.js.map +1 -0
  30. package/dist/commands/stats-cli.d.ts +20 -0
  31. package/dist/commands/stats-cli.d.ts.map +1 -0
  32. package/dist/commands/stats-cli.js +99 -0
  33. package/dist/commands/stats-cli.js.map +1 -0
  34. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  35. package/dist/core/agent-session-runtime.js +4 -1
  36. package/dist/core/agent-session-runtime.js.map +1 -1
  37. package/dist/core/agent-session.d.ts +97 -29
  38. package/dist/core/agent-session.d.ts.map +1 -1
  39. package/dist/core/agent-session.js +583 -199
  40. package/dist/core/agent-session.js.map +1 -1
  41. package/dist/core/bash-executor.d.ts.map +1 -1
  42. package/dist/core/bash-executor.js +8 -2
  43. package/dist/core/bash-executor.js.map +1 -1
  44. package/dist/core/compaction/transaction.d.ts +9 -0
  45. package/dist/core/compaction/transaction.d.ts.map +1 -1
  46. package/dist/core/compaction/transaction.js +17 -2
  47. package/dist/core/compaction/transaction.js.map +1 -1
  48. package/dist/core/context-budget-governor-v2.d.ts +1 -1
  49. package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
  50. package/dist/core/context-budget-governor-v2.js +1 -1
  51. package/dist/core/context-budget-governor-v2.js.map +1 -1
  52. package/dist/core/context-budget-system-prompt.d.ts.map +1 -1
  53. package/dist/core/context-budget-system-prompt.js +18 -2
  54. package/dist/core/context-budget-system-prompt.js.map +1 -1
  55. package/dist/core/context-budget-v2-cache-disk.d.ts +109 -0
  56. package/dist/core/context-budget-v2-cache-disk.d.ts.map +1 -0
  57. package/dist/core/context-budget-v2-cache-disk.js +343 -0
  58. package/dist/core/context-budget-v2-cache-disk.js.map +1 -0
  59. package/dist/core/context-budget-v2-cache-keys.d.ts +22 -0
  60. package/dist/core/context-budget-v2-cache-keys.d.ts.map +1 -1
  61. package/dist/core/context-budget-v2-cache-keys.js +4 -4
  62. package/dist/core/context-budget-v2-cache-keys.js.map +1 -1
  63. package/dist/core/context-budget-v2-cache.d.ts +1 -0
  64. package/dist/core/context-budget-v2-cache.d.ts.map +1 -1
  65. package/dist/core/context-budget-v2-cache.js +1 -0
  66. package/dist/core/context-budget-v2-cache.js.map +1 -1
  67. package/dist/core/context-budget-v2-plan-cache-keys.d.ts.map +1 -1
  68. package/dist/core/context-budget-v2-plan-cache-keys.js +39 -5
  69. package/dist/core/context-budget-v2-plan-cache-keys.js.map +1 -1
  70. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  71. package/dist/core/context-budget-v2-planner.js +17 -14
  72. package/dist/core/context-budget-v2-planner.js.map +1 -1
  73. package/dist/core/context-budget-v2-types.d.ts +1 -0
  74. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  75. package/dist/core/context-budget-v2-types.js.map +1 -1
  76. package/dist/core/extensions/loader.d.ts.map +1 -1
  77. package/dist/core/extensions/loader.js +45 -22
  78. package/dist/core/extensions/loader.js.bak-sharedjiti-20260812-111246 +553 -0
  79. package/dist/core/extensions/loader.js.map +1 -1
  80. package/dist/core/extensions/types.d.ts +4 -0
  81. package/dist/core/extensions/types.d.ts.map +1 -1
  82. package/dist/core/extensions/types.js.map +1 -1
  83. package/dist/core/headroom.d.ts.map +1 -1
  84. package/dist/core/headroom.js +7 -2
  85. package/dist/core/headroom.js.map +1 -1
  86. package/dist/core/mcp/client.d.ts +105 -0
  87. package/dist/core/mcp/client.d.ts.map +1 -0
  88. package/dist/core/mcp/client.js +198 -0
  89. package/dist/core/mcp/client.js.map +1 -0
  90. package/dist/core/mcp/config.d.ts +23 -0
  91. package/dist/core/mcp/config.d.ts.map +1 -0
  92. package/dist/core/mcp/config.js +89 -0
  93. package/dist/core/mcp/config.js.map +1 -0
  94. package/dist/core/mcp/index.d.ts +15 -0
  95. package/dist/core/mcp/index.d.ts.map +1 -0
  96. package/dist/core/mcp/index.js +15 -0
  97. package/dist/core/mcp/index.js.map +1 -0
  98. package/dist/core/mcp/manager.d.ts +84 -0
  99. package/dist/core/mcp/manager.d.ts.map +1 -0
  100. package/dist/core/mcp/manager.js +173 -0
  101. package/dist/core/mcp/manager.js.map +1 -0
  102. package/dist/core/mcp/protocol.d.ts +59 -0
  103. package/dist/core/mcp/protocol.d.ts.map +1 -0
  104. package/dist/core/mcp/protocol.js +103 -0
  105. package/dist/core/mcp/protocol.js.map +1 -0
  106. package/dist/core/mcp/stdio-transport.d.ts +63 -0
  107. package/dist/core/mcp/stdio-transport.d.ts.map +1 -0
  108. package/dist/core/mcp/stdio-transport.js +132 -0
  109. package/dist/core/mcp/stdio-transport.js.map +1 -0
  110. package/dist/core/mcp/tools.d.ts +47 -0
  111. package/dist/core/mcp/tools.d.ts.map +1 -0
  112. package/dist/core/mcp/tools.js +102 -0
  113. package/dist/core/mcp/tools.js.map +1 -0
  114. package/dist/core/package-archive.d.ts +3 -0
  115. package/dist/core/package-archive.d.ts.map +1 -0
  116. package/dist/core/package-archive.js +161 -0
  117. package/dist/core/package-archive.js.map +1 -0
  118. package/dist/core/package-doctor-source-scan.d.ts +13 -0
  119. package/dist/core/package-doctor-source-scan.d.ts.map +1 -0
  120. package/dist/core/package-doctor-source-scan.js +124 -0
  121. package/dist/core/package-doctor-source-scan.js.map +1 -0
  122. package/dist/core/package-doctor.d.ts +41 -0
  123. package/dist/core/package-doctor.d.ts.map +1 -0
  124. package/dist/core/package-doctor.js +145 -0
  125. package/dist/core/package-doctor.js.map +1 -0
  126. package/dist/core/package-manager.d.ts +10 -1
  127. package/dist/core/package-manager.d.ts.map +1 -1
  128. package/dist/core/package-manager.js +175 -42
  129. package/dist/core/package-manager.js.map +1 -1
  130. package/dist/core/package-manifest.d.ts +26 -0
  131. package/dist/core/package-manifest.d.ts.map +1 -0
  132. package/dist/core/package-manifest.js +85 -0
  133. package/dist/core/package-manifest.js.map +1 -0
  134. package/dist/core/pi-compat.d.ts +5 -0
  135. package/dist/core/pi-compat.d.ts.map +1 -0
  136. package/dist/core/pi-compat.js +18 -0
  137. package/dist/core/pi-compat.js.map +1 -0
  138. package/dist/core/reasoning-router-bias.d.ts +10 -14
  139. package/dist/core/reasoning-router-bias.d.ts.map +1 -1
  140. package/dist/core/reasoning-router-bias.js +22 -15
  141. package/dist/core/reasoning-router-bias.js.map +1 -1
  142. package/dist/core/reasoning-router-v4.d.ts +9 -1
  143. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  144. package/dist/core/reasoning-router-v4.js +20 -5
  145. package/dist/core/reasoning-router-v4.js.map +1 -1
  146. package/dist/core/redaction.d.ts +2 -5
  147. package/dist/core/redaction.d.ts.map +1 -1
  148. package/dist/core/redaction.js +14 -1
  149. package/dist/core/redaction.js.map +1 -1
  150. package/dist/core/repository-learning-scope.d.ts +10 -0
  151. package/dist/core/repository-learning-scope.d.ts.map +1 -0
  152. package/dist/core/repository-learning-scope.js +42 -0
  153. package/dist/core/repository-learning-scope.js.map +1 -0
  154. package/dist/core/resource-loader.d.ts.map +1 -1
  155. package/dist/core/resource-loader.js +16 -1
  156. package/dist/core/resource-loader.js.map +1 -1
  157. package/dist/core/router-feedback-collector.d.ts +2 -1
  158. package/dist/core/router-feedback-collector.d.ts.map +1 -1
  159. package/dist/core/router-feedback-collector.js +2 -2
  160. package/dist/core/router-feedback-collector.js.map +1 -1
  161. package/dist/core/runtime-provenance.d.ts +54 -0
  162. package/dist/core/runtime-provenance.d.ts.map +1 -0
  163. package/dist/core/runtime-provenance.js +115 -0
  164. package/dist/core/runtime-provenance.js.map +1 -0
  165. package/dist/core/sandbox/backend.d.ts.map +1 -1
  166. package/dist/core/sandbox/backend.js +39 -21
  167. package/dist/core/sandbox/backend.js.map +1 -1
  168. package/dist/core/sandbox/default-policy.d.ts +4 -5
  169. package/dist/core/sandbox/default-policy.d.ts.map +1 -1
  170. package/dist/core/sandbox/default-policy.js +9 -11
  171. package/dist/core/sandbox/default-policy.js.map +1 -1
  172. package/dist/core/session-bash-runtime.d.ts +4 -4
  173. package/dist/core/session-bash-runtime.d.ts.map +1 -1
  174. package/dist/core/session-bash-runtime.js +6 -5
  175. package/dist/core/session-bash-runtime.js.map +1 -1
  176. package/dist/core/session-compaction-service.d.ts.map +1 -1
  177. package/dist/core/session-compaction-service.js +7 -7
  178. package/dist/core/session-compaction-service.js.map +1 -1
  179. package/dist/core/session-manager.d.ts +4 -1
  180. package/dist/core/session-manager.d.ts.map +1 -1
  181. package/dist/core/session-manager.js +47 -7
  182. package/dist/core/session-manager.js.map +1 -1
  183. package/dist/core/settings-manager.d.ts +7 -4
  184. package/dist/core/settings-manager.d.ts.map +1 -1
  185. package/dist/core/settings-manager.js +11 -3
  186. package/dist/core/settings-manager.js.map +1 -1
  187. package/dist/core/system-prompt.d.ts +9 -1
  188. package/dist/core/system-prompt.d.ts.map +1 -1
  189. package/dist/core/system-prompt.js +10 -4
  190. package/dist/core/system-prompt.js.map +1 -1
  191. package/dist/core/tools/bash.d.ts +2 -2
  192. package/dist/core/tools/bash.d.ts.map +1 -1
  193. package/dist/core/tools/bash.js +2 -1
  194. package/dist/core/tools/bash.js.map +1 -1
  195. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  196. package/dist/core/tools/tool-definition-wrapper.js +15 -0
  197. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  198. package/dist/core/turn-metrics.d.ts +135 -0
  199. package/dist/core/turn-metrics.d.ts.map +1 -0
  200. package/dist/core/turn-metrics.js +261 -0
  201. package/dist/core/turn-metrics.js.map +1 -0
  202. package/dist/core/verified-bash-runtime.d.ts.map +1 -1
  203. package/dist/core/verified-bash-runtime.js +10 -4
  204. package/dist/core/verified-bash-runtime.js.map +1 -1
  205. package/dist/guardrails/replay-ledger-lock-owner.d.ts +7 -0
  206. package/dist/guardrails/replay-ledger-lock-owner.d.ts.map +1 -1
  207. package/dist/guardrails/replay-ledger-lock-owner.js +39 -0
  208. package/dist/guardrails/replay-ledger-lock-owner.js.map +1 -1
  209. package/dist/index.d.ts +6 -1
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +6 -1
  212. package/dist/index.js.map +1 -1
  213. package/dist/main.d.ts.map +1 -1
  214. package/dist/main.js +18 -0
  215. package/dist/main.js.map +1 -1
  216. package/dist/modes/interactive/components/control-panel-layout.d.ts.map +1 -1
  217. package/dist/modes/interactive/components/control-panel-layout.js +2 -2
  218. package/dist/modes/interactive/components/control-panel-layout.js.map +1 -1
  219. package/dist/modes/interactive/components/footer.d.ts +3 -0
  220. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  221. package/dist/modes/interactive/components/footer.js +40 -12
  222. package/dist/modes/interactive/components/footer.js.map +1 -1
  223. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  224. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  225. package/dist/modes/interactive/components/settings-selector.js +10 -0
  226. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  227. package/dist/modes/interactive/components/status-sidebar.d.ts +14 -2
  228. package/dist/modes/interactive/components/status-sidebar.d.ts.map +1 -1
  229. package/dist/modes/interactive/components/status-sidebar.js +106 -19
  230. package/dist/modes/interactive/components/status-sidebar.js.map +1 -1
  231. package/dist/modes/interactive/interactive-mode.d.ts +10 -1
  232. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  233. package/dist/modes/interactive/interactive-mode.js +104 -17
  234. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  235. package/dist/modes/interactive/theme/dark.json +1 -1
  236. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  237. package/dist/modes/interactive/theme/theme.js +1 -0
  238. package/dist/modes/interactive/theme/theme.js.map +1 -1
  239. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  240. package/dist/modes/rpc/rpc-mode.js +1 -1
  241. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  242. package/docs/compaction.md +25 -3
  243. package/docs/containerization.md +14 -2
  244. package/docs/docs.json +8 -0
  245. package/docs/environment-variables.md +1 -1
  246. package/docs/extensions.md +75 -16
  247. package/docs/mcp.md +97 -0
  248. package/docs/metrics.md +87 -0
  249. package/docs/packages.md +25 -4
  250. package/docs/providers.md +1 -1
  251. package/docs/sdk.md +25 -4
  252. package/docs/settings.md +8 -7
  253. package/docs/usage.md +13 -3
  254. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  255. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  256. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  257. package/examples/extensions/gondolin/package-lock.json +2 -2
  258. package/examples/extensions/gondolin/package.json +1 -1
  259. package/examples/extensions/plannotator-approval-bridge.ts +83 -0
  260. package/examples/extensions/sandbox/package-lock.json +2 -2
  261. package/examples/extensions/sandbox/package.json +1 -1
  262. package/examples/extensions/subagent/README.md +21 -11
  263. package/examples/extensions/subagent/adaptive-agent-runtime.ts +9 -3
  264. package/examples/extensions/subagent/agents/planner.md +1 -3
  265. package/examples/extensions/subagent/agents/reviewer.md +1 -3
  266. package/examples/extensions/subagent/agents/scout.md +1 -3
  267. package/examples/extensions/subagent/agents/worker.md +0 -1
  268. package/examples/extensions/subagent/agents.test.ts +9 -0
  269. package/examples/extensions/subagent/agents.ts +11 -4
  270. package/examples/extensions/subagent/deadline-budget.test.ts +32 -0
  271. package/examples/extensions/subagent/deadline-budget.ts +25 -1
  272. package/examples/extensions/subagent/fixtures/fake-omk-json.mjs +10 -0
  273. package/examples/extensions/subagent/index.ts +234 -55
  274. package/examples/extensions/subagent/subagent-execution-policy.test.ts +27 -0
  275. package/examples/extensions/subagent/subagent-extension-smoke.test.ts +167 -2
  276. package/examples/extensions/subagent/workflow-graph.test.ts +80 -0
  277. package/examples/extensions/subagent/workflow-graph.ts +89 -0
  278. package/examples/extensions/with-deps/package-lock.json +2 -2
  279. package/examples/extensions/with-deps/package.json +1 -1
  280. package/npm-shrinkwrap.json +253 -439
  281. package/package.json +8 -8
@@ -7,6 +7,7 @@ Extensions are TypeScript modules that extend omk's behavior. They can subscribe
7
7
  > **Placement for /reload:** Put extensions in `~/.omk/agent/extensions/` (global) or `.omk/extensions/` (project-local) for auto-discovery. Use `omk -e ./path.ts` only for quick tests. Extensions in auto-discovered locations can be hot-reloaded with `/reload`.
8
8
 
9
9
  **Key capabilities:**
10
+
10
11
  - **Custom tools** - Register tools the LLM can call via `omk.registerTool()`
11
12
  - **Event interception** - Block or modify tool calls, inject context, customize compaction
12
13
  - **User interaction** - Prompt users via `ctx.ui` (select, confirm, input, notify)
@@ -16,6 +17,7 @@ Extensions are TypeScript modules that extend omk's behavior. They can subscribe
16
17
  - **Custom rendering** - Control how tool calls/results and messages appear in TUI
17
18
 
18
19
  **Example use cases:**
20
+
19
21
  - Permission gates (confirm before `rm -rf`, `sudo`, etc.)
20
22
  - Git checkpointing (stash at each turn, restore on branch)
21
23
  - Path protection (block writes to `.env`, `node_modules/`)
@@ -50,6 +52,7 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
50
52
  - [Custom UI](#custom-ui)
51
53
  - [Error Handling](#error-handling)
52
54
  - [Mode Behavior](#mode-behavior)
55
+ - [Plannotator Approval Bridge](#plannotator-approval-bridge)
53
56
  - [Examples Reference](#examples-reference)
54
57
 
55
58
  ## Quick Start
@@ -112,7 +115,7 @@ omk -e ./my-extension.ts
112
115
  Extensions are auto-discovered from:
113
116
 
114
117
  | Location | Scope |
115
- |----------|-------|
118
+ | ---------- | ------- |
116
119
  | `~/.omk/agent/extensions/*.ts` | Global (all projects) |
117
120
  | `~/.omk/agent/extensions/*/index.ts` | Global (subdirectory) |
118
121
  | `.omk/extensions/*.ts` | Project-local |
@@ -138,7 +141,7 @@ To share extensions via npm or git as omk packages, see [packages.md](packages.m
138
141
  ## Available Imports
139
142
 
140
143
  | Package | Purpose |
141
- |---------|---------|
144
+ | --------- | --------- |
142
145
  | `open-multi-agent-kit` | Extension types (`ExtensionAPI`, `ExtensionContext`, events) |
143
146
  | `typebox` | Schema definitions for tool parameters |
144
147
  | `omk-agent-core` | General agent framework types and utilities |
@@ -569,6 +572,7 @@ omk.on("message_end", async (event, ctx) => {
569
572
  Fired for tool execution lifecycle updates.
570
573
 
571
574
  In parallel tool mode:
575
+
572
576
  - `tool_execution_start` is emitted in assistant source order during the preflight phase
573
577
  - `tool_execution_update` events may interleave across tools
574
578
  - `tool_execution_end` is emitted in tool completion order after each tool is finalized
@@ -684,6 +688,7 @@ In the default parallel tool execution mode, sibling tool calls from the same as
684
688
  `event.input` is mutable. Mutate it in place to patch tool arguments before execution.
685
689
 
686
690
  Behavior guarantees:
691
+
687
692
  - Mutations to `event.input` affect the actual tool execution
688
693
  - Later `tool_call` handlers see mutations made by earlier handlers
689
694
  - No re-validation is performed after your mutation
@@ -743,6 +748,7 @@ Fired after tool execution finishes and before `tool_execution_end` plus the fin
743
748
  In parallel tool mode, `tool_result` and `tool_execution_end` may interleave in tool completion order, while final `toolResult` message events are still emitted later in assistant source order.
744
749
 
745
750
  `tool_result` handlers chain like middleware:
751
+
746
752
  - Handlers run in extension load order
747
753
  - Each handler sees the latest result after previous handler changes
748
754
  - Handlers can return partial patches (`content`, `details`, or `isError`); omitted fields keep their current values
@@ -810,6 +816,7 @@ omk.on("user_bash", (event, ctx) => {
810
816
  Fired when user input is received, after extension commands are checked but before skill and template expansion. The event sees the raw input text, so `/skill:foo` and `/template` are not yet expanded.
811
817
 
812
818
  **Processing order:**
819
+
813
820
  1. Extension commands (`/cmd`) checked first - if found, handler runs and input event is skipped
814
821
  2. `input` event fires - can intercept, transform, or handle
815
822
  3. If not handled: skill commands (`/skill:name`) expanded to skill content
@@ -848,6 +855,7 @@ omk.on("input", async (event, ctx) => {
848
855
  ```
849
856
 
850
857
  **Results:**
858
+
851
859
  - `continue` - pass through unchanged (default if handler returns nothing)
852
860
  - `transform` - modify text/images, then continue to expansion
853
861
  - `handled` - skip agent entirely (first handler to return this wins)
@@ -895,6 +903,7 @@ Access to models and API keys.
895
903
  The current agent abort signal, or `undefined` when no agent turn is active.
896
904
 
897
905
  Use this for abort-aware nested work started by extension handlers, for example:
906
+
898
907
  - `fetch(..., { signal: ctx.signal })`
899
908
  - model calls that accept `signal`
900
909
  - file or process helpers that accept `AbortSignal`
@@ -1039,6 +1048,7 @@ if (result.cancelled) {
1039
1048
  ```
1040
1049
 
1041
1050
  Options:
1051
+
1042
1052
  - `parentSession`: parent session file to record in the new session header
1043
1053
  - `setup`: mutate the new session's `SessionManager` before `withSession` runs
1044
1054
  - `withSession`: run post-switch work against a fresh replacement-session context. Do not use captured old `omk` / command `ctx`; see [Session replacement lifecycle and footguns](#session-replacement-lifecycle-and-footguns).
@@ -1065,6 +1075,7 @@ if (cloneResult.cancelled) {
1065
1075
  ```
1066
1076
 
1067
1077
  Options:
1078
+
1068
1079
  - `position`: `"before"` (default) forks before the selected user message, restoring that prompt into the editor
1069
1080
  - `position`: `"at"` duplicates the active path through the selected entry without restoring editor text
1070
1081
  - `withSession`: run post-switch work against a fresh replacement-session context. Do not use captured old `omk` / command `ctx`; see [Session replacement lifecycle and footguns](#session-replacement-lifecycle-and-footguns).
@@ -1083,6 +1094,7 @@ const result = await ctx.navigateTree("entry-id-456", {
1083
1094
  ```
1084
1095
 
1085
1096
  Options:
1097
+
1086
1098
  - `summarize`: Whether to generate a summary of the abandoned branch
1087
1099
  - `customInstructions`: Custom instructions for the summarizer
1088
1100
  - `replaceInstructions`: If true, `customInstructions` replaces the default prompt instead of being appended
@@ -1104,6 +1116,7 @@ if (result.cancelled) {
1104
1116
  ```
1105
1117
 
1106
1118
  Options:
1119
+
1107
1120
  - `withSession`: run post-switch work against a fresh replacement-session context. Do not use captured old `omk` / command `ctx`; see [Session replacement lifecycle and footguns](#session-replacement-lifecycle-and-footguns).
1108
1121
 
1109
1122
  To discover available sessions, use the static `SessionManager.list()` or `SessionManager.listAll()` methods:
@@ -1136,6 +1149,7 @@ omk.registerCommand("switch", {
1136
1149
  `withSession` receives a fresh `ReplacedSessionContext`, which extends `ExtensionCommandContext` with async `sendMessage()` and `sendUserMessage()` helpers bound to the replacement session.
1137
1150
 
1138
1151
  Lifecycle and footguns:
1152
+
1139
1153
  - `withSession` runs only after the old session has emitted `session_shutdown`, the old runtime has been torn down, the replacement session has been rebound, and the new extension instance has already received `session_start`.
1140
1154
  - The callback still executes in the original closure, not inside the new extension instance. That means your old extension instance may already have run its shutdown cleanup before `withSession` starts.
1141
1155
  - Captured old `omk` / old command `ctx` session-bound objects are stale after replacement and will throw if used. Use only the `ctx` passed to `withSession` for session-bound work.
@@ -1189,6 +1203,7 @@ omk.registerCommand("reload-runtime", {
1189
1203
  ```
1190
1204
 
1191
1205
  Important behavior:
1206
+
1192
1207
  - `await ctx.reload()` emits `session_shutdown` for the current extension runtime
1193
1208
  - It then reloads resources and emits `session_start` with `reason: "reload"` and `resources_discover` with reason `"reload"`
1194
1209
  - The currently running command handler still continues in the old call frame
@@ -1304,6 +1319,7 @@ omk.sendMessage({
1304
1319
  ```
1305
1320
 
1306
1321
  **Options:**
1322
+
1307
1323
  - `deliverAs` - Delivery mode:
1308
1324
  - `"steer"` (default) - Queues the message while streaming. Delivered after the current assistant turn finishes executing its tool calls, before the next LLM call.
1309
1325
  - `"followUp"` - Waits for agent to finish. Delivered only when agent has no more tool calls.
@@ -1330,6 +1346,7 @@ omk.sendUserMessage("And then summarize", { deliverAs: "followUp" });
1330
1346
  ```
1331
1347
 
1332
1348
  **Options:**
1349
+
1333
1350
  - `deliverAs` - Required when agent is streaming:
1334
1351
  - `"steer"` - Queues the message for delivery after the current assistant turn finishes executing its tool calls
1335
1352
  - `"followUp"` - Waits for agent to finish all tools
@@ -1525,6 +1542,7 @@ omk.setActiveTools(["read", "bash"]); // Switch to read-only
1525
1542
  `omk.getAllTools()` returns `name`, `description`, `parameters`, `promptGuidelines`, and `sourceInfo`.
1526
1543
 
1527
1544
  Typical `sourceInfo.source` values:
1545
+
1528
1546
  - `builtin` for built-in tools
1529
1547
  - `sdk` for tools passed via `createAgentSession({ customTools })`
1530
1548
  - extension source metadata for tools registered by extensions
@@ -1619,6 +1637,7 @@ omk.registerProvider("corporate-ai", {
1619
1637
  ```
1620
1638
 
1621
1639
  **Config options:**
1640
+
1622
1641
  - `name` - Display name for the provider in UI such as `/login`.
1623
1642
  - `baseUrl` - API endpoint URL. Required when defining models.
1624
1643
  - `apiKey` - API key literal, environment interpolation (`$ENV_VAR` or `${ENV_VAR}`), or leading `!command`. Required when defining models (unless `oauth` provided). `$$` escapes `$`, and `$!` escapes a literal `!` without triggering command execution.
@@ -1781,6 +1800,14 @@ omk.registerTool({
1781
1800
  });
1782
1801
  ```
1783
1802
 
1803
+ **Timeouts:** Set `timeoutMs` for a static tool timeout, or return a per-call value from `resolveTimeoutMs(ctx)`. A resolved value takes precedence over `timeoutMs` and `agent.toolTimeouts`; `undefined` falls back to them, while `0` disables the timer. The resolver runs against the current extension context before each call. Values must be integer milliseconds from `0` through `2147483647`; invalid values fail before execution.
1804
+
1805
+ ```typescript
1806
+ resolveTimeoutMs(ctx) {
1807
+ return ctx.thinkingLevel === "ultra" ? 0 : undefined;
1808
+ }
1809
+ ```
1810
+
1784
1811
  **Signaling errors:** To mark a tool execution as failed (sets `isError: true` on the result and reports it to the LLM), throw an error from `execute`. Returning a value never sets the error flag regardless of what properties you include in the return object.
1785
1812
 
1786
1813
  **Early termination:** Return `terminate: true` from `execute()` to hint that the automatic follow-up LLM call should be skipped after the current tool batch. This only takes effect when every finalized tool result in that batch is terminating. See [examples/extensions/structured-output.ts](../examples/extensions/structured-output.ts) for a minimal example where the agent ends on a final structured-output tool call.
@@ -1854,6 +1881,7 @@ omk -e ./tool-override.ts
1854
1881
  ```
1855
1882
 
1856
1883
  Alternatively, use `--no-builtin-tools` to start without any built-in tools while keeping extension tools enabled:
1884
+
1857
1885
  ```bash
1858
1886
  # No built-in tools, only extension tools
1859
1887
  omk --no-builtin-tools -e ./my-extension.ts
@@ -1868,6 +1896,7 @@ See [examples/extensions/tool-override.ts](../examples/extensions/tool-override.
1868
1896
  **Your implementation must match the exact result shape**, including the `details` type. The UI and session logic depend on these shapes for rendering and state tracking.
1869
1897
 
1870
1898
  Built-in tool implementations:
1899
+
1871
1900
  - [read.ts](https://github.com/dmae97/omk/blob/main/packages/coding-agent/src/core/tools/read.ts) - `ReadToolDetails`
1872
1901
  - [bash.ts](https://github.com/dmae97/omk/blob/main/packages/coding-agent/src/core/tools/bash.ts) - `BashToolDetails`
1873
1902
  - [edit.ts](https://github.com/dmae97/omk/blob/main/packages/coding-agent/src/core/tools/edit.ts)
@@ -1928,6 +1957,7 @@ See [examples/extensions/ssh.ts](../examples/extensions/ssh.ts) for a complete S
1928
1957
  ### Output Truncation
1929
1958
 
1930
1959
  **Tools MUST truncate their output** to avoid overwhelming the LLM context. Large outputs can cause:
1960
+
1931
1961
  - Context overflow errors (prompt too long)
1932
1962
  - Compaction failures
1933
1963
  - Degraded model performance
@@ -1970,6 +2000,7 @@ async execute(toolCallId, params, signal, onUpdate, ctx) {
1970
2000
  ```
1971
2001
 
1972
2002
  **Key points:**
2003
+
1973
2004
  - Use `truncateHead` for content where the beginning matters (search results, file reads)
1974
2005
  - Use `truncateTail` for content where the end matters (logs, command output)
1975
2006
  - Always inform the LLM when output is truncated and where to find the full version
@@ -2020,6 +2051,7 @@ omk.registerTool({
2020
2051
  ```
2021
2052
 
2022
2053
  `renderCall` and `renderResult` each receive a `context` object with:
2054
+
2023
2055
  - `args` - the current tool call arguments
2024
2056
  - `state` - shared row-local state across `renderCall` and `renderResult`
2025
2057
  - `lastComponent` - the previously returned component for that slot, if any
@@ -2090,11 +2122,13 @@ renderResult(result, { expanded }, theme, context) {
2090
2122
  ```
2091
2123
 
2092
2124
  Available functions:
2125
+
2093
2126
  - `keyHint(keybinding, description)` - Formats a configured keybinding id such as `"app.tools.expand"` or `"tui.select.confirm"`
2094
2127
  - `keyText(keybinding)` - Returns the raw configured key text for a keybinding id
2095
2128
  - `rawKeyHint(key, description)` - Format a raw key string
2096
2129
 
2097
2130
  Use namespaced keybinding ids:
2131
+
2098
2132
  - Coding-agent ids use the `app.*` namespace, for example `app.tools.expand`, `app.editor.external`, `app.session.rename`
2099
2133
  - Shared TUI ids use the `tui.*` namespace, for example `tui.select.confirm`, `tui.select.cancel`, `tui.input.tab`
2100
2134
 
@@ -2117,6 +2151,7 @@ Custom editors and `ctx.ui.custom()` components receive `keybindings: Keybinding
2117
2151
  #### Fallback
2118
2152
 
2119
2153
  If a slot renderer is not defined or throws:
2154
+
2120
2155
  - `renderCall`: Shows the tool name
2121
2156
  - `renderResult`: Shows raw text from `content`
2122
2157
 
@@ -2125,6 +2160,7 @@ If a slot renderer is not defined or throws:
2125
2160
  Extensions can interact with users via `ctx.ui` methods and customize how messages/tools render.
2126
2161
 
2127
2162
  **For custom components, see [tui.md](tui.md)** which has copy-paste patterns for:
2163
+
2128
2164
  - Selection dialogs (SelectList)
2129
2165
  - Async operations with cancel (BorderedLoader)
2130
2166
  - Settings toggles (SettingsList)
@@ -2173,6 +2209,7 @@ if (confirmed) {
2173
2209
  ```
2174
2210
 
2175
2211
  **Return values on timeout:**
2212
+
2176
2213
  - `select()` returns `undefined`
2177
2214
  - `confirm()` returns `false`
2178
2215
  - `input()` returns `undefined`
@@ -2372,6 +2409,7 @@ if (result) {
2372
2409
  ```
2373
2410
 
2374
2411
  The callback receives:
2412
+
2375
2413
  - `tui` - TUI instance (for screen dimensions, focus management)
2376
2414
  - `theme` - Current theme for styling
2377
2415
  - `keybindings` - App keybinding manager (for checking shortcuts)
@@ -2446,6 +2484,7 @@ export default function (omk: ExtensionAPI) {
2446
2484
  ```
2447
2485
 
2448
2486
  **Key points:**
2487
+
2449
2488
  - Extend `CustomEditor` (not base `Editor`) to get app keybindings (escape to abort, ctrl+d, model switching)
2450
2489
  - Call `super.handleInput(data)` for keys you don't handle
2451
2490
  - Factory receives `theme` and `keybindings` from the app
@@ -2536,7 +2575,7 @@ const highlighted = highlightCode(code, lang, theme);
2536
2575
  ## Mode Behavior
2537
2576
 
2538
2577
  | Mode | `ctx.mode` | `ctx.hasUI` | Notes |
2539
- |------|------------|-------------|-------|
2578
+ | ------ | ------------ | ------------- | ------- |
2540
2579
  | Interactive | `"tui"` | `true` | Full TUI with terminal rendering |
2541
2580
  | RPC (`--mode rpc`) | `"rpc"` | `true` | Dialogs and notifications via JSON protocol; `custom()` returns `undefined`. See [rpc.md](rpc.md) |
2542
2581
  | JSON (`--mode json`) | `"json"` | `false` | Event stream to stdout; UI methods are no-ops |
@@ -2544,13 +2583,32 @@ const highlighted = highlightCode(code, lang, theme);
2544
2583
 
2545
2584
  Use `ctx.mode === "tui"` before TUI-specific features (`custom()`, component factories, terminal input). Use `ctx.hasUI` before dialog and notification methods that work in both TUI and RPC modes.
2546
2585
 
2586
+ ## Plannotator Approval Bridge
2587
+
2588
+ [`plannotator-approval-bridge.ts`](../examples/extensions/plannotator-approval-bridge.ts) is an optional, non-executing approval adapter for the shared Plannotator event API. It sends a correlated `plannotator:request` with action `plan-review`, accepts only the matching `plannotator:review-result`, and persists an immutable receipt. It never dispatches a plan.
2589
+
2590
+ Pin and inspect Plannotator before loading it:
2591
+
2592
+ ```bash
2593
+ omk package doctor npm:@plannotator/pi-extension@0.25.1
2594
+ omk install npm:@plannotator/pi-extension@0.25.1
2595
+ cp packages/coding-agent/examples/extensions/plannotator-approval-bridge.ts .omk/extensions/
2596
+ omk
2597
+ ```
2598
+
2599
+ Then run `/approval-review plans/auth.md` in TUI mode. The bridge fails closed in print, JSON, and RPC modes. Receipts are written with owner-only permissions under the current session directory and appended to the session as `approval-receipt-v1`. They bind the request ID, Plannotator review ID, session ID, decision, plan path, plan byte count, and SHA-256 digest. Feedback is stored only as a byte count and digest.
2600
+
2601
+ The receipt does not authorize modified plan bytes. Any separate executor must call `verifyApprovalForExecution()` immediately before execution and require the current session, path, and content to match an approved receipt. The example intentionally has no executor.
2602
+
2603
+ This command uses Plannotator's standalone plan-review API. If you also use Plannotator's own `/plannotator` plan mode and want to prevent its built-in automatic execution, set `"executionMode": "external"` in Plannotator's project configuration.
2604
+
2547
2605
  ## Examples Reference
2548
2606
 
2549
2607
  All examples in [examples/extensions/](../examples/extensions/).
2550
2608
 
2551
2609
  | Example | Description | Key APIs |
2552
- |---------|-------------|----------|
2553
- | **Tools** |||
2610
+ | --------- | ------------- | ---------- |
2611
+ | **Tools** | | |
2554
2612
  | `hello.ts` | Minimal tool registration | `registerTool` |
2555
2613
  | `question.ts` | Tool with user interaction | `registerTool`, `ui.select` |
2556
2614
  | `questionnaire.ts` | Multi-step wizard tool | `registerTool`, `ui.custom` |
@@ -2559,7 +2617,7 @@ All examples in [examples/extensions/](../examples/extensions/).
2559
2617
  | `structured-output.ts` | Final structured-output tool with `terminate: true` | `registerTool`, terminating tool results |
2560
2618
  | `truncated-tool.ts` | Output truncation example | `registerTool`, `truncateHead` |
2561
2619
  | `tool-override.ts` | Override built-in read tool | `registerTool` (same name as built-in) |
2562
- | **Commands** |||
2620
+ | **Commands** | | |
2563
2621
  | `pirate.ts` | Modify system prompt per-turn | `registerCommand`, `before_agent_start` |
2564
2622
  | `summarize.ts` | Conversation summary command | `registerCommand`, `ui.custom` |
2565
2623
  | `handoff.ts` | Cross-provider model handoff | `registerCommand`, `ui.editor`, `ui.custom` |
@@ -2567,11 +2625,12 @@ All examples in [examples/extensions/](../examples/extensions/).
2567
2625
  | `send-user-message.ts` | Inject user messages | `registerCommand`, `sendUserMessage` |
2568
2626
  | `reload-runtime.ts` | Reload command and LLM tool handoff | `registerCommand`, `ctx.reload()`, `sendUserMessage` |
2569
2627
  | `shutdown-command.ts` | Graceful shutdown command | `registerCommand`, `shutdown()` |
2570
- | **Events & Gates** |||
2628
+ | **Events & Gates** | | |
2571
2629
  | `permission-gate.ts` | Block dangerous commands | `on("tool_call")`, `ui.confirm` |
2572
2630
  | `protected-paths.ts` | Block writes to specific paths | `on("tool_call")` |
2573
2631
  | `confirm-destructive.ts` | Confirm session changes | `on("session_before_switch")`, `on("session_before_fork")` |
2574
2632
  | `dirty-repo-guard.ts` | Warn on dirty git repo | `on("session_before_*")`, `exec` |
2633
+ | `plannotator-approval-bridge.ts` | Correlate browser decisions and persist non-executing immutable receipts | `omk.events`, `ApprovalReceiptStore`, `verifyApprovalForExecution` |
2575
2634
  | `input-transform.ts` | Transform user input | `on("input")` |
2576
2635
  | `input-transform-streaming.ts` | Streaming-aware input transform | `on("input")`, `streamingBehavior` |
2577
2636
  | `model-status.ts` | React to model changes | `on("model_select")`, `setStatus` |
@@ -2580,13 +2639,13 @@ All examples in [examples/extensions/](../examples/extensions/).
2580
2639
  | `claude-rules.ts` | Load rules from files | `on("session_start")`, `on("before_agent_start")` |
2581
2640
  | `prompt-customizer.ts` | Add context-aware tool guidance using `systemPromptOptions` | `on("before_agent_start")`, `BuildSystemPromptOptions` |
2582
2641
  | `file-trigger.ts` | File watcher triggers messages | `sendMessage` |
2583
- | **Compaction & Sessions** |||
2642
+ | **Compaction & Sessions** | | |
2584
2643
  | `custom-compaction.ts` | Custom compaction summary | `on("session_before_compact")` |
2585
2644
  | `trigger-compact.ts` | Trigger compaction manually | `compact()` |
2586
2645
  | `git-checkpoint.ts` | Git stash on turns | `on("turn_start")`, `on("session_before_fork")`, `exec` |
2587
2646
  | `git-merge-and-resolve.ts` | Fetch, merge, and resolve conflicts | `on("agent_end")`, `exec`, `sendUserMessage` |
2588
2647
  | `auto-commit-on-exit.ts` | Commit on shutdown | `on("session_shutdown")`, `exec` |
2589
- | **UI Components** |||
2648
+ | **UI Components** | | |
2590
2649
  | `status-line.ts` | Footer status indicator | `setStatus`, session events |
2591
2650
  | `working-indicator.ts` | Customize the streaming working indicator | `setWorkingIndicator`, `registerCommand` |
2592
2651
  | `github-issue-autocomplete.ts` | Add `#1234` issue completions on top of built-in autocomplete by preloading recent open issues from `gh issue list` | `addAutocompleteProvider`, `on("session_start")`, `exec` |
@@ -2600,30 +2659,30 @@ All examples in [examples/extensions/](../examples/extensions/).
2600
2659
  | `notify.ts` | Simple notifications | `ui.notify` |
2601
2660
  | `timed-confirm.ts` | Dialogs with timeout | `ui.confirm` with timeout/signal |
2602
2661
  | `mac-system-theme.ts` | Auto-switch theme | `setTheme`, `exec` |
2603
- | **Complex Extensions** |||
2662
+ | **Complex Extensions** | | |
2604
2663
  | `plan-mode/` | Full plan mode implementation | All event types, `registerCommand`, `registerShortcut`, `registerFlag`, `setStatus`, `setWidget`, `sendMessage`, `setActiveTools` |
2605
2664
  | `preset.ts` | Saveable presets (model, tools, thinking) | `registerCommand`, `registerShortcut`, `registerFlag`, `setModel`, `setActiveTools`, `setThinkingLevel`, `appendEntry` |
2606
2665
  | `tools.ts` | Toggle tools on/off UI | `registerCommand`, `setActiveTools`, `SettingsList`, session events |
2607
- | **Remote & Sandbox** |||
2666
+ | **Remote & Sandbox** | | |
2608
2667
  | `ssh.ts` | SSH remote execution | `registerFlag`, `on("user_bash")`, `on("before_agent_start")`, tool operations |
2609
2668
  | `interactive-shell.ts` | Persistent shell session | `on("user_bash")` |
2610
2669
  | `sandbox/` | Sandboxed tool execution | Tool operations |
2611
2670
  | `gondolin/` | Route built-in tools and `!` commands into a Gondolin micro-VM | Tool operations, built-in tool overrides, `on("user_bash")` |
2612
2671
  | `subagent/` | Spawn sub-agents | `registerTool`, `exec` |
2613
- | **Games** |||
2672
+ | **Games** | | |
2614
2673
  | `snake.ts` | Snake game | `registerCommand`, `ui.custom`, keyboard handling |
2615
2674
  | `space-invaders.ts` | Space Invaders game | `registerCommand`, `ui.custom` |
2616
2675
  | `doom-overlay/` | Doom in overlay | `ui.custom` with overlay |
2617
- | **Providers** |||
2676
+ | **Providers** | | |
2618
2677
  | `custom-provider-anthropic/` | Custom Anthropic proxy | `registerProvider` |
2619
2678
  | `custom-provider-gitlab-duo/` | GitLab Duo integration | `registerProvider` with OAuth |
2620
- | **Messages & Communication** |||
2679
+ | **Messages & Communication** | | |
2621
2680
  | `message-renderer.ts` | Custom message rendering | `registerMessageRenderer`, `sendMessage` |
2622
2681
  | `event-bus.ts` | Inter-extension events | `omk.events` |
2623
- | **Session Metadata** |||
2682
+ | **Session Metadata** | | |
2624
2683
  | `session-name.ts` | Name sessions for selector | `setSessionName`, `getSessionName` |
2625
2684
  | `bookmark.ts` | Bookmark entries for /tree | `setLabel` |
2626
- | **Misc** |||
2685
+ | **Misc** | | |
2627
2686
  | `inline-bash.ts` | Inline bash in tool calls | `on("tool_call")` |
2628
2687
  | `bash-spawn-hook.ts` | Adjust bash command, cwd, and env before execution | `createBashTool`, `spawnHook` |
2629
2688
  | `with-deps/` | Extension with npm dependencies | Package structure with `package.json` |
package/docs/mcp.md ADDED
@@ -0,0 +1,97 @@
1
+ # MCP
2
+
3
+ OMK speaks the [Model Context Protocol](https://modelcontextprotocol.io) as a
4
+ **client**: it starts configured servers, lists their tools, and exposes those
5
+ tools to the model alongside the built-in ones.
6
+
7
+ Two separate surfaces exist, and they are easy to confuse:
8
+
9
+ | Surface | Module | What it does |
10
+ | --- | --- | --- |
11
+ | Inventory / health | `core/mcp-inventory.ts` | Reads configuration read-only for `omk doctor` and the MCP health view. **Never starts a server.** Env *values* are stripped. |
12
+ | Runtime client | `core/mcp/` | Starts servers, performs the handshake, and registers their tools for a session. |
13
+
14
+ ## Configuration
15
+
16
+ Servers are read from three files, later wins on a name collision:
17
+
18
+ 1. `~/.kimi/mcp.json`
19
+ 2. `~/.omk/mcp.json`
20
+ 3. `<cwd>/.omk/mcp.json`
21
+
22
+ ```json
23
+ {
24
+ "mcpServers": {
25
+ "playwright": {
26
+ "command": "npx",
27
+ "args": ["-y", "@playwright/mcp@latest"],
28
+ "startup_timeout_sec": 60
29
+ },
30
+ "serena": {
31
+ "command": "uvx",
32
+ "args": ["--from", "git+https://github.com/oraios/serena", "serena"],
33
+ "env": { "SERENA_LOG_LEVEL": "error" }
34
+ },
35
+ "retired": { "command": "npx", "args": ["-y", "old-server"], "disabled": true }
36
+ }
37
+ }
38
+ ```
39
+
40
+ | Field | Meaning |
41
+ | --- | --- |
42
+ | `command`, `args` | Executable to spawn. **Required** — entries with only a `url` are skipped, since stdio is the supported transport. |
43
+ | `env` | Extra environment for the child. Merged over the parent environment. Values are runtime-only and are never rendered or logged. |
44
+ | `cwd` | Working directory. Defaults to the session's cwd. |
45
+ | `disabled` / `enabled: false` | Skip without deleting the entry. |
46
+ | `startup_timeout_sec` | Handshake deadline. Raise it for `npx -y …@latest` servers whose first run downloads a package. |
47
+
48
+ ## Using it
49
+
50
+ ```ts
51
+ const status = await session.attachMcpServers();
52
+ // [{ name: "playwright", state: "ready", toolCount: 24, serverVersion: "1.62.0" }]
53
+
54
+ session.getToolDefinition("playwright__navigate");
55
+ ```
56
+
57
+ - **Nothing is spawned until `attachMcpServers()` is called.** A workspace can
58
+ configure 25 servers without paying for them at startup.
59
+ - Tools are exposed as `<server>__<tool>`, truncated to 64 characters with the
60
+ server prefix preserved.
61
+ - A built-in tool always wins a name collision; MCP can never shadow `bash`.
62
+ - Calling `attachMcpServers()` again replaces the previous MCP tools rather than
63
+ duplicating them.
64
+ - `session.dispose()` terminates every server it started.
65
+
66
+ ### Failure behavior
67
+
68
+ Failures are isolated by design, because one broken server must not cost a
69
+ session:
70
+
71
+ | Failure | Result |
72
+ | --- | --- |
73
+ | Server exits during startup | That server is `failed` with its stderr tail; every other server still contributes tools. |
74
+ | Handshake exceeds `startup_timeout_sec` | Same — reported as a timeout, session unaffected. |
75
+ | Server dies mid-session | In-flight requests reject; later calls to its tools return a tool-level error instead of throwing. |
76
+ | Tool returns an MCP error | Surfaces as a normal tool result with `isError: true`, so the model sees the server's own message. |
77
+ | Server emits a non-JSON line | The line is dropped and decoding resynchronizes at the next newline. |
78
+
79
+ ## Checking your configuration
80
+
81
+ ```bash
82
+ node scripts/mcp-smoke.mjs # connect everything, print status
83
+ node scripts/mcp-smoke.mjs github playwright # only these
84
+ OMK_MCP_SMOKE_HANDSHAKE_MS=120000 node scripts/mcp-smoke.mjs # override slow handshakes
85
+ ```
86
+
87
+ The script prints server state, tool counts, and versions. It never prints env
88
+ values.
89
+
90
+ ## Scope
91
+
92
+ Implemented: `initialize`, `notifications/initialized`, `tools/list`,
93
+ `tools/call` over stdio.
94
+
95
+ Not implemented: HTTP/SSE transports, resources, prompts, sampling, and
96
+ server-initiated requests. Every OMK-configured server today is stdio, and
97
+ adding a surface nothing calls would be dead weight.
@@ -0,0 +1,87 @@
1
+ # Turn metrics
2
+
3
+ OMK records one JSON line per agent turn so harness changes can be measured
4
+ instead of guessed.
5
+
6
+ This is separate from the two things that already existed:
7
+
8
+ | Surface | Purpose |
9
+ | --- | --- |
10
+ | `core/run-journal.ts` | Hash-chained **integrity** log (run started/finished/recovered, tool timeout). Answers "was this run tampered with or abandoned". |
11
+ | `core/telemetry.ts` | Install-time opt-in flag. Nothing else. |
12
+ | `core/turn-metrics.ts` | **Performance and quality**: cost, latency, tool failure rates, cache effectiveness. |
13
+
14
+ ## Where it goes
15
+
16
+ `<cwd>/.omk/metrics/turns.jsonl`, append-only, rotated once past 8 MB
17
+ (`turns.jsonl.1`), file mode `600`.
18
+
19
+ | Variable | Effect |
20
+ | --- | --- |
21
+ | `OMK_TURN_METRICS=0` | Disable recording entirely. |
22
+ | `OMK_TURN_METRICS_DIR` | Write somewhere else. |
23
+
24
+ ## Reading it
25
+
26
+ ```bash
27
+ omk stats # aggregate report for the current project
28
+ omk stats --dir <path> # a different metrics directory
29
+ omk stats --json # machine-readable summary
30
+ ```
31
+
32
+ ```text
33
+ Turn metrics — 412 turns across 27 session(s)
34
+ models anthropic/claude-sonnet-4-5
35
+ turn duration p50 4.2s · p95 31.8s
36
+ input 91,204 · output 22,880 · cacheRead 1,904,551 · cacheWrite 88,100
37
+ cache read share 95.4% of prompt-side usage
38
+ cost $4.8812
39
+ compactions 6 · failovers 1 · ctx plan hit 41.2%
40
+
41
+ tool calls fail% p50 p95 total
42
+ bash 688 4.2% 210ms 3.1s 4.1m
43
+ edit 201 9.0% 38ms 140ms 12.4s
44
+ ```
45
+
46
+ ## What is recorded
47
+
48
+ Counts, durations, ids, and error *classes*:
49
+
50
+ ```json
51
+ {
52
+ "schemaVersion": "omk-turn-metrics-1",
53
+ "sessionId": "…", "turnIndex": 12,
54
+ "provider": "anthropic", "model": "claude-sonnet-4-5",
55
+ "startedAtEpochMs": 1, "endedAtEpochMs": 2, "durationMs": 1,
56
+ "usage": { "input": 100, "output": 20, "cacheRead": 900, "cacheWrite": 10, "costUsd": 0.0125 },
57
+ "stopReason": "toolUse",
58
+ "toolCalls": [{ "name": "bash", "durationMs": 120, "ok": false, "error": "exit 1" }],
59
+ "toolCallCount": 1, "toolFailureCount": 1
60
+ }
61
+ ```
62
+
63
+ **Never recorded:** prompt text, tool arguments, tool output, file contents, or
64
+ environment values. Tool error strings are whitespace-collapsed and truncated to
65
+ 200 characters — enough to tell failure modes apart, too short to carry a
66
+ payload.
67
+
68
+ Metrics are advisory. A failed write is counted and dropped; it can never make a
69
+ turn fail.
70
+
71
+ ## Capability baseline
72
+
73
+ Runtime metrics tell you what a session cost, not whether the harness can solve
74
+ tasks. For that, `scripts/tb-mini-suite.mjs` selects a deterministic,
75
+ difficulty-balanced Terminal-Bench 2.1 subset so scores are comparable across
76
+ runs:
77
+
78
+ ```bash
79
+ node scripts/tb-mini-suite.mjs # human-readable selection
80
+ node scripts/tb-mini-suite.mjs --json # feed a runner
81
+ node scripts/tb-mini-suite.mjs --seed 7 # a different fixed subset
82
+ ```
83
+
84
+ Selection is a pure function of (tasks directory, seed, size): the same inputs
85
+ always produce the same task list, which is the whole point of using it as a
86
+ regression gate. The scoring run itself requires Docker, `harbor`, and real
87
+ model spend — it is deliberately not wired into `npm run check`.
package/docs/packages.md CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  # OMK Packages
4
4
 
5
- OMK packages bundle extensions, skills, prompt templates, and themes so you can share them through npm or git. A package can declare resources in `package.json` under the `omk` key, or use conventional directories.
5
+ OMK packages bundle extensions, skills, prompt templates, and themes so you can share them through npm or git. A package can declare resources in `package.json` under `omk` or the compatible `pi` key, or use conventional directories.
6
6
 
7
7
  ## Table of Contents
8
8
 
9
9
  - [Install and Manage](#install-and-manage)
10
+ - [Pi Compatibility and Package Doctor](#pi-compatibility-and-package-doctor)
10
11
  - [Package Sources](#package-sources)
11
12
  - [Creating a OMK Package](#creating-a-omk-package)
12
13
  - [Package Structure](#package-structure)
@@ -28,6 +29,7 @@ omk install ./relative/path/to/package
28
29
 
29
30
  omk remove npm:@foo/bar
30
31
  omk list # show installed packages from settings
32
+ omk package doctor npm:@foo/bar@1.0.0 # static compatibility report as JSON
31
33
  omk update # update omk, update packages, and reconcile pinned git refs
32
34
  omk update --extensions # update packages and reconcile pinned git refs only
33
35
  omk update --self # update omk only
@@ -47,6 +49,24 @@ omk -e npm:@foo/bar
47
49
  omk -e git:github.com/user/repo
48
50
  ```
49
51
 
52
+ ## Pi Compatibility and Package Doctor
53
+
54
+ OMK reads package manifests in strict priority order: `omk`, then `pi`, then conventional directories. The first present manifest is authoritative. If it is malformed, OMK reports the error instead of silently falling back. When both keys exist, `omk` wins and the doctor reports that `pi` was shadowed.
55
+
56
+ A Pi extension directory entry such as `"extensions": ["./"]` resolves to its `index.ts`, `index.js`, `index.mjs`, or `index.cjs`. It is not recursively treated as a directory of independent extensions.
57
+
58
+ Inspect a local, npm, or git source before installing it:
59
+
60
+ ```bash
61
+ omk package doctor ./local-package
62
+ omk package doctor npm:@scope/package@1.2.3 > package-doctor.json
63
+ omk package doctor git:github.com/user/repo@v1
64
+ ```
65
+
66
+ The command emits a versioned JSON report and returns `0` when no compatibility error is found, `1` for an incompatible package or inspection failure, and `2` for invalid CLI usage. It checks manifest precedence, declared resources, legacy Pi runtime imports, `.pi` storage paths, lifecycle event names, headless UI guards, and resume signals.
67
+
68
+ The doctor never imports extension modules. For npm sources it downloads the registry tarball with `npm pack --ignore-scripts` and extracts bounded regular files without installing dependencies. Git inspection clones without running `npm install`. These static checks are advisory and do not make third-party code trusted.
69
+
50
70
  ## Package Sources
51
71
 
52
72
  OMK accepts three source types in settings and `omk install`.
@@ -91,6 +111,7 @@ ssh://git@github.com/user/repo@v1
91
111
  - When reconciliation changes the checkout, omk resets and cleans the clone, then runs `npm install` if `package.json` exists.
92
112
 
93
113
  **SSH examples:**
114
+
94
115
  ```bash
95
116
  # git@host:path shorthand (requires git: prefix)
96
117
  omk install git:git@github.com:user/repo
@@ -113,7 +134,7 @@ Local paths point to files or directories on disk and are added to settings with
113
134
 
114
135
  ## Creating a OMK Package
115
136
 
116
- Add a `omk` manifest to `package.json` or use conventional directories. Include the `omk-package` keyword for discoverability.
137
+ Add an `omk` manifest to `package.json` or use conventional directories. OMK also reads a Pi-compatible `pi` manifest when `omk` is absent. Include the `omk-package` keyword for discoverability.
117
138
 
118
139
  ```json
119
140
  {
@@ -155,7 +176,7 @@ If both are set, video takes precedence.
155
176
 
156
177
  ### Convention Directories
157
178
 
158
- If no `omk` manifest is present, omk auto-discovers resources from these directories:
179
+ If neither an `omk` nor a `pi` manifest is present, omk auto-discovers resources from these directories:
159
180
 
160
181
  - `extensions/` loads `.ts` and `.js` files
161
182
  - `skills/` recursively finds `SKILL.md` folders and loads top-level `.md` files as skills
@@ -164,7 +185,7 @@ If no `omk` manifest is present, omk auto-discovers resources from these directo
164
185
 
165
186
  ## Dependencies
166
187
 
167
- Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. When omk installs a package from npm or git, it runs `npm install`, so those dependencies are installed automatically.
188
+ Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. Normal npm and git installation installs runtime dependencies automatically. `omk package doctor` is different: it does not install dependencies or execute lifecycle scripts.
168
189
 
169
190
  OMK bundles core packages for extensions and skills. If you import any of these, list them in `peerDependencies` with a `"*"` range and do not bundle them: `omk-ai`, `omk-agent-core`, `open-multi-agent-kit`, `omk-tui`, `typebox`.
170
191
 
package/docs/providers.md CHANGED
@@ -33,7 +33,7 @@ Alibaba Model Studio Token Plan is recognized as **QWEN TOKEN PLAN** but shows `
33
33
 
34
34
  - Requires ChatGPT Plus or Pro subscription
35
35
  - Officially endorsed by OpenAI: [Codex for OSS](https://developers.openai.com/community/codex-for-oss)
36
- - `gpt-5.6-moa` is a tool-free virtual model that runs bounded GPT-5.6 Sol and Terra advisers concurrently, then streams a Sol synthesis. It performs three inference calls per turn, caps adviser/synthesis output independently, and is intended for analysis, review, and answer synthesis; use Sol or Terra directly when tools are required.
36
+ - `gpt-5.6-moa` runs bounded, tool-free GPT-5.6 Sol and Terra advisers concurrently, then streams a Sol synthesis with the active tools and tool history. Synthesis tool calls enter the normal agent loop; each follow-up model turn repeats the three-call workflow. Adviser and synthesis output remain independently capped.
37
37
  - The Codex backend accepts `xhigh` as its highest literal reasoning effort. OMK's `max` and `ultra` tiers map to `xhigh`; `ultra` on the MoA model additionally represents the Sol/Terra delegation workflow.
38
38
 
39
39
  ```bash