@tomsun28/pizza 0.0.9 → 0.1.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.
- package/README.md +20 -143
- package/README.zh-CN.md +36 -0
- package/dist/bun/cli.d.ts +2 -0
- package/dist/bun/cli.js +6 -0
- package/dist/bun/register-bedrock.d.ts +1 -0
- package/dist/bun/register-bedrock.js +3 -0
- package/dist/cli/args.d.ts +48 -0
- package/dist/cli/args.js +330 -0
- package/dist/cli/config-selector.d.ts +13 -0
- package/dist/cli/config-selector.js +30 -0
- package/dist/cli/file-processor.d.ts +14 -0
- package/dist/cli/file-processor.js +82 -0
- package/dist/cli/initial-message.d.ts +17 -0
- package/dist/cli/initial-message.js +21 -0
- package/dist/cli/list-models.d.ts +8 -0
- package/dist/cli/list-models.js +96 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +68 -0
- package/dist/config.d.ts +79 -0
- package/dist/config.js +223 -0
- package/dist/core/agent/index.d.ts +6 -0
- package/dist/core/agent/index.js +6 -0
- package/dist/core/agent/types.d.ts +202 -0
- package/dist/core/agent/types.js +51 -0
- package/dist/core/auth-storage.d.ts +135 -0
- package/dist/core/auth-storage.js +417 -0
- package/dist/core/bash-executor.d.ts +31 -0
- package/dist/core/bash-executor.js +107 -0
- package/dist/core/compaction/branch-summarization.d.ts +87 -0
- package/dist/core/compaction/branch-summarization.js +242 -0
- package/dist/core/compaction/compaction-engine.d.ts +40 -0
- package/dist/core/compaction/compaction-engine.js +292 -0
- package/dist/core/compaction/compaction.d.ts +106 -0
- package/dist/core/compaction/compaction.js +295 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/utils.d.ts +37 -0
- package/dist/core/compaction/utils.js +152 -0
- package/dist/core/defaults.d.ts +2 -0
- package/dist/core/defaults.js +1 -0
- package/dist/core/diagnostics.d.ts +14 -0
- package/dist/core/diagnostics.js +1 -0
- package/dist/core/event-bus.d.ts +8 -0
- package/dist/core/event-bus.js +24 -0
- package/dist/core/event-store/events.d.ts +465 -0
- package/dist/core/event-store/events.js +6 -0
- package/dist/core/event-store/index.d.ts +10 -0
- package/dist/core/event-store/index.js +10 -0
- package/dist/core/event-store/sqlite-store.d.ts +27 -0
- package/dist/core/event-store/sqlite-store.js +275 -0
- package/dist/core/event-store/store.d.ts +91 -0
- package/dist/core/event-store/store.js +7 -0
- package/dist/core/event-store/thread-scoped-store.d.ts +29 -0
- package/dist/core/event-store/thread-scoped-store.js +50 -0
- package/dist/core/event-store/types.d.ts +70 -0
- package/dist/core/event-store/types.js +7 -0
- package/dist/core/event-store/workspace.d.ts +37 -0
- package/dist/core/event-store/workspace.js +71 -0
- package/dist/core/exec.d.ts +28 -0
- package/dist/core/exec.js +74 -0
- package/dist/core/export-html/ansi-to-html.d.ts +21 -0
- package/dist/core/export-html/ansi-to-html.js +248 -0
- package/dist/core/export-html/index.d.ts +29 -0
- package/dist/core/export-html/index.js +186 -0
- package/dist/core/export-html/template.css +1017 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1742 -0
- package/dist/core/export-html/tool-renderer.d.ts +39 -0
- package/dist/core/export-html/tool-renderer.js +94 -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 +12 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/loader.d.ts +24 -0
- package/dist/core/extensions/loader.js +492 -0
- package/dist/core/extensions/runner.d.ts +167 -0
- package/dist/core/extensions/runner.js +898 -0
- package/dist/core/extensions/session-context.d.ts +67 -0
- package/dist/core/extensions/session-context.js +272 -0
- package/dist/core/extensions/types.d.ts +1147 -0
- package/dist/core/extensions/types.js +44 -0
- package/dist/core/extensions/wrapper.d.ts +19 -0
- package/dist/core/extensions/wrapper.js +21 -0
- package/dist/core/footer-data-provider.d.ts +47 -0
- package/dist/core/footer-data-provider.js +321 -0
- package/dist/core/goal/index.d.ts +3 -0
- package/dist/core/goal/index.js +1 -0
- package/dist/core/goal/scheduler.d.ts +83 -0
- package/dist/core/goal/scheduler.js +154 -0
- package/dist/core/goal/types.d.ts +182 -0
- package/dist/core/goal/types.js +11 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +8 -0
- package/dist/core/intent/classifier.d.ts +53 -0
- package/dist/core/intent/classifier.js +353 -0
- package/dist/core/intent/index.d.ts +8 -0
- package/dist/core/intent/index.js +8 -0
- package/dist/core/intent/tool-adapter.d.ts +31 -0
- package/dist/core/intent/tool-adapter.js +168 -0
- package/dist/core/intent/types.d.ts +71 -0
- package/dist/core/intent/types.js +6 -0
- package/dist/core/keybindings.d.ts +297 -0
- package/dist/core/keybindings.js +250 -0
- package/dist/core/messages.d.ts +30 -0
- package/dist/core/messages.js +134 -0
- package/dist/core/model-registry.d.ts +131 -0
- package/dist/core/model-registry.js +634 -0
- package/dist/core/model-resolver.d.ts +109 -0
- package/dist/core/model-resolver.js +486 -0
- package/dist/core/output-guard.d.ts +5 -0
- package/dist/core/output-guard.js +58 -0
- package/dist/core/package-manager.d.ts +196 -0
- package/dist/core/package-manager.js +1873 -0
- package/dist/core/projection/boundary-inferrer.d.ts +58 -0
- package/dist/core/projection/boundary-inferrer.js +122 -0
- package/dist/core/projection/event-to-message.d.ts +35 -0
- package/dist/core/projection/event-to-message.js +253 -0
- package/dist/core/projection/goal-projection.d.ts +67 -0
- package/dist/core/projection/goal-projection.js +339 -0
- package/dist/core/projection/index.d.ts +13 -0
- package/dist/core/projection/index.js +13 -0
- package/dist/core/projection/session-manager.d.ts +100 -0
- package/dist/core/projection/session-manager.js +331 -0
- package/dist/core/projection/session-projection.d.ts +58 -0
- package/dist/core/projection/session-projection.js +257 -0
- package/dist/core/projection/task-history.d.ts +13 -0
- package/dist/core/projection/task-history.js +61 -0
- package/dist/core/projection/timeline-projection.d.ts +82 -0
- package/dist/core/projection/timeline-projection.js +276 -0
- package/dist/core/projection/types.d.ts +69 -0
- package/dist/core/projection/types.js +6 -0
- package/dist/core/prompt-templates.d.ts +51 -0
- package/dist/core/prompt-templates.js +249 -0
- package/dist/core/resolve-config-value.d.ts +22 -0
- package/dist/core/resolve-config-value.js +125 -0
- package/dist/core/resource-loader.d.ts +193 -0
- package/dist/core/resource-loader.js +685 -0
- package/dist/core/runtime/ai-client.d.ts +12 -0
- package/dist/core/runtime/ai-client.js +153 -0
- package/dist/core/runtime/checkpoint.d.ts +12 -0
- package/dist/core/runtime/checkpoint.js +78 -0
- package/dist/core/runtime/index.d.ts +12 -0
- package/dist/core/runtime/index.js +12 -0
- package/dist/core/runtime/llm-types.d.ts +99 -0
- package/dist/core/runtime/llm-types.js +6 -0
- package/dist/core/runtime/local-runtime.d.ts +23 -0
- package/dist/core/runtime/local-runtime.js +59 -0
- package/dist/core/runtime/policies.d.ts +72 -0
- package/dist/core/runtime/policies.js +37 -0
- package/dist/core/runtime/reactor.d.ts +213 -0
- package/dist/core/runtime/reactor.js +992 -0
- package/dist/core/runtime/runtime.d.ts +191 -0
- package/dist/core/runtime/runtime.js +449 -0
- package/dist/core/runtime/types.d.ts +42 -0
- package/dist/core/runtime/types.js +1 -0
- package/dist/core/sdk.d.ts +12 -0
- package/dist/core/sdk.js +10 -0
- package/dist/core/session-context-builder.d.ts +9 -0
- package/dist/core/session-context-builder.js +87 -0
- package/dist/core/session-cwd.d.ts +18 -0
- package/dist/core/session-cwd.js +36 -0
- package/dist/core/session-facade-factory.d.ts +79 -0
- package/dist/core/session-facade-factory.js +460 -0
- package/dist/core/session-facade.d.ts +57 -0
- package/dist/core/session-facade.js +91 -0
- package/dist/core/session-listing.d.ts +30 -0
- package/dist/core/session-listing.js +168 -0
- package/dist/core/session-reader.d.ts +19 -0
- package/dist/core/session-reader.js +101 -0
- package/dist/core/session-ref.d.ts +7 -0
- package/dist/core/session-ref.js +25 -0
- package/dist/core/session-services.d.ts +51 -0
- package/dist/core/session-services.js +90 -0
- package/dist/core/session-stats.d.ts +43 -0
- package/dist/core/session-stats.js +41 -0
- package/dist/core/settings-manager.d.ts +236 -0
- package/dist/core/settings-manager.js +706 -0
- package/dist/core/skill-block-parser.d.ts +12 -0
- package/dist/core/skill-block-parser.js +15 -0
- package/dist/core/skills.d.ts +59 -0
- package/dist/core/skills.js +408 -0
- package/dist/core/slash-commands.d.ts +13 -0
- package/dist/core/slash-commands.js +17 -0
- package/dist/core/source-info.d.ts +17 -0
- package/dist/core/source-info.js +18 -0
- package/dist/core/system-prompt.d.ts +27 -0
- package/dist/core/system-prompt.js +179 -0
- package/dist/core/timings.d.ts +7 -0
- package/dist/core/timings.js +30 -0
- package/dist/core/tools/bash.d.ts +95 -0
- package/dist/core/tools/bash.js +513 -0
- package/dist/core/tools/builtin-commands.d.ts +75 -0
- package/dist/core/tools/builtin-commands.js +503 -0
- package/dist/core/tools/compat-commands.d.ts +12 -0
- package/dist/core/tools/compat-commands.js +1280 -0
- package/dist/core/tools/edit-diff.d.ts +59 -0
- package/dist/core/tools/edit-diff.js +263 -0
- package/dist/core/tools/edit.d.ts +49 -0
- package/dist/core/tools/edit.js +340 -0
- package/dist/core/tools/file-mutation-queue.d.ts +5 -0
- package/dist/core/tools/file-mutation-queue.js +36 -0
- package/dist/core/tools/find.d.ts +34 -0
- package/dist/core/tools/find.js +459 -0
- package/dist/core/tools/grep.d.ts +36 -0
- package/dist/core/tools/grep.js +422 -0
- package/dist/core/tools/index.d.ts +70 -0
- package/dist/core/tools/index.js +129 -0
- package/dist/core/tools/line-anchors.d.ts +33 -0
- package/dist/core/tools/line-anchors.js +151 -0
- package/dist/core/tools/ls.d.ts +36 -0
- package/dist/core/tools/ls.js +268 -0
- package/dist/core/tools/path-utils.d.ts +7 -0
- package/dist/core/tools/path-utils.js +80 -0
- package/dist/core/tools/read.d.ts +35 -0
- package/dist/core/tools/read.js +244 -0
- package/dist/core/tools/render-utils.d.ts +20 -0
- package/dist/core/tools/render-utils.js +48 -0
- package/dist/core/tools/session-split.d.ts +9 -0
- package/dist/core/tools/session-split.js +77 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
- package/dist/core/tools/tool-definition-wrapper.js +32 -0
- package/dist/core/tools/truncate.d.ts +69 -0
- package/dist/core/tools/truncate.js +204 -0
- package/dist/core/tools/write.d.ts +25 -0
- package/dist/core/tools/write.js +211 -0
- package/dist/core/types/session-types.d.ts +123 -0
- package/dist/core/types/session-types.js +8 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +38 -0
- package/dist/main.d.ts +11 -2
- package/dist/main.js +577 -149
- package/dist/modes/event-mapper.d.ts +115 -0
- package/dist/modes/event-mapper.js +200 -0
- package/dist/modes/gui/server.d.ts +14 -0
- package/dist/modes/gui/server.js +1032 -0
- package/dist/modes/index.d.ts +10 -0
- package/dist/modes/index.js +9 -0
- package/dist/modes/interactive/assets/clankolas.png +0 -0
- package/dist/modes/interactive/components/armin.d.ts +33 -0
- package/dist/modes/interactive/components/armin.js +328 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
- package/dist/modes/interactive/components/assistant-message.js +115 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
- package/dist/modes/interactive/components/bash-execution.js +169 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
- package/dist/modes/interactive/components/bordered-loader.js +50 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/branch-summary-message.js +41 -0
- package/dist/modes/interactive/components/brand-header.d.ts +33 -0
- package/dist/modes/interactive/components/brand-header.js +235 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +42 -0
- package/dist/modes/interactive/components/config-selector.d.ts +70 -0
- package/dist/modes/interactive/components/config-selector.js +469 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
- package/dist/modes/interactive/components/countdown-timer.js +27 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +27 -0
- package/dist/modes/interactive/components/custom-editor.js +94 -0
- package/dist/modes/interactive/components/custom-message.d.ts +19 -0
- package/dist/modes/interactive/components/custom-message.js +73 -0
- package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
- package/dist/modes/interactive/components/daxnuts.js +137 -0
- package/dist/modes/interactive/components/diff.d.ts +11 -0
- package/dist/modes/interactive/components/diff.js +132 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
- package/dist/modes/interactive/components/dynamic-border.js +19 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
- package/dist/modes/interactive/components/earendil-announcement.js +39 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +19 -0
- package/dist/modes/interactive/components/extension-editor.js +105 -0
- package/dist/modes/interactive/components/extension-input.d.ts +22 -0
- package/dist/modes/interactive/components/extension-input.js +54 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +23 -0
- package/dist/modes/interactive/components/extension-selector.js +70 -0
- package/dist/modes/interactive/components/footer.d.ts +55 -0
- package/dist/modes/interactive/components/footer.js +207 -0
- package/dist/modes/interactive/components/index.d.ts +31 -0
- package/dist/modes/interactive/components/index.js +32 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +7 -0
- package/dist/modes/interactive/components/keybinding-hints.js +21 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +41 -0
- package/dist/modes/interactive/components/login-dialog.js +138 -0
- package/dist/modes/interactive/components/model-selector.d.ts +32 -0
- package/dist/modes/interactive/components/model-selector.js +209 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +18 -0
- package/dist/modes/interactive/components/oauth-selector.js +91 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +57 -0
- package/dist/modes/interactive/components/settings-selector.js +299 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
- package/dist/modes/interactive/components/show-images-selector.js +37 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +44 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
- package/dist/modes/interactive/components/theme-selector.js +47 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
- package/dist/modes/interactive/components/thinking-selector.js +50 -0
- package/dist/modes/interactive/components/timeline-view.d.ts +31 -0
- package/dist/modes/interactive/components/timeline-view.js +81 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +64 -0
- package/dist/modes/interactive/components/tool-execution.js +305 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +88 -0
- package/dist/modes/interactive/components/tree-selector.js +1072 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
- package/dist/modes/interactive/components/user-message-selector.js +110 -0
- package/dist/modes/interactive/components/user-message.d.ts +9 -0
- package/dist/modes/interactive/components/user-message.js +27 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
- package/dist/modes/interactive/components/visual-truncate.js +32 -0
- package/dist/modes/interactive/interactive-mode.d.ts +394 -0
- package/dist/modes/interactive/interactive-mode.js +4116 -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 +80 -0
- package/dist/modes/interactive/theme/theme.js +973 -0
- package/dist/modes/print-mode.d.ts +27 -0
- package/dist/modes/print-mode.js +102 -0
- package/dist/modes/rpc/jsonl.d.ts +16 -0
- package/dist/modes/rpc/jsonl.js +48 -0
- package/dist/modes/rpc/rpc-client.d.ts +219 -0
- package/dist/modes/rpc/rpc-client.js +405 -0
- package/dist/modes/rpc/rpc-mode.d.ts +19 -0
- package/dist/modes/rpc/rpc-mode.js +381 -0
- package/dist/modes/rpc/rpc-types.d.ts +406 -0
- package/dist/modes/rpc/rpc-types.js +7 -0
- package/dist/package-manager-cli.d.ts +3 -0
- package/dist/package-manager-cli.js +233 -0
- package/dist/utils/changelog.d.ts +20 -0
- package/dist/utils/changelog.js +86 -0
- package/dist/utils/child-process.d.ts +10 -0
- package/dist/utils/child-process.js +77 -0
- package/dist/utils/clipboard-image.d.ts +10 -0
- package/dist/utils/clipboard-image.js +244 -0
- package/dist/utils/clipboard-native.d.ts +7 -0
- package/dist/utils/clipboard-native.js +13 -0
- package/dist/utils/clipboard.d.ts +1 -0
- package/dist/utils/clipboard.js +77 -0
- package/dist/utils/exif-orientation.d.ts +4 -0
- package/dist/utils/exif-orientation.js +157 -0
- package/dist/utils/frontmatter.d.ts +7 -0
- package/dist/utils/frontmatter.js +25 -0
- package/dist/utils/git.d.ts +25 -0
- package/dist/utils/git.js +162 -0
- package/dist/utils/image-convert.d.ts +8 -0
- package/dist/utils/image-convert.js +38 -0
- package/dist/utils/image-resize.d.ts +35 -0
- package/dist/utils/image-resize.js +136 -0
- package/dist/utils/mime.d.ts +1 -0
- package/dist/utils/mime.js +25 -0
- package/dist/utils/path-shims.d.ts +1 -0
- package/dist/utils/path-shims.js +90 -0
- package/dist/utils/paths.d.ts +6 -0
- package/dist/utils/paths.js +18 -0
- package/dist/utils/photon.d.ts +20 -0
- package/dist/utils/photon.js +120 -0
- package/dist/utils/shell.d.ts +29 -0
- package/dist/utils/shell.js +189 -0
- package/dist/utils/sleep.d.ts +4 -0
- package/dist/utils/sleep.js +16 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.js +101 -0
- package/dist/vendor/bin/darwin-arm64/fd +0 -0
- package/dist/vendor/bin/darwin-arm64/rg +0 -0
- package/dist/vendor/bin/darwin-x64/fd +0 -0
- package/dist/vendor/bin/darwin-x64/rg +0 -0
- package/dist/vendor/bin/linux-arm64/fd +0 -0
- package/dist/vendor/bin/linux-arm64/rg +0 -0
- package/dist/vendor/bin/linux-x64/fd +0 -0
- package/dist/vendor/bin/linux-x64/rg +0 -0
- package/dist/vendor/bin/win32-arm64/fd.exe +0 -0
- package/dist/vendor/bin/win32-arm64/rg.exe +0 -0
- package/dist/vendor/bin/win32-x64/fd.exe +0 -0
- package/dist/vendor/bin/win32-x64/rg.exe +0 -0
- package/package.json +90 -26
- package/dist/extension/core.d.ts +0 -69
- package/dist/extension/core.js +0 -270
- package/dist/extension/core.js.map +0 -1
- package/dist/extension/index.d.ts +0 -25
- package/dist/extension/index.js +0 -303
- package/dist/extension/index.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/themes/pizza.json +0 -87
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { accessSync, chmodSync, constants, existsSync, mkdtempSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { delimiter, join } from "node:path";
|
|
4
|
+
import { getPackageDir, isBunBinary } from "../config.js";
|
|
5
|
+
import { COMPAT_COMMANDS } from "../core/tools/compat-commands.js";
|
|
6
|
+
const SHIM_ENV_KEY = "PIZZA_SHIM_DIR";
|
|
7
|
+
export function injectPizzaPathShims(env) {
|
|
8
|
+
const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") ?? "PATH";
|
|
9
|
+
const currentPath = env[pathKey] ?? "";
|
|
10
|
+
const pathWithoutOldShim = removePathEntry(currentPath, env[SHIM_ENV_KEY]);
|
|
11
|
+
const missingCommands = COMPAT_COMMANDS.filter((command) => !commandExistsOnPath(command, pathWithoutOldShim));
|
|
12
|
+
if (missingCommands.length === 0) {
|
|
13
|
+
if (pathWithoutOldShim === currentPath && !env[SHIM_ENV_KEY])
|
|
14
|
+
return env;
|
|
15
|
+
const cleanEnv = { ...env, [pathKey]: pathWithoutOldShim };
|
|
16
|
+
delete cleanEnv[SHIM_ENV_KEY];
|
|
17
|
+
return cleanEnv;
|
|
18
|
+
}
|
|
19
|
+
const shimDir = mkdtempSync(join(tmpdir(), "pizza-shims-"));
|
|
20
|
+
for (const command of missingCommands) {
|
|
21
|
+
writeShim(shimDir, command);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
...env,
|
|
25
|
+
[pathKey]: [shimDir, pathWithoutOldShim].filter(Boolean).join(delimiter),
|
|
26
|
+
[SHIM_ENV_KEY]: shimDir,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function removePathEntry(pathValue, entry) {
|
|
30
|
+
if (!entry)
|
|
31
|
+
return pathValue;
|
|
32
|
+
return pathValue
|
|
33
|
+
.split(delimiter)
|
|
34
|
+
.filter((part) => part && part !== entry)
|
|
35
|
+
.join(delimiter);
|
|
36
|
+
}
|
|
37
|
+
function commandExistsOnPath(command, pathValue) {
|
|
38
|
+
const dirs = pathValue.split(delimiter).filter(Boolean);
|
|
39
|
+
const names = executableNames(command);
|
|
40
|
+
for (const dir of dirs) {
|
|
41
|
+
for (const name of names) {
|
|
42
|
+
const candidate = join(dir, name);
|
|
43
|
+
try {
|
|
44
|
+
accessSync(candidate, constants.X_OK);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Try the next candidate.
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
function executableNames(command) {
|
|
55
|
+
if (process.platform !== "win32")
|
|
56
|
+
return [command];
|
|
57
|
+
const pathExt = process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD";
|
|
58
|
+
const extensions = pathExt.split(";").filter(Boolean);
|
|
59
|
+
return [command, ...extensions.map((ext) => `${command}${ext.toLowerCase()}`), ...extensions.map((ext) => `${command}${ext.toUpperCase()}`)];
|
|
60
|
+
}
|
|
61
|
+
function writeShim(shimDir, command) {
|
|
62
|
+
const shimPath = join(shimDir, command);
|
|
63
|
+
const invocation = getCompatInvocation();
|
|
64
|
+
const script = `#!/bin/sh\nexec ${invocation} ${shellQuote(command)} "$@"\n`;
|
|
65
|
+
writeFileSync(shimPath, script, "utf-8");
|
|
66
|
+
chmodSync(shimPath, 0o755);
|
|
67
|
+
}
|
|
68
|
+
function getCompatInvocation() {
|
|
69
|
+
if (isBunBinary) {
|
|
70
|
+
return `${shellQuote(process.execPath)} __compat`;
|
|
71
|
+
}
|
|
72
|
+
const packageDir = getPackageDir();
|
|
73
|
+
const sourceCli = join(packageDir, "src", "cli.ts");
|
|
74
|
+
const tsxLoader = join(packageDir, "node_modules", "tsx", "dist", "loader.mjs");
|
|
75
|
+
const runningFromSource = import.meta.url.includes("/src/") || import.meta.url.includes("\\src\\");
|
|
76
|
+
if (runningFromSource && existsSync(sourceCli) && existsSync(tsxLoader)) {
|
|
77
|
+
return `${shellQuote(process.execPath)} --import ${shellQuote(tsxLoader)} ${shellQuote(sourceCli)} __compat`;
|
|
78
|
+
}
|
|
79
|
+
const distCli = join(packageDir, "dist", "cli.js");
|
|
80
|
+
if (existsSync(distCli)) {
|
|
81
|
+
return `${shellQuote(process.execPath)} ${shellQuote(distCli)} __compat`;
|
|
82
|
+
}
|
|
83
|
+
if (existsSync(sourceCli) && existsSync(tsxLoader)) {
|
|
84
|
+
return `${shellQuote(process.execPath)} --import ${shellQuote(tsxLoader)} ${shellQuote(sourceCli)} __compat`;
|
|
85
|
+
}
|
|
86
|
+
return `${shellQuote(process.execPath)} ${shellQuote(distCli)} __compat`;
|
|
87
|
+
}
|
|
88
|
+
function shellQuote(value) {
|
|
89
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
90
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true if the value is NOT a package source (npm:, git:, etc.)
|
|
3
|
+
* or a URL protocol. Bare names and relative paths without ./ prefix
|
|
4
|
+
* are considered local.
|
|
5
|
+
*/
|
|
6
|
+
export function isLocalPath(value) {
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
// Known non-local prefixes
|
|
9
|
+
if (trimmed.startsWith("npm:") ||
|
|
10
|
+
trimmed.startsWith("git:") ||
|
|
11
|
+
trimmed.startsWith("github:") ||
|
|
12
|
+
trimmed.startsWith("http:") ||
|
|
13
|
+
trimmed.startsWith("https:") ||
|
|
14
|
+
trimmed.startsWith("ssh:")) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Photon image processing wrapper.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a unified interface to @silvia-odwyer/photon-node that works in:
|
|
5
|
+
* 1. Node.js (development, npm run build)
|
|
6
|
+
* 2. Bun compiled binaries (standalone distribution)
|
|
7
|
+
*
|
|
8
|
+
* The challenge: photon-node's CJS entry uses fs.readFileSync(__dirname + '/photon_rs_bg.wasm')
|
|
9
|
+
* which bakes the build machine's absolute path into Bun compiled binaries.
|
|
10
|
+
*
|
|
11
|
+
* Solution:
|
|
12
|
+
* 1. Patch fs.readFileSync to redirect missing photon_rs_bg.wasm reads
|
|
13
|
+
* 2. Copy photon_rs_bg.wasm next to the executable in build:binary
|
|
14
|
+
*/
|
|
15
|
+
export type { PhotonImage as PhotonImageType } from "@silvia-odwyer/photon-node";
|
|
16
|
+
/**
|
|
17
|
+
* Load the photon module asynchronously.
|
|
18
|
+
* Returns cached module on subsequent calls.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadPhoton(): Promise<typeof import("@silvia-odwyer/photon-node") | null>;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Photon image processing wrapper.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a unified interface to @silvia-odwyer/photon-node that works in:
|
|
5
|
+
* 1. Node.js (development, npm run build)
|
|
6
|
+
* 2. Bun compiled binaries (standalone distribution)
|
|
7
|
+
*
|
|
8
|
+
* The challenge: photon-node's CJS entry uses fs.readFileSync(__dirname + '/photon_rs_bg.wasm')
|
|
9
|
+
* which bakes the build machine's absolute path into Bun compiled binaries.
|
|
10
|
+
*
|
|
11
|
+
* Solution:
|
|
12
|
+
* 1. Patch fs.readFileSync to redirect missing photon_rs_bg.wasm reads
|
|
13
|
+
* 2. Copy photon_rs_bg.wasm next to the executable in build:binary
|
|
14
|
+
*/
|
|
15
|
+
import { createRequire } from "module";
|
|
16
|
+
import * as path from "path";
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
18
|
+
const require = createRequire(import.meta.url);
|
|
19
|
+
const fs = require("fs");
|
|
20
|
+
const WASM_FILENAME = "photon_rs_bg.wasm";
|
|
21
|
+
// Lazy-loaded photon module
|
|
22
|
+
let photonModule = null;
|
|
23
|
+
let loadPromise = null;
|
|
24
|
+
function pathOrNull(file) {
|
|
25
|
+
if (typeof file === "string") {
|
|
26
|
+
return file;
|
|
27
|
+
}
|
|
28
|
+
if (file instanceof URL) {
|
|
29
|
+
return fileURLToPath(file);
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function getFallbackWasmPaths() {
|
|
34
|
+
const execDir = path.dirname(process.execPath);
|
|
35
|
+
return [
|
|
36
|
+
path.join(execDir, WASM_FILENAME),
|
|
37
|
+
path.join(execDir, "photon", WASM_FILENAME),
|
|
38
|
+
path.join(process.cwd(), WASM_FILENAME),
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
function patchPhotonWasmRead() {
|
|
42
|
+
const originalReadFileSync = fs.readFileSync.bind(fs);
|
|
43
|
+
const fallbackPaths = getFallbackWasmPaths();
|
|
44
|
+
const mutableFs = fs;
|
|
45
|
+
const patchedReadFileSync = ((...args) => {
|
|
46
|
+
const [file, options] = args;
|
|
47
|
+
const resolvedPath = pathOrNull(file);
|
|
48
|
+
if (resolvedPath?.endsWith(WASM_FILENAME)) {
|
|
49
|
+
try {
|
|
50
|
+
return originalReadFileSync(...args);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const err = error;
|
|
54
|
+
if (err?.code && err.code !== "ENOENT") {
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
for (const fallbackPath of fallbackPaths) {
|
|
58
|
+
if (!fs.existsSync(fallbackPath)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (options === undefined) {
|
|
62
|
+
return originalReadFileSync(fallbackPath);
|
|
63
|
+
}
|
|
64
|
+
return originalReadFileSync(fallbackPath, options);
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return originalReadFileSync(...args);
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
mutableFs.readFileSync = patchedReadFileSync;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
Object.defineProperty(fs, "readFileSync", {
|
|
76
|
+
value: patchedReadFileSync,
|
|
77
|
+
writable: true,
|
|
78
|
+
configurable: true,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return () => {
|
|
82
|
+
try {
|
|
83
|
+
mutableFs.readFileSync = originalReadFileSync;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
Object.defineProperty(fs, "readFileSync", {
|
|
87
|
+
value: originalReadFileSync,
|
|
88
|
+
writable: true,
|
|
89
|
+
configurable: true,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Load the photon module asynchronously.
|
|
96
|
+
* Returns cached module on subsequent calls.
|
|
97
|
+
*/
|
|
98
|
+
export async function loadPhoton() {
|
|
99
|
+
if (photonModule) {
|
|
100
|
+
return photonModule;
|
|
101
|
+
}
|
|
102
|
+
if (loadPromise) {
|
|
103
|
+
return loadPromise;
|
|
104
|
+
}
|
|
105
|
+
loadPromise = (async () => {
|
|
106
|
+
const restoreReadFileSync = patchPhotonWasmRead();
|
|
107
|
+
try {
|
|
108
|
+
photonModule = await import("@silvia-odwyer/photon-node");
|
|
109
|
+
return photonModule;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
photonModule = null;
|
|
113
|
+
return photonModule;
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
restoreReadFileSync();
|
|
117
|
+
}
|
|
118
|
+
})();
|
|
119
|
+
return loadPromise;
|
|
120
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface ShellConfig {
|
|
2
|
+
shell: string;
|
|
3
|
+
args: string[];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolve shell configuration based on platform and an optional explicit shell path.
|
|
7
|
+
* Resolution order:
|
|
8
|
+
* 1. User-specified shellPath
|
|
9
|
+
* 2. On Windows: Git Bash in known locations, then bash on PATH
|
|
10
|
+
* 3. On Unix: /bin/bash, then bash on PATH, then fallback to sh
|
|
11
|
+
*/
|
|
12
|
+
export declare function getShellConfig(customShellPath?: string): ShellConfig;
|
|
13
|
+
export declare function getShellEnv(): NodeJS.ProcessEnv;
|
|
14
|
+
/**
|
|
15
|
+
* Sanitize binary output for display/storage.
|
|
16
|
+
* Removes characters that crash string-width or cause display issues:
|
|
17
|
+
* - Control characters (except tab, newline, carriage return)
|
|
18
|
+
* - Lone surrogates
|
|
19
|
+
* - Unicode Format characters (crash string-width due to a bug)
|
|
20
|
+
* - Characters with undefined code points
|
|
21
|
+
*/
|
|
22
|
+
export declare function sanitizeBinaryOutput(str: string): string;
|
|
23
|
+
export declare function trackDetachedChildPid(pid: number): void;
|
|
24
|
+
export declare function untrackDetachedChildPid(pid: number): void;
|
|
25
|
+
export declare function killTrackedDetachedChildren(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Kill a process and all its children (cross-platform)
|
|
28
|
+
*/
|
|
29
|
+
export declare function killProcessTree(pid: number): void;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { delimiter } from "node:path";
|
|
3
|
+
import { spawn, spawnSync } from "child_process";
|
|
4
|
+
import { getBinDir } from "../config.js";
|
|
5
|
+
/**
|
|
6
|
+
* Find bash executable on PATH (cross-platform)
|
|
7
|
+
*/
|
|
8
|
+
function findBashOnPath() {
|
|
9
|
+
if (process.platform === "win32") {
|
|
10
|
+
// Windows: Use 'where' and verify file exists (where can return non-existent paths)
|
|
11
|
+
try {
|
|
12
|
+
const result = spawnSync("where", ["bash.exe"], { encoding: "utf-8", timeout: 5000 });
|
|
13
|
+
if (result.status === 0 && result.stdout) {
|
|
14
|
+
const firstMatch = result.stdout.trim().split(/\r?\n/)[0];
|
|
15
|
+
if (firstMatch && existsSync(firstMatch)) {
|
|
16
|
+
return firstMatch;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Ignore errors
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
// Unix: Use 'which' and trust its output (handles Termux and special filesystems)
|
|
26
|
+
try {
|
|
27
|
+
const result = spawnSync("which", ["bash"], { encoding: "utf-8", timeout: 5000 });
|
|
28
|
+
if (result.status === 0 && result.stdout) {
|
|
29
|
+
const firstMatch = result.stdout.trim().split(/\r?\n/)[0];
|
|
30
|
+
if (firstMatch) {
|
|
31
|
+
return firstMatch;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Ignore errors
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve shell configuration based on platform and an optional explicit shell path.
|
|
42
|
+
* Resolution order:
|
|
43
|
+
* 1. User-specified shellPath
|
|
44
|
+
* 2. On Windows: Git Bash in known locations, then bash on PATH
|
|
45
|
+
* 3. On Unix: /bin/bash, then bash on PATH, then fallback to sh
|
|
46
|
+
*/
|
|
47
|
+
export function getShellConfig(customShellPath) {
|
|
48
|
+
// 1. Check user-specified shell path
|
|
49
|
+
if (customShellPath) {
|
|
50
|
+
if (existsSync(customShellPath)) {
|
|
51
|
+
return { shell: customShellPath, args: ["-c"] };
|
|
52
|
+
}
|
|
53
|
+
throw new Error(`Custom shell path not found: ${customShellPath}`);
|
|
54
|
+
}
|
|
55
|
+
if (process.platform === "win32") {
|
|
56
|
+
// 2. Try Git Bash in known locations
|
|
57
|
+
const paths = [];
|
|
58
|
+
const programFiles = process.env.ProgramFiles;
|
|
59
|
+
if (programFiles) {
|
|
60
|
+
paths.push(`${programFiles}\\Git\\bin\\bash.exe`);
|
|
61
|
+
}
|
|
62
|
+
const programFilesX86 = process.env["ProgramFiles(x86)"];
|
|
63
|
+
if (programFilesX86) {
|
|
64
|
+
paths.push(`${programFilesX86}\\Git\\bin\\bash.exe`);
|
|
65
|
+
}
|
|
66
|
+
for (const path of paths) {
|
|
67
|
+
if (existsSync(path)) {
|
|
68
|
+
return { shell: path, args: ["-c"] };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// 3. Fallback: search bash.exe on PATH (Cygwin, MSYS2, WSL, etc.)
|
|
72
|
+
const bashOnPath = findBashOnPath();
|
|
73
|
+
if (bashOnPath) {
|
|
74
|
+
return { shell: bashOnPath, args: ["-c"] };
|
|
75
|
+
}
|
|
76
|
+
throw new Error(`No bash shell found. Options:\n` +
|
|
77
|
+
` 1. Install Git for Windows: https://git-scm.com/download/win\n` +
|
|
78
|
+
` 2. Add your bash to PATH (Cygwin, MSYS2, etc.)\n` +
|
|
79
|
+
" 3. Set shellPath in settings.json\n\n" +
|
|
80
|
+
`Searched Git Bash in:\n${paths.map((p) => ` ${p}`).join("\n")}`);
|
|
81
|
+
}
|
|
82
|
+
// Unix: try /bin/bash, then bash on PATH, then fallback to sh
|
|
83
|
+
if (existsSync("/bin/bash")) {
|
|
84
|
+
return { shell: "/bin/bash", args: ["-c"] };
|
|
85
|
+
}
|
|
86
|
+
const bashOnPath = findBashOnPath();
|
|
87
|
+
if (bashOnPath) {
|
|
88
|
+
return { shell: bashOnPath, args: ["-c"] };
|
|
89
|
+
}
|
|
90
|
+
return { shell: "sh", args: ["-c"] };
|
|
91
|
+
}
|
|
92
|
+
export function getShellEnv() {
|
|
93
|
+
const binDir = getBinDir();
|
|
94
|
+
const pathKey = Object.keys(process.env).find((key) => key.toLowerCase() === "path") ?? "PATH";
|
|
95
|
+
const currentPath = process.env[pathKey] ?? "";
|
|
96
|
+
const pathEntries = currentPath.split(delimiter).filter(Boolean);
|
|
97
|
+
const hasBinDir = pathEntries.includes(binDir);
|
|
98
|
+
const updatedPath = hasBinDir ? currentPath : [binDir, currentPath].filter(Boolean).join(delimiter);
|
|
99
|
+
return {
|
|
100
|
+
...process.env,
|
|
101
|
+
[pathKey]: updatedPath,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Sanitize binary output for display/storage.
|
|
106
|
+
* Removes characters that crash string-width or cause display issues:
|
|
107
|
+
* - Control characters (except tab, newline, carriage return)
|
|
108
|
+
* - Lone surrogates
|
|
109
|
+
* - Unicode Format characters (crash string-width due to a bug)
|
|
110
|
+
* - Characters with undefined code points
|
|
111
|
+
*/
|
|
112
|
+
export function sanitizeBinaryOutput(str) {
|
|
113
|
+
// Use Array.from to properly iterate over code points (not code units)
|
|
114
|
+
// This handles surrogate pairs correctly and catches edge cases where
|
|
115
|
+
// codePointAt() might return undefined
|
|
116
|
+
return Array.from(str)
|
|
117
|
+
.filter((char) => {
|
|
118
|
+
// Filter out characters that cause string-width to crash
|
|
119
|
+
// This includes:
|
|
120
|
+
// - Unicode format characters
|
|
121
|
+
// - Lone surrogates (already filtered by Array.from)
|
|
122
|
+
// - Control chars except \t \n \r
|
|
123
|
+
// - Characters with undefined code points
|
|
124
|
+
const code = char.codePointAt(0);
|
|
125
|
+
// Skip if code point is undefined (edge case with invalid strings)
|
|
126
|
+
if (code === undefined)
|
|
127
|
+
return false;
|
|
128
|
+
// Allow tab, newline, carriage return
|
|
129
|
+
if (code === 0x09 || code === 0x0a || code === 0x0d)
|
|
130
|
+
return true;
|
|
131
|
+
// Filter out control characters (0x00-0x1F, except 0x09, 0x0a, 0x0x0d)
|
|
132
|
+
if (code <= 0x1f)
|
|
133
|
+
return false;
|
|
134
|
+
// Filter out Unicode format characters
|
|
135
|
+
if (code >= 0xfff9 && code <= 0xfffb)
|
|
136
|
+
return false;
|
|
137
|
+
return true;
|
|
138
|
+
})
|
|
139
|
+
.join("");
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Detached child processes must be tracked so they can be killed on parent
|
|
143
|
+
* shutdown signals (SIGHUP/SIGTERM).
|
|
144
|
+
*/
|
|
145
|
+
const trackedDetachedChildPids = new Set();
|
|
146
|
+
export function trackDetachedChildPid(pid) {
|
|
147
|
+
trackedDetachedChildPids.add(pid);
|
|
148
|
+
}
|
|
149
|
+
export function untrackDetachedChildPid(pid) {
|
|
150
|
+
trackedDetachedChildPids.delete(pid);
|
|
151
|
+
}
|
|
152
|
+
export function killTrackedDetachedChildren() {
|
|
153
|
+
for (const pid of trackedDetachedChildPids) {
|
|
154
|
+
killProcessTree(pid);
|
|
155
|
+
}
|
|
156
|
+
trackedDetachedChildPids.clear();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Kill a process and all its children (cross-platform)
|
|
160
|
+
*/
|
|
161
|
+
export function killProcessTree(pid) {
|
|
162
|
+
if (process.platform === "win32") {
|
|
163
|
+
// Use taskkill on Windows to kill process tree
|
|
164
|
+
try {
|
|
165
|
+
spawn("taskkill", ["/F", "/T", "/PID", String(pid)], {
|
|
166
|
+
stdio: "ignore",
|
|
167
|
+
detached: true,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Ignore errors if taskkill fails
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
// Use SIGKILL on Unix/Linux/Mac
|
|
176
|
+
try {
|
|
177
|
+
process.kill(-pid, "SIGKILL");
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// Fallback to killing just the child if process group kill fails
|
|
181
|
+
try {
|
|
182
|
+
process.kill(pid, "SIGKILL");
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// Process already dead
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sleep helper that respects abort signal.
|
|
3
|
+
*/
|
|
4
|
+
export function sleep(ms, signal) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
if (signal?.aborted) {
|
|
7
|
+
reject(new Error("Aborted"));
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const timeout = setTimeout(resolve, ms);
|
|
11
|
+
signal?.addEventListener("abort", () => {
|
|
12
|
+
clearTimeout(timeout);
|
|
13
|
+
reject(new Error("Aborted"));
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { spawnSync } from "child_process";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { arch, platform } from "os";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { getBinDir, getBundledBinDir } from "../config.js";
|
|
7
|
+
const TOOLS_DIR = getBinDir();
|
|
8
|
+
function isOfflineModeEnabled() {
|
|
9
|
+
const value = process.env.PIZZA_OFFLINE;
|
|
10
|
+
if (!value)
|
|
11
|
+
return false;
|
|
12
|
+
return value === "1" || value.toLowerCase() === "true" || value.toLowerCase() === "yes";
|
|
13
|
+
}
|
|
14
|
+
const TOOLS = {
|
|
15
|
+
fd: {
|
|
16
|
+
name: "fd",
|
|
17
|
+
binaryName: "fd",
|
|
18
|
+
},
|
|
19
|
+
rg: {
|
|
20
|
+
name: "ripgrep",
|
|
21
|
+
binaryName: "rg",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
// Check if a command exists in PATH by trying to run it
|
|
25
|
+
function commandExists(cmd) {
|
|
26
|
+
try {
|
|
27
|
+
const result = spawnSync(cmd, ["--version"], { stdio: "pipe" });
|
|
28
|
+
// Check for ENOENT error (command not found)
|
|
29
|
+
return result.error === undefined || result.error === null;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function executableName(config) {
|
|
36
|
+
return config.binaryName + (platform() === "win32" ? ".exe" : "");
|
|
37
|
+
}
|
|
38
|
+
function platformArchKey() {
|
|
39
|
+
return `${platform()}-${arch()}`;
|
|
40
|
+
}
|
|
41
|
+
export function getBundledToolPath(tool) {
|
|
42
|
+
const config = TOOLS[tool];
|
|
43
|
+
if (!config)
|
|
44
|
+
return null;
|
|
45
|
+
const bundledPath = join(getBundledBinDir(), platformArchKey(), executableName(config));
|
|
46
|
+
if (existsSync(bundledPath)) {
|
|
47
|
+
return bundledPath;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
// Get the path to a tool (system-wide or in our tools dir)
|
|
52
|
+
export function getToolPath(tool) {
|
|
53
|
+
const config = TOOLS[tool];
|
|
54
|
+
if (!config)
|
|
55
|
+
return null;
|
|
56
|
+
// Check binaries shipped with the package first for stable installs.
|
|
57
|
+
const bundledPath = getBundledToolPath(tool);
|
|
58
|
+
if (bundledPath) {
|
|
59
|
+
return bundledPath;
|
|
60
|
+
}
|
|
61
|
+
// Check our tools directory first
|
|
62
|
+
const localPath = join(TOOLS_DIR, executableName(config));
|
|
63
|
+
if (existsSync(localPath)) {
|
|
64
|
+
return localPath;
|
|
65
|
+
}
|
|
66
|
+
// Check system PATH - if found, just return the command name (it's in PATH)
|
|
67
|
+
if (commandExists(config.binaryName)) {
|
|
68
|
+
return config.binaryName;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
// Termux package names for tools
|
|
73
|
+
const TERMUX_PACKAGES = {
|
|
74
|
+
fd: "fd",
|
|
75
|
+
rg: "ripgrep",
|
|
76
|
+
};
|
|
77
|
+
// Ensure a tool is available
|
|
78
|
+
// Returns the path to the tool, or undefined if unavailable
|
|
79
|
+
export async function ensureTool(tool, silent = false) {
|
|
80
|
+
const existingPath = getToolPath(tool);
|
|
81
|
+
if (existingPath) {
|
|
82
|
+
return existingPath;
|
|
83
|
+
}
|
|
84
|
+
const config = TOOLS[tool];
|
|
85
|
+
if (!config)
|
|
86
|
+
return undefined;
|
|
87
|
+
// On Android/Termux, Linux binaries don't work due to Bionic libc incompatibility.
|
|
88
|
+
// Users must install via pkg.
|
|
89
|
+
if (platform() === "android") {
|
|
90
|
+
const pkgName = TERMUX_PACKAGES[tool] ?? tool;
|
|
91
|
+
if (!silent) {
|
|
92
|
+
console.log(chalk.yellow(`${config.name} not found. Install with: pkg install ${pkgName}`));
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
// Tool not found - automatic download disabled
|
|
97
|
+
if (!silent) {
|
|
98
|
+
console.log(chalk.yellow(`${config.name} not found. Please install it manually.`));
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|