codetrellis 0.0.0-stage → 0.2.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/LICENSE +201 -0
- package/README.md +27 -2
- package/bin/codetrellis.mjs +4 -0
- package/package.json +43 -4
- package/reader/material-reader.mjs +130346 -0
- package/resources/tree-sitter/README.md +150 -0
- package/resources/tree-sitter/tree-sitter-c-sharp.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-go.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-java.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-javascript.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-kotlin.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-php.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-python.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-ruby.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-rust.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-swift.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-tsx.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-typescript.wasm +0 -0
- package/resources/tree-sitter/tree-sitter.wasm +0 -0
- package/src/backend/agent/claude-code-watcher.js +270 -0
- package/src/backend/index.js +8 -0
- package/src/backend/lib/sha256-file.js +39 -0
- package/src/backend/lib/zip-entries.js +98 -0
- package/src/backend/lifecycle.js +102 -0
- package/src/backend/mcp/binding-headers.js +54 -0
- package/src/backend/mcp/client-identity.js +44 -0
- package/src/backend/mcp/connector/command.js +110 -0
- package/src/backend/mcp/connector/core.js +278 -0
- package/src/backend/mcp/connector/files.js +121 -0
- package/src/backend/mcp/connector/hook.js +284 -0
- package/src/backend/mcp/connector/main.js +126 -0
- package/src/backend/mcp/connector/sse-upstream.js +152 -0
- package/src/backend/mcp/helpers.js +43 -0
- package/src/backend/mcp/prompt-builders.js +104 -0
- package/src/backend/mcp/resources.js +197 -0
- package/src/backend/mcp/server.js +813 -0
- package/src/backend/mcp/skill-guide.js +1528 -0
- package/src/backend/mcp/tools/architecture-tools.js +273 -0
- package/src/backend/mcp/tools/audio-tools.js +117 -0
- package/src/backend/mcp/tools/awareness-tools.js +623 -0
- package/src/backend/mcp/tools/budget-tools.js +185 -0
- package/src/backend/mcp/tools/channel-tools.js +205 -0
- package/src/backend/mcp/tools/contribution-tools.js +181 -0
- package/src/backend/mcp/tools/drift-tools.js +252 -0
- package/src/backend/mcp/tools/git-tools.js +316 -0
- package/src/backend/mcp/tools/governance-tools.js +175 -0
- package/src/backend/mcp/tools/graph-tools.js +181 -0
- package/src/backend/mcp/tools/intake-tools.js +244 -0
- package/src/backend/mcp/tools/mobile-tools.js +118 -0
- package/src/backend/mcp/tools/peer-tools.js +330 -0
- package/src/backend/mcp/tools/plan-item-tools.js +1601 -0
- package/src/backend/mcp/tools/plan-tools.js +680 -0
- package/src/backend/mcp/tools/presence-tools.js +185 -0
- package/src/backend/mcp/tools/project-config-tools.js +150 -0
- package/src/backend/mcp/tools/review-tools.js +172 -0
- package/src/backend/mcp/tools/session-tools.js +554 -0
- package/src/backend/mcp/tools/system-docs-tools.js +168 -0
- package/src/backend/mcp/tools/terminal-tools.js +186 -0
- package/src/backend/mcp/tools/test-tools.js +117 -0
- package/src/backend/mcp/tools/ui-tools.js +356 -0
- package/src/backend/mcp/types.js +15 -0
- package/src/backend/middleware/local-auth.js +116 -0
- package/src/backend/server.js +5951 -0
- package/src/backend/services/agent-event-log.js +350 -0
- package/src/backend/services/architecture-rule.js +584 -0
- package/src/backend/services/architecture-rules.js +275 -0
- package/src/backend/services/artefact-content-service.js +181 -0
- package/src/backend/services/artefact-service.js +305 -0
- package/src/backend/services/artefact-watcher.js +167 -0
- package/src/backend/services/ast-parser.js +327 -0
- package/src/backend/services/audio-buffer-service.js +152 -0
- package/src/backend/services/awareness-notices.js +139 -0
- package/src/backend/services/awareness-replies.js +194 -0
- package/src/backend/services/awareness-service.js +344 -0
- package/src/backend/services/awareness-signals.js +267 -0
- package/src/backend/services/baseline-store.js +83 -0
- package/src/backend/services/branch-workstreams.js +341 -0
- package/src/backend/services/breakpoint-service.js +584 -0
- package/src/backend/services/brief-service.js +299 -0
- package/src/backend/services/budget-service.js +528 -0
- package/src/backend/services/callsites/base.js +15 -0
- package/src/backend/services/callsites/csharp.js +148 -0
- package/src/backend/services/callsites/go.js +163 -0
- package/src/backend/services/callsites/index.js +53 -0
- package/src/backend/services/callsites/kotlin.js +123 -0
- package/src/backend/services/callsites/process-env.js +125 -0
- package/src/backend/services/callsites/python.js +91 -0
- package/src/backend/services/callsites/ruby.js +164 -0
- package/src/backend/services/callsites/shared.js +198 -0
- package/src/backend/services/callsites/swift.js +115 -0
- package/src/backend/services/callsites/typescript.js +87 -0
- package/src/backend/services/capability-token.js +108 -0
- package/src/backend/services/change-check.js +156 -0
- package/src/backend/services/channel-dispatcher-service.js +235 -0
- package/src/backend/services/channel-event-file-service.js +125 -0
- package/src/backend/services/channel-event-service.js +297 -0
- package/src/backend/services/check-runs.js +177 -0
- package/src/backend/services/checkout-identity.js +73 -0
- package/src/backend/services/claude-code-parallel.js +221 -0
- package/src/backend/services/claude-desktop-config.js +186 -0
- package/src/backend/services/clock.js +57 -0
- package/src/backend/services/cloud-files.js +191 -0
- package/src/backend/services/coalesce.js +50 -0
- package/src/backend/services/code-breakpoints.js +291 -0
- package/src/backend/services/comment-service.js +168 -0
- package/src/backend/services/commit-attribution.js +134 -0
- package/src/backend/services/commit-edges.js +99 -0
- package/src/backend/services/confined-fs.js +241 -0
- package/src/backend/services/conformity-gate.js +132 -0
- package/src/backend/services/contribution-service.js +409 -0
- package/src/backend/services/coverage-service.js +173 -0
- package/src/backend/services/criteria-service.js +721 -0
- package/src/backend/services/criterion-checks.js +387 -0
- package/src/backend/services/criterion-loop-service.js +411 -0
- package/src/backend/services/cross-system-service.js +231 -0
- package/src/backend/services/database.js +916 -0
- package/src/backend/services/db-schema.js +1358 -0
- package/src/backend/services/deviation-service.js +344 -0
- package/src/backend/services/diff-engine.js +168 -0
- package/src/backend/services/evidence.js +363 -0
- package/src/backend/services/external-intake-service.js +269 -0
- package/src/backend/services/external-pointer-service.js +195 -0
- package/src/backend/services/external-refs-service.js +214 -0
- package/src/backend/services/file-history.js +158 -0
- package/src/backend/services/file-watcher.js +193 -0
- package/src/backend/services/folder-requests.js +118 -0
- package/src/backend/services/freeze-service.js +189 -0
- package/src/backend/services/gemini-cli-hook.js +172 -0
- package/src/backend/services/git-activity-service.js +325 -0
- package/src/backend/services/git-blobs.js +70 -0
- package/src/backend/services/git-branches.js +357 -0
- package/src/backend/services/git-checkout.js +153 -0
- package/src/backend/services/git-commit-service.js +91 -0
- package/src/backend/services/git-env.js +121 -0
- package/src/backend/services/git-identity.js +84 -0
- package/src/backend/services/git-refs.js +386 -0
- package/src/backend/services/git-safety.js +58 -0
- package/src/backend/services/grant-guard.js +67 -0
- package/src/backend/services/html-view-policy.js +135 -0
- package/src/backend/services/human-decision.js +55 -0
- package/src/backend/services/importers.js +159 -0
- package/src/backend/services/intent-service.js +105 -0
- package/src/backend/services/ipc-dispatcher.js +164 -0
- package/src/backend/services/item-git-state.js +208 -0
- package/src/backend/services/line-changes.js +232 -0
- package/src/backend/services/line-history.js +174 -0
- package/src/backend/services/local-api-changes.js +40 -0
- package/src/backend/services/logger.js +217 -0
- package/src/backend/services/material-footprints.js +203 -0
- package/src/backend/services/material-place.js +82 -0
- package/src/backend/services/material-reader/child.js +4 -0
- package/src/backend/services/material-reader/docx-markdown.js +198 -0
- package/src/backend/services/material-reader/fixtures.test-helper.js +169 -0
- package/src/backend/services/material-reader/quote.js +44 -0
- package/src/backend/services/material-reader/read.js +430 -0
- package/src/backend/services/material-reader/reader-host.js +202 -0
- package/src/backend/services/material-signals.js +141 -0
- package/src/backend/services/mcp-capabilities.js +390 -0
- package/src/backend/services/mdns-service.js +304 -0
- package/src/backend/services/mobile-api-server.js +281 -0
- package/src/backend/services/mobile-approvals.js +306 -0
- package/src/backend/services/mobile-awareness.js +180 -0
- package/src/backend/services/mobile-breakpoints.js +115 -0
- package/src/backend/services/mobile-budget.js +98 -0
- package/src/backend/services/mobile-freeze.js +106 -0
- package/src/backend/services/mobile-proposals.js +100 -0
- package/src/backend/services/mobile-rpc-service.js +1289 -0
- package/src/backend/services/mobile-workstreams.js +160 -0
- package/src/backend/services/monorepo-detector.js +131 -0
- package/src/backend/services/other-work.js +45 -0
- package/src/backend/services/pack-seal.js +129 -0
- package/src/backend/services/paired-device-service.js +192 -0
- package/src/backend/services/pairing-server.js +323 -0
- package/src/backend/services/pairing-service.js +200 -0
- package/src/backend/services/pantry-resolution-service.js +166 -0
- package/src/backend/services/parsers/base.js +124 -0
- package/src/backend/services/parsers/csharp.js +224 -0
- package/src/backend/services/parsers/go.js +180 -0
- package/src/backend/services/parsers/index.js +101 -0
- package/src/backend/services/parsers/java.js +103 -0
- package/src/backend/services/parsers/kotlin.js +252 -0
- package/src/backend/services/parsers/php.js +113 -0
- package/src/backend/services/parsers/python.js +189 -0
- package/src/backend/services/parsers/ruby.js +212 -0
- package/src/backend/services/parsers/rust.js +97 -0
- package/src/backend/services/parsers/swift.js +221 -0
- package/src/backend/services/parsers/typescript.js +235 -0
- package/src/backend/services/pattern-scan.js +65 -0
- package/src/backend/services/patterns.js +281 -0
- package/src/backend/services/peer-audit-service.js +123 -0
- package/src/backend/services/peer-auth.js +153 -0
- package/src/backend/services/peer-capabilities.js +209 -0
- package/src/backend/services/peer-connection-service.js +450 -0
- package/src/backend/services/peer-grants.js +33 -0
- package/src/backend/services/persistence.js +116 -0
- package/src/backend/services/personal-sync-service.js +232 -0
- package/src/backend/services/pipeline-approvals.js +72 -0
- package/src/backend/services/pipeline.js +232 -0
- package/src/backend/services/plan-arrivals.js +68 -0
- package/src/backend/services/plan-changes-service.js +273 -0
- package/src/backend/services/plan-conflict-service.js +288 -0
- package/src/backend/services/plan-dependencies.js +91 -0
- package/src/backend/services/plan-doc-guard.js +90 -0
- package/src/backend/services/plan-documents-service.js +275 -0
- package/src/backend/services/plan-event-service.js +154 -0
- package/src/backend/services/plan-file-refs.js +106 -0
- package/src/backend/services/plan-file-service.js +1564 -0
- package/src/backend/services/plan-history-service.js +156 -0
- package/src/backend/services/plan-import-service.js +261 -0
- package/src/backend/services/plan-item-service.js +1223 -0
- package/src/backend/services/plan-migrate-service.js +395 -0
- package/src/backend/services/plan-overlay-service.js +173 -0
- package/src/backend/services/plan-phases-service.js +182 -0
- package/src/backend/services/plan-progress-service.js +134 -0
- package/src/backend/services/plan-review-service.js +262 -0
- package/src/backend/services/plan-service.js +682 -0
- package/src/backend/services/plan-status.js +113 -0
- package/src/backend/services/plan-template-publish-service.js +217 -0
- package/src/backend/services/plan-templates-service.js +242 -0
- package/src/backend/services/plan-templates.js +1164 -0
- package/src/backend/services/planned-overlap-actions.js +200 -0
- package/src/backend/services/plans-home.js +224 -0
- package/src/backend/services/play-forward.js +256 -0
- package/src/backend/services/playback-service.js +117 -0
- package/src/backend/services/power-service.js +167 -0
- package/src/backend/services/power-signals.js +81 -0
- package/src/backend/services/pr-draft-service.js +142 -0
- package/src/backend/services/presence-service.js +122 -0
- package/src/backend/services/pricing.js +60 -0
- package/src/backend/services/project-config-service.js +474 -0
- package/src/backend/services/project-scanner.js +184 -0
- package/src/backend/services/projection-service.js +69 -0
- package/src/backend/services/push-notification-service.js +288 -0
- package/src/backend/services/recent-projects-service.js +204 -0
- package/src/backend/services/record-chain.js +162 -0
- package/src/backend/services/recurrence-rule.js +63 -0
- package/src/backend/services/recurring-agent.js +89 -0
- package/src/backend/services/recurring-scheduler.js +77 -0
- package/src/backend/services/recurring-service.js +276 -0
- package/src/backend/services/reference-service.js +169 -0
- package/src/backend/services/release-public-key.js +30 -0
- package/src/backend/services/release-signature.js +64 -0
- package/src/backend/services/remote-audio-service.js +224 -0
- package/src/backend/services/remote-interaction-service.js +275 -0
- package/src/backend/services/remote-terminal-service.js +324 -0
- package/src/backend/services/rendition/child/main.js +76 -0
- package/src/backend/services/rendition/engine-host.js +249 -0
- package/src/backend/services/rendition/engine-lock.js +39 -0
- package/src/backend/services/rendition/engine-lock.json +14 -0
- package/src/backend/services/rendition/engine-manifest.js +97 -0
- package/src/backend/services/rendition/network-proof.js +73 -0
- package/src/backend/services/rendition/rendition-service.js +175 -0
- package/src/backend/services/replay-frames.js +387 -0
- package/src/backend/services/replay-state.js +201 -0
- package/src/backend/services/resolvers/base.js +108 -0
- package/src/backend/services/resolvers/csharp.js +109 -0
- package/src/backend/services/resolvers/go.js +105 -0
- package/src/backend/services/resolvers/index.js +60 -0
- package/src/backend/services/resolvers/java.js +63 -0
- package/src/backend/services/resolvers/kotlin.js +109 -0
- package/src/backend/services/resolvers/php.js +89 -0
- package/src/backend/services/resolvers/python.js +154 -0
- package/src/backend/services/resolvers/ruby.js +103 -0
- package/src/backend/services/resolvers/rust.js +77 -0
- package/src/backend/services/resolvers/swift.js +98 -0
- package/src/backend/services/resolvers/typescript.js +71 -0
- package/src/backend/services/retention.js +54 -0
- package/src/backend/services/review-architecture.js +236 -0
- package/src/backend/services/review-attest.js +68 -0
- package/src/backend/services/review-bundle.js +226 -0
- package/src/backend/services/review-graduation.js +93 -0
- package/src/backend/services/review-host/bitbucket.js +79 -0
- package/src/backend/services/review-host/detect.js +80 -0
- package/src/backend/services/review-host/github.js +97 -0
- package/src/backend/services/review-host/gitlab.js +77 -0
- package/src/backend/services/review-host/host-state.js +103 -0
- package/src/backend/services/review-host/http.js +58 -0
- package/src/backend/services/review-host/switch.js +120 -0
- package/src/backend/services/review-marks.js +72 -0
- package/src/backend/services/review-notes.js +169 -0
- package/src/backend/services/review-other-work.js +90 -0
- package/src/backend/services/review-queue-service.js +147 -0
- package/src/backend/services/review-risk.js +127 -0
- package/src/backend/services/review-task.js +121 -0
- package/src/backend/services/rule-approvals.js +268 -0
- package/src/backend/services/rule-baseline.js +134 -0
- package/src/backend/services/rule-changes.js +162 -0
- package/src/backend/services/rule-preview.js +47 -0
- package/src/backend/services/rule-proposals.js +104 -0
- package/src/backend/services/rule-scope.js +76 -0
- package/src/backend/services/rulebook.js +286 -0
- package/src/backend/services/rules-at.js +56 -0
- package/src/backend/services/rules-overview.js +88 -0
- package/src/backend/services/schema-reconciler.js +250 -0
- package/src/backend/services/secret-store.js +119 -0
- package/src/backend/services/section-workstreams.js +95 -0
- package/src/backend/services/self-write-tracker.js +75 -0
- package/src/backend/services/sensor-bridge-service.js +285 -0
- package/src/backend/services/session-service.js +192 -0
- package/src/backend/services/settings-service.js +324 -0
- package/src/backend/services/signal-breakpoints.js +172 -0
- package/src/backend/services/signed-approval-record.js +86 -0
- package/src/backend/services/signed-approvals.js +244 -0
- package/src/backend/services/signoff-pack.js +328 -0
- package/src/backend/services/signoff-rows.js +114 -0
- package/src/backend/services/skill-arrival-service.js +138 -0
- package/src/backend/services/skill-model.js +193 -0
- package/src/backend/services/skill-use-service.js +140 -0
- package/src/backend/services/skills-service.js +150 -0
- package/src/backend/services/snapshot-compare-service.js +397 -0
- package/src/backend/services/source-control.js +189 -0
- package/src/backend/services/spec-links-service.js +123 -0
- package/src/backend/services/spec-proposal-withdraw.js +50 -0
- package/src/backend/services/spec-proposals-service.js +470 -0
- package/src/backend/services/sql/embedded.js +95 -0
- package/src/backend/services/sql/index.js +63 -0
- package/src/backend/services/sql/refs.js +357 -0
- package/src/backend/services/sql/schema.js +312 -0
- package/src/backend/services/sql/tokenizer.js +195 -0
- package/src/backend/services/stack-overlaps.js +117 -0
- package/src/backend/services/stack-service.js +225 -0
- package/src/backend/services/state-sync-service.js +384 -0
- package/src/backend/services/stuck-sensor-service.js +200 -0
- package/src/backend/services/system-discovery.js +481 -0
- package/src/backend/services/system-docs-service.js +701 -0
- package/src/backend/services/task-attachments-service.js +340 -0
- package/src/backend/services/task-grounding.js +60 -0
- package/src/backend/services/task-records/check-run-record.js +146 -0
- package/src/backend/services/task-records/check-runs.js +115 -0
- package/src/backend/services/task-records/heads.js +88 -0
- package/src/backend/services/task-records/material-reads.js +225 -0
- package/src/backend/services/task-records/read-record.js +100 -0
- package/src/backend/services/task-records/record.js +173 -0
- package/src/backend/services/task-records/run-record.js +136 -0
- package/src/backend/services/task-records/shared-state.js +548 -0
- package/src/backend/services/task-records/signing.js +140 -0
- package/src/backend/services/task-records/split-signals.js +52 -0
- package/src/backend/services/task-records/test-runs.js +164 -0
- package/src/backend/services/task-records/trust.js +243 -0
- package/src/backend/services/task-rules.js +81 -0
- package/src/backend/services/task-workstreams.js +90 -0
- package/src/backend/services/terminal-history-service.js +266 -0
- package/src/backend/services/terminal-service.js +267 -0
- package/src/backend/services/test-clock.js +53 -0
- package/src/backend/services/tests/grounding.js +266 -0
- package/src/backend/services/tests/junit.js +104 -0
- package/src/backend/services/tests/teammate-runs.js +134 -0
- package/src/backend/services/tests/test-results.js +234 -0
- package/src/backend/services/tree-watcher.js +204 -0
- package/src/backend/services/trellis-service.js +204 -0
- package/src/backend/services/trusted-roots.js +186 -0
- package/src/backend/services/update-download-service.js +342 -0
- package/src/backend/services/update-service.js +266 -0
- package/src/backend/services/watch-ignore.js +76 -0
- package/src/backend/services/webhook-egress.js +206 -0
- package/src/backend/services/webrtc-service.js +413 -0
- package/src/backend/services/work-changes.js +59 -0
- package/src/backend/services/workstream-binding.js +82 -0
- package/src/backend/services/workstream-commits.js +116 -0
- package/src/backend/services/workstream-imports.js +177 -0
- package/src/backend/services/workstream-service.js +335 -0
- package/src/backend/services/workstream-symbols.js +223 -0
- package/src/backend/services/workstream-watch-service.js +391 -0
- package/src/backend/services/worktree-service.js +235 -0
- package/src/cli/agent.js +100 -0
- package/src/cli/args.js +201 -0
- package/src/cli/conformity.js +106 -0
- package/src/cli/desktop.js +91 -0
- package/src/cli/main.js +409 -0
- package/src/cli/pipeline.js +109 -0
- package/src/cli/plan-verbs.js +259 -0
- package/src/cli/review-adapters.js +218 -0
- package/src/cli/review-output.js +93 -0
- package/src/cli/review-post.js +89 -0
- package/src/cli/review-sink.js +183 -0
- package/src/cli/review-skill.js +44 -0
- package/src/cli/review-verify.js +104 -0
- package/src/cli/review.js +386 -0
- package/src/cli/sarif.js +148 -0
- package/src/cli/verbs.js +359 -0
- package/src/shared/build-info.js +39 -0
- package/src/shared/lib/agent-review.js +199 -0
- package/src/shared/lib/agent-turns.js +140 -0
- package/src/shared/lib/awareness-digest.js +120 -0
- package/src/shared/lib/branch-name.js +45 -0
- package/src/shared/lib/breakpoint-words.js +118 -0
- package/src/shared/lib/budget-words.js +56 -0
- package/src/shared/lib/burst.js +69 -0
- package/src/shared/lib/call-entry.js +105 -0
- package/src/shared/lib/check-compare.js +42 -0
- package/src/shared/lib/check-words.js +216 -0
- package/src/shared/lib/csv.js +62 -0
- package/src/shared/lib/folder-entry.js +87 -0
- package/src/shared/lib/freeze-words.js +60 -0
- package/src/shared/lib/fuzzy.js +84 -0
- package/src/shared/lib/git-state-words.js +80 -0
- package/src/shared/lib/grep-entry.js +86 -0
- package/src/shared/lib/grounding-line.js +61 -0
- package/src/shared/lib/import-line.js +71 -0
- package/src/shared/lib/item-status.js +249 -0
- package/src/shared/lib/line-changes.js +53 -0
- package/src/shared/lib/locator.js +71 -0
- package/src/shared/lib/matcher.js +120 -0
- package/src/shared/lib/merge-order.js +65 -0
- package/src/shared/lib/open-findings.js +68 -0
- package/src/shared/lib/other-work.js +108 -0
- package/src/shared/lib/package-entry.js +142 -0
- package/src/shared/lib/plan-vocab.js +40 -0
- package/src/shared/lib/pptx-xml.js +86 -0
- package/src/shared/lib/proposal-words.js +61 -0
- package/src/shared/lib/recurrence.js +183 -0
- package/src/shared/lib/references.js +72 -0
- package/src/shared/lib/rule-pattern.js +56 -0
- package/src/shared/lib/sdp-fingerprint.js +115 -0
- package/src/shared/lib/sdp-minimal.js +123 -0
- package/src/shared/lib/secret-paths.js +34 -0
- package/src/shared/lib/signal-words.js +172 -0
- package/src/shared/lib/signoff.js +56 -0
- package/src/shared/lib/skills-note.js +60 -0
- package/src/shared/lib/spec-sections.js +78 -0
- package/src/shared/lib/symbol-entry.js +60 -0
- package/src/shared/lib/tool-phrasing.js +338 -0
- package/src/shared/lib/turn-gap.js +27 -0
- package/src/shared/lib/workstream-words.js +38 -0
- package/src/shared/lib/xlsx-xml.js +144 -0
- package/src/shared/lib/zip-reader.js +99 -0
- package/src/shared/types/agent.js +27 -0
- package/src/shared/types/architecture-rules.js +30 -0
- package/src/shared/types/ast.js +15 -0
- package/src/shared/types/breakpoint.js +33 -0
- package/src/shared/types/channel.js +41 -0
- package/src/shared/types/criteria.js +15 -0
- package/src/shared/types/graph.js +15 -0
- package/src/shared/types/index.js +53 -0
- package/src/shared/types/peer.js +36 -0
- package/src/shared/types/pipeline.js +15 -0
- package/src/shared/types/plan.js +15 -0
- package/src/shared/types/play-forward.js +15 -0
- package/src/shared/types/power.js +15 -0
- package/src/shared/types/presence.js +15 -0
- package/src/shared/types/project-config.js +35 -0
- package/src/shared/types/project.js +15 -0
- package/src/shared/types/record.js +15 -0
- package/src/shared/types/recurring.js +15 -0
- package/src/shared/types/review.js +15 -0
- package/src/shared/types/settings.js +114 -0
- package/src/shared/types/stack.js +15 -0
- package/src/shared/types/system-doc.js +15 -0
- package/src/shared/types/system.js +15 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var read_exports = {};
|
|
29
|
+
__export(read_exports, {
|
|
30
|
+
MAX_OUTPUT_CHARS: () => MAX_OUTPUT_CHARS,
|
|
31
|
+
readMaterialBytes: () => readMaterialBytes
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(read_exports);
|
|
34
|
+
var import_mammoth = __toESM(require("mammoth"));
|
|
35
|
+
var import_zip_reader = require("../../../shared/lib/zip-reader");
|
|
36
|
+
var import_xlsx_xml = require("../../../shared/lib/xlsx-xml");
|
|
37
|
+
var import_pptx_xml = require("../../../shared/lib/pptx-xml");
|
|
38
|
+
var import_locator = require("../../../shared/lib/locator");
|
|
39
|
+
var import_docx_markdown = require("./docx-markdown");
|
|
40
|
+
var import_csv = require("../../../shared/lib/csv");
|
|
41
|
+
const MAX_OUTPUT_CHARS = 1e5;
|
|
42
|
+
const MAX_PART_BYTES = 30 * 1024 * 1024;
|
|
43
|
+
const MAX_TOTAL_BYTES = 100 * 1024 * 1024;
|
|
44
|
+
const SHEET_CAPS = { maxRows: 5e3, maxCols: 200, maxCells: 25e4 };
|
|
45
|
+
const MAX_PDF_PAGES = 500;
|
|
46
|
+
const MAX_SLIDES = 500;
|
|
47
|
+
const TEXT_CONTEXT_LINES = 15;
|
|
48
|
+
class ReadError extends Error {
|
|
49
|
+
}
|
|
50
|
+
const squash = (s) => s.replace(/\s+/g, " ").trim().toLowerCase();
|
|
51
|
+
const dash = (a, b) => a === b ? String(a) : `${a}\u2013${b}`;
|
|
52
|
+
function fit(sections, notes, rest) {
|
|
53
|
+
const out = [];
|
|
54
|
+
let left = MAX_OUTPUT_CHARS;
|
|
55
|
+
for (const [i, s] of sections.entries()) {
|
|
56
|
+
const cost = s.heading.length + s.body.length + 4;
|
|
57
|
+
if (cost <= left) {
|
|
58
|
+
out.push(s);
|
|
59
|
+
left -= cost;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
let partly = false;
|
|
63
|
+
if (left > 2e3) {
|
|
64
|
+
const heading = `${s.heading} (cut short)`;
|
|
65
|
+
const cut = s.body.slice(0, left - heading.length - 4);
|
|
66
|
+
out.push({ heading, body: cut.slice(0, Math.max(0, cut.lastIndexOf("\n"))) });
|
|
67
|
+
partly = true;
|
|
68
|
+
}
|
|
69
|
+
const skipped = sections.slice(partly ? i + 1 : i).map((x) => x.heading);
|
|
70
|
+
notes.push(`Stopped at about ${MAX_OUTPUT_CHARS.toLocaleString("en-GB")} characters. ${rest(s.heading)}${skipped.length ? ` Not shown: ${skipped.slice(0, 20).join(", ")}${skipped.length > 20 ? ", \u2026" : ""}.` : ""}`);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
function numbered(lines, start, end) {
|
|
76
|
+
const width = String(end).length;
|
|
77
|
+
const out = [];
|
|
78
|
+
for (let n = start; n <= end; n++) out.push(`${String(n).padStart(width)} ${lines[n - 1]}`);
|
|
79
|
+
return out.join("\n");
|
|
80
|
+
}
|
|
81
|
+
function readLines(lines, locator, opts) {
|
|
82
|
+
const total = lines.length;
|
|
83
|
+
const body = (a, b) => opts.number ? numbered(lines, a, b) : lines.slice(a - 1, b).join("\n");
|
|
84
|
+
if (locator.lines !== void 0) {
|
|
85
|
+
const span = (0, import_locator.toSpan)(locator.lines);
|
|
86
|
+
if (!span || span.start < 1 || span.end < span.start) {
|
|
87
|
+
throw new ReadError(`lines must be a line number or a span such as "10-20" \u2014 got ${JSON.stringify(locator.lines)}`);
|
|
88
|
+
}
|
|
89
|
+
if (span.start > total) throw new ReadError(`${opts.name} has ${total} lines; ${span.start} is past the end`);
|
|
90
|
+
const end = Math.min(span.end, total);
|
|
91
|
+
return { where: `lines ${dash(span.start, end)}`, section: { heading: `Lines ${dash(span.start, end)} of ${total}`, body: body(span.start, end) } };
|
|
92
|
+
}
|
|
93
|
+
if (locator.text !== void 0) {
|
|
94
|
+
const quote = squash(locator.text);
|
|
95
|
+
if (!quote) throw new ReadError("text must be the words to find");
|
|
96
|
+
const at = lines.findIndex((_, i) => squash(lines.slice(i, i + 8).join(" ")).includes(quote));
|
|
97
|
+
if (at < 0) throw new ReadError(`${opts.name} does not contain "${locator.text.slice(0, 80)}"`);
|
|
98
|
+
let first = at;
|
|
99
|
+
while (first + 1 < total && squash(lines.slice(first + 1, first + 9).join(" ")).includes(quote)) first++;
|
|
100
|
+
const a = Math.max(1, first + 1 - TEXT_CONTEXT_LINES);
|
|
101
|
+
const b = Math.min(total, first + 1 + TEXT_CONTEXT_LINES);
|
|
102
|
+
return { where: `the passage at line ${first + 1}`, section: { heading: `Lines ${dash(a, b)} of ${total}`, body: body(a, b) } };
|
|
103
|
+
}
|
|
104
|
+
return { where: null, section: { heading: `Lines 1\u2013${total}`, body: body(1, total) } };
|
|
105
|
+
}
|
|
106
|
+
function readTextFile(req, locator) {
|
|
107
|
+
const text = new TextDecoder("utf-8", { fatal: false }).decode(req.bytes);
|
|
108
|
+
const lines = text.split(/\r?\n/);
|
|
109
|
+
if (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
|
|
110
|
+
const notes = [];
|
|
111
|
+
refuseKeys(locator, req.ext === "csv" ? ["lines", "text", "range"] : ["lines", "text"], req);
|
|
112
|
+
const { where, section } = readLines(lines, locator, { number: true, name: req.name });
|
|
113
|
+
const sections = fit([section], notes, () => 'Ask for {"lines": "N-M"} to read further.');
|
|
114
|
+
return { ok: true, format: "text", where, outline: `${lines.length} lines`, sections, notes };
|
|
115
|
+
}
|
|
116
|
+
function readCsvRange(req, locator) {
|
|
117
|
+
refuseKeys(locator, ["range"], req);
|
|
118
|
+
const text = new TextDecoder("utf-8", { fatal: false }).decode(req.bytes);
|
|
119
|
+
const rows = (0, import_csv.parseCsv)(text);
|
|
120
|
+
const shape = (0, import_csv.csvShape)(rows);
|
|
121
|
+
const range = (0, import_locator.parseRange)(String(locator.range).trim());
|
|
122
|
+
if (!range) throw new ReadError(`"${locator.range}" is not a cell or range \u2014 write it as C14 or A1:F20`);
|
|
123
|
+
if (range.to.row > shape.rows || range.to.col > shape.cols) {
|
|
124
|
+
throw new ReadError(`${locator.range} is outside ${req.name}, which has ${shape.rows} rows and ${shape.cols} columns`);
|
|
125
|
+
}
|
|
126
|
+
const at = `${(0, import_xlsx_xml.colLetters)(range.from.col)}${range.from.row}:${(0, import_xlsx_xml.colLetters)(range.to.col)}${range.to.row}`;
|
|
127
|
+
const body = toCsv(rows.slice(range.from.row - 1, range.to.row).map((r) => r.slice(range.from.col - 1, range.to.col)));
|
|
128
|
+
const notes = [];
|
|
129
|
+
return {
|
|
130
|
+
ok: true,
|
|
131
|
+
format: "csv",
|
|
132
|
+
where: `cells ${at}`,
|
|
133
|
+
outline: `${shape.rows} rows, ${shape.cols} columns`,
|
|
134
|
+
sections: fit([{ heading: `Cells ${at}`, body }], notes, () => 'Ask for a smaller {"range"} to read the rest.'),
|
|
135
|
+
notes
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function csvField(v) {
|
|
139
|
+
return /[",\r\n]/.test(v) ? `"${v.replace(/"/g, '""')}"` : v;
|
|
140
|
+
}
|
|
141
|
+
function toCsv(rows) {
|
|
142
|
+
let lastRow = rows.length;
|
|
143
|
+
while (lastRow > 0 && rows[lastRow - 1].every((c) => c === "")) lastRow--;
|
|
144
|
+
const width = Math.max(0, ...rows.slice(0, lastRow).map((r) => {
|
|
145
|
+
let w = r.length;
|
|
146
|
+
while (w > 0 && r[w - 1] === "") w--;
|
|
147
|
+
return w;
|
|
148
|
+
}));
|
|
149
|
+
return rows.slice(0, lastRow).map((r) => Array.from({ length: width }, (_, i) => csvField(r[i] ?? "")).join(",")).join("\n");
|
|
150
|
+
}
|
|
151
|
+
async function readWorkbook(req, locator) {
|
|
152
|
+
refuseKeys(locator, ["sheet", "range", "text"], req);
|
|
153
|
+
const view = new DataView(req.bytes.buffer, req.bytes.byteOffset, req.bytes.byteLength);
|
|
154
|
+
const entries = (0, import_zip_reader.listEntries)(view);
|
|
155
|
+
const budget = { maxPart: MAX_PART_BYTES, maxTotal: MAX_TOTAL_BYTES, used: 0 };
|
|
156
|
+
const part = (name) => (0, import_zip_reader.readText)(view, entries, name, budget);
|
|
157
|
+
const workbook = await part("xl/workbook.xml");
|
|
158
|
+
if (!workbook) throw new ReadError(`${req.name} is not an Excel workbook \u2014 it has no workbook part`);
|
|
159
|
+
const refs = (0, import_xlsx_xml.parseWorkbookSheets)(workbook, await part("xl/_rels/workbook.xml.rels") ?? "");
|
|
160
|
+
const shared = (0, import_xlsx_xml.parseSharedStrings)(await part("xl/sharedStrings.xml") ?? "");
|
|
161
|
+
const dates = (0, import_xlsx_xml.parseDateStyles)(await part("xl/styles.xml") ?? "");
|
|
162
|
+
const notes = ["Each cell is the value the spreadsheet app last saved; formulas are not re-calculated."];
|
|
163
|
+
if (entries.some((e) => /vbaProject\.bin$/i.test(e.name))) notes.push("This workbook carries macros. They were not run.");
|
|
164
|
+
let range = null;
|
|
165
|
+
if (locator.range !== void 0) {
|
|
166
|
+
range = (0, import_locator.parseRange)(String(locator.range).trim());
|
|
167
|
+
if (!range) throw new ReadError(`"${locator.range}" is not a cell or range \u2014 write it as C14 or A1:F20`);
|
|
168
|
+
}
|
|
169
|
+
let chosen = refs;
|
|
170
|
+
if (locator.sheet !== void 0) {
|
|
171
|
+
const want = String(locator.sheet);
|
|
172
|
+
const hit = refs.find((r) => r.name === want) ?? refs.find((r) => r.name.toLowerCase() === want.trim().toLowerCase());
|
|
173
|
+
if (!hit) throw new ReadError(`${req.name} has no sheet "${want}" \u2014 it has ${refs.map((r) => `"${r.name}"`).join(", ") || "none"}`);
|
|
174
|
+
chosen = [hit];
|
|
175
|
+
} else if (range) {
|
|
176
|
+
chosen = refs.slice(0, 1);
|
|
177
|
+
}
|
|
178
|
+
const dims = [];
|
|
179
|
+
const sections = [];
|
|
180
|
+
let cellsLeft = SHEET_CAPS.maxCells;
|
|
181
|
+
for (const ref of refs) {
|
|
182
|
+
const xml = ref.part ? await part(ref.part) : null;
|
|
183
|
+
const dimension = xml ? (0, import_xlsx_xml.sheetDimension)(xml) : null;
|
|
184
|
+
dims.push(`${ref.name}${dimension ? ` (${dimension})` : ""}`);
|
|
185
|
+
if (!chosen.includes(ref) || !xml) continue;
|
|
186
|
+
const caps = range ? { maxRows: range.to.row, maxCols: range.to.col, maxCells: cellsLeft } : { ...SHEET_CAPS, maxCells: cellsLeft };
|
|
187
|
+
const grid = (0, import_xlsx_xml.parseSheetGrid)(xml, shared, dates, caps);
|
|
188
|
+
cellsLeft = Math.max(0, cellsLeft - grid.cells);
|
|
189
|
+
let rows = grid.rows;
|
|
190
|
+
let heading = `Sheet "${ref.name}"`;
|
|
191
|
+
if (range) {
|
|
192
|
+
rows = rows.slice(range.from.row - 1, range.to.row).map((r) => r.slice(range.from.col - 1, range.to.col));
|
|
193
|
+
heading += `, ${(0, import_xlsx_xml.colLetters)(range.from.col)}${range.from.row}:${(0, import_xlsx_xml.colLetters)(range.to.col)}${range.to.row}`;
|
|
194
|
+
} else if (grid.truncated) {
|
|
195
|
+
notes.push(`Sheet "${ref.name}" goes past ${SHEET_CAPS.maxRows.toLocaleString("en-GB")} rows or ${SHEET_CAPS.maxCols} columns; ask for {"sheet": "${ref.name}", "range": "A${SHEET_CAPS.maxRows + 1}:\u2026"} to read further.`);
|
|
196
|
+
}
|
|
197
|
+
if (!range) heading += " from A1";
|
|
198
|
+
sections.push({ heading, body: toCsv(rows) });
|
|
199
|
+
}
|
|
200
|
+
let shown = sections;
|
|
201
|
+
let where = locator.sheet !== void 0 || range ? sections.map((s) => s.heading.replace(/^Sheet /, "sheet ").replace(/ from A1$/, "")).join("; ") : null;
|
|
202
|
+
if (locator.text !== void 0) {
|
|
203
|
+
const quote = squash(locator.text);
|
|
204
|
+
if (!quote) throw new ReadError("text must be the words to find");
|
|
205
|
+
shown = sections.filter((s) => squash(s.body.replace(/"/g, "")).includes(quote) || squash(s.body).includes(quote));
|
|
206
|
+
if (shown.length === 0) throw new ReadError(`No sheet in ${req.name} contains "${locator.text.slice(0, 80)}"`);
|
|
207
|
+
where = shown.map((s) => s.heading.replace(/^Sheet /, "sheet ").replace(/ from A1$/, "")).join("; ");
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
ok: true,
|
|
211
|
+
format: "csv",
|
|
212
|
+
where,
|
|
213
|
+
outline: `${refs.length} sheet${refs.length === 1 ? "" : "s"}: ${dims.join(", ")}`,
|
|
214
|
+
sections: fit(shown, notes, () => 'Ask for one {"sheet"} and a {"range"} to read the rest.'),
|
|
215
|
+
notes
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
async function readWord(req, locator) {
|
|
219
|
+
if (req.rendition && locator.lines === void 0) {
|
|
220
|
+
refuseKeys(locator, ["page", "text", "lines"], req);
|
|
221
|
+
const read = await readPdfPages(req.rendition, req.name, locator, "page");
|
|
222
|
+
return pagesReply(read, locator, "page", [
|
|
223
|
+
"Read from the pages CodeTrellis shows: its rendition of this document, laid out as the person sees it.",
|
|
224
|
+
`To cite this document, quote it: {"text": "\u2026"}. A {"page"} says where the words are on these pages, but is not checked \u2014 a Word document's pages depend on layout.`,
|
|
225
|
+
'Ask for {"lines": "1-200"} to read it as markdown instead, with its headings and tables.'
|
|
226
|
+
]);
|
|
227
|
+
}
|
|
228
|
+
if (locator.page !== void 0) {
|
|
229
|
+
throw new ReadError(`${req.name} is a Word document; its pages depend on layout. Ask for {"lines"} of what this returns, or {"text"}`);
|
|
230
|
+
}
|
|
231
|
+
refuseKeys(locator, ["lines", "text"], req);
|
|
232
|
+
const view = new DataView(req.bytes.buffer, req.bytes.byteOffset, req.bytes.byteLength);
|
|
233
|
+
const entries = (0, import_zip_reader.listEntries)(view);
|
|
234
|
+
if (!entries.some((e) => e.name === "word/document.xml")) {
|
|
235
|
+
throw new ReadError(`${req.name} is not a Word document \u2014 it has no document part`);
|
|
236
|
+
}
|
|
237
|
+
const budget = { maxPart: MAX_PART_BYTES, maxTotal: MAX_TOTAL_BYTES, used: 0 };
|
|
238
|
+
for (const e of entries) await (0, import_zip_reader.readEntry)(view, e, budget);
|
|
239
|
+
let images = 0;
|
|
240
|
+
const result = await import_mammoth.default.convertToHtml({ buffer: Buffer.from(req.bytes.buffer, req.bytes.byteOffset, req.bytes.byteLength) }, {
|
|
241
|
+
// A document can link an image by path instead of embedding it. Never follow one.
|
|
242
|
+
externalFileAccess: false,
|
|
243
|
+
convertImage: import_mammoth.default.images.imgElement(async () => {
|
|
244
|
+
images++;
|
|
245
|
+
return { src: "" };
|
|
246
|
+
})
|
|
247
|
+
});
|
|
248
|
+
const markdown = (0, import_docx_markdown.docxHtmlToMarkdown)(result.value);
|
|
249
|
+
const lines = markdown.split("\n");
|
|
250
|
+
while (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
|
|
251
|
+
const notes = [
|
|
252
|
+
"Converted to markdown: headings, lists, tables and emphasis survive; page layout does not.",
|
|
253
|
+
`To cite this document, quote it: {"text": "\u2026"}. Line numbers here are this markdown's, not the document's.`
|
|
254
|
+
];
|
|
255
|
+
if (images) notes.push(`${images} image${images === 1 ? "" : "s"} shown as [image]; open the document in CodeTrellis to see them.`);
|
|
256
|
+
const { where, section } = readLines(lines, locator, { number: false, name: req.name });
|
|
257
|
+
return {
|
|
258
|
+
ok: true,
|
|
259
|
+
format: "markdown",
|
|
260
|
+
where,
|
|
261
|
+
outline: `${lines.length} lines of markdown`,
|
|
262
|
+
sections: fit([section], notes, () => 'Ask for {"lines": "N-M"} of this markdown to read further.'),
|
|
263
|
+
notes
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function pageSpan(locator, count, noun, name) {
|
|
267
|
+
if (locator.page === void 0) return null;
|
|
268
|
+
const span = (0, import_locator.toSpan)(locator.page);
|
|
269
|
+
if (!span || span.start < 1 || span.end < span.start) {
|
|
270
|
+
throw new ReadError(`page must be a ${noun} number from 1, or a span such as "2-4" \u2014 got ${JSON.stringify(locator.page)}`);
|
|
271
|
+
}
|
|
272
|
+
if (span.start > count) throw new ReadError(`${name} has ${count} ${noun}s; ${span.start} is not one of them`);
|
|
273
|
+
return { start: span.start, end: Math.min(span.end, count) };
|
|
274
|
+
}
|
|
275
|
+
function narrowByText(sections, locator, name) {
|
|
276
|
+
if (locator.text === void 0) return sections;
|
|
277
|
+
const quote = squash(locator.text);
|
|
278
|
+
if (!quote) throw new ReadError("text must be the words to find");
|
|
279
|
+
const hits = sections.filter((s) => squash(`${s.heading} ${s.body}`).includes(quote));
|
|
280
|
+
if (hits.length === 0) throw new ReadError(`${name} does not contain "${locator.text.slice(0, 80)}"`);
|
|
281
|
+
return hits;
|
|
282
|
+
}
|
|
283
|
+
async function readDeck(req, locator) {
|
|
284
|
+
refuseKeys(locator, ["page", "text"], req);
|
|
285
|
+
const view = new DataView(req.bytes.buffer, req.bytes.byteOffset, req.bytes.byteLength);
|
|
286
|
+
const entries = (0, import_zip_reader.listEntries)(view);
|
|
287
|
+
const names = entries.map((e) => e.name);
|
|
288
|
+
if (!names.includes("ppt/presentation.xml")) throw new ReadError(`${req.name} is not a PowerPoint deck \u2014 it has no presentation part`);
|
|
289
|
+
const budget = { maxPart: MAX_PART_BYTES, maxTotal: MAX_TOTAL_BYTES, used: 0 };
|
|
290
|
+
const order = (0, import_pptx_xml.slideOrder)(
|
|
291
|
+
await (0, import_zip_reader.readText)(view, entries, "ppt/presentation.xml", budget),
|
|
292
|
+
await (0, import_zip_reader.readText)(view, entries, "ppt/_rels/presentation.xml.rels", budget),
|
|
293
|
+
names
|
|
294
|
+
);
|
|
295
|
+
const notes = ["Each slide's title and words in presentation order; pictures and charts are not described."];
|
|
296
|
+
if (req.rendition) {
|
|
297
|
+
const read = await readPdfPages(req.rendition, req.name, locator, "slide", order.length);
|
|
298
|
+
if (read) {
|
|
299
|
+
return pagesReply(read, locator, "slide", [
|
|
300
|
+
"Read from the slides as CodeTrellis shows them: the words on each, laid out as the person sees it. Pictures are not described."
|
|
301
|
+
]);
|
|
302
|
+
}
|
|
303
|
+
notes.push("Read from the slides themselves: the view CodeTrellis shows leaves some out (hidden slides), so its pages are not numbered as the slides are.");
|
|
304
|
+
}
|
|
305
|
+
const span = pageSpan(locator, order.length, "slide", req.name);
|
|
306
|
+
const first = span?.start ?? 1;
|
|
307
|
+
const last = Math.min(span?.end ?? order.length, MAX_SLIDES);
|
|
308
|
+
if (order.length > MAX_SLIDES && !span) notes.push(`Only the first ${MAX_SLIDES} slides are read.`);
|
|
309
|
+
const sections = [];
|
|
310
|
+
for (let n = first; n <= last; n++) {
|
|
311
|
+
const xml = await (0, import_zip_reader.readText)(view, entries, order[n - 1], budget);
|
|
312
|
+
const s = xml ? (0, import_pptx_xml.slideText)(n, xml) : { n, title: null, paragraphs: [] };
|
|
313
|
+
sections.push({ heading: `Slide ${n}${s.title ? ` \u2014 ${s.title}` : ""}`, body: s.paragraphs.join("\n") || "(no words)" });
|
|
314
|
+
}
|
|
315
|
+
const shown = narrowByText(sections, locator, req.name);
|
|
316
|
+
const where = locator.text !== void 0 ? shown.map((s) => s.heading.split(" \u2014 ")[0].toLowerCase()).join(", ") : span ? `slide${span.start === span.end ? "" : "s"} ${dash(span.start, span.end)}` : null;
|
|
317
|
+
return {
|
|
318
|
+
ok: true,
|
|
319
|
+
format: "markdown",
|
|
320
|
+
where,
|
|
321
|
+
outline: `${order.length} slide${order.length === 1 ? "" : "s"}`,
|
|
322
|
+
sections: fit(shown, notes, () => 'Ask for {"page": "N-M"} to read further slides.'),
|
|
323
|
+
notes
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
let pdfjsLoaded = null;
|
|
327
|
+
function loadPdfJs() {
|
|
328
|
+
pdfjsLoaded ??= (async () => {
|
|
329
|
+
globalThis.pdfjsWorker = await Promise.resolve().then(() => __toESM(require("pdfjs-dist/legacy/build/pdf.worker.mjs")));
|
|
330
|
+
return await Promise.resolve().then(() => __toESM(require("pdfjs-dist/legacy/build/pdf.mjs")));
|
|
331
|
+
})();
|
|
332
|
+
return pdfjsLoaded;
|
|
333
|
+
}
|
|
334
|
+
async function readPdfPages(bytes, name, locator, noun, expectPages) {
|
|
335
|
+
const Noun = noun === "page" ? "Page" : "Slide";
|
|
336
|
+
const pdfjs = await loadPdfJs();
|
|
337
|
+
const task = pdfjs.getDocument({
|
|
338
|
+
data: bytes,
|
|
339
|
+
isEvalSupported: false,
|
|
340
|
+
enableXfa: false,
|
|
341
|
+
disableFontFace: true,
|
|
342
|
+
useSystemFonts: false,
|
|
343
|
+
stopAtErrors: false,
|
|
344
|
+
verbosity: 0
|
|
345
|
+
});
|
|
346
|
+
try {
|
|
347
|
+
let doc;
|
|
348
|
+
try {
|
|
349
|
+
doc = await task.promise;
|
|
350
|
+
} catch (err) {
|
|
351
|
+
const errName = err.name;
|
|
352
|
+
throw new ReadError(errName === "PasswordException" ? `${name} is password-protected, so its text cannot be read` : `${name} could not be read as a PDF (${err.message})`);
|
|
353
|
+
}
|
|
354
|
+
if (expectPages !== void 0 && doc.numPages !== expectPages) return null;
|
|
355
|
+
const span = pageSpan(locator, doc.numPages, noun, name);
|
|
356
|
+
const notes = [];
|
|
357
|
+
const first = span?.start ?? 1;
|
|
358
|
+
const last = Math.min(span?.end ?? doc.numPages, first + MAX_PDF_PAGES - 1);
|
|
359
|
+
if (!span && doc.numPages > MAX_PDF_PAGES) notes.push(`Only the first ${MAX_PDF_PAGES} ${noun}s are read.`);
|
|
360
|
+
const sections = [];
|
|
361
|
+
let chars = 0;
|
|
362
|
+
for (let n = first; n <= last; n++) {
|
|
363
|
+
const page = await doc.getPage(n);
|
|
364
|
+
const content = await page.getTextContent();
|
|
365
|
+
const body = content.items.map((it) => (it.str ?? "") + (it.hasEOL ? "\n" : "")).join("").replace(/[ \t]+\n/g, "\n").trim();
|
|
366
|
+
page.cleanup();
|
|
367
|
+
sections.push({ heading: `${Noun} ${n}`, body: body || (noun === "page" ? "(no text on this page \u2014 it may be a scanned image)" : "(no text on this slide \u2014 it may be a picture)") });
|
|
368
|
+
chars += body.length;
|
|
369
|
+
if (chars > MAX_OUTPUT_CHARS * 2 && locator.text === void 0) break;
|
|
370
|
+
}
|
|
371
|
+
return { count: doc.numPages, span, sections: narrowByText(sections, locator, name), notes };
|
|
372
|
+
} finally {
|
|
373
|
+
await task.destroy().catch(() => {
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function pagesReply(read, locator, noun, notes) {
|
|
378
|
+
const { count, span, sections } = read;
|
|
379
|
+
const all = [...notes, ...read.notes];
|
|
380
|
+
const where = locator.text !== void 0 ? sections.map((s) => s.heading.toLowerCase()).join(", ") : span ? `${noun}${span.start === span.end ? "" : "s"} ${dash(span.start, span.end)}` : null;
|
|
381
|
+
return {
|
|
382
|
+
ok: true,
|
|
383
|
+
format: "text",
|
|
384
|
+
where,
|
|
385
|
+
outline: `${count} ${noun}${count === 1 ? "" : "s"}`,
|
|
386
|
+
sections: fit(sections, all, () => `Ask for {"page": "N-M"} to read further ${noun}s.`),
|
|
387
|
+
notes: all
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
async function readPdf(req, locator) {
|
|
391
|
+
refuseKeys(locator, ["page", "text"], req);
|
|
392
|
+
const read = await readPdfPages(req.bytes, req.name, locator, "page");
|
|
393
|
+
return pagesReply(read, locator, "page", []);
|
|
394
|
+
}
|
|
395
|
+
function refuseKeys(locator, allowed, req) {
|
|
396
|
+
const extra = Object.keys(locator).filter((k) => locator[k] !== void 0 && !allowed.includes(k));
|
|
397
|
+
if (extra.length) {
|
|
398
|
+
throw new ReadError(`A .${req.ext} file is read by ${allowed.map((k) => `{${k}}`).join(", ")} \u2014 not by ${extra.map((k) => `{${k}}`).join(", ")}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
async function readMaterialBytes(input) {
|
|
402
|
+
const view = (b) => new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
|
|
403
|
+
const req = { ...input, bytes: view(input.bytes), rendition: input.rendition ? view(input.rendition) : null };
|
|
404
|
+
const locator = req.locator ?? {};
|
|
405
|
+
try {
|
|
406
|
+
switch (req.ext) {
|
|
407
|
+
case "xlsx":
|
|
408
|
+
case "xlsm":
|
|
409
|
+
return await readWorkbook(req, locator);
|
|
410
|
+
case "docx":
|
|
411
|
+
return await readWord(req, locator);
|
|
412
|
+
case "pptx":
|
|
413
|
+
return await readDeck(req, locator);
|
|
414
|
+
case "pdf":
|
|
415
|
+
return await readPdf(req, locator);
|
|
416
|
+
default:
|
|
417
|
+
if (req.ext === "csv" && locator.range !== void 0) return readCsvRange(req, locator);
|
|
418
|
+
if (import_locator.TEXT_EXTS.has(req.ext)) return readTextFile(req, locator);
|
|
419
|
+
return { ok: false, reason: `.${req.ext} files are not read as text` };
|
|
420
|
+
}
|
|
421
|
+
} catch (err) {
|
|
422
|
+
if (err instanceof ReadError || err instanceof import_zip_reader.CapError) return { ok: false, reason: err.message };
|
|
423
|
+
return { ok: false, reason: `${req.name} could not be read as a .${req.ext} file (${err.message})` };
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
427
|
+
0 && (module.exports = {
|
|
428
|
+
MAX_OUTPUT_CHARS,
|
|
429
|
+
readMaterialBytes
|
|
430
|
+
});
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var reader_host_exports = {};
|
|
29
|
+
__export(reader_host_exports, {
|
|
30
|
+
READER_HEAP_MB: () => READER_HEAP_MB,
|
|
31
|
+
READ_TIMEOUT_MS: () => READ_TIMEOUT_MS,
|
|
32
|
+
readMaterial: () => readMaterial,
|
|
33
|
+
readerLaunch: () => readerLaunch,
|
|
34
|
+
readerScript: () => readerScript,
|
|
35
|
+
runReader: () => runReader
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(reader_host_exports);
|
|
38
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
39
|
+
var import_node_path = __toESM(require("node:path"));
|
|
40
|
+
var import_node_child_process = require("node:child_process");
|
|
41
|
+
var import_artefact_content_service = require("../artefact-content-service");
|
|
42
|
+
var import_rendition_service = require("../rendition/rendition-service");
|
|
43
|
+
var import_command = require("../../mcp/connector/command");
|
|
44
|
+
var import_confined_fs = require("../confined-fs");
|
|
45
|
+
var import_locator = require("../../../shared/lib/locator");
|
|
46
|
+
var import_cloud_files = require("../cloud-files");
|
|
47
|
+
const READ_CAPS = {
|
|
48
|
+
pdf: 100 * 1024 * 1024,
|
|
49
|
+
pptx: 100 * 1024 * 1024,
|
|
50
|
+
xlsx: 25 * 1024 * 1024,
|
|
51
|
+
xlsm: 25 * 1024 * 1024,
|
|
52
|
+
docx: 25 * 1024 * 1024
|
|
53
|
+
};
|
|
54
|
+
const TEXT_CAP = 20 * 1024 * 1024;
|
|
55
|
+
const IMAGE_CAP = 5 * 1024 * 1024;
|
|
56
|
+
const IMAGE_TYPES = {
|
|
57
|
+
png: { mimeType: "image/png", magic: (b) => b.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])) },
|
|
58
|
+
jpg: { mimeType: "image/jpeg", magic: (b) => b[0] === 255 && b[1] === 216 && b[2] === 255 },
|
|
59
|
+
jpeg: { mimeType: "image/jpeg", magic: (b) => b[0] === 255 && b[1] === 216 && b[2] === 255 },
|
|
60
|
+
gif: { mimeType: "image/gif", magic: (b) => b.subarray(0, 4).toString("latin1") === "GIF8" },
|
|
61
|
+
webp: { mimeType: "image/webp", magic: (b) => b.subarray(0, 4).toString("latin1") === "RIFF" && b.subarray(8, 12).toString("latin1") === "WEBP" }
|
|
62
|
+
};
|
|
63
|
+
const VIDEO_EXTS = /* @__PURE__ */ new Set(["mp4", "webm", "mov"]);
|
|
64
|
+
const READ_TIMEOUT_MS = 3e4;
|
|
65
|
+
const READER_HEAP_MB = 768;
|
|
66
|
+
function readerScript() {
|
|
67
|
+
const resourcesPath = process.resourcesPath;
|
|
68
|
+
if ((0, import_command.isPackagedElectron)({ execPath: process.execPath, electronVersion: process.versions.electron }) && resourcesPath) {
|
|
69
|
+
return import_node_path.default.join(resourcesPath, "reader", "material-reader.mjs");
|
|
70
|
+
}
|
|
71
|
+
const source = import_node_path.default.join(__dirname, "child.ts");
|
|
72
|
+
if (__filename.endsWith(".ts") && import_node_fs.default.existsSync(source)) return source;
|
|
73
|
+
const inPackage = import_node_path.default.resolve(__dirname, "..", "..", "..", "..", "reader", "material-reader.mjs");
|
|
74
|
+
if (import_node_fs.default.existsSync(inPackage)) return inPackage;
|
|
75
|
+
return import_node_path.default.join(process.cwd(), "out", "reader", "material-reader.mjs");
|
|
76
|
+
}
|
|
77
|
+
function readerLaunch(script, opts = {}) {
|
|
78
|
+
const heap = `--max-old-space-size=${opts.heapMb ?? READER_HEAP_MB}`;
|
|
79
|
+
const env = process.versions.electron ? { ELECTRON_RUN_AS_NODE: "1" } : {};
|
|
80
|
+
if (script.endsWith(".ts")) {
|
|
81
|
+
return { execArgv: [heap, "--import", "tsx"], cwd: import_node_path.default.resolve(__dirname, "..", "..", "..", ".."), env };
|
|
82
|
+
}
|
|
83
|
+
return { execArgv: [heap, "--permission", `--allow-fs-read=${script}`], cwd: import_node_path.default.dirname(script), env };
|
|
84
|
+
}
|
|
85
|
+
function runReader(req, opts = {}) {
|
|
86
|
+
return new Promise((resolve) => {
|
|
87
|
+
let settled = false;
|
|
88
|
+
let stderr = "";
|
|
89
|
+
let outOfMemory = false;
|
|
90
|
+
let child;
|
|
91
|
+
try {
|
|
92
|
+
const script = (0, import_confined_fs.canonicalRoot)(opts.script ?? readerScript());
|
|
93
|
+
const launch = readerLaunch(script, opts);
|
|
94
|
+
child = (0, import_node_child_process.fork)(script, [], {
|
|
95
|
+
execPath: process.execPath,
|
|
96
|
+
execArgv: launch.execArgv,
|
|
97
|
+
cwd: launch.cwd,
|
|
98
|
+
env: launch.env,
|
|
99
|
+
// pdf.js warns on every load that it cannot draw, which a reader never
|
|
100
|
+
// asks it to: stdout is dropped, and stderr kept only to tell a heap
|
|
101
|
+
// limit from any other death.
|
|
102
|
+
stdio: ["ignore", "ignore", "pipe", "ipc"],
|
|
103
|
+
serialization: "advanced"
|
|
104
|
+
});
|
|
105
|
+
} catch (err) {
|
|
106
|
+
resolve({ ok: false, reason: `The reader could not start (${err.message})` });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
child.stderr?.on("data", (d) => {
|
|
110
|
+
const joined = stderr + d.toString();
|
|
111
|
+
if (/heap limit|out of memory/i.test(joined)) outOfMemory = true;
|
|
112
|
+
stderr = joined.slice(-4e3);
|
|
113
|
+
});
|
|
114
|
+
const timeoutMs = opts.timeoutMs ?? READ_TIMEOUT_MS;
|
|
115
|
+
const done = (r) => {
|
|
116
|
+
if (settled) return;
|
|
117
|
+
settled = true;
|
|
118
|
+
clearTimeout(timer);
|
|
119
|
+
if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL");
|
|
120
|
+
resolve(r);
|
|
121
|
+
};
|
|
122
|
+
const timer = setTimeout(() => done({
|
|
123
|
+
ok: false,
|
|
124
|
+
timedOut: true,
|
|
125
|
+
reason: `Reading ${req.name} took longer than ${Math.round(timeoutMs / 1e3)}s and was stopped. Ask for a smaller part of it.`
|
|
126
|
+
}), timeoutMs);
|
|
127
|
+
child.once("message", (reply) => done(reply));
|
|
128
|
+
child.once("error", (err) => done({ ok: false, reason: `${req.name} could not be read (${err.message})` }));
|
|
129
|
+
child.once("exit", (code, signal) => {
|
|
130
|
+
const judge = () => setImmediate(() => {
|
|
131
|
+
if (settled) return;
|
|
132
|
+
if (!outOfMemory) {
|
|
133
|
+
console.warn(`[reader] stopped without answering (code ${code}, signal ${signal}): ${stderr.trim().split("\n").slice(-5).join(" | ") || "no output"}`);
|
|
134
|
+
}
|
|
135
|
+
done({
|
|
136
|
+
ok: false,
|
|
137
|
+
reason: outOfMemory ? `${req.name} needs more memory to read than CodeTrellis allows. Ask for a smaller part of it.` : `${req.name} could not be read (the reader stopped)`
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
if (!child.connected) {
|
|
141
|
+
judge();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const cap = setTimeout(judge, 2e3);
|
|
145
|
+
child.once("disconnect", () => {
|
|
146
|
+
clearTimeout(cap);
|
|
147
|
+
judge();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
child.send({ ...req, bytes: req.bytes });
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
async function readBytes(file, cap) {
|
|
154
|
+
try {
|
|
155
|
+
return await (0, import_artefact_content_service.readServableCapped)(file, cap);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
return err instanceof import_cloud_files.NotOnDeviceError ? "cloud" : "missing";
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async function readMaterial(attachmentUid, locator, opts = {}) {
|
|
161
|
+
const file = await (0, import_artefact_content_service.resolveServable)(attachmentUid);
|
|
162
|
+
if (!file) return { ok: false, status: 404, reason: "No material with that uid is a file CodeTrellis can read" };
|
|
163
|
+
const name = import_node_path.default.basename(file.rel);
|
|
164
|
+
const ext = import_node_path.default.extname(file.rel).slice(1).toLowerCase();
|
|
165
|
+
const base = { name, itemUid: file.itemUid };
|
|
166
|
+
const hasLocator = !!locator && Object.values(locator).some((v) => v !== void 0);
|
|
167
|
+
if (VIDEO_EXTS.has(ext)) {
|
|
168
|
+
return { ok: false, status: 415, reason: `${name} is a video; it can be watched in CodeTrellis but not read as text`, ...base };
|
|
169
|
+
}
|
|
170
|
+
if (ext === "xls") {
|
|
171
|
+
return { ok: false, status: 415, reason: `${name} is an old-format Excel workbook, which is not read as text; saved as .xlsx it can be`, ...base };
|
|
172
|
+
}
|
|
173
|
+
const image = IMAGE_TYPES[ext];
|
|
174
|
+
if (image) {
|
|
175
|
+
if (hasLocator) return { ok: false, status: 422, reason: `${name} is an image; it is read whole, without a locator`, ...base };
|
|
176
|
+
const bytes2 = await readBytes(file, IMAGE_CAP);
|
|
177
|
+
if (bytes2 === "cloud") return { ok: false, status: 409, reason: `${name} is not on this device yet: it is still only in the cloud`, ...base };
|
|
178
|
+
if (bytes2 === "missing") return { ok: false, status: 404, reason: `${name} is not there, or is not a regular file in the project`, ...base };
|
|
179
|
+
if (!bytes2) return { ok: false, status: 413, reason: `${name} is larger than the ${IMAGE_CAP / 1024 / 1024} MB an image read returns`, ...base };
|
|
180
|
+
if (!image.magic(bytes2)) return { ok: false, status: 422, reason: `${name} is named .${ext} but is not that kind of image`, ...base };
|
|
181
|
+
return { ok: true, kind: "image", ...base, mimeType: image.mimeType, base64: bytes2.toString("base64"), bytes: bytes2.length };
|
|
182
|
+
}
|
|
183
|
+
const cap = READ_CAPS[ext] ?? (import_locator.TEXT_EXTS.has(ext) ? TEXT_CAP : 0);
|
|
184
|
+
if (!cap) return { ok: false, status: 415, reason: `.${ext} files are not read as text`, ...base };
|
|
185
|
+
const bytes = await readBytes(file, cap);
|
|
186
|
+
if (bytes === "cloud") return { ok: false, status: 409, reason: `${name} is not on this device yet: it is still only in the cloud`, ...base };
|
|
187
|
+
if (bytes === "missing") return { ok: false, status: 404, reason: `${name} is not there, or is not a regular file in the project`, ...base };
|
|
188
|
+
if (!bytes) return { ok: false, status: 413, reason: `${name} is larger than the ${Math.round(cap / 1024 / 1024)} MB CodeTrellis reads of a .${ext} file`, ...base };
|
|
189
|
+
const rendition = ext === "docx" || ext === "pptx" ? await (0, import_rendition_service.existingRendition)(bytes, ext, opts.engine) : null;
|
|
190
|
+
const reply = await runReader({ name, ext, bytes, locator, rendition }, opts);
|
|
191
|
+
if (!reply.ok) return { ok: false, status: "timedOut" in reply ? 504 : 422, reason: reply.reason, ...base };
|
|
192
|
+
return { ok: true, kind: "text", ...base, reply };
|
|
193
|
+
}
|
|
194
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
195
|
+
0 && (module.exports = {
|
|
196
|
+
READER_HEAP_MB,
|
|
197
|
+
READ_TIMEOUT_MS,
|
|
198
|
+
readMaterial,
|
|
199
|
+
readerLaunch,
|
|
200
|
+
readerScript,
|
|
201
|
+
runReader
|
|
202
|
+
});
|