mixdog 1.3.0 → 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/NOTICE.md +52 -9
- package/README.md +8 -4
- package/package.json +2 -2
- package/scripts/native-release-status.mjs +238 -0
- package/src/defaults/shipped-history.json +8 -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 +54 -4
- package/src/defaults/skills/setup/references/surfaces.md +23 -3
- package/src/defaults/skills/setup-guide/SKILL.md +17 -10
- 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/output-styles/common.md +13 -8
- package/src/rules/agent-mode/AGENT_MODE.md +9 -6
- package/src/rules/agent-mode/MIXY.md +11 -6
- 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 +81 -16
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -4
- 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-oauth-catalog.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +34 -16
- 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 +19 -1
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -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-retry-profile.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +10 -2
- 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-responses-input.mjs +3 -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/provider-error-kind.mjs +14 -2
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -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 +5 -5
- 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 +17 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +41 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +6 -4
- 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 +21 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +149 -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/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 +156 -25
- 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/loop-state.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +111 -9
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -14
- 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/loop/usage.mjs +46 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
- 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/provider-replay.mjs +50 -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-lifecycle.mjs +62 -47
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +6 -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-checkpoint.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +5 -2
- 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 +35 -4
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +179 -16
- 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 +49 -14
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +134 -17
- 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 +55 -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 +6 -3
- package/src/runtime/effort-judge/model-install.mjs +16 -8
- package/src/runtime/effort-judge/model-manifest.json +7 -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/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-kind.mjs +152 -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-route-config.d.mts +1 -0
- package/src/runtime/shared/agent-route-config.mjs +22 -8
- package/src/runtime/shared/agent-store.mjs +149 -0
- 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 +457 -0
- package/src/runtime/shared/bounded-download.mjs +4 -2
- package/src/runtime/shared/config-patch.mjs +20 -1
- package/src/runtime/shared/config.mjs +39 -9
- package/src/runtime/shared/connector-catalog.d.mts +1 -2
- package/src/runtime/shared/connector-catalog.mjs +2 -4
- package/src/runtime/shared/connector-triggers.mjs +2 -0
- 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 +7 -1
- package/src/runtime/shared/error-presentation.mjs +113 -10
- package/src/runtime/shared/file-has-data.mjs +28 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
- package/src/runtime/shared/handoff-artifacts.mjs +61 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
- package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
- package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
- package/src/runtime/shared/model-route-fallback.mjs +79 -7
- package/src/runtime/shared/pending-agent-work.mjs +54 -0
- package/src/runtime/shared/plain-preview.mjs +22 -17
- 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/sensitive-path-rules.d.mts +15 -0
- package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
- 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/usage-readout-totals.mjs +15 -13
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +46 -44
- 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 +859 -136
- package/src/session-runtime/agent-room-delivery.mjs +167 -19
- package/src/session-runtime/agent-task-sessions.mjs +831 -69
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +58 -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 +16 -6
- 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 +78 -32
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/handoff-attachments.mjs +593 -0
- 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 +45 -6
- 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-persist.mjs +2 -2
- package/src/session-runtime/model-route/route-tuning.mjs +11 -2
- package/src/session-runtime/model-route/set-route.mjs +82 -2
- package/src/session-runtime/native-web-search.mjs +2 -2
- package/src/session-runtime/new-session-config.mjs +6 -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 +21 -19
- 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/helpers.mjs +24 -5
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +36 -24
- 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 +12 -6
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- 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 +20 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +19 -7
- package/src/session-runtime/setup-tool/settings-contract.mjs +37 -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 -358
- package/src/session-runtime/tool-surface.mjs +5 -3
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +99 -81
- 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 +578 -301
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +113 -53
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
- 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 +60 -11
- package/src/standalone/daemon.mjs +34 -4
- 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/agent-tree/agent-turns.mjs +46 -3
- package/src/standalone/session-service/agent-tree.mjs +4 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +19 -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 +599 -342
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/notice-surface.mjs +3 -4
- 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 -236
- 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 +4 -0
- package/src/tui/session/turn-live-call.mjs +11 -3
- package/src/tui/session/turn.mjs +36 -17
- 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
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Which Lead sessions still wait on agent work they handed off: the rule the
|
|
2
|
+
// desktop turn notifier applies to the agent pool (apps/desktop
|
|
3
|
+
// shared/agent-activity.ts isActiveDesktopAgentEntry /
|
|
4
|
+
// isCancelUnconfirmedDesktopAgentEntry, main/push-turn-events.ts
|
|
5
|
+
// sessionsWithPendingWork), ported for the runtime so a bot's task-session
|
|
6
|
+
// report waits for the same final answer the desktop notifies. Pool rows are
|
|
7
|
+
// listStoredAgentWorkersAsync rows (`sessionId`, root `ownerSessionId`,
|
|
8
|
+
// `status`, `stage`); nested descendants keep the Lead as their owner.
|
|
9
|
+
|
|
10
|
+
const TERMINAL_STATUS = /idle|done|complete|success|closed|error|fail|cancel|killed|timeout/i;
|
|
11
|
+
const ACTIVE_STATUS =
|
|
12
|
+
/^(?:connecting|requesting|streaming|tool[-_\s]?running|running|queued|pending|starting|resource_wait)$/i;
|
|
13
|
+
const CANCELLED_STATUS = /cancel|killed|aborted|interrupted/i;
|
|
14
|
+
const CANCEL_UNCONFIRMED_STATUS = /cancel[-_\s]?(?:unconfirmed|pending)|cancell?ing/i;
|
|
15
|
+
|
|
16
|
+
const record = (value) => (value && typeof value === 'object' && !Array.isArray(value) ? value : {});
|
|
17
|
+
|
|
18
|
+
function statusValues(value) {
|
|
19
|
+
const entry = record(value);
|
|
20
|
+
return [entry.stage, entry.status]
|
|
21
|
+
.map((status) => String(status || '').trim())
|
|
22
|
+
.filter((status, index, values) => Boolean(status) && values.indexOf(status) === index);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** A running or queued row: `status` decides, `stage` only for a row without one. */
|
|
26
|
+
function isActiveAgentRow(value) {
|
|
27
|
+
const statuses = statusValues(value);
|
|
28
|
+
if (statuses.length === 0 || statuses.some((status) => CANCELLED_STATUS.test(status))) return false;
|
|
29
|
+
const lifecycle = String(record(value).status || '').trim() || statuses[0];
|
|
30
|
+
return !TERMINAL_STATUS.test(lifecycle) && ACTIVE_STATUS.test(lifecycle);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** A cancel whose stop is not proven yet. */
|
|
34
|
+
function isCancelUnconfirmedAgentRow(value) {
|
|
35
|
+
return statusValues(value).some((status) => CANCEL_UNCONFIRMED_STATUS.test(status));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Agent work still in flight on one pool row. */
|
|
39
|
+
export function hasPendingAgentWork(value) {
|
|
40
|
+
return isActiveAgentRow(value) || isCancelUnconfirmedAgentRow(value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The owner (Lead) session ids with a child row still in flight. The Lead's
|
|
44
|
+
* own row is skipped: its turn state comes from the session itself. */
|
|
45
|
+
export function sessionsWithPendingWork(rows) {
|
|
46
|
+
const pending = new Set();
|
|
47
|
+
for (const row of Array.isArray(rows) ? rows : []) {
|
|
48
|
+
const sessionId = String(row?.sessionId || '');
|
|
49
|
+
const ownerSessionId = String(row?.ownerSessionId || '') || sessionId;
|
|
50
|
+
if (!ownerSessionId || sessionId === ownerSessionId) continue;
|
|
51
|
+
if (hasPendingAgentWork(row)) pending.add(ownerSessionId);
|
|
52
|
+
}
|
|
53
|
+
return pending;
|
|
54
|
+
}
|
|
@@ -5,23 +5,28 @@
|
|
|
5
5
|
/** `text` without markdown syntax, whitespace folded to single spaces. */
|
|
6
6
|
export function plainPreviewText(text) {
|
|
7
7
|
// HTML comments never show in markdown (a greeting's suggestions ride one).
|
|
8
|
-
return
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
8
|
+
return (
|
|
9
|
+
String(text ?? '')
|
|
10
|
+
.replace(/<!--[\s\S]*?(?:-->|$)/g, ' ')
|
|
11
|
+
.replace(/^[ \t]*(`{3,}|~{3,})[^\n]*$/gm, ' ')
|
|
12
|
+
.replace(/!\[([^\]]*)\]\([^)]*\)/g, '$1')
|
|
13
|
+
.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1')
|
|
14
|
+
.replace(/^[ \t]{0,3}#{1,6}[ \t]+/gm, '')
|
|
15
|
+
.replace(/^[ \t]*>[ \t]?/gm, '')
|
|
16
|
+
.replace(/^[ \t]*(?:[-*+]|\d+[.)])[ \t]+(?:\[[ xX]\][ \t]+)?/gm, '')
|
|
17
|
+
.replace(/^[ \t]*(?:[-*_][ \t]*){3,}$/gm, ' ')
|
|
18
|
+
.replace(/(\*\*|__)(?=\S)([\s\S]*?\S)\1/g, '$2')
|
|
19
|
+
.replace(/(^|[^\w*])\*(?=\S)([^*\n]*?\S)\*(?!\w)/g, '$1$2')
|
|
20
|
+
.replace(/(^|[^\w_])_(?=\S)([^_\n]*?\S)_(?!\w)/g, '$1$2')
|
|
21
|
+
.replace(/~~(?=\S)([\s\S]*?\S)~~/g, '$1')
|
|
22
|
+
.replace(/`+([^`\n]*)`+/g, '$1')
|
|
23
|
+
.replace(/\s+/g, ' ')
|
|
24
|
+
// A summary stored before newlines were kept already folded its list: a
|
|
25
|
+
// dash or bullet right after a sentence end is a marker, not a hyphen.
|
|
26
|
+
.replace(/([.!?。…::])\s[-*+•]\s+(?=\S)/g, '$1 ')
|
|
27
|
+
.trim()
|
|
28
|
+
.slice(0, PREVIEW_CAP)
|
|
29
|
+
);
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
/** A safety cap only: the row clamps the shown text to two lines. */
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
closeSync,
|
|
3
3
|
existsSync,
|
|
4
|
-
fsyncSync,
|
|
5
4
|
mkdirSync,
|
|
6
5
|
openSync,
|
|
7
6
|
readFileSync,
|
|
@@ -15,7 +14,7 @@ import {
|
|
|
15
14
|
import { join } from 'node:path';
|
|
16
15
|
import { execFile } from 'node:child_process';
|
|
17
16
|
import { isDeepStrictEqual, promisify } from 'node:util';
|
|
18
|
-
import { withFileLock, withFileLockSync } from './atomic-file.mjs';
|
|
17
|
+
import { withFileLock, withFileLockSync, writeJsonAtomicSync } from './atomic-file.mjs';
|
|
19
18
|
import { resolvePluginData } from './plugin-paths.mjs';
|
|
20
19
|
|
|
21
20
|
const execFileAsync = promisify(execFile);
|
|
@@ -338,24 +337,21 @@ function markerOwned(active) {
|
|
|
338
337
|
function writeMarker(active) {
|
|
339
338
|
try {
|
|
340
339
|
mkdirSync(active.markerDir, { recursive: true, mode: 0o700 });
|
|
341
|
-
|
|
340
|
+
// Flushed through the handle that wrote it: reopening the file read-only to
|
|
341
|
+
// fsync it is refused on Windows (EPERM), which reported a failure after
|
|
342
|
+
// the marker was already written.
|
|
343
|
+
writeJsonAtomicSync(
|
|
342
344
|
active.markerPath,
|
|
343
|
-
|
|
345
|
+
{
|
|
344
346
|
version: 1,
|
|
345
347
|
timestamp: new Date().toISOString(),
|
|
346
348
|
pid: process.pid,
|
|
347
349
|
ppid: process.ppid,
|
|
348
350
|
token: active.token,
|
|
349
351
|
processIdentity: active.processIdentity,
|
|
350
|
-
}
|
|
351
|
-
{
|
|
352
|
+
},
|
|
353
|
+
{ compact: true, mode: 0o600 }
|
|
352
354
|
);
|
|
353
|
-
const fd = openSync(active.markerPath, 'r');
|
|
354
|
-
try {
|
|
355
|
-
fsyncSync(fd);
|
|
356
|
-
} finally {
|
|
357
|
-
closeSync(fd);
|
|
358
|
-
}
|
|
359
355
|
return true;
|
|
360
356
|
} catch {
|
|
361
357
|
return false;
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* Data shape: { projects: [{ name, path, addedAt, lastSelectedAt? }] }
|
|
9
9
|
*/
|
|
10
10
|
import { homedir } from 'node:os';
|
|
11
|
-
import { existsSync, mkdirSync, readFileSync,
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, statSync } from 'node:fs';
|
|
12
12
|
import { basename, isAbsolute, join, resolve } from 'node:path';
|
|
13
|
-
import {
|
|
13
|
+
import { holdsNoData, readJsonStateSync, updateJsonAtomicSync, writeFileAtomicSync } from './atomic-file.mjs';
|
|
14
14
|
|
|
15
15
|
const MIXDOG_HOME = process.env.MIXDOG_HOME || join(homedir(), '.mixdog');
|
|
16
16
|
const PROJECTS_FILE = process.env.MIXDOG_PROJECTS_FILE
|
|
@@ -30,47 +30,57 @@ function normalizeKey(absPath) {
|
|
|
30
30
|
return process.platform === 'win32' ? text.replace(/[\\/]+$/, '').toLowerCase() : text.replace(/\/+$/, '');
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// The registry document as a store. A strict read (permission checks and
|
|
34
|
+
// mutations) drops entries without an absolute path: they can never grant
|
|
35
|
+
// anything, and the replaced file survives as projects.json.bak.
|
|
36
|
+
function normalizeStore(parsed, strict) {
|
|
37
|
+
const projects = Array.isArray(parsed?.projects) ? parsed.projects : [];
|
|
38
|
+
return {
|
|
39
|
+
projects: projects
|
|
40
|
+
.filter(
|
|
41
|
+
(entry) => entry && typeof entry.path === 'string' && entry.path.trim() && (!strict || isAbsolute(entry.path))
|
|
42
|
+
)
|
|
43
|
+
.map((entry) => ({
|
|
44
|
+
name: String(entry.name || basename(entry.path) || entry.path),
|
|
45
|
+
path: String(entry.path),
|
|
46
|
+
addedAt: Number(entry.addedAt) || 0,
|
|
47
|
+
...(Number(entry.lastSelectedAt) > 0 ? { lastSelectedAt: Number(entry.lastSelectedAt) } : {}),
|
|
48
|
+
})),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// A damaged registry file (NUL, truncated, malformed) is kept aside as
|
|
53
|
+
// projects.json.corrupt-<ts> and the last good projects.json.bak is restored
|
|
54
|
+
// when there is one, else the registry starts empty: a damaged file never
|
|
55
|
+
// blocks adding, removing or selecting a project. Strict callers still see a
|
|
56
|
+
// real I/O failure (EACCES, EIO) as an error — an unreadable registry is not
|
|
57
|
+
// an empty one; the tolerant listing reads it as empty.
|
|
33
58
|
function readStore(strict = false) {
|
|
34
59
|
try {
|
|
35
|
-
|
|
36
|
-
const raw = readFileSync(PROJECTS_FILE, 'utf8');
|
|
37
|
-
const parsed = JSON.parse(raw);
|
|
38
|
-
if (
|
|
39
|
-
strict &&
|
|
40
|
-
(!Array.isArray(parsed?.projects) ||
|
|
41
|
-
parsed.projects.some(
|
|
42
|
-
(entry) => !entry || typeof entry.path !== 'string' || !entry.path.trim() || !isAbsolute(entry.path)
|
|
43
|
-
))
|
|
44
|
-
)
|
|
45
|
-
throw new TypeError('Project registry is invalid.');
|
|
46
|
-
const projects = Array.isArray(parsed?.projects) ? parsed.projects : [];
|
|
47
|
-
return {
|
|
48
|
-
projects: projects
|
|
49
|
-
.filter((entry) => entry && typeof entry.path === 'string' && entry.path.trim())
|
|
50
|
-
.map((entry) => ({
|
|
51
|
-
name: String(entry.name || basename(entry.path) || entry.path),
|
|
52
|
-
path: String(entry.path),
|
|
53
|
-
addedAt: Number(entry.addedAt) || 0,
|
|
54
|
-
...(Number(entry.lastSelectedAt) > 0 ? { lastSelectedAt: Number(entry.lastSelectedAt) } : {}),
|
|
55
|
-
})),
|
|
56
|
-
};
|
|
60
|
+
return normalizeStore(readJsonStateSync(PROJECTS_FILE), strict);
|
|
57
61
|
} catch (error) {
|
|
58
|
-
if (strict
|
|
62
|
+
if (strict) throw error;
|
|
59
63
|
return { projects: [] };
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
// Serialize the entire read/modify/write across cooperating processes, not
|
|
64
|
-
// just publication
|
|
65
|
-
//
|
|
66
|
-
//
|
|
68
|
+
// just publication: the file is read under the registry lock. Preserve
|
|
69
|
+
// synchronous return values and no-op behavior (an unchanged store is not
|
|
70
|
+
// written); failed reads, lock acquisition and writes propagate. Each write
|
|
71
|
+
// keeps the replaced version as projects.json.bak.
|
|
67
72
|
function mutateStore(mutator) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
let outcome;
|
|
74
|
+
updateJsonAtomicSync(
|
|
75
|
+
PROJECTS_FILE,
|
|
76
|
+
(current) => {
|
|
77
|
+
const store = normalizeStore(current, true);
|
|
78
|
+
outcome = mutator(store);
|
|
79
|
+
return outcome.changed ? store : undefined;
|
|
80
|
+
},
|
|
81
|
+
{ backup: true }
|
|
82
|
+
);
|
|
83
|
+
return outcome.value;
|
|
74
84
|
}
|
|
75
85
|
|
|
76
86
|
/**
|
|
@@ -78,7 +88,8 @@ function mutateStore(mutator) {
|
|
|
78
88
|
* selection store and memory project_id classification (resolveProjectId)
|
|
79
89
|
* agree. Rules:
|
|
80
90
|
* - Never overwrite an existing marker (user may have set 'common' or a
|
|
81
|
-
* custom id — respect it).
|
|
91
|
+
* custom id — respect it). A marker holding no data (empty or NUL, what a
|
|
92
|
+
* crash leaves) is no id: it is rewritten.
|
|
82
93
|
* - Only act when absPath is a real directory on disk; never create the
|
|
83
94
|
* project folder itself (addProject does NOT create the directory).
|
|
84
95
|
* - Marker value = provided name, else basename(absPath). Skip when the
|
|
@@ -97,14 +108,12 @@ function ensureProjectIdMarker(absPath, name) {
|
|
|
97
108
|
return; // missing / unstattable → silently skip
|
|
98
109
|
}
|
|
99
110
|
const markerPath = join(absPath, '.mixdog', 'project.id');
|
|
100
|
-
|
|
111
|
+
const present = existsSync(markerPath);
|
|
112
|
+
if (present && !holdsNoData(readFileSync(markerPath))) return; // preserve existing value
|
|
101
113
|
const value = String(name || basename(absPath) || '').trim();
|
|
102
114
|
if (!value || value.toLowerCase() === 'common') return;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const tmp = `${markerPath}.${process.pid}.tmp`;
|
|
106
|
-
writeFileSync(tmp, `${value}\n`, 'utf8');
|
|
107
|
-
renameSync(tmp, markerPath);
|
|
115
|
+
// A missing marker is created only if still missing (a concurrent creator's wins).
|
|
116
|
+
writeFileAtomicSync(markerPath, `${value}\n`, { createOnly: !present });
|
|
108
117
|
} catch {
|
|
109
118
|
/* best-effort marker; never throw */
|
|
110
119
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
|
-
import {
|
|
3
|
+
import { readJsonStateSync, unsupportedState, updateJsonAtomic } from './atomic-file.mjs';
|
|
5
4
|
import { resolvePluginData } from './plugin-paths.mjs';
|
|
6
5
|
|
|
7
6
|
export const ACCOUNT_PROVIDERS = Object.freeze([
|
|
@@ -34,12 +33,19 @@ function requireAccountId(id) {
|
|
|
34
33
|
|
|
35
34
|
function validate(raw) {
|
|
36
35
|
if (raw == null) return { version: 1, providers: {} };
|
|
36
|
+
// A newer build's roster is left in place: reads see no accounts and writes
|
|
37
|
+
// refuse, so a downgrade never discards it.
|
|
38
|
+
if (Number.isSafeInteger(raw.version) && raw.version > 1) {
|
|
39
|
+
throw unsupportedState(`Provider account settings version ${raw.version} is newer than this build.`);
|
|
40
|
+
}
|
|
37
41
|
if (raw.version !== 1 || !raw.providers || typeof raw.providers !== 'object') {
|
|
38
42
|
throw new Error('Provider account settings are unreadable.');
|
|
39
43
|
}
|
|
40
44
|
for (const [provider, pool] of Object.entries(raw.providers)) {
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
// A provider a newer build added is carried as is: this build never reads
|
|
46
|
+
// or writes its pool, and treating it as damage would discard it.
|
|
47
|
+
if (!ACCOUNT_PROVIDERS.includes(provider)) continue;
|
|
48
|
+
if (!Array.isArray(pool?.accounts) || pool.accounts.length > MAX_ACCOUNTS) {
|
|
43
49
|
throw new Error('Invalid provider account list.');
|
|
44
50
|
}
|
|
45
51
|
const ids = pool.accounts.map((row) => requireAccountId(row.id));
|
|
@@ -48,13 +54,11 @@ function validate(raw) {
|
|
|
48
54
|
return raw;
|
|
49
55
|
}
|
|
50
56
|
|
|
57
|
+
// Every OAuth provider's init reads the roster, so a damaged one (crash
|
|
58
|
+
// leftovers, truncation, a shape this build rejects) must never throw: it is
|
|
59
|
+
// kept aside and the last good copy, which every write keeps, is restored.
|
|
51
60
|
function read(dataDir) {
|
|
52
|
-
|
|
53
|
-
return validate(parseJsonText(readFileSync(file(dataDir), 'utf8')));
|
|
54
|
-
} catch (error) {
|
|
55
|
-
if (error.code === 'ENOENT') return validate(null);
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
61
|
+
return readJsonStateSync(file(dataDir), { validate, fallback: validate(null), secret: true });
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
// Labels an earlier build assigned automatically. They read as a different
|
|
@@ -106,7 +110,8 @@ export function readProviderAccountPool(provider, dataDir = resolvePluginData())
|
|
|
106
110
|
|
|
107
111
|
async function update(provider, mutate) {
|
|
108
112
|
requireAccountProvider(provider);
|
|
109
|
-
//
|
|
113
|
+
// A roster that parses yet fails validation is recovered here first; the
|
|
114
|
+
// mutator's validate would otherwise refuse every write. I/O failures throw.
|
|
110
115
|
read();
|
|
111
116
|
const result = await updateJsonAtomic(
|
|
112
117
|
file(),
|
|
@@ -117,7 +122,7 @@ async function update(provider, mutate) {
|
|
|
117
122
|
state.providers[provider] = pool;
|
|
118
123
|
return validate(state);
|
|
119
124
|
},
|
|
120
|
-
{ mode: 0o600, secret: true, fsyncDir: true }
|
|
125
|
+
{ mode: 0o600, secret: true, fsyncDir: true, backup: true }
|
|
121
126
|
);
|
|
122
127
|
return normalizePool(result.providers[provider]);
|
|
123
128
|
}
|
|
@@ -4,7 +4,12 @@ export interface RoutineTrigger {
|
|
|
4
4
|
event?: string;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export declare function routineTriggerHeader(input: {
|
|
7
|
+
export declare function routineTriggerHeader(input: {
|
|
8
|
+
kind: string;
|
|
9
|
+
name: string;
|
|
10
|
+
project?: string;
|
|
11
|
+
now?: Date | number;
|
|
12
|
+
}): string;
|
|
8
13
|
export declare function stripRoutineTriggerHeader(text: unknown): string;
|
|
9
14
|
export declare function normalizeRoutineTrigger(value: unknown): RoutineTrigger | null;
|
|
10
15
|
export declare function routineTriggerField(value: unknown): { routineTrigger?: RoutineTrigger };
|
|
@@ -4,18 +4,26 @@
|
|
|
4
4
|
// carries (live, persisted in meta.transcript, restored) so a chat paints it
|
|
5
5
|
// as a routine marker instead of a user bubble.
|
|
6
6
|
|
|
7
|
+
import { localTimestampParts } from './time-format.mjs';
|
|
8
|
+
|
|
7
9
|
const HEADER_PREFIX = '[Routine trigger]';
|
|
8
10
|
const KINDS = new Set(['schedule', 'webhook']);
|
|
9
11
|
|
|
10
|
-
/** The first line of a routine turn's prompt: which routine fired
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
|
|
12
|
+
/** The first line of a routine turn's prompt: which routine fired, when (local
|
|
13
|
+
* time and zone: the turn gets no other date), and how to treat the turn.
|
|
14
|
+
* It is the routine's only conduct text. Only the turn's content carries it,
|
|
15
|
+
* never the system prompt, so the thread's prompt cache is untouched. */
|
|
16
|
+
export function routineTriggerHeader({ kind, name, project = '', now = new Date() }) {
|
|
14
17
|
const what = kind === 'webhook' ? 'webhook' : 'schedule';
|
|
18
|
+
const at = localTimestampParts(now);
|
|
15
19
|
return [
|
|
16
20
|
`${HEADER_PREFIX} Your ${what} "${String(name)}" fired.`,
|
|
17
|
-
|
|
18
|
-
'
|
|
21
|
+
...(at ? [`Local time: ${at.date} ${at.time.slice(0, 5)} ${at.timeZone} (${at.offset}).`] : []),
|
|
22
|
+
'Carry out its instructions below now, yourself or by delegating.',
|
|
23
|
+
'Nobody is watching this turn and nothing asks for approval: act within your permissions.',
|
|
24
|
+
'Payments and permanent deletes are refused here: report that and suggest doing it from the chat.',
|
|
25
|
+
'If a sign-in, code or CAPTCHA blocks you, stop and say which site needs the user.',
|
|
26
|
+
'Reply in this chat in plain words, without tool names; if you handed work off, say it started — its result arrives here later.',
|
|
19
27
|
...(project ? [`Project folder: ${project}`] : []),
|
|
20
28
|
].join(' ');
|
|
21
29
|
}
|
|
@@ -8,6 +8,29 @@
|
|
|
8
8
|
// maxBytes, or the spawn error itself.
|
|
9
9
|
import { spawn } from 'node:child_process';
|
|
10
10
|
|
|
11
|
+
/** Kills `child` with everything it started. On Windows a plain kill ends only
|
|
12
|
+
* the child itself: `git` there is a launcher whose git.exe (and the alias,
|
|
13
|
+
* hook or filter it runs) would live on, still holding the output pipes. */
|
|
14
|
+
export function killChildTree(child) {
|
|
15
|
+
if (process.platform === 'win32' && child.pid && child.exitCode === null) {
|
|
16
|
+
const taskkill = `${process.env.SystemRoot || 'C:\\Windows'}\\System32\\taskkill.exe`;
|
|
17
|
+
const fallback = () => {
|
|
18
|
+
try {
|
|
19
|
+
child.kill();
|
|
20
|
+
} catch {}
|
|
21
|
+
};
|
|
22
|
+
spawn(taskkill, ['/PID', String(child.pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true })
|
|
23
|
+
.once('error', fallback)
|
|
24
|
+
.once('exit', (code) => {
|
|
25
|
+
if (code !== 0) fallback();
|
|
26
|
+
});
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
child.kill();
|
|
31
|
+
} catch {}
|
|
32
|
+
}
|
|
33
|
+
|
|
11
34
|
export function runChild({ command, args, cwd, input, env, timeoutMs, maxBytes, stdoutEncoding = 'utf8' }) {
|
|
12
35
|
return new Promise((resolvePromise, rejectPromise) => {
|
|
13
36
|
const hasInput = (typeof input === 'string' || ArrayBuffer.isView(input)) && input.length > 0;
|
|
@@ -35,9 +58,7 @@ export function runChild({ command, args, cwd, input, env, timeoutMs, maxBytes,
|
|
|
35
58
|
? setTimeout(() => {
|
|
36
59
|
const error = new Error(`${command} ${args.join(' ')} timed out after ${timeoutMs}ms`);
|
|
37
60
|
error.code = 'ETIMEDOUT';
|
|
38
|
-
|
|
39
|
-
child.kill();
|
|
40
|
-
} catch {}
|
|
61
|
+
killChildTree(child);
|
|
41
62
|
finish(error);
|
|
42
63
|
}, timeoutMs)
|
|
43
64
|
: null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface SensitiveScope {
|
|
2
|
+
root: string[];
|
|
3
|
+
/** Subfolders of the root that stay reachable. */
|
|
4
|
+
except: readonly string[];
|
|
5
|
+
/** Whole tree (a registered private root) or Mixdog's secret subset. */
|
|
6
|
+
whole: boolean;
|
|
7
|
+
}
|
|
8
|
+
export function sensitivePathSegments(path: string): string[];
|
|
9
|
+
export function matchesSensitivePath(
|
|
10
|
+
path: string,
|
|
11
|
+
within?: readonly SensitiveScope[],
|
|
12
|
+
options?: { envTemplates?: boolean }
|
|
13
|
+
): boolean;
|
|
14
|
+
export function mixdogSensitiveScopes(extraData?: readonly string[]): SensitiveScope[];
|
|
15
|
+
export function isSensitiveLocalPath(path: string, options?: { extraData?: readonly string[] }): boolean;
|