mixdog 0.9.152 → 0.9.154
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/LICENSES/browser-import-NOTICE.txt +11 -0
- package/NOTICE.md +11 -0
- package/README.md +8 -10
- package/package.json +19 -3
- package/scripts/computer-task-cost-report.mjs +144 -0
- package/scripts/run-office-live-tests.mjs +32 -0
- package/src/agents/front-worker/AGENT.md +13 -0
- package/src/agents/front-worker/agent.json +6 -0
- package/src/agents/heavy-worker/AGENT.md +10 -11
- package/src/agents/heavy-worker/agent.json +1 -1
- package/src/agents/maintainer/AGENT.md +0 -2
- package/src/agents/reviewer/AGENT.md +9 -13
- package/src/agents/reviewer/agent.json +1 -1
- package/src/agents/security/AGENT.md +14 -0
- package/src/agents/security/agent.json +6 -0
- package/src/agents/worker/AGENT.md +8 -8
- package/src/agents/worker/agent.json +1 -1
- package/src/agents/writer/AGENT.md +14 -0
- package/src/agents/writer/agent.json +6 -0
- package/src/rules/agent/00-common.md +4 -7
- package/src/rules/lead/01-general.md +0 -3
- package/src/rules/shared/10-tool-workflow.md +10 -2
- package/src/rules/shared/60-verification.md +2 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +183 -26
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +4 -0
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +109 -0
- package/src/runtime/agent/orchestrator/config.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +18 -26
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +25 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +103 -10
- package/src/runtime/agent/orchestrator/providers/openai-turn-state.mjs +68 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +36 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +140 -86
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +9 -13
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +72 -4
- package/src/runtime/agent/orchestrator/session/browser-snapshot-supersession.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/compact/handoff.mjs +0 -22
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +11 -23
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +28 -269
- package/src/runtime/agent/orchestrator/session/compact.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +86 -11
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +17 -1
- package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +12 -8
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +110 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +3 -16
- package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +80 -18
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +80 -21
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +33 -72
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +21 -2
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +25 -51
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -110
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +39 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +14 -4
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +41 -8
- package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +129 -12
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +36 -2
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +157 -30
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +57 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +22 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +4 -0
- package/src/runtime/attachments/pdf-extract.mjs +3 -0
- package/src/runtime/attachments/pdfjs-runtime.mjs +13 -0
- package/src/runtime/browser-bridge/action-schema.mjs +251 -0
- package/src/runtime/browser-bridge/client.mjs +75 -26
- package/src/runtime/browser-bridge/tool-defs.mjs +132 -15
- package/src/runtime/computer-bridge/action-schema.mjs +653 -0
- package/src/runtime/computer-bridge/client.mjs +211 -28
- package/src/runtime/computer-bridge/tool-defs.mjs +25 -45
- package/src/runtime/office/assurance-benchmark.mjs +358 -0
- package/src/runtime/office/assurance.mjs +833 -0
- package/src/runtime/office/benchmark.mjs +496 -0
- package/src/runtime/office/capabilities.mjs +551 -0
- package/src/runtime/office/com-adapter.mjs +283 -0
- package/src/runtime/office/content-model.mjs +183 -0
- package/src/runtime/office/contract-benchmark.mjs +105 -0
- package/src/runtime/office/design-library.mjs +1562 -0
- package/src/runtime/office/design-system.mjs +1966 -0
- package/src/runtime/office/index.mjs +2413 -0
- package/src/runtime/office/journal.mjs +82 -0
- package/src/runtime/office/office-com-host.ps1 +3781 -0
- package/src/runtime/office/office-com-session-host.ps1 +855 -0
- package/src/runtime/office/ooxml-validator.mjs +271 -0
- package/src/runtime/office/pagination.mjs +132 -0
- package/src/runtime/office/pdf-adapter.mjs +591 -0
- package/src/runtime/office/pdf-analysis.mjs +372 -0
- package/src/runtime/office/pdf-render.mjs +167 -0
- package/src/runtime/office/pdf-security.mjs +63 -0
- package/src/runtime/office/polish-benchmark.mjs +190 -0
- package/src/runtime/office/portable-ooxml.mjs +1867 -0
- package/src/runtime/office/quality-live-benchmark.mjs +486 -0
- package/src/runtime/office/quality-pipeline.mjs +136 -0
- package/src/runtime/office/tabular.mjs +302 -0
- package/src/runtime/office/templates/mixdog-executive.pptx +0 -0
- package/src/runtime/office/templates/mixdog-executive.pptx.mixdog.json +190 -0
- package/src/runtime/office/tool-defs.mjs +113 -0
- package/src/runtime/office/visual-diff.mjs +89 -0
- package/src/runtime/office/xlsx-assertions.mjs +172 -0
- package/src/runtime/office/xlsx-contract.mjs +147 -0
- package/src/runtime/shared/agent-route-config.mjs +9 -0
- package/src/runtime/shared/tool-execution-contract.mjs +16 -0
- package/src/runtime/shared/tool-surface.mjs +9 -0
- package/src/session-runtime/context-status.mjs +9 -3
- package/src/session-runtime/deferred-tool-delta.mjs +104 -0
- package/src/session-runtime/goal-runtime.mjs +617 -197
- package/src/session-runtime/lifecycle-api.mjs +50 -8
- package/src/session-runtime/provider-request-snapshot.mjs +33 -9
- package/src/session-runtime/resource-api.mjs +31 -94
- package/src/session-runtime/runtime-core.mjs +78 -26
- package/src/session-runtime/session-lifecycle.mjs +34 -12
- package/src/session-runtime/session-title.mjs +2 -2
- package/src/session-runtime/session-turn-api.mjs +15 -14
- package/src/session-runtime/tool-catalog-data.mjs +1 -1
- package/src/session-runtime/tool-catalog.mjs +38 -99
- package/src/session-runtime/tool-defs.mjs +6 -1
- package/src/session-runtime/tool-surface.mjs +18 -8
- package/src/session-runtime/workflow-agents-api.mjs +8 -25
- package/src/session-runtime/workflow.mjs +8 -6
- package/src/standalone/agent-tool/helpers.mjs +2 -2
- package/src/standalone/agent-tool/job-views.mjs +3 -1
- package/src/standalone/agent-tool/notify.mjs +5 -1
- package/src/standalone/agent-tool/render.mjs +3 -0
- package/src/standalone/agent-tool/spawn-flow.mjs +61 -16
- package/src/standalone/agent-tool/tool-def.mjs +1 -1
- package/src/standalone/agent-tool/worker-index.mjs +123 -0
- package/src/standalone/agent-tool/worker-rows.mjs +2 -1
- package/src/standalone/agent-tool.mjs +57 -10
- package/src/standalone/daemon.mjs +105 -6
- package/src/standalone/session-runtime-host.mjs +61 -48
- package/src/standalone/session-runtime-inline-host.mjs +34 -127
- package/src/standalone/session-runtime-worker.mjs +20 -198
- package/src/standalone/session-service.mjs +632 -7
- package/src/tui/dist/index.mjs +24 -1
- package/src/tui/lib/voice-setup.mjs +4 -1
- package/src/tui/session/context-state.mjs +2 -13
- package/src/tui/session/goal-continuation.mjs +38 -7
- package/src/tui/session/session-api-ext.mjs +9 -0
- package/src/tui/session/session-api.mjs +15 -1
- package/src/tui/session/session-flow.mjs +25 -1
- package/src/tui/session/turn.mjs +88 -16
- package/src/tui/session-local.mjs +25 -3
- package/src/vendor/statusline/src/gateway/route-meta.mjs +31 -0
- package/scripts/generate-voice-runtime-manifest.test.mjs +0 -135
- package/scripts/native-binary-arch.test.mjs +0 -111
- package/scripts/patch-replay.test.mjs +0 -94
- package/src/headless-exec.test.mjs +0 -539
- package/src/runtime/agent/orchestrator/agent-trace-timing.test.mjs +0 -57
- package/src/runtime/agent/orchestrator/context/collect-skills.test.mjs +0 -153
- package/src/runtime/agent/orchestrator/mcp/cancellation.test.mjs +0 -139
- package/src/runtime/agent/orchestrator/mcp/features.test.mjs +0 -66
- package/src/runtime/agent/orchestrator/mcp/security.test.mjs +0 -80
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.test.mjs +0 -90
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.test.mjs +0 -215
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.test.mjs +0 -165
- package/src/runtime/agent/orchestrator/providers/media-parity.test.mjs +0 -142
- package/src/runtime/agent/orchestrator/providers/openai-codex-identity.test.mjs +0 -153
- package/src/runtime/agent/orchestrator/providers/openai-codex-model.test.mjs +0 -24
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta-parity.test.mjs +0 -190
- package/src/runtime/agent/orchestrator/providers/provider-replay.test.mjs +0 -235
- package/src/runtime/agent/orchestrator/providers/sse-framing.test.mjs +0 -719
- package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.test.mjs +0 -40
- package/src/runtime/agent/orchestrator/session/compact-policy.test.mjs +0 -176
- package/src/runtime/agent/orchestrator/session/compaction-read-reset.test.mjs +0 -161
- package/src/runtime/agent/orchestrator/session/eager-dispatch.test.mjs +0 -115
- package/src/runtime/agent/orchestrator/session/evidence-union.test.mjs +0 -228
- package/src/runtime/agent/orchestrator/session/image-strip-recovery.test.mjs +0 -245
- package/src/runtime/agent/orchestrator/session/lossless-tool-output.test.mjs +0 -125
- package/src/runtime/agent/orchestrator/session/manager/pending-messages-persistence.test.mjs +0 -325
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.test.mjs +0 -70
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.test.mjs +0 -457
- package/src/runtime/agent/orchestrator/session/provider-prefix-guard.test.mjs +0 -117
- package/src/runtime/agent/orchestrator/session/reduction-metrics.test.mjs +0 -87
- package/src/runtime/agent/orchestrator/session/store/serialize.test.mjs +0 -60
- package/src/runtime/agent/orchestrator/session/store-summary-reader.test.mjs +0 -583
- package/src/runtime/agent/orchestrator/session/task-wait-control.test.mjs +0 -78
- package/src/runtime/agent/orchestrator/tools/builtin/absence-absorption.test.mjs +0 -43
- package/src/runtime/agent/orchestrator/tools/builtin/absolute-glob-expand.test.mjs +0 -63
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool-cwd-env.test.mjs +0 -14
- package/src/runtime/agent/orchestrator/tools/builtin/edit-encoding-eol.test.mjs +0 -224
- package/src/runtime/agent/orchestrator/tools/builtin/edit-sequential-occupation.test.mjs +0 -224
- package/src/runtime/agent/orchestrator/tools/builtin/enoent-outside-project.test.mjs +0 -56
- package/src/runtime/agent/orchestrator/tools/builtin/find-search-budget.test.mjs +0 -103
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.test.mjs +0 -30
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.test.mjs +0 -390
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.test.mjs +0 -83
- package/src/runtime/agent/orchestrator/tools/builtin/grep-output-budget.test.mjs +0 -31
- package/src/runtime/agent/orchestrator/tools/builtin/grep-single-file-rescue.test.mjs +0 -106
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.test.mjs +0 -102
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool-integrity.test.mjs +0 -152
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-health.test.mjs +0 -24
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-transport.test.mjs +0 -24
- package/src/runtime/agent/orchestrator/tools/builtin/noise-dir-visibility.test.mjs +0 -69
- package/src/runtime/agent/orchestrator/tools/builtin/read-glob-survey.test.mjs +0 -71
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.test.mjs +0 -56
- package/src/runtime/agent/orchestrator/tools/builtin/search-builders.test.mjs +0 -16
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-top-k.test.mjs +0 -39
- package/src/runtime/agent/orchestrator/tools/builtin/write-symlink.test.mjs +0 -153
- package/src/runtime/agent/orchestrator/tools/code-graph/aggregate-anchor-relocation.test.mjs +0 -55
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.test.mjs +0 -88
- package/src/runtime/agent/orchestrator/tools/code-graph/loose-file-target.test.mjs +0 -72
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.test.mjs +0 -54
- package/src/runtime/agent/orchestrator/tools/code-graph/search-references.test.mjs +0 -20
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-search-scope.test.mjs +0 -55
- package/src/runtime/agent/orchestrator/tools/code-graph/text-span-mask.test.mjs +0 -268
- package/src/runtime/agent/orchestrator/tools/env-scrub.test.mjs +0 -57
- package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.test.mjs +0 -19
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.test.mjs +0 -104
- package/src/runtime/agent/orchestrator/tools/patch/engine-contract-gate.test.mjs +0 -661
- package/src/runtime/agent/orchestrator/tools/patch/patch-codec-eol.test.mjs +0 -552
- package/src/runtime/agent/orchestrator/tools/patch/patch-symlink.test.mjs +0 -141
- package/src/runtime/agent/orchestrator/tools/patch/v4a-pure-move.test.mjs +0 -57
- package/src/runtime/agent/orchestrator/tools/patch/v4a-section-coalesce.test.mjs +0 -81
- package/src/runtime/agent/orchestrator/tools/spawn-binary-fetcher.test.mjs +0 -52
- package/src/runtime/attachments/store.test.mjs +0 -209
- package/src/runtime/channels/lib/voice-runtime-fetcher.test.mjs +0 -17
- package/src/runtime/channels/lib/webhook/deliveries.test.mjs +0 -18
- package/src/runtime/channels/lib/webhook/relay-tunnel.test.mjs +0 -68
- package/src/runtime/media/adapters/codex-image.test.mjs +0 -22
- package/src/runtime/media/download.test.mjs +0 -52
- package/src/runtime/media/renditions.test.mjs +0 -99
- package/src/runtime/media/store.test.mjs +0 -159
- package/src/runtime/memory/lib/archive-security.test.mjs +0 -128
- package/src/runtime/memory/lib/embedding-model-config.test.mjs +0 -33
- package/src/runtime/memory/lib/http-wire.test.mjs +0 -15
- package/src/runtime/memory/lib/memory-cycle-packets.test.mjs +0 -49
- package/src/runtime/memory/lib/memory-cycle2-shared.test.mjs +0 -78
- package/src/runtime/memory/lib/memory-embedding-migration.test.mjs +0 -50
- package/src/runtime/memory/lib/pg/process.test.mjs +0 -36
- package/src/runtime/memory/lib/trace-store.test.mjs +0 -57
- package/src/runtime/memory/lib/transcript-ingest.test.mjs +0 -52
- package/src/runtime/shared/background-tasks.test.mjs +0 -78
- package/src/runtime/shared/bounded-download.test.mjs +0 -41
- package/src/runtime/shared/channel-notification-routing.test.mjs +0 -25
- package/src/runtime/shared/child-spawn-remote.test.mjs +0 -124
- package/src/runtime/shared/remote-intent.test.mjs +0 -40
- package/src/runtime/shared/resource-admission.test.mjs +0 -43
- package/src/runtime/shared/runtime-root.test.mjs +0 -34
- package/src/runtime/shared/schedule-time.test.mjs +0 -29
- package/src/runtime/shared/session-runtime-health.test.mjs +0 -83
- package/src/runtime/shared/skill-document.test.mjs +0 -81
- package/src/runtime/shared/tool-surface.test.mjs +0 -87
- package/src/runtime/shared/update-checker.test.mjs +0 -33
- package/src/runtime/shared/user-cwd.test.mjs +0 -43
- package/src/runtime/shared/webhook-session-run.test.mjs +0 -14
- package/src/session-runtime/agent-disable.test.mjs +0 -123
- package/src/session-runtime/cwd-plugins.test.mjs +0 -75
- package/src/session-runtime/cwd-tool-routing.test.mjs +0 -61
- package/src/session-runtime/global-extensions.test.mjs +0 -28
- package/src/session-runtime/goal-runtime.test.mjs +0 -108
- package/src/session-runtime/lifecycle-api.test.mjs +0 -21
- package/src/session-runtime/model-settings-persist.test.mjs +0 -105
- package/src/session-runtime/notification-bus.test.mjs +0 -148
- package/src/session-runtime/plugin-mcp-standard.test.mjs +0 -177
- package/src/session-runtime/prewarm.test.mjs +0 -52
- package/src/session-runtime/provider-request-snapshot.test.mjs +0 -37
- package/src/session-runtime/resource-api-global.test.mjs +0 -69
- package/src/session-runtime/session-lifecycle.test.mjs +0 -125
- package/src/session-runtime/session-title.test.mjs +0 -36
- package/src/session-runtime/skills-api.test.mjs +0 -99
- package/src/session-runtime/tool-policy-surface.test.mjs +0 -331
- package/src/standalone/agent-tool/helpers.test.mjs +0 -62
- package/src/standalone/agent-tool/notify.test.mjs +0 -37
- package/src/standalone/agent-tool/spawn-flow.test.mjs +0 -63
- package/src/standalone/channel-restart.test.mjs +0 -145
- package/src/standalone/channel-session-router.test.mjs +0 -37
- package/src/standalone/channel-worker-heartbeat.test.mjs +0 -30
- package/src/standalone/hook-bus/handlers.test.mjs +0 -88
- package/src/standalone/plugin-admin.test.mjs +0 -173
- package/src/standalone/session-runtime-agent-control-client.test.mjs +0 -71
- package/src/standalone/session-runtime-dispatch-cancel.test.mjs +0 -139
- package/src/standalone/session-runtime-host-factory.test.mjs +0 -31
- package/src/standalone/session-runtime-host-health.test.mjs +0 -160
- package/src/standalone/session-runtime-inline-host.test.mjs +0 -83
- package/src/standalone/session-runtime-provider-cooldown.test.mjs +0 -80
- package/src/standalone/session-runtime-shard-host.test.mjs +0 -569
- package/src/standalone/session-runtime-shard-router.test.mjs +0 -101
- package/src/tui/app/live-spinner-visibility.test.mjs +0 -44
- package/src/tui/app/panel-epoch.test.mjs +0 -1009
- package/src/tui/app/panel-handoff.test.mjs +0 -311
- package/src/tui/app/prompt-submit.test.mjs +0 -206
- package/src/tui/session/completion-card-restore.test.mjs +0 -111
- package/src/tui/session/goal-continuation.test.mjs +0 -84
- package/src/tui/session/oauth-flows.test.mjs +0 -134
- package/src/tui/session/queue-helpers.test.mjs +0 -46
- package/src/tui/session/session-action-surface.test.mjs +0 -108
- package/src/tui/session/task-wait-submit.test.mjs +0 -80
- package/src/tui/session/tool-result-status.test.mjs +0 -131
- package/src/tui/session/tui-steering-persist.test.mjs +0 -104
|
@@ -14,6 +14,10 @@ import { createAbortController } from '../../../../shared/abort-controller.mjs';
|
|
|
14
14
|
import { estimateJsonBytes } from '../../../../shared/json-metrics.mjs';
|
|
15
15
|
import { logLlmCall } from '../../../../shared/llm/usage-log.mjs';
|
|
16
16
|
import { appendAgentTrace } from '../../agent-trace.mjs';
|
|
17
|
+
import {
|
|
18
|
+
acknowledgePendingDeferredToolDelta,
|
|
19
|
+
snapshotPendingDeferredToolDelta,
|
|
20
|
+
} from '../../../../../session-runtime/deferred-tool-delta.mjs';
|
|
17
21
|
import { recordStandaloneStatusTelemetry } from './status-telemetry.mjs';
|
|
18
22
|
import { normalizeStaleCompactingStage } from './compaction-runner.mjs';
|
|
19
23
|
import { resolveSessionContextMeta, positiveContextWindow } from './context-meta.mjs';
|
|
@@ -80,6 +84,37 @@ export async function settleAskCleanup(promise, { timeoutMs } = {}) {
|
|
|
80
84
|
return await settleWithin(promise, budget);
|
|
81
85
|
}
|
|
82
86
|
|
|
87
|
+
// Live Agent projection is a per-ask send opt, never a session field.
|
|
88
|
+
// Callers that pass onTextDelta/onAssistantText still need `liveProjection`
|
|
89
|
+
// to un-suppress provider streaming: askSession always wraps those
|
|
90
|
+
// callbacks for interruption tracking, so agent-loop cannot infer intent
|
|
91
|
+
// from `typeof opts.onTextDelta === 'function'`.
|
|
92
|
+
export function resolveAskLiveProjection(askOpts = {}) {
|
|
93
|
+
return askOpts?.liveProjection === true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function emitAskSessionStart(askOpts, detail) {
|
|
97
|
+
if (typeof askOpts?.onSessionStart !== 'function') return;
|
|
98
|
+
try { askOpts.onSessionStart(detail); } catch { /* best-effort */ }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Replacement is opt-in and transactional: a delta-only consumer cannot
|
|
102
|
+
// retract already exposed bytes, so absence, false, or rejection must
|
|
103
|
+
// preserve the original partial and force the provider's terminal
|
|
104
|
+
// no-replay behavior. Live projection never auto-acks.
|
|
105
|
+
export async function acknowledgeAskTextReset(askOpts, detail, onAcknowledged) {
|
|
106
|
+
if (typeof askOpts?.onTextReset !== 'function') return false;
|
|
107
|
+
let acknowledged = false;
|
|
108
|
+
try {
|
|
109
|
+
acknowledged = await askOpts.onTextReset(detail) === true;
|
|
110
|
+
} catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (!acknowledged) return false;
|
|
114
|
+
if (typeof onAcknowledged === 'function') onAcknowledged(detail);
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
83
118
|
export function persistedAssistantTranscriptMetadata(value, fallbackAt = Date.now()) {
|
|
84
119
|
if (!value || typeof value !== 'object') return null;
|
|
85
120
|
const candidateAt = Number(value.assistantAt);
|
|
@@ -194,6 +229,7 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
194
229
|
...(typeof _rawTranscriptMeta.model === 'string' && _rawTranscriptMeta.model ? { model: _rawTranscriptMeta.model } : {}),
|
|
195
230
|
...(typeof _rawTranscriptMeta.provider === 'string' && _rawTranscriptMeta.provider ? { provider: _rawTranscriptMeta.provider } : {}),
|
|
196
231
|
...(typeof _rawTranscriptMeta.agent === 'string' && _rawTranscriptMeta.agent ? { agent: _rawTranscriptMeta.agent } : {}),
|
|
232
|
+
...(typeof _rawTranscriptMeta.sender === 'string' && _rawTranscriptMeta.sender ? { sender: _rawTranscriptMeta.sender } : {}),
|
|
197
233
|
}
|
|
198
234
|
: null;
|
|
199
235
|
const _takeAssistantTranscriptMetadata = () => {
|
|
@@ -229,6 +265,7 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
229
265
|
// can compare against the last turn's generation.
|
|
230
266
|
let askGeneration = 0;
|
|
231
267
|
let _crashRecoveryChecked = false;
|
|
268
|
+
let _sessionStartEmitted = false;
|
|
232
269
|
try {
|
|
233
270
|
// Turn loop (pendingMessages pattern): run the current prompt, then drain
|
|
234
271
|
// any `agent type=send` messages that were queued while this turn was in
|
|
@@ -238,6 +275,7 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
238
275
|
for (;;) {
|
|
239
276
|
let _pwstTurnDrained = null;
|
|
240
277
|
let _turnPendingEntries = [];
|
|
278
|
+
let _turnDeferredToolDelta = null;
|
|
241
279
|
// After the first turn, the next prompt comes from the drained queue.
|
|
242
280
|
// (On the first iteration _pendingTail is empty and `prompt` is the
|
|
243
281
|
// caller's original message.)
|
|
@@ -333,6 +371,16 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
333
371
|
linkParentSignalToSession(sessionId, _linkedParentSignal);
|
|
334
372
|
}
|
|
335
373
|
markSessionAskStart(sessionId);
|
|
374
|
+
if (!_sessionStartEmitted) {
|
|
375
|
+
_sessionStartEmitted = true;
|
|
376
|
+
emitAskSessionStart(askOpts, {
|
|
377
|
+
sessionId,
|
|
378
|
+
agent: preSession.agent || null,
|
|
379
|
+
model: preSession.model || null,
|
|
380
|
+
provider: preSession.provider || null,
|
|
381
|
+
owner: preSession.owner || null,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
336
384
|
// Preprocessing is inside try so provider-not-available / trim failures
|
|
337
385
|
// fall into the catch and mark the session as errored rather than
|
|
338
386
|
// leaving stage='connecting' forever.
|
|
@@ -540,9 +588,13 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
540
588
|
process.stderr.write(`[session] Warning: prompt is very large (est. ${Math.round(promptTokenEstimate)} tokens vs ${softBudget} soft budget)\n`);
|
|
541
589
|
}
|
|
542
590
|
const _currentTimeBlock = buildCurrentTimeBlock(prompt);
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
591
|
+
_turnDeferredToolDelta = snapshotPendingDeferredToolDelta(session);
|
|
592
|
+
const _turnReminderBlock = [
|
|
593
|
+
_currentTimeBlock
|
|
594
|
+
? `<system-reminder>\n# Current Time\n${_currentTimeBlock}\n</system-reminder>`
|
|
595
|
+
: '',
|
|
596
|
+
_turnDeferredToolDelta?.content || '',
|
|
597
|
+
].filter(Boolean).join('\n\n');
|
|
546
598
|
const _baseUserTurnContent = prefixUserTurnContent(prompt, _contextBlock);
|
|
547
599
|
const _userTurnContent = prefixSessionStartContent(_baseUserTurnContent, _turnReminderBlock);
|
|
548
600
|
cancelledUserTurnContent = _userTurnContent;
|
|
@@ -623,23 +675,10 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
623
675
|
_scheduleTurnCheckpoint();
|
|
624
676
|
if (typeof askOpts?.onTextDelta === 'function') askOpts.onTextDelta(chunk);
|
|
625
677
|
};
|
|
626
|
-
const _trackTextReset = async (detail) => {
|
|
627
|
-
|
|
628
|
-
// consumer cannot retract already exposed bytes, so absence,
|
|
629
|
-
// false, or rejection must preserve the original partial and
|
|
630
|
-
// force the provider's terminal no-replay behavior.
|
|
631
|
-
if (typeof askOpts?.onTextReset !== 'function') return false;
|
|
632
|
-
let acknowledged = false;
|
|
633
|
-
try {
|
|
634
|
-
acknowledged = await askOpts.onTextReset(detail) === true;
|
|
635
|
-
} catch {
|
|
636
|
-
return false;
|
|
637
|
-
}
|
|
638
|
-
if (!acknowledged) return false;
|
|
639
|
-
_turnInterruption.tombstoneText(detail?.chars);
|
|
678
|
+
const _trackTextReset = async (detail) => acknowledgeAskTextReset(askOpts, detail, (resetDetail) => {
|
|
679
|
+
_turnInterruption.tombstoneText(resetDetail?.chars);
|
|
640
680
|
_scheduleTurnCheckpoint(true);
|
|
641
|
-
|
|
642
|
-
};
|
|
681
|
+
});
|
|
643
682
|
const _trackReasoningDelta = (chunk) => {
|
|
644
683
|
_turnInterruption.recordReasoningDelta(chunk);
|
|
645
684
|
_scheduleTurnCheckpoint();
|
|
@@ -679,9 +718,13 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
679
718
|
onReasoningDelta: _trackReasoningDelta,
|
|
680
719
|
onAssistantText: _trackAssistantText,
|
|
681
720
|
takeAssistantTranscriptMetadata: _takeAssistantTranscriptMetadata,
|
|
682
|
-
|
|
721
|
+
// Send-opt only. Never copy onto `session` — a transient
|
|
722
|
+
// interactive/live flag must not survive this ask.
|
|
723
|
+
liveProjection: resolveAskLiveProjection(askOpts),
|
|
724
|
+
onAssistantMessageCommitted: (message) => {
|
|
683
725
|
_turnInterruption.markAssistantMessageCommitted();
|
|
684
726
|
_scheduleTurnCheckpoint(true);
|
|
727
|
+
try { askOpts?.onAssistantMessageCommitted?.(message); } catch {}
|
|
685
728
|
},
|
|
686
729
|
onAssistantToolCallObserved: (call, detail) => {
|
|
687
730
|
_turnInterruption.recordToolCalls([call], detail);
|
|
@@ -1008,6 +1051,7 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
1008
1051
|
promptTokens,
|
|
1009
1052
|
prefixHash: prefixHashForLog,
|
|
1010
1053
|
costUsd,
|
|
1054
|
+
transportTiming: result.transportTiming || null,
|
|
1011
1055
|
});
|
|
1012
1056
|
recordStandaloneStatusTelemetry(session, result, Date.now() - _askStartedAt);
|
|
1013
1057
|
}
|
|
@@ -1020,6 +1064,9 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
1020
1064
|
} else if (result.providerStateUpdated === true || result.providerState !== undefined) {
|
|
1021
1065
|
session.providerState = result.providerState;
|
|
1022
1066
|
}
|
|
1067
|
+
if (_turnDeferredToolDelta) {
|
|
1068
|
+
acknowledgePendingDeferredToolDelta(session, _turnDeferredToolDelta.revision);
|
|
1069
|
+
}
|
|
1023
1070
|
const terminalResultPreview = {
|
|
1024
1071
|
...result,
|
|
1025
1072
|
trimmed: messagesDropped > 0,
|
|
@@ -1214,13 +1261,25 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
1214
1261
|
// renderer's ephemeral failure toast.
|
|
1215
1262
|
try {
|
|
1216
1263
|
const _status = Number(err?.httpStatus || err?.status || err?.response?.status || 0) || 0;
|
|
1264
|
+
const _errorDetails = err?.details && typeof err.details === 'object'
|
|
1265
|
+
? err.details
|
|
1266
|
+
: null;
|
|
1217
1267
|
const _parts = [
|
|
1218
1268
|
`session=${sessionId}`,
|
|
1219
1269
|
`name=${err?.name || 'Error'}`,
|
|
1220
1270
|
_status ? `status=${_status}` : null,
|
|
1221
1271
|
err?.code ? `code=${err.code}` : null,
|
|
1222
1272
|
err?.providerErrorType ? `type=${err.providerErrorType}` : null,
|
|
1223
|
-
`kind=${classifyError(err)}`,
|
|
1273
|
+
`kind=${_errorDetails?.kind || classifyError(err)}`,
|
|
1274
|
+
_errorDetails?.reason ? `reason=${_errorDetails.reason}` : null,
|
|
1275
|
+
_errorDetails?.source ? `source=${_errorDetails.source}` : null,
|
|
1276
|
+
Number.isFinite(Number(_errorDetails?.index)) ? `index=${_errorDetails.index}` : null,
|
|
1277
|
+
Number.isFinite(Number(_errorDetails?.previousCount))
|
|
1278
|
+
? `previousCount=${_errorDetails.previousCount}`
|
|
1279
|
+
: null,
|
|
1280
|
+
Number.isFinite(Number(_errorDetails?.nextCount))
|
|
1281
|
+
? `nextCount=${_errorDetails.nextCount}`
|
|
1282
|
+
: null,
|
|
1224
1283
|
Number.isFinite(Number(err?.attempts)) ? `attempts=${err.attempts}` : null,
|
|
1225
1284
|
Number.isFinite(Number(err?.midstreamRetries)) ? `midstreamRetries=${err.midstreamRetries}` : null,
|
|
1226
1285
|
err?.midstreamClassifier ? `midstream=${err.midstreamClassifier}` : null,
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
import { estimateMessagesTokens, estimateRequestReserveTokens, estimateTranscriptContextUsage, resolveCompactBufferRatio } from '../context-utils.mjs';
|
|
17
17
|
import { executeInternalTool } from '../../internal-tools.mjs';
|
|
18
18
|
import {
|
|
19
|
+
callMemoryColdStart,
|
|
20
|
+
recallMemoryTimeoutMs,
|
|
19
21
|
runRecallFastTrackCompact,
|
|
20
22
|
} from '../loop/recall-fasttrack.mjs';
|
|
21
23
|
import {
|
|
@@ -34,9 +36,11 @@ import {
|
|
|
34
36
|
compactTargetBudget as compactTargetBudgetForPolicy,
|
|
35
37
|
currentContextEstimateTokens,
|
|
36
38
|
invalidateProviderContextBaseline,
|
|
39
|
+
recordContextUsageSnapshot,
|
|
37
40
|
resolveGaugeContextTokens,
|
|
38
41
|
resolveWorkerCompactPolicy,
|
|
39
42
|
} from '../loop/compact-policy.mjs';
|
|
43
|
+
import { snapshotProviderRequestTools } from '../../../../../session-runtime/tool-catalog.mjs';
|
|
40
44
|
|
|
41
45
|
// 'compacting' is a transient in-flight stage written just before semantic /
|
|
42
46
|
// recall-fasttrack compaction runs. If the process crashes or only partially
|
|
@@ -58,12 +62,19 @@ export function normalizeStaleCompactingStage(session) {
|
|
|
58
62
|
|
|
59
63
|
// Manual/auto-clear compaction needs the same threshold and post-compact
|
|
60
64
|
// target math as the loop, even when automatic compaction is disabled.
|
|
61
|
-
export function resolveSessionCompactionPolicy(session) {
|
|
65
|
+
export function resolveSessionCompactionPolicy(session, messages = session?.messages) {
|
|
62
66
|
if (!session) return null;
|
|
67
|
+
const requestTools = snapshotProviderRequestTools({
|
|
68
|
+
provider: session.provider,
|
|
69
|
+
tools: session.tools || [],
|
|
70
|
+
nativeTools: [],
|
|
71
|
+
messages: Array.isArray(messages) ? messages : [],
|
|
72
|
+
session,
|
|
73
|
+
});
|
|
63
74
|
return resolveWorkerCompactPolicy({
|
|
64
75
|
...session,
|
|
65
76
|
compaction: { ...(session.compaction || {}), auto: true },
|
|
66
|
-
},
|
|
77
|
+
}, requestTools);
|
|
67
78
|
}
|
|
68
79
|
function addCompactUsageToSession(session, usage) {
|
|
69
80
|
if (!session || !usage) return;
|
|
@@ -79,44 +90,9 @@ function addCompactUsageToSession(session, usage) {
|
|
|
79
90
|
session.totalUncachedInputTokens = (session.totalUncachedInputTokens || 0) + uncachedInputTokens;
|
|
80
91
|
session.tokensCumulative = (session.tokensCumulative || 0) + inputTokens + outputTokens;
|
|
81
92
|
}
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
// and treat it exactly like an RPC failure, so compaction proceeds WITHOUT
|
|
86
|
-
// recall-fasttrack instead of hanging.
|
|
87
|
-
const RECALL_MEMORY_CALL_TIMEOUT_MS = Math.max(
|
|
88
|
-
250,
|
|
89
|
-
Number(process.env.MIXDOG_AGENT_COMPACT_RECALL_TIMEOUT_MS) || 4000,
|
|
90
|
-
);
|
|
91
|
-
function recallMemoryTimeoutMs(session) {
|
|
92
|
-
const configured = positiveContextWindow(session?.compaction?.recallMemoryTimeoutMs);
|
|
93
|
-
// Clamp ALL sources (session-config included) to the 250ms floor so a
|
|
94
|
-
// misconfigured tiny value can't turn the bound into a busy no-wait.
|
|
95
|
-
return Math.max(250, configured || RECALL_MEMORY_CALL_TIMEOUT_MS);
|
|
96
|
-
}
|
|
97
|
-
// Cold-start allowance (clear/manual path only): a booting memory runtime can
|
|
98
|
-
// miss the tight first bound (waitForPort + first-RPC warmup ~2-10s). On a
|
|
99
|
-
// timeout we retry ONCE with a longer bound before honoring the bail-to-
|
|
100
|
-
// semantic contract, so a rebooting runtime succeeds instead of instantly
|
|
101
|
-
// failing. Non-timeout errors and outer aborts propagate immediately.
|
|
102
|
-
// 15s: memory boot is ~2-4s warm-cache / ~10s worst since the PG fast-start
|
|
103
|
-
// fix; keeping this tight bounds the clear path's worst case (2 memory calls
|
|
104
|
-
// retried + 120s semantic) under the TUI auto-clear watchdog (180s).
|
|
105
|
-
const RECALL_COLD_START_TIMEOUT_MS = 15_000;
|
|
106
|
-
function isTimeoutError(err) {
|
|
107
|
-
return typeof err?.message === 'string' && err.message.includes('timed out after');
|
|
108
|
-
}
|
|
109
|
-
async function callMemoryColdStart(args, callerCtx, timeoutMs, executeMemory) {
|
|
110
|
-
try {
|
|
111
|
-
return await callMemoryBounded(args, callerCtx, timeoutMs, executeMemory);
|
|
112
|
-
} catch (err) {
|
|
113
|
-
if (!isTimeoutError(err) || callerCtx?.signal?.aborted) throw err;
|
|
114
|
-
const coldMs = Math.max(timeoutMs, RECALL_COLD_START_TIMEOUT_MS);
|
|
115
|
-
if (coldMs <= timeoutMs) throw err;
|
|
116
|
-
try { process.stderr.write(`[session] recall-fasttrack ${args?.action || 'call'} cold-start retry (${timeoutMs}ms -> ${coldMs}ms)\n`); } catch {}
|
|
117
|
-
return await callMemoryBounded(args, callerCtx, coldMs, executeMemory);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
93
|
+
// Recall-fasttrack memory bounds live with the pipeline itself
|
|
94
|
+
// (loop/recall-fasttrack.mjs) so every caller — this one and the pre-send
|
|
95
|
+
// compaction — shares one timeout contract instead of each wiring its own.
|
|
120
96
|
// Semantic-compact timeout scales with transcript size (clear/manual path):
|
|
121
97
|
// default max(30s, ~10s per 25k estimated message tokens) capped at 120s, so a
|
|
122
98
|
// large (~100k-token) transcript no longer dies on a fixed 30s bound.
|
|
@@ -127,34 +103,6 @@ function semanticCompactTimeoutMs(session, messageTokens) {
|
|
|
127
103
|
const scaled = Math.ceil((messageTokens || 0) / 25_000) * 10_000;
|
|
128
104
|
return Math.min(120_000, Math.max(30_000, scaled));
|
|
129
105
|
}
|
|
130
|
-
async function callMemoryBounded(args, callerCtx, timeoutMs, executeMemory = executeInternalTool) {
|
|
131
|
-
const ac = new AbortController();
|
|
132
|
-
const outer = callerCtx?.signal;
|
|
133
|
-
const onOuterAbort = () => { try { ac.abort(); } catch {} };
|
|
134
|
-
if (outer) {
|
|
135
|
-
if (outer.aborted) ac.abort();
|
|
136
|
-
else { try { outer.addEventListener?.('abort', onOuterAbort, { once: true }); } catch {} }
|
|
137
|
-
}
|
|
138
|
-
let timer = null;
|
|
139
|
-
const timeout = new Promise((_, reject) => {
|
|
140
|
-
timer = setTimeout(() => {
|
|
141
|
-
try { ac.abort(); } catch {}
|
|
142
|
-
reject(new Error(`memory ${args?.action || 'call'} timed out after ${timeoutMs}ms`));
|
|
143
|
-
}, timeoutMs);
|
|
144
|
-
try { timer.unref?.(); } catch {}
|
|
145
|
-
});
|
|
146
|
-
try {
|
|
147
|
-
return await Promise.race([
|
|
148
|
-
executeMemory('memory', args, { ...callerCtx, signal: ac.signal }),
|
|
149
|
-
timeout,
|
|
150
|
-
]);
|
|
151
|
-
} finally {
|
|
152
|
-
if (timer) clearTimeout(timer);
|
|
153
|
-
// Drop the chained-abort listener when the call settles first, so a
|
|
154
|
-
// later outer abort can't fire into a dead controller / leak.
|
|
155
|
-
try { outer?.removeEventListener?.('abort', onOuterAbort); } catch {}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
106
|
// Element-identity change detection (same approach as loop.mjs messagesArrayChanged): two
|
|
159
107
|
// arrays are "unchanged" only when same length AND every slot is the same object
|
|
160
108
|
// reference. Used to reject a no-op prune (which returns a fresh array whose
|
|
@@ -438,11 +386,12 @@ export async function runSessionCompaction(session, opts = {}) {
|
|
|
438
386
|
try { beforeEncoded = JSON.stringify(messages); } catch { beforeEncoded = ''; }
|
|
439
387
|
try { afterEncoded = JSON.stringify(compacted); } catch { afterEncoded = ''; }
|
|
440
388
|
const afterMessageTokens = estimateMessagesTokens(compacted);
|
|
389
|
+
const postCompactPolicy = resolveSessionCompactionPolicy(session, compacted) || alignedPolicy;
|
|
441
390
|
// Same scale as beforeTokens: compaction invalidates the provider baseline,
|
|
442
391
|
// so the gauge's post-compact number is the calibrated transcript estimate
|
|
443
392
|
// plus the request reserve. The raw sum reported roughly half of that.
|
|
444
|
-
const afterTokens =
|
|
445
|
-
? currentContextEstimateTokens(afterMessageTokens,
|
|
393
|
+
const afterTokens = postCompactPolicy
|
|
394
|
+
? currentContextEstimateTokens(afterMessageTokens, postCompactPolicy)
|
|
446
395
|
: afterMessageTokens + reserveTokens;
|
|
447
396
|
const changed = beforeEncoded && afterEncoded
|
|
448
397
|
? beforeEncoded !== afterEncoded
|
|
@@ -471,7 +420,8 @@ export async function runSessionCompaction(session, opts = {}) {
|
|
|
471
420
|
triggerTokens,
|
|
472
421
|
bufferTokens,
|
|
473
422
|
bufferRatio,
|
|
474
|
-
|
|
423
|
+
requestReserveTokens: postCompactPolicy?.requestReserveTokens || 0,
|
|
424
|
+
reserveTokens: postCompactPolicy?.reserveTokens ?? reserveTokens,
|
|
475
425
|
type: compactType,
|
|
476
426
|
compactType,
|
|
477
427
|
lastCompactType: compactType,
|
|
@@ -503,7 +453,18 @@ export async function runSessionCompaction(session, opts = {}) {
|
|
|
503
453
|
} : null,
|
|
504
454
|
compactCount: (session.compaction?.compactCount || 0) + (changed ? 1 : 0),
|
|
505
455
|
};
|
|
506
|
-
if (changed)
|
|
456
|
+
if (changed) {
|
|
457
|
+
invalidateProviderContextBaseline(session);
|
|
458
|
+
if (postCompactPolicy) {
|
|
459
|
+
recordContextUsageSnapshot(session, postCompactPolicy, {
|
|
460
|
+
messages: compacted,
|
|
461
|
+
usedTokens: afterTokens,
|
|
462
|
+
messageTokensEst: afterMessageTokens,
|
|
463
|
+
source: 'post_compact',
|
|
464
|
+
updatedAt: now,
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
}
|
|
507
468
|
// Observability parity with the loop's pre-send pass: record the
|
|
508
469
|
// out-of-loop mutation as compact_meta and park a one-shot intent so the
|
|
509
470
|
// next turn's first send tags its cache break instead of logging an
|
|
@@ -6,7 +6,12 @@ import { loadSession, saveSessionAsync, setLiveSession, evictLiveSession, listSt
|
|
|
6
6
|
import { estimateMessagesTokens, estimateTranscriptContextUsage } from '../context-utils.mjs';
|
|
7
7
|
import { normalizeCompactType, DEFAULT_COMPACT_TYPE, SUMMARY_PREFIX } from '../compact.mjs';
|
|
8
8
|
import { runSessionCompaction, resolveSessionCompactionPolicy } from './compaction-runner.mjs';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
currentContextEstimateTokens,
|
|
11
|
+
invalidateContextUsageSnapshot,
|
|
12
|
+
recordContextUsageSnapshot,
|
|
13
|
+
resolveGaugeContextTokens,
|
|
14
|
+
} from '../loop/compact-policy.mjs';
|
|
10
15
|
import { hasUserConversationMessage, promptContentText, resetSessionBp3Environment } from './prompt-utils.mjs';
|
|
11
16
|
import { getProvider } from '../../providers/registry.mjs';
|
|
12
17
|
import { isSessionCompactionBlocked, getSessionAbortSignal, _runtimeEntries } from './runtime-liveness.mjs';
|
|
@@ -161,7 +166,10 @@ export async function clearSessionMessages(sessionId, options = {}) {
|
|
|
161
166
|
const beforeTokens = (clearPolicy
|
|
162
167
|
? resolveGaugeContextTokens(beforeMessageTokens, clearPolicy, { messages, sessionRef: session })
|
|
163
168
|
: 0) || estimateTranscriptContextUsage(messages, session.tools || [], { provider: session.provider });
|
|
164
|
-
const
|
|
169
|
+
const postClearPolicy = resolveSessionCompactionPolicy(session, keep);
|
|
170
|
+
const afterTokens = postClearPolicy
|
|
171
|
+
? currentContextEstimateTokens(afterMessageTokens, postClearPolicy)
|
|
172
|
+
: estimateTranscriptContextUsage(keep, session.tools || [], { provider: session.provider });
|
|
165
173
|
const now = Date.now();
|
|
166
174
|
// --- Fork the outgoing transcript to a separate resumable session BEFORE
|
|
167
175
|
// the wipe below. Runs for every clear path (plain /clear, auto-clear,
|
|
@@ -264,6 +272,17 @@ export async function clearSessionMessages(sessionId, options = {}) {
|
|
|
264
272
|
lastClearCompactType: clearCompactType || session.compaction?.compactType || null,
|
|
265
273
|
lastClearCompactError: clearCompactError?.message || null,
|
|
266
274
|
};
|
|
275
|
+
if (summaryCarriedForward && postClearPolicy) {
|
|
276
|
+
recordContextUsageSnapshot(session, postClearPolicy, {
|
|
277
|
+
messages: keep,
|
|
278
|
+
usedTokens: afterTokens,
|
|
279
|
+
messageTokensEst: afterMessageTokens,
|
|
280
|
+
source: 'post_clear',
|
|
281
|
+
updatedAt: now,
|
|
282
|
+
});
|
|
283
|
+
} else {
|
|
284
|
+
invalidateContextUsageSnapshot(session);
|
|
285
|
+
}
|
|
267
286
|
session.updatedAt = now;
|
|
268
287
|
await saveSessionAsync(session, { expectedGeneration: session.generation });
|
|
269
288
|
return session;
|
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
_buildLeadMetaContext,
|
|
22
22
|
} from './rules-cache.mjs';
|
|
23
23
|
import {
|
|
24
|
-
applyToolPermissionNarrowing,
|
|
25
24
|
finalizeSessionToolList,
|
|
26
25
|
resolveSessionTools,
|
|
27
26
|
permissionFromToolSpec,
|
|
@@ -213,11 +212,8 @@ export function createSession(opts) {
|
|
|
213
212
|
const resolvedAgent = opts.agent || opts.role || profile?.taskType || null;
|
|
214
213
|
const hiddenAgent = getHiddenAgent(resolvedAgent);
|
|
215
214
|
const isRetrievalAgent = hiddenAgent?.kind === 'retrieval';
|
|
216
|
-
//
|
|
217
|
-
|
|
218
|
-
// Do not leak a Skill manifest into those hidden prompts when no Skill()
|
|
219
|
-
// loader is available.
|
|
220
|
-
const skills = (opts.skipSkills || hiddenAgent) ? [] : collectPromptSkillsCached(opts.cwd);
|
|
215
|
+
// Lead and Agent share the same cwd-scoped Skill inventory.
|
|
216
|
+
const skills = opts.skipSkills ? [] : collectPromptSkillsCached(opts.cwd);
|
|
221
217
|
|
|
222
218
|
// BP1 is shared tool policy. BP2 holds persistent profile/tool catalogs;
|
|
223
219
|
// BP3 holds workflow/role and session/project environment.
|
|
@@ -230,7 +226,6 @@ export function createSession(opts) {
|
|
|
230
226
|
// override role-inapplicable entries.
|
|
231
227
|
const sessionDeny = [
|
|
232
228
|
...(Array.isArray(opts.disallowedTools) ? opts.disallowedTools : []),
|
|
233
|
-
...(hiddenAgent ? ['Skill'] : []),
|
|
234
229
|
...(!ownerIsAgent && workflowDisallowsAgentTool(opts.workflow) ? ['agent'] : []),
|
|
235
230
|
];
|
|
236
231
|
// The edit dialect this model never receives is omitted from the rules as
|
|
@@ -245,60 +240,31 @@ export function createSession(opts) {
|
|
|
245
240
|
? _buildAgentRules(agentRulesProfile)
|
|
246
241
|
: _buildLeadRules({ includeLeadBrief: !delegationFree }));
|
|
247
242
|
const metaContext = skipAgentRules ? '' : (ownerIsAgent ? '' : _buildLeadMetaContext());
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
// bundle. Resolve toolPermission (with profile/preset fallbacks) first, and
|
|
251
|
-
// let the stored/logged `permission` reflect that resolved value — not just
|
|
252
|
-
// opts.permission — so diagnostics show the effective read/write class.
|
|
243
|
+
// Role permission is prompt/diagnostic metadata only. Resolve and persist
|
|
244
|
+
// it without shaping the provider-visible Agent schema.
|
|
253
245
|
const toolPermission = opts.permission
|
|
254
246
|
|| profile?.permission
|
|
255
247
|
|| permissionFromToolSpec(toolPreset)
|
|
256
248
|
|| null;
|
|
257
249
|
const permission = toolPermission;
|
|
258
250
|
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
// - read-only roles (reviewer / hidden retrieval, i.e. any
|
|
264
|
-
// session resolving to permission 'read') -> 'readonly' bundle:
|
|
265
|
-
// read builtins (code_graph/find/glob/list/grep/read) + retrieval
|
|
266
|
-
// (web_search/web_fetch/Skill) + shell/task for self-verification
|
|
267
|
-
// (agent-owned readonly bundle only), no apply_patch, no MCP-write.
|
|
268
|
-
// applyToolPermissionNarrowing('read') below trims the
|
|
269
|
-
// bundle to AGENT_STRING_PERMISSION_READ_ALLOW so the final surface is
|
|
270
|
-
// bit-identical across these roles regardless of MCP registry state.
|
|
271
|
-
// - write roles (worker / heavy-worker / maintainer / …) -> 'full'
|
|
272
|
-
// bundle: the historical full schema.
|
|
273
|
-
// Call-time permission enforcement below is UNCHANGED (defense in depth):
|
|
274
|
-
// applyToolPermissionNarrowing still runs so the bundle choice never
|
|
275
|
-
// widens effective access.
|
|
276
|
-
const isReadOnlyAgentBundle = ownerIsAgent && toolPermission === 'read';
|
|
251
|
+
// Exactly two schema surfaces exist: Lead and Agent. Every Agent role gets
|
|
252
|
+
// the full Lead-capable base bundle; the recursive `agent` control tool is
|
|
253
|
+
// removed later at the owner boundary. Role permission remains prompt/
|
|
254
|
+
// diagnostic metadata and does not fragment the provider-visible schema.
|
|
277
255
|
const toolSpec = ownerIsAgent
|
|
278
|
-
?
|
|
256
|
+
? 'full'
|
|
279
257
|
: (Array.isArray(profile?.tools) ? profile.tools : toolPreset);
|
|
280
258
|
let toolsForRouting = resolveSessionTools(toolSpec, skills, {
|
|
281
259
|
ownerIsAgentSession: ownerIsAgent,
|
|
282
260
|
mcpScopeId: opts.mcpScopeId || null,
|
|
283
261
|
modelName,
|
|
284
262
|
});
|
|
285
|
-
// Fail-closed permission intersection: when a session declares an explicit
|
|
286
|
-
// object-form permission, intersect the
|
|
287
|
-
// resolved tool list with the permission's allow/deny lists. If the
|
|
288
|
-
// intersection produces an empty set the permission config is broken —
|
|
289
|
-
// fail closed (zero tools) rather than silently falling back to the full
|
|
290
|
-
// preset, which would grant the role more surface than declared.
|
|
291
|
-
if (ownerIsAgent) {
|
|
292
|
-
// Pass the RESOLVED agent (opts.agent || opts.role): narrowing keys
|
|
293
|
-
// retrieval/locator roles off this name to strip
|
|
294
|
-
// shell/task; verifying read roles (reviewer) keep them.
|
|
295
|
-
toolsForRouting = applyToolPermissionNarrowing(toolsForRouting, toolPermission, resolvedAgent);
|
|
296
|
-
}
|
|
297
263
|
|
|
298
264
|
const workflowMeta = toSessionWorkflowMeta(opts.workflow);
|
|
299
265
|
const hasCallerAllow = Array.isArray(opts.schemaAllowedTools);
|
|
300
266
|
const tools = finalizeSessionToolList(toolsForRouting, {
|
|
301
|
-
schemaAllowedTools: hasCallerAllow ? opts.schemaAllowedTools : null,
|
|
267
|
+
schemaAllowedTools: ownerIsAgent ? null : (hasCallerAllow ? opts.schemaAllowedTools : null),
|
|
302
268
|
disallowedTools: sessionDeny,
|
|
303
269
|
ownerIsAgent,
|
|
304
270
|
resolvedAgent,
|
|
@@ -478,7 +444,9 @@ export function createSession(opts) {
|
|
|
478
444
|
profileId: profile?.id || null,
|
|
479
445
|
permissionMode: opts.permissionMode ?? null,
|
|
480
446
|
providerCacheOpts: providerCacheOpts || null,
|
|
447
|
+
parentSessionId: opts.parentSessionId || null,
|
|
481
448
|
ownerSessionId: opts.ownerSessionId || null,
|
|
449
|
+
visibility: opts.visibility || null,
|
|
482
450
|
clientHostPid: opts.clientHostPid || null,
|
|
483
451
|
};
|
|
484
452
|
refreshSessionBp3Environment(session, opts.cwd);
|
|
@@ -643,7 +611,7 @@ const _preparedResumes = new Map();
|
|
|
643
611
|
|
|
644
612
|
function _prepareResumeTools(session, preset) {
|
|
645
613
|
const ownerIsAgent = isAgentOwner(session);
|
|
646
|
-
const skills =
|
|
614
|
+
const skills = collectPromptSkillsCached(session.cwd);
|
|
647
615
|
let toolSpec = ownerIsAgent ? 'full' : (preset || session.preset || 'full');
|
|
648
616
|
const agentRuntime = getAgentRuntimeSync();
|
|
649
617
|
if (session.profileId && agentRuntime?.getProfile) {
|
|
@@ -657,19 +625,17 @@ function _prepareResumeTools(session, preset) {
|
|
|
657
625
|
mcpScopeId: session.mcpScopeId || null,
|
|
658
626
|
modelName: session.model,
|
|
659
627
|
});
|
|
660
|
-
if (ownerIsAgent) {
|
|
661
|
-
toolsForRouting = applyToolPermissionNarrowing(toolsForRouting, session.toolPermission, session.agent || null);
|
|
662
|
-
}
|
|
663
628
|
return {
|
|
664
629
|
session,
|
|
665
630
|
preset,
|
|
666
631
|
toolSpec,
|
|
667
632
|
ownerIsAgent,
|
|
668
633
|
tools: finalizeSessionToolList(toolsForRouting, {
|
|
669
|
-
schemaAllowedTools:
|
|
634
|
+
schemaAllowedTools: ownerIsAgent
|
|
635
|
+
? null
|
|
636
|
+
: (Array.isArray(session.schemaAllowedTools) ? session.schemaAllowedTools : null),
|
|
670
637
|
disallowedTools: [
|
|
671
638
|
...(Array.isArray(session.disallowedTools) ? session.disallowedTools : []),
|
|
672
|
-
...(getHiddenAgent(session.agent || null) ? ['Skill'] : []),
|
|
673
639
|
...(!isAgentOwner(session) && workflowDisallowsAgentTool(session.workflow) ? ['agent'] : []),
|
|
674
640
|
],
|
|
675
641
|
ownerIsAgent,
|
|
@@ -715,6 +681,14 @@ export function prefetchSession(sessionId, preset = 'full') {
|
|
|
715
681
|
export function prepareSessionProjection(session, preset = 'full') {
|
|
716
682
|
if (!session?.id) return null;
|
|
717
683
|
const prepared = _preparedResumeForSession(session, preset);
|
|
684
|
+
// This read-only projection describes the last provider-visible session,
|
|
685
|
+
// not the transient bootstrap bundle that resumeSession installs before
|
|
686
|
+
// session-runtime reapplies deferred selections. Keeping the persisted
|
|
687
|
+
// active surface preserves its provider baseline/tool signature while the
|
|
688
|
+
// cached `prepared.tools` remains available for the real resume.
|
|
689
|
+
const projectionTools = Array.isArray(session.tools)
|
|
690
|
+
? session.tools
|
|
691
|
+
: prepared.tools;
|
|
718
692
|
let contextMeta = null;
|
|
719
693
|
try {
|
|
720
694
|
const provider = session.provider ? getProvider(session.provider) : null;
|
|
@@ -727,7 +701,7 @@ export function prepareSessionProjection(session, preset = 'full') {
|
|
|
727
701
|
return {
|
|
728
702
|
...session,
|
|
729
703
|
toolSpec: prepared.toolSpec,
|
|
730
|
-
tools:
|
|
704
|
+
tools: projectionTools,
|
|
731
705
|
...(contextMeta ? {
|
|
732
706
|
contextWindow: contextMeta.contextWindow,
|
|
733
707
|
rawContextWindow: contextMeta.rawContextWindow,
|
|
@@ -58,9 +58,12 @@ export function recordStandaloneStatusTelemetry(session, result, durationMs) {
|
|
|
58
58
|
...summarizeGatewayUsage(routeInfo, providerOut, _compactArg, durationMs),
|
|
59
59
|
requestKind: 'chat',
|
|
60
60
|
sessionId: session.id || null,
|
|
61
|
+
sourceType: session.sourceType || 'lead',
|
|
62
|
+
sourceName: session.sourceName || session.agent || null,
|
|
61
63
|
toolCount: result.toolCallsTotal ?? null,
|
|
62
64
|
messageCount: Array.isArray(session.messages) ? session.messages.length : null,
|
|
63
65
|
cacheStrategy: session.providerCacheOpts?.cacheStrategy || null,
|
|
66
|
+
transportTiming: result.transportTiming || null,
|
|
64
67
|
};
|
|
65
68
|
recordGatewayUsageEvent(summary);
|
|
66
69
|
} catch {
|