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
|
@@ -6,12 +6,15 @@
|
|
|
6
6
|
* transaction ledger that makes creation rollback and deletion resumable:
|
|
7
7
|
* which resources this transaction created ('pending' is written before a
|
|
8
8
|
* resource is made, 'created' after), the deletion decision and any recovery
|
|
9
|
-
* diagnostics. Writes are atomic (temp file + rename) under a file lock
|
|
10
|
-
*
|
|
9
|
+
* diagnostics. Writes are atomic (temp file + rename) under a file lock and keep
|
|
10
|
+
* the replaced version as registry.json.bak. A damaged registry (NUL, truncated,
|
|
11
|
+
* malformed) never blocks worktree operations: its bytes are kept aside as
|
|
12
|
+
* registry.json.corrupt-<ts>, the last good copy is restored when there is one,
|
|
13
|
+
* and otherwise the registry starts empty (worktree folders on disk are never
|
|
14
|
+
* touched by that).
|
|
11
15
|
*/
|
|
12
|
-
import { readFile } from 'node:fs/promises';
|
|
13
16
|
import { join } from 'node:path';
|
|
14
|
-
import {
|
|
17
|
+
import { readJsonState, readJsonStateSync, updateJsonAtomic } from '../atomic-file.mjs';
|
|
15
18
|
import { isPlainObject } from '../object.mjs';
|
|
16
19
|
import { resolvePluginData } from '../plugin-paths.mjs';
|
|
17
20
|
import { normalizeWorktreeEntry, WORKTREE_STORE_DIR } from './contract.mjs';
|
|
@@ -30,24 +33,21 @@ function emptyDoc() {
|
|
|
30
33
|
return { version: REGISTRY_VERSION, entries: {} };
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
} catch (error) {
|
|
38
|
-
if (error?.code === 'ENOENT') return emptyDoc();
|
|
39
|
-
throw error;
|
|
40
|
-
}
|
|
41
|
-
const value = parseJsonText(text);
|
|
42
|
-
if (!isPlainObject(value) || !isPlainObject(value.entries)) {
|
|
43
|
-
throw new Error(`Worktree registry ${path} is malformed.`);
|
|
44
|
-
}
|
|
36
|
+
const isRegistryDoc = (value) => isPlainObject(value) && isPlainObject(value.entries);
|
|
37
|
+
|
|
38
|
+
function validateDoc(value) {
|
|
39
|
+
if (!isRegistryDoc(value)) throw new Error('Worktree registry is malformed.');
|
|
45
40
|
return value;
|
|
46
41
|
}
|
|
47
42
|
|
|
48
43
|
/** Snapshot of every record (plain clones). */
|
|
49
44
|
export async function readRegistry() {
|
|
50
|
-
return
|
|
45
|
+
return (await readJsonState(registryPath(), { validate: validateDoc })) ?? emptyDoc();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** readRegistry for synchronous callers (the workspace admission gate). */
|
|
49
|
+
export function readRegistrySync() {
|
|
50
|
+
return readJsonStateSync(registryPath(), { validate: validateDoc }) ?? emptyDoc();
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
@@ -58,17 +58,17 @@ export async function readRegistry() {
|
|
|
58
58
|
* @returns {Promise<T>}
|
|
59
59
|
*/
|
|
60
60
|
export async function mutateRegistry(mutate) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const doc =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return result;
|
|
61
|
+
let result;
|
|
62
|
+
await updateJsonAtomic(
|
|
63
|
+
registryPath(),
|
|
64
|
+
(current) => {
|
|
65
|
+
const doc = isRegistryDoc(current) ? current : emptyDoc();
|
|
66
|
+
result = mutate(doc);
|
|
67
|
+
return doc;
|
|
69
68
|
},
|
|
70
|
-
{ timeoutMs: 15_000 }
|
|
69
|
+
{ timeoutMs: 15_000, backup: true }
|
|
71
70
|
);
|
|
71
|
+
return result;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export async function getRecord(id) {
|
|
@@ -76,6 +76,11 @@ function powerShellHost(env) {
|
|
|
76
76
|
return false;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
function coreInstallable(id, manifest, env) {
|
|
80
|
+
if (!TIDY_CORE_ENGINE_IDS.includes(id) || !manifestAsset(manifest, id)) return false;
|
|
81
|
+
return id !== 'psscriptanalyzer' || powerShellHost(env);
|
|
82
|
+
}
|
|
83
|
+
|
|
79
84
|
let installJob = null;
|
|
80
85
|
let installInFlight = null;
|
|
81
86
|
// Bumped on every job mutation and every refreshed host-module probe, so the
|
|
@@ -118,6 +123,14 @@ async function cachedHostModuleProbe(engine) {
|
|
|
118
123
|
return entry?.version || '';
|
|
119
124
|
}
|
|
120
125
|
|
|
126
|
+
/** A host-module engine (PSScriptAnalyzer) whose host exists but whose first
|
|
127
|
+
* probe has not answered yet. Until then "module missing" only means "not
|
|
128
|
+
* looked at yet", so the status reports it as pending instead. */
|
|
129
|
+
function hostModuleProbing(catalog, engine) {
|
|
130
|
+
if (!catalog.managedModule || engine.source !== 'missing' || !engine.command) return false;
|
|
131
|
+
return (hostModuleCache.get(String(engine.command))?.at || 0) === 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
121
134
|
function clampPercent(value) {
|
|
122
135
|
return Math.max(0, Math.min(100, Math.round(value)));
|
|
123
136
|
}
|
|
@@ -222,14 +235,17 @@ async function runCoreInstall({
|
|
|
222
235
|
signal = null,
|
|
223
236
|
installEngines = installEnginesImpl,
|
|
224
237
|
resolveEngines = resolveEnginesImpl,
|
|
238
|
+
engines: only = null,
|
|
225
239
|
} = {}) {
|
|
226
240
|
const loaded = manifest || readEnginesManifest();
|
|
227
241
|
const toolsDir = pluginData ? managedToolsDir(pluginData) : '';
|
|
228
|
-
|
|
242
|
+
// A retry for named engines installs just those; the default is the set.
|
|
243
|
+
const wanted = Array.isArray(only) ? TIDY_CORE_ENGINE_IDS.filter((id) => only.includes(id)) : TIDY_CORE_ENGINE_IDS;
|
|
244
|
+
const job = startJob(wanted);
|
|
229
245
|
try {
|
|
230
246
|
const resolution = await resolveEngines({
|
|
231
247
|
cwd: resolutionScope(toolsDir),
|
|
232
|
-
engineIds: [...
|
|
248
|
+
engineIds: [...wanted],
|
|
233
249
|
pluginData,
|
|
234
250
|
manifest: loaded,
|
|
235
251
|
env,
|
|
@@ -238,7 +254,7 @@ async function runCoreInstall({
|
|
|
238
254
|
});
|
|
239
255
|
const resolved = new Map((resolution.engines || []).map((engine) => [engine.id, engine]));
|
|
240
256
|
const pending = [];
|
|
241
|
-
for (const id of
|
|
257
|
+
for (const id of wanted) {
|
|
242
258
|
const catalog = ENGINE_CATALOG[id];
|
|
243
259
|
const engine = resolved.get(id);
|
|
244
260
|
if (id === 'psscriptanalyzer' && !powerShellHost(env)) {
|
|
@@ -400,6 +416,7 @@ function withInstallStatus(inventory) {
|
|
|
400
416
|
toolsDir: inventory.toolsDir,
|
|
401
417
|
core: [...inventory.core],
|
|
402
418
|
engines: inventory.engines.map((engine) => ({ ...engine })),
|
|
419
|
+
probing: inventory.probing,
|
|
403
420
|
installing: tidyInstallStatus(),
|
|
404
421
|
};
|
|
405
422
|
}
|
|
@@ -424,6 +441,7 @@ async function buildEngineInventory({ pluginData, manifest, env, probeVersions,
|
|
|
424
441
|
const source = statusSource(engine.source);
|
|
425
442
|
const version = engine.version || '';
|
|
426
443
|
const installHint = engine.installHint || catalog.installHint || '';
|
|
444
|
+
const probing = hostModuleProbing(catalog, engine);
|
|
427
445
|
return {
|
|
428
446
|
id,
|
|
429
447
|
title: catalog.title || id,
|
|
@@ -437,7 +455,11 @@ async function buildEngineInventory({ pluginData, manifest, env, probeVersions,
|
|
|
437
455
|
// Managed engines carry their on-disk cost; a host binary is the user's.
|
|
438
456
|
...(source === 'managed' ? { bytes: managedEngineBytes(pluginData, id, version) } : {}),
|
|
439
457
|
...(source === 'missing' && installHint ? { installHint } : {}),
|
|
458
|
+
// The host probe has not answered: pending, neither installed nor missing.
|
|
459
|
+
...(probing ? { probing: true } : {}),
|
|
460
|
+
// A missing core engine the Install/Retry control can fetch right now.
|
|
461
|
+
...(source === 'missing' && !probing && coreInstallable(id, loaded, env) ? { installable: true } : {}),
|
|
440
462
|
};
|
|
441
463
|
});
|
|
442
|
-
return { toolsDir, core: [...TIDY_CORE_ENGINE_IDS], engines };
|
|
464
|
+
return { toolsDir, core: [...TIDY_CORE_ENGINE_IDS], engines, probing: engines.some((engine) => engine.probing) };
|
|
443
465
|
}
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
// Policy gating happens BEFORE any network call: 'never' refuses, 'ask' returns
|
|
5
5
|
// needsApproval unless the call carried approveDownloads:true, 'auto' proceeds.
|
|
6
6
|
// Toolchain engines (rustfmt, gofmt, zig fmt, ...) are never downloadable.
|
|
7
|
-
import { chmodSync, existsSync, mkdirSync, renameSync, rmSync, statSync } from 'node:fs';
|
|
7
|
+
import { chmodSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync, statSync } from 'node:fs';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
import { MAX_NATIVE_BINARY_DOWNLOAD_BYTES, streamResponseToFile } from '../shared/bounded-download.mjs';
|
|
11
11
|
import { platformEntryKey, platformKey, sha256File } from '../shared/native-asset.mjs';
|
|
12
|
+
import { fileHasData } from '../shared/file-has-data.mjs';
|
|
12
13
|
import { readJsonSafe } from '../shared/json-file.mjs';
|
|
13
14
|
import { ENGINE_CATALOG } from './engines.mjs';
|
|
14
15
|
import { extractArchive } from './extract.mjs';
|
|
@@ -51,7 +52,7 @@ export function managedEngineBinary({ id, manifest, pluginData }) {
|
|
|
51
52
|
const binPath = String(found.asset.binPath || '');
|
|
52
53
|
if (!binPath) return null;
|
|
53
54
|
const full = join(managedEngineDir(pluginData, id, found.version), binPath);
|
|
54
|
-
return
|
|
55
|
+
return fileHasData(full) ? { path: full, version: found.version } : null;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
/** Throws unless `filePath` hashes to `expected`. */
|
|
@@ -148,44 +149,109 @@ export function planInstall({ ids = [], manifest, pluginData = '', policy = 'aut
|
|
|
148
149
|
return { targets, present, errors, needsApproval: null };
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
// A network switch can leave a socket open that never delivers another byte;
|
|
153
|
+
// without a deadline the install (and the single in-flight job behind it)
|
|
154
|
+
// would wait forever.
|
|
155
|
+
const DEFAULT_STALL_TIMEOUT_MS = 60_000;
|
|
156
|
+
// A `.tmp-<pid>-<ms>-…` staging dir whose owner crashed is never cleaned by
|
|
157
|
+
// that owner; an hour is far beyond any live download.
|
|
158
|
+
const STALE_TMP_AGE_MS = 60 * 60 * 1000;
|
|
159
|
+
|
|
160
|
+
function pidAlive(pid) {
|
|
161
|
+
try {
|
|
162
|
+
process.kill(pid, 0);
|
|
163
|
+
return true;
|
|
164
|
+
} catch (error) {
|
|
165
|
+
return error?.code === 'EPERM';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Remove staging dirs a killed install left behind (dead owner, or ancient). */
|
|
170
|
+
function reclaimStaleStaging(engineRoot) {
|
|
171
|
+
let names;
|
|
172
|
+
try {
|
|
173
|
+
names = readdirSync(engineRoot);
|
|
174
|
+
} catch {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
for (const name of names) {
|
|
178
|
+
const match = /^\.tmp-(\d+)-(\d+)-/.exec(name);
|
|
179
|
+
if (!match) continue;
|
|
180
|
+
const pid = Number(match[1]);
|
|
181
|
+
const ownerGone = pid !== process.pid && !pidAlive(pid);
|
|
182
|
+
if (!ownerGone && Date.now() - Number(match[2]) < STALE_TMP_AGE_MS) continue;
|
|
183
|
+
try {
|
|
184
|
+
rmSync(join(engineRoot, name), { recursive: true, force: true });
|
|
185
|
+
} catch {
|
|
186
|
+
/* best-effort */
|
|
187
|
+
}
|
|
156
188
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async function downloadAsset(target, tmpDir, fetchFn, signal, onProgress, stallTimeoutMs) {
|
|
192
|
+
const archiveFile = join(tmpDir, `asset-${target.id}`);
|
|
193
|
+
const stalled = new AbortController();
|
|
194
|
+
const merged = signal ? AbortSignal.any([signal, stalled.signal]) : stalled.signal;
|
|
195
|
+
let timer;
|
|
196
|
+
const arm = () => {
|
|
197
|
+
clearTimeout(timer);
|
|
198
|
+
timer = setTimeout(() => stalled.abort(), stallTimeoutMs);
|
|
199
|
+
};
|
|
200
|
+
arm();
|
|
201
|
+
try {
|
|
202
|
+
const response = await fetchFn(target.url, { signal: merged, redirect: 'follow' });
|
|
203
|
+
if (!response?.ok) {
|
|
204
|
+
throw new Error(`${LABEL} ${target.id}: HTTP ${response?.status || 0} for ${target.url}`);
|
|
205
|
+
}
|
|
206
|
+
await streamResponseToFile(response, archiveFile, {
|
|
207
|
+
maxBytes: MAX_NATIVE_BINARY_DOWNLOAD_BYTES,
|
|
208
|
+
label: `${LABEL} ${target.id}`,
|
|
209
|
+
signal: merged,
|
|
210
|
+
// Byte progress per engine: the desktop card renders it live, so the
|
|
211
|
+
// callback carries the engine id the bytes belong to. Any bytes also
|
|
212
|
+
// prove the connection is alive.
|
|
213
|
+
onProgress: ({ downloaded, total }) => {
|
|
214
|
+
arm();
|
|
215
|
+
if (typeof onProgress === 'function') {
|
|
216
|
+
onProgress({ id: target.id, receivedBytes: downloaded, totalBytes: total });
|
|
167
217
|
}
|
|
168
|
-
|
|
169
|
-
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
} catch (error) {
|
|
221
|
+
if (stalled.signal.aborted && !signal?.aborted) {
|
|
222
|
+
throw new Error(`${LABEL} ${target.id}: download stalled (no data for ${stallTimeoutMs / 1000}s)`);
|
|
223
|
+
}
|
|
224
|
+
throw error;
|
|
225
|
+
} finally {
|
|
226
|
+
clearTimeout(timer);
|
|
227
|
+
}
|
|
170
228
|
return archiveFile;
|
|
171
229
|
}
|
|
172
230
|
|
|
173
231
|
/** Download + verify + extract one engine into its versioned managed dir. */
|
|
174
232
|
export async function installEngine(
|
|
175
233
|
target,
|
|
176
|
-
{
|
|
234
|
+
{
|
|
235
|
+
pluginData,
|
|
236
|
+
fetchFn = globalThis.fetch,
|
|
237
|
+
signal = null,
|
|
238
|
+
onProgress = null,
|
|
239
|
+
stallTimeoutMs = DEFAULT_STALL_TIMEOUT_MS,
|
|
240
|
+
} = {}
|
|
177
241
|
) {
|
|
178
242
|
const engineRoot = join(managedToolsDir(pluginData), target.id);
|
|
179
243
|
const finalDir = managedEngineDir(pluginData, target.id, target.version);
|
|
180
244
|
const binFull = join(finalDir, target.binPath);
|
|
181
|
-
|
|
245
|
+
// An engine binary a crash left NUL-filled is not present: it is installed again.
|
|
246
|
+
if (fileHasData(binFull)) {
|
|
182
247
|
return { id: target.id, version: target.version, path: binFull, bytes: 0, status: 'present' };
|
|
183
248
|
}
|
|
184
249
|
mkdirSync(engineRoot, { recursive: true });
|
|
250
|
+
reclaimStaleStaging(engineRoot);
|
|
185
251
|
const tmpDir = join(engineRoot, `.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
186
252
|
mkdirSync(tmpDir, { recursive: true });
|
|
187
253
|
try {
|
|
188
|
-
const archiveFile = await downloadAsset(target, tmpDir, fetchFn, signal, onProgress);
|
|
254
|
+
const archiveFile = await downloadAsset(target, tmpDir, fetchFn, signal, onProgress, stallTimeoutMs);
|
|
189
255
|
await verifyDownloadDigest(archiveFile, target.sha256);
|
|
190
256
|
const bytes = statSync(archiveFile).size;
|
|
191
257
|
const stageDir = join(tmpDir, 'stage');
|
|
@@ -207,6 +273,7 @@ export async function installEngine(
|
|
|
207
273
|
}
|
|
208
274
|
}
|
|
209
275
|
try {
|
|
276
|
+
if (existsSync(finalDir) && !fileHasData(binFull)) rmSync(finalDir, { recursive: true, force: true });
|
|
210
277
|
renameSync(stageDir, finalDir);
|
|
211
278
|
} catch (error) {
|
|
212
279
|
// A concurrent install won the race; its verified copy is equivalent.
|
|
@@ -235,6 +302,7 @@ export async function installEngines({
|
|
|
235
302
|
fetchFn = globalThis.fetch,
|
|
236
303
|
signal = null,
|
|
237
304
|
onProgress = null,
|
|
305
|
+
stallTimeoutMs = undefined,
|
|
238
306
|
} = {}) {
|
|
239
307
|
const loaded = manifest || readEnginesManifest();
|
|
240
308
|
const plan = planInstall({ ids, manifest: loaded, pluginData, policy, approveDownloads });
|
|
@@ -249,7 +317,7 @@ export async function installEngines({
|
|
|
249
317
|
}
|
|
250
318
|
for (const target of plan.targets) {
|
|
251
319
|
try {
|
|
252
|
-
installed.push(await installEngine(target, { pluginData, fetchFn, signal, onProgress }));
|
|
320
|
+
installed.push(await installEngine(target, { pluginData, fetchFn, signal, onProgress, stallTimeoutMs }));
|
|
253
321
|
} catch (error) {
|
|
254
322
|
errors.push({ id: target.id, error: error?.message || String(error) });
|
|
255
323
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { resolvePluginData } from '../../shared/plugin-paths.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { readJsonStateSync, writeJsonAtomicSync } from '../../shared/atomic-file.mjs';
|
|
5
5
|
|
|
6
6
|
// Unified mode: web search shares the plugin data dir with the rest of mixdog.
|
|
7
7
|
const SHARED_DATA_DIR = resolvePluginData();
|
|
@@ -19,22 +19,10 @@ export function ensureDataDir() {
|
|
|
19
19
|
fs.mkdirSync(DATA_DIR, { recursive: true });
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// usage/cache state: a damaged file (empty, NUL-filled, truncated) is kept as
|
|
23
|
+
// <file>.corrupt-<ts> and reads as `fallback`, so search/fetch keep working.
|
|
22
24
|
export function readJson(filePath, fallback) {
|
|
23
|
-
|
|
24
|
-
const raw = fs.readFileSync(filePath, 'utf8');
|
|
25
|
-
try {
|
|
26
|
-
return JSON.parse(raw);
|
|
27
|
-
} catch (parseErr) {
|
|
28
|
-
try {
|
|
29
|
-
renameWithRetrySync(filePath, `${filePath}.corrupt.${Date.now()}`);
|
|
30
|
-
} catch {}
|
|
31
|
-
process.stderr.write(`[web-search-config] corrupt JSON backed up: ${filePath}\n`);
|
|
32
|
-
throw parseErr;
|
|
33
|
-
}
|
|
34
|
-
} catch (err) {
|
|
35
|
-
if (err.code === 'ENOENT') return fallback;
|
|
36
|
-
throw err;
|
|
37
|
-
}
|
|
25
|
+
return readJsonStateSync(filePath, { fallback });
|
|
38
26
|
}
|
|
39
27
|
|
|
40
28
|
export function writeJson(filePath, value) {
|