@pixelbyte-software/pixcode 1.51.7 → 1.51.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 +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-BvQgSoyC.js → index-Gs7C4hZT.js} +70 -70
- 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 +58 -58
- 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/index.js +91 -65
- package/dist-server/server/index.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/hermes-gateway.js +5 -5
- package/dist-server/server/services/public-api-manifest.js +51 -51
- 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 -165
- package/scripts/hermes/pixcode-mcp-server.mjs +1009 -1009
- 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 -426
- 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 -79
- 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 -349
- 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 -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 +283 -283
- package/server/claude-sdk.js +920 -920
- package/server/cli.js +1035 -1035
- 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 +895 -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 +111 -81
- package/server/load-env.js +35 -35
- package/server/middleware/auth.js +155 -155
- 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.ts +100 -100
- 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 -642
- package/server/modules/orchestration/index.ts +101 -101
- 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 +891 -891
- 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 +142 -142
- package/server/routes/codex.js +20 -20
- package/server/routes/commands.js +538 -538
- 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 +1641 -1641
- package/server/routes/live-view.js +387 -387
- package/server/routes/mcp-utils.js +13 -13
- package/server/routes/messages.js +50 -50
- package/server/routes/network.js +117 -117
- package/server/routes/platformization.js +182 -182
- package/server/routes/plugins.js +320 -320
- package/server/routes/production-agent-loop.js +90 -90
- package/server/routes/projects.js +911 -911
- package/server/routes/public-api.js +34 -34
- package/server/routes/qwen.js +27 -27
- package/server/routes/remote.js +50 -50
- 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 -1562
- 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 +773 -773
- 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 -190
- 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
|
@@ -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() {
|
|
@@ -3027,7 +3027,59 @@ function handleShellConnection(ws, request) {
|
|
|
3027
3027
|
let shellProcess = null;
|
|
3028
3028
|
let ptySessionKey = null;
|
|
3029
3029
|
let urlDetectionBuffer = '';
|
|
3030
|
+
let outputBuffer = '';
|
|
3031
|
+
let outputFlushTimer = null;
|
|
3030
3032
|
const announcedAuthUrls = new Set();
|
|
3033
|
+
function flushOutputBuffer() {
|
|
3034
|
+
if (!outputBuffer || !ptySessionKey) {
|
|
3035
|
+
outputFlushTimer = null;
|
|
3036
|
+
return;
|
|
3037
|
+
}
|
|
3038
|
+
const rawData = outputBuffer;
|
|
3039
|
+
outputBuffer = '';
|
|
3040
|
+
outputFlushTimer = null;
|
|
3041
|
+
const session = ptySessionsMap.get(ptySessionKey);
|
|
3042
|
+
if (!session)
|
|
3043
|
+
return;
|
|
3044
|
+
session.updatedAt = Date.now();
|
|
3045
|
+
appendPtySessionBuffer(session, rawData);
|
|
3046
|
+
if (session.ws && session.ws.readyState === WebSocket.OPEN) {
|
|
3047
|
+
let outputData = rawData;
|
|
3048
|
+
const cleanChunk = stripAnsiSequences(rawData);
|
|
3049
|
+
urlDetectionBuffer = `${urlDetectionBuffer}${cleanChunk}`.slice(-SHELL_URL_PARSE_BUFFER_LIMIT);
|
|
3050
|
+
outputData = outputData.replace(/OPEN_URL:\s*(https?:\/\/[^\s\x1b\x07]+)/g, '[INFO] Opening in browser: $1');
|
|
3051
|
+
outputData = hideProviderApprovalChoiceLines(outputData);
|
|
3052
|
+
const emitAuthUrl = (detectedUrl, autoOpen = false) => {
|
|
3053
|
+
const normalizedUrl = normalizeDetectedUrl(detectedUrl);
|
|
3054
|
+
if (!normalizedUrl)
|
|
3055
|
+
return;
|
|
3056
|
+
const isNewUrl = !announcedAuthUrls.has(normalizedUrl);
|
|
3057
|
+
if (isNewUrl) {
|
|
3058
|
+
announcedAuthUrls.add(normalizedUrl);
|
|
3059
|
+
session.ws.send(JSON.stringify({
|
|
3060
|
+
type: 'auth_url',
|
|
3061
|
+
url: normalizedUrl,
|
|
3062
|
+
autoOpen
|
|
3063
|
+
}));
|
|
3064
|
+
}
|
|
3065
|
+
};
|
|
3066
|
+
const normalizedDetectedUrls = extractUrlsFromText(urlDetectionBuffer)
|
|
3067
|
+
.map((url) => normalizeDetectedUrl(url))
|
|
3068
|
+
.filter(Boolean);
|
|
3069
|
+
const dedupedDetectedUrls = Array.from(new Set(normalizedDetectedUrls)).filter((url, _, urls) => !urls.some((otherUrl) => otherUrl !== url && otherUrl.startsWith(url)));
|
|
3070
|
+
dedupedDetectedUrls.forEach((url) => emitAuthUrl(url, false));
|
|
3071
|
+
if (shouldAutoOpenUrlFromOutput(cleanChunk) && dedupedDetectedUrls.length > 0) {
|
|
3072
|
+
const bestUrl = dedupedDetectedUrls.reduce((longest, current) => current.length > longest.length ? current : longest);
|
|
3073
|
+
emitAuthUrl(bestUrl, true);
|
|
3074
|
+
}
|
|
3075
|
+
if (outputData) {
|
|
3076
|
+
session.ws.send(JSON.stringify({
|
|
3077
|
+
type: 'output',
|
|
3078
|
+
data: outputData
|
|
3079
|
+
}));
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3031
3083
|
ws.on('message', async (message) => {
|
|
3032
3084
|
try {
|
|
3033
3085
|
const data = JSON.parse(message);
|
|
@@ -3091,18 +3143,17 @@ function handleShellConnection(ws, request) {
|
|
|
3091
3143
|
initialCommand.includes('codex login') ||
|
|
3092
3144
|
initialCommand.includes('qwen auth') ||
|
|
3093
3145
|
initialCommand.includes('auth login'));
|
|
3094
|
-
//
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
//
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
const providerSuffix = isPlainShell ? '' : `_${provider}`;
|
|
3146
|
+
// Every UI shell instance gets a unique tabId. This guarantees that
|
|
3147
|
+
// multiple tabs of the same provider (e.g. two OpenCode windows) do
|
|
3148
|
+
// not share or overwrite the same PTY session. If the client does not
|
|
3149
|
+
// send a tabId (legacy callers), generate one on the backend so the
|
|
3150
|
+
// key is still unique for this connection.
|
|
3151
|
+
const tabId = typeof data.tabId === 'string' && data.tabId.trim()
|
|
3152
|
+
? data.tabId.trim()
|
|
3153
|
+
: `tab_${crypto.randomUUID()}`;
|
|
3154
|
+
const providerKey = isPlainShell ? 'plain' : provider;
|
|
3104
3155
|
const ownerUserId = request.user?.id ?? request.user?.userId ?? 'anonymous';
|
|
3105
|
-
ptySessionKey = `${ownerUserId}_${projectPath}_${sessionId || '
|
|
3156
|
+
ptySessionKey = `${ownerUserId}_${projectPath}_${providerKey}_${tabId}_${sessionId || 'new'}`;
|
|
3106
3157
|
// Kill any existing login session before starting fresh
|
|
3107
3158
|
if (isLoginCommand) {
|
|
3108
3159
|
const oldSession = ptySessionsMap.get(ptySessionKey);
|
|
@@ -3111,17 +3162,12 @@ function handleShellConnection(ws, request) {
|
|
|
3111
3162
|
}
|
|
3112
3163
|
}
|
|
3113
3164
|
else if (forceNewSession) {
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
else {
|
|
3121
|
-
const killedSessions = killProviderPtySessions(projectPath, provider, ownerUserId);
|
|
3122
|
-
if (killedSessions > 0) {
|
|
3123
|
-
console.log(`🧹 Fresh ${provider} session requested; terminated ${killedSessions} cached PTY session(s).`);
|
|
3124
|
-
}
|
|
3165
|
+
// Only terminate the PTY that belongs to this exact tabId, not
|
|
3166
|
+
// every session for the same provider. This lets users run
|
|
3167
|
+
// multiple OpenCode/Claude/etc. instances side-by-side.
|
|
3168
|
+
const oldSession = ptySessionsMap.get(ptySessionKey);
|
|
3169
|
+
if (oldSession) {
|
|
3170
|
+
terminatePtySession(ptySessionKey, oldSession, `fresh ${isPlainShell ? 'plain shell' : provider} session`);
|
|
3125
3171
|
}
|
|
3126
3172
|
}
|
|
3127
3173
|
const existingSession = (isLoginCommand || forceNewSession) ? null : ptySessionsMap.get(ptySessionKey);
|
|
@@ -3357,6 +3403,7 @@ function handleShellConnection(ws, request) {
|
|
|
3357
3403
|
userId: ownerUserId,
|
|
3358
3404
|
projectPath,
|
|
3359
3405
|
sessionId,
|
|
3406
|
+
tabId,
|
|
3360
3407
|
hermesLaunchId,
|
|
3361
3408
|
provider,
|
|
3362
3409
|
isPlainShell,
|
|
@@ -3373,55 +3420,23 @@ function handleShellConnection(ws, request) {
|
|
|
3373
3420
|
if (terminalStartupInput && !isPlainShell) {
|
|
3374
3421
|
writeTerminalStartupInput(createdSession, terminalStartupInput, 'new provider session', 4500);
|
|
3375
3422
|
}
|
|
3376
|
-
// Handle data output
|
|
3423
|
+
// Handle data output — batch rapid chunks so high-volume CLI
|
|
3424
|
+
// output does not flood the WebSocket with one JSON frame per
|
|
3425
|
+
// keystroke-sized chunk.
|
|
3377
3426
|
shellProcess.onData((data) => {
|
|
3378
|
-
|
|
3379
|
-
if (!
|
|
3380
|
-
|
|
3381
|
-
session.updatedAt = Date.now();
|
|
3382
|
-
appendPtySessionBuffer(session, data);
|
|
3383
|
-
if (session.ws && session.ws.readyState === WebSocket.OPEN) {
|
|
3384
|
-
let outputData = data;
|
|
3385
|
-
const cleanChunk = stripAnsiSequences(data);
|
|
3386
|
-
urlDetectionBuffer = `${urlDetectionBuffer}${cleanChunk}`.slice(-SHELL_URL_PARSE_BUFFER_LIMIT);
|
|
3387
|
-
outputData = outputData.replace(/OPEN_URL:\s*(https?:\/\/[^\s\x1b\x07]+)/g, '[INFO] Opening in browser: $1');
|
|
3388
|
-
outputData = hideProviderApprovalChoiceLines(outputData);
|
|
3389
|
-
const emitAuthUrl = (detectedUrl, autoOpen = false) => {
|
|
3390
|
-
const normalizedUrl = normalizeDetectedUrl(detectedUrl);
|
|
3391
|
-
if (!normalizedUrl)
|
|
3392
|
-
return;
|
|
3393
|
-
const isNewUrl = !announcedAuthUrls.has(normalizedUrl);
|
|
3394
|
-
if (isNewUrl) {
|
|
3395
|
-
announcedAuthUrls.add(normalizedUrl);
|
|
3396
|
-
session.ws.send(JSON.stringify({
|
|
3397
|
-
type: 'auth_url',
|
|
3398
|
-
url: normalizedUrl,
|
|
3399
|
-
autoOpen
|
|
3400
|
-
}));
|
|
3401
|
-
}
|
|
3402
|
-
};
|
|
3403
|
-
const normalizedDetectedUrls = extractUrlsFromText(urlDetectionBuffer)
|
|
3404
|
-
.map((url) => normalizeDetectedUrl(url))
|
|
3405
|
-
.filter(Boolean);
|
|
3406
|
-
// Prefer the most complete URL if shorter prefix variants are also present.
|
|
3407
|
-
const dedupedDetectedUrls = Array.from(new Set(normalizedDetectedUrls)).filter((url, _, urls) => !urls.some((otherUrl) => otherUrl !== url && otherUrl.startsWith(url)));
|
|
3408
|
-
dedupedDetectedUrls.forEach((url) => emitAuthUrl(url, false));
|
|
3409
|
-
if (shouldAutoOpenUrlFromOutput(cleanChunk) && dedupedDetectedUrls.length > 0) {
|
|
3410
|
-
const bestUrl = dedupedDetectedUrls.reduce((longest, current) => current.length > longest.length ? current : longest);
|
|
3411
|
-
emitAuthUrl(bestUrl, true);
|
|
3412
|
-
}
|
|
3413
|
-
// Send regular output
|
|
3414
|
-
if (outputData) {
|
|
3415
|
-
session.ws.send(JSON.stringify({
|
|
3416
|
-
type: 'output',
|
|
3417
|
-
data: outputData
|
|
3418
|
-
}));
|
|
3419
|
-
}
|
|
3427
|
+
outputBuffer += data;
|
|
3428
|
+
if (!outputFlushTimer) {
|
|
3429
|
+
outputFlushTimer = setTimeout(flushOutputBuffer, 8);
|
|
3420
3430
|
}
|
|
3421
3431
|
});
|
|
3422
3432
|
// Handle process exit
|
|
3423
3433
|
shellProcess.onExit((exitCode) => {
|
|
3424
3434
|
console.log('🔚 Shell process exited with code:', exitCode.exitCode, 'signal:', exitCode.signal);
|
|
3435
|
+
if (outputFlushTimer) {
|
|
3436
|
+
clearTimeout(outputFlushTimer);
|
|
3437
|
+
outputFlushTimer = null;
|
|
3438
|
+
}
|
|
3439
|
+
flushOutputBuffer();
|
|
3425
3440
|
const session = ptySessionsMap.get(ptySessionKey);
|
|
3426
3441
|
if (session?.pty && session.pty !== shellProcess) {
|
|
3427
3442
|
console.log('↩️ Ignoring stale PTY exit for replacement session:', ptySessionKey);
|
|
@@ -3517,6 +3532,10 @@ function handleShellConnection(ws, request) {
|
|
|
3517
3532
|
});
|
|
3518
3533
|
ws.on('close', () => {
|
|
3519
3534
|
console.log('🔌 Shell client disconnected');
|
|
3535
|
+
if (outputFlushTimer) {
|
|
3536
|
+
clearTimeout(outputFlushTimer);
|
|
3537
|
+
outputFlushTimer = null;
|
|
3538
|
+
}
|
|
3520
3539
|
if (ptySessionKey) {
|
|
3521
3540
|
const session = ptySessionsMap.get(ptySessionKey);
|
|
3522
3541
|
if (session) {
|
|
@@ -3525,6 +3544,13 @@ function handleShellConnection(ws, request) {
|
|
|
3525
3544
|
session.ws = null;
|
|
3526
3545
|
return;
|
|
3527
3546
|
}
|
|
3547
|
+
// Plain shells are cheap to recreate, so terminate them immediately
|
|
3548
|
+
// instead of keeping a 30-minute zombie PTY around.
|
|
3549
|
+
if (session.isPlainShell) {
|
|
3550
|
+
console.log('🧹 Terminating plain shell PTY on disconnect:', ptySessionKey);
|
|
3551
|
+
terminatePtySession(ptySessionKey, session, 'plain shell disconnect');
|
|
3552
|
+
return;
|
|
3553
|
+
}
|
|
3528
3554
|
console.log('⏳ PTY session kept alive, will timeout in 30 minutes:', ptySessionKey);
|
|
3529
3555
|
session.ws = null;
|
|
3530
3556
|
session.timeoutId = setTimeout(() => {
|