mixdog 0.9.3 → 0.9.5
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/README.md +112 -38
- package/package.json +10 -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/r5-orchestrated-task.json +7 -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-r13-clientmeta.json +464 -0
- package/scripts/bench/round-r14-betafeatures.json +466 -0
- package/scripts/bench/round-r15-fulldefault.json +462 -0
- package/scripts/bench/round-r16-sessionid.json +466 -0
- package/scripts/bench/round-r17-wirebytes.json +456 -0
- package/scripts/bench/round-r18-prewarm.json +468 -0
- package/scripts/bench/round-r19-clean.json +472 -0
- package/scripts/bench/round-r20-prewarm-clean.json +475 -0
- package/scripts/bench/round-r21-delta-retry.json +473 -0
- package/scripts/bench/round-r22-full-probe.json +693 -0
- package/scripts/bench/round-r23-itemprobe.json +701 -0
- package/scripts/bench/round-r24-shapefix.json +677 -0
- package/scripts/bench/round-r25-serial.json +464 -0
- package/scripts/bench/round-r26-parallel3.json +671 -0
- package/scripts/bench/round-r27-parallel10.json +894 -0
- package/scripts/bench/round-r28-parallel10-stagger.json +882 -0
- package/scripts/bench/round-r29-parallel10-stagger166.json +886 -0
- package/scripts/bench/round-r30-instid.json +253 -0
- package/scripts/bench/round-r31-upgradeprobe.json +256 -0
- package/scripts/bench/round-r32-vs-codex-lead.json +254 -0
- package/scripts/bench/round-r33-vs-codex-codex.json +115 -0
- package/scripts/bench/round-r34-orchestrated.json +120 -0
- package/scripts/bench/round-r35-orchestrated-codex.json +61 -0
- package/scripts/bench/round-r36-orchestrated-capped.json +128 -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 +251 -32
- package/scripts/freevar-smoke.mjs +95 -0
- package/scripts/internal-comms-bench.mjs +3 -4
- package/scripts/internal-comms-smoke.mjs +10 -9
- package/scripts/model-catalog-audit.mjs +209 -0
- package/scripts/model-list-sanitize-test.mjs +37 -0
- 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-bench.mjs +76 -13
- package/scripts/recall-quality-cases.json +12 -0
- package/scripts/recall-usecase-cases.json +18 -0
- package/scripts/session-bench.mjs +152 -6
- package/scripts/tool-smoke.mjs +25 -65
- 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 +9 -8
- package/src/agents/maintainer/AGENT.md +4 -0
- package/src/agents/reviewer/AGENT.md +2 -1
- package/src/agents/scheduler-task/AGENT.md +2 -3
- package/src/agents/webhook-handler/AGENT.md +2 -3
- package/src/agents/worker/AGENT.md +10 -7
- package/src/app.mjs +12 -1
- package/src/headless-role.mjs +7 -1
- package/src/lib/rules-builder.cjs +4 -0
- package/src/mixdog-session-runtime.mjs +647 -2056
- package/src/output-styles/default.md +30 -9
- package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
- package/src/output-styles/minimal.md +8 -6
- package/src/output-styles/simple.md +21 -7
- package/src/rules/agent/00-common.md +6 -3
- package/src/rules/agent/30-explorer.md +16 -5
- package/src/rules/lead/01-general.md +5 -5
- package/src/rules/lead/lead-brief.md +15 -0
- package/src/rules/lead/lead-tool.md +6 -15
- package/src/rules/shared/01-tool.md +17 -21
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +8 -3
- 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 +105 -11
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +356 -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 +740 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +349 -2131
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +143 -1002
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +229 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +465 -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/provider-catalog-cache.mjs +80 -0
- 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 +275 -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 +278 -402
- 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/stall-policy.mjs +20 -1
- 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 +35 -44
- 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 +27 -318
- package/src/runtime/channels/backends/telegram.mjs +8 -12
- package/src/runtime/channels/index.mjs +247 -701
- package/src/runtime/channels/lib/backend-dispatch.mjs +46 -0
- package/src/runtime/channels/lib/config.mjs +37 -149
- package/src/runtime/channels/lib/event-pipeline.mjs +22 -5
- package/src/runtime/channels/lib/event-queue.mjs +78 -13
- package/src/runtime/channels/lib/inbound-routing.mjs +74 -0
- package/src/runtime/channels/lib/interaction-workflows.mjs +5 -113
- 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/scheduler.mjs +27 -113
- 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 +313 -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 +43 -616
- package/src/runtime/channels/tool-defs.mjs +11 -130
- package/src/runtime/memory/index.mjs +210 -1948
- package/src/runtime/memory/lib/core-memory-store.mjs +5 -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/embedding-warmup.mjs +58 -0
- package/src/runtime/memory/lib/ko-morph.mjs +195 -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 +69 -12
- package/src/runtime/memory/lib/memory-text-utils.mjs +46 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
- package/src/runtime/memory/lib/query-handlers.mjs +802 -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/config.mjs +14 -4
- package/src/runtime/shared/launcher-control.mjs +2 -2
- package/src/runtime/shared/markdown-frontmatter.mjs +19 -0
- package/src/runtime/shared/schedules-store.mjs +13 -3
- 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 +23 -0
- package/src/runtime/shared/update-checker.mjs +7 -4
- package/src/session-runtime/config-helpers.mjs +119 -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 +205 -0
- package/src/session-runtime/quick-search-models.mjs +47 -0
- package/src/session-runtime/session-hooks.mjs +93 -0
- package/src/session-runtime/settings-api.mjs +352 -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/session-runtime/workflow.mjs +1 -1
- 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 +138 -669
- package/src/standalone/channel-admin.mjs +102 -90
- package/src/standalone/channel-worker.mjs +4 -7
- package/src/standalone/explore-tool.mjs +64 -14
- 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 +1059 -8110
- package/src/tui/app/app-format.mjs +213 -0
- package/src/tui/app/channel-pickers.mjs +508 -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 +356 -0
- package/src/tui/app/model-options.mjs +334 -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 +489 -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 +677 -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 +512 -0
- package/src/tui/app/use-transcript-window.mjs +607 -0
- package/src/tui/components/ConfirmBar.jsx +10 -7
- package/src/tui/components/Picker.jsx +64 -15
- package/src/tui/components/PromptInput.jsx +33 -102
- package/src/tui/components/SlashCommandPalette.jsx +8 -1
- package/src/tui/components/StatusLine.jsx +69 -15
- 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 +13553 -12384
- 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 +170 -574
- package/src/tui/figures.mjs +5 -0
- package/src/tui/index.jsx +65 -1
- 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 +77 -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 +16 -18
- package/src/workflows/sequential/WORKFLOW.md +16 -18
- package/vendor/ink/build/display-width.js +19 -3
- package/vendor/ink/build/ink.js +112 -7
- 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/channels/lib/holidays.mjs +0 -138
- 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,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Codex OAuth model-catalog transforms.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from openai-oauth.mjs: pure catalog helpers — API-shape
|
|
5
|
+
* normalization, family classification, version comparison, and the
|
|
6
|
+
* per-family "latest" pass. No module state; openai-oauth.mjs re-exports
|
|
7
|
+
* _displayCodexModel for existing importers.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// OAuth catalog returns dated ids (gpt-5.4-mini-2026-03-17). Strip the trailing
|
|
11
|
+
// -YYYY-MM-DD to get the version alias (gpt-5.4-mini). Unknown shapes pass
|
|
12
|
+
// through unchanged.
|
|
13
|
+
export function _displayCodexModel(id) {
|
|
14
|
+
if (!id || typeof id !== 'string') return id;
|
|
15
|
+
return id.replace(/-\d{4}-\d{2}-\d{2}$/, '');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function _positiveCodexContextWindow(value) {
|
|
19
|
+
const n = Number(value);
|
|
20
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function _codexContextWindowFromApi(m) {
|
|
24
|
+
return _positiveCodexContextWindow(m?.context_window)
|
|
25
|
+
|| _positiveCodexContextWindow(m?.max_context_window)
|
|
26
|
+
|| null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function _codexFamily(id) {
|
|
30
|
+
const s = String(id || '').toLowerCase();
|
|
31
|
+
if (s.includes('nano')) return 'gpt-nano';
|
|
32
|
+
if (s.includes('mini')) return 'gpt-mini';
|
|
33
|
+
if (s.includes('codex')) return 'gpt-codex';
|
|
34
|
+
if (s.startsWith('gpt-5.5')) return 'gpt-5.5';
|
|
35
|
+
if (s.startsWith('gpt-5.4')) return 'gpt-5.4';
|
|
36
|
+
if (s.startsWith('gpt-5.2')) return 'gpt-5.2';
|
|
37
|
+
if (s.startsWith('gpt-5')) return 'gpt-5';
|
|
38
|
+
return 'gpt';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function _normalizeCodexModel(m) {
|
|
42
|
+
const id = m?.slug || m?.id;
|
|
43
|
+
const family = _codexFamily(id);
|
|
44
|
+
const serviceTiers = Array.isArray(m?.service_tiers)
|
|
45
|
+
? m.service_tiers
|
|
46
|
+
.map(t => ({
|
|
47
|
+
id: String(t?.id || '').trim(),
|
|
48
|
+
name: String(t?.name || '').trim(),
|
|
49
|
+
description: String(t?.description || '').trim(),
|
|
50
|
+
}))
|
|
51
|
+
.filter(t => t.id)
|
|
52
|
+
: [];
|
|
53
|
+
const additionalSpeedTiers = Array.isArray(m?.additional_speed_tiers)
|
|
54
|
+
? m.additional_speed_tiers.map(t => String(t || '').trim()).filter(Boolean)
|
|
55
|
+
: [];
|
|
56
|
+
// Catalog ids are version aliases without separate display dating.
|
|
57
|
+
return {
|
|
58
|
+
id,
|
|
59
|
+
name: m?.display_name || id,
|
|
60
|
+
display: m?.display_name || id,
|
|
61
|
+
family,
|
|
62
|
+
provider: 'openai-oauth',
|
|
63
|
+
contextWindow: _codexContextWindowFromApi(m),
|
|
64
|
+
maxContextWindow: _positiveCodexContextWindow(m?.max_context_window),
|
|
65
|
+
outputTokens: m?.max_output_tokens || m?.output_tokens || 32768,
|
|
66
|
+
autoCompactTokenLimit: m?.auto_compact_token_limit || null,
|
|
67
|
+
effectiveContextWindowPercent: m?.effective_context_window_percent || null,
|
|
68
|
+
tier: 'version',
|
|
69
|
+
latest: false,
|
|
70
|
+
description: m?.description || '',
|
|
71
|
+
reasoningLevels: (m?.supported_reasoning_levels || []).map(r => r.effort),
|
|
72
|
+
serviceTiers,
|
|
73
|
+
defaultServiceTier: m?.default_service_tier || null,
|
|
74
|
+
additionalSpeedTiers,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Compare two model ids by the X.Y version embedded in `gpt-X.Y`. Mirrors
|
|
79
|
+
// anthropic-oauth's _compareVersion; these ids have no trailing date so
|
|
80
|
+
// the version lives in the dotted number, not a -YYYY-MM-DD suffix.
|
|
81
|
+
export function _compareVersion(a, b) {
|
|
82
|
+
const na = (String(a).match(/gpt-(\d+)\.(\d+)/) || []).slice(1).map(Number);
|
|
83
|
+
const nb = (String(b).match(/gpt-(\d+)\.(\d+)/) || []).slice(1).map(Number);
|
|
84
|
+
for (let i = 0; i < Math.max(na.length, nb.length); i++) {
|
|
85
|
+
if ((na[i] || 0) !== (nb[i] || 0)) return (na[i] || 0) - (nb[i] || 0);
|
|
86
|
+
}
|
|
87
|
+
return String(a).localeCompare(String(b));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Main gpt-5 chat family only: exclude the mini/nano/codex variants so "latest"
|
|
91
|
+
// resolves to the flagship, not a smaller sibling.
|
|
92
|
+
export function _isMainCodexFamily(family) {
|
|
93
|
+
return typeof family === 'string' && family.startsWith('gpt-5');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Mark the highest-version model per family as `latest: true`. VERSION-based
|
|
97
|
+
// (ids carry no `created`), mirroring anthropic-oauth's per-family pass.
|
|
98
|
+
export function _markLatestCodex(models) {
|
|
99
|
+
const byFamily = new Map();
|
|
100
|
+
for (const m of models) {
|
|
101
|
+
if (!m?.id) continue;
|
|
102
|
+
const cur = byFamily.get(m.family);
|
|
103
|
+
if (!cur || _compareVersion(m.id, cur.id) > 0) {
|
|
104
|
+
byFamily.set(m.family, m);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const m of byFamily.values()) m.latest = true;
|
|
108
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openai-compat-trace.mjs — shared trace/token helpers for the OpenAI-compat
|
|
3
|
+
* provider family.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from openai-compat.mjs. Holds the two low-level helpers
|
|
6
|
+
* (summarizeTraceMessages, extractCompatCachedTokens) consumed by both
|
|
7
|
+
* openai-compat.mjs and openai-compat-xai.mjs cache-trace writers. Isolating
|
|
8
|
+
* them here breaks the former import cycle between those two modules.
|
|
9
|
+
*/
|
|
10
|
+
import { traceHash, stableTraceStringify, traceTextShape } from './trace-utils.mjs';
|
|
11
|
+
|
|
12
|
+
export function summarizeTraceMessages(messages) {
|
|
13
|
+
const summaries = (messages || []).map((m, index) => {
|
|
14
|
+
const content = typeof m?.content === 'string'
|
|
15
|
+
? { type: 'text', ...traceTextShape(m.content) }
|
|
16
|
+
: { type: m?.content == null ? 'null' : typeof m.content, hash: traceHash(stableTraceStringify(m?.content ?? null)) };
|
|
17
|
+
const toolCalls = Array.isArray(m?.tool_calls)
|
|
18
|
+
? m.tool_calls.map(tc => ({
|
|
19
|
+
name: tc?.function?.name || null,
|
|
20
|
+
argsHash: traceHash(tc?.function?.arguments || ''),
|
|
21
|
+
}))
|
|
22
|
+
: [];
|
|
23
|
+
return {
|
|
24
|
+
index,
|
|
25
|
+
role: m?.role || null,
|
|
26
|
+
content,
|
|
27
|
+
...(typeof m?.reasoning_content === 'string'
|
|
28
|
+
? { reasoningContent: traceTextShape(m.reasoning_content) }
|
|
29
|
+
: {}),
|
|
30
|
+
toolCallCount: toolCalls.length,
|
|
31
|
+
...(toolCalls.length ? { toolCalls } : {}),
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
if (summaries.length <= 12) return summaries;
|
|
35
|
+
return [
|
|
36
|
+
...summaries.slice(0, 8),
|
|
37
|
+
{ omittedTurns: summaries.length - 12 },
|
|
38
|
+
...summaries.slice(-4),
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function extractCompatCachedTokens(usage) {
|
|
43
|
+
const candidates = [
|
|
44
|
+
usage?.prompt_tokens_details?.cached_tokens,
|
|
45
|
+
usage?.input_tokens_details?.cached_tokens,
|
|
46
|
+
usage?.prompt_cache_hit_tokens,
|
|
47
|
+
usage?.cached_prompt_text_tokens,
|
|
48
|
+
];
|
|
49
|
+
for (const v of candidates) {
|
|
50
|
+
const n = Number(v);
|
|
51
|
+
if (Number.isFinite(n) && n > 0) return n;
|
|
52
|
+
}
|
|
53
|
+
for (const v of candidates) {
|
|
54
|
+
const n = Number(v);
|
|
55
|
+
if (Number.isFinite(n)) return n;
|
|
56
|
+
}
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openai-compat-wire.mjs — message/tool wire conversion + response parsing for
|
|
3
|
+
* the OpenAI-compat provider.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from openai-compat.mjs. Pure (stateless) converters between the
|
|
6
|
+
* agent's internal message/tool shape and the OpenAI Chat Completions /
|
|
7
|
+
* Responses API wire shapes, plus the response tool-call / text / search-source
|
|
8
|
+
* parsers. No provider instance state; openai-compat.mjs imports these entry
|
|
9
|
+
* points and re-exports the ones its tests/importers reference.
|
|
10
|
+
*/
|
|
11
|
+
import {
|
|
12
|
+
parseCompletedToolCallArgumentsJson,
|
|
13
|
+
} from './openai-compat-stream.mjs';
|
|
14
|
+
import {
|
|
15
|
+
normalizeContentForOpenAIChat,
|
|
16
|
+
normalizeContentForOpenAIResponses,
|
|
17
|
+
splitToolContentForOpenAIChat,
|
|
18
|
+
splitToolContentForOpenAIResponses,
|
|
19
|
+
} from './media-normalization.mjs';
|
|
20
|
+
import {
|
|
21
|
+
customToolCallFromResponseItem,
|
|
22
|
+
} from './custom-tool-wire.mjs';
|
|
23
|
+
|
|
24
|
+
export function positiveTokenInt(value) {
|
|
25
|
+
const n = Number(value);
|
|
26
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function resolveCompatMaxOutputTokens(opts = {}) {
|
|
30
|
+
return positiveTokenInt(
|
|
31
|
+
opts.maxOutputTokens
|
|
32
|
+
?? opts.outputTokens
|
|
33
|
+
?? opts.max_output_tokens
|
|
34
|
+
?? opts.maxTokens
|
|
35
|
+
?? opts.max_tokens,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function toOpenAIMessages(messages, providerName, options = {}) {
|
|
40
|
+
// NOTE: chat.completions has no equivalent slot for replaying reasoning
|
|
41
|
+
// encrypted_content the way the Responses API does (no `type:'reasoning'`
|
|
42
|
+
// input item). Whatever reasoningItems may be attached to assistant
|
|
43
|
+
// messages by the openai-oauth provider is intentionally dropped here —
|
|
44
|
+
// strict providers (xai) reject unknown roles/types and would 400 the
|
|
45
|
+
// request. Documented in v0.1.160 (GPT reasoning replay).
|
|
46
|
+
//
|
|
47
|
+
// DeepSeek thinking models require the prior turn's `reasoning_content`
|
|
48
|
+
// string to be echoed back inside the assistant message, otherwise the API
|
|
49
|
+
// returns 400. xAI reasoning models also preserve their official multi-turn
|
|
50
|
+
// shape and cache prefix stability when prior assistant reasoning_content
|
|
51
|
+
// is replayed; reasoning_effort itself remains caller/user-selected.
|
|
52
|
+
const replaysReasoningContent = options.replaysReasoningContent === true
|
|
53
|
+
|| providerName === 'deepseek'
|
|
54
|
+
|| providerName === 'xai';
|
|
55
|
+
const out = [];
|
|
56
|
+
const pendingToolMedia = [];
|
|
57
|
+
const flushToolMedia = () => {
|
|
58
|
+
if (!pendingToolMedia.length) return;
|
|
59
|
+
out.push({ role: 'user', content: pendingToolMedia.splice(0) });
|
|
60
|
+
};
|
|
61
|
+
for (const m of messages) {
|
|
62
|
+
if (m.role === 'tool') {
|
|
63
|
+
const { output, mediaContent } = splitToolContentForOpenAIChat(m.content);
|
|
64
|
+
out.push({
|
|
65
|
+
role: 'tool',
|
|
66
|
+
tool_call_id: m.toolCallId || '',
|
|
67
|
+
content: output,
|
|
68
|
+
});
|
|
69
|
+
if (mediaContent) pendingToolMedia.push(...mediaContent);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
flushToolMedia();
|
|
73
|
+
if (m.role === 'assistant' && m.toolCalls?.length) {
|
|
74
|
+
const msg = {
|
|
75
|
+
role: 'assistant',
|
|
76
|
+
content: normalizeContentForOpenAIChat(m.content, { role: 'assistant' }) || null,
|
|
77
|
+
tool_calls: m.toolCalls.map((tc) => ({
|
|
78
|
+
id: tc.id,
|
|
79
|
+
type: 'function',
|
|
80
|
+
function: { name: tc.name, arguments: JSON.stringify(tc.arguments) },
|
|
81
|
+
})),
|
|
82
|
+
};
|
|
83
|
+
if (replaysReasoningContent && m.reasoningContent) msg.reasoning_content = m.reasoningContent;
|
|
84
|
+
out.push(msg);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (m.role === 'assistant' && replaysReasoningContent && m.reasoningContent) {
|
|
88
|
+
out.push({ role: m.role, content: normalizeContentForOpenAIChat(m.content, { role: 'assistant' }), reasoning_content: m.reasoningContent });
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
out.push({ role: m.role, content: normalizeContentForOpenAIChat(m.content, { role: m.role }) });
|
|
92
|
+
}
|
|
93
|
+
flushToolMedia();
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function toOpenAITools(tools) {
|
|
98
|
+
return tools.map((t) => ({
|
|
99
|
+
type: 'function',
|
|
100
|
+
function: {
|
|
101
|
+
name: t.name,
|
|
102
|
+
description: t.description,
|
|
103
|
+
parameters: t.inputSchema,
|
|
104
|
+
},
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function toResponsesTools(tools) {
|
|
109
|
+
return tools.map((t) => {
|
|
110
|
+
if (t?.name === 'tool_search') {
|
|
111
|
+
return {
|
|
112
|
+
type: 'tool_search',
|
|
113
|
+
execution: 'client',
|
|
114
|
+
description: t.description,
|
|
115
|
+
parameters: t.inputSchema,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// xAI/Grok Responses rejects the OpenAI-only `type:'custom'` freeform
|
|
119
|
+
// variant ("unknown variant 'custom'"). Serialize freeform/grammar
|
|
120
|
+
// tools (e.g. apply_patch) as ordinary function tools instead. Grammar
|
|
121
|
+
// tools may carry no usable inputSchema, so fall back to a permissive
|
|
122
|
+
// object schema so grok still registers a valid function tool.
|
|
123
|
+
return {
|
|
124
|
+
type: 'function',
|
|
125
|
+
name: t.name,
|
|
126
|
+
description: t.description,
|
|
127
|
+
parameters: t.inputSchema || { type: 'object', additionalProperties: true },
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function nativeResponsesTools(opts) {
|
|
133
|
+
return Array.isArray(opts?.nativeTools)
|
|
134
|
+
? opts.nativeTools.filter(t => t && typeof t === 'object')
|
|
135
|
+
: [];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Known tool-name sets for the leaked-tool-call guard, derived from the exact
|
|
139
|
+
// request body so a recovered leaked call is only synthesized when it names a
|
|
140
|
+
// tool the model was actually offered. Chat tools nest the name under
|
|
141
|
+
// `function.name`; Responses tools carry a top-level `name`.
|
|
142
|
+
export function knownToolNamesFromOpenAITools(tools) {
|
|
143
|
+
return new Set(
|
|
144
|
+
(Array.isArray(tools) ? tools : [])
|
|
145
|
+
.map((t) => (typeof t?.function?.name === 'string' ? t.function.name
|
|
146
|
+
: typeof t?.name === 'string' ? t.name : null))
|
|
147
|
+
.filter(Boolean),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function knownToolNamesFromResponsesTools(tools) {
|
|
152
|
+
return new Set(
|
|
153
|
+
(Array.isArray(tools) ? tools : [])
|
|
154
|
+
.map((t) => (typeof t?.name === 'string' ? t.name : null))
|
|
155
|
+
.filter(Boolean),
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function parseToolCalls(choice, label) {
|
|
160
|
+
const calls = choice.message?.tool_calls;
|
|
161
|
+
if (!calls?.length)
|
|
162
|
+
return undefined;
|
|
163
|
+
// finish_reason present ⇒ the turn completed; a JSON.parse failure on the
|
|
164
|
+
// arguments is deterministic bad JSON (permanent), not stream truncation.
|
|
165
|
+
const finishReason = choice.finish_reason || null;
|
|
166
|
+
return calls
|
|
167
|
+
.filter((tc) => tc.type === 'function')
|
|
168
|
+
.map((tc) => ({
|
|
169
|
+
id: tc.id,
|
|
170
|
+
name: tc.function.name,
|
|
171
|
+
arguments: parseCompletedToolCallArgumentsJson(tc.function.arguments, label, { id: tc.id, name: tc.function.name, finishReason }),
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function parseResponsesToolCalls(response, label) {
|
|
176
|
+
const out = [];
|
|
177
|
+
// A Responses tool call is only parsed off a completed/done item, so any
|
|
178
|
+
// malformed-JSON failure here is deterministic, not mid-stream truncation.
|
|
179
|
+
const finishReason = response?.status || 'completed';
|
|
180
|
+
for (const item of response?.output || []) {
|
|
181
|
+
if (item?.type === 'function_call') {
|
|
182
|
+
out.push({
|
|
183
|
+
id: item.call_id || item.id,
|
|
184
|
+
name: item.name,
|
|
185
|
+
arguments: parseCompletedToolCallArgumentsJson(item.arguments, label, { id: item.call_id || item.id, name: item.name, finishReason }),
|
|
186
|
+
});
|
|
187
|
+
} else if (item?.type === 'custom_tool_call') {
|
|
188
|
+
const call = customToolCallFromResponseItem(item);
|
|
189
|
+
if (call) out.push(call);
|
|
190
|
+
} else if (item?.type === 'tool_search_call') {
|
|
191
|
+
const _tsArgs = item.arguments && typeof item.arguments === 'object' && !Array.isArray(item.arguments)
|
|
192
|
+
? item.arguments
|
|
193
|
+
: parseCompletedToolCallArgumentsJson(item.arguments || '{}', label, { id: item.call_id || item.id, name: 'tool_search', finishReason });
|
|
194
|
+
out.push({
|
|
195
|
+
id: item.call_id || item.id,
|
|
196
|
+
name: 'tool_search',
|
|
197
|
+
// Schema is a plain object ({query,select,limit}); an array
|
|
198
|
+
// (parsed JSON or passthrough) must never pass through as args.
|
|
199
|
+
arguments: (_tsArgs && typeof _tsArgs === 'object' && !Array.isArray(_tsArgs)) ? _tsArgs : {},
|
|
200
|
+
nativeType: 'tool_search_call',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return out.length ? out : undefined;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function responseOutputText(response) {
|
|
208
|
+
if (typeof response?.output_text === 'string') return response.output_text;
|
|
209
|
+
const chunks = [];
|
|
210
|
+
for (const item of response?.output || []) {
|
|
211
|
+
if (item?.type !== 'message' || !Array.isArray(item.content)) continue;
|
|
212
|
+
for (const part of item.content) {
|
|
213
|
+
if (part?.type === 'output_text' && typeof part.text === 'string') chunks.push(part.text);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return chunks.join('');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function collectCompatResponseSearchSources(response) {
|
|
220
|
+
const citations = [];
|
|
221
|
+
const webSearchCalls = [];
|
|
222
|
+
const seen = new Set();
|
|
223
|
+
const addCitation = (source, fallback = {}) => {
|
|
224
|
+
if (!source) return;
|
|
225
|
+
if (typeof source === 'string') {
|
|
226
|
+
const url = source.trim();
|
|
227
|
+
if (!url || seen.has(url)) return;
|
|
228
|
+
seen.add(url);
|
|
229
|
+
citations.push({ title: url, url, snippet: '', source: fallback.source || 'citation', provider: 'xai' });
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (typeof source !== 'object') return;
|
|
233
|
+
const url = String(
|
|
234
|
+
source.url
|
|
235
|
+
|| source.uri
|
|
236
|
+
|| source.href
|
|
237
|
+
|| source.source_url
|
|
238
|
+
|| source.url_citation?.url
|
|
239
|
+
|| '',
|
|
240
|
+
).trim();
|
|
241
|
+
if (!url || seen.has(url)) return;
|
|
242
|
+
seen.add(url);
|
|
243
|
+
citations.push({
|
|
244
|
+
title: String(source.title || source.name || source.query || source.url_citation?.title || fallback.title || url).trim(),
|
|
245
|
+
url,
|
|
246
|
+
snippet: String(source.snippet || source.text || source.description || '').trim(),
|
|
247
|
+
source: source.source || fallback.source || 'citation',
|
|
248
|
+
provider: source.provider || 'xai',
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
for (const citation of Array.isArray(response?.citations) ? response.citations : []) addCitation(citation);
|
|
252
|
+
for (const item of Array.isArray(response?.output) ? response.output : []) {
|
|
253
|
+
if (item?.type === 'web_search_call') {
|
|
254
|
+
webSearchCalls.push({ id: item.id || '', status: item.status || '', action: item.action || null });
|
|
255
|
+
const action = item.action || {};
|
|
256
|
+
for (const source of Array.isArray(action.sources) ? action.sources : []) addCitation(source, { title: action.query || '', source: 'web_search_call' });
|
|
257
|
+
if (action.url) addCitation({ url: action.url, title: action.query || '' }, { source: 'web_search_call' });
|
|
258
|
+
for (const url of Array.isArray(action.urls) ? action.urls : []) addCitation({ url, title: action.query || '' }, { source: 'web_search_call' });
|
|
259
|
+
}
|
|
260
|
+
for (const citation of Array.isArray(item?.citations) ? item.citations : []) addCitation(citation);
|
|
261
|
+
for (const part of Array.isArray(item?.content) ? item.content : []) {
|
|
262
|
+
for (const annotation of Array.isArray(part?.annotations) ? part.annotations : []) {
|
|
263
|
+
addCitation(annotation, { source: 'annotation' });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return { citations, webSearchCalls };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export function toResponsesInputMessage(m, pendingToolMedia = null, customToolCallNameById = null) {
|
|
271
|
+
if (m.role === 'tool') {
|
|
272
|
+
if (Array.isArray(m.nativeToolSearch?.openaiTools)) {
|
|
273
|
+
return {
|
|
274
|
+
type: 'tool_search_output',
|
|
275
|
+
call_id: m.toolCallId || '',
|
|
276
|
+
status: 'completed',
|
|
277
|
+
execution: 'client',
|
|
278
|
+
tools: m.nativeToolSearch.openaiTools,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
const { output, mediaContent } = splitToolContentForOpenAIResponses(m.content);
|
|
282
|
+
// xai path: never emit `custom_tool_call_output` (the `custom` variant
|
|
283
|
+
// is rejected by grok). Replay prior tool outputs as the standard
|
|
284
|
+
// `function_call_output` item regardless of original native type.
|
|
285
|
+
const item = {
|
|
286
|
+
type: 'function_call_output',
|
|
287
|
+
call_id: m.toolCallId || '',
|
|
288
|
+
output: output,
|
|
289
|
+
};
|
|
290
|
+
if (mediaContent && pendingToolMedia) pendingToolMedia.push(...mediaContent);
|
|
291
|
+
return item;
|
|
292
|
+
}
|
|
293
|
+
if (m.role === 'assistant' && Array.isArray(m.toolCalls) && m.toolCalls.length > 0) {
|
|
294
|
+
const items = [];
|
|
295
|
+
if (m.content) items.push({ role: 'assistant', content: normalizeContentForOpenAIResponses(m.content, { role: 'assistant' }) });
|
|
296
|
+
for (const tc of m.toolCalls) {
|
|
297
|
+
if (tc.nativeType === 'tool_search_call' || tc.name === 'tool_search') {
|
|
298
|
+
items.push({
|
|
299
|
+
type: 'tool_search_call',
|
|
300
|
+
call_id: tc.id,
|
|
301
|
+
execution: 'client',
|
|
302
|
+
arguments: tc.arguments || {},
|
|
303
|
+
});
|
|
304
|
+
} else {
|
|
305
|
+
// xai path: prior native `custom_tool_call` history is replayed
|
|
306
|
+
// as a standard `function_call` (grok rejects the `custom`
|
|
307
|
+
// variant). tc.arguments already holds the recovered object
|
|
308
|
+
// form, so the same stringify path as regular calls applies.
|
|
309
|
+
items.push({
|
|
310
|
+
type: 'function_call',
|
|
311
|
+
call_id: tc.id,
|
|
312
|
+
name: tc.name,
|
|
313
|
+
arguments: JSON.stringify(tc.arguments || {}),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return items;
|
|
318
|
+
}
|
|
319
|
+
return { role: m.role, content: normalizeContentForOpenAIResponses(m.content || '', { role: m.role }) };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function xaiSystemInstructions(messages) {
|
|
323
|
+
const instructions = (messages || [])
|
|
324
|
+
.filter(m => m?.role === 'system')
|
|
325
|
+
.map(m => String(m.content || ''))
|
|
326
|
+
.filter(Boolean)
|
|
327
|
+
.join('\n\n');
|
|
328
|
+
return instructions || undefined;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function toXaiResponsesInput(messages, providerState, options = {}) {
|
|
332
|
+
const includeSystem = options.includeSystem !== false;
|
|
333
|
+
const state = providerState?.xaiResponses || null;
|
|
334
|
+
let startIndex = 0;
|
|
335
|
+
let resetReason = null;
|
|
336
|
+
let previousResponseId = typeof state?.previousResponseId === 'string' ? state.previousResponseId : null;
|
|
337
|
+
const expectedModel = options.model ? String(options.model) : '';
|
|
338
|
+
const stateModel = state?.model ? String(state.model) : '';
|
|
339
|
+
const seen = Number.isInteger(state?.seenMessageCount) ? state.seenMessageCount : null;
|
|
340
|
+
if (previousResponseId && expectedModel && stateModel && stateModel !== expectedModel) {
|
|
341
|
+
previousResponseId = null;
|
|
342
|
+
resetReason = 'model_changed';
|
|
343
|
+
}
|
|
344
|
+
if (previousResponseId && (seen == null || seen < 0 || seen > messages.length)) {
|
|
345
|
+
previousResponseId = null;
|
|
346
|
+
resetReason = seen == null ? 'missing_seen_message_count' : 'seen_message_count_out_of_range';
|
|
347
|
+
}
|
|
348
|
+
if (previousResponseId) {
|
|
349
|
+
startIndex = Math.max(0, Math.min(seen, messages.length));
|
|
350
|
+
if (messages[startIndex]?.role === 'assistant') startIndex += 1;
|
|
351
|
+
}
|
|
352
|
+
const input = [];
|
|
353
|
+
const pendingToolMedia = [];
|
|
354
|
+
const customToolCallNameById = new Map();
|
|
355
|
+
const flushToolMedia = () => {
|
|
356
|
+
if (!pendingToolMedia.length) return;
|
|
357
|
+
input.push({ role: 'user', content: pendingToolMedia.splice(0) });
|
|
358
|
+
};
|
|
359
|
+
for (const m of messages.slice(startIndex)) {
|
|
360
|
+
if (!includeSystem && m.role === 'system') continue;
|
|
361
|
+
if (m.role !== 'tool') flushToolMedia();
|
|
362
|
+
const converted = toResponsesInputMessage(m, pendingToolMedia, customToolCallNameById);
|
|
363
|
+
if (Array.isArray(converted)) input.push(...converted);
|
|
364
|
+
else input.push(converted);
|
|
365
|
+
}
|
|
366
|
+
flushToolMedia();
|
|
367
|
+
return { input, previousResponseId, startIndex, continuationResetReason: resetReason };
|
|
368
|
+
}
|