mixdog 1.3.0 → 1.3.2
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/NOTICE.md +52 -9
- package/README.md +8 -4
- package/package.json +2 -2
- package/scripts/native-release-status.mjs +238 -0
- package/src/defaults/shipped-history.json +8 -1
- package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
- package/src/defaults/skills/setup/SKILL.md +23 -1
- package/src/defaults/skills/setup/references/actions.md +54 -4
- package/src/defaults/skills/setup/references/surfaces.md +23 -3
- package/src/defaults/skills/setup-guide/SKILL.md +17 -10
- package/src/defaults/skills/visualize/SKILL.md +9 -6
- package/src/defaults/skills/visualize/references/craft.md +8 -1
- package/src/help.mjs +1 -1
- package/src/lib/keychain-cjs.cjs +4 -1
- package/src/lib/rules-builder.cjs +14 -7
- package/src/output-styles/common.md +13 -8
- package/src/rules/agent-mode/AGENT_MODE.md +9 -6
- package/src/rules/agent-mode/MIXY.md +11 -6
- package/src/rules/lead/LEAD.md +2 -2
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/20-research.md +2 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
- package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
- package/src/runtime/agent/orchestrator/config.mjs +11 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +81 -16
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -4
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +6 -10
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +80 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +67 -38
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +34 -16
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +19 -1
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -0
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -1
- package/src/runtime/agent/orchestrator/providers/mixdog-local.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +5 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +10 -2
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +30 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +14 -2
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
- package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +5 -5
- package/src/runtime/agent/orchestrator/runtime-core/route-context-state.mjs +81 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +12 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +17 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +41 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +21 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +149 -45
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +14 -11
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +68 -18
- package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
- package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +156 -25
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +21 -9
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +189 -105
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +111 -9
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -14
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +38 -5
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +46 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +99 -0
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +62 -47
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +6 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +42 -10
- package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +35 -4
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +179 -16
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +8 -3
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +36 -1
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +49 -14
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +134 -17
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +35 -13
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +6 -14
- package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +34 -21
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
- package/src/runtime/attachments/attachment-reference.mjs +155 -0
- package/src/runtime/attachments/limits.mjs +5 -1
- package/src/runtime/attachments/office-extract.mjs +3 -6
- package/src/runtime/attachments/pdf-extract.mjs +84 -10
- package/src/runtime/attachments/store.mjs +55 -30
- package/src/runtime/browser-bridge/client.mjs +73 -20
- package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
- package/src/runtime/channels/lib/scheduler.mjs +14 -7
- package/src/runtime/channels/lib/state-file.mjs +15 -15
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
- package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
- package/src/runtime/channels/lib/worker-main.mjs +3 -2
- package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
- package/src/runtime/effort-judge/judge-client.mjs +6 -3
- package/src/runtime/effort-judge/model-install.mjs +16 -8
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- package/src/runtime/local-provider/asset-installer.mjs +10 -4
- package/src/runtime/local-provider/catalog.mjs +5 -2
- package/src/runtime/local-provider/registered-models.mjs +64 -27
- package/src/runtime/local-provider/server.mjs +2 -3
- package/src/runtime/media/adapters/image-api.mjs +89 -0
- package/src/runtime/media/auth.mjs +64 -1
- package/src/runtime/media/catalog.mjs +66 -4
- package/src/runtime/media/jobs.mjs +4 -0
- package/src/runtime/media/lanes.mjs +46 -5
- package/src/runtime/media/media-usage.mjs +17 -0
- package/src/runtime/media/renditions.mjs +15 -15
- package/src/runtime/media/store.mjs +36 -35
- package/src/runtime/media/tool.mjs +8 -1
- package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
- package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
- package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
- package/src/runtime/memory/lib/pg/process.mjs +8 -4
- package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
- package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
- package/src/runtime/office/core/journal.mjs +7 -14
- package/src/runtime/office/design/library/design-library-core.mjs +4 -16
- package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
- package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
- package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
- package/src/runtime/office/pdf/pdf-render.mjs +30 -18
- package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +4 -0
- package/src/runtime/shared/agent-kind-migration.mjs +200 -0
- package/src/runtime/shared/agent-kind.mjs +152 -0
- package/src/runtime/shared/agent-message-envelope.d.mts +6 -0
- package/src/runtime/shared/agent-message-envelope.mjs +44 -0
- package/src/runtime/shared/agent-reap-state.d.mts +4 -0
- package/src/runtime/shared/agent-route-config.d.mts +1 -0
- package/src/runtime/shared/agent-route-config.mjs +22 -8
- package/src/runtime/shared/agent-store.mjs +149 -0
- package/src/runtime/shared/agent-task-starts.mjs +27 -0
- package/src/runtime/shared/atomic-file.d.mts +50 -0
- package/src/runtime/shared/atomic-file.mjs +394 -132
- package/src/runtime/shared/background-tasks.mjs +7 -4
- package/src/runtime/shared/bot-hops.mjs +30 -0
- package/src/runtime/shared/bot-split-migration.mjs +457 -0
- package/src/runtime/shared/bounded-download.mjs +4 -2
- package/src/runtime/shared/config-patch.mjs +20 -1
- package/src/runtime/shared/config.mjs +39 -9
- package/src/runtime/shared/connector-catalog.d.mts +1 -2
- package/src/runtime/shared/connector-catalog.mjs +2 -4
- package/src/runtime/shared/connector-triggers.mjs +2 -0
- package/src/runtime/shared/defaults-separation.mjs +6 -2
- package/src/runtime/shared/delegated-approval-host.mjs +74 -0
- package/src/runtime/shared/err-text.mjs +7 -1
- package/src/runtime/shared/error-presentation.mjs +113 -10
- package/src/runtime/shared/file-has-data.mjs +28 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
- package/src/runtime/shared/handoff-artifacts.mjs +61 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
- package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
- package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
- package/src/runtime/shared/model-route-fallback.mjs +79 -7
- package/src/runtime/shared/pending-agent-work.mjs +54 -0
- package/src/runtime/shared/plain-preview.mjs +22 -17
- package/src/runtime/shared/process-lifecycle.mjs +8 -12
- package/src/runtime/shared/projects.mjs +50 -41
- package/src/runtime/shared/provider-accounts.mjs +17 -12
- package/src/runtime/shared/routine-trigger.d.mts +6 -1
- package/src/runtime/shared/routine-trigger.mjs +14 -6
- package/src/runtime/shared/run-child.d.mts +3 -0
- package/src/runtime/shared/run-child.mjs +24 -3
- package/src/runtime/shared/sensitive-path-rules.d.mts +15 -0
- package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
- package/src/runtime/shared/session-baseline-store.mjs +8 -2
- package/src/runtime/shared/singleton-owner.mjs +7 -6
- package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
- package/src/runtime/shared/staged-update.mjs +4 -2
- package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
- package/src/runtime/shared/tool-execution-contract.mjs +6 -0
- package/src/runtime/shared/transcript-metadata.mjs +28 -3
- package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
- package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
- package/src/runtime/shared/turn-snapshot.mjs +44 -2
- package/src/runtime/shared/usage-readout-totals.mjs +15 -13
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +46 -44
- package/src/runtime/shared/utf8-cut.mjs +10 -0
- package/src/runtime/shared/worktrees/activity-gate.mjs +269 -61
- package/src/runtime/shared/worktrees/registry.mjs +26 -26
- package/src/runtime/tidy/core-install.mjs +26 -4
- package/src/runtime/tidy/install.mjs +91 -23
- package/src/runtime/web-search/lib/config.mjs +4 -16
- package/src/session-runtime/agent-home-delivery.mjs +859 -136
- package/src/session-runtime/agent-room-delivery.mjs +167 -19
- package/src/session-runtime/agent-task-sessions.mjs +831 -69
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +58 -24
- package/src/session-runtime/boot/config.mjs +1 -0
- package/src/session-runtime/boot/facade.mjs +11 -1
- package/src/session-runtime/boot/infrastructure.mjs +14 -2
- package/src/session-runtime/boot/providers.mjs +16 -6
- package/src/session-runtime/boot/shared.mjs +12 -6
- package/src/session-runtime/boot/tools.mjs +2 -2
- package/src/session-runtime/bot-status.mjs +432 -0
- package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
- package/src/session-runtime/config-lifecycle.mjs +78 -32
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/handoff-attachments.mjs +593 -0
- package/src/session-runtime/held-requests.mjs +36 -33
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +45 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown.mjs +11 -3
- package/src/session-runtime/mcp-glue/connect.mjs +100 -186
- package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
- package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
- package/src/session-runtime/media-api.mjs +5 -2
- package/src/session-runtime/model-route/route-persist.mjs +2 -2
- package/src/session-runtime/model-route/route-tuning.mjs +11 -2
- package/src/session-runtime/model-route/set-route.mjs +82 -2
- package/src/session-runtime/native-web-search.mjs +2 -2
- package/src/session-runtime/new-session-config.mjs +6 -1
- package/src/session-runtime/owned-automation-run.mjs +8 -1
- package/src/session-runtime/room-member-gate.mjs +16 -3
- package/src/session-runtime/route-resolution.mjs +21 -19
- package/src/session-runtime/route-state.mjs +1 -59
- package/src/session-runtime/routine-home-turn.mjs +5 -3
- package/src/session-runtime/runtime-bootstrap.mjs +5 -3
- package/src/session-runtime/runtime-paths.mjs +11 -5
- package/src/session-runtime/runtime-tunables.mjs +6 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +11 -2
- package/src/session-runtime/services/agent-tool/close-flow.mjs +4 -2
- package/src/session-runtime/services/agent-tool/execute-send.mjs +1 -0
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +1 -0
- package/src/session-runtime/services/agent-tool/helpers.mjs +24 -5
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +36 -24
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +12 -6
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +22 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +4 -6
- package/src/session-runtime/services/agent-tool.mjs +6 -0
- package/src/session-runtime/services/daemon-crash-capture/daemon-exit-record.mjs +1 -1
- package/src/session-runtime/services/daemon-crash-capture/retention.mjs +4 -3
- package/src/session-runtime/services/hook-bus/config-loader.mjs +14 -5
- package/src/session-runtime/services/hook-bus/rule-file.mjs +49 -11
- package/src/session-runtime/services/plugin-admin.mjs +26 -26
- package/src/session-runtime/services/provider-admin.mjs +14 -4
- package/src/session-runtime/services/schedule-access.mjs +33 -4
- package/src/session-runtime/services/seeds.mjs +4 -3
- package/src/session-runtime/services/usage-dashboard.mjs +1 -1
- package/src/session-runtime/services/usage-stats-model.mjs +2 -1
- package/src/session-runtime/session-create/materialize.mjs +2 -3
- package/src/session-runtime/session-create/session-options.mjs +15 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +63 -1
- package/src/session-runtime/settings-compaction-api.mjs +86 -39
- package/src/session-runtime/setup-tool/executor.mjs +20 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +19 -7
- package/src/session-runtime/setup-tool/settings-contract.mjs +37 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
- package/src/session-runtime/skills-api.mjs +12 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +265 -0
- package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
- package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
- package/src/session-runtime/tool-policy/policy-stage.mjs +165 -0
- package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
- package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
- package/src/session-runtime/tool-policy-refresh.mjs +47 -358
- package/src/session-runtime/tool-surface.mjs +5 -3
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +99 -81
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +2 -1
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +578 -301
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +113 -53
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
- package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
- package/src/session-runtime/workspace/workspace-state.mjs +7 -6
- package/src/standalone/daemon-agent-control.mjs +4 -1
- package/src/standalone/daemon-session-control.mjs +60 -11
- package/src/standalone/daemon.mjs +34 -4
- package/src/standalone/local-session-runtime.mjs +22 -14
- package/src/standalone/session-client.mjs +7 -2
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +46 -3
- package/src/standalone/session-service/agent-tree.mjs +4 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +19 -0
- package/src/standalone/session-service.mjs +11 -0
- package/src/standalone/session-state-projection.mjs +19 -9
- package/src/standalone/session-tool-output.mjs +35 -9
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
- package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
- package/src/tui/dist/index.mjs +599 -342
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/notice-surface.mjs +3 -4
- package/src/tui/session/session-api/intake/abort.mjs +19 -1
- package/src/tui/session/session-api/media.mjs +2 -1
- package/src/tui/session/session-api/routes-agent-definitions.mjs +75 -0
- package/src/tui/session/session-api/routes-write.mjs +203 -0
- package/src/tui/session/session-api/routes.mjs +23 -236
- package/src/tui/session/session-api/settings.mjs +14 -1
- package/src/tui/session/session-flow/drain.mjs +28 -3
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +4 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +8 -3
- package/src/tui/session/tool-approval.mjs +185 -20
- package/src/tui/session/transcript-intake.mjs +4 -0
- package/src/tui/session/turn-live-call.mjs +11 -3
- package/src/tui/session/turn.mjs +36 -17
- package/src/tui/transcript-tool-failures.mjs +8 -2
- package/src/vendor/statusline/src/gateway/route-meta.mjs +7 -8
- package/src/vendor/statusline/src/gateway/session-routes.mjs +6 -7
- package/src/rules/agent-mode/ROUTINE.md +0 -6
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* consume a retry verdict, and settle a completed send into the loop state.
|
|
5
5
|
*/
|
|
6
6
|
import { traceCacheBreak } from '../../cache-break-trace.mjs';
|
|
7
|
+
import { anthropicPrefixChanges } from '../../providers/lib/anthropic-prefix-trace.mjs';
|
|
7
8
|
import { resolveLiveToolCwd } from './tool-exec.mjs';
|
|
8
9
|
import { notifySkillsApplied, prepareExplicitSkills, recordAppliedSkills } from '../explicit-skills.mjs';
|
|
9
10
|
import { addUsage, usageDeltaEvent } from './usage.mjs';
|
|
10
|
-
import { isVisibleStreamProgress } from '../../../../shared/stream-progress.mjs';
|
|
11
11
|
import { prepareProviderRequest } from './request-boundary.mjs';
|
|
12
12
|
import { applyStepEffort } from './step-auto-effort.mjs';
|
|
13
13
|
import { projectProviderRequest } from './request-projection.mjs';
|
|
@@ -182,15 +182,10 @@ export async function sendProviderRequest(state, round) {
|
|
|
182
182
|
tools: round.sendTools,
|
|
183
183
|
opts,
|
|
184
184
|
});
|
|
185
|
-
// The
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
const observeStreamDelta = (kind, ...rest) => {
|
|
190
|
-
if (!firstVisibleAt && isVisibleStreamProgress(kind)) firstVisibleAt = Date.now();
|
|
191
|
-
return callerOnStreamDelta?.(kind, ...rest);
|
|
192
|
-
};
|
|
193
|
-
opts.onStreamDelta = observeStreamDelta;
|
|
185
|
+
// The request's time for the speed figures, the wait for the first token
|
|
186
|
+
// included: the span the usage ledger recorded as `duration_ms` (stamped on
|
|
187
|
+
// the response); wall time only for a response no ledger row timed.
|
|
188
|
+
const requestStartedAt = Date.now();
|
|
194
189
|
let result;
|
|
195
190
|
try {
|
|
196
191
|
result = await runWithProviderRequestToolsScope(round.requestToolScope, () =>
|
|
@@ -218,8 +213,6 @@ export async function sendProviderRequest(state, round) {
|
|
|
218
213
|
sideQuestion?.discard();
|
|
219
214
|
if (!(await advanceAgentRoute(state, error))) throw error;
|
|
220
215
|
result = { action: 'retry_route' };
|
|
221
|
-
} finally {
|
|
222
|
-
if (opts.onStreamDelta === observeStreamDelta) opts.onStreamDelta = callerOnStreamDelta;
|
|
223
216
|
}
|
|
224
217
|
if (result.action === 'proceed') sideQuestion?.settle(result.response);
|
|
225
218
|
else sideQuestion?.discard();
|
|
@@ -230,7 +223,9 @@ export async function sendProviderRequest(state, round) {
|
|
|
230
223
|
prefixGuardCandidate,
|
|
231
224
|
sendStartedAt,
|
|
232
225
|
sendEndedAt,
|
|
233
|
-
|
|
226
|
+
requestMs: Number.isFinite(result.response?.usageDurationMs)
|
|
227
|
+
? Math.max(0, result.response.usageDurationMs)
|
|
228
|
+
: Math.max(0, sendEndedAt - requestStartedAt),
|
|
234
229
|
preSendMs,
|
|
235
230
|
toolResumeMs,
|
|
236
231
|
};
|
|
@@ -358,6 +353,8 @@ function traceActualCacheMiss(state, sent, response, { previousGuardState, previ
|
|
|
358
353
|
previousCachedPrefixTokens: baseline,
|
|
359
354
|
idleMs,
|
|
360
355
|
missingPrefixGuardBaseline: !previousGuardState,
|
|
356
|
+
// Which wire block moved ('none': same bytes, so the cache itself dropped it).
|
|
357
|
+
...anthropicPrefixChanges(sessionId),
|
|
361
358
|
},
|
|
362
359
|
state.cacheBreakTraceOptions
|
|
363
360
|
);
|
|
@@ -443,7 +440,7 @@ export function settleSendResult(state, round, sent) {
|
|
|
443
440
|
usage: reportedUsage,
|
|
444
441
|
sendTools: round.sendTools,
|
|
445
442
|
toolCalls: response.toolCalls?.length || 0,
|
|
446
|
-
|
|
443
|
+
requestMs: sent.requestMs,
|
|
447
444
|
})
|
|
448
445
|
)
|
|
449
446
|
);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Steering-message normalization/merge helpers.
|
|
2
2
|
// Merges queued steering entries into a single content payload + display text.
|
|
3
3
|
import { stableMessageId } from '../../../../shared/transcript-metadata.mjs';
|
|
4
|
+
import { raiseTurnHop } from '../../../../shared/bot-hops.mjs';
|
|
4
5
|
|
|
5
6
|
function steeringContentText(content) {
|
|
6
7
|
if (typeof content === 'string') return content;
|
|
@@ -140,6 +141,8 @@ function injectSteeringEntry(merged, { messages, opts, stage, onSkillPrompt }) {
|
|
|
140
141
|
// gets it back (onSteerMessage) for the row it draws. A steered prompt
|
|
141
142
|
// keeps the id the surface gave it, else gets one.
|
|
142
143
|
const messageId = stableMessageId(merged.transcriptMeta?.messageId);
|
|
144
|
+
// A bot's message at a higher hop makes the running turn bot-descended at that hop.
|
|
145
|
+
raiseTurnHop(opts.session, merged.transcriptMeta);
|
|
143
146
|
const steeringTranscriptMeta =
|
|
144
147
|
merged.transcriptMeta && typeof merged.transcriptMeta === 'object'
|
|
145
148
|
? { at: submittedAt ?? injectedAt, ...merged.transcriptMeta, messageId }
|
|
@@ -6,15 +6,20 @@ import { resolvePreToolAskApproval } from '../tool-helpers.mjs';
|
|
|
6
6
|
import { runAbortable, throwIfAborted } from '../../../../../shared/abort-race.mjs';
|
|
7
7
|
import { evaluateExecPolicy } from '../../../tools/bash-policy-scan.mjs';
|
|
8
8
|
import { beginSessionApprovalWait } from '../../manager/runtime-liveness.mjs';
|
|
9
|
-
import { agentMcpToolPermission } from '../../../mcp/agent-connectors.mjs';
|
|
10
|
-
import {
|
|
9
|
+
import { agentMcpToolPermission, writeAgentMcpToolPermission } from '../../../mcp/agent-connectors.mjs';
|
|
10
|
+
import {
|
|
11
|
+
actingContactBotId,
|
|
12
|
+
humanGateDecision,
|
|
13
|
+
recordHumanDecision,
|
|
14
|
+
rememberSurfaceOf,
|
|
15
|
+
} from '../../human-gate/gate.mjs';
|
|
11
16
|
import { applyEditedArgs } from '../../human-gate/requests.mjs';
|
|
12
17
|
|
|
13
18
|
const isArgsObject = (value) => value && typeof value === 'object' && !Array.isArray(value);
|
|
14
19
|
|
|
15
20
|
async function askApproval(
|
|
16
21
|
call,
|
|
17
|
-
{ callerSessionId, executeOpts, toolApprovalHook, decision, request = null, gate = null }
|
|
22
|
+
{ callerSessionId, executeOpts, toolApprovalHook, decision, request = null, gate = null, onApproved = null }
|
|
18
23
|
) {
|
|
19
24
|
const askReason = String(decision?.reason || 'approval requested by hook').trim();
|
|
20
25
|
// While the user decides, the session is waiting on them, not working.
|
|
@@ -46,26 +51,52 @@ async function askApproval(
|
|
|
46
51
|
}
|
|
47
52
|
// The user approved this very call on the richer outbound card.
|
|
48
53
|
if (request?.kind === 'outbound') call.outboundApproved = true;
|
|
54
|
+
await onApproved?.(approval);
|
|
49
55
|
return null;
|
|
50
56
|
}
|
|
51
57
|
|
|
58
|
+
/** The renderer translates this exact text (desktop-toasts.tsx ALLOW_NOT_SAVED_TEXT). */
|
|
59
|
+
export const ALLOW_NOT_SAVED_NOTICE = 'Allowed this once. The setting could not be saved.';
|
|
52
60
|
export const CONNECTOR_APPROVAL_REASON = 'This connector tool is set to ask before it runs for this agent.';
|
|
53
61
|
|
|
54
62
|
/**
|
|
55
63
|
* A connector tool the running agent set to `needs_approval` asks through the
|
|
56
64
|
* ordinary approval hook, whatever the PreToolUse hooks decided. Run after
|
|
57
65
|
* them, on the final call: a renamed call is judged under its final name.
|
|
58
|
-
* A call the outbound
|
|
66
|
+
* A call the outbound gate owns (its card approved it, or a remembered
|
|
67
|
+
* outbound grant answered it) is not asked a second time.
|
|
59
68
|
* @returns {Promise<{ denial: string } | null>} the denial, or null to run
|
|
60
69
|
*/
|
|
61
70
|
export function applyConnectorApproval(call, { agentId, callerSessionId, executeOpts, toolApprovalHook }) {
|
|
62
71
|
if (call.outboundApproved) return null;
|
|
63
72
|
if (agentMcpToolPermission(agentId, call.name) !== 'needs_approval') return null;
|
|
73
|
+
// "Always allow" is offered only to the contact bot that is acting, for its
|
|
74
|
+
// own policy entry for this one tool: never another bot, Mixy or the Lead.
|
|
75
|
+
const botId = actingContactBotId(callerSessionId);
|
|
76
|
+
const rememberable = Boolean(botId) && botId === agentId;
|
|
64
77
|
return askApproval(call, {
|
|
65
78
|
callerSessionId,
|
|
66
79
|
executeOpts,
|
|
67
80
|
toolApprovalHook,
|
|
68
81
|
decision: { reason: CONNECTOR_APPROVAL_REASON },
|
|
82
|
+
request: rememberable
|
|
83
|
+
? {
|
|
84
|
+
kind: 'approval',
|
|
85
|
+
agentId: botId,
|
|
86
|
+
remember: ['once', 'agent'],
|
|
87
|
+
rememberAt: rememberSurfaceOf(callerSessionId),
|
|
88
|
+
}
|
|
89
|
+
: null,
|
|
90
|
+
onApproved: async (approval) => {
|
|
91
|
+
if (!rememberable || approval?.remember !== 'agent') return;
|
|
92
|
+
try {
|
|
93
|
+
if (await writeAgentMcpToolPermission(botId, call.name, 'auto')) return;
|
|
94
|
+
} catch {
|
|
95
|
+
// fall through to the notice below
|
|
96
|
+
}
|
|
97
|
+
// Not saved: this call still runs once, and the next one asks again.
|
|
98
|
+
toolApprovalHook?.notice?.(ALLOW_NOT_SAVED_NOTICE, 'warn');
|
|
99
|
+
},
|
|
69
100
|
});
|
|
70
101
|
}
|
|
71
102
|
|
|
@@ -120,7 +151,7 @@ export async function applyBeforeToolHook({
|
|
|
120
151
|
// Judged as the call will run: only a rewriting decision changes name/args.
|
|
121
152
|
const hookAction = String(hookDecision?.action || hookDecision?.decision || '').toLowerCase();
|
|
122
153
|
const rewritten = hookAction === 'ask' || hookAction === 'modify' || hookAction === 'rewrite';
|
|
123
|
-
const { decision, request, gate } = await humanGateDecision(
|
|
154
|
+
const { decision, request, gate, remembered } = await humanGateDecision(
|
|
124
155
|
{
|
|
125
156
|
name:
|
|
126
157
|
rewritten && typeof hookDecision?.name === 'string' && hookDecision.name.trim()
|
|
@@ -132,6 +163,8 @@ export async function applyBeforeToolHook({
|
|
|
132
163
|
{ sessionId: callerSessionId, mcpScopeId }
|
|
133
164
|
);
|
|
134
165
|
const action = String(decision?.action || decision?.decision || '').toLowerCase();
|
|
166
|
+
// A remembered outbound grant answered this call: the connector ask is not repeated.
|
|
167
|
+
if (remembered) call.outboundApproved = true;
|
|
135
168
|
if (action === 'deny' || action === 'block') {
|
|
136
169
|
const reason = decision?.reason ? `: ${decision.reason}` : '';
|
|
137
170
|
return { denial: `Error: tool "${name}" denied by hook${reason}` };
|
|
@@ -17,6 +17,26 @@ import { isOnDeferredToolSurface } from '../deferred-call-through.mjs';
|
|
|
17
17
|
import { _executeCodeGraphToolLazy } from '../../manager/runtime-loaders.mjs';
|
|
18
18
|
import { requiresReadBody } from '../tool-classify.mjs';
|
|
19
19
|
import { executeCursorNativeBuiltin } from '../../../tools/builtin/external-tool-adapters.mjs';
|
|
20
|
+
import { providerNativePdf, providerReadsImages } from '../../../providers/registry.mjs';
|
|
21
|
+
import { getModelMetadataSync } from '../../../../../shared/llm/model-catalog.mjs';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* How read returns a PDF to this session's model. Native PDF support decides
|
|
25
|
+
* only whether a short PDF may arrive whole as a document block. A scanned
|
|
26
|
+
* page arrives as a page image whenever the model sees images — the provider
|
|
27
|
+
* sends image input (only the text-only local runtime does not) and the
|
|
28
|
+
* catalog does not say the model lacks it — and as OCR text otherwise.
|
|
29
|
+
*/
|
|
30
|
+
export function pdfReadModes(
|
|
31
|
+
sessionRef,
|
|
32
|
+
{ nativePdf = providerNativePdf, readsImages = providerReadsImages, catalogRow = getModelMetadataSync } = {}
|
|
33
|
+
) {
|
|
34
|
+
const provider = sessionRef?.provider;
|
|
35
|
+
const model = sessionRef?.model;
|
|
36
|
+
const seesImages =
|
|
37
|
+
readsImages(provider) && (model ? catalogRow(model, provider)?.supportsVision : undefined) !== false;
|
|
38
|
+
return { pdfPageMode: seesImages ? 'image' : 'ocr', pdfNativeDocument: nativePdf(provider) };
|
|
39
|
+
}
|
|
20
40
|
|
|
21
41
|
function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts }) {
|
|
22
42
|
const mcpScopeId = sessionRef?.mcpScopeId || null;
|
|
@@ -107,6 +127,7 @@ export function dispatchToolCall({ name, args }, ctx) {
|
|
|
107
127
|
: {}),
|
|
108
128
|
// Runtime-granted only; any value inherited from executeOpts is overridden.
|
|
109
129
|
elevationApproved: ctx.elevationApproved === true,
|
|
130
|
+
...pdfReadModes(sessionRef),
|
|
110
131
|
};
|
|
111
132
|
return executeCursorNativeBuiltin(
|
|
112
133
|
name,
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// tool-exec/after-hook.mjs — PostToolUse result override
|
|
7
7
|
// tool-exec/read-only-deadline.mjs — bounded read-only I/O with partial-output grace
|
|
8
8
|
import { isMcpTool } from '../../mcp/client.mjs';
|
|
9
|
+
import { connectorPolicyAgentOf } from '../../mcp/agent-connectors.mjs';
|
|
9
10
|
import { prepareDeferredToolCallThrough } from './deferred-call-through.mjs';
|
|
10
11
|
import { refreshDeferredMcpToolCatalog } from '../../runtime-core/tool-catalog.mjs';
|
|
11
12
|
import { bridgeTargetUnavailable } from '../../runtime-core/tool-bridge.mjs';
|
|
@@ -54,7 +55,7 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
|
|
|
54
55
|
});
|
|
55
56
|
if (hooked.denial) return hooked.denial;
|
|
56
57
|
const connectorDenied = await applyConnectorApproval(hooked, {
|
|
57
|
-
agentId: sessionRef
|
|
58
|
+
agentId: connectorPolicyAgentOf(sessionRef),
|
|
58
59
|
callerSessionId,
|
|
59
60
|
executeOpts,
|
|
60
61
|
toolApprovalHook,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
bridgeSurfaceOutdated,
|
|
9
9
|
sessionToolExposure,
|
|
10
10
|
TOOL_EXPOSURE_BRIDGE,
|
|
11
|
+
TOOL_EXPOSURE_NATIVE,
|
|
11
12
|
TOOL_SURFACE_MIGRATION_INTENT,
|
|
12
13
|
toolExposureMigrationNeeded,
|
|
13
14
|
toolExposureModeForProvider,
|
|
@@ -122,6 +123,17 @@ export function applyAgentToolExposure(session, { existing = false } = {}) {
|
|
|
122
123
|
const bridge =
|
|
123
124
|
!allowlisted && toolExposureModeForProvider(session.provider, session.wireRoute) === TOOL_EXPOSURE_BRIDGE;
|
|
124
125
|
if (!bridge && before === null) return false;
|
|
126
|
+
// A native deferred surface (the session runtime builds one) stays one:
|
|
127
|
+
// re-selected over the tools just resolved, never stripped to the full
|
|
128
|
+
// array. Native → native is no exposure change, so nothing is tagged.
|
|
129
|
+
if (!bridge && before === TOOL_EXPOSURE_NATIVE) {
|
|
130
|
+
session.tools = session.tools.slice();
|
|
131
|
+
applyDeferredToolSurface(session, session.deferredSurfaceMode || 'full', [], {
|
|
132
|
+
provider: session.provider,
|
|
133
|
+
model: session.model,
|
|
134
|
+
});
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
125
137
|
// A surface an earlier bridge revision built is rebuilt now.
|
|
126
138
|
const outdated = bridgeSurfaceOutdated(session);
|
|
127
139
|
// The tools just resolved are the whole authority: no earlier catalog, MCP
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// native tool-search payload parsing, bash-session routing, and approval.
|
|
4
4
|
import { isMcpTool } from '../../mcp/client.mjs';
|
|
5
5
|
import { unattendedApprovalPort } from '../human-gate/gate.mjs';
|
|
6
|
+
import { isGrantedRun, runAskOutcome } from '../human-gate/run-policy.mjs';
|
|
6
7
|
import { isBuiltinTool } from '../../tools/builtin.mjs';
|
|
7
8
|
import { isInternalTool } from '../../internal-tools.mjs';
|
|
8
9
|
import { loadSkillToolDependencies } from '../../runtime-core/skill-tool-loading.mjs';
|
|
@@ -212,12 +213,13 @@ export async function resolvePreToolAskApproval({
|
|
|
212
213
|
}) {
|
|
213
214
|
const name = String(toolName || 'tool');
|
|
214
215
|
const reason = String(askReason || 'approval requested by hook').trim();
|
|
215
|
-
//
|
|
216
|
-
// run
|
|
216
|
+
// A schedule or webhook run never asks: saving it was the user's grant
|
|
217
|
+
// (human-gate/run-policy.mjs). A room member is held for its owner when no
|
|
217
218
|
// approval UI is attached (session-runtime/held-requests.mjs).
|
|
218
219
|
const unattended = unattendedApprovalPort();
|
|
219
220
|
const run = unattended?.runOf?.(sessionId) || null;
|
|
220
|
-
|
|
221
|
+
if (isGrantedRun(run)) return runAskOutcome({ name, request });
|
|
222
|
+
const held = run && typeof toolApprovalHook !== 'function';
|
|
221
223
|
const ask = held ? unattended.hold : toolApprovalHook;
|
|
222
224
|
if (typeof ask !== 'function') {
|
|
223
225
|
return { denial: formatMissingToolApprovalUiDenial(name, reason) };
|
|
@@ -238,8 +240,12 @@ export async function resolvePreToolAskApproval({
|
|
|
238
240
|
return { denial: `Error: tool "${name}" denied by hook: ${detail}` };
|
|
239
241
|
}
|
|
240
242
|
if (!approvalGranted(approval)) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
+
// A person (or the hold for one) said no: never a policy hook to work around.
|
|
244
|
+
const detail = String(approvalReason(approval, reason || 'not approved')).replace(/[.\s]+$/, '');
|
|
245
|
+
return {
|
|
246
|
+
denial: `Error: tool "${name}" was not approved: ${detail}. Do not retry it or reach the same result another way; report it.`,
|
|
247
|
+
approval,
|
|
248
|
+
};
|
|
243
249
|
}
|
|
244
250
|
return { approval };
|
|
245
251
|
}
|
|
@@ -41,7 +41,7 @@ export function usageDeltaEvent({
|
|
|
41
41
|
usage,
|
|
42
42
|
sendTools,
|
|
43
43
|
toolCalls = 0,
|
|
44
|
-
|
|
44
|
+
requestMs = 0,
|
|
45
45
|
}) {
|
|
46
46
|
return {
|
|
47
47
|
sessionId,
|
|
@@ -57,9 +57,10 @@ export function usageDeltaEvent({
|
|
|
57
57
|
deltaToolCalls: toolCalls,
|
|
58
58
|
...reasoningUsage(usage),
|
|
59
59
|
deltaPrompt: usage.promptTokens || 0,
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
|
|
60
|
+
// Request start → end of this response (first-token wait included, as the
|
|
61
|
+
// ledger's duration_ms); 0 when the call was not timed. Only timed output
|
|
62
|
+
// enters speed figures.
|
|
63
|
+
requestMs,
|
|
63
64
|
// A provider that cannot measure the prompt or its cache split says so;
|
|
64
65
|
// its zeros are unknowns, not readings (no cache hit can be derived).
|
|
65
66
|
promptKnown: usage.inputTokensKnown !== false && usage.cacheTokensKnown !== false,
|
|
@@ -79,6 +80,47 @@ export function usageDeltaEvent({
|
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
const SUMMED_USAGE_FIELDS = [
|
|
84
|
+
'inputTokens',
|
|
85
|
+
'outputTokens',
|
|
86
|
+
'cachedTokens',
|
|
87
|
+
'cacheWriteTokens',
|
|
88
|
+
'cacheWrite1hTokens',
|
|
89
|
+
'promptTokens',
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
/** What `total` added after the running total `earlier` (both from addUsage); null when nothing. */
|
|
93
|
+
export function usageSince(total, earlier) {
|
|
94
|
+
if (!total) return null;
|
|
95
|
+
if (!earlier) return { ...total };
|
|
96
|
+
const delta = {};
|
|
97
|
+
for (const field of SUMMED_USAGE_FIELDS) delta[field] = Math.max(0, (total[field] || 0) - (earlier[field] || 0));
|
|
98
|
+
if (total.reasoningTokens != null) {
|
|
99
|
+
delta.reasoningTokens = Math.max(0, total.reasoningTokens - (earlier.reasoningTokens ?? 0));
|
|
100
|
+
delta.reasoningTokensComplete = total.reasoningTokensComplete === true;
|
|
101
|
+
}
|
|
102
|
+
if (total.costUsd != null) delta.costUsd = Math.max(0, total.costUsd - (earlier.costUsd || 0));
|
|
103
|
+
if (total.contextTokens) delta.contextTokens = total.contextTokens;
|
|
104
|
+
return Object.values(delta).some((value) => typeof value === 'number' && value > 0) ? delta : null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The turn's usage split per model when the route switched mid-turn:
|
|
109
|
+
* `hops` holds, per left model, the running total when it was left. Each
|
|
110
|
+
* segment carries only its own tokens so it is priced at its own rates.
|
|
111
|
+
*/
|
|
112
|
+
export function routeUsageSegments(hops, total, current) {
|
|
113
|
+
if (!Array.isArray(hops) || !hops.length) return null;
|
|
114
|
+
const boundaries = [...hops, { ...current, usage: total }];
|
|
115
|
+
return boundaries
|
|
116
|
+
.map((segment, index) => ({
|
|
117
|
+
provider: segment.provider,
|
|
118
|
+
model: segment.model,
|
|
119
|
+
usage: usageSince(segment.usage, index ? boundaries[index - 1].usage : null),
|
|
120
|
+
}))
|
|
121
|
+
.filter((segment) => segment.usage);
|
|
122
|
+
}
|
|
123
|
+
|
|
82
124
|
export function addUsage(total, usage) {
|
|
83
125
|
const delta = normalizeUsage(usage);
|
|
84
126
|
if (!delta) return total;
|
|
@@ -11,6 +11,7 @@ import { autoEffortModel, turnEffortConfigurationMode } from '../../providers/ef
|
|
|
11
11
|
import {
|
|
12
12
|
autoEffortApplicable,
|
|
13
13
|
autoEffortBase,
|
|
14
|
+
clampAutoEffortBase,
|
|
14
15
|
normalizeAutoEffortMode,
|
|
15
16
|
resolveAutoEffort,
|
|
16
17
|
} from '../../providers/auto-effort.mjs';
|
|
@@ -58,6 +59,15 @@ export function autoEffortMode() {
|
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
/** The global "Auto reasoning base" setting; absent or unreadable is medium. */
|
|
63
|
+
export function autoEffortBaseSetting() {
|
|
64
|
+
try {
|
|
65
|
+
return autoEffortBase(readSection('agent')?.autoEffortBase);
|
|
66
|
+
} catch {
|
|
67
|
+
return autoEffortBase(undefined);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
61
71
|
/**
|
|
62
72
|
* Starts the judge worker when a session is created or opened on a route that
|
|
63
73
|
* Auto effort can judge, so the first judged turn does not wait for the cold
|
|
@@ -102,7 +112,9 @@ export async function resolveTurnAutoEffort({ sessionId, session, provider, inpu
|
|
|
102
112
|
if (!request || request.startsWith('<')) return null;
|
|
103
113
|
if (!turnEffortConfigurationMode(session, provider)) return null;
|
|
104
114
|
const chosen = String(session.effort || '').toLowerCase();
|
|
105
|
-
const
|
|
115
|
+
const options = effortOptionsFor(session.provider, autoEffortModel(session.provider, provider, session.model));
|
|
116
|
+
const setting = autoEffortBaseSetting();
|
|
117
|
+
const base = clampAutoEffortBase({ base: setting, options }) ?? autoEffortBase(setting);
|
|
106
118
|
const record = {
|
|
107
119
|
at: new Date().toISOString(),
|
|
108
120
|
sessionId,
|
|
@@ -113,7 +125,6 @@ export async function resolveTurnAutoEffort({ sessionId, session, provider, inpu
|
|
|
113
125
|
base,
|
|
114
126
|
requestChars: request.length,
|
|
115
127
|
};
|
|
116
|
-
const options = effortOptionsFor(session.provider, autoEffortModel(session.provider, provider, session.model));
|
|
117
128
|
// No judged outcome can apply when the base is off the model's ladder, so
|
|
118
129
|
// the judge is not asked (in observe mode too: nothing would be logged).
|
|
119
130
|
if (!autoEffortApplicable({ base, options })) {
|
|
@@ -120,14 +120,24 @@ function recordAgentRuntimeCall(session, result) {
|
|
|
120
120
|
export async function recordAskUsage({ session, result, askStartedAt, turnSignal }) {
|
|
121
121
|
const prefixHashForLog = recordAgentRuntimeCall(session, result);
|
|
122
122
|
if (!result.usage) return;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
123
|
+
// A turn that switched models mid-way books one row per model, each priced
|
|
124
|
+
// at that model's rates; otherwise one row for the whole turn.
|
|
125
|
+
const segments = result.usageSegments?.length
|
|
126
|
+
? result.usageSegments
|
|
127
|
+
: [{ provider: session.provider, model: session.model, usage: result.usage }];
|
|
128
|
+
for (const segment of segments) {
|
|
129
|
+
await logSessionLlmUsage({
|
|
130
|
+
session:
|
|
131
|
+
segment.provider === session.provider && segment.model === session.model
|
|
132
|
+
? session
|
|
133
|
+
: { ...session, provider: segment.provider, model: segment.model },
|
|
134
|
+
usage: segment.usage,
|
|
135
|
+
startedAt: askStartedAt,
|
|
136
|
+
signal: turnSignal,
|
|
137
|
+
prefixHash: prefixHashForLog,
|
|
138
|
+
transportTiming: result.transportTiming || null,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
131
141
|
recordStandaloneStatusTelemetry(session, result, Date.now() - askStartedAt);
|
|
132
142
|
}
|
|
133
143
|
|
|
@@ -19,12 +19,15 @@ import { retainedFailedTurnInput, rewindUnansweredPrompt } from './failed-turn-r
|
|
|
19
19
|
import { buildAgentLoopOptions, trackedToolCallHook } from './ask-turn-loop-options.mjs';
|
|
20
20
|
import { _api_call_with_interrupt } from './ask-call-interrupt.mjs';
|
|
21
21
|
import { backfillFallbackSessionTitle } from './session-fallback-title.mjs';
|
|
22
|
+
import { stampTurnHop } from '../../../../shared/bot-hops.mjs';
|
|
22
23
|
|
|
23
24
|
/** Resolves the provider, builds the user turn and pre-commits it; returns
|
|
24
25
|
* what the loop and the commit need from this preparation. */
|
|
25
26
|
export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, transcriptMeta }) {
|
|
26
27
|
const { turn, runtime, turnSignal, askGeneration, checkpoint, turnToken, startedAt, codexTurnId } = opened;
|
|
27
28
|
const session = turn.session;
|
|
29
|
+
// Where the turn sits in a bot-to-bot chain (session-runtime/bot-hops.mjs).
|
|
30
|
+
stampTurnHop(session, transcriptMeta, input.promptSource);
|
|
28
31
|
const retained = input.retryTurnId
|
|
29
32
|
? retainedFailedTurnInput(session.messages, input.retryTurnId, input.retryAttemptId)
|
|
30
33
|
: null;
|
|
@@ -187,6 +190,7 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
|
|
|
187
190
|
deferredToolDelta: userTurn.deferredToolDelta,
|
|
188
191
|
goalReminder: userTurn.goalReminder,
|
|
189
192
|
workflowNotice: userTurn.workflowNotice,
|
|
193
|
+
orchestrationModeNotice: userTurn.orchestrationModeNotice,
|
|
190
194
|
workspaceNotice: userTurn.workspaceNotice,
|
|
191
195
|
setupNotice: userTurn.setupNotice,
|
|
192
196
|
};
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
snapshotPendingSetupNotice,
|
|
21
21
|
} from './prompt-utils.mjs';
|
|
22
22
|
import { snapshotPendingWorkflowNotice } from './workflow-switch-notice.mjs';
|
|
23
|
+
import { snapshotPendingOrchestrationModeNotice } from './orchestration-mode-switch-notice.mjs';
|
|
23
24
|
import { codexWireSendOpts } from './session-id.mjs';
|
|
24
25
|
import { _tryBridgeExplicitPrefetch } from './prefetch-bridge.mjs';
|
|
25
26
|
import { filterModelVisibleSessionMessages } from './message-sanitize.mjs';
|
|
@@ -184,8 +185,12 @@ export async function buildUserTurn({
|
|
|
184
185
|
// A mid-conversation workflow switch: the prompt and tools were rebuilt
|
|
185
186
|
// for the new workflow; this turn tells the model once.
|
|
186
187
|
const workflowNotice = snapshotPendingWorkflowNotice(session);
|
|
188
|
+
// A mid-conversation orchestration mode switch, after the workflow notice
|
|
189
|
+
// so the mode it names wins over the one a workflow reminder carries.
|
|
190
|
+
const orchestrationModeNotice = snapshotPendingOrchestrationModeNotice(session);
|
|
187
191
|
const reminderBlock = [
|
|
188
192
|
workflowNotice?.content || '',
|
|
193
|
+
orchestrationModeNotice?.content || '',
|
|
189
194
|
workspaceNotice?.content || '',
|
|
190
195
|
setupNotice?.content || '',
|
|
191
196
|
currentTimeBlock ? `<system-reminder>\n# Current Time\n${currentTimeBlock}\n</system-reminder>` : '',
|
|
@@ -215,6 +220,7 @@ export async function buildUserTurn({
|
|
|
215
220
|
deferredToolDelta,
|
|
216
221
|
goalReminder,
|
|
217
222
|
workflowNotice,
|
|
223
|
+
orchestrationModeNotice,
|
|
218
224
|
workspaceNotice,
|
|
219
225
|
setupNotice,
|
|
220
226
|
userTurnMessage,
|
|
@@ -10,6 +10,7 @@ import { acknowledgePendingDeferredToolDelta } from '../../runtime-core/deferred
|
|
|
10
10
|
import { acknowledgePendingGoalReminder } from '../../runtime-core/goal-reminder.mjs';
|
|
11
11
|
import { acknowledgePendingSetupNotice, acknowledgePendingWorkspaceNotice } from './prompt-utils.mjs';
|
|
12
12
|
import { acknowledgePendingWorkflowNotice } from './workflow-switch-notice.mjs';
|
|
13
|
+
import { acknowledgePendingOrchestrationModeNotice } from './orchestration-mode-switch-notice.mjs';
|
|
13
14
|
import {
|
|
14
15
|
finalizePendingMessageDelivery,
|
|
15
16
|
drainPendingMessages,
|
|
@@ -141,6 +142,9 @@ export async function commitAskTurn({ sessionId, opened, prepared, result, rawTr
|
|
|
141
142
|
acknowledgePendingGoalReminder(session, prepared.goalReminder.revision);
|
|
142
143
|
}
|
|
143
144
|
if (prepared.workflowNotice) acknowledgePendingWorkflowNotice(session, prepared.workflowNotice.revision);
|
|
145
|
+
if (prepared.orchestrationModeNotice) {
|
|
146
|
+
acknowledgePendingOrchestrationModeNotice(session, prepared.orchestrationModeNotice.revision);
|
|
147
|
+
}
|
|
144
148
|
if (prepared.workspaceNotice) {
|
|
145
149
|
acknowledgePendingWorkspaceNotice(session, prepared.workspaceNotice.revision);
|
|
146
150
|
}
|
|
@@ -110,17 +110,12 @@ function withoutLegacyCompactFields(value) {
|
|
|
110
110
|
delete next[key];
|
|
111
111
|
return next;
|
|
112
112
|
}
|
|
113
|
-
// Handoff-summary timeout
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
function handoffSummaryTimeoutMs(session, messageTokens) {
|
|
120
|
-
const override = positiveInt(session?.compaction?.timeoutMs);
|
|
121
|
-
if (override) return override;
|
|
122
|
-
const scaled = Math.ceil((messageTokens || 0) / 25_000) * 10_000;
|
|
123
|
-
return Math.min(HANDOFF_TIMEOUT_MAX_MS, Math.max(60_000, scaled));
|
|
113
|
+
// Handoff-summary timeout (clear/manual path): the same 300s as automatic
|
|
114
|
+
// compaction, whatever the transcript size — the summary may run on a slow
|
|
115
|
+
// reasoning model or a stalled provider connection, and a timeout fails the
|
|
116
|
+
// compaction. session.compaction.timeoutMs still overrides.
|
|
117
|
+
function handoffSummaryTimeoutMs(session) {
|
|
118
|
+
return positiveInt(session?.compaction?.timeoutMs) || HANDOFF_TIMEOUT_MAX_MS;
|
|
124
119
|
}
|
|
125
120
|
/**
|
|
126
121
|
* ONE wiring for the fresh-context handoff pass: provider, summary model,
|
|
@@ -144,13 +139,8 @@ export async function runHandoffCompaction({
|
|
|
144
139
|
provider = null,
|
|
145
140
|
model = null,
|
|
146
141
|
config,
|
|
147
|
-
messageTokensEst = null,
|
|
148
142
|
requireReduction = false,
|
|
149
143
|
} = {}) {
|
|
150
|
-
const messageList = Array.isArray(messages) ? messages : [];
|
|
151
|
-
const transcriptTokens = Number.isFinite(Number(messageTokensEst))
|
|
152
|
-
? Number(messageTokensEst)
|
|
153
|
-
: estimateMessagesTokens(messageList);
|
|
154
144
|
return runFreshContextCompact({
|
|
155
145
|
sessionRef: session,
|
|
156
146
|
messages,
|
|
@@ -159,7 +149,7 @@ export async function runHandoffCompaction({
|
|
|
159
149
|
reserveTokens,
|
|
160
150
|
contextWindow: positiveInt(contextWindow) || positiveInt(session?.contextWindow) || boundaryTokens,
|
|
161
151
|
boundaryTokens,
|
|
162
|
-
handoffTimeoutMs: handoffSummaryTimeoutMs(session
|
|
152
|
+
handoffTimeoutMs: handoffSummaryTimeoutMs(session),
|
|
163
153
|
},
|
|
164
154
|
sessionId,
|
|
165
155
|
signal,
|
|
@@ -336,7 +326,6 @@ async function runSessionHandoff(plan, opts) {
|
|
|
336
326
|
provider: opts.provider || getProvider(session.provider) || null,
|
|
337
327
|
model: opts.model,
|
|
338
328
|
config: opts.config,
|
|
339
|
-
messageTokensEst: plan.beforeMessageTokens,
|
|
340
329
|
requireReduction: plan.requireReduction,
|
|
341
330
|
});
|
|
342
331
|
if (Array.isArray(run.freshContextResult?.messages)) {
|
|
@@ -609,7 +598,43 @@ function withAppendedMessages(plan, numbers, appended) {
|
|
|
609
598
|
const TRANSCRIPT_MOVED_ERROR =
|
|
610
599
|
'compact: the conversation changed while compacting; compaction not applied, run it again';
|
|
611
600
|
|
|
601
|
+
// Why a compaction took as long as it did: persisted next to lastSummaryModel
|
|
602
|
+
// and echoed as one daemon.log line. Wall time runs start → end of commit; the
|
|
603
|
+
// summary call's own time comes from the handoff pipeline, so the remainder is
|
|
604
|
+
// planning, transcript comparison and the commit below. The archive write is
|
|
605
|
+
// scheduled by the commit and runs later, off it.
|
|
606
|
+
function recordCompactionTiming(plan, freshContextResult, { startedAt, commitStartedAt, afterTokens }) {
|
|
607
|
+
const { session, resolvedSessionId } = plan;
|
|
608
|
+
const committedAt = Date.now();
|
|
609
|
+
const pipeline = freshContextResult?.diagnostics?.pipeline;
|
|
610
|
+
const summaryMs = pipeline?.generated?.durationMs ?? null;
|
|
611
|
+
// How the summary ran: a fork of the cached request or the isolated
|
|
612
|
+
// request, and on which route (session / maintenance / lighter).
|
|
613
|
+
let summaryRun = null;
|
|
614
|
+
if (pipeline?.summaryRoute) {
|
|
615
|
+
const kind = pipeline.generated?.mode === 'shared-prefix' ? 'fork' : 'isolated';
|
|
616
|
+
summaryRun = `${kind}:${pipeline.summaryRoute}`;
|
|
617
|
+
}
|
|
618
|
+
const timing = {
|
|
619
|
+
lastStartedAt: startedAt,
|
|
620
|
+
lastCommittedAt: committedAt,
|
|
621
|
+
lastDurationMs: committedAt - startedAt,
|
|
622
|
+
lastPipelineMs: pipeline?.totalMs ?? null,
|
|
623
|
+
lastSummaryMs: summaryMs,
|
|
624
|
+
lastCommitMs: committedAt - commitStartedAt,
|
|
625
|
+
lastCompactMode: summaryRun ? `${pipeline.mode}:${summaryRun}` : pipeline?.mode || null,
|
|
626
|
+
};
|
|
627
|
+
Object.assign(session.compaction, timing);
|
|
628
|
+
writeStderrBestEffort(
|
|
629
|
+
`compaction session=${resolvedSessionId || 'unknown'} source=${freshContextResult?.handoffSource || 'session-local'} ` +
|
|
630
|
+
`model=${freshContextResult?.summaryModel || '-'} mode=${summaryRun || '-'} total=${timing.lastDurationMs}ms ` +
|
|
631
|
+
`summary=${summaryMs ?? 0}ms commit=${timing.lastCommitMs}ms ` +
|
|
632
|
+
`in=${plan.beforeTokens} out=${afterTokens}\n`
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
|
|
612
636
|
async function commitSessionCompaction(plan, run, compactStartedAt) {
|
|
637
|
+
const commitStartedAt = Date.now();
|
|
613
638
|
const { session, messages, mode, force, resolvedSessionId, reserveTokens } = plan;
|
|
614
639
|
const { freshContextResult } = run;
|
|
615
640
|
const numbers = await afterCompactionNumbers(plan, run.compacted);
|
|
@@ -688,6 +713,7 @@ async function commitSessionCompaction(plan, run, compactStartedAt) {
|
|
|
688
713
|
if (changed) {
|
|
689
714
|
session.pendingCacheBreakIntent = mode === 'auto' ? 'post_turn_compaction' : 'manual_compaction';
|
|
690
715
|
}
|
|
716
|
+
recordCompactionTiming(plan, freshContextResult, { startedAt: compactStartedAt, commitStartedAt, afterTokens });
|
|
691
717
|
return compactionResult(
|
|
692
718
|
plan,
|
|
693
719
|
{ changed, reason: unchangedReason },
|