mixdog 1.3.1 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/package.json +8 -8
- package/scripts/native-release-status.mjs +238 -0
- package/scripts/verify-runtime-dependency-versions.mjs +158 -0
- package/src/agents/reviewer/AGENT.md +5 -7
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +9 -1
- package/src/defaults/skills/browser-use/SKILL.md +6 -3
- package/src/defaults/skills/local-provider/SKILL.md +33 -6
- package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
- package/src/defaults/skills/setup/SKILL.md +23 -1
- package/src/defaults/skills/setup/references/actions.md +50 -3
- package/src/defaults/skills/setup/references/surfaces.md +23 -3
- package/src/defaults/skills/setup-guide/SKILL.md +7 -3
- package/src/defaults/skills/visualize/SKILL.md +9 -6
- package/src/defaults/skills/visualize/references/craft.md +8 -1
- package/src/help.mjs +1 -1
- package/src/lib/keychain-cjs.cjs +4 -1
- package/src/lib/rules-builder.cjs +14 -7
- package/src/rules/agent-mode/AGENT_MODE.md +8 -5
- package/src/rules/agent-mode/MIXY.md +6 -8
- package/src/rules/lead/LEAD.md +7 -10
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/20-research.md +2 -0
- package/src/rules/shared/45-destructive.md +5 -1
- package/src/rules/shared/60-verification.md +6 -4
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
- package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
- package/src/runtime/agent/orchestrator/config.mjs +11 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -5
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +6 -10
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +84 -32
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +38 -11
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +15 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +84 -42
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +27 -8
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -1
- package/src/runtime/agent/orchestrator/providers/mixdog-local.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +5 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +30 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
- package/src/runtime/agent/orchestrator/providers/registry.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +13 -1
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
- package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +5 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +10 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +4 -6
- package/src/runtime/agent/orchestrator/runtime-core/route-context-state.mjs +81 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +52 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +35 -13
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +7 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +8 -3
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +196 -45
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/continuation.mjs +15 -6
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +45 -19
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +44 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +185 -37
- package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
- package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +240 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +102 -35
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +19 -9
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +199 -109
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/empty-nudge.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +62 -13
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +22 -6
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +5 -5
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +33 -8
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/call-prep.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/manager/agent-listing-notice.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +27 -14
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +32 -1
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +115 -0
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +28 -9
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +4 -9
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +14 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +7 -3
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +52 -11
- package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +18 -3
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +126 -12
- package/src/runtime/agent/orchestrator/session/runtime-user-context.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +16 -3
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +140 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +15 -5
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +49 -1
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +80 -1
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +33 -1
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.d.mts +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +37 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +35 -5
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +47 -14
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +127 -20
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +557 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +10 -12
- package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +42 -23
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
- package/src/runtime/attachments/attachment-reference.mjs +155 -0
- package/src/runtime/attachments/legacy-office.mjs +110 -0
- package/src/runtime/attachments/limits.mjs +5 -1
- package/src/runtime/attachments/office-extract.mjs +3 -6
- package/src/runtime/attachments/pdf-extract.mjs +84 -10
- package/src/runtime/attachments/prompt-restore.mjs +70 -0
- package/src/runtime/attachments/store.mjs +109 -33
- package/src/runtime/browser-bridge/client.mjs +73 -20
- package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
- package/src/runtime/channels/lib/scheduler.mjs +14 -7
- package/src/runtime/channels/lib/state-file.mjs +15 -15
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
- package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
- package/src/runtime/channels/lib/worker-main.mjs +3 -2
- package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
- package/src/runtime/effort-judge/judge-client.mjs +66 -16
- package/src/runtime/effort-judge/model-install.mjs +47 -7
- package/src/runtime/local-provider/asset-installer.mjs +10 -4
- package/src/runtime/local-provider/catalog.mjs +5 -2
- package/src/runtime/local-provider/registered-models.mjs +64 -27
- package/src/runtime/local-provider/server.mjs +2 -3
- package/src/runtime/media/adapters/image-api.mjs +89 -0
- package/src/runtime/media/auth.mjs +64 -1
- package/src/runtime/media/catalog.mjs +66 -4
- package/src/runtime/media/jobs.mjs +4 -0
- package/src/runtime/media/lanes.mjs +46 -5
- package/src/runtime/media/media-usage.mjs +17 -0
- package/src/runtime/media/renditions.mjs +15 -15
- package/src/runtime/media/store.mjs +36 -35
- package/src/runtime/media/tool.mjs +8 -1
- package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
- package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
- package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +14 -2
- package/src/runtime/memory/lib/pg/process.mjs +8 -4
- package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
- package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
- package/src/runtime/office/core/journal.mjs +7 -14
- package/src/runtime/office/design/library/design-library-core.mjs +4 -16
- package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
- package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
- package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
- package/src/runtime/office/pdf/pdf-render.mjs +30 -18
- package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +135 -29
- package/src/runtime/shared/agent-avatar-sprites.mjs +23 -8
- package/src/runtime/shared/agent-avatar.mjs +3 -2
- package/src/runtime/shared/agent-kind-migration.mjs +200 -0
- package/src/runtime/shared/agent-message-envelope.d.mts +6 -0
- package/src/runtime/shared/agent-message-envelope.mjs +44 -0
- package/src/runtime/shared/agent-reap-state.d.mts +4 -0
- package/src/runtime/shared/agent-room-host.d.mts +31 -0
- package/src/runtime/shared/agent-room-host.mjs +58 -0
- package/src/runtime/shared/agent-store.mjs +24 -7
- package/src/runtime/shared/agent-task-starts.mjs +27 -0
- package/src/runtime/shared/atomic-file.d.mts +50 -0
- package/src/runtime/shared/atomic-file.mjs +394 -132
- package/src/runtime/shared/background-tasks.mjs +7 -4
- package/src/runtime/shared/bot-hops.mjs +35 -0
- package/src/runtime/shared/bot-split-migration.mjs +1 -1
- package/src/runtime/shared/bounded-download.mjs +4 -2
- package/src/runtime/shared/config.mjs +39 -9
- package/src/runtime/shared/defaults-separation.mjs +6 -2
- package/src/runtime/shared/delegated-approval-host.mjs +74 -0
- package/src/runtime/shared/err-text.mjs +4 -0
- package/src/runtime/shared/error-presentation.mjs +22 -4
- package/src/runtime/shared/file-has-data.mjs +28 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
- package/src/runtime/shared/pending-agent-work.mjs +54 -0
- package/src/runtime/shared/process-lifecycle.mjs +8 -12
- package/src/runtime/shared/projects.mjs +50 -41
- package/src/runtime/shared/provider-accounts.mjs +17 -12
- package/src/runtime/shared/redact-directories.mjs +18 -0
- package/src/runtime/shared/remove-directory.mjs +28 -0
- package/src/runtime/shared/routine-trigger.d.mts +6 -1
- package/src/runtime/shared/routine-trigger.mjs +14 -6
- package/src/runtime/shared/run-child.d.mts +3 -0
- package/src/runtime/shared/run-child.mjs +24 -3
- package/src/runtime/shared/session-baseline-store.mjs +8 -2
- package/src/runtime/shared/session-sidebar-host.d.mts +11 -2
- package/src/runtime/shared/session-sidebar-host.mjs +16 -3
- package/src/runtime/shared/singleton-owner.mjs +7 -6
- package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
- package/src/runtime/shared/staged-update.mjs +4 -2
- package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
- package/src/runtime/shared/tool-execution-contract.mjs +10 -0
- package/src/runtime/shared/tool-work-units.mjs +12 -9
- package/src/runtime/shared/transcript-metadata.mjs +28 -3
- package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
- package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
- package/src/runtime/shared/turn-snapshot.mjs +277 -124
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +92 -61
- package/src/runtime/shared/utf8-cut.mjs +10 -0
- package/src/runtime/shared/worktrees/activity-gate.mjs +251 -61
- package/src/runtime/shared/worktrees/contract.mjs +11 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +11 -2
- package/src/runtime/shared/worktrees/manager.mjs +419 -52
- package/src/runtime/shared/worktrees/registry.mjs +29 -27
- package/src/runtime/shared/worktrees/tool-host.mjs +39 -0
- package/src/runtime/tidy/core-install.mjs +26 -4
- package/src/runtime/tidy/install.mjs +91 -23
- package/src/runtime/tidy/process.mjs +41 -8
- package/src/runtime/tidy/resolve.mjs +10 -7
- package/src/runtime/web-search/lib/config.mjs +4 -16
- package/src/session-runtime/agent-home-delivery.mjs +542 -204
- package/src/session-runtime/agent-profile-changes.mjs +16 -0
- package/src/session-runtime/agent-room-delivery.mjs +81 -35
- package/src/session-runtime/agent-task-sessions.mjs +811 -179
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +48 -24
- package/src/session-runtime/boot/config.mjs +1 -0
- package/src/session-runtime/boot/facade.mjs +16 -7
- package/src/session-runtime/boot/infrastructure.mjs +14 -2
- package/src/session-runtime/boot/providers.mjs +2 -2
- package/src/session-runtime/boot/shared.mjs +12 -6
- package/src/session-runtime/boot/tools.mjs +23 -3
- package/src/session-runtime/bot-status.mjs +432 -0
- package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
- package/src/session-runtime/config-lifecycle.mjs +60 -55
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/held-requests.mjs +31 -33
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +24 -26
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown.mjs +11 -3
- package/src/session-runtime/mcp-glue/connect.mjs +100 -186
- package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
- package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
- package/src/session-runtime/media-api.mjs +5 -2
- package/src/session-runtime/model-recency.mjs +1 -0
- package/src/session-runtime/model-route/route-tuning.mjs +4 -1
- package/src/session-runtime/model-route/set-route.mjs +61 -1
- package/src/session-runtime/owned-automation-run.mjs +8 -1
- package/src/session-runtime/provider-models/row-hydration.mjs +8 -1
- package/src/session-runtime/quick-model-rows/model-meta.mjs +2 -0
- package/src/session-runtime/quick-model-rows/provider-rows.mjs +7 -1
- package/src/session-runtime/route-resolution.mjs +16 -8
- package/src/session-runtime/route-state.mjs +1 -59
- package/src/session-runtime/routine-home-turn.mjs +5 -3
- package/src/session-runtime/runtime-bootstrap.mjs +5 -3
- package/src/session-runtime/runtime-paths.mjs +11 -5
- package/src/session-runtime/runtime-review-api.mjs +4 -1
- package/src/session-runtime/runtime-tunables.mjs +6 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +11 -2
- package/src/session-runtime/services/agent-tool/close-flow.mjs +4 -2
- package/src/session-runtime/services/agent-tool/execute-send.mjs +1 -0
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +34 -19
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +25 -21
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +7 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +8 -5
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +22 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +4 -6
- package/src/session-runtime/services/agent-tool.mjs +6 -0
- package/src/session-runtime/services/daemon-crash-capture/daemon-exit-record.mjs +1 -1
- package/src/session-runtime/services/daemon-crash-capture/retention.mjs +4 -3
- package/src/session-runtime/services/hook-bus/config-loader.mjs +14 -5
- package/src/session-runtime/services/hook-bus/rule-file.mjs +49 -11
- package/src/session-runtime/services/plugin-admin.mjs +26 -26
- package/src/session-runtime/services/provider-admin.mjs +26 -6
- package/src/session-runtime/services/schedule-access.mjs +33 -4
- package/src/session-runtime/services/seeds.mjs +4 -3
- package/src/session-runtime/services/usage-dashboard.mjs +1 -1
- package/src/session-runtime/services/usage-stats-model.mjs +2 -1
- package/src/session-runtime/services/worktree-access.mjs +27 -0
- package/src/session-runtime/session-create/materialize.mjs +2 -3
- package/src/session-runtime/session-create/session-options.mjs +15 -2
- package/src/session-runtime/session-hooks.mjs +9 -17
- package/src/session-runtime/settings-builtin-tools-api.mjs +65 -1
- package/src/session-runtime/settings-compaction-api.mjs +86 -39
- package/src/session-runtime/setup-tool/executor.mjs +12 -2
- package/src/session-runtime/setup-tool/settings-contract.mjs +34 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
- package/src/session-runtime/skills-api.mjs +12 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +349 -0
- package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
- package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
- package/src/session-runtime/tool-policy/policy-stage.mjs +183 -0
- package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
- package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
- package/src/session-runtime/tool-policy-refresh.mjs +48 -369
- package/src/session-runtime/tool-surface.mjs +10 -4
- package/src/session-runtime/turn/session-ops.mjs +8 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +95 -88
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +7 -2
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +527 -333
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +85 -63
- package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
- package/src/session-runtime/workspace/transition-steps.mjs +1 -18
- package/src/session-runtime/workspace/transitions.mjs +279 -67
- package/src/session-runtime/workspace/workspace-state.mjs +7 -6
- package/src/session-runtime/workspace/worktree-tool.mjs +194 -0
- package/src/standalone/daemon-agent-control.mjs +4 -1
- package/src/standalone/daemon-lag-profiler.mjs +3 -1
- package/src/standalone/daemon-session-control.mjs +173 -15
- package/src/standalone/daemon-telemetry.mjs +9 -0
- package/src/standalone/daemon.mjs +33 -10
- package/src/standalone/local-session-runtime.mjs +33 -16
- package/src/standalone/session-client.mjs +7 -2
- package/src/standalone/session-protocol.mjs +8 -0
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +2 -0
- package/src/standalone/session-service/agent-route-follow.mjs +69 -0
- package/src/standalone/session-service/session-calls/session-turns.mjs +33 -4
- package/src/standalone/session-service.mjs +21 -0
- package/src/standalone/session-state-projection.mjs +19 -9
- package/src/standalone/session-tool-output.mjs +36 -9
- package/src/standalone/staged-import.mjs +47 -0
- package/src/tui/App.jsx +2 -0
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
- package/src/tui/app/message-selector.mjs +15 -2
- package/src/tui/app/model-options.mjs +16 -2
- package/src/tui/app/model-picker.mjs +2 -1
- package/src/tui/app/route-pickers.mjs +3 -1
- package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
- package/src/tui/dist/index.mjs +617 -369
- package/src/tui/paste-attachments.mjs +0 -1
- package/src/tui/paste-text-policy.mjs +4 -5
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/agent-job-feed/execution-delivery.mjs +4 -1
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/notice-surface.mjs +3 -0
- package/src/tui/session/session-api/intake/abort.mjs +52 -18
- package/src/tui/session/session-api/intake/rewind.mjs +39 -4
- package/src/tui/session/session-api/media.mjs +2 -1
- package/src/tui/session/session-api/routes-agent-definitions.mjs +76 -0
- package/src/tui/session/session-api/routes-write.mjs +203 -0
- package/src/tui/session/session-api/routes.mjs +23 -247
- package/src/tui/session/session-api/settings.mjs +14 -1
- package/src/tui/session/session-flow/drain.mjs +28 -3
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +4 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +8 -3
- package/src/tui/session/tool-approval.mjs +142 -14
- package/src/tui/session/transcript-intake.mjs +2 -0
- package/src/tui/session/turn.mjs +23 -14
- package/src/tui/transcript-tool-failures.mjs +8 -2
- package/src/vendor/statusline/src/gateway/route-meta.mjs +7 -8
- package/src/vendor/statusline/src/gateway/session-routes.mjs +6 -7
- package/src/rules/agent-mode/ROUTINE.md +0 -6
- package/src/session-runtime/room-member-gate.mjs +0 -48
|
@@ -38,12 +38,16 @@ export const CODE_GRAPH_DISK_MEMORY_MAX_BYTES = Math.max(
|
|
|
38
38
|
// Younger .tmp files may belong to an in-flight persist still holding the sibling .lock;
|
|
39
39
|
// DEFAULT_LOCK_TIMEOUT_MS is 8s — 120s is a safe margin for large graph JSON writes.
|
|
40
40
|
export const ORPHAN_TMP_MIN_AGE_MS = 120_000;
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
// Atomic writer temp name: `<basename>.mixdog-tmp-<16hex>`; the dot-prefixed
|
|
42
|
+
// `.<basename>.<24hex>.tmp` is what older builds left behind.
|
|
43
|
+
export const RE_CACHE_TMP =
|
|
44
|
+
/^(?:\.[0-9a-f]{16}\.json\.[0-9a-f]{24}\.tmp|[0-9a-f]{16}\.json\.mixdog-tmp-[0-9a-f]{16,24})$/i;
|
|
45
|
+
export const RE_MANIFEST_TMP = /^(?:\.manifest\.json\.[0-9a-f]{24}\.tmp|manifest\.json\.mixdog-tmp-[0-9a-f]{16,24})$/i;
|
|
43
46
|
export const RE_CACHE_LOCK = /^[0-9a-f]{16}\.json\.lock$/i;
|
|
44
47
|
// Same debris, for the `<hash>.calls.json` call-site sidecar written beside
|
|
45
|
-
// each entry
|
|
46
|
-
export const RE_CALLS_CACHE_TMP =
|
|
48
|
+
// each entry.
|
|
49
|
+
export const RE_CALLS_CACHE_TMP =
|
|
50
|
+
/^(?:\.[0-9a-f]{16}\.calls\.json\.[0-9a-f]{24}\.tmp|[0-9a-f]{16}\.calls\.json\.mixdog-tmp-[0-9a-f]{16,24})$/i;
|
|
47
51
|
export const RE_CALLS_CACHE_LOCK = /^[0-9a-f]{16}\.calls\.json\.lock$/i;
|
|
48
52
|
export const CODE_GRAPH_MEMORY_MAX_ENTRIES = Math.max(
|
|
49
53
|
1,
|
|
@@ -62,9 +62,9 @@ const identityKey = (entry) => `${entry.pid}:${entry.token ?? ''}`;
|
|
|
62
62
|
* leave the process group). `observe()` takes one strict table read and
|
|
63
63
|
* answers 'running', 'gone' or 'unknown':
|
|
64
64
|
* - the root is alive (same identity) → running
|
|
65
|
-
* - no complete pre-exit capture exists → unknown
|
|
66
65
|
* - a tracked identity, a descendant still linked to one,
|
|
67
66
|
* or (POSIX) a member of the command's group is alive → running
|
|
67
|
+
* - no complete pre-exit capture exists → unknown
|
|
68
68
|
* - a tracked process without a creation token is present → unknown
|
|
69
69
|
* A failed table read rejects; callers treat it as unknown. */
|
|
70
70
|
export function createProcessTreeTracker({ pid, members = [], exitObserved = false } = {}) {
|
|
@@ -137,9 +137,9 @@ export function createProcessTreeTracker({ pid, members = [], exitObserved = fal
|
|
|
137
137
|
/** Pre-termination snapshot; call while the root still runs. */
|
|
138
138
|
async capture({ rootExited = false } = {}) {
|
|
139
139
|
if (rootPid <= 0) return false;
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
|
|
140
|
+
// Even if an in-flight read saw the root, children may have appeared
|
|
141
|
+
// since it began. Join the next fresh read before parent links break.
|
|
142
|
+
const table = await readProcessTable();
|
|
143
143
|
absorb(table, rootIsAlive(table, rootExited));
|
|
144
144
|
return complete;
|
|
145
145
|
},
|
|
@@ -159,7 +159,6 @@ export function createProcessTreeTracker({ pid, members = [], exitObserved = fal
|
|
|
159
159
|
live = [{ pid: rootPid, token: rootToken, name: table.nameOf.get(rootPid) || '' }];
|
|
160
160
|
return 'running';
|
|
161
161
|
}
|
|
162
|
-
if (!complete) return 'unknown';
|
|
163
162
|
let unknown = false;
|
|
164
163
|
for (const entry of tracked.values()) {
|
|
165
164
|
const state = present(table, entry);
|
|
@@ -167,7 +166,9 @@ export function createProcessTreeTracker({ pid, members = [], exitObserved = fal
|
|
|
167
166
|
else if (state === null) unknown = true;
|
|
168
167
|
}
|
|
169
168
|
if (live.length > 0) return 'running';
|
|
170
|
-
|
|
169
|
+
// Known survivors can still be swept after an incomplete capture, but
|
|
170
|
+
// their absence cannot prove that an unobserved descendant is gone.
|
|
171
|
+
return !complete || unknown ? 'unknown' : 'gone';
|
|
171
172
|
},
|
|
172
173
|
};
|
|
173
174
|
}
|
|
@@ -196,21 +197,13 @@ function sweepLiveIdentities(tracker) {
|
|
|
196
197
|
* `sweep` (a killed tree): a pass that finds captured identities alive
|
|
197
198
|
* terminates them and observes again in the same pass, so a cancellation
|
|
198
199
|
* ends with the tree gone instead of a held folder over live processes.
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* exited, a tree without a complete pre-kill snapshot is observed after
|
|
202
|
-
* exit (what is still linked to the root) instead of answering 'unknown'
|
|
203
|
-
* forever — no one is left to release it, and the close must end in a
|
|
204
|
-
* definitive state. `onSurvivors(pids)` reports the pids a pass that is
|
|
205
|
-
* not 'gone' found alive, whenever that set changes, so out-of-process
|
|
206
|
-
* readers can tell a live hold from a stale one. */
|
|
200
|
+
* A missing pre-kill capture stays unknown even if the owning session
|
|
201
|
+
* closes: its lifetime is not evidence that every descendant has exited. */
|
|
207
202
|
export function watchTermination({
|
|
208
203
|
tracker,
|
|
209
204
|
rootExited = () => true,
|
|
210
205
|
onTerminated,
|
|
211
206
|
onUnconfirmed = null,
|
|
212
|
-
onSurvivors = null,
|
|
213
|
-
ownerClosed = null,
|
|
214
207
|
releaseRequested = null,
|
|
215
208
|
intervalMs = TERMINATION_RECHECK_MS,
|
|
216
209
|
sweep = false,
|
|
@@ -218,7 +211,6 @@ export function watchTermination({
|
|
|
218
211
|
let timer = null;
|
|
219
212
|
let stopped = false;
|
|
220
213
|
let reportedUnconfirmed = false;
|
|
221
|
-
let survivorKey = null;
|
|
222
214
|
const stop = () => {
|
|
223
215
|
stopped = true;
|
|
224
216
|
if (timer) clearTimeout(timer);
|
|
@@ -234,7 +226,6 @@ export function watchTermination({
|
|
|
234
226
|
if (releaseRequested?.()) state = 'gone';
|
|
235
227
|
else
|
|
236
228
|
try {
|
|
237
|
-
if (!tracker.complete && rootExited() && ownerClosed?.()) tracker.acceptExitObservation();
|
|
238
229
|
observation = tracker.observe({ rootExited: rootExited() });
|
|
239
230
|
observation.catch(() => {});
|
|
240
231
|
// A pass that has not answered by the next cadence tick is unknown.
|
|
@@ -262,18 +253,6 @@ export function watchTermination({
|
|
|
262
253
|
/* presentation only */
|
|
263
254
|
}
|
|
264
255
|
}
|
|
265
|
-
if (state !== 'gone' && onSurvivors) {
|
|
266
|
-
const pids = tracker.live.map((entry) => entry.pid);
|
|
267
|
-
const key = pids.join(',');
|
|
268
|
-
if (key !== survivorKey) {
|
|
269
|
-
survivorKey = key;
|
|
270
|
-
try {
|
|
271
|
-
onSurvivors(pids);
|
|
272
|
-
} catch {
|
|
273
|
-
/* presentation only */
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
256
|
if (state === 'gone') {
|
|
278
257
|
try {
|
|
279
258
|
await onTerminated();
|
|
@@ -8,8 +8,6 @@ import { unregisterOwnedShellTree } from './owned-shell-trees.mjs';
|
|
|
8
8
|
import {
|
|
9
9
|
adoptShellWorkspaceAdmission,
|
|
10
10
|
clearTerminationHold,
|
|
11
|
-
isShellOwnerSessionClosed,
|
|
12
|
-
noteShellJobSurvivors,
|
|
13
11
|
registerTerminationHold,
|
|
14
12
|
takeReleaseRequest,
|
|
15
13
|
} from '../builtin/lib/shell-job-records.mjs';
|
|
@@ -28,13 +26,24 @@ import {
|
|
|
28
26
|
// it follows confirmed termination only (see below).
|
|
29
27
|
const UNCONFIRMED_KILL_CLEANUP_CEILING_MS = 60_000;
|
|
30
28
|
|
|
29
|
+
/** Settles once a held run's whole tree is confirmed gone (or its hold was
|
|
30
|
+
* force-released): what its result left in use defers to this. */
|
|
31
|
+
function treeSettled(run) {
|
|
32
|
+
if (!run.treeSettled) {
|
|
33
|
+
run.treeSettled = new Promise((resolve) => {
|
|
34
|
+
run.resolveTreeSettled = resolve;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return run.treeSettled;
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
/** Lifecycle completion of a run whose result is already reported: release
|
|
32
41
|
* `run.workspaceAdmission` and retire the live record only once the root AND
|
|
33
42
|
* every descendant identity captured before the kill are confirmed gone. One
|
|
34
43
|
* observation loop at the termination cadence; running, unknown (incomplete
|
|
35
44
|
* snapshot, failed table read) and a failing release all re-check, and no
|
|
36
45
|
* timer ever releases on its own. */
|
|
37
|
-
export function releaseAdmissionOnConfirmedTermination(run, { markNow = true } = {}) {
|
|
46
|
+
export function releaseAdmissionOnConfirmedTermination(run, { markNow = true, sweep = run.killed === true } = {}) {
|
|
38
47
|
const { child } = run;
|
|
39
48
|
if (!child || run.stopTerminationWatch) return;
|
|
40
49
|
// Visible as "termination unconfirmed" until the lifecycle ends, with an
|
|
@@ -42,12 +51,14 @@ export function releaseAdmissionOnConfirmedTermination(run, { markNow = true } =
|
|
|
42
51
|
// kill is marked at once; an owner-cancelled tree whose root is already
|
|
43
52
|
// gone only once its first observation is not 'gone'.
|
|
44
53
|
if (markNow) keepTerminationUnconfirmedRecord(run);
|
|
54
|
+
treeSettled(run);
|
|
45
55
|
const release = () => {
|
|
46
56
|
run.workspaceAdmission?.();
|
|
47
57
|
run.workspaceAdmission = null;
|
|
48
58
|
run.stopTerminationWatch?.();
|
|
49
59
|
clearTerminationHold(run.foregroundRecordId);
|
|
50
60
|
clearForegroundRecord(run);
|
|
61
|
+
run.resolveTreeSettled();
|
|
51
62
|
};
|
|
52
63
|
registerTerminationHold(run.foregroundRecordId, {
|
|
53
64
|
ownerSessionId: run.foregroundRecordInput?.ownerSessionId || null,
|
|
@@ -59,11 +70,9 @@ export function releaseAdmissionOnConfirmedTermination(run, { markNow = true } =
|
|
|
59
70
|
tracker: run.terminationTracker,
|
|
60
71
|
rootExited: () => child.exitCode != null || child.signalCode != null,
|
|
61
72
|
// A killed run is not over while processes it started still run.
|
|
62
|
-
sweep
|
|
73
|
+
sweep,
|
|
63
74
|
onTerminated: release,
|
|
64
75
|
onUnconfirmed: markNow ? null : () => keepTerminationUnconfirmedRecord(run),
|
|
65
|
-
onSurvivors: (pids) => void noteShellJobSurvivors(run.foregroundRecordId, pids),
|
|
66
|
-
ownerClosed: () => isShellOwnerSessionClosed(run.foregroundRecordInput?.ownerSessionId),
|
|
67
76
|
releaseRequested: () => takeReleaseRequest(run.foregroundRecordId),
|
|
68
77
|
});
|
|
69
78
|
}
|
|
@@ -202,17 +211,19 @@ export function createSettle(run, releasePromotedCapture) {
|
|
|
202
211
|
// The test compares captured BYTES, not rendered UTF-16 length: a CJK
|
|
203
212
|
// head+tail holds ~1/3 the char count of its byte size and under a
|
|
204
213
|
// length test would delete the very file its own marker names.
|
|
214
|
+
const dropCapture =
|
|
215
|
+
!run.killUnconfirmed && taskOutput.spilled && taskOutput.totalDiskBytes() <= SHELL_OUTPUT_INLINE_CAP;
|
|
205
216
|
if (run.killUnconfirmed) {
|
|
206
217
|
// Never confirmed dead: deleting the capture files or handing back the
|
|
207
218
|
// lease now would release resources a live process still owns. The
|
|
208
219
|
// spilled paths therefore survive and travel with the result below, and
|
|
209
220
|
// the workspace admission stays held until termination is confirmed.
|
|
210
221
|
deferCleanupToChildExit(run);
|
|
211
|
-
} else if (taskOutput.spilled && taskOutput.totalDiskBytes() <= SHELL_OUTPUT_INLINE_CAP) {
|
|
212
|
-
taskOutput.deleteFiles();
|
|
213
|
-
void releaseResourceLease(run);
|
|
214
222
|
} else {
|
|
215
|
-
taskOutput.closeFds();
|
|
223
|
+
const releaseCapture = () => (dropCapture ? taskOutput.deleteFiles() : taskOutput.closeFds());
|
|
224
|
+
// A captured descendant of a killed tree may still write the capture.
|
|
225
|
+
if (confirmKill) void treeSettled(run).then(releaseCapture);
|
|
226
|
+
else releaseCapture();
|
|
216
227
|
void releaseResourceLease(run);
|
|
217
228
|
}
|
|
218
229
|
let descendants = null;
|
|
@@ -256,9 +267,9 @@ export function createSettle(run, releasePromotedCapture) {
|
|
|
256
267
|
timedOut: run.timedOut,
|
|
257
268
|
killed: run.killed,
|
|
258
269
|
killCause: run.killCause,
|
|
259
|
-
stdoutPath: taskOutput.spilled ? taskOutput.stdoutPath : null,
|
|
270
|
+
stdoutPath: taskOutput.spilled && !dropCapture ? taskOutput.stdoutPath : null,
|
|
260
271
|
stdoutFileSize: taskOutput.stdoutFileSize,
|
|
261
|
-
stderrPath: taskOutput.spilled ? taskOutput.stderrPath : null,
|
|
272
|
+
stderrPath: taskOutput.spilled && !dropCapture ? taskOutput.stderrPath : null,
|
|
262
273
|
stderrFileSize: taskOutput.stderrFileSize,
|
|
263
274
|
taskId: run.taskId,
|
|
264
275
|
partialOutput: run.partialOutput,
|
|
@@ -266,6 +277,7 @@ export function createSettle(run, releasePromotedCapture) {
|
|
|
266
277
|
failurePhase: run.failurePhase,
|
|
267
278
|
failureReason: run.failureReason,
|
|
268
279
|
descendants,
|
|
280
|
+
settled: run.treeSettled,
|
|
269
281
|
})
|
|
270
282
|
);
|
|
271
283
|
};
|
|
@@ -289,8 +289,9 @@ export async function spawnShellChild(input) {
|
|
|
289
289
|
if (!detail || !['completed', 'failed', 'cancelled'].includes(detail.nativeStatus)) {
|
|
290
290
|
throw new Error('The child termination could not be confirmed; workspace admission is retained.');
|
|
291
291
|
}
|
|
292
|
-
|
|
293
|
-
|
|
292
|
+
// The root is gone, but not necessarily what it started: the
|
|
293
|
+
// reservation follows the captured tree, swept like any killed one.
|
|
294
|
+
releaseAdmissionOnConfirmedTermination(input.run, { markNow: false, sweep: true });
|
|
294
295
|
} catch (cleanupError) {
|
|
295
296
|
input.run.killUnconfirmed = true;
|
|
296
297
|
// No settle will ever run for this run; the reservation is released
|
|
@@ -104,8 +104,9 @@ export function createShellRun({ abortSignal, resolve, jobId = null }) {
|
|
|
104
104
|
// `settled`: whichever transition wins first wins for good.
|
|
105
105
|
autoBackgrounded: false,
|
|
106
106
|
autoBackgroundJobId: null,
|
|
107
|
-
// [exitCode, signal] of a 'close'
|
|
108
|
-
// flight; a promotion that then fails settles the
|
|
107
|
+
// [exitCode, signal] of a 'close' (or an expired drain grace) that arrived
|
|
108
|
+
// while promotion was in flight; a promotion that then fails settles the
|
|
109
|
+
// run with it.
|
|
109
110
|
promotionClose: null,
|
|
110
111
|
autoBgTimer: null,
|
|
111
112
|
killUnconfirmed: false,
|
|
@@ -125,6 +126,9 @@ export function createShellRun({ abortSignal, resolve, jobId = null }) {
|
|
|
125
126
|
// observation loop that holds the workspace until they are gone.
|
|
126
127
|
terminationTracker: null,
|
|
127
128
|
stopTerminationWatch: null,
|
|
129
|
+
// Settles when that loop ends (lib/shell-run-settle.mjs treeSettled).
|
|
130
|
+
treeSettled: null,
|
|
131
|
+
resolveTreeSettled: null,
|
|
128
132
|
};
|
|
129
133
|
}
|
|
130
134
|
|
|
@@ -41,7 +41,8 @@ function quarantinePathFor(fullPath) {
|
|
|
41
41
|
const dir = dirname(fullPath);
|
|
42
42
|
const name = basename(fullPath).slice(0, 80);
|
|
43
43
|
for (let attempt = 0; attempt < 8; attempt++) {
|
|
44
|
-
|
|
44
|
+
// No leading dot: sync-drive folders (e.g. Naver MYBOX) refuse dot-prefixed names.
|
|
45
|
+
const candidate = join(dir, `${name}.mixdog-delete-${randomBytes(8).toString('hex')}`);
|
|
45
46
|
try {
|
|
46
47
|
lstatSync(candidate);
|
|
47
48
|
} catch (err) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Patch replay capture: every apply_patch failure is frozen (args + target
|
|
2
2
|
// file snapshots) for `npm run patch:replay`. Best-effort throughout — a
|
|
3
3
|
// capture problem never changes the tool result.
|
|
4
|
-
import { readdirSync,
|
|
4
|
+
import { readdirSync, mkdirSync, rmSync } from 'node:fs';
|
|
5
|
+
import { writeJsonAtomicSync } from '../../../../shared/atomic-file.mjs';
|
|
5
6
|
import { resolve as pathResolve, isAbsolute, join as pathJoin } from 'node:path';
|
|
6
7
|
import {
|
|
7
8
|
createSnapshotBudget,
|
|
@@ -203,7 +204,8 @@ export function maybeCapturePatchReplay(capture, errorText) {
|
|
|
203
204
|
? { file_snapshot_meta: capture.fileSnapshotMeta }
|
|
204
205
|
: {}),
|
|
205
206
|
};
|
|
206
|
-
|
|
207
|
+
// Whole-file publication; `patch:replay` skips a record it cannot parse.
|
|
208
|
+
writeJsonAtomicSync(pathJoin(dir, `${id}.json`), record, { mode: 0o600 });
|
|
207
209
|
// Retention: keep the newest 40 captures. The id prefix is Date.now() in
|
|
208
210
|
// base36 (fixed width until ~2059), so a lexicographic sort is
|
|
209
211
|
// chronological and the oldest records sort first.
|
|
@@ -8,7 +8,17 @@
|
|
|
8
8
|
// { existed: true, content: null, omitted: true, size, mode }. Omitted is not
|
|
9
9
|
// empty content — restore never writes it, and only reports it untouched when
|
|
10
10
|
// the file provably still is.
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
chmodSync,
|
|
13
|
+
closeSync,
|
|
14
|
+
existsSync,
|
|
15
|
+
fsyncSync,
|
|
16
|
+
mkdirSync,
|
|
17
|
+
openSync,
|
|
18
|
+
rmSync,
|
|
19
|
+
statSync,
|
|
20
|
+
writeFileSync,
|
|
21
|
+
} from 'node:fs';
|
|
12
22
|
import { dirname as pathDirname } from 'node:path';
|
|
13
23
|
import {
|
|
14
24
|
createSnapshotBudget,
|
|
@@ -83,6 +93,27 @@ function omittedSnapshotIssue(snapshot) {
|
|
|
83
93
|
return `${what}; the file changed and cannot be restored`;
|
|
84
94
|
}
|
|
85
95
|
|
|
96
|
+
// Filesystems that refuse fsync answer with one of these; durability is
|
|
97
|
+
// best-effort there and must not fail the restore.
|
|
98
|
+
const FSYNC_TOLERATED = new Set(['EPERM', 'ENOTSUP', 'EINVAL']);
|
|
99
|
+
|
|
100
|
+
// The restore rewrites a file of the user's project in place: flush it through
|
|
101
|
+
// the handle that wrote it, like the write tool does, so a crash cannot leave
|
|
102
|
+
// the restored file with its size committed and every byte NUL.
|
|
103
|
+
function writeRestoredFile(path, content) {
|
|
104
|
+
const fd = openSync(path, 'w');
|
|
105
|
+
try {
|
|
106
|
+
writeFileSync(fd, content);
|
|
107
|
+
try {
|
|
108
|
+
fsyncSync(fd);
|
|
109
|
+
} catch (err) {
|
|
110
|
+
if (!FSYNC_TOLERATED.has(err?.code)) throw err;
|
|
111
|
+
}
|
|
112
|
+
} finally {
|
|
113
|
+
closeSync(fd);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
86
117
|
export function restorePatchRollbackState(snapshots, readStateScope) {
|
|
87
118
|
const errors = [];
|
|
88
119
|
const paths = [];
|
|
@@ -96,7 +127,7 @@ export function restorePatchRollbackState(snapshots, readStateScope) {
|
|
|
96
127
|
try {
|
|
97
128
|
if (snapshot.existed) {
|
|
98
129
|
mkdirSync(pathDirname(snapshot.fullPath), { recursive: true });
|
|
99
|
-
|
|
130
|
+
writeRestoredFile(snapshot.fullPath, snapshot.content);
|
|
100
131
|
if (snapshot.mode != null) chmodSync(snapshot.fullPath, snapshot.mode);
|
|
101
132
|
} else if (existsSync(snapshot.fullPath)) {
|
|
102
133
|
rmSync(snapshot.fullPath, { force: true });
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.7.
|
|
2
|
+
"version": "0.7.34",
|
|
3
3
|
"_comment": "Rewritten by .github/workflows/patch-release.yml on each tagged release. assets maps platformKey (process.platform-process.arch, e.g. win32-x64, linux-x64, darwin-arm64) to { url, sha256 } of the mixdog-patch binary on the GitHub release. A local cargo build under native/mixdog-patch/target/release always takes precedence; otherwise the binary is fetched per this manifest into the data dir (apply is native-only — no JS apply engine).",
|
|
4
4
|
"assets": {
|
|
5
5
|
"darwin-arm64": {
|
|
6
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.
|
|
7
|
-
"sha256": "
|
|
6
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.34/mixdog-patch-darwin-arm64",
|
|
7
|
+
"sha256": "b7e2bd6649ae64801d7f2720fea11fdd8e52ca2fcc21fedb717691cc6f8e6341"
|
|
8
8
|
},
|
|
9
9
|
"darwin-x64": {
|
|
10
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.
|
|
11
|
-
"sha256": "
|
|
10
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.34/mixdog-patch-darwin-x64",
|
|
11
|
+
"sha256": "d0d11eda8b65ee34a3b510eb9f3a57970e977076cd9c8854bf336ec62e3f6d23"
|
|
12
12
|
},
|
|
13
13
|
"linux-arm64": {
|
|
14
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.
|
|
15
|
-
"sha256": "
|
|
14
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.34/mixdog-patch-linux-arm64",
|
|
15
|
+
"sha256": "cb3a530dd68e18edef1cc01025ee89c1b4296f847b76a8f6ea8110710b66912e"
|
|
16
16
|
},
|
|
17
17
|
"linux-x64": {
|
|
18
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.
|
|
19
|
-
"sha256": "
|
|
18
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.34/mixdog-patch-linux-x64",
|
|
19
|
+
"sha256": "4743bb6b23db574f282df0a2744ca4b5b2a7e5049533cf00bc26b93ce235231c"
|
|
20
20
|
},
|
|
21
21
|
"win32-arm64": {
|
|
22
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.
|
|
23
|
-
"sha256": "
|
|
22
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.34/mixdog-patch-win32-arm64.exe",
|
|
23
|
+
"sha256": "626496b0a2f804f769c20f8d1f6d35d9caab89b8ddb38c5e320ba1d146bf84f6"
|
|
24
24
|
},
|
|
25
25
|
"win32-x64": {
|
|
26
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.
|
|
27
|
-
"sha256": "
|
|
26
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/patch-v0.7.34/mixdog-patch-win32-x64.exe",
|
|
27
|
+
"sha256": "03c73fe9895dad6684060e7b0155bb41a8dc96ad75c49c9c9b550cbec27afd1d"
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -421,15 +421,17 @@ function attachChildExit(run, releasePromotedCapture) {
|
|
|
421
421
|
child.once('exit', (code, signal) => {
|
|
422
422
|
if (!run.rootExitAtMs) run.rootExitAtMs = Date.now();
|
|
423
423
|
const grace = setTimeout(() => {
|
|
424
|
-
if (run.settled) return;
|
|
424
|
+
if (run.settled || run.promotionClose) return;
|
|
425
|
+
run.partialOutput = true;
|
|
425
426
|
if (run.autoBackgrounded) {
|
|
426
427
|
// A promoted child whose 'close' never arrives (grandchild holding
|
|
427
428
|
// the stdio) would otherwise keep its spill descriptors forever:
|
|
428
|
-
// 'exit' is the only terminal event this path gets.
|
|
429
|
+
// 'exit' is the only terminal event this path gets. A promotion that
|
|
430
|
+
// is still pending and then fails settles the run with it.
|
|
431
|
+
run.promotionClose = [code == null ? 1 : code, signal];
|
|
429
432
|
releasePromotedCapture();
|
|
430
433
|
return;
|
|
431
434
|
}
|
|
432
|
-
run.partialOutput = true;
|
|
433
435
|
run.settle(code == null ? 1 : code, signal);
|
|
434
436
|
}, 3000);
|
|
435
437
|
if (grace.unref) grace.unref();
|
|
@@ -637,7 +637,9 @@ export class ExecResult {
|
|
|
637
637
|
this.backgrounded = opts.backgrounded === true;
|
|
638
638
|
this.jobId = opts.jobId || null;
|
|
639
639
|
// A command queued behind a saturated shell lane is no shell job; this
|
|
640
|
-
// promise settles when the queued run finishes.
|
|
640
|
+
// promise settles when the queued run finishes. A foreground result
|
|
641
|
+
// reported while its tree may still run (a kill, unverified descendants)
|
|
642
|
+
// carries the promise that settles once that tree is gone.
|
|
641
643
|
this.settled = opts.settled || null;
|
|
642
644
|
this.backgroundMessage = opts.backgroundMessage || null;
|
|
643
645
|
// Survivors observed AFTER the shell process exited (process group on
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attachments sent by reference instead of inline.
|
|
3
|
+
*
|
|
4
|
+
* A PDF or image the user attached already lives in the content-addressed
|
|
5
|
+
* store on this machine. When inlining it would crowd the context window, the
|
|
6
|
+
* message carries a short text part instead: the file's name, size, page count
|
|
7
|
+
* and text-layer status, and the path the model reads it from — so the model
|
|
8
|
+
* pulls in only the pages the request needs (read with `pages`). The part keeps
|
|
9
|
+
* the attachment's `attachmentRef` (nested, so it is not itself a stored-text
|
|
10
|
+
* reference) and the store's census keeps the bytes as long as the message
|
|
11
|
+
* names them.
|
|
12
|
+
*/
|
|
13
|
+
import { inlineFileKind } from '../shared/inline-file-kind.mjs';
|
|
14
|
+
import { attachmentFilePath, isAttachmentReference, storeInlineDocumentPart, storeInlineImagePart } from './store.mjs';
|
|
15
|
+
|
|
16
|
+
/** Up to this many pages per read call; the read tool enforces the same cap. */
|
|
17
|
+
export const READ_PDF_MAX_PAGES_PER_CALL = 20;
|
|
18
|
+
|
|
19
|
+
function sizeLabel(bytes) {
|
|
20
|
+
const value = Number(bytes) || 0;
|
|
21
|
+
if (value >= 1024 * 1024) return `${(value / (1024 * 1024)).toFixed(1)} MB`;
|
|
22
|
+
if (value >= 1024) return `${Math.max(1, Math.round(value / 1024))} KB`;
|
|
23
|
+
return `${value} bytes`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function quotedName(name, fallback) {
|
|
27
|
+
const base = String(name || '')
|
|
28
|
+
.split(/[\\/]/)
|
|
29
|
+
.pop()
|
|
30
|
+
.replace(/["\r\n]/g, '')
|
|
31
|
+
.trim();
|
|
32
|
+
return `"${base || fallback}"`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** How much of a PDF reads as text, in words the model can act on. */
|
|
36
|
+
export function textLayerLabel(pageCount, textPages) {
|
|
37
|
+
const pages = Number(pageCount);
|
|
38
|
+
const withText = Number(textPages);
|
|
39
|
+
if (!(pages > 0) || !Number.isFinite(withText) || withText < 0) return 'text layer not checked';
|
|
40
|
+
if (withText === 0) return 'no text layer (scanned pages)';
|
|
41
|
+
if (withText >= pages) return 'text layer on every page';
|
|
42
|
+
return `text layer on ${withText} of ${pages} pages; the rest are scanned`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function pdfReferenceText(info, path) {
|
|
46
|
+
const plural = info.pageCount === 1 ? '' : 's';
|
|
47
|
+
const pages = info.pageCount > 0 ? `${info.pageCount} page${plural}, ` : '';
|
|
48
|
+
return [
|
|
49
|
+
`[Attachment kept on disk, not inlined: ${quotedName(info.filename, 'document.pdf')} ` +
|
|
50
|
+
`(PDF, ${pages}${textLayerLabel(info.pageCount, info.textPages)}, ${sizeLabel(info.sizeBytes)})`,
|
|
51
|
+
`Path: ${path}`,
|
|
52
|
+
`Read only what the request needs: read this path with pages, e.g. pages="1-5" (up to ` +
|
|
53
|
+
`${READ_PDF_MAX_PAGES_PER_CALL} pages per call). Pages with a text layer come back as text; ` +
|
|
54
|
+
'scanned pages come back as page images, or as OCR text when the model is text-only.]',
|
|
55
|
+
].join('\n');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function imageReferenceText(info, path) {
|
|
59
|
+
return [
|
|
60
|
+
`[Image kept on disk, not inlined: ${quotedName(info.filename, 'image')} ` +
|
|
61
|
+
`(${info.mimeType || 'image'}, ${sizeLabel(info.sizeBytes)})`,
|
|
62
|
+
`Path: ${path}`,
|
|
63
|
+
'View it with read on this path when the request needs it.]',
|
|
64
|
+
].join('\n');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// The stored form of a media part that can travel by reference, or null. An
|
|
68
|
+
// inline payload is written to the store first so it gets a path too.
|
|
69
|
+
function storedMediaPart(part) {
|
|
70
|
+
if (!part || typeof part !== 'object') return null;
|
|
71
|
+
if (part.type === 'image') {
|
|
72
|
+
if (isAttachmentReference(part)) return part;
|
|
73
|
+
return storeInlineImagePart(part);
|
|
74
|
+
}
|
|
75
|
+
if (part.type === 'file' || part.type === 'document') {
|
|
76
|
+
const stored = isAttachmentReference(part) ? part : storeInlineDocumentPart(part);
|
|
77
|
+
if (!stored) return null;
|
|
78
|
+
const mimeType = String(stored.mimeType || stored.mediaType || '');
|
|
79
|
+
return inlineFileKind(mimeType, '') === 'pdf' ? stored : null;
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Whether `part` is a media part this module can turn into a reference. */
|
|
85
|
+
export function isReferencableMediaPart(part) {
|
|
86
|
+
if (!part || typeof part !== 'object') return false;
|
|
87
|
+
if (part.type === 'image') {
|
|
88
|
+
return isAttachmentReference(part) || typeof part.data === 'string' || part.source?.type === 'base64';
|
|
89
|
+
}
|
|
90
|
+
if (part.type === 'document') return part.source?.type === 'base64';
|
|
91
|
+
if (part.type !== 'file') return false;
|
|
92
|
+
const mimeType = String(part.mimeType || part.mediaType || 'application/pdf');
|
|
93
|
+
return inlineFileKind(mimeType, isAttachmentReference(part) ? '' : part.data || '', part.filename) === 'pdf';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Whether `part` is a reference this module produced. */
|
|
97
|
+
export function isMediaReferencePart(part) {
|
|
98
|
+
return Boolean(part && part.type === 'text' && part.attachmentReference && typeof part.text === 'string');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The reference text part standing for one media part, or null when the part
|
|
103
|
+
* cannot travel by reference (a URL image, a non-PDF file, a store failure).
|
|
104
|
+
*/
|
|
105
|
+
export function mediaPartToReference(part) {
|
|
106
|
+
let stored;
|
|
107
|
+
try {
|
|
108
|
+
stored = storedMediaPart(part);
|
|
109
|
+
} catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
if (!stored) return null;
|
|
113
|
+
const kind = stored.type === 'image' ? 'image' : 'pdf';
|
|
114
|
+
const pageCount = Math.floor(Number(part.pageCount ?? stored.pageCount)) || 0;
|
|
115
|
+
const textPagesRaw = part.textPages ?? stored.textPages;
|
|
116
|
+
const info = {
|
|
117
|
+
attachmentRef: stored.attachmentRef,
|
|
118
|
+
kind,
|
|
119
|
+
filename: String(part.filename || part.title || part.name || stored.filename || ''),
|
|
120
|
+
mimeType: String(stored.mimeType || stored.mediaType || (kind === 'pdf' ? 'application/pdf' : 'image/png')),
|
|
121
|
+
sizeBytes: Number(stored.sizeBytes) || 0,
|
|
122
|
+
...(pageCount > 0 ? { pageCount } : {}),
|
|
123
|
+
...(Number.isFinite(Number(textPagesRaw)) && textPagesRaw !== null ? { textPages: Number(textPagesRaw) } : {}),
|
|
124
|
+
};
|
|
125
|
+
const path = attachmentFilePath(info.attachmentRef);
|
|
126
|
+
return {
|
|
127
|
+
type: 'text',
|
|
128
|
+
text: kind === 'pdf' ? pdfReferenceText(info, path) : imageReferenceText(info, path),
|
|
129
|
+
attachmentReference: info,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A user `message` with every referencable media part of its own content
|
|
135
|
+
* replaced by its reference text (other roles, tool results and nested content
|
|
136
|
+
* stay as they are).
|
|
137
|
+
* Returns the same message when nothing changed.
|
|
138
|
+
*/
|
|
139
|
+
export function referenceMessageMedia(message) {
|
|
140
|
+
if (message?.role !== 'user' || !Array.isArray(message.content)) return message;
|
|
141
|
+
let changed = false;
|
|
142
|
+
const content = message.content.map((part) => {
|
|
143
|
+
if (!isReferencableMediaPart(part)) return part;
|
|
144
|
+
const reference = mediaPartToReference(part);
|
|
145
|
+
if (!reference) return part;
|
|
146
|
+
changed = true;
|
|
147
|
+
return reference;
|
|
148
|
+
});
|
|
149
|
+
return changed ? { ...message, content } : message;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Whether the message's own content still carries referencable media. */
|
|
153
|
+
export function messageHasReferencableMedia(message) {
|
|
154
|
+
return Array.isArray(message?.content) && message.content.some(isReferencableMediaPart);
|
|
155
|
+
}
|