mixdog 1.3.4 → 1.4.0
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/LICENSES/oh-my-pi-MIT.txt +23 -0
- package/NOTICE.md +17 -2
- package/README.md +11 -0
- package/package.json +3 -11
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/embed-google-oauth-client.mjs +49 -0
- package/scripts/gate-local.mjs +4 -2
- package/scripts/lib/test-spawn-ledger.mjs +46 -1
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +10 -1
- package/scripts/test.mjs +12 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +25 -1
- package/src/defaults/skills/browser-use/SKILL.md +77 -17
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +33 -9
- package/src/defaults/skills/setup/SKILL.md +29 -2
- package/src/defaults/skills/setup/references/actions.md +117 -28
- package/src/defaults/skills/setup/references/surfaces.md +77 -35
- package/src/defaults/skills/setup-guide/SKILL.md +3 -3
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/keychain-cjs.cjs +359 -29
- package/src/lib/rules-builder.cjs +10 -8
- package/src/rules/agent/AGENT.md +6 -6
- package/src/rules/agent-mode/AGENT_MODE.md +10 -2
- package/src/rules/agent-mode/MIXY.md +12 -0
- package/src/rules/lead/LEAD.md +18 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/config.mjs +34 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +177 -73
- package/src/runtime/agent/orchestrator/mcp/client.mjs +25 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +230 -137
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +64 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +160 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +142 -104
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
- package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
- package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +19 -1
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +43 -3
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/wire-protobuf-codec.mjs +368 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +148 -25
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +47 -9
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +51 -3
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +14 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +23 -5
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
- package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +47 -11
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +133 -18
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +25 -2
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/schedule-errors.mjs +51 -0
- package/src/runtime/channels/lib/scheduler.mjs +135 -154
- package/src/runtime/channels/lib/schedules-db.mjs +83 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +14 -2
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +19 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/office/com/com-adapter.mjs +17 -1
- package/src/runtime/office/com/office-com-host.ps1 +51 -1
- package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
- package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
- package/src/runtime/office/pdf/document-preview.mjs +326 -8
- package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
- package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
- package/src/runtime/office/portable/portable-soffice.mjs +45 -5
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bot-hops.mjs +62 -2
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +51 -35
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +33 -2
- package/src/runtime/shared/connector-catalog.mjs +166 -8
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -14
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/developer-options.mjs +32 -1
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/google-oauth-client.generated.json +4 -0
- package/src/runtime/shared/google-oauth-client.mjs +34 -9
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
- package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/llm/well-formed.mjs +66 -0
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +231 -59
- package/src/runtime/shared/provider-api-key.mjs +19 -8
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +52 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +34 -1
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -14
- package/src/runtime/shared/transcript-metadata.mjs +38 -0
- package/src/runtime/shared/user-data-guard.mjs +30 -2
- package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
- package/src/runtime/shared/worktrees/test-support.mjs +9 -4
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +27 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +486 -179
- package/src/session-runtime/agent-room-delivery.mjs +28 -1
- package/src/session-runtime/agent-task-sessions.mjs +561 -199
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/begin.mjs +3 -2
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +8 -1
- package/src/session-runtime/bot-chain.mjs +32 -0
- package/src/session-runtime/bot-status.mjs +7 -4
- package/src/session-runtime/channel-config-api.mjs +63 -17
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
- package/src/session-runtime/internal-tool-executor.mjs +4 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +61 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +927 -0
- package/src/session-runtime/model-route/route-tuning.mjs +10 -6
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +35 -13
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-auth/login.mjs +7 -0
- package/src/session-runtime/provider-models/row-hydration.mjs +13 -2
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/routine-home-turn.mjs +33 -6
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/schedule-session-run.mjs +7 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +73 -31
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +128 -25
- package/src/session-runtime/services/schedule-access.mjs +14 -0
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +8 -4
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +28 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +187 -29
- package/src/session-runtime/setup-tool/extended-actions.mjs +33 -2
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +68 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +92 -6
- package/src/session-runtime/task-session-route.mjs +99 -0
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +21 -4
- package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
- package/src/session-runtime/tool-surface.mjs +4 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
- package/src/session-runtime/workspace/transitions.mjs +10 -2
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +161 -157
- package/src/standalone/daemon.mjs +33 -2
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +10 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-service.mjs +13 -0
- package/src/standalone/session-tool-output.mjs +21 -10
- package/src/tui/app/model-options.mjs +4 -27
- package/src/tui/dist/index.mjs +81 -65
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +23 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/integrations.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +8 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +30 -2
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +36 -3
- package/src/tui/session/turn.mjs +23 -2
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -158,8 +158,9 @@ function runtimePaths(verDir) {
|
|
|
158
158
|
// Download with retry
|
|
159
159
|
// ---------------------------------------------------------------------------
|
|
160
160
|
|
|
161
|
-
async function downloadWithRetry(url, destPath, expectedBytes) {
|
|
161
|
+
async function downloadWithRetry(url, destPath, expectedBytes, signal) {
|
|
162
162
|
return downloadToFileWithRetry(url, destPath, {
|
|
163
|
+
signal,
|
|
163
164
|
maxBytes: expectedBytes,
|
|
164
165
|
expectedBytes,
|
|
165
166
|
label: 'memory runtime download',
|
|
@@ -532,11 +533,12 @@ function publishRuntimeDir(runtimeBaseDir, stagingDir, key, sha256) {
|
|
|
532
533
|
* staging lock, ending with the stale-version GC. Returns the installed
|
|
533
534
|
* runtime-{version} directory.
|
|
534
535
|
*/
|
|
535
|
-
async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, version, pkey }) {
|
|
536
|
+
async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, version, pkey, signal }) {
|
|
536
537
|
// tar is only required for the download/extract path. Probe here (not at
|
|
537
538
|
// ensureRuntime entry) so a machine without tar can still reuse an
|
|
538
539
|
// already-extracted, sha-matching cached runtime via the fast path.
|
|
539
540
|
await probeTar();
|
|
541
|
+
signal?.throwIfAborted();
|
|
540
542
|
|
|
541
543
|
__mixdogMemoryLog(`[runtime-fetcher] downloading runtime ${version} for ${pkey} (~${size} bytes) …\n`);
|
|
542
544
|
|
|
@@ -566,7 +568,7 @@ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, versio
|
|
|
566
568
|
`[runtime-fetcher] retrying runtime download from fallback release repo — ${candidateUrl}\n`
|
|
567
569
|
);
|
|
568
570
|
}
|
|
569
|
-
await downloadWithRetry(candidateUrl, tarPath, size);
|
|
571
|
+
await downloadWithRetry(candidateUrl, tarPath, size, signal);
|
|
570
572
|
await verifySha256(tarPath, sha256);
|
|
571
573
|
downloadOk = true;
|
|
572
574
|
break;
|
|
@@ -575,9 +577,12 @@ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, versio
|
|
|
575
577
|
try {
|
|
576
578
|
rmSync(tarPath, { force: true });
|
|
577
579
|
} catch {}
|
|
580
|
+
// A cancelled install tries no fallback repository.
|
|
581
|
+
signal?.throwIfAborted();
|
|
578
582
|
}
|
|
579
583
|
}
|
|
580
584
|
if (!downloadOk && lastDownloadErr) throw lastDownloadErr;
|
|
585
|
+
signal?.throwIfAborted();
|
|
581
586
|
await _extractRuntimeTarGz(tarPath, stagingDir, stagingDir);
|
|
582
587
|
} finally {
|
|
583
588
|
try {
|
|
@@ -591,6 +596,11 @@ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, versio
|
|
|
591
596
|
} catch {}
|
|
592
597
|
throw new Error(`[runtime-fetcher] download or verify failed for ${version}`);
|
|
593
598
|
}
|
|
599
|
+
// Cancelled after the extract: drop the unpublished tree, publish nothing.
|
|
600
|
+
if (signal?.aborted) {
|
|
601
|
+
rmSync(stagingDir, { recursive: true, force: true });
|
|
602
|
+
signal.throwIfAborted();
|
|
603
|
+
}
|
|
594
604
|
|
|
595
605
|
// Stamp sha256 inside staging dir.
|
|
596
606
|
writeFileAtomicSync(join(stagingDir, '.version-sha256'), sha256);
|
|
@@ -615,6 +625,11 @@ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, versio
|
|
|
615
625
|
gcRuntimeDir(runtimeBaseDir, key);
|
|
616
626
|
} finally {
|
|
617
627
|
releaseStagingLock(stagingLock);
|
|
628
|
+
// Publishing is synchronous past the last cancellation check, so an
|
|
629
|
+
// aborted signal here means nothing was published.
|
|
630
|
+
if (signal?.aborted) {
|
|
631
|
+
__mixdogMemoryLog(`[runtime-fetcher] install of ${version} cancelled; its staging was removed\n`);
|
|
632
|
+
}
|
|
618
633
|
}
|
|
619
634
|
|
|
620
635
|
__mixdogMemoryLog(`[runtime-fetcher] runtime ready at ${verDir}\n`);
|
|
@@ -631,7 +646,10 @@ export const _runtimeLayoutInternals = {
|
|
|
631
646
|
runtimeInstallKey,
|
|
632
647
|
};
|
|
633
648
|
|
|
634
|
-
|
|
649
|
+
/** `signal` cancels a download/install in progress: its retry waits end, its
|
|
650
|
+
* partial files and staging lock are removed and nothing is published, so the
|
|
651
|
+
* next call starts a fresh install. */
|
|
652
|
+
export async function ensureRuntime(dataDir, { signal = null } = {}) {
|
|
635
653
|
const key = resolve(dataDir);
|
|
636
654
|
if (runtimeCache.has(key)) return runtimeCache.get(key);
|
|
637
655
|
|
|
@@ -655,7 +673,7 @@ export async function ensureRuntime(dataDir) {
|
|
|
655
673
|
|
|
656
674
|
const verDir =
|
|
657
675
|
cachedRuntimeDir(runtimeBaseDir, version, sha256) ??
|
|
658
|
-
(await installRuntimeVersion({ runtimeBaseDir, url, sha256, size, version, pkey }));
|
|
676
|
+
(await installRuntimeVersion({ runtimeBaseDir, url, sha256, size, version, pkey, signal }));
|
|
659
677
|
|
|
660
678
|
const result = { runtimeDir: verDir, ...runtimePaths(verDir), version };
|
|
661
679
|
runtimeCache.set(key, result);
|
|
@@ -39,6 +39,15 @@ function spawnPowerShell(script) {
|
|
|
39
39
|
);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// Resolves once the host process is gone. A signal-terminated child has exitCode null but signalCode set,
|
|
43
|
+
// and its 'close' may already have been emitted, so both are checked before waiting for the event.
|
|
44
|
+
export function hostExitSignal(child) {
|
|
45
|
+
return new Promise((done) => {
|
|
46
|
+
if (child.exitCode !== null || child.signalCode !== null) done();
|
|
47
|
+
else child.once('close', () => done());
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
42
51
|
async function callMicrosoftOfficeOnce(payload, { timeoutMs = DEFAULT_TIMEOUT_MS, signal = null } = {}) {
|
|
43
52
|
return await new Promise((resolve) => {
|
|
44
53
|
const child = spawnPowerShell(HOST_SCRIPT);
|
|
@@ -65,13 +74,20 @@ async function callMicrosoftOfficeOnce(payload, { timeoutMs = DEFAULT_TIMEOUT_MS
|
|
|
65
74
|
},
|
|
66
75
|
};
|
|
67
76
|
void drainSessionClient(client, error).then((cleanup) => {
|
|
68
|
-
|
|
77
|
+
const result = {
|
|
69
78
|
ok: false,
|
|
70
79
|
cancelled,
|
|
71
80
|
error: officeCleanupError(error, cleanup),
|
|
72
81
|
operationMayHaveCompleted: true,
|
|
73
82
|
cleanup,
|
|
83
|
+
};
|
|
84
|
+
// Settles when the host process is gone, which may be after this result when the
|
|
85
|
+
// grace period lapsed: callers that own files the host holds open wait on it.
|
|
86
|
+
// Non-enumerable so the result still serializes unchanged.
|
|
87
|
+
Object.defineProperty(result, 'hostExit', {
|
|
88
|
+
value: hostExitSignal(child),
|
|
74
89
|
});
|
|
90
|
+
finish(result);
|
|
75
91
|
});
|
|
76
92
|
};
|
|
77
93
|
const onAbort = () => beginCleanup('Microsoft Office operation was cancelled', true);
|
|
@@ -7545,6 +7545,52 @@ function Open-ValidationDocument($app, [string]$format, [string]$path) {
|
|
|
7545
7545
|
}
|
|
7546
7546
|
}
|
|
7547
7547
|
|
|
7548
|
+
$script:PreviewPasswordMessage = 'This file is password-protected. (OFFICE_PREVIEW_PASSWORD_PROTECTED)'
|
|
7549
|
+
|
|
7550
|
+
# An encrypted Office Open XML package is an OLE container (D0 CF 11 E0), not a ZIP. Office would stop to ask
|
|
7551
|
+
# for the password, and a hidden application cannot show the question, so the request is refused up front.
|
|
7552
|
+
function Assert-PreviewNotEncrypted([string]$path) {
|
|
7553
|
+
$extension = [System.IO.Path]::GetExtension($path).TrimStart('.').ToLowerInvariant()
|
|
7554
|
+
if (@('docx', 'docm', 'dotx', 'xlsx', 'xlsm', 'pptx', 'pptm') -notcontains $extension) { return }
|
|
7555
|
+
$header = New-Object byte[] 4
|
|
7556
|
+
$stream = [System.IO.File]::Open($path, 'Open', 'Read', 'ReadWrite')
|
|
7557
|
+
try { $read = $stream.Read($header, 0, 4) } finally { $stream.Dispose() }
|
|
7558
|
+
if ($read -eq 4 -and $header[0] -eq 0xD0 -and $header[1] -eq 0xCF -and $header[2] -eq 0x11 -and $header[3] -eq 0xE0) {
|
|
7559
|
+
throw $script:PreviewPasswordMessage
|
|
7560
|
+
}
|
|
7561
|
+
}
|
|
7562
|
+
|
|
7563
|
+
$script:PreviewWrongPasswordMessage = "That password didn't work. (OFFICE_PREVIEW_WRONG_PASSWORD)"
|
|
7564
|
+
|
|
7565
|
+
# The read-only open of the file preview. Word and Excel get the user's password when the request carries one
|
|
7566
|
+
# (Documents.Open PasswordDocument, Workbooks.Open Password), else a placeholder, so a protected legacy file fails
|
|
7567
|
+
# at once instead of waiting on a prompt nobody can see. Word's "password is incorrect" (0x800A1520) becomes the
|
|
7568
|
+
# plain message: the protected one without a password, the wrong-password one with it. Presentations.Open takes no
|
|
7569
|
+
# password, so PowerPoint never gets one. Links are not updated, macros stay off and DisplayAlerts is off
|
|
7570
|
+
# (New-HiddenApplication). Automation opens do not go through Protected View.
|
|
7571
|
+
function Open-PreviewDocument($app, [string]$format, [string]$path, [string]$password) {
|
|
7572
|
+
$placeholder = 'mixdog-preview-no-password'
|
|
7573
|
+
$openPassword = if ($password) { $password } else { $placeholder }
|
|
7574
|
+
try {
|
|
7575
|
+
switch ($format) {
|
|
7576
|
+
'docx' { return $app.Documents.Open($path, $false, $true, $false, $openPassword, $placeholder, $false, $placeholder, $placeholder) }
|
|
7577
|
+
# No WriteResPassword: Excel rejects one for a workbook without write reservation (0x800A03EC), and a
|
|
7578
|
+
# read-only open never asks for it.
|
|
7579
|
+
'xlsx' { return $app.Workbooks.Open($path, 0, $true, [Type]::Missing, $openPassword, [Type]::Missing, $true) }
|
|
7580
|
+
'pptx' { return $app.Presentations.Open($path, $true, $true, $false) }
|
|
7581
|
+
}
|
|
7582
|
+
}
|
|
7583
|
+
catch {
|
|
7584
|
+
$inner = $_.Exception
|
|
7585
|
+
while ($null -ne $inner.InnerException) { $inner = $inner.InnerException }
|
|
7586
|
+
if ($format -eq 'docx' -and $inner.HResult -eq 0x800A1520) {
|
|
7587
|
+
if ($password) { throw $script:PreviewWrongPasswordMessage }
|
|
7588
|
+
throw $script:PreviewPasswordMessage
|
|
7589
|
+
}
|
|
7590
|
+
throw
|
|
7591
|
+
}
|
|
7592
|
+
}
|
|
7593
|
+
|
|
7548
7594
|
function Validate-NativeDocument([string]$path, [string]$format) {
|
|
7549
7595
|
$validationApp = $null
|
|
7550
7596
|
$validationDocument = $null
|
|
@@ -7757,9 +7803,13 @@ try {
|
|
|
7757
7803
|
$live = $true
|
|
7758
7804
|
}
|
|
7759
7805
|
else {
|
|
7806
|
+
if ($payload.readOnly -eq $true) { Assert-PreviewNotEncrypted $path }
|
|
7760
7807
|
$app = New-HiddenApplication $format $progId
|
|
7761
7808
|
$createdApp = $true
|
|
7762
|
-
|
|
7809
|
+
# A read-only request (the file preview) opens the document read-only, with no link updates and no
|
|
7810
|
+
# recalculation, and never waits on a password prompt. The close below discards, so nothing can be
|
|
7811
|
+
# written back.
|
|
7812
|
+
$document = if ($payload.readOnly -eq $true) { Open-PreviewDocument $app $format $path ([string]$payload.password) } else { Open-BackgroundDocument $app $format $path }
|
|
7763
7813
|
}
|
|
7764
7814
|
|
|
7765
7815
|
switch ([string]$payload.action) {
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
// A minimal Compound File Binary ([MS-CFB]) writer for tests: real container structure (header, FAT, DIFAT, mini
|
|
2
|
+
// FAT, mini stream, directory with sibling trees), laid out the way Office writes it.
|
|
3
|
+
import { createCipheriv, createHash, createHmac, randomBytes } from 'node:crypto';
|
|
4
|
+
|
|
5
|
+
const END_OF_CHAIN = 0xfffffffe;
|
|
6
|
+
const FAT_SECTOR = 0xfffffffd;
|
|
7
|
+
const DIFAT_SECTOR = 0xfffffffc;
|
|
8
|
+
const NO_STREAM = 0xffffffff;
|
|
9
|
+
const MINI_SECTOR_SIZE = 64;
|
|
10
|
+
const MINI_STREAM_CUTOFF = 4096;
|
|
11
|
+
const HEADER_DIFAT_ENTRIES = 109;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Entries under the root storage: `{ name, data }` is a stream, `{ name, children }` a storage of further entries.
|
|
15
|
+
* `version` is the CFB major version: 3 (512-byte sectors) or 4 (4096-byte sectors).
|
|
16
|
+
*/
|
|
17
|
+
export function buildCfb(entries, { version = 3 } = {}) {
|
|
18
|
+
const sectorSize = version === 4 ? 4096 : 512;
|
|
19
|
+
const entriesPerSector = sectorSize / 4;
|
|
20
|
+
const root = { name: 'Root Entry', type: 5, children: entries };
|
|
21
|
+
|
|
22
|
+
// Directory ids in storage order, root first; the siblings under each storage form one balanced tree.
|
|
23
|
+
const nodes = [];
|
|
24
|
+
const register = (node) => {
|
|
25
|
+
node.id = nodes.length;
|
|
26
|
+
nodes.push(node);
|
|
27
|
+
for (const child of node.children ?? []) register(child);
|
|
28
|
+
};
|
|
29
|
+
register(root);
|
|
30
|
+
const link = (siblings) => {
|
|
31
|
+
const ordered = [...siblings].sort(
|
|
32
|
+
(a, b) => a.name.length - b.name.length || (a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1)
|
|
33
|
+
);
|
|
34
|
+
const build = (low, high) => {
|
|
35
|
+
if (low > high) return NO_STREAM;
|
|
36
|
+
const middle = (low + high) >> 1;
|
|
37
|
+
const node = ordered[middle];
|
|
38
|
+
node.left = build(low, middle - 1);
|
|
39
|
+
node.right = build(middle + 1, high);
|
|
40
|
+
return node.id;
|
|
41
|
+
};
|
|
42
|
+
return build(0, ordered.length - 1);
|
|
43
|
+
};
|
|
44
|
+
for (const node of nodes) {
|
|
45
|
+
node.left ??= NO_STREAM;
|
|
46
|
+
node.right ??= NO_STREAM;
|
|
47
|
+
node.type ??= node.children ? 1 : 2;
|
|
48
|
+
if (node.children) node.child = link(node.children);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const sectors = [];
|
|
52
|
+
const fat = [];
|
|
53
|
+
const allocate = (bytes) => {
|
|
54
|
+
const count = Math.ceil(bytes.length / sectorSize);
|
|
55
|
+
const start = sectors.length;
|
|
56
|
+
for (let i = 0; i < count; i++) {
|
|
57
|
+
const sector = Buffer.alloc(sectorSize);
|
|
58
|
+
bytes.copy(sector, 0, i * sectorSize, (i + 1) * sectorSize);
|
|
59
|
+
sectors.push(sector);
|
|
60
|
+
fat.push(i === count - 1 ? END_OF_CHAIN : sectors.length);
|
|
61
|
+
}
|
|
62
|
+
return count ? start : END_OF_CHAIN;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const miniStreams = [];
|
|
66
|
+
const miniFat = [];
|
|
67
|
+
for (const node of nodes) {
|
|
68
|
+
if (node.type !== 2) continue;
|
|
69
|
+
node.size = node.data.length;
|
|
70
|
+
if (node.size >= MINI_STREAM_CUTOFF) {
|
|
71
|
+
node.start = allocate(node.data);
|
|
72
|
+
} else if (node.size === 0) {
|
|
73
|
+
node.start = END_OF_CHAIN;
|
|
74
|
+
} else {
|
|
75
|
+
const count = Math.ceil(node.size / MINI_SECTOR_SIZE);
|
|
76
|
+
node.start = miniFat.length;
|
|
77
|
+
for (let i = 0; i < count; i++) miniFat.push(i === count - 1 ? END_OF_CHAIN : miniFat.length + 1);
|
|
78
|
+
miniStreams.push(Buffer.concat([node.data, Buffer.alloc(count * MINI_SECTOR_SIZE - node.size)]));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const miniStream = Buffer.concat(miniStreams);
|
|
82
|
+
root.size = miniStream.length;
|
|
83
|
+
root.start = allocate(miniStream);
|
|
84
|
+
|
|
85
|
+
const miniFatBytes = Buffer.alloc(Math.ceil(miniFat.length / entriesPerSector) * entriesPerSector * 4, 0xff);
|
|
86
|
+
miniFat.forEach((next, i) => {
|
|
87
|
+
miniFatBytes.writeUInt32LE(next, i * 4);
|
|
88
|
+
});
|
|
89
|
+
const miniFatStart = allocate(miniFatBytes);
|
|
90
|
+
|
|
91
|
+
const directoryBytes = Buffer.alloc(Math.ceil(nodes.length / (sectorSize / 128)) * sectorSize);
|
|
92
|
+
directoryBytes.fill(0xff, 0, directoryBytes.length);
|
|
93
|
+
nodes.forEach((node, i) => {
|
|
94
|
+
const at = i * 128;
|
|
95
|
+
directoryBytes.fill(0, at, at + 128);
|
|
96
|
+
directoryBytes.write(node.name, at, 'utf16le');
|
|
97
|
+
directoryBytes.writeUInt16LE((node.name.length + 1) * 2, at + 64);
|
|
98
|
+
directoryBytes[at + 66] = node.type;
|
|
99
|
+
directoryBytes[at + 67] = 1;
|
|
100
|
+
directoryBytes.writeUInt32LE(node.left, at + 68);
|
|
101
|
+
directoryBytes.writeUInt32LE(node.right, at + 72);
|
|
102
|
+
directoryBytes.writeUInt32LE(node.child ?? NO_STREAM, at + 76);
|
|
103
|
+
directoryBytes.writeUInt32LE(node.start ?? 0, at + 116);
|
|
104
|
+
directoryBytes.writeUInt32LE(node.size ?? 0, at + 120);
|
|
105
|
+
});
|
|
106
|
+
// Entries past the last one are unallocated: type 0, with every id unset.
|
|
107
|
+
for (let at = nodes.length * 128; at < directoryBytes.length; at += 128) directoryBytes.fill(0, at, at + 68);
|
|
108
|
+
const directoryStart = allocate(directoryBytes);
|
|
109
|
+
|
|
110
|
+
// The FAT describes every sector including its own and the DIFAT's, so their counts settle together.
|
|
111
|
+
let fatCount = 0;
|
|
112
|
+
let difatCount = 0;
|
|
113
|
+
while (fatCount * entriesPerSector < fat.length + fatCount + difatCount) {
|
|
114
|
+
fatCount++;
|
|
115
|
+
difatCount =
|
|
116
|
+
fatCount > HEADER_DIFAT_ENTRIES ? Math.ceil((fatCount - HEADER_DIFAT_ENTRIES) / (entriesPerSector - 1)) : 0;
|
|
117
|
+
}
|
|
118
|
+
const fatSectorIds = Array.from({ length: fatCount }, (_, i) => sectors.length + i);
|
|
119
|
+
const difatSectorIds = Array.from({ length: difatCount }, (_, i) => sectors.length + fatCount + i);
|
|
120
|
+
const fatEntries = [...fat, ...fatSectorIds.map(() => FAT_SECTOR), ...difatSectorIds.map(() => DIFAT_SECTOR)];
|
|
121
|
+
const fatBytes = Buffer.alloc(fatCount * sectorSize, 0xff);
|
|
122
|
+
fatEntries.forEach((next, i) => {
|
|
123
|
+
fatBytes.writeUInt32LE(next, i * 4);
|
|
124
|
+
});
|
|
125
|
+
for (let i = 0; i < fatCount; i++) sectors.push(fatBytes.subarray(i * sectorSize, (i + 1) * sectorSize));
|
|
126
|
+
const beyondHeader = fatSectorIds.slice(HEADER_DIFAT_ENTRIES);
|
|
127
|
+
for (let i = 0; i < difatCount; i++) {
|
|
128
|
+
const sector = Buffer.alloc(sectorSize, 0xff);
|
|
129
|
+
beyondHeader.slice(i * (entriesPerSector - 1), (i + 1) * (entriesPerSector - 1)).forEach((id, j) => {
|
|
130
|
+
sector.writeUInt32LE(id, j * 4);
|
|
131
|
+
});
|
|
132
|
+
sector.writeUInt32LE(i === difatCount - 1 ? END_OF_CHAIN : difatSectorIds[i + 1], sectorSize - 4);
|
|
133
|
+
sectors.push(sector);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const header = Buffer.alloc(sectorSize);
|
|
137
|
+
Buffer.from([0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1]).copy(header, 0);
|
|
138
|
+
header.writeUInt16LE(0x3e, 24);
|
|
139
|
+
header.writeUInt16LE(version, 26);
|
|
140
|
+
header.writeUInt16LE(0xfffe, 28);
|
|
141
|
+
header.writeUInt16LE(version === 4 ? 12 : 9, 30);
|
|
142
|
+
header.writeUInt16LE(6, 32);
|
|
143
|
+
header.writeUInt32LE(version === 4 ? directoryBytes.length / sectorSize : 0, 40);
|
|
144
|
+
header.writeUInt32LE(fatCount, 44);
|
|
145
|
+
header.writeUInt32LE(directoryStart, 48);
|
|
146
|
+
header.writeUInt32LE(MINI_STREAM_CUTOFF, 56);
|
|
147
|
+
header.writeUInt32LE(miniFatStart, 60);
|
|
148
|
+
header.writeUInt32LE(miniFatBytes.length / sectorSize, 64);
|
|
149
|
+
header.writeUInt32LE(difatCount ? difatSectorIds[0] : END_OF_CHAIN, 68);
|
|
150
|
+
header.writeUInt32LE(difatCount, 72);
|
|
151
|
+
header.fill(0xff, 76, 512);
|
|
152
|
+
fatSectorIds.slice(0, HEADER_DIFAT_ENTRIES).forEach((id, i) => {
|
|
153
|
+
header.writeUInt32LE(id, 76 + i * 4);
|
|
154
|
+
});
|
|
155
|
+
return Buffer.concat([header, ...sectors]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** The root-level streams of an encrypted OOXML document ([MS-OFFCRYPTO] 2.3.4), with the given ciphertext size. */
|
|
159
|
+
export function encryptedOoxmlEntries(packageBytes = 5000) {
|
|
160
|
+
return [
|
|
161
|
+
{ name: 'EncryptionInfo', data: Buffer.from([4, 0, 4, 0, 0x40, 0, 0, 0, ...Buffer.from('<encryption/>')]) },
|
|
162
|
+
{ name: 'EncryptedPackage', data: Buffer.concat([Buffer.alloc(8), Buffer.alloc(packageBytes, 0x5a)]) },
|
|
163
|
+
{
|
|
164
|
+
name: '\u0006DataSpaces',
|
|
165
|
+
children: [
|
|
166
|
+
{ name: 'Version', data: Buffer.alloc(76) },
|
|
167
|
+
{ name: 'DataSpaceMap', data: Buffer.alloc(112) },
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const sha = (algorithm, ...parts) => {
|
|
174
|
+
const digest = createHash(algorithm);
|
|
175
|
+
for (const part of parts) digest.update(part);
|
|
176
|
+
return digest.digest();
|
|
177
|
+
};
|
|
178
|
+
const le32 = (value) => {
|
|
179
|
+
const bytes = Buffer.alloc(4);
|
|
180
|
+
bytes.writeUInt32LE(value, 0);
|
|
181
|
+
return bytes;
|
|
182
|
+
};
|
|
183
|
+
const padTo = (bytes, block) => Buffer.concat([bytes, Buffer.alloc((block - (bytes.length % block)) % block)]);
|
|
184
|
+
const aes = (mode, key, iv, data) => {
|
|
185
|
+
const cipher = createCipheriv(`aes-${key.length * 8}-${mode}`, key, iv);
|
|
186
|
+
cipher.setAutoPadding(false);
|
|
187
|
+
return Buffer.concat([cipher.update(data), cipher.final()]);
|
|
188
|
+
};
|
|
189
|
+
const spun = (algorithm, salt, password, count) => {
|
|
190
|
+
let value = sha(algorithm, salt, Buffer.from(password, 'utf16le'));
|
|
191
|
+
for (let i = 0; i < count; i++) value = sha(algorithm, le32(i), value);
|
|
192
|
+
return value;
|
|
193
|
+
};
|
|
194
|
+
const withSize = (plain, ciphertext) => {
|
|
195
|
+
const size = Buffer.alloc(8);
|
|
196
|
+
size.writeBigUInt64LE(BigInt(plain.length), 0);
|
|
197
|
+
return Buffer.concat([size, ciphertext]);
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// 2.3.4.10 HashAlgorithm values the fixture writes, with their OpenSSL names.
|
|
201
|
+
const AGILE_HASHES = { 'SHA-1': 'sha1', SHA1: 'sha1', SHA256: 'sha256', SHA384: 'sha384', SHA512: 'sha512' };
|
|
202
|
+
// Truncated to, or padded with 0x36 up to, `length` bytes (2.3.4.11, 2.3.4.12).
|
|
203
|
+
const fitted = (bytes, length) =>
|
|
204
|
+
bytes.length >= length
|
|
205
|
+
? bytes.subarray(0, length)
|
|
206
|
+
: Buffer.concat([bytes, Buffer.alloc(length - bytes.length, 0x36)]);
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* The root-level streams of `plain` encrypted with `password` the way Office writes it, following [MS-OFFCRYPTO]
|
|
210
|
+
* in the encrypting direction: agile encryption (2.3.4.10–2.3.4.15, AES-256-CBC, SHA-512 or `hashAlgorithm`) by
|
|
211
|
+
* default, or standard encryption (2.3.4.5–2.3.4.9, AES-128-ECB, SHA-1). `spinCount` is lowered for agile tests to
|
|
212
|
+
* keep them fast. The keyData salt is `keySaltSize` bytes. Agile encryption carries dataIntegrity (2.3.4.14) unless
|
|
213
|
+
* `integrity` is false, its HMAC key a salt of `hmacSaltSize` bytes: hashSize, as Excel writes it, unless given.
|
|
214
|
+
*/
|
|
215
|
+
export function encryptOoxmlEntries(
|
|
216
|
+
plain,
|
|
217
|
+
password,
|
|
218
|
+
{
|
|
219
|
+
scheme = 'agile',
|
|
220
|
+
spinCount = 1000,
|
|
221
|
+
hashAlgorithm = 'SHA512',
|
|
222
|
+
keySaltSize = 16,
|
|
223
|
+
integrity = true,
|
|
224
|
+
hmacSaltSize,
|
|
225
|
+
} = {}
|
|
226
|
+
) {
|
|
227
|
+
let encryptionInfo;
|
|
228
|
+
let encryptedPackage;
|
|
229
|
+
if (scheme === 'agile') {
|
|
230
|
+
const algorithm = AGILE_HASHES[hashAlgorithm];
|
|
231
|
+
const hashSize = sha(algorithm).length;
|
|
232
|
+
const secret = randomBytes(32);
|
|
233
|
+
const keySalt = randomBytes(keySaltSize);
|
|
234
|
+
const passwordSalt = randomBytes(16);
|
|
235
|
+
const hashed = spun(algorithm, passwordSalt, password, spinCount);
|
|
236
|
+
const keyFor = (block) => fitted(sha(algorithm, hashed, Buffer.from(block)), 32);
|
|
237
|
+
const verifierInput = randomBytes(16);
|
|
238
|
+
const encrypted = (block, data) => aes('cbc', keyFor(block), passwordSalt, padTo(data, 16)).toString('base64');
|
|
239
|
+
const segments = [];
|
|
240
|
+
for (let offset = 0, index = 0; offset < plain.length; offset += 4096, index++) {
|
|
241
|
+
const iv = fitted(sha(algorithm, keySalt, le32(index)), 16);
|
|
242
|
+
segments.push(aes('cbc', secret, iv, padTo(plain.subarray(offset, offset + 4096), 16)));
|
|
243
|
+
}
|
|
244
|
+
encryptedPackage = withSize(plain, Buffer.concat(segments));
|
|
245
|
+
// 2.3.4.14: an HMAC of the whole stream keyed by a random salt, both encrypted with the package key.
|
|
246
|
+
const sealed = (block, data) =>
|
|
247
|
+
aes('cbc', secret, fitted(sha(algorithm, keySalt, Buffer.from(block)), 16), padTo(data, 16)).toString('base64');
|
|
248
|
+
const hmacSalt = randomBytes(hmacSaltSize ?? hashSize);
|
|
249
|
+
const hmac = createHmac(algorithm, hmacSalt).update(encryptedPackage).digest();
|
|
250
|
+
const dataIntegrity = integrity
|
|
251
|
+
? `<dataIntegrity encryptedHmacKey="${sealed([0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, 0xf6], hmacSalt)}"` +
|
|
252
|
+
` encryptedHmacValue="${sealed([0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, 0x33], hmac)}"/>`
|
|
253
|
+
: '';
|
|
254
|
+
const cipher = `blockSize="16" keyBits="256" hashSize="${hashSize}" cipherAlgorithm="AES" cipherChaining="ChainingModeCBC" hashAlgorithm="${hashAlgorithm}"`;
|
|
255
|
+
const xml =
|
|
256
|
+
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n` +
|
|
257
|
+
`<encryption xmlns="http://schemas.microsoft.com/office/2006/encryption" xmlns:p="http://schemas.microsoft.com/office/2006/keyEncryptor/password">` +
|
|
258
|
+
`<keyData saltSize="${keySaltSize}" ${cipher} saltValue="${keySalt.toString('base64')}"/>` +
|
|
259
|
+
dataIntegrity +
|
|
260
|
+
`<keyEncryptors><keyEncryptor uri="http://schemas.microsoft.com/office/2006/keyEncryptor/password">` +
|
|
261
|
+
`<p:encryptedKey spinCount="${spinCount}" saltSize="16" ${cipher} saltValue="${passwordSalt.toString('base64')}"` +
|
|
262
|
+
` encryptedVerifierHashInput="${encrypted([0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79], verifierInput)}"` +
|
|
263
|
+
` encryptedVerifierHashValue="${encrypted([0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e], sha(algorithm, verifierInput))}"` +
|
|
264
|
+
` encryptedKeyValue="${encrypted([0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6], secret)}"/>` +
|
|
265
|
+
`</keyEncryptor></keyEncryptors></encryption>`;
|
|
266
|
+
encryptionInfo = Buffer.concat([Buffer.from([4, 0, 4, 0, 0x40, 0, 0, 0]), Buffer.from(xml, 'utf8')]);
|
|
267
|
+
} else {
|
|
268
|
+
const salt = randomBytes(16);
|
|
269
|
+
const final = sha('sha1', spun('sha1', salt, password, 50_000), le32(0));
|
|
270
|
+
const derive = (fill) => {
|
|
271
|
+
const buffer = Buffer.alloc(64, fill);
|
|
272
|
+
for (let i = 0; i < final.length; i++) buffer[i] ^= final[i];
|
|
273
|
+
return sha('sha1', buffer);
|
|
274
|
+
};
|
|
275
|
+
const key = Buffer.concat([derive(0x36), derive(0x5c)]).subarray(0, 16);
|
|
276
|
+
const verifier = randomBytes(16);
|
|
277
|
+
const csp = Buffer.from('Microsoft Enhanced RSA and AES Cryptographic Provider\0', 'utf16le');
|
|
278
|
+
const header = Buffer.concat([...[0x24, 0, 0x660e, 0x8004, 128, 0x18, 0, 0].map(le32), csp]);
|
|
279
|
+
encryptionInfo = Buffer.concat([
|
|
280
|
+
Buffer.from([3, 0, 2, 0]),
|
|
281
|
+
le32(0x24),
|
|
282
|
+
le32(header.length),
|
|
283
|
+
header,
|
|
284
|
+
le32(16),
|
|
285
|
+
salt,
|
|
286
|
+
aes('ecb', key, null, verifier),
|
|
287
|
+
le32(20),
|
|
288
|
+
aes('ecb', key, null, padTo(sha('sha1', verifier), 16)),
|
|
289
|
+
]);
|
|
290
|
+
encryptedPackage = withSize(plain, aes('ecb', key, null, padTo(plain, 16)));
|
|
291
|
+
}
|
|
292
|
+
return [
|
|
293
|
+
{ name: 'EncryptionInfo', data: encryptionInfo },
|
|
294
|
+
{ name: 'EncryptedPackage', data: encryptedPackage },
|
|
295
|
+
{
|
|
296
|
+
name: '\u0006DataSpaces',
|
|
297
|
+
children: [
|
|
298
|
+
{ name: 'Version', data: Buffer.alloc(76) },
|
|
299
|
+
{ name: 'DataSpaceMap', data: Buffer.alloc(112) },
|
|
300
|
+
],
|
|
301
|
+
},
|
|
302
|
+
];
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/** A binary Word document's "WordDocument" stream whose FibBase ([MS-DOC] 2.5.1) has fEncrypted set or clear. */
|
|
306
|
+
export function wordDocumentStream(encrypted) {
|
|
307
|
+
const data = Buffer.alloc(6000, 3);
|
|
308
|
+
data.writeUInt16LE(0xa5ec, 0);
|
|
309
|
+
data.writeUInt16LE(0x00c1, 2);
|
|
310
|
+
data.writeUInt16LE(encrypted ? 0x0100 | 0x0200 : 0x0200, 10);
|
|
311
|
+
return { name: 'WordDocument', data };
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** A "Current User" stream holding a CurrentUserAtom ([MS-PPT] 2.3.2) with this headerToken. */
|
|
315
|
+
export function currentUserStream(headerToken, userName = 'Mixdog') {
|
|
316
|
+
const name = Buffer.from(userName, 'latin1');
|
|
317
|
+
const atom = Buffer.alloc(28 + name.length + 4);
|
|
318
|
+
atom.writeUInt16LE(0x0ff6, 2);
|
|
319
|
+
atom.writeUInt32LE(atom.length - 8, 4);
|
|
320
|
+
atom.writeUInt32LE(0x14, 8);
|
|
321
|
+
atom.writeUInt32LE(headerToken, 12);
|
|
322
|
+
atom.writeUInt16LE(name.length, 20);
|
|
323
|
+
atom.writeUInt16LE(0x03f4, 22);
|
|
324
|
+
atom[24] = 3;
|
|
325
|
+
name.copy(atom, 28);
|
|
326
|
+
atom.writeUInt32LE(8, 28 + name.length);
|
|
327
|
+
return { name: 'Current User', data: atom };
|
|
328
|
+
}
|