mixdog 0.9.3 → 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 +7 -3
- 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/freevar-smoke.mjs +95 -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/provider-toolcall-test.mjs +7 -3
- 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 +23 -63
- package/scripts/tui-render-smoke.mjs +90 -0
- package/scripts/webhook-smoke.mjs +208 -0
- package/src/agents/debugger/AGENT.md +4 -1
- package/src/agents/heavy-worker/AGENT.md +6 -5
- package/src/agents/maintainer/AGENT.md +4 -0
- package/src/agents/reviewer/AGENT.md +2 -1
- package/src/agents/worker/AGENT.md +8 -4
- package/src/lib/rules-builder.cjs +4 -0
- package/src/mixdog-session-runtime.mjs +632 -2042
- 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/rules/agent/00-common.md +2 -0
- package/src/rules/lead/lead-brief.md +12 -0
- package/src/rules/lead/lead-tool.md +0 -11
- 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/providers/anthropic-effort.mjs +62 -20
- 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 +81 -1281
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -3
- 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 +43 -1013
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +17 -3
- 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/openai-codex-model.mjs +108 -0
- 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 +40 -1143
- 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 +297 -2123
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +130 -1002
- 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/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-policy.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -3
- 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/termination.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
- package/src/runtime/agent/orchestrator/session/loop.mjs +251 -397
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +12 -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/usage-metrics.mjs +210 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +166 -1087
- 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/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 +32 -41
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
- 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 -92
- 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 +28 -265
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +0 -6
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +57 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +10 -122
- package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
- 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 +0 -21
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +9 -72
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
- 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 +229 -663
- package/src/runtime/channels/lib/backend-dispatch.mjs +44 -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/output-forwarder.mjs +1 -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/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/tool-defs.mjs +11 -130
- package/src/runtime/memory/index.mjs +201 -1948
- 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/embedding-warmup.mjs +58 -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 +24 -842
- 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-store.mjs +22 -2
- package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
- package/src/runtime/memory/lib/query-handlers.mjs +780 -0
- package/src/runtime/memory/lib/recall-format.mjs +55 -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 +5 -13
- 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/atomic-file.mjs +26 -1
- package/src/runtime/shared/launcher-control.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 +23 -0
- package/src/runtime/shared/update-checker.mjs +7 -4
- package/src/session-runtime/config-helpers.mjs +84 -2
- package/src/session-runtime/config-lifecycle.mjs +232 -0
- package/src/session-runtime/cwd-plugins.mjs +226 -0
- package/src/session-runtime/mcp-glue.mjs +177 -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 +11 -9
- 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/settings-api.mjs +319 -0
- package/src/session-runtime/tool-catalog.mjs +29 -29
- package/src/session-runtime/tool-defs.mjs +84 -0
- package/src/session-runtime/warmup-schedulers.mjs +201 -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 +110 -671
- package/src/standalone/channel-worker.mjs +4 -7
- package/src/standalone/explore-tool.mjs +30 -9
- 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 +77 -870
- package/src/standalone/memory-runtime-proxy.mjs +7 -0
- package/src/standalone/opencode-go-login.mjs +5 -1
- package/src/standalone/provider-admin.mjs +1 -16
- package/src/standalone/usage-dashboard.mjs +3 -1
- package/src/tui/App.jsx +945 -8094
- 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 +23 -101
- 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 +52 -594
- 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/display-width.mjs +20 -3
- package/src/tui/dist/index.mjs +19652 -18630
- package/src/tui/engine/agent-job-feed.mjs +133 -0
- package/src/tui/engine/notification-plan.mjs +76 -0
- package/src/tui/engine/render-timing.mjs +17 -0
- package/src/tui/engine/tool-approval.mjs +94 -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.mjs +122 -562
- package/src/tui/figures.mjs +5 -0
- package/src/tui/index.jsx +105 -0
- package/src/tui/input-editing.mjs +2 -2
- package/src/tui/markdown/format-token.mjs +4 -1
- package/src/tui/statusline-ansi-bridge.mjs +11 -3
- package/src/tui/theme.mjs +6 -0
- 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 +67 -501
- package/src/ui/tool-card.mjs +0 -1
- package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
- package/src/workflows/default/WORKFLOW.md +1 -1
- package/src/workflows/sequential/WORKFLOW.md +1 -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/external-tool-adapters.test.mjs +0 -162
- 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/task-notification-envelope.test.mjs +0 -107
- 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/input-editing.selection.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/paste-fix.test.mjs +0 -119
- 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
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { sendViaWebSocket } from './openai-oauth-ws.mjs';
|
|
16
16
|
import { buildRequestBody } from './openai-oauth.mjs';
|
|
17
17
|
import { enrichModels } from './model-catalog.mjs';
|
|
18
|
+
import { sanitizeModelList } from './model-list-sanitize.mjs';
|
|
18
19
|
import {
|
|
19
20
|
resolveProviderCacheKey,
|
|
20
21
|
resolveProviderPromptCacheLane,
|
|
@@ -143,7 +144,7 @@ export class OpenAIDirectProvider {
|
|
|
143
144
|
// cutoff) can drop deprecated generations.
|
|
144
145
|
created: typeof m.created === 'number' ? m.created : null,
|
|
145
146
|
}));
|
|
146
|
-
return await enrichModels(models);
|
|
147
|
+
return sanitizeModelList(await enrichModels(models), { provider: 'openai' });
|
|
147
148
|
} catch {
|
|
148
149
|
return [];
|
|
149
150
|
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
// Budget math, tool-output pruning, cycle1 draining, and preserved-fact
|
|
2
|
+
// extraction. Extracted verbatim from compact.mjs (behavior-preserving).
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import {
|
|
5
|
+
sanitizeToolPairs,
|
|
6
|
+
dedupToolResultBodies,
|
|
7
|
+
reconcileDedupStubs,
|
|
8
|
+
estimateMessagesTokens,
|
|
9
|
+
DEFAULT_COMPACTION_KEEP_TOKENS,
|
|
10
|
+
} from '../context-utils.mjs';
|
|
11
|
+
import { extractText, summarizeToolCall, redactRawSecretString, TOOL_CALL_FACT_ARGS_MAX_CHARS } from './text-utils.mjs';
|
|
12
|
+
|
|
13
|
+
// Floor for the reserve-adjusted compact budget. When the tool-schema/request
|
|
14
|
+
// reserve rivals the whole budget (huge agent tool surfaces), subtracting the
|
|
15
|
+
// full reserve could leave a degenerate target; keep enough room to attempt a
|
|
16
|
+
// summary and let the final fit check decide. Logged as degraded because a
|
|
17
|
+
// floored budget can still overflow on the next send.
|
|
18
|
+
const MIN_EFFECTIVE_COMPACT_BUDGET_TOKENS = 1024;
|
|
19
|
+
export function effectiveBudget(budgetTokens, opts) {
|
|
20
|
+
if (!(budgetTokens > 0)) throw new Error('compact: budgetTokens must be > 0');
|
|
21
|
+
const reserve = Number(opts?.reserveTokens) || 0;
|
|
22
|
+
if (reserve <= 0) return budgetTokens;
|
|
23
|
+
// Subtract the FULL reserve so an accepted compact actually fits next to
|
|
24
|
+
// the request reserve on the following send. The previous 50%-of-budget cap
|
|
25
|
+
// under-reserved large tool surfaces (agent sessions): a compact could be
|
|
26
|
+
// "accepted" at budget/2 while the true remaining room was smaller, then
|
|
27
|
+
// overflow immediately on the next request.
|
|
28
|
+
const remaining = budgetTokens - reserve;
|
|
29
|
+
if (remaining >= MIN_EFFECTIVE_COMPACT_BUDGET_TOKENS) return remaining;
|
|
30
|
+
const floored = Math.max(1, Math.min(budgetTokens, MIN_EFFECTIVE_COMPACT_BUDGET_TOKENS));
|
|
31
|
+
try { process.stderr.write(`[compact] degraded budget: reserve=${reserve} leaves ${remaining} of budget=${budgetTokens}; flooring to ${floored}\n`); } catch { /* best-effort */ }
|
|
32
|
+
return floored;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const PRUNE_TOOL_OUTPUT_MAX_CHARS = 2_000;
|
|
36
|
+
const PRUNE_TOOL_OUTPUT_HEAD_CHARS = 1_000;
|
|
37
|
+
const PRUNE_TOOL_OUTPUT_TAIL_CHARS = 600;
|
|
38
|
+
const PRUNE_TAIL_TURNS = 2;
|
|
39
|
+
export const MIN_PRESERVE_RECENT_TOKENS = 2_000;
|
|
40
|
+
export const PRESERVED_FACTS_MAX_CHARS = 600;
|
|
41
|
+
|
|
42
|
+
// Count raw (unchunked) pending rows still present in a dump_session_roots
|
|
43
|
+
// payload. recall-fasttrack must keep cycle1-chunking until this reaches 0 so
|
|
44
|
+
// the injected root is the chunked summary, not the raw transcript tail.
|
|
45
|
+
export function countRawPendingRows(dumpText) {
|
|
46
|
+
const text = String(dumpText || '');
|
|
47
|
+
const matches = text.match(/(?:^|\n)# raw_pending\s+\d+\s+id=/gi);
|
|
48
|
+
return matches ? matches.length : 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Drain a single session's cycle1 in fixed window×concurrency units, looping
|
|
52
|
+
// until no raw rows remain (or a pass stops making progress / the deadline
|
|
53
|
+
// elapses). This replaces the previous single-pass cycle1 so large sessions
|
|
54
|
+
// get fully chunked before their root is injected into the compacted context.
|
|
55
|
+
export async function drainSessionCycle1(runTool, { sessionId, cycleArgs = {}, dumpArgs, maxPasses = 0, deadlineMs = 0 } = {}) {
|
|
56
|
+
if (typeof runTool !== 'function') throw new Error('drainSessionCycle1: runTool is required');
|
|
57
|
+
if (!sessionId) throw new Error('drainSessionCycle1: sessionId is required');
|
|
58
|
+
if (!dumpArgs) throw new Error('drainSessionCycle1: dumpArgs is required');
|
|
59
|
+
const startedAt = Date.now();
|
|
60
|
+
const hardPasses = Math.max(1, Number(maxPasses) || 50);
|
|
61
|
+
const lines = [];
|
|
62
|
+
let cycle1Error = null;
|
|
63
|
+
let recallText = await runTool('memory', dumpArgs);
|
|
64
|
+
let rawRemaining = countRawPendingRows(recallText);
|
|
65
|
+
let pass = 0;
|
|
66
|
+
while (rawRemaining > 0 && pass < hardPasses) {
|
|
67
|
+
if (deadlineMs > 0 && (Date.now() - startedAt) >= deadlineMs) break;
|
|
68
|
+
pass += 1;
|
|
69
|
+
const passDeadline = deadlineMs > 0
|
|
70
|
+
? Math.max(1, deadlineMs - (Date.now() - startedAt))
|
|
71
|
+
: 0;
|
|
72
|
+
let passText = '';
|
|
73
|
+
try {
|
|
74
|
+
passText = await runTool('memory', {
|
|
75
|
+
action: 'cycle1',
|
|
76
|
+
sessionId,
|
|
77
|
+
...cycleArgs,
|
|
78
|
+
...(passDeadline > 0 ? { _callerDeadlineMs: passDeadline } : {}),
|
|
79
|
+
});
|
|
80
|
+
} catch (err) {
|
|
81
|
+
cycle1Error = err?.message ? String(err.message) : String(err);
|
|
82
|
+
lines.push(`cycle1 pass=${pass} error=${cycle1Error}`);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
if (passText) lines.push(`cycle1 pass=${pass}: ${String(passText).trim()}`);
|
|
86
|
+
recallText = await runTool('memory', dumpArgs);
|
|
87
|
+
const nextRaw = countRawPendingRows(recallText);
|
|
88
|
+
// No forward progress (raw not shrinking) — stop instead of spinning.
|
|
89
|
+
if (nextRaw >= rawRemaining) {
|
|
90
|
+
rawRemaining = nextRaw;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
rawRemaining = nextRaw;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
recallText,
|
|
97
|
+
cycle1Text: lines.join('\n'),
|
|
98
|
+
passes: pass,
|
|
99
|
+
rawRemaining,
|
|
100
|
+
error: cycle1Error,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function preservedFactHints() {
|
|
105
|
+
return String(process.env.MIXDOG_COMPACT_FACT_HINTS || '')
|
|
106
|
+
.split(/[\n,;]+/u)
|
|
107
|
+
.map(s => s.trim())
|
|
108
|
+
.filter(Boolean)
|
|
109
|
+
.map(s => s.toLocaleLowerCase());
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const PRESERVED_FACT_HINTS = preservedFactHints();
|
|
113
|
+
|
|
114
|
+
function hasConfiguredPreservedFactHint(text) {
|
|
115
|
+
const lower = String(text || '').toLocaleLowerCase();
|
|
116
|
+
return PRESERVED_FACT_HINTS.some(hint => hint && lower.includes(hint));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function extractPreservedFacts(messages) {
|
|
120
|
+
if (!messages || messages.length === 0) return '';
|
|
121
|
+
const candidates = [];
|
|
122
|
+
const seenSignatures = new Set();
|
|
123
|
+
const add = (prefix, text, score, messageIndex, lineIndex = 0) => {
|
|
124
|
+
const clean = text.replace(/`/g, '').trim();
|
|
125
|
+
if (clean.length < 10) return;
|
|
126
|
+
const sig = clean.slice(0, 80).toLowerCase().replace(/\s+/g, ' ');
|
|
127
|
+
if (seenSignatures.has(sig)) return;
|
|
128
|
+
seenSignatures.add(sig);
|
|
129
|
+
candidates.push({ prefix, text: clean, score, messageIndex, lineIndex });
|
|
130
|
+
};
|
|
131
|
+
const classifyLine = (t) => {
|
|
132
|
+
// Language-neutral structural cues: exact assignments, paths, URLs,
|
|
133
|
+
// symbolic error/constant identifiers, and optional user-configured
|
|
134
|
+
// locale/domain hints. Do not bake human-language keyword lists here.
|
|
135
|
+
if (/[\p{L}\p{N}_$./:-]{2,}\s*=\s*\S+/u.test(t)) return { prefix: '•', score: 100 };
|
|
136
|
+
if (/(?:^|[\s('"`])https?:\/\/[^\s'"`<>]+/iu.test(t)) return { prefix: '•', score: 95 };
|
|
137
|
+
if (/(?:^|[\s('"`])(?:[A-Za-z]:[\\/]|\.{1,2}[\\/]|~?[\\/][^\s'"`<>]+|[\p{L}\p{N}_$.-]+[\\/][^\s'"`<>]+|[\p{L}\p{N}_$.-]+\.(?:mjs|cjs|js|jsx|ts|tsx|json|md|rs|go|py|java|kt|cs|cpp|c|h|hpp|css|html|yml|yaml|toml|lock|sh|ps1)\b)/iu.test(t)) return { prefix: '•', score: 95 };
|
|
138
|
+
if (/\b[A-Z][A-Z0-9_:-]{2,}\b/.test(t)) return { prefix: '•', score: 90 };
|
|
139
|
+
if (hasConfiguredPreservedFactHint(t)) return { prefix: '!', score: 70 };
|
|
140
|
+
return null;
|
|
141
|
+
};
|
|
142
|
+
for (let mi = 0; mi < messages.length; mi += 1) {
|
|
143
|
+
const m = messages[mi];
|
|
144
|
+
const text = extractText(m);
|
|
145
|
+
if (!text) continue;
|
|
146
|
+
const lines = text.split('\n');
|
|
147
|
+
for (let li = 0; li < lines.length; li += 1) {
|
|
148
|
+
const line = lines[li];
|
|
149
|
+
const t = line.trim();
|
|
150
|
+
if (t.length < 10 || t.length > 250) continue;
|
|
151
|
+
const cls = classifyLine(t);
|
|
152
|
+
if (cls) add(cls.prefix, redactRawSecretString(t), cls.score, mi, li);
|
|
153
|
+
}
|
|
154
|
+
if (m?.role === 'assistant' && Array.isArray(m.toolCalls)) {
|
|
155
|
+
for (const tc of m.toolCalls) {
|
|
156
|
+
const name = tc?.function?.name || tc?.name || '';
|
|
157
|
+
if (name) {
|
|
158
|
+
const summary = summarizeToolCall(tc, TOOL_CALL_FACT_ARGS_MAX_CHARS);
|
|
159
|
+
const sig = `tool:${summary.slice(0, 160).toLowerCase()}`;
|
|
160
|
+
if (seenSignatures.has(sig)) continue;
|
|
161
|
+
seenSignatures.add(sig);
|
|
162
|
+
candidates.push({ prefix: '•', text: `Tool: ${summary}`, score: 50, messageIndex: mi, lineIndex: Number.MAX_SAFE_INTEGER });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (candidates.length === 0) return '';
|
|
168
|
+
candidates.sort((a, b) =>
|
|
169
|
+
(b.score - a.score)
|
|
170
|
+
|| (b.messageIndex - a.messageIndex)
|
|
171
|
+
|| (b.lineIndex - a.lineIndex)
|
|
172
|
+
);
|
|
173
|
+
let result = '## Preserved Facts\n';
|
|
174
|
+
let kept = 0;
|
|
175
|
+
for (const c of candidates) {
|
|
176
|
+
if (kept >= 25) break;
|
|
177
|
+
let line = `- ${c.prefix} ${c.text}\n`;
|
|
178
|
+
if (result.length + line.length > PRESERVED_FACTS_MAX_CHARS) {
|
|
179
|
+
const room = PRESERVED_FACTS_MAX_CHARS - result.length - 8;
|
|
180
|
+
if (kept === 0 && room > 32) line = `- ${c.prefix} ${c.text.slice(0, room)}…\n`;
|
|
181
|
+
else continue;
|
|
182
|
+
}
|
|
183
|
+
result += line;
|
|
184
|
+
kept += 1;
|
|
185
|
+
}
|
|
186
|
+
return kept > 0 ? result : '';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function protectedTailStart(messages, tailTurns = PRUNE_TAIL_TURNS) {
|
|
190
|
+
let seenUsers = 0;
|
|
191
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
192
|
+
if (messages[i]?.role !== 'user') continue;
|
|
193
|
+
seenUsers += 1;
|
|
194
|
+
if (seenUsers >= tailTurns) return i;
|
|
195
|
+
}
|
|
196
|
+
return 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function pruneToolOutputText(text, maxChars, toolCallId) {
|
|
200
|
+
const value = String(text ?? '').replace(/\r\n/g, '\n');
|
|
201
|
+
if (value.length <= maxChars) return value;
|
|
202
|
+
const hash = createHash('sha256').update(value).digest('hex').slice(0, 16);
|
|
203
|
+
const head = value.slice(0, PRUNE_TOOL_OUTPUT_HEAD_CHARS);
|
|
204
|
+
const tail = value.slice(-PRUNE_TOOL_OUTPUT_TAIL_CHARS);
|
|
205
|
+
return [
|
|
206
|
+
`[mixdog pruned old tool output: ${value.length} chars, sha256:${hash}${toolCallId ? `, tool_use_id=${toolCallId}` : ''}]`,
|
|
207
|
+
head,
|
|
208
|
+
'... [old tool output omitted during worker compaction] ...',
|
|
209
|
+
tail,
|
|
210
|
+
].join('\n');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function pruneToolOutputs(messages, budgetTokens, opts = {}) {
|
|
214
|
+
const budget = effectiveBudget(budgetTokens, opts);
|
|
215
|
+
let result = reconcileDedupStubs(dedupToolResultBodies(sanitizeToolPairs(messages)));
|
|
216
|
+
if (estimateMessagesTokens(result) <= budget) return result;
|
|
217
|
+
|
|
218
|
+
const maxChars = Math.max(256, Number(opts?.maxToolOutputChars) || PRUNE_TOOL_OUTPUT_MAX_CHARS);
|
|
219
|
+
const protectFrom = protectedTailStart(result, Number(opts?.tailTurns) || PRUNE_TAIL_TURNS);
|
|
220
|
+
const candidates = [];
|
|
221
|
+
for (let i = 0; i < protectFrom; i += 1) {
|
|
222
|
+
const m = result[i];
|
|
223
|
+
if (m?.role !== 'tool' || typeof m.content !== 'string') continue;
|
|
224
|
+
if (m.content.length <= maxChars) continue;
|
|
225
|
+
candidates.push({ index: i, length: m.content.length });
|
|
226
|
+
}
|
|
227
|
+
candidates.sort((a, b) => b.length - a.length);
|
|
228
|
+
for (const c of candidates) {
|
|
229
|
+
const m = result[c.index];
|
|
230
|
+
result[c.index] = {
|
|
231
|
+
...m,
|
|
232
|
+
content: pruneToolOutputText(m.content, maxChars, m.toolCallId),
|
|
233
|
+
compacted: true,
|
|
234
|
+
compactedKind: 'tool_output_prune',
|
|
235
|
+
};
|
|
236
|
+
if (estimateMessagesTokens(result) <= budget) break;
|
|
237
|
+
}
|
|
238
|
+
return reconcileDedupStubs(result);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Anchor-independent tool-output prune (loop overflow safety net).
|
|
242
|
+
//
|
|
243
|
+
// pruneToolOutputs protects the most-recent tailTurns of USER-anchored history,
|
|
244
|
+
// so a single-turn transcript with no user boundary yields protectFrom=0 and
|
|
245
|
+
// prunes nothing. This variant needs no user anchor: it middle-truncates the
|
|
246
|
+
// OLDEST oversized tool_result bodies first, walking forward, until the
|
|
247
|
+
// transcript fits the budget. The newest tool_result is truncated last (and
|
|
248
|
+
// only if still necessary) so fresh state is preserved as long as possible.
|
|
249
|
+
// Structure/pairing is preserved (only string content shrinks), and the result
|
|
250
|
+
// is re-reconciled so tool pairing stays provider-valid.
|
|
251
|
+
export function pruneToolOutputsUnanchored(messages, budgetTokens, opts = {}) {
|
|
252
|
+
const budget = effectiveBudget(budgetTokens, opts);
|
|
253
|
+
let result = reconcileDedupStubs(dedupToolResultBodies(sanitizeToolPairs(messages)));
|
|
254
|
+
if (estimateMessagesTokens(result) <= budget) return result;
|
|
255
|
+
|
|
256
|
+
const maxChars = Math.max(256, Number(opts?.maxToolOutputChars) || PRUNE_TOOL_OUTPUT_MAX_CHARS);
|
|
257
|
+
// Oldest -> newest so recent tool output survives longest. No user-turn
|
|
258
|
+
// protection: every oversized tool_result is a candidate.
|
|
259
|
+
for (let i = 0; i < result.length; i += 1) {
|
|
260
|
+
const m = result[i];
|
|
261
|
+
if (m?.role !== 'tool' || typeof m.content !== 'string') continue;
|
|
262
|
+
if (m.content.length <= maxChars) continue;
|
|
263
|
+
result[i] = {
|
|
264
|
+
...m,
|
|
265
|
+
content: pruneToolOutputText(m.content, maxChars, m.toolCallId),
|
|
266
|
+
compacted: true,
|
|
267
|
+
compactedKind: 'tool_output_prune',
|
|
268
|
+
};
|
|
269
|
+
if (estimateMessagesTokens(result) <= budget) break;
|
|
270
|
+
}
|
|
271
|
+
return reconcileDedupStubs(result);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export function preserveRecentBudget(budget, opts = {}) {
|
|
275
|
+
const maxForBudget = Math.max(1, Math.floor(Number(budget || 0) * 0.8));
|
|
276
|
+
const explicit = Number(opts.preserveRecentTokens ?? opts.keepTokens);
|
|
277
|
+
if (Number.isFinite(explicit) && explicit > 0) {
|
|
278
|
+
return Math.max(1, Math.min(Math.floor(explicit), maxForBudget));
|
|
279
|
+
}
|
|
280
|
+
return Math.max(
|
|
281
|
+
1,
|
|
282
|
+
Math.min(
|
|
283
|
+
DEFAULT_COMPACTION_KEEP_TOKENS,
|
|
284
|
+
Math.max(MIN_PRESERVE_RECENT_TOKENS, Math.floor(budget * 0.25)),
|
|
285
|
+
maxForBudget,
|
|
286
|
+
),
|
|
287
|
+
);
|
|
288
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Shared compaction constants and compact-type helpers. Extracted verbatim
|
|
2
|
+
// from compact.mjs (behavior-preserving). compact.mjs re-exports the public
|
|
3
|
+
// members from here so the external surface is unchanged.
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_COMPACTION_BUFFER_TOKENS,
|
|
6
|
+
DEFAULT_COMPACTION_BUFFER_RATIO,
|
|
7
|
+
MAX_COMPACTION_BUFFER_RATIO,
|
|
8
|
+
DEFAULT_COMPACTION_KEEP_TOKENS,
|
|
9
|
+
normalizeCompactionBufferRatio,
|
|
10
|
+
compactionBufferTokensForBoundary,
|
|
11
|
+
} from '../context-utils.mjs';
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
DEFAULT_COMPACTION_BUFFER_TOKENS,
|
|
15
|
+
DEFAULT_COMPACTION_BUFFER_RATIO,
|
|
16
|
+
MAX_COMPACTION_BUFFER_RATIO,
|
|
17
|
+
DEFAULT_COMPACTION_KEEP_TOKENS,
|
|
18
|
+
normalizeCompactionBufferRatio,
|
|
19
|
+
compactionBufferTokensForBoundary,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const SUMMARY_PREFIX = 'A previous model worked on this task and produced the compacted handoff summary below. Build on the work already done and avoid duplicating it; treat the summary as authoritative context for continuing the task. You also retain the preserved recent turns that follow.';
|
|
23
|
+
export const SUMMARY_OUTPUT_TOKENS = 4_096;
|
|
24
|
+
// Unified context-share rule: every derived "how much of the model context
|
|
25
|
+
// may this budget take" ratio uses ONE number — 5%. Consumers:
|
|
26
|
+
// - compact target budget (loop/compact-policy.mjs COMPACT_TARGET_RATIO)
|
|
27
|
+
// - recall-fasttrack injection cap (loop.mjs recallTokenCap)
|
|
28
|
+
// Keep them in lockstep; do not fork per-consumer ratios without a decision.
|
|
29
|
+
export const CONTEXT_SHARE_RATIO = 0.05;
|
|
30
|
+
// Floor for the recall-injection cap so small-context models still get a
|
|
31
|
+
// usable recall slice (cap = max(floor, contextWindow * CONTEXT_SHARE_RATIO)).
|
|
32
|
+
export const RECALL_TOKEN_CAP_FLOOR_TOKENS = 2_048;
|
|
33
|
+
// Minimum room the generated summary needs after the mandatory (system +
|
|
34
|
+
// preserved tail) cost is accounted for. When the configured target budget is
|
|
35
|
+
// smaller than the mandatory cost (e.g. the preserved recent turn carries a
|
|
36
|
+
// large tool result), the compaction MUST still proceed: the old head is the
|
|
37
|
+
// part being summarized away, so dropping it already shrinks the transcript.
|
|
38
|
+
// Refusing with "exceeds budget" here is what surfaced as auto-clear / overflow
|
|
39
|
+
// compact failures. Floor the working budget to mandatory + this room instead.
|
|
40
|
+
export const COMPACT_SUMMARY_MIN_ROOM_TOKENS = 4_000;
|
|
41
|
+
|
|
42
|
+
export const COMPACT_TYPE_SEMANTIC = 'semantic';
|
|
43
|
+
export const COMPACT_TYPE_RECALL_FASTTRACK = 'recall-fasttrack';
|
|
44
|
+
export const DEFAULT_COMPACT_TYPE = COMPACT_TYPE_SEMANTIC;
|
|
45
|
+
export const COMPACT_TYPES = Object.freeze([
|
|
46
|
+
COMPACT_TYPE_SEMANTIC,
|
|
47
|
+
COMPACT_TYPE_RECALL_FASTTRACK,
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
export function normalizeCompactType(value, fallback = DEFAULT_COMPACT_TYPE) {
|
|
51
|
+
const raw = String(value ?? '').trim().toLowerCase().replace(/_/g, '-');
|
|
52
|
+
if (!raw) return fallback;
|
|
53
|
+
if (raw === '1' || raw === 'type1' || raw === 'type-1' || raw === 'bench1' || raw === 'bench-1' || raw === 'semantic' || raw === 'summary') {
|
|
54
|
+
return COMPACT_TYPE_SEMANTIC;
|
|
55
|
+
}
|
|
56
|
+
// Recall fast-track aliases. `replace(/_/g,'-')` above already folds
|
|
57
|
+
// snake_case (fast_track -> fast-track), but list both dash/no-dash forms
|
|
58
|
+
// explicitly so callers passing either spelling resolve deterministically.
|
|
59
|
+
if (raw === '2' || raw === 'type2' || raw === 'type-2' || raw === 'recall' || raw === 'recall-fast' || raw === 'recall-fasttrack' || raw === 'recall-fast-track' || raw === 'fasttrack' || raw === 'fast-track') {
|
|
60
|
+
return COMPACT_TYPE_RECALL_FASTTRACK;
|
|
61
|
+
}
|
|
62
|
+
// Unknown / unrecognized value: fall back to the caller-provided default
|
|
63
|
+
// (semantic by default). Callers that need to detect an unknown value
|
|
64
|
+
// should compare the input against COMPACT_TYPES before normalizing.
|
|
65
|
+
return fallback;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function compactTypeIsSemantic(value) {
|
|
69
|
+
return normalizeCompactType(value) === COMPACT_TYPE_SEMANTIC;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function compactTypeIsRecallFastTrack(value) {
|
|
73
|
+
return normalizeCompactType(value) === COMPACT_TYPE_RECALL_FASTTRACK;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function compactDebugEnabled() {
|
|
77
|
+
return String(process.env.MIXDOG_COMPACT_DEBUG || '').trim() === '1';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function compactDebugLog(scope, details = {}) {
|
|
81
|
+
if (!compactDebugEnabled()) return;
|
|
82
|
+
try {
|
|
83
|
+
process.stderr.write(`[compact] ${scope} ${JSON.stringify(details)}\n`);
|
|
84
|
+
} catch { /* best-effort diagnostics only */ }
|
|
85
|
+
}
|