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
|
@@ -31,10 +31,30 @@ export const PROCESS_RESTART_FAILURE = 'process-restart';
|
|
|
31
31
|
/** The row's turn was stopped by the progress (stall) watchdog. */
|
|
32
32
|
export const WATCHDOG_STALL_FAILURE = 'stalled';
|
|
33
33
|
|
|
34
|
+
/** A failed row whose turn a process restart ended and whose owner has not
|
|
35
|
+
* been told yet (restart-notify). It is the only record of that owed result,
|
|
36
|
+
* so closing the worker never drops it. */
|
|
37
|
+
export const isUnnotifiedRestartFailure = (row) =>
|
|
38
|
+
row?.status === 'failed' &&
|
|
39
|
+
row.failureReason === PROCESS_RESTART_FAILURE &&
|
|
40
|
+
Boolean(clean(row.ownerSessionId)) &&
|
|
41
|
+
!row.restartNotified;
|
|
42
|
+
|
|
34
43
|
/** A turn's settled row status and failure reason: a watchdog stop is a
|
|
35
44
|
* failure whatever partial output it handed back (`finalStatus` may still
|
|
36
|
-
* read `idle` for the job's sake);
|
|
37
|
-
|
|
45
|
+
* read `idle` for the job's sake); a turn the process exit cut off (its `job`
|
|
46
|
+
* cancelled with terminalReason PROCESS_RESTART_FAILURE, lifecycle/teardown)
|
|
47
|
+
* fails as a restart failure under its task id, which the next process tells
|
|
48
|
+
* its owner; everything else keeps `finalStatus`. */
|
|
49
|
+
export function settledWorkerStatus(finalStatus, stalled, job = null) {
|
|
50
|
+
if (job?.status === 'cancelled' && job.terminalReason === PROCESS_RESTART_FAILURE) {
|
|
51
|
+
return {
|
|
52
|
+
status: 'failed',
|
|
53
|
+
stage: 'failed',
|
|
54
|
+
failureReason: PROCESS_RESTART_FAILURE,
|
|
55
|
+
...(job.taskId ? { task_id: job.taskId } : {}),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
38
58
|
return stalled
|
|
39
59
|
? { status: 'failed', stage: 'failed', failureReason: WATCHDOG_STALL_FAILURE }
|
|
40
60
|
: { status: finalStatus, stage: finalStatus };
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
createRowLiveness,
|
|
23
23
|
isActiveWorkerRow,
|
|
24
24
|
isStaleApprovalWait,
|
|
25
|
+
isUnnotifiedRestartFailure,
|
|
25
26
|
PROCESS_RESTART_FAILURE,
|
|
26
27
|
runtimeDied,
|
|
27
28
|
} from './worker-index/row-liveness.mjs';
|
|
@@ -101,12 +102,15 @@ export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCw
|
|
|
101
102
|
const rowFromSession = (session, fallbackTag = '', extra = {}) =>
|
|
102
103
|
workerRowFromSession(session, fallbackTag, extra, (sessionId) => mgr.getSessionRuntime?.(sessionId));
|
|
103
104
|
|
|
105
|
+
// A row whose owner is still owed its restart failure stays: closing the
|
|
106
|
+
// worker (a process exit closes every one) must not lose that result.
|
|
104
107
|
function removeWorkerRow({ tag = '', sessionId = '' } = {}) {
|
|
105
108
|
const targetTag = clean(tag);
|
|
106
109
|
const targetSessionId = clean(sessionId);
|
|
107
110
|
batch.flush();
|
|
108
111
|
store.write((byKey) => {
|
|
109
112
|
for (const [key, row] of [...byKey.entries()]) {
|
|
113
|
+
if (isUnnotifiedRestartFailure(row)) continue;
|
|
110
114
|
if ((targetSessionId && row.sessionId === targetSessionId) || (targetTag && row.tag === targetTag)) {
|
|
111
115
|
byKey.delete(key);
|
|
112
116
|
}
|
|
@@ -194,12 +198,6 @@ export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCw
|
|
|
194
198
|
return true;
|
|
195
199
|
}
|
|
196
200
|
|
|
197
|
-
const isUnnotifiedRestartFailure = (row) =>
|
|
198
|
-
row.status === 'failed' &&
|
|
199
|
-
row.failureReason === PROCESS_RESTART_FAILURE &&
|
|
200
|
-
Boolean(clean(row.ownerSessionId)) &&
|
|
201
|
-
!row.restartNotified;
|
|
202
|
-
|
|
203
201
|
/** Rows whose turn a process restart ended and whose owner has not been told
|
|
204
202
|
* yet — whoever settled the row (this process at startup, or the
|
|
205
203
|
* predecessor's exit flush). Read-only: the caller enqueues the owner's
|
|
@@ -169,6 +169,12 @@ export function createStandaloneAgent({
|
|
|
169
169
|
},
|
|
170
170
|
getStatus,
|
|
171
171
|
recoverWorkers,
|
|
172
|
+
// Daemon start: settle the rows the previous process left running and
|
|
173
|
+
// queue each owner's failure result; resolves once they are queued.
|
|
174
|
+
settleRestartFailures: () => {
|
|
175
|
+
registry.recoverStaleWorkerRows({ deadOnly: true });
|
|
176
|
+
return notifyRestartFailures();
|
|
177
|
+
},
|
|
172
178
|
upsertLeadSession: registry.upsertLeadSession,
|
|
173
179
|
updateLeadWorkerCwd: registry.updateLeadWorkerCwd,
|
|
174
180
|
forgetLeadSession: registry.forgetLeadSession,
|
|
@@ -165,7 +165,7 @@ export function reconcileLostDaemonCaptures({
|
|
|
165
165
|
for (const name of names) {
|
|
166
166
|
const file = path.join(dir, name);
|
|
167
167
|
const record = readRecord(file);
|
|
168
|
-
if (
|
|
168
|
+
if (record?.kind !== 'mixdog-daemon-crash-capture') continue;
|
|
169
169
|
if (!record.pid || record.pid === selfPid || record.exitedAt || record.daemonExit || record.exitReason) continue;
|
|
170
170
|
if (pidAlive(record.pid)) continue;
|
|
171
171
|
try {
|
|
@@ -21,9 +21,10 @@ import { daemonCrashCaptureDir } from './paths.mjs';
|
|
|
21
21
|
// Prune only files this module creates: `daemon-<yyyymmdd>-<hhmmss>-<pid>-<rand>`.
|
|
22
22
|
const CAPTURE_STEM_RE = /^daemon-\d{8}-\d{6}-\d+-[0-9a-f]{4}$/;
|
|
23
23
|
const CAPTURE_SUFFIXES = ['.err.log', '.json'];
|
|
24
|
-
// Debris from this module's own atomic sidecar writes (
|
|
25
|
-
//
|
|
26
|
-
|
|
24
|
+
// Debris from this module's own atomic sidecar writes (the atomic writer names
|
|
25
|
+
// its temp `<basename>.mixdog-tmp-<hex>`; older builds `.<basename>.<hex>.tmp`),
|
|
26
|
+
// never anyone else's file.
|
|
27
|
+
const CAPTURE_TEMP_RE = /^\.?daemon-\d{8}-\d{6}-(\d+)-[0-9a-f]{4}\.json\.(?:[0-9a-f]+\.tmp|mixdog-tmp-[0-9a-f]+)$/;
|
|
27
28
|
export const CRASH_CAPTURE_KEEP_BOOTS = 8;
|
|
28
29
|
const CRASH_CAPTURE_KEEP_BYTES = 2 * 1024 * 1024;
|
|
29
30
|
const CRASH_CAPTURE_TAIL_BYTES = 256 * 1024;
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
* file-stamp set, standard events merged, legacy rules collected, and the
|
|
5
5
|
* parse errors both reported and recorded on the result.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
8
|
-
import { applyHookRulePatches, hookFileStamp } from './rule-file.mjs';
|
|
7
|
+
import { applyHookRulePatches, hookFileStamp, readHookDocument } from './rule-file.mjs';
|
|
9
8
|
import {
|
|
10
9
|
hookConfigEntries,
|
|
11
10
|
mergeEvents,
|
|
@@ -61,14 +60,24 @@ export function createConfigLoader({ dataDir, rulesPath, emit, pendingPatches })
|
|
|
61
60
|
for (const entry of entries) {
|
|
62
61
|
const filePath = entry.path;
|
|
63
62
|
let parsed = null;
|
|
63
|
+
let damaged = false;
|
|
64
64
|
try {
|
|
65
|
-
|
|
65
|
+
// The rules file is this module's own (written with a `.bak`): a
|
|
66
|
+
// damaged copy is restored from it. Other hooks files are only read.
|
|
67
|
+
parsed = readHookDocument(filePath, {
|
|
68
|
+
restore: filePath === rulesPath,
|
|
69
|
+
onDamaged: (error) => {
|
|
70
|
+
damaged = true;
|
|
71
|
+
errors.push({ file: filePath, error: error?.message || String(error) });
|
|
72
|
+
},
|
|
73
|
+
});
|
|
66
74
|
} catch (error) {
|
|
67
|
-
|
|
68
|
-
if (!(error instanceof SyntaxError)) cacheable = false;
|
|
75
|
+
cacheable = false;
|
|
69
76
|
errors.push({ file: filePath, error: error?.message || String(error) });
|
|
70
77
|
continue;
|
|
71
78
|
}
|
|
79
|
+
// Missing, or damaged without a good copy (reported above): no hooks.
|
|
80
|
+
if (damaged || parsed === null) continue;
|
|
72
81
|
sources.push(filePath);
|
|
73
82
|
sourceEntries.push({
|
|
74
83
|
path: filePath,
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { isDeepStrictEqual } from 'node:util';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
holdsNoData,
|
|
5
|
+
parseJsonText,
|
|
6
|
+
readJsonStateSync,
|
|
7
|
+
updateJsonAtomicSync,
|
|
8
|
+
} from '../../../runtime/shared/atomic-file.mjs';
|
|
5
9
|
import { normalizeRules } from './config.mjs';
|
|
6
10
|
|
|
7
11
|
export function hookFileStamp(path) {
|
|
@@ -14,13 +18,41 @@ export function hookFileStamp(path) {
|
|
|
14
18
|
}
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
// The hooks document at `path`, or null when it is missing or damaged (empty,
|
|
22
|
+
// NUL-filled after a crash, or not JSON). A damaged file must not turn every
|
|
23
|
+
// tool call into a policy-check failure, and must not silently drop the deny
|
|
24
|
+
// rules of a good copy: with `restore` (the rules file this module writes with
|
|
25
|
+
// a `.bak`), a valid `<path>.bak` is restored and read — the damaged bytes are
|
|
26
|
+
// kept aside as `<path>.corrupt-<ts>`. Without a good copy the file stays in
|
|
27
|
+
// place (a hand-edit can still fix it) and `onDamaged(error)` reports it; the
|
|
28
|
+
// caller then has no rules from it. Hooks files the user or a plugin owns are
|
|
29
|
+
// read with `restore: false`: never moved, locked or replaced. Real I/O errors
|
|
30
|
+
// still throw.
|
|
31
|
+
export function readHookDocument(path, { restore = true, onDamaged } = {}) {
|
|
32
|
+
let text;
|
|
18
33
|
try {
|
|
19
|
-
|
|
34
|
+
text = readFileSync(path, 'utf8');
|
|
20
35
|
} catch (error) {
|
|
21
36
|
if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') return null;
|
|
22
37
|
throw error;
|
|
23
38
|
}
|
|
39
|
+
let damage;
|
|
40
|
+
if (holdsNoData(text)) {
|
|
41
|
+
damage = new SyntaxError('the file holds no data (empty or NUL-filled)');
|
|
42
|
+
} else {
|
|
43
|
+
try {
|
|
44
|
+
return parseJsonText(text);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
47
|
+
damage = error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (restore) {
|
|
51
|
+
const restored = readJsonStateSync(path, { fallback: null, keepWithoutBackup: true });
|
|
52
|
+
if (restored !== null) return restored;
|
|
53
|
+
}
|
|
54
|
+
onDamaged?.(damage);
|
|
55
|
+
return null;
|
|
24
56
|
}
|
|
25
57
|
|
|
26
58
|
function replaceRules(document, rules) {
|
|
@@ -36,13 +68,19 @@ function replaceRules(document, rules) {
|
|
|
36
68
|
}
|
|
37
69
|
|
|
38
70
|
export function updateHookRules(path, update) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
71
|
+
let next;
|
|
72
|
+
// A damaged file is kept aside as <path>.corrupt-<ts> (its last good copy
|
|
73
|
+
// <path>.bak restored) before the update, never overwritten.
|
|
74
|
+
updateJsonAtomicSync(
|
|
75
|
+
path,
|
|
76
|
+
(document) => {
|
|
77
|
+
const rules = normalizeRules(document).filter((rule) => rule && typeof rule === 'object');
|
|
78
|
+
next = update(rules);
|
|
79
|
+
return replaceRules(document, next);
|
|
80
|
+
},
|
|
81
|
+
{ backup: true }
|
|
82
|
+
);
|
|
83
|
+
return { stamp: hookFileStamp(path), rules: next };
|
|
46
84
|
}
|
|
47
85
|
|
|
48
86
|
export function applyHookRulePatches(rules, patches, { strict = true } = {}) {
|
|
@@ -3,12 +3,11 @@ import { existsSync, mkdirSync, readdirSync, renameSync, rmSync } from 'node:fs'
|
|
|
3
3
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { createHash, randomUUID } from 'node:crypto';
|
|
6
|
-
import {
|
|
6
|
+
import { readJsonStateSync, updateJsonAtomicSync, withFileLockSync } from '../../runtime/shared/atomic-file.mjs';
|
|
7
7
|
import { resolvePluginData } from '../../runtime/shared/plugin-paths.mjs';
|
|
8
8
|
import { pluginManifest } from '../../runtime/shared/plugin-manifest.mjs';
|
|
9
9
|
import { pluginMetadata } from '../../runtime/shared/plugin-metadata.mjs';
|
|
10
10
|
import { clean } from '../../runtime/shared/clean.mjs';
|
|
11
|
-
import { readJsonSafe } from '../../runtime/shared/json-file.mjs';
|
|
12
11
|
|
|
13
12
|
const REGISTRY_VERSION = 1;
|
|
14
13
|
|
|
@@ -28,38 +27,39 @@ function installRoot(dataDir = resolvePluginData()) {
|
|
|
28
27
|
return join(pluginBaseDir(dataDir), 'installed');
|
|
29
28
|
}
|
|
30
29
|
|
|
30
|
+
const emptyRegistry = () => ({ version: REGISTRY_VERSION, plugins: [] });
|
|
31
|
+
const hasPluginList = (raw) => Boolean(raw && Array.isArray(raw.plugins));
|
|
32
|
+
|
|
33
|
+
// A damaged registry (empty, NUL-filled after a crash, malformed, or not a
|
|
34
|
+
// plugin list) never blocks the plugin features: its bytes are kept aside as
|
|
35
|
+
// registry.json.corrupt-<ts>, the last good copy registry.json.bak is
|
|
36
|
+
// restored when there is one, else the registry starts empty. I/O errors
|
|
37
|
+
// still throw.
|
|
31
38
|
function loadRegistry(dataDir = resolvePluginData()) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
return readJsonStateSync(registryPath(dataDir), {
|
|
40
|
+
validate(raw) {
|
|
41
|
+
if (!hasPluginList(raw)) throw new Error('plugin registry has no plugin list');
|
|
42
|
+
return raw;
|
|
43
|
+
},
|
|
44
|
+
fallback: emptyRegistry(),
|
|
45
|
+
secret: true,
|
|
46
|
+
});
|
|
37
47
|
}
|
|
38
48
|
|
|
39
49
|
function mutateRegistry(dataDir, mutator) {
|
|
40
50
|
const path = registryPath(dataDir);
|
|
41
51
|
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
version: REGISTRY_VERSION,
|
|
51
|
-
plugins: Array.isArray(registry.plugins) ? registry.plugins : [],
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
lock: false,
|
|
55
|
-
secret: true,
|
|
56
|
-
fsyncDir: true,
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
return result;
|
|
52
|
+
let result;
|
|
53
|
+
updateJsonAtomicSync(
|
|
54
|
+
path,
|
|
55
|
+
(raw) => {
|
|
56
|
+
const registry = hasPluginList(raw) ? raw : emptyRegistry();
|
|
57
|
+
result = mutator(registry);
|
|
58
|
+
return { version: REGISTRY_VERSION, plugins: registry.plugins };
|
|
60
59
|
},
|
|
61
|
-
{ secret: true }
|
|
60
|
+
{ secret: true, fsyncDir: true, backup: true }
|
|
62
61
|
);
|
|
62
|
+
return result;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function displayNameFromUrl(url) {
|
|
@@ -394,7 +394,10 @@ function oauthProviderSetup(p, providers, checkSecrets) {
|
|
|
394
394
|
|
|
395
395
|
const CUSTOM_ID_RE = /^custom-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
396
396
|
const CUSTOM_TEST_TIMEOUT_MS = 20_000;
|
|
397
|
-
|
|
397
|
+
// A catalog host can sit behind a slow gateway: api.nano-gpt.com's /models
|
|
398
|
+
// answered 503 only after ~44 s, so the wait must outlast that to surface the
|
|
399
|
+
// service's own answer instead of a local timeout.
|
|
400
|
+
const CUSTOM_DISCOVERY_TIMEOUT_MS = 60_000;
|
|
398
401
|
|
|
399
402
|
export function isCustomProviderConfig(entry) {
|
|
400
403
|
return Boolean(entry) && typeof entry === 'object' && entry.type === 'custom';
|
|
@@ -439,6 +442,7 @@ function publicCustomModelRows(rows) {
|
|
|
439
442
|
model.hidden = item.hidden === true;
|
|
440
443
|
model.manual = item.manual === true;
|
|
441
444
|
for (const key of [
|
|
445
|
+
'supportsVision',
|
|
442
446
|
'supportsReasoning',
|
|
443
447
|
'reasoningOptions',
|
|
444
448
|
'reasoningLevels',
|
|
@@ -585,7 +589,8 @@ async function modelProxyProviderSetup(options) {
|
|
|
585
589
|
});
|
|
586
590
|
const custom = Object.entries(providers)
|
|
587
591
|
.filter(([id, entry]) => isCustomProviderId(id) && entry?.type === 'custom')
|
|
588
|
-
|
|
592
|
+
// Older desktops advertise no name: the id is the fallback.
|
|
593
|
+
.map(([id, entry]) => ({ id, name: (typeof entry.name === 'string' && entry.name.trim()) || id }));
|
|
589
594
|
return {
|
|
590
595
|
managedByClient: true,
|
|
591
596
|
api: [...project(API_PROVIDERS, 'api', 'api-key'), ...project(custom, 'api', 'custom')],
|
|
@@ -949,7 +954,9 @@ async function withTimeout(run, ms, label) {
|
|
|
949
954
|
const timeout = new Promise((_, reject) => {
|
|
950
955
|
timer = setTimeout(() => {
|
|
951
956
|
controller.abort();
|
|
952
|
-
reject(
|
|
957
|
+
reject(
|
|
958
|
+
Object.assign(new Error(`${label} timed out after ${Math.round(ms / 1000)}s`), { code: 'EPROVIDERTIMEOUT' })
|
|
959
|
+
);
|
|
953
960
|
}, ms);
|
|
954
961
|
});
|
|
955
962
|
try {
|
|
@@ -1106,7 +1113,15 @@ export async function saveCustomProvider(cfgMod, rawInput) {
|
|
|
1106
1113
|
return typed ? serializeCustomKeySave(id, commit) : commit();
|
|
1107
1114
|
}
|
|
1108
1115
|
|
|
1109
|
-
const MODEL_PATCH_KEYS = new Set([
|
|
1116
|
+
const MODEL_PATCH_KEYS = new Set([
|
|
1117
|
+
'manual',
|
|
1118
|
+
'hidden',
|
|
1119
|
+
'name',
|
|
1120
|
+
'contextWindow',
|
|
1121
|
+
'maxOutputTokens',
|
|
1122
|
+
'supportsVision',
|
|
1123
|
+
'reasoning',
|
|
1124
|
+
]);
|
|
1110
1125
|
const REASONING_PATCH_KEYS = new Set(['levels', 'wireFormat', 'wireValues', 'replay']);
|
|
1111
1126
|
|
|
1112
1127
|
// Tri-state merge: undefined preserves, null deletes the property, a value replaces it.
|
|
@@ -1330,7 +1345,11 @@ export async function discoverCustomProviderModels(cfgMod, rawInput) {
|
|
|
1330
1345
|
try {
|
|
1331
1346
|
const { createCustomProvider } = await loadCustomProviderModule();
|
|
1332
1347
|
const provider = await createCustomProvider(id || 'custom-discovery', { ...config, apiKey });
|
|
1333
|
-
const listed = await withTimeout(
|
|
1348
|
+
const listed = await withTimeout(
|
|
1349
|
+
(signal) => provider.listModels({ signal, timeoutMs: CUSTOM_DISCOVERY_TIMEOUT_MS }),
|
|
1350
|
+
CUSTOM_DISCOVERY_TIMEOUT_MS,
|
|
1351
|
+
'model discovery'
|
|
1352
|
+
);
|
|
1334
1353
|
const models = publicCustomModelRows(listed);
|
|
1335
1354
|
// A failed discovery that still left manual rows reports its error too.
|
|
1336
1355
|
const failure = provider.customDiscoveryError;
|
|
@@ -1343,8 +1362,9 @@ export async function discoverCustomProviderModels(cfgMod, rawInput) {
|
|
|
1343
1362
|
function discoveryErrorView(error, secrets) {
|
|
1344
1363
|
const status = Number.isInteger(error?.status) ? error.status : undefined;
|
|
1345
1364
|
const authKind = status === 401 || status === 403 ? 'authentication' : 'request';
|
|
1365
|
+
const kind = status === 404 || status === 405 ? 'unavailable' : authKind;
|
|
1346
1366
|
return {
|
|
1347
|
-
kind:
|
|
1367
|
+
kind: error?.code === 'EPROVIDERTIMEOUT' ? 'timeout' : kind,
|
|
1348
1368
|
...(status === undefined ? {} : { status }),
|
|
1349
1369
|
message: sanitizeCustomError(error, secrets).message,
|
|
1350
1370
|
};
|
|
@@ -11,17 +11,31 @@
|
|
|
11
11
|
// - a group-room member session is no background run, but it speaks for the
|
|
12
12
|
// room, not for the user: it creates or changes no agent, automation or
|
|
13
13
|
// other setting either.
|
|
14
|
+
// - an unattended run — a routine turn in a bot's home chat (Mixy's too), or
|
|
15
|
+
// work it or a room started (held-requests.mjs unattendedRunOf) — is checked
|
|
16
|
+
// first and only ever narrows: at most its own bot's agent scope
|
|
17
|
+
// (`unattended: true`), which manages that bot's own automations and route
|
|
18
|
+
// and changes no other setting.
|
|
14
19
|
// The app's own panels call channel-admin directly and act for the human.
|
|
15
20
|
import { MIXY_AGENT_ID, agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
16
21
|
import { roomMemberOfSession } from '../../runtime/agent/orchestrator/session/agent-room.mjs';
|
|
17
22
|
import { mixyDisplayName } from '../../runtime/agent/orchestrator/session/mixy-name.mjs';
|
|
18
23
|
import { isAgentOwner } from '../../runtime/agent/orchestrator/agent-owner.mjs';
|
|
24
|
+
import { unattendedRunOf } from '../held-requests.mjs';
|
|
19
25
|
|
|
20
26
|
const INTERACTIVE_SOURCE_TYPES = new Set(['', 'lead', 'cli']);
|
|
27
|
+
// What an unattended run may still change: its own bot's automations (each
|
|
28
|
+
// checked by assertAutomationAccess) and its own route (assertOwnAgentSettings).
|
|
29
|
+
const UNATTENDED_OWN_ACTIONS = new Set([
|
|
30
|
+
'save_automation',
|
|
31
|
+
'set_automation_enabled',
|
|
32
|
+
'delete_automation',
|
|
33
|
+
'run_automation',
|
|
34
|
+
'set_agent_route',
|
|
35
|
+
]);
|
|
21
36
|
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
const id = String(session?.id || '');
|
|
37
|
+
/** The scope by the session's id and record alone. */
|
|
38
|
+
function provenanceScope(session, id) {
|
|
25
39
|
const member = roomMemberOfSession(id);
|
|
26
40
|
if (member) return { kind: 'room-member', agentId: member.agentId };
|
|
27
41
|
const homeAgent = agentIdOfHomeSession(id);
|
|
@@ -35,6 +49,17 @@ export function scheduleCallerScope(session) {
|
|
|
35
49
|
return headless ? { kind: 'headless' } : { kind: 'human' };
|
|
36
50
|
}
|
|
37
51
|
|
|
52
|
+
/** `{ kind: 'human' | 'agent' | 'room-member' | 'headless', agentId?, unattended? }` of a session record. */
|
|
53
|
+
export function scheduleCallerScope(session) {
|
|
54
|
+
const id = String(session?.id || '');
|
|
55
|
+
const scope = provenanceScope(session, id);
|
|
56
|
+
const run = id ? unattendedRunOf(id) : null;
|
|
57
|
+
if (!run || scope.kind === 'headless' || scope.kind === 'room-member') return scope;
|
|
58
|
+
if (run.kind === 'room') return { kind: 'room-member', agentId: run.agentId };
|
|
59
|
+
if (!run.agentId || (scope.kind === 'agent' && scope.agentId !== run.agentId)) return { kind: 'headless' };
|
|
60
|
+
return { kind: 'agent', agentId: run.agentId, unattended: true };
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
/** Throws unless `scope` may `action` the `kind` ('schedule' | 'webhook')
|
|
39
64
|
* automation `current` (null when creating) with `owner` the requested owner
|
|
40
65
|
* ('' keeps the saved one). `agentIds` are the agents a transfer may name;
|
|
@@ -83,8 +108,12 @@ export function assertOwnAgentSettings(scope, agentId, action) {
|
|
|
83
108
|
}
|
|
84
109
|
}
|
|
85
110
|
|
|
86
|
-
/** Throws when `scope` is a headless run: it reads settings, never changes
|
|
111
|
+
/** Throws when `scope` is a headless run: it reads settings, never changes
|
|
112
|
+
* them; an unattended run changes only its own bot's automations and route. */
|
|
87
113
|
export function assertInteractiveCaller(scope, action) {
|
|
114
|
+
if (scope?.unattended && !UNATTENDED_OWN_ACTIONS.has(action)) {
|
|
115
|
+
throw new Error(`An unattended run cannot change settings (setup ${action})`);
|
|
116
|
+
}
|
|
88
117
|
if (scope?.kind === 'human' || scope?.kind === 'agent') return;
|
|
89
118
|
if (scope?.kind === 'room-member') throw new Error(`A group-room member cannot change settings (setup ${action})`);
|
|
90
119
|
throw new Error(`A background run cannot change settings (setup ${action})`);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { writeFileAtomicSync } from '../../runtime/shared/atomic-file.mjs';
|
|
3
4
|
import { pluginSkillsRoots } from '../../runtime/shared/plugin-manifest.mjs';
|
|
4
5
|
import {
|
|
5
6
|
EMPTY_HISTORY,
|
|
@@ -43,7 +44,7 @@ export function ensureStandaloneEnvironment({ rootDir, dataDir }) {
|
|
|
43
44
|
retireSeededPackCopies({ rootDir, dataDir, backup, includeHistory });
|
|
44
45
|
if (includeHistory && !backup.failures) {
|
|
45
46
|
try {
|
|
46
|
-
|
|
47
|
+
writeFileAtomicSync(markerFile, `${stamp}\n`);
|
|
47
48
|
} catch {
|
|
48
49
|
/* marker only; the sweep simply repeats */
|
|
49
50
|
}
|
|
@@ -68,7 +69,7 @@ function cleanupRetiredChannelSecrets(dataDir) {
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
try {
|
|
71
|
-
|
|
72
|
+
writeFileAtomicSync(marker, `${new Date().toISOString()}\n`);
|
|
72
73
|
} catch {
|
|
73
74
|
/* marker only */
|
|
74
75
|
}
|
|
@@ -92,7 +92,7 @@ function refreshScope(options) {
|
|
|
92
92
|
* then resolve whatever usage the provider — or a local budget fallback — can
|
|
93
93
|
* supply. The row is appended to `rows` before the first emit so every paint
|
|
94
94
|
* from here on includes it. */
|
|
95
|
-
async function apiProviderRow(item, {
|
|
95
|
+
async function apiProviderRow(item, { providers, preview, snapshotOptions, rows, emit }) {
|
|
96
96
|
const providerCfg = providers[item.id] || {};
|
|
97
97
|
const row = baseRow(item, 'api', providerCfg);
|
|
98
98
|
row.status = row.authenticated ? 'checking' : 'missing';
|
|
@@ -535,7 +535,8 @@ function exportUnpricedModels(state) {
|
|
|
535
535
|
const rows = [];
|
|
536
536
|
for (const provider of state.providers.values()) {
|
|
537
537
|
for (const model of provider.models.values()) {
|
|
538
|
-
if (model.turns > 0 && model.costKnownTurns < model.turns)
|
|
538
|
+
if (model.turns > 0 && model.costKnownTurns < model.turns)
|
|
539
|
+
rows.push({ provider: provider.provider, model: model.model });
|
|
539
540
|
}
|
|
540
541
|
}
|
|
541
542
|
return rows.sort((a, b) => a.provider.localeCompare(b.provider) || a.model.localeCompare(b.model));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Who may change worktrees from a chat (the git tool's managed-worktree
|
|
2
|
+
// operations, the daemon's cross-session `worktree` control). A worktree
|
|
3
|
+
// mutation — entering, returning, merging, removing, pruning, `git worktree
|
|
4
|
+
// add/remove`, a snapshot — runs only in a conversation session: a Lead
|
|
5
|
+
// session of the desktop or TUI, or a bot's chat. Unattended runs (schedules,
|
|
6
|
+
// webhooks, routines, room seats) are refused by the run's trusted identity;
|
|
7
|
+
// delegated workers have no worktree host at all. Listing stays open.
|
|
8
|
+
//
|
|
9
|
+
// The scope is the session-level caller scope (schedule-access.mjs
|
|
10
|
+
// scheduleCallerScope: the session's provenance and its unattended-run mark),
|
|
11
|
+
// never anything the model or a message supplies.
|
|
12
|
+
import { scheduleCallerScope } from './schedule-access.mjs';
|
|
13
|
+
|
|
14
|
+
/** `{ kind, agentId?, unattended?, attended }` of a calling session record. */
|
|
15
|
+
export function worktreeCallerScope(session) {
|
|
16
|
+
const scope = scheduleCallerScope(session);
|
|
17
|
+
const attended = (scope.kind === 'human' || scope.kind === 'agent') && scope.unattended !== true;
|
|
18
|
+
return { ...scope, attended };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Throws unless `scope` (worktreeCallerScope) may change worktrees; `what` names the refused action. */
|
|
22
|
+
export function assertWorktreeMutationAllowed(scope, what) {
|
|
23
|
+
if (scope?.attended === true) return;
|
|
24
|
+
throw new Error(
|
|
25
|
+
`${what} changes worktrees only in a conversation session (a Lead session or a bot chat); schedule, webhook, routine and room runs may only list them`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// event, and the optional WS transport prewarm.
|
|
4
4
|
import { deferredSurfaceModeForLead } from '../../runtime/agent/orchestrator/runtime-core/effort.mjs';
|
|
5
5
|
import { filterMcpToolsForSession } from '../../runtime/agent/orchestrator/runtime-core/extension-scopes.mjs';
|
|
6
|
-
import { attachSessionHooks } from '../session-hooks.mjs';
|
|
7
6
|
import { applyDeferredToolSurface } from '../../runtime/agent/orchestrator/runtime-core/tool-catalog.mjs';
|
|
8
7
|
import { writeStatuslineRoute } from '../statusline-route.mjs';
|
|
9
8
|
import { sessionOptions } from './session-options.mjs';
|
|
@@ -42,10 +41,10 @@ function seedToolSurface(deps, reason) {
|
|
|
42
41
|
|
|
43
42
|
/** Adopt the provider session and publish it to hooks and statusline. */
|
|
44
43
|
export function materializeSession(deps, reason, coreMemoryContext) {
|
|
45
|
-
const { rt, adoptSession, mgr, hooks,
|
|
44
|
+
const { rt, adoptSession, mgr, hooks, statusRoutes } = deps;
|
|
45
|
+
// adoptSession attaches the hook bridge (boot/infrastructure.mjs sessionAdopter).
|
|
46
46
|
adoptSession(mgr.createSession(sessionOptions(deps, coreMemoryContext)));
|
|
47
47
|
rt.reservedSessionId = null;
|
|
48
|
-
attachSessionHooks(rt.session, { hooks, hookCommonPayload, getCwd: () => rt.currentCwd });
|
|
49
48
|
seedToolSurface(deps, reason);
|
|
50
49
|
writeStatuslineRoute(statusRoutes, rt.session, rt.route);
|
|
51
50
|
hooks.emit('session:create', {
|
|
@@ -9,7 +9,20 @@ import { readAgentFrontmatterPermission } from '../services/agent-tool/helpers.m
|
|
|
9
9
|
import { LEAD_DISALLOWED_TOOLS } from '../../runtime/agent/orchestrator/runtime-core/tool-defs.mjs';
|
|
10
10
|
import { HEADLESS_TOOL_PROFILE } from '../../runtime/agent/orchestrator/runtime-core/tool-profile.mjs';
|
|
11
11
|
import { AGENT_MODE, resolveSessionMode } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
|
|
12
|
-
import { MIXY_AGENT_ID } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
12
|
+
import { MIXY_AGENT_ID, agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
13
|
+
import { roomMemberOfSession } from '../../runtime/agent/orchestrator/session/agent-room.mjs';
|
|
14
|
+
import { unattendedApprovalPort } from '../../runtime/agent/orchestrator/session/human-gate/gate.mjs';
|
|
15
|
+
|
|
16
|
+
/** Where a bot created its task session, recorded after its id in the
|
|
17
|
+
* session's `sourceName` (`agent:<id>@home|room|run`): the desktop lets the
|
|
18
|
+
* task act as the bot (its standing allows, "always allow") only when it came
|
|
19
|
+
* from the bot's own attended chat. None when the origin is anything else. */
|
|
20
|
+
function taskOriginSuffix(taskOrigin) {
|
|
21
|
+
const from = clean(taskOrigin?.sessionId);
|
|
22
|
+
if (roomMemberOfSession(from)) return '@room';
|
|
23
|
+
if (unattendedApprovalPort()?.runOf?.(from)) return '@run';
|
|
24
|
+
return agentIdOfHomeSession(from) === clean(taskOrigin?.agentId) ? '@home' : '';
|
|
25
|
+
}
|
|
13
26
|
|
|
14
27
|
// Ownership and permission fields an agent-owned session inherits from its profile.
|
|
15
28
|
function agentOwnedSessionFields(sessionProfile) {
|
|
@@ -83,7 +96,7 @@ export function sessionOptions(deps, coreMemoryContext) {
|
|
|
83
96
|
sourceName: agentOwned
|
|
84
97
|
? sessionProfile?.sourceName || sessionProfile?.agent || 'agent'
|
|
85
98
|
: taskOrigin
|
|
86
|
-
? `agent:${taskOrigin.agentId}`
|
|
99
|
+
? `agent:${taskOrigin.agentId}${taskOriginSuffix(taskOrigin)}`
|
|
87
100
|
: 'main',
|
|
88
101
|
...(taskOrigin ? { taskOrigin } : {}),
|
|
89
102
|
...(rt.approvalMode ? { approvalMode: rt.approvalMode } : {}),
|
|
@@ -5,9 +5,6 @@
|
|
|
5
5
|
// facade's hookCommonPayload / currentCwd accessor + the session itself. All
|
|
6
6
|
// properties are non-enumerable/configurable/writable so the loop/manager can
|
|
7
7
|
// read them by name without changing session enumeration.
|
|
8
|
-
import { roomMemberOfSession } from '../runtime/agent/orchestrator/session/agent-room.mjs';
|
|
9
|
-
import { roomMemberToolDecision } from './room-member-gate.mjs';
|
|
10
|
-
|
|
11
8
|
export function attachSessionHooks(session, { hooks, hookCommonPayload, getCwd }) {
|
|
12
9
|
const identity = (input) => ({
|
|
13
10
|
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
@@ -28,26 +25,21 @@ export function attachSessionHooks(session, { hooks, hookCommonPayload, getCwd }
|
|
|
28
25
|
// rejection cannot escape the tool loop or the compaction flow.
|
|
29
26
|
const dispatcher = (event, payload) => (input) => hooks.dispatch(event, hookCommonPayload(payload(input)));
|
|
30
27
|
|
|
31
|
-
// PreToolUse bridge. A group-room member
|
|
32
|
-
//
|
|
33
|
-
define('beforeToolHook', async (input, options = {}) =>
|
|
34
|
-
|
|
35
|
-
const args = input?.args || input?.tool_input;
|
|
36
|
-
const cwd = input?.cwd || getCwd();
|
|
37
|
-
const decision = await hooks.beforeTool(
|
|
28
|
+
// PreToolUse bridge. A group-room member follows the same rules as its
|
|
29
|
+
// agent's home thread: no room-only approval on top.
|
|
30
|
+
define('beforeToolHook', async (input, options = {}) =>
|
|
31
|
+
hooks.beforeTool(
|
|
38
32
|
hookCommonPayload({
|
|
39
33
|
...input,
|
|
40
34
|
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
41
|
-
tool_name: name,
|
|
42
|
-
tool_input: args,
|
|
35
|
+
tool_name: input?.name || input?.tool_name,
|
|
36
|
+
tool_input: input?.args || input?.tool_input,
|
|
43
37
|
tool_use_id: input?.toolCallId || input?.tool_use_id,
|
|
44
|
-
cwd,
|
|
38
|
+
cwd: input?.cwd || getCwd(),
|
|
45
39
|
}),
|
|
46
40
|
options
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
return roomMemberToolDecision({ name, args, cwd }, decision);
|
|
50
|
-
});
|
|
41
|
+
)
|
|
42
|
+
);
|
|
51
43
|
// PostToolUse: bridge runtime tool completions to the standard hook bus.
|
|
52
44
|
define('afterToolHook', dispatcher('PostToolUse', toolPayload));
|
|
53
45
|
// PostToolUseFailure: dispatched by loop.mjs only when a tool execution
|