@pencil-agent/nano-pencil 0.0.1
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.
Potentially problematic release.
This version of @pencil-agent/nano-pencil might be problematic. Click here for more details.
- package/CHANGELOG.md +2839 -0
- package/README.md +72 -0
- package/dist/cli/args.d.ts +48 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +298 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/config-selector.d.ts +14 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/file-processor.d.ts +15 -0
- package/dist/cli/file-processor.d.ts.map +1 -0
- package/dist/cli/file-processor.js +79 -0
- package/dist/cli/file-processor.js.map +1 -0
- package/dist/cli/list-models.d.ts +9 -0
- package/dist/cli/list-models.d.ts.map +1 -0
- package/dist/cli/list-models.js +92 -0
- package/dist/cli/list-models.js.map +1 -0
- package/dist/cli/session-picker.d.ts +9 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +34 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +11 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +68 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +203 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-session.d.ts +571 -0
- package/dist/core/agent-session.d.ts.map +1 -0
- package/dist/core/agent-session.js +2343 -0
- package/dist/core/agent-session.js.map +1 -0
- package/dist/core/auth-storage.d.ts +129 -0
- package/dist/core/auth-storage.d.ts.map +1 -0
- package/dist/core/auth-storage.js +394 -0
- package/dist/core/auth-storage.js.map +1 -0
- package/dist/core/bash-executor.d.ts +47 -0
- package/dist/core/bash-executor.d.ts.map +1 -0
- package/dist/core/bash-executor.js +212 -0
- package/dist/core/bash-executor.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +86 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
- package/dist/core/compaction/branch-summarization.js +242 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +121 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -0
- package/dist/core/compaction/compaction.js +607 -0
- package/dist/core/compaction/compaction.js.map +1 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.d.ts.map +1 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/index.js.map +1 -0
- package/dist/core/compaction/utils.d.ts +35 -0
- package/dist/core/compaction/utils.d.ts.map +1 -0
- package/dist/core/compaction/utils.js +138 -0
- package/dist/core/compaction/utils.js.map +1 -0
- package/dist/core/defaults.d.ts +3 -0
- package/dist/core/defaults.d.ts.map +1 -0
- package/dist/core/defaults.js +2 -0
- package/dist/core/defaults.js.map +1 -0
- package/dist/core/diagnostics.d.ts +15 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/event-bus.d.ts +9 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +25 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/exec.d.ts +29 -0
- package/dist/core/exec.d.ts.map +1 -0
- package/dist/core/exec.js +71 -0
- package/dist/core/exec.js.map +1 -0
- package/dist/core/export-html/ansi-to-html.d.ts +22 -0
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
- package/dist/core/export-html/ansi-to-html.js +249 -0
- package/dist/core/export-html/ansi-to-html.js.map +1 -0
- package/dist/core/export-html/index.d.ts +34 -0
- package/dist/core/export-html/index.d.ts.map +1 -0
- package/dist/core/export-html/index.js +222 -0
- package/dist/core/export-html/index.js.map +1 -0
- package/dist/core/export-html/template.css +971 -0
- package/dist/core/export-html/template.html +54 -0
- package/dist/core/export-html/template.js +1586 -0
- package/dist/core/export-html/tool-renderer.d.ts +35 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
- package/dist/core/export-html/tool-renderer.js +57 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +6 -0
- package/dist/core/extensions/index.d.ts +11 -0
- package/dist/core/extensions/index.d.ts.map +1 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/index.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +25 -0
- package/dist/core/extensions/loader.d.ts.map +1 -0
- package/dist/core/extensions/loader.js +400 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +146 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/extensions/runner.js +641 -0
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +984 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/extensions/types.js +35 -0
- package/dist/core/extensions/types.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts +27 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -0
- package/dist/core/extensions/wrapper.js +102 -0
- package/dist/core/extensions/wrapper.js.map +1 -0
- package/dist/core/footer-data-provider.d.ts +32 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -0
- package/dist/core/footer-data-provider.js +134 -0
- package/dist/core/footer-data-provider.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/keybindings.d.ts +55 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/keybindings.js +153 -0
- package/dist/core/keybindings.js.map +1 -0
- package/dist/core/messages.d.ts +77 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +123 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/model-registry.d.ts +110 -0
- package/dist/core/model-registry.d.ts.map +1 -0
- package/dist/core/model-registry.js +518 -0
- package/dist/core/model-registry.js.map +1 -0
- package/dist/core/model-resolver.d.ts +104 -0
- package/dist/core/model-resolver.d.ts.map +1 -0
- package/dist/core/model-resolver.js +432 -0
- package/dist/core/model-resolver.js.map +1 -0
- package/dist/core/package-manager.d.ts +151 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +1447 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +50 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/prompt-templates.js +251 -0
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +17 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -0
- package/dist/core/resolve-config-value.js +59 -0
- package/dist/core/resolve-config-value.js.map +1 -0
- package/dist/core/resource-loader.d.ts +184 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +670 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/sdk.d.ts +90 -0
- package/dist/core/sdk.d.ts.map +1 -0
- package/dist/core/sdk.js +235 -0
- package/dist/core/sdk.js.map +1 -0
- package/dist/core/session-manager.d.ts +323 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +1091 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/settings-manager.d.ts +225 -0
- package/dist/core/settings-manager.d.ts.map +1 -0
- package/dist/core/settings-manager.js +653 -0
- package/dist/core/settings-manager.js.map +1 -0
- package/dist/core/skills.d.ts +58 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +364 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/slash-commands.d.ts +15 -0
- package/dist/core/slash-commands.d.ts.map +1 -0
- package/dist/core/slash-commands.js +22 -0
- package/dist/core/slash-commands.js.map +1 -0
- package/dist/core/system-prompt.d.ts +24 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +137 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/timings.d.ts +7 -0
- package/dist/core/timings.d.ts.map +1 -0
- package/dist/core/timings.js +25 -0
- package/dist/core/timings.js.map +1 -0
- package/dist/core/tools/bash.d.ts +55 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +242 -0
- package/dist/core/tools/bash.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +63 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +243 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +39 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +146 -0
- package/dist/core/tools/edit.js.map +1 -0
- package/dist/core/tools/find.d.ts +39 -0
- package/dist/core/tools/find.d.ts.map +1 -0
- package/dist/core/tools/find.js +206 -0
- package/dist/core/tools/find.js.map +1 -0
- package/dist/core/tools/grep.d.ts +45 -0
- package/dist/core/tools/grep.d.ts.map +1 -0
- package/dist/core/tools/grep.js +239 -0
- package/dist/core/tools/grep.js.map +1 -0
- package/dist/core/tools/index.d.ts +73 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +61 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/ls.d.ts +40 -0
- package/dist/core/tools/ls.d.ts.map +1 -0
- package/dist/core/tools/ls.js +118 -0
- package/dist/core/tools/ls.js.map +1 -0
- package/dist/core/tools/path-utils.d.ts +8 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -0
- package/dist/core/tools/path-utils.js +81 -0
- package/dist/core/tools/path-utils.js.map +1 -0
- package/dist/core/tools/read.d.ts +39 -0
- package/dist/core/tools/read.d.ts.map +1 -0
- package/dist/core/tools/read.js +166 -0
- package/dist/core/tools/read.js.map +1 -0
- package/dist/core/tools/truncate.d.ts +70 -0
- package/dist/core/tools/truncate.d.ts.map +1 -0
- package/dist/core/tools/truncate.js +205 -0
- package/dist/core/tools/truncate.js.map +1 -0
- package/dist/core/tools/write.d.ts +29 -0
- package/dist/core/tools/write.d.ts.map +1 -0
- package/dist/core/tools/write.js +78 -0
- package/dist/core/tools/write.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +8 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +670 -0
- package/dist/main.js.map +1 -0
- package/dist/migrations.d.ts +33 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +261 -0
- package/dist/migrations.js.map +1 -0
- package/dist/modes/index.d.ts +9 -0
- package/dist/modes/index.d.ts.map +1 -0
- package/dist/modes/index.js +8 -0
- package/dist/modes/index.js.map +1 -0
- package/dist/modes/interactive/components/armin.d.ts +34 -0
- package/dist/modes/interactive/components/armin.d.ts.map +1 -0
- package/dist/modes/interactive/components/armin.js +333 -0
- package/dist/modes/interactive/components/armin.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +16 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/assistant-message.js +96 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +35 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/bash-execution.js +162 -0
- package/dist/modes/interactive/components/bash-execution.js.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.js +51 -0
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.js +44 -0
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts +71 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +479 -0
- package/dist/modes/interactive/components/config-selector.js.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.js +33 -0
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +21 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-editor.js +70 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +20 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-message.js +79 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -0
- package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
- package/dist/modes/interactive/components/daxnuts.js +140 -0
- package/dist/modes/interactive/components/daxnuts.js.map +1 -0
- package/dist/modes/interactive/components/diff.d.ts +12 -0
- package/dist/modes/interactive/components/diff.d.ts.map +1 -0
- package/dist/modes/interactive/components/diff.js +133 -0
- package/dist/modes/interactive/components/diff.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.js +21 -0
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +17 -0
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-editor.js +102 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -0
- package/dist/modes/interactive/components/extension-input.d.ts +23 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-input.js +61 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +24 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-selector.js +78 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +26 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -0
- package/dist/modes/interactive/components/footer.js +213 -0
- package/dist/modes/interactive/components/footer.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +32 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -0
- package/dist/modes/interactive/components/index.js +33 -0
- package/dist/modes/interactive/components/index.js.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +41 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.js +61 -0
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +42 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
- package/dist/modes/interactive/components/login-dialog.js +145 -0
- package/dist/modes/interactive/components/login-dialog.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +47 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-selector.js +271 -0
- package/dist/modes/interactive/components/model-selector.js.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +19 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.js +97 -0
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +49 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +275 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.js +155 -0
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +95 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector.js +851 -0
- package/dist/modes/interactive/components/session-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +56 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-selector.js +287 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.js +35 -0
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/theme-selector.js +46 -0
- package/dist/modes/interactive/components/theme-selector.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.js +47 -0
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +75 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +752 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +68 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/tree-selector.js +934 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.js +113 -0
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts +8 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message.js +16 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.js +33 -0
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +315 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +3714 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +84 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.d.ts +78 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme.js +944 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -0
- package/dist/modes/print-mode.d.ts +28 -0
- package/dist/modes/print-mode.d.ts.map +1 -0
- package/dist/modes/print-mode.js +101 -0
- package/dist/modes/print-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +217 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-client.js +405 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts +20 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-mode.js +511 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +409 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-types.js +8 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -0
- package/dist/nanopencil-defaults.d.ts +35 -0
- package/dist/nanopencil-defaults.d.ts.map +1 -0
- package/dist/nanopencil-defaults.js +66 -0
- package/dist/nanopencil-defaults.js.map +1 -0
- package/dist/utils/changelog.d.ts +21 -0
- package/dist/utils/changelog.d.ts.map +1 -0
- package/dist/utils/changelog.js +87 -0
- package/dist/utils/changelog.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts +11 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -0
- package/dist/utils/clipboard-image.js +162 -0
- package/dist/utils/clipboard-image.js.map +1 -0
- package/dist/utils/clipboard-native.d.ts +7 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -0
- package/dist/utils/clipboard-native.js +14 -0
- package/dist/utils/clipboard-native.js.map +1 -0
- package/dist/utils/clipboard.d.ts +2 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +67 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +8 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +26 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/git.d.ts +26 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +163 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/image-convert.d.ts +9 -0
- package/dist/utils/image-convert.d.ts.map +1 -0
- package/dist/utils/image-convert.js +35 -0
- package/dist/utils/image-convert.js.map +1 -0
- package/dist/utils/image-resize.d.ts +36 -0
- package/dist/utils/image-resize.d.ts.map +1 -0
- package/dist/utils/image-resize.js +181 -0
- package/dist/utils/image-resize.js.map +1 -0
- package/dist/utils/mime.d.ts +2 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +26 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/photon.d.ts +21 -0
- package/dist/utils/photon.d.ts.map +1 -0
- package/dist/utils/photon.js +121 -0
- package/dist/utils/photon.js.map +1 -0
- package/dist/utils/shell.d.ts +26 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +186 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.d.ts.map +1 -0
- package/dist/utils/tools-manager.js +251 -0
- package/dist/utils/tools-manager.js.map +1 -0
- package/docs/compaction.md +390 -0
- package/docs/custom-provider.md +548 -0
- package/docs/development.md +69 -0
- package/docs/extensions.md +1935 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/json.md +79 -0
- package/docs/keybindings.md +174 -0
- package/docs/models.md +293 -0
- package/docs/packages.md +209 -0
- package/docs/prompt-templates.md +67 -0
- package/docs/providers.md +186 -0
- package/docs/publish-npm.md +79 -0
- package/docs/rpc.md +1317 -0
- package/docs/sdk.md +968 -0
- package/docs/session.md +412 -0
- package/docs/settings.md +223 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +231 -0
- package/docs/terminal-setup.md +70 -0
- package/docs/termux.md +127 -0
- package/docs/themes.md +295 -0
- package/docs/tree.md +219 -0
- package/docs/tui.md +887 -0
- package/docs/windows.md +17 -0
- package/examples/README.md +25 -0
- package/examples/extensions/README.md +204 -0
- package/examples/extensions/antigravity-image-gen.ts +413 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/built-in-tool-renderer.ts +246 -0
- package/examples/extensions/claude-rules.ts +86 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +59 -0
- package/examples/extensions/custom-compaction.ts +114 -0
- package/examples/extensions/custom-footer.ts +64 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/custom-provider-qwen-cli/index.ts +345 -0
- package/examples/extensions/custom-provider-qwen-cli/package.json +16 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +79 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/handoff.ts +150 -0
- package/examples/extensions/hello.ts +25 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +426 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +55 -0
- package/examples/extensions/overlay-qa-tests.ts +881 -0
- package/examples/extensions/overlay-test.ts +150 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +65 -0
- package/examples/extensions/plan-mode/index.ts +340 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +398 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/qna.ts +119 -0
- package/examples/extensions/question.ts +264 -0
- package/examples/extensions/questionnaire.ts +427 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +124 -0
- package/examples/extensions/sandbox/index.ts +318 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +40 -0
- package/examples/extensions/subagent/README.md +172 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +126 -0
- package/examples/extensions/subagent/index.ts +964 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +195 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +299 -0
- package/examples/extensions/tool-override.ts +143 -0
- package/examples/extensions/tools.ts +146 -0
- package/examples/extensions/trigger-compact.ts +40 -0
- package/examples/extensions/truncated-tool.ts +192 -0
- package/examples/extensions/widget-placement.ts +17 -0
- package/examples/extensions/with-deps/index.ts +36 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/rpc-extension-ui.ts +632 -0
- package/examples/sdk/01-minimal.ts +22 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +55 -0
- package/examples/sdk/04-skills.ts +46 -0
- package/examples/sdk/05-tools.ts +56 -0
- package/examples/sdk/06-extensions.ts +88 -0
- package/examples/sdk/07-context-files.ts +40 -0
- package/examples/sdk/08-prompt-templates.ts +47 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
- package/examples/sdk/10-settings.ts +51 -0
- package/examples/sdk/11-sessions.ts +48 -0
- package/examples/sdk/12-full-control.ts +82 -0
- package/examples/sdk/README.md +144 -0
- package/package.json +103 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "fs";
|
|
2
|
+
/**
|
|
3
|
+
* Parse changelog entries from CHANGELOG.md
|
|
4
|
+
* Scans for ## lines and collects content until next ## or EOF
|
|
5
|
+
*/
|
|
6
|
+
export function parseChangelog(changelogPath) {
|
|
7
|
+
if (!existsSync(changelogPath)) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const content = readFileSync(changelogPath, "utf-8");
|
|
12
|
+
const lines = content.split("\n");
|
|
13
|
+
const entries = [];
|
|
14
|
+
let currentLines = [];
|
|
15
|
+
let currentVersion = null;
|
|
16
|
+
for (const line of lines) {
|
|
17
|
+
// Check if this is a version header (## [x.y.z] ...)
|
|
18
|
+
if (line.startsWith("## ")) {
|
|
19
|
+
// Save previous entry if exists
|
|
20
|
+
if (currentVersion && currentLines.length > 0) {
|
|
21
|
+
entries.push({
|
|
22
|
+
...currentVersion,
|
|
23
|
+
content: currentLines.join("\n").trim(),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
// Try to parse version from this line
|
|
27
|
+
const versionMatch = line.match(/##\s+\[?(\d+)\.(\d+)\.(\d+)\]?/);
|
|
28
|
+
if (versionMatch) {
|
|
29
|
+
currentVersion = {
|
|
30
|
+
major: Number.parseInt(versionMatch[1], 10),
|
|
31
|
+
minor: Number.parseInt(versionMatch[2], 10),
|
|
32
|
+
patch: Number.parseInt(versionMatch[3], 10),
|
|
33
|
+
};
|
|
34
|
+
currentLines = [line];
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Reset if we can't parse version
|
|
38
|
+
currentVersion = null;
|
|
39
|
+
currentLines = [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (currentVersion) {
|
|
43
|
+
// Collect lines for current version
|
|
44
|
+
currentLines.push(line);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Save last entry
|
|
48
|
+
if (currentVersion && currentLines.length > 0) {
|
|
49
|
+
entries.push({
|
|
50
|
+
...currentVersion,
|
|
51
|
+
content: currentLines.join("\n").trim(),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return entries;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.error(`Warning: Could not parse changelog: ${error}`);
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
|
|
63
|
+
*/
|
|
64
|
+
export function compareVersions(v1, v2) {
|
|
65
|
+
if (v1.major !== v2.major)
|
|
66
|
+
return v1.major - v2.major;
|
|
67
|
+
if (v1.minor !== v2.minor)
|
|
68
|
+
return v1.minor - v2.minor;
|
|
69
|
+
return v1.patch - v2.patch;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get entries newer than lastVersion
|
|
73
|
+
*/
|
|
74
|
+
export function getNewEntries(entries, lastVersion) {
|
|
75
|
+
// Parse lastVersion
|
|
76
|
+
const parts = lastVersion.split(".").map(Number);
|
|
77
|
+
const last = {
|
|
78
|
+
major: parts[0] || 0,
|
|
79
|
+
minor: parts[1] || 0,
|
|
80
|
+
patch: parts[2] || 0,
|
|
81
|
+
content: "",
|
|
82
|
+
};
|
|
83
|
+
return entries.filter((entry) => compareVersions(entry, last) > 0);
|
|
84
|
+
}
|
|
85
|
+
// Re-export getChangelogPath from paths.ts for convenience
|
|
86
|
+
export { getChangelogPath } from "../config.js";
|
|
87
|
+
//# sourceMappingURL=changelog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"fs\";\n\nexport interface ChangelogEntry {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tcontent: string;\n}\n\n/**\n * Parse changelog entries from CHANGELOG.md\n * Scans for ## lines and collects content until next ## or EOF\n */\nexport function parseChangelog(changelogPath: string): ChangelogEntry[] {\n\tif (!existsSync(changelogPath)) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(changelogPath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst entries: ChangelogEntry[] = [];\n\n\t\tlet currentLines: string[] = [];\n\t\tlet currentVersion: { major: number; minor: number; patch: number } | null = null;\n\n\t\tfor (const line of lines) {\n\t\t\t// Check if this is a version header (## [x.y.z] ...)\n\t\t\tif (line.startsWith(\"## \")) {\n\t\t\t\t// Save previous entry if exists\n\t\t\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\t...currentVersion,\n\t\t\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Try to parse version from this line\n\t\t\t\tconst versionMatch = line.match(/##\\s+\\[?(\\d+)\\.(\\d+)\\.(\\d+)\\]?/);\n\t\t\t\tif (versionMatch) {\n\t\t\t\t\tcurrentVersion = {\n\t\t\t\t\t\tmajor: Number.parseInt(versionMatch[1], 10),\n\t\t\t\t\t\tminor: Number.parseInt(versionMatch[2], 10),\n\t\t\t\t\t\tpatch: Number.parseInt(versionMatch[3], 10),\n\t\t\t\t\t};\n\t\t\t\t\tcurrentLines = [line];\n\t\t\t\t} else {\n\t\t\t\t\t// Reset if we can't parse version\n\t\t\t\t\tcurrentVersion = null;\n\t\t\t\t\tcurrentLines = [];\n\t\t\t\t}\n\t\t\t} else if (currentVersion) {\n\t\t\t\t// Collect lines for current version\n\t\t\t\tcurrentLines.push(line);\n\t\t\t}\n\t\t}\n\n\t\t// Save last entry\n\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\tentries.push({\n\t\t\t\t...currentVersion,\n\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t});\n\t\t}\n\n\t\treturn entries;\n\t} catch (error) {\n\t\tconsole.error(`Warning: Could not parse changelog: ${error}`);\n\t\treturn [];\n\t}\n}\n\n/**\n * Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2\n */\nexport function compareVersions(v1: ChangelogEntry, v2: ChangelogEntry): number {\n\tif (v1.major !== v2.major) return v1.major - v2.major;\n\tif (v1.minor !== v2.minor) return v1.minor - v2.minor;\n\treturn v1.patch - v2.patch;\n}\n\n/**\n * Get entries newer than lastVersion\n */\nexport function getNewEntries(entries: ChangelogEntry[], lastVersion: string): ChangelogEntry[] {\n\t// Parse lastVersion\n\tconst parts = lastVersion.split(\".\").map(Number);\n\tconst last: ChangelogEntry = {\n\t\tmajor: parts[0] || 0,\n\t\tminor: parts[1] || 0,\n\t\tpatch: parts[2] || 0,\n\t\tcontent: \"\",\n\t};\n\n\treturn entries.filter((entry) => compareVersions(entry, last) > 0);\n}\n\n// Re-export getChangelogPath from paths.ts for convenience\nexport { getChangelogPath } from \"../config.js\";\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type ClipboardImage = {
|
|
2
|
+
bytes: Uint8Array;
|
|
3
|
+
mimeType: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function isWaylandSession(env?: NodeJS.ProcessEnv): boolean;
|
|
6
|
+
export declare function extensionForImageMimeType(mimeType: string): string | null;
|
|
7
|
+
export declare function readClipboardImage(options?: {
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
platform?: NodeJS.Platform;
|
|
10
|
+
}): Promise<ClipboardImage | null>;
|
|
11
|
+
//# sourceMappingURL=clipboard-image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard-image.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard-image.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC;AAQF,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE9E;AAMD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAazE;AA8HD,wBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC3B,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAwCjC","sourcesContent":["import { spawnSync } from \"child_process\";\n\nimport { clipboard } from \"./clipboard-native.js\";\nimport { loadPhoton } from \"./photon.js\";\n\nexport type ClipboardImage = {\n\tbytes: Uint8Array;\n\tmimeType: string;\n};\n\nconst SUPPORTED_IMAGE_MIME_TYPES = [\"image/png\", \"image/jpeg\", \"image/webp\", \"image/gif\"] as const;\n\nconst DEFAULT_LIST_TIMEOUT_MS = 1000;\nconst DEFAULT_READ_TIMEOUT_MS = 3000;\nconst DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;\n\nexport function isWaylandSession(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn Boolean(env.WAYLAND_DISPLAY) || env.XDG_SESSION_TYPE === \"wayland\";\n}\n\nfunction baseMimeType(mimeType: string): string {\n\treturn mimeType.split(\";\")[0]?.trim().toLowerCase() ?? mimeType.toLowerCase();\n}\n\nexport function extensionForImageMimeType(mimeType: string): string | null {\n\tswitch (baseMimeType(mimeType)) {\n\t\tcase \"image/png\":\n\t\t\treturn \"png\";\n\t\tcase \"image/jpeg\":\n\t\t\treturn \"jpg\";\n\t\tcase \"image/webp\":\n\t\t\treturn \"webp\";\n\t\tcase \"image/gif\":\n\t\t\treturn \"gif\";\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nfunction selectPreferredImageMimeType(mimeTypes: string[]): string | null {\n\tconst normalized = mimeTypes\n\t\t.map((t) => t.trim())\n\t\t.filter(Boolean)\n\t\t.map((t) => ({ raw: t, base: baseMimeType(t) }));\n\n\tfor (const preferred of SUPPORTED_IMAGE_MIME_TYPES) {\n\t\tconst match = normalized.find((t) => t.base === preferred);\n\t\tif (match) {\n\t\t\treturn match.raw;\n\t\t}\n\t}\n\n\tconst anyImage = normalized.find((t) => t.base.startsWith(\"image/\"));\n\treturn anyImage?.raw ?? null;\n}\n\nfunction isSupportedImageMimeType(mimeType: string): boolean {\n\tconst base = baseMimeType(mimeType);\n\treturn SUPPORTED_IMAGE_MIME_TYPES.some((t) => t === base);\n}\n\n/**\n * Convert unsupported image formats to PNG using Photon.\n * Returns null if conversion is unavailable or fails.\n */\nasync function convertToPng(bytes: Uint8Array): Promise<Uint8Array | null> {\n\tconst photon = await loadPhoton();\n\tif (!photon) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst image = photon.PhotonImage.new_from_byteslice(bytes);\n\t\ttry {\n\t\t\treturn image.get_bytes();\n\t\t} finally {\n\t\t\timage.free();\n\t\t}\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction runCommand(\n\tcommand: string,\n\targs: string[],\n\toptions?: { timeoutMs?: number; maxBufferBytes?: number },\n): { stdout: Buffer; ok: boolean } {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_READ_TIMEOUT_MS;\n\tconst maxBufferBytes = options?.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES;\n\n\tconst result = spawnSync(command, args, {\n\t\ttimeout: timeoutMs,\n\t\tmaxBuffer: maxBufferBytes,\n\t});\n\n\tif (result.error) {\n\t\treturn { ok: false, stdout: Buffer.alloc(0) };\n\t}\n\n\tif (result.status !== 0) {\n\t\treturn { ok: false, stdout: Buffer.alloc(0) };\n\t}\n\n\tconst stdout = Buffer.isBuffer(result.stdout)\n\t\t? result.stdout\n\t\t: Buffer.from(result.stdout ?? \"\", typeof result.stdout === \"string\" ? \"utf-8\" : undefined);\n\n\treturn { ok: true, stdout };\n}\n\nfunction readClipboardImageViaWlPaste(): ClipboardImage | null {\n\tconst list = runCommand(\"wl-paste\", [\"--list-types\"], { timeoutMs: DEFAULT_LIST_TIMEOUT_MS });\n\tif (!list.ok) {\n\t\treturn null;\n\t}\n\n\tconst types = list.stdout\n\t\t.toString(\"utf-8\")\n\t\t.split(/\\r?\\n/)\n\t\t.map((t) => t.trim())\n\t\t.filter(Boolean);\n\n\tconst selectedType = selectPreferredImageMimeType(types);\n\tif (!selectedType) {\n\t\treturn null;\n\t}\n\n\tconst data = runCommand(\"wl-paste\", [\"--type\", selectedType, \"--no-newline\"]);\n\tif (!data.ok || data.stdout.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn { bytes: data.stdout, mimeType: baseMimeType(selectedType) };\n}\n\nfunction readClipboardImageViaXclip(): ClipboardImage | null {\n\tconst targets = runCommand(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"TARGETS\", \"-o\"], {\n\t\ttimeoutMs: DEFAULT_LIST_TIMEOUT_MS,\n\t});\n\n\tlet candidateTypes: string[] = [];\n\tif (targets.ok) {\n\t\tcandidateTypes = targets.stdout\n\t\t\t.toString(\"utf-8\")\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.map((t) => t.trim())\n\t\t\t.filter(Boolean);\n\t}\n\n\tconst preferred = candidateTypes.length > 0 ? selectPreferredImageMimeType(candidateTypes) : null;\n\tconst tryTypes = preferred ? [preferred, ...SUPPORTED_IMAGE_MIME_TYPES] : [...SUPPORTED_IMAGE_MIME_TYPES];\n\n\tfor (const mimeType of tryTypes) {\n\t\tconst data = runCommand(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", mimeType, \"-o\"]);\n\t\tif (data.ok && data.stdout.length > 0) {\n\t\t\treturn { bytes: data.stdout, mimeType: baseMimeType(mimeType) };\n\t\t}\n\t}\n\n\treturn null;\n}\n\nexport async function readClipboardImage(options?: {\n\tenv?: NodeJS.ProcessEnv;\n\tplatform?: NodeJS.Platform;\n}): Promise<ClipboardImage | null> {\n\tconst env = options?.env ?? process.env;\n\tconst platform = options?.platform ?? process.platform;\n\n\tif (env.TERMUX_VERSION) {\n\t\treturn null;\n\t}\n\n\tlet image: ClipboardImage | null = null;\n\n\tif (platform === \"linux\" && isWaylandSession(env)) {\n\t\timage = readClipboardImageViaWlPaste() ?? readClipboardImageViaXclip();\n\t} else {\n\t\tif (!clipboard || !clipboard.hasImage()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst imageData = await clipboard.getImageBinary();\n\t\tif (!imageData || imageData.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst bytes = imageData instanceof Uint8Array ? imageData : Uint8Array.from(imageData);\n\t\timage = { bytes, mimeType: \"image/png\" };\n\t}\n\n\tif (!image) {\n\t\treturn null;\n\t}\n\n\t// Convert unsupported formats (e.g., BMP from WSLg) to PNG\n\tif (!isSupportedImageMimeType(image.mimeType)) {\n\t\tconst pngBytes = await convertToPng(image.bytes);\n\t\tif (!pngBytes) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { bytes: pngBytes, mimeType: \"image/png\" };\n\t}\n\n\treturn image;\n}\n"]}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import { clipboard } from "./clipboard-native.js";
|
|
3
|
+
import { loadPhoton } from "./photon.js";
|
|
4
|
+
const SUPPORTED_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
5
|
+
const DEFAULT_LIST_TIMEOUT_MS = 1000;
|
|
6
|
+
const DEFAULT_READ_TIMEOUT_MS = 3000;
|
|
7
|
+
const DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
8
|
+
export function isWaylandSession(env = process.env) {
|
|
9
|
+
return Boolean(env.WAYLAND_DISPLAY) || env.XDG_SESSION_TYPE === "wayland";
|
|
10
|
+
}
|
|
11
|
+
function baseMimeType(mimeType) {
|
|
12
|
+
return mimeType.split(";")[0]?.trim().toLowerCase() ?? mimeType.toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
export function extensionForImageMimeType(mimeType) {
|
|
15
|
+
switch (baseMimeType(mimeType)) {
|
|
16
|
+
case "image/png":
|
|
17
|
+
return "png";
|
|
18
|
+
case "image/jpeg":
|
|
19
|
+
return "jpg";
|
|
20
|
+
case "image/webp":
|
|
21
|
+
return "webp";
|
|
22
|
+
case "image/gif":
|
|
23
|
+
return "gif";
|
|
24
|
+
default:
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function selectPreferredImageMimeType(mimeTypes) {
|
|
29
|
+
const normalized = mimeTypes
|
|
30
|
+
.map((t) => t.trim())
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.map((t) => ({ raw: t, base: baseMimeType(t) }));
|
|
33
|
+
for (const preferred of SUPPORTED_IMAGE_MIME_TYPES) {
|
|
34
|
+
const match = normalized.find((t) => t.base === preferred);
|
|
35
|
+
if (match) {
|
|
36
|
+
return match.raw;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const anyImage = normalized.find((t) => t.base.startsWith("image/"));
|
|
40
|
+
return anyImage?.raw ?? null;
|
|
41
|
+
}
|
|
42
|
+
function isSupportedImageMimeType(mimeType) {
|
|
43
|
+
const base = baseMimeType(mimeType);
|
|
44
|
+
return SUPPORTED_IMAGE_MIME_TYPES.some((t) => t === base);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Convert unsupported image formats to PNG using Photon.
|
|
48
|
+
* Returns null if conversion is unavailable or fails.
|
|
49
|
+
*/
|
|
50
|
+
async function convertToPng(bytes) {
|
|
51
|
+
const photon = await loadPhoton();
|
|
52
|
+
if (!photon) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const image = photon.PhotonImage.new_from_byteslice(bytes);
|
|
57
|
+
try {
|
|
58
|
+
return image.get_bytes();
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
image.free();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function runCommand(command, args, options) {
|
|
69
|
+
const timeoutMs = options?.timeoutMs ?? DEFAULT_READ_TIMEOUT_MS;
|
|
70
|
+
const maxBufferBytes = options?.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES;
|
|
71
|
+
const result = spawnSync(command, args, {
|
|
72
|
+
timeout: timeoutMs,
|
|
73
|
+
maxBuffer: maxBufferBytes,
|
|
74
|
+
});
|
|
75
|
+
if (result.error) {
|
|
76
|
+
return { ok: false, stdout: Buffer.alloc(0) };
|
|
77
|
+
}
|
|
78
|
+
if (result.status !== 0) {
|
|
79
|
+
return { ok: false, stdout: Buffer.alloc(0) };
|
|
80
|
+
}
|
|
81
|
+
const stdout = Buffer.isBuffer(result.stdout)
|
|
82
|
+
? result.stdout
|
|
83
|
+
: Buffer.from(result.stdout ?? "", typeof result.stdout === "string" ? "utf-8" : undefined);
|
|
84
|
+
return { ok: true, stdout };
|
|
85
|
+
}
|
|
86
|
+
function readClipboardImageViaWlPaste() {
|
|
87
|
+
const list = runCommand("wl-paste", ["--list-types"], { timeoutMs: DEFAULT_LIST_TIMEOUT_MS });
|
|
88
|
+
if (!list.ok) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const types = list.stdout
|
|
92
|
+
.toString("utf-8")
|
|
93
|
+
.split(/\r?\n/)
|
|
94
|
+
.map((t) => t.trim())
|
|
95
|
+
.filter(Boolean);
|
|
96
|
+
const selectedType = selectPreferredImageMimeType(types);
|
|
97
|
+
if (!selectedType) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const data = runCommand("wl-paste", ["--type", selectedType, "--no-newline"]);
|
|
101
|
+
if (!data.ok || data.stdout.length === 0) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return { bytes: data.stdout, mimeType: baseMimeType(selectedType) };
|
|
105
|
+
}
|
|
106
|
+
function readClipboardImageViaXclip() {
|
|
107
|
+
const targets = runCommand("xclip", ["-selection", "clipboard", "-t", "TARGETS", "-o"], {
|
|
108
|
+
timeoutMs: DEFAULT_LIST_TIMEOUT_MS,
|
|
109
|
+
});
|
|
110
|
+
let candidateTypes = [];
|
|
111
|
+
if (targets.ok) {
|
|
112
|
+
candidateTypes = targets.stdout
|
|
113
|
+
.toString("utf-8")
|
|
114
|
+
.split(/\r?\n/)
|
|
115
|
+
.map((t) => t.trim())
|
|
116
|
+
.filter(Boolean);
|
|
117
|
+
}
|
|
118
|
+
const preferred = candidateTypes.length > 0 ? selectPreferredImageMimeType(candidateTypes) : null;
|
|
119
|
+
const tryTypes = preferred ? [preferred, ...SUPPORTED_IMAGE_MIME_TYPES] : [...SUPPORTED_IMAGE_MIME_TYPES];
|
|
120
|
+
for (const mimeType of tryTypes) {
|
|
121
|
+
const data = runCommand("xclip", ["-selection", "clipboard", "-t", mimeType, "-o"]);
|
|
122
|
+
if (data.ok && data.stdout.length > 0) {
|
|
123
|
+
return { bytes: data.stdout, mimeType: baseMimeType(mimeType) };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
export async function readClipboardImage(options) {
|
|
129
|
+
const env = options?.env ?? process.env;
|
|
130
|
+
const platform = options?.platform ?? process.platform;
|
|
131
|
+
if (env.TERMUX_VERSION) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
let image = null;
|
|
135
|
+
if (platform === "linux" && isWaylandSession(env)) {
|
|
136
|
+
image = readClipboardImageViaWlPaste() ?? readClipboardImageViaXclip();
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (!clipboard || !clipboard.hasImage()) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
const imageData = await clipboard.getImageBinary();
|
|
143
|
+
if (!imageData || imageData.length === 0) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
const bytes = imageData instanceof Uint8Array ? imageData : Uint8Array.from(imageData);
|
|
147
|
+
image = { bytes, mimeType: "image/png" };
|
|
148
|
+
}
|
|
149
|
+
if (!image) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
// Convert unsupported formats (e.g., BMP from WSLg) to PNG
|
|
153
|
+
if (!isSupportedImageMimeType(image.mimeType)) {
|
|
154
|
+
const pngBytes = await convertToPng(image.bytes);
|
|
155
|
+
if (!pngBytes) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
return { bytes: pngBytes, mimeType: "image/png" };
|
|
159
|
+
}
|
|
160
|
+
return image;
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=clipboard-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard-image.js","sourceRoot":"","sources":["../../src/utils/clipboard-image.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"child_process\";\n\nimport { clipboard } from \"./clipboard-native.js\";\nimport { loadPhoton } from \"./photon.js\";\n\nexport type ClipboardImage = {\n\tbytes: Uint8Array;\n\tmimeType: string;\n};\n\nconst SUPPORTED_IMAGE_MIME_TYPES = [\"image/png\", \"image/jpeg\", \"image/webp\", \"image/gif\"] as const;\n\nconst DEFAULT_LIST_TIMEOUT_MS = 1000;\nconst DEFAULT_READ_TIMEOUT_MS = 3000;\nconst DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;\n\nexport function isWaylandSession(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn Boolean(env.WAYLAND_DISPLAY) || env.XDG_SESSION_TYPE === \"wayland\";\n}\n\nfunction baseMimeType(mimeType: string): string {\n\treturn mimeType.split(\";\")[0]?.trim().toLowerCase() ?? mimeType.toLowerCase();\n}\n\nexport function extensionForImageMimeType(mimeType: string): string | null {\n\tswitch (baseMimeType(mimeType)) {\n\t\tcase \"image/png\":\n\t\t\treturn \"png\";\n\t\tcase \"image/jpeg\":\n\t\t\treturn \"jpg\";\n\t\tcase \"image/webp\":\n\t\t\treturn \"webp\";\n\t\tcase \"image/gif\":\n\t\t\treturn \"gif\";\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nfunction selectPreferredImageMimeType(mimeTypes: string[]): string | null {\n\tconst normalized = mimeTypes\n\t\t.map((t) => t.trim())\n\t\t.filter(Boolean)\n\t\t.map((t) => ({ raw: t, base: baseMimeType(t) }));\n\n\tfor (const preferred of SUPPORTED_IMAGE_MIME_TYPES) {\n\t\tconst match = normalized.find((t) => t.base === preferred);\n\t\tif (match) {\n\t\t\treturn match.raw;\n\t\t}\n\t}\n\n\tconst anyImage = normalized.find((t) => t.base.startsWith(\"image/\"));\n\treturn anyImage?.raw ?? null;\n}\n\nfunction isSupportedImageMimeType(mimeType: string): boolean {\n\tconst base = baseMimeType(mimeType);\n\treturn SUPPORTED_IMAGE_MIME_TYPES.some((t) => t === base);\n}\n\n/**\n * Convert unsupported image formats to PNG using Photon.\n * Returns null if conversion is unavailable or fails.\n */\nasync function convertToPng(bytes: Uint8Array): Promise<Uint8Array | null> {\n\tconst photon = await loadPhoton();\n\tif (!photon) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst image = photon.PhotonImage.new_from_byteslice(bytes);\n\t\ttry {\n\t\t\treturn image.get_bytes();\n\t\t} finally {\n\t\t\timage.free();\n\t\t}\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction runCommand(\n\tcommand: string,\n\targs: string[],\n\toptions?: { timeoutMs?: number; maxBufferBytes?: number },\n): { stdout: Buffer; ok: boolean } {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_READ_TIMEOUT_MS;\n\tconst maxBufferBytes = options?.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES;\n\n\tconst result = spawnSync(command, args, {\n\t\ttimeout: timeoutMs,\n\t\tmaxBuffer: maxBufferBytes,\n\t});\n\n\tif (result.error) {\n\t\treturn { ok: false, stdout: Buffer.alloc(0) };\n\t}\n\n\tif (result.status !== 0) {\n\t\treturn { ok: false, stdout: Buffer.alloc(0) };\n\t}\n\n\tconst stdout = Buffer.isBuffer(result.stdout)\n\t\t? result.stdout\n\t\t: Buffer.from(result.stdout ?? \"\", typeof result.stdout === \"string\" ? \"utf-8\" : undefined);\n\n\treturn { ok: true, stdout };\n}\n\nfunction readClipboardImageViaWlPaste(): ClipboardImage | null {\n\tconst list = runCommand(\"wl-paste\", [\"--list-types\"], { timeoutMs: DEFAULT_LIST_TIMEOUT_MS });\n\tif (!list.ok) {\n\t\treturn null;\n\t}\n\n\tconst types = list.stdout\n\t\t.toString(\"utf-8\")\n\t\t.split(/\\r?\\n/)\n\t\t.map((t) => t.trim())\n\t\t.filter(Boolean);\n\n\tconst selectedType = selectPreferredImageMimeType(types);\n\tif (!selectedType) {\n\t\treturn null;\n\t}\n\n\tconst data = runCommand(\"wl-paste\", [\"--type\", selectedType, \"--no-newline\"]);\n\tif (!data.ok || data.stdout.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn { bytes: data.stdout, mimeType: baseMimeType(selectedType) };\n}\n\nfunction readClipboardImageViaXclip(): ClipboardImage | null {\n\tconst targets = runCommand(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"TARGETS\", \"-o\"], {\n\t\ttimeoutMs: DEFAULT_LIST_TIMEOUT_MS,\n\t});\n\n\tlet candidateTypes: string[] = [];\n\tif (targets.ok) {\n\t\tcandidateTypes = targets.stdout\n\t\t\t.toString(\"utf-8\")\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.map((t) => t.trim())\n\t\t\t.filter(Boolean);\n\t}\n\n\tconst preferred = candidateTypes.length > 0 ? selectPreferredImageMimeType(candidateTypes) : null;\n\tconst tryTypes = preferred ? [preferred, ...SUPPORTED_IMAGE_MIME_TYPES] : [...SUPPORTED_IMAGE_MIME_TYPES];\n\n\tfor (const mimeType of tryTypes) {\n\t\tconst data = runCommand(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", mimeType, \"-o\"]);\n\t\tif (data.ok && data.stdout.length > 0) {\n\t\t\treturn { bytes: data.stdout, mimeType: baseMimeType(mimeType) };\n\t\t}\n\t}\n\n\treturn null;\n}\n\nexport async function readClipboardImage(options?: {\n\tenv?: NodeJS.ProcessEnv;\n\tplatform?: NodeJS.Platform;\n}): Promise<ClipboardImage | null> {\n\tconst env = options?.env ?? process.env;\n\tconst platform = options?.platform ?? process.platform;\n\n\tif (env.TERMUX_VERSION) {\n\t\treturn null;\n\t}\n\n\tlet image: ClipboardImage | null = null;\n\n\tif (platform === \"linux\" && isWaylandSession(env)) {\n\t\timage = readClipboardImageViaWlPaste() ?? readClipboardImageViaXclip();\n\t} else {\n\t\tif (!clipboard || !clipboard.hasImage()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst imageData = await clipboard.getImageBinary();\n\t\tif (!imageData || imageData.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst bytes = imageData instanceof Uint8Array ? imageData : Uint8Array.from(imageData);\n\t\timage = { bytes, mimeType: \"image/png\" };\n\t}\n\n\tif (!image) {\n\t\treturn null;\n\t}\n\n\t// Convert unsupported formats (e.g., BMP from WSLg) to PNG\n\tif (!isSupportedImageMimeType(image.mimeType)) {\n\t\tconst pngBytes = await convertToPng(image.bytes);\n\t\tif (!pngBytes) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { bytes: pngBytes, mimeType: \"image/png\" };\n\t}\n\n\treturn image;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard-native.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard-native.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC7C,CAAC;AAGF,QAAA,IAAI,SAAS,EAAE,eAAe,GAAG,IAAW,CAAC;AAY7C,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import { createRequire } from \"module\";\n\nexport type ClipboardModule = {\n\thasImage: () => boolean;\n\tgetImageBinary: () => Promise<Array<number>>;\n};\n\nconst require = createRequire(import.meta.url);\nlet clipboard: ClipboardModule | null = null;\n\nconst hasDisplay = process.platform !== \"linux\" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);\n\nif (!process.env.TERMUX_VERSION && hasDisplay) {\n\ttry {\n\t\tclipboard = require(\"@mariozechner/clipboard\") as ClipboardModule;\n\t} catch {\n\t\tclipboard = null;\n\t}\n}\n\nexport { clipboard };\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createRequire } from "module";
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
let clipboard = null;
|
|
4
|
+
const hasDisplay = process.platform !== "linux" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
|
|
5
|
+
if (!process.env.TERMUX_VERSION && hasDisplay) {
|
|
6
|
+
try {
|
|
7
|
+
clipboard = require("@mariozechner/clipboard");
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
clipboard = null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export { clipboard };
|
|
14
|
+
//# sourceMappingURL=clipboard-native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard-native.js","sourceRoot":"","sources":["../../src/utils/clipboard-native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAOvC,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,IAAI,SAAS,GAA2B,IAAI,CAAC;AAE7C,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AAE/G,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,UAAU,EAAE,CAAC;IAC/C,IAAI,CAAC;QACJ,SAAS,GAAG,OAAO,CAAC,yBAAyB,CAAoB,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACR,SAAS,GAAG,IAAI,CAAC;IAClB,CAAC;AACF,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import { createRequire } from \"module\";\n\nexport type ClipboardModule = {\n\thasImage: () => boolean;\n\tgetImageBinary: () => Promise<Array<number>>;\n};\n\nconst require = createRequire(import.meta.url);\nlet clipboard: ClipboardModule | null = null;\n\nconst hasDisplay = process.platform !== \"linux\" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);\n\nif (!process.env.TERMUX_VERSION && hasDisplay) {\n\ttry {\n\t\tclipboard = require(\"@mariozechner/clipboard\") as ClipboardModule;\n\t} catch {\n\t\tclipboard = null;\n\t}\n}\n\nexport { clipboard };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAIA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAyDlD","sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { platform } from \"os\";\nimport { isWaylandSession } from \"./clipboard-image.js\";\n\nexport function copyToClipboard(text: string): void {\n\t// Always emit OSC 52 - works over SSH/mosh, harmless locally\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\n\t// Also try native tools (best effort for local sessions)\n\tconst p = platform();\n\tconst options = { input: text, timeout: 5000 };\n\n\ttry {\n\t\tif (p === \"darwin\") {\n\t\t\texecSync(\"pbcopy\", options);\n\t\t} else if (p === \"win32\") {\n\t\t\texecSync(\"clip\", options);\n\t\t} else {\n\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\tif (process.env.TERMUX_VERSION) {\n\t\t\t\ttry {\n\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\treturn;\n\t\t\t\t} catch {\n\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst isWayland = isWaylandSession();\n\t\t\tif (isWayland) {\n\t\t\t\ttry {\n\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\" });\n\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead\n\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], { stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n\t\t\t\t\tproc.stdin.on(\"error\", () => {\n\t\t\t\t\t\t// Ignore EPIPE errors if wl-copy exits early\n\t\t\t\t\t});\n\t\t\t\t\tproc.stdin.write(text);\n\t\t\t\t\tproc.stdin.end();\n\t\t\t\t\tproc.unref();\n\t\t\t\t} catch {\n\t\t\t\t\t// Fall back to xclip/xsel (works on XWayland)\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"xclip -selection clipboard\", options);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\texecSync(\"xsel --clipboard --input\", options);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\texecSync(\"xclip -selection clipboard\", options);\n\t\t\t\t} catch {\n\t\t\t\t\texecSync(\"xsel --clipboard --input\", options);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ignore - OSC 52 already emitted as fallback\n\t}\n}\n"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { execSync, spawn } from "child_process";
|
|
2
|
+
import { platform } from "os";
|
|
3
|
+
import { isWaylandSession } from "./clipboard-image.js";
|
|
4
|
+
export function copyToClipboard(text) {
|
|
5
|
+
// Always emit OSC 52 - works over SSH/mosh, harmless locally
|
|
6
|
+
const encoded = Buffer.from(text).toString("base64");
|
|
7
|
+
process.stdout.write(`\x1b]52;c;${encoded}\x07`);
|
|
8
|
+
// Also try native tools (best effort for local sessions)
|
|
9
|
+
const p = platform();
|
|
10
|
+
const options = { input: text, timeout: 5000 };
|
|
11
|
+
try {
|
|
12
|
+
if (p === "darwin") {
|
|
13
|
+
execSync("pbcopy", options);
|
|
14
|
+
}
|
|
15
|
+
else if (p === "win32") {
|
|
16
|
+
execSync("clip", options);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
// Linux. Try Termux, Wayland, or X11 clipboard tools.
|
|
20
|
+
if (process.env.TERMUX_VERSION) {
|
|
21
|
+
try {
|
|
22
|
+
execSync("termux-clipboard-set", options);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Fall back to Wayland or X11 tools.
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const isWayland = isWaylandSession();
|
|
30
|
+
if (isWayland) {
|
|
31
|
+
try {
|
|
32
|
+
// Verify wl-copy exists (spawn errors are async and won't be caught)
|
|
33
|
+
execSync("which wl-copy", { stdio: "ignore" });
|
|
34
|
+
// wl-copy with execSync hangs due to fork behavior; use spawn instead
|
|
35
|
+
const proc = spawn("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
36
|
+
proc.stdin.on("error", () => {
|
|
37
|
+
// Ignore EPIPE errors if wl-copy exits early
|
|
38
|
+
});
|
|
39
|
+
proc.stdin.write(text);
|
|
40
|
+
proc.stdin.end();
|
|
41
|
+
proc.unref();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Fall back to xclip/xsel (works on XWayland)
|
|
45
|
+
try {
|
|
46
|
+
execSync("xclip -selection clipboard", options);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
execSync("xsel --clipboard --input", options);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
try {
|
|
55
|
+
execSync("xclip -selection clipboard", options);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
execSync("xsel --clipboard --input", options);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Ignore - OSC 52 already emitted as fallback
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=clipboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,UAAU,eAAe,CAAC,IAAY,EAAQ;IACnD,6DAA6D;IAC7D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,OAAO,MAAM,CAAC,CAAC;IAEjD,yDAAyD;IACzD,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAE/C,IAAI,CAAC;QACJ,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;YACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC7B,CAAC;aAAM,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACP,sDAAsD;YACtD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACJ,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;oBAC1C,OAAO;gBACR,CAAC;gBAAC,MAAM,CAAC;oBACR,qCAAqC;gBACtC,CAAC;YACF,CAAC;YAED,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;YACrC,IAAI,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC;oBACJ,qEAAqE;oBACrE,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;oBAC/C,sEAAsE;oBACtE,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;oBAC3E,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC;wBAC5B,6CAA6C;oBADhB,CAE7B,CAAC,CAAC;oBACH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACvB,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;oBACjB,IAAI,CAAC,KAAK,EAAE,CAAC;gBACd,CAAC;gBAAC,MAAM,CAAC;oBACR,8CAA8C;oBAC9C,IAAI,CAAC;wBACJ,QAAQ,CAAC,4BAA4B,EAAE,OAAO,CAAC,CAAC;oBACjD,CAAC;oBAAC,MAAM,CAAC;wBACR,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC,CAAC;oBAC/C,CAAC;gBACF,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC;oBACJ,QAAQ,CAAC,4BAA4B,EAAE,OAAO,CAAC,CAAC;gBACjD,CAAC;gBAAC,MAAM,CAAC;oBACR,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC,CAAC;gBAC/C,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,8CAA8C;IAC/C,CAAC;AAAA,CACD","sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { platform } from \"os\";\nimport { isWaylandSession } from \"./clipboard-image.js\";\n\nexport function copyToClipboard(text: string): void {\n\t// Always emit OSC 52 - works over SSH/mosh, harmless locally\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\n\t// Also try native tools (best effort for local sessions)\n\tconst p = platform();\n\tconst options = { input: text, timeout: 5000 };\n\n\ttry {\n\t\tif (p === \"darwin\") {\n\t\t\texecSync(\"pbcopy\", options);\n\t\t} else if (p === \"win32\") {\n\t\t\texecSync(\"clip\", options);\n\t\t} else {\n\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\tif (process.env.TERMUX_VERSION) {\n\t\t\t\ttry {\n\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\treturn;\n\t\t\t\t} catch {\n\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst isWayland = isWaylandSession();\n\t\t\tif (isWayland) {\n\t\t\t\ttry {\n\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\" });\n\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead\n\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], { stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n\t\t\t\t\tproc.stdin.on(\"error\", () => {\n\t\t\t\t\t\t// Ignore EPIPE errors if wl-copy exits early\n\t\t\t\t\t});\n\t\t\t\t\tproc.stdin.write(text);\n\t\t\t\t\tproc.stdin.end();\n\t\t\t\t\tproc.unref();\n\t\t\t\t} catch {\n\t\t\t\t\t// Fall back to xclip/xsel (works on XWayland)\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"xclip -selection clipboard\", options);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\texecSync(\"xsel --clipboard --input\", options);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\texecSync(\"xclip -selection clipboard\", options);\n\t\t\t\t} catch {\n\t\t\t\t\texecSync(\"xsel --clipboard --input\", options);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ignore - OSC 52 already emitted as fallback\n\t}\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type ParsedFrontmatter<T extends Record<string, unknown>> = {
|
|
2
|
+
frontmatter: T;
|
|
3
|
+
body: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const parseFrontmatter: <T extends Record<string, unknown> = Record<string, unknown>>(content: string) => ParsedFrontmatter<T>;
|
|
6
|
+
export declare const stripFrontmatter: (content: string) => string;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=frontmatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"AAEA,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC3D,WAAW,EAAE,CAAC,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AAsBF,eAAO,MAAM,gBAAgB,GAAI,CAAC,oGASjC,CAAC;AAEF,eAAO,MAAM,gBAAgB,6BAA8D,CAAC","sourcesContent":["import { parse } from \"yaml\";\n\ntype ParsedFrontmatter<T extends Record<string, unknown>> = {\n\tfrontmatter: T;\n\tbody: string;\n};\n\nconst normalizeNewlines = (value: string): string => value.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\nconst extractFrontmatter = (content: string): { yamlString: string | null; body: string } => {\n\tconst normalized = normalizeNewlines(content);\n\n\tif (!normalized.startsWith(\"---\")) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\tconst endIndex = normalized.indexOf(\"\\n---\", 3);\n\tif (endIndex === -1) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\treturn {\n\t\tyamlString: normalized.slice(4, endIndex),\n\t\tbody: normalized.slice(endIndex + 4).trim(),\n\t};\n};\n\nexport const parseFrontmatter = <T extends Record<string, unknown> = Record<string, unknown>>(\n\tcontent: string,\n): ParsedFrontmatter<T> => {\n\tconst { yamlString, body } = extractFrontmatter(content);\n\tif (!yamlString) {\n\t\treturn { frontmatter: {} as T, body };\n\t}\n\tconst parsed = parse(yamlString);\n\treturn { frontmatter: (parsed ?? {}) as T, body };\n};\n\nexport const stripFrontmatter = (content: string): string => parseFrontmatter(content).body;\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { parse } from "yaml";
|
|
2
|
+
const normalizeNewlines = (value) => value.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3
|
+
const extractFrontmatter = (content) => {
|
|
4
|
+
const normalized = normalizeNewlines(content);
|
|
5
|
+
if (!normalized.startsWith("---")) {
|
|
6
|
+
return { yamlString: null, body: normalized };
|
|
7
|
+
}
|
|
8
|
+
const endIndex = normalized.indexOf("\n---", 3);
|
|
9
|
+
if (endIndex === -1) {
|
|
10
|
+
return { yamlString: null, body: normalized };
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
yamlString: normalized.slice(4, endIndex),
|
|
14
|
+
body: normalized.slice(endIndex + 4).trim(),
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export const parseFrontmatter = (content) => {
|
|
18
|
+
const { yamlString, body } = extractFrontmatter(content);
|
|
19
|
+
if (!yamlString) {
|
|
20
|
+
return { frontmatter: {}, body };
|
|
21
|
+
}
|
|
22
|
+
const parsed = parse(yamlString);
|
|
23
|
+
return { frontmatter: (parsed ?? {}), body };
|
|
24
|
+
};
|
|
25
|
+
export const stripFrontmatter = (content) => parseFrontmatter(content).body;
|
|
26
|
+
//# sourceMappingURL=frontmatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAO7B,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAEvG,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAA+C,EAAE,CAAC;IAC5F,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE9C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAChD,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO;QACN,UAAU,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC;QACzC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE;KAC3C,CAAC;AAAA,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC/B,OAAe,EACQ,EAAE,CAAC;IAC1B,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,OAAO,EAAE,WAAW,EAAE,EAAO,EAAE,IAAI,EAAE,CAAC;IACvC,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;IACjC,OAAO,EAAE,WAAW,EAAE,CAAC,MAAM,IAAI,EAAE,CAAM,EAAE,IAAI,EAAE,CAAC;AAAA,CAClD,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC","sourcesContent":["import { parse } from \"yaml\";\n\ntype ParsedFrontmatter<T extends Record<string, unknown>> = {\n\tfrontmatter: T;\n\tbody: string;\n};\n\nconst normalizeNewlines = (value: string): string => value.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\nconst extractFrontmatter = (content: string): { yamlString: string | null; body: string } => {\n\tconst normalized = normalizeNewlines(content);\n\n\tif (!normalized.startsWith(\"---\")) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\tconst endIndex = normalized.indexOf(\"\\n---\", 3);\n\tif (endIndex === -1) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\treturn {\n\t\tyamlString: normalized.slice(4, endIndex),\n\t\tbody: normalized.slice(endIndex + 4).trim(),\n\t};\n};\n\nexport const parseFrontmatter = <T extends Record<string, unknown> = Record<string, unknown>>(\n\tcontent: string,\n): ParsedFrontmatter<T> => {\n\tconst { yamlString, body } = extractFrontmatter(content);\n\tif (!yamlString) {\n\t\treturn { frontmatter: {} as T, body };\n\t}\n\tconst parsed = parse(yamlString);\n\treturn { frontmatter: (parsed ?? {}) as T, body };\n};\n\nexport const stripFrontmatter = (content: string): string => parseFrontmatter(content).body;\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parsed git URL information.
|
|
3
|
+
*/
|
|
4
|
+
export type GitSource = {
|
|
5
|
+
/** Always "git" for git sources */
|
|
6
|
+
type: "git";
|
|
7
|
+
/** Clone URL (always valid for git clone, without ref suffix) */
|
|
8
|
+
repo: string;
|
|
9
|
+
/** Git host domain (e.g., "github.com") */
|
|
10
|
+
host: string;
|
|
11
|
+
/** Repository path (e.g., "user/repo") */
|
|
12
|
+
path: string;
|
|
13
|
+
/** Git ref (branch, tag, commit) if specified */
|
|
14
|
+
ref?: string;
|
|
15
|
+
/** True if ref was specified (package won't be auto-updated) */
|
|
16
|
+
pinned: boolean;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Parse git source into a GitSource.
|
|
20
|
+
*
|
|
21
|
+
* Rules:
|
|
22
|
+
* - With git: prefix, accept all historical shorthand forms.
|
|
23
|
+
* - Without git: prefix, only accept explicit protocol URLs.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseGitUrl(source: string): GitSource | null;
|
|
26
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACvB,mCAAmC;IACnC,IAAI,EAAE,KAAK,CAAC;IACZ,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,MAAM,EAAE,OAAO,CAAC;CAChB,CAAC;AA4GF;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CA0D5D","sourcesContent":["import hostedGitInfo from \"hosted-git-info\";\n\n/**\n * Parsed git URL information.\n */\nexport type GitSource = {\n\t/** Always \"git\" for git sources */\n\ttype: \"git\";\n\t/** Clone URL (always valid for git clone, without ref suffix) */\n\trepo: string;\n\t/** Git host domain (e.g., \"github.com\") */\n\thost: string;\n\t/** Repository path (e.g., \"user/repo\") */\n\tpath: string;\n\t/** Git ref (branch, tag, commit) if specified */\n\tref?: string;\n\t/** True if ref was specified (package won't be auto-updated) */\n\tpinned: boolean;\n};\n\nfunction splitRef(url: string): { repo: string; ref?: string } {\n\tconst scpLikeMatch = url.match(/^git@([^:]+):(.+)$/);\n\tif (scpLikeMatch) {\n\t\tconst pathWithMaybeRef = scpLikeMatch[2] ?? \"\";\n\t\tconst refSeparator = pathWithMaybeRef.indexOf(\"@\");\n\t\tif (refSeparator < 0) return { repo: url };\n\t\tconst repoPath = pathWithMaybeRef.slice(0, refSeparator);\n\t\tconst ref = pathWithMaybeRef.slice(refSeparator + 1);\n\t\tif (!repoPath || !ref) return { repo: url };\n\t\treturn {\n\t\t\trepo: `git@${scpLikeMatch[1] ?? \"\"}:${repoPath}`,\n\t\t\tref,\n\t\t};\n\t}\n\n\tif (url.includes(\"://\")) {\n\t\ttry {\n\t\t\tconst parsed = new URL(url);\n\t\t\tconst pathWithMaybeRef = parsed.pathname.replace(/^\\/+/, \"\");\n\t\t\tconst refSeparator = pathWithMaybeRef.indexOf(\"@\");\n\t\t\tif (refSeparator < 0) return { repo: url };\n\t\t\tconst repoPath = pathWithMaybeRef.slice(0, refSeparator);\n\t\t\tconst ref = pathWithMaybeRef.slice(refSeparator + 1);\n\t\t\tif (!repoPath || !ref) return { repo: url };\n\t\t\tparsed.pathname = `/${repoPath}`;\n\t\t\treturn {\n\t\t\t\trepo: parsed.toString().replace(/\\/$/, \"\"),\n\t\t\t\tref,\n\t\t\t};\n\t\t} catch {\n\t\t\treturn { repo: url };\n\t\t}\n\t}\n\n\tconst slashIndex = url.indexOf(\"/\");\n\tif (slashIndex < 0) {\n\t\treturn { repo: url };\n\t}\n\tconst host = url.slice(0, slashIndex);\n\tconst pathWithMaybeRef = url.slice(slashIndex + 1);\n\tconst refSeparator = pathWithMaybeRef.indexOf(\"@\");\n\tif (refSeparator < 0) {\n\t\treturn { repo: url };\n\t}\n\tconst repoPath = pathWithMaybeRef.slice(0, refSeparator);\n\tconst ref = pathWithMaybeRef.slice(refSeparator + 1);\n\tif (!repoPath || !ref) {\n\t\treturn { repo: url };\n\t}\n\treturn {\n\t\trepo: `${host}/${repoPath}`,\n\t\tref,\n\t};\n}\n\nfunction parseGenericGitUrl(url: string): GitSource | null {\n\tconst { repo: repoWithoutRef, ref } = splitRef(url);\n\tlet repo = repoWithoutRef;\n\tlet host = \"\";\n\tlet path = \"\";\n\n\tconst scpLikeMatch = repoWithoutRef.match(/^git@([^:]+):(.+)$/);\n\tif (scpLikeMatch) {\n\t\thost = scpLikeMatch[1] ?? \"\";\n\t\tpath = scpLikeMatch[2] ?? \"\";\n\t} else if (\n\t\trepoWithoutRef.startsWith(\"https://\") ||\n\t\trepoWithoutRef.startsWith(\"http://\") ||\n\t\trepoWithoutRef.startsWith(\"ssh://\") ||\n\t\trepoWithoutRef.startsWith(\"git://\")\n\t) {\n\t\ttry {\n\t\t\tconst parsed = new URL(repoWithoutRef);\n\t\t\thost = parsed.hostname;\n\t\t\tpath = parsed.pathname.replace(/^\\/+/, \"\");\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t} else {\n\t\tconst slashIndex = repoWithoutRef.indexOf(\"/\");\n\t\tif (slashIndex < 0) {\n\t\t\treturn null;\n\t\t}\n\t\thost = repoWithoutRef.slice(0, slashIndex);\n\t\tpath = repoWithoutRef.slice(slashIndex + 1);\n\t\tif (!host.includes(\".\") && host !== \"localhost\") {\n\t\t\treturn null;\n\t\t}\n\t\trepo = `https://${repoWithoutRef}`;\n\t}\n\n\tconst normalizedPath = path.replace(/\\.git$/, \"\").replace(/^\\/+/, \"\");\n\tif (!host || !normalizedPath || normalizedPath.split(\"/\").length < 2) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\ttype: \"git\",\n\t\trepo,\n\t\thost,\n\t\tpath: normalizedPath,\n\t\tref,\n\t\tpinned: Boolean(ref),\n\t};\n}\n\n/**\n * Parse git source into a GitSource.\n *\n * Rules:\n * - With git: prefix, accept all historical shorthand forms.\n * - Without git: prefix, only accept explicit protocol URLs.\n */\nexport function parseGitUrl(source: string): GitSource | null {\n\tconst trimmed = source.trim();\n\tconst hasGitPrefix = trimmed.startsWith(\"git:\");\n\tconst url = hasGitPrefix ? trimmed.slice(4).trim() : trimmed;\n\n\tif (!hasGitPrefix && !/^(https?|ssh|git):\\/\\//i.test(url)) {\n\t\treturn null;\n\t}\n\n\tconst split = splitRef(url);\n\n\tconst hostedCandidates = [split.ref ? `${split.repo}#${split.ref}` : undefined, url].filter(\n\t\t(value): value is string => Boolean(value),\n\t);\n\tfor (const candidate of hostedCandidates) {\n\t\tconst info = hostedGitInfo.fromUrl(candidate);\n\t\tif (info) {\n\t\t\tif (split.ref && info.project?.includes(\"@\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst useHttpsPrefix =\n\t\t\t\t!split.repo.startsWith(\"http://\") &&\n\t\t\t\t!split.repo.startsWith(\"https://\") &&\n\t\t\t\t!split.repo.startsWith(\"ssh://\") &&\n\t\t\t\t!split.repo.startsWith(\"git://\") &&\n\t\t\t\t!split.repo.startsWith(\"git@\");\n\t\t\treturn {\n\t\t\t\ttype: \"git\",\n\t\t\t\trepo: useHttpsPrefix ? `https://${split.repo}` : split.repo,\n\t\t\t\thost: info.domain || \"\",\n\t\t\t\tpath: `${info.user}/${info.project}`.replace(/\\.git$/, \"\"),\n\t\t\t\tref: info.committish || split.ref || undefined,\n\t\t\t\tpinned: Boolean(info.committish || split.ref),\n\t\t\t};\n\t\t}\n\t}\n\n\tconst httpsCandidates = [split.ref ? `https://${split.repo}#${split.ref}` : undefined, `https://${url}`].filter(\n\t\t(value): value is string => Boolean(value),\n\t);\n\tfor (const candidate of httpsCandidates) {\n\t\tconst info = hostedGitInfo.fromUrl(candidate);\n\t\tif (info) {\n\t\t\tif (split.ref && info.project?.includes(\"@\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttype: \"git\",\n\t\t\t\trepo: `https://${split.repo}`,\n\t\t\t\thost: info.domain || \"\",\n\t\t\t\tpath: `${info.user}/${info.project}`.replace(/\\.git$/, \"\"),\n\t\t\t\tref: info.committish || split.ref || undefined,\n\t\t\t\tpinned: Boolean(info.committish || split.ref),\n\t\t\t};\n\t\t}\n\t}\n\n\treturn parseGenericGitUrl(url);\n}\n"]}
|