@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.
- package/README.de.md +116 -198
- package/README.ja.md +116 -192
- package/README.ko.md +116 -192
- package/README.md +201 -223
- package/README.ru.md +116 -198
- package/README.tr.md +205 -175
- package/README.zh-CN.md +116 -192
- package/dist/api-automation.html +110 -0
- package/dist/api-docs.html +18 -18
- package/dist/assets/index-BzRaZegN.css +32 -0
- package/dist/assets/{index-CyxRiNt0.js → index-OkHfhUMk.js} +176 -175
- package/dist/docs.html +294 -0
- package/dist/features.html +112 -0
- package/dist/humans.txt +15 -0
- package/dist/index.html +2 -2
- package/dist/landing.html +217 -0
- package/dist/llms-full.txt +117 -0
- package/dist/llms.txt +53 -0
- package/dist/openapi.yaml +12 -9
- package/dist/orchestration.html +125 -0
- package/dist/robots.txt +4 -0
- package/dist/site.css +536 -0
- package/dist/sitemap.xml +51 -0
- package/dist-server/server/cli.js +51 -2
- package/dist-server/server/cli.js.map +1 -1
- package/dist-server/server/daemon/manager.js +0 -1
- package/dist-server/server/daemon/manager.js.map +1 -1
- package/dist-server/server/database/db.js +3 -2
- package/dist-server/server/database/db.js.map +1 -1
- package/dist-server/server/middleware/auth.js +9 -8
- package/dist-server/server/middleware/auth.js.map +1 -1
- package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +156 -32
- package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +8 -1
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/routes/agent.js +72 -11
- package/dist-server/server/routes/agent.js.map +1 -1
- package/dist-server/server/services/notification-orchestrator.js +11 -2
- package/dist-server/server/services/notification-orchestrator.js.map +1 -1
- package/dist-server/server/services/provider-cli-versions.js +142 -0
- package/dist-server/server/services/provider-cli-versions.js.map +1 -0
- package/dist-server/server/services/startup-update.js +208 -0
- package/dist-server/server/services/startup-update.js.map +1 -0
- package/package.json +35 -10
- package/server/cli.js +58 -3
- package/server/daemon/manager.js +0 -1
- package/server/database/db.js +3 -2
- package/server/middleware/auth.js +9 -8
- package/server/modules/orchestration/workflows/workflow-runner.ts +172 -32
- package/server/modules/providers/provider.routes.ts +8 -1
- package/server/routes/agent.js +75 -10
- package/server/services/notification-orchestrator.js +11 -2
- package/server/services/provider-cli-versions.js +149 -0
- package/server/services/startup-update.js +234 -0
- 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.
|
|
4
|
-
"description": "
|
|
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
|
-
"
|
|
64
|
+
"claude-code-ui",
|
|
65
|
+
"claude code ui",
|
|
66
|
+
"anthropic",
|
|
56
67
|
"codex",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
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
|
-
"
|
|
64
|
-
"openai",
|
|
83
|
+
"opencode ui",
|
|
65
84
|
"google",
|
|
66
|
-
"
|
|
85
|
+
"mcp",
|
|
86
|
+
"mcp manager",
|
|
87
|
+
"telegram bot",
|
|
88
|
+
"api automation",
|
|
89
|
+
"git ui",
|
|
90
|
+
"terminal ui",
|
|
67
91
|
"web-ui",
|
|
68
|
-
"
|
|
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
|
}
|
package/server/daemon/manager.js
CHANGED
|
@@ -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
|
}
|
package/server/database/db.js
CHANGED
|
@@ -376,7 +376,7 @@ const userDb = {
|
|
|
376
376
|
// API key operations
|
|
377
377
|
// ---------------------------------------------------------------------------
|
|
378
378
|
const apiKeysDb = {
|
|
379
|
-
generateApiKey: () => '
|
|
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
|
|
46
|
-
// with `ck_`
|
|
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
|
|
57
|
-
|| (queryToken
|
|
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 (`
|
|
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
|
|
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 (
|
|
144
|
+
if (isPixcodeApiKey(token)) {
|
|
144
145
|
try {
|
|
145
146
|
const user = apiKeysDb.validateApiKey(token);
|
|
146
147
|
if (!user) return null;
|