mixdog 1.3.1 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/package.json +8 -8
- package/scripts/native-release-status.mjs +238 -0
- package/scripts/verify-runtime-dependency-versions.mjs +158 -0
- package/src/agents/reviewer/AGENT.md +5 -7
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +9 -1
- package/src/defaults/skills/browser-use/SKILL.md +6 -3
- package/src/defaults/skills/local-provider/SKILL.md +33 -6
- 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 +50 -3
- package/src/defaults/skills/setup/references/surfaces.md +23 -3
- package/src/defaults/skills/setup-guide/SKILL.md +7 -3
- 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/rules/agent-mode/AGENT_MODE.md +8 -5
- package/src/rules/agent-mode/MIXY.md +6 -8
- package/src/rules/lead/LEAD.md +7 -10
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/20-research.md +2 -0
- package/src/rules/shared/45-destructive.md +5 -1
- package/src/rules/shared/60-verification.md +6 -4
- 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 +9 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -5
- 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 +84 -32
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +38 -11
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +15 -3
- 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 +84 -42
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +27 -8
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- 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-config.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -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-wire.mjs +2 -1
- 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-ws.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
- package/src/runtime/agent/orchestrator/providers/registry.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +13 -1
- 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-runtime.mjs +5 -0
- 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/goal-turns.mjs +10 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +4 -6
- 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 +52 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +35 -13
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +7 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +8 -3
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -1
- 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 +30 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +196 -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/continuation.mjs +15 -6
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +45 -19
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +44 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +185 -37
- 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 +6 -2
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +4 -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 +240 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +102 -35
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +19 -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 +199 -109
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/empty-nudge.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +62 -13
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +22 -6
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +5 -5
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +33 -8
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/call-prep.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +27 -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/manager/agent-listing-notice.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +27 -14
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +32 -1
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +115 -0
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +6 -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/prompt-utils.mjs +36 -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-crud.mjs +28 -9
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +4 -9
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +14 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +7 -3
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +52 -11
- package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +18 -3
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +126 -12
- package/src/runtime/agent/orchestrator/session/runtime-user-context.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +16 -3
- 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/stale-sweep.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +140 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +15 -5
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +49 -1
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +80 -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/store-summary-reader.mjs +33 -1
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.d.mts +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +37 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +1 -0
- 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 +35 -5
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +47 -14
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +6 -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/git-command-tool.mjs +127 -20
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +557 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +10 -12
- 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 +42 -23
- 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/legacy-office.mjs +110 -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/prompt-restore.mjs +70 -0
- package/src/runtime/attachments/store.mjs +109 -33
- 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 +66 -16
- package/src/runtime/effort-judge/model-install.mjs +47 -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/memory-chunk-quality.mjs +14 -2
- 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 +135 -29
- package/src/runtime/shared/agent-avatar-sprites.mjs +23 -8
- package/src/runtime/shared/agent-avatar.mjs +3 -2
- package/src/runtime/shared/agent-kind-migration.mjs +200 -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-room-host.d.mts +31 -0
- package/src/runtime/shared/agent-room-host.mjs +58 -0
- package/src/runtime/shared/agent-store.mjs +24 -7
- 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 +35 -0
- package/src/runtime/shared/bot-split-migration.mjs +1 -1
- package/src/runtime/shared/bounded-download.mjs +4 -2
- package/src/runtime/shared/config.mjs +39 -9
- 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 +4 -0
- package/src/runtime/shared/error-presentation.mjs +22 -4
- package/src/runtime/shared/file-has-data.mjs +28 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
- package/src/runtime/shared/pending-agent-work.mjs +54 -0
- 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/redact-directories.mjs +18 -0
- package/src/runtime/shared/remove-directory.mjs +28 -0
- 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/session-baseline-store.mjs +8 -2
- package/src/runtime/shared/session-sidebar-host.d.mts +11 -2
- package/src/runtime/shared/session-sidebar-host.mjs +16 -3
- 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 +10 -0
- package/src/runtime/shared/tool-work-units.mjs +12 -9
- 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 +277 -124
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +92 -61
- package/src/runtime/shared/utf8-cut.mjs +10 -0
- package/src/runtime/shared/worktrees/activity-gate.mjs +251 -61
- package/src/runtime/shared/worktrees/contract.mjs +11 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +11 -2
- package/src/runtime/shared/worktrees/manager.mjs +419 -52
- package/src/runtime/shared/worktrees/registry.mjs +29 -27
- package/src/runtime/shared/worktrees/tool-host.mjs +39 -0
- package/src/runtime/tidy/core-install.mjs +26 -4
- package/src/runtime/tidy/install.mjs +91 -23
- package/src/runtime/tidy/process.mjs +41 -8
- package/src/runtime/tidy/resolve.mjs +10 -7
- package/src/runtime/web-search/lib/config.mjs +4 -16
- package/src/session-runtime/agent-home-delivery.mjs +542 -204
- package/src/session-runtime/agent-profile-changes.mjs +16 -0
- package/src/session-runtime/agent-room-delivery.mjs +81 -35
- package/src/session-runtime/agent-task-sessions.mjs +811 -179
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +48 -24
- package/src/session-runtime/boot/config.mjs +1 -0
- package/src/session-runtime/boot/facade.mjs +16 -7
- package/src/session-runtime/boot/infrastructure.mjs +14 -2
- package/src/session-runtime/boot/providers.mjs +2 -2
- package/src/session-runtime/boot/shared.mjs +12 -6
- package/src/session-runtime/boot/tools.mjs +23 -3
- 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 +60 -55
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/held-requests.mjs +31 -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 +24 -26
- 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-recency.mjs +1 -0
- package/src/session-runtime/model-route/route-tuning.mjs +4 -1
- package/src/session-runtime/model-route/set-route.mjs +61 -1
- package/src/session-runtime/owned-automation-run.mjs +8 -1
- package/src/session-runtime/provider-models/row-hydration.mjs +8 -1
- package/src/session-runtime/quick-model-rows/model-meta.mjs +2 -0
- package/src/session-runtime/quick-model-rows/provider-rows.mjs +7 -1
- package/src/session-runtime/route-resolution.mjs +16 -8
- 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-review-api.mjs +4 -1
- 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/job-views/agent-list.mjs +34 -19
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +25 -21
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +7 -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 +8 -5
- 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 +26 -6
- 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/services/worktree-access.mjs +27 -0
- 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/session-hooks.mjs +9 -17
- package/src/session-runtime/settings-builtin-tools-api.mjs +65 -1
- package/src/session-runtime/settings-compaction-api.mjs +86 -39
- package/src/session-runtime/setup-tool/executor.mjs +12 -2
- package/src/session-runtime/setup-tool/settings-contract.mjs +34 -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 +349 -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 +183 -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 +48 -369
- package/src/session-runtime/tool-surface.mjs +10 -4
- package/src/session-runtime/turn/session-ops.mjs +8 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +95 -88
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +7 -2
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +527 -333
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +85 -63
- 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/transition-steps.mjs +1 -18
- package/src/session-runtime/workspace/transitions.mjs +279 -67
- package/src/session-runtime/workspace/workspace-state.mjs +7 -6
- package/src/session-runtime/workspace/worktree-tool.mjs +194 -0
- package/src/standalone/daemon-agent-control.mjs +4 -1
- package/src/standalone/daemon-lag-profiler.mjs +3 -1
- package/src/standalone/daemon-session-control.mjs +173 -15
- package/src/standalone/daemon-telemetry.mjs +9 -0
- package/src/standalone/daemon.mjs +33 -10
- package/src/standalone/local-session-runtime.mjs +33 -16
- package/src/standalone/session-client.mjs +7 -2
- package/src/standalone/session-protocol.mjs +8 -0
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +2 -0
- package/src/standalone/session-service/agent-route-follow.mjs +69 -0
- package/src/standalone/session-service/session-calls/session-turns.mjs +33 -4
- package/src/standalone/session-service.mjs +21 -0
- package/src/standalone/session-state-projection.mjs +19 -9
- package/src/standalone/session-tool-output.mjs +36 -9
- package/src/standalone/staged-import.mjs +47 -0
- package/src/tui/App.jsx +2 -0
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
- package/src/tui/app/message-selector.mjs +15 -2
- package/src/tui/app/model-options.mjs +16 -2
- package/src/tui/app/model-picker.mjs +2 -1
- package/src/tui/app/route-pickers.mjs +3 -1
- 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 +617 -369
- package/src/tui/paste-attachments.mjs +0 -1
- package/src/tui/paste-text-policy.mjs +4 -5
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/agent-job-feed/execution-delivery.mjs +4 -1
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/notice-surface.mjs +3 -0
- package/src/tui/session/session-api/intake/abort.mjs +52 -18
- package/src/tui/session/session-api/intake/rewind.mjs +39 -4
- package/src/tui/session/session-api/media.mjs +2 -1
- package/src/tui/session/session-api/routes-agent-definitions.mjs +76 -0
- package/src/tui/session/session-api/routes-write.mjs +203 -0
- package/src/tui/session/session-api/routes.mjs +23 -247
- 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 +142 -14
- package/src/tui/session/transcript-intake.mjs +2 -0
- package/src/tui/session/turn.mjs +23 -14
- 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
- package/src/session-runtime/room-member-gate.mjs +0 -48
|
@@ -27,12 +27,34 @@
|
|
|
27
27
|
* messages BP, which also handles tool_result accumulation and per-call
|
|
28
28
|
* task/event data while isolating volatile text from stable prefix BPs.
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
30
|
+
* Lead class vs agent class: the Lead class is every Lead session — a coding
|
|
31
|
+
* Lead (incl. a task session a bot creates with `session create`, which is a
|
|
32
|
+
* coding Lead with agent 'lead'), raw/CLI callers without an agent, and every
|
|
33
|
+
* agent-mode Lead (a bot's home thread `sess_home_*` incl. Mixy and routine
|
|
34
|
+
* turns in it, a room member session, a schedule/webhook run). Sub-agents a
|
|
35
|
+
* Lead or home thread spawns (owner:'agent') and hidden roles are the agent
|
|
36
|
+
* class (isLeadCacheClass).
|
|
37
|
+
*
|
|
38
|
+
* OpenAI caching (https://developers.openai.com/api/docs/guides/prompt-caching,
|
|
39
|
+
* checked 2026-10-21):
|
|
40
|
+
* - OpenAI (public API key): prompt_cache_key plus model-specific lifetime
|
|
41
|
+
* when response storage is enabled. GPT-5.6+ Responses take
|
|
42
|
+
* prompt_cache_options.ttl: "30m" (default, writes 1.25x input) or "12h"
|
|
43
|
+
* (writes 2.5x); reads 0.1x (0.05x on GPT-6.1 Sol) either way. Earlier
|
|
44
|
+
* models keep prompt_cache_retention '24h' on the extended-retention list.
|
|
45
|
+
* The request ttl is "30m" (moving tail); Lead-class sessions add one
|
|
46
|
+
* explicit "12h" breakpoint at the end of the stable prefix (tools +
|
|
47
|
+
* instructions + environment developer item; top-level instructions
|
|
48
|
+
* cannot carry a breakpoint). Break-even: the 12h write costs
|
|
49
|
+
* (2.5-1.25)=1.25x the prefix once per 12h window, every gap > 30m saves
|
|
50
|
+
* a 1.25x rewrite for a 0.1x read (1.15x), so it pays from ~1.09 long gaps
|
|
51
|
+
* per 12h — an hourly routine or a returning user pays it back many times;
|
|
52
|
+
* a short sub-agent never sees one, so agents stay on "30m".
|
|
53
|
+
* - OpenAI OAuth (Codex/ChatGPT login): prompt_cache_key only, request body
|
|
54
|
+
* unchanged. Since 2026-10-20 OpenAI keeps the cache of logged-in Codex
|
|
55
|
+
* users indefinitely ("we keep cache forever … guaranteed to hit the
|
|
56
|
+
* cache", https://x.com/thsottiaux/status/2112712984644784534), so the
|
|
57
|
+
* tail never expires: no cache-driven idle clear or compaction.
|
|
36
58
|
* - Gemini: provider-managed explicit cachedContents with 5m default TTL, plus
|
|
37
59
|
* implicit caching as a fallback when the prefix is below cache minimums.
|
|
38
60
|
* - xAI: conversation routing for chat; Responses omits prompt_cache_key
|
|
@@ -46,6 +68,8 @@
|
|
|
46
68
|
import { createHash } from 'node:crypto';
|
|
47
69
|
import { stableHashStringify } from '../stable-hash-stringify.mjs';
|
|
48
70
|
import { getHiddenAgent } from '../internal-agents.mjs';
|
|
71
|
+
import { isAgentOwner } from '../agent-owner.mjs';
|
|
72
|
+
import { isAgentModeSession } from '../session/agent-mode.mjs';
|
|
49
73
|
import { cleanString } from '../../../shared/clean.mjs';
|
|
50
74
|
import { nonNegativeInt, positiveInt } from '../../../shared/numbers.mjs';
|
|
51
75
|
|
|
@@ -63,6 +87,20 @@ function isOneShotMaintenanceAgent(agent) {
|
|
|
63
87
|
return Boolean(hidden && hidden.kind === 'maintenance' && hidden.toolSchemaProfile === 'none');
|
|
64
88
|
}
|
|
65
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Whether a session gets the Lead cache class (see the header): the Lead,
|
|
92
|
+
* raw callers without an agent, and agent-mode Leads (a bot's home thread,
|
|
93
|
+
* a room member session, a schedule/webhook run) whose `agent` is the bot's
|
|
94
|
+
* id. `session` is the record or create options (`id`, `owner`,
|
|
95
|
+
* `sessionMode`, `ownerAgentId`); a delegated sub-agent (owner:'agent') and
|
|
96
|
+
* hidden roles are always the agent class.
|
|
97
|
+
*/
|
|
98
|
+
export function isLeadCacheClass(agent, session = null) {
|
|
99
|
+
if (getHiddenAgent(agent) || (session && isAgentOwner(session))) return false;
|
|
100
|
+
if (!agent || agent === 'lead') return true;
|
|
101
|
+
return Boolean(session) && isAgentModeSession(session);
|
|
102
|
+
}
|
|
103
|
+
|
|
66
104
|
/**
|
|
67
105
|
* Lead-session BP4 (messages tail) TTL, linked to the autoClear idle-sweep
|
|
68
106
|
* config (config.mjs `autoClear: { enabled, idleMs }`, normalized via
|
|
@@ -94,7 +132,9 @@ export function resolveLeadMessagesTtl(autoClear) {
|
|
|
94
132
|
* warm window survives per-session gaps. The volatile message tail (BP4) is
|
|
95
133
|
* per-session.
|
|
96
134
|
*
|
|
97
|
-
* Lead sessions
|
|
135
|
+
* Lead-class sessions (isLeadCacheClass — incl. bot home threads, whose
|
|
136
|
+
* hourly routine turns otherwise re-wrote the whole chat on a 5m tail) are
|
|
137
|
+
* linked to the user's autoClear idle-sweep config (see
|
|
98
138
|
* resolveLeadMessagesTtl); its Anthropic default is 1h, while explicit
|
|
99
139
|
* shorter overrides retain the shorter-sweep behavior. The 2026-07-16 6.8h
|
|
100
140
|
* trace supports the 1h Lead tail: 24/25 Lead intra-session gaps over 5m were
|
|
@@ -109,8 +149,10 @@ export function resolveLeadMessagesTtl(autoClear) {
|
|
|
109
149
|
* shouldCompactForExpiredAgentCache), so the cold request rewrites the
|
|
110
150
|
* compacted transcript instead of the whole accumulated tail. Replayed agent
|
|
111
151
|
* cost vs a 1h tail: -24.6% with that compaction, +2.7% without it.
|
|
112
|
-
* (
|
|
113
|
-
*
|
|
152
|
+
* (These tiers only drive explicit-breakpoint providers — Anthropic. OpenAI's
|
|
153
|
+
* lifetimes are resolveOpenAiPrefixCacheTtl / providerTailCacheLifetimeMs;
|
|
154
|
+
* the 5m-vs-1h reasoning does not apply to openai-oauth, whose cache does
|
|
155
|
+
* not expire.)
|
|
114
156
|
*
|
|
115
157
|
* Exception: one-shot LLM-only maintenance roles are asked once on a fresh
|
|
116
158
|
* session and closed, so their per-call message tail is never read back and
|
|
@@ -120,7 +162,7 @@ export function resolveLeadMessagesTtl(autoClear) {
|
|
|
120
162
|
* Anthropic's minimum cacheable length is simply not written, so the marker
|
|
121
163
|
* costs nothing there.
|
|
122
164
|
*/
|
|
123
|
-
export function resolveCacheStrategy(agent, { autoClear } = {}) {
|
|
165
|
+
export function resolveCacheStrategy(agent, { autoClear, session = null } = {}) {
|
|
124
166
|
if (isOneShotMaintenanceAgent(agent)) {
|
|
125
167
|
return { tools: 'none', system: '1h', tier3: '1h', messages: 'none' };
|
|
126
168
|
}
|
|
@@ -137,18 +179,60 @@ export function resolveCacheStrategy(agent, { autoClear } = {}) {
|
|
|
137
179
|
}
|
|
138
180
|
return strategy;
|
|
139
181
|
};
|
|
140
|
-
if (
|
|
141
|
-
// Hidden and
|
|
142
|
-
// rebuilds once it expires — only
|
|
143
|
-
// autoClear.
|
|
182
|
+
if (!isLeadCacheClass(agent, session)) {
|
|
183
|
+
// Hidden roles and sub-agents use a flat 5m tail that pre-send
|
|
184
|
+
// compaction rebuilds once it expires — only Lead-class tails are linked
|
|
185
|
+
// to autoClear.
|
|
144
186
|
return applyEnv({ tools: 'none', system: '1h', tier3: '1h', messages: '5m' });
|
|
145
187
|
}
|
|
146
|
-
// Lead
|
|
147
|
-
//
|
|
188
|
+
// Lead class (Lead, raw/CLI callers, bot home threads and other
|
|
189
|
+
// agent-mode Leads): message tail TTL is linked to autoClear (see
|
|
148
190
|
// resolveLeadMessagesTtl).
|
|
149
191
|
return applyEnv({ tools: 'none', system: '1h', tier3: '1h', messages: resolveLeadMessagesTtl(autoClear) });
|
|
150
192
|
}
|
|
151
193
|
|
|
194
|
+
// OpenAI public API, GPT-5.6+ Responses: the moving tail rides the request
|
|
195
|
+
// ttl "30m"; Lead-class sessions pin their stable prefix with one "12h"
|
|
196
|
+
// breakpoint (header: break-even). Earlier models' typical retention is
|
|
197
|
+
// ~30 min as well.
|
|
198
|
+
export const OPENAI_TAIL_CACHE_TTL = '30m';
|
|
199
|
+
export const OPENAI_LEAD_PREFIX_CACHE_TTL = '12h';
|
|
200
|
+
const ANTHROPIC_TAIL_LIFETIME_MS = Object.freeze({ '5m': 5 * 60_000, '1h': 60 * 60_000 });
|
|
201
|
+
const OPENAI_TAIL_LIFETIME_MS = 30 * 60_000;
|
|
202
|
+
|
|
203
|
+
/** The OpenAI (API key) stable-prefix TTL for a session: '12h' for the Lead
|
|
204
|
+
* class, null (request default "30m" only) for sub-agents and hidden roles. */
|
|
205
|
+
export function resolveOpenAiPrefixCacheTtl(agent, session = null) {
|
|
206
|
+
return isLeadCacheClass(agent, session) ? OPENAI_LEAD_PREFIX_CACHE_TTL : null;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Single source of truth for how long a session's message-tail cache stays
|
|
211
|
+
* readable, per provider, in ms. null = no expiring tail to act on: the cache
|
|
212
|
+
* does not expire (openai-oauth — logged-in Codex cache is kept indefinitely),
|
|
213
|
+
* or the provider exposes no tail lifetime. Any "compact or clear because the
|
|
214
|
+
* tail cache expired" rule must read this.
|
|
215
|
+
* - openai-oauth → null (permanent; never compact for cache reasons)
|
|
216
|
+
* - openai → 30m (request ttl "30m"; the Lead's 12h prefix survives)
|
|
217
|
+
* - Anthropic → the session cacheStrategy.messages tier (5m / 1h)
|
|
218
|
+
*/
|
|
219
|
+
export function providerTailCacheLifetimeMs(provider, cacheStrategy = null) {
|
|
220
|
+
const key = cleanString(provider).toLowerCase();
|
|
221
|
+
if (key === 'openai-oauth') return null;
|
|
222
|
+
if (key === 'openai') return OPENAI_TAIL_LIFETIME_MS;
|
|
223
|
+
if (cacheCapabilityForProvider(key) === 'explicit-breakpoint') {
|
|
224
|
+
return ANTHROPIC_TAIL_LIFETIME_MS[cacheStrategy?.messages] ?? null;
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Whether `session`'s message tail expired since its last model call. */
|
|
230
|
+
export function sessionTailCacheExpired(session, now = Date.now()) {
|
|
231
|
+
const lifetime = providerTailCacheLifetimeMs(session?.provider, session?.providerCacheOpts?.cacheStrategy);
|
|
232
|
+
const lastSendAt = Number(session?.lastProviderSendAt);
|
|
233
|
+
return lifetime !== null && lastSendAt > 0 && now - lastSendAt > lifetime;
|
|
234
|
+
}
|
|
235
|
+
|
|
152
236
|
// Provider cache capability kinds:
|
|
153
237
|
// 'explicit-breakpoint' — explicit provider-side cache_control writes
|
|
154
238
|
// 'key-prefix' — provider-managed shard keyed by cache key/session
|
|
@@ -482,22 +566,26 @@ function oneShotPromptCacheOpts(agent) {
|
|
|
482
566
|
|
|
483
567
|
/**
|
|
484
568
|
* Cache send options for a role's requests on `provider`: the breakpoint
|
|
485
|
-
* strategy on explicit-breakpoint providers
|
|
486
|
-
*
|
|
569
|
+
* strategy on explicit-breakpoint providers, the Lead-class 12h prefix TTL on
|
|
570
|
+
* the OpenAI public API, plus the one-shot shared scope. Session and
|
|
571
|
+
* session-less callers use this one resolution; `options.session` (record or
|
|
572
|
+
* create options) classifies agent-mode Leads such as bot home threads.
|
|
487
573
|
*/
|
|
488
574
|
export function roleProviderCacheOpts(provider, agent, options = {}) {
|
|
489
|
-
if (cacheCapabilityForProvider(provider) !== 'explicit-breakpoint') return oneShotPromptCacheOpts(agent);
|
|
490
575
|
return buildProviderCacheOpts(provider, null, agent, options);
|
|
491
576
|
}
|
|
492
577
|
|
|
493
578
|
export function buildProviderCacheOpts(provider, _sessionId, agent, options = {}) {
|
|
494
|
-
const ttls = resolveCacheStrategy(agent, options);
|
|
495
579
|
const capability = cacheCapabilityForProvider(provider);
|
|
496
|
-
if (
|
|
497
|
-
//
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
return
|
|
580
|
+
if (provider === 'openai') {
|
|
581
|
+
// Read by applyOpenAIDirectCachePolicy (GPT-5.6+ Responses only).
|
|
582
|
+
const prefixTtl = resolveOpenAiPrefixCacheTtl(agent, options.session);
|
|
583
|
+
const opts = { ...(prefixTtl ? { promptCachePrefixTtl: prefixTtl } : {}), ...oneShotPromptCacheOpts(agent) };
|
|
584
|
+
return Object.keys(opts).length ? opts : null;
|
|
501
585
|
}
|
|
502
|
-
return
|
|
586
|
+
if (capability !== 'explicit-breakpoint') return oneShotPromptCacheOpts(agent);
|
|
587
|
+
// 2026-03-06 Anthropic dropped default TTL 1h→5m. We request 1h via
|
|
588
|
+
// cache_control ttl:"1h"; no beta header is required.
|
|
589
|
+
// Verified 2026-04-17 (ephemeral_1h_input_tokens=4722).
|
|
590
|
+
return { cacheStrategy: resolveCacheStrategy(agent, options), ...oneShotPromptCacheOpts(agent) };
|
|
503
591
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { configuredAgentRouteCandidates, isAgentDisabled } from '../../../shared/agent-route-config.mjs';
|
|
2
|
+
import { normalizeContextTokens } from '../../../shared/llm/default-context-window.mjs';
|
|
2
3
|
import { loadConfig } from '../config.mjs';
|
|
3
4
|
import { getHiddenAgent } from '../internal-agents.mjs';
|
|
4
5
|
|
|
@@ -13,6 +14,13 @@ function normalizeMaintenanceCandidate(candidate) {
|
|
|
13
14
|
effort: String(candidate.effort || '').trim() || undefined,
|
|
14
15
|
fast: candidate.fast === true,
|
|
15
16
|
...(candidate.autoEffort === false ? { autoEffort: false } : {}),
|
|
17
|
+
...(candidate.modelParameters && typeof candidate.modelParameters === 'object'
|
|
18
|
+
? { modelParameters: { ...candidate.modelParameters } }
|
|
19
|
+
: {}),
|
|
20
|
+
...(Number(candidate.contextPercent) > 0 ? { contextPercent: Number(candidate.contextPercent) } : {}),
|
|
21
|
+
...(normalizeContextTokens(candidate.contextTokens)
|
|
22
|
+
? { contextTokens: normalizeContextTokens(candidate.contextTokens) }
|
|
23
|
+
: {}),
|
|
16
24
|
};
|
|
17
25
|
}
|
|
18
26
|
|
|
@@ -20,7 +20,8 @@ export function createRoomSupervisorCompletion(deps = {}) {
|
|
|
20
20
|
const log = deps.log || ((line) => process.stderr.write(line));
|
|
21
21
|
|
|
22
22
|
/** The decision for one step (parseRoomDecision), null for an unusable
|
|
23
|
-
* reply
|
|
23
|
+
* reply, `{ action: 'unmanaged' }` when no Maintainer model is configured;
|
|
24
|
+
* throws when the configured provider is unavailable. */
|
|
24
25
|
return async function decideRoomTurn(input = {}) {
|
|
25
26
|
const members = (Array.isArray(input?.members) ? input.members : [])
|
|
26
27
|
.filter((member) => member && typeof member.id === 'string' && member.id)
|
|
@@ -32,12 +33,12 @@ export function createRoomSupervisorCompletion(deps = {}) {
|
|
|
32
33
|
if (!members.length) return null;
|
|
33
34
|
const config = load();
|
|
34
35
|
// The Maintainer's own route only: a step runs after every turn, so it
|
|
35
|
-
// never falls back to the default (Lead) model the user pays most for
|
|
36
|
-
//
|
|
36
|
+
// never falls back to the default (Lead) model the user pays most for.
|
|
37
|
+
// Without one the room is unmoderated: the members called answer once.
|
|
37
38
|
const route = resolveRoute({ agent: 'cycle1-agent', config, includeDefault: false });
|
|
38
39
|
const providerName = String(route?.provider || '').trim();
|
|
39
40
|
const model = String(route?.model || '').trim();
|
|
40
|
-
if (!providerName || !model)
|
|
41
|
+
if (!providerName || !model) return { action: 'unmanaged' };
|
|
41
42
|
const signal = AbortSignal.timeout(TIMEOUT_MS);
|
|
42
43
|
await initialize(config.providers || {}, { signal });
|
|
43
44
|
const provider = providerFor(providerName);
|
|
@@ -237,6 +237,8 @@ function traceAgentUsage({
|
|
|
237
237
|
chainContinuous,
|
|
238
238
|
continuationResetReason,
|
|
239
239
|
inputTokensInclusive,
|
|
240
|
+
// Anthropic: per-block prefix hashes of the request (providers/lib/anthropic-prefix-trace.mjs).
|
|
241
|
+
prefixBlocks,
|
|
240
242
|
}) {
|
|
241
243
|
const identity = currentUsageContext();
|
|
242
244
|
provider = identity?.provider || provider;
|
|
@@ -291,6 +293,7 @@ function traceAgentUsage({
|
|
|
291
293
|
service_tier: resolvedServiceTier,
|
|
292
294
|
raw_usage: rawUsage || null,
|
|
293
295
|
...chainFields,
|
|
296
|
+
...(prefixBlocks ? { prefix_blocks: prefixBlocks } : {}),
|
|
294
297
|
},
|
|
295
298
|
});
|
|
296
299
|
}
|
|
@@ -51,6 +51,8 @@ export function buildCacheBreakPayload(record = {}) {
|
|
|
51
51
|
input_prefix_mismatch_expected_hash: cleanHash(record.inputPrefixMismatchExpectedHash),
|
|
52
52
|
input_prefix_mismatch_actual_type: cleanText(record.inputPrefixMismatchActualType),
|
|
53
53
|
input_prefix_mismatch_actual_hash: cleanHash(record.inputPrefixMismatchActualHash),
|
|
54
|
+
changed_blocks: cleanText(record.changedBlocks),
|
|
55
|
+
system_markers_changed: typeof record.markersChanged === 'boolean' ? record.markersChanged : null,
|
|
54
56
|
};
|
|
55
57
|
return Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== null));
|
|
56
58
|
}
|
|
@@ -77,6 +79,8 @@ function formatCacheBreakLine(record = {}) {
|
|
|
77
79
|
['previousCachedPrefixTokens', payload.previous_cached_prefix_tokens],
|
|
78
80
|
['idleMs', payload.idle_ms],
|
|
79
81
|
['noGuardBaseline', payload.missing_prefix_guard_baseline],
|
|
82
|
+
['changedBlocks', payload.changed_blocks],
|
|
83
|
+
['systemMarkersChanged', payload.system_markers_changed],
|
|
80
84
|
].filter(([, value]) => value !== null && value !== undefined);
|
|
81
85
|
return `[cache-break] ${fields.map(([key, value]) => (typeof value === 'string' ? `${key}=${JSON.stringify(value)}` : `${key}=${value}`)).join(' ')}`;
|
|
82
86
|
}
|
|
@@ -144,6 +144,8 @@ export function normalizePreset(preset) {
|
|
|
144
144
|
// Auto effort is on unless the preset opts out; only the off state is kept.
|
|
145
145
|
if (preset.autoEffort === false) out.autoEffort = false;
|
|
146
146
|
out.tools = ['full', 'readonly', 'mcp'].includes(preset.tools) ? preset.tools : 'full';
|
|
147
|
+
// The Lead preset's fallback models (validated when written, by the route normalizer).
|
|
148
|
+
if (Array.isArray(preset.fallbacks) && preset.fallbacks.length) out.fallbacks = preset.fallbacks;
|
|
147
149
|
return out;
|
|
148
150
|
}
|
|
149
151
|
|
|
@@ -127,9 +127,16 @@ function canonicalizeAutoClearStorage(value) {
|
|
|
127
127
|
const provider = String(key || '')
|
|
128
128
|
.trim()
|
|
129
129
|
.toLowerCase();
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
130
|
+
// 0 (also 'unlimited' / 'never') is the stored "never auto-clear" value
|
|
131
|
+
// (runtime-core/config-helpers.mjs AUTO_CLEAR_UNLIMITED).
|
|
132
|
+
const text = typeof candidate === 'string' ? candidate.trim().toLowerCase() : null;
|
|
133
|
+
let duration;
|
|
134
|
+
if (text === 'unlimited' || text === 'never') duration = 0;
|
|
135
|
+
else if (text === '') duration = Number.NaN;
|
|
136
|
+
else duration = Number(candidate);
|
|
137
|
+
if (!provider || candidate === null || typeof candidate === 'boolean' || !Number.isFinite(duration) || duration < 0)
|
|
138
|
+
continue;
|
|
139
|
+
providerIdleMs[provider] = duration === 0 ? 0 : Math.max(60_000, Math.round(duration));
|
|
133
140
|
}
|
|
134
141
|
delete next.thresholdMs;
|
|
135
142
|
delete next.idleMillis;
|
|
@@ -4,6 +4,7 @@ import { mergeStoredProviders } from './config-providers-merge.mjs';
|
|
|
4
4
|
import { normalizeExtensionScopes } from '../../shared/extension-scopes.mjs';
|
|
5
5
|
import { applyConfigPatch, diffConfig } from '../../shared/config-patch.mjs';
|
|
6
6
|
import { normalizeWorkflowSelection } from '../../shared/orchestration.mjs';
|
|
7
|
+
import { AUTO_EFFORT_BASE, autoEffortBase } from './providers/auto-effort.mjs';
|
|
7
8
|
import { DEFAULT_INSTRUCTION_FILES_MODE, normalizeInstructionFilesMode } from '../../shared/instruction-files-mode.mjs';
|
|
8
9
|
import {
|
|
9
10
|
DEFAULT_DISABLED_AGENT_ROSTER,
|
|
@@ -205,6 +206,13 @@ function storedInstructionFiles(agent) {
|
|
|
205
206
|
return mode === DEFAULT_INSTRUCTION_FILES_MODE ? {} : { instructionFiles: mode };
|
|
206
207
|
}
|
|
207
208
|
|
|
209
|
+
// `autoEffortBase` (providers/auto-effort.mjs): only a valid non-default level
|
|
210
|
+
// is kept; absent means medium.
|
|
211
|
+
function storedAutoEffortBase(agent) {
|
|
212
|
+
const base = autoEffortBase(agent?.autoEffortBase);
|
|
213
|
+
return base === AUTO_EFFORT_BASE ? {} : { autoEffortBase: base };
|
|
214
|
+
}
|
|
215
|
+
|
|
208
216
|
export function loadConfig(options = {}) {
|
|
209
217
|
const includeSecrets = options.secrets !== false;
|
|
210
218
|
// `secrets: 'presence'`: credentials are detected (env, OAuth files, which
|
|
@@ -269,6 +277,7 @@ export function loadConfig(options = {}) {
|
|
|
269
277
|
disabledAgents: legacyDisabledAgents ? disabledAgentIds(raw) : effectiveDisabledAgents(raw),
|
|
270
278
|
...(raw.memoryTools && typeof raw.memoryTools === 'object' ? { memoryTools: { ...raw.memoryTools } } : {}),
|
|
271
279
|
...storedInstructionFiles(raw),
|
|
280
|
+
...storedAutoEffortBase(raw),
|
|
272
281
|
...normalizeWorkflowSelection(raw),
|
|
273
282
|
profile: normalizeProfileConfig(raw.profile),
|
|
274
283
|
skills: normalizeSkillsConfig(raw.skills),
|
|
@@ -463,6 +472,8 @@ function buildAgentSaveBuilder(config) {
|
|
|
463
472
|
else delete next.aiSessionTitles;
|
|
464
473
|
delete next.instructionFiles;
|
|
465
474
|
Object.assign(next, storedInstructionFiles(config));
|
|
475
|
+
delete next.autoEffortBase;
|
|
476
|
+
Object.assign(next, storedAutoEffortBase(config));
|
|
466
477
|
delete next.workflowRoutes;
|
|
467
478
|
// Defaults live in code: values equal to the current default are not stored.
|
|
468
479
|
return storedAgentForm(removeRetiredAgentFields(next));
|
|
@@ -375,6 +375,14 @@ function agentManifest(agent) {
|
|
|
375
375
|
return {};
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
/** The name a bot goes by (its manifest name, Mixy's display name), else its id. */
|
|
379
|
+
export function agentDisplayName(agent) {
|
|
380
|
+
if (agent === 'lead') return mixyDisplayName();
|
|
381
|
+
if (typeof agent !== 'string' || !PERSONA_AGENT_ID.test(agent) || agent.includes('..')) return String(agent || '');
|
|
382
|
+
const name = agentManifest(agent).name;
|
|
383
|
+
return (typeof name === 'string' ? name.replace(/\s+/g, ' ').trim() : '') || agent;
|
|
384
|
+
}
|
|
385
|
+
|
|
378
386
|
export function agentModeIdentityLine(agent) {
|
|
379
387
|
if (agent === 'lead') return `You are ${mixyDisplayName()}, the user's assistant in Mixdog.`;
|
|
380
388
|
if (typeof agent !== 'string' || !PERSONA_AGENT_ID.test(agent) || agent.includes('..')) return '';
|
|
@@ -489,7 +497,7 @@ export function composeSystemPrompt(opts) {
|
|
|
489
497
|
// variants, AGENT_MODE.md, the sub-agent catalog (the same for every
|
|
490
498
|
// agent other than Mixy);
|
|
491
499
|
// 3. Mixy only — MIXY.md and its contact-agent catalog;
|
|
492
|
-
// 4. per session or agent, last —
|
|
500
|
+
// 4. per session or agent, last — identity, caller prompt,
|
|
493
501
|
// role, persona, instruction files and core memory (changes most).
|
|
494
502
|
const sessionMarkerCore = joinPromptSlices([
|
|
495
503
|
trimmedPromptSlice(opts.workflowContext),
|
|
@@ -500,7 +508,6 @@ export function composeSystemPrompt(opts) {
|
|
|
500
508
|
trimmedPromptSlice(opts.agentCatalogContext),
|
|
501
509
|
opts.mixyRules || '',
|
|
502
510
|
trimmedPromptSlice(opts.contactCatalogContext),
|
|
503
|
-
opts.routineRules || '',
|
|
504
511
|
opts.identityContext || '',
|
|
505
512
|
opts.userPrompt || '',
|
|
506
513
|
roleInstructionContext,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// or a project may use. Every installed connector is on by default for every
|
|
3
3
|
// agent and project, existing and future ones; a policy only switches some off:
|
|
4
4
|
// agents/<id>/agent.json connectors: { off: [serverId…], tools?: { [serverId]: { [tool]: permission } } }
|
|
5
|
+
// (bots/<id>/ for a store bot; Mixy — runtime id `lead` — in her identity folder)
|
|
5
6
|
// <data>/project-connectors.json { projects: { [projectRoot]: { off: [serverId…] } } }
|
|
6
7
|
// `tools` keeps per-tool overrides (auto | needs_approval | disabled); a tool
|
|
7
8
|
// without one is auto, except a catalog connector's high-risk tools, which
|
|
@@ -12,11 +13,16 @@
|
|
|
12
13
|
// connected tool, so the schema and the BP2 manifest stay shared.
|
|
13
14
|
import { readFileSync, statSync } from 'node:fs';
|
|
14
15
|
import { join } from 'node:path';
|
|
16
|
+
import { holdsNoData, parseJsonText, readJsonStateSync } from '../../../shared/atomic-file.mjs';
|
|
17
|
+
|
|
18
|
+
const NO_DATA = new Error('the file holds no data');
|
|
15
19
|
import { cwdWithinProjects } from '../../../shared/extension-scopes.mjs';
|
|
16
20
|
import { resolvePluginData } from '../../../shared/plugin-paths.mjs';
|
|
17
|
-
import { userDefinitionDir } from '../../../shared/agent-store.mjs';
|
|
21
|
+
import { mixyIdentityDir, userDefinitionDir } from '../../../shared/agent-store.mjs';
|
|
18
22
|
import { isSelfMcpToolName, parseMcpToolName } from '../../../shared/tool-primitives.mjs';
|
|
19
23
|
import { connectorToolDefault } from '../../../shared/connector-catalog.mjs';
|
|
24
|
+
import { MIXY_AGENT_ID } from '../session/agent-home.mjs';
|
|
25
|
+
import { AGENT_MODE, sessionModeOf } from '../session/agent-mode.mjs';
|
|
20
26
|
import { serverConnector } from './server-connectors.mjs';
|
|
21
27
|
|
|
22
28
|
export const CONNECTOR_PERMISSIONS = Object.freeze(['auto', 'needs_approval', 'disabled']);
|
|
@@ -127,9 +133,25 @@ function readJson(path, parse) {
|
|
|
127
133
|
return error?.code === 'ENOENT' || error?.code === 'ENOTDIR' ? null : unreadable(path, error);
|
|
128
134
|
}
|
|
129
135
|
try {
|
|
130
|
-
|
|
136
|
+
if (holdsNoData(text)) throw NO_DATA;
|
|
137
|
+
return parse(parseJsonText(text));
|
|
131
138
|
} catch (error) {
|
|
132
|
-
return
|
|
139
|
+
return recoverDamaged(path, parse, error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// A damaged policy (empty, NUL-filled, torn, invalid) must never fail open.
|
|
144
|
+
// With a valid last good copy `<file>.bak` the damaged file is kept aside and
|
|
145
|
+
// the copy restored, so the user's deny list survives. Without one the file
|
|
146
|
+
// stays where it is (`keepWithoutBackup`) and every connector stays off until
|
|
147
|
+
// the policy is saved again — moving it aside would make the next read "no
|
|
148
|
+
// policy" (all on). A busy recovery lock also answers deny-all.
|
|
149
|
+
function recoverDamaged(path, parse, error) {
|
|
150
|
+
try {
|
|
151
|
+
const value = readJsonStateSync(path, { validate: parse, fallback: DENY_ALL_CONNECTORS, keepWithoutBackup: true });
|
|
152
|
+
return value === DENY_ALL_CONNECTORS ? unreadable(path, error) : value;
|
|
153
|
+
} catch (recoveryError) {
|
|
154
|
+
return unreadable(path, recoveryError);
|
|
133
155
|
}
|
|
134
156
|
}
|
|
135
157
|
|
|
@@ -146,11 +168,22 @@ export function readConnectorsFile(path) {
|
|
|
146
168
|
return readJson(path, (manifest) => parseConnectorPolicy(manifest?.connectors));
|
|
147
169
|
}
|
|
148
170
|
|
|
149
|
-
/** The agent's saved policy under `dataDir`, or null when it has none.
|
|
171
|
+
/** The agent's saved policy under `dataDir`, or null when it has none. Mixy's
|
|
172
|
+
* runtime id is `lead`: her policy is in her identity folder (bots/mixy once
|
|
173
|
+
* the bot store is active, agents/lead before), the file her profile writes. */
|
|
150
174
|
export function agentConnectors(agentId, dataDir = resolvePluginData()) {
|
|
151
175
|
const id = clean(agentId);
|
|
152
176
|
if (!id || !AGENT_DIR_ID.test(id)) return null;
|
|
153
|
-
|
|
177
|
+
const dir = id === MIXY_AGENT_ID ? mixyIdentityDir(dataDir) : userDefinitionDir(dataDir, id);
|
|
178
|
+
return cachedRead(join(dir, 'agent.json'), readConnectorsFile);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** The agent whose connector policy `session` runs under. A coding Lead shares
|
|
182
|
+
* Mixy's runtime id `lead` but is not her: the policy her profile edits is
|
|
183
|
+
* hers alone, so a coding Lead has none ('') and only its Project's applies. */
|
|
184
|
+
export function connectorPolicyAgentOf(session) {
|
|
185
|
+
const agent = clean(session?.agent);
|
|
186
|
+
return agent === MIXY_AGENT_ID && sessionModeOf(session) !== AGENT_MODE ? '' : agent;
|
|
154
187
|
}
|
|
155
188
|
|
|
156
189
|
/** Uncached: the project policy file → `[{ root, off }]`, null without one,
|
|
@@ -186,6 +219,65 @@ export function connectorToolPermission(policy, toolOrName) {
|
|
|
186
219
|
return policy?.tools?.[mcp.server]?.[mcp.tool] || connectorToolDefault(serverConnector(mcp.server), mcp.tool);
|
|
187
220
|
}
|
|
188
221
|
|
|
222
|
+
const PERMISSION_RANK = Object.freeze({ disabled: 0, needs_approval: 1, auto: 2 });
|
|
223
|
+
export const NO_WIDEN_MESSAGE = 'This change would widen what the bot may do without asking; make it on the desktop.';
|
|
224
|
+
|
|
225
|
+
/** Whether replacing the stored policy `before` (a stored value, a parsed
|
|
226
|
+
* policy or null) with `after` (`{ off, tools }` or null) could give any
|
|
227
|
+
* tool more authority, judged on EFFECTIVE permissions: a connector switched
|
|
228
|
+
* back on, a tool allowed, or an override removed (the tool then runs on its
|
|
229
|
+
* default, which is `needs_approval` for a catalog connector's high-risk
|
|
230
|
+
* tools and `auto` otherwise). A legacy allow list or an unreadable policy is
|
|
231
|
+
* not compared: it counts as widening. */
|
|
232
|
+
export function connectorPolicyWidens(before, after) {
|
|
233
|
+
let old;
|
|
234
|
+
try {
|
|
235
|
+
old = before == null ? { off: [], tools: {} } : parseConnectorPolicy(before);
|
|
236
|
+
} catch {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
if (old.allow) return true;
|
|
240
|
+
const next = after == null ? { off: [], tools: {} } : after;
|
|
241
|
+
const offBefore = new Set(old.off);
|
|
242
|
+
const offAfter = new Set(next.off || []);
|
|
243
|
+
for (const server of offBefore) if (!offAfter.has(server)) return true;
|
|
244
|
+
const toolsBefore = old.tools || {};
|
|
245
|
+
const toolsAfter = next.tools || {};
|
|
246
|
+
for (const server of new Set([...Object.keys(toolsBefore), ...Object.keys(toolsAfter)])) {
|
|
247
|
+
const tools = new Set([...Object.keys(toolsBefore[server] || {}), ...Object.keys(toolsAfter[server] || {})]);
|
|
248
|
+
for (const tool of tools) {
|
|
249
|
+
// No override: at least asks / at most runs freely.
|
|
250
|
+
const was = offBefore.has(server) ? 0 : (PERMISSION_RANK[toolsBefore[server]?.[tool]] ?? 1);
|
|
251
|
+
const now = offAfter.has(server) ? 0 : (PERMISSION_RANK[toolsAfter[server]?.[tool]] ?? 2);
|
|
252
|
+
if (now > was) return true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** Throws NO_WIDEN_MESSAGE when `after` could widen `before` (see connectorPolicyWidens). */
|
|
259
|
+
export function assertConnectorPolicyNotWidened(before, after) {
|
|
260
|
+
if (connectorPolicyWidens(before, after)) throw new Error(NO_WIDEN_MESSAGE);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
let toolPermissionWriter = null;
|
|
264
|
+
/** The host attaches the one writer of an agent's per-tool permission (the
|
|
265
|
+
* agent editor keeps every other agent.json key). */
|
|
266
|
+
export function setConnectorToolPermissionWriter(write) {
|
|
267
|
+
toolPermissionWriter = typeof write === 'function' ? write : null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** Save `permission` for the connector tool `toolOrName` under `agentId`'s own
|
|
271
|
+
* policy. False when it is no connector tool or no writer is attached. */
|
|
272
|
+
export async function writeAgentMcpToolPermission(agentId, toolOrName, permission) {
|
|
273
|
+
const mcp = parseMcpToolName(toolOrName);
|
|
274
|
+
if (!toolPermissionWriter || !mcp || isSelfMcpToolName(toolOrName) || !CONNECTOR_PERMISSIONS.includes(permission)) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
await toolPermissionWriter(agentId, mcp.server, mcp.tool, permission);
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
|
|
189
281
|
/** The permission `agentId` has for the MCP tool `toolOrName`. */
|
|
190
282
|
export function agentMcpToolPermission(agentId, toolOrName) {
|
|
191
283
|
if (!parseMcpToolName(toolOrName)) return 'auto';
|
|
@@ -117,14 +117,11 @@ async function enumerate({ strict = false } = {}) {
|
|
|
117
117
|
* names and (POSIX) process groups. Rejects instead of returning a partial
|
|
118
118
|
* table, so callers can tell "nothing found" from "could not look".
|
|
119
119
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* confirmation by a whole re-check. Such a caller starts a read when none
|
|
126
|
-
* runs, else joins the one queued to begin when the running read settles —
|
|
127
|
-
* every observer asking meanwhile shares it. At most one enumerator runs at
|
|
120
|
+
* Every caller sees a table from a read begun after it asked: an earlier
|
|
121
|
+
* read may miss newly spawned descendants before a kill, or report a killed
|
|
122
|
+
* tree alive afterwards. A caller starts a read when none runs, else joins
|
|
123
|
+
* the one queued to begin when the running read settles — every caller
|
|
124
|
+
* asking meanwhile shares it. At most one enumerator runs at
|
|
128
125
|
* a time, however many shells settle or watch at once (each one is a
|
|
129
126
|
* PowerShell process on Windows; one per settle and watch pass compounded
|
|
130
127
|
* machine load into multi-second daemon stalls). */
|
|
@@ -137,8 +134,7 @@ function startTableRead() {
|
|
|
137
134
|
tableInFlight = read;
|
|
138
135
|
return read;
|
|
139
136
|
}
|
|
140
|
-
export function readProcessTable(
|
|
141
|
-
if (shared && tableInFlight) return tableInFlight;
|
|
137
|
+
export function readProcessTable() {
|
|
142
138
|
if (nextTable) return nextTable;
|
|
143
139
|
if (!tableInFlight) return startTableRead();
|
|
144
140
|
const settled = () => {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { setMaxListeners } from 'node:events';
|
|
2
|
-
import { mkdirSync
|
|
2
|
+
import { mkdirSync } from 'node:fs';
|
|
3
|
+
import { writeFileAtomicSync } from '../../../shared/atomic-file.mjs';
|
|
3
4
|
import { writeFile } from 'node:fs/promises';
|
|
4
5
|
import {
|
|
5
6
|
MAX_ATTACHMENT_BLOB_BYTES,
|
|
@@ -772,9 +773,11 @@ function spillMcpBinary(buffer, extension) {
|
|
|
772
773
|
const path = join(dir, `mcp-${hash}.${extension}`);
|
|
773
774
|
try {
|
|
774
775
|
mkdirSync(dir, { recursive: true });
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
776
|
+
// Named by its content hash: whole-file create-if-absent (a crash never
|
|
777
|
+
// leaves a torn file under the name that would be trusted as the content).
|
|
778
|
+
writeFileAtomicSync(path, buffer, { createOnly: true });
|
|
779
|
+
} catch {
|
|
780
|
+
return null;
|
|
778
781
|
}
|
|
779
782
|
return path;
|
|
780
783
|
}
|