mixdog 0.9.63 → 0.9.65
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 +3 -0
- package/package.json +9 -2
- package/scripts/code-graph-description-contract.mjs +3 -3
- package/scripts/verify-release-assets.mjs +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +11 -14
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -2
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +19 -124
- package/src/runtime/agent/orchestrator/context/collect.mjs +6 -6
- package/src/runtime/agent/orchestrator/dispatch-persist.mjs +2 -2
- package/src/runtime/agent/orchestrator/internal-agents.mjs +2 -2
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +333 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -277
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +6 -6
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +196 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +460 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +14 -593
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -280
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +357 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-headers.mjs +216 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +2 -188
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/compact/budget.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/compact/file-reattach.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +17 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +18 -26
- package/src/runtime/agent/orchestrator/session/loop/termination.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/delivered-completions.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +49 -0
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +49 -0
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +260 -0
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +72 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +163 -0
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -561
- package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +2 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +11 -11
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/bash-session.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +2 -154
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/cwd-utils.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/fs-reachability.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/glob-walk.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/path-locks.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +2 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-image-resize.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-open.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-spawn.mjs +519 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +5 -449
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +212 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +1 -7
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +9 -36
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +15 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/search-references.mjs +429 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +2 -395
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-state.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/mutation-planner.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/next-call-utils.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +72 -9
- package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/result-compression.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +2 -444
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +505 -0
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/backend-dispatch.mjs +20 -5
- package/src/runtime/channels/lib/scheduler.mjs +1 -1
- package/src/runtime/channels/lib/telegram-format.mjs +1 -1
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +4 -4
- package/src/runtime/channels/tool-defs.mjs +2 -3
- package/src/runtime/memory/index.mjs +1 -5
- package/src/runtime/memory/lib/core-memory-candidates.mjs +357 -0
- package/src/runtime/memory/lib/core-memory-store.mjs +7 -357
- package/src/runtime/memory/lib/cycle-signatures.mjs +1 -1
- package/src/runtime/memory/lib/embedding-model-config.mjs +1 -1
- package/src/runtime/memory/lib/embedding-provider.mjs +1 -5
- package/src/runtime/memory/lib/embedding-worker.mjs +1 -5
- package/src/runtime/memory/lib/ko-morph.mjs +2 -2
- package/src/runtime/memory/lib/memory-config-flags.mjs +2 -5
- package/src/runtime/memory/lib/memory-cycle-requests.mjs +3 -7
- package/src/runtime/memory/lib/memory-cycle1.mjs +4 -8
- package/src/runtime/memory/lib/memory-cycle2-gate.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2-shared.mjs +2 -5
- package/src/runtime/memory/lib/memory-cycle3.mjs +1 -5
- package/src/runtime/memory/lib/memory-embed.mjs +2 -6
- package/src/runtime/memory/lib/memory-log.mjs +8 -0
- package/src/runtime/memory/lib/memory-ops-policy.mjs +4 -8
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +1 -1
- package/src/runtime/memory/lib/memory-recall-store.mjs +2 -193
- package/src/runtime/memory/lib/memory-score.mjs +1 -1
- package/src/runtime/memory/lib/memory-text-utils.mjs +2 -2
- package/src/runtime/memory/lib/memory.mjs +2 -6
- package/src/runtime/memory/lib/pg/adapter.mjs +2 -6
- package/src/runtime/memory/lib/pg/process.mjs +1 -5
- package/src/runtime/memory/lib/pg/supervisor.mjs +1 -5
- package/src/runtime/memory/lib/recall-format.mjs +2 -2
- package/src/runtime/memory/lib/recall-scoring.mjs +195 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -5
- package/src/runtime/memory/lib/trace-store.mjs +2 -6
- package/src/runtime/search/lib/http-fetch.mjs +6 -6
- package/src/runtime/search/lib/web-tools.mjs +2 -2
- package/src/runtime/shared/buffered-appender.mjs +1 -1
- package/src/runtime/shared/child-guardian.mjs +1 -1
- package/src/runtime/shared/child-spawn-gate.mjs +1 -1
- package/src/runtime/shared/config.mjs +4 -4
- package/src/runtime/shared/launcher-control.mjs +9 -10
- package/src/runtime/shared/llm/index.mjs +5 -20
- package/src/runtime/shared/markdown-frontmatter.mjs +1 -1
- package/src/runtime/shared/memory-snapshot.mjs +4 -4
- package/src/runtime/shared/pristine-execution.mjs +1 -1
- package/src/runtime/shared/process-lifecycle.mjs +0 -1
- package/src/runtime/shared/process-shutdown.mjs +1 -1
- package/src/runtime/shared/resource-admission.mjs +2 -2
- package/src/runtime/shared/schedule-session-run.mjs +1 -1
- package/src/runtime/shared/schedules-db.mjs +1 -1
- package/src/runtime/shared/service-discovery.mjs +2 -2
- package/src/runtime/shared/staged-update.mjs +6 -6
- package/src/runtime/shared/tool-execution-contract.mjs +1 -1
- package/src/runtime/shared/tool-primitives.mjs +1 -1
- package/src/runtime/shared/tool-surface.mjs +2 -2
- package/src/runtime/shared/turn-snapshot.mjs +184 -0
- package/src/runtime/shared/update-checker.mjs +1 -1
- package/src/runtime/shared/user-cwd.mjs +3 -3
- package/src/runtime/shared/user-data-guard.mjs +4 -4
- package/src/runtime/shared/workspace-router.mjs +5 -5
- package/src/session-runtime/config-helpers.mjs +2 -3
- package/src/session-runtime/config-lifecycle.mjs +1 -1
- package/src/session-runtime/hitch-profile.mjs +1 -1
- package/src/session-runtime/lifecycle-api.mjs +6 -4
- package/src/session-runtime/model-recency.mjs +5 -5
- package/src/session-runtime/plugin-mcp.mjs +1 -1
- package/src/session-runtime/provider-request-snapshot.mjs +338 -0
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/session-text.mjs +4 -4
- package/src/session-runtime/session-turn-api.mjs +7 -0
- package/src/session-runtime/tool-catalog-schema.mjs +197 -0
- package/src/session-runtime/tool-catalog.mjs +6 -483
- package/src/session-runtime/tool-defs.mjs +1 -1
- package/src/standalone/agent-task-status.mjs +1 -1
- package/src/standalone/agent-tool/helpers.mjs +2 -2
- package/src/standalone/channel-admin.mjs +4 -4
- package/src/standalone/explore-tool.mjs +3 -3
- package/src/standalone/hook-bus/config.mjs +1 -1
- package/src/standalone/hook-bus/constants.mjs +1 -1
- package/src/standalone/hook-bus/rules.mjs +1 -1
- package/src/standalone/projects.mjs +1 -1
- package/src/standalone/provider-admin.mjs +2 -2
- package/src/tui/App.jsx +1 -1
- package/src/tui/app/app-format.mjs +2 -2
- package/src/tui/app/clipboard.mjs +3 -3
- package/src/tui/app/input-parsers.mjs +1 -1
- package/src/tui/app/text-layout.mjs +1 -1
- package/src/tui/app/transcript-row-estimate.mjs +360 -0
- package/src/tui/app/transcript-window.mjs +5 -347
- package/src/tui/app/use-mouse-input.mjs +1 -1
- package/src/tui/app/use-prompt-handlers.mjs +1 -1
- package/src/tui/components/tool-execution/surface-detail.mjs +9 -9
- package/src/tui/components/tool-execution/text-format.mjs +2 -2
- package/src/tui/components/tool-output-format.mjs +7 -7
- package/src/tui/display-width.mjs +4 -4
- package/src/tui/dist/index.mjs +187 -99
- package/src/tui/engine/agent-envelope.mjs +5 -5
- package/src/tui/engine/live-share.mjs +100 -0
- package/src/tui/engine/notification-plan.mjs +1 -1
- package/src/tui/engine/queue-helpers.mjs +3 -3
- package/src/tui/engine/render-timing.mjs +4 -5
- package/src/tui/engine/session-api-ext.mjs +6 -3
- package/src/tui/engine/tool-result-status.mjs +5 -5
- package/src/tui/engine/tool-result-text.mjs +1 -1
- package/src/tui/engine/transcript-spill.mjs +585 -0
- package/src/tui/engine/tui-steering-persist.mjs +1 -1
- package/src/tui/engine.mjs +29 -474
- package/src/tui/lib/voice-setup.mjs +1 -1
- package/src/tui/markdown/format-token.mjs +1 -1
- package/src/tui/markdown/render-ansi.mjs +1 -1
- package/src/tui/markdown/table-layout.mjs +4 -4
- package/src/tui/paste-attachments.mjs +1 -1
- package/src/tui/prompt-history-store.mjs +3 -3
- package/src/tui/statusline-ansi-bridge.mjs +2 -2
- package/src/tui/theme.mjs +1 -1
- package/src/tui/transcript-tool-failures.mjs +2 -2
- package/src/ui/ansi.mjs +0 -9
- package/src/ui/statusline-format.mjs +2 -4
- package/scripts/_bench-cwc.json +0 -20
- package/scripts/_jitter-fuzz.jsx +0 -42
- package/scripts/_jitter-fuzz2.jsx +0 -30
- package/scripts/_jitter-probe.jsx +0 -35
- package/scripts/_jp2.jsx +0 -16
- package/scripts/_smoke_wd.mjs +0 -7
- package/scripts/abort-recovery-test.mjs +0 -175
- package/scripts/agent-dispatch-abort-compose-test.mjs +0 -31
- package/scripts/agent-live-arg-guard-smoke.mjs +0 -20
- package/scripts/agent-live-path-suffix-smoke.mjs +0 -34
- package/scripts/agent-live-toolcall-args-smoke.mjs +0 -45
- package/scripts/agent-loop-policy-test.mjs +0 -37
- package/scripts/agent-model-liveness-test.mjs +0 -763
- package/scripts/agent-parallel-smoke.mjs +0 -435
- package/scripts/agent-route-batch-test.mjs +0 -40
- package/scripts/agent-tag-reuse-smoke.mjs +0 -441
- package/scripts/agent-terminal-reap-test.mjs +0 -252
- package/scripts/agent-trace-io-test.mjs +0 -133
- package/scripts/ansi-color-capability-test.mjs +0 -90
- package/scripts/anthropic-admission-retry-integration-test.mjs +0 -119
- package/scripts/anthropic-maxtokens-test.mjs +0 -119
- package/scripts/anthropic-oauth-refresh-race-test.mjs +0 -397
- package/scripts/anthropic-transport-policy-test.mjs +0 -726
- package/scripts/apply-patch-edit-smoke.mjs +0 -71
- package/scripts/arg-guard-test.mjs +0 -93
- package/scripts/async-notify-settlement-test.mjs +0 -99
- package/scripts/atomic-lock-tryonce-test.mjs +0 -125
- package/scripts/background-task-meta-smoke.mjs +0 -38
- package/scripts/bench-run.mjs +0 -508
- package/scripts/boot-smoke.mjs +0 -137
- package/scripts/build-runtime-windows.ps1 +0 -242
- package/scripts/channel-daemon-smoke.mjs +0 -1103
- package/scripts/code-graph-aggregate-cwd-test.mjs +0 -158
- package/scripts/code-graph-disk-hit-test.mjs +0 -290
- package/scripts/code-graph-dispatch-test.mjs +0 -96
- package/scripts/code-graph-root-federation-test.mjs +0 -273
- package/scripts/compact-active-turn-test.mjs +0 -68
- package/scripts/compact-file-reattach-test.mjs +0 -88
- package/scripts/compact-pressure-test.mjs +0 -788
- package/scripts/compact-prior-context-flatten-test.mjs +0 -252
- package/scripts/compact-recall-digest-test.mjs +0 -57
- package/scripts/compact-smoke.mjs +0 -1017
- package/scripts/compact-trigger-migration-smoke.mjs +0 -261
- package/scripts/compacted-placeholder-scrub-test.mjs +0 -63
- package/scripts/context-mcp-metering-test.mjs +0 -1406
- package/scripts/debounced-skills-async-save-test.mjs +0 -57
- package/scripts/deferred-tool-loading-test.mjs +0 -250
- package/scripts/desktop-session-bridge-test.mjs +0 -1013
- package/scripts/dispatch-persist-recovery-test.mjs +0 -141
- package/scripts/embedding-worker-exit-test.mjs +0 -76
- package/scripts/execution-completion-dedup-test.mjs +0 -205
- package/scripts/execution-pending-resume-kick-test.mjs +0 -151
- package/scripts/execution-resume-esc-integration-test.mjs +0 -176
- package/scripts/explore-bench-tmp.mjs +0 -36
- package/scripts/explore-bench.mjs +0 -248
- package/scripts/explore-prompt-policy-test.mjs +0 -256
- package/scripts/explore-timeout-cancel-test.mjs +0 -345
- package/scripts/find-fuzzy-hidden-test.mjs +0 -267
- package/scripts/forwarder-rebind-tail-test.mjs +0 -67
- package/scripts/freevar-smoke.mjs +0 -98
- package/scripts/gemini-provider-test.mjs +0 -1448
- package/scripts/generate-oc-icons.mjs +0 -11
- package/scripts/grok-oauth-refresh-race-test.mjs +0 -273
- package/scripts/headless-pristine-execution-test.mjs +0 -614
- package/scripts/hook-bus-test.mjs +0 -552
- package/scripts/ingest-pure-conversation-smoke.mjs +0 -175
- package/scripts/internal-comms-bench-test.mjs +0 -226
- package/scripts/internal-comms-bench.mjs +0 -853
- package/scripts/internal-comms-smoke.mjs +0 -277
- package/scripts/internal-tools-normalization-test.mjs +0 -62
- package/scripts/interrupted-turn-history-test.mjs +0 -399
- package/scripts/lead-workflow-smoke.mjs +0 -592
- package/scripts/lifecycle-api-test.mjs +0 -137
- package/scripts/live-share-test.mjs +0 -148
- package/scripts/live-worker-smoke.mjs +0 -333
- package/scripts/log-writer-guard-smoke.mjs +0 -131
- package/scripts/maintenance-default-routes-test.mjs +0 -164
- package/scripts/max-output-recovery-persist-test.mjs +0 -81
- package/scripts/max-output-recovery-test.mjs +0 -368
- package/scripts/mcp-client-normalization-test.mjs +0 -45
- package/scripts/mcp-grace-deferred-test.mjs +0 -225
- package/scripts/memory-core-input-test.mjs +0 -167
- package/scripts/memory-cycle-routing-test.mjs +0 -111
- package/scripts/memory-meta-concurrency-test.mjs +0 -20
- package/scripts/memory-pg-recovery-test.mjs +0 -59
- package/scripts/memory-rule-contract-test.mjs +0 -93
- package/scripts/model-list-sanitize-test.mjs +0 -37
- package/scripts/mouse-tracking-restore-smoke.mjs +0 -107
- package/scripts/native-edit-wire-test.mjs +0 -152
- package/scripts/notify-completion-mirror-test.mjs +0 -73
- package/scripts/openai-oauth-refresh-race-test.mjs +0 -120
- package/scripts/openai-oauth-ws-1006-retry-test.mjs +0 -954
- package/scripts/openai-ws-early-settle-test.mjs +0 -216
- package/scripts/output-style-bench.mjs +0 -292
- package/scripts/output-style-smoke.mjs +0 -145
- package/scripts/parent-abort-link-test.mjs +0 -90
- package/scripts/patch-binary-cache-test.mjs +0 -181
- package/scripts/path-suffix-test.mjs +0 -57
- package/scripts/pending-completion-drop-test.mjs +0 -239
- package/scripts/pending-messages-lock-nonblocking-test.mjs +0 -62
- package/scripts/pretool-ask-runtime-test.mjs +0 -54
- package/scripts/process-lifecycle-test.mjs +0 -461
- package/scripts/prompt-immediate-render-test.mjs +0 -89
- package/scripts/prompt-input-parity-test.mjs +0 -145
- package/scripts/provider-admission-scheduler-test.mjs +0 -681
- package/scripts/provider-contract-test.mjs +0 -632
- package/scripts/provider-stream-stall-test.mjs +0 -276
- package/scripts/provider-toolcall-test.mjs +0 -3063
- package/scripts/reactive-compact-persist-smoke.mjs +0 -203
- package/scripts/recall-bench.mjs +0 -359
- package/scripts/resource-admission-test.mjs +0 -792
- package/scripts/result-classification-test.mjs +0 -75
- package/scripts/rg-runner-test.mjs +0 -240
- package/scripts/routing-corpus-test.mjs +0 -349
- package/scripts/sanitize-tool-pairs-test.mjs +0 -260
- package/scripts/session-bench-cache-break-test.mjs +0 -102
- package/scripts/session-bench.mjs +0 -1708
- package/scripts/session-context-bench.mjs +0 -344
- package/scripts/session-heartbeat-lifecycle-test.mjs +0 -68
- package/scripts/session-ingest-compaction-smoke.mjs +0 -279
- package/scripts/session-ingest-smoke.mjs +0 -177
- package/scripts/session-orphan-sweep-test.mjs +0 -109
- package/scripts/set-effort-config-test.mjs +0 -41
- package/scripts/shell-failure-diagnostics-test.mjs +0 -280
- package/scripts/shell-hardening-test.mjs +0 -209
- package/scripts/shell-jobs-windows-hide-test.mjs +0 -164
- package/scripts/ship-mode-test.mjs +0 -98
- package/scripts/smoke-loop-failure-summary-test.mjs +0 -38
- package/scripts/smoke-loop-failure-summary.mjs +0 -16
- package/scripts/smoke-loop-report.mjs +0 -221
- package/scripts/smoke-loop.mjs +0 -202
- package/scripts/smoke-runtime-negative.ps1 +0 -106
- package/scripts/statusline-quota-hysteresis-test.mjs +0 -62
- package/scripts/steering-drain-buckets-test.mjs +0 -467
- package/scripts/steering-fold-provenance-test.mjs +0 -71
- package/scripts/streaming-tail-window-test.mjs +0 -175
- package/scripts/submit-commandbusy-race-test.mjs +0 -257
- package/scripts/task-bench.mjs +0 -205
- package/scripts/terminal-bench-isolation-guards-test.mjs +0 -102
- package/scripts/termio-input-smoke.mjs +0 -199
- package/scripts/tool-result-hook-test.mjs +0 -48
- package/scripts/tool-smoke.mjs +0 -2453
- package/scripts/tool-tui-presentation-test.mjs +0 -286
- package/scripts/toolcall-args-test.mjs +0 -239
- package/scripts/tui-ambiguous-width-test.mjs +0 -113
- package/scripts/tui-background-failure-smoke.mjs +0 -73
- package/scripts/tui-perf-run.ps1 +0 -26
- package/scripts/tui-render-smoke.mjs +0 -90
- package/scripts/tui-runtime-load-bench-entry.jsx +0 -608
- package/scripts/tui-runtime-load-bench.mjs +0 -50
- package/scripts/tui-store-frame-batch-test.mjs +0 -99
- package/scripts/tui-transcript-jitter-harness-entry.jsx +0 -383
- package/scripts/tui-transcript-perf-test.mjs +0 -934
- package/scripts/usage-metrics-epoch-smoke.mjs +0 -114
- package/scripts/verify-release-assets-test.mjs +0 -281
- package/scripts/web-fetch-routing-test.mjs +0 -158
- package/scripts/webhook-smoke.mjs +0 -201
- package/scripts/windows-hide-spawn-options-test.mjs +0 -19
- package/scripts/worker-notify-rejection-test.mjs +0 -51
- package/scripts/write-backpressure-test.mjs +0 -147
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
bumpUsageMetricsEpoch,
|
|
4
|
-
bumpUsageMetricsTurnId,
|
|
5
|
-
resolveUsageMetricsEpoch,
|
|
6
|
-
usageMetricsIdempotencyKey,
|
|
7
|
-
applyAskTerminalUsageTotals,
|
|
8
|
-
} from '../src/runtime/agent/orchestrator/session/manager.mjs';
|
|
9
|
-
|
|
10
|
-
function assert(condition, message) {
|
|
11
|
-
if (!condition) throw new Error(message);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function applyDelta(sessionId, session, delta, seen) {
|
|
15
|
-
const epoch = resolveUsageMetricsEpoch(session, delta);
|
|
16
|
-
session.usageMetricsEpoch = epoch;
|
|
17
|
-
const ikey = usageMetricsIdempotencyKey(sessionId, session, delta);
|
|
18
|
-
const isReplay = seen.has(ikey);
|
|
19
|
-
seen.add(ikey);
|
|
20
|
-
if (!isReplay) {
|
|
21
|
-
session.totalInputTokens = (session.totalInputTokens || 0) + (delta.deltaInput || 0);
|
|
22
|
-
}
|
|
23
|
-
session.lastIterationIndex = delta.iterationIndex;
|
|
24
|
-
return isReplay;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const sessionId = 'smoke-sess';
|
|
28
|
-
const session = { usageMetricsEpoch: 0, lastIterationIndex: null, totalInputTokens: 0 };
|
|
29
|
-
const seen = new Set();
|
|
30
|
-
|
|
31
|
-
assert(
|
|
32
|
-
applyDelta(sessionId, session, { iterationIndex: 1, deltaInput: 100 }, seen) === false,
|
|
33
|
-
'first iteration should count',
|
|
34
|
-
);
|
|
35
|
-
assert(session.totalInputTokens === 100, 'first iteration tokens');
|
|
36
|
-
|
|
37
|
-
bumpUsageMetricsEpoch(session);
|
|
38
|
-
assert(session.usageMetricsEpoch === 1, 'compact reset should bump epoch');
|
|
39
|
-
|
|
40
|
-
const replay = applyDelta(sessionId, session, {
|
|
41
|
-
iterationIndex: 1,
|
|
42
|
-
usageMetricsEpoch: session.usageMetricsEpoch,
|
|
43
|
-
deltaInput: 50,
|
|
44
|
-
}, seen);
|
|
45
|
-
assert(replay === false, 'equal index after compact reset must not be treated as replay');
|
|
46
|
-
assert(session.totalInputTokens === 150, 'post-compact iteration must add tokens');
|
|
47
|
-
|
|
48
|
-
assert(
|
|
49
|
-
applyDelta(sessionId, session, {
|
|
50
|
-
iterationIndex: 1,
|
|
51
|
-
usageMetricsEpoch: 1,
|
|
52
|
-
deltaInput: 999,
|
|
53
|
-
}, seen) === true,
|
|
54
|
-
'retry of same epoch+index should replay',
|
|
55
|
-
);
|
|
56
|
-
assert(session.totalInputTokens === 150, 'replay must not double-count');
|
|
57
|
-
|
|
58
|
-
// Semantic compact + provider send at same iteration/epoch (no_change compact path)
|
|
59
|
-
const collisionSeen = new Set();
|
|
60
|
-
const collisionSession = { usageMetricsEpoch: 0, lastIterationIndex: null, totalInputTokens: 0 };
|
|
61
|
-
assert(
|
|
62
|
-
applyDelta(sessionId, collisionSession, {
|
|
63
|
-
iterationIndex: 1,
|
|
64
|
-
source: 'semantic_compact',
|
|
65
|
-
deltaInput: 20,
|
|
66
|
-
}, collisionSeen) === false,
|
|
67
|
-
'semantic compact usage should count',
|
|
68
|
-
);
|
|
69
|
-
assert(
|
|
70
|
-
applyDelta(sessionId, collisionSession, {
|
|
71
|
-
iterationIndex: 1,
|
|
72
|
-
source: 'provider_send',
|
|
73
|
-
deltaInput: 80,
|
|
74
|
-
}, collisionSeen) === false,
|
|
75
|
-
'provider send at same iteration must not replay semantic compact key',
|
|
76
|
-
);
|
|
77
|
-
assert(collisionSession.totalInputTokens === 100, 'semantic + provider usage both counted');
|
|
78
|
-
|
|
79
|
-
// Integrated incremental + terminal: totals applied once when incremental flag set
|
|
80
|
-
const integrated = { totalInputTokens: 1000, totalOutputTokens: 0, tokensCumulative: 1000 };
|
|
81
|
-
integrated.totalInputTokens += 40;
|
|
82
|
-
integrated.totalOutputTokens += 6;
|
|
83
|
-
integrated.tokensCumulative += 46;
|
|
84
|
-
applyAskTerminalUsageTotals(integrated, {
|
|
85
|
-
usage: { inputTokens: 40, outputTokens: 6 },
|
|
86
|
-
lastTurnUsage: { inputTokens: 40, outputTokens: 6 },
|
|
87
|
-
}, { skipTotalsIfIncremental: true });
|
|
88
|
-
assert(integrated.totalInputTokens === 1040, 'terminal must not double-count incremental turn totals');
|
|
89
|
-
assert(integrated.totalOutputTokens === 6, 'terminal must not double-count output');
|
|
90
|
-
assert(integrated.lastInputTokens === 40, 'terminal still updates last-turn window snapshot');
|
|
91
|
-
|
|
92
|
-
// Cross-ask collision (reviewer07): ask #2 reuses iteration indices 1-2
|
|
93
|
-
const crossSeen = new Set();
|
|
94
|
-
const crossSession = { usageMetricsEpoch: 0, usageMetricsTurnId: 0, lastIterationIndex: null, totalInputTokens: 0 };
|
|
95
|
-
bumpUsageMetricsTurnId(crossSession);
|
|
96
|
-
assert(crossSession.usageMetricsTurnId === 1, 'ask #1 turn id');
|
|
97
|
-
assert(applyDelta(sessionId, crossSession, { iterationIndex: 1, source: 'provider_send', deltaInput: 100 }, crossSeen) === false);
|
|
98
|
-
assert(applyDelta(sessionId, crossSession, { iterationIndex: 2, source: 'provider_send', deltaInput: 200 }, crossSeen) === false);
|
|
99
|
-
assert(crossSession.totalInputTokens === 300, 'ask #1 iterations counted');
|
|
100
|
-
bumpUsageMetricsTurnId(crossSession);
|
|
101
|
-
assert(crossSession.usageMetricsTurnId === 2, 'ask #2 turn id');
|
|
102
|
-
assert(
|
|
103
|
-
applyDelta(sessionId, crossSession, { iterationIndex: 1, source: 'provider_send', deltaInput: 10 }, crossSeen) === false,
|
|
104
|
-
'ask #2 iteration 1 must not replay ask #1 key',
|
|
105
|
-
);
|
|
106
|
-
assert(
|
|
107
|
-
applyDelta(sessionId, crossSession, { iterationIndex: 2, source: 'provider_send', deltaInput: 20 }, crossSeen) === false,
|
|
108
|
-
'ask #2 iteration 2 must not replay ask #1 key',
|
|
109
|
-
);
|
|
110
|
-
assert(applyDelta(sessionId, crossSession, { iterationIndex: 3, source: 'provider_send', deltaInput: 30 }, crossSeen) === false);
|
|
111
|
-
assert(crossSession.totalInputTokens === 360, 'ask #2 tokens must include iter 1-3 without undercount');
|
|
112
|
-
|
|
113
|
-
process.stdout.write('usage-metrics-epoch-smoke: ok\n');
|
|
114
|
-
|
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
|
-
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
4
|
-
import { tmpdir } from 'node:os';
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
import test from 'node:test';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
GRAPH_PLATFORMS,
|
|
10
|
-
PATCH_PLATFORMS,
|
|
11
|
-
validateGraphManifest,
|
|
12
|
-
validatePatchManifest,
|
|
13
|
-
validateRuntimeManifest,
|
|
14
|
-
verifyAssetDownloads,
|
|
15
|
-
verifyReleaseAssets,
|
|
16
|
-
} from './verify-release-assets.mjs';
|
|
17
|
-
|
|
18
|
-
const VERSION = '1.2.3';
|
|
19
|
-
const APP_VERSION = '0.9.49';
|
|
20
|
-
const GRAPH_VERSION = '0.1.0';
|
|
21
|
-
const bytes = Buffer.from('local release fixture');
|
|
22
|
-
const sha256 = createHash('sha256').update(bytes).digest('hex');
|
|
23
|
-
|
|
24
|
-
function patchFixture() {
|
|
25
|
-
return {
|
|
26
|
-
version: VERSION,
|
|
27
|
-
_comment: 'test fixture',
|
|
28
|
-
assets: Object.fromEntries(Object.entries(PATCH_PLATFORMS).map(([platform, filename]) => [
|
|
29
|
-
platform,
|
|
30
|
-
{
|
|
31
|
-
url: `https://github.com/tribgames/mixdog/releases/download/patch-v${VERSION}/${filename}`,
|
|
32
|
-
sha256,
|
|
33
|
-
},
|
|
34
|
-
])),
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function runtimeFixture() {
|
|
39
|
-
return {
|
|
40
|
-
release_tag: 'runtime-v1.2.3',
|
|
41
|
-
assets: Object.fromEntries(Object.keys(PATCH_PLATFORMS).map((platform) => [
|
|
42
|
-
platform,
|
|
43
|
-
{ url: `https://fixtures.invalid/${platform}`, sha256, size: bytes.length },
|
|
44
|
-
])),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function graphFixture() {
|
|
49
|
-
return {
|
|
50
|
-
version: GRAPH_VERSION,
|
|
51
|
-
_comment: 'test fixture',
|
|
52
|
-
assets: Object.fromEntries(Object.entries(GRAPH_PLATFORMS).map(([platform, filename]) => [
|
|
53
|
-
platform,
|
|
54
|
-
{
|
|
55
|
-
url: `https://github.com/tribgames/mixdog/releases/download/graph-v${GRAPH_VERSION}/${filename}`,
|
|
56
|
-
sha256,
|
|
57
|
-
},
|
|
58
|
-
])),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
test('accepts independent strict patch, runtime, app, and graph versions', () => {
|
|
63
|
-
assert.equal(validatePatchManifest(patchFixture(), `[package]\nversion = "${VERSION}"\n`).version, VERSION);
|
|
64
|
-
assert.equal(validateRuntimeManifest(runtimeFixture()).release_tag, 'runtime-v1.2.3');
|
|
65
|
-
assert.equal(validateGraphManifest(graphFixture(), { version: APP_VERSION }).version, GRAPH_VERSION);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test('rejects stale Cargo version, partial schema, and wrong patch tag URL', () => {
|
|
69
|
-
assert.throws(
|
|
70
|
-
() => validatePatchManifest(patchFixture(), '[package]\nversion = "1.2.2"\n'),
|
|
71
|
-
/does not match manifest version/,
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const partial = patchFixture();
|
|
75
|
-
delete partial.assets['linux-arm64'];
|
|
76
|
-
assert.throws(
|
|
77
|
-
() => validatePatchManifest(partial, `[package]\nversion = "${VERSION}"\n`),
|
|
78
|
-
/keys must be exactly/,
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
const wrongTag = patchFixture();
|
|
82
|
-
wrongTag.assets['linux-x64'].url = wrongTag.assets['linux-x64'].url.replace('patch-v1.2.3', 'patch-v1.2.2');
|
|
83
|
-
assert.throws(
|
|
84
|
-
() => validatePatchManifest(wrongTag, `[package]\nversion = "${VERSION}"\n`),
|
|
85
|
-
/patch-v1\.2\.3/,
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const extraPatch = patchFixture();
|
|
89
|
-
extraPatch.assets['freebsd-x64'] = extraPatch.assets['linux-x64'];
|
|
90
|
-
assert.throws(
|
|
91
|
-
() => validatePatchManifest(extraPatch, `[package]\nversion = "${VERSION}"\n`),
|
|
92
|
-
/keys must be exactly/,
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
const extraRuntime = runtimeFixture();
|
|
96
|
-
extraRuntime.assets['freebsd-x64'] = extraRuntime.assets['linux-x64'];
|
|
97
|
-
assert.throws(() => validateRuntimeManifest(extraRuntime), /keys must be exactly/);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test('rejects stale, noncanonical, partial, and malformed graph manifests', () => {
|
|
101
|
-
const partial = graphFixture();
|
|
102
|
-
delete partial.assets['darwin-arm64'];
|
|
103
|
-
assert.throws(() => validateGraphManifest(partial, { version: APP_VERSION }), /keys must be exactly/);
|
|
104
|
-
|
|
105
|
-
for (const replacement of [
|
|
106
|
-
'https://github.com/tribgames/mixdog/releases/download/v0.7.18/mixdog-graph-linux-x64',
|
|
107
|
-
'https://github.com/tribgames/mixdog/releases/download/graph-v0.1.1/mixdog-graph-linux-x64',
|
|
108
|
-
'https://example.com/tribgames/mixdog/releases/download/graph-v0.1.0/mixdog-graph-linux-x64',
|
|
109
|
-
'https://github.com/tribgames/mixdog/releases/download/graph-v0.1.0/mixdog-graph-wrong',
|
|
110
|
-
]) {
|
|
111
|
-
const noncanonical = graphFixture();
|
|
112
|
-
noncanonical.assets['linux-x64'].url = replacement;
|
|
113
|
-
assert.throws(
|
|
114
|
-
() => validateGraphManifest(noncanonical, { version: APP_VERSION }),
|
|
115
|
-
/graph asset URL must be/,
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const malformedDigest = graphFixture();
|
|
120
|
-
malformedDigest.assets['win32-x64'].sha256 = 'not-a-digest';
|
|
121
|
-
assert.throws(
|
|
122
|
-
() => validateGraphManifest(malformedDigest, { version: APP_VERSION }),
|
|
123
|
-
/invalid graph asset sha256/,
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
const malformedVersion = graphFixture();
|
|
127
|
-
malformedVersion.version = '0.1';
|
|
128
|
-
assert.throws(
|
|
129
|
-
() => validateGraphManifest(malformedVersion, { version: APP_VERSION }),
|
|
130
|
-
/not strict MAJOR\.MINOR\.PATCH/,
|
|
131
|
-
);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test('downloads local fixture responses, retries, and checks sha256 without network', async () => {
|
|
135
|
-
let calls = 0;
|
|
136
|
-
await verifyAssetDownloads(
|
|
137
|
-
{ fixture: { url: 'https://fixtures.invalid/asset', sha256, size: bytes.length } },
|
|
138
|
-
{
|
|
139
|
-
fetchImpl: async () => {
|
|
140
|
-
calls += 1;
|
|
141
|
-
if (calls === 1) throw new Error('fixture transient failure');
|
|
142
|
-
return new Response(bytes);
|
|
143
|
-
},
|
|
144
|
-
retryDelay: async () => {},
|
|
145
|
-
},
|
|
146
|
-
);
|
|
147
|
-
assert.equal(calls, 2);
|
|
148
|
-
|
|
149
|
-
calls = 0;
|
|
150
|
-
await assert.rejects(
|
|
151
|
-
verifyAssetDownloads(
|
|
152
|
-
{ fixture: { url: 'https://fixtures.invalid/asset', sha256: '0'.repeat(64) } },
|
|
153
|
-
{
|
|
154
|
-
fetchImpl: async () => {
|
|
155
|
-
calls += 1;
|
|
156
|
-
return new Response(bytes);
|
|
157
|
-
},
|
|
158
|
-
retryDelay: async () => {},
|
|
159
|
-
},
|
|
160
|
-
),
|
|
161
|
-
/verification failed after 3 attempts: sha256 mismatch/,
|
|
162
|
-
);
|
|
163
|
-
assert.equal(calls, 3);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test('cancels an undeclared-size patch stream immediately at the absolute ceiling', async () => {
|
|
167
|
-
let chunksProduced = 0;
|
|
168
|
-
let cancellations = 0;
|
|
169
|
-
let aborts = 0;
|
|
170
|
-
const stream = new ReadableStream(
|
|
171
|
-
{
|
|
172
|
-
pull(controller) {
|
|
173
|
-
chunksProduced += 1;
|
|
174
|
-
controller.enqueue(Buffer.from('abc'));
|
|
175
|
-
},
|
|
176
|
-
cancel() {
|
|
177
|
-
cancellations += 1;
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
{ highWaterMark: 0 },
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
await assert.rejects(
|
|
184
|
-
verifyAssetDownloads(
|
|
185
|
-
{ fixture: { url: 'https://fixtures.invalid/asset', sha256 } },
|
|
186
|
-
{
|
|
187
|
-
attempts: 1,
|
|
188
|
-
maxAssetBytes: 5,
|
|
189
|
-
fetchImpl: async (_url, { signal }) => {
|
|
190
|
-
signal.addEventListener('abort', () => { aborts += 1; });
|
|
191
|
-
return { ok: true, status: 200, body: stream };
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
),
|
|
195
|
-
/byte ceiling exceeded \(5 bytes\)/,
|
|
196
|
-
);
|
|
197
|
-
assert.equal(chunksProduced, 2);
|
|
198
|
-
assert.equal(cancellations, 1);
|
|
199
|
-
assert.equal(aborts, 1);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
test('cancels immediately when a stream exceeds its declared size below the absolute ceiling', async () => {
|
|
203
|
-
let chunksProduced = 0;
|
|
204
|
-
let cancellations = 0;
|
|
205
|
-
let aborts = 0;
|
|
206
|
-
const stream = new ReadableStream(
|
|
207
|
-
{
|
|
208
|
-
pull(controller) {
|
|
209
|
-
chunksProduced += 1;
|
|
210
|
-
controller.enqueue(Buffer.from('abc'));
|
|
211
|
-
},
|
|
212
|
-
cancel() {
|
|
213
|
-
cancellations += 1;
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
|
-
{ highWaterMark: 0 },
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
await assert.rejects(
|
|
220
|
-
verifyAssetDownloads(
|
|
221
|
-
{ fixture: { url: 'https://fixtures.invalid/asset', sha256, size: 5 } },
|
|
222
|
-
{
|
|
223
|
-
attempts: 1,
|
|
224
|
-
maxAssetBytes: 10,
|
|
225
|
-
fetchImpl: async (_url, { signal }) => {
|
|
226
|
-
signal.addEventListener('abort', () => { aborts += 1; });
|
|
227
|
-
return { ok: true, status: 200, body: stream };
|
|
228
|
-
},
|
|
229
|
-
},
|
|
230
|
-
),
|
|
231
|
-
/byte ceiling exceeded \(5 bytes\)/,
|
|
232
|
-
);
|
|
233
|
-
assert.equal(chunksProduced, 2);
|
|
234
|
-
assert.equal(cancellations, 1);
|
|
235
|
-
assert.equal(aborts, 1);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
test('full guard reads deterministic fixtures and downloads every declared asset', async () => {
|
|
239
|
-
const dir = await mkdtemp(join(tmpdir(), 'mixdog-release-assets-'));
|
|
240
|
-
const patch = patchFixture();
|
|
241
|
-
const runtime = runtimeFixture();
|
|
242
|
-
const graph = graphFixture();
|
|
243
|
-
const expectedUrls = new Set(
|
|
244
|
-
[...Object.values(patch.assets), ...Object.values(runtime.assets), ...Object.values(graph.assets)]
|
|
245
|
-
.map(({ url }) => url),
|
|
246
|
-
);
|
|
247
|
-
const paths = {
|
|
248
|
-
patchManifestPath: join(dir, 'patch.json'),
|
|
249
|
-
cargoPath: join(dir, 'Cargo.toml'),
|
|
250
|
-
runtimeManifestPath: join(dir, 'runtime.json'),
|
|
251
|
-
graphManifestPath: join(dir, 'graph.json'),
|
|
252
|
-
packagePath: join(dir, 'package.json'),
|
|
253
|
-
};
|
|
254
|
-
await Promise.all([
|
|
255
|
-
writeFile(paths.patchManifestPath, JSON.stringify(patch)),
|
|
256
|
-
writeFile(paths.cargoPath, `[package]\nversion = "${VERSION}"\n`),
|
|
257
|
-
writeFile(paths.runtimeManifestPath, JSON.stringify(runtime)),
|
|
258
|
-
writeFile(paths.graphManifestPath, JSON.stringify(graph)),
|
|
259
|
-
writeFile(paths.packagePath, JSON.stringify({ version: APP_VERSION })),
|
|
260
|
-
]);
|
|
261
|
-
let downloads = 0;
|
|
262
|
-
const requestedUrls = [];
|
|
263
|
-
try {
|
|
264
|
-
await verifyReleaseAssets({
|
|
265
|
-
...paths,
|
|
266
|
-
downloadOptions: {
|
|
267
|
-
attempts: 1,
|
|
268
|
-
timeoutMs: 1000,
|
|
269
|
-
fetchImpl: async (url) => {
|
|
270
|
-
downloads += 1;
|
|
271
|
-
requestedUrls.push(url);
|
|
272
|
-
return new Response(bytes);
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
});
|
|
276
|
-
} finally {
|
|
277
|
-
await rm(dir, { recursive: true, force: true });
|
|
278
|
-
}
|
|
279
|
-
assert.equal(downloads, 15);
|
|
280
|
-
assert.deepEqual(new Set(requestedUrls), expectedUrls);
|
|
281
|
-
});
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import test from 'node:test';
|
|
3
|
-
import assert from 'node:assert/strict';
|
|
4
|
-
import http from 'node:http';
|
|
5
|
-
import {
|
|
6
|
-
isLoopbackHttpUrl,
|
|
7
|
-
preDispatchDenyForSession,
|
|
8
|
-
} from '../src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs';
|
|
9
|
-
import { executeTool } from '../src/runtime/agent/orchestrator/session/loop/tool-exec.mjs';
|
|
10
|
-
import {
|
|
11
|
-
getInternalTools,
|
|
12
|
-
setInternalToolsProvider,
|
|
13
|
-
} from '../src/runtime/agent/orchestrator/internal-tools.mjs';
|
|
14
|
-
import { previewSessionTools } from '../src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs';
|
|
15
|
-
import { TOOL_DEFS as SEARCH_TOOL_DEFS } from '../src/runtime/search/tool-defs.mjs';
|
|
16
|
-
import { dispatchSearchRuntimeTool } from '../src/session-runtime/runtime-core.mjs';
|
|
17
|
-
import {
|
|
18
|
-
fetchLoopbackText,
|
|
19
|
-
fetchPublicImage,
|
|
20
|
-
} from '../src/runtime/search/lib/http-fetch.mjs';
|
|
21
|
-
|
|
22
|
-
test('pre-dispatch keeps hook-facing web_fetch name unchanged', () => {
|
|
23
|
-
const local = { name: 'web_fetch', arguments: { url: 'http://127.0.0.1:4321/status' } };
|
|
24
|
-
const image = { name: 'web_fetch', arguments: { url: 'https://cdn.example.com/a.png?x=1' } };
|
|
25
|
-
const document = { name: 'web_fetch', arguments: { url: 'https://example.com/docs' } };
|
|
26
|
-
assert.equal(preDispatchDenyForSession({}, local), null);
|
|
27
|
-
assert.equal(preDispatchDenyForSession({}, image), null);
|
|
28
|
-
assert.equal(preDispatchDenyForSession({}, document), null);
|
|
29
|
-
assert.equal(local.name, 'web_fetch');
|
|
30
|
-
assert.equal(image.name, 'web_fetch');
|
|
31
|
-
assert.equal(document.name, 'web_fetch');
|
|
32
|
-
assert.equal(isLoopbackHttpUrl('http://localhost:80/'), true);
|
|
33
|
-
assert.equal(isLoopbackHttpUrl('http://192.168.1.2/'), false);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test('hidden routed tools remain dispatchable but absent from every model schema', () => {
|
|
37
|
-
setInternalToolsProvider({
|
|
38
|
-
tools: SEARCH_TOOL_DEFS,
|
|
39
|
-
executor: async () => '',
|
|
40
|
-
});
|
|
41
|
-
const registered = getInternalTools().map((tool) => tool.name);
|
|
42
|
-
assert.equal(registered.includes('local_fetch'), true);
|
|
43
|
-
assert.equal(registered.includes('image_fetch'), true);
|
|
44
|
-
for (const spec of ['full', 'mcp', 'readonly', ['tools:mcp']]) {
|
|
45
|
-
const visible = previewSessionTools(spec, []).map((tool) => tool.name);
|
|
46
|
-
assert.equal(visible.includes('local_fetch'), false, `local_fetch leaked for ${JSON.stringify(spec)}`);
|
|
47
|
-
assert.equal(visible.includes('image_fetch'), false, `image_fetch leaked for ${JSON.stringify(spec)}`);
|
|
48
|
-
assert.equal(visible.includes('web_fetch'), true, `web_fetch missing for ${JSON.stringify(spec)}`);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('hook sees public name before routed dispatch and can change routing inputs', async () => {
|
|
53
|
-
const observed = [];
|
|
54
|
-
setInternalToolsProvider({
|
|
55
|
-
tools: SEARCH_TOOL_DEFS,
|
|
56
|
-
executor: async (name, args) => {
|
|
57
|
-
observed.push({ stage: 'dispatch', name, args });
|
|
58
|
-
return { content: [{ type: 'text', text: name }] };
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
const result = await executeTool(
|
|
62
|
-
'web_fetch',
|
|
63
|
-
{ url: 'https://example.com/document' },
|
|
64
|
-
process.cwd(),
|
|
65
|
-
'routing-order-test',
|
|
66
|
-
{
|
|
67
|
-
beforeToolHook: async ({ name, args }) => {
|
|
68
|
-
observed.push({ stage: 'hook', name, args });
|
|
69
|
-
return { action: 'modify', args: { url: 'http://127.0.0.1:4321/status' } };
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
{ toolCallId: 'routing-order-call' },
|
|
73
|
-
);
|
|
74
|
-
assert.equal(result, 'local_fetch');
|
|
75
|
-
assert.deepEqual(observed.map(({ stage, name }) => ({ stage, name })), [
|
|
76
|
-
{ stage: 'hook', name: 'web_fetch' },
|
|
77
|
-
{ stage: 'dispatch', name: 'local_fetch' },
|
|
78
|
-
]);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test('cancellation signal propagates across executeTool and runtime search dispatch', async () => {
|
|
82
|
-
const received = [];
|
|
83
|
-
setInternalToolsProvider({
|
|
84
|
-
tools: SEARCH_TOOL_DEFS,
|
|
85
|
-
executor: (name, args, callerCtx) => dispatchSearchRuntimeTool(name, args, callerCtx, {
|
|
86
|
-
getSearchModule: async () => ({
|
|
87
|
-
handleToolCall: async (_name, _args, options) => {
|
|
88
|
-
received.push({ name: _name, signal: options.signal });
|
|
89
|
-
await new Promise((resolve, reject) => {
|
|
90
|
-
if (options.signal.aborted) reject(options.signal.reason);
|
|
91
|
-
else options.signal.addEventListener('abort', () => reject(options.signal.reason), { once: true });
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
}),
|
|
95
|
-
getCurrentCwd: () => process.cwd(),
|
|
96
|
-
getSession: () => null,
|
|
97
|
-
notifyFnForSession: () => null,
|
|
98
|
-
runNativeWebSearch: async () => null,
|
|
99
|
-
}),
|
|
100
|
-
});
|
|
101
|
-
for (const [index, testCase] of [
|
|
102
|
-
{ url: 'https://example.com/document', expectedName: 'web_fetch' },
|
|
103
|
-
{ url: 'http://127.0.0.1:4321/status', expectedName: 'local_fetch' },
|
|
104
|
-
].entries()) {
|
|
105
|
-
const controller = new AbortController();
|
|
106
|
-
const running = executeTool(
|
|
107
|
-
'web_fetch',
|
|
108
|
-
{ url: testCase.url },
|
|
109
|
-
process.cwd(),
|
|
110
|
-
`cancel-test-${index}`,
|
|
111
|
-
{},
|
|
112
|
-
{ toolCallId: `cancel-call-${index}`, signal: controller.signal },
|
|
113
|
-
);
|
|
114
|
-
controller.abort(new Error(`cancelled-by-test-${index}`));
|
|
115
|
-
await assert.rejects(running, new RegExp(`cancelled-by-test-${index}`));
|
|
116
|
-
assert.equal(received[index].name, testCase.expectedName);
|
|
117
|
-
assert.equal(received[index].signal, controller.signal);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test('local_fetch reads loopback and rejects redirect escape', async (t) => {
|
|
122
|
-
const server = http.createServer((req, res) => {
|
|
123
|
-
if (req.url === '/escape') {
|
|
124
|
-
res.writeHead(302, { location: 'http://169.254.169.254/latest/meta-data/' });
|
|
125
|
-
res.end();
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
res.writeHead(200, { 'content-type': 'text/plain' });
|
|
129
|
-
res.end('local-ok');
|
|
130
|
-
});
|
|
131
|
-
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
132
|
-
t.after(() => server.close());
|
|
133
|
-
const { port } = server.address();
|
|
134
|
-
assert.equal(await fetchLoopbackText(`http://127.0.0.1:${port}/ok`), 'local-ok');
|
|
135
|
-
await assert.rejects(fetchLoopbackText(`http://127.0.0.1:${port}/escape`), /non-loopback/);
|
|
136
|
-
await assert.rejects(fetchLoopbackText('http://10.0.0.1/'), /non-loopback/);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('public image fetch is bounded, media-shaped, and blocks private redirect targets', async () => {
|
|
140
|
-
const png = Buffer.from('89504e470d0a1a0a', 'hex');
|
|
141
|
-
const okFetch = async () => new Response(png, {
|
|
142
|
-
status: 200,
|
|
143
|
-
headers: { 'content-type': 'image/png', 'content-length': String(png.length) },
|
|
144
|
-
});
|
|
145
|
-
const image = await fetchPublicImage('https://images.example.com/a.png', { fetchImpl: okFetch });
|
|
146
|
-
assert.deepEqual(image, { mimeType: 'image/png', data: png.toString('base64'), bytes: png.length });
|
|
147
|
-
|
|
148
|
-
let calls = 0;
|
|
149
|
-
const redirectFetch = async () => {
|
|
150
|
-
calls++;
|
|
151
|
-
return new Response(null, { status: 302, headers: { location: 'http://169.254.169.254/latest/meta-data/' } });
|
|
152
|
-
};
|
|
153
|
-
await assert.rejects(
|
|
154
|
-
fetchPublicImage('https://images.example.com/a.png', { fetchImpl: redirectFetch }),
|
|
155
|
-
/private address/,
|
|
156
|
-
);
|
|
157
|
-
assert.equal(calls, 1);
|
|
158
|
-
});
|