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,98 @@
|
|
|
1
|
+
use crate::io::blocking::Blocking;
|
|
2
|
+
use crate::io::{AsyncRead, ReadBuf};
|
|
3
|
+
|
|
4
|
+
use std::io;
|
|
5
|
+
use std::pin::Pin;
|
|
6
|
+
use std::task::Context;
|
|
7
|
+
use std::task::Poll;
|
|
8
|
+
|
|
9
|
+
cfg_io_std! {
|
|
10
|
+
/// A handle to the standard input stream of a process.
|
|
11
|
+
///
|
|
12
|
+
/// The handle implements the [`AsyncRead`] trait, but beware that concurrent
|
|
13
|
+
/// reads of `Stdin` must be executed with care.
|
|
14
|
+
///
|
|
15
|
+
/// This handle is best used for non-interactive uses, such as when a file
|
|
16
|
+
/// is piped into the application. For technical reasons, `stdin` is
|
|
17
|
+
/// implemented by using an ordinary blocking read on a separate thread, and
|
|
18
|
+
/// it is impossible to cancel that read. This can make shutdown of the
|
|
19
|
+
/// runtime hang until the user presses enter.
|
|
20
|
+
///
|
|
21
|
+
/// For interactive uses, it is recommended to spawn a thread dedicated to
|
|
22
|
+
/// user input and use blocking IO directly in that thread.
|
|
23
|
+
///
|
|
24
|
+
/// Created by the [`stdin`] function.
|
|
25
|
+
///
|
|
26
|
+
/// [`stdin`]: fn@stdin
|
|
27
|
+
/// [`AsyncRead`]: trait@AsyncRead
|
|
28
|
+
#[derive(Debug)]
|
|
29
|
+
pub struct Stdin {
|
|
30
|
+
std: Blocking<std::io::Stdin>,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Constructs a new handle to the standard input of the current process.
|
|
34
|
+
///
|
|
35
|
+
/// This handle is best used for non-interactive uses, such as when a file
|
|
36
|
+
/// is piped into the application. For technical reasons, `stdin` is
|
|
37
|
+
/// implemented by using an ordinary blocking read on a separate thread, and
|
|
38
|
+
/// it is impossible to cancel that read. This can make shutdown of the
|
|
39
|
+
/// runtime hang until the user presses enter.
|
|
40
|
+
///
|
|
41
|
+
/// For interactive uses, it is recommended to spawn a thread dedicated to
|
|
42
|
+
/// user input and use blocking IO directly in that thread.
|
|
43
|
+
pub fn stdin() -> Stdin {
|
|
44
|
+
let std = io::stdin();
|
|
45
|
+
// SAFETY: The `Read` implementation of `std` does not read from the
|
|
46
|
+
// buffer it is borrowing and correctly reports the length of the data
|
|
47
|
+
// written into the buffer.
|
|
48
|
+
let std = unsafe { Blocking::new(std) };
|
|
49
|
+
Stdin {
|
|
50
|
+
std,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#[cfg(unix)]
|
|
56
|
+
mod sys {
|
|
57
|
+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
|
58
|
+
|
|
59
|
+
use super::Stdin;
|
|
60
|
+
|
|
61
|
+
impl AsRawFd for Stdin {
|
|
62
|
+
fn as_raw_fd(&self) -> RawFd {
|
|
63
|
+
std::io::stdin().as_raw_fd()
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
impl AsFd for Stdin {
|
|
68
|
+
fn as_fd(&self) -> BorrowedFd<'_> {
|
|
69
|
+
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
cfg_windows! {
|
|
75
|
+
use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
|
|
76
|
+
|
|
77
|
+
impl AsRawHandle for Stdin {
|
|
78
|
+
fn as_raw_handle(&self) -> RawHandle {
|
|
79
|
+
std::io::stdin().as_raw_handle()
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
impl AsHandle for Stdin {
|
|
84
|
+
fn as_handle(&self) -> BorrowedHandle<'_> {
|
|
85
|
+
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
impl AsyncRead for Stdin {
|
|
91
|
+
fn poll_read(
|
|
92
|
+
mut self: Pin<&mut Self>,
|
|
93
|
+
cx: &mut Context<'_>,
|
|
94
|
+
buf: &mut ReadBuf<'_>,
|
|
95
|
+
) -> Poll<io::Result<()>> {
|
|
96
|
+
Pin::new(&mut self.std).poll_read(cx, buf)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
//! Contains utilities for stdout and stderr.
|
|
2
|
+
use crate::io::AsyncWrite;
|
|
3
|
+
use std::pin::Pin;
|
|
4
|
+
use std::task::{Context, Poll};
|
|
5
|
+
/// # Windows
|
|
6
|
+
/// [`AsyncWrite`] adapter that finds last char boundary in given buffer and does not write the rest,
|
|
7
|
+
/// if buffer contents seems to be `utf8`. Otherwise it only trims buffer down to `DEFAULT_MAX_BUF_SIZE`.
|
|
8
|
+
/// That's why, wrapped writer will always receive well-formed utf-8 bytes.
|
|
9
|
+
/// # Other platforms
|
|
10
|
+
/// Passes data to `inner` as is.
|
|
11
|
+
#[derive(Debug)]
|
|
12
|
+
pub(crate) struct SplitByUtf8BoundaryIfWindows<W> {
|
|
13
|
+
inner: W,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
impl<W> SplitByUtf8BoundaryIfWindows<W> {
|
|
17
|
+
pub(crate) fn new(inner: W) -> Self {
|
|
18
|
+
Self { inner }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// this constant is defined by Unicode standard.
|
|
23
|
+
const MAX_BYTES_PER_CHAR: usize = 4;
|
|
24
|
+
|
|
25
|
+
// Subject for tweaking here
|
|
26
|
+
const MAGIC_CONST: usize = 8;
|
|
27
|
+
|
|
28
|
+
impl<W> crate::io::AsyncWrite for SplitByUtf8BoundaryIfWindows<W>
|
|
29
|
+
where
|
|
30
|
+
W: AsyncWrite + Unpin,
|
|
31
|
+
{
|
|
32
|
+
fn poll_write(
|
|
33
|
+
mut self: Pin<&mut Self>,
|
|
34
|
+
cx: &mut Context<'_>,
|
|
35
|
+
mut buf: &[u8],
|
|
36
|
+
) -> Poll<Result<usize, std::io::Error>> {
|
|
37
|
+
// just a closure to avoid repetitive code
|
|
38
|
+
let mut call_inner = move |buf| Pin::new(&mut self.inner).poll_write(cx, buf);
|
|
39
|
+
|
|
40
|
+
// 1. Only windows stdio can suffer from non-utf8.
|
|
41
|
+
// We also check for `test` so that we can write some tests
|
|
42
|
+
// for further code. Since `AsyncWrite` can always shrink
|
|
43
|
+
// buffer at its discretion, excessive (i.e. in tests) shrinking
|
|
44
|
+
// does not break correctness.
|
|
45
|
+
// 2. If buffer is small, it will not be shrunk.
|
|
46
|
+
// That's why, it's "textness" will not change, so we don't have
|
|
47
|
+
// to fixup it.
|
|
48
|
+
if cfg!(not(any(target_os = "windows", test)))
|
|
49
|
+
|| buf.len() <= crate::io::blocking::DEFAULT_MAX_BUF_SIZE
|
|
50
|
+
{
|
|
51
|
+
return call_inner(buf);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
buf = &buf[..crate::io::blocking::DEFAULT_MAX_BUF_SIZE];
|
|
55
|
+
|
|
56
|
+
// Now there are two possibilities.
|
|
57
|
+
// If caller gave is binary buffer, we **should not** shrink it
|
|
58
|
+
// anymore, because excessive shrinking hits performance.
|
|
59
|
+
// If caller gave as binary buffer, we **must** additionally
|
|
60
|
+
// shrink it to strip incomplete char at the end of buffer.
|
|
61
|
+
// that's why check we will perform now is allowed to have
|
|
62
|
+
// false-positive.
|
|
63
|
+
|
|
64
|
+
// Now let's look at the first MAX_BYTES_PER_CHAR * MAGIC_CONST bytes.
|
|
65
|
+
// if they are (possibly incomplete) utf8, then we can be quite sure
|
|
66
|
+
// that input buffer was utf8.
|
|
67
|
+
|
|
68
|
+
let have_to_fix_up = match std::str::from_utf8(&buf[..MAX_BYTES_PER_CHAR * MAGIC_CONST]) {
|
|
69
|
+
Ok(_) => true,
|
|
70
|
+
Err(err) => {
|
|
71
|
+
let incomplete_bytes = MAX_BYTES_PER_CHAR * MAGIC_CONST - err.valid_up_to();
|
|
72
|
+
incomplete_bytes < MAX_BYTES_PER_CHAR
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
if have_to_fix_up {
|
|
77
|
+
// We must pop several bytes at the end which form incomplete
|
|
78
|
+
// character. To achieve it, we exploit UTF8 encoding:
|
|
79
|
+
// for any code point, all bytes except first start with 0b10 prefix.
|
|
80
|
+
// see https://en.wikipedia.org/wiki/UTF-8#Encoding for details
|
|
81
|
+
let trailing_incomplete_char_size = buf
|
|
82
|
+
.iter()
|
|
83
|
+
.rev()
|
|
84
|
+
.take(MAX_BYTES_PER_CHAR)
|
|
85
|
+
.position(|byte| *byte < 0b1000_0000 || *byte >= 0b1100_0000)
|
|
86
|
+
.unwrap_or(0)
|
|
87
|
+
+ 1;
|
|
88
|
+
buf = &buf[..buf.len() - trailing_incomplete_char_size];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
call_inner(buf)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
fn poll_flush(
|
|
95
|
+
mut self: Pin<&mut Self>,
|
|
96
|
+
cx: &mut Context<'_>,
|
|
97
|
+
) -> Poll<Result<(), std::io::Error>> {
|
|
98
|
+
Pin::new(&mut self.inner).poll_flush(cx)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fn poll_shutdown(
|
|
102
|
+
mut self: Pin<&mut Self>,
|
|
103
|
+
cx: &mut Context<'_>,
|
|
104
|
+
) -> Poll<Result<(), std::io::Error>> {
|
|
105
|
+
Pin::new(&mut self.inner).poll_shutdown(cx)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
#[cfg(test)]
|
|
110
|
+
#[cfg(not(loom))]
|
|
111
|
+
mod tests {
|
|
112
|
+
use crate::io::blocking::DEFAULT_MAX_BUF_SIZE;
|
|
113
|
+
use crate::io::AsyncWriteExt;
|
|
114
|
+
use std::io;
|
|
115
|
+
use std::pin::Pin;
|
|
116
|
+
use std::task::Context;
|
|
117
|
+
use std::task::Poll;
|
|
118
|
+
|
|
119
|
+
struct TextMockWriter;
|
|
120
|
+
|
|
121
|
+
impl crate::io::AsyncWrite for TextMockWriter {
|
|
122
|
+
fn poll_write(
|
|
123
|
+
self: Pin<&mut Self>,
|
|
124
|
+
_cx: &mut Context<'_>,
|
|
125
|
+
buf: &[u8],
|
|
126
|
+
) -> Poll<Result<usize, io::Error>> {
|
|
127
|
+
assert!(buf.len() <= DEFAULT_MAX_BUF_SIZE);
|
|
128
|
+
assert!(std::str::from_utf8(buf).is_ok());
|
|
129
|
+
Poll::Ready(Ok(buf.len()))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
|
133
|
+
Poll::Ready(Ok(()))
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
fn poll_shutdown(
|
|
137
|
+
self: Pin<&mut Self>,
|
|
138
|
+
_cx: &mut Context<'_>,
|
|
139
|
+
) -> Poll<Result<(), io::Error>> {
|
|
140
|
+
Poll::Ready(Ok(()))
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
struct LoggingMockWriter {
|
|
145
|
+
write_history: Vec<usize>,
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
impl LoggingMockWriter {
|
|
149
|
+
fn new() -> Self {
|
|
150
|
+
LoggingMockWriter {
|
|
151
|
+
write_history: Vec::new(),
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
impl crate::io::AsyncWrite for LoggingMockWriter {
|
|
157
|
+
fn poll_write(
|
|
158
|
+
mut self: Pin<&mut Self>,
|
|
159
|
+
_cx: &mut Context<'_>,
|
|
160
|
+
buf: &[u8],
|
|
161
|
+
) -> Poll<Result<usize, io::Error>> {
|
|
162
|
+
assert!(buf.len() <= DEFAULT_MAX_BUF_SIZE);
|
|
163
|
+
self.write_history.push(buf.len());
|
|
164
|
+
Poll::Ready(Ok(buf.len()))
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
|
168
|
+
Poll::Ready(Ok(()))
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
fn poll_shutdown(
|
|
172
|
+
self: Pin<&mut Self>,
|
|
173
|
+
_cx: &mut Context<'_>,
|
|
174
|
+
) -> Poll<Result<(), io::Error>> {
|
|
175
|
+
Poll::Ready(Ok(()))
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
#[test]
|
|
180
|
+
#[cfg_attr(miri, ignore)] // takes a really long time with miri
|
|
181
|
+
fn test_splitter() {
|
|
182
|
+
let data = str::repeat("█", DEFAULT_MAX_BUF_SIZE);
|
|
183
|
+
let mut wr = super::SplitByUtf8BoundaryIfWindows::new(TextMockWriter);
|
|
184
|
+
let fut = async move {
|
|
185
|
+
wr.write_all(data.as_bytes()).await.unwrap();
|
|
186
|
+
};
|
|
187
|
+
crate::runtime::Builder::new_current_thread()
|
|
188
|
+
.build()
|
|
189
|
+
.unwrap()
|
|
190
|
+
.block_on(fut);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
#[test]
|
|
194
|
+
#[cfg_attr(miri, ignore)] // takes a really long time with miri
|
|
195
|
+
fn test_pseudo_text() {
|
|
196
|
+
// In this test we write a piece of binary data, whose beginning is
|
|
197
|
+
// text though. We then validate that even in this corner case buffer
|
|
198
|
+
// was not shrunk too much.
|
|
199
|
+
let checked_count = super::MAGIC_CONST * super::MAX_BYTES_PER_CHAR;
|
|
200
|
+
let mut data: Vec<u8> = str::repeat("a", checked_count).into();
|
|
201
|
+
data.extend(std::iter::repeat(0b1010_1010).take(DEFAULT_MAX_BUF_SIZE - checked_count + 1));
|
|
202
|
+
let mut writer = LoggingMockWriter::new();
|
|
203
|
+
let mut splitter = super::SplitByUtf8BoundaryIfWindows::new(&mut writer);
|
|
204
|
+
crate::runtime::Builder::new_current_thread()
|
|
205
|
+
.build()
|
|
206
|
+
.unwrap()
|
|
207
|
+
.block_on(async {
|
|
208
|
+
splitter.write_all(&data).await.unwrap();
|
|
209
|
+
});
|
|
210
|
+
// Check that at most two writes were performed
|
|
211
|
+
assert!(writer.write_history.len() <= 2);
|
|
212
|
+
// Check that all has been written
|
|
213
|
+
assert_eq!(
|
|
214
|
+
writer.write_history.iter().copied().sum::<usize>(),
|
|
215
|
+
data.len()
|
|
216
|
+
);
|
|
217
|
+
// Check that at most MAX_BYTES_PER_CHAR + 1 (i.e. 5) bytes were shrunk
|
|
218
|
+
// from the buffer: one because it was outside of DEFAULT_MAX_BUF_SIZE boundary, and
|
|
219
|
+
// up to one "utf8 code point".
|
|
220
|
+
assert!(data.len() - writer.write_history[0] <= super::MAX_BYTES_PER_CHAR + 1);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
use crate::io::blocking::Blocking;
|
|
2
|
+
use crate::io::stdio_common::SplitByUtf8BoundaryIfWindows;
|
|
3
|
+
use crate::io::AsyncWrite;
|
|
4
|
+
use std::io;
|
|
5
|
+
use std::pin::Pin;
|
|
6
|
+
use std::task::Context;
|
|
7
|
+
use std::task::Poll;
|
|
8
|
+
|
|
9
|
+
cfg_io_std! {
|
|
10
|
+
/// A handle to the standard output stream of a process.
|
|
11
|
+
///
|
|
12
|
+
/// Concurrent writes to stdout must be executed with care: Only individual
|
|
13
|
+
/// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
|
|
14
|
+
/// you should be aware that writes using [`write_all`] are not guaranteed
|
|
15
|
+
/// to occur as a single write, so multiple threads writing data with
|
|
16
|
+
/// [`write_all`] may result in interleaved output.
|
|
17
|
+
///
|
|
18
|
+
/// Created by the [`stdout`] function.
|
|
19
|
+
///
|
|
20
|
+
/// [`stdout`]: stdout()
|
|
21
|
+
/// [`AsyncWrite`]: AsyncWrite
|
|
22
|
+
/// [`write_all`]: crate::io::AsyncWriteExt::write_all()
|
|
23
|
+
///
|
|
24
|
+
/// # Examples
|
|
25
|
+
///
|
|
26
|
+
/// ```
|
|
27
|
+
/// use tokio::io::{self, AsyncWriteExt};
|
|
28
|
+
///
|
|
29
|
+
/// #[tokio::main]
|
|
30
|
+
/// async fn main() -> io::Result<()> {
|
|
31
|
+
/// let mut stdout = io::stdout();
|
|
32
|
+
/// stdout.write_all(b"Hello world!").await?;
|
|
33
|
+
/// Ok(())
|
|
34
|
+
/// }
|
|
35
|
+
/// ```
|
|
36
|
+
///
|
|
37
|
+
/// The following is an example of using `stdio` with loop.
|
|
38
|
+
///
|
|
39
|
+
/// ```
|
|
40
|
+
/// use tokio::io::{self, AsyncWriteExt};
|
|
41
|
+
///
|
|
42
|
+
/// #[tokio::main]
|
|
43
|
+
/// async fn main() {
|
|
44
|
+
/// let messages = vec!["hello", " world\n"];
|
|
45
|
+
///
|
|
46
|
+
/// // When you use `stdio` in a loop, it is recommended to create
|
|
47
|
+
/// // a single `stdio` instance outside the loop and call a write
|
|
48
|
+
/// // operation against that instance on each loop.
|
|
49
|
+
/// //
|
|
50
|
+
/// // Repeatedly creating `stdout` instances inside the loop and
|
|
51
|
+
/// // writing to that handle could result in mangled output since
|
|
52
|
+
/// // each write operation is handled by a different blocking thread.
|
|
53
|
+
/// let mut stdout = io::stdout();
|
|
54
|
+
///
|
|
55
|
+
/// for message in &messages {
|
|
56
|
+
/// stdout.write_all(message.as_bytes()).await.unwrap();
|
|
57
|
+
/// stdout.flush().await.unwrap();
|
|
58
|
+
/// }
|
|
59
|
+
/// }
|
|
60
|
+
/// ```
|
|
61
|
+
#[derive(Debug)]
|
|
62
|
+
pub struct Stdout {
|
|
63
|
+
std: SplitByUtf8BoundaryIfWindows<Blocking<std::io::Stdout>>,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// Constructs a new handle to the standard output of the current process.
|
|
67
|
+
///
|
|
68
|
+
/// The returned handle allows writing to standard out from the within the
|
|
69
|
+
/// Tokio runtime.
|
|
70
|
+
///
|
|
71
|
+
/// Concurrent writes to stdout must be executed with care: Only individual
|
|
72
|
+
/// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
|
|
73
|
+
/// you should be aware that writes using [`write_all`] are not guaranteed
|
|
74
|
+
/// to occur as a single write, so multiple threads writing data with
|
|
75
|
+
/// [`write_all`] may result in interleaved output.
|
|
76
|
+
///
|
|
77
|
+
/// Note that unlike [`std::io::stdout`], each call to this `stdout()`
|
|
78
|
+
/// produces a new writer, so for example, this program does **not** flush stdout:
|
|
79
|
+
///
|
|
80
|
+
/// ```no_run
|
|
81
|
+
/// # use tokio::io::AsyncWriteExt;
|
|
82
|
+
/// # #[tokio::main]
|
|
83
|
+
/// # async fn main() -> std::io::Result<()> {
|
|
84
|
+
/// tokio::io::stdout().write_all(b"aa").await?;
|
|
85
|
+
/// tokio::io::stdout().flush().await?;
|
|
86
|
+
/// # Ok(())
|
|
87
|
+
/// # }
|
|
88
|
+
/// ```
|
|
89
|
+
///
|
|
90
|
+
/// [`std::io::stdout`]: std::io::stdout
|
|
91
|
+
/// [`AsyncWrite`]: AsyncWrite
|
|
92
|
+
/// [`write_all`]: crate::io::AsyncWriteExt::write_all()
|
|
93
|
+
///
|
|
94
|
+
/// # Examples
|
|
95
|
+
///
|
|
96
|
+
/// ```
|
|
97
|
+
/// use tokio::io::{self, AsyncWriteExt};
|
|
98
|
+
///
|
|
99
|
+
/// #[tokio::main]
|
|
100
|
+
/// async fn main() -> io::Result<()> {
|
|
101
|
+
/// let mut stdout = io::stdout();
|
|
102
|
+
/// stdout.write_all(b"Hello world!").await?;
|
|
103
|
+
/// Ok(())
|
|
104
|
+
/// }
|
|
105
|
+
/// ```
|
|
106
|
+
///
|
|
107
|
+
/// The following is an example of using `stdio` with loop.
|
|
108
|
+
///
|
|
109
|
+
/// ```
|
|
110
|
+
/// use tokio::io::{self, AsyncWriteExt};
|
|
111
|
+
///
|
|
112
|
+
/// #[tokio::main]
|
|
113
|
+
/// async fn main() {
|
|
114
|
+
/// let messages = vec!["hello", " world\n"];
|
|
115
|
+
///
|
|
116
|
+
/// // When you use `stdio` in a loop, it is recommended to create
|
|
117
|
+
/// // a single `stdio` instance outside the loop and call a write
|
|
118
|
+
/// // operation against that instance on each loop.
|
|
119
|
+
/// //
|
|
120
|
+
/// // Repeatedly creating `stdout` instances inside the loop and
|
|
121
|
+
/// // writing to that handle could result in mangled output since
|
|
122
|
+
/// // each write operation is handled by a different blocking thread.
|
|
123
|
+
/// let mut stdout = io::stdout();
|
|
124
|
+
///
|
|
125
|
+
/// for message in &messages {
|
|
126
|
+
/// stdout.write_all(message.as_bytes()).await.unwrap();
|
|
127
|
+
/// stdout.flush().await.unwrap();
|
|
128
|
+
/// }
|
|
129
|
+
/// }
|
|
130
|
+
/// ```
|
|
131
|
+
pub fn stdout() -> Stdout {
|
|
132
|
+
let std = io::stdout();
|
|
133
|
+
// SAFETY: The `Read` implementation of `std` does not read from the
|
|
134
|
+
// buffer it is borrowing and correctly reports the length of the data
|
|
135
|
+
// written into the buffer.
|
|
136
|
+
let blocking = unsafe { Blocking::new(std) };
|
|
137
|
+
Stdout {
|
|
138
|
+
std: SplitByUtf8BoundaryIfWindows::new(blocking),
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#[cfg(unix)]
|
|
144
|
+
mod sys {
|
|
145
|
+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
|
146
|
+
|
|
147
|
+
use super::Stdout;
|
|
148
|
+
|
|
149
|
+
impl AsRawFd for Stdout {
|
|
150
|
+
fn as_raw_fd(&self) -> RawFd {
|
|
151
|
+
std::io::stdout().as_raw_fd()
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
impl AsFd for Stdout {
|
|
156
|
+
fn as_fd(&self) -> BorrowedFd<'_> {
|
|
157
|
+
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
cfg_windows! {
|
|
163
|
+
use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
|
|
164
|
+
|
|
165
|
+
impl AsRawHandle for Stdout {
|
|
166
|
+
fn as_raw_handle(&self) -> RawHandle {
|
|
167
|
+
std::io::stdout().as_raw_handle()
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
impl AsHandle for Stdout {
|
|
172
|
+
fn as_handle(&self) -> BorrowedHandle<'_> {
|
|
173
|
+
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
impl AsyncWrite for Stdout {
|
|
179
|
+
fn poll_write(
|
|
180
|
+
mut self: Pin<&mut Self>,
|
|
181
|
+
cx: &mut Context<'_>,
|
|
182
|
+
buf: &[u8],
|
|
183
|
+
) -> Poll<io::Result<usize>> {
|
|
184
|
+
Pin::new(&mut self.std).poll_write(cx, buf)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
|
188
|
+
Pin::new(&mut self.std).poll_flush(cx)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
fn poll_shutdown(
|
|
192
|
+
mut self: Pin<&mut Self>,
|
|
193
|
+
cx: &mut Context<'_>,
|
|
194
|
+
) -> Poll<Result<(), io::Error>> {
|
|
195
|
+
Pin::new(&mut self.std).poll_shutdown(cx)
|
|
196
|
+
}
|
|
197
|
+
}
|