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,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _token-measure.ts — Measured token counting via Anthropic API.
|
|
3
|
+
*
|
|
4
|
+
* Two modes:
|
|
5
|
+
* estimateTokens(text) — synchronous chars/4 heuristic (always available)
|
|
6
|
+
* measureTokens(text) — async Anthropic API call returning true input_tokens
|
|
7
|
+
*
|
|
8
|
+
* Design constraints:
|
|
9
|
+
* - NEVER blocks a hot path. All API calls are fire-and-forget from callers.
|
|
10
|
+
* - Returns null on missing API key, timeout, or any failure.
|
|
11
|
+
* - SHA-256 LRU cache persisted at ~/.ashlr/token-measure-cache.json (max 500).
|
|
12
|
+
* - 5s AbortSignal timeout per call.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { createHash } from "crypto";
|
|
16
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
17
|
+
import { homedir } from "os";
|
|
18
|
+
import { join } from "path";
|
|
19
|
+
import { estimateTokensFromString } from "@ashlr/core-efficiency";
|
|
20
|
+
|
|
21
|
+
export type MeasurementMode = "estimate" | "measured";
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Estimate (synchronous, always available)
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Estimate token count using the chars/4 heuristic. Wraps the shared
|
|
29
|
+
* estimateTokensFromString from @ashlr/core-efficiency for a single import
|
|
30
|
+
* surface.
|
|
31
|
+
*/
|
|
32
|
+
export function estimateTokens(text: string): number {
|
|
33
|
+
return estimateTokensFromString(text);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Cache
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
interface CacheEntry {
|
|
41
|
+
tokens: number;
|
|
42
|
+
/** ISO timestamp — used for eviction ordering */
|
|
43
|
+
at: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface CacheShape {
|
|
47
|
+
/** sha256(text) → entry */
|
|
48
|
+
entries: Record<string, CacheEntry>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const MAX_CACHE_ENTRIES = 500;
|
|
52
|
+
|
|
53
|
+
function cachePath(): string {
|
|
54
|
+
return join(process.env.HOME ?? homedir(), ".ashlr", "token-measure-cache.json");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function loadCache(): CacheShape {
|
|
58
|
+
try {
|
|
59
|
+
const p = cachePath();
|
|
60
|
+
if (!existsSync(p)) return { entries: {} };
|
|
61
|
+
const raw = readFileSync(p, "utf-8");
|
|
62
|
+
const parsed = JSON.parse(raw) as Partial<CacheShape>;
|
|
63
|
+
if (!parsed.entries || typeof parsed.entries !== "object") return { entries: {} };
|
|
64
|
+
return { entries: parsed.entries };
|
|
65
|
+
} catch {
|
|
66
|
+
return { entries: {} };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function saveCache(cache: CacheShape): void {
|
|
71
|
+
try {
|
|
72
|
+
const p = cachePath();
|
|
73
|
+
mkdirSync(join(p, ".."), { recursive: true });
|
|
74
|
+
writeFileSync(p, JSON.stringify(cache), "utf-8");
|
|
75
|
+
} catch {
|
|
76
|
+
// best-effort
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function cacheKey(text: string): string {
|
|
81
|
+
return createHash("sha256").update(text).digest("hex");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function evictIfNeeded(cache: CacheShape): void {
|
|
85
|
+
const keys = Object.keys(cache.entries);
|
|
86
|
+
if (keys.length <= MAX_CACHE_ENTRIES) return;
|
|
87
|
+
// Sort by timestamp ascending, drop oldest to get under limit
|
|
88
|
+
const sorted = keys.sort((a, b) => {
|
|
89
|
+
const ta = cache.entries[a]?.at ?? "";
|
|
90
|
+
const tb = cache.entries[b]?.at ?? "";
|
|
91
|
+
return ta < tb ? -1 : ta > tb ? 1 : 0;
|
|
92
|
+
});
|
|
93
|
+
const toRemove = sorted.slice(0, keys.length - MAX_CACHE_ENTRIES);
|
|
94
|
+
for (const k of toRemove) {
|
|
95
|
+
delete cache.entries[k];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Measure (async, requires ANTHROPIC_API_KEY)
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Measure true token count via Anthropic API.
|
|
105
|
+
*
|
|
106
|
+
* Returns null when:
|
|
107
|
+
* - ANTHROPIC_API_KEY is not set
|
|
108
|
+
* - Request times out (5s)
|
|
109
|
+
* - Any network or API error
|
|
110
|
+
* - Response shape is unexpected
|
|
111
|
+
*
|
|
112
|
+
* Results are cached by SHA-256(text) to avoid redundant API calls.
|
|
113
|
+
* NEVER throws — callers must be able to fire-and-forget.
|
|
114
|
+
*/
|
|
115
|
+
export async function measureTokens(text: string): Promise<number | null> {
|
|
116
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
117
|
+
if (!apiKey) return null;
|
|
118
|
+
|
|
119
|
+
const key = cacheKey(text);
|
|
120
|
+
const cache = loadCache();
|
|
121
|
+
|
|
122
|
+
// Cache hit
|
|
123
|
+
const cached = cache.entries[key];
|
|
124
|
+
if (cached && typeof cached.tokens === "number") {
|
|
125
|
+
return cached.tokens;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
130
|
+
method: "POST",
|
|
131
|
+
signal: AbortSignal.timeout(5_000),
|
|
132
|
+
headers: {
|
|
133
|
+
"x-api-key": apiKey,
|
|
134
|
+
"anthropic-version": "2023-06-01",
|
|
135
|
+
"content-type": "application/json",
|
|
136
|
+
},
|
|
137
|
+
body: JSON.stringify({
|
|
138
|
+
model: "claude-haiku-4-5",
|
|
139
|
+
max_tokens: 1,
|
|
140
|
+
messages: [{ role: "user", content: [{ type: "text", text }] }],
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (!res.ok) return null;
|
|
145
|
+
|
|
146
|
+
const json = (await res.json()) as { usage?: { input_tokens?: number } };
|
|
147
|
+
const tokens = json?.usage?.input_tokens;
|
|
148
|
+
if (typeof tokens !== "number" || !Number.isFinite(tokens)) return null;
|
|
149
|
+
|
|
150
|
+
// Store in cache
|
|
151
|
+
cache.entries[key] = { tokens, at: new Date().toISOString() };
|
|
152
|
+
evictIfNeeded(cache);
|
|
153
|
+
saveCache(cache);
|
|
154
|
+
|
|
155
|
+
return tokens;
|
|
156
|
+
} catch {
|
|
157
|
+
// timeout, network error, JSON parse error — all return null
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared MCP server scaffold.
|
|
3
|
+
*
|
|
4
|
+
* Tools migrate from per-server boilerplate (stdio setup, ListTools/CallTool
|
|
5
|
+
* request handlers, lookup-by-name switch) to this handler-style registration
|
|
6
|
+
* so they can be composed into a single router process (see `_router.ts`) or
|
|
7
|
+
* continue running as standalone MCP servers via `runStandalone()`.
|
|
8
|
+
*
|
|
9
|
+
* Adoption is incremental. Existing servers keep working unchanged; they can
|
|
10
|
+
* opt-in by switching their `new Server(...)` + `setRequestHandler(...)`
|
|
11
|
+
* boilerplate to `registerTool({...})` + `runStandalone(name)`.
|
|
12
|
+
*
|
|
13
|
+
* Cross-track contract: all four tracks (router, context-db, ast, compression)
|
|
14
|
+
* target this interface so handlers can be hoisted into `_router.ts` without
|
|
15
|
+
* per-track refactors.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
19
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
20
|
+
import {
|
|
21
|
+
CallToolRequestSchema,
|
|
22
|
+
ListToolsRequestSchema,
|
|
23
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
24
|
+
|
|
25
|
+
import { logEvent } from "./_events";
|
|
26
|
+
import { writeCrashDump } from "./_crash-dump";
|
|
27
|
+
import { openContextDb, type ContextDb } from "./_embedding-cache";
|
|
28
|
+
import { recordTelemetryEvent, isTelemetryEnabled } from "./_telemetry";
|
|
29
|
+
import { detectMcpHost, type McpHost } from "./_mcp-host";
|
|
30
|
+
|
|
31
|
+
/** Protocol-native guidance applies to every MCP host without host-specific hooks. */
|
|
32
|
+
export const MCP_EFFICIENCY_INSTRUCTIONS = [
|
|
33
|
+
"Use Ashlr tools for scoped, token-efficient repository retrieval: orient/tree for structure, grep for relevant symbols, then read the required files or ranges.",
|
|
34
|
+
"Compact or summarized results are navigation aids. Retrieve omitted source before editing or verifying behavior; never treat omitted content as absent.",
|
|
35
|
+
"Preserve task requirements, AGENTS.md instructions, authorization boundaries, citations, exact error details and verification evidence. Expand retrieval when any of these are missing.",
|
|
36
|
+
"Use diff-format edits and focused tests. Savings estimates apply only to the tool output actually shortened; model quality, task success and token savings require separate evidence.",
|
|
37
|
+
].join("\n");
|
|
38
|
+
|
|
39
|
+
export interface ToolCallContext {
|
|
40
|
+
/** CLAUDE_SESSION_ID (or ASHLR_SESSION_ID override) when present. */
|
|
41
|
+
sessionId?: string;
|
|
42
|
+
/** Raw process env — handlers should prefer this over globals for testability. */
|
|
43
|
+
env: NodeJS.ProcessEnv;
|
|
44
|
+
/** Which MCP host invoked this tool. Defaults to "claude-code" for backwards compat. */
|
|
45
|
+
host?: McpHost;
|
|
46
|
+
/**
|
|
47
|
+
* When true, the handler should skip savings accounting (recordSaving).
|
|
48
|
+
* Set by ashlr__pipe on intermediate ctx calls so that only the pipe
|
|
49
|
+
* itself records ONE aggregate saving — not each sub-call individually.
|
|
50
|
+
* Handlers that call recordSaving unconditionally may ignore this field;
|
|
51
|
+
* the savings-server and stats helpers check it in the pipe's call path.
|
|
52
|
+
*/
|
|
53
|
+
_noAccounting?: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ToolTextContent {
|
|
57
|
+
type: "text";
|
|
58
|
+
text: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface ToolResult {
|
|
62
|
+
content: ToolTextContent[];
|
|
63
|
+
isError?: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ToolHandler {
|
|
67
|
+
name: string;
|
|
68
|
+
description: string;
|
|
69
|
+
inputSchema: unknown;
|
|
70
|
+
handler: (args: Record<string, unknown>, ctx: ToolCallContext) => Promise<ToolResult>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const registry = new Map<string, ToolHandler>();
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Register a tool handler. Safe to call multiple times per-name (last
|
|
77
|
+
* registration wins — useful for tests and for track overrides during the
|
|
78
|
+
* router rollout).
|
|
79
|
+
*/
|
|
80
|
+
export function registerTool(tool: ToolHandler): void {
|
|
81
|
+
registry.set(tool.name, tool);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Return all currently registered handlers. */
|
|
85
|
+
export function listTools(): ToolHandler[] {
|
|
86
|
+
return Array.from(registry.values());
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Lookup a registered handler by name. */
|
|
90
|
+
export function getTool(name: string): ToolHandler | undefined {
|
|
91
|
+
return registry.get(name);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Test helper: drop all registrations. Do not call from production code. */
|
|
95
|
+
export function __resetRegistryForTests(): void {
|
|
96
|
+
registry.clear();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Test helper: return a snapshot of the current registry so a caller can
|
|
101
|
+
* restore it after a scoped reset. Pair with `__restoreRegistryForTests`
|
|
102
|
+
* to keep the crash-isolation suite from leaking a wiped registry into
|
|
103
|
+
* tests that depend on the production handler set being present.
|
|
104
|
+
*/
|
|
105
|
+
export function __snapshotRegistryForTests(): ReadonlyMap<string, ToolHandler> {
|
|
106
|
+
return new Map(registry);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Test helper: overwrite the current registry with a previously snapshotted map. */
|
|
110
|
+
export function __restoreRegistryForTests(snap: ReadonlyMap<string, ToolHandler>): void {
|
|
111
|
+
registry.clear();
|
|
112
|
+
for (const [k, v] of snap) registry.set(k, v);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// Shared process-wide resources
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
//
|
|
119
|
+
// Handlers registered on a single router process share the expensive
|
|
120
|
+
// resources (SQLite handles, LLM clients) via the getters below. Before
|
|
121
|
+
// router consolidation, every server opened its own context.db handle —
|
|
122
|
+
// fine standalone, wasteful once N handlers live in one process. These
|
|
123
|
+
// getters are lazy so importing `_tool-base` stays cheap for tests that
|
|
124
|
+
// don't touch embedding infra.
|
|
125
|
+
|
|
126
|
+
let _sharedCtxDb: ContextDb | null = null;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Process-wide embedding cache handle. Migrated handlers should call this
|
|
130
|
+
* instead of `openContextDb()` directly so the router keeps one SQLite
|
|
131
|
+
* handle per process. Honors `ASHLR_CONTEXT_DB_DISABLE=1` (returns a
|
|
132
|
+
* no-op stub) since the underlying factory already does.
|
|
133
|
+
*
|
|
134
|
+
* Concurrency note: this check-then-set is safe only while `openContextDb()`
|
|
135
|
+
* is synchronous (which it is today — bun:sqlite opens on the main thread).
|
|
136
|
+
* If the factory ever becomes async, two concurrent awaits will each observe
|
|
137
|
+
* `null` and open two handles. At that point, replace the lazy init with a
|
|
138
|
+
* `Promise<ContextDb>` memo so the first caller owns the open.
|
|
139
|
+
*/
|
|
140
|
+
export function getEmbeddingCache(): ContextDb {
|
|
141
|
+
if (!_sharedCtxDb) _sharedCtxDb = openContextDb();
|
|
142
|
+
return _sharedCtxDb;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Build an `isError: true` ToolResult for a caught exception with a
|
|
147
|
+
* tool-specific prefix. Handlers that want to surface expected errors as
|
|
148
|
+
* first-class results (rather than letting the dispatch catch emit a
|
|
149
|
+
* `tool_crashed` event) use this to keep the boilerplate in one place.
|
|
150
|
+
*/
|
|
151
|
+
export function toErrorResult(prefix: string, err: unknown): ToolResult {
|
|
152
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
153
|
+
return {
|
|
154
|
+
content: [{ type: "text", text: `${prefix}: ${message}` }],
|
|
155
|
+
isError: true,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Run the current tool registry as a standalone MCP server on stdio. Used by
|
|
161
|
+
* per-server entry points during the v1.12 → v1.13 migration so stale
|
|
162
|
+
* `plugin.json` files keep working. After router migration completes, most
|
|
163
|
+
* callers will go through `_router.ts` instead.
|
|
164
|
+
*/
|
|
165
|
+
export async function runStandalone(
|
|
166
|
+
serverName: string,
|
|
167
|
+
serverVersion: string = "1.0.0",
|
|
168
|
+
): Promise<void> {
|
|
169
|
+
const server = new Server(
|
|
170
|
+
{ name: serverName, version: serverVersion },
|
|
171
|
+
{ capabilities: { tools: {} }, instructions: MCP_EFFICIENCY_INSTRUCTIONS },
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
175
|
+
tools: listTools().map((t) => ({
|
|
176
|
+
name: t.name,
|
|
177
|
+
description: t.description,
|
|
178
|
+
inputSchema: t.inputSchema,
|
|
179
|
+
})),
|
|
180
|
+
}));
|
|
181
|
+
|
|
182
|
+
// Matches the inline pattern every per-server uses today: TS infers the
|
|
183
|
+
// object-literal return as a valid variant of the SDK's ServerResult union.
|
|
184
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
185
|
+
const tool = getTool(req.params.name);
|
|
186
|
+
if (!tool) {
|
|
187
|
+
return {
|
|
188
|
+
content: [{ type: "text" as const, text: `Unknown tool: ${req.params.name}` }],
|
|
189
|
+
isError: true,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const ctx: ToolCallContext = {
|
|
193
|
+
sessionId:
|
|
194
|
+
process.env.CLAUDE_SESSION_ID || process.env.ASHLR_SESSION_ID || undefined,
|
|
195
|
+
env: process.env,
|
|
196
|
+
host: detectMcpHost(),
|
|
197
|
+
};
|
|
198
|
+
try {
|
|
199
|
+
// SDK's ServerResult is a union that includes a task-based variant; a
|
|
200
|
+
// typed ToolResult does not widen to the union from a variable, so we
|
|
201
|
+
// cast at the call site (same effective shape, glob-server-style).
|
|
202
|
+
const dispatchStart = Date.now();
|
|
203
|
+
const result = (await tool.handler(req.params.arguments ?? {}, ctx)) as unknown;
|
|
204
|
+
const dispatchMs = Date.now() - dispatchStart;
|
|
205
|
+
|
|
206
|
+
// 1.1 — Emit tool_name on every MCP tool dispatch (opt-in, privacy-safe).
|
|
207
|
+
// tool.name is the MCP tool name (e.g. "ashlr__grep"). No args/paths logged.
|
|
208
|
+
if (isTelemetryEnabled()) {
|
|
209
|
+
recordTelemetryEvent({
|
|
210
|
+
kind: "tool_call",
|
|
211
|
+
tool: tool.name,
|
|
212
|
+
tool_name: tool.name,
|
|
213
|
+
rawBytes: 0, // byte accounting happens inside each handler
|
|
214
|
+
compactBytes: 0,
|
|
215
|
+
fellBack: false,
|
|
216
|
+
providerUsed: "local",
|
|
217
|
+
durationMs: dispatchMs,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return result as { content: unknown[] };
|
|
222
|
+
} catch (err) {
|
|
223
|
+
// Per-handler crash isolation: one handler's throw must not take the
|
|
224
|
+
// whole router down. Emit a tool_crashed event for observability, write
|
|
225
|
+
// a redacted on-disk crash dump for post-mortem, then return a
|
|
226
|
+
// structured error response.
|
|
227
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
228
|
+
const stack = err instanceof Error ? err.stack : undefined;
|
|
229
|
+
await logEvent("tool_crashed", {
|
|
230
|
+
tool: tool.name,
|
|
231
|
+
reason: msg,
|
|
232
|
+
extra: stack ? { stack: stack.split("\n").slice(0, 5).join("\n") } : undefined,
|
|
233
|
+
}).catch(() => undefined);
|
|
234
|
+
await writeCrashDump({
|
|
235
|
+
tool: tool.name,
|
|
236
|
+
args: req.params.arguments ?? {},
|
|
237
|
+
error: err,
|
|
238
|
+
});
|
|
239
|
+
return {
|
|
240
|
+
content: [{ type: "text" as const, text: `[ashlr:${tool.name}] handler crashed: ${msg}` }],
|
|
241
|
+
isError: true,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const transport = new StdioServerTransport();
|
|
247
|
+
await server.connect(transport);
|
|
248
|
+
}
|