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
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
// Text/token/message helpers and secret redaction for compaction. Extracted
|
|
2
|
+
// verbatim from compact.mjs (behavior-preserving).
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { estimateMessagesTokens } from '../context-utils.mjs';
|
|
5
|
+
|
|
6
|
+
const TOOL_ARG_STRING_MAX_CHARS = 360;
|
|
7
|
+
const TOOL_ARG_ARRAY_MAX_ITEMS = 8;
|
|
8
|
+
const TOOL_ARG_MAX_DEPTH = 4;
|
|
9
|
+
export const TOOL_CALL_ARGS_MAX_CHARS = 260;
|
|
10
|
+
export const TOOL_CALL_FACT_ARGS_MAX_CHARS = 140;
|
|
11
|
+
export const TOOL_CALLS_MAX = 4;
|
|
12
|
+
const SENSITIVE_TOOL_ARG_KEY_RE = /(?:^|[_-])(?:api[_-]?key|authorization|auth|cookie|credential|passwd|password|refresh[_-]?token|secret|token)(?:$|[_-])/i;
|
|
13
|
+
// Word alternation for raw-string (non-JSON) secret redaction. Mirrors the
|
|
14
|
+
// keys in SENSITIVE_TOOL_ARG_KEY_RE and the session-ingest redactor so a raw
|
|
15
|
+
// tool-call argument string like `authorization: Bearer abc.def` or
|
|
16
|
+
// `password="abc def"` never reaches preserved facts or the compaction prompt.
|
|
17
|
+
const SENSITIVE_TOOL_ARG_KEY_WORD = '(?:api[_-]?key|authorization|auth|cookie|credential|passwd|password|refresh[_-]?token|secret|token)';
|
|
18
|
+
// Full key matcher: the sensitive WORD may carry a prefix and/or suffix segment
|
|
19
|
+
// joined by `_`/`-` so prefixed variants like `access_token`, `access-token`,
|
|
20
|
+
// `x-api-key`, and `bearer_token` are matched as whole keys (not just the bare
|
|
21
|
+
// word at key start). Prefix/suffix are bounded by a `_`/`-` separator so the
|
|
22
|
+
// word stays at an identifier boundary.
|
|
23
|
+
const SENSITIVE_TOOL_ARG_KEY_FULL = `(?:[A-Za-z0-9_-]*[_-])?${SENSITIVE_TOOL_ARG_KEY_WORD}(?:[_-][A-Za-z0-9_-]*)?`;
|
|
24
|
+
// camelCase variants (case-SENSITIVE, deliberately not /i): a capitalized
|
|
25
|
+
// sensitive word CLOSING the key — `accessToken`, `authToken`, `bearerToken`,
|
|
26
|
+
// `sessionSecret`, `myPassword`. Bounded so plural/compound counters
|
|
27
|
+
// (`tokens`, `maxOutputTokens`, `budgetTokens`) do NOT match.
|
|
28
|
+
const SENSITIVE_TOOL_ARG_KEY_CAMEL_WORD = '(?:Api[_-]?Key|Authorization|Auth|Cookie|Credential|Passwd|Password|Refresh[_-]?Token|Secret|Token)';
|
|
29
|
+
const SENSITIVE_TOOL_ARG_KEY_CAMEL_RE = new RegExp(`[a-z0-9]${SENSITIVE_TOOL_ARG_KEY_CAMEL_WORD}s?$`);
|
|
30
|
+
function isSensitiveToolArgKey(key) {
|
|
31
|
+
const k = String(key || '');
|
|
32
|
+
return SENSITIVE_TOOL_ARG_KEY_RE.test(k) || SENSITIVE_TOOL_ARG_KEY_CAMEL_RE.test(k);
|
|
33
|
+
}
|
|
34
|
+
const SENSITIVE_RAW_KEY_RES = [
|
|
35
|
+
new RegExp(`((?:^|[\\s,{(?&])["']?${SENSITIVE_TOOL_ARG_KEY_FULL}["']?\\s*[:=]\\s*)`, 'gi'),
|
|
36
|
+
// Case-sensitive camelCase raw keys (`accessToken=...`, `myAuthToken: ...`).
|
|
37
|
+
new RegExp(`((?:^|[\\s,{(?&])["']?[A-Za-z0-9_-]*[a-z0-9]${SENSITIVE_TOOL_ARG_KEY_CAMEL_WORD}["']?\\s*[:=]\\s*)`, 'g'),
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
// Redact `key: value` / `key=value` secret pairs inside a raw (non-JSON)
|
|
41
|
+
// string. Consumes the WHOLE value after the key — spaces, `Bearer `/`Basic `
|
|
42
|
+
// scheme words, quoted values with internal spaces, and `;`-separated cookie
|
|
43
|
+
// pairs — so no secret fragment survives. Kept local to compact-core to avoid a
|
|
44
|
+
// cross-module dependency on the memory lib; logic matches session-ingest's
|
|
45
|
+
// redactRawArgString.
|
|
46
|
+
export function redactRawSecretString(text) {
|
|
47
|
+
let value = String(text ?? '');
|
|
48
|
+
if (!value) return value;
|
|
49
|
+
for (const keyRe of SENSITIVE_RAW_KEY_RES) {
|
|
50
|
+
keyRe.lastIndex = 0;
|
|
51
|
+
let out = '';
|
|
52
|
+
let last = 0;
|
|
53
|
+
let match;
|
|
54
|
+
while ((match = keyRe.exec(value)) !== null) {
|
|
55
|
+
const prefixEnd = match.index + match[0].length;
|
|
56
|
+
out += value.slice(last, prefixEnd);
|
|
57
|
+
let i = prefixEnd;
|
|
58
|
+
const quote = value[i] === '"' || value[i] === "'" ? value[i] : '';
|
|
59
|
+
if (quote) {
|
|
60
|
+
i += 1;
|
|
61
|
+
while (i < value.length && value[i] !== quote) i += 1;
|
|
62
|
+
if (i < value.length) i += 1; // include closing quote
|
|
63
|
+
} else {
|
|
64
|
+
// Header-style `key: value` may carry scheme words and spaces
|
|
65
|
+
// (`authorization: Bearer abc.def`) — consume the whole value so
|
|
66
|
+
// no fragment survives. KV-style `key=value` stops at whitespace
|
|
67
|
+
// so space-separated trailing keys (`token=abc fileName=x`) are
|
|
68
|
+
// preserved.
|
|
69
|
+
const headerStyle = /:\s*$/.test(match[0]);
|
|
70
|
+
const stopRe = headerStyle ? /[,)}\n]/ : /[,)}\s]/;
|
|
71
|
+
while (i < value.length && !stopRe.test(value[i])) i += 1;
|
|
72
|
+
}
|
|
73
|
+
out += '[redacted]';
|
|
74
|
+
last = i;
|
|
75
|
+
keyRe.lastIndex = i;
|
|
76
|
+
}
|
|
77
|
+
out += value.slice(last);
|
|
78
|
+
value = out;
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function sha16(value) {
|
|
84
|
+
const text = typeof value === 'string' ? value : JSON.stringify(value ?? null);
|
|
85
|
+
return createHash('sha256').update(text).digest('hex').slice(0, 16);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function roleCounts(messages) {
|
|
89
|
+
const counts = new Map();
|
|
90
|
+
for (const m of messages) counts.set(m?.role || 'unknown', (counts.get(m?.role || 'unknown') || 0) + 1);
|
|
91
|
+
return [...counts.entries()].map(([role, count]) => `${role}:${count}`).join(', ');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function extractText(m) {
|
|
95
|
+
if (!m || typeof m !== 'object') return '';
|
|
96
|
+
if (typeof m.content === 'string') return m.content;
|
|
97
|
+
if (Array.isArray(m.content)) {
|
|
98
|
+
return m.content
|
|
99
|
+
.map((item) => {
|
|
100
|
+
if (!item || typeof item !== 'object') return '';
|
|
101
|
+
if (typeof item.text === 'string') return item.text;
|
|
102
|
+
if (typeof item.content === 'string') return item.content;
|
|
103
|
+
return '';
|
|
104
|
+
})
|
|
105
|
+
.filter(Boolean)
|
|
106
|
+
.join('\n');
|
|
107
|
+
}
|
|
108
|
+
try { return JSON.stringify(m.content ?? ''); } catch { return ''; }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function truncateMiddle(text, maxChars) {
|
|
112
|
+
const value = String(text ?? '').replace(/\r\n/g, '\n');
|
|
113
|
+
if (maxChars <= 0 || value.length === 0) return '';
|
|
114
|
+
if (value.length <= maxChars) return value;
|
|
115
|
+
if (maxChars <= 8) return value.slice(0, maxChars);
|
|
116
|
+
const head = Math.ceil((maxChars - 5) / 2);
|
|
117
|
+
const tail = Math.floor((maxChars - 5) / 2);
|
|
118
|
+
return `${value.slice(0, head)} … ${value.slice(value.length - tail)}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function normalizeToolArgValue(value, key = '', depth = 0) {
|
|
122
|
+
if (isSensitiveToolArgKey(key)) return '[redacted]';
|
|
123
|
+
if (typeof value === 'bigint') return String(value);
|
|
124
|
+
// Defense-in-depth: a non-sensitive KEY can still carry a secret embedded
|
|
125
|
+
// in its string VALUE (e.g. a freeform `headers` string). Redact raw
|
|
126
|
+
// key:value secret pairs before truncating.
|
|
127
|
+
if (typeof value === 'string') return truncateMiddle(redactRawSecretString(value), TOOL_ARG_STRING_MAX_CHARS);
|
|
128
|
+
if (!value || typeof value !== 'object') return value ?? null;
|
|
129
|
+
if (depth >= TOOL_ARG_MAX_DEPTH) return Array.isArray(value) ? `[array:${value.length}]` : '[object]';
|
|
130
|
+
if (Array.isArray(value)) {
|
|
131
|
+
const out = value.slice(0, TOOL_ARG_ARRAY_MAX_ITEMS)
|
|
132
|
+
.map((item, index) => normalizeToolArgValue(item, String(index), depth + 1));
|
|
133
|
+
if (value.length > TOOL_ARG_ARRAY_MAX_ITEMS) out.push(`+${value.length - TOOL_ARG_ARRAY_MAX_ITEMS} more`);
|
|
134
|
+
return out;
|
|
135
|
+
}
|
|
136
|
+
const out = {};
|
|
137
|
+
for (const k of Object.keys(value).sort()) {
|
|
138
|
+
out[k] = normalizeToolArgValue(value[k], k, depth + 1);
|
|
139
|
+
}
|
|
140
|
+
return out;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function stableToolArgJson(value) {
|
|
144
|
+
if (value == null) return '';
|
|
145
|
+
if (typeof value === 'string') {
|
|
146
|
+
const text = value.trim();
|
|
147
|
+
if (!text) return '';
|
|
148
|
+
if (/^[\[{]/.test(text)) {
|
|
149
|
+
try { return JSON.stringify(normalizeToolArgValue(JSON.parse(text))); } catch { /* keep raw */ }
|
|
150
|
+
}
|
|
151
|
+
// Non-JSON raw string: redact secret key:value pairs before truncating
|
|
152
|
+
// so toolCallSummary / preserved facts / compaction prompt metadata
|
|
153
|
+
// never leak `authorization: Bearer ...`, passwords, cookies, tokens.
|
|
154
|
+
return truncateMiddle(redactRawSecretString(text), TOOL_ARG_STRING_MAX_CHARS);
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
return JSON.stringify(normalizeToolArgValue(value));
|
|
158
|
+
} catch {
|
|
159
|
+
return truncateMiddle(redactRawSecretString(String(value || '')), TOOL_ARG_STRING_MAX_CHARS);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function toolCallArgsText(tc, maxChars = TOOL_CALL_ARGS_MAX_CHARS) {
|
|
164
|
+
if (!(maxChars > 0)) return '';
|
|
165
|
+
const raw = tc?.arguments ?? tc?.function?.arguments;
|
|
166
|
+
const text = stableToolArgJson(raw);
|
|
167
|
+
return text ? truncateMiddle(text, maxChars) : '';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function summarizeToolCall(tc, maxArgChars = TOOL_CALL_ARGS_MAX_CHARS) {
|
|
171
|
+
const name = tc?.name || tc?.function?.name || tc?.id || '?';
|
|
172
|
+
const args = toolCallArgsText(tc, maxArgChars);
|
|
173
|
+
return args ? `${name}(${args})` : name;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function toolCallArgBudget(perMessageChars) {
|
|
177
|
+
const chars = Number(perMessageChars);
|
|
178
|
+
if (!Number.isFinite(chars) || chars <= 0) return 0;
|
|
179
|
+
return Math.min(TOOL_CALL_ARGS_MAX_CHARS, Math.max(32, Math.floor(chars * 0.5)));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function toolCallSummary(m, maxArgChars = TOOL_CALL_ARGS_MAX_CHARS) {
|
|
183
|
+
if (!Array.isArray(m?.toolCalls) || m.toolCalls.length === 0) return '';
|
|
184
|
+
const calls = m.toolCalls
|
|
185
|
+
.slice(0, TOOL_CALLS_MAX)
|
|
186
|
+
.map(tc => summarizeToolCall(tc, maxArgChars));
|
|
187
|
+
if (m.toolCalls.length > TOOL_CALLS_MAX) calls.push(`+${m.toolCalls.length - TOOL_CALLS_MAX} more`);
|
|
188
|
+
return ` tool_calls=${calls.join(';')}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function toolResultId(m) {
|
|
192
|
+
return m?.role === 'tool' && m.toolCallId ? ` tool_result=${m.toolCallId}` : '';
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function safeEstimateMessagesTokens(messages) {
|
|
196
|
+
try { return estimateMessagesTokens(messages); }
|
|
197
|
+
catch { return null; }
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function textByteLength(text) {
|
|
201
|
+
try { return Buffer.byteLength(String(text || ''), 'utf8'); }
|
|
202
|
+
catch { return String(text || '').length; }
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function messageContentHasMarker(m, marker) {
|
|
206
|
+
if (!m || !marker) return false;
|
|
207
|
+
if (typeof m.content === 'string') return m.content.includes(marker);
|
|
208
|
+
if (Array.isArray(m.content)) {
|
|
209
|
+
return m.content.some((part) => {
|
|
210
|
+
if (!part || typeof part !== 'object') return false;
|
|
211
|
+
return String(part.text || part.content || '').includes(marker);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// --- Verbatim redaction for messages kept through compaction ---------------
|
|
218
|
+
|
|
219
|
+
// Redaction-ONLY recursive walk for tool-call argument VALUES kept verbatim
|
|
220
|
+
// through compaction. Unlike normalizeToolArgValue (which is for prompt-side
|
|
221
|
+
// summaries and truncates/summarizes/key-sorts), this preserves shape exactly:
|
|
222
|
+
// - sensitive KEY -> '[redacted]'
|
|
223
|
+
// - string value -> redactRawSecretString(value) (no truncation/middle-cut)
|
|
224
|
+
// - array -> same length, items walked in order (no slicing/caps)
|
|
225
|
+
// - object -> same keys in INSERTION order (no sorting/depth caps)
|
|
226
|
+
// - other primitive (number/boolean/bigint/null) -> returned unchanged
|
|
227
|
+
// Returns { value, changed } so callers can preserve byte-exact input when the
|
|
228
|
+
// walk altered nothing. Only sensitive-key values and embedded raw secret pairs
|
|
229
|
+
// inside strings are altered; everything else is structure identical.
|
|
230
|
+
function redactToolArgValueOnly(value, key = '') {
|
|
231
|
+
if (isSensitiveToolArgKey(key)) {
|
|
232
|
+
return { value: '[redacted]', changed: value !== '[redacted]' };
|
|
233
|
+
}
|
|
234
|
+
if (value == null) return { value, changed: false };
|
|
235
|
+
if (typeof value === 'string') {
|
|
236
|
+
const redacted = redactRawSecretString(value);
|
|
237
|
+
return { value: redacted, changed: redacted !== value };
|
|
238
|
+
}
|
|
239
|
+
if (Array.isArray(value)) {
|
|
240
|
+
let changed = false;
|
|
241
|
+
const out = value.map((item) => {
|
|
242
|
+
const r = redactToolArgValueOnly(item, '');
|
|
243
|
+
if (r.changed) changed = true;
|
|
244
|
+
return r.value;
|
|
245
|
+
});
|
|
246
|
+
return { value: changed ? out : value, changed };
|
|
247
|
+
}
|
|
248
|
+
if (typeof value === 'object') {
|
|
249
|
+
let changed = false;
|
|
250
|
+
const out = {};
|
|
251
|
+
for (const k of Object.keys(value)) {
|
|
252
|
+
const r = redactToolArgValueOnly(value[k], k);
|
|
253
|
+
if (r.changed) changed = true;
|
|
254
|
+
out[k] = r.value;
|
|
255
|
+
}
|
|
256
|
+
return { value: changed ? out : value, changed };
|
|
257
|
+
}
|
|
258
|
+
return { value, changed: false };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Redact sensitive values inside a single tool-call arguments payload while
|
|
262
|
+
// preserving its original shape (string stays a string, object stays an
|
|
263
|
+
// object) so the provider-valid tool_call structure is not broken. Used to
|
|
264
|
+
// scrub messages that survive compaction VERBATIM (preserved tail / mandatory
|
|
265
|
+
// context), where prompt-side redaction does not apply. Redaction-only — no
|
|
266
|
+
// truncation, summarization, key sorting, or depth/array caps.
|
|
267
|
+
function redactToolCallArgumentsValue(rawArgs) {
|
|
268
|
+
if (rawArgs == null) return rawArgs;
|
|
269
|
+
if (typeof rawArgs === 'string') {
|
|
270
|
+
const trimmed = rawArgs.trim();
|
|
271
|
+
if (/^[\[{]/.test(trimmed)) {
|
|
272
|
+
try {
|
|
273
|
+
// Parse, redaction-only walk; only reserialize when the walk
|
|
274
|
+
// actually changed a sensitive value. When nothing changed,
|
|
275
|
+
// return the ORIGINAL string byte-exact (no JSON re-formatting).
|
|
276
|
+
const { value, changed } = redactToolArgValueOnly(JSON.parse(trimmed));
|
|
277
|
+
return changed ? JSON.stringify(value) : rawArgs;
|
|
278
|
+
} catch { /* fall through to raw redaction */ }
|
|
279
|
+
}
|
|
280
|
+
return redactRawSecretString(rawArgs);
|
|
281
|
+
}
|
|
282
|
+
if (typeof rawArgs === 'object') {
|
|
283
|
+
try {
|
|
284
|
+
const { value, changed } = redactToolArgValueOnly(rawArgs);
|
|
285
|
+
return changed ? value : rawArgs;
|
|
286
|
+
} catch { return rawArgs; }
|
|
287
|
+
}
|
|
288
|
+
return rawArgs;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Return a copy of a message with sensitive tool-call argument values redacted,
|
|
292
|
+
// keeping role / content / toolCallId / tool names+ids and non-sensitive args
|
|
293
|
+
// intact. Non-tool-bearing messages are returned unchanged (same reference).
|
|
294
|
+
function redactMessageToolCallSecrets(m) {
|
|
295
|
+
if (!m || typeof m !== 'object' || !Array.isArray(m.toolCalls) || m.toolCalls.length === 0) {
|
|
296
|
+
return m;
|
|
297
|
+
}
|
|
298
|
+
let changed = false;
|
|
299
|
+
const toolCalls = m.toolCalls.map((tc) => {
|
|
300
|
+
if (!tc || typeof tc !== 'object') return tc;
|
|
301
|
+
const out = { ...tc };
|
|
302
|
+
if ('arguments' in tc && tc.arguments != null) {
|
|
303
|
+
const redacted = redactToolCallArgumentsValue(tc.arguments);
|
|
304
|
+
if (redacted !== tc.arguments) { out.arguments = redacted; changed = true; }
|
|
305
|
+
}
|
|
306
|
+
if (tc.function && typeof tc.function === 'object' && tc.function.arguments != null) {
|
|
307
|
+
const redacted = redactToolCallArgumentsValue(tc.function.arguments);
|
|
308
|
+
if (redacted !== tc.function.arguments) {
|
|
309
|
+
out.function = { ...tc.function, arguments: redacted };
|
|
310
|
+
changed = true;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return out;
|
|
314
|
+
});
|
|
315
|
+
if (!changed) return m;
|
|
316
|
+
return { ...m, toolCalls };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Scrub an array of messages that are kept verbatim through compaction so a
|
|
320
|
+
// recent assistant tool call carrying a secret (e.g. `authorization: Bearer
|
|
321
|
+
// ...`) cannot survive into the returned compacted transcript. Only assistant
|
|
322
|
+
// toolCalls argument VALUES are touched; structure/order/pairing is preserved.
|
|
323
|
+
export function redactToolCallSecretsInMessages(messages) {
|
|
324
|
+
if (!Array.isArray(messages)) return messages;
|
|
325
|
+
return messages.map((m) => redactMessageToolCallSecrets(m));
|
|
326
|
+
}
|