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,111 @@
|
|
|
1
|
+
// Provider-model version parsing, recency comparison, sorting, and cache-row
|
|
2
|
+
// construction. Extracted from mixdog-session-runtime.mjs. Pure except for the
|
|
3
|
+
// injected route provider (for sort priority) and searchCapableFor predicate.
|
|
4
|
+
import { clean } from './session-text.mjs';
|
|
5
|
+
|
|
6
|
+
export function parsedProviderModelVersion(id) {
|
|
7
|
+
const text = clean(id).toLowerCase();
|
|
8
|
+
const claude = text.match(/^claude-[a-z]+-(\d+)(?:[-.](\d+))?/);
|
|
9
|
+
if (claude) return [Number(claude[1]) || 0, Number(claude[2]) || 0];
|
|
10
|
+
const compact = text.match(/(?:^|[-_])(?:o|gpt|grok|qwen|llama|mistral|gemma|phi|glm)(\d+)(?:\.(\d+))?(?:\.(\d{1,3}))?/);
|
|
11
|
+
if (compact) return compact.slice(1).filter((v) => v != null).map((v) => Number(v) || 0);
|
|
12
|
+
const generic = text.match(/(?:^|[-_v])(\d+)(?:\.(\d+))?(?:\.(\d{1,3}))?/);
|
|
13
|
+
return generic ? generic.slice(1).filter((v) => v != null).map((v) => Number(v) || 0) : [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function compareProviderModelVersion(a, b) {
|
|
17
|
+
const va = parsedProviderModelVersion(a.id || a.display || a.name);
|
|
18
|
+
const vb = parsedProviderModelVersion(b.id || b.display || b.name);
|
|
19
|
+
if (va.length === 0 && vb.length === 0) return 0;
|
|
20
|
+
if (va.length === 0) return 1;
|
|
21
|
+
if (vb.length === 0) return -1;
|
|
22
|
+
for (let i = 0; i < Math.max(va.length, vb.length); i += 1) {
|
|
23
|
+
const delta = (vb[i] || 0) - (va[i] || 0);
|
|
24
|
+
if (delta) return delta;
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function providerModelReleaseTime(model) {
|
|
30
|
+
if (model?.releaseDate) {
|
|
31
|
+
const t = Date.parse(model.releaseDate);
|
|
32
|
+
if (Number.isFinite(t)) return t;
|
|
33
|
+
}
|
|
34
|
+
const created = Number(model?.created);
|
|
35
|
+
if (Number.isFinite(created) && created > 0) {
|
|
36
|
+
return created < 1_000_000_000_000 ? created * 1000 : created;
|
|
37
|
+
}
|
|
38
|
+
const dated = clean(model?.id).match(/(?:^|-)(\d{4})(\d{2})(\d{2})(?:$|-)/);
|
|
39
|
+
return dated ? (Date.parse(`${dated[1]}-${dated[2]}-${dated[3]}`) || 0) : 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function isClaudeProviderModel(model) {
|
|
43
|
+
return clean(model?.provider).toLowerCase().includes('anthropic')
|
|
44
|
+
&& /^claude-[a-z]+-/.test(clean(model?.id).toLowerCase());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function compareProviderModelRecency(a, b) {
|
|
48
|
+
if (isClaudeProviderModel(a) && isClaudeProviderModel(b)) {
|
|
49
|
+
if (a.latest !== b.latest) return a.latest ? -1 : 1;
|
|
50
|
+
const versionDelta = compareProviderModelVersion(a, b);
|
|
51
|
+
if (versionDelta) return versionDelta;
|
|
52
|
+
const ta = providerModelReleaseTime(a);
|
|
53
|
+
const tb = providerModelReleaseTime(b);
|
|
54
|
+
if (ta !== tb) return tb - ta;
|
|
55
|
+
return clean(a.display || a.id).localeCompare(clean(b.display || b.id));
|
|
56
|
+
}
|
|
57
|
+
const ta = providerModelReleaseTime(a);
|
|
58
|
+
const tb = providerModelReleaseTime(b);
|
|
59
|
+
if (ta !== tb) return tb - ta;
|
|
60
|
+
if (a.latest !== b.latest) return a.latest ? -1 : 1;
|
|
61
|
+
const versionDelta = compareProviderModelVersion(a, b);
|
|
62
|
+
if (versionDelta) return versionDelta;
|
|
63
|
+
return clean(a.display || a.id).localeCompare(clean(b.display || b.id));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function sortProviderModels(models, primaryProvider = '') {
|
|
67
|
+
return (models || []).sort((a, b) => {
|
|
68
|
+
const ar = a.provider === primaryProvider ? 0 : 1;
|
|
69
|
+
const br = b.provider === primaryProvider ? 0 : 1;
|
|
70
|
+
if (ar !== br) return ar - br;
|
|
71
|
+
if (a.provider !== b.provider) return a.provider.localeCompare(b.provider);
|
|
72
|
+
return compareProviderModelRecency(a, b);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function isSelectableLlmModel(model) {
|
|
77
|
+
const id = clean(model?.id).toLowerCase();
|
|
78
|
+
const display = clean(model?.display || model?.name).toLowerCase();
|
|
79
|
+
const mode = clean(model?.mode).toLowerCase();
|
|
80
|
+
const text = `${id} ${display}`;
|
|
81
|
+
if (!id) return false;
|
|
82
|
+
if (mode && !['chat', 'completion', 'responses', 'messages'].includes(mode)) return false;
|
|
83
|
+
if (/(^|[-_\s])(image|images|video|videos|audio|tts|stt|speech|embed|embedding|embeddings|rerank|reranker|realtime|moderation|imagine)([-_\s]|$)/i.test(text)) return false;
|
|
84
|
+
if (/(^|[-_\s])(dall[-_\s]?e|sora|imagen)([-_\s]|$)/i.test(text)) return false;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function providerModelCacheRow(name, m, searchCapableFor) {
|
|
89
|
+
return {
|
|
90
|
+
id: m.id,
|
|
91
|
+
provider: name,
|
|
92
|
+
display: m.display || m.name || m.id,
|
|
93
|
+
created: typeof m.created === 'number' ? m.created : null,
|
|
94
|
+
releaseDate: m.releaseDate || null,
|
|
95
|
+
contextWindow: m.contextWindow,
|
|
96
|
+
outputTokens: m.outputTokens || null,
|
|
97
|
+
family: m.family || null,
|
|
98
|
+
tier: m.tier || null,
|
|
99
|
+
latest: m.latest === true,
|
|
100
|
+
description: m.description || '',
|
|
101
|
+
supportsVision: m.supportsVision === true,
|
|
102
|
+
supportsFunctionCalling: m.supportsFunctionCalling === true,
|
|
103
|
+
supportsWebSearch: searchCapableFor(name, m),
|
|
104
|
+
supportsPromptCaching: m.supportsPromptCaching === true,
|
|
105
|
+
supportsReasoning: m.supportsReasoning === true,
|
|
106
|
+
reasoningLevels: Array.isArray(m.reasoningLevels) ? m.reasoningLevels : undefined,
|
|
107
|
+
reasoningOptions: Array.isArray(m.reasoningOptions) ? m.reasoningOptions : [],
|
|
108
|
+
reasoningContentField: m.reasoningContentField || null,
|
|
109
|
+
mode: m.mode || null,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// Native (provider-hosted) web-search runtime, extracted from
|
|
2
|
+
// mixdog-session-runtime.mjs. Dependency-injected factory pattern: closes over
|
|
3
|
+
// route/searchRoute/config/reg/session accessors supplied by the facade.
|
|
4
|
+
import { clean } from './session-text.mjs';
|
|
5
|
+
|
|
6
|
+
export function createNativeSearch({
|
|
7
|
+
getRoute,
|
|
8
|
+
getSearchRoute,
|
|
9
|
+
setSearchRoute,
|
|
10
|
+
getConfig,
|
|
11
|
+
getSession,
|
|
12
|
+
getReg,
|
|
13
|
+
ensureFullConfig,
|
|
14
|
+
ensureProvidersReady,
|
|
15
|
+
ensureProviderEnabled,
|
|
16
|
+
normalizeSearchProviderId,
|
|
17
|
+
normalizeSearchRouteConfig,
|
|
18
|
+
isDefaultSearchRouteConfig,
|
|
19
|
+
isSearchCapableProvider,
|
|
20
|
+
searchCapableFor,
|
|
21
|
+
}) {
|
|
22
|
+
function normalizeSearchAllowedDomain(site) {
|
|
23
|
+
const raw = clean(site);
|
|
24
|
+
if (!raw) return '';
|
|
25
|
+
try {
|
|
26
|
+
return new URL(/^https?:\/\//i.test(raw) ? raw : `https://${raw}`).hostname.toLowerCase();
|
|
27
|
+
} catch {
|
|
28
|
+
return raw.replace(/^https?:\/\//i, '').split('/')[0].toLowerCase();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function nativeSearchUserLocation(locale) {
|
|
33
|
+
if (!locale || typeof locale !== 'object' || Array.isArray(locale)) return null;
|
|
34
|
+
const location = { type: 'approximate' };
|
|
35
|
+
for (const key of ['country', 'region', 'city', 'timezone']) {
|
|
36
|
+
const value = clean(locale[key]);
|
|
37
|
+
if (value) location[key] = value;
|
|
38
|
+
}
|
|
39
|
+
return Object.keys(location).length > 1 ? location : null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function nativeSearchTool(args = {}, toolType = 'web_search', providerId = '') {
|
|
43
|
+
const providerName = normalizeSearchProviderId(providerId);
|
|
44
|
+
const domain = normalizeSearchAllowedDomain(args.site);
|
|
45
|
+
const type = clean(toolType) || 'web_search';
|
|
46
|
+
const location = nativeSearchUserLocation(args.locale);
|
|
47
|
+
if (providerName === 'gemini') {
|
|
48
|
+
return { type: type || 'google_search' };
|
|
49
|
+
}
|
|
50
|
+
if (providerName === 'anthropic' || providerName === 'anthropic-oauth') {
|
|
51
|
+
const tool = {
|
|
52
|
+
type: 'web_search_20250305',
|
|
53
|
+
name: 'web_search',
|
|
54
|
+
max_uses: Math.max(1, Math.min(10, Number(args.maxResults) || 5)),
|
|
55
|
+
};
|
|
56
|
+
if (domain) tool.allowed_domains = [domain];
|
|
57
|
+
if (location) tool.user_location = location;
|
|
58
|
+
return tool;
|
|
59
|
+
}
|
|
60
|
+
if (providerName === 'grok-oauth' || providerName === 'xai') {
|
|
61
|
+
const tool = { type };
|
|
62
|
+
if (domain) tool.filters = { allowed_domains: [domain] };
|
|
63
|
+
return tool;
|
|
64
|
+
}
|
|
65
|
+
const tool = {
|
|
66
|
+
type,
|
|
67
|
+
};
|
|
68
|
+
if (type === 'web_search') {
|
|
69
|
+
tool.search_context_size = clean(args.contextSize) || 'low';
|
|
70
|
+
if (domain) tool.filters = { allowed_domains: [domain] };
|
|
71
|
+
if (location) tool.user_location = location;
|
|
72
|
+
}
|
|
73
|
+
return tool;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function nativeSearchToolTypes(routeLike = {}) {
|
|
77
|
+
const envToolType = clean(process.env.MIXDOG_NATIVE_SEARCH_TOOL_TYPE);
|
|
78
|
+
if (envToolType) return [envToolType];
|
|
79
|
+
const configured = clean(routeLike.toolType);
|
|
80
|
+
if (configured) return [configured];
|
|
81
|
+
const providerName = normalizeSearchProviderId(routeLike.provider);
|
|
82
|
+
if (providerName === 'gemini') return ['google_search'];
|
|
83
|
+
if (providerName === 'anthropic' || providerName === 'anthropic-oauth') return ['web_search'];
|
|
84
|
+
if (providerName === 'grok-oauth' || providerName === 'xai') return ['web_search'];
|
|
85
|
+
return ['web_search', 'web_search_preview'];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function currentMainSearchModelMeta() {
|
|
89
|
+
const route = getRoute();
|
|
90
|
+
if (!route?.provider || !route?.model) return null;
|
|
91
|
+
return { ...route, id: route.model, display: route.model, name: route.model };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function nativeSearchRoutes() {
|
|
95
|
+
const route = getRoute();
|
|
96
|
+
const cfg = ensureFullConfig();
|
|
97
|
+
const searchRoute = normalizeSearchRouteConfig(cfg.searchRoute) || normalizeSearchRouteConfig(getSearchRoute());
|
|
98
|
+
setSearchRoute(searchRoute);
|
|
99
|
+
if (!searchRoute) return [];
|
|
100
|
+
if (isDefaultSearchRouteConfig(searchRoute)) {
|
|
101
|
+
const mainModel = currentMainSearchModelMeta();
|
|
102
|
+
if (!mainModel || !searchCapableFor(route.provider, mainModel)) return [];
|
|
103
|
+
return [{
|
|
104
|
+
key: `default\n${route.provider}\n${route.model}`,
|
|
105
|
+
provider: normalizeSearchProviderId(route.provider),
|
|
106
|
+
model: route.model,
|
|
107
|
+
source: 'default-search-route',
|
|
108
|
+
effort: route.effectiveEffort || route.effort || null,
|
|
109
|
+
fast: route.fast === true,
|
|
110
|
+
toolType: searchRoute.toolType || null,
|
|
111
|
+
}];
|
|
112
|
+
}
|
|
113
|
+
const providerName = normalizeSearchProviderId(searchRoute.provider);
|
|
114
|
+
if (!isSearchCapableProvider(providerName)) return [];
|
|
115
|
+
return [{
|
|
116
|
+
key: `${providerName}\n${searchRoute.model}`,
|
|
117
|
+
provider: providerName,
|
|
118
|
+
model: searchRoute.model,
|
|
119
|
+
source: 'search-route',
|
|
120
|
+
effort: searchRoute.effort || null,
|
|
121
|
+
fast: searchRoute.fast === true,
|
|
122
|
+
toolType: searchRoute.toolType || null,
|
|
123
|
+
}];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function nativeSearchMessages(searchArgs = {}) {
|
|
127
|
+
const prompt = searchArgs.prompt || '';
|
|
128
|
+
return [
|
|
129
|
+
{
|
|
130
|
+
role: 'system',
|
|
131
|
+
content: [
|
|
132
|
+
'You are Mixdog native web search.',
|
|
133
|
+
'Use the hosted web_search tool for current or external facts.',
|
|
134
|
+
'Answer concisely, cite source URLs, and do not request local tools or file edits.',
|
|
135
|
+
].join('\n'),
|
|
136
|
+
},
|
|
137
|
+
{ role: 'user', content: prompt },
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function flattenNativeSearchSources(result = {}) {
|
|
142
|
+
const out = [];
|
|
143
|
+
const add = (source, fallbackTitle = '') => {
|
|
144
|
+
if (!source || typeof source !== 'object') return;
|
|
145
|
+
const url = clean(source.url || source.uri || source.href || source.source_url);
|
|
146
|
+
if (!url) return;
|
|
147
|
+
out.push({
|
|
148
|
+
title: clean(source.title || source.query || source.name || fallbackTitle || url),
|
|
149
|
+
url,
|
|
150
|
+
snippet: clean(source.snippet || source.text || source.description),
|
|
151
|
+
source: source.source || 'native-web-search',
|
|
152
|
+
provider: source.provider || 'native-web-search',
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
for (const citation of Array.isArray(result.citations) ? result.citations : []) add(citation);
|
|
156
|
+
for (const call of Array.isArray(result.webSearchCalls) ? result.webSearchCalls : []) {
|
|
157
|
+
const action = call?.action || {};
|
|
158
|
+
for (const source of Array.isArray(action.sources) ? action.sources : []) add(source, action.query || '');
|
|
159
|
+
if (action.url) add({ url: action.url, title: action.query || '' });
|
|
160
|
+
for (const url of Array.isArray(action.urls) ? action.urls : []) add({ url, title: action.query || '' });
|
|
161
|
+
}
|
|
162
|
+
const seen = new Set();
|
|
163
|
+
return out.filter((item) => {
|
|
164
|
+
const key = item.url || `${item.title}\n${item.snippet}`;
|
|
165
|
+
if (!key || seen.has(key)) return false;
|
|
166
|
+
seen.add(key);
|
|
167
|
+
return true;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async function runNativeWebSearch(searchArgs = {}, { signal } = {}) {
|
|
172
|
+
const route = getRoute();
|
|
173
|
+
const session = getSession();
|
|
174
|
+
const reg = getReg();
|
|
175
|
+
const candidates = nativeSearchRoutes();
|
|
176
|
+
if (!candidates.length) {
|
|
177
|
+
if (isDefaultSearchRouteConfig(getSearchRoute())) {
|
|
178
|
+
throw new Error(`default search route requires the current main model to support native web search (${route?.provider || 'unknown'}/${route?.model || 'unknown'})`);
|
|
179
|
+
}
|
|
180
|
+
throw new Error('search route is not configured; open /search to choose a search provider/model');
|
|
181
|
+
}
|
|
182
|
+
const errors = [];
|
|
183
|
+
for (const candidate of candidates) {
|
|
184
|
+
for (const toolType of nativeSearchToolTypes(candidate)) {
|
|
185
|
+
try {
|
|
186
|
+
// Read config lazily: nativeSearchRoutes() above may have run
|
|
187
|
+
// ensureFullConfig() and replaced the facade config with the
|
|
188
|
+
// secret-bearing one — an early snapshot would miss those secrets.
|
|
189
|
+
await ensureProvidersReady(ensureProviderEnabled(getConfig(), candidate.provider));
|
|
190
|
+
const providerImpl = reg.getProvider(candidate.provider);
|
|
191
|
+
if (!providerImpl || typeof providerImpl.send !== 'function') {
|
|
192
|
+
throw new Error(`provider "${candidate.provider}" is not ready`);
|
|
193
|
+
}
|
|
194
|
+
const model = candidate.model;
|
|
195
|
+
const searchTool = nativeSearchTool(searchArgs, toolType, candidate.provider);
|
|
196
|
+
const startedAt = Date.now();
|
|
197
|
+
const result = await providerImpl.send(
|
|
198
|
+
nativeSearchMessages(searchArgs),
|
|
199
|
+
model,
|
|
200
|
+
undefined,
|
|
201
|
+
{
|
|
202
|
+
signal,
|
|
203
|
+
role: 'web-search',
|
|
204
|
+
sessionId: `${session?.id || 'search'}:native-search:${Date.now().toString(36)}`,
|
|
205
|
+
sourceType: 'native-search',
|
|
206
|
+
sourceName: 'search',
|
|
207
|
+
nativeTools: [searchTool],
|
|
208
|
+
nativeInclude: candidate.provider === 'openai' || candidate.provider === 'openai-oauth'
|
|
209
|
+
? ['web_search_call.action.sources']
|
|
210
|
+
: [],
|
|
211
|
+
toolChoice: candidate.provider === 'gemini' ? 'auto' : 'required',
|
|
212
|
+
...(candidate.effort ? { effort: candidate.effort } : {}),
|
|
213
|
+
fast: candidate.fast === true,
|
|
214
|
+
onStageChange: () => {},
|
|
215
|
+
onStreamDelta: () => {},
|
|
216
|
+
},
|
|
217
|
+
);
|
|
218
|
+
const sources = flattenNativeSearchSources(result);
|
|
219
|
+
return {
|
|
220
|
+
content: String(result?.content || '').trim(),
|
|
221
|
+
provider: candidate.provider,
|
|
222
|
+
model: result?.model || candidate.model || null,
|
|
223
|
+
usage: result?.usage || null,
|
|
224
|
+
citations: sources,
|
|
225
|
+
webSearchCalls: result?.webSearchCalls || [],
|
|
226
|
+
durationMs: Date.now() - startedAt,
|
|
227
|
+
};
|
|
228
|
+
} catch (err) {
|
|
229
|
+
errors.push(`${candidate.provider}${candidate.model ? `/${candidate.model}` : ''}/${toolType}: ${err?.message || String(err)}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
throw new Error(`native web search failed: ${errors.join(' | ')}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
normalizeSearchAllowedDomain,
|
|
238
|
+
nativeSearchUserLocation,
|
|
239
|
+
nativeSearchTool,
|
|
240
|
+
nativeSearchToolTypes,
|
|
241
|
+
currentMainSearchModelMeta,
|
|
242
|
+
nativeSearchRoutes,
|
|
243
|
+
nativeSearchMessages,
|
|
244
|
+
flattenNativeSearchSources,
|
|
245
|
+
runNativeWebSearch,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Output-style catalog + metadata parsing. Roots are injected so this module
|
|
2
|
+
// stays free of the runtime's path constants.
|
|
3
|
+
import { basename, join } from 'node:path';
|
|
4
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
5
|
+
import { clean } from './session-text.mjs';
|
|
6
|
+
import { readJsonSafe } from './fs-utils.mjs';
|
|
7
|
+
|
|
8
|
+
const OUTPUT_STYLE_ORDER = ['default', 'simple', 'minimal', 'extreme-minimal'];
|
|
9
|
+
const OUTPUT_STYLE_ALIASES = new Map([
|
|
10
|
+
['compact', 'default'],
|
|
11
|
+
['normal', 'default'],
|
|
12
|
+
['extreme', 'extreme-minimal'],
|
|
13
|
+
['extremesimple', 'extreme-minimal'],
|
|
14
|
+
['extreme-simple', 'extreme-minimal'],
|
|
15
|
+
['extreme_simple', 'extreme-minimal'],
|
|
16
|
+
['extrememinimal', 'extreme-minimal'],
|
|
17
|
+
['extreme_minimal', 'extreme-minimal'],
|
|
18
|
+
['mono', 'extreme-minimal'],
|
|
19
|
+
['oneline', 'extreme-minimal'],
|
|
20
|
+
['one-line', 'extreme-minimal'],
|
|
21
|
+
['one_line', 'extreme-minimal'],
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
export function normalizeOutputStyleId(value) {
|
|
25
|
+
const raw = clean(value).toLowerCase();
|
|
26
|
+
if (!raw) return '';
|
|
27
|
+
const slug = raw.replace(/[_\s]+/g, '-').replace(/^-+|-+$/g, '');
|
|
28
|
+
const compact = slug.replace(/[_.-]+/g, '');
|
|
29
|
+
if (OUTPUT_STYLE_ALIASES.has(slug)) return OUTPUT_STYLE_ALIASES.get(slug);
|
|
30
|
+
if (OUTPUT_STYLE_ALIASES.has(compact)) return OUTPUT_STYLE_ALIASES.get(compact);
|
|
31
|
+
return /^[a-z0-9.-]+$/.test(slug) ? slug : '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function outputStyleCompactKey(value) {
|
|
35
|
+
return normalizeOutputStyleId(value).replace(/[_.-]+/g, '');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function titleCaseOutputStyle(id) {
|
|
39
|
+
return clean(id)
|
|
40
|
+
.split(/[_.-]+/)
|
|
41
|
+
.filter(Boolean)
|
|
42
|
+
.map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
|
|
43
|
+
.join(' ') || 'Default';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function parseOutputStyleFrontmatter(markdown) {
|
|
47
|
+
const match = String(markdown || '').match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
48
|
+
const meta = {};
|
|
49
|
+
if (!match) return meta;
|
|
50
|
+
for (const line of match[1].split(/\r?\n/)) {
|
|
51
|
+
const kv = line.match(/^([A-Za-z0-9_-]+):\s*(.*?)\s*$/);
|
|
52
|
+
if (!kv) continue;
|
|
53
|
+
meta[kv[1]] = kv[2].replace(/^['"]|['"]$/g, '').trim();
|
|
54
|
+
}
|
|
55
|
+
return meta;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readOutputStyleMetadata(filePath, source) {
|
|
59
|
+
let raw = '';
|
|
60
|
+
try { raw = readFileSync(filePath, 'utf8'); } catch { return null; }
|
|
61
|
+
const meta = parseOutputStyleFrontmatter(raw);
|
|
62
|
+
const fileId = normalizeOutputStyleId(basename(filePath).replace(/\.md$/i, ''));
|
|
63
|
+
const id = normalizeOutputStyleId(meta.name) || fileId;
|
|
64
|
+
if (!id) return null;
|
|
65
|
+
const aliases = clean(meta.aliases)
|
|
66
|
+
.split(',')
|
|
67
|
+
.map((value) => normalizeOutputStyleId(value))
|
|
68
|
+
.filter(Boolean);
|
|
69
|
+
const label = clean(meta.title || meta.label) || titleCaseOutputStyle(id);
|
|
70
|
+
return {
|
|
71
|
+
id,
|
|
72
|
+
label,
|
|
73
|
+
description: clean(meta.description),
|
|
74
|
+
aliases,
|
|
75
|
+
source,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function listOutputStyleCatalog(rootDir, dataDir) {
|
|
80
|
+
const byId = new Map();
|
|
81
|
+
const dirs = [
|
|
82
|
+
{ dir: join(rootDir, 'output-styles'), source: 'builtin' },
|
|
83
|
+
{ dir: join(dataDir, 'output-styles'), source: 'user' },
|
|
84
|
+
];
|
|
85
|
+
for (const { dir, source } of dirs) {
|
|
86
|
+
let entries = [];
|
|
87
|
+
try { entries = readdirSync(dir, { withFileTypes: true }); } catch { continue; }
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md')) continue;
|
|
90
|
+
const style = readOutputStyleMetadata(join(dir, entry.name), source);
|
|
91
|
+
if (style) byId.set(style.id, style);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return [...byId.values()].sort((a, b) => {
|
|
95
|
+
const ai = OUTPUT_STYLE_ORDER.indexOf(a.id);
|
|
96
|
+
const bi = OUTPUT_STYLE_ORDER.indexOf(b.id);
|
|
97
|
+
if (ai !== bi) return (ai < 0 ? 999 : ai) - (bi < 0 ? 999 : bi);
|
|
98
|
+
return a.label.localeCompare(b.label, 'en', { sensitivity: 'base' });
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function findOutputStyle(value, styles) {
|
|
103
|
+
const id = normalizeOutputStyleId(value);
|
|
104
|
+
const compact = outputStyleCompactKey(value);
|
|
105
|
+
if (!id && !compact) return null;
|
|
106
|
+
return (styles || []).find((style) => {
|
|
107
|
+
if (style.id === id || outputStyleCompactKey(style.id) === compact) return true;
|
|
108
|
+
if (outputStyleCompactKey(style.label) === compact) return true;
|
|
109
|
+
return (style.aliases || []).some((alias) => alias === id || outputStyleCompactKey(alias) === compact);
|
|
110
|
+
}) || null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function configuredOutputStyleValue(dataDir) {
|
|
114
|
+
const unified = readJsonSafe(join(dataDir, 'mixdog-config.json')) || {};
|
|
115
|
+
return clean(unified.outputStyle || (unified.agent && unified.agent.outputStyle) || 'default') || 'default';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function outputStyleStatus(rootDir, dataDir) {
|
|
119
|
+
const styles = listOutputStyleCatalog(rootDir, dataDir);
|
|
120
|
+
const configured = configuredOutputStyleValue(dataDir);
|
|
121
|
+
const current = findOutputStyle(configured, styles)
|
|
122
|
+
|| findOutputStyle('default', styles)
|
|
123
|
+
|| styles[0]
|
|
124
|
+
|| { id: 'default', label: 'Default', description: '', aliases: [], source: 'builtin' };
|
|
125
|
+
return { configured, current, styles };
|
|
126
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Plugin/project MCP server discovery + normalization, and skill-file counting.
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
3
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
4
|
+
import { clean } from './session-text.mjs';
|
|
5
|
+
import { readJsonSafe } from './fs-utils.mjs';
|
|
6
|
+
|
|
7
|
+
// Project-local MCP ingress: read `.mcp.json` from the project root and return
|
|
8
|
+
// a cleaned { name: cfg } map. Best-effort — never throws. Accepts either the
|
|
9
|
+
// standard `{ mcpServers: {...} }` shape or a bare name->cfg map. Self-ref
|
|
10
|
+
// servers (`mixdog` / `trib-plugin`) are stripped for parity with loadConfig.
|
|
11
|
+
// Inputs are not mutated.
|
|
12
|
+
export function readProjectMcpServers(cwd) {
|
|
13
|
+
const path = join(cwd || '.', '.mcp.json');
|
|
14
|
+
if (!existsSync(path)) return {};
|
|
15
|
+
let raw;
|
|
16
|
+
try {
|
|
17
|
+
raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
18
|
+
} catch (error) {
|
|
19
|
+
process.stderr.write(`[mcp-client] Ignoring unparseable .mcp.json at ${path}: ${error?.message || String(error)}\n`);
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};
|
|
23
|
+
const map = raw.mcpServers && typeof raw.mcpServers === 'object' && !Array.isArray(raw.mcpServers)
|
|
24
|
+
? raw.mcpServers
|
|
25
|
+
: raw;
|
|
26
|
+
if (!map || typeof map !== 'object' || Array.isArray(map)) return {};
|
|
27
|
+
const out = {};
|
|
28
|
+
for (const [name, cfg] of Object.entries(map)) {
|
|
29
|
+
const key = clean(name);
|
|
30
|
+
if (!key) continue;
|
|
31
|
+
const lower = key.toLowerCase();
|
|
32
|
+
if (lower === 'mixdog' || lower === 'trib-plugin') continue;
|
|
33
|
+
if (!cfg || typeof cfg !== 'object' || Array.isArray(cfg)) continue;
|
|
34
|
+
// stdio entries (command + no url) spawn relative to the process launch
|
|
35
|
+
// dir, but mixdog tracks the project dir in memory (no process.chdir).
|
|
36
|
+
// Anchor their cwd to the .mcp.json directory: default when absent, resolve
|
|
37
|
+
// relative values against it, keep absolute values as-is.
|
|
38
|
+
const isStdio = typeof cfg.command === 'string' && cfg.command !== '' && !cfg.url;
|
|
39
|
+
if (isStdio) {
|
|
40
|
+
out[key] = { ...cfg, cwd: typeof cfg.cwd === 'string' && cfg.cwd ? resolve(cwd, cfg.cwd) : resolve(cwd) };
|
|
41
|
+
} else {
|
|
42
|
+
out[key] = cfg;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function countSkillFiles(root) {
|
|
49
|
+
const skillsDir = join(root, 'skills');
|
|
50
|
+
if (!existsSync(skillsDir)) return 0;
|
|
51
|
+
let count = 0;
|
|
52
|
+
const walk = (dir) => {
|
|
53
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
54
|
+
const full = join(dir, entry.name);
|
|
55
|
+
if (entry.isDirectory()) walk(full);
|
|
56
|
+
else if (/^(SKILL|skill)\.md$/i.test(entry.name) || entry.name.toLowerCase().endsWith('.md')) count += 1;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
try { walk(skillsDir); } catch { return count; }
|
|
60
|
+
return count;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function mcpScriptForPlugin(root) {
|
|
64
|
+
const candidates = [
|
|
65
|
+
'.mcp.json',
|
|
66
|
+
'scripts/run-mcp.mjs',
|
|
67
|
+
'mcp/server.mjs',
|
|
68
|
+
'server.mjs',
|
|
69
|
+
];
|
|
70
|
+
return candidates.find((rel) => existsSync(join(root, rel))) || null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function substitutePluginRootTokens(value, root) {
|
|
74
|
+
if (typeof value !== 'string') return value;
|
|
75
|
+
return value
|
|
76
|
+
.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, root)
|
|
77
|
+
.replace(/\$\{CODEX_PLUGIN_ROOT\}/g, root);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function substitutePluginRootTokensDeep(value, root) {
|
|
81
|
+
if (typeof value === 'string') return substitutePluginRootTokens(value, root);
|
|
82
|
+
if (Array.isArray(value)) return value.map((v) => substitutePluginRootTokensDeep(v, root));
|
|
83
|
+
if (value && typeof value === 'object') {
|
|
84
|
+
const out = {};
|
|
85
|
+
for (const [k, v] of Object.entries(value)) out[k] = substitutePluginRootTokensDeep(v, root);
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function normalizePluginMcpServerConfig(cfg, root) {
|
|
92
|
+
const substituted = substitutePluginRootTokensDeep(cfg, root) || {};
|
|
93
|
+
const out = { ...substituted };
|
|
94
|
+
if (typeof out.cwd === 'string' && out.cwd) {
|
|
95
|
+
out.cwd = isAbsolute(out.cwd) ? out.cwd : join(root, out.cwd);
|
|
96
|
+
} else {
|
|
97
|
+
out.cwd = root;
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function pluginManifest(root) {
|
|
103
|
+
return readJsonSafe(join(root, '.codex-plugin', 'plugin.json'))
|
|
104
|
+
|| readJsonSafe(join(root, 'plugin.json'))
|
|
105
|
+
|| {};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function pluginMcpServerName(plugin = {}) {
|
|
109
|
+
const base = clean(plugin.name || plugin.title || 'plugin')
|
|
110
|
+
.toLowerCase()
|
|
111
|
+
.replace(/[^a-z0-9_.-]+/g, '-')
|
|
112
|
+
.replace(/^-+|-+$/g, '');
|
|
113
|
+
return base ? `plugin-${base}` : 'plugin-mcp';
|
|
114
|
+
}
|