@pixelbyte-software/pixcode 1.35.4 → 1.36.0

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.
Files changed (55) hide show
  1. package/README.de.md +116 -198
  2. package/README.ja.md +116 -192
  3. package/README.ko.md +116 -192
  4. package/README.md +201 -223
  5. package/README.ru.md +116 -198
  6. package/README.tr.md +205 -175
  7. package/README.zh-CN.md +116 -192
  8. package/dist/api-automation.html +110 -0
  9. package/dist/api-docs.html +18 -18
  10. package/dist/assets/index-BzRaZegN.css +32 -0
  11. package/dist/assets/{index-CyxRiNt0.js → index-OkHfhUMk.js} +176 -175
  12. package/dist/docs.html +294 -0
  13. package/dist/features.html +112 -0
  14. package/dist/humans.txt +15 -0
  15. package/dist/index.html +2 -2
  16. package/dist/landing.html +217 -0
  17. package/dist/llms-full.txt +117 -0
  18. package/dist/llms.txt +53 -0
  19. package/dist/openapi.yaml +12 -9
  20. package/dist/orchestration.html +125 -0
  21. package/dist/robots.txt +4 -0
  22. package/dist/site.css +536 -0
  23. package/dist/sitemap.xml +51 -0
  24. package/dist-server/server/cli.js +51 -2
  25. package/dist-server/server/cli.js.map +1 -1
  26. package/dist-server/server/daemon/manager.js +0 -1
  27. package/dist-server/server/daemon/manager.js.map +1 -1
  28. package/dist-server/server/database/db.js +3 -2
  29. package/dist-server/server/database/db.js.map +1 -1
  30. package/dist-server/server/middleware/auth.js +9 -8
  31. package/dist-server/server/middleware/auth.js.map +1 -1
  32. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +156 -32
  33. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -1
  34. package/dist-server/server/modules/providers/provider.routes.js +8 -1
  35. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  36. package/dist-server/server/routes/agent.js +72 -11
  37. package/dist-server/server/routes/agent.js.map +1 -1
  38. package/dist-server/server/services/notification-orchestrator.js +11 -2
  39. package/dist-server/server/services/notification-orchestrator.js.map +1 -1
  40. package/dist-server/server/services/provider-cli-versions.js +142 -0
  41. package/dist-server/server/services/provider-cli-versions.js.map +1 -0
  42. package/dist-server/server/services/startup-update.js +208 -0
  43. package/dist-server/server/services/startup-update.js.map +1 -0
  44. package/package.json +35 -10
  45. package/server/cli.js +58 -3
  46. package/server/daemon/manager.js +0 -1
  47. package/server/database/db.js +3 -2
  48. package/server/middleware/auth.js +9 -8
  49. package/server/modules/orchestration/workflows/workflow-runner.ts +172 -32
  50. package/server/modules/providers/provider.routes.ts +8 -1
  51. package/server/routes/agent.js +75 -10
  52. package/server/services/notification-orchestrator.js +11 -2
  53. package/server/services/provider-cli-versions.js +149 -0
  54. package/server/services/startup-update.js +234 -0
  55. package/dist/assets/index-BwmhA_le.css +0 -32
@@ -0,0 +1,208 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { spawn, spawnSync } from 'node:child_process';
4
+ import { Readable } from 'node:stream';
5
+ const packageName = '@pixelbyte-software/pixcode';
6
+ const registryUrl = `https://registry.npmjs.org/${encodeURIComponent(packageName)}`;
7
+ const startupUpdateAppliedEnv = 'PIXCODE_STARTUP_UPDATE_APPLIED';
8
+ const isTruthyEnv = (value) => /^(1|true|yes|on)$/i.test(String(value || '').trim());
9
+ export function compareVersions(left, right) {
10
+ const a = String(left || '0.0.0').replace(/^v/, '').split('.').map(Number);
11
+ const b = String(right || '0.0.0').replace(/^v/, '').split('.').map(Number);
12
+ for (let i = 0; i < Math.max(a.length, b.length); i += 1) {
13
+ const av = Number.isFinite(a[i]) ? a[i] : 0;
14
+ const bv = Number.isFinite(b[i]) ? b[i] : 0;
15
+ if (av !== bv)
16
+ return av - bv;
17
+ }
18
+ return 0;
19
+ }
20
+ function commandName(name) {
21
+ if (process.platform === 'win32') {
22
+ return name === 'npm' ? 'npm.cmd' : `${name}.exe`;
23
+ }
24
+ return name;
25
+ }
26
+ function runCapture(command, args, options = {}) {
27
+ const result = spawnSync(command, args, {
28
+ cwd: options.cwd,
29
+ env: options.env || process.env,
30
+ encoding: 'utf8',
31
+ shell: false,
32
+ });
33
+ if (result.error)
34
+ throw result.error;
35
+ if (result.status !== 0) {
36
+ throw new Error((result.stderr || result.stdout || `${command} exited with code ${result.status}`).trim());
37
+ }
38
+ return result.stdout.trim();
39
+ }
40
+ function runInherited(command, args, options = {}) {
41
+ return new Promise((resolve, reject) => {
42
+ const child = spawn(command, args, {
43
+ cwd: options.cwd,
44
+ env: options.env || process.env,
45
+ stdio: 'inherit',
46
+ shell: false,
47
+ windowsHide: false,
48
+ });
49
+ child.on('error', reject);
50
+ child.on('close', (code) => {
51
+ if (code === 0) {
52
+ resolve();
53
+ return;
54
+ }
55
+ reject(new Error(`${command} ${args.join(' ')} exited with code ${code}`));
56
+ });
57
+ });
58
+ }
59
+ async function readLatestPackageMetadata() {
60
+ const response = await fetch(registryUrl, { headers: { accept: 'application/json' } });
61
+ if (!response.ok)
62
+ throw new Error(`Registry returned HTTP ${response.status}`);
63
+ const metadata = await response.json();
64
+ const latestVersion = metadata?.['dist-tags']?.latest;
65
+ const latestEntry = latestVersion ? metadata?.versions?.[latestVersion] : null;
66
+ const tarballUrl = latestEntry?.dist?.tarball;
67
+ if (!latestVersion || !tarballUrl) {
68
+ throw new Error('Registry response missing latest version or tarball URL.');
69
+ }
70
+ return { latestVersion, tarballUrl };
71
+ }
72
+ async function installNpmGlobal(latestVersion, color) {
73
+ const npm = commandName('npm');
74
+ color?.info && console.log(`${color.info('[INFO]')} Installing ${packageName}@${latestVersion} globally before opening the port...`);
75
+ await runInherited(npm, ['install', '-g', `${packageName}@${latestVersion}`]);
76
+ }
77
+ async function updateGitCheckout(appRoot, color) {
78
+ const git = commandName('git');
79
+ const npm = commandName('npm');
80
+ const currentBranch = runCapture(git, ['branch', '--show-current'], { cwd: appRoot });
81
+ if (currentBranch !== 'main') {
82
+ return { updated: false, skipped: true, reason: `git checkout is on ${currentBranch || 'detached HEAD'}, not main` };
83
+ }
84
+ const status = runCapture(git, ['status', '--porcelain'], { cwd: appRoot });
85
+ if (status) {
86
+ return { updated: false, skipped: true, reason: 'git checkout has local changes' };
87
+ }
88
+ color?.info && console.log(`${color.info('[INFO]')} Fetching origin/main before opening the port...`);
89
+ await runInherited(git, ['fetch', 'origin', 'main'], { cwd: appRoot });
90
+ const localHead = runCapture(git, ['rev-parse', 'HEAD'], { cwd: appRoot });
91
+ const remoteHead = runCapture(git, ['rev-parse', 'origin/main'], { cwd: appRoot });
92
+ if (localHead === remoteHead) {
93
+ return { updated: false };
94
+ }
95
+ color?.info && console.log(`${color.info('[INFO]')} Pulling latest Pixcode from GitHub before opening the port...`);
96
+ await runInherited(git, ['pull', '--ff-only', 'origin', 'main'], { cwd: appRoot });
97
+ color?.info && console.log(`${color.info('[INFO]')} Reconciling dependencies after git update...`);
98
+ await runInherited(npm, ['install', '--no-audit', '--no-fund'], { cwd: appRoot });
99
+ return { updated: true, version: readPackageVersion(appRoot) };
100
+ }
101
+ function readPackageVersion(appRoot) {
102
+ try {
103
+ const raw = fs.readFileSync(path.join(appRoot, 'package.json'), 'utf8');
104
+ return JSON.parse(raw).version || null;
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ async function extractRuntimeTarball({ runtimeDir, tarballUrl, latestVersion, currentVersion, color }) {
111
+ color?.info && console.log(`${color.info('[INFO]')} Updating runtime ${currentVersion} -> ${latestVersion} before opening the port...`);
112
+ const tarballRes = await fetch(tarballUrl);
113
+ if (!tarballRes.ok || !tarballRes.body) {
114
+ throw new Error(`Tarball fetch failed: HTTP ${tarballRes.status}`);
115
+ }
116
+ const stagingDir = path.join(runtimeDir, '.staging');
117
+ const backupDir = path.join(runtimeDir, '.previous');
118
+ fs.rmSync(stagingDir, { recursive: true, force: true });
119
+ fs.mkdirSync(stagingDir, { recursive: true });
120
+ const tarModule = await import('tar');
121
+ const tarExtract = tarModule.x || tarModule.default?.x;
122
+ if (!tarExtract)
123
+ throw new Error('tar extractor not available');
124
+ await new Promise((resolve, reject) => {
125
+ const nodeStream = typeof Readable.fromWeb === 'function' && tarballRes.body?.getReader
126
+ ? Readable.fromWeb(tarballRes.body)
127
+ : tarballRes.body;
128
+ const extractor = tarExtract({ cwd: stagingDir, strip: 1 });
129
+ nodeStream.pipe(extractor);
130
+ extractor.on('finish', resolve);
131
+ extractor.on('error', reject);
132
+ nodeStream.on('error', reject);
133
+ });
134
+ fs.rmSync(backupDir, { recursive: true, force: true });
135
+ fs.mkdirSync(backupDir, { recursive: true });
136
+ for (const entry of fs.readdirSync(stagingDir)) {
137
+ const src = path.join(stagingDir, entry);
138
+ const dst = path.join(runtimeDir, entry);
139
+ if (fs.existsSync(dst)) {
140
+ fs.renameSync(dst, path.join(backupDir, entry));
141
+ }
142
+ fs.renameSync(src, dst);
143
+ }
144
+ fs.rmSync(stagingDir, { recursive: true, force: true });
145
+ const depsChanged = (() => {
146
+ try {
147
+ const prevPkg = JSON.parse(fs.readFileSync(path.join(backupDir, 'package.json'), 'utf8'));
148
+ const nextPkg = JSON.parse(fs.readFileSync(path.join(runtimeDir, 'package.json'), 'utf8'));
149
+ return JSON.stringify(prevPkg.dependencies || {}) !== JSON.stringify(nextPkg.dependencies || {});
150
+ }
151
+ catch {
152
+ return true;
153
+ }
154
+ })();
155
+ if (depsChanged) {
156
+ color?.info && console.log(`${color.info('[INFO]')} Reconciling runtime node_modules...`);
157
+ await runInherited(commandName('npm'), ['install', '--production', '--no-audit', '--no-fund', '--no-save'], { cwd: runtimeDir });
158
+ }
159
+ }
160
+ export async function runStartupAutoUpdate({ appRoot, currentVersion, installMode, color, } = {}) {
161
+ if (isTruthyEnv(process.env.PIXCODE_DISABLE_STARTUP_UPDATE)) {
162
+ return { updated: false, skipped: true, reason: 'disabled by PIXCODE_DISABLE_STARTUP_UPDATE' };
163
+ }
164
+ if (isTruthyEnv(process.env.PIXCODE_SKIP_UPDATE_CHECK)) {
165
+ return { updated: false, skipped: true, reason: 'disabled by PIXCODE_SKIP_UPDATE_CHECK' };
166
+ }
167
+ if (process.env[startupUpdateAppliedEnv] === '1') {
168
+ return { updated: false, skipped: true, reason: 'already applied in this launch chain' };
169
+ }
170
+ if (!appRoot || !currentVersion) {
171
+ return { updated: false, skipped: true, reason: 'missing app root or current version' };
172
+ }
173
+ try {
174
+ if (installMode === 'git') {
175
+ return await updateGitCheckout(appRoot, color);
176
+ }
177
+ const { latestVersion, tarballUrl } = await readLatestPackageMetadata();
178
+ if (compareVersions(latestVersion, currentVersion) <= 0) {
179
+ return { updated: false, latestVersion };
180
+ }
181
+ if (process.env.PIXCODE_RUNTIME_DIR) {
182
+ await extractRuntimeTarball({
183
+ runtimeDir: process.env.PIXCODE_RUNTIME_DIR,
184
+ tarballUrl,
185
+ latestVersion,
186
+ currentVersion,
187
+ color,
188
+ });
189
+ return { updated: true, version: latestVersion, restartMode: 'exit42' };
190
+ }
191
+ await installNpmGlobal(latestVersion, color);
192
+ return { updated: true, version: latestVersion, restartMode: 'reexec' };
193
+ }
194
+ catch (error) {
195
+ return {
196
+ updated: false,
197
+ failed: true,
198
+ error: error instanceof Error ? error.message : String(error),
199
+ };
200
+ }
201
+ }
202
+ export function startupUpdateReexecEnv() {
203
+ return {
204
+ ...process.env,
205
+ [startupUpdateAppliedEnv]: '1',
206
+ };
207
+ }
208
+ //# sourceMappingURL=startup-update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup-update.js","sourceRoot":"","sources":["../../../server/services/startup-update.js"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pixelbyte-software/pixcode",
3
- "version": "1.35.4",
4
- "description": "Pixcode a desktop and mobile web UI for Claude Code, Cursor CLI, Codex, Gemini CLI, Qwen Code, and OpenCode.",
3
+ "version": "1.36.0",
4
+ "description": "Self-hosted AI coding agent control room for Claude Code, Cursor CLI, OpenAI Codex, Gemini CLI, Qwen Code, and OpenCode with chat, files, shell, Git, orchestration, API keys, Telegram, MCP, plugins, themes, and desktop/server deployment.",
5
5
  "type": "module",
6
6
  "main": "dist-server/server/index.js",
7
7
  "bin": {
@@ -50,23 +50,48 @@
50
50
  "update:platform": "./update-platform.sh"
51
51
  },
52
52
  "keywords": [
53
+ "pixcode",
54
+ "ai coding agent",
55
+ "ai coding assistant",
56
+ "self-hosted ai ide",
57
+ "self-hosted developer tool",
58
+ "coding agent ui",
59
+ "coding agent dashboard",
60
+ "multi-agent orchestration",
61
+ "agent orchestration",
53
62
  "claude code",
54
63
  "claude-code",
55
- "pixcode",
64
+ "claude-code-ui",
65
+ "claude code ui",
66
+ "anthropic",
56
67
  "codex",
57
- "gemini",
58
- "gemini-cli",
68
+ "codex-ui",
69
+ "openai codex",
70
+ "openai-codex",
71
+ "openai",
59
72
  "cursor",
60
73
  "cursor-cli",
74
+ "cursor cli ui",
75
+ "gemini",
76
+ "gemini-cli",
77
+ "gemini cli ui",
78
+ "qwen",
79
+ "qwen-code",
80
+ "qwen code ui",
61
81
  "opencode",
62
82
  "opencode-cli",
63
- "anthropic",
64
- "openai",
83
+ "opencode ui",
65
84
  "google",
66
- "coding-agent",
85
+ "mcp",
86
+ "mcp manager",
87
+ "telegram bot",
88
+ "api automation",
89
+ "git ui",
90
+ "terminal ui",
67
91
  "web-ui",
68
- "ui",
69
- "mobile IDE"
92
+ "desktop app",
93
+ "mobile IDE",
94
+ "yapay zeka kodlama"
70
95
  ],
71
96
  "author": "Pixcode Contributors",
72
97
  "license": "AGPL-3.0-or-later",
package/server/cli.js CHANGED
@@ -18,9 +18,11 @@ import fs from 'fs';
18
18
  import path from 'path';
19
19
  import os from 'os';
20
20
  import net from 'node:net';
21
+ import { spawn } from 'node:child_process';
21
22
 
22
23
  import { findAppRoot, getModuleDir } from './utils/runtime-paths.js';
23
24
  import { buildDaemonCliCommand, handleDaemonCommand, hasInstalledDaemonUnit } from './daemon-manager.js';
25
+ import { runStartupAutoUpdate, startupUpdateReexecEnv } from './services/startup-update.js';
24
26
 
25
27
  const __dirname = getModuleDir(import.meta.url);
26
28
  // The CLI is compiled into dist-server/server, but it still needs to read the top-level
@@ -62,6 +64,7 @@ const c = {
62
64
  // Load package.json for version info
63
65
  const packageJsonPath = path.join(APP_ROOT, 'package.json');
64
66
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
67
+ const installMode = fs.existsSync(path.join(APP_ROOT, '.git')) ? 'git' : 'npm';
65
68
  // Match the runtime fallback in load-env.js so "pixcode status" reports the same default
66
69
  // database location that the backend will actually use when no DATABASE_PATH is configured.
67
70
  const DEFAULT_DATABASE_PATH = path.join(os.homedir(), '.pixcode', 'auth.db');
@@ -640,13 +643,62 @@ async function sandboxCommand(args) {
640
643
 
641
644
  // Start the server
642
645
  async function startServer() {
643
- // Check for updates silently on startup
644
- checkForUpdates(true);
645
-
646
646
  // Import and run the server
647
647
  await import('./index.js');
648
648
  }
649
649
 
650
+ async function reexecAfterStartupUpdate() {
651
+ await new Promise((resolve, reject) => {
652
+ const child = spawn(process.execPath, process.argv.slice(1), {
653
+ cwd: process.cwd(),
654
+ env: startupUpdateReexecEnv(),
655
+ stdio: 'inherit',
656
+ windowsHide: false,
657
+ });
658
+ child.on('error', reject);
659
+ child.on('close', (code, signal) => {
660
+ if (signal) {
661
+ process.kill(process.pid, signal);
662
+ return;
663
+ }
664
+ process.exit(code ?? 0);
665
+ });
666
+ });
667
+ }
668
+
669
+ async function runStartupUpdateGate() {
670
+ const result = await runStartupAutoUpdate({
671
+ appRoot: APP_ROOT,
672
+ currentVersion: packageJson.version,
673
+ installMode,
674
+ color: c,
675
+ });
676
+
677
+ if (result.failed) {
678
+ console.log(`${c.warn('[WARN]')} Startup update check failed: ${result.error}`);
679
+ console.log(`${c.tip('[TIP]')} Continuing with the current version (${packageJson.version}).`);
680
+ return false;
681
+ }
682
+
683
+ if (result.skipped && result.reason && process.env.PIXCODE_DEBUG_STARTUP_UPDATE === '1') {
684
+ console.log(`${c.dim('[INFO]')} Startup update skipped: ${result.reason}`);
685
+ }
686
+
687
+ if (!result.updated) {
688
+ return false;
689
+ }
690
+
691
+ console.log(`${c.ok('[OK]')} Startup update applied${result.version ? ` (${result.version})` : ''}.`);
692
+ if (result.restartMode === 'exit42') {
693
+ console.log(`${c.info('[INFO]')} Restarting through the desktop wrapper before opening the port...`);
694
+ process.exit(42);
695
+ }
696
+
697
+ console.log(`${c.info('[INFO]')} Restarting Pixcode on the updated code before opening the port...`);
698
+ await reexecAfterStartupUpdate();
699
+ return true;
700
+ }
701
+
650
702
  async function isPortOpen(port, timeoutMs = 800) {
651
703
  return await new Promise((resolve) => {
652
704
  const socket = net.createConnection({ host: '127.0.0.1', port: Number(port) });
@@ -888,6 +940,9 @@ async function main() {
888
940
 
889
941
  switch (command) {
890
942
  case 'start':
943
+ if (await runStartupUpdateGate()) {
944
+ break;
945
+ }
891
946
  if (await maybeAutoDaemonStart(options)) {
892
947
  break;
893
948
  }
@@ -394,7 +394,6 @@ export function startDaemon({ nodePath, cliEntryPath, serverPort, databasePath }
394
394
  windowsHide: true,
395
395
  env: {
396
396
  ...process.env,
397
- PIXCODE_SKIP_UPDATE_CHECK: '1',
398
397
  SERVER_PORT: String(resolvedPort),
399
398
  ...(resolvedDatabasePath ? { DATABASE_PATH: resolvedDatabasePath } : {})
400
399
  }
@@ -376,7 +376,7 @@ const userDb = {
376
376
  // API key operations
377
377
  // ---------------------------------------------------------------------------
378
378
  const apiKeysDb = {
379
- generateApiKey: () => 'ck_' + crypto.randomBytes(32).toString('hex'),
379
+ generateApiKey: () => 'px_' + crypto.randomBytes(32).toString('hex'),
380
380
 
381
381
  createApiKey: (userId, keyName) => {
382
382
  const apiKey = apiKeysDb.generateApiKey();
@@ -493,7 +493,7 @@ const credentialsDb = {
493
493
  // ---------------------------------------------------------------------------
494
494
  const DEFAULT_NOTIFICATION_PREFERENCES = {
495
495
  channels: { inApp: false, webPush: false },
496
- events: { actionRequired: true, stop: true, error: true },
496
+ events: { actionRequired: true, stop: true, error: true, updates: true },
497
497
  };
498
498
 
499
499
  const normalizeNotificationPreferences = (value) => {
@@ -507,6 +507,7 @@ const normalizeNotificationPreferences = (value) => {
507
507
  actionRequired: source.events?.actionRequired !== false,
508
508
  stop: source.events?.stop !== false,
509
509
  error: source.events?.error !== false,
510
+ updates: source.events?.updates !== false,
510
511
  },
511
512
  };
512
513
  };
@@ -5,6 +5,7 @@ import { IS_PLATFORM } from '../constants/config.js';
5
5
 
6
6
  // Use env var if set, otherwise auto-generate a unique secret per installation
7
7
  const JWT_SECRET = process.env.JWT_SECRET || appConfigDb.getOrCreateJwtSecret();
8
+ const isPixcodeApiKey = (token) => typeof token === 'string' && (token.startsWith('px_') || token.startsWith('ck_'));
8
9
 
9
10
  // Optional API key middleware
10
11
  const validateApiKey = (req, res, next) => {
@@ -42,9 +43,8 @@ const authenticateToken = async (req, res, next) => {
42
43
  // - X-API-Key: <apikey> (legacy, kept for /api/agent compatibility)
43
44
  // - ?token=<jwt> (EventSource workaround — can't set headers)
44
45
  // - ?apiKey=<apikey> (EventSource workaround)
45
- // Auth-token mode is decided by the prefix: keys generated by Pixcode start
46
- // with `ck_` (see apiKeysDb.generateApiKey) anything else falls through
47
- // to JWT verification.
46
+ // Auth-token mode is decided by the prefix: new keys generated by Pixcode
47
+ // start with `px_`; older `ck_` keys remain valid for existing installs.
48
48
  const authHeader = req.headers['authorization'];
49
49
  const bearerToken = authHeader && authHeader.startsWith('Bearer ') ? authHeader.slice(7).trim() : null;
50
50
  const apiKeyHeader = req.headers['x-api-key'];
@@ -53,8 +53,8 @@ const authenticateToken = async (req, res, next) => {
53
53
 
54
54
  // Try API-key paths first when the credential is unambiguously an API key.
55
55
  const explicitApiKey = apiKeyHeader || queryApiKey
56
- || (bearerToken && bearerToken.startsWith('ck_') ? bearerToken : null)
57
- || (queryToken && queryToken.startsWith('ck_') ? queryToken : null);
56
+ || (isPixcodeApiKey(bearerToken) ? bearerToken : null)
57
+ || (isPixcodeApiKey(queryToken) ? queryToken : null);
58
58
 
59
59
  if (explicitApiKey) {
60
60
  try {
@@ -131,16 +131,17 @@ const authenticateWebSocket = (token) => {
131
131
  }
132
132
  }
133
133
 
134
- // Normal OSS validation — accept either an API key (`ck_…`) or a JWT.
134
+ // Normal OSS validation — accept either an API key (`px_…` or legacy
135
+ // `ck_…`) or a JWT.
135
136
  // Mirrors the REST `authenticateToken` middleware so any tool that has
136
- // a `ck_` key (CI scripts, the api-tester subagent, the user's own
137
+ // a Pixcode API key (CI scripts, the api-tester subagent, the user's own
137
138
  // automation, ...) can also open a WebSocket without first exchanging
138
139
  // the key for a JWT.
139
140
  if (!token) {
140
141
  return null;
141
142
  }
142
143
 
143
- if (typeof token === 'string' && token.startsWith('ck_')) {
144
+ if (isPixcodeApiKey(token)) {
144
145
  try {
145
146
  const user = apiKeysDb.validateApiKey(token);
146
147
  if (!user) return null;