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,170 @@
|
|
|
1
|
+
// Quick (offline) provider/model picker row builders, extracted from
|
|
2
|
+
// mixdog-session-runtime.mjs. Dependency-injected factory: closes over
|
|
3
|
+
// route/config/search accessors and shared row helpers supplied by the facade.
|
|
4
|
+
import { clean } from './session-text.mjs';
|
|
5
|
+
import { QUICK_SEARCH_MODELS } from './quick-search-models.mjs';
|
|
6
|
+
import { SEARCH_DEFAULT_PROVIDER, SEARCH_DEFAULT_MODEL } from './workflow.mjs';
|
|
7
|
+
|
|
8
|
+
export function createQuickModelRows({
|
|
9
|
+
getRoute,
|
|
10
|
+
getSearchRoute,
|
|
11
|
+
displayConfig,
|
|
12
|
+
providerModelCacheRow,
|
|
13
|
+
providerModelsFromCacheRows,
|
|
14
|
+
sortProviderModels,
|
|
15
|
+
modelMetaByRoute,
|
|
16
|
+
modelMetaKey,
|
|
17
|
+
normalizeSearchProviderId,
|
|
18
|
+
normalizeSearchRouteConfig,
|
|
19
|
+
isSearchCapableProvider,
|
|
20
|
+
searchCapableFor,
|
|
21
|
+
currentMainSearchModelMeta,
|
|
22
|
+
}) {
|
|
23
|
+
function quickProviderModelRows() {
|
|
24
|
+
const route = getRoute();
|
|
25
|
+
const pickerConfig = displayConfig();
|
|
26
|
+
const rows = [];
|
|
27
|
+
const seen = new Set();
|
|
28
|
+
const addRoute = (routeLike = {}) => {
|
|
29
|
+
const provider = clean(routeLike.provider);
|
|
30
|
+
const model = clean(routeLike.model);
|
|
31
|
+
if (!provider || !model) return;
|
|
32
|
+
const key = `${provider}:${model}`;
|
|
33
|
+
if (seen.has(key)) return;
|
|
34
|
+
seen.add(key);
|
|
35
|
+
const row = providerModelCacheRow(provider, {
|
|
36
|
+
id: model,
|
|
37
|
+
name: routeLike.modelDisplay || routeLike.display || model,
|
|
38
|
+
display: routeLike.modelDisplay || routeLike.display || model,
|
|
39
|
+
latest: routeLike.latest === true,
|
|
40
|
+
supportsReasoning: !!routeLike.effort,
|
|
41
|
+
mode: 'chat',
|
|
42
|
+
});
|
|
43
|
+
rows.push(row);
|
|
44
|
+
modelMetaByRoute.set(modelMetaKey(provider, model), row);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
addRoute(route);
|
|
48
|
+
for (const preset of pickerConfig.presets || []) addRoute(preset);
|
|
49
|
+
for (const workflowRoute of Object.values(pickerConfig.workflowRoutes || {})) addRoute(workflowRoute);
|
|
50
|
+
for (const agentRoute of Object.values(pickerConfig.agents || {})) addRoute(agentRoute);
|
|
51
|
+
return providerModelsFromCacheRows(rows);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function addQuickSearchModel(rows, seen, provider, model) {
|
|
55
|
+
const providerName = normalizeSearchProviderId(provider);
|
|
56
|
+
const modelId = clean(model?.id || model);
|
|
57
|
+
if (!providerName || !modelId || !isSearchCapableProvider(providerName)) return;
|
|
58
|
+
const key = `${providerName}:${modelId}`;
|
|
59
|
+
if (seen.has(key)) return;
|
|
60
|
+
const row = providerModelCacheRow(providerName, {
|
|
61
|
+
id: modelId,
|
|
62
|
+
name: model?.name || model?.display || modelId,
|
|
63
|
+
display: model?.display || model?.name || modelId,
|
|
64
|
+
contextWindow: model?.contextWindow || null,
|
|
65
|
+
outputTokens: model?.outputTokens || null,
|
|
66
|
+
latest: model?.latest === true,
|
|
67
|
+
supportsWebSearch: true,
|
|
68
|
+
supportsFunctionCalling: model?.supportsFunctionCalling === true,
|
|
69
|
+
supportsPromptCaching: model?.supportsPromptCaching === true,
|
|
70
|
+
supportsReasoning: model?.supportsReasoning === true,
|
|
71
|
+
reasoningLevels: Array.isArray(model?.reasoningLevels) ? model.reasoningLevels : undefined,
|
|
72
|
+
reasoningOptions: Array.isArray(model?.reasoningOptions) ? model.reasoningOptions : [],
|
|
73
|
+
mode: 'chat',
|
|
74
|
+
});
|
|
75
|
+
if (row.supportsWebSearch !== true) return;
|
|
76
|
+
seen.add(key);
|
|
77
|
+
rows.push({
|
|
78
|
+
...row,
|
|
79
|
+
provider: providerName,
|
|
80
|
+
searchCapable: true,
|
|
81
|
+
searchToolType: row.searchToolType || 'web_search',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function addDefaultSearchModel(rows, seen = new Set()) {
|
|
86
|
+
const route = getRoute();
|
|
87
|
+
const mainModel = currentMainSearchModelMeta();
|
|
88
|
+
if (!mainModel || !searchCapableFor(route.provider, mainModel)) return;
|
|
89
|
+
const key = `${SEARCH_DEFAULT_PROVIDER}:${SEARCH_DEFAULT_MODEL}`;
|
|
90
|
+
if (seen.has(key)) return;
|
|
91
|
+
seen.add(key);
|
|
92
|
+
rows.push({
|
|
93
|
+
id: SEARCH_DEFAULT_MODEL,
|
|
94
|
+
provider: SEARCH_DEFAULT_PROVIDER,
|
|
95
|
+
display: 'Default',
|
|
96
|
+
name: 'Default',
|
|
97
|
+
description: `Use current main model: ${route.provider}/${route.model}`,
|
|
98
|
+
supportsWebSearch: true,
|
|
99
|
+
searchCapable: true,
|
|
100
|
+
searchToolType: 'web_search',
|
|
101
|
+
mode: 'chat',
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function quickSearchProviderModelRows() {
|
|
106
|
+
const route = getRoute();
|
|
107
|
+
const pickerConfig = displayConfig();
|
|
108
|
+
const rows = [];
|
|
109
|
+
const seen = new Set();
|
|
110
|
+
addDefaultSearchModel(rows, seen);
|
|
111
|
+
for (const [name, providerConfig] of Object.entries(pickerConfig.providers || {})) {
|
|
112
|
+
const providerName = normalizeSearchProviderId(name);
|
|
113
|
+
if (!providerConfig?.enabled || !isSearchCapableProvider(providerName)) continue;
|
|
114
|
+
for (const model of QUICK_SEARCH_MODELS[providerName] || []) {
|
|
115
|
+
addQuickSearchModel(rows, seen, providerName, model);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const configuredSearch = normalizeSearchRouteConfig(pickerConfig.searchRoute) || normalizeSearchRouteConfig(getSearchRoute());
|
|
119
|
+
if (configuredSearch?.provider && configuredSearch?.model) {
|
|
120
|
+
addQuickSearchModel(rows, seen, configuredSearch.provider, {
|
|
121
|
+
id: configuredSearch.model,
|
|
122
|
+
display: configuredSearch.model,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const mainModel = currentMainSearchModelMeta();
|
|
126
|
+
if (mainModel && searchCapableFor(route.provider, mainModel)) {
|
|
127
|
+
addQuickSearchModel(rows, seen, route.provider, {
|
|
128
|
+
id: route.model,
|
|
129
|
+
display: route.model,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return searchModelsFromRows(rows);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function searchModelsFromRows(rows) {
|
|
136
|
+
return sortProviderModels((rows || [])
|
|
137
|
+
.filter((row) => row.supportsWebSearch === true)
|
|
138
|
+
.map((row) => ({
|
|
139
|
+
...row,
|
|
140
|
+
provider: normalizeSearchProviderId(row.provider),
|
|
141
|
+
searchCapable: true,
|
|
142
|
+
searchToolType: row.searchToolType || 'web_search',
|
|
143
|
+
})));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function searchRowsWithDefault(rows = []) {
|
|
147
|
+
const out = [];
|
|
148
|
+
const seen = new Set();
|
|
149
|
+
addDefaultSearchModel(out, seen);
|
|
150
|
+
for (const row of rows || []) {
|
|
151
|
+
const providerName = normalizeSearchProviderId(row?.provider);
|
|
152
|
+
const modelId = clean(row?.id || row?.model);
|
|
153
|
+
if (providerName === SEARCH_DEFAULT_PROVIDER && modelId.toLowerCase() === SEARCH_DEFAULT_MODEL) continue;
|
|
154
|
+
const key = `${providerName}:${modelId}`;
|
|
155
|
+
if (!providerName || !modelId || seen.has(key)) continue;
|
|
156
|
+
seen.add(key);
|
|
157
|
+
out.push(row);
|
|
158
|
+
}
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
quickProviderModelRows,
|
|
164
|
+
addQuickSearchModel,
|
|
165
|
+
addDefaultSearchModel,
|
|
166
|
+
quickSearchProviderModelRows,
|
|
167
|
+
searchModelsFromRows,
|
|
168
|
+
searchRowsWithDefault,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Static quick-pick model catalog surfaced during onboarding / search setup.
|
|
2
|
+
// Pure data extracted from mixdog-session-runtime.mjs.
|
|
3
|
+
|
|
4
|
+
export const ONBOARDING_VERSION = 1;
|
|
5
|
+
|
|
6
|
+
export const QUICK_SEARCH_MODELS = Object.freeze({
|
|
7
|
+
'openai-oauth': [
|
|
8
|
+
{ id: 'gpt-5.5', display: 'GPT-5.5', latest: true, contextWindow: 1000000 },
|
|
9
|
+
{ id: 'gpt-5.4', display: 'GPT-5.4', latest: true, contextWindow: 1000000 },
|
|
10
|
+
{ id: 'gpt-5', display: 'GPT-5', contextWindow: 400000 },
|
|
11
|
+
{ id: 'gpt-4.1', display: 'GPT-4.1', contextWindow: 1000000 },
|
|
12
|
+
],
|
|
13
|
+
openai: [
|
|
14
|
+
{ id: 'gpt-5.5', display: 'GPT-5.5', latest: true, contextWindow: 1000000 },
|
|
15
|
+
{ id: 'gpt-5.4', display: 'GPT-5.4', latest: true, contextWindow: 1000000 },
|
|
16
|
+
{ id: 'gpt-5', display: 'GPT-5', contextWindow: 400000 },
|
|
17
|
+
{ id: 'gpt-4.1', display: 'GPT-4.1', contextWindow: 1000000 },
|
|
18
|
+
{ id: 'gpt-4o', display: 'GPT-4o', contextWindow: 128000 },
|
|
19
|
+
],
|
|
20
|
+
'grok-oauth': [
|
|
21
|
+
{ id: 'grok-4.3', display: 'Grok 4.3', latest: true, contextWindow: 1000000 },
|
|
22
|
+
{ id: 'grok-4.20', display: 'Grok 4.20', contextWindow: 1000000 },
|
|
23
|
+
{ id: 'grok-4', display: 'Grok 4', contextWindow: 256000 },
|
|
24
|
+
],
|
|
25
|
+
xai: [
|
|
26
|
+
{ id: 'grok-4.3', display: 'Grok 4.3', latest: true, contextWindow: 1000000 },
|
|
27
|
+
{ id: 'grok-4.20', display: 'Grok 4.20', contextWindow: 1000000 },
|
|
28
|
+
{ id: 'grok-4', display: 'Grok 4', contextWindow: 256000 },
|
|
29
|
+
],
|
|
30
|
+
gemini: [
|
|
31
|
+
{ id: 'gemini-3-pro', display: 'Gemini 3 Pro', latest: true, contextWindow: 1000000 },
|
|
32
|
+
{ id: 'gemini-2.5-pro', display: 'Gemini 2.5 Pro', contextWindow: 1000000 },
|
|
33
|
+
{ id: 'gemini-2.5-flash', display: 'Gemini 2.5 Flash', contextWindow: 1000000 },
|
|
34
|
+
{ id: 'gemini-2.0-flash', display: 'Gemini 2.0 Flash', contextWindow: 1000000 },
|
|
35
|
+
],
|
|
36
|
+
'anthropic-oauth': [
|
|
37
|
+
{ id: 'claude-opus-4-8', display: 'Claude Opus 4.8', latest: true, contextWindow: 1000000 },
|
|
38
|
+
{ id: 'claude-sonnet-4-6', display: 'Claude Sonnet 4.6', latest: true, contextWindow: 1000000 },
|
|
39
|
+
{ id: 'claude-haiku-4-5-20251001', display: 'Claude Haiku 4.5', contextWindow: 200000 },
|
|
40
|
+
],
|
|
41
|
+
anthropic: [
|
|
42
|
+
{ id: 'claude-opus-4-8', display: 'Claude Opus 4.8', latest: true, contextWindow: 1000000 },
|
|
43
|
+
{ id: 'claude-sonnet-4-6', display: 'Claude Sonnet 4.6', latest: true, contextWindow: 1000000 },
|
|
44
|
+
{ id: 'claude-haiku-4-5-20251001', display: 'Claude Haiku 4.5', contextWindow: 200000 },
|
|
45
|
+
],
|
|
46
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// session-hooks.mjs — attaches the standard hook-bus bridge properties
|
|
2
|
+
// (beforeToolHook / afterToolHook / afterToolFailureHook / afterToolBatchHook /
|
|
3
|
+
// preCompactHook / postCompactHook) onto a freshly created session object.
|
|
4
|
+
// Extracted from mixdog-session-runtime.mjs createCurrentSession(): a
|
|
5
|
+
// self-contained cluster whose only couplings are the hooks bus and the
|
|
6
|
+
// facade's hookCommonPayload / currentCwd accessor + the session itself. All
|
|
7
|
+
// properties are non-enumerable/configurable/writable exactly as before so the
|
|
8
|
+
// loop/manager can read them by name without changing session enumeration.
|
|
9
|
+
|
|
10
|
+
export function attachSessionHooks(session, { hooks, hookCommonPayload, getCwd }) {
|
|
11
|
+
const currentCwd = () => getCwd();
|
|
12
|
+
// PreToolUse bridge.
|
|
13
|
+
Object.defineProperty(session, 'beforeToolHook', {
|
|
14
|
+
value: (input) => hooks.beforeTool(hookCommonPayload({
|
|
15
|
+
...input,
|
|
16
|
+
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
17
|
+
tool_name: input?.name || input?.tool_name,
|
|
18
|
+
tool_input: input?.args || input?.tool_input,
|
|
19
|
+
tool_use_id: input?.toolCallId || input?.tool_use_id,
|
|
20
|
+
cwd: input?.cwd || currentCwd(),
|
|
21
|
+
})),
|
|
22
|
+
enumerable: false,
|
|
23
|
+
configurable: true,
|
|
24
|
+
writable: true,
|
|
25
|
+
});
|
|
26
|
+
// PostToolUse: bridge runtime tool completions to the standard hook bus.
|
|
27
|
+
// dispatch() returns a promise; the loop's afterToolHook caller already
|
|
28
|
+
// try/catches, so a rejection cannot escape the tool loop.
|
|
29
|
+
Object.defineProperty(session, 'afterToolHook', {
|
|
30
|
+
value: (input) => hooks.dispatch('PostToolUse', hookCommonPayload({
|
|
31
|
+
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
32
|
+
cwd: input?.cwd || currentCwd(),
|
|
33
|
+
tool_name: input?.name,
|
|
34
|
+
tool_input: input?.args,
|
|
35
|
+
tool_use_id: input?.toolCallId || input?.tool_use_id,
|
|
36
|
+
tool_response: input?.result,
|
|
37
|
+
})),
|
|
38
|
+
enumerable: false,
|
|
39
|
+
configurable: true,
|
|
40
|
+
writable: true,
|
|
41
|
+
});
|
|
42
|
+
// PostToolUseFailure: dispatched by loop.mjs only when a tool execution
|
|
43
|
+
// resolved to a failure (thrown-error path or an is_error result). Same
|
|
44
|
+
// shape as afterToolHook; `result` carries the error text. Best-effort.
|
|
45
|
+
Object.defineProperty(session, 'afterToolFailureHook', {
|
|
46
|
+
value: (input) => hooks.dispatch('PostToolUseFailure', hookCommonPayload({
|
|
47
|
+
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
48
|
+
cwd: input?.cwd || currentCwd(),
|
|
49
|
+
tool_name: input?.name,
|
|
50
|
+
tool_input: input?.args,
|
|
51
|
+
tool_use_id: input?.toolCallId || input?.tool_use_id,
|
|
52
|
+
tool_response: input?.result,
|
|
53
|
+
})),
|
|
54
|
+
enumerable: false,
|
|
55
|
+
configurable: true,
|
|
56
|
+
writable: true,
|
|
57
|
+
});
|
|
58
|
+
// PostToolBatch: dispatched by loop.mjs after a full parallel batch of
|
|
59
|
+
// tool calls resolves and before the next model call. No matcher event.
|
|
60
|
+
Object.defineProperty(session, 'afterToolBatchHook', {
|
|
61
|
+
value: (input) => hooks.dispatch('PostToolBatch', hookCommonPayload({
|
|
62
|
+
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
63
|
+
cwd: input?.cwd || currentCwd(),
|
|
64
|
+
})),
|
|
65
|
+
enumerable: false,
|
|
66
|
+
configurable: true,
|
|
67
|
+
writable: true,
|
|
68
|
+
});
|
|
69
|
+
// PreCompact / PostCompact: dispatched by manager.mjs/loop.mjs compaction
|
|
70
|
+
// flow via these session-property hooks (manager has no hooks bus access).
|
|
71
|
+
// payload { trigger: 'auto' | 'manual' }. Best-effort.
|
|
72
|
+
Object.defineProperty(session, 'preCompactHook', {
|
|
73
|
+
value: (input) => hooks.dispatch('PreCompact', hookCommonPayload({
|
|
74
|
+
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
75
|
+
cwd: input?.cwd || currentCwd(),
|
|
76
|
+
trigger: input?.trigger || 'auto',
|
|
77
|
+
})),
|
|
78
|
+
enumerable: false,
|
|
79
|
+
configurable: true,
|
|
80
|
+
writable: true,
|
|
81
|
+
});
|
|
82
|
+
Object.defineProperty(session, 'postCompactHook', {
|
|
83
|
+
value: (input) => hooks.dispatch('PostCompact', hookCommonPayload({
|
|
84
|
+
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
85
|
+
cwd: input?.cwd || currentCwd(),
|
|
86
|
+
trigger: input?.trigger || 'auto',
|
|
87
|
+
})),
|
|
88
|
+
enumerable: false,
|
|
89
|
+
configurable: true,
|
|
90
|
+
writable: true,
|
|
91
|
+
});
|
|
92
|
+
return session;
|
|
93
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
// settings-api.mjs — pure settings delegate methods extracted from the main
|
|
2
|
+
// runtime API object in mixdog-session-runtime.mjs. These are the small
|
|
3
|
+
// config/settings members with NO heavy closure deps beyond the injected
|
|
4
|
+
// helpers; the returned object is SPREAD into the facade's API object so the
|
|
5
|
+
// external surface stays byte-identical. Methods that reference `this.*`
|
|
6
|
+
// resolve against the spread target, so cross-member calls (e.g.
|
|
7
|
+
// setProfile -> this.getProfile) keep working when spread into the facade.
|
|
8
|
+
|
|
9
|
+
export function createSettingsApi({
|
|
10
|
+
// config accessors / mutable state
|
|
11
|
+
getConfig,
|
|
12
|
+
getRoute,
|
|
13
|
+
getSession,
|
|
14
|
+
getRemoteEnabled,
|
|
15
|
+
// config-lifecycle
|
|
16
|
+
saveConfigAndAdopt,
|
|
17
|
+
scheduleBackendSave,
|
|
18
|
+
// normalizers / helpers
|
|
19
|
+
cfgMod,
|
|
20
|
+
hasOwn,
|
|
21
|
+
normalizeAutoClearConfig,
|
|
22
|
+
autoClearIdleMsForProvider,
|
|
23
|
+
normalizeCompactionConfig,
|
|
24
|
+
normalizeCompactTypeSetting,
|
|
25
|
+
normalizeSystemShellConfig,
|
|
26
|
+
normalizeSystemShellCommand,
|
|
27
|
+
setConfiguredShell,
|
|
28
|
+
setRecapEnabledInConfig,
|
|
29
|
+
setModuleEnabledInConfig,
|
|
30
|
+
summarizeWorkflowRoutes,
|
|
31
|
+
parseDurationMs,
|
|
32
|
+
formatDurationMs,
|
|
33
|
+
localPackageVersion,
|
|
34
|
+
// state getters / feature flags
|
|
35
|
+
memoryEnabled,
|
|
36
|
+
recapEnabledFn,
|
|
37
|
+
channelsEnabled,
|
|
38
|
+
autoUpdateEnabled,
|
|
39
|
+
getUpdateCheckState,
|
|
40
|
+
getUpdateProcessState,
|
|
41
|
+
// side-effect callbacks
|
|
42
|
+
invalidateContextStatusCache,
|
|
43
|
+
invalidatePreSessionToolSurface,
|
|
44
|
+
scheduleChannelStart,
|
|
45
|
+
channels,
|
|
46
|
+
clearChannelStartTimer,
|
|
47
|
+
checkForUpdateInternal,
|
|
48
|
+
runUpdateNowInternal,
|
|
49
|
+
reloadChannelsSoon,
|
|
50
|
+
ONBOARDING_VERSION,
|
|
51
|
+
// channel-admin token delegates
|
|
52
|
+
saveDiscordToken,
|
|
53
|
+
forgetDiscordToken,
|
|
54
|
+
saveTelegramToken,
|
|
55
|
+
forgetTelegramToken,
|
|
56
|
+
saveWebhookAuthtoken,
|
|
57
|
+
forgetWebhookAuthtoken,
|
|
58
|
+
setBackend,
|
|
59
|
+
}) {
|
|
60
|
+
return {
|
|
61
|
+
getOnboardingStatus() {
|
|
62
|
+
const nextConfig = getConfig();
|
|
63
|
+
return {
|
|
64
|
+
completed: nextConfig?.onboarding?.completed === true,
|
|
65
|
+
version: nextConfig?.onboarding?.version || 0,
|
|
66
|
+
default: nextConfig?.default || null,
|
|
67
|
+
workflowRoutes: summarizeWorkflowRoutes(nextConfig),
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
// Mark onboarding as done WITHOUT touching routes/agents/provider. Used by
|
|
71
|
+
// the TUI "skip" (Esc) path so the wizard doesn't reappear next launch,
|
|
72
|
+
// while leaving any existing config routes untouched.
|
|
73
|
+
skipOnboarding() {
|
|
74
|
+
const config = getConfig();
|
|
75
|
+
const nextConfig = { ...config };
|
|
76
|
+
nextConfig.onboarding = {
|
|
77
|
+
...(nextConfig.onboarding || {}),
|
|
78
|
+
completed: true,
|
|
79
|
+
version: ONBOARDING_VERSION,
|
|
80
|
+
completedAt: new Date().toISOString(),
|
|
81
|
+
skipped: true,
|
|
82
|
+
};
|
|
83
|
+
saveConfigAndAdopt(nextConfig);
|
|
84
|
+
return this.getOnboardingStatus();
|
|
85
|
+
},
|
|
86
|
+
getAutoClear() {
|
|
87
|
+
const config = getConfig();
|
|
88
|
+
const route = getRoute();
|
|
89
|
+
const normalized = normalizeAutoClearConfig(config.autoClear);
|
|
90
|
+
const provider = route?.provider || null;
|
|
91
|
+
const providerDefault = autoClearIdleMsForProvider(provider);
|
|
92
|
+
const idleMs = normalized.custom ? normalized.idleMs : providerDefault;
|
|
93
|
+
return {
|
|
94
|
+
enabled: normalized.enabled,
|
|
95
|
+
idleMs,
|
|
96
|
+
custom: normalized.custom,
|
|
97
|
+
providerDefault,
|
|
98
|
+
provider,
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
// --- User profile (/profile statusline command) ---------------------
|
|
102
|
+
// getProfile returns the normalized { title, language } plus the resolved
|
|
103
|
+
// language catalog entry and the full language list for the picker UI.
|
|
104
|
+
getProfile() {
|
|
105
|
+
const config = getConfig();
|
|
106
|
+
const profile = cfgMod.normalizeProfileConfig(config.profile);
|
|
107
|
+
return {
|
|
108
|
+
...profile,
|
|
109
|
+
languageEntry: cfgMod.profileLanguageEntry(profile.language),
|
|
110
|
+
languages: cfgMod.PROFILE_LANGUAGES,
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
// setProfile patches title and/or language and persists. Unknown language
|
|
114
|
+
// ids normalize back to 'system'. Prompt-side injection is wired separately
|
|
115
|
+
// (composeSystemPrompt) — this only owns the stored value.
|
|
116
|
+
setProfile(input = {}) {
|
|
117
|
+
const config = getConfig();
|
|
118
|
+
const current = cfgMod.normalizeProfileConfig(config.profile);
|
|
119
|
+
const next = { ...current };
|
|
120
|
+
if (hasOwn(input, 'title') || hasOwn(input, 'name')) {
|
|
121
|
+
next.title = input.title ?? input.name ?? '';
|
|
122
|
+
}
|
|
123
|
+
if (hasOwn(input, 'language') || hasOwn(input, 'lang')) {
|
|
124
|
+
next.language = input.language ?? input.lang ?? 'system';
|
|
125
|
+
}
|
|
126
|
+
const normalized = cfgMod.normalizeProfileConfig(next);
|
|
127
|
+
saveConfigAndAdopt({ ...config, profile: normalized });
|
|
128
|
+
return this.getProfile();
|
|
129
|
+
},
|
|
130
|
+
getCompactionSettings() {
|
|
131
|
+
const config = getConfig();
|
|
132
|
+
return normalizeCompactionConfig(config.compaction, { memoryEnabled: memoryEnabled() });
|
|
133
|
+
},
|
|
134
|
+
setCompactionSettings(input = {}) {
|
|
135
|
+
const config = getConfig();
|
|
136
|
+
const current = normalizeCompactionConfig(config.compaction, { memoryEnabled: memoryEnabled() });
|
|
137
|
+
const next = { ...current };
|
|
138
|
+
if (hasOwn(input, 'auto')) next.auto = input.auto !== false;
|
|
139
|
+
if (hasOwn(input, 'enabled')) next.auto = input.enabled !== false;
|
|
140
|
+
if (hasOwn(input, 'type') || hasOwn(input, 'compactType') || hasOwn(input, 'compact_type')) {
|
|
141
|
+
const requestedType = input.type ?? input.compactType ?? input.compact_type;
|
|
142
|
+
const compactType = normalizeCompactTypeSetting(requestedType, current.compactType || current.type || 'semantic');
|
|
143
|
+
next.type = compactType;
|
|
144
|
+
next.compactType = compactType;
|
|
145
|
+
}
|
|
146
|
+
const nextConfig = { ...config };
|
|
147
|
+
nextConfig.compaction = normalizeCompactionConfig(next, { memoryEnabled: memoryEnabled() });
|
|
148
|
+
saveConfigAndAdopt(nextConfig);
|
|
149
|
+
const config2 = getConfig();
|
|
150
|
+
const session = getSession();
|
|
151
|
+
if (session) {
|
|
152
|
+
session.compaction = {
|
|
153
|
+
...(session.compaction || {}),
|
|
154
|
+
...normalizeCompactionConfig(config2.compaction, { memoryEnabled: memoryEnabled() }),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
invalidateContextStatusCache();
|
|
158
|
+
return normalizeCompactionConfig(config2.compaction, { memoryEnabled: memoryEnabled() });
|
|
159
|
+
},
|
|
160
|
+
// Recap toggle: user-facing switch that gates ONLY the background memory
|
|
161
|
+
// cycles (1/2/3). The memory module (transcript watcher/ingest, on-demand
|
|
162
|
+
// recall/fasttrack drains) is always-on. Persisted via the same
|
|
163
|
+
// saveConfigAndAdopt path as compaction/autoClear. The memory daemon
|
|
164
|
+
// re-reads recap from the agent config section each cycle tick, so toggling
|
|
165
|
+
// takes effect without a restart (no memory-service stop/start here).
|
|
166
|
+
getRecapSettings() {
|
|
167
|
+
return { enabled: recapEnabledFn() };
|
|
168
|
+
},
|
|
169
|
+
setRecapEnabled(enabled) {
|
|
170
|
+
const config = getConfig();
|
|
171
|
+
const nextConfig = setRecapEnabledInConfig({ ...config }, enabled !== false);
|
|
172
|
+
saveConfigAndAdopt(nextConfig);
|
|
173
|
+
invalidatePreSessionToolSurface();
|
|
174
|
+
invalidateContextStatusCache();
|
|
175
|
+
return this.getRecapSettings();
|
|
176
|
+
},
|
|
177
|
+
// Thin aliases kept for the current TUI callsites (updated separately).
|
|
178
|
+
// enabled here reflects the recap toggle; memory itself is always-on.
|
|
179
|
+
getMemorySettings() {
|
|
180
|
+
return {
|
|
181
|
+
enabled: recapEnabledFn(),
|
|
182
|
+
compactFastTrackAvailable: true,
|
|
183
|
+
};
|
|
184
|
+
},
|
|
185
|
+
async setMemoryEnabled(enabled) {
|
|
186
|
+
return this.setRecapEnabled(enabled);
|
|
187
|
+
},
|
|
188
|
+
getChannelSettings(options = {}) {
|
|
189
|
+
return {
|
|
190
|
+
enabled: channelsEnabled(),
|
|
191
|
+
...(options?.includeStatus === false ? {} : { status: channels.status() }),
|
|
192
|
+
};
|
|
193
|
+
},
|
|
194
|
+
async setChannelsEnabled(enabled) {
|
|
195
|
+
const config = getConfig();
|
|
196
|
+
const nextConfig = setModuleEnabledInConfig({ ...config }, 'channels', enabled !== false);
|
|
197
|
+
saveConfigAndAdopt(nextConfig);
|
|
198
|
+
if (!channelsEnabled()) {
|
|
199
|
+
clearChannelStartTimer();
|
|
200
|
+
await channels.stop('settings-disabled', { waitForExit: false }).catch(() => {});
|
|
201
|
+
} else {
|
|
202
|
+
// Enabling channels in settings only boots the worker when this session
|
|
203
|
+
// is in remote mode; otherwise the toggle just persists config.
|
|
204
|
+
if (getRemoteEnabled()) scheduleChannelStart(0);
|
|
205
|
+
}
|
|
206
|
+
invalidatePreSessionToolSurface();
|
|
207
|
+
return this.getChannelSettings();
|
|
208
|
+
},
|
|
209
|
+
getSystemShell() {
|
|
210
|
+
const config = getConfig();
|
|
211
|
+
return normalizeSystemShellConfig(config.shell);
|
|
212
|
+
},
|
|
213
|
+
setSystemShell(input = {}) {
|
|
214
|
+
const config = getConfig();
|
|
215
|
+
const command = normalizeSystemShellCommand(typeof input === 'string' ? input : input?.command);
|
|
216
|
+
saveConfigAndAdopt({
|
|
217
|
+
...config,
|
|
218
|
+
shell: command ? { ...(config.shell || {}), command } : {},
|
|
219
|
+
});
|
|
220
|
+
setConfiguredShell(command);
|
|
221
|
+
return normalizeSystemShellConfig(getConfig().shell);
|
|
222
|
+
},
|
|
223
|
+
setAutoClear(input = {}) {
|
|
224
|
+
const config = getConfig();
|
|
225
|
+
const current = normalizeAutoClearConfig(config.autoClear);
|
|
226
|
+
const next = { ...current };
|
|
227
|
+
if (hasOwn(input, 'enabled')) next.enabled = input.enabled !== false;
|
|
228
|
+
if (input.reset === true || (hasOwn(input, 'idleMs') && input.idleMs == null)) {
|
|
229
|
+
next.idleMs = null;
|
|
230
|
+
} else if (hasOwn(input, 'idleMs')) {
|
|
231
|
+
const idleMs = Number(input.idleMs);
|
|
232
|
+
if (!Number.isFinite(idleMs) || idleMs <= 0) throw new Error('autoclear idleMs must be a positive number');
|
|
233
|
+
next.idleMs = Math.max(60_000, Math.round(idleMs));
|
|
234
|
+
}
|
|
235
|
+
if (hasOwn(input, 'duration')) {
|
|
236
|
+
const idleMs = parseDurationMs(input.duration);
|
|
237
|
+
if (!idleMs) throw new Error('usage: /autoclear [on|off|status|<minutes|1h|90m>]');
|
|
238
|
+
next.idleMs = idleMs;
|
|
239
|
+
if (!hasOwn(input, 'enabled')) next.enabled = true;
|
|
240
|
+
}
|
|
241
|
+
saveConfigAndAdopt({ ...config, autoClear: next });
|
|
242
|
+
const resolved = this.getAutoClear();
|
|
243
|
+
return { ...resolved, label: formatDurationMs(resolved.idleMs) };
|
|
244
|
+
},
|
|
245
|
+
getUpdateSettings() {
|
|
246
|
+
const updateCheckState = getUpdateCheckState();
|
|
247
|
+
return {
|
|
248
|
+
autoUpdate: autoUpdateEnabled(),
|
|
249
|
+
currentVersion: updateCheckState.currentVersion || localPackageVersion(),
|
|
250
|
+
latestVersion: updateCheckState.latestVersion,
|
|
251
|
+
updateAvailable: updateCheckState.updateAvailable,
|
|
252
|
+
lastCheckedAt: updateCheckState.lastCheckedAt,
|
|
253
|
+
};
|
|
254
|
+
},
|
|
255
|
+
setAutoUpdate(enabled) {
|
|
256
|
+
const config = getConfig();
|
|
257
|
+
saveConfigAndAdopt({
|
|
258
|
+
...config,
|
|
259
|
+
update: { ...(config.update || {}), auto: enabled === true },
|
|
260
|
+
});
|
|
261
|
+
return this.getUpdateSettings();
|
|
262
|
+
},
|
|
263
|
+
async checkForUpdate(options = {}) {
|
|
264
|
+
await checkForUpdateInternal({ force: options?.force === true });
|
|
265
|
+
return this.getUpdateSettings();
|
|
266
|
+
},
|
|
267
|
+
async runUpdateNow() {
|
|
268
|
+
const state = await runUpdateNowInternal();
|
|
269
|
+
return { ok: state.phase === 'installed', ...state };
|
|
270
|
+
},
|
|
271
|
+
getUpdateStatus() {
|
|
272
|
+
return { ...getUpdateProcessState() };
|
|
273
|
+
},
|
|
274
|
+
saveDiscordToken(token) {
|
|
275
|
+
const result = saveDiscordToken(token);
|
|
276
|
+
reloadChannelsSoon();
|
|
277
|
+
return result;
|
|
278
|
+
},
|
|
279
|
+
forgetDiscordToken() {
|
|
280
|
+
const result = forgetDiscordToken();
|
|
281
|
+
reloadChannelsSoon();
|
|
282
|
+
return result;
|
|
283
|
+
},
|
|
284
|
+
saveTelegramToken(token) {
|
|
285
|
+
const result = saveTelegramToken(token);
|
|
286
|
+
reloadChannelsSoon();
|
|
287
|
+
return result;
|
|
288
|
+
},
|
|
289
|
+
forgetTelegramToken() {
|
|
290
|
+
const result = forgetTelegramToken();
|
|
291
|
+
reloadChannelsSoon();
|
|
292
|
+
return result;
|
|
293
|
+
},
|
|
294
|
+
setBackend(name) {
|
|
295
|
+
// Validate synchronously (same contract as before: bad input throws on
|
|
296
|
+
// this call so the TUI's try/catch can react immediately). The actual
|
|
297
|
+
// channels-section file read-modify-write is the hitch source on the
|
|
298
|
+
// settings-toggle key handler, so defer it through the same debounce
|
|
299
|
+
// pattern as saveConfigAndAdopt/flushConfigSave instead of writing to
|
|
300
|
+
// disk synchronously inside the key handler.
|
|
301
|
+
const value = String(name || '').trim();
|
|
302
|
+
if (value !== 'discord' && value !== 'telegram') {
|
|
303
|
+
throw new Error('backend must be discord or telegram');
|
|
304
|
+
}
|
|
305
|
+
scheduleBackendSave(value);
|
|
306
|
+
return { ok: true, backend: value };
|
|
307
|
+
},
|
|
308
|
+
saveWebhookAuthtoken(token) {
|
|
309
|
+
const result = saveWebhookAuthtoken(token);
|
|
310
|
+
reloadChannelsSoon();
|
|
311
|
+
return result;
|
|
312
|
+
},
|
|
313
|
+
forgetWebhookAuthtoken() {
|
|
314
|
+
const result = forgetWebhookAuthtoken();
|
|
315
|
+
reloadChannelsSoon();
|
|
316
|
+
return result;
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
}
|