mixdog 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/package.json +2 -2
- package/scripts/native-release-status.mjs +238 -0
- package/src/defaults/shipped-history.json +5 -1
- package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
- package/src/defaults/skills/setup/SKILL.md +23 -1
- package/src/defaults/skills/setup/references/actions.md +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 +2 -2
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/20-research.md +2 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
- package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
- package/src/runtime/agent/orchestrator/config.mjs +11 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +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 +80 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +67 -38
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +27 -8
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +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 +9 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
- package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +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 +12 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -5
- 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 +2 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +17 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +133 -38
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +14 -11
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +68 -18
- package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
- package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +136 -32
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +21 -9
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +189 -105
- package/src/runtime/agent/orchestrator/session/loop/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 +3 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +38 -5
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +99 -0
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +3 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-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 +42 -10
- 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 +120 -9
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +8 -3
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +36 -1
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +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 +35 -13
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +6 -14
- package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +34 -21
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
- package/src/runtime/attachments/attachment-reference.mjs +155 -0
- package/src/runtime/attachments/limits.mjs +5 -1
- package/src/runtime/attachments/office-extract.mjs +3 -6
- package/src/runtime/attachments/pdf-extract.mjs +84 -10
- package/src/runtime/attachments/store.mjs +49 -30
- package/src/runtime/browser-bridge/client.mjs +73 -20
- package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
- package/src/runtime/channels/lib/scheduler.mjs +14 -7
- package/src/runtime/channels/lib/state-file.mjs +15 -15
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
- package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
- package/src/runtime/channels/lib/worker-main.mjs +3 -2
- package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
- package/src/runtime/effort-judge/judge-client.mjs +5 -2
- package/src/runtime/effort-judge/model-install.mjs +16 -8
- package/src/runtime/local-provider/asset-installer.mjs +10 -4
- package/src/runtime/local-provider/catalog.mjs +5 -2
- package/src/runtime/local-provider/registered-models.mjs +64 -27
- package/src/runtime/local-provider/server.mjs +2 -3
- package/src/runtime/media/adapters/image-api.mjs +89 -0
- package/src/runtime/media/auth.mjs +64 -1
- package/src/runtime/media/catalog.mjs +66 -4
- package/src/runtime/media/jobs.mjs +4 -0
- package/src/runtime/media/lanes.mjs +46 -5
- package/src/runtime/media/media-usage.mjs +17 -0
- package/src/runtime/media/renditions.mjs +15 -15
- package/src/runtime/media/store.mjs +36 -35
- package/src/runtime/media/tool.mjs +8 -1
- package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
- package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
- package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
- package/src/runtime/memory/lib/pg/process.mjs +8 -4
- package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
- package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
- package/src/runtime/office/core/journal.mjs +7 -14
- package/src/runtime/office/design/library/design-library-core.mjs +4 -16
- package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
- package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
- package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
- package/src/runtime/office/pdf/pdf-render.mjs +30 -18
- package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +4 -0
- package/src/runtime/shared/agent-kind-migration.mjs +200 -0
- package/src/runtime/shared/agent-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-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 +30 -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/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/singleton-owner.mjs +7 -6
- package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
- package/src/runtime/shared/staged-update.mjs +4 -2
- package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
- package/src/runtime/shared/tool-execution-contract.mjs +6 -0
- package/src/runtime/shared/transcript-metadata.mjs +28 -3
- package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
- package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
- package/src/runtime/shared/turn-snapshot.mjs +44 -2
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +41 -42
- package/src/runtime/shared/utf8-cut.mjs +10 -0
- package/src/runtime/shared/worktrees/activity-gate.mjs +269 -61
- package/src/runtime/shared/worktrees/registry.mjs +26 -26
- package/src/runtime/tidy/core-install.mjs +26 -4
- package/src/runtime/tidy/install.mjs +91 -23
- package/src/runtime/web-search/lib/config.mjs +4 -16
- package/src/session-runtime/agent-home-delivery.mjs +555 -199
- package/src/session-runtime/agent-room-delivery.mjs +143 -36
- package/src/session-runtime/agent-task-sessions.mjs +667 -165
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +45 -24
- package/src/session-runtime/boot/config.mjs +1 -0
- package/src/session-runtime/boot/facade.mjs +11 -1
- package/src/session-runtime/boot/infrastructure.mjs +14 -2
- package/src/session-runtime/boot/providers.mjs +2 -2
- package/src/session-runtime/boot/shared.mjs +12 -6
- package/src/session-runtime/boot/tools.mjs +2 -2
- package/src/session-runtime/bot-status.mjs +432 -0
- package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
- package/src/session-runtime/config-lifecycle.mjs +60 -55
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/held-requests.mjs +36 -33
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +19 -4
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown.mjs +11 -3
- package/src/session-runtime/mcp-glue/connect.mjs +100 -186
- package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
- package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
- package/src/session-runtime/media-api.mjs +5 -2
- package/src/session-runtime/model-route/route-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/room-member-gate.mjs +16 -3
- 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-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/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 +4 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +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 +14 -4
- package/src/session-runtime/services/schedule-access.mjs +33 -4
- package/src/session-runtime/services/seeds.mjs +4 -3
- package/src/session-runtime/services/usage-dashboard.mjs +1 -1
- package/src/session-runtime/services/usage-stats-model.mjs +2 -1
- package/src/session-runtime/session-create/materialize.mjs +2 -3
- package/src/session-runtime/session-create/session-options.mjs +15 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +63 -1
- package/src/session-runtime/settings-compaction-api.mjs +86 -39
- package/src/session-runtime/setup-tool/executor.mjs +8 -2
- package/src/session-runtime/setup-tool/settings-contract.mjs +31 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
- package/src/session-runtime/skills-api.mjs +12 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +265 -0
- package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
- package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
- package/src/session-runtime/tool-policy/policy-stage.mjs +165 -0
- package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
- package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
- package/src/session-runtime/tool-policy-refresh.mjs +47 -369
- package/src/session-runtime/tool-surface.mjs +5 -3
- 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 +2 -1
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +519 -333
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +46 -46
- package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
- package/src/session-runtime/workspace/workspace-state.mjs +7 -6
- package/src/standalone/daemon-agent-control.mjs +4 -1
- package/src/standalone/daemon-session-control.mjs +51 -10
- package/src/standalone/daemon.mjs +28 -10
- package/src/standalone/local-session-runtime.mjs +22 -14
- package/src/standalone/session-client.mjs +7 -2
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-service.mjs +11 -0
- package/src/standalone/session-state-projection.mjs +19 -9
- package/src/standalone/session-tool-output.mjs +35 -9
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
- package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
- package/src/tui/dist/index.mjs +529 -333
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/session-api/intake/abort.mjs +19 -1
- package/src/tui/session/session-api/media.mjs +2 -1
- package/src/tui/session/session-api/routes-agent-definitions.mjs +75 -0
- package/src/tui/session/session-api/routes-write.mjs +203 -0
- package/src/tui/session/session-api/routes.mjs +23 -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 +185 -20
- 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
|
@@ -5,26 +5,65 @@
|
|
|
5
5
|
* active one into store state (state.toolApproval). They need live session
|
|
6
6
|
* state, so the closure identifiers (state/set/nextId/disposed/timeout) are
|
|
7
7
|
* threaded through the factory argument via getters — never stale snapshots.
|
|
8
|
+
*
|
|
9
|
+
* Delegation (`surfaceOf`, human-gate/gate.mjs approvalSurface): a sub-agent's
|
|
10
|
+
* approval is also offered to the top-level conversation the user watches
|
|
11
|
+
* (runtime/shared/delegated-approval-host.mjs), labelled with the agent chain.
|
|
12
|
+
* That session's queue holds a copy (`mirror`): it never times out, survives
|
|
13
|
+
* that session's own turn ending, and its answer is forwarded to the owning
|
|
14
|
+
* queue, so either place settles the one request once.
|
|
8
15
|
*/
|
|
9
16
|
import {
|
|
10
17
|
humanRequestFields,
|
|
11
18
|
normalizeHumanResponse,
|
|
12
19
|
} from '../../runtime/agent/orchestrator/session/human-gate/requests.mjs';
|
|
20
|
+
import {
|
|
21
|
+
delegateApproval,
|
|
22
|
+
delegatedApprovalsFor,
|
|
23
|
+
registerApprovalQueue,
|
|
24
|
+
withdrawDelegatedApproval,
|
|
25
|
+
} from '../../runtime/shared/delegated-approval-host.mjs';
|
|
26
|
+
|
|
27
|
+
/** Approvals a sub-agent shows in the top-level chat too; a question, a secret
|
|
28
|
+
* or a takeover stays in its own session (its answer or window is there). */
|
|
29
|
+
const DELEGATED_KINDS = new Set(['', 'approval', 'outbound', 'permission']);
|
|
13
30
|
|
|
14
|
-
|
|
31
|
+
/** The wait limit an approval has when its request names none, from
|
|
32
|
+
* MIXDOG_TOOL_APPROVAL_TIMEOUT_MS (milliseconds, one second at least): null —
|
|
33
|
+
* no limit — unless the variable sets one, which tests and ops use. An
|
|
34
|
+
* approval waits until the user answers, Stop/turn abort denies it, or its
|
|
35
|
+
* runtime closes. */
|
|
36
|
+
export function resolveToolApprovalTimeoutMs(env = process.env) {
|
|
37
|
+
const value = Number(env.MIXDOG_TOOL_APPROVAL_TIMEOUT_MS);
|
|
38
|
+
return Number.isFinite(value) && value > 0 ? Math.max(1000, Math.round(value)) : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function createToolApproval({ getState, set, nextId, getDisposed, timeoutMs = null, surfaceOf = null }) {
|
|
42
|
+
const defaultTimeoutMs = Number.isFinite(Number(timeoutMs)) && Number(timeoutMs) > 0 ? Number(timeoutMs) : null;
|
|
15
43
|
const toolApprovalQueue = [];
|
|
16
44
|
let activeToolApproval = null;
|
|
45
|
+
const ownSessionId = () => String(getState()?.sessionId || '');
|
|
46
|
+
const unregister =
|
|
47
|
+
typeof surfaceOf === 'function'
|
|
48
|
+
? registerApprovalQueue({
|
|
49
|
+
sessionId: ownSessionId,
|
|
50
|
+
disposed: () => getDisposed(),
|
|
51
|
+
offer: offerDelegatedApproval,
|
|
52
|
+
withdraw: withdrawDelegatedCopy,
|
|
53
|
+
})
|
|
54
|
+
: () => {};
|
|
17
55
|
|
|
18
56
|
function normalizeToolApprovalRequest(input = {}, id = nextId()) {
|
|
19
57
|
const now = Date.now();
|
|
20
58
|
// An explicit `timeoutMs: null` means no wait limit (no timer, no expiry);
|
|
21
|
-
// any other missing/invalid value falls back to the session default
|
|
59
|
+
// any other missing/invalid value falls back to the session default,
|
|
60
|
+
// which is itself no limit unless the runtime configures one.
|
|
22
61
|
const requestTimeoutMs =
|
|
23
62
|
input?.timeoutMs === null
|
|
24
63
|
? null
|
|
25
64
|
: Number.isFinite(Number(input?.timeoutMs)) && Number(input.timeoutMs) > 0
|
|
26
65
|
? Number(input.timeoutMs)
|
|
27
|
-
:
|
|
66
|
+
: defaultTimeoutMs;
|
|
28
67
|
return {
|
|
29
68
|
id,
|
|
30
69
|
name: String(input?.name || input?.tool_name || 'tool'),
|
|
@@ -41,12 +80,14 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
41
80
|
...humanRequestFields(input),
|
|
42
81
|
};
|
|
43
82
|
}
|
|
44
|
-
//
|
|
45
|
-
// the timer only on presentation let a queued request sit past
|
|
46
|
-
// (retaining its promise and surfacing an obsolete approval later).
|
|
83
|
+
// A request that has a limit expires from ITS OWN requestedAt, queued or
|
|
84
|
+
// active. Arming the timer only on presentation let a queued request sit past
|
|
85
|
+
// expiresAt (retaining its promise and surfacing an obsolete approval later).
|
|
86
|
+
// One without a limit (expiresAt null — the default) arms nothing.
|
|
47
87
|
function armToolApprovalTimeout(entry) {
|
|
48
|
-
|
|
49
|
-
|
|
88
|
+
// A copy expires with its owner, which withdraws it.
|
|
89
|
+
if (!entry || entry.mirror || entry.timer || !Number.isFinite(entry.request?.expiresAt)) return;
|
|
90
|
+
const remainingMs = Math.max(0, entry.request.expiresAt - Date.now());
|
|
50
91
|
entry.timer = setTimeout(() => {
|
|
51
92
|
finishToolApproval(entry.id, false, 'approval timed out', '', undefined, undefined, { timedOut: true });
|
|
52
93
|
}, remainingMs);
|
|
@@ -55,21 +96,75 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
55
96
|
// Settle one entry: drop its timeout, then hand the waiter its answer. The
|
|
56
97
|
// resolve stays guarded — a waiter whose caller already went away must never
|
|
57
98
|
// take the rest of the queue down with it.
|
|
58
|
-
function settleToolApproval(entry, approved, reason, answers, reply, extra, device = '') {
|
|
99
|
+
function settleToolApproval(entry, approved, reason, answers, reply, extra, device = '', forwarded = false) {
|
|
59
100
|
if (entry?.timer) clearTimeout(entry.timer);
|
|
60
101
|
const result = { approved, reason };
|
|
61
102
|
if (answers !== undefined) result.answers = answers;
|
|
62
103
|
if (reply !== undefined) result.reply = reply;
|
|
63
|
-
// A human-kind request answers with its canonical response (never a value)
|
|
64
|
-
|
|
65
|
-
|
|
104
|
+
// A human-kind request answers with its canonical response (never a value),
|
|
105
|
+
// judged against what the answering place offered: this queue's own view,
|
|
106
|
+
// or — answered on its copy — the full request the copy already narrowed.
|
|
107
|
+
const answered = forwarded ? entry?.full || entry?.request : entry?.request;
|
|
108
|
+
if (answered?.remember) {
|
|
109
|
+
Object.assign(result, normalizeHumanResponse(answered, approved, extra));
|
|
66
110
|
if (device) result.device = device;
|
|
67
111
|
}
|
|
68
112
|
if (extra?.timedOut === true) result.timedOut = true;
|
|
113
|
+
// Settled here: its copy in the top-level chat goes away.
|
|
114
|
+
if (entry?.delegated) withdrawDelegatedApproval(entry.id, { approved, device });
|
|
69
115
|
try {
|
|
70
116
|
entry.resolve(result);
|
|
71
117
|
} catch {}
|
|
72
118
|
}
|
|
119
|
+
/** Hand a copy's answer to the queue that owns the request; false when the
|
|
120
|
+
* owner had already settled it. */
|
|
121
|
+
function forwardToOwner(entry, approved, reason, device, answers, reply, extra) {
|
|
122
|
+
try {
|
|
123
|
+
return entry.mirror.answer(approved, reason, device, answers, reply, onlyOffered(entry.request, extra)) === true;
|
|
124
|
+
} catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/** `request` as this session shows it: a remembering scope is offered only
|
|
129
|
+
* in the one session the request names for it (`rememberAt`, the bot's own
|
|
130
|
+
* chat); everywhere else — and when it names none — it asks once. */
|
|
131
|
+
function viewFor(request) {
|
|
132
|
+
if (!Array.isArray(request?.remember) || request.remember.length <= 1) return request;
|
|
133
|
+
const here = ownSessionId();
|
|
134
|
+
return here && request.rememberAt === here ? request : { ...request, remember: ['once'] };
|
|
135
|
+
}
|
|
136
|
+
/** `extra` without a remember scope `view` did not offer. */
|
|
137
|
+
function onlyOffered(view, extra) {
|
|
138
|
+
if (!extra || extra.remember === undefined) return extra;
|
|
139
|
+
return (view?.remember || ['once']).includes(extra.remember) ? extra : { ...extra, remember: 'once' };
|
|
140
|
+
}
|
|
141
|
+
function offerDelegatedApproval(delegated) {
|
|
142
|
+
if (getDisposed() || delegated.sessionId !== ownSessionId()) return;
|
|
143
|
+
if (activeToolApproval?.id === delegated.id || toolApprovalQueue.some((entry) => entry.id === delegated.id)) return;
|
|
144
|
+
toolApprovalQueue.push({ id: delegated.id, request: viewFor(delegated.request), mirror: delegated, timer: null });
|
|
145
|
+
presentNextToolApproval();
|
|
146
|
+
}
|
|
147
|
+
function withdrawDelegatedCopy(id, result) {
|
|
148
|
+
if (activeToolApproval?.mirror && activeToolApproval.id === id) {
|
|
149
|
+
activeToolApproval = null;
|
|
150
|
+
const device = String(result?.device || '');
|
|
151
|
+
set({
|
|
152
|
+
toolApproval: null,
|
|
153
|
+
toolApprovalResult: device ? { id, approved: result.approved === true, device, at: Date.now() } : null,
|
|
154
|
+
});
|
|
155
|
+
presentNextToolApproval();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const index = toolApprovalQueue.findIndex((entry) => entry.mirror && entry.id === id);
|
|
159
|
+
if (index >= 0) toolApprovalQueue.splice(index, 1);
|
|
160
|
+
}
|
|
161
|
+
/** Show the delegated approvals waiting for this session (it loaded, or its
|
|
162
|
+
* session id became the top-level one after the request was made). */
|
|
163
|
+
function adoptDelegatedApprovals() {
|
|
164
|
+
const sessionId = ownSessionId();
|
|
165
|
+
if (!sessionId || typeof surfaceOf !== 'function') return;
|
|
166
|
+
for (const delegated of delegatedApprovalsFor(sessionId)) offerDelegatedApproval(delegated);
|
|
167
|
+
}
|
|
73
168
|
function presentNextToolApproval() {
|
|
74
169
|
if (activeToolApproval || getDisposed()) return;
|
|
75
170
|
const entry = toolApprovalQueue.shift();
|
|
@@ -88,7 +183,8 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
88
183
|
device = '',
|
|
89
184
|
answers = undefined,
|
|
90
185
|
reply = undefined,
|
|
91
|
-
extra = undefined
|
|
186
|
+
extra = undefined,
|
|
187
|
+
{ forwarded = false } = {}
|
|
92
188
|
) {
|
|
93
189
|
const targetId = String(id || '');
|
|
94
190
|
if (activeToolApproval && activeToolApproval.id === targetId) {
|
|
@@ -100,44 +196,113 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
100
196
|
? { id: targetId, approved: approved === true, device: String(device), at: Date.now() }
|
|
101
197
|
: null;
|
|
102
198
|
set({ toolApproval: null, toolApprovalResult });
|
|
103
|
-
|
|
199
|
+
let accepted = true;
|
|
200
|
+
if (entry.mirror) {
|
|
201
|
+
accepted = forwardToOwner(entry, approved, reason, device, answers, reply, extra);
|
|
202
|
+
} else {
|
|
203
|
+
settleToolApproval(
|
|
204
|
+
entry,
|
|
205
|
+
approved === true,
|
|
206
|
+
String(reason || ''),
|
|
207
|
+
answers,
|
|
208
|
+
reply,
|
|
209
|
+
extra,
|
|
210
|
+
String(device || ''),
|
|
211
|
+
forwarded
|
|
212
|
+
);
|
|
213
|
+
}
|
|
104
214
|
presentNextToolApproval();
|
|
105
|
-
return
|
|
215
|
+
return accepted;
|
|
106
216
|
}
|
|
107
217
|
const index = toolApprovalQueue.findIndex((entry) => entry.id === targetId);
|
|
108
218
|
if (index >= 0) {
|
|
109
219
|
const [entry] = toolApprovalQueue.splice(index, 1);
|
|
110
|
-
|
|
220
|
+
if (entry.mirror) return forwardToOwner(entry, approved, reason, device, answers, reply, extra);
|
|
221
|
+
settleToolApproval(
|
|
222
|
+
entry,
|
|
223
|
+
approved === true,
|
|
224
|
+
String(reason || ''),
|
|
225
|
+
answers,
|
|
226
|
+
reply,
|
|
227
|
+
extra,
|
|
228
|
+
String(device || ''),
|
|
229
|
+
forwarded
|
|
230
|
+
);
|
|
111
231
|
return true;
|
|
112
232
|
}
|
|
113
233
|
return false;
|
|
114
234
|
}
|
|
235
|
+
/** Deny this session's own requests. A copy of a sub-agent's request stays
|
|
236
|
+
* (that agent still waits) until this runtime closes, which drops it
|
|
237
|
+
* unanswered: the next runtime of this session adopts it again. */
|
|
115
238
|
function denyAllToolApprovals(reason = 'approval cancelled') {
|
|
116
|
-
|
|
239
|
+
const closing = getDisposed();
|
|
240
|
+
if (closing) unregister();
|
|
241
|
+
if (activeToolApproval && !(activeToolApproval.mirror && !closing)) {
|
|
117
242
|
const entry = activeToolApproval;
|
|
118
243
|
activeToolApproval = null;
|
|
119
|
-
settleToolApproval(entry, false, reason);
|
|
244
|
+
if (!entry.mirror) settleToolApproval(entry, false, reason);
|
|
120
245
|
}
|
|
246
|
+
const kept = [];
|
|
121
247
|
while (toolApprovalQueue.length > 0) {
|
|
122
|
-
|
|
248
|
+
const entry = toolApprovalQueue.shift();
|
|
249
|
+
if (!entry.mirror) settleToolApproval(entry, false, reason);
|
|
250
|
+
else if (!closing) kept.push(entry);
|
|
123
251
|
}
|
|
252
|
+
toolApprovalQueue.push(...kept);
|
|
253
|
+
if (activeToolApproval) return;
|
|
124
254
|
if (getState().toolApproval) set({ toolApproval: null });
|
|
255
|
+
presentNextToolApproval();
|
|
125
256
|
}
|
|
126
257
|
function requestToolApproval(input = {}) {
|
|
127
258
|
if (getDisposed()) return Promise.resolve({ approved: false, reason: 'runtime disposed' });
|
|
128
259
|
return new Promise((resolve) => {
|
|
129
260
|
const id = nextId();
|
|
130
|
-
const
|
|
261
|
+
const full = normalizeToolApprovalRequest(input, id);
|
|
262
|
+
const surface = delegationSurface(full);
|
|
263
|
+
if (surface) {
|
|
264
|
+
// Who asks, from the top-level chat down ("사무관 › Worker"), and where the copy is.
|
|
265
|
+
full.chain = surface.chain;
|
|
266
|
+
full.surfaceSessionId = surface.sessionId;
|
|
267
|
+
}
|
|
268
|
+
// `request` is what this session shows (and accepts answers against);
|
|
269
|
+
// `full` what the copy in the top-level chat is made from.
|
|
270
|
+
const entry = { id, request: viewFor(full), full, resolve, timer: null, delegated: Boolean(surface) };
|
|
131
271
|
toolApprovalQueue.push(entry);
|
|
132
272
|
armToolApprovalTimeout(entry);
|
|
133
273
|
presentNextToolApproval();
|
|
274
|
+
if (surface) {
|
|
275
|
+
delegateApproval({
|
|
276
|
+
id,
|
|
277
|
+
sessionId: surface.sessionId,
|
|
278
|
+
request: full,
|
|
279
|
+
answer: (approved, reason, device, answers, reply, extra) =>
|
|
280
|
+
finishToolApproval(id, approved, reason, device, answers, reply, extra, { forwarded: true }),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
134
283
|
});
|
|
135
284
|
}
|
|
285
|
+
/** `{ sessionId, chain }` of the top-level chat a sub-agent's request also
|
|
286
|
+
* shows in, or null (no delegation, another kind, or this is the top). */
|
|
287
|
+
function delegationSurface(request) {
|
|
288
|
+
if (typeof surfaceOf !== 'function' || !DELEGATED_KINDS.has(request.kind)) return null;
|
|
289
|
+
const own = String(request.sessionId || ownSessionId());
|
|
290
|
+
let surface = null;
|
|
291
|
+
try {
|
|
292
|
+
surface = surfaceOf(own);
|
|
293
|
+
} catch {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
const sessionId = String(surface?.sessionId || '');
|
|
297
|
+
if (!sessionId || sessionId === own || sessionId === ownSessionId()) return null;
|
|
298
|
+
return { sessionId, chain: Array.isArray(surface.chain) ? surface.chain.map(String) : [] };
|
|
299
|
+
}
|
|
136
300
|
|
|
137
301
|
return {
|
|
138
302
|
presentNextToolApproval,
|
|
139
303
|
finishToolApproval,
|
|
140
304
|
denyAllToolApprovals,
|
|
141
305
|
requestToolApproval,
|
|
306
|
+
adoptDelegatedApprovals,
|
|
142
307
|
};
|
|
143
308
|
}
|
|
@@ -123,6 +123,8 @@ export function createTranscriptIntake({ getState, flags, pushItem, patchItem, t
|
|
|
123
123
|
...routineTriggerField(extra),
|
|
124
124
|
...(extra && typeof extra.sender === 'string' && extra.sender ? { sender: extra.sender } : {}),
|
|
125
125
|
...(extra && typeof extra.device === 'string' && extra.device ? { device: extra.device } : {}),
|
|
126
|
+
// The bot that sent this message (a bot's `session send`).
|
|
127
|
+
...(extra && typeof extra.fromAgent === 'string' && extra.fromAgent ? { fromAgent: extra.fromAgent } : {}),
|
|
126
128
|
// Delivered into the running turn (steering): the desktop row's read mark.
|
|
127
129
|
...(extra?.steered === true ? { steered: true } : {}),
|
|
128
130
|
// Byte-free attachment metadata (name/mime/size) from the queue entry —
|
package/src/tui/session/turn.mjs
CHANGED
|
@@ -10,8 +10,9 @@ import { applyUsageDelta } from './session-stats.mjs';
|
|
|
10
10
|
import {
|
|
11
11
|
createTranscriptRouteMetadata,
|
|
12
12
|
transcriptRouteMetadataFields,
|
|
13
|
+
transcriptSourceFields,
|
|
13
14
|
} from '../../runtime/shared/transcript-metadata.mjs';
|
|
14
|
-
import { publishModelSwitch } from './session-api/routes.mjs';
|
|
15
|
+
import { publishModelSwitch, publishSessionSwitches } from './session-api/routes.mjs';
|
|
15
16
|
import { compactEventLabel } from '../../runtime/shared/compact-event-label.mjs';
|
|
16
17
|
import { pickVerb, pickDoneVerb, compactEventDetail } from './labels.mjs';
|
|
17
18
|
import { isCancelLikeError } from '../../runtime/shared/err-text.mjs';
|
|
@@ -172,6 +173,7 @@ function promptRestoreFor(displayText, options, submittedIds, content = null) {
|
|
|
172
173
|
pastedImages: options.pastedImages && typeof options.pastedImages === 'object' ? options.pastedImages : null,
|
|
173
174
|
pastedTexts: options.pastedTexts && typeof options.pastedTexts === 'object' ? options.pastedTexts : null,
|
|
174
175
|
onCommitted: typeof options.onCommitted === 'function' ? options.onCommitted : null,
|
|
176
|
+
onAborted: typeof options.onAborted === 'function' ? options.onAborted : null,
|
|
175
177
|
restorable: options.restorable !== false,
|
|
176
178
|
submittedIds,
|
|
177
179
|
// Which device submitted the prompt: only that device may get it back.
|
|
@@ -202,7 +204,7 @@ export function commitPromptRestore(flags, turn) {
|
|
|
202
204
|
restore.content = null;
|
|
203
205
|
}
|
|
204
206
|
|
|
205
|
-
function steeringItemExtras(steeringMeta) {
|
|
207
|
+
export function steeringItemExtras(steeringMeta) {
|
|
206
208
|
return {
|
|
207
209
|
// The steered message's stable id, so a compaction that drops it greys
|
|
208
210
|
// this row.
|
|
@@ -217,12 +219,7 @@ function steeringItemExtras(steeringMeta) {
|
|
|
217
219
|
? { execution: steeringMeta.execution }
|
|
218
220
|
: {}),
|
|
219
221
|
...(Array.isArray(steeringMeta?.images) && steeringMeta.images.length ? { images: steeringMeta.images } : {}),
|
|
220
|
-
...(
|
|
221
|
-
? { sender: steeringMeta.transcriptMeta.sender }
|
|
222
|
-
: {}),
|
|
223
|
-
...(typeof steeringMeta?.transcriptMeta?.device === 'string' && steeringMeta.transcriptMeta.device
|
|
224
|
-
? { device: steeringMeta.transcriptMeta.device }
|
|
225
|
-
: {}),
|
|
222
|
+
...transcriptSourceFields(steeringMeta?.transcriptMeta),
|
|
226
223
|
};
|
|
227
224
|
}
|
|
228
225
|
|
|
@@ -231,7 +228,7 @@ function steeringItemExtras(steeringMeta) {
|
|
|
231
228
|
// first (including a streamed tail that never got a trailing '\n') so the
|
|
232
229
|
// steered user turn and the next assistant response do not merge into one
|
|
233
230
|
// bubble and the tail is not dropped when the injection races finalization.
|
|
234
|
-
function injectSteerMessage({ stream, cards, pushUserOrSyntheticItem }, text, steeringMeta = {}) {
|
|
231
|
+
export function injectSteerMessage({ stream, cards, pushUserOrSyntheticItem }, text, steeringMeta = {}) {
|
|
235
232
|
// A suppressed live-completion twin is model-visible only; its Response
|
|
236
233
|
// card was already pushed at delivery time.
|
|
237
234
|
if (text === STEERING_SUPPRESSED_DISPLAY) return;
|
|
@@ -294,7 +291,7 @@ async function approveToolRequest(ctx, request) {
|
|
|
294
291
|
// contextStatus path instead of competing with its provider-aligned value.
|
|
295
292
|
function publishContextPressure({ syncContextStats, getState, set }, info) {
|
|
296
293
|
if (info?.willCompact !== true) return;
|
|
297
|
-
const used = Math.max(0, Number(info
|
|
294
|
+
const used = Math.max(0, Number(info.usedTokens) || 0);
|
|
298
295
|
if (!used) return;
|
|
299
296
|
syncContextStats({ allowEstimated: true });
|
|
300
297
|
set({ stats: { ...getState().stats } });
|
|
@@ -424,10 +421,18 @@ export function toolHandlers(ctx) {
|
|
|
424
421
|
// state parked on screen until the next model event arrives.
|
|
425
422
|
set({ spinner: { ...spinner, mode: 'requesting' } });
|
|
426
423
|
},
|
|
427
|
-
onToolApproval:
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
424
|
+
onToolApproval: Object.assign(
|
|
425
|
+
async (request) => {
|
|
426
|
+
if (!isCurrentTurn()) return { approved: false, reason: 'turn no longer active' };
|
|
427
|
+
return approveToolRequest(ctx, request);
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
// A word to the person after their answer (e.g. an always-allow that could not be saved).
|
|
431
|
+
// A transcript notice of THIS session: the desktop's toast region draws only the
|
|
432
|
+
// host-level snapshot's toasts, while the pane that asked reads its own session lane.
|
|
433
|
+
notice: (text, tone = 'warn') => ctx.pushNotice?.(text, tone, { transcript: true }),
|
|
434
|
+
}
|
|
435
|
+
),
|
|
431
436
|
};
|
|
432
437
|
}
|
|
433
438
|
|
|
@@ -768,6 +773,10 @@ export function createRunTurn(bag) {
|
|
|
768
773
|
if (!isCurrentTurn()) return;
|
|
769
774
|
publishModelSwitch(bag, boundary);
|
|
770
775
|
},
|
|
776
|
+
onSessionSwitches: (switches) => {
|
|
777
|
+
if (!isCurrentTurn()) return;
|
|
778
|
+
publishSessionSwitches(bag, switches);
|
|
779
|
+
},
|
|
771
780
|
});
|
|
772
781
|
if (!isCurrentTurn()) turn.cancelled = true;
|
|
773
782
|
else completeTurn(ctx, result, session);
|
|
@@ -8,11 +8,14 @@ import { parseToolArgs } from '../runtime/shared/tool-surface.mjs';
|
|
|
8
8
|
// Anchor to the orchestrator's actual denial envelope:
|
|
9
9
|
// `Error: tool "<name>" denied by hook[: ...]`
|
|
10
10
|
// `Error: tool "<name>" denied by hook: approval required but no approval UI is available`
|
|
11
|
+
// `Error: tool "<name>" was not approved: <reason>. Do not retry it …` (a person said no)
|
|
11
12
|
// Matching the bare phrase anywhere in the body produced FALSE POSITIVES when a
|
|
12
13
|
// normal (successful) tool result merely CONTAINED the text — e.g. a read/grep
|
|
13
14
|
// over this very file or the hook source. The denial is always an Error
|
|
14
15
|
// envelope emitted at the START of the result, so anchor on that prefix.
|
|
15
|
-
const HOOK_DENIAL_RE = /^Error:\s*tool\s*"[^"]*"\s*denied by hook\b/im;
|
|
16
|
+
const HOOK_DENIAL_RE = /^Error:\s*tool\s*"[^"]*"\s*(?:denied by hook|was not approved)\b/im;
|
|
17
|
+
// The not-approved denial's instruction to the model, not shown to the user.
|
|
18
|
+
const NOT_APPROVED_INSTRUCTION_RE = /\s*Do not retry it or reach the same result another way; report it\.\s*$/;
|
|
16
19
|
const APPROVAL_UNAVAILABLE_RE = /denied by hook:\s*approval required but no approval UI is available/i;
|
|
17
20
|
|
|
18
21
|
export function toolItemResultText(item) {
|
|
@@ -44,7 +47,10 @@ export function isHookApprovalDenialToolItem(item) {
|
|
|
44
47
|
export function formatHookDenialDetail(text) {
|
|
45
48
|
const raw = String(text ?? '').trim();
|
|
46
49
|
if (!raw) return '';
|
|
47
|
-
const stripped = raw
|
|
50
|
+
const stripped = raw
|
|
51
|
+
.replace(/^Error:\s*tool\s*"[^"]*"\s*/i, '')
|
|
52
|
+
.replace(NOT_APPROVED_INSTRUCTION_RE, '')
|
|
53
|
+
.trim();
|
|
48
54
|
return stripped || raw;
|
|
49
55
|
}
|
|
50
56
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync,
|
|
3
|
-
renameSync, statSync, fstatSync,
|
|
3
|
+
renameSync, statSync, fstatSync,
|
|
4
4
|
} from 'fs';
|
|
5
|
-
import { appendFile, mkdir, readFile
|
|
5
|
+
import { appendFile, mkdir, readFile } from 'fs/promises';
|
|
6
|
+
import { writeFileAtomicAsync, writeFileAtomicSync } from '../../../../runtime/shared/atomic-file.mjs';
|
|
6
7
|
import { dirname, join } from 'path';
|
|
7
8
|
import { resolvePluginData } from '../../../../runtime/shared/plugin-paths.mjs';
|
|
8
9
|
import { readSection } from '../../../../runtime/shared/config.mjs';
|
|
@@ -586,9 +587,9 @@ function ensureUsageStoreMigrated() {
|
|
|
586
587
|
if (!existsSync(store)) {
|
|
587
588
|
const raw = readJsonFile(legacy);
|
|
588
589
|
const events = (Array.isArray(raw?.events) ? raw.events : []).slice(-MAX_USAGE_EVENTS);
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
590
|
+
// Flushed before it is published: the store would otherwise be NUL
|
|
591
|
+
// after a crash, losing the migrated history.
|
|
592
|
+
writeFileAtomicSync(store, events.map(e => JSON.stringify(e) + '\n').join(''));
|
|
592
593
|
}
|
|
593
594
|
let backup = legacy + LEGACY_BACKUP_SUFFIX;
|
|
594
595
|
if (existsSync(backup)) backup = `${legacy}.${Date.now()}${LEGACY_BACKUP_SUFFIX}`;
|
|
@@ -645,9 +646,7 @@ async function compactUsageStore(store) {
|
|
|
645
646
|
await withFileLock(usageLockPath(store), async () => {
|
|
646
647
|
const lines = (await readFile(store, 'utf8')).split('\n').filter(l => l.trim());
|
|
647
648
|
if (lines.length <= MAX_USAGE_EVENTS * 1.5) return;
|
|
648
|
-
|
|
649
|
-
await writeFile(tmp, lines.slice(-MAX_USAGE_EVENTS).join('\n') + '\n');
|
|
650
|
-
await rename(tmp, store);
|
|
649
|
+
await writeFileAtomicAsync(store, lines.slice(-MAX_USAGE_EVENTS).join('\n') + '\n');
|
|
651
650
|
});
|
|
652
651
|
} catch {
|
|
653
652
|
// Compaction is best effort; the next flush retries.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'fs';
|
|
2
1
|
import { join } from 'path';
|
|
3
2
|
import { resolvePluginData } from '../../../../runtime/shared/plugin-paths.mjs';
|
|
4
|
-
import { updateJsonAtomicSync } from '../../../../runtime/shared/atomic-file.mjs';
|
|
3
|
+
import { readJsonStateSync, updateJsonAtomicSync } from '../../../../runtime/shared/atomic-file.mjs';
|
|
5
4
|
import { CLAUDE_CURRENT_MODE } from './claude-current.mjs';
|
|
6
5
|
|
|
7
6
|
const STORE_FILE = 'gateway-session-routes.json';
|
|
@@ -68,9 +67,9 @@ export function gatewaySessionRoutesPath() {
|
|
|
68
67
|
|
|
69
68
|
function readStore() {
|
|
70
69
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const parsed =
|
|
70
|
+
// A damaged store (NUL, truncated) is kept aside as *.corrupt-<ts> and its
|
|
71
|
+
// last good copy restored, so a session never loses its route pin to it.
|
|
72
|
+
const parsed = readJsonStateSync(gatewaySessionRoutesPath(), { fallback: {} });
|
|
74
73
|
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
75
74
|
} catch {
|
|
76
75
|
return {};
|
|
@@ -187,7 +186,7 @@ export function writeGatewaySessionRoutes(entries = []) {
|
|
|
187
186
|
sessions: pruneRouteMap(sessions, updatedAt, MAX_SESSION_ROUTES),
|
|
188
187
|
sessionHosts: pruneRouteMap(sessionHosts, updatedAt, MAX_HOST_ROUTES),
|
|
189
188
|
};
|
|
190
|
-
}, { compact: true,
|
|
189
|
+
}, { compact: true, backup: true });
|
|
191
190
|
return true;
|
|
192
191
|
} catch {
|
|
193
192
|
return false;
|
|
@@ -216,7 +215,7 @@ export function clearGatewaySessionRoute(sessionId, options = {}) {
|
|
|
216
215
|
delete sessions[sid];
|
|
217
216
|
}
|
|
218
217
|
return { version: 2, updatedAt: Date.now(), sessions, sessionHosts };
|
|
219
|
-
}, { compact: true,
|
|
218
|
+
}, { compact: true, backup: true });
|
|
220
219
|
return true;
|
|
221
220
|
} catch {
|
|
222
221
|
return false;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
- No user is present in this run. Do not wait for clarification; when
|
|
2
|
-
approval is required, follow the approval-hold path. Hand the result to the
|
|
3
|
-
configured delivery and do not send a duplicate message.
|
|
4
|
-
- Report the outcome in plain words for the user; never name internal tools,
|
|
5
|
-
actions or parameters. If a sign-in, code or CAPTCHA blocks the task, stop
|
|
6
|
-
and say which site needs the user to sign in.
|