@pixelbyte-software/pixcode 1.54.7 → 1.54.9
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 +418 -418
- 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-D-4VRH1a.js → index-Bm6uAqKU.js} +186 -184
- package/dist/assets/index-Dz1luE0u.css +32 -0
- package/dist/clear-cache.html +85 -85
- package/dist/convert-icons.md +52 -52
- package/dist/docs.html +308 -308
- 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/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/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 +100 -100
- package/dist-server/server/daemon/manager.js +33 -33
- package/dist-server/server/daemon-manager.js +64 -64
- package/dist-server/server/index.js +148 -14
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/projects.js +16 -6
- package/dist-server/server/projects.js.map +1 -1
- package/dist-server/server/routes/auth.js +17 -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 +17 -17
- package/dist-server/server/routes/live-view.js +46 -46
- package/dist-server/server/services/public-api-manifest.js +51 -51
- package/package.json +224 -224
- 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/smoke/backend-resource-bounds.mjs +152 -152
- 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/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/mobile-ux.mjs +76 -76
- 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 +331 -331
- 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 -461
- 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 +298 -298
- package/server/claude-sdk.js +927 -927
- package/server/cli.js +1106 -1106
- 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 +988 -988
- 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 +5659 -5529
- package/server/load-env.js +35 -35
- package/server/middleware/account-lockout.js +112 -112
- package/server/middleware/auth.js +277 -277
- package/server/middleware/rate-limiter.js +87 -87
- 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 -60
- package/server/modules/orchestration/a2a/adapters/json-event.adapter.ts +101 -101
- 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/auth.middleware.ts +29 -29
- package/server/modules/orchestration/a2a/bus.ts +46 -46
- package/server/modules/orchestration/a2a/routes.ts +586 -586
- package/server/modules/orchestration/a2a/task-dispatcher.ts +345 -345
- 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/index.ts +99 -99
- 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 +81 -81
- package/server/modules/orchestration/tasks/orchestration-task.service.ts +201 -201
- 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 +2062 -2062
- 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-sessions.provider.ts +286 -286
- package/server/modules/providers/list/qwen/qwen-auth.provider.ts +146 -146
- package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
- package/server/modules/providers/provider.registry.ts +40 -40
- package/server/modules/providers/provider.routes.ts +982 -982
- 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/tests/mcp.test.ts +293 -293
- package/server/openai-codex.js +468 -468
- package/server/opencode-cli.js +491 -491
- package/server/opencode-response-handler.js +111 -111
- package/server/projects.js +3135 -3125
- package/server/qwen-code-cli.js +410 -410
- package/server/routes/agent.js +1451 -1451
- package/server/routes/auth.js +298 -286
- package/server/routes/codex.js +20 -20
- package/server/routes/commands.js +581 -581
- package/server/routes/cursor.js +61 -61
- package/server/routes/diagnostics.js +44 -44
- package/server/routes/gemini.js +25 -25
- package/server/routes/git.js +1822 -1822
- package/server/routes/live-view.js +434 -434
- package/server/routes/mcp-utils.js +13 -13
- package/server/routes/messages.js +97 -97
- package/server/routes/network.js +143 -143
- package/server/routes/platformization.js +231 -231
- package/server/routes/plugins.js +690 -690
- package/server/routes/production-agent-loop.js +90 -90
- package/server/routes/projects.js +918 -918
- package/server/routes/public-api.js +34 -34
- package/server/routes/qwen.js +27 -27
- package/server/routes/remote.js +56 -56
- package/server/routes/settings.js +321 -321
- package/server/routes/telegram.js +163 -163
- 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 +403 -403
- 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 +1052 -1052
- 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 +181 -181
- package/server/services/qr-login.js +126 -126
- package/server/services/remote-connection.js +127 -127
- package/server/services/runtime-manager.js +323 -323
- package/server/services/startup-update.js +259 -259
- package/server/services/telegram/bot.js +393 -393
- package/server/services/telegram/control-center.js +2453 -2453
- package/server/services/telegram/telegram-gateway.js +314 -314
- package/server/services/telegram/telegram-http-client.js +201 -201
- package/server/services/telegram/translations.js +470 -470
- package/server/services/webhooks.js +216 -216
- package/server/sessionManager.js +225 -225
- package/server/setup-wizard.js +283 -283
- 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 +461 -461
- package/server/utils/plugin-process-manager.js +185 -185
- package/server/utils/port-access.js +227 -227
- package/server/utils/runtime-paths.js +37 -37
- package/server/utils/security-log.js +84 -84
- 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-DvudRU5X.css +0 -32
|
@@ -221,22 +221,22 @@ function buildDaemonServiceUnit({ appRoot, serverPort, databasePath, nodeExecPat
|
|
|
221
221
|
nodeExecPath,
|
|
222
222
|
cliEntry,
|
|
223
223
|
});
|
|
224
|
-
return `[Unit]
|
|
225
|
-
Description=Pixcode Server
|
|
226
|
-
After=network.target
|
|
227
|
-
|
|
228
|
-
[Service]
|
|
229
|
-
Type=simple
|
|
230
|
-
WorkingDirectory=${appRoot}
|
|
231
|
-
ExecStart=${execStart}
|
|
232
|
-
Environment=HOST=0.0.0.0
|
|
233
|
-
Environment=CI=true
|
|
234
|
-
Environment=PIXCODE_DAEMON_MANAGED=1
|
|
235
|
-
Restart=always
|
|
236
|
-
RestartSec=2
|
|
237
|
-
|
|
238
|
-
[Install]
|
|
239
|
-
WantedBy=default.target
|
|
224
|
+
return `[Unit]
|
|
225
|
+
Description=Pixcode Server
|
|
226
|
+
After=network.target
|
|
227
|
+
|
|
228
|
+
[Service]
|
|
229
|
+
Type=simple
|
|
230
|
+
WorkingDirectory=${appRoot}
|
|
231
|
+
ExecStart=${execStart}
|
|
232
|
+
Environment=HOST=0.0.0.0
|
|
233
|
+
Environment=CI=true
|
|
234
|
+
Environment=PIXCODE_DAEMON_MANAGED=1
|
|
235
|
+
Restart=always
|
|
236
|
+
RestartSec=2
|
|
237
|
+
|
|
238
|
+
[Install]
|
|
239
|
+
WantedBy=default.target
|
|
240
240
|
`;
|
|
241
241
|
}
|
|
242
242
|
function resolveFrontendDaemonEntry(appRoot, cliEntry) {
|
|
@@ -277,22 +277,22 @@ function buildFrontendDaemonServiceUnit({ appRoot, frontendPort, nodeExecPath, c
|
|
|
277
277
|
nodeExecPath,
|
|
278
278
|
cliEntry,
|
|
279
279
|
});
|
|
280
|
-
return `[Unit]
|
|
281
|
-
Description=Pixcode Frontend (Vite Dev Server)
|
|
282
|
-
After=network.target
|
|
283
|
-
|
|
284
|
-
[Service]
|
|
285
|
-
Type=simple
|
|
286
|
-
WorkingDirectory=${appRoot}
|
|
287
|
-
ExecStart=${execStart}
|
|
288
|
-
Environment=HOST=0.0.0.0
|
|
289
|
-
Environment=CI=true
|
|
290
|
-
Environment=PIXCODE_DAEMON_MANAGED=1
|
|
291
|
-
Restart=always
|
|
292
|
-
RestartSec=2
|
|
293
|
-
|
|
294
|
-
[Install]
|
|
295
|
-
WantedBy=default.target
|
|
280
|
+
return `[Unit]
|
|
281
|
+
Description=Pixcode Frontend (Vite Dev Server)
|
|
282
|
+
After=network.target
|
|
283
|
+
|
|
284
|
+
[Service]
|
|
285
|
+
Type=simple
|
|
286
|
+
WorkingDirectory=${appRoot}
|
|
287
|
+
ExecStart=${execStart}
|
|
288
|
+
Environment=HOST=0.0.0.0
|
|
289
|
+
Environment=CI=true
|
|
290
|
+
Environment=PIXCODE_DAEMON_MANAGED=1
|
|
291
|
+
Restart=always
|
|
292
|
+
RestartSec=2
|
|
293
|
+
|
|
294
|
+
[Install]
|
|
295
|
+
WantedBy=default.target
|
|
296
296
|
`;
|
|
297
297
|
}
|
|
298
298
|
function normalizeState(value) {
|
|
@@ -489,38 +489,38 @@ function showDaemonHelp(c, context = {}) {
|
|
|
489
489
|
const statusExample = buildDaemonCliCommand({ subcommand: 'status', mode: 'system' }, context);
|
|
490
490
|
const doctorExample = buildDaemonCliCommand({ subcommand: 'doctor', mode: 'auto' }, context);
|
|
491
491
|
const logsExample = buildDaemonCliCommand({ subcommand: 'logs', mode: 'system' }, context);
|
|
492
|
-
console.log(`
|
|
493
|
-
${c.bright('Pixcode Daemon')} - Persistent Linux service manager
|
|
494
|
-
|
|
495
|
-
Usage:
|
|
496
|
-
${usagePrefix} daemon [subcommand] [options]
|
|
497
|
-
|
|
498
|
-
Subcommands:
|
|
499
|
-
${c.bright('install')} Install/update unit, reload daemon, enable and start now
|
|
500
|
-
${c.bright('start')} Start the service
|
|
501
|
-
${c.bright('stop')} Stop the service (temporary; auto-start remains enabled)
|
|
502
|
-
${c.bright('restart')} Restart the service
|
|
503
|
-
${c.bright('status')} Show active/enabled state
|
|
504
|
-
${c.bright('logs')} Show recent service logs
|
|
505
|
-
${c.bright('enable')} Enable auto-start at boot
|
|
506
|
-
${c.bright('disable')} Disable auto-start at boot
|
|
507
|
-
${c.bright('uninstall')} Stop, disable, and remove the service unit
|
|
508
|
-
${c.bright('doctor')} Run diagnostics (bus, linger, units, state, port, logs)
|
|
509
|
-
${c.bright('help')} Show this help
|
|
510
|
-
|
|
511
|
-
Options:
|
|
512
|
-
-p, --port <port> Set service server port (default: 3001)
|
|
513
|
-
--frontend-port <port> Start a separate frontend Vite service on this port (legacy/dev)
|
|
514
|
-
--single-port, --no-frontend
|
|
515
|
-
Serve the built UI from the backend port only (default)
|
|
516
|
-
-m, --mode <mode> Service mode: user | system | auto (default: system)
|
|
517
|
-
--database-path <path> Set service database path
|
|
518
|
-
|
|
519
|
-
Examples:
|
|
520
|
-
$ ${installExample}
|
|
521
|
-
$ ${statusExample}
|
|
522
|
-
$ ${doctorExample}
|
|
523
|
-
$ ${logsExample}
|
|
492
|
+
console.log(`
|
|
493
|
+
${c.bright('Pixcode Daemon')} - Persistent Linux service manager
|
|
494
|
+
|
|
495
|
+
Usage:
|
|
496
|
+
${usagePrefix} daemon [subcommand] [options]
|
|
497
|
+
|
|
498
|
+
Subcommands:
|
|
499
|
+
${c.bright('install')} Install/update unit, reload daemon, enable and start now
|
|
500
|
+
${c.bright('start')} Start the service
|
|
501
|
+
${c.bright('stop')} Stop the service (temporary; auto-start remains enabled)
|
|
502
|
+
${c.bright('restart')} Restart the service
|
|
503
|
+
${c.bright('status')} Show active/enabled state
|
|
504
|
+
${c.bright('logs')} Show recent service logs
|
|
505
|
+
${c.bright('enable')} Enable auto-start at boot
|
|
506
|
+
${c.bright('disable')} Disable auto-start at boot
|
|
507
|
+
${c.bright('uninstall')} Stop, disable, and remove the service unit
|
|
508
|
+
${c.bright('doctor')} Run diagnostics (bus, linger, units, state, port, logs)
|
|
509
|
+
${c.bright('help')} Show this help
|
|
510
|
+
|
|
511
|
+
Options:
|
|
512
|
+
-p, --port <port> Set service server port (default: 3001)
|
|
513
|
+
--frontend-port <port> Start a separate frontend Vite service on this port (legacy/dev)
|
|
514
|
+
--single-port, --no-frontend
|
|
515
|
+
Serve the built UI from the backend port only (default)
|
|
516
|
+
-m, --mode <mode> Service mode: user | system | auto (default: system)
|
|
517
|
+
--database-path <path> Set service database path
|
|
518
|
+
|
|
519
|
+
Examples:
|
|
520
|
+
$ ${installExample}
|
|
521
|
+
$ ${statusExample}
|
|
522
|
+
$ ${doctorExample}
|
|
523
|
+
$ ${logsExample}
|
|
524
524
|
`);
|
|
525
525
|
}
|
|
526
526
|
export function hasInstalledDaemonUnit() {
|
|
@@ -453,10 +453,20 @@ async function runRuntimeDirUpdateJob(job, runtimeDir, latestVersion, tarballUrl
|
|
|
453
453
|
});
|
|
454
454
|
return latestVersion;
|
|
455
455
|
}
|
|
456
|
+
function isNodeVersionSupported() {
|
|
457
|
+
const match = process.version?.match(/^v(\d+)\./);
|
|
458
|
+
if (!match)
|
|
459
|
+
return true; // can't detect, assume ok
|
|
460
|
+
return parseInt(match[1], 10) >= 20;
|
|
461
|
+
}
|
|
456
462
|
async function runCommandUpdateJob(job, updateCommand, updateCwd) {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
463
|
+
if (!isNodeVersionSupported()) {
|
|
464
|
+
const msg = `Node.js ${process.version} is too old. Pixcode requires Node.js 20+. Please upgrade Node.js first.\n`;
|
|
465
|
+
appendUpdateJobLog(job, 'stderr', msg);
|
|
466
|
+
throw new Error(msg.trim());
|
|
467
|
+
}
|
|
468
|
+
const runCommand = (cmd) => new Promise((resolve, reject) => {
|
|
469
|
+
const child = spawn(cmd, {
|
|
460
470
|
cwd: updateCwd,
|
|
461
471
|
env: process.env,
|
|
462
472
|
shell: true,
|
|
@@ -468,15 +478,43 @@ async function runCommandUpdateJob(job, updateCommand, updateCwd) {
|
|
|
468
478
|
}
|
|
469
479
|
catch { /* noop */ }
|
|
470
480
|
child.stdout?.on('data', (data) => appendUpdateJobLog(job, 'stdout', data.toString()));
|
|
471
|
-
|
|
481
|
+
let stderrBuf = '';
|
|
482
|
+
child.stderr?.on('data', (data) => {
|
|
483
|
+
const chunk = data.toString();
|
|
484
|
+
stderrBuf += chunk;
|
|
485
|
+
appendUpdateJobLog(job, 'stderr', chunk);
|
|
486
|
+
});
|
|
472
487
|
child.on('error', reject);
|
|
473
488
|
child.on('close', (code) => {
|
|
474
489
|
if (code === 0)
|
|
475
490
|
resolve();
|
|
476
491
|
else
|
|
477
|
-
reject(
|
|
492
|
+
reject({ code, stderr: stderrBuf });
|
|
478
493
|
});
|
|
479
494
|
});
|
|
495
|
+
appendUpdateJobLog(job, 'meta', `Running: ${updateCommand}\n`);
|
|
496
|
+
try {
|
|
497
|
+
await runCommand(updateCommand);
|
|
498
|
+
}
|
|
499
|
+
catch (err) {
|
|
500
|
+
// On Linux/macOS, retry with sudo if the initial attempt failed with EACCES.
|
|
501
|
+
// npm install -g needs write access to /usr/local/lib/node_modules/,
|
|
502
|
+
// which the running user may not have.
|
|
503
|
+
if (process.platform !== 'win32' && (err.stderr?.includes('EACCES') || err.stderr?.includes('permission denied'))) {
|
|
504
|
+
const sudoCmd = `sudo -n ${updateCommand}`;
|
|
505
|
+
appendUpdateJobLog(job, 'meta', `Permission denied. Retrying with sudo...\n`);
|
|
506
|
+
try {
|
|
507
|
+
await runCommand(sudoCmd);
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
catch (sudoErr) {
|
|
511
|
+
appendUpdateJobLog(job, 'stderr', `Sudo update also failed: ${sudoErr.stderr || sudoErr.code}\n`);
|
|
512
|
+
appendUpdateJobLog(job, 'meta', 'Tip: Run the update manually with: sudo npm install -g @pixelbyte-software/pixcode@latest\n');
|
|
513
|
+
throw new Error(`Update command exited with code ${err.code}`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
throw new Error(`Update command exited with code ${err.code}`);
|
|
517
|
+
}
|
|
480
518
|
}
|
|
481
519
|
function readCurrentPackageVersion() {
|
|
482
520
|
try {
|
|
@@ -1070,6 +1108,10 @@ const FILE_TREE_MAX_ITEMS = Number.parseInt(process.env.PIXCODE_FILE_TREE_MAX_IT
|
|
|
1070
1108
|
const FILE_TREE_MAX_DIRECTORIES = Number.parseInt(process.env.PIXCODE_FILE_TREE_MAX_DIRECTORIES || '', 10) || 1200;
|
|
1071
1109
|
const FILE_TREE_SCAN_MAX_MS = Number.parseInt(process.env.PIXCODE_FILE_TREE_SCAN_MAX_MS || '', 10) || 4000;
|
|
1072
1110
|
const FILE_TREE_MAX_ENTRIES_PER_DIRECTORY = Number.parseInt(process.env.PIXCODE_FILE_TREE_MAX_ENTRIES_PER_DIRECTORY || '', 10) || 1500;
|
|
1111
|
+
const FILE_TREE_MAX_DEPTH_DEFAULT = 5; // was 10, reduced to avoid deep traversal on huge projects
|
|
1112
|
+
const FILE_TREE_CACHE_TTL_MS = 3000; // short-lived cache for rapid successive requests
|
|
1113
|
+
const FILE_TREE_CACHE_MAX_ENTRIES = 50;
|
|
1114
|
+
const fileTreeCache = new Map();
|
|
1073
1115
|
const FILE_TREE_EXCLUDED_ENTRY_NAMES = new Set([
|
|
1074
1116
|
'.cache',
|
|
1075
1117
|
'.git',
|
|
@@ -1606,6 +1648,7 @@ app.get('/health', (req, res) => {
|
|
|
1606
1648
|
timestamp: new Date().toISOString(),
|
|
1607
1649
|
installMode,
|
|
1608
1650
|
version: SERVER_VERSION,
|
|
1651
|
+
nodeVersion: process.version,
|
|
1609
1652
|
pendingRestart: updateState.pendingRestart,
|
|
1610
1653
|
lastAppliedUpdate: updateState.lastAppliedUpdate,
|
|
1611
1654
|
});
|
|
@@ -2319,6 +2362,14 @@ app.post('/api/system/update', authenticateToken, requireAdmin, requireApiScope(
|
|
|
2319
2362
|
console.warn('[update] Registry precheck failed:', (err && err.message) || err);
|
|
2320
2363
|
}
|
|
2321
2364
|
}
|
|
2365
|
+
// Check Node.js version before starting update
|
|
2366
|
+
if (!isNodeVersionSupported()) {
|
|
2367
|
+
send('log', { stream: 'stderr', chunk: `Node.js ${process.version} is too old. Pixcode requires Node.js 20+.\n` });
|
|
2368
|
+
send('log', { stream: 'meta', chunk: 'Please upgrade Node.js and try again.\n' });
|
|
2369
|
+
send('done', { success: false, error: `Node.js ${process.version} is too old. Pixcode requires Node.js 20+. Please upgrade Node.js first.` });
|
|
2370
|
+
endStream();
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2322
2373
|
send('log', { stream: 'meta', chunk: `Running: ${updateCommandLabel}\n` });
|
|
2323
2374
|
// Cross-platform shell invocation. `detached: true` + `unref()` below
|
|
2324
2375
|
// means the install child survives if this server process gets killed
|
|
@@ -2327,7 +2378,7 @@ app.post('/api/system/update', authenticateToken, requireAdmin, requireApiScope(
|
|
|
2327
2378
|
// can segfault or the supervisor kills it). Without detachment, a
|
|
2328
2379
|
// killed parent tears down the npm child too and users end up with
|
|
2329
2380
|
// a half-installed package and no server at all.
|
|
2330
|
-
|
|
2381
|
+
let child = spawn(updateCommand, {
|
|
2331
2382
|
cwd: updateCwd,
|
|
2332
2383
|
env: process.env,
|
|
2333
2384
|
shell: true,
|
|
@@ -2353,7 +2404,9 @@ app.post('/api/system/update', authenticateToken, requireAdmin, requireApiScope(
|
|
|
2353
2404
|
child.stdout?.on('data', (data) => {
|
|
2354
2405
|
send('log', { stream: 'stdout', chunk: data.toString() });
|
|
2355
2406
|
});
|
|
2407
|
+
let stderrBuf = '';
|
|
2356
2408
|
child.stderr?.on('data', (data) => {
|
|
2409
|
+
stderrBuf += data.toString();
|
|
2357
2410
|
send('log', { stream: 'stderr', chunk: data.toString() });
|
|
2358
2411
|
});
|
|
2359
2412
|
child.on('error', (error) => {
|
|
@@ -2363,7 +2416,7 @@ app.post('/api/system/update', authenticateToken, requireAdmin, requireApiScope(
|
|
|
2363
2416
|
send('done', { success: false, error: error.message });
|
|
2364
2417
|
endStream();
|
|
2365
2418
|
});
|
|
2366
|
-
child.on('close', (code) => {
|
|
2419
|
+
child.on('close', async (code) => {
|
|
2367
2420
|
if (ended)
|
|
2368
2421
|
return;
|
|
2369
2422
|
if (clientAborted) {
|
|
@@ -2376,13 +2429,61 @@ app.post('/api/system/update', authenticateToken, requireAdmin, requireApiScope(
|
|
|
2376
2429
|
version: SERVER_VERSION,
|
|
2377
2430
|
message: 'Update completed. Restart the server to apply changes.',
|
|
2378
2431
|
});
|
|
2432
|
+
endStream();
|
|
2433
|
+
return;
|
|
2379
2434
|
}
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2435
|
+
// On Linux/macOS, retry with sudo on EACCES (npm install -g permission error)
|
|
2436
|
+
if (code !== 0 && process.platform !== 'win32' && (stderrBuf.includes('EACCES') || stderrBuf.includes('permission denied'))) {
|
|
2437
|
+
const sudoCmd = `sudo -n ${updateCommand}`;
|
|
2438
|
+
send('log', { stream: 'meta', chunk: 'Permission denied. Retrying with sudo...\n' });
|
|
2439
|
+
try {
|
|
2440
|
+
await new Promise((resolveSudo, rejectSudo) => {
|
|
2441
|
+
let sudoEnded = false;
|
|
2442
|
+
const sudoChild = spawn(sudoCmd, {
|
|
2443
|
+
cwd: updateCwd,
|
|
2444
|
+
env: process.env,
|
|
2445
|
+
shell: true,
|
|
2446
|
+
detached: true,
|
|
2447
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
2448
|
+
});
|
|
2449
|
+
try {
|
|
2450
|
+
sudoChild.unref();
|
|
2451
|
+
}
|
|
2452
|
+
catch { /* noop */ }
|
|
2453
|
+
sudoChild.stdout?.on('data', (d) => send('log', { stream: 'stdout', chunk: d.toString() }));
|
|
2454
|
+
let sudoStderr = '';
|
|
2455
|
+
sudoChild.stderr?.on('data', (d) => { sudoStderr += d.toString(); send('log', { stream: 'stderr', chunk: d.toString() }); });
|
|
2456
|
+
sudoChild.on('error', (e) => { if (!sudoEnded) {
|
|
2457
|
+
sudoEnded = true;
|
|
2458
|
+
rejectSudo(e);
|
|
2459
|
+
} });
|
|
2460
|
+
sudoChild.on('close', (sudoCode) => {
|
|
2461
|
+
if (sudoEnded)
|
|
2462
|
+
return;
|
|
2463
|
+
sudoEnded = true;
|
|
2464
|
+
if (sudoCode === 0)
|
|
2465
|
+
resolveSudo();
|
|
2466
|
+
else
|
|
2467
|
+
rejectSudo(new Error(`Sudo update exited with code ${sudoCode}`));
|
|
2468
|
+
});
|
|
2469
|
+
});
|
|
2470
|
+
send('done', {
|
|
2471
|
+
success: true,
|
|
2472
|
+
version: SERVER_VERSION,
|
|
2473
|
+
message: 'Update completed (with sudo). Restart the server to apply changes.',
|
|
2474
|
+
});
|
|
2475
|
+
endStream();
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
catch (sudoErr) {
|
|
2479
|
+
send('log', { stream: 'stderr', chunk: `Sudo update failed: ${sudoErr.message}\n` });
|
|
2480
|
+
send('log', { stream: 'meta', chunk: 'Tip: Run the update manually with: sudo npm install -g @pixelbyte-software/pixcode@latest\n' });
|
|
2481
|
+
}
|
|
2385
2482
|
}
|
|
2483
|
+
send('done', {
|
|
2484
|
+
success: false,
|
|
2485
|
+
error: `Update command exited with code ${code}`,
|
|
2486
|
+
});
|
|
2386
2487
|
endStream();
|
|
2387
2488
|
});
|
|
2388
2489
|
});
|
|
@@ -2867,7 +2968,7 @@ app.get('/api/projects/:projectName/files', authenticateToken, requireProjectAcc
|
|
|
2867
2968
|
catch (e) {
|
|
2868
2969
|
return res.status(404).json({ error: `Project path not found: ${actualPath}` });
|
|
2869
2970
|
}
|
|
2870
|
-
const files = await getFileTree(actualPath,
|
|
2971
|
+
const files = await getFileTree(actualPath, FILE_TREE_MAX_DEPTH_DEFAULT, 0, true);
|
|
2871
2972
|
res.json(filterFileTreeForUser(files, req.user, {
|
|
2872
2973
|
name: req.params.projectName,
|
|
2873
2974
|
projectName: req.params.projectName,
|
|
@@ -4697,6 +4798,26 @@ function permToRwx(perm) {
|
|
|
4697
4798
|
const x = perm & 1 ? 'x' : '-';
|
|
4698
4799
|
return r + w + x;
|
|
4699
4800
|
}
|
|
4801
|
+
// File tree result cache (keyed by path:depth:showHidden, TTL 3s)
|
|
4802
|
+
function readFileTreeCache(cacheKey) {
|
|
4803
|
+
const entry = fileTreeCache.get(cacheKey);
|
|
4804
|
+
if (!entry || entry.expiresAt <= Date.now()) {
|
|
4805
|
+
if (entry)
|
|
4806
|
+
fileTreeCache.delete(cacheKey);
|
|
4807
|
+
// Prune stale entries
|
|
4808
|
+
if (fileTreeCache.size > FILE_TREE_CACHE_MAX_ENTRIES) {
|
|
4809
|
+
const keys = [...fileTreeCache.keys()];
|
|
4810
|
+
for (const k of keys.slice(0, keys.length - FILE_TREE_CACHE_MAX_ENTRIES)) {
|
|
4811
|
+
fileTreeCache.delete(k);
|
|
4812
|
+
}
|
|
4813
|
+
}
|
|
4814
|
+
return undefined;
|
|
4815
|
+
}
|
|
4816
|
+
return entry.tree;
|
|
4817
|
+
}
|
|
4818
|
+
function writeFileTreeCache(cacheKey, tree) {
|
|
4819
|
+
fileTreeCache.set(cacheKey, { tree, expiresAt: Date.now() + FILE_TREE_CACHE_TTL_MS });
|
|
4820
|
+
}
|
|
4700
4821
|
function createFileTreeScanContext() {
|
|
4701
4822
|
return {
|
|
4702
4823
|
startedAt: Date.now(),
|
|
@@ -4752,6 +4873,13 @@ async function readDirectoryEntriesBounded(dirPath, context) {
|
|
|
4752
4873
|
return entries;
|
|
4753
4874
|
}
|
|
4754
4875
|
async function getFileTree(dirPath, maxDepth = 3, currentDepth = 0, showHidden = true, scanContext = null) {
|
|
4876
|
+
// Check cache on top-level call
|
|
4877
|
+
if (currentDepth === 0 && !scanContext) {
|
|
4878
|
+
const cacheKey = `${path.resolve(dirPath)}:${maxDepth}:${showHidden}`;
|
|
4879
|
+
const cached = readFileTreeCache(cacheKey);
|
|
4880
|
+
if (cached)
|
|
4881
|
+
return cached;
|
|
4882
|
+
}
|
|
4755
4883
|
const context = scanContext || createFileTreeScanContext();
|
|
4756
4884
|
const items = [];
|
|
4757
4885
|
if (!hasFileTreeBudget(context)) {
|
|
@@ -4798,12 +4926,18 @@ async function getFileTree(dirPath, maxDepth = 3, currentDepth = 0, showHidden =
|
|
|
4798
4926
|
}
|
|
4799
4927
|
items.push(item);
|
|
4800
4928
|
}
|
|
4801
|
-
|
|
4929
|
+
const sorted = items.sort((a, b) => {
|
|
4802
4930
|
if (a.type !== b.type) {
|
|
4803
4931
|
return a.type === 'directory' ? -1 : 1;
|
|
4804
4932
|
}
|
|
4805
4933
|
return a.name.localeCompare(b.name);
|
|
4806
4934
|
});
|
|
4935
|
+
// Store in cache on top-level call
|
|
4936
|
+
if (currentDepth === 0 && !scanContext) {
|
|
4937
|
+
const cacheKey = `${path.resolve(dirPath)}:${maxDepth}:${showHidden}`;
|
|
4938
|
+
writeFileTreeCache(cacheKey, sorted);
|
|
4939
|
+
}
|
|
4940
|
+
return sorted;
|
|
4807
4941
|
}
|
|
4808
4942
|
const SERVER_PORT = process.env.SERVER_PORT || 3001;
|
|
4809
4943
|
const HOST = process.env.HOST || '0.0.0.0';
|