mixdog 0.9.2 → 0.9.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/package.json +8 -3
- package/scripts/anthropic-maxtokens-test.mjs +119 -0
- package/scripts/bench/lead-review-tasks-r3.json +20 -0
- package/scripts/bench/lead-review-tasks.json +20 -0
- package/scripts/bench/r4-mixed-tasks.json +20 -0
- package/scripts/bench/review-tasks.json +20 -0
- package/scripts/bench/round-codex.json +114 -0
- package/scripts/bench/round-mixdog-lead-r3.json +269 -0
- package/scripts/bench/round-mixdog-lead.json +269 -0
- package/scripts/bench/round-mixdog.json +126 -0
- package/scripts/bench/round-r10-bigsample.json +679 -0
- package/scripts/bench/round-r11-codexalign.json +257 -0
- package/scripts/bench/round-r4-codex.json +114 -0
- package/scripts/bench/round-r4-mixed.json +225 -0
- package/scripts/bench/round-r5-gpt-lead.json +259 -0
- package/scripts/bench/round-r6-codex.json +114 -0
- package/scripts/bench/round-r6-solo.json +257 -0
- package/scripts/bench/round-r7-full.json +254 -0
- package/scripts/bench/round-r8-fulldefault.json +255 -0
- package/scripts/bench-run.mjs +215 -29
- package/scripts/build-tui.mjs +13 -1
- package/scripts/explore-bench.mjs +124 -0
- package/scripts/freevar-smoke.mjs +95 -0
- package/scripts/hook-bus-test.mjs +191 -0
- package/scripts/internal-comms-bench.mjs +1 -0
- package/scripts/internal-comms-smoke.mjs +10 -9
- package/scripts/mouse-probe.mjs +45 -0
- package/scripts/output-style-bench.mjs +13 -6
- package/scripts/output-style-smoke.mjs +4 -4
- package/scripts/path-suffix-test.mjs +57 -0
- package/scripts/provider-toolcall-test.mjs +7 -3
- package/scripts/recall-bench.mjs +207 -0
- package/scripts/recall-usecase-cases.json +18 -0
- package/scripts/recall-usecase-probe.json +6 -0
- package/scripts/session-bench.mjs +152 -6
- package/scripts/tool-smoke.mjs +30 -67
- package/scripts/tui-render-smoke.mjs +90 -0
- package/scripts/webhook-smoke.mjs +208 -0
- package/src/agents/debugger/AGENT.md +5 -2
- package/src/agents/heavy-worker/AGENT.md +21 -11
- package/src/agents/maintainer/AGENT.md +4 -0
- package/src/agents/reviewer/AGENT.md +3 -2
- package/src/agents/worker/AGENT.md +21 -11
- package/src/lib/rules-builder.cjs +4 -0
- package/src/mixdog-session-runtime.mjs +933 -3731
- package/src/output-styles/default.md +34 -9
- package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
- package/src/output-styles/minimal.md +4 -1
- package/src/output-styles/simple.md +22 -7
- package/src/repl.mjs +5 -5
- package/src/rules/agent/00-common.md +2 -0
- package/src/rules/agent/30-explorer.md +8 -11
- package/src/rules/lead/lead-brief.md +12 -0
- package/src/rules/lead/lead-tool.md +2 -9
- package/src/rules/shared/01-tool.md +11 -5
- package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
- package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
- package/src/runtime/agent/orchestrator/config.mjs +69 -2
- package/src/runtime/agent/orchestrator/context/collect.mjs +51 -0
- package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +63 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +97 -1343
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +78 -10
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +1 -13
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +44 -1014
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +86 -11
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +348 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
- package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +19 -12
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +41 -1142
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +732 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +303 -2119
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +140 -995
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +227 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +436 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +7 -8
- package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
- package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
- package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +274 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
- package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +182 -0
- package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
- package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop.mjs +409 -1304
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +149 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +226 -2114
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +33 -42
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +78 -304
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +11 -6
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +551 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1080 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +36 -4277
- package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
- package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
- package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
- package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
- package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -23
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +10 -74
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
- package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
- package/src/runtime/channels/backends/discord-access.mjs +32 -0
- package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
- package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
- package/src/runtime/channels/backends/discord.mjs +12 -292
- package/src/runtime/channels/index.mjs +241 -894
- package/src/runtime/channels/lib/backend-dispatch.mjs +44 -0
- package/src/runtime/channels/lib/boot-profile.mjs +23 -0
- package/src/runtime/channels/lib/crash-log.mjs +106 -0
- package/src/runtime/channels/lib/event-pipeline.mjs +18 -1
- package/src/runtime/channels/lib/event-queue.mjs +63 -4
- package/src/runtime/channels/lib/inbound-routing.mjs +111 -0
- package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
- package/src/runtime/channels/lib/output-forwarder.mjs +9 -1
- package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
- package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
- package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
- package/src/runtime/channels/lib/session-discovery.mjs +56 -4
- package/src/runtime/channels/lib/telegram-format.mjs +19 -22
- package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
- package/src/runtime/channels/lib/tool-format.mjs +1 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
- package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
- package/src/runtime/channels/lib/webhook/deliveries.mjs +312 -0
- package/src/runtime/channels/lib/webhook/log.mjs +42 -0
- package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
- package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
- package/src/runtime/channels/lib/webhook.mjs +36 -570
- package/src/runtime/channels/lib/whisper-language.mjs +42 -0
- package/src/runtime/channels/tool-defs.mjs +11 -130
- package/src/runtime/memory/index.mjs +258 -2050
- package/src/runtime/memory/lib/core-memory-store.mjs +351 -1
- package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
- package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
- package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
- package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
- package/src/runtime/memory/lib/http-wire.mjs +57 -0
- package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
- package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
- package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
- package/src/runtime/memory/lib/memory-cycle2.mjs +72 -837
- package/src/runtime/memory/lib/memory-embed.mjs +149 -0
- package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
- package/src/runtime/memory/lib/memory-recall-store.mjs +22 -2
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
- package/src/runtime/memory/lib/memory.mjs +20 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
- package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
- package/src/runtime/memory/lib/query-handlers.mjs +780 -0
- package/src/runtime/memory/lib/recall-format.mjs +238 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
- package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
- package/src/runtime/memory/tool-defs.mjs +6 -14
- package/src/runtime/search/lib/http-fetch.mjs +274 -0
- package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
- package/src/runtime/search/lib/web-tools.mjs +24 -602
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +26 -1
- package/src/runtime/shared/background-tasks.mjs +2 -3
- package/src/runtime/shared/buffered-appender.mjs +149 -0
- package/src/runtime/shared/launcher-control.mjs +2 -2
- package/src/runtime/shared/task-notification-envelope.mjs +98 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +308 -0
- package/src/runtime/shared/tool-result-summary.mjs +515 -0
- package/src/runtime/shared/tool-surface.mjs +80 -898
- package/src/runtime/shared/transcript-writer.mjs +52 -2
- package/src/runtime/shared/update-checker.mjs +7 -4
- package/src/session-runtime/config-helpers.mjs +291 -0
- package/src/session-runtime/config-lifecycle.mjs +232 -0
- package/src/session-runtime/cwd-plugins.mjs +226 -0
- package/src/session-runtime/effort.mjs +128 -0
- package/src/session-runtime/fs-utils.mjs +10 -0
- package/src/session-runtime/mcp-glue.mjs +177 -0
- package/src/session-runtime/model-capabilities.mjs +130 -0
- package/src/session-runtime/model-recency.mjs +111 -0
- package/src/session-runtime/native-search.mjs +247 -0
- package/src/session-runtime/output-styles.mjs +126 -0
- package/src/session-runtime/plugin-mcp.mjs +114 -0
- package/src/session-runtime/prewarm.mjs +142 -0
- package/src/session-runtime/provider-models.mjs +278 -0
- package/src/session-runtime/provider-usage.mjs +120 -0
- package/src/session-runtime/quick-model-rows.mjs +170 -0
- package/src/session-runtime/quick-search-models.mjs +46 -0
- package/src/session-runtime/session-hooks.mjs +93 -0
- package/src/session-runtime/session-text.mjs +100 -0
- package/src/session-runtime/settings-api.mjs +319 -0
- package/src/session-runtime/statusline-route.mjs +35 -0
- package/src/session-runtime/tool-catalog.mjs +720 -0
- package/src/session-runtime/tool-defs.mjs +84 -0
- package/src/session-runtime/warmup-schedulers.mjs +201 -0
- package/src/session-runtime/workflow.mjs +358 -0
- package/src/standalone/agent-tool/helpers.mjs +237 -0
- package/src/standalone/agent-tool/notify.mjs +107 -0
- package/src/standalone/agent-tool/provider-init.mjs +143 -0
- package/src/standalone/agent-tool/render.mjs +152 -0
- package/src/standalone/agent-tool/tool-def.mjs +55 -0
- package/src/standalone/agent-tool.mjs +155 -677
- package/src/standalone/channel-worker.mjs +7 -9
- package/src/standalone/explore-tool.mjs +40 -12
- package/src/standalone/hook-bus/config.mjs +207 -0
- package/src/standalone/hook-bus/constants.mjs +90 -0
- package/src/standalone/hook-bus/handlers.mjs +481 -0
- package/src/standalone/hook-bus/payload.mjs +31 -0
- package/src/standalone/hook-bus/rules.mjs +77 -0
- package/src/standalone/hook-bus.mjs +110 -746
- package/src/standalone/memory-runtime-proxy.mjs +7 -0
- package/src/standalone/opencode-go-login.mjs +125 -0
- package/src/standalone/provider-admin.mjs +15 -19
- package/src/standalone/usage-dashboard.mjs +3 -1
- package/src/tui/App.jsx +1163 -7571
- package/src/tui/app/app-format.mjs +206 -0
- package/src/tui/app/channel-pickers.mjs +510 -0
- package/src/tui/app/clipboard.mjs +67 -0
- package/src/tui/app/core-memory-picker.mjs +210 -0
- package/src/tui/app/extension-pickers.mjs +506 -0
- package/src/tui/app/input-parsers.mjs +193 -0
- package/src/tui/app/maintenance-pickers.mjs +324 -0
- package/src/tui/app/model-options.mjs +330 -0
- package/src/tui/app/model-picker.mjs +365 -0
- package/src/tui/app/onboarding-steps.mjs +400 -0
- package/src/tui/app/project-picker.mjs +247 -0
- package/src/tui/app/provider-setup-picker.mjs +580 -0
- package/src/tui/app/resume-picker.mjs +55 -0
- package/src/tui/app/route-pickers.mjs +419 -0
- package/src/tui/app/settings-picker.mjs +490 -0
- package/src/tui/app/slash-commands.mjs +101 -0
- package/src/tui/app/slash-dispatch.mjs +427 -0
- package/src/tui/app/text-layout.mjs +46 -0
- package/src/tui/app/theme-effort-pickers.mjs +154 -0
- package/src/tui/app/transcript-window.mjs +671 -0
- package/src/tui/app/use-mouse-input.mjs +460 -0
- package/src/tui/app/use-prompt-handlers.mjs +310 -0
- package/src/tui/app/use-transcript-scroll.mjs +510 -0
- package/src/tui/app/use-transcript-window.mjs +589 -0
- package/src/tui/components/ConfirmBar.jsx +1 -1
- package/src/tui/components/Picker.jsx +32 -4
- package/src/tui/components/PromptInput.jsx +259 -80
- package/src/tui/components/SlashCommandPalette.jsx +8 -1
- package/src/tui/components/StatusLine.jsx +63 -12
- package/src/tui/components/TextEntryPanel.jsx +11 -0
- package/src/tui/components/ToolExecution.jsx +56 -588
- package/src/tui/components/TranscriptItem.jsx +105 -0
- package/src/tui/components/UsagePanel.jsx +18 -4
- package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
- package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
- package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
- package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
- package/src/tui/components/tool-execution/text-format.mjs +161 -0
- package/src/tui/components/tool-output-format.mjs +2 -2
- package/src/tui/display-width.mjs +20 -3
- package/src/tui/dist/index.mjs +18034 -17188
- package/src/tui/engine/agent-envelope.mjs +296 -0
- package/src/tui/engine/agent-job-feed.mjs +133 -0
- package/src/tui/engine/boot-profile.mjs +21 -0
- package/src/tui/engine/labels.mjs +67 -0
- package/src/tui/engine/notice-text.mjs +112 -0
- package/src/tui/engine/notification-plan.mjs +76 -0
- package/src/tui/engine/queue-helpers.mjs +161 -0
- package/src/tui/engine/render-timing.mjs +17 -0
- package/src/tui/engine/session-stats.mjs +46 -0
- package/src/tui/engine/tool-approval.mjs +94 -0
- package/src/tui/engine/tool-call-fields.mjs +23 -0
- package/src/tui/engine/tool-card-results.mjs +234 -0
- package/src/tui/engine/tool-result-status.mjs +135 -0
- package/src/tui/engine/tool-result-text.mjs +126 -0
- package/src/tui/engine.mjs +405 -1385
- package/src/tui/figures.mjs +5 -0
- package/src/tui/index.jsx +105 -0
- package/src/tui/input-editing.mjs +60 -10
- package/src/tui/keyboard-protocol.mjs +2 -2
- package/src/tui/lib/voice-recorder.mjs +35 -19
- package/src/tui/markdown/format-token.mjs +11 -9
- package/src/tui/paste-attachments.mjs +38 -0
- package/src/tui/statusline-ansi-bridge.mjs +11 -3
- package/src/tui/theme.mjs +6 -0
- package/src/tui/themes/base.mjs +2 -2
- package/src/tui/themes/kanagawa.mjs +4 -4
- package/src/tui/themes/teal.mjs +4 -5
- package/src/tui/themes/utils.mjs +1 -1
- package/src/ui/statusline-agents.mjs +213 -0
- package/src/ui/statusline-format.mjs +146 -0
- package/src/ui/statusline-segments.mjs +148 -0
- package/src/ui/statusline.mjs +77 -462
- package/src/ui/tool-card.mjs +0 -1
- package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
- package/src/workflows/default/WORKFLOW.md +16 -9
- package/src/workflows/sequential/WORKFLOW.md +16 -11
- package/src/workflows/solo/WORKFLOW.md +5 -1
- package/vendor/ink/build/display-width.js +19 -3
- package/vendor/ink/build/ink.js +103 -6
- package/vendor/ink/build/log-update.js +17 -3
- package/vendor/ink/build/wrap-text.js +125 -0
- package/scripts/_test-folder-dialog.mjs +0 -30
- package/scripts/fix-brief-fn.mjs +0 -35
- package/scripts/fix-format-tool-surface.mjs +0 -24
- package/scripts/fix-tool-exec-visible.mjs +0 -42
- package/scripts/patch-agent-brief.mjs +0 -48
- package/scripts/patch-app.mjs +0 -21
- package/scripts/patch-app2.mjs +0 -18
- package/scripts/patch-dist-brief.mjs +0 -96
- package/scripts/patch-tool-exec.mjs +0 -70
- package/src/examples/schedules/SCHEDULE.example.md +0 -32
- package/src/examples/webhooks/WEBHOOK.example.md +0 -40
- package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
- package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
- package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
- package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
- package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
- package/src/standalone/agent-task-status.test.mjs +0 -76
- package/src/tui/components/tool-output-format.test.mjs +0 -399
- package/src/tui/display-width.test.mjs +0 -35
- package/src/tui/engine-runtime-notification.test.mjs +0 -115
- package/src/tui/engine-tool-result-text.test.mjs +0 -75
- package/src/tui/markdown/format-token.test.mjs +0 -354
- package/src/tui/markdown/render-ansi.test.mjs +0 -108
- package/src/tui/markdown/stream-fence.test.mjs +0 -26
- package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
- package/src/tui/prompt-history-store.test.mjs +0 -52
- package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
- package/src/tui/transcript-tool-failures.test.mjs +0 -111
- package/src/ui/markdown.test.mjs +0 -70
- package/src/ui/statusline-context-label.test.mjs +0 -15
- package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
- package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Compaction debug/diagnostic helpers extracted from loop.mjs.
|
|
2
|
+
import { estimateMessagesTokens } from '../context-utils.mjs';
|
|
3
|
+
|
|
4
|
+
export function estimateMessagesTokensSafe(messages) {
|
|
5
|
+
try { return estimateMessagesTokens(messages); }
|
|
6
|
+
catch { return null; }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function compactDebugEnabled() {
|
|
10
|
+
return String(process.env.MIXDOG_COMPACT_DEBUG || '').trim() === '1';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function compactDiagnosticError(err) {
|
|
14
|
+
if (!err) return null;
|
|
15
|
+
const text = String(err?.message || err);
|
|
16
|
+
return text.length > 500 ? `${text.slice(0, 499)}…` : text;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function compactByteLength(text) {
|
|
20
|
+
try { return Buffer.byteLength(String(text || ''), 'utf8'); }
|
|
21
|
+
catch { return String(text || '').length; }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function compactDebugLog(scope, details = {}) {
|
|
25
|
+
if (!compactDebugEnabled()) return;
|
|
26
|
+
try { process.stderr.write(`[compact] ${scope} ${JSON.stringify(details)}\n`); }
|
|
27
|
+
catch { /* best-effort diagnostics only */ }
|
|
28
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// Compaction policy resolution, pressure/target budgeting, telemetry
|
|
2
|
+
// persistence, and event emission — extracted from loop.mjs.
|
|
3
|
+
// runRecallFastTrackCompact stays in the loop (it drives the recall pipeline
|
|
4
|
+
// against live session state).
|
|
5
|
+
import {
|
|
6
|
+
estimateRequestReserveTokens,
|
|
7
|
+
resolveCompactBufferRatio,
|
|
8
|
+
resolveCompactBufferTokens,
|
|
9
|
+
} from '../context-utils.mjs';
|
|
10
|
+
import {
|
|
11
|
+
compactTypeIsRecallFastTrack,
|
|
12
|
+
compactTypeIsSemantic,
|
|
13
|
+
normalizeCompactType,
|
|
14
|
+
DEFAULT_COMPACT_TYPE,
|
|
15
|
+
DEFAULT_COMPACTION_KEEP_TOKENS,
|
|
16
|
+
CONTEXT_SHARE_RATIO,
|
|
17
|
+
} from '../compact.mjs';
|
|
18
|
+
import { positiveTokenInt, envFlag, envTokenInt } from './env.mjs';
|
|
19
|
+
import { isAgentOwner } from '../../agent-owner.mjs';
|
|
20
|
+
|
|
21
|
+
const COMPACT_SAFETY_PERCENT = 1.00;
|
|
22
|
+
// Unified context-share rule (compact/constants.mjs CONTEXT_SHARE_RATIO): the
|
|
23
|
+
// post-compaction target is 5% of the boundary/context window — the same 5%
|
|
24
|
+
// the recall-fasttrack injection cap uses (loop.mjs recallTokenCap). One
|
|
25
|
+
// number governs every "share of model context" budget.
|
|
26
|
+
const COMPACT_TARGET_RATIO = CONTEXT_SHARE_RATIO;
|
|
27
|
+
const COMPACT_TARGET_MIN_TOKENS = 4_000;
|
|
28
|
+
const COMPACT_TARGET_MAX_TOKENS = 16_000;
|
|
29
|
+
|
|
30
|
+
function resolveSemanticCompactSetting(sessionRef, cfg = {}) {
|
|
31
|
+
if (process.env.MIXDOG_AGENT_COMPACT_SEMANTIC !== undefined) return envFlag('MIXDOG_AGENT_COMPACT_SEMANTIC', true);
|
|
32
|
+
if (cfg.semantic === false || cfg.semantic === 'false' || cfg.semantic === 'off') return false;
|
|
33
|
+
if (cfg.semantic === true || cfg.semantic === 'true' || cfg.semantic === 'on') return true;
|
|
34
|
+
// The compact type is already explicit (`semantic` by default). Honor it
|
|
35
|
+
// directly instead of substituting another compaction path.
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function resolveCompactTypeSetting(sessionRef, cfg = {}) {
|
|
40
|
+
// Agent-owned sessions are ALWAYS semantic. recall-fasttrack rebuilds
|
|
41
|
+
// context from Memory recall, which is scoped to the user's main-session
|
|
42
|
+
// history — an agent's tool-loop history is not in the recall pool, so a
|
|
43
|
+
// fasttrack compact would inject unrelated main-session memories and drop
|
|
44
|
+
// the agent's own working context. Env/config overrides do not apply.
|
|
45
|
+
if (isAgentOwner(sessionRef)) return DEFAULT_COMPACT_TYPE;
|
|
46
|
+
const configured = process.env.MIXDOG_AGENT_COMPACT_TYPE
|
|
47
|
+
?? process.env.MIXDOG_COMPACT_TYPE
|
|
48
|
+
?? cfg.type
|
|
49
|
+
?? cfg.compactType
|
|
50
|
+
?? cfg.compact_type;
|
|
51
|
+
return normalizeCompactType(configured, DEFAULT_COMPACT_TYPE);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function resolveCompactTargetRatio(cfg = {}) {
|
|
55
|
+
const raw = cfg.targetPercent
|
|
56
|
+
?? cfg.targetPct
|
|
57
|
+
?? cfg.targetRatio
|
|
58
|
+
?? cfg.targetFraction
|
|
59
|
+
?? process.env.MIXDOG_AGENT_COMPACT_TARGET_PERCENT
|
|
60
|
+
?? process.env.MIXDOG_COMPACT_TARGET_PERCENT
|
|
61
|
+
?? COMPACT_TARGET_RATIO;
|
|
62
|
+
const n = Number(raw);
|
|
63
|
+
if (!Number.isFinite(n) || n <= 0) return COMPACT_TARGET_RATIO;
|
|
64
|
+
return n > 1 ? n / 100 : n;
|
|
65
|
+
}
|
|
66
|
+
function resolveCompactTargetTokens(boundaryTokens, cfg = {}) {
|
|
67
|
+
const boundary = positiveTokenInt(boundaryTokens);
|
|
68
|
+
if (!boundary) return null;
|
|
69
|
+
const explicit = positiveTokenInt(cfg.targetTokens ?? cfg.target)
|
|
70
|
+
|| envTokenInt('MIXDOG_AGENT_COMPACT_TARGET_TOKENS')
|
|
71
|
+
|| envTokenInt('MIXDOG_COMPACT_TARGET_TOKENS');
|
|
72
|
+
if (explicit) return Math.max(1, Math.min(boundary, explicit));
|
|
73
|
+
const minTarget = Math.min(boundary, positiveTokenInt(cfg.targetMinTokens ?? cfg.minTargetTokens)
|
|
74
|
+
|| envTokenInt('MIXDOG_AGENT_COMPACT_TARGET_MIN_TOKENS')
|
|
75
|
+
|| envTokenInt('MIXDOG_COMPACT_TARGET_MIN_TOKENS')
|
|
76
|
+
|| COMPACT_TARGET_MIN_TOKENS);
|
|
77
|
+
const maxTarget = Math.min(boundary, positiveTokenInt(cfg.targetMaxTokens ?? cfg.maxTargetTokens)
|
|
78
|
+
|| envTokenInt('MIXDOG_AGENT_COMPACT_TARGET_MAX_TOKENS')
|
|
79
|
+
|| envTokenInt('MIXDOG_COMPACT_TARGET_MAX_TOKENS')
|
|
80
|
+
|| COMPACT_TARGET_MAX_TOKENS);
|
|
81
|
+
const byRatio = Math.max(1, Math.floor(boundary * resolveCompactTargetRatio(cfg)));
|
|
82
|
+
return Math.max(1, Math.min(boundary, maxTarget, Math.max(minTarget, byRatio)));
|
|
83
|
+
}
|
|
84
|
+
function resolveCompactKeepTokens(cfg = {}) {
|
|
85
|
+
return positiveTokenInt(cfg.keepTokens ?? cfg.keep?.tokens ?? cfg.preserveRecentTokens)
|
|
86
|
+
|| envTokenInt('MIXDOG_AGENT_COMPACT_KEEP_TOKENS')
|
|
87
|
+
|| DEFAULT_COMPACTION_KEEP_TOKENS;
|
|
88
|
+
}
|
|
89
|
+
export function resolveWorkerCompactPolicy(sessionRef, tools) {
|
|
90
|
+
if (!sessionRef) return null;
|
|
91
|
+
const cfg = sessionRef.compaction || {};
|
|
92
|
+
const auto = cfg.auto !== false && envFlag('MIXDOG_AGENT_COMPACT_AUTO', true);
|
|
93
|
+
if (!auto) return { auto: false };
|
|
94
|
+
const contextWindow = positiveTokenInt(sessionRef.contextWindow ?? cfg.contextWindow);
|
|
95
|
+
const explicitBoundary = positiveTokenInt(sessionRef.compactBoundaryTokens ?? cfg.boundaryTokens);
|
|
96
|
+
const autoLimit = positiveTokenInt(sessionRef.autoCompactTokenLimit ?? cfg.autoCompactTokenLimit);
|
|
97
|
+
const boundaryTokens = explicitBoundary && contextWindow
|
|
98
|
+
? Math.min(explicitBoundary, contextWindow)
|
|
99
|
+
: (explicitBoundary || contextWindow || autoLimit);
|
|
100
|
+
if (!boundaryTokens) return null;
|
|
101
|
+
const compactBoundaryTokens = Math.max(1, Math.floor(boundaryTokens * COMPACT_SAFETY_PERCENT));
|
|
102
|
+
// Only an explicit auto-compact limit STRICTLY BELOW the boundary acts as
|
|
103
|
+
// the trigger. A persisted value == boundary (legacy derived full-window
|
|
104
|
+
// autoCompactTokenLimit) would set autoTriggerTokens == boundary and
|
|
105
|
+
// collapse/override the default trigger, so it is ignored in favor of the
|
|
106
|
+
// default boundary trigger.
|
|
107
|
+
const autoTriggerTokens = autoLimit && autoLimit < compactBoundaryTokens ? Math.max(1, autoLimit) : null;
|
|
108
|
+
// Sanitized explicit limit: only a sub-boundary value is a real auto-compact
|
|
109
|
+
// limit. Anything >= boundary is a legacy derived full-window artifact and
|
|
110
|
+
// is reported as null so rememberCompactTelemetry does not re-persist it
|
|
111
|
+
// back onto the session and re-collapse the buffer on the next turn.
|
|
112
|
+
const explicitAutoCompactTokenLimit = autoTriggerTokens;
|
|
113
|
+
const bufferTokens = autoTriggerTokens
|
|
114
|
+
? Math.max(0, compactBoundaryTokens - autoTriggerTokens)
|
|
115
|
+
: resolveCompactBufferTokens(compactBoundaryTokens, cfg);
|
|
116
|
+
const bufferRatio = compactBoundaryTokens ? (bufferTokens / compactBoundaryTokens) : resolveCompactBufferRatio(cfg);
|
|
117
|
+
const triggerTokens = autoTriggerTokens || Math.max(1, compactBoundaryTokens - bufferTokens);
|
|
118
|
+
const configuredReserve = positiveTokenInt(cfg.reservedTokens)
|
|
119
|
+
|| envTokenInt('MIXDOG_AGENT_COMPACT_RESERVED_TOKENS')
|
|
120
|
+
|| 0;
|
|
121
|
+
const requestReserve = estimateRequestReserveTokens(tools);
|
|
122
|
+
const keepTokens = resolveCompactKeepTokens(cfg);
|
|
123
|
+
const compactType = resolveCompactTypeSetting(sessionRef, cfg);
|
|
124
|
+
return {
|
|
125
|
+
auto: true,
|
|
126
|
+
type: compactType,
|
|
127
|
+
compactType,
|
|
128
|
+
prune: cfg.prune === true || envFlag('MIXDOG_AGENT_COMPACT_PRUNE', false),
|
|
129
|
+
boundaryTokens: compactBoundaryTokens,
|
|
130
|
+
triggerTokens,
|
|
131
|
+
bufferTokens,
|
|
132
|
+
bufferRatio,
|
|
133
|
+
contextWindow,
|
|
134
|
+
rawContextWindow: positiveTokenInt(sessionRef.rawContextWindow ?? cfg.rawContextWindow) || contextWindow,
|
|
135
|
+
effectiveContextWindowPercent: Number.isFinite(Number(sessionRef.effectiveContextWindowPercent ?? cfg.effectiveContextWindowPercent))
|
|
136
|
+
? Number(sessionRef.effectiveContextWindowPercent ?? cfg.effectiveContextWindowPercent)
|
|
137
|
+
: null,
|
|
138
|
+
autoCompactTokenLimit: explicitAutoCompactTokenLimit,
|
|
139
|
+
semantic: compactTypeIsSemantic(compactType) && resolveSemanticCompactSetting(sessionRef, cfg),
|
|
140
|
+
recallFastTrack: compactTypeIsRecallFastTrack(compactType),
|
|
141
|
+
semanticTimeoutMs: positiveTokenInt(cfg.timeoutMs) || envTokenInt('MIXDOG_AGENT_COMPACT_TIMEOUT_MS') || 30_000,
|
|
142
|
+
tailTurns: positiveTokenInt(cfg.tailTurns) || envTokenInt('MIXDOG_AGENT_COMPACT_TAIL_TURNS') || 2,
|
|
143
|
+
keepTokens,
|
|
144
|
+
preserveRecentTokens: positiveTokenInt(cfg.preserveRecentTokens) || envTokenInt('MIXDOG_AGENT_COMPACT_PRESERVE_RECENT_TOKENS') || keepTokens,
|
|
145
|
+
reserveTokens: requestReserve + configuredReserve,
|
|
146
|
+
requestReserveTokens: requestReserve,
|
|
147
|
+
configuredReserveTokens: configuredReserve,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/** Transcript + request reserve only (never provider lastContextTokens). */
|
|
151
|
+
function compactPressureTokens(messageTokensEst, policy) {
|
|
152
|
+
if (messageTokensEst === null) return 0;
|
|
153
|
+
return Math.max(0, messageTokensEst + (policy?.reserveTokens || 0));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Telemetry pressure when a reactive overflow retry forces the next compact. */
|
|
157
|
+
export function compactionTelemetryPressureTokens(messageTokensEst, policy, { reactivePending = false } = {}) {
|
|
158
|
+
const base = compactPressureTokens(messageTokensEst, policy);
|
|
159
|
+
if (!reactivePending) return base;
|
|
160
|
+
const floor = positiveTokenInt(policy?.triggerTokens) || positiveTokenInt(policy?.boundaryTokens) || 0;
|
|
161
|
+
return floor ? Math.max(base, floor) : base;
|
|
162
|
+
}
|
|
163
|
+
export function compactTargetBudget(policy) {
|
|
164
|
+
const boundary = positiveTokenInt(policy?.boundaryTokens);
|
|
165
|
+
if (!boundary) return null;
|
|
166
|
+
const reserve = Math.max(0, Number(policy?.reserveTokens) || 0);
|
|
167
|
+
const targetEffective = resolveCompactTargetTokens(boundary, policy) || boundary;
|
|
168
|
+
return Math.max(1, Math.min(boundary, targetEffective + reserve));
|
|
169
|
+
}
|
|
170
|
+
export function shouldCompactForSession(messageTokensEst, policy, { forceReactive = false } = {}) {
|
|
171
|
+
if (!policy?.auto || !policy.boundaryTokens) return false;
|
|
172
|
+
if (forceReactive) return true;
|
|
173
|
+
if (messageTokensEst === null) return true;
|
|
174
|
+
return compactPressureTokens(messageTokensEst, policy) >= (policy.triggerTokens || policy.boundaryTokens);
|
|
175
|
+
}
|
|
176
|
+
export function countPrunedToolOutputs(before, after) {
|
|
177
|
+
if (!Array.isArray(before) || !Array.isArray(after)) return 0;
|
|
178
|
+
let count = 0;
|
|
179
|
+
const n = Math.min(before.length, after.length);
|
|
180
|
+
for (let i = 0; i < n; i += 1) {
|
|
181
|
+
if (before[i]?.role !== 'tool' || after[i]?.role !== 'tool') continue;
|
|
182
|
+
if (before[i]?.content !== after[i]?.content && after[i]?.compactedKind === 'tool_output_prune') count += 1;
|
|
183
|
+
}
|
|
184
|
+
return count;
|
|
185
|
+
}
|
|
186
|
+
export function rememberCompactTelemetry(sessionRef, policy, meta = {}) {
|
|
187
|
+
if (!sessionRef || !policy) return;
|
|
188
|
+
const prev = sessionRef.compaction && typeof sessionRef.compaction === 'object'
|
|
189
|
+
? sessionRef.compaction
|
|
190
|
+
: {};
|
|
191
|
+
const changed = meta.compactChanged === true || meta.pruneCount > 0;
|
|
192
|
+
sessionRef.compaction = {
|
|
193
|
+
...prev,
|
|
194
|
+
auto: policy.auto !== false,
|
|
195
|
+
prune: policy.prune === true,
|
|
196
|
+
reservedTokens: policy.configuredReserveTokens || prev.reservedTokens || null,
|
|
197
|
+
requestReserveTokens: policy.requestReserveTokens || 0,
|
|
198
|
+
reserveTokens: policy.reserveTokens || 0,
|
|
199
|
+
boundaryTokens: policy.boundaryTokens || null,
|
|
200
|
+
triggerTokens: policy.triggerTokens || null,
|
|
201
|
+
bufferTokens: policy.bufferTokens || 0,
|
|
202
|
+
bufferRatio: policy.bufferRatio ?? prev.bufferRatio ?? null,
|
|
203
|
+
contextWindow: policy.contextWindow || null,
|
|
204
|
+
rawContextWindow: policy.rawContextWindow || null,
|
|
205
|
+
effectiveContextWindowPercent: policy.effectiveContextWindowPercent ?? null,
|
|
206
|
+
autoCompactTokenLimit: policy.autoCompactTokenLimit || null,
|
|
207
|
+
type: policy.compactType || policy.type || DEFAULT_COMPACT_TYPE,
|
|
208
|
+
compactType: policy.compactType || policy.type || DEFAULT_COMPACT_TYPE,
|
|
209
|
+
semantic: policy.semantic === true ? 'auto' : false,
|
|
210
|
+
recallFastTrack: policy.recallFastTrack === true,
|
|
211
|
+
semanticModel: policy.semanticModel || null,
|
|
212
|
+
semanticTimeoutMs: policy.semanticTimeoutMs || null,
|
|
213
|
+
tailTurns: policy.tailTurns || null,
|
|
214
|
+
keepTokens: policy.keepTokens || null,
|
|
215
|
+
preserveRecentTokens: policy.preserveRecentTokens || null,
|
|
216
|
+
lastCheckedAt: Date.now(),
|
|
217
|
+
lastBeforeTokens: meta.beforeTokens ?? null,
|
|
218
|
+
lastAfterTokens: meta.afterTokens ?? null,
|
|
219
|
+
lastPressureTokens: meta.pressureTokens ?? null,
|
|
220
|
+
currentEstimatedTokens: meta.pressureTokens ?? prev.currentEstimatedTokens ?? null,
|
|
221
|
+
lastApiRequestTokens: positiveTokenInt(sessionRef?.lastContextTokens) || prev.lastApiRequestTokens || null,
|
|
222
|
+
lastStage: meta.stage || prev.lastStage || null,
|
|
223
|
+
lastChanged: changed,
|
|
224
|
+
lastTrigger: meta.trigger || prev.lastTrigger || null,
|
|
225
|
+
lastSemantic: meta.semanticCompact === true,
|
|
226
|
+
lastSemanticError: Object.hasOwn(meta, 'semanticError')
|
|
227
|
+
? (meta.semanticError ?? null)
|
|
228
|
+
: (prev.lastSemanticError ?? null),
|
|
229
|
+
lastRecallFastTrack: meta.recallFastTrack === true,
|
|
230
|
+
lastRecallFastTrackError: Object.hasOwn(meta, 'recallFastTrackError')
|
|
231
|
+
? (meta.recallFastTrackError ?? null)
|
|
232
|
+
: (prev.lastRecallFastTrackError ?? null),
|
|
233
|
+
lastError: Object.hasOwn(meta, 'compactError') || Object.hasOwn(meta, 'lastError')
|
|
234
|
+
? (meta.compactError ?? meta.lastError ?? null)
|
|
235
|
+
: (prev.lastError ?? null),
|
|
236
|
+
lastPruneCount: meta.pruneCount || 0,
|
|
237
|
+
lastDurationMs: meta.durationMs != null && Number.isFinite(Number(meta.durationMs))
|
|
238
|
+
? Math.max(0, Math.round(Number(meta.durationMs)))
|
|
239
|
+
: null,
|
|
240
|
+
compactCount: (prev.compactCount || 0) + (changed ? 1 : 0),
|
|
241
|
+
};
|
|
242
|
+
if (changed) {
|
|
243
|
+
const changedAt = Date.now();
|
|
244
|
+
sessionRef.compaction.lastChangedAt = changedAt;
|
|
245
|
+
sessionRef.compaction.lastCompactAt = changedAt;
|
|
246
|
+
sessionRef.lastContextTokensStaleAfterCompact = true;
|
|
247
|
+
}
|
|
248
|
+
sessionRef.contextWindow = policy.contextWindow || sessionRef.contextWindow;
|
|
249
|
+
sessionRef.rawContextWindow = policy.rawContextWindow || sessionRef.rawContextWindow;
|
|
250
|
+
sessionRef.compactBoundaryTokens = policy.boundaryTokens || sessionRef.compactBoundaryTokens || null;
|
|
251
|
+
// Persist only the sanitized (sub-boundary) explicit limit. policy.autoCompactTokenLimit
|
|
252
|
+
// is already null for legacy derived full-window values, so a stale
|
|
253
|
+
// boundary-sized autoCompactTokenLimit on the session is cleared here rather
|
|
254
|
+
// than carried forward to re-collapse the buffer next turn.
|
|
255
|
+
{
|
|
256
|
+
const _boundary = positiveTokenInt(sessionRef.compactBoundaryTokens);
|
|
257
|
+
const _prevLimit = positiveTokenInt(sessionRef.autoCompactTokenLimit);
|
|
258
|
+
const _keepPrev = _prevLimit && (!_boundary || _prevLimit < _boundary) ? _prevLimit : null;
|
|
259
|
+
sessionRef.autoCompactTokenLimit = policy.autoCompactTokenLimit || _keepPrev || null;
|
|
260
|
+
}
|
|
261
|
+
if (policy.effectiveContextWindowPercent !== null) {
|
|
262
|
+
sessionRef.effectiveContextWindowPercent = policy.effectiveContextWindowPercent;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function emitCompactEvent(opts, event = {}) {
|
|
267
|
+
if (!opts || typeof opts.onCompactEvent !== 'function') return;
|
|
268
|
+
try { opts.onCompactEvent({ ts: Date.now(), ...event }); }
|
|
269
|
+
catch { /* best-effort UI/log hook */ }
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function compactEventType(policy, fallback = DEFAULT_COMPACT_TYPE) {
|
|
273
|
+
return policy?.compactType || policy?.type || fallback;
|
|
274
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Completion-first loop guards: escalation ladder (level-2 steering),
|
|
2
|
+
// cross-turn identical read-only call dedup, and worker soft-cap wrap-up.
|
|
3
|
+
// Pure string/signature helpers extracted from loop.mjs so the loop body only
|
|
4
|
+
// wires state + messages. No provider/manager coupling.
|
|
5
|
+
|
|
6
|
+
// Deterministic, key-sorted stringify for cross-turn call signatures. Mirrors
|
|
7
|
+
// _canonicalArgs but exposed by name for the dedup signature contract.
|
|
8
|
+
export function stableStringify(value) {
|
|
9
|
+
if (value == null || typeof value !== 'object') {
|
|
10
|
+
try { return JSON.stringify(value); } catch { return String(value); }
|
|
11
|
+
}
|
|
12
|
+
if (Array.isArray(value)) {
|
|
13
|
+
try { return `[${value.map(stableStringify).join(',')}]`; } catch { return String(value); }
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const keys = Object.keys(value).sort();
|
|
17
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(',')}}`;
|
|
18
|
+
} catch { return String(value); }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function crossTurnSignature(name, args) {
|
|
22
|
+
return `${name}:${stableStringify(args)}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Tool names that are non-eager (no readOnlyHint) but are NOT edits/progress —
|
|
26
|
+
// they must not reset the escalation ladder's "zero edit" condition. Skill /
|
|
27
|
+
// recall / agent / task / cwd / tool_search are exploration/meta plumbing.
|
|
28
|
+
const NON_PROGRESS_TOOLS = new Set(['Skill', 'recall', 'agent', 'task', 'cwd', 'tool_search']);
|
|
29
|
+
|
|
30
|
+
// True when a successfully-executed tool represents real edit/progress. A tool
|
|
31
|
+
// counts as progress only if its def lacks readOnlyHint (not eager) AND it is
|
|
32
|
+
// not in the meta/non-progress set. apply_patch and shell/bash always count.
|
|
33
|
+
export function isEditProgressTool(name, isEager) {
|
|
34
|
+
if (isEager) return false;
|
|
35
|
+
const bare = name && name.startsWith('mcp__') ? name.split('__').pop() : name;
|
|
36
|
+
if (bare === 'apply_patch' || bare === 'shell' || bare === 'bash' || bare === 'bash_session') return true;
|
|
37
|
+
return !NON_PROGRESS_TOOLS.has(bare);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Step 1 — level-2 escalation steering. N = cumulative level-1 fires.
|
|
41
|
+
// `readOnlyRole` swaps the edit-oriented directive for a report-oriented one:
|
|
42
|
+
// read-permission sessions (reviewer-style) cannot apply_patch, so telling
|
|
43
|
+
// them to edit is self-contradictory and pushes premature termination.
|
|
44
|
+
export function level2SteerMessage(n, readOnlyRole = false) {
|
|
45
|
+
if (readOnlyRole) {
|
|
46
|
+
return `<system-reminder>\nYou have received this batching reminder ${n} times. Converge now: report your findings from what you have already read, or state exactly what information is missing for a verdict. A partial report with named gaps is a valid, successful completion — continued exploration is not.\n</system-reminder>`;
|
|
47
|
+
}
|
|
48
|
+
return `<system-reminder>\nYou have received this batching reminder ${n} times without making any edit. Stop exploring now: either apply_patch with what you already know, or return a blocked report stating exactly what is missing. A blocked report is a valid, successful completion — continued exploration is not.\n</system-reminder>`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Step 2 — cross-turn dedup stub. `stuck` appends the escalation tail at the
|
|
52
|
+
// 5th+ dedup stub in the session.
|
|
53
|
+
export function crossTurnDedupStub(name, firstIteration, stuck) {
|
|
54
|
+
let s = `[cross-turn-dedup] identical read-only \`${name}\` call already executed in iteration ${firstIteration}; its result is unchanged and already in context. Use it, or change path/offset/pattern for new information.`;
|
|
55
|
+
if (stuck) s += ` Repeated identical calls indicate you are stuck — apply what you know or return blocked.`;
|
|
56
|
+
return s;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Step 3 — worker soft-cap wrap-up assistant-visible directive + refusal stub.
|
|
60
|
+
export const SOFT_CAP_WRAPUP_MESSAGE = `MAXIMUM EXPLORATION BUDGET REACHED. Tools are now disabled. Respond with text only: summarize work completed so far, list remaining/incomplete items, and state what is blocking or what should be done next. This overrides all other instructions.`;
|
|
61
|
+
export const SOFT_CAP_REFUSAL_STUB = `Tools are disabled: exploration budget reached. Provide your final text summary.`;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Agent context-overflow error, extracted from loop.mjs. Raised when the latest
|
|
2
|
+
// turn cannot fit the target context budget even after compaction.
|
|
3
|
+
|
|
4
|
+
export class AgentContextOverflowError extends Error {
|
|
5
|
+
constructor({ stage, sessionId, provider, model, contextWindow, budgetTokens, reserveTokens, messageTokensEst }, cause) {
|
|
6
|
+
const target = [provider, model].filter(Boolean).join('/') || 'target model';
|
|
7
|
+
const causeMsg = cause && cause.message ? `: ${cause.message}` : '';
|
|
8
|
+
super(
|
|
9
|
+
`agent context overflow (${target}, stage=${stage || 'compact'}): ` +
|
|
10
|
+
`latest turn cannot fit target context budget=${budgetTokens ?? 'unknown'} ` +
|
|
11
|
+
`reserve=${reserveTokens ?? 'unknown'} contextWindow=${contextWindow ?? 'unknown'} ` +
|
|
12
|
+
`messageTokensEst=${messageTokensEst ?? 'unknown'}${causeMsg}`,
|
|
13
|
+
);
|
|
14
|
+
this.name = 'AgentContextOverflowError';
|
|
15
|
+
this.code = 'AGENT_CONTEXT_OVERFLOW';
|
|
16
|
+
this.sessionId = sessionId || null;
|
|
17
|
+
this.provider = provider || null;
|
|
18
|
+
this.model = model || null;
|
|
19
|
+
this.contextWindow = contextWindow ?? null;
|
|
20
|
+
this.budgetTokens = budgetTokens ?? null;
|
|
21
|
+
this.reserveTokens = reserveTokens ?? null;
|
|
22
|
+
this.messageTokensEst = messageTokensEst ?? null;
|
|
23
|
+
if (cause) this.cause = cause;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function agentContextOverflowError({ stage, sessionId, sessionRef, model, budgetTokens, reserveTokens, messageTokensEst }, cause) {
|
|
28
|
+
return new AgentContextOverflowError({
|
|
29
|
+
stage,
|
|
30
|
+
sessionId,
|
|
31
|
+
provider: sessionRef?.provider || null,
|
|
32
|
+
model: sessionRef?.model || model || null,
|
|
33
|
+
contextWindow: sessionRef?.contextWindow ?? null,
|
|
34
|
+
budgetTokens,
|
|
35
|
+
reserveTokens,
|
|
36
|
+
messageTokensEst,
|
|
37
|
+
}, cause);
|
|
38
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Env-var / token parsing helpers extracted from loop.mjs.
|
|
2
|
+
|
|
3
|
+
export function positiveTokenInt(value) {
|
|
4
|
+
const n = Number(value);
|
|
5
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : null;
|
|
6
|
+
}
|
|
7
|
+
export function envFlag(name, fallback = false) {
|
|
8
|
+
const v = process.env[name];
|
|
9
|
+
if (v === undefined) return fallback;
|
|
10
|
+
return !['0', 'false', 'off', 'no'].includes(String(v).trim().toLowerCase());
|
|
11
|
+
}
|
|
12
|
+
export function envTokenInt(name) {
|
|
13
|
+
return positiveTokenInt(process.env[name]);
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Hidden (sub-agent) role registry, extracted from loop.mjs.
|
|
2
|
+
// Source of truth: defaults/agents.json — read once and cached. HIDDEN_AGENT_NAMES
|
|
3
|
+
// is built eagerly so it stays in sync with the declarative registry (no
|
|
4
|
+
// hardcoded duplicate).
|
|
5
|
+
import { readFileSync as _readFileSync } from 'fs';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname, resolve as resolvePath } from 'path';
|
|
8
|
+
|
|
9
|
+
const _AGENTS_JSON = resolvePath(dirname(fileURLToPath(import.meta.url)), '../../../../../defaults/agents.json');
|
|
10
|
+
let _hiddenAgentsCache = null;
|
|
11
|
+
function _getHiddenAgents() {
|
|
12
|
+
if (_hiddenAgentsCache) return _hiddenAgentsCache;
|
|
13
|
+
try {
|
|
14
|
+
_hiddenAgentsCache = JSON.parse(_readFileSync(_AGENTS_JSON, 'utf8'));
|
|
15
|
+
} catch { _hiddenAgentsCache = { agents: [] }; }
|
|
16
|
+
return _hiddenAgentsCache;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const HIDDEN_AGENT_NAMES = new Set(
|
|
20
|
+
(_getHiddenAgents().agents || []).map((r) => r && r.agent).filter((n) => typeof n === 'string' && n.length > 0)
|
|
21
|
+
);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Shared pre-dispatch deny — single source of truth for the remaining
|
|
2
|
+
// control-plane / role scoping rejects. Called by BOTH the eager dispatch
|
|
3
|
+
// path (startEagerTool) and the serial dispatch path (executeTool body).
|
|
4
|
+
// Returns null when the call is allowed to proceed; otherwise returns the
|
|
5
|
+
// Error string the serial path would emit. The eager caller ignores the
|
|
6
|
+
// message body and just treats non-null as "do not start eager".
|
|
7
|
+
//
|
|
8
|
+
// This is NOT a permission gate — runtime permission enforcement was removed
|
|
9
|
+
// (every tool call is trusted). What remains is architectural scoping:
|
|
10
|
+
// agent workers are sandboxed to code/research tools. They must never reach
|
|
11
|
+
// owner/host control surfaces: session management, the ENTIRE channels module
|
|
12
|
+
// (Discord messaging, schedules, webhook/config, channel-bridge toggle,
|
|
13
|
+
// command injection), or host input injection. Explicit name list (no imports)
|
|
14
|
+
// keeps this hot-path gate dependency-free; add new owner/channel tools here.
|
|
15
|
+
import { isAgentOwner } from '../../agent-owner.mjs';
|
|
16
|
+
|
|
17
|
+
const WORKER_DENIED_TOOLS = new Set([
|
|
18
|
+
// session control-plane — unified into the single `agent` tool
|
|
19
|
+
// (type=spawn|send|close|list). Denying the one name blocks all worker
|
|
20
|
+
// session control.
|
|
21
|
+
'agent',
|
|
22
|
+
// channels module (owner/Discord-facing)
|
|
23
|
+
'reply', 'fetch',
|
|
24
|
+
// host input injection
|
|
25
|
+
'inject_input',
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
function _preDispatchDeny(call, toolKind, sessionRef) {
|
|
29
|
+
const name = call?.name;
|
|
30
|
+
if (typeof name !== 'string' || !name) return null;
|
|
31
|
+
const _agentOwned = sessionRef?.scope?.startsWith?.('agent:')
|
|
32
|
+
|| isAgentOwner(sessionRef);
|
|
33
|
+
const _controlPlaneTool = WORKER_DENIED_TOOLS.has(name);
|
|
34
|
+
if (_agentOwned && _controlPlaneTool) {
|
|
35
|
+
return `Error: control-plane tool "${name}" is Lead-only and not available to agent workers.`;
|
|
36
|
+
}
|
|
37
|
+
const noToolAgent = sessionRef?.agent === 'cycle1-agent' || sessionRef?.agent === 'cycle2-agent';
|
|
38
|
+
if (noToolAgent) {
|
|
39
|
+
return `Error: tool "${name}" is not available in agent "${sessionRef.agent}". Re-emit the answer as pipe-separated text per the agent's output format (first character a digit, NO tool_use blocks, NO JSON, NO prose, NO apology).`;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Exported for smoke tests — same runtime deny as the agent loop. */
|
|
45
|
+
export function preDispatchDenyForSession(sessionRef, call, toolKind = 'builtin') {
|
|
46
|
+
return _preDispatchDeny(call, toolKind, sessionRef);
|
|
47
|
+
}
|