@gajae-code/coding-agent 0.17.2 → 0.17.5
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/CHANGELOG.md +267 -0
- package/dist/types/cli/daemon-cli.d.ts +3 -1
- package/dist/types/cli/github-release.d.ts +17 -0
- package/dist/types/cli/public-command-entry.d.ts +56 -0
- package/dist/types/cli/public-command-errors.d.ts +126 -0
- package/dist/types/cli/public-command-evidence.d.ts +99 -0
- package/dist/types/cli/public-command-help.d.ts +65 -0
- package/dist/types/cli/public-command-registry.d.ts +69 -0
- package/dist/types/cli/session-picker.d.ts +1 -1
- package/dist/types/cli/setup-cli.d.ts +1 -0
- package/dist/types/cli/skills-cli.d.ts +5 -0
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +4 -50
- package/dist/types/commands/sdk.d.ts +20 -37
- package/dist/types/commands/setup.d.ts +3 -0
- package/dist/types/commands/skills.d.ts +9 -0
- package/dist/types/config/autorouting-tier-map.d.ts +1049 -3
- package/dist/types/config/file-lock.d.ts +13 -3
- package/dist/types/config/model-profile-activation.d.ts +45 -1
- package/dist/types/config/model-registry.d.ts +14 -3
- package/dist/types/config/model-resolver.d.ts +1 -1
- package/dist/types/config/settings-schema.d.ts +11 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
- package/dist/types/daemon/operator-contract.d.ts +5 -1
- package/dist/types/eval/js/worker-protocol.d.ts +2 -0
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/extensibility/extensions/types.d.ts +12 -0
- package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
- package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +11 -2
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
- package/dist/types/extensibility/shared-events.d.ts +3 -1
- package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
- package/dist/types/harness-control-plane/control-endpoint.d.ts +4 -1
- package/dist/types/harness-control-plane/finalize.d.ts +14 -3
- package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
- package/dist/types/internal-urls/index.d.ts +1 -0
- package/dist/types/internal-urls/parse.d.ts +9 -1
- package/dist/types/main.d.ts +23 -1
- package/dist/types/modes/acp/acp-agent.d.ts +55 -1
- package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
- package/dist/types/modes/components/session-selector.d.ts +5 -2
- package/dist/types/modes/components/user-message-selector.d.ts +5 -2
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
- package/dist/types/modes/types.d.ts +2 -2
- package/dist/types/runtime/process-lifecycle.d.ts +2 -0
- package/dist/types/runtime-mcp/loader.d.ts +2 -0
- package/dist/types/runtime-mcp/manager.d.ts +69 -6
- package/dist/types/runtime-mcp/pool.d.ts +17 -0
- package/dist/types/runtime-mcp/redaction.d.ts +20 -0
- package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
- package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
- package/dist/types/sdk/broker/broker.d.ts +17 -4
- package/dist/types/sdk/broker/ensure.d.ts +3 -0
- package/dist/types/sdk/broker/identity.d.ts +5 -1
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
- package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
- package/dist/types/sdk/broker/managed-task-dag.d.ts +1335 -0
- package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
- package/dist/types/sdk/broker/runtime.d.ts +1 -1
- package/dist/types/sdk/broker/session-index.d.ts +22 -3
- package/dist/types/sdk/broker/spawn-authority.d.ts +12 -0
- package/dist/types/sdk/broker/startup-failure.d.ts +4 -0
- package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
- package/dist/types/sdk/bus/index.d.ts +19 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +7 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
- package/dist/types/sdk/cli/master-cli.d.ts +6 -10
- package/dist/types/sdk/cli/rows.d.ts +19 -1
- package/dist/types/sdk/cli/session-cli.d.ts +22 -5
- package/dist/types/sdk/client/client.d.ts +2 -0
- package/dist/types/sdk/guides/cli.d.ts +3 -4
- package/dist/types/sdk/guides/verify.d.ts +2 -0
- package/dist/types/sdk/host/host.d.ts +9 -0
- package/dist/types/sdk/host/session-runtime.d.ts +31 -0
- package/dist/types/sdk/host/types.d.ts +10 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +85 -0
- package/dist/types/sdk/prompt-deadline-manager.d.ts +37 -0
- package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
- package/dist/types/sdk/router/session-router.d.ts +2 -0
- package/dist/types/sdk/session.d.ts +3 -3
- package/dist/types/sdk/startup-capability.d.ts +2 -0
- package/dist/types/sdk/transport/relay.d.ts +1 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +48 -4
- package/dist/types/sdk/transport/stdio.d.ts +5 -1
- package/dist/types/session/agent-session.d.ts +175 -23
- package/dist/types/session/fallback-chain-controller.d.ts +6 -6
- package/dist/types/session/fold-coordinator.d.ts +17 -3
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
- package/dist/types/session/session-manager.d.ts +64 -1
- package/dist/types/session/session-work-lease.d.ts +14 -0
- package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
- package/dist/types/setup/provider-onboarding.d.ts +81 -1
- package/dist/types/task/types.d.ts +2 -0
- package/dist/types/tools/bash-interactive.d.ts +1 -0
- package/dist/types/tools/bash.d.ts +37 -11
- package/dist/types/tools/fetch.d.ts +10 -1
- package/dist/types/tools/job.d.ts +1 -1
- package/dist/types/tools/steer-fold.d.ts +31 -0
- package/dist/types/tools/subagent.d.ts +8 -1
- package/dist/types/utils/git.d.ts +28 -2
- package/dist/types/utils/mupdf-embedded.d.ts +2 -0
- package/dist/types/utils/mupdf.d.ts +4 -0
- package/dist/types/utils/session-title-generation.d.ts +6 -0
- package/dist/types/utils/title-generator.d.ts +11 -2
- package/dist/types/web/scrapers/types.d.ts +3 -0
- package/package.json +18 -10
- package/scripts/build-binary.ts +9 -3
- package/scripts/compile-args.ts +0 -9
- package/scripts/embed-mupdf.ts +52 -0
- package/scripts/generate-sdk-operation-inventory.ts +31 -1
- package/scripts/vendor-markit.ts +196 -0
- package/src/async/job-manager.ts +22 -1
- package/src/cli/daemon-cli.ts +53 -18
- package/src/cli/github-release.ts +87 -5
- package/src/cli/mcp-cli.ts +38 -4
- package/src/cli/public-command-entry.ts +450 -0
- package/src/cli/public-command-errors.ts +581 -0
- package/src/cli/public-command-evidence.ts +717 -0
- package/src/cli/public-command-help.ts +360 -0
- package/src/cli/public-command-registry.ts +541 -0
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +10 -1
- package/src/cli/skills-cli.ts +46 -2
- package/src/cli/stats-cli.ts +11 -1
- package/src/cli.ts +61 -1
- package/src/commands/daemon.ts +65 -69
- package/src/commands/sdk.ts +175 -117
- package/src/commands/setup.ts +2 -0
- package/src/commands/skills.ts +11 -0
- package/src/config/autorouting-tier-map.ts +543 -3
- package/src/config/file-lock.ts +206 -65
- package/src/config/model-discovery-manager.ts +4 -4
- package/src/config/model-profile-activation.ts +417 -66
- package/src/config/model-registry.ts +254 -36
- package/src/config/model-resolver.ts +6 -1
- package/src/config/settings-schema.ts +26 -2
- package/src/coordinator-mcp/policy.ts +10 -5
- package/src/coordinator-mcp/question-gate-codec.ts +17 -0
- package/src/coordinator-mcp/question-state.ts +179 -9
- package/src/coordinator-mcp/server.ts +521 -87
- package/src/coordinator-mcp/session-reaper.ts +6 -4
- package/src/crash/record-loader.ts +6 -2
- package/src/daemon/operator-contract.ts +26 -12
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
- package/src/eval/js/context-manager.ts +8 -8
- package/src/eval/js/worker-core.ts +9 -4
- package/src/eval/js/worker-protocol.ts +2 -0
- package/src/exec/bash-executor.ts +3 -0
- package/src/extensibility/extensions/runner.ts +52 -4
- package/src/extensibility/extensions/types.ts +10 -0
- package/src/extensibility/gjc-plugins/registry.ts +196 -37
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +46 -8
- package/src/extensibility/runtime-skill-discovery.ts +61 -3
- package/src/extensibility/shared-events.ts +3 -1
- package/src/gjc-runtime/session-state-lock.ts +165 -24
- package/src/gjc-runtime/state-writer.ts +317 -6
- package/src/gjc-runtime/ultragoal-succession.ts +31 -3
- package/src/harness-control-plane/control-endpoint.ts +24 -6
- package/src/harness-control-plane/finalize.ts +312 -25
- package/src/harness-control-plane/owner.ts +323 -89
- package/src/internal-urls/docs-index.generated.ts +23 -20
- package/src/internal-urls/embedded-protocol.ts +83 -0
- package/src/internal-urls/index.ts +1 -0
- package/src/internal-urls/parse.ts +21 -1
- package/src/internal-urls/router.ts +4 -2
- package/src/main.ts +192 -74
- package/src/modes/acp/acp-agent.ts +973 -56
- package/src/modes/acp/startup-provenance.ts +59 -0
- package/src/modes/components/custom-provider-wizard.ts +308 -7
- package/src/modes/components/gjc-bundle-settings.ts +21 -1
- package/src/modes/components/oauth-selector.ts +9 -0
- package/src/modes/components/session-selector.ts +47 -4
- package/src/modes/components/tool-status-header.ts +72 -6
- package/src/modes/components/user-message-selector.ts +57 -15
- package/src/modes/controllers/command-controller.ts +58 -32
- package/src/modes/controllers/extension-ui-controller.ts +33 -7
- package/src/modes/controllers/input-controller.ts +4 -0
- package/src/modes/controllers/runtime-mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +161 -15
- package/src/modes/interactive-mode.ts +21 -7
- package/src/modes/runtime-init.ts +1 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
- package/src/modes/types.ts +2 -2
- package/src/prompts/agent-fragments/browser-aside.md +1 -0
- package/src/prompts/system/title-system.md +1 -1
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/job.md +1 -1
- package/src/prompts/tools/read.md +2 -0
- package/src/runtime/network-prewarm-service.test.ts +36 -1
- package/src/runtime/network-prewarm-service.ts +28 -3
- package/src/runtime/process-lifecycle.ts +22 -11
- package/src/runtime-mcp/config.ts +16 -1
- package/src/runtime-mcp/loader.ts +6 -3
- package/src/runtime-mcp/manager.ts +845 -109
- package/src/runtime-mcp/pool.test.ts +31 -0
- package/src/runtime-mcp/pool.ts +304 -28
- package/src/runtime-mcp/redaction.ts +42 -0
- package/src/runtime-mcp/startup-policy.ts +7 -0
- package/src/runtime-mcp/tool-bridge.ts +71 -0
- package/src/runtime-mcp/transports/http.ts +108 -25
- package/src/sdk/acp/adapter.ts +27 -8
- package/src/sdk/broker/broker.ts +1431 -198
- package/src/sdk/broker/ensure.ts +21 -3
- package/src/sdk/broker/identity.ts +22 -1
- package/src/sdk/broker/lifecycle-ledger.ts +95 -31
- package/src/sdk/broker/lifecycle.ts +690 -141
- package/src/sdk/broker/managed-task-dag.ts +1927 -0
- package/src/sdk/broker/managed-task-verification.ts +642 -0
- package/src/sdk/broker/runtime.ts +1 -1
- package/src/sdk/broker/session-index.ts +97 -4
- package/src/sdk/broker/spawn-authority.ts +175 -14
- package/src/sdk/broker/startup-failure.ts +80 -1
- package/src/sdk/broker/stderr-drainer.ts +59 -0
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
- package/src/sdk/bus/index.ts +707 -81
- package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
- package/src/sdk/bus/telegram-daemon-contract.ts +7 -1
- package/src/sdk/bus/telegram-daemon.ts +10 -3
- package/src/sdk/cli/master-cli.ts +47 -36
- package/src/sdk/cli/rows.ts +30 -7
- package/src/sdk/cli/session-cli.ts +705 -184
- package/src/sdk/client/client.ts +18 -0
- package/src/sdk/guides/catalog.ts +2 -2
- package/src/sdk/guides/cli.ts +20 -62
- package/src/sdk/guides/verify.ts +14 -0
- package/src/sdk/host/host.ts +49 -5
- package/src/sdk/host/session-runtime.test.ts +184 -2
- package/src/sdk/host/session-runtime.ts +322 -101
- package/src/sdk/host/types.ts +12 -1
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
- package/src/sdk/host/websocket-transport.ts +40 -6
- package/src/sdk/index.ts +11 -0
- package/src/sdk/lifecycle/service.ts +2 -0
- package/src/sdk/prompt-deadline-flush.ts +356 -0
- package/src/sdk/prompt-deadline-manager.ts +133 -1
- package/src/sdk/prompt-tool-boundary.ts +121 -0
- package/src/sdk/protocol/operation-inventory.generated.json +106 -0
- package/src/sdk/router/session-router.ts +9 -1
- package/src/sdk/session.ts +763 -116
- package/src/sdk/startup-capability.ts +1 -1
- package/src/sdk/transport/relay.ts +71 -6
- package/src/sdk/transport/serve-cli.ts +397 -42
- package/src/sdk/transport/socket.ts +12 -11
- package/src/sdk/transport/stdio.ts +7 -3
- package/src/session/agent-session.ts +2472 -407
- package/src/session/fallback-chain-controller.ts +6 -7
- package/src/session/fold-coordinator.ts +24 -5
- package/src/session/internal/managed-session-scope.ts +68 -18
- package/src/session/internal/managed-session-storage.ts +334 -12
- package/src/session/session-manager.ts +382 -44
- package/src/session/session-work-lease.ts +34 -0
- package/src/setup/model-onboarding-guidance.ts +1 -1
- package/src/setup/provider-onboarding.ts +397 -24
- package/src/setup/provider-presets.json +2 -1
- package/src/slash-commands/builtin-registry.ts +259 -15
- package/src/task/executor.ts +46 -17
- package/src/task/index.ts +14 -2
- package/src/task/types.ts +2 -0
- package/src/tools/bash-interactive.ts +2 -0
- package/src/tools/bash.ts +118 -78
- package/src/tools/fetch.ts +140 -25
- package/src/tools/job.ts +151 -25
- package/src/tools/output-meta.ts +15 -2
- package/src/tools/path-utils.ts +27 -3
- package/src/tools/read.ts +3 -3
- package/src/tools/steer-fold.ts +107 -0
- package/src/tools/subagent-render.ts +24 -1
- package/src/tools/subagent.ts +27 -1
- package/src/tools/tool-catalog.generated.ts +29 -2
- package/src/tools/tool-errors.ts +4 -0
- package/src/utils/git.ts +53 -3
- package/src/utils/markit.ts +55 -41
- package/src/utils/mupdf-assets.d.ts +4 -0
- package/src/utils/mupdf-embedded.ts +4 -0
- package/src/utils/mupdf.ts +136 -0
- package/src/utils/session-title-generation.ts +29 -0
- package/src/utils/title-generator.ts +46 -2
- package/src/web/scrapers/types.ts +24 -3
- package/vendor/markit-ai/LICENSE +21 -0
- package/vendor/markit-ai/MANIFEST.json +412 -0
- package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
- package/vendor/markit-ai/dist/commands/config.js +139 -0
- package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
- package/vendor/markit-ai/dist/commands/convert.js +113 -0
- package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/formats.js +92 -0
- package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/init.js +29 -0
- package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/onboard.js +61 -0
- package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
- package/vendor/markit-ai/dist/commands/plugin.js +58 -0
- package/vendor/markit-ai/dist/config.d.ts +26 -0
- package/vendor/markit-ai/dist/config.js +42 -0
- package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
- package/vendor/markit-ai/dist/converters/audio.js +104 -0
- package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
- package/vendor/markit-ai/dist/converters/csv.js +83 -0
- package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/docx.js +57 -0
- package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/epub.js +128 -0
- package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
- package/vendor/markit-ai/dist/converters/github.js +148 -0
- package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/html.js +30 -0
- package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/image.js +124 -0
- package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
- package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
- package/vendor/markit-ai/dist/converters/iwork.js +391 -0
- package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/json.js +21 -0
- package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
- package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
- package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
- package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
- package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
- package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
- package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
- package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
- package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
- package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
- package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
- package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
- package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
- package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
- package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
- package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
- package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/pptx.js +289 -0
- package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
- package/vendor/markit-ai/dist/converters/rss.js +138 -0
- package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
- package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
- package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/xml.js +18 -0
- package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/yaml.js +17 -0
- package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/zip.js +57 -0
- package/vendor/markit-ai/dist/index.d.ts +30 -0
- package/vendor/markit-ai/dist/index.js +26 -0
- package/vendor/markit-ai/dist/main.d.ts +2 -0
- package/vendor/markit-ai/dist/main.js +191 -0
- package/vendor/markit-ai/dist/markit.d.ts +45 -0
- package/vendor/markit-ai/dist/markit.js +267 -0
- package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
- package/vendor/markit-ai/dist/plugins/api.js +42 -0
- package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
- package/vendor/markit-ai/dist/plugins/index.js +3 -0
- package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
- package/vendor/markit-ai/dist/plugins/installer.js +176 -0
- package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
- package/vendor/markit-ai/dist/plugins/loader.js +61 -0
- package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
- package/vendor/markit-ai/dist/plugins/types.js +1 -0
- package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
- package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
- package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
- package/vendor/markit-ai/dist/providers/index.js +56 -0
- package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
- package/vendor/markit-ai/dist/providers/openai.js +76 -0
- package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
- package/vendor/markit-ai/dist/providers/types.js +1 -0
- package/vendor/markit-ai/dist/types.d.ts +36 -0
- package/vendor/markit-ai/dist/types.js +1 -0
- package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
- package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
- package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
- package/vendor/markit-ai/dist/utils/output.js +31 -0
- package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
- package/vendor/markit-ai/dist/utils/turndown.js +70 -0
- package/vendor/markit-ai/package.json +74 -0
- package/vendor/markit-ai.patch +49 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { XMLParser } from "fast-xml-parser";
|
|
4
|
+
import JSZip from "jszip";
|
|
5
|
+
const EXTENSIONS = [".pptx"];
|
|
6
|
+
const MIMETYPES = [
|
|
7
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
8
|
+
];
|
|
9
|
+
export class PptxConverter {
|
|
10
|
+
name = "pptx";
|
|
11
|
+
accepts(streamInfo) {
|
|
12
|
+
if (streamInfo.extension && EXTENSIONS.includes(streamInfo.extension))
|
|
13
|
+
return true;
|
|
14
|
+
if (streamInfo.mimetype &&
|
|
15
|
+
MIMETYPES.some((m) => streamInfo.mimetype?.startsWith(m)))
|
|
16
|
+
return true;
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
async convert(input, streamInfo) {
|
|
20
|
+
const zip = await JSZip.loadAsync(input);
|
|
21
|
+
const parser = new XMLParser({
|
|
22
|
+
ignoreAttributes: false,
|
|
23
|
+
attributeNamePrefix: "@_",
|
|
24
|
+
textNodeName: "#text",
|
|
25
|
+
processEntities: { maxTotalExpansions: 1_000_000 },
|
|
26
|
+
});
|
|
27
|
+
// Get slide order from presentation.xml
|
|
28
|
+
const presXml = await zip.file("ppt/presentation.xml")?.async("string");
|
|
29
|
+
if (!presXml)
|
|
30
|
+
throw new Error("Invalid PPTX: missing presentation.xml");
|
|
31
|
+
const pres = parser.parse(presXml);
|
|
32
|
+
const sldIdList = pres["p:presentation"]?.["p:sldIdLst"]?.["p:sldId"];
|
|
33
|
+
const sldIds = Array.isArray(sldIdList)
|
|
34
|
+
? sldIdList
|
|
35
|
+
: sldIdList
|
|
36
|
+
? [sldIdList]
|
|
37
|
+
: [];
|
|
38
|
+
// Get relationship mappings
|
|
39
|
+
const relsXml = await zip
|
|
40
|
+
.file("ppt/_rels/presentation.xml.rels")
|
|
41
|
+
?.async("string");
|
|
42
|
+
const rels = relsXml ? parser.parse(relsXml) : null;
|
|
43
|
+
const relList = rels?.Relationships?.Relationship;
|
|
44
|
+
const relArray = Array.isArray(relList)
|
|
45
|
+
? relList
|
|
46
|
+
: relList
|
|
47
|
+
? [relList]
|
|
48
|
+
: [];
|
|
49
|
+
const relMap = new Map();
|
|
50
|
+
for (const r of relArray) {
|
|
51
|
+
relMap.set(r["@_Id"], r["@_Target"]);
|
|
52
|
+
}
|
|
53
|
+
// Map slide IDs to file paths in order
|
|
54
|
+
const slidePaths = [];
|
|
55
|
+
for (const sld of sldIds) {
|
|
56
|
+
const rId = sld["@_r:id"];
|
|
57
|
+
const target = relMap.get(rId);
|
|
58
|
+
if (target)
|
|
59
|
+
slidePaths.push(`ppt/${target}`);
|
|
60
|
+
}
|
|
61
|
+
// If we couldn't resolve from rels, fall back to finding slide files
|
|
62
|
+
if (slidePaths.length === 0) {
|
|
63
|
+
const slideFiles = Object.keys(zip.files)
|
|
64
|
+
.filter((f) => /^ppt\/slides\/slide\d+\.xml$/.test(f))
|
|
65
|
+
.sort((a, b) => {
|
|
66
|
+
const na = parseInt(a.match(/slide(\d+)/)?.[1] || "0", 10);
|
|
67
|
+
const nb = parseInt(b.match(/slide(\d+)/)?.[1] || "0", 10);
|
|
68
|
+
return na - nb;
|
|
69
|
+
});
|
|
70
|
+
slidePaths.push(...slideFiles);
|
|
71
|
+
}
|
|
72
|
+
const imageDir = streamInfo.imageDir;
|
|
73
|
+
if (imageDir) {
|
|
74
|
+
mkdirSync(imageDir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
const sections = [];
|
|
77
|
+
let imageCount = 0;
|
|
78
|
+
for (let i = 0; i < slidePaths.length; i++) {
|
|
79
|
+
const slideXml = await zip.file(slidePaths[i])?.async("string");
|
|
80
|
+
if (!slideXml)
|
|
81
|
+
continue;
|
|
82
|
+
const slide = parser.parse(slideXml);
|
|
83
|
+
const spTree = slide["p:sld"]?.["p:cSld"]?.["p:spTree"];
|
|
84
|
+
if (!spTree)
|
|
85
|
+
continue;
|
|
86
|
+
// Parse slide-level rels for image references
|
|
87
|
+
const slideRelsPath = `${slidePaths[i].replace("slides/slide", "slides/_rels/slide")}.rels`;
|
|
88
|
+
const slideRelsXml = await zip.file(slideRelsPath)?.async("string");
|
|
89
|
+
const slideRelMap = new Map();
|
|
90
|
+
if (slideRelsXml) {
|
|
91
|
+
const slideRels = parser.parse(slideRelsXml);
|
|
92
|
+
const relItems = toList(slideRels?.Relationships?.Relationship);
|
|
93
|
+
for (const r of relItems) {
|
|
94
|
+
slideRelMap.set(r["@_Id"], r["@_Target"]);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const slideLines = [`<!-- Slide ${i + 1} -->`];
|
|
98
|
+
const shapes = spTree["p:sp"];
|
|
99
|
+
const shapeList = Array.isArray(shapes) ? shapes : shapes ? [shapes] : [];
|
|
100
|
+
let isTitle = true;
|
|
101
|
+
for (const shape of shapeList) {
|
|
102
|
+
const text = this.extractText(shape);
|
|
103
|
+
if (!text)
|
|
104
|
+
continue;
|
|
105
|
+
if (isTitle) {
|
|
106
|
+
slideLines.push(`# ${text}`);
|
|
107
|
+
isTitle = false;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
slideLines.push(text);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Extract embedded images
|
|
114
|
+
const pics = toList(spTree["p:pic"]);
|
|
115
|
+
for (const pic of pics) {
|
|
116
|
+
const blipFill = pic["p:blipFill"];
|
|
117
|
+
const rEmbed = blipFill?.["a:blip"]?.["@_r:embed"];
|
|
118
|
+
if (!rEmbed)
|
|
119
|
+
continue;
|
|
120
|
+
const target = slideRelMap.get(rEmbed);
|
|
121
|
+
if (!target)
|
|
122
|
+
continue;
|
|
123
|
+
// Resolve relative target against slide directory
|
|
124
|
+
const imagePath = target.startsWith("/")
|
|
125
|
+
? target.slice(1)
|
|
126
|
+
: `ppt/slides/${target}`;
|
|
127
|
+
// Normalize path (e.g. ppt/slides/../media/image1.png → ppt/media/image1.png)
|
|
128
|
+
const normalizedPath = imagePath
|
|
129
|
+
.split("/")
|
|
130
|
+
.reduce((parts, seg) => {
|
|
131
|
+
if (seg === "..")
|
|
132
|
+
parts.pop();
|
|
133
|
+
else
|
|
134
|
+
parts.push(seg);
|
|
135
|
+
return parts;
|
|
136
|
+
}, [])
|
|
137
|
+
.join("/");
|
|
138
|
+
const imageFile = zip.file(normalizedPath);
|
|
139
|
+
if (!imageFile)
|
|
140
|
+
continue;
|
|
141
|
+
imageCount++;
|
|
142
|
+
const name = pic["p:nvSpPr"]?.["p:cNvPr"]?.["@_name"] ||
|
|
143
|
+
pic["p:nvPicPr"]?.["p:cNvPr"]?.["@_name"] ||
|
|
144
|
+
`image_${imageCount}`;
|
|
145
|
+
if (imageDir) {
|
|
146
|
+
try {
|
|
147
|
+
const ext = normalizedPath.split(".").pop() || "png";
|
|
148
|
+
const filename = `slide${i + 1}_${imageCount}.${ext}`;
|
|
149
|
+
const filepath = join(imageDir, filename);
|
|
150
|
+
const buf = await imageFile.async("nodebuffer");
|
|
151
|
+
writeFileSync(filepath, buf);
|
|
152
|
+
slideLines.push(``);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
slideLines.push(`<!-- image: ${name} (slide ${i + 1}) -->`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
slideLines.push(`<!-- image: ${name} (slide ${i + 1}) -->`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Tables
|
|
163
|
+
const graphicFrames = spTree["p:graphicFrame"];
|
|
164
|
+
const gfList = Array.isArray(graphicFrames)
|
|
165
|
+
? graphicFrames
|
|
166
|
+
: graphicFrames
|
|
167
|
+
? [graphicFrames]
|
|
168
|
+
: [];
|
|
169
|
+
for (const gf of gfList) {
|
|
170
|
+
const table = this.extractTable(gf);
|
|
171
|
+
if (table)
|
|
172
|
+
slideLines.push(table);
|
|
173
|
+
}
|
|
174
|
+
// Slide notes
|
|
175
|
+
const noteFile = slidePaths[i].replace("slides/slide", "notesSlides/notesSlide");
|
|
176
|
+
const noteXml = await zip.file(noteFile)?.async("string");
|
|
177
|
+
if (noteXml) {
|
|
178
|
+
const note = parser.parse(noteXml);
|
|
179
|
+
const noteSpTree = note["p:notes"]?.["p:cSld"]?.["p:spTree"];
|
|
180
|
+
if (noteSpTree) {
|
|
181
|
+
const noteShapes = noteSpTree["p:sp"];
|
|
182
|
+
const noteList = Array.isArray(noteShapes)
|
|
183
|
+
? noteShapes
|
|
184
|
+
: noteShapes
|
|
185
|
+
? [noteShapes]
|
|
186
|
+
: [];
|
|
187
|
+
const noteTexts = [];
|
|
188
|
+
for (const ns of noteList) {
|
|
189
|
+
// Skip slide image placeholder
|
|
190
|
+
const phType = ns["p:nvSpPr"]?.["p:nvPr"]?.["p:ph"]?.["@_type"];
|
|
191
|
+
if (phType === "sldImg")
|
|
192
|
+
continue;
|
|
193
|
+
const t = this.extractText(ns);
|
|
194
|
+
if (t)
|
|
195
|
+
noteTexts.push(t);
|
|
196
|
+
}
|
|
197
|
+
if (noteTexts.length > 0) {
|
|
198
|
+
slideLines.push("\n### Notes:");
|
|
199
|
+
slideLines.push(noteTexts.join("\n"));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
sections.push(slideLines.join("\n"));
|
|
204
|
+
}
|
|
205
|
+
return { markdown: sections.join("\n\n").trim() };
|
|
206
|
+
}
|
|
207
|
+
extractText(shape) {
|
|
208
|
+
const txBody = shape["p:txBody"];
|
|
209
|
+
if (!txBody)
|
|
210
|
+
return "";
|
|
211
|
+
const paragraphs = txBody["a:p"];
|
|
212
|
+
const pList = Array.isArray(paragraphs)
|
|
213
|
+
? paragraphs
|
|
214
|
+
: paragraphs
|
|
215
|
+
? [paragraphs]
|
|
216
|
+
: [];
|
|
217
|
+
const lines = [];
|
|
218
|
+
for (const p of pList) {
|
|
219
|
+
const runs = p["a:r"];
|
|
220
|
+
const rList = Array.isArray(runs) ? runs : runs ? [runs] : [];
|
|
221
|
+
const parts = [];
|
|
222
|
+
for (const r of rList) {
|
|
223
|
+
const t = r["a:t"];
|
|
224
|
+
if (t != null)
|
|
225
|
+
parts.push(typeof t === "object" ? t["#text"] || "" : String(t));
|
|
226
|
+
}
|
|
227
|
+
if (parts.length > 0)
|
|
228
|
+
lines.push(parts.join(""));
|
|
229
|
+
}
|
|
230
|
+
return lines.join("\n").trim();
|
|
231
|
+
}
|
|
232
|
+
extractTable(gf) {
|
|
233
|
+
const tbl = gf?.["a:graphic"]?.["a:graphicData"]?.["a:tbl"];
|
|
234
|
+
if (!tbl)
|
|
235
|
+
return null;
|
|
236
|
+
const rows = tbl["a:tr"];
|
|
237
|
+
const rowList = Array.isArray(rows) ? rows : rows ? [rows] : [];
|
|
238
|
+
if (rowList.length === 0)
|
|
239
|
+
return null;
|
|
240
|
+
const mdRows = [];
|
|
241
|
+
for (const row of rowList) {
|
|
242
|
+
const cells = row["a:tc"];
|
|
243
|
+
const cellList = Array.isArray(cells) ? cells : cells ? [cells] : [];
|
|
244
|
+
const cellTexts = [];
|
|
245
|
+
for (const cell of cellList) {
|
|
246
|
+
const txBody = cell["a:txBody"];
|
|
247
|
+
if (!txBody) {
|
|
248
|
+
cellTexts.push("");
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const paragraphs = txBody["a:p"];
|
|
252
|
+
const pList = Array.isArray(paragraphs)
|
|
253
|
+
? paragraphs
|
|
254
|
+
: paragraphs
|
|
255
|
+
? [paragraphs]
|
|
256
|
+
: [];
|
|
257
|
+
const parts = [];
|
|
258
|
+
for (const p of pList) {
|
|
259
|
+
const runs = p["a:r"];
|
|
260
|
+
const rList = Array.isArray(runs) ? runs : runs ? [runs] : [];
|
|
261
|
+
for (const r of rList) {
|
|
262
|
+
const t = r["a:t"];
|
|
263
|
+
if (t != null)
|
|
264
|
+
parts.push(typeof t === "object" ? t["#text"] || "" : String(t));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
cellTexts.push(parts.join(" "));
|
|
268
|
+
}
|
|
269
|
+
mdRows.push(cellTexts);
|
|
270
|
+
}
|
|
271
|
+
if (mdRows.length === 0)
|
|
272
|
+
return null;
|
|
273
|
+
const [header, ...body] = mdRows;
|
|
274
|
+
const lines = [];
|
|
275
|
+
lines.push(`| ${header.join(" | ")} |`);
|
|
276
|
+
lines.push(`| ${header.map(() => "---").join(" | ")} |`);
|
|
277
|
+
for (const row of body) {
|
|
278
|
+
while (row.length < header.length)
|
|
279
|
+
row.push("");
|
|
280
|
+
lines.push(`| ${row.join(" | ")} |`);
|
|
281
|
+
}
|
|
282
|
+
return lines.join("\n");
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function toList(val) {
|
|
286
|
+
if (!val)
|
|
287
|
+
return [];
|
|
288
|
+
return Array.isArray(val) ? val : [val];
|
|
289
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConversionResult, Converter, StreamInfo } from "../types.js";
|
|
2
|
+
export declare class RssConverter implements Converter {
|
|
3
|
+
name: string;
|
|
4
|
+
accepts(streamInfo: StreamInfo): boolean;
|
|
5
|
+
convert(input: Buffer, _streamInfo: StreamInfo): Promise<ConversionResult>;
|
|
6
|
+
private parseRss;
|
|
7
|
+
private parseAtom;
|
|
8
|
+
private htmlToMd;
|
|
9
|
+
private extract;
|
|
10
|
+
private extractAll;
|
|
11
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { createTurndown } from "../utils/turndown.js";
|
|
2
|
+
const _EXTENSIONS = [".rss", ".atom", ".xml"];
|
|
3
|
+
const MIMETYPES = [
|
|
4
|
+
"application/rss+xml",
|
|
5
|
+
"application/rss",
|
|
6
|
+
"application/atom+xml",
|
|
7
|
+
"application/atom",
|
|
8
|
+
"text/xml",
|
|
9
|
+
"application/xml",
|
|
10
|
+
];
|
|
11
|
+
export class RssConverter {
|
|
12
|
+
name = "rss";
|
|
13
|
+
accepts(streamInfo) {
|
|
14
|
+
// Only accept known RSS/Atom extensions directly
|
|
15
|
+
if (streamInfo.extension &&
|
|
16
|
+
[".rss", ".atom"].includes(streamInfo.extension))
|
|
17
|
+
return true;
|
|
18
|
+
// For .xml, we'll try and fail gracefully
|
|
19
|
+
if (streamInfo.extension === ".xml")
|
|
20
|
+
return true;
|
|
21
|
+
if (streamInfo.mimetype &&
|
|
22
|
+
MIMETYPES.some((m) => streamInfo.mimetype?.startsWith(m)))
|
|
23
|
+
return true;
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
async convert(input, _streamInfo) {
|
|
27
|
+
const text = new TextDecoder("utf-8").decode(input);
|
|
28
|
+
// Detect feed type
|
|
29
|
+
if (text.includes("<rss")) {
|
|
30
|
+
return this.parseRss(text);
|
|
31
|
+
}
|
|
32
|
+
else if (text.includes("<feed")) {
|
|
33
|
+
return this.parseAtom(text);
|
|
34
|
+
}
|
|
35
|
+
// Not a feed — fall through for XML as generic text
|
|
36
|
+
throw new Error("Not an RSS or Atom feed");
|
|
37
|
+
}
|
|
38
|
+
parseRss(xml) {
|
|
39
|
+
const turndown = createTurndown();
|
|
40
|
+
const sections = [];
|
|
41
|
+
// Extract from the <channel> block specifically
|
|
42
|
+
const channelMatch = xml.match(/<channel>([\s\S]*?)<\/channel>/i);
|
|
43
|
+
const channelXml = channelMatch ? channelMatch[1] : xml;
|
|
44
|
+
const channelTitle = this.extract(channelXml, "title");
|
|
45
|
+
const channelDesc = this.extract(channelXml, "description");
|
|
46
|
+
if (channelTitle)
|
|
47
|
+
sections.push(`# ${channelTitle}`);
|
|
48
|
+
if (channelDesc)
|
|
49
|
+
sections.push(this.htmlToMd(channelDesc, turndown));
|
|
50
|
+
// Extract items
|
|
51
|
+
const items = this.extractAll(xml, "item");
|
|
52
|
+
for (const item of items) {
|
|
53
|
+
const title = this.extract(item, "title");
|
|
54
|
+
const pubDate = this.extract(item, "pubDate");
|
|
55
|
+
const description = this.extract(item, "description");
|
|
56
|
+
const content = this.extract(item, "content:encoded");
|
|
57
|
+
const link = this.extract(item, "link");
|
|
58
|
+
const parts = [];
|
|
59
|
+
if (title)
|
|
60
|
+
parts.push(`## ${title}`);
|
|
61
|
+
if (pubDate)
|
|
62
|
+
parts.push(`Published: ${pubDate}`);
|
|
63
|
+
if (link)
|
|
64
|
+
parts.push(`[Link](${link})`);
|
|
65
|
+
if (content) {
|
|
66
|
+
parts.push(this.htmlToMd(content, turndown));
|
|
67
|
+
}
|
|
68
|
+
else if (description) {
|
|
69
|
+
parts.push(this.htmlToMd(description, turndown));
|
|
70
|
+
}
|
|
71
|
+
if (parts.length > 0)
|
|
72
|
+
sections.push(parts.join("\n"));
|
|
73
|
+
}
|
|
74
|
+
return { markdown: sections.join("\n\n").trim(), title: channelTitle };
|
|
75
|
+
}
|
|
76
|
+
parseAtom(xml) {
|
|
77
|
+
const turndown = createTurndown();
|
|
78
|
+
const sections = [];
|
|
79
|
+
const feedTitle = this.extract(xml, "title");
|
|
80
|
+
const subtitle = this.extract(xml, "subtitle");
|
|
81
|
+
if (feedTitle)
|
|
82
|
+
sections.push(`# ${feedTitle}`);
|
|
83
|
+
if (subtitle)
|
|
84
|
+
sections.push(subtitle);
|
|
85
|
+
const entries = this.extractAll(xml, "entry");
|
|
86
|
+
for (const entry of entries) {
|
|
87
|
+
const title = this.extract(entry, "title");
|
|
88
|
+
const updated = this.extract(entry, "updated");
|
|
89
|
+
const summary = this.extract(entry, "summary");
|
|
90
|
+
const content = this.extract(entry, "content");
|
|
91
|
+
const parts = [];
|
|
92
|
+
if (title)
|
|
93
|
+
parts.push(`## ${title}`);
|
|
94
|
+
if (updated)
|
|
95
|
+
parts.push(`Updated: ${updated}`);
|
|
96
|
+
if (content) {
|
|
97
|
+
parts.push(this.htmlToMd(content, turndown));
|
|
98
|
+
}
|
|
99
|
+
else if (summary) {
|
|
100
|
+
parts.push(this.htmlToMd(summary, turndown));
|
|
101
|
+
}
|
|
102
|
+
if (parts.length > 0)
|
|
103
|
+
sections.push(parts.join("\n"));
|
|
104
|
+
}
|
|
105
|
+
return { markdown: sections.join("\n\n").trim(), title: feedTitle };
|
|
106
|
+
}
|
|
107
|
+
htmlToMd(html, turndown) {
|
|
108
|
+
// Unescape CDATA and HTML entities that might be in RSS
|
|
109
|
+
const unescaped = html
|
|
110
|
+
.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, "$1")
|
|
111
|
+
.replace(/</g, "<")
|
|
112
|
+
.replace(/>/g, ">")
|
|
113
|
+
.replace(/&/g, "&");
|
|
114
|
+
// If it looks like HTML, convert it
|
|
115
|
+
if (unescaped.includes("<")) {
|
|
116
|
+
return turndown.turndown(unescaped).trim();
|
|
117
|
+
}
|
|
118
|
+
return unescaped.trim();
|
|
119
|
+
}
|
|
120
|
+
extract(xml, tag) {
|
|
121
|
+
// Handle both <tag>content</tag> and <tag><![CDATA[content]]></tag>
|
|
122
|
+
const re = new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`, "i");
|
|
123
|
+
const match = xml.match(re);
|
|
124
|
+
if (!match)
|
|
125
|
+
return undefined;
|
|
126
|
+
return (match[1].replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, "$1").trim() || undefined);
|
|
127
|
+
}
|
|
128
|
+
extractAll(xml, tag) {
|
|
129
|
+
const results = [];
|
|
130
|
+
const re = new RegExp(`<${tag}[^>]*>[\\s\\S]*?</${tag}>`, "gi");
|
|
131
|
+
let match = re.exec(xml);
|
|
132
|
+
while (match !== null) {
|
|
133
|
+
results.push(match[0]);
|
|
134
|
+
match = re.exec(xml);
|
|
135
|
+
}
|
|
136
|
+
return results;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ConversionResult, Converter, StreamInfo } from "../types.js";
|
|
2
|
+
export declare class WikipediaConverter implements Converter {
|
|
3
|
+
name: string;
|
|
4
|
+
accepts(streamInfo: StreamInfo): boolean;
|
|
5
|
+
convert(input: Buffer, streamInfo: StreamInfo): Promise<ConversionResult>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createTurndown } from "../utils/turndown.js";
|
|
2
|
+
const WIKIPEDIA_RE = /^https?:\/\/[a-zA-Z]{2,3}\.wikipedia\.org\//;
|
|
3
|
+
export class WikipediaConverter {
|
|
4
|
+
name = "wikipedia";
|
|
5
|
+
accepts(streamInfo) {
|
|
6
|
+
if (!streamInfo.url)
|
|
7
|
+
return false;
|
|
8
|
+
return WIKIPEDIA_RE.test(streamInfo.url);
|
|
9
|
+
}
|
|
10
|
+
async convert(input, streamInfo) {
|
|
11
|
+
const html = new TextDecoder(streamInfo.charset || "utf-8").decode(input);
|
|
12
|
+
// Extract the main content div
|
|
13
|
+
const contentMatch = html.match(/<div[^>]*id="mw-content-text"[^>]*>([\s\S]*?)<\/div>\s*(?:<\/div>|$)/i);
|
|
14
|
+
// Extract title
|
|
15
|
+
const titleMatch = html.match(/<span[^>]*class="mw-page-title-main"[^>]*>([\s\S]*?)<\/span>/i) || html.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
|
|
16
|
+
const title = titleMatch
|
|
17
|
+
? titleMatch[1].replace(/ - Wikipedia$/, "").trim()
|
|
18
|
+
: undefined;
|
|
19
|
+
const turndown = createTurndown();
|
|
20
|
+
// Clean up Wikipedia-specific elements
|
|
21
|
+
let content = contentMatch ? contentMatch[1] : html;
|
|
22
|
+
content = content
|
|
23
|
+
.replace(/<script[\s\S]*?<\/script>/gi, "")
|
|
24
|
+
.replace(/<style[\s\S]*?<\/style>/gi, "")
|
|
25
|
+
.replace(/<div[^>]*class="[^"]*mw-editsection[^"]*"[\s\S]*?<\/div>/gi, "") // edit links
|
|
26
|
+
.replace(/<sup[^>]*class="[^"]*reference[^"]*"[\s\S]*?<\/sup>/gi, "") // reference numbers
|
|
27
|
+
.replace(/<div[^>]*class="[^"]*navbox[\s\S]*?<\/div>/gi, "") // navboxes
|
|
28
|
+
.replace(/<table[^>]*class="[^"]*sidebar[\s\S]*?<\/table>/gi, ""); // sidebars
|
|
29
|
+
const markdown = turndown.turndown(content).trim();
|
|
30
|
+
const result = title ? `# ${title}\n\n${markdown}` : markdown;
|
|
31
|
+
return { markdown: result, title };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ConversionResult, Converter, StreamInfo } from "../types.js";
|
|
2
|
+
export declare class XlsxConverter implements Converter {
|
|
3
|
+
name: string;
|
|
4
|
+
accepts(streamInfo: StreamInfo): boolean;
|
|
5
|
+
convert(input: Buffer, _streamInfo: StreamInfo): Promise<ConversionResult>;
|
|
6
|
+
private getCellValue;
|
|
7
|
+
private getSharedString;
|
|
8
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { XMLParser } from "fast-xml-parser";
|
|
2
|
+
import JSZip from "jszip";
|
|
3
|
+
const EXTENSIONS = [".xlsx"];
|
|
4
|
+
const MIMETYPES = [
|
|
5
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
6
|
+
];
|
|
7
|
+
export class XlsxConverter {
|
|
8
|
+
name = "xlsx";
|
|
9
|
+
accepts(streamInfo) {
|
|
10
|
+
if (streamInfo.extension && EXTENSIONS.includes(streamInfo.extension))
|
|
11
|
+
return true;
|
|
12
|
+
if (streamInfo.mimetype &&
|
|
13
|
+
MIMETYPES.some((m) => streamInfo.mimetype?.startsWith(m)))
|
|
14
|
+
return true;
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
async convert(input, _streamInfo) {
|
|
18
|
+
const zip = await JSZip.loadAsync(input);
|
|
19
|
+
const parser = new XMLParser({
|
|
20
|
+
ignoreAttributes: false,
|
|
21
|
+
attributeNamePrefix: "@_",
|
|
22
|
+
textNodeName: "#text",
|
|
23
|
+
processEntities: { maxTotalExpansions: 1_000_000 },
|
|
24
|
+
});
|
|
25
|
+
// Parse shared strings
|
|
26
|
+
const ssXml = await zip.file("xl/sharedStrings.xml")?.async("string");
|
|
27
|
+
const ss = ssXml ? parser.parse(ssXml) : null;
|
|
28
|
+
const siList = ss?.sst?.si;
|
|
29
|
+
const shared = toArray(siList);
|
|
30
|
+
// Parse workbook for sheet names
|
|
31
|
+
const wbXml = await zip.file("xl/workbook.xml")?.async("string");
|
|
32
|
+
if (!wbXml)
|
|
33
|
+
throw new Error("Invalid XLSX: missing workbook.xml");
|
|
34
|
+
const wb = parser.parse(wbXml);
|
|
35
|
+
const sheets = toArray(wb.workbook?.sheets?.sheet);
|
|
36
|
+
// Parse workbook rels to map rIds to sheet files
|
|
37
|
+
const relsXml = await zip
|
|
38
|
+
.file("xl/_rels/workbook.xml.rels")
|
|
39
|
+
?.async("string");
|
|
40
|
+
const rels = relsXml ? parser.parse(relsXml) : null;
|
|
41
|
+
const relList = toArray(rels?.Relationships?.Relationship);
|
|
42
|
+
const relMap = new Map();
|
|
43
|
+
for (const r of relList) {
|
|
44
|
+
relMap.set(r["@_Id"], r["@_Target"]);
|
|
45
|
+
}
|
|
46
|
+
const sections = [];
|
|
47
|
+
for (const sheet of sheets) {
|
|
48
|
+
const sheetName = sheet["@_name"];
|
|
49
|
+
const rId = sheet["@_r:id"];
|
|
50
|
+
const target = relMap.get(rId);
|
|
51
|
+
if (!target)
|
|
52
|
+
continue;
|
|
53
|
+
const sheetPath = target.startsWith("/")
|
|
54
|
+
? target.slice(1)
|
|
55
|
+
: `xl/${target}`;
|
|
56
|
+
const sheetXml = await zip.file(sheetPath)?.async("string");
|
|
57
|
+
if (!sheetXml)
|
|
58
|
+
continue;
|
|
59
|
+
const parsed = parser.parse(sheetXml);
|
|
60
|
+
const rows = toArray(parsed.worksheet?.sheetData?.row);
|
|
61
|
+
if (rows.length === 0)
|
|
62
|
+
continue;
|
|
63
|
+
// Extract all rows as string arrays
|
|
64
|
+
const tableRows = [];
|
|
65
|
+
for (const row of rows) {
|
|
66
|
+
const cells = toArray(row.c);
|
|
67
|
+
const values = [];
|
|
68
|
+
for (const cell of cells) {
|
|
69
|
+
values.push(this.getCellValue(cell, shared));
|
|
70
|
+
}
|
|
71
|
+
tableRows.push(values);
|
|
72
|
+
}
|
|
73
|
+
if (tableRows.length === 0)
|
|
74
|
+
continue;
|
|
75
|
+
// Normalize column count
|
|
76
|
+
const maxCols = Math.max(...tableRows.map((r) => r.length));
|
|
77
|
+
for (const row of tableRows) {
|
|
78
|
+
while (row.length < maxCols)
|
|
79
|
+
row.push("");
|
|
80
|
+
}
|
|
81
|
+
sections.push(`## ${sheetName}`);
|
|
82
|
+
const [header, ...body] = tableRows;
|
|
83
|
+
const lines = [];
|
|
84
|
+
lines.push(`| ${header.join(" | ")} |`);
|
|
85
|
+
lines.push(`| ${header.map(() => "---").join(" | ")} |`);
|
|
86
|
+
for (const row of body) {
|
|
87
|
+
lines.push(`| ${row.join(" | ")} |`);
|
|
88
|
+
}
|
|
89
|
+
sections.push(lines.join("\n"));
|
|
90
|
+
}
|
|
91
|
+
return { markdown: sections.join("\n\n") };
|
|
92
|
+
}
|
|
93
|
+
getCellValue(cell, shared) {
|
|
94
|
+
// Shared string
|
|
95
|
+
if (cell["@_t"] === "s") {
|
|
96
|
+
return this.getSharedString(shared, Number(cell.v));
|
|
97
|
+
}
|
|
98
|
+
// Inline string
|
|
99
|
+
if (cell["@_t"] === "inlineStr") {
|
|
100
|
+
const is = cell.is;
|
|
101
|
+
if (!is)
|
|
102
|
+
return "";
|
|
103
|
+
if (is.t != null)
|
|
104
|
+
return textValue(is.t);
|
|
105
|
+
if (is.r)
|
|
106
|
+
return toArray(is.r)
|
|
107
|
+
.map((r) => textValue(r.t))
|
|
108
|
+
.join("");
|
|
109
|
+
return "";
|
|
110
|
+
}
|
|
111
|
+
// Boolean
|
|
112
|
+
if (cell["@_t"] === "b") {
|
|
113
|
+
return cell.v === 1 || cell.v === "1" ? "TRUE" : "FALSE";
|
|
114
|
+
}
|
|
115
|
+
// Number or formula result
|
|
116
|
+
if (cell.v != null)
|
|
117
|
+
return String(cell.v);
|
|
118
|
+
return "";
|
|
119
|
+
}
|
|
120
|
+
getSharedString(shared, idx) {
|
|
121
|
+
const si = shared[idx];
|
|
122
|
+
if (!si)
|
|
123
|
+
return "";
|
|
124
|
+
// Simple text
|
|
125
|
+
if (si.t != null)
|
|
126
|
+
return textValue(si.t);
|
|
127
|
+
// Rich text runs
|
|
128
|
+
if (si.r) {
|
|
129
|
+
return toArray(si.r)
|
|
130
|
+
.map((r) => textValue(r.t))
|
|
131
|
+
.join("");
|
|
132
|
+
}
|
|
133
|
+
return "";
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function textValue(t) {
|
|
137
|
+
if (t == null)
|
|
138
|
+
return "";
|
|
139
|
+
if (typeof t === "object")
|
|
140
|
+
return t["#text"] || "";
|
|
141
|
+
return String(t);
|
|
142
|
+
}
|
|
143
|
+
function toArray(val) {
|
|
144
|
+
if (!val)
|
|
145
|
+
return [];
|
|
146
|
+
return Array.isArray(val) ? val : [val];
|
|
147
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ConversionResult, Converter, StreamInfo } from "../types.js";
|
|
2
|
+
export declare class XmlConverter implements Converter {
|
|
3
|
+
name: string;
|
|
4
|
+
accepts(streamInfo: StreamInfo): boolean;
|
|
5
|
+
convert(input: Buffer, streamInfo: StreamInfo): Promise<ConversionResult>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const EXTENSIONS = [".xml", ".svg"];
|
|
2
|
+
const MIMETYPES = ["text/xml", "application/xml"];
|
|
3
|
+
export class XmlConverter {
|
|
4
|
+
name = "xml";
|
|
5
|
+
accepts(streamInfo) {
|
|
6
|
+
if (streamInfo.extension && EXTENSIONS.includes(streamInfo.extension))
|
|
7
|
+
return true;
|
|
8
|
+
if (streamInfo.mimetype &&
|
|
9
|
+
MIMETYPES.some((m) => streamInfo.mimetype?.startsWith(m)))
|
|
10
|
+
return true;
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
async convert(input, streamInfo) {
|
|
14
|
+
const text = new TextDecoder(streamInfo.charset || "utf-8").decode(input);
|
|
15
|
+
const ext = streamInfo.extension?.slice(1) || "xml";
|
|
16
|
+
return { markdown: `\`\`\`${ext}\n${text}\n\`\`\`` };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ConversionResult, Converter, StreamInfo } from "../types.js";
|
|
2
|
+
export declare class YamlConverter implements Converter {
|
|
3
|
+
name: string;
|
|
4
|
+
accepts(streamInfo: StreamInfo): boolean;
|
|
5
|
+
convert(input: Buffer, streamInfo: StreamInfo): Promise<ConversionResult>;
|
|
6
|
+
}
|