@f5-sales-demo/xcsh 19.51.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (899) hide show
  1. package/CHANGELOG.md +7073 -0
  2. package/README.md +14 -0
  3. package/examples/README.md +21 -0
  4. package/examples/custom-tools/README.md +109 -0
  5. package/examples/custom-tools/hello/index.ts +20 -0
  6. package/examples/custom-tools/todo/index.ts +206 -0
  7. package/examples/extensions/README.md +143 -0
  8. package/examples/extensions/api-demo.ts +89 -0
  9. package/examples/extensions/chalk-logger.ts +25 -0
  10. package/examples/extensions/hello.ts +32 -0
  11. package/examples/extensions/pirate.ts +43 -0
  12. package/examples/extensions/plan-mode.ts +551 -0
  13. package/examples/extensions/reload-runtime.ts +37 -0
  14. package/examples/extensions/todo.ts +296 -0
  15. package/examples/extensions/tools.ts +145 -0
  16. package/examples/extensions/with-deps/index.ts +36 -0
  17. package/examples/extensions/with-deps/package-lock.json +31 -0
  18. package/examples/extensions/with-deps/package.json +16 -0
  19. package/examples/hooks/README.md +56 -0
  20. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  21. package/examples/hooks/confirm-destructive.ts +58 -0
  22. package/examples/hooks/custom-compaction.ts +115 -0
  23. package/examples/hooks/dirty-repo-guard.ts +51 -0
  24. package/examples/hooks/file-trigger.ts +40 -0
  25. package/examples/hooks/git-checkpoint.ts +52 -0
  26. package/examples/hooks/handoff.ts +149 -0
  27. package/examples/hooks/permission-gate.ts +33 -0
  28. package/examples/hooks/protected-paths.ts +29 -0
  29. package/examples/hooks/qna.ts +118 -0
  30. package/examples/hooks/status-line.ts +39 -0
  31. package/examples/sdk/01-minimal.ts +21 -0
  32. package/examples/sdk/02-custom-model.ts +49 -0
  33. package/examples/sdk/03-custom-prompt.ts +43 -0
  34. package/examples/sdk/04-skills.ts +43 -0
  35. package/examples/sdk/06-extensions.ts +80 -0
  36. package/examples/sdk/06-hooks.ts +61 -0
  37. package/examples/sdk/07-context-files.ts +35 -0
  38. package/examples/sdk/08-prompt-templates.ts +41 -0
  39. package/examples/sdk/08-slash-commands.ts +46 -0
  40. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  41. package/examples/sdk/11-sessions.ts +47 -0
  42. package/examples/sdk/README.md +172 -0
  43. package/package.json +539 -0
  44. package/scripts/build-info/resolvers.ts +51 -0
  45. package/scripts/capture-ax-fixture.ts +84 -0
  46. package/scripts/capture-login-fixture.ts +30 -0
  47. package/scripts/check-workflow-field-coverage.ts +101 -0
  48. package/scripts/extension-uat-harness.ts +340 -0
  49. package/scripts/format-prompts.ts +68 -0
  50. package/scripts/generate-api-spec-index.ts +580 -0
  51. package/scripts/generate-branding-index.ts +81 -0
  52. package/scripts/generate-build-info.ts +106 -0
  53. package/scripts/generate-console-catalog.ts +88 -0
  54. package/scripts/generate-console-field-metadata.ts +74 -0
  55. package/scripts/generate-docs-index.ts +40 -0
  56. package/scripts/generate-template.ts +32 -0
  57. package/scripts/generate-terraform-index.ts +81 -0
  58. package/scripts/mermaid-gallery.ts +132 -0
  59. package/scripts/uat-matrix-modalities.ts +451 -0
  60. package/scripts/uat-matrix-report.ts +175 -0
  61. package/scripts/uat-matrix.ts +353 -0
  62. package/src/async/index.ts +2 -0
  63. package/src/async/job-manager.ts +416 -0
  64. package/src/async/support.ts +5 -0
  65. package/src/autoresearch/apply-contract-to-state.ts +1 -0
  66. package/src/autoresearch/command-resume.md +17 -0
  67. package/src/autoresearch/contract.ts +205 -0
  68. package/src/autoresearch/dashboard.ts +374 -0
  69. package/src/autoresearch/git.ts +191 -0
  70. package/src/autoresearch/helpers.ts +328 -0
  71. package/src/autoresearch/index.ts +402 -0
  72. package/src/autoresearch/prompt.md +236 -0
  73. package/src/autoresearch/resume-message.md +16 -0
  74. package/src/autoresearch/state.ts +303 -0
  75. package/src/autoresearch/tools/init-experiment.ts +400 -0
  76. package/src/autoresearch/tools/log-experiment.ts +793 -0
  77. package/src/autoresearch/tools/run-experiment.ts +679 -0
  78. package/src/autoresearch/types.ts +114 -0
  79. package/src/browser/acquire.ts +249 -0
  80. package/src/browser/actions.ts +126 -0
  81. package/src/browser/auth.ts +176 -0
  82. package/src/browser/ax.ts +134 -0
  83. package/src/browser/cdp-core.ts +45 -0
  84. package/src/browser/cdp-page-actions.ts +51 -0
  85. package/src/browser/chrome-locate.ts +66 -0
  86. package/src/browser/dom-context.ts +89 -0
  87. package/src/browser/dt-context.ts +100 -0
  88. package/src/browser/extension-bridge.ts +182 -0
  89. package/src/browser/extension-page-actions.ts +397 -0
  90. package/src/browser/extension-provider.ts +373 -0
  91. package/src/browser/index.ts +17 -0
  92. package/src/browser/input-commit.ts +74 -0
  93. package/src/browser/native-messaging.ts +20 -0
  94. package/src/browser/page-actions.ts +18 -0
  95. package/src/browser/provider.ts +155 -0
  96. package/src/browser/resolver.ts +126 -0
  97. package/src/browser/selector.ts +40 -0
  98. package/src/bun-imports.d.ts +22 -0
  99. package/src/capability/context-file.ts +43 -0
  100. package/src/capability/extension-module.ts +34 -0
  101. package/src/capability/extension.ts +47 -0
  102. package/src/capability/fs.ts +107 -0
  103. package/src/capability/hook.ts +40 -0
  104. package/src/capability/index.ts +438 -0
  105. package/src/capability/instruction.ts +37 -0
  106. package/src/capability/mcp.ts +74 -0
  107. package/src/capability/prompt.ts +35 -0
  108. package/src/capability/rule.ts +224 -0
  109. package/src/capability/settings.ts +34 -0
  110. package/src/capability/skill.ts +50 -0
  111. package/src/capability/slash-command.ts +40 -0
  112. package/src/capability/ssh.ts +41 -0
  113. package/src/capability/system-prompt.ts +34 -0
  114. package/src/capability/tool.ts +38 -0
  115. package/src/capability/types.ts +168 -0
  116. package/src/cli/agents-cli.ts +138 -0
  117. package/src/cli/args.ts +286 -0
  118. package/src/cli/chrome-cli.ts +88 -0
  119. package/src/cli/classify-install-target.ts +50 -0
  120. package/src/cli/commands/init-xdg.ts +27 -0
  121. package/src/cli/config-cli.ts +418 -0
  122. package/src/cli/file-processor.ts +121 -0
  123. package/src/cli/grep-cli.ts +160 -0
  124. package/src/cli/grievances-cli.ts +78 -0
  125. package/src/cli/initial-message.ts +58 -0
  126. package/src/cli/jupyter-cli.ts +106 -0
  127. package/src/cli/list-models.ts +128 -0
  128. package/src/cli/plugin-cli.ts +964 -0
  129. package/src/cli/read-cli.ts +68 -0
  130. package/src/cli/session-picker.ts +52 -0
  131. package/src/cli/setup-cli.ts +479 -0
  132. package/src/cli/shell-cli.ts +174 -0
  133. package/src/cli/ssh-cli.ts +179 -0
  134. package/src/cli/stats-cli.ts +182 -0
  135. package/src/cli/update-cli.ts +446 -0
  136. package/src/cli/web-search-cli.ts +203 -0
  137. package/src/cli.ts +123 -0
  138. package/src/commands/agents.ts +57 -0
  139. package/src/commands/chrome-host.ts +71 -0
  140. package/src/commands/chrome.ts +28 -0
  141. package/src/commands/commit.ts +36 -0
  142. package/src/commands/config.ts +51 -0
  143. package/src/commands/grep.ts +48 -0
  144. package/src/commands/grievances.ts +20 -0
  145. package/src/commands/jupyter.ts +32 -0
  146. package/src/commands/launch.ts +144 -0
  147. package/src/commands/plugin.ts +78 -0
  148. package/src/commands/read.ts +33 -0
  149. package/src/commands/setup.ts +42 -0
  150. package/src/commands/shell.ts +29 -0
  151. package/src/commands/ssh.ts +60 -0
  152. package/src/commands/stats.ts +29 -0
  153. package/src/commands/update.ts +21 -0
  154. package/src/commands/web-search.ts +46 -0
  155. package/src/commit/agentic/agent.ts +314 -0
  156. package/src/commit/agentic/fallback.ts +96 -0
  157. package/src/commit/agentic/index.ts +354 -0
  158. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  159. package/src/commit/agentic/prompts/session-user.md +25 -0
  160. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  161. package/src/commit/agentic/prompts/system.md +38 -0
  162. package/src/commit/agentic/state.ts +60 -0
  163. package/src/commit/agentic/tools/analyze-file.ts +127 -0
  164. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  165. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  166. package/src/commit/agentic/tools/git-overview.ts +81 -0
  167. package/src/commit/agentic/tools/index.ts +54 -0
  168. package/src/commit/agentic/tools/propose-changelog.ts +139 -0
  169. package/src/commit/agentic/tools/propose-commit.ts +122 -0
  170. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  171. package/src/commit/agentic/tools/schemas.ts +31 -0
  172. package/src/commit/agentic/tools/split-commit.ts +251 -0
  173. package/src/commit/agentic/topo-sort.ts +44 -0
  174. package/src/commit/agentic/trivial.ts +51 -0
  175. package/src/commit/agentic/validation.ts +183 -0
  176. package/src/commit/analysis/conventional.ts +122 -0
  177. package/src/commit/analysis/index.ts +4 -0
  178. package/src/commit/analysis/scope.ts +242 -0
  179. package/src/commit/analysis/summary.ts +105 -0
  180. package/src/commit/analysis/validation.ts +66 -0
  181. package/src/commit/changelog/detect.ts +40 -0
  182. package/src/commit/changelog/generate.ts +101 -0
  183. package/src/commit/changelog/index.ts +234 -0
  184. package/src/commit/changelog/parse.ts +44 -0
  185. package/src/commit/cli.ts +85 -0
  186. package/src/commit/git/diff.ts +148 -0
  187. package/src/commit/index.ts +5 -0
  188. package/src/commit/map-reduce/index.ts +69 -0
  189. package/src/commit/map-reduce/map-phase.ts +193 -0
  190. package/src/commit/map-reduce/reduce-phase.ts +108 -0
  191. package/src/commit/map-reduce/utils.ts +9 -0
  192. package/src/commit/message.ts +11 -0
  193. package/src/commit/model-selection.ts +66 -0
  194. package/src/commit/pipeline.ts +242 -0
  195. package/src/commit/prompts/analysis-system.md +148 -0
  196. package/src/commit/prompts/analysis-user.md +38 -0
  197. package/src/commit/prompts/changelog-system.md +50 -0
  198. package/src/commit/prompts/changelog-user.md +18 -0
  199. package/src/commit/prompts/file-observer-system.md +24 -0
  200. package/src/commit/prompts/file-observer-user.md +8 -0
  201. package/src/commit/prompts/reduce-system.md +50 -0
  202. package/src/commit/prompts/reduce-user.md +17 -0
  203. package/src/commit/prompts/summary-retry.md +3 -0
  204. package/src/commit/prompts/summary-system.md +38 -0
  205. package/src/commit/prompts/summary-user.md +13 -0
  206. package/src/commit/prompts/types-description.md +2 -0
  207. package/src/commit/types.ts +118 -0
  208. package/src/commit/utils/exclusions.ts +42 -0
  209. package/src/commit/utils.ts +44 -0
  210. package/src/config/auto-config.ts +698 -0
  211. package/src/config/context-schema.json +115 -0
  212. package/src/config/file-lock.ts +121 -0
  213. package/src/config/keybindings.ts +493 -0
  214. package/src/config/mcp-schema.json +230 -0
  215. package/src/config/model-equivalence.ts +675 -0
  216. package/src/config/model-registry.ts +2265 -0
  217. package/src/config/model-resolver.ts +1289 -0
  218. package/src/config/prompt-templates.ts +271 -0
  219. package/src/config/resolve-config-value.ts +110 -0
  220. package/src/config/settings-schema.ts +2155 -0
  221. package/src/config/settings.ts +730 -0
  222. package/src/config.ts +418 -0
  223. package/src/cursor.ts +323 -0
  224. package/src/dap/client.ts +674 -0
  225. package/src/dap/config.ts +150 -0
  226. package/src/dap/defaults.json +211 -0
  227. package/src/dap/index.ts +4 -0
  228. package/src/dap/session.ts +1255 -0
  229. package/src/dap/types.ts +600 -0
  230. package/src/debug/index.ts +440 -0
  231. package/src/debug/log-formatting.ts +58 -0
  232. package/src/debug/log-viewer.ts +908 -0
  233. package/src/debug/profiler.ts +158 -0
  234. package/src/debug/report-bundle.ts +365 -0
  235. package/src/debug/system-info.ts +107 -0
  236. package/src/discovery/agents-md.ts +67 -0
  237. package/src/discovery/agents.ts +219 -0
  238. package/src/discovery/builtin.ts +851 -0
  239. package/src/discovery/claude-plugins.ts +297 -0
  240. package/src/discovery/claude.ts +543 -0
  241. package/src/discovery/cline.ts +83 -0
  242. package/src/discovery/codex.ts +535 -0
  243. package/src/discovery/cursor.ts +220 -0
  244. package/src/discovery/gemini.ts +396 -0
  245. package/src/discovery/github.ts +118 -0
  246. package/src/discovery/helpers.ts +934 -0
  247. package/src/discovery/index.ts +79 -0
  248. package/src/discovery/language.ts +46 -0
  249. package/src/discovery/mcp-json.ts +171 -0
  250. package/src/discovery/opencode.ts +393 -0
  251. package/src/discovery/plugin-dir-roots.ts +28 -0
  252. package/src/discovery/ssh.ts +153 -0
  253. package/src/discovery/substitute-plugin-root.ts +29 -0
  254. package/src/discovery/vscode.ts +105 -0
  255. package/src/discovery/windsurf.ts +147 -0
  256. package/src/edit/diff.ts +818 -0
  257. package/src/edit/index.ts +481 -0
  258. package/src/edit/line-hash.ts +67 -0
  259. package/src/edit/modes/chunk.ts +762 -0
  260. package/src/edit/modes/hashline.ts +1366 -0
  261. package/src/edit/modes/patch.ts +1791 -0
  262. package/src/edit/modes/replace.ts +1115 -0
  263. package/src/edit/normalize.ts +375 -0
  264. package/src/edit/renderer.ts +627 -0
  265. package/src/exa/factory.ts +61 -0
  266. package/src/exa/index.ts +27 -0
  267. package/src/exa/mcp-client.ts +293 -0
  268. package/src/exa/render.ts +232 -0
  269. package/src/exa/researcher.ts +47 -0
  270. package/src/exa/search.ts +86 -0
  271. package/src/exa/types.ts +166 -0
  272. package/src/exa/websets.ts +247 -0
  273. package/src/exec/bash-executor.ts +332 -0
  274. package/src/exec/exec.ts +53 -0
  275. package/src/exec/idle-timeout-watchdog.ts +126 -0
  276. package/src/exec/non-interactive-env.ts +48 -0
  277. package/src/export/custom-share.ts +65 -0
  278. package/src/export/html/index.ts +161 -0
  279. package/src/export/html/template.css +1001 -0
  280. package/src/export/html/template.generated.ts +2 -0
  281. package/src/export/html/template.html +46 -0
  282. package/src/export/html/template.js +1950 -0
  283. package/src/export/html/template.macro.ts +24 -0
  284. package/src/export/html/vendor/highlight.min.js +1213 -0
  285. package/src/export/html/vendor/marked.min.js +6 -0
  286. package/src/export/ttsr.ts +434 -0
  287. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +25 -0
  288. package/src/extensibility/custom-commands/bundled/review/index.ts +456 -0
  289. package/src/extensibility/custom-commands/index.ts +2 -0
  290. package/src/extensibility/custom-commands/loader.ts +236 -0
  291. package/src/extensibility/custom-commands/types.ts +111 -0
  292. package/src/extensibility/custom-tools/index.ts +7 -0
  293. package/src/extensibility/custom-tools/loader.ts +238 -0
  294. package/src/extensibility/custom-tools/types.ts +251 -0
  295. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  296. package/src/extensibility/extensions/index.ts +15 -0
  297. package/src/extensibility/extensions/loader.ts +572 -0
  298. package/src/extensibility/extensions/runner.ts +848 -0
  299. package/src/extensibility/extensions/types.ts +1394 -0
  300. package/src/extensibility/extensions/wrapper.ts +191 -0
  301. package/src/extensibility/hooks/index.ts +5 -0
  302. package/src/extensibility/hooks/loader.ts +255 -0
  303. package/src/extensibility/hooks/runner.ts +425 -0
  304. package/src/extensibility/hooks/tool-wrapper.ts +108 -0
  305. package/src/extensibility/hooks/types.ts +826 -0
  306. package/src/extensibility/plugins/doctor.ts +66 -0
  307. package/src/extensibility/plugins/git-url.ts +281 -0
  308. package/src/extensibility/plugins/index.ts +9 -0
  309. package/src/extensibility/plugins/installer.ts +192 -0
  310. package/src/extensibility/plugins/loader.ts +267 -0
  311. package/src/extensibility/plugins/manager.ts +731 -0
  312. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  313. package/src/extensibility/plugins/marketplace/fetcher.ts +318 -0
  314. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  315. package/src/extensibility/plugins/marketplace/manager.ts +781 -0
  316. package/src/extensibility/plugins/marketplace/prerequisites.ts +255 -0
  317. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  318. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  319. package/src/extensibility/plugins/marketplace/types.ts +201 -0
  320. package/src/extensibility/plugins/parser.ts +105 -0
  321. package/src/extensibility/plugins/types.ts +194 -0
  322. package/src/extensibility/skills.ts +269 -0
  323. package/src/extensibility/slash-commands.ts +246 -0
  324. package/src/extensibility/tool-proxy.ts +25 -0
  325. package/src/extensibility/utils.ts +38 -0
  326. package/src/index.ts +61 -0
  327. package/src/internal-urls/agent-protocol.ts +136 -0
  328. package/src/internal-urls/api-catalog-resolve.ts +495 -0
  329. package/src/internal-urls/api-catalog-types.ts +94 -0
  330. package/src/internal-urls/api-spec-resolve.ts +1036 -0
  331. package/src/internal-urls/api-spec-types.ts +239 -0
  332. package/src/internal-urls/artifact-protocol.ts +97 -0
  333. package/src/internal-urls/branding-index.generated.ts +88 -0
  334. package/src/internal-urls/build-info-runtime.ts +302 -0
  335. package/src/internal-urls/build-info.generated.ts +33 -0
  336. package/src/internal-urls/computer-profile.ts +692 -0
  337. package/src/internal-urls/console-catalog-types.ts +21 -0
  338. package/src/internal-urls/console-catalog.generated.ts +532 -0
  339. package/src/internal-urls/console-field-metadata-types.ts +59 -0
  340. package/src/internal-urls/console-field-metadata.generated.ts +4841 -0
  341. package/src/internal-urls/console-resolve.ts +178 -0
  342. package/src/internal-urls/docs-index.generated.ts +698 -0
  343. package/src/internal-urls/extension-api.md +147 -0
  344. package/src/internal-urls/index.ts +46 -0
  345. package/src/internal-urls/jobs-protocol.ts +119 -0
  346. package/src/internal-urls/json-query.ts +126 -0
  347. package/src/internal-urls/local-protocol.ts +206 -0
  348. package/src/internal-urls/mcp-protocol.ts +156 -0
  349. package/src/internal-urls/memory-protocol.ts +133 -0
  350. package/src/internal-urls/parse.ts +72 -0
  351. package/src/internal-urls/profile-collectors.ts +106 -0
  352. package/src/internal-urls/router.ts +55 -0
  353. package/src/internal-urls/rule-protocol.ts +55 -0
  354. package/src/internal-urls/skill-protocol.ts +111 -0
  355. package/src/internal-urls/terraform-index.generated.ts +1852 -0
  356. package/src/internal-urls/terraform-resolve.ts +184 -0
  357. package/src/internal-urls/terraform-types.ts +45 -0
  358. package/src/internal-urls/types.ts +52 -0
  359. package/src/internal-urls/user-profile.ts +363 -0
  360. package/src/internal-urls/xcsh-protocol.ts +644 -0
  361. package/src/ipy/cancellation.ts +28 -0
  362. package/src/ipy/executor.ts +1155 -0
  363. package/src/ipy/gateway-coordinator.ts +424 -0
  364. package/src/ipy/kernel.ts +1091 -0
  365. package/src/ipy/modules.ts +144 -0
  366. package/src/ipy/prelude.py +849 -0
  367. package/src/ipy/prelude.ts +3 -0
  368. package/src/ipy/runtime.ts +221 -0
  369. package/src/locales/ar.json +512 -0
  370. package/src/locales/de.json +512 -0
  371. package/src/locales/en.json +549 -0
  372. package/src/locales/es.json +512 -0
  373. package/src/locales/fr.json +512 -0
  374. package/src/locales/hi.json +512 -0
  375. package/src/locales/index.ts +29 -0
  376. package/src/locales/it.json +512 -0
  377. package/src/locales/ja.json +512 -0
  378. package/src/locales/ko.json +512 -0
  379. package/src/locales/pt-br.json +512 -0
  380. package/src/locales/th.json +512 -0
  381. package/src/locales/zh-cn.json +512 -0
  382. package/src/locales/zh-tw.json +512 -0
  383. package/src/lsp/client.ts +941 -0
  384. package/src/lsp/clients/biome-client.ts +202 -0
  385. package/src/lsp/clients/index.ts +50 -0
  386. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  387. package/src/lsp/clients/swiftlint-client.ts +120 -0
  388. package/src/lsp/config.ts +418 -0
  389. package/src/lsp/defaults.json +999 -0
  390. package/src/lsp/edits.ts +109 -0
  391. package/src/lsp/index.ts +1746 -0
  392. package/src/lsp/lspmux.ts +233 -0
  393. package/src/lsp/render.ts +692 -0
  394. package/src/lsp/startup-events.ts +13 -0
  395. package/src/lsp/types.ts +444 -0
  396. package/src/lsp/utils.ts +691 -0
  397. package/src/main.ts +944 -0
  398. package/src/mcp/client.ts +482 -0
  399. package/src/mcp/config-writer.ts +225 -0
  400. package/src/mcp/config.ts +365 -0
  401. package/src/mcp/discoverable-tool-metadata.ts +202 -0
  402. package/src/mcp/index.ts +29 -0
  403. package/src/mcp/json-rpc.ts +84 -0
  404. package/src/mcp/loader.ts +124 -0
  405. package/src/mcp/manager.ts +1152 -0
  406. package/src/mcp/oauth-discovery.ts +349 -0
  407. package/src/mcp/oauth-flow.ts +387 -0
  408. package/src/mcp/render.ts +157 -0
  409. package/src/mcp/smithery-auth.ts +104 -0
  410. package/src/mcp/smithery-connect.ts +145 -0
  411. package/src/mcp/smithery-registry.ts +477 -0
  412. package/src/mcp/tool-bridge.ts +417 -0
  413. package/src/mcp/tool-cache.ts +117 -0
  414. package/src/mcp/transports/http.ts +475 -0
  415. package/src/mcp/transports/index.ts +6 -0
  416. package/src/mcp/transports/stdio.ts +325 -0
  417. package/src/mcp/types.ts +423 -0
  418. package/src/memories/index.ts +1115 -0
  419. package/src/memories/storage.ts +577 -0
  420. package/src/modes/acp/acp-agent.ts +1361 -0
  421. package/src/modes/acp/acp-event-mapper.ts +538 -0
  422. package/src/modes/acp/acp-mode.ts +15 -0
  423. package/src/modes/acp/index.ts +2 -0
  424. package/src/modes/components/agent-dashboard.ts +1124 -0
  425. package/src/modes/components/assistant-message.ts +213 -0
  426. package/src/modes/components/bash-execution.ts +345 -0
  427. package/src/modes/components/bordered-loader.ts +41 -0
  428. package/src/modes/components/branch-summary-message.ts +45 -0
  429. package/src/modes/components/btw-panel.ts +103 -0
  430. package/src/modes/components/compaction-summary-message.ts +51 -0
  431. package/src/modes/components/context-add-wizard.ts +534 -0
  432. package/src/modes/components/countdown-timer.ts +75 -0
  433. package/src/modes/components/custom-editor.ts +238 -0
  434. package/src/modes/components/custom-message.ts +91 -0
  435. package/src/modes/components/diff.ts +210 -0
  436. package/src/modes/components/dynamic-border.ts +25 -0
  437. package/src/modes/components/extensions/extension-dashboard.ts +326 -0
  438. package/src/modes/components/extensions/extension-list.ts +492 -0
  439. package/src/modes/components/extensions/index.ts +9 -0
  440. package/src/modes/components/extensions/inspector-panel.ts +317 -0
  441. package/src/modes/components/extensions/state-manager.ts +587 -0
  442. package/src/modes/components/extensions/types.ts +191 -0
  443. package/src/modes/components/footer.ts +262 -0
  444. package/src/modes/components/gutter-block.ts +315 -0
  445. package/src/modes/components/history-search.ts +158 -0
  446. package/src/modes/components/hook-editor.ts +151 -0
  447. package/src/modes/components/hook-input.ts +81 -0
  448. package/src/modes/components/hook-message.ts +100 -0
  449. package/src/modes/components/hook-selector.ts +192 -0
  450. package/src/modes/components/index.ts +36 -0
  451. package/src/modes/components/keybinding-hints.ts +65 -0
  452. package/src/modes/components/login-dialog.ts +164 -0
  453. package/src/modes/components/mcp-add-wizard.ts +1314 -0
  454. package/src/modes/components/model-selector.ts +946 -0
  455. package/src/modes/components/oauth-selector.ts +211 -0
  456. package/src/modes/components/plugin-selector.ts +95 -0
  457. package/src/modes/components/plugin-settings.ts +477 -0
  458. package/src/modes/components/plugins/index.ts +5 -0
  459. package/src/modes/components/plugins/plugin-dashboard.ts +523 -0
  460. package/src/modes/components/plugins/plugin-inspector-pane.ts +84 -0
  461. package/src/modes/components/plugins/plugin-list-pane.ts +109 -0
  462. package/src/modes/components/plugins/state-manager.ts +229 -0
  463. package/src/modes/components/plugins/types.ts +51 -0
  464. package/src/modes/components/plugins/utils.ts +6 -0
  465. package/src/modes/components/python-execution.ts +244 -0
  466. package/src/modes/components/queue-mode-selector.ts +56 -0
  467. package/src/modes/components/read-tool-group.ts +137 -0
  468. package/src/modes/components/session-observer-overlay.ts +483 -0
  469. package/src/modes/components/session-selector.ts +343 -0
  470. package/src/modes/components/settings-defs.ts +568 -0
  471. package/src/modes/components/settings-selector.ts +641 -0
  472. package/src/modes/components/show-images-selector.ts +45 -0
  473. package/src/modes/components/skill-message.ts +90 -0
  474. package/src/modes/components/status-line/context-gradient.ts +64 -0
  475. package/src/modes/components/status-line/git-utils.ts +42 -0
  476. package/src/modes/components/status-line/hex-ansi.ts +29 -0
  477. package/src/modes/components/status-line/index.ts +4 -0
  478. package/src/modes/components/status-line/presets.ts +174 -0
  479. package/src/modes/components/status-line/segments.ts +494 -0
  480. package/src/modes/components/status-line/separators.ts +55 -0
  481. package/src/modes/components/status-line/token-rate.ts +66 -0
  482. package/src/modes/components/status-line/types.ts +96 -0
  483. package/src/modes/components/status-line-segment-editor.ts +361 -0
  484. package/src/modes/components/status-line.ts +729 -0
  485. package/src/modes/components/theme-selector.ts +63 -0
  486. package/src/modes/components/thinking-selector.ts +52 -0
  487. package/src/modes/components/todo-reminder.ts +54 -0
  488. package/src/modes/components/tool-execution.ts +781 -0
  489. package/src/modes/components/tree-selector.ts +908 -0
  490. package/src/modes/components/ttsr-notification.ts +80 -0
  491. package/src/modes/components/user-message-selector.ts +141 -0
  492. package/src/modes/components/user-message.ts +100 -0
  493. package/src/modes/components/visual-truncate.ts +63 -0
  494. package/src/modes/components/welcome-checks.ts +313 -0
  495. package/src/modes/components/welcome.ts +270 -0
  496. package/src/modes/controllers/btw-controller.ts +193 -0
  497. package/src/modes/controllers/chord-routing.ts +37 -0
  498. package/src/modes/controllers/command-controller.ts +1293 -0
  499. package/src/modes/controllers/context-command-controller.ts +61 -0
  500. package/src/modes/controllers/event-controller.ts +743 -0
  501. package/src/modes/controllers/extension-ui-controller.ts +983 -0
  502. package/src/modes/controllers/input-controller.ts +877 -0
  503. package/src/modes/controllers/mcp-command-controller.ts +1940 -0
  504. package/src/modes/controllers/selector-controller.ts +1292 -0
  505. package/src/modes/controllers/ssh-command-controller.ts +421 -0
  506. package/src/modes/index.ts +34 -0
  507. package/src/modes/interactive-mode.ts +1781 -0
  508. package/src/modes/oauth-manual-input.ts +42 -0
  509. package/src/modes/print-mode.ts +196 -0
  510. package/src/modes/prompt-action-autocomplete.ts +231 -0
  511. package/src/modes/rpc/host-tools.ts +186 -0
  512. package/src/modes/rpc/rpc-client.ts +762 -0
  513. package/src/modes/rpc/rpc-mode.ts +877 -0
  514. package/src/modes/rpc/rpc-types.ts +322 -0
  515. package/src/modes/session-observer-registry.ts +146 -0
  516. package/src/modes/shared.ts +30 -0
  517. package/src/modes/theme/defaults/index.ts +7 -0
  518. package/src/modes/theme/defaults/xcsh-dark.json +113 -0
  519. package/src/modes/theme/defaults/xcsh-light.json +115 -0
  520. package/src/modes/theme/mermaid-cache.ts +151 -0
  521. package/src/modes/theme/mermaid-palette.ts +39 -0
  522. package/src/modes/theme/theme-schema.json +553 -0
  523. package/src/modes/theme/theme.ts +2563 -0
  524. package/src/modes/types.ts +273 -0
  525. package/src/modes/utils/hotkeys-markdown.ts +60 -0
  526. package/src/modes/utils/keybinding-matchers.ts +30 -0
  527. package/src/modes/utils/read-group-outcome-aggregator.ts +55 -0
  528. package/src/modes/utils/sanitize-error-message.ts +60 -0
  529. package/src/modes/utils/tools-markdown.ts +28 -0
  530. package/src/modes/utils/ui-helpers.ts +734 -0
  531. package/src/plan-mode/approved-plan.ts +55 -0
  532. package/src/plan-mode/state.ts +6 -0
  533. package/src/priority.json +37 -0
  534. package/src/prompts/agents/designer.md +67 -0
  535. package/src/prompts/agents/explore.md +61 -0
  536. package/src/prompts/agents/frontmatter.md +10 -0
  537. package/src/prompts/agents/init.md +36 -0
  538. package/src/prompts/agents/librarian.md +121 -0
  539. package/src/prompts/agents/plan.md +49 -0
  540. package/src/prompts/agents/reviewer.md +127 -0
  541. package/src/prompts/agents/task.md +16 -0
  542. package/src/prompts/ci-green-request.md +35 -0
  543. package/src/prompts/compaction/branch-summary-context.md +5 -0
  544. package/src/prompts/compaction/branch-summary-preamble.md +2 -0
  545. package/src/prompts/compaction/branch-summary.md +30 -0
  546. package/src/prompts/compaction/compaction-short-summary.md +9 -0
  547. package/src/prompts/compaction/compaction-summary-context.md +5 -0
  548. package/src/prompts/compaction/compaction-summary.md +38 -0
  549. package/src/prompts/compaction/compaction-turn-prefix.md +17 -0
  550. package/src/prompts/compaction/compaction-update-summary.md +45 -0
  551. package/src/prompts/memories/consolidation.md +30 -0
  552. package/src/prompts/memories/read-path.md +11 -0
  553. package/src/prompts/memories/stage_one_input.md +6 -0
  554. package/src/prompts/memories/stage_one_system.md +21 -0
  555. package/src/prompts/review-request.md +70 -0
  556. package/src/prompts/system/agent-creation-architect.md +65 -0
  557. package/src/prompts/system/agent-creation-user.md +6 -0
  558. package/src/prompts/system/auto-handoff-threshold-focus.md +1 -0
  559. package/src/prompts/system/btw-user.md +8 -0
  560. package/src/prompts/system/commit-message-system.md +2 -0
  561. package/src/prompts/system/custom-system-prompt.md +82 -0
  562. package/src/prompts/system/eager-todo.md +13 -0
  563. package/src/prompts/system/file-operations.md +10 -0
  564. package/src/prompts/system/handoff-document.md +48 -0
  565. package/src/prompts/system/plan-mode-active.md +114 -0
  566. package/src/prompts/system/plan-mode-approved.md +23 -0
  567. package/src/prompts/system/plan-mode-reference.md +14 -0
  568. package/src/prompts/system/plan-mode-subagent.md +34 -0
  569. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  570. package/src/prompts/system/subagent-submit-reminder.md +7 -0
  571. package/src/prompts/system/subagent-system-prompt.md +36 -0
  572. package/src/prompts/system/subagent-user-prompt.md +12 -0
  573. package/src/prompts/system/summarization-system.md +3 -0
  574. package/src/prompts/system/system-prompt.md +698 -0
  575. package/src/prompts/system/title-system.md +2 -0
  576. package/src/prompts/system/ttsr-interrupt.md +7 -0
  577. package/src/prompts/system/web-search.md +28 -0
  578. package/src/prompts/tools/ask.md +28 -0
  579. package/src/prompts/tools/ast-edit.md +48 -0
  580. package/src/prompts/tools/ast-grep.md +54 -0
  581. package/src/prompts/tools/async-result.md +5 -0
  582. package/src/prompts/tools/bash.md +67 -0
  583. package/src/prompts/tools/browser.md +26 -0
  584. package/src/prompts/tools/calculator.md +10 -0
  585. package/src/prompts/tools/cancel-job.md +5 -0
  586. package/src/prompts/tools/catalog-workflow-runner.md +13 -0
  587. package/src/prompts/tools/checkpoint.md +16 -0
  588. package/src/prompts/tools/chunk-edit.md +279 -0
  589. package/src/prompts/tools/debug.md +43 -0
  590. package/src/prompts/tools/display-image.md +23 -0
  591. package/src/prompts/tools/exit-plan-mode.md +41 -0
  592. package/src/prompts/tools/find.md +26 -0
  593. package/src/prompts/tools/gemini-image.md +7 -0
  594. package/src/prompts/tools/grep.md +29 -0
  595. package/src/prompts/tools/hashline.md +131 -0
  596. package/src/prompts/tools/inspect-image-system.md +20 -0
  597. package/src/prompts/tools/inspect-image.md +32 -0
  598. package/src/prompts/tools/lsp.md +33 -0
  599. package/src/prompts/tools/patch.md +77 -0
  600. package/src/prompts/tools/poll.md +5 -0
  601. package/src/prompts/tools/python.md +60 -0
  602. package/src/prompts/tools/read-chunk.md +35 -0
  603. package/src/prompts/tools/read.md +63 -0
  604. package/src/prompts/tools/render-mermaid.md +9 -0
  605. package/src/prompts/tools/replace.md +36 -0
  606. package/src/prompts/tools/resolve.md +8 -0
  607. package/src/prompts/tools/rewind.md +13 -0
  608. package/src/prompts/tools/search-tool-bm25.md +34 -0
  609. package/src/prompts/tools/ssh.md +44 -0
  610. package/src/prompts/tools/task-summary.md +28 -0
  611. package/src/prompts/tools/task.md +131 -0
  612. package/src/prompts/tools/todo-write.md +89 -0
  613. package/src/prompts/tools/vim.md +98 -0
  614. package/src/prompts/tools/web-search.md +10 -0
  615. package/src/prompts/tools/write.md +14 -0
  616. package/src/prompts/tools/xcsh-api.md +283 -0
  617. package/src/resource-management/index.ts +42 -0
  618. package/src/sdk.ts +2123 -0
  619. package/src/secrets/index.ts +146 -0
  620. package/src/secrets/obfuscator.ts +290 -0
  621. package/src/secrets/regex.ts +21 -0
  622. package/src/services/context-env.ts +102 -0
  623. package/src/services/xcsh-api-client.ts +230 -0
  624. package/src/services/xcsh-context-command.ts +803 -0
  625. package/src/services/xcsh-context-display.ts +49 -0
  626. package/src/services/xcsh-context-indicators.ts +17 -0
  627. package/src/services/xcsh-context-segment.ts +39 -0
  628. package/src/services/xcsh-context.ts +1410 -0
  629. package/src/services/xcsh-env.ts +107 -0
  630. package/src/services/xcsh-knowledge.ts +177 -0
  631. package/src/services/xcsh-table.ts +164 -0
  632. package/src/session/agent-session.ts +6690 -0
  633. package/src/session/agent-storage.ts +451 -0
  634. package/src/session/artifacts.ts +132 -0
  635. package/src/session/auth-storage.ts +17 -0
  636. package/src/session/blob-store.ts +135 -0
  637. package/src/session/compaction/branch-summarization.ts +322 -0
  638. package/src/session/compaction/compaction.ts +1388 -0
  639. package/src/session/compaction/index.ts +7 -0
  640. package/src/session/compaction/pruning.ts +91 -0
  641. package/src/session/compaction/utils.ts +184 -0
  642. package/src/session/history-storage.ts +253 -0
  643. package/src/session/messages.ts +597 -0
  644. package/src/session/session-dump-format.ts +203 -0
  645. package/src/session/session-manager.ts +2816 -0
  646. package/src/session/session-storage.ts +370 -0
  647. package/src/session/streaming-output.ts +770 -0
  648. package/src/session/tool-choice-queue.ts +213 -0
  649. package/src/slash-commands/builtin-registry.ts +1614 -0
  650. package/src/slash-commands/export-command.ts +178 -0
  651. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  652. package/src/slash-commands/resource-commands.ts +250 -0
  653. package/src/ssh/config-writer.ts +183 -0
  654. package/src/ssh/connection-manager.ts +445 -0
  655. package/src/ssh/ssh-executor.ts +131 -0
  656. package/src/ssh/sshfs-mount.ts +137 -0
  657. package/src/ssh/utils.ts +8 -0
  658. package/src/stt/downloader.ts +71 -0
  659. package/src/stt/index.ts +3 -0
  660. package/src/stt/recorder.ts +351 -0
  661. package/src/stt/setup.ts +52 -0
  662. package/src/stt/stt-controller.ts +160 -0
  663. package/src/stt/transcribe.py +70 -0
  664. package/src/stt/transcriber.ts +91 -0
  665. package/src/system-prompt.ts +688 -0
  666. package/src/task/agents.ts +166 -0
  667. package/src/task/commands.ts +131 -0
  668. package/src/task/discovery.ts +126 -0
  669. package/src/task/executor.ts +1324 -0
  670. package/src/task/index.ts +1197 -0
  671. package/src/task/isolation-backend.ts +72 -0
  672. package/src/task/name-generator.ts +1577 -0
  673. package/src/task/output-manager.ts +107 -0
  674. package/src/task/parallel.ts +116 -0
  675. package/src/task/render.ts +1035 -0
  676. package/src/task/subprocess-tool-registry.ts +88 -0
  677. package/src/task/template.ts +33 -0
  678. package/src/task/types.ts +230 -0
  679. package/src/task/worktree.ts +580 -0
  680. package/src/task/xcsh-command.ts +26 -0
  681. package/src/thinking.ts +87 -0
  682. package/src/tools/action-renderer.ts +198 -0
  683. package/src/tools/archive-reader.ts +315 -0
  684. package/src/tools/ask.ts +791 -0
  685. package/src/tools/ast-edit.ts +492 -0
  686. package/src/tools/ast-grep.ts +453 -0
  687. package/src/tools/auto-generated-guard.ts +305 -0
  688. package/src/tools/bash-interactive.ts +383 -0
  689. package/src/tools/bash-interceptor.ts +67 -0
  690. package/src/tools/bash-normalize.ts +107 -0
  691. package/src/tools/bash-skill-urls.ts +246 -0
  692. package/src/tools/bash.ts +878 -0
  693. package/src/tools/browser-renderer.ts +129 -0
  694. package/src/tools/browser.ts +1366 -0
  695. package/src/tools/calculator.ts +543 -0
  696. package/src/tools/cancel-job.ts +100 -0
  697. package/src/tools/catalog-workflow-runner.ts +718 -0
  698. package/src/tools/checkpoint.ts +133 -0
  699. package/src/tools/context.ts +39 -0
  700. package/src/tools/debug.ts +1004 -0
  701. package/src/tools/display-image-renderer.ts +96 -0
  702. package/src/tools/display-image.ts +109 -0
  703. package/src/tools/exit-plan-mode.ts +101 -0
  704. package/src/tools/fetch.ts +1462 -0
  705. package/src/tools/find.ts +437 -0
  706. package/src/tools/fs-cache-invalidation.ts +33 -0
  707. package/src/tools/gemini-image.ts +1004 -0
  708. package/src/tools/grep.ts +705 -0
  709. package/src/tools/index.ts +442 -0
  710. package/src/tools/inspect-image-renderer.ts +101 -0
  711. package/src/tools/inspect-image.ts +176 -0
  712. package/src/tools/json-tree.ts +266 -0
  713. package/src/tools/jtd-to-json-schema.ts +199 -0
  714. package/src/tools/jtd-to-typescript.ts +136 -0
  715. package/src/tools/jtd-utils.ts +102 -0
  716. package/src/tools/list-limit.ts +40 -0
  717. package/src/tools/mermaid-renderer.ts +127 -0
  718. package/src/tools/notebook.ts +288 -0
  719. package/src/tools/output-meta.ts +588 -0
  720. package/src/tools/path-utils.ts +560 -0
  721. package/src/tools/plan-mode-guard.ts +41 -0
  722. package/src/tools/poll-tool.ts +177 -0
  723. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  724. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  725. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  726. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  727. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  728. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  729. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  730. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  731. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  732. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  733. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  734. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  735. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  736. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  737. package/src/tools/python.ts +1184 -0
  738. package/src/tools/read.ts +1591 -0
  739. package/src/tools/render-mermaid.ts +93 -0
  740. package/src/tools/render-utils.ts +677 -0
  741. package/src/tools/renderers.ts +82 -0
  742. package/src/tools/report-tool-issue.ts +80 -0
  743. package/src/tools/resolve.ts +196 -0
  744. package/src/tools/review.ts +238 -0
  745. package/src/tools/search-tool-bm25.ts +288 -0
  746. package/src/tools/sqlite-reader.ts +623 -0
  747. package/src/tools/ssh.ts +322 -0
  748. package/src/tools/submit-result.ts +229 -0
  749. package/src/tools/todo-render.ts +33 -0
  750. package/src/tools/todo-write.ts +440 -0
  751. package/src/tools/tool-errors.ts +62 -0
  752. package/src/tools/tool-result.ts +93 -0
  753. package/src/tools/tool-timeouts.ts +30 -0
  754. package/src/tools/vim.ts +981 -0
  755. package/src/tools/write.ts +671 -0
  756. package/src/tools/xcsh-api-renderer.ts +402 -0
  757. package/src/tools/xcsh-api.ts +887 -0
  758. package/src/tui/code-cell.ts +101 -0
  759. package/src/tui/file-list.ts +47 -0
  760. package/src/tui/index.ts +11 -0
  761. package/src/tui/output-block.ts +175 -0
  762. package/src/tui/status-line.ts +39 -0
  763. package/src/tui/tree-list.ts +84 -0
  764. package/src/tui/types.ts +15 -0
  765. package/src/tui/utils.ts +103 -0
  766. package/src/utils/changelog.ts +98 -0
  767. package/src/utils/clipboard.ts +80 -0
  768. package/src/utils/command-args.ts +76 -0
  769. package/src/utils/commit-message-generator.ts +137 -0
  770. package/src/utils/edit-mode.ts +50 -0
  771. package/src/utils/event-bus.ts +33 -0
  772. package/src/utils/external-editor.ts +65 -0
  773. package/src/utils/file-display-mode.ts +37 -0
  774. package/src/utils/file-mentions.ts +376 -0
  775. package/src/utils/fuzzy.ts +108 -0
  776. package/src/utils/git.ts +1495 -0
  777. package/src/utils/gitstatus.ts +140 -0
  778. package/src/utils/image-convert.ts +27 -0
  779. package/src/utils/image-loading.ts +98 -0
  780. package/src/utils/image-passthrough.ts +118 -0
  781. package/src/utils/image-resize.ts +272 -0
  782. package/src/utils/image-viewer.ts +17 -0
  783. package/src/utils/lang-from-path.ts +239 -0
  784. package/src/utils/markit.ts +81 -0
  785. package/src/utils/open.ts +20 -0
  786. package/src/utils/session-color.ts +55 -0
  787. package/src/utils/shell-snapshot.ts +188 -0
  788. package/src/utils/title-generator.ts +193 -0
  789. package/src/utils/tool-choice.ts +28 -0
  790. package/src/utils/tools-manager.ts +356 -0
  791. package/src/vim/buffer.ts +309 -0
  792. package/src/vim/commands.ts +382 -0
  793. package/src/vim/engine.ts +2426 -0
  794. package/src/vim/parser.ts +151 -0
  795. package/src/vim/render.ts +252 -0
  796. package/src/vim/types.ts +197 -0
  797. package/src/web/kagi.ts +174 -0
  798. package/src/web/parallel.ts +346 -0
  799. package/src/web/scrapers/artifacthub.ts +207 -0
  800. package/src/web/scrapers/arxiv.ts +83 -0
  801. package/src/web/scrapers/aur.ts +162 -0
  802. package/src/web/scrapers/biorxiv.ts +133 -0
  803. package/src/web/scrapers/bluesky.ts +262 -0
  804. package/src/web/scrapers/brew.ts +172 -0
  805. package/src/web/scrapers/cheatsh.ts +68 -0
  806. package/src/web/scrapers/chocolatey.ts +196 -0
  807. package/src/web/scrapers/choosealicense.ts +95 -0
  808. package/src/web/scrapers/cisa-kev.ts +87 -0
  809. package/src/web/scrapers/clojars.ts +154 -0
  810. package/src/web/scrapers/coingecko.ts +177 -0
  811. package/src/web/scrapers/crates-io.ts +110 -0
  812. package/src/web/scrapers/crossref.ts +136 -0
  813. package/src/web/scrapers/devto.ts +147 -0
  814. package/src/web/scrapers/discogs.ts +306 -0
  815. package/src/web/scrapers/discourse.ts +197 -0
  816. package/src/web/scrapers/dockerhub.ts +138 -0
  817. package/src/web/scrapers/docs-rs.ts +653 -0
  818. package/src/web/scrapers/fdroid.ts +134 -0
  819. package/src/web/scrapers/firefox-addons.ts +191 -0
  820. package/src/web/scrapers/flathub.ts +223 -0
  821. package/src/web/scrapers/github-gist.ts +58 -0
  822. package/src/web/scrapers/github.ts +452 -0
  823. package/src/web/scrapers/gitlab.ts +401 -0
  824. package/src/web/scrapers/go-pkg.ts +266 -0
  825. package/src/web/scrapers/hackage.ts +140 -0
  826. package/src/web/scrapers/hackernews.ts +189 -0
  827. package/src/web/scrapers/hex.ts +105 -0
  828. package/src/web/scrapers/huggingface.ts +321 -0
  829. package/src/web/scrapers/iacr.ts +89 -0
  830. package/src/web/scrapers/index.ts +252 -0
  831. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  832. package/src/web/scrapers/lemmy.ts +203 -0
  833. package/src/web/scrapers/lobsters.ts +175 -0
  834. package/src/web/scrapers/mastodon.ts +292 -0
  835. package/src/web/scrapers/maven.ts +138 -0
  836. package/src/web/scrapers/mdn.ts +169 -0
  837. package/src/web/scrapers/metacpan.ts +222 -0
  838. package/src/web/scrapers/musicbrainz.ts +250 -0
  839. package/src/web/scrapers/npm.ts +98 -0
  840. package/src/web/scrapers/nuget.ts +183 -0
  841. package/src/web/scrapers/nvd.ts +222 -0
  842. package/src/web/scrapers/ollama.ts +239 -0
  843. package/src/web/scrapers/open-vsx.ts +106 -0
  844. package/src/web/scrapers/opencorporates.ts +292 -0
  845. package/src/web/scrapers/openlibrary.ts +336 -0
  846. package/src/web/scrapers/orcid.ts +286 -0
  847. package/src/web/scrapers/osv.ts +176 -0
  848. package/src/web/scrapers/packagist.ts +160 -0
  849. package/src/web/scrapers/pub-dev.ts +143 -0
  850. package/src/web/scrapers/pubmed.ts +211 -0
  851. package/src/web/scrapers/pypi.ts +112 -0
  852. package/src/web/scrapers/rawg.ts +110 -0
  853. package/src/web/scrapers/readthedocs.ts +120 -0
  854. package/src/web/scrapers/reddit.ts +95 -0
  855. package/src/web/scrapers/repology.ts +251 -0
  856. package/src/web/scrapers/rfc.ts +201 -0
  857. package/src/web/scrapers/rubygems.ts +103 -0
  858. package/src/web/scrapers/searchcode.ts +190 -0
  859. package/src/web/scrapers/sec-edgar.ts +261 -0
  860. package/src/web/scrapers/semantic-scholar.ts +171 -0
  861. package/src/web/scrapers/snapcraft.ts +187 -0
  862. package/src/web/scrapers/sourcegraph.ts +336 -0
  863. package/src/web/scrapers/spdx.ts +108 -0
  864. package/src/web/scrapers/spotify.ts +198 -0
  865. package/src/web/scrapers/stackoverflow.ts +120 -0
  866. package/src/web/scrapers/terraform.ts +277 -0
  867. package/src/web/scrapers/tldr.ts +47 -0
  868. package/src/web/scrapers/twitter.ts +93 -0
  869. package/src/web/scrapers/types.ts +267 -0
  870. package/src/web/scrapers/utils.ts +109 -0
  871. package/src/web/scrapers/vimeo.ts +133 -0
  872. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  873. package/src/web/scrapers/w3c.ts +156 -0
  874. package/src/web/scrapers/wikidata.ts +344 -0
  875. package/src/web/scrapers/wikipedia.ts +84 -0
  876. package/src/web/scrapers/youtube.ts +313 -0
  877. package/src/web/search/errors.ts +120 -0
  878. package/src/web/search/index.ts +346 -0
  879. package/src/web/search/params.ts +129 -0
  880. package/src/web/search/provider.ts +97 -0
  881. package/src/web/search/providers/anthropic.ts +339 -0
  882. package/src/web/search/providers/base.ts +35 -0
  883. package/src/web/search/providers/brave.ts +150 -0
  884. package/src/web/search/providers/codex.ts +402 -0
  885. package/src/web/search/providers/exa.ts +264 -0
  886. package/src/web/search/providers/firecrawl.ts +115 -0
  887. package/src/web/search/providers/gemini.ts +566 -0
  888. package/src/web/search/providers/jina.ts +99 -0
  889. package/src/web/search/providers/kagi.ts +70 -0
  890. package/src/web/search/providers/kimi.ts +157 -0
  891. package/src/web/search/providers/parallel.ts +63 -0
  892. package/src/web/search/providers/perplexity.ts +546 -0
  893. package/src/web/search/providers/synthetic.ts +113 -0
  894. package/src/web/search/providers/tavily.ts +162 -0
  895. package/src/web/search/providers/utils.ts +36 -0
  896. package/src/web/search/providers/zai.ts +311 -0
  897. package/src/web/search/render.ts +348 -0
  898. package/src/web/search/types.ts +438 -0
  899. package/src/web/search/utils.ts +17 -0
@@ -0,0 +1,849 @@
1
+ from __future__ import annotations
2
+ # OMP IPython prelude helpers
3
+ if "__xcsh_prelude_loaded__" not in globals():
4
+ __xcsh_prelude_loaded__ = True
5
+ from pathlib import Path
6
+ import os, re, json, shutil, subprocess, inspect
7
+ from datetime import datetime
8
+ from IPython.display import display
9
+
10
+ def _emit_status(op: str, **data):
11
+ """Emit structured status event for TUI rendering."""
12
+ display({"application/x-xcsh-status": {"op": op, **data}}, raw=True)
13
+
14
+ def _category(cat: str):
15
+ """Decorator to tag a prelude function with its category."""
16
+ def decorator(fn):
17
+ fn._xcsh_category = cat
18
+ return fn
19
+ return decorator
20
+
21
+ @_category("Shell")
22
+ def env(key: str | None = None, value: str | None = None):
23
+ """Get/set environment variables."""
24
+ if key is None:
25
+ items = dict(sorted(os.environ.items()))
26
+ _emit_status("env", count=len(items), keys=list(items.keys())[:20])
27
+ return items
28
+ if value is not None:
29
+ os.environ[key] = value
30
+ _emit_status("env", key=key, value=value, action="set")
31
+ return value
32
+ val = os.environ.get(key)
33
+ _emit_status("env", key=key, value=val, action="get")
34
+ return val
35
+
36
+ @_category("File I/O")
37
+ def read(path: str | Path, *, offset: int = 1, limit: int | None = None) -> str:
38
+ """Read file contents. offset/limit are 1-indexed line numbers."""
39
+ p = Path(path)
40
+ data = p.read_text(encoding="utf-8")
41
+ lines = data.splitlines(keepends=True)
42
+ if offset > 1 or limit is not None:
43
+ start = max(0, offset - 1)
44
+ end = start + limit if limit else len(lines)
45
+ lines = lines[start:end]
46
+ data = "".join(lines)
47
+ preview = data[:500]
48
+ _emit_status("read", path=str(p), chars=len(data), preview=preview)
49
+ return data
50
+
51
+ @_category("File I/O")
52
+ def write(path: str | Path, content: str) -> Path:
53
+ """Write file contents (create parents)."""
54
+ p = Path(path)
55
+ p.parent.mkdir(parents=True, exist_ok=True)
56
+ p.write_text(content, encoding="utf-8")
57
+ _emit_status("write", path=str(p), chars=len(content))
58
+ return p
59
+
60
+ @_category("File I/O")
61
+ def append(path: str | Path, content: str) -> Path:
62
+ """Append to file."""
63
+ p = Path(path)
64
+ p.parent.mkdir(parents=True, exist_ok=True)
65
+ with p.open("a", encoding="utf-8") as f:
66
+ f.write(content)
67
+ _emit_status("append", path=str(p), chars=len(content))
68
+ return p
69
+
70
+ @_category("File ops")
71
+ def rm(path: str | Path, *, recursive: bool = False) -> None:
72
+ """Delete file or directory (recursive optional)."""
73
+ p = Path(path)
74
+ if p.is_dir():
75
+ if recursive:
76
+ shutil.rmtree(p)
77
+ _emit_status("rm", path=str(p), recursive=True)
78
+ return
79
+ _emit_status("rm", path=str(p), error="directory, use recursive=True")
80
+ return
81
+ if p.exists():
82
+ p.unlink()
83
+ _emit_status("rm", path=str(p))
84
+ else:
85
+ _emit_status("rm", path=str(p), error="missing")
86
+
87
+ @_category("File ops")
88
+ def mv(src: str | Path, dst: str | Path) -> Path:
89
+ """Move or rename a file/directory."""
90
+ src_p = Path(src)
91
+ dst_p = Path(dst)
92
+ dst_p.parent.mkdir(parents=True, exist_ok=True)
93
+ shutil.move(str(src_p), str(dst_p))
94
+ _emit_status("mv", src=str(src_p), dst=str(dst_p))
95
+ return dst_p
96
+
97
+ @_category("File ops")
98
+ def cp(src: str | Path, dst: str | Path) -> Path:
99
+ """Copy a file or directory."""
100
+ src_p = Path(src)
101
+ dst_p = Path(dst)
102
+ dst_p.parent.mkdir(parents=True, exist_ok=True)
103
+ if src_p.is_dir():
104
+ shutil.copytree(src_p, dst_p, dirs_exist_ok=True)
105
+ else:
106
+ shutil.copy2(src_p, dst_p)
107
+ _emit_status("cp", src=str(src_p), dst=str(dst_p))
108
+ return dst_p
109
+
110
+ def _load_gitignore_patterns(base: Path) -> list[str]:
111
+ """Load .gitignore patterns from base directory and parents."""
112
+ patterns: list[str] = []
113
+ # Always exclude these
114
+ patterns.extend(["**/.git", "**/.git/**", "**/node_modules", "**/node_modules/**"])
115
+ # Walk up to find .gitignore files
116
+ current = base.resolve()
117
+ for _ in range(20): # Limit depth
118
+ gitignore = current / ".gitignore"
119
+ if gitignore.exists():
120
+ try:
121
+ for line in gitignore.read_text().splitlines():
122
+ line = line.strip()
123
+ if line and not line.startswith("#"):
124
+ # Normalize pattern for fnmatch
125
+ if line.startswith("/"):
126
+ patterns.append(str(current / line[1:]))
127
+ else:
128
+ patterns.append(f"**/{line}")
129
+ except Exception:
130
+ pass
131
+ parent = current.parent
132
+ if parent == current:
133
+ break
134
+ current = parent
135
+ return patterns
136
+
137
+ def _match_gitignore(path: Path, patterns: list[str], base: Path) -> bool:
138
+ """Check if path matches any gitignore pattern."""
139
+ import fnmatch
140
+ rel = str(path.relative_to(base)) if path.is_relative_to(base) else str(path)
141
+ abs_path = str(path.resolve())
142
+ for pat in patterns:
143
+ if pat.startswith("**/"):
144
+ # Match against any part of the path
145
+ if fnmatch.fnmatch(rel, pat) or fnmatch.fnmatch(rel, pat[3:]):
146
+ return True
147
+ # Also check each path component
148
+ for part in path.parts:
149
+ if fnmatch.fnmatch(part, pat[3:]):
150
+ return True
151
+ elif fnmatch.fnmatch(abs_path, pat) or fnmatch.fnmatch(rel, pat):
152
+ return True
153
+ return False
154
+
155
+ @_category("Search")
156
+ def find(
157
+ pattern: str,
158
+ path: str | Path = ".",
159
+ *,
160
+ type: str = "file",
161
+ limit: int = 1000,
162
+ hidden: bool = False,
163
+ sort_by_mtime: bool = False,
164
+ maxdepth: int | None = None,
165
+ mindepth: int | None = None,
166
+ ) -> list[Path]:
167
+ """Recursive glob find. Respects .gitignore.
168
+
169
+ maxdepth/mindepth are relative to path (0 = path itself, 1 = direct children).
170
+ """
171
+ p = Path(path).resolve()
172
+ base_depth = len(p.parts)
173
+ ignore_patterns = _load_gitignore_patterns(p)
174
+ matches: list[Path] = []
175
+ for m in p.rglob(pattern):
176
+ if len(matches) >= limit:
177
+ break
178
+ # Check depth constraints
179
+ rel_depth = len(m.resolve().parts) - base_depth
180
+ if maxdepth is not None and rel_depth > maxdepth:
181
+ continue
182
+ if mindepth is not None and rel_depth < mindepth:
183
+ continue
184
+ # Skip hidden files unless requested
185
+ if not hidden and any(part.startswith(".") for part in m.parts):
186
+ continue
187
+ # Skip gitignored paths
188
+ if _match_gitignore(m, ignore_patterns, p):
189
+ continue
190
+ # Filter by type
191
+ if type == "file" and m.is_dir():
192
+ continue
193
+ if type == "dir" and not m.is_dir():
194
+ continue
195
+ matches.append(m)
196
+ if sort_by_mtime:
197
+ matches.sort(key=lambda x: x.stat().st_mtime, reverse=True)
198
+ else:
199
+ matches.sort()
200
+ _emit_status("find", pattern=pattern, path=str(p), count=len(matches), matches=[str(m) for m in matches[:20]])
201
+ return matches
202
+
203
+ @_category("Search")
204
+ def grep(
205
+ pattern: str,
206
+ path: str | Path,
207
+ *,
208
+ ignore_case: bool = False,
209
+ literal: bool = False,
210
+ context: int = 0,
211
+ ) -> list[tuple[int, str]]:
212
+ """Grep a single file. Returns (line_number, text) tuples."""
213
+ p = Path(path)
214
+ lines = p.read_text(encoding="utf-8").splitlines()
215
+ if literal:
216
+ if ignore_case:
217
+ match_fn = lambda line: pattern.lower() in line.lower()
218
+ else:
219
+ match_fn = lambda line: pattern in line
220
+ else:
221
+ flags = re.IGNORECASE if ignore_case else 0
222
+ rx = re.compile(pattern, flags)
223
+ match_fn = lambda line: rx.search(line) is not None
224
+
225
+ match_lines: set[int] = set()
226
+ for i, line in enumerate(lines, 1):
227
+ if match_fn(line):
228
+ match_lines.add(i)
229
+
230
+ # Expand with context
231
+ if context > 0:
232
+ expanded: set[int] = set()
233
+ for ln in match_lines:
234
+ for offset in range(-context, context + 1):
235
+ expanded.add(ln + offset)
236
+ output_lines = sorted(ln for ln in expanded if 1 <= ln <= len(lines))
237
+ else:
238
+ output_lines = sorted(match_lines)
239
+
240
+ hits = [(ln, lines[ln - 1]) for ln in output_lines]
241
+ _emit_status("grep", pattern=pattern, path=str(p), count=len(match_lines), hits=[{"line": h[0], "text": h[1][:100]} for h in hits[:10]])
242
+ return hits
243
+
244
+ @_category("Search")
245
+ def rgrep(
246
+ pattern: str,
247
+ path: str | Path = ".",
248
+ *,
249
+ glob_pattern: str = "*",
250
+ ignore_case: bool = False,
251
+ literal: bool = False,
252
+ limit: int = 100,
253
+ hidden: bool = False,
254
+ ) -> list[tuple[Path, int, str]]:
255
+ """Recursive grep across files matching glob_pattern. Respects .gitignore."""
256
+ if literal:
257
+ if ignore_case:
258
+ match_fn = lambda line: pattern.lower() in line.lower()
259
+ else:
260
+ match_fn = lambda line: pattern in line
261
+ else:
262
+ flags = re.IGNORECASE if ignore_case else 0
263
+ rx = re.compile(pattern, flags)
264
+ match_fn = lambda line: rx.search(line) is not None
265
+
266
+ base = Path(path)
267
+ ignore_patterns = _load_gitignore_patterns(base)
268
+ hits: list[tuple[Path, int, str]] = []
269
+ for file_path in base.rglob(glob_pattern):
270
+ if len(hits) >= limit:
271
+ break
272
+ if file_path.is_dir():
273
+ continue
274
+ # Skip hidden files unless requested
275
+ if not hidden and any(part.startswith(".") for part in file_path.parts):
276
+ continue
277
+ # Skip gitignored paths
278
+ if _match_gitignore(file_path, ignore_patterns, base):
279
+ continue
280
+ try:
281
+ lines = file_path.read_text(encoding="utf-8").splitlines()
282
+ except Exception:
283
+ continue
284
+ for i, line in enumerate(lines, 1):
285
+ if len(hits) >= limit:
286
+ break
287
+ if match_fn(line):
288
+ hits.append((file_path, i, line))
289
+ _emit_status("rgrep", pattern=pattern, path=str(base), count=len(hits), hits=[{"file": str(h[0]), "line": h[1], "text": h[2][:80]} for h in hits[:10]])
290
+ return hits
291
+
292
+ @_category("Find/Replace")
293
+ def replace(path: str | Path, pattern: str, repl: str, *, regex: bool = False) -> int:
294
+ """Replace text in a file (regex optional)."""
295
+ p = Path(path)
296
+ data = p.read_text(encoding="utf-8")
297
+ if regex:
298
+ new, count = re.subn(pattern, repl, data)
299
+ else:
300
+ new = data.replace(pattern, repl)
301
+ count = data.count(pattern)
302
+ p.write_text(new, encoding="utf-8")
303
+ _emit_status("replace", path=str(p), count=count)
304
+ return count
305
+
306
+ class ShellResult:
307
+ """Result from shell command execution."""
308
+ __slots__ = ("args", "stdout", "stderr", "returncode")
309
+ def __init__(self, args: str, stdout: str, stderr: str, returncode: int):
310
+ self.args = args
311
+ self.stdout = stdout
312
+ self.stderr = stderr
313
+ self.returncode = returncode
314
+
315
+ @property
316
+ def code(self) -> int:
317
+ return self.returncode
318
+
319
+ @property
320
+ def exit_code(self) -> int:
321
+ return self.returncode
322
+
323
+ def check_returncode(self) -> None:
324
+ if self.returncode != 0:
325
+ raise subprocess.CalledProcessError(
326
+ self.returncode, self.args, output=self.stdout, stderr=self.stderr
327
+ )
328
+
329
+ def __repr__(self):
330
+ if self.returncode == 0:
331
+ return ""
332
+ return f"exit code {self.returncode}"
333
+
334
+ def __bool__(self):
335
+ return self.returncode == 0
336
+
337
+ def _make_shell_result(proc: subprocess.CompletedProcess[str], cmd: str) -> ShellResult:
338
+ """Create ShellResult and emit status."""
339
+ output = proc.stdout + proc.stderr if proc.stderr else proc.stdout
340
+ _emit_status("sh", cmd=cmd[:80], code=proc.returncode, output=output[:500])
341
+ return ShellResult(cmd, proc.stdout, proc.stderr, proc.returncode)
342
+
343
+ import signal as _signal
344
+
345
+ def _run_with_interrupt(args: list[str], cwd: str | None, timeout: int | None, cmd: str) -> ShellResult:
346
+ """Run subprocess with proper interrupt handling."""
347
+ proc = subprocess.Popen(
348
+ args,
349
+ cwd=cwd,
350
+ stdout=subprocess.PIPE,
351
+ stderr=subprocess.PIPE,
352
+ text=True,
353
+ start_new_session=True,
354
+ )
355
+ try:
356
+ stdout, stderr = proc.communicate(timeout=timeout)
357
+ except KeyboardInterrupt:
358
+ os.killpg(proc.pid, _signal.SIGINT)
359
+ try:
360
+ stdout, stderr = proc.communicate(timeout=2)
361
+ except subprocess.TimeoutExpired:
362
+ os.killpg(proc.pid, _signal.SIGKILL)
363
+ stdout, stderr = proc.communicate()
364
+ result = subprocess.CompletedProcess(args, -_signal.SIGINT, stdout, stderr)
365
+ return _make_shell_result(result, cmd)
366
+ except subprocess.TimeoutExpired:
367
+ os.killpg(proc.pid, _signal.SIGKILL)
368
+ stdout, stderr = proc.communicate()
369
+ result = subprocess.CompletedProcess(args, -_signal.SIGKILL, stdout, stderr)
370
+ return _make_shell_result(result, cmd)
371
+ result = subprocess.CompletedProcess(args, proc.returncode, stdout, stderr)
372
+ return _make_shell_result(result, cmd)
373
+
374
+ @_category("Shell")
375
+ def run(cmd: str, *, cwd: str | Path | None = None, timeout: int | None = None) -> ShellResult:
376
+ """Run a shell command. Returns ShellResult with stdout/stderr and returncode/exit_code fields."""
377
+ shell_path = shutil.which("bash") or shutil.which("sh") or "/bin/sh"
378
+ args = [shell_path, "-c", cmd]
379
+ return _run_with_interrupt(args, str(cwd) if cwd else None, timeout, cmd)
380
+
381
+ @_category("Text")
382
+ def sort_lines(text: str, *, reverse: bool = False, unique: bool = False) -> str:
383
+ """Sort lines of text."""
384
+ lines = text.splitlines()
385
+ if unique:
386
+ lines = list(dict.fromkeys(lines))
387
+ lines = sorted(lines, reverse=reverse)
388
+ out = "\n".join(lines)
389
+ _emit_status("sort_lines", lines=len(lines), unique=unique, reverse=reverse)
390
+ return out
391
+
392
+ @_category("Text")
393
+ def uniq(text: str, *, count: bool = False) -> str | list[tuple[int, str]]:
394
+ """Remove duplicate adjacent lines (like uniq)."""
395
+ lines = text.splitlines()
396
+ if not lines:
397
+ _emit_status("uniq", groups=0)
398
+ return [] if count else ""
399
+ groups: list[tuple[int, str]] = []
400
+ current = lines[0]
401
+ current_count = 1
402
+ for line in lines[1:]:
403
+ if line == current:
404
+ current_count += 1
405
+ continue
406
+ groups.append((current_count, current))
407
+ current = line
408
+ current_count = 1
409
+ groups.append((current_count, current))
410
+ _emit_status("uniq", groups=len(groups), count_mode=count)
411
+ if count:
412
+ return groups
413
+ return "\n".join(line for _, line in groups)
414
+
415
+ @_category("Text")
416
+ def counter(
417
+ items: str | list,
418
+ *,
419
+ limit: int | None = None,
420
+ reverse: bool = True,
421
+ ) -> list[tuple[int, str]]:
422
+ """Count occurrences and sort by frequency. Like sort | uniq -c | sort -rn.
423
+
424
+ items: text (splits into lines) or list of strings
425
+ reverse: True for descending (most common first), False for ascending
426
+ Returns: [(count, item), ...] sorted by count
427
+ """
428
+ from collections import Counter
429
+ if isinstance(items, str):
430
+ items = items.splitlines()
431
+ counts = Counter(items)
432
+ sorted_items = sorted(counts.items(), key=lambda x: (x[1], x[0]), reverse=reverse)
433
+ if limit is not None:
434
+ sorted_items = sorted_items[:limit]
435
+ result = [(count, item) for item, count in sorted_items]
436
+ _emit_status("counter", unique=len(counts), total=sum(counts.values()), top=result[:10])
437
+ return result
438
+
439
+ @_category("Text")
440
+ def cols(text: str, *indices: int, sep: str | None = None) -> str:
441
+ """Extract columns from text (0-indexed). Like cut."""
442
+ result_lines = []
443
+ for line in text.splitlines():
444
+ parts = line.split(sep) if sep else line.split()
445
+ selected = [parts[i] for i in indices if i < len(parts)]
446
+ result_lines.append(" ".join(selected))
447
+ out = "\n".join(result_lines)
448
+ _emit_status("cols", lines=len(result_lines), columns=list(indices))
449
+ return out
450
+
451
+ @_category("Navigation")
452
+ def tree(path: str | Path = ".", *, max_depth: int = 3, show_hidden: bool = False) -> str:
453
+ """Return directory tree."""
454
+ base = Path(path)
455
+ lines = []
456
+ def walk(p: Path, prefix: str, depth: int):
457
+ if depth > max_depth:
458
+ return
459
+ items = sorted(p.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower()))
460
+ items = [i for i in items if show_hidden or not i.name.startswith(".")]
461
+ for i, item in enumerate(items):
462
+ is_last = i == len(items) - 1
463
+ connector = "└── " if is_last else "├── "
464
+ suffix = "/" if item.is_dir() else ""
465
+ lines.append(f"{prefix}{connector}{item.name}{suffix}")
466
+ if item.is_dir():
467
+ ext = " " if is_last else "│ "
468
+ walk(item, prefix + ext, depth + 1)
469
+ lines.append(str(base) + "/")
470
+ walk(base, "", 1)
471
+ out = "\n".join(lines)
472
+ _emit_status("tree", path=str(base), entries=len(lines) - 1, preview=out[:1000])
473
+ return out
474
+
475
+ @_category("Navigation")
476
+ def stat(path: str | Path) -> dict:
477
+ """Get file/directory info."""
478
+ p = Path(path)
479
+ s = p.stat()
480
+ info = {
481
+ "path": str(p),
482
+ "size": s.st_size,
483
+ "is_file": p.is_file(),
484
+ "is_dir": p.is_dir(),
485
+ "mtime": datetime.fromtimestamp(s.st_mtime).isoformat(),
486
+ "mode": oct(s.st_mode),
487
+ }
488
+ _emit_status("stat", path=str(p), size=s.st_size, is_dir=p.is_dir(), mtime=info["mtime"])
489
+ return info
490
+
491
+ @_category("Batch")
492
+ def diff(a: str | Path, b: str | Path) -> str:
493
+ """Compare two files, return unified diff."""
494
+ import difflib
495
+ path_a, path_b = Path(a), Path(b)
496
+ lines_a = path_a.read_text(encoding="utf-8").splitlines(keepends=True)
497
+ lines_b = path_b.read_text(encoding="utf-8").splitlines(keepends=True)
498
+ result = difflib.unified_diff(lines_a, lines_b, fromfile=str(path_a), tofile=str(path_b))
499
+ out = "".join(result)
500
+ _emit_status("diff", file_a=str(path_a), file_b=str(path_b), identical=not out, preview=out[:500])
501
+ return out
502
+
503
+ @_category("Search")
504
+ def glob_files(pattern: str, path: str | Path = ".", *, hidden: bool = False) -> list[Path]:
505
+ """Non-recursive glob (use find() for recursive). Respects .gitignore."""
506
+ p = Path(path)
507
+ ignore_patterns = _load_gitignore_patterns(p)
508
+ matches: list[Path] = []
509
+ for m in p.glob(pattern):
510
+ # Skip hidden files unless requested
511
+ if not hidden and m.name.startswith("."):
512
+ continue
513
+ # Skip gitignored paths
514
+ if _match_gitignore(m, ignore_patterns, p):
515
+ continue
516
+ matches.append(m)
517
+ matches = sorted(matches)
518
+ _emit_status("glob", pattern=pattern, path=str(p), count=len(matches), matches=[str(m) for m in matches[:20]])
519
+ return matches
520
+
521
+ @_category("Find/Replace")
522
+ def sed(path: str | Path, pattern: str, repl: str, *, flags: int = 0) -> int:
523
+ """Regex replace in file (like sed -i). Returns count."""
524
+ p = Path(path)
525
+ data = p.read_text(encoding="utf-8")
526
+ new, count = re.subn(pattern, repl, data, flags=flags)
527
+ p.write_text(new, encoding="utf-8")
528
+ _emit_status("sed", path=str(p), count=count)
529
+ return count
530
+
531
+ @_category("Find/Replace")
532
+ def rsed(
533
+ pattern: str,
534
+ repl: str,
535
+ path: str | Path = ".",
536
+ *,
537
+ glob_pattern: str = "*",
538
+ flags: int = 0,
539
+ hidden: bool = False,
540
+ ) -> int:
541
+ """Recursive sed across files matching glob_pattern. Respects .gitignore."""
542
+ base = Path(path)
543
+ ignore_patterns = _load_gitignore_patterns(base)
544
+ total = 0
545
+ files_changed = 0
546
+ changed_files = []
547
+ for file_path in base.rglob(glob_pattern):
548
+ if file_path.is_dir():
549
+ continue
550
+ # Skip hidden files unless requested
551
+ if not hidden and any(part.startswith(".") for part in file_path.parts):
552
+ continue
553
+ # Skip gitignored paths
554
+ if _match_gitignore(file_path, ignore_patterns, base):
555
+ continue
556
+ try:
557
+ data = file_path.read_text(encoding="utf-8")
558
+ new, count = re.subn(pattern, repl, data, flags=flags)
559
+ if count > 0:
560
+ file_path.write_text(new, encoding="utf-8")
561
+ total += count
562
+ files_changed += 1
563
+ if len(changed_files) < 10:
564
+ changed_files.append({"file": str(file_path), "count": count})
565
+ except Exception:
566
+ continue
567
+ _emit_status("rsed", path=str(base), count=total, files=files_changed, changed=changed_files)
568
+ return total
569
+
570
+ @_category("Line ops")
571
+ def lines(path: str | Path, start: int = 1, end: int | None = None) -> str:
572
+ """Extract line range from file (1-indexed, inclusive). Like sed -n 'N,Mp'."""
573
+ p = Path(path)
574
+ all_lines = p.read_text(encoding="utf-8").splitlines()
575
+ if end is None:
576
+ end = len(all_lines)
577
+ start = max(1, start)
578
+ end = min(len(all_lines), end)
579
+ selected = all_lines[start - 1 : end]
580
+ out = "\n".join(selected)
581
+ _emit_status("lines", path=str(p), start=start, end=end, count=len(selected), preview=out[:500])
582
+ return out
583
+
584
+ @_category("Line ops")
585
+ def delete_lines(path: str | Path, start: int, end: int | None = None) -> int:
586
+ """Delete line range from file (1-indexed, inclusive). Like sed -i 'N,Md'."""
587
+ p = Path(path)
588
+ all_lines = p.read_text(encoding="utf-8").splitlines()
589
+ if end is None:
590
+ end = start
591
+ start = max(1, start)
592
+ end = min(len(all_lines), end)
593
+ count = end - start + 1
594
+ new_lines = all_lines[: start - 1] + all_lines[end:]
595
+ p.write_text("\n".join(new_lines) + ("\n" if all_lines else ""), encoding="utf-8")
596
+ _emit_status("delete_lines", path=str(p), start=start, end=end, count=count)
597
+ return count
598
+
599
+ @_category("Line ops")
600
+ def delete_matching(path: str | Path, pattern: str, *, regex: bool = True) -> int:
601
+ """Delete lines matching pattern. Like sed -i '/pattern/d'."""
602
+ p = Path(path)
603
+ all_lines = p.read_text(encoding="utf-8").splitlines()
604
+ if regex:
605
+ rx = re.compile(pattern)
606
+ new_lines = [l for l in all_lines if not rx.search(l)]
607
+ else:
608
+ new_lines = [l for l in all_lines if pattern not in l]
609
+ count = len(all_lines) - len(new_lines)
610
+ p.write_text("\n".join(new_lines) + ("\n" if all_lines else ""), encoding="utf-8")
611
+ _emit_status("delete_matching", path=str(p), pattern=pattern, count=count)
612
+ return count
613
+
614
+ @_category("Line ops")
615
+ def insert_at(path: str | Path, line_num: int, text: str, *, after: bool = True) -> Path:
616
+ """Insert text at line. after=True (sed 'Na\\'), after=False (sed 'Ni\\')."""
617
+ p = Path(path)
618
+ all_lines = p.read_text(encoding="utf-8").splitlines()
619
+ new_lines = text.splitlines()
620
+ line_num = max(1, min(len(all_lines) + 1, line_num))
621
+ if after:
622
+ idx = min(line_num, len(all_lines))
623
+ all_lines = all_lines[:idx] + new_lines + all_lines[idx:]
624
+ pos = "after"
625
+ else:
626
+ idx = line_num - 1
627
+ all_lines = all_lines[:idx] + new_lines + all_lines[idx:]
628
+ pos = "before"
629
+ p.write_text("\n".join(all_lines) + "\n", encoding="utf-8")
630
+ _emit_status("insert_at", path=str(p), line=line_num, lines_inserted=len(new_lines), position=pos)
631
+ return p
632
+
633
+ @_category("Agent")
634
+ def output(
635
+ *ids: str,
636
+ format: str = "raw",
637
+ query: str | None = None,
638
+ offset: int | None = None,
639
+ limit: int | None = None,
640
+ ) -> str | dict | list[dict]:
641
+ """Read task/agent output by ID. Returns text or JSON depending on format.
642
+
643
+ Args:
644
+ *ids: Output IDs to read (e.g., 'explore_0', 'reviewer_1')
645
+ format: 'raw' (default), 'json' (dict with metadata), 'stripped' (no ANSI)
646
+ query: jq-like query for JSON outputs (e.g., '.endpoints[0].file')
647
+ offset: Line number to start reading from (1-indexed)
648
+ limit: Maximum number of lines to read
649
+
650
+ Returns:
651
+ Single ID: str (format='raw'/'stripped') or dict (format='json')
652
+ Multiple IDs: list of dict with 'id' and 'content'/'data' keys
653
+
654
+ Examples:
655
+ output('explore_0') # Read as raw text
656
+ output('reviewer_0', format='json') # Read with metadata
657
+ output('explore_0', query='.files[0]') # Extract JSON field
658
+ output('explore_0', offset=10, limit=20) # Lines 10-29
659
+ output('explore_0', 'reviewer_1') # Read multiple outputs
660
+ """
661
+ session_file = os.environ.get("PI_SESSION_FILE")
662
+ if not session_file:
663
+ _emit_status("output", error="No session file available")
664
+ raise RuntimeError("No session - output artifacts unavailable")
665
+
666
+ artifacts_dir = session_file.rsplit(".", 1)[0] # Strip .jsonl extension
667
+ if not Path(artifacts_dir).exists():
668
+ _emit_status("output", error="Artifacts directory not found", path=artifacts_dir)
669
+ raise RuntimeError(f"No artifacts directory found: {artifacts_dir}")
670
+
671
+ if not ids:
672
+ _emit_status("output", error="No IDs provided")
673
+ raise ValueError("At least one output ID is required")
674
+
675
+ if query and (offset is not None or limit is not None):
676
+ _emit_status("output", error="query cannot be combined with offset/limit")
677
+ raise ValueError("query cannot be combined with offset/limit")
678
+
679
+ results: list[dict] = []
680
+ not_found: list[str] = []
681
+
682
+ for output_id in ids:
683
+ output_path = Path(artifacts_dir) / f"{output_id}.md"
684
+ if not output_path.exists():
685
+ not_found.append(output_id)
686
+ continue
687
+
688
+ raw_content = output_path.read_text(encoding="utf-8")
689
+ raw_lines = raw_content.splitlines()
690
+ total_lines = len(raw_lines)
691
+
692
+ selected_content = raw_content
693
+ range_info: dict | None = None
694
+
695
+ # Handle query
696
+ if query:
697
+ try:
698
+ json_value = json.loads(raw_content)
699
+ except json.JSONDecodeError as e:
700
+ _emit_status("output", id=output_id, error=f"Not valid JSON: {e}")
701
+ raise ValueError(f"Output {output_id} is not valid JSON: {e}")
702
+
703
+ # Apply jq-like query
704
+ result_value = _apply_query(json_value, query)
705
+ try:
706
+ selected_content = json.dumps(result_value, indent=2) if result_value is not None else "null"
707
+ except (TypeError, ValueError):
708
+ selected_content = str(result_value)
709
+
710
+ # Handle offset/limit
711
+ elif offset is not None or limit is not None:
712
+ start_line = max(1, offset or 1)
713
+ if start_line > total_lines:
714
+ _emit_status("output", id=output_id, error=f"Offset {start_line} beyond end ({total_lines} lines)")
715
+ raise ValueError(f"Offset {start_line} is beyond end of output ({total_lines} lines) for {output_id}")
716
+
717
+ effective_limit = limit if limit is not None else total_lines - start_line + 1
718
+ end_line = min(total_lines, start_line + effective_limit - 1)
719
+ selected_lines = raw_lines[start_line - 1 : end_line]
720
+ selected_content = "\n".join(selected_lines)
721
+ range_info = {"start_line": start_line, "end_line": end_line, "total_lines": total_lines}
722
+
723
+ # Strip ANSI codes if requested
724
+ if format == "stripped":
725
+ import re
726
+ selected_content = re.sub(r"\x1b\[[0-9;]*m", "", selected_content)
727
+
728
+ # Build result
729
+ if format == "json":
730
+ result_data = {
731
+ "id": output_id,
732
+ "path": str(output_path),
733
+ "line_count": total_lines if not query else len(selected_content.splitlines()),
734
+ "char_count": len(raw_content) if not query else len(selected_content),
735
+ "content": selected_content,
736
+ }
737
+ if range_info:
738
+ result_data["range"] = range_info
739
+ if query:
740
+ result_data["query"] = query
741
+ results.append(result_data)
742
+ else:
743
+ results.append({"id": output_id, "content": selected_content})
744
+
745
+ # Handle not found
746
+ if not_found:
747
+ available = sorted(
748
+ [f.stem for f in Path(artifacts_dir).glob("*.md")]
749
+ )
750
+ error_msg = f"Output not found: {', '.join(not_found)}"
751
+ if available:
752
+ error_msg += f"\n\nAvailable outputs: {', '.join(available[:20])}"
753
+ if len(available) > 20:
754
+ error_msg += f" (and {len(available) - 20} more)"
755
+ _emit_status("output", not_found=not_found, available_count=len(available))
756
+ raise FileNotFoundError(error_msg)
757
+
758
+ # Return format
759
+ if len(ids) == 1:
760
+ if format == "json":
761
+ _emit_status("output", id=ids[0], chars=results[0]["char_count"])
762
+ return results[0]
763
+ _emit_status("output", id=ids[0], chars=len(results[0]["content"]))
764
+ return results[0]["content"]
765
+
766
+ # Multiple IDs
767
+ if format == "json":
768
+ total_chars = sum(r["char_count"] for r in results)
769
+ _emit_status("output", count=len(results), total_chars=total_chars)
770
+ return results
771
+
772
+ combined_output: list[dict] = []
773
+ for r in results:
774
+ combined_output.append({"id": r["id"], "content": r["content"]})
775
+ total_chars = sum(len(r["content"]) for r in combined_output)
776
+ _emit_status("output", count=len(combined_output), total_chars=total_chars)
777
+ return combined_output
778
+
779
+ def _apply_query(data: any, query: str) -> any:
780
+ """Apply jq-like query to data. Supports .key, [index], and chaining."""
781
+ if not query:
782
+ return data
783
+
784
+ query = query.strip()
785
+ if query.startswith("."):
786
+ query = query[1:]
787
+ if not query:
788
+ return data
789
+
790
+ # Parse query into tokens
791
+ tokens = []
792
+ current_token = ""
793
+ i = 0
794
+ while i < len(query):
795
+ ch = query[i]
796
+ if ch == ".":
797
+ if current_token:
798
+ tokens.append(("key", current_token))
799
+ current_token = ""
800
+ elif ch == "[":
801
+ if current_token:
802
+ tokens.append(("key", current_token))
803
+ current_token = ""
804
+ # Find matching ]
805
+ j = i + 1
806
+ while j < len(query) and query[j] != "]":
807
+ j += 1
808
+ bracket_content = query[i+1:j]
809
+ if bracket_content.startswith('"') and bracket_content.endswith('"'):
810
+ tokens.append(("key", bracket_content[1:-1]))
811
+ else:
812
+ tokens.append(("index", int(bracket_content)))
813
+ i = j
814
+ else:
815
+ current_token += ch
816
+ i += 1
817
+ if current_token:
818
+ tokens.append(("key", current_token))
819
+
820
+ # Apply tokens
821
+ current = data
822
+ for token_type, value in tokens:
823
+ if token_type == "index":
824
+ if not isinstance(current, list) or value >= len(current):
825
+ return None
826
+ current = current[value]
827
+ elif token_type == "key":
828
+ if not isinstance(current, dict) or value not in current:
829
+ return None
830
+ current = current[value]
831
+
832
+ return current
833
+
834
+ def __xcsh_prelude_docs__() -> list[dict[str, str]]:
835
+ """Return prelude helper docs for templating. Discovers functions by _xcsh_category attribute."""
836
+ helpers: list[dict[str, str]] = []
837
+ for name, obj in globals().items():
838
+ if not callable(obj) or not hasattr(obj, "_xcsh_category"):
839
+ continue
840
+ signature = str(inspect.signature(obj))
841
+ doc = inspect.getdoc(obj) or ""
842
+ docline = doc.splitlines()[0] if doc else ""
843
+ helpers.append({
844
+ "name": name,
845
+ "signature": signature,
846
+ "docstring": docline,
847
+ "category": obj._xcsh_category,
848
+ })
849
+ return sorted(helpers, key=lambda h: (h["category"], h["name"]))