ashlr-plugin 1.36.4

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 (499) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.claude-plugin/marketplace.json +39 -0
  3. package/.claude-plugin/plugin.json +36 -0
  4. package/.codex/agents/README.md +9 -0
  5. package/.codex/agents/ashlr-explorer.md +36 -0
  6. package/.codex/agents/ashlr-worker.md +38 -0
  7. package/.codex-plugin/plugin.json +45 -0
  8. package/.mcp.json +14 -0
  9. package/LICENSE +21 -0
  10. package/README.md +311 -0
  11. package/agents/ashlr-code.md +69 -0
  12. package/agents/ashlr-explore.md +44 -0
  13. package/agents/ashlr-plan.md +54 -0
  14. package/bench/fixtures/notebook-large.ipynb +660 -0
  15. package/bench/fixtures/notebook-small.ipynb +39 -0
  16. package/bench/fixtures/tasklist-closed.json +62 -0
  17. package/bench/fixtures/tasklist-large-mixed.json +27 -0
  18. package/bench/fixtures/tasklist-sprint-open.json +79 -0
  19. package/bench/fixtures/websearch-bun-runtime.json +32 -0
  20. package/bench/fixtures/websearch-react-hooks-patterns.json +32 -0
  21. package/bench/fixtures/websearch-typescript-generics.json +38 -0
  22. package/bench/refs/node-sdk/.refrev +1 -0
  23. package/bench/refs/node-sdk/README.md +17 -0
  24. package/bench/refs/node-sdk/src/agent/agent.ts +163 -0
  25. package/bench/refs/node-sdk/src/agent/create-agent-ui-stream.ts +83 -0
  26. package/bench/refs/node-sdk/src/agent/tool-loop-agent.ts +238 -0
  27. package/bench/refs/node-sdk/src/embed/embed-many.ts +409 -0
  28. package/bench/refs/node-sdk/src/embed/embed-result.ts +50 -0
  29. package/bench/refs/node-sdk/src/embed/embed.ts +257 -0
  30. package/bench/refs/node-sdk/src/error/invalid-argument-error.ts +34 -0
  31. package/bench/refs/node-sdk/src/error/invalid-tool-input-error.ts +33 -0
  32. package/bench/refs/node-sdk/src/error/no-object-generated-error.ts +70 -0
  33. package/bench/refs/node-sdk/src/generate-image/generate-image-result.ts +42 -0
  34. package/bench/refs/node-sdk/src/generate-image/generate-image.ts +362 -0
  35. package/bench/refs/node-sdk/src/generate-object/generate-object-result.ts +67 -0
  36. package/bench/refs/node-sdk/src/generate-object/generate-object.ts +501 -0
  37. package/bench/refs/node-sdk/src/generate-object/inject-json-instruction.ts +30 -0
  38. package/bench/refs/node-sdk/src/generate-object/output-strategy.ts +415 -0
  39. package/bench/refs/node-sdk/src/generate-object/repair-text.ts +12 -0
  40. package/bench/refs/node-sdk/src/generate-object/stream-object.ts +960 -0
  41. package/bench/refs/node-sdk/src/generate-speech/generate-speech.ts +191 -0
  42. package/bench/refs/node-sdk/src/generate-text/generate-text.ts +1484 -0
  43. package/bench/refs/node-sdk/src/generate-text/stream-text.ts +2708 -0
  44. package/bench/refs/node-sdk/src/generate-text/tool-call.ts +59 -0
  45. package/bench/refs/node-sdk/src/generate-text/tool-result.ts +36 -0
  46. package/bench/refs/node-sdk/src/telemetry/create-telemetry-dispatcher.ts +146 -0
  47. package/bench/refs/node-sdk/src/telemetry/telemetry-registry.ts +15 -0
  48. package/bench/refs/node-sdk/src/telemetry/telemetry.ts +223 -0
  49. package/bench/refs/node-sdk/src/util/async-iterable-stream.ts +94 -0
  50. package/bench/refs/node-sdk/src/util/consume-stream.ts +31 -0
  51. package/bench/refs/node-sdk/src/util/create-stitchable-stream.ts +112 -0
  52. package/bench/refs/node-sdk/src/util/download/download.ts +74 -0
  53. package/bench/refs/node-sdk/src/util/error-handler.ts +1 -0
  54. package/bench/refs/node-sdk/src/util/fix-json.ts +401 -0
  55. package/bench/refs/node-sdk/src/util/merge-objects.ts +79 -0
  56. package/bench/refs/python-lib/.refrev +1 -0
  57. package/bench/refs/python-lib/README.md +18 -0
  58. package/bench/refs/python-lib/pandas/core/_numba/executor.py +249 -0
  59. package/bench/refs/python-lib/pandas/core/_numba/extensions.py +586 -0
  60. package/bench/refs/python-lib/pandas/core/_numba/kernels/mean_.py +198 -0
  61. package/bench/refs/python-lib/pandas/core/_numba/kernels/min_max_.py +178 -0
  62. package/bench/refs/python-lib/pandas/core/_numba/kernels/sum_.py +255 -0
  63. package/bench/refs/python-lib/pandas/core/_numba/kernels/var_.py +251 -0
  64. package/bench/refs/python-lib/pandas/core/accessor.py +520 -0
  65. package/bench/refs/python-lib/pandas/core/api.py +138 -0
  66. package/bench/refs/python-lib/pandas/core/array_algos/masked_accumulations.py +97 -0
  67. package/bench/refs/python-lib/pandas/core/array_algos/masked_reductions.py +252 -0
  68. package/bench/refs/python-lib/pandas/core/array_algos/putmask.py +150 -0
  69. package/bench/refs/python-lib/pandas/core/array_algos/quantile.py +232 -0
  70. package/bench/refs/python-lib/pandas/core/array_algos/replace.py +159 -0
  71. package/bench/refs/python-lib/pandas/core/array_algos/take.py +609 -0
  72. package/bench/refs/python-lib/pandas/core/arraylike.py +534 -0
  73. package/bench/refs/python-lib/pandas/core/arrays/_arrow_string_mixins.py +434 -0
  74. package/bench/refs/python-lib/pandas/core/arrays/_mixins.py +630 -0
  75. package/bench/refs/python-lib/pandas/core/arrays/_ranges.py +276 -0
  76. package/bench/refs/python-lib/pandas/core/arrays/_utils.py +77 -0
  77. package/bench/refs/python-lib/pandas/core/arrays/arrow/accessors.py +521 -0
  78. package/bench/refs/python-lib/pandas/core/arrays/arrow/extension_types.py +174 -0
  79. package/bench/refs/python-lib/pandas/core/arrays/boolean.py +454 -0
  80. package/bench/refs/python-lib/pandas/core/arrays/floating.py +192 -0
  81. package/bench/refs/python-lib/pandas/core/arrays/integer.py +296 -0
  82. package/bench/refs/python-lib/pandas/core/arrays/masked.py +2140 -0
  83. package/bench/refs/python-lib/pandas/core/arrays/numeric.py +305 -0
  84. package/bench/refs/python-lib/pandas/core/arrays/numpy_.py +701 -0
  85. package/bench/refs/python-lib/pandas/core/arrays/period.py +1586 -0
  86. package/bench/refs/python-lib/pandas/core/arrays/sparse/accessor.py +505 -0
  87. package/bench/refs/python-lib/pandas/core/arrays/sparse/scipy_sparse.py +208 -0
  88. package/bench/refs/rust-project/.refrev +1 -0
  89. package/bench/refs/rust-project/README.md +17 -0
  90. package/bench/refs/rust-project/tokio/src/doc/os.rs +68 -0
  91. package/bench/refs/rust-project/tokio/src/fs/dir_builder.rs +129 -0
  92. package/bench/refs/rust-project/tokio/src/fs/file.rs +1113 -0
  93. package/bench/refs/rust-project/tokio/src/fs/mocks.rs +176 -0
  94. package/bench/refs/rust-project/tokio/src/fs/mod.rs +324 -0
  95. package/bench/refs/rust-project/tokio/src/fs/open_options.rs +856 -0
  96. package/bench/refs/rust-project/tokio/src/fs/read.rs +80 -0
  97. package/bench/refs/rust-project/tokio/src/fs/read_dir.rs +357 -0
  98. package/bench/refs/rust-project/tokio/src/fs/write.rs +99 -0
  99. package/bench/refs/rust-project/tokio/src/future/maybe_done.rs +123 -0
  100. package/bench/refs/rust-project/tokio/src/future/try_join.rs +82 -0
  101. package/bench/refs/rust-project/tokio/src/io/async_buf_read.rs +117 -0
  102. package/bench/refs/rust-project/tokio/src/io/async_read.rs +133 -0
  103. package/bench/refs/rust-project/tokio/src/io/async_seek.rs +96 -0
  104. package/bench/refs/rust-project/tokio/src/io/async_write.rs +402 -0
  105. package/bench/refs/rust-project/tokio/src/io/blocking.rs +339 -0
  106. package/bench/refs/rust-project/tokio/src/io/interest.rs +345 -0
  107. package/bench/refs/rust-project/tokio/src/io/join.rs +130 -0
  108. package/bench/refs/rust-project/tokio/src/io/mod.rs +308 -0
  109. package/bench/refs/rust-project/tokio/src/io/poll_evented.rs +319 -0
  110. package/bench/refs/rust-project/tokio/src/io/read_buf.rs +344 -0
  111. package/bench/refs/rust-project/tokio/src/io/ready.rs +322 -0
  112. package/bench/refs/rust-project/tokio/src/io/split.rs +166 -0
  113. package/bench/refs/rust-project/tokio/src/io/stderr.rs +148 -0
  114. package/bench/refs/rust-project/tokio/src/io/stdin.rs +98 -0
  115. package/bench/refs/rust-project/tokio/src/io/stdio_common.rs +222 -0
  116. package/bench/refs/rust-project/tokio/src/io/stdout.rs +197 -0
  117. package/bench/refs/rust-project/tokio/src/io/util/buf_reader.rs +311 -0
  118. package/bench/refs/rust-project/tokio/src/io/util/buf_stream.rs +207 -0
  119. package/bench/refs/rust-project/tokio/src/io/util/buf_writer.rs +310 -0
  120. package/bench/refs/rust-project/tokio/src/io/util/chain.rs +144 -0
  121. package/commands/_spawn-patterns.json +32 -0
  122. package/commands/ashlr-allow.md +21 -0
  123. package/commands/ashlr-benchmark.md +53 -0
  124. package/commands/ashlr-brief.md +97 -0
  125. package/commands/ashlr-budget.md +76 -0
  126. package/commands/ashlr-compact.md +54 -0
  127. package/commands/ashlr-dashboard.md +37 -0
  128. package/commands/ashlr-doctor.md +56 -0
  129. package/commands/ashlr-eco-mode.md +92 -0
  130. package/commands/ashlr-genome-init.md +24 -0
  131. package/commands/ashlr-genome-keygen.md +36 -0
  132. package/commands/ashlr-genome-loop.md +118 -0
  133. package/commands/ashlr-genome-push.md +36 -0
  134. package/commands/ashlr-genome-rewrap.md +48 -0
  135. package/commands/ashlr-genome-team-init.md +67 -0
  136. package/commands/ashlr-handoff.md +23 -0
  137. package/commands/ashlr-help.md +86 -0
  138. package/commands/ashlr-hook-timings.md +30 -0
  139. package/commands/ashlr-leaderboard.md +50 -0
  140. package/commands/ashlr-ollama-setup.md +39 -0
  141. package/commands/ashlr-orchestrate-status.md +72 -0
  142. package/commands/ashlr-orchestrate.md +83 -0
  143. package/commands/ashlr-parallelize.md +63 -0
  144. package/commands/ashlr-report-crash.md +33 -0
  145. package/commands/ashlr-resume.md +72 -0
  146. package/commands/ashlr-savings.md +24 -0
  147. package/commands/ashlr-settings.md +50 -0
  148. package/commands/ashlr-spawn.md +61 -0
  149. package/commands/ashlr-start.md +60 -0
  150. package/commands/ashlr-status.md +64 -0
  151. package/commands/ashlr-team-invite.md +47 -0
  152. package/commands/ashlr-tier.md +122 -0
  153. package/commands/ashlr-tour.md +60 -0
  154. package/commands/ashlr-update.md +155 -0
  155. package/commands/ashlr-upgrade.md +96 -0
  156. package/commands/goal.md +58 -0
  157. package/commands/loop.md +40 -0
  158. package/docs/CNAME +1 -0
  159. package/docs/PRO_TIER.md +104 -0
  160. package/docs/README.md +21 -0
  161. package/docs/architecture.md +415 -0
  162. package/docs/ashlr-pipe.md +161 -0
  163. package/docs/assets/logo.svg +19 -0
  164. package/docs/assets/og.png +0 -0
  165. package/docs/assets/og.svg +41 -0
  166. package/docs/benchmarks-v2.json +355 -0
  167. package/docs/benchmarks.json +102 -0
  168. package/docs/benchmarks.md +211 -0
  169. package/docs/billing.md +185 -0
  170. package/docs/cloud-genome.md +155 -0
  171. package/docs/competitive-wozcode.md +92 -0
  172. package/docs/deploy.md +325 -0
  173. package/docs/email-templates.md +113 -0
  174. package/docs/embed-tuning.md +103 -0
  175. package/docs/genome.md +120 -0
  176. package/docs/github-oauth-onboarding.md +127 -0
  177. package/docs/hero-video-script.md +129 -0
  178. package/docs/index.html +2262 -0
  179. package/docs/install-prompt.md +78 -0
  180. package/docs/install-windows.md +132 -0
  181. package/docs/install.ps1 +171 -0
  182. package/docs/install.sh +146 -0
  183. package/docs/launch/README.md +114 -0
  184. package/docs/launch/hn.md +49 -0
  185. package/docs/launch/reddit.md +45 -0
  186. package/docs/launch/x.md +65 -0
  187. package/docs/launch-post.md +112 -0
  188. package/docs/legal.md +78 -0
  189. package/docs/llm-providers.md +99 -0
  190. package/docs/multi-host-mcp.md +217 -0
  191. package/docs/multi-turn-architecture.md +108 -0
  192. package/docs/operations/deployment.md +108 -0
  193. package/docs/operations/error-monitoring.md +70 -0
  194. package/docs/operations/weekly-digest.md +70 -0
  195. package/docs/operations.md +494 -0
  196. package/docs/platform-support.md +133 -0
  197. package/docs/policy-packs.md +188 -0
  198. package/docs/press-kit/fact-sheet.md +78 -0
  199. package/docs/press-kit/founder-bio.md +3 -0
  200. package/docs/press-kit/logo.svg +33 -0
  201. package/docs/press-kit/screenshots.md +146 -0
  202. package/docs/pricing.md +251 -0
  203. package/docs/pro-backend-architecture.md +523 -0
  204. package/docs/producthunt.md +52 -0
  205. package/docs/router-migration.md +110 -0
  206. package/docs/session-log-schema.md +68 -0
  207. package/docs/social.md +95 -0
  208. package/docs/team-genome.md +528 -0
  209. package/docs/telemetry.md +194 -0
  210. package/docs/test-isolation.md +100 -0
  211. package/docs/upgrade.md +159 -0
  212. package/hooks/_hook-errors.ts +87 -0
  213. package/hooks/_hook-perf-emit.ts +113 -0
  214. package/hooks/_hook-timing-ledger.ts +1133 -0
  215. package/hooks/_nudge-throttle.ts +127 -0
  216. package/hooks/_recent-blocks.ts +127 -0
  217. package/hooks/audit-upload.ts +86 -0
  218. package/hooks/codex-hooks.json +171 -0
  219. package/hooks/commit-attribution.ts +179 -0
  220. package/hooks/edit-batching-nudge.ts +154 -0
  221. package/hooks/genome-scribe-hook.ts +219 -0
  222. package/hooks/hooks.json +294 -0
  223. package/hooks/orient-nudge-hook.ts +242 -0
  224. package/hooks/policy-enforce.ts +214 -0
  225. package/hooks/post-tool-use-embedding.ts +93 -0
  226. package/hooks/post-tool-use-genome.sh +37 -0
  227. package/hooks/post-tool-use-genome.ts +69 -0
  228. package/hooks/posttooluse-correlate.ts +122 -0
  229. package/hooks/posttooluse-dedupe-output.ts +241 -0
  230. package/hooks/posttooluse-genome-refresh.ts +223 -0
  231. package/hooks/posttooluse-native-nudge.ts +205 -0
  232. package/hooks/posttooluse-stale-result.ts +277 -0
  233. package/hooks/pretooluse-bash.ts +63 -0
  234. package/hooks/pretooluse-budget-guard.ts +318 -0
  235. package/hooks/pretooluse-common.ts +985 -0
  236. package/hooks/pretooluse-eco-router.ts +196 -0
  237. package/hooks/pretooluse-edit.sh +93 -0
  238. package/hooks/pretooluse-edit.ts +197 -0
  239. package/hooks/pretooluse-glob.ts +70 -0
  240. package/hooks/pretooluse-grep.sh +85 -0
  241. package/hooks/pretooluse-grep.ts +96 -0
  242. package/hooks/pretooluse-notebookedit.ts +121 -0
  243. package/hooks/pretooluse-read.sh +118 -0
  244. package/hooks/pretooluse-read.ts +118 -0
  245. package/hooks/pretooluse-task.ts +130 -0
  246. package/hooks/pretooluse-webfetch.ts +66 -0
  247. package/hooks/pretooluse-websearch.ts +85 -0
  248. package/hooks/pretooluse-write.ts +128 -0
  249. package/hooks/pulse-emit.ts +197 -0
  250. package/hooks/session-end-consolidate.sh +35 -0
  251. package/hooks/session-end-consolidate.ts +188 -0
  252. package/hooks/session-end-stats-gc.ts +80 -0
  253. package/hooks/session-log-append.sh +94 -0
  254. package/hooks/session-log-append.ts +116 -0
  255. package/hooks/session-start.ts +993 -0
  256. package/hooks/sessionend-hook-health-nudge.ts +451 -0
  257. package/hooks/sessionend-savings-nudge.ts +318 -0
  258. package/hooks/sessionend-status-line-nudge.ts +296 -0
  259. package/hooks/sessionstart-brief.ts +140 -0
  260. package/hooks/sessionstart-cost-refactor.ts +95 -0
  261. package/hooks/sessionstart-efficient.ts +110 -0
  262. package/hooks/sessionstart-genome-author.ts +93 -0
  263. package/hooks/sessionstart-lean-tools.ts +98 -0
  264. package/hooks/sessionstart-search.ts +97 -0
  265. package/hooks/stop-accounting.ts +152 -0
  266. package/hooks/subagent-stop-rollup.ts +162 -0
  267. package/hooks/userpromptsubmit-brief-trigger.ts +156 -0
  268. package/package.json +56 -0
  269. package/ports/README.md +108 -0
  270. package/ports/cursor/mcp.json +11 -0
  271. package/ports/goose/recipe.yaml +26 -0
  272. package/scripts/ashlr-mcp.ts +40 -0
  273. package/scripts/auto-update.ts +177 -0
  274. package/scripts/baseline-scan.ts +831 -0
  275. package/scripts/bench-orchestrate.ts +377 -0
  276. package/scripts/benchmark-refs.ts +292 -0
  277. package/scripts/bootstrap.mjs +100 -0
  278. package/scripts/brief-eval.ts +234 -0
  279. package/scripts/bump-version.ts +82 -0
  280. package/scripts/bun-resolve.d.mts +11 -0
  281. package/scripts/bun-resolve.mjs +59 -0
  282. package/scripts/calibrate-grep.ts +467 -0
  283. package/scripts/capture-grep-workload.ts +260 -0
  284. package/scripts/check-tier.ts +61 -0
  285. package/scripts/check-version-sync.ts +97 -0
  286. package/scripts/cli-orchestrate-status.ts +386 -0
  287. package/scripts/cli-orchestrate.ts +303 -0
  288. package/scripts/cli.ts +478 -0
  289. package/scripts/cloud-smoke-test.ts +313 -0
  290. package/scripts/coach-report.ts +373 -0
  291. package/scripts/context-db-migrate.ts +137 -0
  292. package/scripts/context-status.ts +43 -0
  293. package/scripts/demo-run.ts +255 -0
  294. package/scripts/deploy-smoke.sh +140 -0
  295. package/scripts/doctor.ts +992 -0
  296. package/scripts/embed-file-worker.ts +104 -0
  297. package/scripts/embed-tune.ts +308 -0
  298. package/scripts/errors-report.ts +428 -0
  299. package/scripts/find-test-leak.ts +69 -0
  300. package/scripts/generate-badge.ts +357 -0
  301. package/scripts/genome-auto-consolidate.ts +533 -0
  302. package/scripts/genome-auto-propose.ts +578 -0
  303. package/scripts/genome-cloud-pull.ts +363 -0
  304. package/scripts/genome-cloud-push.ts +382 -0
  305. package/scripts/genome-cloud-sync.ts +587 -0
  306. package/scripts/genome-commit-watcher.ts +295 -0
  307. package/scripts/genome-init.ts +986 -0
  308. package/scripts/genome-key.ts +233 -0
  309. package/scripts/genome-keygen.ts +168 -0
  310. package/scripts/genome-link.ts +59 -0
  311. package/scripts/genome-refresh-worker.ts +364 -0
  312. package/scripts/genome-rewrap.ts +90 -0
  313. package/scripts/genome-synthesizer.ts +679 -0
  314. package/scripts/genome-team-init.ts +312 -0
  315. package/scripts/handoff-pack.ts +438 -0
  316. package/scripts/hook-bootstrap.mjs +75 -0
  317. package/scripts/hook-timing-reader.ts +371 -0
  318. package/scripts/hook-timings-report.ts +554 -0
  319. package/scripts/install-genome-hooks.ts +196 -0
  320. package/scripts/install-onnx-model.ts +154 -0
  321. package/scripts/install-permissions.ts +276 -0
  322. package/scripts/install-status-line.ts +150 -0
  323. package/scripts/mcp-entrypoint.sh +78 -0
  324. package/scripts/mcp-entrypoint.ts +130 -0
  325. package/scripts/mdx-angle-bracket-lint.ts +152 -0
  326. package/scripts/measure-cold-start.ts +126 -0
  327. package/scripts/migrate-stats-to-sqlite.ts +86 -0
  328. package/scripts/ollama-setup.ts +498 -0
  329. package/scripts/onboarding-wizard.ts +1691 -0
  330. package/scripts/orchestrate-emit-telemetry.ts +177 -0
  331. package/scripts/orchestrate-expand.ts +517 -0
  332. package/scripts/orchestrate-run.ts +744 -0
  333. package/scripts/print-legend.ts +50 -0
  334. package/scripts/product-metadata.ts +38 -0
  335. package/scripts/prune-old-memories.ts +208 -0
  336. package/scripts/publish.sh +88 -0
  337. package/scripts/read-calibration.ts +122 -0
  338. package/scripts/report-crash.ts +226 -0
  339. package/scripts/run-benchmark.ts +750 -0
  340. package/scripts/run-root-tests.ts +28 -0
  341. package/scripts/savings-dashboard.ts +1258 -0
  342. package/scripts/savings-report-extras.ts +447 -0
  343. package/scripts/savings-status-line.ts +873 -0
  344. package/scripts/session-event-emit.ts +266 -0
  345. package/scripts/session-greet.ts +686 -0
  346. package/scripts/session-log-report.ts +551 -0
  347. package/scripts/session-resume.ts +614 -0
  348. package/scripts/set-hook-mode.ts +83 -0
  349. package/scripts/smoke-cross-platform.ts +117 -0
  350. package/scripts/smoke-realtime.ts +257 -0
  351. package/scripts/smoke-tools.ts +21 -0
  352. package/scripts/stats-cloud-pull.ts +213 -0
  353. package/scripts/stats-cloud-sync.ts +261 -0
  354. package/scripts/telemetry-flush.ts +160 -0
  355. package/scripts/telemetry-status.ts +266 -0
  356. package/scripts/timing-budget.ts +35 -0
  357. package/scripts/ui-animation.ts +120 -0
  358. package/scripts/ui.ts +431 -0
  359. package/scripts/upgrade-flow.ts +775 -0
  360. package/scripts/weekly-digest.ts +394 -0
  361. package/servers/_accounting.ts +78 -0
  362. package/servers/_ask-router.ts +84 -0
  363. package/servers/_ast-chunker.ts +434 -0
  364. package/servers/_ast-helpers.ts +183 -0
  365. package/servers/_ast-languages.ts +153 -0
  366. package/servers/_ast-refactor/_shared.ts +221 -0
  367. package/servers/_ast-refactor/cross-file-rename.ts +560 -0
  368. package/servers/_ast-refactor/extract-function.ts +357 -0
  369. package/servers/_ast-refactor/file-local-rename.ts +172 -0
  370. package/servers/_ast-refactor.ts +41 -0
  371. package/servers/_ast-skeleton.ts +107 -0
  372. package/servers/_bash-summarizers-registry.ts +1096 -0
  373. package/servers/_crash-dump.ts +210 -0
  374. package/servers/_cwd-clamp.ts +342 -0
  375. package/servers/_edit-log.ts +28 -0
  376. package/servers/_edit-match.ts +236 -0
  377. package/servers/_edit-validate.ts +196 -0
  378. package/servers/_embed-calibration.ts +123 -0
  379. package/servers/_embedding-cache.ts +401 -0
  380. package/servers/_embedding-model.ts +329 -0
  381. package/servers/_events.ts +113 -0
  382. package/servers/_genome-cache.ts +154 -0
  383. package/servers/_genome-commits.ts +172 -0
  384. package/servers/_genome-crypto-v2.ts +242 -0
  385. package/servers/_genome-crypto.ts +259 -0
  386. package/servers/_genome-discoveries.ts +140 -0
  387. package/servers/_genome-embed-populator.ts +216 -0
  388. package/servers/_genome-freshness.ts +134 -0
  389. package/servers/_genome-issues.ts +171 -0
  390. package/servers/_genome-live.ts +263 -0
  391. package/servers/_genome-prs.ts +188 -0
  392. package/servers/_genome-search.ts +479 -0
  393. package/servers/_genome-sync.ts +297 -0
  394. package/servers/_history-tracker.ts +279 -0
  395. package/servers/_http-helpers.ts +151 -0
  396. package/servers/_identity-hash.ts +151 -0
  397. package/servers/_llm-providers/anthropic.ts +132 -0
  398. package/servers/_llm-providers/cloud.ts +195 -0
  399. package/servers/_llm-providers/index.ts +350 -0
  400. package/servers/_llm-providers/local.ts +127 -0
  401. package/servers/_llm-providers/onnx.ts +393 -0
  402. package/servers/_llm-providers/types.ts +27 -0
  403. package/servers/_manifest-v2.ts +447 -0
  404. package/servers/_mcp-host.ts +93 -0
  405. package/servers/_nudge-events.ts +451 -0
  406. package/servers/_orchestrate-executor.ts +316 -0
  407. package/servers/_prefetch.ts +435 -0
  408. package/servers/_pricing.ts +256 -0
  409. package/servers/_pro.ts +381 -0
  410. package/servers/_read-cache.ts +44 -0
  411. package/servers/_router-handlers.ts +46 -0
  412. package/servers/_router.ts +55 -0
  413. package/servers/_run-with-timeout.ts +173 -0
  414. package/servers/_savings-render.ts +214 -0
  415. package/servers/_stats-sqlite.ts +640 -0
  416. package/servers/_stats.ts +1183 -0
  417. package/servers/_status-line-cells.ts +469 -0
  418. package/servers/_streaks.ts +162 -0
  419. package/servers/_summarize.ts +208 -0
  420. package/servers/_task-graph-render.ts +217 -0
  421. package/servers/_task-graph.ts +545 -0
  422. package/servers/_telemetry.ts +719 -0
  423. package/servers/_test-parsers.ts +530 -0
  424. package/servers/_test-watch.ts +626 -0
  425. package/servers/_text-helpers.ts +37 -0
  426. package/servers/_token-measure.ts +160 -0
  427. package/servers/_tool-base.ts +248 -0
  428. package/servers/_weekly-digest.ts +391 -0
  429. package/servers/ask-server-handlers.ts +49 -0
  430. package/servers/ask-server.ts +174 -0
  431. package/servers/bash-server-handlers.ts +138 -0
  432. package/servers/bash-server.ts +1136 -0
  433. package/servers/bench.ts +186 -0
  434. package/servers/diff-semantic-server-handlers.ts +39 -0
  435. package/servers/diff-semantic-server.ts +566 -0
  436. package/servers/diff-server-handlers.ts +317 -0
  437. package/servers/diff-server.ts +20 -0
  438. package/servers/edit-server-handlers.ts +31 -0
  439. package/servers/edit-server.ts +209 -0
  440. package/servers/edit-structural-server-handlers.ts +322 -0
  441. package/servers/efficiency-server-handlers.ts +161 -0
  442. package/servers/efficiency-server.ts +1135 -0
  443. package/servers/flush-server-handlers.ts +21 -0
  444. package/servers/flush-server.ts +19 -0
  445. package/servers/genome-server-handlers.ts +118 -0
  446. package/servers/genome-server.ts +397 -0
  447. package/servers/github-server-handlers.ts +187 -0
  448. package/servers/github-server.ts +856 -0
  449. package/servers/glob-server-handlers.ts +233 -0
  450. package/servers/glob-server.ts +20 -0
  451. package/servers/grep-server-handlers.ts +61 -0
  452. package/servers/grep-server.ts +564 -0
  453. package/servers/http-server-handlers.ts +36 -0
  454. package/servers/http-server.ts +149 -0
  455. package/servers/logs-server-handlers.ts +42 -0
  456. package/servers/logs-server.ts +359 -0
  457. package/servers/ls-server-handlers.ts +166 -0
  458. package/servers/ls-server.ts +20 -0
  459. package/servers/multi-edit-server-handlers.ts +51 -0
  460. package/servers/multi-edit-server.ts +422 -0
  461. package/servers/notebook-edit-server-handlers.ts +34 -0
  462. package/servers/notebook-edit-server.ts +181 -0
  463. package/servers/orient-server-handlers.ts +52 -0
  464. package/servers/orient-server.ts +436 -0
  465. package/servers/pipe-server-handlers.ts +68 -0
  466. package/servers/pipe-server.ts +300 -0
  467. package/servers/read-server-handlers.ts +42 -0
  468. package/servers/read-server.ts +206 -0
  469. package/servers/rename-file-server-handlers.ts +67 -0
  470. package/servers/rename-file-server.ts +699 -0
  471. package/servers/savings-server-handlers.ts +27 -0
  472. package/servers/savings-server.ts +54 -0
  473. package/servers/search-replace-regex-server-handlers.ts +96 -0
  474. package/servers/search-replace-regex-server.ts +751 -0
  475. package/servers/sql-server-handlers.ts +58 -0
  476. package/servers/sql-server.ts +505 -0
  477. package/servers/task-server-handlers.ts +358 -0
  478. package/servers/task-server.ts +24 -0
  479. package/servers/test-server-handlers.ts +351 -0
  480. package/servers/test-server.ts +20 -0
  481. package/servers/tree-server-handlers.ts +503 -0
  482. package/servers/tree-server.ts +20 -0
  483. package/servers/webfetch-server-handlers.ts +166 -0
  484. package/servers/webfetch-server.ts +20 -0
  485. package/servers/websearch-server-handlers.ts +215 -0
  486. package/servers/websearch-server.ts +19 -0
  487. package/servers/write-server-handlers.ts +27 -0
  488. package/servers/write-server.ts +97 -0
  489. package/skills/ashlr-brief/SKILL.md +80 -0
  490. package/skills/ashlr-codex-doctor/SKILL.md +21 -0
  491. package/skills/ashlr-codex-efficient-tools/SKILL.md +17 -0
  492. package/skills/ashlr-codex-genome-refresh/SKILL.md +20 -0
  493. package/skills/ashlr-codex-parallel-explore/SKILL.md +20 -0
  494. package/skills/ashlr-codex-savings/SKILL.md +17 -0
  495. package/skills/ashlr-cost-refactor/SKILL.md +50 -0
  496. package/skills/ashlr-efficient/SKILL.md +64 -0
  497. package/skills/ashlr-genome-author/SKILL.md +43 -0
  498. package/skills/ashlr-lean-tools/SKILL.md +43 -0
  499. package/skills/ashlr-search/SKILL.md +46 -0
@@ -0,0 +1,80 @@
1
+ use crate::fs::asyncify;
2
+
3
+ use std::{io, path::Path};
4
+
5
+ /// Reads the entire contents of a file into a bytes vector.
6
+ ///
7
+ /// This is an async version of [`std::fs::read`].
8
+ ///
9
+ /// This is a convenience function for using [`File::open`] and [`read_to_end`]
10
+ /// with fewer imports and without an intermediate variable. It pre-allocates a
11
+ /// buffer based on the file size when available, so it is generally faster than
12
+ /// reading into a vector created with `Vec::new()`.
13
+ ///
14
+ /// This operation is implemented by running the equivalent blocking operation
15
+ /// on a separate thread pool using [`spawn_blocking`].
16
+ ///
17
+ /// [`File::open`]: super::File::open
18
+ /// [`read_to_end`]: crate::io::AsyncReadExt::read_to_end
19
+ /// [`spawn_blocking`]: crate::task::spawn_blocking
20
+ ///
21
+ /// # Errors
22
+ ///
23
+ /// This function will return an error if `path` does not already exist.
24
+ /// Other errors may also be returned according to [`OpenOptions::open`].
25
+ ///
26
+ /// [`OpenOptions::open`]: super::OpenOptions::open
27
+ ///
28
+ /// It will also return an error if it encounters while reading an error
29
+ /// of a kind other than [`ErrorKind::Interrupted`].
30
+ ///
31
+ /// [`ErrorKind::Interrupted`]: std::io::ErrorKind::Interrupted
32
+ ///
33
+ /// # io_uring support
34
+ ///
35
+ /// On Linux, you can also use io_uring for executing system calls. To enable
36
+ /// io_uring, you need to specify the `--cfg tokio_unstable` flag at compile time,
37
+ /// enable the io-uring cargo feature, and set the `Builder::enable_io_uring`
38
+ /// runtime option.
39
+ ///
40
+ /// Support for io_uring is currently experimental, so its behavior may change
41
+ /// or it may be removed in future versions.
42
+ ///
43
+ /// # Examples
44
+ ///
45
+ /// ```no_run
46
+ /// use tokio::fs;
47
+ /// use std::net::SocketAddr;
48
+ ///
49
+ /// #[tokio::main]
50
+ /// async fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
51
+ /// let contents = fs::read("address.txt").await?;
52
+ /// let foo: SocketAddr = String::from_utf8_lossy(&contents).parse()?;
53
+ /// Ok(())
54
+ /// }
55
+ /// ```
56
+ pub async fn read(path: impl AsRef<Path>) -> io::Result<Vec<u8>> {
57
+ let path = path.as_ref().to_owned();
58
+
59
+ #[cfg(all(
60
+ tokio_unstable,
61
+ feature = "io-uring",
62
+ feature = "rt",
63
+ feature = "fs",
64
+ target_os = "linux"
65
+ ))]
66
+ {
67
+ use crate::fs::read_uring;
68
+
69
+ let handle = crate::runtime::Handle::current();
70
+ let driver_handle = handle.inner.driver().io();
71
+ if driver_handle
72
+ .check_and_init(io_uring::opcode::Read::CODE)
73
+ .await?
74
+ {
75
+ return read_uring(&path).await;
76
+ }
77
+ }
78
+
79
+ asyncify(move || std::fs::read(path)).await
80
+ }
@@ -0,0 +1,357 @@
1
+ use crate::fs::asyncify;
2
+
3
+ use std::collections::VecDeque;
4
+ use std::ffi::OsString;
5
+ use std::fs::{FileType, Metadata};
6
+ use std::future::Future;
7
+ use std::io;
8
+ use std::path::{Path, PathBuf};
9
+ use std::pin::Pin;
10
+ use std::sync::Arc;
11
+ use std::task::{ready, Context, Poll};
12
+
13
+ #[cfg(test)]
14
+ use super::mocks::spawn_blocking;
15
+ #[cfg(test)]
16
+ use super::mocks::JoinHandle;
17
+ #[cfg(not(test))]
18
+ use crate::blocking::spawn_blocking;
19
+ #[cfg(not(test))]
20
+ use crate::blocking::JoinHandle;
21
+
22
+ const CHUNK_SIZE: usize = 32;
23
+
24
+ /// Returns a stream over the entries within a directory.
25
+ ///
26
+ /// This is an async version of [`std::fs::read_dir`].
27
+ ///
28
+ /// This operation is implemented by running the equivalent blocking
29
+ /// operation on a separate thread pool using [`spawn_blocking`].
30
+ ///
31
+ /// [`spawn_blocking`]: crate::task::spawn_blocking
32
+ pub async fn read_dir(path: impl AsRef<Path>) -> io::Result<ReadDir> {
33
+ let path = path.as_ref().to_owned();
34
+ asyncify(|| -> io::Result<ReadDir> {
35
+ let mut std = std::fs::read_dir(path)?;
36
+ let mut buf = VecDeque::with_capacity(CHUNK_SIZE);
37
+ let remain = ReadDir::next_chunk(&mut buf, &mut std);
38
+
39
+ Ok(ReadDir(State::Idle(Some((buf, std, remain)))))
40
+ })
41
+ .await
42
+ }
43
+
44
+ /// Reads the entries in a directory.
45
+ ///
46
+ /// This struct is returned from the [`read_dir`] function of this module and
47
+ /// will yield instances of [`DirEntry`]. Through a [`DirEntry`] information
48
+ /// like the entry's path and possibly other metadata can be learned.
49
+ ///
50
+ /// A `ReadDir` can be turned into a `Stream` with [`ReadDirStream`].
51
+ ///
52
+ /// [`ReadDirStream`]: https://docs.rs/tokio-stream/0.1/tokio_stream/wrappers/struct.ReadDirStream.html
53
+ ///
54
+ /// # Errors
55
+ ///
56
+ /// This stream will return an [`Err`] if there's some sort of intermittent
57
+ /// IO error during iteration.
58
+ ///
59
+ /// [`read_dir`]: read_dir
60
+ /// [`DirEntry`]: DirEntry
61
+ /// [`Err`]: std::result::Result::Err
62
+ #[derive(Debug)]
63
+ #[must_use = "streams do nothing unless polled"]
64
+ pub struct ReadDir(State);
65
+
66
+ #[derive(Debug)]
67
+ enum State {
68
+ Idle(Option<(VecDeque<io::Result<DirEntry>>, std::fs::ReadDir, bool)>),
69
+ Pending(JoinHandle<(VecDeque<io::Result<DirEntry>>, std::fs::ReadDir, bool)>),
70
+ }
71
+
72
+ impl ReadDir {
73
+ /// Returns the next entry in the directory stream.
74
+ ///
75
+ /// # Cancel safety
76
+ ///
77
+ /// This method is cancellation safe.
78
+ pub async fn next_entry(&mut self) -> io::Result<Option<DirEntry>> {
79
+ use std::future::poll_fn;
80
+ poll_fn(|cx| self.poll_next_entry(cx)).await
81
+ }
82
+
83
+ /// Polls for the next directory entry in the stream.
84
+ ///
85
+ /// This method returns:
86
+ ///
87
+ /// * `Poll::Pending` if the next directory entry is not yet available.
88
+ /// * `Poll::Ready(Ok(Some(entry)))` if the next directory entry is available.
89
+ /// * `Poll::Ready(Ok(None))` if there are no more directory entries in this
90
+ /// stream.
91
+ /// * `Poll::Ready(Err(err))` if an IO error occurred while reading the next
92
+ /// directory entry.
93
+ ///
94
+ /// When the method returns `Poll::Pending`, the `Waker` in the provided
95
+ /// `Context` is scheduled to receive a wakeup when the next directory entry
96
+ /// becomes available on the underlying IO resource.
97
+ ///
98
+ /// Note that on multiple calls to `poll_next_entry`, only the `Waker` from
99
+ /// the `Context` passed to the most recent call is scheduled to receive a
100
+ /// wakeup.
101
+ pub fn poll_next_entry(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<Option<DirEntry>>> {
102
+ loop {
103
+ match self.0 {
104
+ State::Idle(ref mut data) => {
105
+ let (buf, _, ref remain) = data.as_mut().unwrap();
106
+
107
+ if let Some(ent) = buf.pop_front() {
108
+ return Poll::Ready(ent.map(Some));
109
+ } else if !remain {
110
+ return Poll::Ready(Ok(None));
111
+ }
112
+
113
+ let (mut buf, mut std, _) = data.take().unwrap();
114
+
115
+ self.0 = State::Pending(spawn_blocking(move || {
116
+ let remain = ReadDir::next_chunk(&mut buf, &mut std);
117
+ (buf, std, remain)
118
+ }));
119
+ }
120
+ State::Pending(ref mut rx) => {
121
+ self.0 = State::Idle(Some(ready!(Pin::new(rx).poll(cx))?));
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ fn next_chunk(buf: &mut VecDeque<io::Result<DirEntry>>, std: &mut std::fs::ReadDir) -> bool {
128
+ for _ in 0..CHUNK_SIZE {
129
+ let ret = match std.next() {
130
+ Some(ret) => ret,
131
+ None => return false,
132
+ };
133
+
134
+ let success = ret.is_ok();
135
+
136
+ buf.push_back(ret.map(|std| DirEntry {
137
+ #[cfg(not(any(
138
+ target_os = "solaris",
139
+ target_os = "illumos",
140
+ target_os = "haiku",
141
+ target_os = "vxworks",
142
+ target_os = "aix",
143
+ target_os = "nto",
144
+ target_os = "vita",
145
+ )))]
146
+ file_type: std.file_type().ok(),
147
+ std: Arc::new(std),
148
+ }));
149
+
150
+ if !success {
151
+ break;
152
+ }
153
+ }
154
+
155
+ true
156
+ }
157
+ }
158
+
159
+ feature! {
160
+ #![unix]
161
+
162
+ use std::os::unix::fs::DirEntryExt;
163
+
164
+ impl DirEntry {
165
+ /// Returns the underlying `d_ino` field in the contained `dirent`
166
+ /// structure.
167
+ ///
168
+ /// # Examples
169
+ ///
170
+ /// ```
171
+ /// use tokio::fs;
172
+ ///
173
+ /// # #[tokio::main]
174
+ /// # async fn main() -> std::io::Result<()> {
175
+ /// let mut entries = fs::read_dir(".").await?;
176
+ /// while let Some(entry) = entries.next_entry().await? {
177
+ /// // Here, `entry` is a `DirEntry`.
178
+ /// println!("{:?}: {}", entry.file_name(), entry.ino());
179
+ /// }
180
+ /// # Ok(())
181
+ /// # }
182
+ /// ```
183
+ pub fn ino(&self) -> u64 {
184
+ self.as_inner().ino()
185
+ }
186
+ }
187
+ }
188
+
189
+ /// Entries returned by the [`ReadDir`] stream.
190
+ ///
191
+ /// [`ReadDir`]: struct@ReadDir
192
+ ///
193
+ /// This is a specialized version of [`std::fs::DirEntry`] for usage from the
194
+ /// Tokio runtime.
195
+ ///
196
+ /// An instance of `DirEntry` represents an entry inside of a directory on the
197
+ /// filesystem. Each entry can be inspected via methods to learn about the full
198
+ /// path or possibly other metadata through per-platform extension traits.
199
+ #[derive(Debug)]
200
+ pub struct DirEntry {
201
+ #[cfg(not(any(
202
+ target_os = "solaris",
203
+ target_os = "illumos",
204
+ target_os = "haiku",
205
+ target_os = "vxworks",
206
+ target_os = "aix",
207
+ target_os = "nto",
208
+ target_os = "vita",
209
+ )))]
210
+ file_type: Option<FileType>,
211
+ std: Arc<std::fs::DirEntry>,
212
+ }
213
+
214
+ impl DirEntry {
215
+ /// Returns the full path to the file that this entry represents.
216
+ ///
217
+ /// The full path is created by joining the original path to `read_dir`
218
+ /// with the filename of this entry.
219
+ ///
220
+ /// # Examples
221
+ ///
222
+ /// ```no_run
223
+ /// use tokio::fs;
224
+ ///
225
+ /// # async fn dox() -> std::io::Result<()> {
226
+ /// let mut entries = fs::read_dir(".").await?;
227
+ ///
228
+ /// while let Some(entry) = entries.next_entry().await? {
229
+ /// println!("{:?}", entry.path());
230
+ /// }
231
+ /// # Ok(())
232
+ /// # }
233
+ /// ```
234
+ ///
235
+ /// This prints output like:
236
+ ///
237
+ /// ```text
238
+ /// "./whatever.txt"
239
+ /// "./foo.html"
240
+ /// "./hello_world.rs"
241
+ /// ```
242
+ ///
243
+ /// The exact text, of course, depends on what files you have in `.`.
244
+ pub fn path(&self) -> PathBuf {
245
+ self.std.path()
246
+ }
247
+
248
+ /// Returns the bare file name of this directory entry without any other
249
+ /// leading path component.
250
+ ///
251
+ /// # Examples
252
+ ///
253
+ /// ```
254
+ /// use tokio::fs;
255
+ ///
256
+ /// # async fn dox() -> std::io::Result<()> {
257
+ /// let mut entries = fs::read_dir(".").await?;
258
+ ///
259
+ /// while let Some(entry) = entries.next_entry().await? {
260
+ /// println!("{:?}", entry.file_name());
261
+ /// }
262
+ /// # Ok(())
263
+ /// # }
264
+ /// ```
265
+ pub fn file_name(&self) -> OsString {
266
+ self.std.file_name()
267
+ }
268
+
269
+ /// Returns the metadata for the file that this entry points at.
270
+ ///
271
+ /// This function will not traverse symlinks if this entry points at a
272
+ /// symlink.
273
+ ///
274
+ /// # Platform-specific behavior
275
+ ///
276
+ /// On Windows this function is cheap to call (no extra system calls
277
+ /// needed), but on Unix platforms this function is the equivalent of
278
+ /// calling `symlink_metadata` on the path.
279
+ ///
280
+ /// # Examples
281
+ ///
282
+ /// ```
283
+ /// use tokio::fs;
284
+ ///
285
+ /// # async fn dox() -> std::io::Result<()> {
286
+ /// let mut entries = fs::read_dir(".").await?;
287
+ ///
288
+ /// while let Some(entry) = entries.next_entry().await? {
289
+ /// if let Ok(metadata) = entry.metadata().await {
290
+ /// // Now let's show our entry's permissions!
291
+ /// println!("{:?}: {:?}", entry.path(), metadata.permissions());
292
+ /// } else {
293
+ /// println!("Couldn't get file type for {:?}", entry.path());
294
+ /// }
295
+ /// }
296
+ /// # Ok(())
297
+ /// # }
298
+ /// ```
299
+ pub async fn metadata(&self) -> io::Result<Metadata> {
300
+ let std = self.std.clone();
301
+ asyncify(move || std.metadata()).await
302
+ }
303
+
304
+ /// Returns the file type for the file that this entry points at.
305
+ ///
306
+ /// This function will not traverse symlinks if this entry points at a
307
+ /// symlink.
308
+ ///
309
+ /// # Platform-specific behavior
310
+ ///
311
+ /// On Windows and most Unix platforms this function is free (no extra
312
+ /// system calls needed), but some Unix platforms may require the equivalent
313
+ /// call to `symlink_metadata` to learn about the target file type.
314
+ ///
315
+ /// # Examples
316
+ ///
317
+ /// ```
318
+ /// use tokio::fs;
319
+ ///
320
+ /// # async fn dox() -> std::io::Result<()> {
321
+ /// let mut entries = fs::read_dir(".").await?;
322
+ ///
323
+ /// while let Some(entry) = entries.next_entry().await? {
324
+ /// if let Ok(file_type) = entry.file_type().await {
325
+ /// // Now let's show our entry's file type!
326
+ /// println!("{:?}: {:?}", entry.path(), file_type);
327
+ /// } else {
328
+ /// println!("Couldn't get file type for {:?}", entry.path());
329
+ /// }
330
+ /// }
331
+ /// # Ok(())
332
+ /// # }
333
+ /// ```
334
+ pub async fn file_type(&self) -> io::Result<FileType> {
335
+ #[cfg(not(any(
336
+ target_os = "solaris",
337
+ target_os = "illumos",
338
+ target_os = "haiku",
339
+ target_os = "vxworks",
340
+ target_os = "aix",
341
+ target_os = "nto",
342
+ target_os = "vita",
343
+ )))]
344
+ if let Some(file_type) = self.file_type {
345
+ return Ok(file_type);
346
+ }
347
+
348
+ let std = self.std.clone();
349
+ asyncify(move || std.file_type()).await
350
+ }
351
+
352
+ /// Returns a reference to the underlying `std::fs::DirEntry`.
353
+ #[cfg(unix)]
354
+ pub(super) fn as_inner(&self) -> &std::fs::DirEntry {
355
+ &self.std
356
+ }
357
+ }
@@ -0,0 +1,99 @@
1
+ use crate::{fs::asyncify, util::as_ref::OwnedBuf};
2
+
3
+ use std::{io, path::Path};
4
+
5
+ /// Creates a future that will open a file for writing and write the entire
6
+ /// contents of `contents` to it.
7
+ ///
8
+ /// This is the async equivalent of [`std::fs::write`][std].
9
+ ///
10
+ /// This operation is implemented by running the equivalent blocking operation
11
+ /// on a separate thread pool using [`spawn_blocking`].
12
+ ///
13
+ /// [`spawn_blocking`]: crate::task::spawn_blocking
14
+ /// [std]: fn@std::fs::write
15
+ ///
16
+ /// # Examples
17
+ ///
18
+ /// ```no_run
19
+ /// use tokio::fs;
20
+ ///
21
+ /// # async fn dox() -> std::io::Result<()> {
22
+ /// fs::write("foo.txt", b"Hello world!").await?;
23
+ /// # Ok(())
24
+ /// # }
25
+ /// ```
26
+ pub async fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> io::Result<()> {
27
+ let path = path.as_ref();
28
+ let contents = crate::util::as_ref::upgrade(contents);
29
+
30
+ #[cfg(all(
31
+ tokio_unstable,
32
+ feature = "io-uring",
33
+ feature = "rt",
34
+ feature = "fs",
35
+ target_os = "linux"
36
+ ))]
37
+ {
38
+ let handle = crate::runtime::Handle::current();
39
+ let driver_handle = handle.inner.driver().io();
40
+ if driver_handle
41
+ .check_and_init(io_uring::opcode::Write::CODE)
42
+ .await?
43
+ {
44
+ return write_uring(path, contents).await;
45
+ }
46
+ }
47
+
48
+ write_spawn_blocking(path, contents).await
49
+ }
50
+
51
+ #[cfg(all(
52
+ tokio_unstable,
53
+ feature = "io-uring",
54
+ feature = "rt",
55
+ feature = "fs",
56
+ target_os = "linux"
57
+ ))]
58
+ async fn write_uring(path: &Path, mut buf: OwnedBuf) -> io::Result<()> {
59
+ use crate::{fs::OpenOptions, runtime::driver::op::Op};
60
+ use std::os::fd::OwnedFd;
61
+
62
+ let file = OpenOptions::new()
63
+ .write(true)
64
+ .create(true)
65
+ .truncate(true)
66
+ .open(path)
67
+ .await?;
68
+
69
+ let mut fd: OwnedFd = file
70
+ .try_into_std()
71
+ .expect("unexpected in-flight operation detected")
72
+ .into();
73
+
74
+ let total: usize = buf.as_ref().len();
75
+ let mut buf_offset: usize = 0;
76
+ let mut file_offset: u64 = 0;
77
+ while buf_offset < total {
78
+ let (res, _buf, _fd) = Op::write_at(fd, buf, buf_offset, file_offset)?.await;
79
+
80
+ let n = match res {
81
+ Ok(0) => return Err(io::ErrorKind::WriteZero.into()),
82
+ Ok(n) => n,
83
+ Err(e) if e.kind() == io::ErrorKind::Interrupted => 0,
84
+ Err(e) => return Err(e),
85
+ };
86
+
87
+ buf = _buf;
88
+ fd = _fd;
89
+ buf_offset += n as usize;
90
+ file_offset += n as u64;
91
+ }
92
+
93
+ Ok(())
94
+ }
95
+
96
+ async fn write_spawn_blocking(path: &Path, contents: OwnedBuf) -> io::Result<()> {
97
+ let path = path.to_owned();
98
+ asyncify(move || std::fs::write(path, contents)).await
99
+ }
@@ -0,0 +1,123 @@
1
+ //! Definition of the [`MaybeDone`] combinator.
2
+
3
+ use pin_project_lite::pin_project;
4
+ use std::future::{Future, IntoFuture};
5
+ use std::pin::Pin;
6
+ use std::task::{ready, Context, Poll};
7
+
8
+ pin_project! {
9
+ /// A future that may have completed.
10
+ #[derive(Debug)]
11
+ #[project = MaybeDoneProj]
12
+ #[project_replace = MaybeDoneProjReplace]
13
+ #[repr(C)] // https://github.com/rust-lang/miri/issues/3780
14
+ pub enum MaybeDone<Fut: Future> {
15
+ /// A not-yet-completed future.
16
+ Future { #[pin] future: Fut },
17
+ /// The output of the completed future.
18
+ Done { output: Fut::Output },
19
+ /// The empty variant after the result of a [`MaybeDone`] has been
20
+ /// taken using the [`take_output`](MaybeDone::take_output) method.
21
+ Gone,
22
+ }
23
+ }
24
+
25
+ /// Wraps a future into a `MaybeDone`.
26
+ pub fn maybe_done<F: IntoFuture>(future: F) -> MaybeDone<F::IntoFuture> {
27
+ MaybeDone::Future {
28
+ future: future.into_future(),
29
+ }
30
+ }
31
+
32
+ impl<Fut: Future> MaybeDone<Fut> {
33
+ /// Returns an [`Option`] containing a mutable reference to the output of the future.
34
+ /// The output of this method will be [`Some`] if and only if the inner
35
+ /// future has been completed and [`take_output`](MaybeDone::take_output)
36
+ /// has not yet been called.
37
+ pub fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Output> {
38
+ match self.project() {
39
+ MaybeDoneProj::Done { output } => Some(output),
40
+ _ => None,
41
+ }
42
+ }
43
+
44
+ /// Attempts to take the output of a `MaybeDone` without driving it
45
+ /// towards completion.
46
+ #[inline]
47
+ pub fn take_output(self: Pin<&mut Self>) -> Option<Fut::Output> {
48
+ match *self {
49
+ MaybeDone::Done { .. } => {}
50
+ MaybeDone::Future { .. } | MaybeDone::Gone => return None,
51
+ };
52
+ if let MaybeDoneProjReplace::Done { output } = self.project_replace(MaybeDone::Gone) {
53
+ Some(output)
54
+ } else {
55
+ unreachable!()
56
+ }
57
+ }
58
+ }
59
+
60
+ impl<Fut: Future> Future for MaybeDone<Fut> {
61
+ type Output = ();
62
+
63
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
64
+ let output = match self.as_mut().project() {
65
+ MaybeDoneProj::Future { future } => ready!(future.poll(cx)),
66
+ MaybeDoneProj::Done { .. } => return Poll::Ready(()),
67
+ MaybeDoneProj::Gone => panic!("MaybeDone polled after value taken"),
68
+ };
69
+ self.set(MaybeDone::Done { output });
70
+ Poll::Ready(())
71
+ }
72
+ }
73
+
74
+ // Test for https://github.com/tokio-rs/tokio/issues/6729
75
+ #[cfg(test)]
76
+ mod miri_tests {
77
+ use super::maybe_done;
78
+
79
+ use std::{
80
+ future::Future,
81
+ pin::Pin,
82
+ sync::Arc,
83
+ task::{Context, Poll, Wake},
84
+ };
85
+
86
+ struct ThingAdder<'a> {
87
+ thing: &'a mut String,
88
+ }
89
+
90
+ impl Future for ThingAdder<'_> {
91
+ type Output = ();
92
+
93
+ fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
94
+ unsafe {
95
+ *self.get_unchecked_mut().thing += ", world";
96
+ }
97
+ Poll::Pending
98
+ }
99
+ }
100
+
101
+ #[test]
102
+ fn maybe_done_miri() {
103
+ let mut thing = "hello".to_owned();
104
+
105
+ // The async block is necessary to trigger the miri failure.
106
+ #[allow(clippy::redundant_async_block)]
107
+ let fut = async move { ThingAdder { thing: &mut thing }.await };
108
+
109
+ let mut fut = maybe_done(fut);
110
+ let mut fut = unsafe { Pin::new_unchecked(&mut fut) };
111
+
112
+ let waker = Arc::new(DummyWaker).into();
113
+ let mut ctx = Context::from_waker(&waker);
114
+ assert_eq!(fut.as_mut().poll(&mut ctx), Poll::Pending);
115
+ assert_eq!(fut.as_mut().poll(&mut ctx), Poll::Pending);
116
+ }
117
+
118
+ struct DummyWaker;
119
+
120
+ impl Wake for DummyWaker {
121
+ fn wake(self: Arc<Self>) {}
122
+ }
123
+ }