@wahack/pi-coding-agent 15.11.0

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 (1152) hide show
  1. package/CHANGELOG.md +10031 -0
  2. package/README.md +36 -0
  3. package/examples/README.md +21 -0
  4. package/examples/custom-tools/README.md +104 -0
  5. package/examples/custom-tools/hello/index.ts +20 -0
  6. package/examples/extensions/README.md +142 -0
  7. package/examples/extensions/api-demo.ts +79 -0
  8. package/examples/extensions/chalk-logger.ts +25 -0
  9. package/examples/extensions/hello.ts +31 -0
  10. package/examples/extensions/pirate.ts +43 -0
  11. package/examples/extensions/plan-mode.ts +549 -0
  12. package/examples/extensions/reload-runtime.ts +38 -0
  13. package/examples/extensions/thinking-note.ts +13 -0
  14. package/examples/extensions/tools.ts +145 -0
  15. package/examples/extensions/with-deps/index.ts +36 -0
  16. package/examples/extensions/with-deps/package-lock.json +31 -0
  17. package/examples/extensions/with-deps/package.json +17 -0
  18. package/examples/hooks/README.md +56 -0
  19. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  20. package/examples/hooks/confirm-destructive.ts +58 -0
  21. package/examples/hooks/custom-compaction.ts +115 -0
  22. package/examples/hooks/dirty-repo-guard.ts +51 -0
  23. package/examples/hooks/file-trigger.ts +40 -0
  24. package/examples/hooks/git-checkpoint.ts +52 -0
  25. package/examples/hooks/handoff.ts +149 -0
  26. package/examples/hooks/permission-gate.ts +33 -0
  27. package/examples/hooks/protected-paths.ts +29 -0
  28. package/examples/hooks/qna.ts +118 -0
  29. package/examples/hooks/status-line.ts +39 -0
  30. package/examples/sdk/01-minimal.ts +21 -0
  31. package/examples/sdk/02-custom-model.ts +49 -0
  32. package/examples/sdk/03-custom-prompt.ts +46 -0
  33. package/examples/sdk/04-skills.ts +43 -0
  34. package/examples/sdk/06-extensions.ts +82 -0
  35. package/examples/sdk/06-hooks.ts +61 -0
  36. package/examples/sdk/07-context-files.ts +35 -0
  37. package/examples/sdk/08-prompt-templates.ts +41 -0
  38. package/examples/sdk/08-slash-commands.ts +46 -0
  39. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  40. package/examples/sdk/11-sessions.ts +47 -0
  41. package/examples/sdk/12-redis-sessions.ts +54 -0
  42. package/examples/sdk/13-sql-sessions.ts +61 -0
  43. package/examples/sdk/README.md +172 -0
  44. package/package.json +554 -0
  45. package/scripts/build-binary.ts +100 -0
  46. package/scripts/bundle-dist.ts +90 -0
  47. package/scripts/format-prompts.ts +68 -0
  48. package/scripts/generate-docs-index.ts +40 -0
  49. package/scripts/generate-template.ts +33 -0
  50. package/scripts/omp +42 -0
  51. package/scripts/omp.ts +19 -0
  52. package/src/async/index.ts +1 -0
  53. package/src/async/job-manager.ts +625 -0
  54. package/src/auto-thinking/classifier.ts +185 -0
  55. package/src/autoresearch/command-resume.md +14 -0
  56. package/src/autoresearch/dashboard.ts +436 -0
  57. package/src/autoresearch/git.ts +319 -0
  58. package/src/autoresearch/helpers.ts +218 -0
  59. package/src/autoresearch/index.ts +536 -0
  60. package/src/autoresearch/prompt-setup.md +43 -0
  61. package/src/autoresearch/prompt.md +103 -0
  62. package/src/autoresearch/resume-message.md +10 -0
  63. package/src/autoresearch/state.ts +273 -0
  64. package/src/autoresearch/storage.ts +699 -0
  65. package/src/autoresearch/tools/init-experiment.ts +272 -0
  66. package/src/autoresearch/tools/log-experiment.ts +524 -0
  67. package/src/autoresearch/tools/run-experiment.ts +407 -0
  68. package/src/autoresearch/tools/update-notes.ts +109 -0
  69. package/src/autoresearch/types.ts +168 -0
  70. package/src/bun-imports.d.ts +28 -0
  71. package/src/capability/context-file.ts +44 -0
  72. package/src/capability/extension-module.ts +34 -0
  73. package/src/capability/extension.ts +47 -0
  74. package/src/capability/fs.ts +117 -0
  75. package/src/capability/hook.ts +40 -0
  76. package/src/capability/index.ts +436 -0
  77. package/src/capability/instruction.ts +37 -0
  78. package/src/capability/mcp.ts +74 -0
  79. package/src/capability/prompt.ts +35 -0
  80. package/src/capability/rule-buckets.ts +66 -0
  81. package/src/capability/rule.ts +261 -0
  82. package/src/capability/settings.ts +34 -0
  83. package/src/capability/skill.ts +63 -0
  84. package/src/capability/slash-command.ts +40 -0
  85. package/src/capability/ssh.ts +41 -0
  86. package/src/capability/system-prompt.ts +34 -0
  87. package/src/capability/tool.ts +38 -0
  88. package/src/capability/types.ts +168 -0
  89. package/src/cli/agents-cli.ts +138 -0
  90. package/src/cli/args.ts +340 -0
  91. package/src/cli/auth-broker-cli.ts +895 -0
  92. package/src/cli/auth-gateway-cli.ts +611 -0
  93. package/src/cli/classify-install-target.ts +76 -0
  94. package/src/cli/claude-trace-cli.ts +795 -0
  95. package/src/cli/commands/init-xdg.ts +27 -0
  96. package/src/cli/completion-gen.ts +550 -0
  97. package/src/cli/config-cli.ts +418 -0
  98. package/src/cli/dry-balance-cli.ts +856 -0
  99. package/src/cli/extension-flags.ts +48 -0
  100. package/src/cli/file-processor.ts +133 -0
  101. package/src/cli/gallery-cli.ts +230 -0
  102. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  103. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  104. package/src/cli/gallery-fixtures/edit.ts +194 -0
  105. package/src/cli/gallery-fixtures/fs.ts +220 -0
  106. package/src/cli/gallery-fixtures/index.ts +40 -0
  107. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  108. package/src/cli/gallery-fixtures/memory.ts +81 -0
  109. package/src/cli/gallery-fixtures/misc.ts +250 -0
  110. package/src/cli/gallery-fixtures/search.ts +213 -0
  111. package/src/cli/gallery-fixtures/shell.ts +167 -0
  112. package/src/cli/gallery-fixtures/types.ts +57 -0
  113. package/src/cli/gallery-fixtures/web.ts +158 -0
  114. package/src/cli/gallery-screenshot.ts +279 -0
  115. package/src/cli/grep-cli.ts +160 -0
  116. package/src/cli/grievances-cli.ts +256 -0
  117. package/src/cli/initial-message.ts +58 -0
  118. package/src/cli/list-models.ts +194 -0
  119. package/src/cli/plugin-cli.ts +996 -0
  120. package/src/cli/read-cli.ts +57 -0
  121. package/src/cli/session-picker.ts +79 -0
  122. package/src/cli/setup-cli.ts +231 -0
  123. package/src/cli/shell-cli.ts +176 -0
  124. package/src/cli/ssh-cli.ts +179 -0
  125. package/src/cli/startup-cwd.ts +68 -0
  126. package/src/cli/stats-cli.ts +238 -0
  127. package/src/cli/tiny-models-cli.ts +127 -0
  128. package/src/cli/update-cli.ts +611 -0
  129. package/src/cli/usage-cli.ts +603 -0
  130. package/src/cli/web-search-cli.ts +132 -0
  131. package/src/cli/worktree-cli.ts +291 -0
  132. package/src/cli-commands.ts +79 -0
  133. package/src/cli.ts +200 -0
  134. package/src/commands/acp.ts +24 -0
  135. package/src/commands/agents.ts +57 -0
  136. package/src/commands/auth-broker.ts +99 -0
  137. package/src/commands/auth-gateway.ts +69 -0
  138. package/src/commands/commit.ts +46 -0
  139. package/src/commands/complete.ts +66 -0
  140. package/src/commands/completions.ts +60 -0
  141. package/src/commands/config.ts +51 -0
  142. package/src/commands/dry-balance.ts +43 -0
  143. package/src/commands/gallery.ts +52 -0
  144. package/src/commands/grep.ts +48 -0
  145. package/src/commands/grievances.ts +51 -0
  146. package/src/commands/install.ts +107 -0
  147. package/src/commands/launch.ts +169 -0
  148. package/src/commands/plugin.ts +78 -0
  149. package/src/commands/read.ts +38 -0
  150. package/src/commands/setup.ts +67 -0
  151. package/src/commands/shell.ts +29 -0
  152. package/src/commands/ssh.ts +60 -0
  153. package/src/commands/stats.ts +29 -0
  154. package/src/commands/tiny-models.ts +36 -0
  155. package/src/commands/update.ts +21 -0
  156. package/src/commands/usage.ts +35 -0
  157. package/src/commands/web-search.ts +42 -0
  158. package/src/commands/worktree.ts +56 -0
  159. package/src/commit/agentic/agent.ts +317 -0
  160. package/src/commit/agentic/fallback.ts +96 -0
  161. package/src/commit/agentic/index.ts +355 -0
  162. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  163. package/src/commit/agentic/prompts/session-user.md +25 -0
  164. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  165. package/src/commit/agentic/prompts/system.md +38 -0
  166. package/src/commit/agentic/state.ts +60 -0
  167. package/src/commit/agentic/tools/analyze-file.ts +146 -0
  168. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  169. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  170. package/src/commit/agentic/tools/git-overview.ts +81 -0
  171. package/src/commit/agentic/tools/index.ts +54 -0
  172. package/src/commit/agentic/tools/propose-changelog.ts +144 -0
  173. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  174. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  175. package/src/commit/agentic/tools/schemas.ts +23 -0
  176. package/src/commit/agentic/tools/split-commit.ts +245 -0
  177. package/src/commit/agentic/topo-sort.ts +44 -0
  178. package/src/commit/agentic/trivial.ts +51 -0
  179. package/src/commit/agentic/validation.ts +183 -0
  180. package/src/commit/analysis/conventional.ts +64 -0
  181. package/src/commit/analysis/index.ts +4 -0
  182. package/src/commit/analysis/scope.ts +242 -0
  183. package/src/commit/analysis/summary.ts +105 -0
  184. package/src/commit/analysis/validation.ts +66 -0
  185. package/src/commit/changelog/detect.ts +40 -0
  186. package/src/commit/changelog/generate.ts +97 -0
  187. package/src/commit/changelog/index.ts +234 -0
  188. package/src/commit/changelog/parse.ts +44 -0
  189. package/src/commit/cli.ts +85 -0
  190. package/src/commit/git/diff.ts +148 -0
  191. package/src/commit/index.ts +5 -0
  192. package/src/commit/map-reduce/index.ts +69 -0
  193. package/src/commit/map-reduce/map-phase.ts +193 -0
  194. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  195. package/src/commit/map-reduce/utils.ts +9 -0
  196. package/src/commit/message.ts +11 -0
  197. package/src/commit/model-selection.ts +92 -0
  198. package/src/commit/pipeline.ts +243 -0
  199. package/src/commit/prompts/analysis-system.md +148 -0
  200. package/src/commit/prompts/analysis-user.md +38 -0
  201. package/src/commit/prompts/changelog-system.md +50 -0
  202. package/src/commit/prompts/changelog-user.md +18 -0
  203. package/src/commit/prompts/file-observer-system.md +24 -0
  204. package/src/commit/prompts/file-observer-user.md +8 -0
  205. package/src/commit/prompts/reduce-system.md +50 -0
  206. package/src/commit/prompts/reduce-user.md +17 -0
  207. package/src/commit/prompts/summary-retry.md +3 -0
  208. package/src/commit/prompts/summary-system.md +38 -0
  209. package/src/commit/prompts/summary-user.md +13 -0
  210. package/src/commit/prompts/types-description.md +2 -0
  211. package/src/commit/shared-llm.ts +77 -0
  212. package/src/commit/types.ts +118 -0
  213. package/src/commit/utils/exclusions.ts +42 -0
  214. package/src/commit/utils.ts +58 -0
  215. package/src/config/api-key-resolver.ts +60 -0
  216. package/src/config/append-only-context-mode.ts +31 -0
  217. package/src/config/config-file.ts +317 -0
  218. package/src/config/file-lock.ts +164 -0
  219. package/src/config/keybindings.ts +628 -0
  220. package/src/config/mcp-schema.json +230 -0
  221. package/src/config/model-discovery.ts +554 -0
  222. package/src/config/model-registry.ts +2090 -0
  223. package/src/config/model-resolver.ts +1502 -0
  224. package/src/config/model-roles.ts +74 -0
  225. package/src/config/models-config-schema.ts +226 -0
  226. package/src/config/models-config.ts +129 -0
  227. package/src/config/prompt-templates.ts +185 -0
  228. package/src/config/resolve-config-value.ts +94 -0
  229. package/src/config/settings-schema.ts +3530 -0
  230. package/src/config/settings.ts +1178 -0
  231. package/src/config.ts +242 -0
  232. package/src/cursor.ts +340 -0
  233. package/src/dap/client.ts +760 -0
  234. package/src/dap/config.ts +189 -0
  235. package/src/dap/defaults.json +212 -0
  236. package/src/dap/index.ts +4 -0
  237. package/src/dap/session.ts +1441 -0
  238. package/src/dap/types.ts +610 -0
  239. package/src/debug/index.ts +515 -0
  240. package/src/debug/log-formatting.ts +58 -0
  241. package/src/debug/log-viewer.ts +908 -0
  242. package/src/debug/profiler.ts +162 -0
  243. package/src/debug/protocol-probe.ts +267 -0
  244. package/src/debug/raw-sse-buffer.ts +273 -0
  245. package/src/debug/raw-sse.ts +292 -0
  246. package/src/debug/report-bundle.ts +374 -0
  247. package/src/debug/system-info.ts +111 -0
  248. package/src/debug/terminal-info.ts +124 -0
  249. package/src/discovery/agents-md.ts +67 -0
  250. package/src/discovery/agents.ts +230 -0
  251. package/src/discovery/at-imports.ts +273 -0
  252. package/src/discovery/builtin-defaults.ts +39 -0
  253. package/src/discovery/builtin-rules/index.ts +54 -0
  254. package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
  255. package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
  256. package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
  257. package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
  258. package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
  259. package/src/discovery/builtin-rules/rs-result-type.md +19 -0
  260. package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
  261. package/src/discovery/builtin-rules/ts-import-type.md +42 -0
  262. package/src/discovery/builtin-rules/ts-no-any.md +56 -0
  263. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
  264. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
  265. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  266. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  267. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  268. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
  269. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  270. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  271. package/src/discovery/builtin.ts +906 -0
  272. package/src/discovery/claude-plugins.ts +386 -0
  273. package/src/discovery/claude.ts +584 -0
  274. package/src/discovery/cline.ts +83 -0
  275. package/src/discovery/codex.ts +522 -0
  276. package/src/discovery/cursor.ts +220 -0
  277. package/src/discovery/gemini.ts +383 -0
  278. package/src/discovery/github.ts +154 -0
  279. package/src/discovery/helpers.ts +1016 -0
  280. package/src/discovery/index.ts +81 -0
  281. package/src/discovery/mcp-json.ts +171 -0
  282. package/src/discovery/omp-extension-roots.ts +190 -0
  283. package/src/discovery/omp-plugins.ts +383 -0
  284. package/src/discovery/opencode.ts +398 -0
  285. package/src/discovery/plugin-dir-roots.ts +28 -0
  286. package/src/discovery/ssh.ts +153 -0
  287. package/src/discovery/substitute-plugin-root.ts +29 -0
  288. package/src/discovery/vscode.ts +105 -0
  289. package/src/discovery/windsurf.ts +147 -0
  290. package/src/edit/apply-patch/index.ts +87 -0
  291. package/src/edit/apply-patch/parser.ts +174 -0
  292. package/src/edit/diff.ts +999 -0
  293. package/src/edit/file-snapshot-store.ts +91 -0
  294. package/src/edit/hashline/block-resolver.ts +33 -0
  295. package/src/edit/hashline/diff.ts +290 -0
  296. package/src/edit/hashline/execute.ts +242 -0
  297. package/src/edit/hashline/filesystem.ts +130 -0
  298. package/src/edit/hashline/index.ts +5 -0
  299. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  300. package/src/edit/hashline/params.ts +18 -0
  301. package/src/edit/index.ts +571 -0
  302. package/src/edit/modes/apply-patch.lark +19 -0
  303. package/src/edit/modes/apply-patch.ts +53 -0
  304. package/src/edit/modes/patch.ts +1891 -0
  305. package/src/edit/modes/replace.ts +1137 -0
  306. package/src/edit/normalize.ts +345 -0
  307. package/src/edit/notebook.ts +242 -0
  308. package/src/edit/read-file.ts +25 -0
  309. package/src/edit/renderer.ts +769 -0
  310. package/src/edit/streaming.ts +517 -0
  311. package/src/eval/__tests__/agent-bridge.test.ts +708 -0
  312. package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
  313. package/src/eval/__tests__/budget-bridge.test.ts +69 -0
  314. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  315. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  316. package/src/eval/__tests__/idle-timeout.test.ts +80 -0
  317. package/src/eval/__tests__/js-context-manager.test.ts +241 -0
  318. package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
  319. package/src/eval/agent-bridge.ts +319 -0
  320. package/src/eval/backend.ts +71 -0
  321. package/src/eval/bridge-timeout.ts +44 -0
  322. package/src/eval/budget-bridge.ts +48 -0
  323. package/src/eval/completion-bridge.ts +207 -0
  324. package/src/eval/concurrency-bridge.ts +34 -0
  325. package/src/eval/idle-timeout.ts +91 -0
  326. package/src/eval/index.ts +4 -0
  327. package/src/eval/js/context-manager.ts +502 -0
  328. package/src/eval/js/executor.ts +173 -0
  329. package/src/eval/js/index.ts +51 -0
  330. package/src/eval/js/shared/helpers.ts +283 -0
  331. package/src/eval/js/shared/indirect-eval.ts +30 -0
  332. package/src/eval/js/shared/local-module-loader.ts +342 -0
  333. package/src/eval/js/shared/prelude.ts +2 -0
  334. package/src/eval/js/shared/prelude.txt +246 -0
  335. package/src/eval/js/shared/rewrite-imports.ts +532 -0
  336. package/src/eval/js/shared/runtime.ts +352 -0
  337. package/src/eval/js/shared/types.ts +18 -0
  338. package/src/eval/js/tool-bridge.ts +162 -0
  339. package/src/eval/js/worker-core.ts +132 -0
  340. package/src/eval/js/worker-entry.ts +30 -0
  341. package/src/eval/js/worker-protocol.ts +47 -0
  342. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  343. package/src/eval/py/display.ts +71 -0
  344. package/src/eval/py/executor.ts +742 -0
  345. package/src/eval/py/index.ts +68 -0
  346. package/src/eval/py/kernel.ts +748 -0
  347. package/src/eval/py/prelude.py +658 -0
  348. package/src/eval/py/prelude.ts +3 -0
  349. package/src/eval/py/runner.py +1133 -0
  350. package/src/eval/py/runtime.ts +276 -0
  351. package/src/eval/py/spawn-options.ts +126 -0
  352. package/src/eval/py/tool-bridge.ts +182 -0
  353. package/src/eval/session-id.ts +8 -0
  354. package/src/eval/types.ts +48 -0
  355. package/src/exa/index.ts +2 -0
  356. package/src/exa/mcp-client.ts +370 -0
  357. package/src/exa/types.ts +69 -0
  358. package/src/exec/bash-executor.ts +419 -0
  359. package/src/exec/exec.ts +53 -0
  360. package/src/exec/non-interactive-env.ts +48 -0
  361. package/src/export/custom-share.ts +65 -0
  362. package/src/export/html/index.ts +164 -0
  363. package/src/export/html/template.css +1051 -0
  364. package/src/export/html/template.generated.ts +2 -0
  365. package/src/export/html/template.html +46 -0
  366. package/src/export/html/template.js +2271 -0
  367. package/src/export/html/template.macro.ts +25 -0
  368. package/src/export/html/vendor/highlight.min.js +1213 -0
  369. package/src/export/html/vendor/marked.min.js +6 -0
  370. package/src/export/ttsr.ts +583 -0
  371. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  372. package/src/extensibility/custom-commands/bundled/review/index.ts +489 -0
  373. package/src/extensibility/custom-commands/index.ts +2 -0
  374. package/src/extensibility/custom-commands/loader.ts +238 -0
  375. package/src/extensibility/custom-commands/types.ts +113 -0
  376. package/src/extensibility/custom-tools/index.ts +7 -0
  377. package/src/extensibility/custom-tools/loader.ts +269 -0
  378. package/src/extensibility/custom-tools/types.ts +270 -0
  379. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  380. package/src/extensibility/extensions/compact-handler.ts +40 -0
  381. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  382. package/src/extensibility/extensions/index.ts +16 -0
  383. package/src/extensibility/extensions/loader.ts +572 -0
  384. package/src/extensibility/extensions/runner.ts +922 -0
  385. package/src/extensibility/extensions/types.ts +1322 -0
  386. package/src/extensibility/extensions/wrapper.ts +223 -0
  387. package/src/extensibility/hooks/index.ts +5 -0
  388. package/src/extensibility/hooks/loader.ts +257 -0
  389. package/src/extensibility/hooks/runner.ts +425 -0
  390. package/src/extensibility/hooks/tool-wrapper.ts +107 -0
  391. package/src/extensibility/hooks/types.ts +606 -0
  392. package/src/extensibility/legacy-pi-ai-shim.ts +24 -0
  393. package/src/extensibility/legacy-pi-coding-agent-shim.ts +15 -0
  394. package/src/extensibility/plugins/doctor.ts +65 -0
  395. package/src/extensibility/plugins/git-url.ts +367 -0
  396. package/src/extensibility/plugins/index.ts +9 -0
  397. package/src/extensibility/plugins/installer.ts +192 -0
  398. package/src/extensibility/plugins/legacy-pi-compat.ts +682 -0
  399. package/src/extensibility/plugins/loader.ts +313 -0
  400. package/src/extensibility/plugins/manager.ts +827 -0
  401. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  402. package/src/extensibility/plugins/marketplace/fetcher.ts +317 -0
  403. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  404. package/src/extensibility/plugins/marketplace/manager.ts +770 -0
  405. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  406. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  407. package/src/extensibility/plugins/marketplace/types.ts +191 -0
  408. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  409. package/src/extensibility/plugins/parser.ts +105 -0
  410. package/src/extensibility/plugins/types.ts +194 -0
  411. package/src/extensibility/shared-events.ts +343 -0
  412. package/src/extensibility/skills.ts +312 -0
  413. package/src/extensibility/slash-commands.ts +227 -0
  414. package/src/extensibility/tool-proxy.ts +25 -0
  415. package/src/extensibility/typebox.ts +418 -0
  416. package/src/extensibility/utils.ts +44 -0
  417. package/src/goals/index.ts +3 -0
  418. package/src/goals/runtime.ts +528 -0
  419. package/src/goals/state.ts +37 -0
  420. package/src/goals/tools/goal-tool.ts +251 -0
  421. package/src/hindsight/backend.ts +354 -0
  422. package/src/hindsight/bank.ts +156 -0
  423. package/src/hindsight/client.ts +598 -0
  424. package/src/hindsight/config.ts +175 -0
  425. package/src/hindsight/content.ts +210 -0
  426. package/src/hindsight/index.ts +8 -0
  427. package/src/hindsight/mental-models.ts +429 -0
  428. package/src/hindsight/seeds.json +32 -0
  429. package/src/hindsight/state.ts +488 -0
  430. package/src/hindsight/transcript.ts +71 -0
  431. package/src/index.ts +59 -0
  432. package/src/internal-urls/agent-protocol.ts +146 -0
  433. package/src/internal-urls/artifact-protocol.ts +107 -0
  434. package/src/internal-urls/docs-index.generated.ts +106 -0
  435. package/src/internal-urls/history-protocol.ts +113 -0
  436. package/src/internal-urls/index.ts +25 -0
  437. package/src/internal-urls/issue-pr-protocol.ts +584 -0
  438. package/src/internal-urls/json-query.ts +126 -0
  439. package/src/internal-urls/local-protocol.ts +287 -0
  440. package/src/internal-urls/mcp-protocol.ts +151 -0
  441. package/src/internal-urls/memory-protocol.ts +169 -0
  442. package/src/internal-urls/omp-protocol.ts +93 -0
  443. package/src/internal-urls/parse.ts +72 -0
  444. package/src/internal-urls/registry-helpers.ts +25 -0
  445. package/src/internal-urls/router.ts +105 -0
  446. package/src/internal-urls/rule-protocol.ts +45 -0
  447. package/src/internal-urls/skill-protocol.ts +96 -0
  448. package/src/internal-urls/types.ts +152 -0
  449. package/src/internal-urls/vault-protocol.ts +936 -0
  450. package/src/irc/bus.ts +292 -0
  451. package/src/lib/xai-http.ts +124 -0
  452. package/src/lsp/client.ts +1193 -0
  453. package/src/lsp/clients/biome-client.ts +264 -0
  454. package/src/lsp/clients/index.ts +50 -0
  455. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  456. package/src/lsp/clients/swiftlint-client.ts +120 -0
  457. package/src/lsp/config.ts +502 -0
  458. package/src/lsp/defaults.json +493 -0
  459. package/src/lsp/diagnostics-ledger.ts +51 -0
  460. package/src/lsp/edits.ts +267 -0
  461. package/src/lsp/index.ts +2477 -0
  462. package/src/lsp/lspmux.ts +233 -0
  463. package/src/lsp/render.ts +694 -0
  464. package/src/lsp/startup-events.ts +13 -0
  465. package/src/lsp/types.ts +455 -0
  466. package/src/lsp/utils.ts +718 -0
  467. package/src/main.ts +1325 -0
  468. package/src/mcp/client.ts +484 -0
  469. package/src/mcp/config-writer.ts +225 -0
  470. package/src/mcp/config.ts +365 -0
  471. package/src/mcp/index.ts +29 -0
  472. package/src/mcp/json-rpc.ts +122 -0
  473. package/src/mcp/loader.ts +124 -0
  474. package/src/mcp/manager.ts +1275 -0
  475. package/src/mcp/oauth-discovery.ts +442 -0
  476. package/src/mcp/oauth-flow.ts +442 -0
  477. package/src/mcp/render.ts +132 -0
  478. package/src/mcp/smithery-auth.ts +104 -0
  479. package/src/mcp/smithery-connect.ts +145 -0
  480. package/src/mcp/smithery-registry.ts +477 -0
  481. package/src/mcp/timeout.ts +59 -0
  482. package/src/mcp/tool-bridge.ts +426 -0
  483. package/src/mcp/tool-cache.ts +117 -0
  484. package/src/mcp/transports/http.ts +519 -0
  485. package/src/mcp/transports/index.ts +6 -0
  486. package/src/mcp/transports/stdio.ts +528 -0
  487. package/src/mcp/types.ts +423 -0
  488. package/src/memories/index.ts +1150 -0
  489. package/src/memories/storage.ts +577 -0
  490. package/src/memory-backend/index.ts +18 -0
  491. package/src/memory-backend/local-backend.ts +39 -0
  492. package/src/memory-backend/off-backend.ts +25 -0
  493. package/src/memory-backend/resolve.ts +25 -0
  494. package/src/memory-backend/runtime.ts +66 -0
  495. package/src/memory-backend/types.ts +166 -0
  496. package/src/mnemopi/backend.ts +547 -0
  497. package/src/mnemopi/config.ts +160 -0
  498. package/src/mnemopi/index.ts +3 -0
  499. package/src/mnemopi/state.ts +584 -0
  500. package/src/modes/acp/acp-agent.ts +2407 -0
  501. package/src/modes/acp/acp-client-bridge.ts +154 -0
  502. package/src/modes/acp/acp-event-mapper.ts +929 -0
  503. package/src/modes/acp/acp-mode.ts +23 -0
  504. package/src/modes/acp/index.ts +2 -0
  505. package/src/modes/acp/terminal-auth.ts +37 -0
  506. package/src/modes/components/agent-dashboard.ts +1206 -0
  507. package/src/modes/components/agent-hub.ts +1071 -0
  508. package/src/modes/components/assistant-message.ts +307 -0
  509. package/src/modes/components/bash-execution.ts +220 -0
  510. package/src/modes/components/bordered-loader.ts +41 -0
  511. package/src/modes/components/branch-summary-message.ts +45 -0
  512. package/src/modes/components/btw-panel.ts +104 -0
  513. package/src/modes/components/chat-block.ts +111 -0
  514. package/src/modes/components/compaction-summary-message.ts +87 -0
  515. package/src/modes/components/copy-selector.ts +206 -0
  516. package/src/modes/components/countdown-timer.ts +75 -0
  517. package/src/modes/components/custom-editor.ts +398 -0
  518. package/src/modes/components/custom-message.ts +63 -0
  519. package/src/modes/components/diff.ts +277 -0
  520. package/src/modes/components/dynamic-border.ts +34 -0
  521. package/src/modes/components/error-banner.ts +33 -0
  522. package/src/modes/components/eval-execution.ts +158 -0
  523. package/src/modes/components/execution-shared.ts +101 -0
  524. package/src/modes/components/extensions/extension-dashboard.ts +399 -0
  525. package/src/modes/components/extensions/extension-list.ts +502 -0
  526. package/src/modes/components/extensions/index.ts +9 -0
  527. package/src/modes/components/extensions/inspector-panel.ts +317 -0
  528. package/src/modes/components/extensions/state-manager.ts +627 -0
  529. package/src/modes/components/extensions/types.ts +186 -0
  530. package/src/modes/components/footer.ts +274 -0
  531. package/src/modes/components/history-search.ts +280 -0
  532. package/src/modes/components/hook-editor.ts +167 -0
  533. package/src/modes/components/hook-input.ts +87 -0
  534. package/src/modes/components/hook-message.ts +66 -0
  535. package/src/modes/components/hook-selector.ts +660 -0
  536. package/src/modes/components/index.ts +38 -0
  537. package/src/modes/components/keybinding-hints.ts +65 -0
  538. package/src/modes/components/late-diagnostics-message.ts +60 -0
  539. package/src/modes/components/login-dialog.ts +164 -0
  540. package/src/modes/components/mcp-add-wizard.ts +1340 -0
  541. package/src/modes/components/message-frame.ts +88 -0
  542. package/src/modes/components/model-selector.ts +1271 -0
  543. package/src/modes/components/oauth-selector.ts +368 -0
  544. package/src/modes/components/omfg-panel.ts +141 -0
  545. package/src/modes/components/overlay-box.ts +108 -0
  546. package/src/modes/components/plan-review-overlay.ts +820 -0
  547. package/src/modes/components/plan-toc.ts +138 -0
  548. package/src/modes/components/plugin-selector.ts +95 -0
  549. package/src/modes/components/plugin-settings.ts +722 -0
  550. package/src/modes/components/queue-mode-selector.ts +56 -0
  551. package/src/modes/components/read-tool-group.ts +670 -0
  552. package/src/modes/components/segment-track.ts +52 -0
  553. package/src/modes/components/session-selector.ts +625 -0
  554. package/src/modes/components/settings-defs.ts +189 -0
  555. package/src/modes/components/settings-selector.ts +651 -0
  556. package/src/modes/components/show-images-selector.ts +45 -0
  557. package/src/modes/components/skill-message.ts +89 -0
  558. package/src/modes/components/status-line/component.ts +869 -0
  559. package/src/modes/components/status-line/context-thresholds.ts +79 -0
  560. package/src/modes/components/status-line/git-utils.ts +42 -0
  561. package/src/modes/components/status-line/index.ts +5 -0
  562. package/src/modes/components/status-line/presets.ts +106 -0
  563. package/src/modes/components/status-line/segments.ts +584 -0
  564. package/src/modes/components/status-line/separators.ts +55 -0
  565. package/src/modes/components/status-line/token-rate.ts +66 -0
  566. package/src/modes/components/status-line/types.ts +108 -0
  567. package/src/modes/components/theme-selector.ts +63 -0
  568. package/src/modes/components/thinking-selector.ts +52 -0
  569. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  570. package/src/modes/components/tips.txt +19 -0
  571. package/src/modes/components/todo-reminder.ts +38 -0
  572. package/src/modes/components/tool-execution.ts +1024 -0
  573. package/src/modes/components/transcript-container.ts +608 -0
  574. package/src/modes/components/tree-selector.ts +978 -0
  575. package/src/modes/components/ttsr-notification.ts +122 -0
  576. package/src/modes/components/user-message-selector.ts +227 -0
  577. package/src/modes/components/user-message.ts +66 -0
  578. package/src/modes/components/visual-truncate.ts +63 -0
  579. package/src/modes/components/welcome.ts +493 -0
  580. package/src/modes/controllers/btw-controller.ts +105 -0
  581. package/src/modes/controllers/command-controller-shared.ts +109 -0
  582. package/src/modes/controllers/command-controller.ts +1566 -0
  583. package/src/modes/controllers/event-controller.ts +1054 -0
  584. package/src/modes/controllers/extension-ui-controller.ts +886 -0
  585. package/src/modes/controllers/input-controller.ts +1073 -0
  586. package/src/modes/controllers/mcp-command-controller.ts +2017 -0
  587. package/src/modes/controllers/omfg-controller.ts +283 -0
  588. package/src/modes/controllers/omfg-rule.ts +647 -0
  589. package/src/modes/controllers/selector-controller.ts +1108 -0
  590. package/src/modes/controllers/ssh-command-controller.ts +384 -0
  591. package/src/modes/controllers/streaming-reveal.ts +279 -0
  592. package/src/modes/controllers/tan-command-controller.ts +173 -0
  593. package/src/modes/controllers/todo-command-controller.ts +485 -0
  594. package/src/modes/data/emojis.json +1 -0
  595. package/src/modes/emoji-autocomplete.ts +285 -0
  596. package/src/modes/gradient-highlight.ts +87 -0
  597. package/src/modes/image-references.ts +117 -0
  598. package/src/modes/index.ts +17 -0
  599. package/src/modes/interactive-mode.ts +3370 -0
  600. package/src/modes/internal-url-autocomplete.ts +143 -0
  601. package/src/modes/loop-limit.ts +140 -0
  602. package/src/modes/magic-keywords.ts +20 -0
  603. package/src/modes/markdown-prose.ts +247 -0
  604. package/src/modes/oauth-manual-input.ts +69 -0
  605. package/src/modes/orchestrate.ts +42 -0
  606. package/src/modes/print-mode.ts +126 -0
  607. package/src/modes/prompt-action-autocomplete.ts +260 -0
  608. package/src/modes/rpc/host-tools.ts +186 -0
  609. package/src/modes/rpc/host-uris.ts +235 -0
  610. package/src/modes/rpc/rpc-client.ts +963 -0
  611. package/src/modes/rpc/rpc-mode.ts +947 -0
  612. package/src/modes/rpc/rpc-subagents.ts +265 -0
  613. package/src/modes/rpc/rpc-types.ts +458 -0
  614. package/src/modes/runtime-init.ts +116 -0
  615. package/src/modes/session-observer-registry.ts +146 -0
  616. package/src/modes/setup-version.ts +11 -0
  617. package/src/modes/setup-wizard/index.ts +99 -0
  618. package/src/modes/setup-wizard/lazy.ts +16 -0
  619. package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
  620. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  621. package/src/modes/setup-wizard/scenes/providers.ts +69 -0
  622. package/src/modes/setup-wizard/scenes/sign-in.ts +205 -0
  623. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  624. package/src/modes/setup-wizard/scenes/theme.ts +299 -0
  625. package/src/modes/setup-wizard/scenes/types.ts +48 -0
  626. package/src/modes/setup-wizard/scenes/web-search.ts +129 -0
  627. package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
  628. package/src/modes/shared.ts +47 -0
  629. package/src/modes/theme/dark.json +95 -0
  630. package/src/modes/theme/defaults/alabaster.json +93 -0
  631. package/src/modes/theme/defaults/amethyst.json +96 -0
  632. package/src/modes/theme/defaults/anthracite.json +93 -0
  633. package/src/modes/theme/defaults/basalt.json +91 -0
  634. package/src/modes/theme/defaults/birch.json +95 -0
  635. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  636. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  637. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  638. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  639. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  640. package/src/modes/theme/defaults/dark-copper.json +95 -0
  641. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  642. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  643. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  644. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  645. package/src/modes/theme/defaults/dark-ember.json +95 -0
  646. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  647. package/src/modes/theme/defaults/dark-forest.json +96 -0
  648. package/src/modes/theme/defaults/dark-github.json +105 -0
  649. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  650. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  651. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  652. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  653. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  654. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  655. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  656. package/src/modes/theme/defaults/dark-nord.json +97 -0
  657. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  658. package/src/modes/theme/defaults/dark-one.json +100 -0
  659. package/src/modes/theme/defaults/dark-poimandres.json +142 -0
  660. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  661. package/src/modes/theme/defaults/dark-reef.json +91 -0
  662. package/src/modes/theme/defaults/dark-retro.json +92 -0
  663. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  664. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  665. package/src/modes/theme/defaults/dark-slate.json +95 -0
  666. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  667. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  668. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  669. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  670. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  671. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  672. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  673. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  674. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  675. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  676. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  677. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  678. package/src/modes/theme/defaults/graphite.json +92 -0
  679. package/src/modes/theme/defaults/index.ts +199 -0
  680. package/src/modes/theme/defaults/light-arctic.json +107 -0
  681. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  682. package/src/modes/theme/defaults/light-canyon.json +91 -0
  683. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  684. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  685. package/src/modes/theme/defaults/light-coral.json +95 -0
  686. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  687. package/src/modes/theme/defaults/light-dawn.json +90 -0
  688. package/src/modes/theme/defaults/light-dunes.json +91 -0
  689. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  690. package/src/modes/theme/defaults/light-forest.json +100 -0
  691. package/src/modes/theme/defaults/light-frost.json +95 -0
  692. package/src/modes/theme/defaults/light-github.json +115 -0
  693. package/src/modes/theme/defaults/light-glacier.json +91 -0
  694. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  695. package/src/modes/theme/defaults/light-haze.json +90 -0
  696. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  697. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  698. package/src/modes/theme/defaults/light-lavender.json +95 -0
  699. package/src/modes/theme/defaults/light-meadow.json +91 -0
  700. package/src/modes/theme/defaults/light-mint.json +95 -0
  701. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  702. package/src/modes/theme/defaults/light-ocean.json +99 -0
  703. package/src/modes/theme/defaults/light-one.json +99 -0
  704. package/src/modes/theme/defaults/light-opal.json +91 -0
  705. package/src/modes/theme/defaults/light-orchard.json +91 -0
  706. package/src/modes/theme/defaults/light-paper.json +95 -0
  707. package/src/modes/theme/defaults/light-poimandres.json +142 -0
  708. package/src/modes/theme/defaults/light-prism.json +90 -0
  709. package/src/modes/theme/defaults/light-retro.json +98 -0
  710. package/src/modes/theme/defaults/light-sand.json +95 -0
  711. package/src/modes/theme/defaults/light-savanna.json +91 -0
  712. package/src/modes/theme/defaults/light-solarized.json +102 -0
  713. package/src/modes/theme/defaults/light-soleil.json +90 -0
  714. package/src/modes/theme/defaults/light-sunset.json +99 -0
  715. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  716. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  717. package/src/modes/theme/defaults/light-wetland.json +91 -0
  718. package/src/modes/theme/defaults/light-zenith.json +89 -0
  719. package/src/modes/theme/defaults/limestone.json +94 -0
  720. package/src/modes/theme/defaults/mahogany.json +97 -0
  721. package/src/modes/theme/defaults/marble.json +93 -0
  722. package/src/modes/theme/defaults/obsidian.json +91 -0
  723. package/src/modes/theme/defaults/onyx.json +91 -0
  724. package/src/modes/theme/defaults/pearl.json +93 -0
  725. package/src/modes/theme/defaults/porcelain.json +91 -0
  726. package/src/modes/theme/defaults/quartz.json +96 -0
  727. package/src/modes/theme/defaults/sandstone.json +95 -0
  728. package/src/modes/theme/defaults/titanium.json +90 -0
  729. package/src/modes/theme/light.json +93 -0
  730. package/src/modes/theme/mermaid-cache.ts +29 -0
  731. package/src/modes/theme/shimmer.ts +235 -0
  732. package/src/modes/theme/theme-schema.json +459 -0
  733. package/src/modes/theme/theme.ts +2676 -0
  734. package/src/modes/turn-budget.ts +31 -0
  735. package/src/modes/types.ts +359 -0
  736. package/src/modes/ultrathink.ts +41 -0
  737. package/src/modes/utils/context-usage.ts +339 -0
  738. package/src/modes/utils/copy-targets.ts +360 -0
  739. package/src/modes/utils/hotkeys-markdown.ts +61 -0
  740. package/src/modes/utils/keybinding-matchers.ts +51 -0
  741. package/src/modes/utils/tools-markdown.ts +27 -0
  742. package/src/modes/utils/ui-helpers.ts +801 -0
  743. package/src/modes/workflow.ts +42 -0
  744. package/src/plan-mode/approved-plan.ts +186 -0
  745. package/src/plan-mode/plan-handoff.ts +37 -0
  746. package/src/plan-mode/plan-protection.ts +31 -0
  747. package/src/plan-mode/state.ts +6 -0
  748. package/src/priority.json +41 -0
  749. package/src/prompts/agents/designer.md +66 -0
  750. package/src/prompts/agents/explore.md +58 -0
  751. package/src/prompts/agents/frontmatter.md +11 -0
  752. package/src/prompts/agents/init.md +33 -0
  753. package/src/prompts/agents/librarian.md +119 -0
  754. package/src/prompts/agents/oracle.md +55 -0
  755. package/src/prompts/agents/plan.md +48 -0
  756. package/src/prompts/agents/reviewer.md +140 -0
  757. package/src/prompts/agents/task.md +16 -0
  758. package/src/prompts/ci-green-request.md +36 -0
  759. package/src/prompts/dry-balance-bench.md +8 -0
  760. package/src/prompts/goals/goal-budget-limit.md +16 -0
  761. package/src/prompts/goals/goal-continuation.md +28 -0
  762. package/src/prompts/goals/goal-mode-active.md +23 -0
  763. package/src/prompts/memories/consolidation.md +30 -0
  764. package/src/prompts/memories/read-path.md +11 -0
  765. package/src/prompts/memories/stage_one_input.md +6 -0
  766. package/src/prompts/memories/stage_one_system.md +21 -0
  767. package/src/prompts/review-custom-request.md +22 -0
  768. package/src/prompts/review-headless-request.md +16 -0
  769. package/src/prompts/review-request.md +69 -0
  770. package/src/prompts/steering/user-interjection.md +10 -0
  771. package/src/prompts/system/agent-creation-architect.md +50 -0
  772. package/src/prompts/system/agent-creation-user.md +6 -0
  773. package/src/prompts/system/auto-continue.md +1 -0
  774. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  775. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  776. package/src/prompts/system/background-tan-dispatch.md +8 -0
  777. package/src/prompts/system/btw-user.md +8 -0
  778. package/src/prompts/system/commit-message-system.md +14 -0
  779. package/src/prompts/system/custom-system-prompt.md +64 -0
  780. package/src/prompts/system/eager-todo.md +13 -0
  781. package/src/prompts/system/empty-stop-retry.md +6 -0
  782. package/src/prompts/system/irc-incoming.md +7 -0
  783. package/src/prompts/system/manual-continue.md +7 -0
  784. package/src/prompts/system/memory-consolidation-system.md +8 -0
  785. package/src/prompts/system/memory-extraction-system.md +26 -0
  786. package/src/prompts/system/omfg-user.md +50 -0
  787. package/src/prompts/system/orchestrate-notice.md +40 -0
  788. package/src/prompts/system/plan-mode-active.md +109 -0
  789. package/src/prompts/system/plan-mode-approved.md +25 -0
  790. package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
  791. package/src/prompts/system/plan-mode-reference.md +11 -0
  792. package/src/prompts/system/plan-mode-subagent.md +33 -0
  793. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  794. package/src/prompts/system/project-prompt.md +52 -0
  795. package/src/prompts/system/subagent-system-prompt.md +64 -0
  796. package/src/prompts/system/subagent-user-prompt.md +3 -0
  797. package/src/prompts/system/subagent-yield-reminder.md +12 -0
  798. package/src/prompts/system/system-prompt.md +258 -0
  799. package/src/prompts/system/tiny-title-system.md +8 -0
  800. package/src/prompts/system/title-system.md +16 -0
  801. package/src/prompts/system/ttsr-interrupt.md +7 -0
  802. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  803. package/src/prompts/system/ultrathink-notice.md +3 -0
  804. package/src/prompts/system/web-search.md +25 -0
  805. package/src/prompts/system/workflow-notice.md +70 -0
  806. package/src/prompts/tools/apply-patch.md +65 -0
  807. package/src/prompts/tools/ask.md +30 -0
  808. package/src/prompts/tools/ast-edit.md +39 -0
  809. package/src/prompts/tools/ast-grep.md +42 -0
  810. package/src/prompts/tools/async-result.md +8 -0
  811. package/src/prompts/tools/bash.md +46 -0
  812. package/src/prompts/tools/browser.md +73 -0
  813. package/src/prompts/tools/checkpoint.md +16 -0
  814. package/src/prompts/tools/debug.md +34 -0
  815. package/src/prompts/tools/eval.md +92 -0
  816. package/src/prompts/tools/find.md +36 -0
  817. package/src/prompts/tools/github.md +21 -0
  818. package/src/prompts/tools/goal.md +18 -0
  819. package/src/prompts/tools/image-gen.md +7 -0
  820. package/src/prompts/tools/inspect-image-system.md +20 -0
  821. package/src/prompts/tools/inspect-image.md +32 -0
  822. package/src/prompts/tools/irc.md +59 -0
  823. package/src/prompts/tools/job.md +19 -0
  824. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  825. package/src/prompts/tools/lsp.md +42 -0
  826. package/src/prompts/tools/memory-edit.md +8 -0
  827. package/src/prompts/tools/patch.md +70 -0
  828. package/src/prompts/tools/read.md +84 -0
  829. package/src/prompts/tools/recall.md +5 -0
  830. package/src/prompts/tools/reflect.md +5 -0
  831. package/src/prompts/tools/render-mermaid.md +9 -0
  832. package/src/prompts/tools/replace.md +30 -0
  833. package/src/prompts/tools/resolve.md +9 -0
  834. package/src/prompts/tools/retain.md +6 -0
  835. package/src/prompts/tools/rewind.md +13 -0
  836. package/src/prompts/tools/search-tool-bm25.md +32 -0
  837. package/src/prompts/tools/search.md +24 -0
  838. package/src/prompts/tools/ssh.md +31 -0
  839. package/src/prompts/tools/task-summary.md +17 -0
  840. package/src/prompts/tools/task.md +88 -0
  841. package/src/prompts/tools/todo.md +62 -0
  842. package/src/prompts/tools/web-search.md +10 -0
  843. package/src/prompts/tools/write.md +14 -0
  844. package/src/registry/agent-lifecycle.ts +218 -0
  845. package/src/registry/agent-registry.ts +151 -0
  846. package/src/sdk.ts +2558 -0
  847. package/src/secrets/index.ts +123 -0
  848. package/src/secrets/obfuscator.ts +298 -0
  849. package/src/secrets/regex.ts +21 -0
  850. package/src/session/agent-session.ts +10121 -0
  851. package/src/session/agent-storage.ts +455 -0
  852. package/src/session/artifacts.ts +135 -0
  853. package/src/session/auth-broker-config.ts +131 -0
  854. package/src/session/auth-storage.ts +29 -0
  855. package/src/session/blob-store.ts +255 -0
  856. package/src/session/client-bridge.ts +85 -0
  857. package/src/session/history-storage.ts +348 -0
  858. package/src/session/indexed-session-storage.ts +430 -0
  859. package/src/session/messages.ts +541 -0
  860. package/src/session/redis-session-storage.ts +170 -0
  861. package/src/session/session-dump-format.ts +209 -0
  862. package/src/session/session-history-format.ts +246 -0
  863. package/src/session/session-manager.ts +3676 -0
  864. package/src/session/session-storage.ts +529 -0
  865. package/src/session/shake-types.ts +43 -0
  866. package/src/session/sql-session-storage.ts +314 -0
  867. package/src/session/streaming-output.ts +1330 -0
  868. package/src/session/tool-choice-queue.ts +213 -0
  869. package/src/session/yield-queue.ts +173 -0
  870. package/src/slash-commands/acp-builtins.ts +70 -0
  871. package/src/slash-commands/builtin-registry.ts +1798 -0
  872. package/src/slash-commands/helpers/context-report.ts +39 -0
  873. package/src/slash-commands/helpers/format.ts +46 -0
  874. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  875. package/src/slash-commands/helpers/mcp.ts +532 -0
  876. package/src/slash-commands/helpers/parse.ts +85 -0
  877. package/src/slash-commands/helpers/ssh.ts +195 -0
  878. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  879. package/src/slash-commands/helpers/todo.ts +279 -0
  880. package/src/slash-commands/helpers/usage-report.ts +95 -0
  881. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  882. package/src/slash-commands/types.ts +135 -0
  883. package/src/ssh/config-writer.ts +183 -0
  884. package/src/ssh/connection-manager.ts +509 -0
  885. package/src/ssh/ssh-executor.ts +189 -0
  886. package/src/ssh/sshfs-mount.ts +140 -0
  887. package/src/ssh/utils.ts +8 -0
  888. package/src/stt/downloader.ts +71 -0
  889. package/src/stt/index.ts +3 -0
  890. package/src/stt/recorder.ts +351 -0
  891. package/src/stt/setup.ts +52 -0
  892. package/src/stt/stt-controller.ts +160 -0
  893. package/src/stt/transcribe.py +70 -0
  894. package/src/stt/transcriber.ts +91 -0
  895. package/src/stubs/natives/index.ts +814 -0
  896. package/src/stubs/natives/package.json +7 -0
  897. package/src/stubs/tui/index.ts +282 -0
  898. package/src/stubs/tui/package.json +7 -0
  899. package/src/system-prompt.ts +611 -0
  900. package/src/task/agents.ts +167 -0
  901. package/src/task/commands.ts +132 -0
  902. package/src/task/discovery.ts +122 -0
  903. package/src/task/executor.ts +2133 -0
  904. package/src/task/index.ts +1419 -0
  905. package/src/task/name-generator.ts +1577 -0
  906. package/src/task/omp-command.ts +26 -0
  907. package/src/task/output-manager.ts +88 -0
  908. package/src/task/parallel.ts +116 -0
  909. package/src/task/render.ts +1381 -0
  910. package/src/task/repair-args.ts +129 -0
  911. package/src/task/subprocess-tool-registry.ts +88 -0
  912. package/src/task/types.ts +336 -0
  913. package/src/task/worktree.ts +514 -0
  914. package/src/telemetry-export.ts +144 -0
  915. package/src/thinking.ts +167 -0
  916. package/src/tiny/compiled-runtime.ts +179 -0
  917. package/src/tiny/device.ts +111 -0
  918. package/src/tiny/dtype.ts +101 -0
  919. package/src/tiny/models.ts +242 -0
  920. package/src/tiny/text.ts +165 -0
  921. package/src/tiny/title-client.ts +543 -0
  922. package/src/tiny/title-protocol.ts +56 -0
  923. package/src/tiny/worker.ts +568 -0
  924. package/src/tool-discovery/mode.ts +24 -0
  925. package/src/tool-discovery/tool-index.ts +256 -0
  926. package/src/tools/approval.ts +189 -0
  927. package/src/tools/archive-reader.ts +721 -0
  928. package/src/tools/ask.ts +928 -0
  929. package/src/tools/ast-edit.ts +642 -0
  930. package/src/tools/ast-grep.ts +452 -0
  931. package/src/tools/auto-generated-guard.ts +322 -0
  932. package/src/tools/bash-command-fixup.ts +37 -0
  933. package/src/tools/bash-interactive.ts +408 -0
  934. package/src/tools/bash-interceptor.ts +67 -0
  935. package/src/tools/bash-pty-selection.ts +14 -0
  936. package/src/tools/bash-skill-urls.ts +248 -0
  937. package/src/tools/bash.ts +1386 -0
  938. package/src/tools/browser/attach.ts +175 -0
  939. package/src/tools/browser/launch.ts +660 -0
  940. package/src/tools/browser/readable.ts +112 -0
  941. package/src/tools/browser/registry.ts +197 -0
  942. package/src/tools/browser/render.ts +216 -0
  943. package/src/tools/browser/tab-protocol.ts +105 -0
  944. package/src/tools/browser/tab-supervisor.ts +628 -0
  945. package/src/tools/browser/tab-worker-entry.ts +21 -0
  946. package/src/tools/browser/tab-worker.ts +1226 -0
  947. package/src/tools/browser.ts +343 -0
  948. package/src/tools/checkpoint.ts +136 -0
  949. package/src/tools/conflict-detect.ts +718 -0
  950. package/src/tools/context.ts +39 -0
  951. package/src/tools/debug.ts +1067 -0
  952. package/src/tools/eval-backends.ts +27 -0
  953. package/src/tools/eval-render.ts +752 -0
  954. package/src/tools/eval.ts +577 -0
  955. package/src/tools/fetch.ts +1926 -0
  956. package/src/tools/file-recorder.ts +35 -0
  957. package/src/tools/find.ts +609 -0
  958. package/src/tools/fs-cache-invalidation.ts +28 -0
  959. package/src/tools/gh-cache-invalidation.ts +255 -0
  960. package/src/tools/gh-format.ts +12 -0
  961. package/src/tools/gh-renderer.ts +481 -0
  962. package/src/tools/gh.ts +3720 -0
  963. package/src/tools/github-cache.ts +637 -0
  964. package/src/tools/grouped-file-output.ts +210 -0
  965. package/src/tools/image-gen.ts +1517 -0
  966. package/src/tools/index.ts +599 -0
  967. package/src/tools/inspect-image-renderer.ts +132 -0
  968. package/src/tools/inspect-image.ts +174 -0
  969. package/src/tools/irc.ts +723 -0
  970. package/src/tools/job.ts +557 -0
  971. package/src/tools/json-tree.ts +243 -0
  972. package/src/tools/jtd-to-json-schema.ts +219 -0
  973. package/src/tools/jtd-to-typescript.ts +136 -0
  974. package/src/tools/jtd-utils.ts +102 -0
  975. package/src/tools/list-limit.ts +40 -0
  976. package/src/tools/match-line-format.ts +20 -0
  977. package/src/tools/memory-edit.ts +59 -0
  978. package/src/tools/memory-recall.ts +100 -0
  979. package/src/tools/memory-reflect.ts +88 -0
  980. package/src/tools/memory-render.ts +202 -0
  981. package/src/tools/memory-retain.ts +91 -0
  982. package/src/tools/output-meta.ts +754 -0
  983. package/src/tools/output-schema-validator.ts +132 -0
  984. package/src/tools/path-utils.ts +1054 -0
  985. package/src/tools/plan-mode-guard.ts +108 -0
  986. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  987. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  988. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  989. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  990. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  991. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  992. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  993. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  994. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  995. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  996. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  997. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  998. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  999. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  1000. package/src/tools/read.ts +2929 -0
  1001. package/src/tools/render-mermaid.ts +69 -0
  1002. package/src/tools/render-utils.ts +838 -0
  1003. package/src/tools/renderers.ts +77 -0
  1004. package/src/tools/report-tool-issue.ts +534 -0
  1005. package/src/tools/resolve.ts +276 -0
  1006. package/src/tools/review.ts +253 -0
  1007. package/src/tools/search-tool-bm25.ts +351 -0
  1008. package/src/tools/search.ts +1580 -0
  1009. package/src/tools/sqlite-reader.ts +828 -0
  1010. package/src/tools/ssh.ts +349 -0
  1011. package/src/tools/todo.ts +982 -0
  1012. package/src/tools/tool-errors.ts +62 -0
  1013. package/src/tools/tool-result.ts +94 -0
  1014. package/src/tools/tool-timeouts.ts +30 -0
  1015. package/src/tools/tts.ts +133 -0
  1016. package/src/tools/write.ts +1217 -0
  1017. package/src/tools/yield.ts +269 -0
  1018. package/src/tui/code-cell.ts +216 -0
  1019. package/src/tui/file-list.ts +55 -0
  1020. package/src/tui/hyperlink.ts +175 -0
  1021. package/src/tui/index.ts +12 -0
  1022. package/src/tui/output-block.ts +240 -0
  1023. package/src/tui/status-line.ts +54 -0
  1024. package/src/tui/tree-list.ts +84 -0
  1025. package/src/tui/types.ts +15 -0
  1026. package/src/tui/utils.ts +103 -0
  1027. package/src/utils/block-context.ts +312 -0
  1028. package/src/utils/changelog.ts +132 -0
  1029. package/src/utils/clipboard.ts +193 -0
  1030. package/src/utils/command-args.ts +76 -0
  1031. package/src/utils/commit-message-generator.ts +151 -0
  1032. package/src/utils/edit-mode.ts +41 -0
  1033. package/src/utils/enhanced-paste.ts +230 -0
  1034. package/src/utils/event-bus.ts +33 -0
  1035. package/src/utils/external-editor.ts +65 -0
  1036. package/src/utils/file-display-mode.ts +45 -0
  1037. package/src/utils/file-mentions.ts +281 -0
  1038. package/src/utils/git.ts +1833 -0
  1039. package/src/utils/image-loading.ts +132 -0
  1040. package/src/utils/image-resize.ts +309 -0
  1041. package/src/utils/jj.ts +248 -0
  1042. package/src/utils/lang-from-path.ts +239 -0
  1043. package/src/utils/markit.ts +89 -0
  1044. package/src/utils/open.ts +55 -0
  1045. package/src/utils/session-color.ts +68 -0
  1046. package/src/utils/shell-snapshot.ts +187 -0
  1047. package/src/utils/sixel.ts +69 -0
  1048. package/src/utils/title-generator.ts +373 -0
  1049. package/src/utils/tool-choice.ts +33 -0
  1050. package/src/utils/tools-manager.ts +363 -0
  1051. package/src/web/kagi.ts +305 -0
  1052. package/src/web/parallel.ts +353 -0
  1053. package/src/web/scrapers/artifacthub.ts +207 -0
  1054. package/src/web/scrapers/arxiv.ts +83 -0
  1055. package/src/web/scrapers/aur.ts +162 -0
  1056. package/src/web/scrapers/biorxiv.ts +133 -0
  1057. package/src/web/scrapers/bluesky.ts +262 -0
  1058. package/src/web/scrapers/brew.ts +172 -0
  1059. package/src/web/scrapers/cheatsh.ts +68 -0
  1060. package/src/web/scrapers/chocolatey.ts +196 -0
  1061. package/src/web/scrapers/choosealicense.ts +95 -0
  1062. package/src/web/scrapers/cisa-kev.ts +87 -0
  1063. package/src/web/scrapers/clojars.ts +154 -0
  1064. package/src/web/scrapers/coingecko.ts +177 -0
  1065. package/src/web/scrapers/crates-io.ts +97 -0
  1066. package/src/web/scrapers/crossref.ts +136 -0
  1067. package/src/web/scrapers/devto.ts +147 -0
  1068. package/src/web/scrapers/discogs.ts +306 -0
  1069. package/src/web/scrapers/discourse.ts +197 -0
  1070. package/src/web/scrapers/dockerhub.ts +138 -0
  1071. package/src/web/scrapers/docs-rs.ts +653 -0
  1072. package/src/web/scrapers/fdroid.ts +134 -0
  1073. package/src/web/scrapers/firefox-addons.ts +191 -0
  1074. package/src/web/scrapers/flathub.ts +223 -0
  1075. package/src/web/scrapers/github-gist.ts +58 -0
  1076. package/src/web/scrapers/github.ts +704 -0
  1077. package/src/web/scrapers/gitlab.ts +401 -0
  1078. package/src/web/scrapers/go-pkg.ts +266 -0
  1079. package/src/web/scrapers/hackage.ts +140 -0
  1080. package/src/web/scrapers/hackernews.ts +189 -0
  1081. package/src/web/scrapers/hex.ts +105 -0
  1082. package/src/web/scrapers/huggingface.ts +321 -0
  1083. package/src/web/scrapers/iacr.ts +89 -0
  1084. package/src/web/scrapers/index.ts +252 -0
  1085. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1086. package/src/web/scrapers/lemmy.ts +203 -0
  1087. package/src/web/scrapers/lobsters.ts +175 -0
  1088. package/src/web/scrapers/mastodon.ts +292 -0
  1089. package/src/web/scrapers/maven.ts +138 -0
  1090. package/src/web/scrapers/mdn.ts +173 -0
  1091. package/src/web/scrapers/metacpan.ts +222 -0
  1092. package/src/web/scrapers/musicbrainz.ts +250 -0
  1093. package/src/web/scrapers/npm.ts +98 -0
  1094. package/src/web/scrapers/nuget.ts +183 -0
  1095. package/src/web/scrapers/nvd.ts +222 -0
  1096. package/src/web/scrapers/ollama.ts +239 -0
  1097. package/src/web/scrapers/open-vsx.ts +106 -0
  1098. package/src/web/scrapers/opencorporates.ts +292 -0
  1099. package/src/web/scrapers/openlibrary.ts +336 -0
  1100. package/src/web/scrapers/orcid.ts +286 -0
  1101. package/src/web/scrapers/osv.ts +176 -0
  1102. package/src/web/scrapers/packagist.ts +160 -0
  1103. package/src/web/scrapers/pub-dev.ts +143 -0
  1104. package/src/web/scrapers/pubmed.ts +211 -0
  1105. package/src/web/scrapers/pypi.ts +112 -0
  1106. package/src/web/scrapers/rawg.ts +110 -0
  1107. package/src/web/scrapers/readthedocs.ts +120 -0
  1108. package/src/web/scrapers/reddit.ts +95 -0
  1109. package/src/web/scrapers/repology.ts +251 -0
  1110. package/src/web/scrapers/rfc.ts +201 -0
  1111. package/src/web/scrapers/rubygems.ts +103 -0
  1112. package/src/web/scrapers/searchcode.ts +189 -0
  1113. package/src/web/scrapers/sec-edgar.ts +261 -0
  1114. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1115. package/src/web/scrapers/snapcraft.ts +187 -0
  1116. package/src/web/scrapers/sourcegraph.ts +336 -0
  1117. package/src/web/scrapers/spdx.ts +108 -0
  1118. package/src/web/scrapers/spotify.ts +198 -0
  1119. package/src/web/scrapers/stackoverflow.ts +120 -0
  1120. package/src/web/scrapers/terraform.ts +277 -0
  1121. package/src/web/scrapers/tldr.ts +47 -0
  1122. package/src/web/scrapers/twitter.ts +94 -0
  1123. package/src/web/scrapers/types.ts +397 -0
  1124. package/src/web/scrapers/utils.ts +109 -0
  1125. package/src/web/scrapers/vimeo.ts +133 -0
  1126. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1127. package/src/web/scrapers/w3c.ts +156 -0
  1128. package/src/web/scrapers/wikidata.ts +344 -0
  1129. package/src/web/scrapers/wikipedia.ts +84 -0
  1130. package/src/web/scrapers/youtube.ts +325 -0
  1131. package/src/web/search/index.ts +292 -0
  1132. package/src/web/search/provider.ts +157 -0
  1133. package/src/web/search/providers/anthropic.ts +318 -0
  1134. package/src/web/search/providers/base.ts +89 -0
  1135. package/src/web/search/providers/brave.ts +152 -0
  1136. package/src/web/search/providers/codex.ts +591 -0
  1137. package/src/web/search/providers/exa.ts +400 -0
  1138. package/src/web/search/providers/gemini.ts +460 -0
  1139. package/src/web/search/providers/jina.ts +111 -0
  1140. package/src/web/search/providers/kagi.ts +86 -0
  1141. package/src/web/search/providers/kimi.ts +196 -0
  1142. package/src/web/search/providers/parallel.ts +225 -0
  1143. package/src/web/search/providers/perplexity.ts +730 -0
  1144. package/src/web/search/providers/searxng.ts +313 -0
  1145. package/src/web/search/providers/synthetic.ts +114 -0
  1146. package/src/web/search/providers/tavily.ts +176 -0
  1147. package/src/web/search/providers/utils.ts +128 -0
  1148. package/src/web/search/providers/zai.ts +333 -0
  1149. package/src/web/search/render.ts +262 -0
  1150. package/src/web/search/types.ts +482 -0
  1151. package/src/web/search/utils.ts +17 -0
  1152. package/src/workspace-tree.ts +286 -0
@@ -0,0 +1,1133 @@
1
+ """OMP Python runner — subprocess wrapper used by the coding-agent host.
2
+
3
+ NDJSON protocol over stdin/stdout. Host writes one JSON object per line;
4
+ wrapper writes typed frames back.
5
+
6
+ Host -> wrapper:
7
+ {"id": str, "code": str, "silent": bool?, "storeHistory": bool?}
8
+ {"id": str, "code": str, "silent": bool?, "storeHistory": bool?, "cwd": str?, "env": dict?}
9
+ {"type": "exit"} # graceful shutdown
10
+
11
+ Wrapper -> host:
12
+ {"type": "started", "id": ...}
13
+ {"type": "stdout", "id": ..., "data": str}
14
+ {"type": "stderr", "id": ..., "data": str}
15
+ {"type": "display", "id": ..., "bundle": {<mime>: <value>}}
16
+ {"type": "result", "id": ..., "bundle": {<mime>: <value>}}
17
+ {"type": "error", "id": ..., "ename": str, "evalue": str, "traceback": [str]}
18
+ {"type": "done", "id": ..., "status": "ok"|"error",
19
+ "executionCount": int, "cancelled": bool}
20
+
21
+ The runner is intentionally self-contained: no third-party imports, no IPython.
22
+ Magics are translated by a small line-scanner before AST parsing; rich display
23
+ falls back through `_repr_*_` methods so pandas/PIL/plotly etc. still render
24
+ when installed.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import asyncio
30
+ import ast
31
+ import contextvars
32
+ import base64
33
+ import builtins
34
+ import inspect
35
+ import io
36
+ import json
37
+ import os
38
+ import re
39
+ import runpy
40
+ import shlex
41
+ import signal
42
+ import subprocess
43
+ import sys
44
+ import threading
45
+ import time
46
+ import traceback
47
+ from pathlib import Path
48
+ from typing import Any
49
+
50
+ # ---------------------------------------------------------------------------
51
+ # Frame writer
52
+ # ---------------------------------------------------------------------------
53
+
54
+ # Frames travel on a private dup of the original stdout. fd 1 itself is then
55
+ # repointed at a capture pipe: child processes spawned by user code without
56
+ # stdout=PIPE inherit fd 1, and their output is forwarded to the host as
57
+ # regular stdout frames by a drain thread instead of being written raw into
58
+ # the NDJSON channel (where it would be dropped as invalid JSON — or worse,
59
+ # spoof a frame). The wire protocol is unchanged: the host still reads NDJSON
60
+ # frames from the subprocess stdout.
61
+ _RAW_STDERR = sys.__stderr__
62
+ try:
63
+ _FRAME_FD = os.dup(sys.__stdout__.fileno())
64
+ _RAW_STDOUT = os.fdopen(_FRAME_FD, "w", encoding="utf-8", errors="backslashreplace")
65
+ _CAPTURE_READ_FD, _capture_write_fd = os.pipe()
66
+ os.dup2(_capture_write_fd, sys.__stdout__.fileno())
67
+ os.close(_capture_write_fd)
68
+ except (AttributeError, OSError, ValueError, io.UnsupportedOperation):
69
+ _RAW_STDOUT = sys.__stdout__
70
+ _CAPTURE_READ_FD = None
71
+ _OUT_LOCK = threading.Lock()
72
+
73
+
74
+ def _json_default(o: Any) -> Any:
75
+ try:
76
+ return repr(o)
77
+ except Exception:
78
+ return f"<unrepr {type(o).__name__}>"
79
+
80
+
81
+ def _emit(frame: dict) -> None:
82
+ """Serialize a frame and write it to the host as a single NDJSON line."""
83
+ line = json.dumps(frame, ensure_ascii=False, default=_json_default)
84
+ with _OUT_LOCK:
85
+ _RAW_STDOUT.write(line)
86
+ _RAW_STDOUT.write("\n")
87
+ _RAW_STDOUT.flush()
88
+
89
+
90
+ # ---------------------------------------------------------------------------
91
+ # User stdout/stderr proxies
92
+ # ---------------------------------------------------------------------------
93
+
94
+
95
+ class _StreamProxy(io.TextIOBase):
96
+ """Emit ``write()`` data as typed frames tied to the current request.
97
+
98
+ Writes are coalesced per request: a frame is emitted once the buffer holds
99
+ a complete line (everything up to the last newline goes out together) or
100
+ grows past ``_MAX_BUFFER`` bytes, so the common ``print()`` pair of
101
+ ``write(text)`` + ``write("\\n")`` costs one frame instead of two. Partial
102
+ lines are bounded by ``flush()`` and the end-of-request flush.
103
+ """
104
+
105
+ _MAX_BUFFER = 8192
106
+
107
+ def __init__(self, kind: str) -> None:
108
+ super().__init__()
109
+ self._kind = kind
110
+ self._lock = threading.Lock()
111
+ self._buffers: dict[str, str] = {}
112
+
113
+ def writable(self) -> bool: # noqa: D401 - protocol method
114
+ return True
115
+
116
+ def isatty(self) -> bool: # noqa: D401 - protocol method
117
+ return False
118
+
119
+ def write(self, data: Any) -> int: # type: ignore[override]
120
+ if not isinstance(data, str):
121
+ data = str(data)
122
+ if not data:
123
+ return 0
124
+ rid = _CURRENT_RID.get()
125
+ if rid is None:
126
+ _RAW_STDERR.write(data)
127
+ _RAW_STDERR.flush()
128
+ return len(data)
129
+ emit_text = None
130
+ with self._lock:
131
+ buf = self._buffers.pop(rid, "") + data
132
+ if len(buf) >= self._MAX_BUFFER:
133
+ emit_text = buf
134
+ else:
135
+ nl = buf.rfind("\n")
136
+ if nl >= 0:
137
+ emit_text = buf[: nl + 1]
138
+ rest = buf[nl + 1 :]
139
+ if rest:
140
+ self._buffers[rid] = rest
141
+ else:
142
+ self._buffers[rid] = buf
143
+ if emit_text:
144
+ _emit({"type": self._kind, "id": rid, "data": emit_text})
145
+ return len(data)
146
+
147
+ def flush(self) -> None: # noqa: D401 - protocol method
148
+ rid = _CURRENT_RID.get()
149
+ if rid is not None:
150
+ self.flush_rid(rid)
151
+ return None
152
+
153
+ def flush_rid(self, rid: str) -> None:
154
+ """Flush any buffered partial line for ``rid`` as its own frame."""
155
+ with self._lock:
156
+ buf = self._buffers.pop(rid, None)
157
+ if buf:
158
+ _emit({"type": self._kind, "id": rid, "data": buf})
159
+
160
+
161
+ def _flush_stream_proxies(rid: str) -> None:
162
+ """Drain buffered proxy output for ``rid`` (called before its done frame)."""
163
+ for stream in (sys.stdout, sys.stderr):
164
+ if isinstance(stream, _StreamProxy):
165
+ stream.flush_rid(rid)
166
+
167
+
168
+ # ---------------------------------------------------------------------------
169
+ # Runner state
170
+ # ---------------------------------------------------------------------------
171
+
172
+
173
+ class _RunnerState:
174
+ def __init__(self) -> None:
175
+ self.execution_count: int = 0
176
+ self.cancel_requested: bool = False
177
+ # User globals — kept across requests when running in session mode.
178
+ self.user_ns: dict[str, Any] = {
179
+ "__name__": "__main__",
180
+ "__doc__": None,
181
+ "__builtins__": builtins,
182
+ }
183
+ self.last_install_marker: int = 0
184
+ self.loop: asyncio.AbstractEventLoop | None = None
185
+ self.active_executions: int = 0
186
+ # Best-effort attribution target for captured fd-1 bytes (child
187
+ # processes inheriting stdout). With overlapping requests the most
188
+ # recently started one wins — strictly better than dropping the bytes.
189
+ self.capture_rid: str | None = None
190
+
191
+
192
+ _CURRENT_RID: contextvars.ContextVar[str | None] = contextvars.ContextVar("omp_current_rid", default=None)
193
+
194
+ _STATE = _RunnerState()
195
+
196
+
197
+ def _drain_captured_stdout() -> None:
198
+ """Forward bytes written to the captured fd 1 as stdout frames.
199
+
200
+ Runs on a daemon thread for the life of the process. Child processes that
201
+ inherit fd 1 (any ``subprocess`` call without ``stdout=PIPE``) land here.
202
+ """
203
+ if _CAPTURE_READ_FD is None:
204
+ return
205
+ import codecs
206
+
207
+ decoder = codecs.getincrementaldecoder("utf-8")("replace")
208
+ while True:
209
+ try:
210
+ chunk = os.read(_CAPTURE_READ_FD, 65536)
211
+ except OSError:
212
+ return
213
+ if not chunk:
214
+ return
215
+ text = decoder.decode(chunk)
216
+ if not text:
217
+ continue
218
+ rid = _STATE.capture_rid
219
+ if rid is None:
220
+ _RAW_STDERR.write(text)
221
+ _RAW_STDERR.flush()
222
+ else:
223
+ _emit({"type": "stdout", "id": rid, "data": text})
224
+
225
+
226
+ def _start_capture_drain() -> None:
227
+ if _CAPTURE_READ_FD is None:
228
+ return
229
+ thread = threading.Thread(target=_drain_captured_stdout, name="omp-fd1-capture", daemon=True)
230
+ thread.start()
231
+
232
+
233
+ # ---------------------------------------------------------------------------
234
+ # Magic source transformer
235
+ # ---------------------------------------------------------------------------
236
+
237
+
238
+ _MAGIC_LINE_RE = re.compile(r"^(?P<indent>[ \t]*)(?P<name>[A-Za-z_][A-Za-z_0-9]*)(?:[ \t]+(?P<args>.*))?$")
239
+ _ASSIGN_LINE_RE = re.compile(
240
+ r"^(?P<indent>[ \t]*)(?P<lhs>[A-Za-z_][A-Za-z_0-9.\[\], ]*?)\s*=\s*(?P<rhs>.+)$"
241
+ )
242
+
243
+
244
+ def _fold_continuations(lines: list[str], start: int) -> tuple[str, int]:
245
+ """Fold trailing backslash continuations starting at ``start``. Returns
246
+ ``(folded_text, lines_consumed)``."""
247
+ parts: list[str] = []
248
+ i = start
249
+ while i < len(lines):
250
+ line = lines[i]
251
+ if line.endswith("\\"):
252
+ parts.append(line[:-1])
253
+ i += 1
254
+ continue
255
+ parts.append(line)
256
+ i += 1
257
+ break
258
+ return ("".join(parts), i - start)
259
+
260
+
261
+ def _quote_arg(text: str) -> str:
262
+ """Return a Python string literal that round-trips ``text`` exactly."""
263
+ return json.dumps(text, ensure_ascii=False)
264
+
265
+
266
+ def transform_cell(source: str) -> str:
267
+ """Translate IPython-style magics + shell escapes into plain Python.
268
+
269
+ Rules
270
+ -----
271
+ * ``%name args`` -> ``__omp_magic("name", "args")``
272
+ * ``var = %name args`` -> ``var = __omp_magic("name", "args")``
273
+ * ``!cmd`` -> ``__omp_shell("cmd")``
274
+ * ``var = !cmd`` -> ``var = __omp_shell("cmd")``
275
+ * ``%%name args\\n<body>`` -> ``__omp_magic_cell("name", "args", "<body>")``
276
+ (cell magic must be the first non-whitespace token of a top-level line and
277
+ consumes the remainder of the cell)
278
+
279
+ Lines inside strings or comments are left alone — we operate on the raw
280
+ text before parsing, but the scanner only fires on the first token of each
281
+ physical line and never touches the body of triple-quoted strings because
282
+ those bodies are never first tokens themselves.
283
+ """
284
+
285
+ if "%" not in source and "!" not in source:
286
+ return source
287
+
288
+ lines = source.splitlines()
289
+ out: list[str] = []
290
+ i = 0
291
+ while i < len(lines):
292
+ line = lines[i]
293
+ stripped = line.lstrip()
294
+ indent = line[: len(line) - len(stripped)]
295
+
296
+ # Cell magic — consumes from here to EOF.
297
+ if stripped.startswith("%%"):
298
+ head, _ = _split_magic_head(stripped[2:])
299
+ name, args = head
300
+ body_lines = lines[i + 1 :]
301
+ body = "\n".join(body_lines)
302
+ out.append(
303
+ f"{indent}__omp_magic_cell({_quote_arg(name)}, {_quote_arg(args)}, {_quote_arg(body)})"
304
+ )
305
+ return "\n".join(out)
306
+
307
+ # Line magic / shell at start of line.
308
+ if stripped.startswith("%") and not stripped.startswith("%%"):
309
+ folded, consumed = _fold_continuations(lines, i)
310
+ stripped_folded = folded.lstrip()
311
+ indent = folded[: len(folded) - len(stripped_folded)]
312
+ head, _ = _split_magic_head(stripped_folded[1:])
313
+ name, args = head
314
+ out.append(f"{indent}__omp_magic({_quote_arg(name)}, {_quote_arg(args)})")
315
+ i += consumed
316
+ continue
317
+
318
+ if stripped.startswith("!"):
319
+ folded, consumed = _fold_continuations(lines, i)
320
+ stripped_folded = folded.lstrip()
321
+ indent = folded[: len(folded) - len(stripped_folded)]
322
+ cmd = stripped_folded[1:].strip()
323
+ out.append(f"{indent}__omp_shell({_quote_arg(cmd)})")
324
+ i += consumed
325
+ continue
326
+
327
+ # Assignment forms: var = %magic / var = !cmd
328
+ m = _ASSIGN_LINE_RE.match(line)
329
+ if m:
330
+ rhs = m.group("rhs").strip()
331
+ if rhs.startswith("!"):
332
+ cmd = rhs[1:].strip()
333
+ out.append(f"{m.group('indent')}{m.group('lhs').rstrip()} = __omp_shell({_quote_arg(cmd)})")
334
+ i += 1
335
+ continue
336
+ if rhs.startswith("%") and not rhs.startswith("%%"):
337
+ head, _ = _split_magic_head(rhs[1:])
338
+ name, args = head
339
+ out.append(
340
+ f"{m.group('indent')}{m.group('lhs').rstrip()} = __omp_magic({_quote_arg(name)}, {_quote_arg(args)})"
341
+ )
342
+ i += 1
343
+ continue
344
+
345
+ out.append(line)
346
+ i += 1
347
+
348
+ return "\n".join(out)
349
+
350
+
351
+ def _split_magic_head(text: str) -> tuple[tuple[str, str], str]:
352
+ """Split ``"name rest"`` into ``("name", "rest")``."""
353
+ text = text.lstrip()
354
+ if not text:
355
+ return ("", ""), ""
356
+ m = re.match(r"([A-Za-z_][A-Za-z_0-9]*)(?:\s+(.*))?$", text)
357
+ if not m:
358
+ return ("", text), ""
359
+ return (m.group(1), (m.group(2) or "").rstrip()), ""
360
+
361
+
362
+ # ---------------------------------------------------------------------------
363
+ # Magic registry
364
+ # ---------------------------------------------------------------------------
365
+
366
+
367
+ _LINE_MAGICS: dict[str, Callable[[str], Any]] = {}
368
+ _CELL_MAGICS: dict[str, Callable[[str, str], Any]] = {}
369
+
370
+
371
+ def line_magic(name: str) -> Callable[[Callable[[str], Any]], Callable[[str], Any]]:
372
+ def decorator(fn: Callable[[str], Any]) -> Callable[[str], Any]:
373
+ _LINE_MAGICS[name] = fn
374
+ return fn
375
+
376
+ return decorator
377
+
378
+
379
+ def cell_magic(name: str) -> Callable[[Callable[[str, str], Any]], Callable[[str, str], Any]]:
380
+ def decorator(fn: Callable[[str, str], Any]) -> Callable[[str, str], Any]:
381
+ _CELL_MAGICS[name] = fn
382
+ return fn
383
+
384
+ return decorator
385
+
386
+
387
+ def _emit_status(op: str, **data: Any) -> None:
388
+ bundle = {"application/x-omp-status": {"op": op, **data}}
389
+ rid = _CURRENT_RID.get()
390
+ if rid is None:
391
+ return
392
+ _emit({"type": "display", "id": rid, "bundle": bundle})
393
+
394
+
395
+ @line_magic("pip")
396
+ def _magic_pip(args: str) -> None:
397
+ argv = shlex.split(args) if args else ["--help"]
398
+ cmd = [sys.executable, "-m", "pip", *argv]
399
+ proc = subprocess.Popen(
400
+ cmd,
401
+ stdout=subprocess.PIPE,
402
+ stderr=subprocess.STDOUT,
403
+ text=True,
404
+ bufsize=1,
405
+ )
406
+ installed_packages: list[str] = []
407
+ assert proc.stdout is not None
408
+ for raw_line in proc.stdout:
409
+ sys.stdout.write(raw_line)
410
+ m = re.search(r"Successfully installed\s+(.+)$", raw_line)
411
+ if m:
412
+ for token in m.group(1).split():
413
+ # Token is name-version; drop the version suffix.
414
+ pkg = token.rsplit("-", 1)[0]
415
+ installed_packages.append(pkg.replace("_", "-"))
416
+ proc.wait()
417
+ if installed_packages:
418
+ import importlib
419
+
420
+ importlib.invalidate_caches()
421
+ prefixes = {pkg.lower().replace("-", "_") for pkg in installed_packages}
422
+ for mod_name in list(sys.modules):
423
+ head = mod_name.split(".", 1)[0].lower()
424
+ if head in prefixes:
425
+ sys.modules.pop(mod_name, None)
426
+ _emit_status("pip", args=args, installed=installed_packages, exit_code=proc.returncode)
427
+
428
+
429
+ @line_magic("cd")
430
+ def _magic_cd(args: str) -> str:
431
+ path = os.path.expanduser(args.strip()) or os.path.expanduser("~")
432
+ os.chdir(path)
433
+ cwd = os.getcwd()
434
+ _emit_status("cd", path=cwd)
435
+ return cwd
436
+
437
+
438
+ @line_magic("pwd")
439
+ def _magic_pwd(_args: str) -> str:
440
+ cwd = os.getcwd()
441
+ _emit_status("pwd", path=cwd)
442
+ return cwd
443
+
444
+
445
+ @line_magic("ls")
446
+ def _magic_ls(args: str) -> list[str]:
447
+ target = os.path.expanduser(args.strip()) or "."
448
+ entries = sorted(os.listdir(target))
449
+ _emit_status("ls", path=os.path.abspath(target), count=len(entries))
450
+ return entries
451
+
452
+
453
+ @line_magic("env")
454
+ def _magic_env(args: str) -> Any:
455
+ args = args.strip()
456
+ if not args:
457
+ return dict(sorted(os.environ.items()))
458
+ if "=" in args:
459
+ key, value = args.split("=", 1)
460
+ os.environ[key.strip()] = value.strip()
461
+ return value.strip()
462
+ return os.environ.get(args)
463
+
464
+
465
+ @line_magic("set_env")
466
+ def _magic_set_env(args: str) -> str:
467
+ parts = args.split(None, 1)
468
+ if len(parts) != 2:
469
+ raise ValueError("Usage: %set_env KEY VALUE")
470
+ key, value = parts
471
+ os.environ[key] = value
472
+ return value
473
+
474
+
475
+ @line_magic("time")
476
+ def _magic_time(args: str) -> Any:
477
+ start = time.perf_counter()
478
+ result = eval(args, _STATE.user_ns)
479
+ elapsed = time.perf_counter() - start
480
+ sys.stdout.write(f"Wall time: {elapsed * 1000:.2f} ms\n")
481
+ _emit_status("time", elapsed_ms=round(elapsed * 1000, 3))
482
+ return result
483
+
484
+
485
+ @line_magic("timeit")
486
+ def _magic_timeit(args: str) -> None:
487
+ import timeit as _timeit
488
+
489
+ timer = _timeit.Timer(stmt=args, globals=_STATE.user_ns)
490
+ iters, total = timer.autorange()
491
+ per = total / iters
492
+ sys.stdout.write(f"{iters} loops, best of 1: {per * 1e6:.2f} us per loop\n")
493
+ _emit_status("timeit", loops=iters, total_ms=round(total * 1000, 3))
494
+
495
+
496
+ @line_magic("who")
497
+ def _magic_who(_args: str) -> list[str]:
498
+ names = sorted(
499
+ name
500
+ for name, value in _STATE.user_ns.items()
501
+ if not name.startswith("_") and not callable(value) or hasattr(value, "__class__")
502
+ )
503
+ return [n for n in names if not n.startswith("__")]
504
+
505
+
506
+ @line_magic("whos")
507
+ def _magic_whos(_args: str) -> list[tuple[str, str]]:
508
+ rows = []
509
+ for name in sorted(_STATE.user_ns):
510
+ if name.startswith("__"):
511
+ continue
512
+ value = _STATE.user_ns[name]
513
+ rows.append((name, type(value).__name__))
514
+ return rows
515
+
516
+
517
+ @line_magic("reset")
518
+ def _magic_reset(_args: str) -> None:
519
+ _STATE.user_ns.clear()
520
+ _STATE.user_ns.update({"__name__": "__main__", "__doc__": None, "__builtins__": builtins})
521
+ _install_builtins(_STATE.user_ns)
522
+ _emit_status("reset")
523
+
524
+
525
+ @line_magic("load")
526
+ def _magic_load(args: str) -> None:
527
+ path = Path(os.path.expanduser(args.strip()))
528
+ source = path.read_text(encoding="utf-8")
529
+ _emit({"type": "display", "id": _CURRENT_RID.get(), "bundle": {"text/plain": source}})
530
+ _exec_source(source, _STATE.user_ns)
531
+
532
+
533
+ @line_magic("run")
534
+ def _magic_run(args: str) -> None:
535
+ parts = shlex.split(args) if args else []
536
+ if not parts:
537
+ raise ValueError("Usage: %run <path>")
538
+ target = os.path.expanduser(parts[0])
539
+ saved_argv = sys.argv
540
+ try:
541
+ sys.argv = [target, *parts[1:]]
542
+ result_ns = runpy.run_path(target, run_name="__main__")
543
+ finally:
544
+ sys.argv = saved_argv
545
+ for name, value in result_ns.items():
546
+ if name.startswith("__"):
547
+ continue
548
+ _STATE.user_ns[name] = value
549
+
550
+
551
+ @cell_magic("bash")
552
+ def _magic_cell_bash(args: str, body: str) -> int:
553
+ return _run_shell_body(body, shell_arg="/bin/bash")
554
+
555
+
556
+ @cell_magic("sh")
557
+ def _magic_cell_sh(args: str, body: str) -> int:
558
+ return _run_shell_body(body, shell_arg="/bin/sh")
559
+
560
+
561
+ @cell_magic("capture")
562
+ def _magic_cell_capture(args: str, body: str) -> str:
563
+ """Capture stdout/stderr of body; bind to ``args`` (a name) if provided."""
564
+ captured = io.StringIO()
565
+ saved_stdout, saved_stderr = sys.stdout, sys.stderr
566
+ sys.stdout = sys.stderr = captured
567
+ try:
568
+ _exec_source(body, _STATE.user_ns)
569
+ finally:
570
+ sys.stdout, sys.stderr = saved_stdout, saved_stderr
571
+ text = captured.getvalue()
572
+ name = args.strip()
573
+ if name:
574
+ _STATE.user_ns[name] = text
575
+ return text
576
+
577
+
578
+ @cell_magic("timeit")
579
+ def _magic_cell_timeit(args: str, body: str) -> None:
580
+ import timeit as _timeit
581
+
582
+ timer = _timeit.Timer(stmt=body, globals=_STATE.user_ns)
583
+ iters, total = timer.autorange()
584
+ per = total / iters
585
+ sys.stdout.write(f"{iters} loops, best of 1: {per * 1e6:.2f} us per loop\n")
586
+ _emit_status("timeit", loops=iters, total_ms=round(total * 1000, 3))
587
+
588
+
589
+ @cell_magic("writefile")
590
+ def _magic_cell_writefile(args: str, body: str) -> str:
591
+ path = Path(os.path.expanduser(args.strip()))
592
+ path.parent.mkdir(parents=True, exist_ok=True)
593
+ path.write_text(body, encoding="utf-8")
594
+ _emit_status("writefile", path=str(path), bytes=len(body))
595
+ return str(path)
596
+
597
+
598
+ def _run_shell_body(body: str, *, shell_arg: str) -> int:
599
+ proc = subprocess.Popen(
600
+ [shell_arg, "-c", body],
601
+ stdout=subprocess.PIPE,
602
+ stderr=subprocess.STDOUT,
603
+ text=True,
604
+ bufsize=1,
605
+ )
606
+ assert proc.stdout is not None
607
+ for raw_line in proc.stdout:
608
+ sys.stdout.write(raw_line)
609
+ proc.wait()
610
+ return proc.returncode
611
+
612
+
613
+ def __omp_magic(name: str, args: str) -> Any:
614
+ fn = _LINE_MAGICS.get(name)
615
+ if fn is None:
616
+ raise NameError(f"UsageError: Line magic function '%{name}' not found.")
617
+ return fn(args)
618
+
619
+
620
+ def __omp_magic_cell(name: str, args: str, body: str) -> Any:
621
+ fn = _CELL_MAGICS.get(name)
622
+ if fn is None:
623
+ raise NameError(f"UsageError: Cell magic function '%%{name}' not found.")
624
+ return fn(args, body)
625
+
626
+
627
+ class _ShellResult(list):
628
+ """Result of ``!cmd`` — list of stripped output lines."""
629
+
630
+ def __init__(self, lines: list[str], returncode: int) -> None:
631
+ super().__init__(lines)
632
+ self.returncode = returncode
633
+
634
+ @property
635
+ def n(self) -> str: # IPython compat
636
+ return "\n".join(self)
637
+
638
+ @property
639
+ def s(self) -> str: # IPython compat
640
+ return " ".join(self)
641
+
642
+
643
+ def __omp_shell(cmd: str) -> _ShellResult:
644
+ proc = subprocess.run(
645
+ cmd,
646
+ shell=True,
647
+ stdout=subprocess.PIPE,
648
+ stderr=subprocess.STDOUT,
649
+ text=True,
650
+ )
651
+ if proc.stdout:
652
+ sys.stdout.write(proc.stdout)
653
+ lines = [line for line in (proc.stdout or "").splitlines()]
654
+ return _ShellResult(lines, proc.returncode)
655
+
656
+
657
+ # ---------------------------------------------------------------------------
658
+ # Display dispatch
659
+ # ---------------------------------------------------------------------------
660
+
661
+
662
+ _REPR_MIMES = [
663
+ ("_repr_html_", "text/html"),
664
+ ("_repr_markdown_", "text/markdown"),
665
+ ("_repr_svg_", "image/svg+xml"),
666
+ ("_repr_png_", "image/png"),
667
+ ("_repr_jpeg_", "image/jpeg"),
668
+ ("_repr_json_", "application/json"),
669
+ ("_repr_latex_", "text/latex"),
670
+ ]
671
+
672
+
673
+ def _coerce_image_bytes(value: Any) -> str:
674
+ if isinstance(value, (bytes, bytearray)):
675
+ return base64.b64encode(bytes(value)).decode("ascii")
676
+ if isinstance(value, str):
677
+ return value
678
+ return base64.b64encode(repr(value).encode("utf-8")).decode("ascii")
679
+
680
+
681
+ def _mime_bundle(value: Any) -> dict:
682
+ """Build a Jupyter-style MIME bundle for ``value``.
683
+
684
+ Honors ``_repr_mimebundle_`` first, falls back to individual ``_repr_*_``
685
+ accessors, and always provides ``text/plain``.
686
+ """
687
+ bundle: dict[str, Any] = {}
688
+
689
+ mimebundle = getattr(value, "_repr_mimebundle_", None)
690
+ if callable(mimebundle):
691
+ try:
692
+ data = mimebundle()
693
+ except Exception:
694
+ data = None
695
+ if isinstance(data, tuple):
696
+ data = data[0]
697
+ if isinstance(data, dict):
698
+ bundle.update({str(k): v for k, v in data.items()})
699
+
700
+ for attr, mime in _REPR_MIMES:
701
+ if mime in bundle:
702
+ continue
703
+ repr_fn = getattr(value, attr, None)
704
+ if not callable(repr_fn):
705
+ continue
706
+ try:
707
+ data = repr_fn()
708
+ except Exception:
709
+ continue
710
+ if data is None:
711
+ continue
712
+ if mime in ("image/png", "image/jpeg"):
713
+ bundle[mime] = _coerce_image_bytes(data)
714
+ else:
715
+ bundle[mime] = data
716
+
717
+ if "text/plain" not in bundle:
718
+ try:
719
+ bundle["text/plain"] = repr(value)
720
+ except Exception:
721
+ bundle["text/plain"] = f"<unrepr {type(value).__name__}>"
722
+
723
+ return bundle
724
+
725
+
726
+ def _emit_display(bundle: dict, *, kind: str = "display") -> None:
727
+ rid = _CURRENT_RID.get()
728
+ if rid is None:
729
+ return
730
+ _emit({"type": kind, "id": rid, "bundle": bundle})
731
+
732
+
733
+ def __omp_display(value: Any, *, raw: bool = False, kind: str = "display") -> None:
734
+ if raw:
735
+ if not isinstance(value, dict):
736
+ raise TypeError("display(..., raw=True) requires a MIME bundle dict")
737
+ bundle = {str(k): v for k, v in value.items()}
738
+ if "text/plain" not in bundle:
739
+ bundle["text/plain"] = ""
740
+ _emit_display(bundle, kind=kind)
741
+ return
742
+ _emit_display(_mime_bundle(value), kind=kind)
743
+
744
+
745
+ # ---------------------------------------------------------------------------
746
+ # Matplotlib post-cell flush
747
+ # ---------------------------------------------------------------------------
748
+
749
+
750
+ def _flush_matplotlib_figures() -> None:
751
+ plt = sys.modules.get("matplotlib.pyplot")
752
+ if plt is None:
753
+ return
754
+ try:
755
+ fignums = list(plt.get_fignums())
756
+ except Exception:
757
+ return
758
+ for num in fignums:
759
+ try:
760
+ fig = plt.figure(num)
761
+ buf = io.BytesIO()
762
+ fig.savefig(buf, format="png", bbox_inches="tight")
763
+ data = base64.b64encode(buf.getvalue()).decode("ascii")
764
+ _emit_display({"image/png": data, "text/plain": f"<Figure {num}>"})
765
+ plt.close(fig)
766
+ except Exception:
767
+ continue
768
+
769
+
770
+ # Force a non-interactive backend before user code imports matplotlib. Set as
771
+ # environ default so the user can still override it explicitly.
772
+ os.environ.setdefault("MPLBACKEND", "Agg")
773
+
774
+
775
+ # ---------------------------------------------------------------------------
776
+ # Builtin injection
777
+ # ---------------------------------------------------------------------------
778
+
779
+
780
+ def _install_builtins(ns: dict) -> None:
781
+ ns["display"] = __omp_display
782
+ ns["__omp_display"] = __omp_display
783
+ ns["__omp_magic"] = __omp_magic
784
+ ns["__omp_magic_cell"] = __omp_magic_cell
785
+ ns["__omp_shell"] = __omp_shell
786
+ ns["__omp_current_run_id__"] = lambda: _CURRENT_RID.get()
787
+
788
+
789
+ _install_builtins(_STATE.user_ns)
790
+
791
+
792
+ # ---------------------------------------------------------------------------
793
+ # Source execution (split last expression for rich display)
794
+ # ---------------------------------------------------------------------------
795
+
796
+
797
+ _TLA_FLAG = getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x2000)
798
+
799
+
800
+ def _await_sync(coro) -> Any:
801
+ try:
802
+ running_loop = asyncio.get_running_loop()
803
+ except RuntimeError:
804
+ running_loop = None
805
+ if running_loop is not None and running_loop.is_running():
806
+ raise RuntimeError("top-level await is not supported from synchronous magic execution")
807
+ return asyncio.run(coro)
808
+
809
+
810
+ def _run_compiled_sync(code, ns: dict, *, want_value: bool) -> Any:
811
+ """Synchronous execution path used by nested magic helpers."""
812
+ if code.co_flags & inspect.CO_COROUTINE:
813
+ result = _await_sync(eval(code, ns))
814
+ return result if want_value else None
815
+ if want_value:
816
+ return eval(code, ns)
817
+ exec(code, ns)
818
+ return None
819
+
820
+
821
+
822
+ async def _run_compiled_async(code, ns: dict, *, want_value: bool) -> Any:
823
+ """Execute a code object in the persistent event loop.
824
+
825
+ Coroutine code is awaited in this task so top-level ``await`` interleaves
826
+ with sibling requests. Plain statement/expression code runs on the main
827
+ runner thread so SIGINT can interrupt it reliably.
828
+ """
829
+ if code.co_flags & inspect.CO_COROUTINE:
830
+ result = await eval(code, ns)
831
+ return result if want_value else None
832
+ if want_value:
833
+ return eval(code, ns)
834
+ exec(code, ns)
835
+ return None
836
+
837
+
838
+ def _compile_source(source: str) -> tuple[Any, Any | None, bool]:
839
+ module = ast.parse(source, mode="exec")
840
+ if not module.body:
841
+ return None, None, False
842
+
843
+ last = module.body[-1]
844
+ if isinstance(last, ast.Expr):
845
+ body_module = ast.Module(body=module.body[:-1], type_ignores=[])
846
+ expr_module = ast.Expression(body=last.value)
847
+ ast.copy_location(expr_module, last)
848
+ body_code = compile(body_module, "<cell>", "exec", flags=_TLA_FLAG)
849
+ expr_code = compile(expr_module, "<cell>", "eval", flags=_TLA_FLAG)
850
+ return body_code, expr_code, True
851
+
852
+ return compile(module, "<cell>", "exec", flags=_TLA_FLAG), None, False
853
+
854
+
855
+ def _exec_source(source: str, ns: dict) -> None:
856
+ """Synchronous source execution for legacy magic helpers."""
857
+ body_code, expr_code, has_expr = _compile_source(source)
858
+ if body_code is None:
859
+ return
860
+ _run_compiled_sync(body_code, ns, want_value=False)
861
+ if has_expr and expr_code is not None:
862
+ value = _run_compiled_sync(expr_code, ns, want_value=True)
863
+ if value is not None:
864
+ __omp_display(value, kind="result")
865
+
866
+
867
+ async def _exec_source_async(source: str, ns: dict) -> None:
868
+ """Compile + execute ``source``; if the last node is an expression, route
869
+ its value through ``__omp_display`` so dataframes/figures render rich.
870
+ Top-level ``await`` / ``async for`` / ``async with`` is permitted; awaited
871
+ regions yield to other requests in the runner's persistent event loop."""
872
+ body_code, expr_code, has_expr = _compile_source(source)
873
+ if body_code is None:
874
+ return
875
+ await _run_compiled_async(body_code, ns, want_value=False)
876
+ if has_expr and expr_code is not None:
877
+ value = await _run_compiled_async(expr_code, ns, want_value=True)
878
+ if value is not None:
879
+ __omp_display(value, kind="result")
880
+
881
+
882
+ # ---------------------------------------------------------------------------
883
+ # Signal handling
884
+ # ---------------------------------------------------------------------------
885
+
886
+
887
+ def _install_idle_sigint() -> None:
888
+ try:
889
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
890
+ except (OSError, ValueError):
891
+ # Some platforms (Windows in non-console mode) reject this; fine.
892
+ pass
893
+
894
+
895
+ def _install_exec_sigint() -> None:
896
+ try:
897
+ signal.signal(signal.SIGINT, signal.default_int_handler)
898
+ except (OSError, ValueError):
899
+ pass
900
+
901
+
902
+ def _begin_exec_sigint() -> None:
903
+ _STATE.active_executions += 1
904
+ _install_exec_sigint()
905
+
906
+
907
+ def _end_exec_sigint() -> None:
908
+ if _STATE.active_executions > 0:
909
+ _STATE.active_executions -= 1
910
+ if _STATE.active_executions == 0:
911
+ _install_idle_sigint()
912
+
913
+
914
+ _MANAGED_ENV_KEYS = (
915
+ "PI_SESSION_FILE",
916
+ "PI_ARTIFACTS_DIR",
917
+ "PI_TOOL_BRIDGE_URL",
918
+ "PI_TOOL_BRIDGE_TOKEN",
919
+ "PI_TOOL_BRIDGE_SESSION",
920
+ "PI_EVAL_LOCAL_ROOTS",
921
+ )
922
+
923
+
924
+ def _apply_request_runtime(req: dict) -> None:
925
+ cwd = req.get("cwd")
926
+ if isinstance(cwd, str) and cwd:
927
+ os.chdir(cwd)
928
+ try:
929
+ sys.path.remove(cwd)
930
+ except ValueError:
931
+ pass
932
+ sys.path.insert(0, cwd)
933
+
934
+ env = req.get("env")
935
+ if isinstance(env, dict):
936
+ for key in _MANAGED_ENV_KEYS:
937
+ value = env.get(key)
938
+ if isinstance(value, str):
939
+ os.environ[key] = value
940
+ elif value is None:
941
+ os.environ.pop(key, None)
942
+
943
+ def _start_parent_watchdog() -> None:
944
+ """Self-terminate when the host process dies.
945
+
946
+ The main loop only exits when stdin EOFs, which only happens once user
947
+ code finishes and the next ``readline`` call returns. If the host gets
948
+ SIGKILL mid-execution (or any way that skips graceful shutdown) the
949
+ runner would otherwise outlive its parent and keep holding kernel
950
+ state. Poll ``os.getppid()`` instead and ``os._exit`` the moment we get
951
+ reparented \u2014 covers POSIX hosts. Windows has no reliable ppid
952
+ equivalent; there we still bail out on the next stdin read.
953
+ """
954
+ if os.name != "posix":
955
+ return
956
+ original_ppid = os.getppid()
957
+ if original_ppid <= 1:
958
+ return
959
+
960
+ def watch() -> None:
961
+ while True:
962
+ try:
963
+ if os.getppid() != original_ppid:
964
+ os._exit(0)
965
+ except Exception:
966
+ return
967
+ time.sleep(10)
968
+
969
+ thread = threading.Thread(target=watch, name="omp-parent-watchdog", daemon=True)
970
+ thread.start()
971
+
972
+
973
+ # ---------------------------------------------------------------------------
974
+ # Request dispatch
975
+ # ---------------------------------------------------------------------------
976
+
977
+
978
+ async def _handle_request_async(req: dict) -> None:
979
+ rid = str(req.get("id"))
980
+ token = _CURRENT_RID.set(rid)
981
+ _STATE.capture_rid = rid
982
+ _STATE.user_ns["__omp_run_id__"] = rid
983
+ _STATE.cancel_requested = False
984
+ _STATE.execution_count += 1
985
+ execution_count = _STATE.execution_count
986
+ _emit({"type": "started", "id": rid})
987
+
988
+ status: str = "ok"
989
+ cancelled = False
990
+
991
+ try:
992
+ try:
993
+ _apply_request_runtime(req)
994
+ transformed = transform_cell(req.get("code", ""))
995
+ except SyntaxError as exc:
996
+ _emit_error(rid, exc)
997
+ _emit({
998
+ "type": "done",
999
+ "id": rid,
1000
+ "status": "error",
1001
+ "executionCount": execution_count,
1002
+ "cancelled": False,
1003
+ })
1004
+ return
1005
+ except BaseException as exc: # noqa: BLE001 - runtime setup errors must settle the request
1006
+ _emit_error(rid, exc)
1007
+ _emit({
1008
+ "type": "done",
1009
+ "id": rid,
1010
+ "status": "error",
1011
+ "executionCount": execution_count,
1012
+ "cancelled": False,
1013
+ })
1014
+ return
1015
+
1016
+ _begin_exec_sigint()
1017
+ try:
1018
+ await _exec_source_async(transformed, _STATE.user_ns)
1019
+ except KeyboardInterrupt:
1020
+ cancelled = True
1021
+ status = "error"
1022
+ _emit_error(rid, KeyboardInterrupt("Execution interrupted"))
1023
+ except SystemExit as exc:
1024
+ status = "error"
1025
+ _emit_error(rid, exc)
1026
+ except BaseException as exc: # noqa: BLE001 - we want to surface every user error
1027
+ status = "error"
1028
+ _emit_error(rid, exc)
1029
+ finally:
1030
+ _end_exec_sigint()
1031
+ try:
1032
+ _flush_matplotlib_figures()
1033
+ except Exception:
1034
+ pass
1035
+
1036
+ _flush_stream_proxies(rid)
1037
+ _emit({
1038
+ "type": "done",
1039
+ "id": rid,
1040
+ "status": status,
1041
+ "executionCount": execution_count,
1042
+ "cancelled": cancelled,
1043
+ })
1044
+ finally:
1045
+ if _STATE.capture_rid == rid:
1046
+ _STATE.capture_rid = None
1047
+ _flush_stream_proxies(rid)
1048
+ _CURRENT_RID.reset(token)
1049
+
1050
+
1051
+ def _emit_error(rid: str, exc: BaseException) -> None:
1052
+ tb_lines = traceback.format_exception(type(exc), exc, exc.__traceback__)
1053
+ _emit({
1054
+ "type": "error",
1055
+ "id": rid,
1056
+ "ename": type(exc).__name__,
1057
+ "evalue": str(exc),
1058
+ "traceback": [line.rstrip("\n") for line in tb_lines],
1059
+ })
1060
+
1061
+
1062
+ # ---------------------------------------------------------------------------
1063
+ # Main loop
1064
+ # ---------------------------------------------------------------------------
1065
+
1066
+
1067
+ def _read_stdin(loop: asyncio.AbstractEventLoop, queue: asyncio.Queue, stdin) -> None:
1068
+ for raw_line in stdin:
1069
+ line = raw_line.strip()
1070
+ if not line:
1071
+ continue
1072
+ try:
1073
+ req = json.loads(line)
1074
+ except json.JSONDecodeError as exc:
1075
+ _emit({
1076
+ "type": "error",
1077
+ "id": "",
1078
+ "ename": "ProtocolError",
1079
+ "evalue": f"Invalid JSON request: {exc}",
1080
+ "traceback": [],
1081
+ })
1082
+ continue
1083
+ loop.call_soon_threadsafe(queue.put_nowait, req)
1084
+ loop.call_soon_threadsafe(queue.put_nowait, {"type": "exit"})
1085
+
1086
+
1087
+ async def _main_async() -> None:
1088
+ sys.stdout = _StreamProxy("stdout")
1089
+ sys.stderr = _StreamProxy("stderr")
1090
+ _install_idle_sigint()
1091
+ _start_parent_watchdog()
1092
+ _start_capture_drain()
1093
+
1094
+ stdin = sys.__stdin__
1095
+ if stdin is None:
1096
+ return
1097
+
1098
+ loop = asyncio.get_running_loop()
1099
+ _STATE.loop = loop
1100
+ queue: asyncio.Queue = asyncio.Queue()
1101
+ reader = threading.Thread(target=_read_stdin, args=(loop, queue, stdin), name="omp-stdin-reader", daemon=True)
1102
+ reader.start()
1103
+
1104
+ tasks: set[asyncio.Task] = set()
1105
+ def _task_done(task: asyncio.Task) -> None:
1106
+ tasks.discard(task)
1107
+ try:
1108
+ exc = task.exception()
1109
+ except asyncio.CancelledError:
1110
+ return
1111
+ if exc is not None:
1112
+ _emit_error("", exc)
1113
+ try:
1114
+ while True:
1115
+ req = await queue.get()
1116
+ if req.get("type") == "exit":
1117
+ break
1118
+ task = asyncio.create_task(_handle_request_async(req))
1119
+ tasks.add(task)
1120
+ task.add_done_callback(_task_done)
1121
+ finally:
1122
+ for task in tasks:
1123
+ task.cancel()
1124
+ if tasks:
1125
+ await asyncio.gather(*tasks, return_exceptions=True)
1126
+
1127
+
1128
+ def main() -> None:
1129
+ asyncio.run(_main_async())
1130
+
1131
+
1132
+ if __name__ == "__main__":
1133
+ main()