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,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openai-ws-delta.mjs — request/response item matching + incremental-input
|
|
3
|
+
* delta computation for the OpenAI OAuth WebSocket transport.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from openai-ws-stream.mjs (no behavior change): the pure helpers
|
|
6
|
+
* that decide whether a warm socket can send only the input tail
|
|
7
|
+
* (_computeDelta / _sansInput / _logicalResponseItemMatch / ...). No socket or
|
|
8
|
+
* stream state — deterministic functions over request bodies + prior-response
|
|
9
|
+
* snapshots. openai-ws-stream.mjs re-exports these so existing importers
|
|
10
|
+
* (openai-oauth-ws.mjs et al) resolve unchanged.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// If the cached request (sans input) matches the current one and the current
|
|
14
|
+
// input starts with the cached input, return only the tail. Otherwise return
|
|
15
|
+
// the full input (fresh turn).
|
|
16
|
+
export function _sansInput(body) {
|
|
17
|
+
const { input: _ignored, previous_response_id: _prevIgnored, ...rest } = body;
|
|
18
|
+
return rest;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function _stableStringify(obj) {
|
|
22
|
+
// Shallow stable-ish: JSON.stringify with sorted top-level keys. Nested
|
|
23
|
+
// arrays (tools, include) are order-sensitive and reflect intent, so we
|
|
24
|
+
// do not sort them.
|
|
25
|
+
if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) return JSON.stringify(obj);
|
|
26
|
+
const keys = Object.keys(obj).sort();
|
|
27
|
+
const parts = [];
|
|
28
|
+
for (const k of keys) parts.push(JSON.stringify(k) + ':' + _stableStringify(obj[k]));
|
|
29
|
+
return '{' + parts.join(',') + '}';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function _cloneJson(value) {
|
|
33
|
+
if (value == null) return value;
|
|
34
|
+
try { return JSON.parse(JSON.stringify(value)); } catch { return value; }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function _normalizeArguments(value) {
|
|
38
|
+
if (value == null) return '';
|
|
39
|
+
if (typeof value === 'string') {
|
|
40
|
+
const trimmed = value.trim();
|
|
41
|
+
try { return _stableStringify(JSON.parse(trimmed || '{}')); } catch { return trimmed; }
|
|
42
|
+
}
|
|
43
|
+
return _stableStringify(value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function _normalizeContentPart(part) {
|
|
47
|
+
if (!part || typeof part !== 'object') return part;
|
|
48
|
+
const type = part.type === 'input_text' ? 'output_text' : part.type;
|
|
49
|
+
if (type === 'output_text') return { type, text: part.text || '' };
|
|
50
|
+
return part;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _contentPartsEqual(a, b) {
|
|
54
|
+
const aa = Array.isArray(a) ? a.map(_normalizeContentPart) : [];
|
|
55
|
+
const bb = Array.isArray(b) ? b.map(_normalizeContentPart) : [];
|
|
56
|
+
return _stableStringify(aa) === _stableStringify(bb);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function _logicalResponseItemMatch(inputItem, responseItem) {
|
|
60
|
+
if (!inputItem || !responseItem) return false;
|
|
61
|
+
const inputType = inputItem.type || (inputItem.role === 'assistant' ? 'message' : '');
|
|
62
|
+
const responseType = responseItem.type || '';
|
|
63
|
+
if (responseType === 'function_call') {
|
|
64
|
+
if (inputType !== 'function_call') return false;
|
|
65
|
+
const inputCallId = String(inputItem.call_id || '');
|
|
66
|
+
const responseCallId = String(responseItem.call_id || '');
|
|
67
|
+
const inputName = String(inputItem.name || '');
|
|
68
|
+
const responseName = String(responseItem.name || '');
|
|
69
|
+
if (inputCallId && responseCallId) {
|
|
70
|
+
// call_id is the server-side anchor. The replayed history may carry
|
|
71
|
+
// locally compacted arguments, but previous_response_id already
|
|
72
|
+
// points at the canonical output item.
|
|
73
|
+
return inputCallId === responseCallId && inputName === responseName;
|
|
74
|
+
}
|
|
75
|
+
return inputName === responseName
|
|
76
|
+
&& _normalizeArguments(inputItem.arguments) === _normalizeArguments(responseItem.arguments);
|
|
77
|
+
}
|
|
78
|
+
if (responseType === 'tool_search_call') {
|
|
79
|
+
if (inputType !== 'tool_search_call') return false;
|
|
80
|
+
const inputCallId = String(inputItem.call_id || '');
|
|
81
|
+
const responseCallId = String(responseItem.call_id || '');
|
|
82
|
+
if (inputCallId && responseCallId) return inputCallId === responseCallId;
|
|
83
|
+
return _normalizeArguments(inputItem.arguments) === _normalizeArguments(responseItem.arguments);
|
|
84
|
+
}
|
|
85
|
+
if (responseType === 'custom_tool_call') {
|
|
86
|
+
if (inputType !== 'custom_tool_call') return false;
|
|
87
|
+
const inputCallId = String(inputItem.call_id || '');
|
|
88
|
+
const responseCallId = String(responseItem.call_id || '');
|
|
89
|
+
const inputName = String(inputItem.name || '');
|
|
90
|
+
const responseName = String(responseItem.name || '');
|
|
91
|
+
if (inputCallId && responseCallId) return inputCallId === responseCallId && inputName === responseName;
|
|
92
|
+
return inputName === responseName && String(inputItem.input || '') === String(responseItem.input || '');
|
|
93
|
+
}
|
|
94
|
+
if (responseType === 'message') {
|
|
95
|
+
const inputRole = inputItem.role || (inputType === 'message' ? 'assistant' : '');
|
|
96
|
+
const responseRole = responseItem.role || 'assistant';
|
|
97
|
+
return inputType === 'message'
|
|
98
|
+
&& inputRole === responseRole
|
|
99
|
+
&& _contentPartsEqual(inputItem.content, responseItem.content);
|
|
100
|
+
}
|
|
101
|
+
if (responseType === 'reasoning') {
|
|
102
|
+
return inputType === 'reasoning'
|
|
103
|
+
&& (!!responseItem.id ? inputItem.id === responseItem.id : true)
|
|
104
|
+
&& (!!responseItem.encrypted_content
|
|
105
|
+
? inputItem.encrypted_content === responseItem.encrypted_content
|
|
106
|
+
: true);
|
|
107
|
+
}
|
|
108
|
+
if (responseType === 'web_search_call') {
|
|
109
|
+
return inputType === 'web_search_call'
|
|
110
|
+
&& (!!responseItem.id ? inputItem.id === responseItem.id : true)
|
|
111
|
+
&& _stableStringify(inputItem.action || null) === _stableStringify(responseItem.action || null);
|
|
112
|
+
}
|
|
113
|
+
if (inputType !== responseType) return false;
|
|
114
|
+
const stripVolatile = (item) => {
|
|
115
|
+
if (!item || typeof item !== 'object') return item;
|
|
116
|
+
const { id: _id, status: _status, ...rest } = item;
|
|
117
|
+
return rest;
|
|
118
|
+
};
|
|
119
|
+
return _stableStringify(stripVolatile(inputItem)) === _stableStringify(stripVolatile(responseItem));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function _requestInputItemsMatch(a, b) {
|
|
123
|
+
return _stableStringify(a) === _stableStringify(b);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function _stripRequestPrefix(curInput, prevInput) {
|
|
127
|
+
const current = Array.isArray(curInput) ? curInput : [];
|
|
128
|
+
const previous = Array.isArray(prevInput) ? prevInput : [];
|
|
129
|
+
if (current.length < previous.length) return null;
|
|
130
|
+
for (let i = 0; i < previous.length; i += 1) {
|
|
131
|
+
if (!_requestInputItemsMatch(current[i], previous[i])) return null;
|
|
132
|
+
}
|
|
133
|
+
return current.slice(previous.length);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function _isReplayLikeHead(item, responseItem) {
|
|
137
|
+
if (!item || !responseItem) return false;
|
|
138
|
+
const inputType = item.type || (item.role === 'assistant' ? 'message' : '');
|
|
139
|
+
const responseType = responseItem.type || '';
|
|
140
|
+
if (responseType === 'message') return inputType === 'message';
|
|
141
|
+
if (responseType === 'function_call') return inputType === 'function_call';
|
|
142
|
+
if (responseType === 'tool_search_call') return inputType === 'tool_search_call';
|
|
143
|
+
return inputType === responseType;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function _stripResponseItemsFromHead(items, responseItems) {
|
|
147
|
+
const tail = Array.isArray(items) ? items : [];
|
|
148
|
+
const outputs = Array.isArray(responseItems) ? responseItems : [];
|
|
149
|
+
let cursor = 0;
|
|
150
|
+
let stripped = 0;
|
|
151
|
+
let skipped = 0;
|
|
152
|
+
for (const output of outputs) {
|
|
153
|
+
if (cursor >= tail.length) break;
|
|
154
|
+
if (_logicalResponseItemMatch(tail[cursor], output)) {
|
|
155
|
+
cursor += 1;
|
|
156
|
+
stripped += 1;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (_isReplayLikeHead(tail[cursor], output)) {
|
|
160
|
+
return {
|
|
161
|
+
ok: false,
|
|
162
|
+
reason: `response_output_mismatch:${output?.type || 'unknown'}`,
|
|
163
|
+
tail,
|
|
164
|
+
stripped,
|
|
165
|
+
skipped,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
skipped += 1;
|
|
169
|
+
}
|
|
170
|
+
return { ok: true, reason: null, tail: tail.slice(cursor), stripped, skipped };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function _computeDelta({ entry, body }) {
|
|
174
|
+
// Codex-aligned default: reuse the cached WS response chain by sending
|
|
175
|
+
// previous_response_id plus only the incremental input tail when the
|
|
176
|
+
// current request is a strict extension of the last one. Keep a full-frame
|
|
177
|
+
// escape hatch for A/B runs and emergency rollback.
|
|
178
|
+
const deltaSetting = String(process.env.MIXDOG_OAI_WS_DELTA || '').trim().toLowerCase();
|
|
179
|
+
const forceFull = ['1', 'true', 'yes', 'on'].includes(String(process.env.MIXDOG_OAI_WS_FULL || '').trim().toLowerCase())
|
|
180
|
+
|| ['0', 'false', 'no', 'off'].includes(deltaSetting);
|
|
181
|
+
if (forceFull) {
|
|
182
|
+
return { mode: 'full', reason: 'full_forced', frame: { type: 'response.create', ...body } };
|
|
183
|
+
}
|
|
184
|
+
if (!entry || !entry.lastRequestSansInput || !entry.lastResponseId) {
|
|
185
|
+
return { mode: 'full', reason: 'no_anchor', frame: { type: 'response.create', ...body } };
|
|
186
|
+
}
|
|
187
|
+
if (!Array.isArray(entry.lastRequestInput)) {
|
|
188
|
+
return { mode: 'full', reason: 'no_input_snapshot', frame: { type: 'response.create', ...body } };
|
|
189
|
+
}
|
|
190
|
+
const curSans = _stableStringify(_sansInput(body));
|
|
191
|
+
if (curSans !== entry.lastRequestSansInput) {
|
|
192
|
+
return { mode: 'full', reason: 'request_properties_changed', frame: { type: 'response.create', ...body } };
|
|
193
|
+
}
|
|
194
|
+
const curInput = Array.isArray(body.input) ? body.input : [];
|
|
195
|
+
const afterPreviousInput = _stripRequestPrefix(curInput, entry.lastRequestInput);
|
|
196
|
+
if (!afterPreviousInput) {
|
|
197
|
+
return { mode: 'full', reason: 'input_prefix_mismatch', frame: { type: 'response.create', ...body } };
|
|
198
|
+
}
|
|
199
|
+
const stripped = _stripResponseItemsFromHead(afterPreviousInput, entry.lastResponseItems);
|
|
200
|
+
if (!stripped.ok) {
|
|
201
|
+
return { mode: 'full', reason: stripped.reason, frame: { type: 'response.create', ...body } };
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
mode: 'delta',
|
|
205
|
+
reason: null,
|
|
206
|
+
strippedResponseItems: stripped.stripped,
|
|
207
|
+
skippedResponseItems: stripped.skipped,
|
|
208
|
+
frame: (() => {
|
|
209
|
+
const { model, instructions, input: _input, ...rest } = body;
|
|
210
|
+
return {
|
|
211
|
+
type: 'response.create',
|
|
212
|
+
model,
|
|
213
|
+
...(typeof instructions === 'string' && instructions.length ? { instructions } : {}),
|
|
214
|
+
previous_response_id: entry.lastResponseId,
|
|
215
|
+
input: stripped.tail,
|
|
216
|
+
...rest,
|
|
217
|
+
};
|
|
218
|
+
})(),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function _estimateFrameTokens(frame) {
|
|
223
|
+
try {
|
|
224
|
+
const s = JSON.stringify(frame);
|
|
225
|
+
return Math.ceil(s.length / 4);
|
|
226
|
+
} catch { return 0; }
|
|
227
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openai-ws-events.mjs — usage assembly + event/close parsing helpers for the
|
|
3
|
+
* OpenAI OAuth WebSocket transport.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from openai-ws-stream.mjs (no behavior change): the pure,
|
|
6
|
+
* socket-free helpers used by the _streamResponse loop to combine warmup +
|
|
7
|
+
* actual usage, parse server event frames, derive incomplete reasons, and map
|
|
8
|
+
* WS close codes to HTTP status. openai-ws-stream.mjs re-exports these so
|
|
9
|
+
* existing importers resolve unchanged.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
function _usageNum(value) {
|
|
13
|
+
const n = Number(value || 0);
|
|
14
|
+
return Number.isFinite(n) ? n : 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function _combineUsageWithWarmup(actual, warmup) {
|
|
18
|
+
if (!warmup) return actual;
|
|
19
|
+
if (!actual) return warmup;
|
|
20
|
+
const actualRaw = actual.raw || {};
|
|
21
|
+
const warmupRaw = warmup.raw || {};
|
|
22
|
+
const actualTicks = _usageNum(actualRaw.cost_in_usd_ticks);
|
|
23
|
+
const warmupTicks = _usageNum(warmupRaw.cost_in_usd_ticks);
|
|
24
|
+
return {
|
|
25
|
+
...actual,
|
|
26
|
+
inputTokens: _usageNum(actual.inputTokens) + _usageNum(warmup.inputTokens),
|
|
27
|
+
outputTokens: _usageNum(actual.outputTokens) + _usageNum(warmup.outputTokens),
|
|
28
|
+
cachedTokens: _usageNum(actual.cachedTokens) + _usageNum(warmup.cachedTokens),
|
|
29
|
+
promptTokens: _usageNum(actual.promptTokens) + _usageNum(warmup.promptTokens),
|
|
30
|
+
warmupInputTokens: _usageNum(warmup.inputTokens),
|
|
31
|
+
warmupCachedTokens: _usageNum(warmup.cachedTokens),
|
|
32
|
+
warmupOutputTokens: _usageNum(warmup.outputTokens),
|
|
33
|
+
raw: {
|
|
34
|
+
...actualRaw,
|
|
35
|
+
warmup_usage: warmupRaw,
|
|
36
|
+
...(actualTicks || warmupTicks ? { cost_in_usd_ticks: actualTicks + warmupTicks } : {}),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function _parseEvent(raw) {
|
|
42
|
+
try { return JSON.parse(raw); } catch { return null; }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function _incompleteReasonFromEvent(event) {
|
|
46
|
+
const reasonObj = event?.response?.incomplete_details
|
|
47
|
+
|| event?.incomplete_details
|
|
48
|
+
|| event?.response?.status_details
|
|
49
|
+
|| null;
|
|
50
|
+
return String(reasonObj?.reason || event?.response?.status || 'incomplete');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function _isMaxOutputIncompleteReason(reason) {
|
|
54
|
+
return /^(?:max_output_tokens|max_tokens|length|output_token_limit)$/i.test(String(reason || '').trim());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function _httpStatusFromWsClose(code, reason) {
|
|
58
|
+
const n = Number(code || 0);
|
|
59
|
+
const r = String(reason || '').toLowerCase();
|
|
60
|
+
if (n === 4401
|
|
61
|
+
|| /\b(?:unauthorized|unauthorised|authentication|auth(?:enticated?)?|not authenticated|token expired|access token)\b/.test(r)) {
|
|
62
|
+
return 401;
|
|
63
|
+
}
|
|
64
|
+
if (n === 4403 || /\b(?:forbidden|policy|permission denied)\b/.test(r)) return 403;
|
|
65
|
+
if (n === 4429 || /\b(?:rate limit|quota)\b/.test(r)) return 429;
|
|
66
|
+
return 0;
|
|
67
|
+
}
|