mixdog 0.7.1
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/.claude-plugin/marketplace.json +31 -0
- package/.claude-plugin/plugin.json +20 -0
- package/.gitattributes +34 -0
- package/.mcp.json +14 -0
- package/ARCHITECTURE.md +77 -0
- package/CHANGELOG.md +7 -0
- package/CONTRIBUTING.md +45 -0
- package/DATA-FLOW.md +79 -0
- package/LICENSE +21 -0
- package/README.md +389 -0
- package/SECURITY.md +138 -0
- package/UNINSTALL.md +112 -0
- package/agents/maintenance.md +5 -0
- package/agents/memory-classification.md +30 -0
- package/agents/scheduler-task.md +18 -0
- package/agents/webhook-handler.md +27 -0
- package/agents/worker.md +24 -0
- package/bin/bridge +133 -0
- package/bin/statusline-launcher.mjs +78 -0
- package/bin/statusline-lib.mjs +550 -0
- package/bin/statusline.mjs +607 -0
- package/bun.lock +802 -0
- package/commands/config.md +16 -0
- package/commands/doctor.md +13 -0
- package/commands/setup.md +17 -0
- package/defaults/cycle3-review-prompt.md +90 -0
- package/defaults/hidden-roles.json +65 -0
- package/defaults/memory-chunk-prompt.md +63 -0
- package/defaults/memory-promote-prompt.md +135 -0
- package/defaults/mixdog-config.template.json +27 -0
- package/defaults/user-workflow.json +8 -0
- package/defaults/user-workflow.md +12 -0
- package/hooks/hooks.json +73 -0
- package/hooks/lib/active-instance.cjs +77 -0
- package/hooks/lib/permission-evaluator.cjs +411 -0
- package/hooks/lib/permission-route.cjs +63 -0
- package/hooks/lib/permission-rules.cjs +170 -0
- package/hooks/lib/settings-loader.cjs +116 -0
- package/hooks/post-tool-use.cjs +84 -0
- package/hooks/pre-mcp-sandbox.cjs +158 -0
- package/hooks/pre-tool-subagent.cjs +253 -0
- package/hooks/session-start.cjs +1372 -0
- package/hooks/turn-timer.cjs +82 -0
- package/lib/claude-md-writer.cjs +386 -0
- package/lib/config-cjs.cjs +61 -0
- package/lib/hook-pipe-path.cjs +10 -0
- package/lib/keychain-cjs.cjs +263 -0
- package/lib/plugin-paths.cjs +61 -0
- package/lib/rules-builder.cjs +241 -0
- package/lib/text-utils.cjs +61 -0
- package/native/README.md +117 -0
- package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
- package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
- package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
- package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
- package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
- package/package.json +107 -0
- package/prompts/code-review.txt +16 -0
- package/prompts/security-audit.txt +17 -0
- package/rules/bridge/00-common.md +39 -0
- package/rules/bridge/20-skip-protocol.md +18 -0
- package/rules/bridge/30-explorer.md +33 -0
- package/rules/bridge/40-cycle1-agent.md +52 -0
- package/rules/bridge/41-cycle2-agent.md +62 -0
- package/rules/bridge/42-cycle3-agent.md +44 -0
- package/rules/lead/00-tool-lead.md +61 -0
- package/rules/lead/01-general.md +23 -0
- package/rules/lead/02-channels.md +49 -0
- package/rules/lead/03-team.md +27 -0
- package/rules/lead/04-workflow.md +20 -0
- package/rules/shared/00-language.md +14 -0
- package/rules/shared/01-tool.md +138 -0
- package/scripts/bootstrap.mjs +184 -0
- package/scripts/bridge-unify-smoke.mjs +308 -0
- package/scripts/build-runtime-linux.sh +348 -0
- package/scripts/build-runtime-macos.sh +217 -0
- package/scripts/build-runtime-windows.ps1 +242 -0
- package/scripts/builtin-utils-smoke.mjs +392 -0
- package/scripts/check-json.mjs +45 -0
- package/scripts/check-syntax-changed.mjs +102 -0
- package/scripts/check-syntax.mjs +58 -0
- package/scripts/code-graph-batch.test.mjs +33 -0
- package/scripts/config-preserve-smoke.mjs +180 -0
- package/scripts/doctor.mjs +484 -0
- package/scripts/edit-normalize-fuzz.mjs +130 -0
- package/scripts/edit-normalize-smoke.mjs +401 -0
- package/scripts/edit-operation-smoke.mjs +369 -0
- package/scripts/edit2-smoke.mjs +63 -0
- package/scripts/fuzzy-e2e.mjs +28 -0
- package/scripts/fuzzy-smoke.mjs +26 -0
- package/scripts/generate-runtime-manifest.mjs +166 -0
- package/scripts/guard-smoke.mjs +66 -0
- package/scripts/hidden-role-schema-smoke.mjs +162 -0
- package/scripts/hook-routing-smoke.mjs +29 -0
- package/scripts/inject-input.ps1 +204 -0
- package/scripts/io-complex-smoke.mjs +667 -0
- package/scripts/io-explore-bench.mjs +424 -0
- package/scripts/io-guardrails-smoke.mjs +205 -0
- package/scripts/io-mini-bench-baseline.json +11 -0
- package/scripts/io-mini-bench.mjs +216 -0
- package/scripts/io-route-harness.mjs +933 -0
- package/scripts/io-telemetry-report.mjs +691 -0
- package/scripts/mutation-bench.mjs +564 -0
- package/scripts/mutation-io-smoke.mjs +1081 -0
- package/scripts/native-patch-bridge-smoke.mjs +288 -0
- package/scripts/native-patch-smoke.mjs +304 -0
- package/scripts/patch-interior-context-smoke.mjs +49 -0
- package/scripts/patch-newline-utf8-smoke.mjs +157 -0
- package/scripts/perf-hook-smoke.mjs +71 -0
- package/scripts/permission-eval-smoke.mjs +426 -0
- package/scripts/prep-patch.mjs +53 -0
- package/scripts/prep-shim.mjs +96 -0
- package/scripts/provider-cache-smoke.mjs +687 -0
- package/scripts/report-runtime-health.mjs +132 -0
- package/scripts/run-mcp.mjs +1547 -0
- package/scripts/salvage-v4a-shatter.test.mjs +58 -0
- package/scripts/scoped-cache-io-smoke.mjs +103 -0
- package/scripts/shell-policy-round3-smoke.mjs +46 -0
- package/scripts/smoke-runtime-negative.ps1 +100 -0
- package/scripts/smoke-runtime-negative.sh +95 -0
- package/scripts/stall-policy-smoke.mjs +50 -0
- package/scripts/start-memory-worker.mjs +23 -0
- package/scripts/statusline-launcher-smoke.mjs +82 -0
- package/scripts/stress-atomic-write.mjs +1028 -0
- package/scripts/test-config-rmw-restore.mjs +122 -0
- package/scripts/test-fault-inject.mjs +164 -0
- package/scripts/test-large-file.mjs +174 -0
- package/scripts/tool-edge-smoke.mjs +209 -0
- package/scripts/uninstall.mjs +201 -0
- package/scripts/webhook-selfheal-smoke.mjs +29 -0
- package/scripts/write-overwrite-guard-smoke.mjs +56 -0
- package/server-main.mjs +3055 -0
- package/server.mjs +468 -0
- package/setup/config-merge.mjs +254 -0
- package/setup/install.mjs +120 -0
- package/setup/launch-core.mjs +507 -0
- package/setup/launch.mjs +101 -0
- package/setup/setup-server.mjs +3206 -0
- package/setup/setup.html +3693 -0
- package/skills/retro-skill-proposer/SKILL.md +92 -0
- package/skills/schedule-add/SKILL.md +77 -0
- package/skills/setup/SKILL.md +346 -0
- package/skills/webhook-add/SKILL.md +81 -0
- package/src/agent/bridge-stall-watchdog.mjs +337 -0
- package/src/agent/index.mjs +2138 -0
- package/src/agent/orchestrator/activity-bus.mjs +38 -0
- package/src/agent/orchestrator/ai-wrapped-dispatch.mjs +1010 -0
- package/src/agent/orchestrator/bridge-retry.mjs +220 -0
- package/src/agent/orchestrator/bridge-trace.mjs +583 -0
- package/src/agent/orchestrator/cache-mtime.mjs +58 -0
- package/src/agent/orchestrator/config.mjs +358 -0
- package/src/agent/orchestrator/context/collect.mjs +651 -0
- package/src/agent/orchestrator/dispatch-persist.mjs +549 -0
- package/src/agent/orchestrator/drain-registry.mjs +50 -0
- package/src/agent/orchestrator/explore-validator.mjs +8 -0
- package/src/agent/orchestrator/internal-roles.mjs +118 -0
- package/src/agent/orchestrator/internal-tools.mjs +88 -0
- package/src/agent/orchestrator/jobs.mjs +116 -0
- package/src/agent/orchestrator/mcp/client.mjs +364 -0
- package/src/agent/orchestrator/providers/anthropic-betas.mjs +21 -0
- package/src/agent/orchestrator/providers/anthropic-oauth.mjs +1745 -0
- package/src/agent/orchestrator/providers/anthropic.mjs +437 -0
- package/src/agent/orchestrator/providers/gemini.mjs +1175 -0
- package/src/agent/orchestrator/providers/grok-oauth.mjs +782 -0
- package/src/agent/orchestrator/providers/model-catalog.mjs +241 -0
- package/src/agent/orchestrator/providers/openai-compat.mjs +1467 -0
- package/src/agent/orchestrator/providers/openai-oauth-ws.mjs +1890 -0
- package/src/agent/orchestrator/providers/openai-oauth.mjs +1307 -0
- package/src/agent/orchestrator/providers/openai-ws.mjs +104 -0
- package/src/agent/orchestrator/providers/registry.mjs +192 -0
- package/src/agent/orchestrator/providers/retry-classifier.mjs +325 -0
- package/src/agent/orchestrator/session/abort-lookup.mjs +13 -0
- package/src/agent/orchestrator/session/cache/post-edit-marks.mjs +42 -0
- package/src/agent/orchestrator/session/cache/prefetch-cache.mjs +142 -0
- package/src/agent/orchestrator/session/cache/read-cache.mjs +319 -0
- package/src/agent/orchestrator/session/cache/scoped-cache-outcome.mjs +11 -0
- package/src/agent/orchestrator/session/cache/scoped-cache.mjs +361 -0
- package/src/agent/orchestrator/session/cache/util.mjs +49 -0
- package/src/agent/orchestrator/session/loop.mjs +1478 -0
- package/src/agent/orchestrator/session/manager.mjs +1975 -0
- package/src/agent/orchestrator/session/read-dedup.mjs +6 -0
- package/src/agent/orchestrator/session/result-classification.mjs +65 -0
- package/src/agent/orchestrator/session/save-session-worker.mjs +18 -0
- package/src/agent/orchestrator/session/store.mjs +624 -0
- package/src/agent/orchestrator/session/stream-watchdog.mjs +130 -0
- package/src/agent/orchestrator/session/tool-result-offload.mjs +166 -0
- package/src/agent/orchestrator/session/trim.mjs +491 -0
- package/src/agent/orchestrator/smart-bridge/CACHE-SHARD.md +115 -0
- package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +327 -0
- package/src/agent/orchestrator/smart-bridge/cache-obs.mjs +150 -0
- package/src/agent/orchestrator/smart-bridge/cache-strategy.mjs +228 -0
- package/src/agent/orchestrator/smart-bridge/index.mjs +215 -0
- package/src/agent/orchestrator/smart-bridge/profiles.mjs +37 -0
- package/src/agent/orchestrator/smart-bridge/registry.mjs +348 -0
- package/src/agent/orchestrator/smart-bridge/session-builder.mjs +116 -0
- package/src/agent/orchestrator/stall-policy.mjs +195 -0
- package/src/agent/orchestrator/tool-loop-guard.mjs +75 -0
- package/src/agent/orchestrator/tools/bash-policy-scan.mjs +77 -0
- package/src/agent/orchestrator/tools/bash-session.mjs +721 -0
- package/src/agent/orchestrator/tools/builtin/advisory-lock.mjs +171 -0
- package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +455 -0
- package/src/agent/orchestrator/tools/builtin/atomic-write.mjs +236 -0
- package/src/agent/orchestrator/tools/builtin/bash-tool.mjs +480 -0
- package/src/agent/orchestrator/tools/builtin/binary-file.mjs +76 -0
- package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +256 -0
- package/src/agent/orchestrator/tools/builtin/cache-layers.mjs +386 -0
- package/src/agent/orchestrator/tools/builtin/cwd-utils.mjs +37 -0
- package/src/agent/orchestrator/tools/builtin/device-paths.mjs +154 -0
- package/src/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +292 -0
- package/src/agent/orchestrator/tools/builtin/diff-utils.mjs +109 -0
- package/src/agent/orchestrator/tools/builtin/edit-base-guard.mjs +58 -0
- package/src/agent/orchestrator/tools/builtin/edit-byte-plan.mjs +240 -0
- package/src/agent/orchestrator/tools/builtin/edit-byte-utils.mjs +113 -0
- package/src/agent/orchestrator/tools/builtin/edit-commit.mjs +74 -0
- package/src/agent/orchestrator/tools/builtin/edit-context-utils.mjs +242 -0
- package/src/agent/orchestrator/tools/builtin/edit-diagnostics.mjs +211 -0
- package/src/agent/orchestrator/tools/builtin/edit-engine.mjs +1364 -0
- package/src/agent/orchestrator/tools/builtin/edit-failure-context.mjs +126 -0
- package/src/agent/orchestrator/tools/builtin/edit-hint.mjs +141 -0
- package/src/agent/orchestrator/tools/builtin/edit-match-utils.mjs +194 -0
- package/src/agent/orchestrator/tools/builtin/edit-partial-write.mjs +60 -0
- package/src/agent/orchestrator/tools/builtin/edit-stale-refresh.mjs +168 -0
- package/src/agent/orchestrator/tools/builtin/edit-tool.mjs +173 -0
- package/src/agent/orchestrator/tools/builtin/edit-utf8-guard.mjs +48 -0
- package/src/agent/orchestrator/tools/builtin/fs-reachability.mjs +48 -0
- package/src/agent/orchestrator/tools/builtin/fuzzy-match.mjs +99 -0
- package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +170 -0
- package/src/agent/orchestrator/tools/builtin/grep-formatting.mjs +113 -0
- package/src/agent/orchestrator/tools/builtin/hash-utils.mjs +6 -0
- package/src/agent/orchestrator/tools/builtin/list-formatting.mjs +7 -0
- package/src/agent/orchestrator/tools/builtin/list-tool.mjs +593 -0
- package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +89 -0
- package/src/agent/orchestrator/tools/builtin/notebook-edit-tool.mjs +300 -0
- package/src/agent/orchestrator/tools/builtin/open-config-tool.mjs +26 -0
- package/src/agent/orchestrator/tools/builtin/path-diagnostics.mjs +152 -0
- package/src/agent/orchestrator/tools/builtin/path-locks.mjs +35 -0
- package/src/agent/orchestrator/tools/builtin/path-utils.mjs +201 -0
- package/src/agent/orchestrator/tools/builtin/read-args.mjs +103 -0
- package/src/agent/orchestrator/tools/builtin/read-batch.mjs +172 -0
- package/src/agent/orchestrator/tools/builtin/read-constants.mjs +40 -0
- package/src/agent/orchestrator/tools/builtin/read-formatting.mjs +118 -0
- package/src/agent/orchestrator/tools/builtin/read-image-resize.mjs +189 -0
- package/src/agent/orchestrator/tools/builtin/read-image.mjs +88 -0
- package/src/agent/orchestrator/tools/builtin/read-lines.mjs +12 -0
- package/src/agent/orchestrator/tools/builtin/read-mode-tool.mjs +455 -0
- package/src/agent/orchestrator/tools/builtin/read-open.mjs +190 -0
- package/src/agent/orchestrator/tools/builtin/read-range-index.mjs +271 -0
- package/src/agent/orchestrator/tools/builtin/read-ranges.mjs +26 -0
- package/src/agent/orchestrator/tools/builtin/read-single-tool.mjs +728 -0
- package/src/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +173 -0
- package/src/agent/orchestrator/tools/builtin/read-special-files.mjs +268 -0
- package/src/agent/orchestrator/tools/builtin/read-streaming.mjs +602 -0
- package/src/agent/orchestrator/tools/builtin/read-tool.mjs +530 -0
- package/src/agent/orchestrator/tools/builtin/read-windows.mjs +107 -0
- package/src/agent/orchestrator/tools/builtin/rename-tool.mjs +196 -0
- package/src/agent/orchestrator/tools/builtin/rg-runner.mjs +422 -0
- package/src/agent/orchestrator/tools/builtin/search-builders.mjs +158 -0
- package/src/agent/orchestrator/tools/builtin/search-tool.mjs +869 -0
- package/src/agent/orchestrator/tools/builtin/shell-analysis.mjs +653 -0
- package/src/agent/orchestrator/tools/builtin/shell-jobs.mjs +936 -0
- package/src/agent/orchestrator/tools/builtin/shell-output.mjs +36 -0
- package/src/agent/orchestrator/tools/builtin/shell-runtime.mjs +214 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +143 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-store.mjs +206 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-validation.mjs +98 -0
- package/src/agent/orchestrator/tools/builtin/text-stats.mjs +69 -0
- package/src/agent/orchestrator/tools/builtin/windows-roots.mjs +23 -0
- package/src/agent/orchestrator/tools/builtin/write-tool.mjs +401 -0
- package/src/agent/orchestrator/tools/builtin.mjs +500 -0
- package/src/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +39 -0
- package/src/agent/orchestrator/tools/code-graph-tool-defs.mjs +24 -0
- package/src/agent/orchestrator/tools/code-graph.mjs +4095 -0
- package/src/agent/orchestrator/tools/cwd-tool.mjs +298 -0
- package/src/agent/orchestrator/tools/destructive-warning.mjs +323 -0
- package/src/agent/orchestrator/tools/edit-normalize.mjs +603 -0
- package/src/agent/orchestrator/tools/env-scrub.mjs +100 -0
- package/src/agent/orchestrator/tools/graph-binary-fetcher.mjs +144 -0
- package/src/agent/orchestrator/tools/graph-manifest.json +26 -0
- package/src/agent/orchestrator/tools/host-input.mjs +204 -0
- package/src/agent/orchestrator/tools/mutation-content-cache.mjs +67 -0
- package/src/agent/orchestrator/tools/mutation-planner.mjs +75 -0
- package/src/agent/orchestrator/tools/next-call-utils.mjs +48 -0
- package/src/agent/orchestrator/tools/patch-binary-fetcher.mjs +133 -0
- package/src/agent/orchestrator/tools/patch-manifest.json +26 -0
- package/src/agent/orchestrator/tools/patch-tool-defs.mjs +20 -0
- package/src/agent/orchestrator/tools/patch.mjs +2754 -0
- package/src/agent/orchestrator/tools/progress-message.mjs +118 -0
- package/src/agent/orchestrator/tools/result-compression.mjs +279 -0
- package/src/agent/orchestrator/tools/shell-command.mjs +865 -0
- package/src/agent/orchestrator/tools/shell-exec-policy.mjs +89 -0
- package/src/agent/orchestrator/tools/shell-policy-danger-target.mjs +27 -0
- package/src/agent/orchestrator/tools/shell-policy-imports.mjs +7 -0
- package/src/agent/orchestrator/tools/shell-policy.mjs +345 -0
- package/src/agent/orchestrator/tools/shell-snapshot.mjs +313 -0
- package/src/agent/orchestrator/workflow-store.mjs +93 -0
- package/src/agent/tool-defs.mjs +103 -0
- package/src/channels/backends/discord.mjs +784 -0
- package/src/channels/data/voice-runtime-manifest.json +138 -0
- package/src/channels/index.mjs +3229 -0
- package/src/channels/lib/cli-worker-host.mjs +12 -0
- package/src/channels/lib/config-lock.mjs +13 -0
- package/src/channels/lib/config.mjs +292 -0
- package/src/channels/lib/drop-trace.mjs +71 -0
- package/src/channels/lib/event-pipeline.mjs +81 -0
- package/src/channels/lib/event-queue.mjs +345 -0
- package/src/channels/lib/executor.mjs +168 -0
- package/src/channels/lib/format.mjs +188 -0
- package/src/channels/lib/holidays.mjs +138 -0
- package/src/channels/lib/hook-pipe-server.mjs +802 -0
- package/src/channels/lib/interaction-workflows.mjs +184 -0
- package/src/channels/lib/memory-client.mjs +149 -0
- package/src/channels/lib/output-forwarder.mjs +765 -0
- package/src/channels/lib/runtime-paths.mjs +479 -0
- package/src/channels/lib/scheduler.mjs +723 -0
- package/src/channels/lib/session-control.mjs +36 -0
- package/src/channels/lib/session-discovery.mjs +103 -0
- package/src/channels/lib/settings.mjs +11 -0
- package/src/channels/lib/state-file.mjs +68 -0
- package/src/channels/lib/status-snapshot.mjs +219 -0
- package/src/channels/lib/tool-format.mjs +140 -0
- package/src/channels/lib/transcript-discovery.mjs +195 -0
- package/src/channels/lib/voice-runtime-fetcher.mjs +734 -0
- package/src/channels/lib/webhook.mjs +1179 -0
- package/src/channels/lib/whisper-server.mjs +477 -0
- package/src/channels/tool-defs.mjs +170 -0
- package/src/daemon/host.mjs +118 -0
- package/src/daemon/mcp-transport.mjs +47 -0
- package/src/daemon/session.mjs +100 -0
- package/src/daemon/thin-client.mjs +71 -0
- package/src/daemon/transport.mjs +163 -0
- package/src/memory/data/runtime-manifest.json +40 -0
- package/src/memory/index.mjs +3305 -0
- package/src/memory/lib/agent-ipc.mjs +93 -0
- package/src/memory/lib/bridge-trace-queries.mjs +120 -0
- package/src/memory/lib/core-memory-store.mjs +330 -0
- package/src/memory/lib/embedding-provider.mjs +269 -0
- package/src/memory/lib/embedding-worker.mjs +323 -0
- package/src/memory/lib/llm-worker-host.mjs +17 -0
- package/src/memory/lib/memory-cycle.mjs +11 -0
- package/src/memory/lib/memory-cycle1.mjs +641 -0
- package/src/memory/lib/memory-cycle2.mjs +1284 -0
- package/src/memory/lib/memory-cycle3.mjs +540 -0
- package/src/memory/lib/memory-embed.mjs +299 -0
- package/src/memory/lib/memory-extraction.mjs +5 -0
- package/src/memory/lib/memory-maintenance-store.mjs +32 -0
- package/src/memory/lib/memory-ops-policy.mjs +190 -0
- package/src/memory/lib/memory-recall-id-patch.mjs +15 -0
- package/src/memory/lib/memory-recall-read-query.mjs +7 -0
- package/src/memory/lib/memory-recall-scope-filter.mjs +63 -0
- package/src/memory/lib/memory-recall-store.mjs +621 -0
- package/src/memory/lib/memory-retrievers.mjs +112 -0
- package/src/memory/lib/memory-score.mjs +71 -0
- package/src/memory/lib/memory-text-utils.mjs +58 -0
- package/src/memory/lib/memory.mjs +412 -0
- package/src/memory/lib/model-profile.mjs +85 -0
- package/src/memory/lib/pg/adapter.mjs +308 -0
- package/src/memory/lib/pg/process.mjs +360 -0
- package/src/memory/lib/pg/supervisor.mjs +396 -0
- package/src/memory/lib/project-id-resolver.mjs +86 -0
- package/src/memory/lib/runtime-fetcher.mjs +442 -0
- package/src/memory/lib/trace-store.mjs +728 -0
- package/src/memory/tool-defs.mjs +79 -0
- package/src/search/index.mjs +1173 -0
- package/src/search/lib/backends/anthropic-oauth.mjs +98 -0
- package/src/search/lib/backends/exa.mjs +50 -0
- package/src/search/lib/backends/firecrawl.mjs +61 -0
- package/src/search/lib/backends/gemini-api.mjs +83 -0
- package/src/search/lib/backends/grok-oauth.mjs +86 -0
- package/src/search/lib/backends/index.mjs +150 -0
- package/src/search/lib/backends/openai-api.mjs +144 -0
- package/src/search/lib/backends/openai-oauth.mjs +98 -0
- package/src/search/lib/backends/openai-web-search.mjs +76 -0
- package/src/search/lib/backends/tavily.mjs +55 -0
- package/src/search/lib/backends/xai-api.mjs +113 -0
- package/src/search/lib/cache.mjs +131 -0
- package/src/search/lib/config.mjs +192 -0
- package/src/search/lib/formatter.mjs +115 -0
- package/src/search/lib/provider-usage.mjs +67 -0
- package/src/search/lib/providers.mjs +47 -0
- package/src/search/lib/search-intent.mjs +109 -0
- package/src/search/lib/setup-handler.mjs +261 -0
- package/src/search/lib/state.mjs +201 -0
- package/src/search/lib/web-tools.mjs +1207 -0
- package/src/search/tool-defs.mjs +83 -0
- package/src/setup/defender-exclusion.mjs +183 -0
- package/src/shared/abort-controller.mjs +15 -0
- package/src/shared/atomic-file.mjs +420 -0
- package/src/shared/config.mjs +350 -0
- package/src/shared/daemon-recycle.mjs +108 -0
- package/src/shared/disable-claude-builtins.mjs +88 -0
- package/src/shared/err-text.mjs +12 -0
- package/src/shared/llm/cost.mjs +66 -0
- package/src/shared/llm/http-agent.mjs +123 -0
- package/src/shared/llm/index.mjs +41 -0
- package/src/shared/llm/pid-cleanup.mjs +27 -0
- package/src/shared/llm/usage-log.mjs +47 -0
- package/src/shared/plugin-paths.mjs +58 -0
- package/src/shared/schedules-store.mjs +70 -0
- package/src/shared/seed.mjs +119 -0
- package/src/shared/user-cwd.mjs +213 -0
- package/src/shared/user-data-guard.mjs +238 -0
- package/src/status/aggregator.mjs +584 -0
- package/src/status/server.mjs +413 -0
- package/tools.json +1653 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Per-tool live-status message builder (ported from claude-code's progress
|
|
2
|
+
// generalization / getActivityDescription). Dependency-light and
|
|
3
|
+
// side-effect-free: given a tool name + its raw args, return a short
|
|
4
|
+
// human-readable "what's happening now" string. Used by the central dispatch
|
|
5
|
+
// path to emit a single start-of-tool progress notification. Every tool gets a
|
|
6
|
+
// meaningful verb; `running ${name}` is only the last-resort fallback.
|
|
7
|
+
//
|
|
8
|
+
// Verbs are kept symmetric with claude-code's wording: Read→"reading",
|
|
9
|
+
// Edit→"editing", Write→"writing", Grep→"searching for", Glob→"finding",
|
|
10
|
+
// web search→"searching web for", web fetch→"fetching".
|
|
11
|
+
|
|
12
|
+
// Truncate long arg values so a progress line never blows past ~60 chars.
|
|
13
|
+
function _t(value, max = 60) {
|
|
14
|
+
const s = String(value ?? '');
|
|
15
|
+
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Count-aware noun so a label never reads "1 files" or "3 query/queries".
|
|
19
|
+
// English progress strings only; default plural appends "s".
|
|
20
|
+
function _plural(n, one, many) {
|
|
21
|
+
return `${n} ${n === 1 ? one : (many || one + 's')}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function formatToolStartProgress(name, args = {}) {
|
|
25
|
+
const a = args || {};
|
|
26
|
+
switch (name) {
|
|
27
|
+
// ── builtin: files / shell ───────────────────────────────────────
|
|
28
|
+
case 'read':
|
|
29
|
+
return a.symbol ? `reading symbol ${_t(a.symbol)}` : `reading ${_t(a.path)}`;
|
|
30
|
+
case 'edit': {
|
|
31
|
+
if (Array.isArray(a.edits)) return `editing ${_plural(a.edits.length, 'file')}`;
|
|
32
|
+
if (a.notebook_path) return `editing notebook ${_t(a.notebook_path)}`;
|
|
33
|
+
if (a.symbol) return `renaming ${_t(a.symbol)}`;
|
|
34
|
+
return `editing ${_t(a.path)}`;
|
|
35
|
+
}
|
|
36
|
+
case 'write':
|
|
37
|
+
return Array.isArray(a.writes) ? `writing ${_plural(a.writes.length, 'file')}` : `writing ${_t(a.path)}`;
|
|
38
|
+
case 'apply_patch':
|
|
39
|
+
return a.dry_run ? 'validating patch' : 'applying patch';
|
|
40
|
+
case 'bash':
|
|
41
|
+
return a.command ? `running ${_t(a.command)}` : 'running shell';
|
|
42
|
+
case 'job_wait': {
|
|
43
|
+
const checking = a.action && a.action !== 'wait';
|
|
44
|
+
return `${checking ? 'checking' : 'waiting for'} job ${_t(a.job_id)}`;
|
|
45
|
+
}
|
|
46
|
+
case 'diagnostics':
|
|
47
|
+
return `running diagnostics${a.path ? ` for ${_t(a.path)}` : ''}`;
|
|
48
|
+
|
|
49
|
+
// ── builtin / code_graph: search & navigation ────────────────────
|
|
50
|
+
case 'grep':
|
|
51
|
+
return Array.isArray(a.pattern) ? `searching for ${_plural(a.pattern.length, 'pattern')}` : `searching for ${_t(a.pattern)}`;
|
|
52
|
+
case 'glob':
|
|
53
|
+
return Array.isArray(a.pattern) ? `finding ${_plural(a.pattern.length, 'glob')}` : `finding ${_t(a.pattern)}`;
|
|
54
|
+
case 'list':
|
|
55
|
+
return a.mode === 'find' ? 'finding files' : `listing ${_t(a.path || 'cwd')}`;
|
|
56
|
+
case 'code_graph':
|
|
57
|
+
if (a.symbol) return `locating ${_t(a.symbol)}`;
|
|
58
|
+
return a.file ? `mapping ${_t(a.file)}` : 'analyzing code graph';
|
|
59
|
+
|
|
60
|
+
// ── search module: web ───────────────────────────────────────────
|
|
61
|
+
case 'search':
|
|
62
|
+
return Array.isArray(a.query) ? `searching web (${_plural(a.query.length, 'query', 'queries')})` : `searching web for ${_t(a.query)}`;
|
|
63
|
+
case 'web_fetch':
|
|
64
|
+
return Array.isArray(a.url) ? `fetching ${_plural(a.url.length, 'URL')}` : `fetching ${_t(a.url)}`;
|
|
65
|
+
|
|
66
|
+
// ── agent module: explore / bridge / models ──────────────────────
|
|
67
|
+
case 'explore': {
|
|
68
|
+
const n = Array.isArray(a.query) ? a.query.length : (a.query ? 1 : 0);
|
|
69
|
+
return `exploring ${_plural(n, 'query', 'queries')}`;
|
|
70
|
+
}
|
|
71
|
+
case 'bridge': {
|
|
72
|
+
if (a.role) return `dispatching ${_t(a.role)}`;
|
|
73
|
+
if (a.tag) return `messaging ${_t(a.tag)}`;
|
|
74
|
+
return 'dispatching agent';
|
|
75
|
+
}
|
|
76
|
+
case 'list_models':
|
|
77
|
+
return 'listing models';
|
|
78
|
+
|
|
79
|
+
// ── memory module ────────────────────────────────────────────────
|
|
80
|
+
case 'recall':
|
|
81
|
+
return 'recalling memory';
|
|
82
|
+
case 'memory':
|
|
83
|
+
return 'managing memory';
|
|
84
|
+
|
|
85
|
+
// ── channels module ──────────────────────────────────────────────
|
|
86
|
+
case 'reply':
|
|
87
|
+
return 'replying';
|
|
88
|
+
case 'react':
|
|
89
|
+
return 'reacting';
|
|
90
|
+
case 'edit_message':
|
|
91
|
+
return 'editing message';
|
|
92
|
+
case 'download_attachment':
|
|
93
|
+
return 'downloading attachment';
|
|
94
|
+
case 'fetch':
|
|
95
|
+
return 'fetching messages';
|
|
96
|
+
case 'schedule_status':
|
|
97
|
+
return 'checking schedules';
|
|
98
|
+
case 'trigger_schedule':
|
|
99
|
+
return a.name ? `triggering ${_t(a.name)}` : 'triggering schedule';
|
|
100
|
+
case 'schedule_control':
|
|
101
|
+
return 'scheduling';
|
|
102
|
+
case 'activate_channel_bridge':
|
|
103
|
+
return 'activating channel';
|
|
104
|
+
case 'reload_config':
|
|
105
|
+
return 'reloading config';
|
|
106
|
+
case 'inject_command':
|
|
107
|
+
return 'injecting command';
|
|
108
|
+
|
|
109
|
+
// ── host_input / cwd ─────────────────────────────────────────────
|
|
110
|
+
case 'inject_input':
|
|
111
|
+
return 'injecting input';
|
|
112
|
+
case 'cwd':
|
|
113
|
+
return a.action === 'set' ? 'setting cwd' : 'resolving cwd';
|
|
114
|
+
|
|
115
|
+
default:
|
|
116
|
+
return `running ${name}`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Result Compression — lossless-only chained passes.
|
|
3
|
+
*
|
|
4
|
+
* Pass order (each strictly reduce-only or self-guarded):
|
|
5
|
+
* 1. stripAnsi — remove CSI / OSC escape sequences
|
|
6
|
+
* 2. collapseCarriageReturns — terminal `\r(?!\n)` is a cursor reset;
|
|
7
|
+
* bytes before the last \r on a line
|
|
8
|
+
* were overwritten and never visible.
|
|
9
|
+
* CRLF preserved.
|
|
10
|
+
* 3. stripNulBytes — NUL has no meaning in UTF-8 text;
|
|
11
|
+
* only present from binary-leak outputs
|
|
12
|
+
* already malformed.
|
|
13
|
+
* 4. stripUtf8Bom — leading U+FEFF is a metadata marker,
|
|
14
|
+
* not content. Only the leading BOM is
|
|
15
|
+
* stripped (interior FEFF kept).
|
|
16
|
+
* 5. normalizeTrailingNewlines — trailing \n+ collapsed to single \n.
|
|
17
|
+
*
|
|
18
|
+
* All five passes are LOSSLESS w.r.t. semantically-relevant content:
|
|
19
|
+
* each removes bytes that the terminal/file reader would have ignored
|
|
20
|
+
* anyway (terminal-overwritten, binary garbage, BOM marker, trailing
|
|
21
|
+
* blank lines). No dedup / separator collapse / whitespace rewrite /
|
|
22
|
+
* middle-elision / long-line truncation is applied — those are lossy
|
|
23
|
+
* and have been removed. Oversize results route to the recoverable
|
|
24
|
+
* offload sidecar in session/tool-result-offload.mjs instead.
|
|
25
|
+
*
|
|
26
|
+
* Final expand guard: if the chained output is not strictly shorter
|
|
27
|
+
* than the input, return the input unchanged.
|
|
28
|
+
*
|
|
29
|
+
* Compression is opt-in per tool: tools whose definition carries
|
|
30
|
+
* `annotations.compressible: true` OR `annotations.compressibleLossless: true`
|
|
31
|
+
* are processed. Both annotations now resolve to the same lossless
|
|
32
|
+
* chain — there is no separate lossy tier.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import * as nodeUtil from 'node:util';
|
|
36
|
+
import { traceBridgeCompress, traceBridgeBatch } from '../bridge-trace.mjs';
|
|
37
|
+
import { BUILTIN_TOOLS } from './builtin.mjs';
|
|
38
|
+
import { PATCH_TOOL_DEFS } from './patch-tool-defs.mjs';
|
|
39
|
+
import { CODE_GRAPH_TOOL_DEFS } from './code-graph-tool-defs.mjs';
|
|
40
|
+
|
|
41
|
+
const ANSI_FALLBACK_RE = /\x1b(?:\[[0-?]*[ -/]*[@-~]|\][\s\S]*?(?:\x07|\x1b\\|\x9c))/g;
|
|
42
|
+
|
|
43
|
+
const ALL_TOOL_DEFS = [...BUILTIN_TOOLS, ...PATCH_TOOL_DEFS, ...CODE_GRAPH_TOOL_DEFS];
|
|
44
|
+
const _stripAnsiImpl = typeof globalThis.Bun?.stripANSI === 'function'
|
|
45
|
+
? (s) => globalThis.Bun.stripANSI(s)
|
|
46
|
+
: (typeof nodeUtil.stripVTControlCharacters === 'function'
|
|
47
|
+
? (s) => nodeUtil.stripVTControlCharacters(s)
|
|
48
|
+
: (s) => String(s).replace(ANSI_FALLBACK_RE, () => ''));
|
|
49
|
+
|
|
50
|
+
function bareToolName(name) {
|
|
51
|
+
if (typeof name !== 'string' || !name) return name;
|
|
52
|
+
const m = name.match(/^mcp__.+?__(.+)$/);
|
|
53
|
+
return m ? m[1] : name;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isCompressionEligible(name) {
|
|
57
|
+
const bare = bareToolName(name);
|
|
58
|
+
const def = ALL_TOOL_DEFS.find(t => t.name === bare);
|
|
59
|
+
if (!def) return false;
|
|
60
|
+
return def.annotations?.compressible === true
|
|
61
|
+
|| def.annotations?.compressibleLossless === true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Grep (and read, if ever compressed) carry file bytes that may include literal
|
|
65
|
+
// `\r` in source; terminal-style CR collapse would delete content.
|
|
66
|
+
function skipCarriageReturnCollapse(toolName) {
|
|
67
|
+
const bare = bareToolName(toolName);
|
|
68
|
+
return bare === 'grep' || bare === 'read';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function stripAnsi(text) {
|
|
72
|
+
if (typeof text !== 'string') return text;
|
|
73
|
+
return _stripAnsiImpl(text);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Carriage-return overwrite collapse. In a terminal, `\r` not followed
|
|
77
|
+
// by `\n` resets the cursor to column 0; the next print overwrites the
|
|
78
|
+
// line. Anything between the previous `\n` (or string start) and the
|
|
79
|
+
// last `\r(?!\n)` on the same line was visually overwritten before the
|
|
80
|
+
// user ever saw it. Lossless w.r.t. terminal display. CRLF (`\r\n`) is
|
|
81
|
+
// the standard Windows line ending and is preserved by the negative
|
|
82
|
+
// lookahead. JSON/text outputs that contain literal `\r` escape
|
|
83
|
+
// sequences (`\\r`) are NOT affected because those decode to two
|
|
84
|
+
// characters (`\` + `r`), not a real `\r`.
|
|
85
|
+
function collapseCarriageReturns(text) {
|
|
86
|
+
if (typeof text !== 'string') return text;
|
|
87
|
+
if (text.indexOf('\r') === -1) return text;
|
|
88
|
+
let out = '';
|
|
89
|
+
let lineStart = 0;
|
|
90
|
+
let keepStart = 0;
|
|
91
|
+
let changed = false;
|
|
92
|
+
for (let i = 0; i < text.length; i++) {
|
|
93
|
+
const ch = text.charCodeAt(i);
|
|
94
|
+
if (ch === 13) {
|
|
95
|
+
if (text.charCodeAt(i + 1) === 10) continue;
|
|
96
|
+
if (!changed) {
|
|
97
|
+
out = text.slice(0, lineStart);
|
|
98
|
+
changed = true;
|
|
99
|
+
}
|
|
100
|
+
keepStart = i + 1;
|
|
101
|
+
} else if (ch === 10) {
|
|
102
|
+
if (changed) out += text.slice(keepStart, i + 1);
|
|
103
|
+
lineStart = i + 1;
|
|
104
|
+
keepStart = lineStart;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (!changed) return text;
|
|
108
|
+
return out + text.slice(keepStart);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// NUL byte strip. UTF-8 text has no semantic use for NUL (\x00); the
|
|
112
|
+
// only way it appears in a tool result is from a binary-leak output
|
|
113
|
+
// (e.g. cat on a binary, ill-formed log). The result is already
|
|
114
|
+
// malformed for the LLM context; removing the NUL bytes neither helps
|
|
115
|
+
// nor harms semantics, just trims noise.
|
|
116
|
+
function stripNulBytes(text) {
|
|
117
|
+
if (typeof text !== 'string') return text;
|
|
118
|
+
return text.replace(/\x00/g, '');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// UTF-8 BOM strip (leading only). U+FEFF at the start of a text stream
|
|
122
|
+
// is a byte-order marker / encoding hint, not content; some editors and
|
|
123
|
+
// the Windows powershell pipeline insert it. Interior FEFF is left
|
|
124
|
+
// alone (it could be intentional in the data).
|
|
125
|
+
function stripUtf8Bom(text) {
|
|
126
|
+
if (typeof text !== 'string') return text;
|
|
127
|
+
return text.charCodeAt(0) === 0xFEFF ? text.slice(1) : text;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Trailing-newline normalize. Tool outputs frequently end with several
|
|
131
|
+
// blank lines (shell prompts, redirected stdout buffer flush) that
|
|
132
|
+
// carry no information. Collapsing the tail to a single trailing
|
|
133
|
+
// newline preserves the file-ends-with-newline convention while
|
|
134
|
+
// stripping the visually-empty padding.
|
|
135
|
+
function normalizeTrailingNewlines(text) {
|
|
136
|
+
if (typeof text !== 'string') return text;
|
|
137
|
+
return text.replace(/\n+$/, '\n');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Retained as named exports for non-tool-result consumers (bridge
|
|
141
|
+
// aggregated worker bodies in ai-wrapped-dispatch). These functions are
|
|
142
|
+
// NO LONGER part of the tool-result compression chain — that chain is
|
|
143
|
+
// lossless-only.
|
|
144
|
+
export function normalizeWhitespace(text) {
|
|
145
|
+
if (typeof text !== 'string') return text;
|
|
146
|
+
return text
|
|
147
|
+
.split('\n')
|
|
148
|
+
.map(line => line.replace(/[ \t]+$/, ''))
|
|
149
|
+
.join('\n')
|
|
150
|
+
.replace(/\n{3,}/g, '\n\n');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function dedupRepeatedLines(text) {
|
|
154
|
+
if (typeof text !== 'string') return text;
|
|
155
|
+
const lines = text.split('\n');
|
|
156
|
+
const out = [];
|
|
157
|
+
let prev = null;
|
|
158
|
+
let dupRun = 0;
|
|
159
|
+
const flush = () => {
|
|
160
|
+
if (dupRun === 0) return;
|
|
161
|
+
if (dupRun < 5) {
|
|
162
|
+
for (let i = 0; i < dupRun; i++) out.push(prev);
|
|
163
|
+
} else {
|
|
164
|
+
out.push(` (×${dupRun + 1} identical lines collapsed)`);
|
|
165
|
+
}
|
|
166
|
+
dupRun = 0;
|
|
167
|
+
};
|
|
168
|
+
for (const line of lines) {
|
|
169
|
+
if (prev !== null && line === prev) {
|
|
170
|
+
dupRun += 1;
|
|
171
|
+
} else {
|
|
172
|
+
flush();
|
|
173
|
+
out.push(line);
|
|
174
|
+
prev = line;
|
|
175
|
+
dupRun = 0;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
flush();
|
|
179
|
+
return out.join('\n');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function compressToolResult(toolName, args, result, ctx) {
|
|
183
|
+
if (typeof result !== 'string') return result;
|
|
184
|
+
if (!isCompressionEligible(toolName)) return result;
|
|
185
|
+
const before = result.length;
|
|
186
|
+
let out = stripAnsi(result);
|
|
187
|
+
if (!skipCarriageReturnCollapse(toolName)) {
|
|
188
|
+
out = collapseCarriageReturns(out);
|
|
189
|
+
}
|
|
190
|
+
out = stripNulBytes(out);
|
|
191
|
+
out = stripUtf8Bom(out);
|
|
192
|
+
out = normalizeTrailingNewlines(out);
|
|
193
|
+
if (out.length >= before) return result;
|
|
194
|
+
if (ctx?.sessionId) {
|
|
195
|
+
try { traceBridgeCompress({ sessionId: ctx.sessionId, toolName, before, after: out.length }); } catch { /* trace best-effort */ }
|
|
196
|
+
}
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Per-turn batch shape recorder. Called once per assistant turn (right
|
|
201
|
+
// after the model returns toolCalls) with the count. Trace consumers
|
|
202
|
+
// can compute multi-tool adoption ratio (calls > 1 / total turns)
|
|
203
|
+
// directly from these rows instead of re-parsing every assistant
|
|
204
|
+
// message body.
|
|
205
|
+
export function recordToolBatch(sessionId, toolCallCount) {
|
|
206
|
+
const n = Number(toolCallCount);
|
|
207
|
+
if (!sessionId || !Number.isFinite(n) || n <= 0) return;
|
|
208
|
+
try { traceBridgeBatch({ sessionId, toolCallCount: n }); } catch { /* trace best-effort */ }
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export const _internals = {
|
|
212
|
+
collapseCarriageReturns,
|
|
213
|
+
normalizeTrailingNewlines,
|
|
214
|
+
stripNulBytes,
|
|
215
|
+
stripUtf8Bom,
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// R17 — structural tail-trim for verbose tool outputs (Lead-direct / loop paths).
|
|
219
|
+
const TAIL_TRIM_MIN_LINES = 300;
|
|
220
|
+
const TAIL_TRIM_MIN_BYTES = 8192;
|
|
221
|
+
const TAIL_TRIM_HEAD = 30;
|
|
222
|
+
const TAIL_TRIM_TAIL = 80;
|
|
223
|
+
const TAIL_TRIM_MAX_LINE_CHARS = 2_000;
|
|
224
|
+
|
|
225
|
+
function _trimLongLines(content) {
|
|
226
|
+
const lines = content.split('\n');
|
|
227
|
+
let changed = false;
|
|
228
|
+
const out = lines.map((line) => {
|
|
229
|
+
if (line.length <= TAIL_TRIM_MAX_LINE_CHARS) return line;
|
|
230
|
+
changed = true;
|
|
231
|
+
const cps = [...line];
|
|
232
|
+
const head = cps.slice(0, 1_500).join('');
|
|
233
|
+
const tail = cps.slice(-300).join('');
|
|
234
|
+
return `${head} ... [line truncated: ${line.length} chars total] ... ${tail}`;
|
|
235
|
+
});
|
|
236
|
+
return changed ? out.join('\n') : content;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @param {string} content
|
|
241
|
+
* @param {{ trimLongLines?: boolean, fullOutputPath?: string, sequential?: boolean }} [opts]
|
|
242
|
+
*/
|
|
243
|
+
export function tailTrimLargeOutput(content, opts = {}) {
|
|
244
|
+
if (typeof content !== 'string') return content;
|
|
245
|
+
let text = content;
|
|
246
|
+
if (opts.trimLongLines) {
|
|
247
|
+
const trimmed = _trimLongLines(text);
|
|
248
|
+
// Apply long-line trimming, then FALL THROUGH to the byte/line tail-trim
|
|
249
|
+
// so a still-oversized (many-line) result is also capped. Returning here
|
|
250
|
+
// skipped tail-trim and the full-output marker for such output.
|
|
251
|
+
if (trimmed !== text) text = trimmed;
|
|
252
|
+
}
|
|
253
|
+
if (Buffer.byteLength(text, 'utf8') <= TAIL_TRIM_MIN_BYTES) return text;
|
|
254
|
+
const lines = text.split('\n');
|
|
255
|
+
if (lines.length <= TAIL_TRIM_MIN_LINES) return text;
|
|
256
|
+
const elided = lines.length - TAIL_TRIM_HEAD - TAIL_TRIM_TAIL;
|
|
257
|
+
if (elided <= 0) return text;
|
|
258
|
+
const totalBytes = Buffer.byteLength(text, 'utf8');
|
|
259
|
+
// Sequential outputs (e.g. a windowed `read`) are consumed front-to-back:
|
|
260
|
+
// a head+tail keep destroys the middle the caller explicitly asked for.
|
|
261
|
+
// Keep the head intact within the same line budget and tell the caller
|
|
262
|
+
// how to continue instead.
|
|
263
|
+
if (opts.sequential) {
|
|
264
|
+
const kept = TAIL_TRIM_HEAD + TAIL_TRIM_TAIL;
|
|
265
|
+
const head = lines.slice(0, kept);
|
|
266
|
+
let marker = `\n... ${lines.length - kept} lines elided of ${lines.length} total (${totalBytes} bytes) — head kept intact; sequential output: re-run with offset advanced past the last line above ...\n`;
|
|
267
|
+
if (opts.fullOutputPath) {
|
|
268
|
+
marker += `[full output saved: ${opts.fullOutputPath}]\n`;
|
|
269
|
+
}
|
|
270
|
+
return head.join('\n') + marker;
|
|
271
|
+
}
|
|
272
|
+
const head = lines.slice(0, TAIL_TRIM_HEAD);
|
|
273
|
+
const tail = lines.slice(lines.length - TAIL_TRIM_TAIL);
|
|
274
|
+
let marker = `\n... ${elided} lines elided, total ${totalBytes} bytes — head ${TAIL_TRIM_HEAD} + tail ${TAIL_TRIM_TAIL} lines kept ...\n`;
|
|
275
|
+
if (opts.fullOutputPath) {
|
|
276
|
+
marker += `[full output saved: ${opts.fullOutputPath}]\n`;
|
|
277
|
+
}
|
|
278
|
+
return head.join('\n') + marker + tail.join('\n');
|
|
279
|
+
}
|