@pixelbyte-software/pixcode 1.51.2 → 1.51.4
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/CODE_OF_CONDUCT.md +41 -41
- package/CONTRIBUTING.md +155 -155
- package/LICENSE +718 -718
- package/README.de.md +169 -169
- package/README.ja.md +167 -167
- package/README.ko.md +167 -167
- package/README.md +419 -419
- package/README.ru.md +169 -169
- package/README.tr.md +298 -298
- package/README.zh-CN.md +167 -167
- package/SECURITY.md +46 -46
- package/dist/api-automation.html +110 -110
- package/dist/api-docs.html +548 -548
- package/dist/assets/index-B9N-gfOQ.css +32 -0
- package/dist/assets/{index-EN9ngyxf.js → index-HfGHXhD6.js} +175 -175
- package/dist/clear-cache.html +85 -85
- package/dist/convert-icons.md +52 -52
- package/dist/docs.html +308 -308
- package/dist/favicon.svg +8 -8
- package/dist/features.html +133 -133
- package/dist/generate-icons.js +48 -48
- package/dist/humans.txt +15 -15
- package/dist/icons/codex-white.svg +3 -3
- package/dist/icons/codex.svg +3 -3
- package/dist/icons/cursor-white.svg +11 -11
- package/dist/icons/icon-128x128.svg +9 -9
- package/dist/icons/icon-144x144.svg +9 -9
- package/dist/icons/icon-152x152.svg +9 -9
- package/dist/icons/icon-192x192.svg +9 -9
- package/dist/icons/icon-384x384.svg +9 -9
- package/dist/icons/icon-512x512.svg +9 -9
- package/dist/icons/icon-72x72.svg +9 -9
- package/dist/icons/icon-96x96.svg +9 -9
- package/dist/icons/icon-template.svg +9 -9
- package/dist/icons/qwen-logo.svg +14 -14
- package/dist/index.html +59 -59
- package/dist/landing.html +268 -268
- package/dist/llms-full.txt +119 -119
- package/dist/llms.txt +53 -53
- package/dist/logo.svg +12 -12
- package/dist/manifest.json +60 -60
- package/dist/openapi.yaml +1696 -1696
- package/dist/orchestration.html +125 -125
- package/dist/robots.txt +4 -4
- package/dist/site.css +692 -692
- package/dist/sitemap.xml +51 -51
- package/dist/sw.js +132 -132
- package/dist-server/server/cli.js +96 -96
- package/dist-server/server/daemon/manager.js +33 -33
- package/dist-server/server/daemon-manager.js +64 -64
- package/dist-server/server/database/db.js +14 -2
- package/dist-server/server/database/db.js.map +1 -1
- package/dist-server/server/index.js +191 -31
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/middleware/auth.js +16 -5
- package/dist-server/server/middleware/auth.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.js +84 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.test.js +43 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.test.js.map +1 -0
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js +55 -1
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js.map +1 -1
- package/dist-server/server/modules/orchestration/index.js +1 -0
- package/dist-server/server/modules/orchestration/index.js.map +1 -1
- package/dist-server/server/routes/auth.js +12 -5
- package/dist-server/server/routes/auth.js.map +1 -1
- package/dist-server/server/routes/commands.js +25 -25
- package/dist-server/server/routes/git.js +29 -17
- package/dist-server/server/routes/git.js.map +1 -1
- package/dist-server/server/routes/live-view.js +46 -46
- package/dist-server/server/routes/platformization.js +7 -6
- package/dist-server/server/routes/platformization.js.map +1 -1
- package/dist-server/server/services/hermes-gateway.js +310 -0
- package/dist-server/server/services/hermes-gateway.js.map +1 -1
- package/dist-server/server/services/platformization.js +58 -2
- package/dist-server/server/services/platformization.js.map +1 -1
- package/dist-server/server/services/public-api-manifest.js +59 -51
- package/dist-server/server/services/public-api-manifest.js.map +1 -1
- package/package.json +222 -222
- package/scripts/fix-node-pty.js +67 -67
- package/scripts/github/create-v1.38-issues.mjs +351 -351
- package/scripts/github/create-vscode-workbench-issues.mjs +121 -121
- package/scripts/hermes/configure-pixcode-mcp.mjs +165 -163
- package/scripts/hermes/pixcode-mcp-server.mjs +1009 -958
- package/scripts/smoke/changes-panel-layout.mjs +48 -48
- package/scripts/smoke/chat-composer-fixed-layout.mjs +55 -55
- package/scripts/smoke/chat-message-timeline-order.mjs +41 -41
- package/scripts/smoke/chat-realtime-hydration.mjs +44 -44
- package/scripts/smoke/chat-session-provider-pools.mjs +35 -35
- package/scripts/smoke/chat-session-state.mjs +19 -19
- package/scripts/smoke/code-editor-theme.mjs +55 -55
- package/scripts/smoke/code-editor-vscode-engine.mjs +91 -91
- package/scripts/smoke/command-center-agent-writes.mjs +79 -79
- package/scripts/smoke/command-center-non-git.mjs +46 -46
- package/scripts/smoke/context-packet.mjs +43 -43
- package/scripts/smoke/control-room-ux-redesign.mjs +91 -91
- package/scripts/smoke/daemon-entrypoint.mjs +20 -20
- package/scripts/smoke/default-landing-routing.mjs +33 -33
- package/scripts/smoke/desktop-native-notifications.mjs +30 -30
- package/scripts/smoke/desktop-tray-icon.mjs +33 -33
- package/scripts/smoke/discord-release-workflow.mjs +24 -24
- package/scripts/smoke/git-install-update.mjs +255 -255
- package/scripts/smoke/handoff-artifact-protocol.mjs +50 -50
- package/scripts/smoke/hermes-api-install.mjs +56 -56
- package/scripts/smoke/hermes-gateway-persistence.mjs +104 -104
- package/scripts/smoke/hermes-mcp-pixcode-roundtrip.mjs +426 -367
- package/scripts/smoke/hermes-rest-chat-api.mjs +162 -162
- package/scripts/smoke/hermes-rest-chat-live.mjs +45 -45
- package/scripts/smoke/hermes-rest-codex-launch.mjs +209 -209
- package/scripts/smoke/hermes-rest-gateway.mjs +79 -70
- package/scripts/smoke/hermes-rest-live.mjs +42 -42
- package/scripts/smoke/hermes-roundtrip.mjs +167 -167
- package/scripts/smoke/hermes-settings-commands.mjs +349 -346
- package/scripts/smoke/hermes-smoke-launcher-guard.mjs +34 -34
- package/scripts/smoke/live-view-diagnostics.mjs +53 -53
- package/scripts/smoke/live-view-environment.mjs +92 -92
- package/scripts/smoke/live-view-integration.mjs +450 -450
- package/scripts/smoke/mac-desktop-runtime.mjs +37 -37
- package/scripts/smoke/mobile-tunnel-guidance.mjs +29 -29
- package/scripts/smoke/model-registry.mjs +36 -36
- package/scripts/smoke/multi-project-ui.mjs +45 -45
- package/scripts/smoke/multi-worker-slots.mjs +42 -42
- package/scripts/smoke/notification-center.mjs +87 -87
- package/scripts/smoke/notification-inapp-preference.mjs +23 -23
- package/scripts/smoke/notification-taxonomy.mjs +58 -58
- package/scripts/smoke/orchestration-api.mjs +172 -172
- package/scripts/smoke/orchestration-execution-dashboard.mjs +33 -33
- package/scripts/smoke/orchestration-live-run.mjs +176 -176
- package/scripts/smoke/orchestration-mobile-scroll.mjs +29 -29
- package/scripts/smoke/orchestration-model-sync.mjs +30 -30
- package/scripts/smoke/orchestration-permission-fallback.mjs +34 -34
- package/scripts/smoke/orchestration-runtime-guards.mjs +48 -48
- package/scripts/smoke/orchestration-user-facing-output.mjs +25 -25
- package/scripts/smoke/permission-policy.mjs +50 -50
- package/scripts/smoke/pixcode-workbench-1-48.mjs +167 -167
- package/scripts/smoke/provider-models-opencode-live.mjs +66 -66
- package/scripts/smoke/provider-rest-api.mjs +124 -124
- package/scripts/smoke/provider-selection-status.mjs +52 -52
- package/scripts/smoke/run-state-refresh.mjs +52 -52
- package/scripts/smoke/runtime-manager.mjs +99 -99
- package/scripts/smoke/shell-manual-disconnect.mjs +30 -30
- package/scripts/smoke/side-panel-editor-layout.mjs +34 -34
- package/scripts/smoke/static-root-routing.mjs +21 -21
- package/scripts/smoke/strict-handoff-compact.mjs +60 -60
- package/scripts/smoke/taskmaster-config.mjs +24 -24
- package/scripts/smoke/taskmaster-execution-telegram.mjs +3 -3
- package/scripts/smoke/taskmaster-onboarding.mjs +3 -3
- package/scripts/smoke/taskmaster-run-graph.mjs +3 -3
- package/scripts/smoke/telegram-control.mjs +242 -242
- package/scripts/smoke/tunnel-persistence.mjs +56 -56
- package/scripts/smoke/update-issue-progress.mjs +69 -69
- package/scripts/smoke/update-ux.mjs +55 -55
- package/scripts/smoke/v138-completion.mjs +132 -132
- package/scripts/smoke/v138-desktop-release-hardening.mjs +69 -69
- package/scripts/smoke/v138-diagnostics.mjs +63 -63
- package/scripts/smoke/v138-issue-planner.mjs +33 -33
- package/scripts/smoke/v143-remote-control.mjs +76 -76
- package/scripts/smoke/v144-production-loop.mjs +47 -47
- package/scripts/smoke/v145-platformization.mjs +46 -46
- package/scripts/smoke/v146-control-room-ui.mjs +150 -150
- package/scripts/smoke/version-modal-autoshow.mjs +29 -29
- package/scripts/smoke/vscode-workbench-layout.mjs +63 -63
- package/scripts/smoke/vscode-workbench-polish.mjs +461 -436
- package/scripts/smoke/workflow-fallback-replay.mjs +56 -56
- package/scripts/smoke/workflow-templates.mjs +43 -43
- package/scripts/smoke/workflow-trace-timeline.mjs +46 -46
- package/scripts/update-git-install.mjs +293 -293
- package/server/claude-sdk.js +920 -920
- package/server/cli.js +1039 -1039
- package/server/constants/config.js +4 -4
- package/server/cursor-cli.js +344 -344
- package/server/daemon/manager.js +563 -563
- package/server/daemon-manager.js +964 -964
- package/server/database/db.js +908 -895
- package/server/database/json-store.js +197 -197
- package/server/gemini-cli.js +550 -550
- package/server/gemini-response-handler.js +79 -79
- package/server/index.js +201 -30
- package/server/load-env.js +35 -35
- package/server/middleware/auth.js +171 -156
- package/server/modules/orchestration/a2a/adapter-registry.ts +108 -108
- package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +63 -63
- package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +286 -286
- package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -244
- package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -249
- package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/adapters/json-event.adapter.test.ts +60 -0
- package/server/modules/orchestration/a2a/adapters/json-event.adapter.ts +101 -0
- package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/agent-card.ts +55 -55
- package/server/modules/orchestration/a2a/routes.ts +590 -590
- package/server/modules/orchestration/a2a/task-store.ts +178 -178
- package/server/modules/orchestration/a2a/types.ts +126 -126
- package/server/modules/orchestration/a2a/validator.ts +113 -113
- package/server/modules/orchestration/hermes/hermes.routes.ts +642 -583
- package/server/modules/orchestration/index.ts +101 -100
- package/server/modules/orchestration/preview/port-watcher.ts +112 -112
- package/server/modules/orchestration/preview/preview-proxy.ts +60 -60
- package/server/modules/orchestration/preview/types.ts +19 -19
- package/server/modules/orchestration/security/permission-policy.ts +401 -401
- package/server/modules/orchestration/tasks/orchestration-task-store.ts +41 -41
- package/server/modules/orchestration/tasks/orchestration-task.routes.ts +64 -64
- package/server/modules/orchestration/tasks/orchestration-task.service.ts +209 -209
- package/server/modules/orchestration/tasks/orchestration-task.types.ts +40 -40
- package/server/modules/orchestration/tasks/task-run-graph.ts +155 -155
- package/server/modules/orchestration/workflows/approval-queue.ts +106 -106
- package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -127
- package/server/modules/orchestration/workflows/context-packet.ts +186 -186
- package/server/modules/orchestration/workflows/handoff-artifact.ts +175 -175
- package/server/modules/orchestration/workflows/workflow-fallback-policy.ts +161 -161
- package/server/modules/orchestration/workflows/workflow-replay.ts +254 -254
- package/server/modules/orchestration/workflows/workflow-runner.ts +2070 -2070
- package/server/modules/orchestration/workflows/workflow-store.ts +97 -97
- package/server/modules/orchestration/workflows/workflow-templates.ts +272 -272
- package/server/modules/orchestration/workflows/workflow-trace.ts +424 -424
- package/server/modules/orchestration/workflows/workflow.routes.ts +586 -586
- package/server/modules/orchestration/workflows/workflow.types.ts +111 -111
- package/server/modules/orchestration/workflows/workspace-target.ts +122 -122
- package/server/modules/orchestration/workspace/docker-workspace.ts +136 -136
- package/server/modules/orchestration/workspace/path-safety.ts +55 -55
- package/server/modules/orchestration/workspace/types.ts +52 -52
- package/server/modules/orchestration/workspace/workspace-manager.ts +102 -102
- package/server/modules/orchestration/workspace/worktree-workspace.ts +126 -126
- package/server/modules/providers/index.ts +2 -2
- package/server/modules/providers/list/claude/claude-auth.provider.ts +146 -146
- package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
- package/server/modules/providers/list/claude/claude.provider.ts +15 -15
- package/server/modules/providers/list/codex/codex-auth.provider.ts +117 -117
- package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
- package/server/modules/providers/list/codex/codex.provider.ts +15 -15
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +147 -147
- package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
- package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
- package/server/modules/providers/list/gemini/gemini-auth.provider.ts +173 -173
- package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
- package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +131 -131
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +286 -286
- package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
- package/server/modules/providers/list/qwen/qwen-auth.provider.ts +146 -146
- package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
- package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
- package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
- package/server/modules/providers/provider.registry.ts +40 -40
- package/server/modules/providers/provider.routes.ts +944 -944
- package/server/modules/providers/services/mcp.service.ts +86 -86
- package/server/modules/providers/services/provider-auth.service.ts +26 -26
- package/server/modules/providers/services/sessions.service.ts +45 -45
- package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
- package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
- package/server/modules/providers/shared/provider-configs.ts +142 -142
- package/server/modules/providers/tests/mcp.test.ts +293 -293
- package/server/openai-codex.js +462 -462
- package/server/opencode-cli.js +491 -491
- package/server/opencode-response-handler.js +111 -111
- package/server/projects.js +3008 -3008
- package/server/qwen-code-cli.js +410 -410
- package/server/qwen-response-handler.js +73 -73
- package/server/routes/agent.js +1435 -1435
- package/server/routes/auth.js +154 -146
- package/server/routes/codex.js +20 -20
- package/server/routes/commands.js +570 -570
- package/server/routes/cursor.js +61 -61
- package/server/routes/diagnostics.js +41 -41
- package/server/routes/gemini.js +25 -25
- package/server/routes/git.js +1650 -1635
- package/server/routes/live-view.js +411 -411
- package/server/routes/mcp-utils.js +13 -13
- package/server/routes/messages.js +62 -62
- package/server/routes/network.js +125 -125
- package/server/routes/platformization.js +198 -197
- package/server/routes/plugins.js +320 -320
- package/server/routes/production-agent-loop.js +90 -90
- package/server/routes/projects.js +917 -917
- package/server/routes/public-api.js +34 -34
- package/server/routes/qwen.js +27 -27
- package/server/routes/remote.js +55 -55
- package/server/routes/settings.js +321 -321
- package/server/routes/telegram.js +140 -140
- package/server/routes/user.js +125 -125
- package/server/routes/webhooks.js +63 -63
- package/server/services/control-room.js +102 -102
- package/server/services/diagnostics.js +165 -165
- package/server/services/external-access.js +375 -375
- package/server/services/hermes-gateway.js +1562 -1247
- package/server/services/hermes-install-jobs.js +729 -729
- package/server/services/install-jobs.js +715 -715
- package/server/services/live-view.js +956 -956
- package/server/services/managed-runtimes.js +493 -493
- package/server/services/model-registry.js +144 -144
- package/server/services/notification-orchestrator.js +365 -365
- package/server/services/notification-taxonomy.js +204 -204
- package/server/services/platformization.js +844 -779
- package/server/services/production-agent-loop.js +248 -248
- package/server/services/provider-cli-versions.js +149 -149
- package/server/services/provider-credentials.js +189 -189
- package/server/services/provider-models.js +396 -396
- package/server/services/public-api-manifest.js +190 -182
- package/server/services/remote-connection.js +127 -127
- package/server/services/runtime-manager.js +323 -323
- package/server/services/startup-update.js +234 -234
- package/server/services/telegram/bot.js +331 -331
- package/server/services/telegram/control-center.js +979 -979
- package/server/services/telegram/telegram-http-client.js +151 -151
- package/server/services/telegram/translations.js +340 -340
- package/server/services/vapid-keys.js +36 -36
- package/server/services/webhooks.js +216 -216
- package/server/sessionManager.js +225 -225
- package/server/shared/interfaces.ts +54 -54
- package/server/shared/types.ts +172 -172
- package/server/shared/utils.ts +193 -193
- package/server/tsconfig.json +36 -36
- package/server/utils/colors.js +21 -21
- package/server/utils/commandParser.js +305 -305
- package/server/utils/frontmatter.js +18 -18
- package/server/utils/gitConfig.js +34 -34
- package/server/utils/plugin-loader.js +457 -457
- package/server/utils/plugin-process-manager.js +185 -185
- package/server/utils/port-access.js +209 -209
- package/server/utils/runtime-paths.js +37 -37
- package/server/utils/url-detection.js +71 -71
- package/server/vite-daemon.js +79 -79
- package/shared/modelConstants.js +161 -161
- package/shared/networkHosts.js +22 -22
- package/dist/assets/index-DMz0zv6T.css +0 -32
|
@@ -1,323 +1,323 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process';
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
|
|
5
|
-
import { buildCliSpawnEnv, findExecutableOnPath, resolveNpmCommand } from './install-jobs.js';
|
|
6
|
-
import { getManagedRuntimeStatus } from './managed-runtimes.js';
|
|
7
|
-
|
|
8
|
-
const RUNTIME_CHECK_TIMEOUT_MS = 1800;
|
|
9
|
-
|
|
10
|
-
export const RUNTIME_DEFINITIONS = {
|
|
11
|
-
node: {
|
|
12
|
-
id: 'node',
|
|
13
|
-
name: 'Node.js',
|
|
14
|
-
commands: ['node'],
|
|
15
|
-
versionArgs: ['--version'],
|
|
16
|
-
installAction: 'Install Node.js 22 or newer and ensure node is available on PATH.',
|
|
17
|
-
},
|
|
18
|
-
npm: {
|
|
19
|
-
id: 'npm',
|
|
20
|
-
name: 'Node package runner',
|
|
21
|
-
commands: ['npm'],
|
|
22
|
-
versionArgs: ['--version'],
|
|
23
|
-
managedRuntimeId: 'npm',
|
|
24
|
-
installAction: 'Install Node.js/npm or let Pixcode prepare its managed Node package runner.',
|
|
25
|
-
},
|
|
26
|
-
php: {
|
|
27
|
-
id: 'php',
|
|
28
|
-
name: 'PHP',
|
|
29
|
-
commands: ['php'],
|
|
30
|
-
versionArgs: ['--version'],
|
|
31
|
-
managedRuntimeId: 'frankenphp',
|
|
32
|
-
installAction: 'Install PHP or let Pixcode prepare its managed PHP runtime.',
|
|
33
|
-
},
|
|
34
|
-
python: {
|
|
35
|
-
id: 'python',
|
|
36
|
-
name: 'Python',
|
|
37
|
-
commands: process.platform === 'win32' ? ['python', 'py'] : ['python3', 'python'],
|
|
38
|
-
versionArgs: ['--version'],
|
|
39
|
-
installAction: 'Install Python 3 and ensure python3 or python is available on PATH.',
|
|
40
|
-
},
|
|
41
|
-
go: {
|
|
42
|
-
id: 'go',
|
|
43
|
-
name: 'Go',
|
|
44
|
-
commands: ['go'],
|
|
45
|
-
versionArgs: ['version'],
|
|
46
|
-
installAction: 'Install Go and ensure go is available on PATH.',
|
|
47
|
-
},
|
|
48
|
-
java: {
|
|
49
|
-
id: 'java',
|
|
50
|
-
name: 'Java',
|
|
51
|
-
commands: ['java'],
|
|
52
|
-
versionArgs: ['-version'],
|
|
53
|
-
installAction: 'Install a JDK and ensure java is available on PATH.',
|
|
54
|
-
},
|
|
55
|
-
rust: {
|
|
56
|
-
id: 'rust',
|
|
57
|
-
name: 'Rust',
|
|
58
|
-
commands: ['cargo', 'rustc'],
|
|
59
|
-
versionArgs: ['--version'],
|
|
60
|
-
installAction: 'Install Rust with rustup and ensure cargo is available on PATH.',
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
function runtimeDiagnostic(definition, status, detail) {
|
|
65
|
-
if (status === 'available') {
|
|
66
|
-
return {
|
|
67
|
-
message: `${definition.name} is available.`,
|
|
68
|
-
action: 'No action needed.',
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (status === 'too_old') {
|
|
73
|
-
return {
|
|
74
|
-
message: `${definition.name} is installed but does not meet the required version.`,
|
|
75
|
-
action: definition.installAction,
|
|
76
|
-
detail,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (status === 'error') {
|
|
81
|
-
return {
|
|
82
|
-
message: `${definition.name} was found but could not be started.`,
|
|
83
|
-
action: definition.installAction,
|
|
84
|
-
detail,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
message: `${definition.name} is not available on this machine.`,
|
|
90
|
-
action: definition.installAction,
|
|
91
|
-
detail,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function normalizeVersion(output) {
|
|
96
|
-
const match = String(output || '').match(/(?:v|version\s*)?(\d+\.\d+\.\d+)/i);
|
|
97
|
-
return match?.[1];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function runVersion(command, args, env) {
|
|
101
|
-
return new Promise((resolve) => {
|
|
102
|
-
let output = '';
|
|
103
|
-
let settled = false;
|
|
104
|
-
const child = spawn(command, args, {
|
|
105
|
-
env,
|
|
106
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
107
|
-
windowsHide: true,
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const finish = (result) => {
|
|
111
|
-
if (settled) return;
|
|
112
|
-
settled = true;
|
|
113
|
-
clearTimeout(timer);
|
|
114
|
-
resolve(result);
|
|
115
|
-
};
|
|
116
|
-
const timer = setTimeout(() => {
|
|
117
|
-
try {
|
|
118
|
-
child.kill();
|
|
119
|
-
} catch {
|
|
120
|
-
// Ignore a raced process exit.
|
|
121
|
-
}
|
|
122
|
-
finish({ ok: false, error: `${command} version check timed out.` });
|
|
123
|
-
}, RUNTIME_CHECK_TIMEOUT_MS);
|
|
124
|
-
|
|
125
|
-
child.stdout.on('data', (chunk) => {
|
|
126
|
-
output += chunk.toString();
|
|
127
|
-
});
|
|
128
|
-
child.stderr.on('data', (chunk) => {
|
|
129
|
-
output += chunk.toString();
|
|
130
|
-
});
|
|
131
|
-
child.on('error', (error) => {
|
|
132
|
-
finish({ ok: false, error: error.message });
|
|
133
|
-
});
|
|
134
|
-
child.on('exit', (code) => {
|
|
135
|
-
finish({
|
|
136
|
-
ok: code === 0,
|
|
137
|
-
output,
|
|
138
|
-
error: code === 0 ? undefined : `${command} exited with code ${code}.`,
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function findExecutableOnDeclaredPath(name, env = process.env) {
|
|
145
|
-
const separator = process.platform === 'win32' ? ';' : ':';
|
|
146
|
-
const extensions = process.platform === 'win32'
|
|
147
|
-
? ['.cmd', '.exe', '.bat', '.ps1', '']
|
|
148
|
-
: [''];
|
|
149
|
-
const pathDirs = (env.PATH || env.Path || '').split(separator).filter(Boolean);
|
|
150
|
-
for (const dir of pathDirs) {
|
|
151
|
-
for (const extension of extensions) {
|
|
152
|
-
const candidate = path.join(dir, `${name}${extension}`);
|
|
153
|
-
try {
|
|
154
|
-
if (candidate && fs.existsSync(candidate)) return candidate;
|
|
155
|
-
} catch {
|
|
156
|
-
// Ignore invalid PATH entries.
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function commandPathForRuntime(id, definition, env, strictPath = false) {
|
|
164
|
-
const spawnEnv = buildCliSpawnEnv(env);
|
|
165
|
-
if (id === 'node') return process.execPath;
|
|
166
|
-
if (id === 'npm') return resolveNpmCommand(spawnEnv);
|
|
167
|
-
|
|
168
|
-
for (const command of definition.commands) {
|
|
169
|
-
const executable = strictPath
|
|
170
|
-
? findExecutableOnDeclaredPath(command, env)
|
|
171
|
-
: findExecutableOnPath(command, spawnEnv);
|
|
172
|
-
if (executable) return executable;
|
|
173
|
-
}
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async function discoverSystemRuntime(id, definition, env, options = {}) {
|
|
178
|
-
const executable = commandPathForRuntime(id, definition, env, Boolean(options.strictPath));
|
|
179
|
-
if (!executable) {
|
|
180
|
-
return {
|
|
181
|
-
id,
|
|
182
|
-
name: definition.name,
|
|
183
|
-
status: 'missing',
|
|
184
|
-
source: 'none',
|
|
185
|
-
installStatus: 'missing',
|
|
186
|
-
diagnostic: runtimeDiagnostic(definition, 'missing'),
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const versionResult = await runVersion(executable, definition.versionArgs, env);
|
|
191
|
-
if (!versionResult.ok) {
|
|
192
|
-
return {
|
|
193
|
-
id,
|
|
194
|
-
name: definition.name,
|
|
195
|
-
status: 'error',
|
|
196
|
-
source: 'system',
|
|
197
|
-
path: executable,
|
|
198
|
-
installStatus: 'installed',
|
|
199
|
-
diagnostic: runtimeDiagnostic(definition, 'error', versionResult.error),
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return {
|
|
204
|
-
id,
|
|
205
|
-
name: definition.name,
|
|
206
|
-
status: 'available',
|
|
207
|
-
source: 'system',
|
|
208
|
-
path: executable,
|
|
209
|
-
version: normalizeVersion(versionResult.output),
|
|
210
|
-
installStatus: 'installed',
|
|
211
|
-
diagnostic: runtimeDiagnostic(definition, 'available'),
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
async function discoverManagedRuntime(id, definition, env, preferManaged) {
|
|
216
|
-
if (!definition.managedRuntimeId || !preferManaged) return null;
|
|
217
|
-
|
|
218
|
-
const managedRuntime = await getManagedRuntimeStatus(definition.managedRuntimeId, {
|
|
219
|
-
env,
|
|
220
|
-
preferManaged: true,
|
|
221
|
-
});
|
|
222
|
-
const available = managedRuntime.status === 'installed' || managedRuntime.status === 'system';
|
|
223
|
-
return {
|
|
224
|
-
id,
|
|
225
|
-
name: definition.name,
|
|
226
|
-
status: available ? 'available' : 'missing',
|
|
227
|
-
source: 'managed',
|
|
228
|
-
path: managedRuntime.executablePath,
|
|
229
|
-
version: managedRuntime.version,
|
|
230
|
-
installStatus: managedRuntime.status,
|
|
231
|
-
installable: managedRuntime.installable,
|
|
232
|
-
managedRuntime,
|
|
233
|
-
diagnostic: runtimeDiagnostic(definition, available ? 'available' : 'missing', managedRuntime.reason),
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export async function discoverRuntime(id, options = {}) {
|
|
238
|
-
const definition = RUNTIME_DEFINITIONS[id];
|
|
239
|
-
if (!definition) {
|
|
240
|
-
return {
|
|
241
|
-
id,
|
|
242
|
-
name: id,
|
|
243
|
-
status: 'unsupported',
|
|
244
|
-
source: 'none',
|
|
245
|
-
installStatus: 'unsupported',
|
|
246
|
-
diagnostic: {
|
|
247
|
-
message: `${id} is not registered in the Pixcode runtime manager.`,
|
|
248
|
-
action: 'Add a runtime definition before using this stack.',
|
|
249
|
-
},
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const env = options.env || process.env;
|
|
254
|
-
const managed = await discoverManagedRuntime(id, definition, env, Boolean(options.preferManaged));
|
|
255
|
-
if (managed) return managed;
|
|
256
|
-
return discoverSystemRuntime(id, definition, env, options);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function isPackageManagerCommand(command) {
|
|
260
|
-
return command === 'npm' || command === 'pnpm' || command === 'yarn' || command === 'bun';
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function runtimeIdForLiveViewCommand(command) {
|
|
264
|
-
if (!command) return null;
|
|
265
|
-
if (isPackageManagerCommand(command.command) || command.packageManager) return 'node';
|
|
266
|
-
if (command.framework === 'PHP' || command.command === 'php') return 'php';
|
|
267
|
-
if (command.framework === 'Django' || command.framework === 'FastAPI' || command.framework === 'Flask') return 'python';
|
|
268
|
-
if (command.framework === 'Go' || command.command === 'go') return 'go';
|
|
269
|
-
if (command.framework === 'Rust' || command.command === 'cargo') return 'rust';
|
|
270
|
-
if (command.framework === 'Java' || command.command === 'java') return 'java';
|
|
271
|
-
return null;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
export async function resolveLiveViewRuntime(command, options = {}) {
|
|
275
|
-
const env = options.env || process.env;
|
|
276
|
-
const runtimeId = runtimeIdForLiveViewCommand(command);
|
|
277
|
-
if (!runtimeId) {
|
|
278
|
-
return {
|
|
279
|
-
available: true,
|
|
280
|
-
reason: 'No dedicated runtime check is required for this Live View command.',
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (runtimeId === 'node') {
|
|
285
|
-
const runtime = await discoverRuntime('node', { env });
|
|
286
|
-
const managedRuntime = await getManagedRuntimeStatus('npm', {
|
|
287
|
-
env,
|
|
288
|
-
preferManaged: Boolean(options.preferManaged),
|
|
289
|
-
});
|
|
290
|
-
return {
|
|
291
|
-
available: true,
|
|
292
|
-
runtime,
|
|
293
|
-
managedRuntime,
|
|
294
|
-
reason: managedRuntime.reason || 'Pixcode will run this project with its managed Node package runner.',
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (runtimeId === 'php') {
|
|
299
|
-
const runtime = await discoverRuntime('php', {
|
|
300
|
-
env,
|
|
301
|
-
preferManaged: Boolean(options.preferManaged),
|
|
302
|
-
});
|
|
303
|
-
return {
|
|
304
|
-
available: Boolean(runtime.managedRuntime?.installable) || runtime.status === 'available',
|
|
305
|
-
runtime,
|
|
306
|
-
managedRuntime: runtime.managedRuntime,
|
|
307
|
-
reason: runtime.managedRuntime?.reason || runtime.diagnostic.message,
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const runtime = await discoverRuntime(runtimeId, { env });
|
|
312
|
-
return {
|
|
313
|
-
available: runtime.status === 'available',
|
|
314
|
-
runtime,
|
|
315
|
-
reason: runtime.status === 'available' ? runtime.diagnostic.message : runtime.diagnostic.action,
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
export const runtimeManager = {
|
|
320
|
-
definitions: RUNTIME_DEFINITIONS,
|
|
321
|
-
discover: discoverRuntime,
|
|
322
|
-
resolveLiveViewRuntime,
|
|
323
|
-
};
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
import { buildCliSpawnEnv, findExecutableOnPath, resolveNpmCommand } from './install-jobs.js';
|
|
6
|
+
import { getManagedRuntimeStatus } from './managed-runtimes.js';
|
|
7
|
+
|
|
8
|
+
const RUNTIME_CHECK_TIMEOUT_MS = 1800;
|
|
9
|
+
|
|
10
|
+
export const RUNTIME_DEFINITIONS = {
|
|
11
|
+
node: {
|
|
12
|
+
id: 'node',
|
|
13
|
+
name: 'Node.js',
|
|
14
|
+
commands: ['node'],
|
|
15
|
+
versionArgs: ['--version'],
|
|
16
|
+
installAction: 'Install Node.js 22 or newer and ensure node is available on PATH.',
|
|
17
|
+
},
|
|
18
|
+
npm: {
|
|
19
|
+
id: 'npm',
|
|
20
|
+
name: 'Node package runner',
|
|
21
|
+
commands: ['npm'],
|
|
22
|
+
versionArgs: ['--version'],
|
|
23
|
+
managedRuntimeId: 'npm',
|
|
24
|
+
installAction: 'Install Node.js/npm or let Pixcode prepare its managed Node package runner.',
|
|
25
|
+
},
|
|
26
|
+
php: {
|
|
27
|
+
id: 'php',
|
|
28
|
+
name: 'PHP',
|
|
29
|
+
commands: ['php'],
|
|
30
|
+
versionArgs: ['--version'],
|
|
31
|
+
managedRuntimeId: 'frankenphp',
|
|
32
|
+
installAction: 'Install PHP or let Pixcode prepare its managed PHP runtime.',
|
|
33
|
+
},
|
|
34
|
+
python: {
|
|
35
|
+
id: 'python',
|
|
36
|
+
name: 'Python',
|
|
37
|
+
commands: process.platform === 'win32' ? ['python', 'py'] : ['python3', 'python'],
|
|
38
|
+
versionArgs: ['--version'],
|
|
39
|
+
installAction: 'Install Python 3 and ensure python3 or python is available on PATH.',
|
|
40
|
+
},
|
|
41
|
+
go: {
|
|
42
|
+
id: 'go',
|
|
43
|
+
name: 'Go',
|
|
44
|
+
commands: ['go'],
|
|
45
|
+
versionArgs: ['version'],
|
|
46
|
+
installAction: 'Install Go and ensure go is available on PATH.',
|
|
47
|
+
},
|
|
48
|
+
java: {
|
|
49
|
+
id: 'java',
|
|
50
|
+
name: 'Java',
|
|
51
|
+
commands: ['java'],
|
|
52
|
+
versionArgs: ['-version'],
|
|
53
|
+
installAction: 'Install a JDK and ensure java is available on PATH.',
|
|
54
|
+
},
|
|
55
|
+
rust: {
|
|
56
|
+
id: 'rust',
|
|
57
|
+
name: 'Rust',
|
|
58
|
+
commands: ['cargo', 'rustc'],
|
|
59
|
+
versionArgs: ['--version'],
|
|
60
|
+
installAction: 'Install Rust with rustup and ensure cargo is available on PATH.',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function runtimeDiagnostic(definition, status, detail) {
|
|
65
|
+
if (status === 'available') {
|
|
66
|
+
return {
|
|
67
|
+
message: `${definition.name} is available.`,
|
|
68
|
+
action: 'No action needed.',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (status === 'too_old') {
|
|
73
|
+
return {
|
|
74
|
+
message: `${definition.name} is installed but does not meet the required version.`,
|
|
75
|
+
action: definition.installAction,
|
|
76
|
+
detail,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (status === 'error') {
|
|
81
|
+
return {
|
|
82
|
+
message: `${definition.name} was found but could not be started.`,
|
|
83
|
+
action: definition.installAction,
|
|
84
|
+
detail,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
message: `${definition.name} is not available on this machine.`,
|
|
90
|
+
action: definition.installAction,
|
|
91
|
+
detail,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function normalizeVersion(output) {
|
|
96
|
+
const match = String(output || '').match(/(?:v|version\s*)?(\d+\.\d+\.\d+)/i);
|
|
97
|
+
return match?.[1];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function runVersion(command, args, env) {
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
let output = '';
|
|
103
|
+
let settled = false;
|
|
104
|
+
const child = spawn(command, args, {
|
|
105
|
+
env,
|
|
106
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
107
|
+
windowsHide: true,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const finish = (result) => {
|
|
111
|
+
if (settled) return;
|
|
112
|
+
settled = true;
|
|
113
|
+
clearTimeout(timer);
|
|
114
|
+
resolve(result);
|
|
115
|
+
};
|
|
116
|
+
const timer = setTimeout(() => {
|
|
117
|
+
try {
|
|
118
|
+
child.kill();
|
|
119
|
+
} catch {
|
|
120
|
+
// Ignore a raced process exit.
|
|
121
|
+
}
|
|
122
|
+
finish({ ok: false, error: `${command} version check timed out.` });
|
|
123
|
+
}, RUNTIME_CHECK_TIMEOUT_MS);
|
|
124
|
+
|
|
125
|
+
child.stdout.on('data', (chunk) => {
|
|
126
|
+
output += chunk.toString();
|
|
127
|
+
});
|
|
128
|
+
child.stderr.on('data', (chunk) => {
|
|
129
|
+
output += chunk.toString();
|
|
130
|
+
});
|
|
131
|
+
child.on('error', (error) => {
|
|
132
|
+
finish({ ok: false, error: error.message });
|
|
133
|
+
});
|
|
134
|
+
child.on('exit', (code) => {
|
|
135
|
+
finish({
|
|
136
|
+
ok: code === 0,
|
|
137
|
+
output,
|
|
138
|
+
error: code === 0 ? undefined : `${command} exited with code ${code}.`,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function findExecutableOnDeclaredPath(name, env = process.env) {
|
|
145
|
+
const separator = process.platform === 'win32' ? ';' : ':';
|
|
146
|
+
const extensions = process.platform === 'win32'
|
|
147
|
+
? ['.cmd', '.exe', '.bat', '.ps1', '']
|
|
148
|
+
: [''];
|
|
149
|
+
const pathDirs = (env.PATH || env.Path || '').split(separator).filter(Boolean);
|
|
150
|
+
for (const dir of pathDirs) {
|
|
151
|
+
for (const extension of extensions) {
|
|
152
|
+
const candidate = path.join(dir, `${name}${extension}`);
|
|
153
|
+
try {
|
|
154
|
+
if (candidate && fs.existsSync(candidate)) return candidate;
|
|
155
|
+
} catch {
|
|
156
|
+
// Ignore invalid PATH entries.
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function commandPathForRuntime(id, definition, env, strictPath = false) {
|
|
164
|
+
const spawnEnv = buildCliSpawnEnv(env);
|
|
165
|
+
if (id === 'node') return process.execPath;
|
|
166
|
+
if (id === 'npm') return resolveNpmCommand(spawnEnv);
|
|
167
|
+
|
|
168
|
+
for (const command of definition.commands) {
|
|
169
|
+
const executable = strictPath
|
|
170
|
+
? findExecutableOnDeclaredPath(command, env)
|
|
171
|
+
: findExecutableOnPath(command, spawnEnv);
|
|
172
|
+
if (executable) return executable;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function discoverSystemRuntime(id, definition, env, options = {}) {
|
|
178
|
+
const executable = commandPathForRuntime(id, definition, env, Boolean(options.strictPath));
|
|
179
|
+
if (!executable) {
|
|
180
|
+
return {
|
|
181
|
+
id,
|
|
182
|
+
name: definition.name,
|
|
183
|
+
status: 'missing',
|
|
184
|
+
source: 'none',
|
|
185
|
+
installStatus: 'missing',
|
|
186
|
+
diagnostic: runtimeDiagnostic(definition, 'missing'),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const versionResult = await runVersion(executable, definition.versionArgs, env);
|
|
191
|
+
if (!versionResult.ok) {
|
|
192
|
+
return {
|
|
193
|
+
id,
|
|
194
|
+
name: definition.name,
|
|
195
|
+
status: 'error',
|
|
196
|
+
source: 'system',
|
|
197
|
+
path: executable,
|
|
198
|
+
installStatus: 'installed',
|
|
199
|
+
diagnostic: runtimeDiagnostic(definition, 'error', versionResult.error),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
id,
|
|
205
|
+
name: definition.name,
|
|
206
|
+
status: 'available',
|
|
207
|
+
source: 'system',
|
|
208
|
+
path: executable,
|
|
209
|
+
version: normalizeVersion(versionResult.output),
|
|
210
|
+
installStatus: 'installed',
|
|
211
|
+
diagnostic: runtimeDiagnostic(definition, 'available'),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async function discoverManagedRuntime(id, definition, env, preferManaged) {
|
|
216
|
+
if (!definition.managedRuntimeId || !preferManaged) return null;
|
|
217
|
+
|
|
218
|
+
const managedRuntime = await getManagedRuntimeStatus(definition.managedRuntimeId, {
|
|
219
|
+
env,
|
|
220
|
+
preferManaged: true,
|
|
221
|
+
});
|
|
222
|
+
const available = managedRuntime.status === 'installed' || managedRuntime.status === 'system';
|
|
223
|
+
return {
|
|
224
|
+
id,
|
|
225
|
+
name: definition.name,
|
|
226
|
+
status: available ? 'available' : 'missing',
|
|
227
|
+
source: 'managed',
|
|
228
|
+
path: managedRuntime.executablePath,
|
|
229
|
+
version: managedRuntime.version,
|
|
230
|
+
installStatus: managedRuntime.status,
|
|
231
|
+
installable: managedRuntime.installable,
|
|
232
|
+
managedRuntime,
|
|
233
|
+
diagnostic: runtimeDiagnostic(definition, available ? 'available' : 'missing', managedRuntime.reason),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export async function discoverRuntime(id, options = {}) {
|
|
238
|
+
const definition = RUNTIME_DEFINITIONS[id];
|
|
239
|
+
if (!definition) {
|
|
240
|
+
return {
|
|
241
|
+
id,
|
|
242
|
+
name: id,
|
|
243
|
+
status: 'unsupported',
|
|
244
|
+
source: 'none',
|
|
245
|
+
installStatus: 'unsupported',
|
|
246
|
+
diagnostic: {
|
|
247
|
+
message: `${id} is not registered in the Pixcode runtime manager.`,
|
|
248
|
+
action: 'Add a runtime definition before using this stack.',
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const env = options.env || process.env;
|
|
254
|
+
const managed = await discoverManagedRuntime(id, definition, env, Boolean(options.preferManaged));
|
|
255
|
+
if (managed) return managed;
|
|
256
|
+
return discoverSystemRuntime(id, definition, env, options);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function isPackageManagerCommand(command) {
|
|
260
|
+
return command === 'npm' || command === 'pnpm' || command === 'yarn' || command === 'bun';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function runtimeIdForLiveViewCommand(command) {
|
|
264
|
+
if (!command) return null;
|
|
265
|
+
if (isPackageManagerCommand(command.command) || command.packageManager) return 'node';
|
|
266
|
+
if (command.framework === 'PHP' || command.command === 'php') return 'php';
|
|
267
|
+
if (command.framework === 'Django' || command.framework === 'FastAPI' || command.framework === 'Flask') return 'python';
|
|
268
|
+
if (command.framework === 'Go' || command.command === 'go') return 'go';
|
|
269
|
+
if (command.framework === 'Rust' || command.command === 'cargo') return 'rust';
|
|
270
|
+
if (command.framework === 'Java' || command.command === 'java') return 'java';
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export async function resolveLiveViewRuntime(command, options = {}) {
|
|
275
|
+
const env = options.env || process.env;
|
|
276
|
+
const runtimeId = runtimeIdForLiveViewCommand(command);
|
|
277
|
+
if (!runtimeId) {
|
|
278
|
+
return {
|
|
279
|
+
available: true,
|
|
280
|
+
reason: 'No dedicated runtime check is required for this Live View command.',
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (runtimeId === 'node') {
|
|
285
|
+
const runtime = await discoverRuntime('node', { env });
|
|
286
|
+
const managedRuntime = await getManagedRuntimeStatus('npm', {
|
|
287
|
+
env,
|
|
288
|
+
preferManaged: Boolean(options.preferManaged),
|
|
289
|
+
});
|
|
290
|
+
return {
|
|
291
|
+
available: true,
|
|
292
|
+
runtime,
|
|
293
|
+
managedRuntime,
|
|
294
|
+
reason: managedRuntime.reason || 'Pixcode will run this project with its managed Node package runner.',
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (runtimeId === 'php') {
|
|
299
|
+
const runtime = await discoverRuntime('php', {
|
|
300
|
+
env,
|
|
301
|
+
preferManaged: Boolean(options.preferManaged),
|
|
302
|
+
});
|
|
303
|
+
return {
|
|
304
|
+
available: Boolean(runtime.managedRuntime?.installable) || runtime.status === 'available',
|
|
305
|
+
runtime,
|
|
306
|
+
managedRuntime: runtime.managedRuntime,
|
|
307
|
+
reason: runtime.managedRuntime?.reason || runtime.diagnostic.message,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const runtime = await discoverRuntime(runtimeId, { env });
|
|
312
|
+
return {
|
|
313
|
+
available: runtime.status === 'available',
|
|
314
|
+
runtime,
|
|
315
|
+
reason: runtime.status === 'available' ? runtime.diagnostic.message : runtime.diagnostic.action,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export const runtimeManager = {
|
|
320
|
+
definitions: RUNTIME_DEFINITIONS,
|
|
321
|
+
discover: discoverRuntime,
|
|
322
|
+
resolveLiveViewRuntime,
|
|
323
|
+
};
|