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.
- package/.agents/plugins/marketplace.json +20 -0
- package/.claude-plugin/marketplace.json +39 -0
- package/.claude-plugin/plugin.json +36 -0
- package/.codex/agents/README.md +9 -0
- package/.codex/agents/ashlr-explorer.md +36 -0
- package/.codex/agents/ashlr-worker.md +38 -0
- package/.codex-plugin/plugin.json +45 -0
- package/.mcp.json +14 -0
- package/LICENSE +21 -0
- package/README.md +311 -0
- package/agents/ashlr-code.md +69 -0
- package/agents/ashlr-explore.md +44 -0
- package/agents/ashlr-plan.md +54 -0
- package/bench/fixtures/notebook-large.ipynb +660 -0
- package/bench/fixtures/notebook-small.ipynb +39 -0
- package/bench/fixtures/tasklist-closed.json +62 -0
- package/bench/fixtures/tasklist-large-mixed.json +27 -0
- package/bench/fixtures/tasklist-sprint-open.json +79 -0
- package/bench/fixtures/websearch-bun-runtime.json +32 -0
- package/bench/fixtures/websearch-react-hooks-patterns.json +32 -0
- package/bench/fixtures/websearch-typescript-generics.json +38 -0
- package/bench/refs/node-sdk/.refrev +1 -0
- package/bench/refs/node-sdk/README.md +17 -0
- package/bench/refs/node-sdk/src/agent/agent.ts +163 -0
- package/bench/refs/node-sdk/src/agent/create-agent-ui-stream.ts +83 -0
- package/bench/refs/node-sdk/src/agent/tool-loop-agent.ts +238 -0
- package/bench/refs/node-sdk/src/embed/embed-many.ts +409 -0
- package/bench/refs/node-sdk/src/embed/embed-result.ts +50 -0
- package/bench/refs/node-sdk/src/embed/embed.ts +257 -0
- package/bench/refs/node-sdk/src/error/invalid-argument-error.ts +34 -0
- package/bench/refs/node-sdk/src/error/invalid-tool-input-error.ts +33 -0
- package/bench/refs/node-sdk/src/error/no-object-generated-error.ts +70 -0
- package/bench/refs/node-sdk/src/generate-image/generate-image-result.ts +42 -0
- package/bench/refs/node-sdk/src/generate-image/generate-image.ts +362 -0
- package/bench/refs/node-sdk/src/generate-object/generate-object-result.ts +67 -0
- package/bench/refs/node-sdk/src/generate-object/generate-object.ts +501 -0
- package/bench/refs/node-sdk/src/generate-object/inject-json-instruction.ts +30 -0
- package/bench/refs/node-sdk/src/generate-object/output-strategy.ts +415 -0
- package/bench/refs/node-sdk/src/generate-object/repair-text.ts +12 -0
- package/bench/refs/node-sdk/src/generate-object/stream-object.ts +960 -0
- package/bench/refs/node-sdk/src/generate-speech/generate-speech.ts +191 -0
- package/bench/refs/node-sdk/src/generate-text/generate-text.ts +1484 -0
- package/bench/refs/node-sdk/src/generate-text/stream-text.ts +2708 -0
- package/bench/refs/node-sdk/src/generate-text/tool-call.ts +59 -0
- package/bench/refs/node-sdk/src/generate-text/tool-result.ts +36 -0
- package/bench/refs/node-sdk/src/telemetry/create-telemetry-dispatcher.ts +146 -0
- package/bench/refs/node-sdk/src/telemetry/telemetry-registry.ts +15 -0
- package/bench/refs/node-sdk/src/telemetry/telemetry.ts +223 -0
- package/bench/refs/node-sdk/src/util/async-iterable-stream.ts +94 -0
- package/bench/refs/node-sdk/src/util/consume-stream.ts +31 -0
- package/bench/refs/node-sdk/src/util/create-stitchable-stream.ts +112 -0
- package/bench/refs/node-sdk/src/util/download/download.ts +74 -0
- package/bench/refs/node-sdk/src/util/error-handler.ts +1 -0
- package/bench/refs/node-sdk/src/util/fix-json.ts +401 -0
- package/bench/refs/node-sdk/src/util/merge-objects.ts +79 -0
- package/bench/refs/python-lib/.refrev +1 -0
- package/bench/refs/python-lib/README.md +18 -0
- package/bench/refs/python-lib/pandas/core/_numba/executor.py +249 -0
- package/bench/refs/python-lib/pandas/core/_numba/extensions.py +586 -0
- package/bench/refs/python-lib/pandas/core/_numba/kernels/mean_.py +198 -0
- package/bench/refs/python-lib/pandas/core/_numba/kernels/min_max_.py +178 -0
- package/bench/refs/python-lib/pandas/core/_numba/kernels/sum_.py +255 -0
- package/bench/refs/python-lib/pandas/core/_numba/kernels/var_.py +251 -0
- package/bench/refs/python-lib/pandas/core/accessor.py +520 -0
- package/bench/refs/python-lib/pandas/core/api.py +138 -0
- package/bench/refs/python-lib/pandas/core/array_algos/masked_accumulations.py +97 -0
- package/bench/refs/python-lib/pandas/core/array_algos/masked_reductions.py +252 -0
- package/bench/refs/python-lib/pandas/core/array_algos/putmask.py +150 -0
- package/bench/refs/python-lib/pandas/core/array_algos/quantile.py +232 -0
- package/bench/refs/python-lib/pandas/core/array_algos/replace.py +159 -0
- package/bench/refs/python-lib/pandas/core/array_algos/take.py +609 -0
- package/bench/refs/python-lib/pandas/core/arraylike.py +534 -0
- package/bench/refs/python-lib/pandas/core/arrays/_arrow_string_mixins.py +434 -0
- package/bench/refs/python-lib/pandas/core/arrays/_mixins.py +630 -0
- package/bench/refs/python-lib/pandas/core/arrays/_ranges.py +276 -0
- package/bench/refs/python-lib/pandas/core/arrays/_utils.py +77 -0
- package/bench/refs/python-lib/pandas/core/arrays/arrow/accessors.py +521 -0
- package/bench/refs/python-lib/pandas/core/arrays/arrow/extension_types.py +174 -0
- package/bench/refs/python-lib/pandas/core/arrays/boolean.py +454 -0
- package/bench/refs/python-lib/pandas/core/arrays/floating.py +192 -0
- package/bench/refs/python-lib/pandas/core/arrays/integer.py +296 -0
- package/bench/refs/python-lib/pandas/core/arrays/masked.py +2140 -0
- package/bench/refs/python-lib/pandas/core/arrays/numeric.py +305 -0
- package/bench/refs/python-lib/pandas/core/arrays/numpy_.py +701 -0
- package/bench/refs/python-lib/pandas/core/arrays/period.py +1586 -0
- package/bench/refs/python-lib/pandas/core/arrays/sparse/accessor.py +505 -0
- package/bench/refs/python-lib/pandas/core/arrays/sparse/scipy_sparse.py +208 -0
- package/bench/refs/rust-project/.refrev +1 -0
- package/bench/refs/rust-project/README.md +17 -0
- package/bench/refs/rust-project/tokio/src/doc/os.rs +68 -0
- package/bench/refs/rust-project/tokio/src/fs/dir_builder.rs +129 -0
- package/bench/refs/rust-project/tokio/src/fs/file.rs +1113 -0
- package/bench/refs/rust-project/tokio/src/fs/mocks.rs +176 -0
- package/bench/refs/rust-project/tokio/src/fs/mod.rs +324 -0
- package/bench/refs/rust-project/tokio/src/fs/open_options.rs +856 -0
- package/bench/refs/rust-project/tokio/src/fs/read.rs +80 -0
- package/bench/refs/rust-project/tokio/src/fs/read_dir.rs +357 -0
- package/bench/refs/rust-project/tokio/src/fs/write.rs +99 -0
- package/bench/refs/rust-project/tokio/src/future/maybe_done.rs +123 -0
- package/bench/refs/rust-project/tokio/src/future/try_join.rs +82 -0
- package/bench/refs/rust-project/tokio/src/io/async_buf_read.rs +117 -0
- package/bench/refs/rust-project/tokio/src/io/async_read.rs +133 -0
- package/bench/refs/rust-project/tokio/src/io/async_seek.rs +96 -0
- package/bench/refs/rust-project/tokio/src/io/async_write.rs +402 -0
- package/bench/refs/rust-project/tokio/src/io/blocking.rs +339 -0
- package/bench/refs/rust-project/tokio/src/io/interest.rs +345 -0
- package/bench/refs/rust-project/tokio/src/io/join.rs +130 -0
- package/bench/refs/rust-project/tokio/src/io/mod.rs +308 -0
- package/bench/refs/rust-project/tokio/src/io/poll_evented.rs +319 -0
- package/bench/refs/rust-project/tokio/src/io/read_buf.rs +344 -0
- package/bench/refs/rust-project/tokio/src/io/ready.rs +322 -0
- package/bench/refs/rust-project/tokio/src/io/split.rs +166 -0
- package/bench/refs/rust-project/tokio/src/io/stderr.rs +148 -0
- package/bench/refs/rust-project/tokio/src/io/stdin.rs +98 -0
- package/bench/refs/rust-project/tokio/src/io/stdio_common.rs +222 -0
- package/bench/refs/rust-project/tokio/src/io/stdout.rs +197 -0
- package/bench/refs/rust-project/tokio/src/io/util/buf_reader.rs +311 -0
- package/bench/refs/rust-project/tokio/src/io/util/buf_stream.rs +207 -0
- package/bench/refs/rust-project/tokio/src/io/util/buf_writer.rs +310 -0
- package/bench/refs/rust-project/tokio/src/io/util/chain.rs +144 -0
- package/commands/_spawn-patterns.json +32 -0
- package/commands/ashlr-allow.md +21 -0
- package/commands/ashlr-benchmark.md +53 -0
- package/commands/ashlr-brief.md +97 -0
- package/commands/ashlr-budget.md +76 -0
- package/commands/ashlr-compact.md +54 -0
- package/commands/ashlr-dashboard.md +37 -0
- package/commands/ashlr-doctor.md +56 -0
- package/commands/ashlr-eco-mode.md +92 -0
- package/commands/ashlr-genome-init.md +24 -0
- package/commands/ashlr-genome-keygen.md +36 -0
- package/commands/ashlr-genome-loop.md +118 -0
- package/commands/ashlr-genome-push.md +36 -0
- package/commands/ashlr-genome-rewrap.md +48 -0
- package/commands/ashlr-genome-team-init.md +67 -0
- package/commands/ashlr-handoff.md +23 -0
- package/commands/ashlr-help.md +86 -0
- package/commands/ashlr-hook-timings.md +30 -0
- package/commands/ashlr-leaderboard.md +50 -0
- package/commands/ashlr-ollama-setup.md +39 -0
- package/commands/ashlr-orchestrate-status.md +72 -0
- package/commands/ashlr-orchestrate.md +83 -0
- package/commands/ashlr-parallelize.md +63 -0
- package/commands/ashlr-report-crash.md +33 -0
- package/commands/ashlr-resume.md +72 -0
- package/commands/ashlr-savings.md +24 -0
- package/commands/ashlr-settings.md +50 -0
- package/commands/ashlr-spawn.md +61 -0
- package/commands/ashlr-start.md +60 -0
- package/commands/ashlr-status.md +64 -0
- package/commands/ashlr-team-invite.md +47 -0
- package/commands/ashlr-tier.md +122 -0
- package/commands/ashlr-tour.md +60 -0
- package/commands/ashlr-update.md +155 -0
- package/commands/ashlr-upgrade.md +96 -0
- package/commands/goal.md +58 -0
- package/commands/loop.md +40 -0
- package/docs/CNAME +1 -0
- package/docs/PRO_TIER.md +104 -0
- package/docs/README.md +21 -0
- package/docs/architecture.md +415 -0
- package/docs/ashlr-pipe.md +161 -0
- package/docs/assets/logo.svg +19 -0
- package/docs/assets/og.png +0 -0
- package/docs/assets/og.svg +41 -0
- package/docs/benchmarks-v2.json +355 -0
- package/docs/benchmarks.json +102 -0
- package/docs/benchmarks.md +211 -0
- package/docs/billing.md +185 -0
- package/docs/cloud-genome.md +155 -0
- package/docs/competitive-wozcode.md +92 -0
- package/docs/deploy.md +325 -0
- package/docs/email-templates.md +113 -0
- package/docs/embed-tuning.md +103 -0
- package/docs/genome.md +120 -0
- package/docs/github-oauth-onboarding.md +127 -0
- package/docs/hero-video-script.md +129 -0
- package/docs/index.html +2262 -0
- package/docs/install-prompt.md +78 -0
- package/docs/install-windows.md +132 -0
- package/docs/install.ps1 +171 -0
- package/docs/install.sh +146 -0
- package/docs/launch/README.md +114 -0
- package/docs/launch/hn.md +49 -0
- package/docs/launch/reddit.md +45 -0
- package/docs/launch/x.md +65 -0
- package/docs/launch-post.md +112 -0
- package/docs/legal.md +78 -0
- package/docs/llm-providers.md +99 -0
- package/docs/multi-host-mcp.md +217 -0
- package/docs/multi-turn-architecture.md +108 -0
- package/docs/operations/deployment.md +108 -0
- package/docs/operations/error-monitoring.md +70 -0
- package/docs/operations/weekly-digest.md +70 -0
- package/docs/operations.md +494 -0
- package/docs/platform-support.md +133 -0
- package/docs/policy-packs.md +188 -0
- package/docs/press-kit/fact-sheet.md +78 -0
- package/docs/press-kit/founder-bio.md +3 -0
- package/docs/press-kit/logo.svg +33 -0
- package/docs/press-kit/screenshots.md +146 -0
- package/docs/pricing.md +251 -0
- package/docs/pro-backend-architecture.md +523 -0
- package/docs/producthunt.md +52 -0
- package/docs/router-migration.md +110 -0
- package/docs/session-log-schema.md +68 -0
- package/docs/social.md +95 -0
- package/docs/team-genome.md +528 -0
- package/docs/telemetry.md +194 -0
- package/docs/test-isolation.md +100 -0
- package/docs/upgrade.md +159 -0
- package/hooks/_hook-errors.ts +87 -0
- package/hooks/_hook-perf-emit.ts +113 -0
- package/hooks/_hook-timing-ledger.ts +1133 -0
- package/hooks/_nudge-throttle.ts +127 -0
- package/hooks/_recent-blocks.ts +127 -0
- package/hooks/audit-upload.ts +86 -0
- package/hooks/codex-hooks.json +171 -0
- package/hooks/commit-attribution.ts +179 -0
- package/hooks/edit-batching-nudge.ts +154 -0
- package/hooks/genome-scribe-hook.ts +219 -0
- package/hooks/hooks.json +294 -0
- package/hooks/orient-nudge-hook.ts +242 -0
- package/hooks/policy-enforce.ts +214 -0
- package/hooks/post-tool-use-embedding.ts +93 -0
- package/hooks/post-tool-use-genome.sh +37 -0
- package/hooks/post-tool-use-genome.ts +69 -0
- package/hooks/posttooluse-correlate.ts +122 -0
- package/hooks/posttooluse-dedupe-output.ts +241 -0
- package/hooks/posttooluse-genome-refresh.ts +223 -0
- package/hooks/posttooluse-native-nudge.ts +205 -0
- package/hooks/posttooluse-stale-result.ts +277 -0
- package/hooks/pretooluse-bash.ts +63 -0
- package/hooks/pretooluse-budget-guard.ts +318 -0
- package/hooks/pretooluse-common.ts +985 -0
- package/hooks/pretooluse-eco-router.ts +196 -0
- package/hooks/pretooluse-edit.sh +93 -0
- package/hooks/pretooluse-edit.ts +197 -0
- package/hooks/pretooluse-glob.ts +70 -0
- package/hooks/pretooluse-grep.sh +85 -0
- package/hooks/pretooluse-grep.ts +96 -0
- package/hooks/pretooluse-notebookedit.ts +121 -0
- package/hooks/pretooluse-read.sh +118 -0
- package/hooks/pretooluse-read.ts +118 -0
- package/hooks/pretooluse-task.ts +130 -0
- package/hooks/pretooluse-webfetch.ts +66 -0
- package/hooks/pretooluse-websearch.ts +85 -0
- package/hooks/pretooluse-write.ts +128 -0
- package/hooks/pulse-emit.ts +197 -0
- package/hooks/session-end-consolidate.sh +35 -0
- package/hooks/session-end-consolidate.ts +188 -0
- package/hooks/session-end-stats-gc.ts +80 -0
- package/hooks/session-log-append.sh +94 -0
- package/hooks/session-log-append.ts +116 -0
- package/hooks/session-start.ts +993 -0
- package/hooks/sessionend-hook-health-nudge.ts +451 -0
- package/hooks/sessionend-savings-nudge.ts +318 -0
- package/hooks/sessionend-status-line-nudge.ts +296 -0
- package/hooks/sessionstart-brief.ts +140 -0
- package/hooks/sessionstart-cost-refactor.ts +95 -0
- package/hooks/sessionstart-efficient.ts +110 -0
- package/hooks/sessionstart-genome-author.ts +93 -0
- package/hooks/sessionstart-lean-tools.ts +98 -0
- package/hooks/sessionstart-search.ts +97 -0
- package/hooks/stop-accounting.ts +152 -0
- package/hooks/subagent-stop-rollup.ts +162 -0
- package/hooks/userpromptsubmit-brief-trigger.ts +156 -0
- package/package.json +56 -0
- package/ports/README.md +108 -0
- package/ports/cursor/mcp.json +11 -0
- package/ports/goose/recipe.yaml +26 -0
- package/scripts/ashlr-mcp.ts +40 -0
- package/scripts/auto-update.ts +177 -0
- package/scripts/baseline-scan.ts +831 -0
- package/scripts/bench-orchestrate.ts +377 -0
- package/scripts/benchmark-refs.ts +292 -0
- package/scripts/bootstrap.mjs +100 -0
- package/scripts/brief-eval.ts +234 -0
- package/scripts/bump-version.ts +82 -0
- package/scripts/bun-resolve.d.mts +11 -0
- package/scripts/bun-resolve.mjs +59 -0
- package/scripts/calibrate-grep.ts +467 -0
- package/scripts/capture-grep-workload.ts +260 -0
- package/scripts/check-tier.ts +61 -0
- package/scripts/check-version-sync.ts +97 -0
- package/scripts/cli-orchestrate-status.ts +386 -0
- package/scripts/cli-orchestrate.ts +303 -0
- package/scripts/cli.ts +478 -0
- package/scripts/cloud-smoke-test.ts +313 -0
- package/scripts/coach-report.ts +373 -0
- package/scripts/context-db-migrate.ts +137 -0
- package/scripts/context-status.ts +43 -0
- package/scripts/demo-run.ts +255 -0
- package/scripts/deploy-smoke.sh +140 -0
- package/scripts/doctor.ts +992 -0
- package/scripts/embed-file-worker.ts +104 -0
- package/scripts/embed-tune.ts +308 -0
- package/scripts/errors-report.ts +428 -0
- package/scripts/find-test-leak.ts +69 -0
- package/scripts/generate-badge.ts +357 -0
- package/scripts/genome-auto-consolidate.ts +533 -0
- package/scripts/genome-auto-propose.ts +578 -0
- package/scripts/genome-cloud-pull.ts +363 -0
- package/scripts/genome-cloud-push.ts +382 -0
- package/scripts/genome-cloud-sync.ts +587 -0
- package/scripts/genome-commit-watcher.ts +295 -0
- package/scripts/genome-init.ts +986 -0
- package/scripts/genome-key.ts +233 -0
- package/scripts/genome-keygen.ts +168 -0
- package/scripts/genome-link.ts +59 -0
- package/scripts/genome-refresh-worker.ts +364 -0
- package/scripts/genome-rewrap.ts +90 -0
- package/scripts/genome-synthesizer.ts +679 -0
- package/scripts/genome-team-init.ts +312 -0
- package/scripts/handoff-pack.ts +438 -0
- package/scripts/hook-bootstrap.mjs +75 -0
- package/scripts/hook-timing-reader.ts +371 -0
- package/scripts/hook-timings-report.ts +554 -0
- package/scripts/install-genome-hooks.ts +196 -0
- package/scripts/install-onnx-model.ts +154 -0
- package/scripts/install-permissions.ts +276 -0
- package/scripts/install-status-line.ts +150 -0
- package/scripts/mcp-entrypoint.sh +78 -0
- package/scripts/mcp-entrypoint.ts +130 -0
- package/scripts/mdx-angle-bracket-lint.ts +152 -0
- package/scripts/measure-cold-start.ts +126 -0
- package/scripts/migrate-stats-to-sqlite.ts +86 -0
- package/scripts/ollama-setup.ts +498 -0
- package/scripts/onboarding-wizard.ts +1691 -0
- package/scripts/orchestrate-emit-telemetry.ts +177 -0
- package/scripts/orchestrate-expand.ts +517 -0
- package/scripts/orchestrate-run.ts +744 -0
- package/scripts/print-legend.ts +50 -0
- package/scripts/product-metadata.ts +38 -0
- package/scripts/prune-old-memories.ts +208 -0
- package/scripts/publish.sh +88 -0
- package/scripts/read-calibration.ts +122 -0
- package/scripts/report-crash.ts +226 -0
- package/scripts/run-benchmark.ts +750 -0
- package/scripts/run-root-tests.ts +28 -0
- package/scripts/savings-dashboard.ts +1258 -0
- package/scripts/savings-report-extras.ts +447 -0
- package/scripts/savings-status-line.ts +873 -0
- package/scripts/session-event-emit.ts +266 -0
- package/scripts/session-greet.ts +686 -0
- package/scripts/session-log-report.ts +551 -0
- package/scripts/session-resume.ts +614 -0
- package/scripts/set-hook-mode.ts +83 -0
- package/scripts/smoke-cross-platform.ts +117 -0
- package/scripts/smoke-realtime.ts +257 -0
- package/scripts/smoke-tools.ts +21 -0
- package/scripts/stats-cloud-pull.ts +213 -0
- package/scripts/stats-cloud-sync.ts +261 -0
- package/scripts/telemetry-flush.ts +160 -0
- package/scripts/telemetry-status.ts +266 -0
- package/scripts/timing-budget.ts +35 -0
- package/scripts/ui-animation.ts +120 -0
- package/scripts/ui.ts +431 -0
- package/scripts/upgrade-flow.ts +775 -0
- package/scripts/weekly-digest.ts +394 -0
- package/servers/_accounting.ts +78 -0
- package/servers/_ask-router.ts +84 -0
- package/servers/_ast-chunker.ts +434 -0
- package/servers/_ast-helpers.ts +183 -0
- package/servers/_ast-languages.ts +153 -0
- package/servers/_ast-refactor/_shared.ts +221 -0
- package/servers/_ast-refactor/cross-file-rename.ts +560 -0
- package/servers/_ast-refactor/extract-function.ts +357 -0
- package/servers/_ast-refactor/file-local-rename.ts +172 -0
- package/servers/_ast-refactor.ts +41 -0
- package/servers/_ast-skeleton.ts +107 -0
- package/servers/_bash-summarizers-registry.ts +1096 -0
- package/servers/_crash-dump.ts +210 -0
- package/servers/_cwd-clamp.ts +342 -0
- package/servers/_edit-log.ts +28 -0
- package/servers/_edit-match.ts +236 -0
- package/servers/_edit-validate.ts +196 -0
- package/servers/_embed-calibration.ts +123 -0
- package/servers/_embedding-cache.ts +401 -0
- package/servers/_embedding-model.ts +329 -0
- package/servers/_events.ts +113 -0
- package/servers/_genome-cache.ts +154 -0
- package/servers/_genome-commits.ts +172 -0
- package/servers/_genome-crypto-v2.ts +242 -0
- package/servers/_genome-crypto.ts +259 -0
- package/servers/_genome-discoveries.ts +140 -0
- package/servers/_genome-embed-populator.ts +216 -0
- package/servers/_genome-freshness.ts +134 -0
- package/servers/_genome-issues.ts +171 -0
- package/servers/_genome-live.ts +263 -0
- package/servers/_genome-prs.ts +188 -0
- package/servers/_genome-search.ts +479 -0
- package/servers/_genome-sync.ts +297 -0
- package/servers/_history-tracker.ts +279 -0
- package/servers/_http-helpers.ts +151 -0
- package/servers/_identity-hash.ts +151 -0
- package/servers/_llm-providers/anthropic.ts +132 -0
- package/servers/_llm-providers/cloud.ts +195 -0
- package/servers/_llm-providers/index.ts +350 -0
- package/servers/_llm-providers/local.ts +127 -0
- package/servers/_llm-providers/onnx.ts +393 -0
- package/servers/_llm-providers/types.ts +27 -0
- package/servers/_manifest-v2.ts +447 -0
- package/servers/_mcp-host.ts +93 -0
- package/servers/_nudge-events.ts +451 -0
- package/servers/_orchestrate-executor.ts +316 -0
- package/servers/_prefetch.ts +435 -0
- package/servers/_pricing.ts +256 -0
- package/servers/_pro.ts +381 -0
- package/servers/_read-cache.ts +44 -0
- package/servers/_router-handlers.ts +46 -0
- package/servers/_router.ts +55 -0
- package/servers/_run-with-timeout.ts +173 -0
- package/servers/_savings-render.ts +214 -0
- package/servers/_stats-sqlite.ts +640 -0
- package/servers/_stats.ts +1183 -0
- package/servers/_status-line-cells.ts +469 -0
- package/servers/_streaks.ts +162 -0
- package/servers/_summarize.ts +208 -0
- package/servers/_task-graph-render.ts +217 -0
- package/servers/_task-graph.ts +545 -0
- package/servers/_telemetry.ts +719 -0
- package/servers/_test-parsers.ts +530 -0
- package/servers/_test-watch.ts +626 -0
- package/servers/_text-helpers.ts +37 -0
- package/servers/_token-measure.ts +160 -0
- package/servers/_tool-base.ts +248 -0
- package/servers/_weekly-digest.ts +391 -0
- package/servers/ask-server-handlers.ts +49 -0
- package/servers/ask-server.ts +174 -0
- package/servers/bash-server-handlers.ts +138 -0
- package/servers/bash-server.ts +1136 -0
- package/servers/bench.ts +186 -0
- package/servers/diff-semantic-server-handlers.ts +39 -0
- package/servers/diff-semantic-server.ts +566 -0
- package/servers/diff-server-handlers.ts +317 -0
- package/servers/diff-server.ts +20 -0
- package/servers/edit-server-handlers.ts +31 -0
- package/servers/edit-server.ts +209 -0
- package/servers/edit-structural-server-handlers.ts +322 -0
- package/servers/efficiency-server-handlers.ts +161 -0
- package/servers/efficiency-server.ts +1135 -0
- package/servers/flush-server-handlers.ts +21 -0
- package/servers/flush-server.ts +19 -0
- package/servers/genome-server-handlers.ts +118 -0
- package/servers/genome-server.ts +397 -0
- package/servers/github-server-handlers.ts +187 -0
- package/servers/github-server.ts +856 -0
- package/servers/glob-server-handlers.ts +233 -0
- package/servers/glob-server.ts +20 -0
- package/servers/grep-server-handlers.ts +61 -0
- package/servers/grep-server.ts +564 -0
- package/servers/http-server-handlers.ts +36 -0
- package/servers/http-server.ts +149 -0
- package/servers/logs-server-handlers.ts +42 -0
- package/servers/logs-server.ts +359 -0
- package/servers/ls-server-handlers.ts +166 -0
- package/servers/ls-server.ts +20 -0
- package/servers/multi-edit-server-handlers.ts +51 -0
- package/servers/multi-edit-server.ts +422 -0
- package/servers/notebook-edit-server-handlers.ts +34 -0
- package/servers/notebook-edit-server.ts +181 -0
- package/servers/orient-server-handlers.ts +52 -0
- package/servers/orient-server.ts +436 -0
- package/servers/pipe-server-handlers.ts +68 -0
- package/servers/pipe-server.ts +300 -0
- package/servers/read-server-handlers.ts +42 -0
- package/servers/read-server.ts +206 -0
- package/servers/rename-file-server-handlers.ts +67 -0
- package/servers/rename-file-server.ts +699 -0
- package/servers/savings-server-handlers.ts +27 -0
- package/servers/savings-server.ts +54 -0
- package/servers/search-replace-regex-server-handlers.ts +96 -0
- package/servers/search-replace-regex-server.ts +751 -0
- package/servers/sql-server-handlers.ts +58 -0
- package/servers/sql-server.ts +505 -0
- package/servers/task-server-handlers.ts +358 -0
- package/servers/task-server.ts +24 -0
- package/servers/test-server-handlers.ts +351 -0
- package/servers/test-server.ts +20 -0
- package/servers/tree-server-handlers.ts +503 -0
- package/servers/tree-server.ts +20 -0
- package/servers/webfetch-server-handlers.ts +166 -0
- package/servers/webfetch-server.ts +20 -0
- package/servers/websearch-server-handlers.ts +215 -0
- package/servers/websearch-server.ts +19 -0
- package/servers/write-server-handlers.ts +27 -0
- package/servers/write-server.ts +97 -0
- package/skills/ashlr-brief/SKILL.md +80 -0
- package/skills/ashlr-codex-doctor/SKILL.md +21 -0
- package/skills/ashlr-codex-efficient-tools/SKILL.md +17 -0
- package/skills/ashlr-codex-genome-refresh/SKILL.md +20 -0
- package/skills/ashlr-codex-parallel-explore/SKILL.md +20 -0
- package/skills/ashlr-codex-savings/SKILL.md +17 -0
- package/skills/ashlr-cost-refactor/SKILL.md +50 -0
- package/skills/ashlr-efficient/SKILL.md +64 -0
- package/skills/ashlr-genome-author/SKILL.md +43 -0
- package/skills/ashlr-lean-tools/SKILL.md +43 -0
- 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
|
+
}
|