@pixelbyte-software/pixcode 1.33.6 → 1.33.8

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 (36) hide show
  1. package/dist/assets/index-B1ghfb4w.css +32 -0
  2. package/dist/assets/{index-D6ErCuvV.js → index-JU38YIxa.js} +148 -148
  3. package/dist/favicon.svg +8 -8
  4. package/dist/icons/icon-128x128.svg +9 -9
  5. package/dist/icons/icon-144x144.svg +9 -9
  6. package/dist/icons/icon-152x152.svg +9 -9
  7. package/dist/icons/icon-192x192.svg +9 -9
  8. package/dist/icons/icon-384x384.svg +9 -9
  9. package/dist/icons/icon-512x512.svg +9 -9
  10. package/dist/icons/icon-72x72.svg +9 -9
  11. package/dist/icons/icon-96x96.svg +9 -9
  12. package/dist/icons/icon-template.svg +9 -9
  13. package/dist/index.html +2 -2
  14. package/dist/logo.svg +12 -12
  15. package/package.json +1 -1
  16. package/server/database/db.js +794 -794
  17. package/server/database/json-store.js +194 -194
  18. package/server/modules/providers/list/opencode/opencode-auth.provider.ts +130 -130
  19. package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
  20. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +193 -193
  21. package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
  22. package/server/modules/providers/list/qwen/qwen-auth.provider.ts +145 -145
  23. package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
  24. package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +218 -218
  25. package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
  26. package/server/modules/providers/shared/provider-configs.ts +142 -142
  27. package/server/qwen-code-cli.js +395 -395
  28. package/server/qwen-response-handler.js +73 -73
  29. package/server/routes/qwen.js +27 -27
  30. package/server/services/external-access.js +171 -171
  31. package/server/services/provider-credentials.js +155 -155
  32. package/server/services/provider-models.js +381 -381
  33. package/server/services/telegram/telegram-http-client.js +130 -130
  34. package/server/services/vapid-keys.js +36 -36
  35. package/server/utils/port-access.js +209 -209
  36. package/dist/assets/index-cWbTlXsr.css +0 -32
@@ -1,209 +1,209 @@
1
- import os from 'os';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import readline from 'readline';
5
- import { execSync } from 'child_process';
6
-
7
- import { c } from './colors.js';
8
-
9
- /**
10
- * Tracks inbound port access decisions across runs so the server doesn't
11
- * re-prompt the user (on Windows/macOS) every start, and can skip work on
12
- * Linux where a rule has already been applied.
13
- */
14
- const STATE_FILE = path.join(os.homedir(), '.pixcode', 'port-access.json');
15
-
16
- function loadState() {
17
- try {
18
- return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
19
- } catch {
20
- return {};
21
- }
22
- }
23
-
24
- function saveState(state) {
25
- try {
26
- fs.mkdirSync(path.dirname(STATE_FILE), { recursive: true });
27
- fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
28
- } catch {
29
- // Persisting the decision is a nice-to-have; failure shouldn't block start.
30
- }
31
- }
32
-
33
- /** Return all non-loopback IPv4 addresses assigned to this host. */
34
- export function getLanIps() {
35
- const ifs = os.networkInterfaces();
36
- const ips = [];
37
- for (const name of Object.keys(ifs)) {
38
- for (const ni of ifs[name] || []) {
39
- if (ni.family === 'IPv4' && !ni.internal) ips.push(ni.address);
40
- }
41
- }
42
- return ips;
43
- }
44
-
45
- function askYN(question) {
46
- return new Promise((resolve) => {
47
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
48
- resolve(null); // headless / daemon context — skip
49
- return;
50
- }
51
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
52
- rl.question(question, (answer) => {
53
- rl.close();
54
- const normalized = answer.trim().toLowerCase();
55
- resolve(['y', 'yes', 'e', 'evet'].includes(normalized));
56
- });
57
- });
58
- }
59
-
60
- // ---------------- Linux ----------------
61
-
62
- function tryUfw(port) {
63
- try {
64
- execSync('command -v ufw', { stdio: 'pipe' });
65
- const status = execSync('ufw status', { stdio: 'pipe', encoding: 'utf8' });
66
- // UFW inactive = no rule needed; the port is already reachable.
67
- if (!/active/i.test(status)) return 'inactive';
68
- execSync(`sudo -n ufw allow ${port}/tcp`, { stdio: 'pipe' });
69
- return 'applied';
70
- } catch {
71
- return null;
72
- }
73
- }
74
-
75
- function tryFirewalld(port) {
76
- try {
77
- execSync('command -v firewall-cmd', { stdio: 'pipe' });
78
- const state = execSync('firewall-cmd --state', { stdio: 'pipe', encoding: 'utf8' });
79
- if (!/running/i.test(state)) return 'inactive';
80
- execSync(`sudo -n firewall-cmd --add-port=${port}/tcp --permanent`, { stdio: 'pipe' });
81
- execSync('sudo -n firewall-cmd --reload', { stdio: 'pipe' });
82
- return 'applied';
83
- } catch {
84
- return null;
85
- }
86
- }
87
-
88
- // ---------------- Windows ----------------
89
-
90
- function applyWindowsRule(port) {
91
- const ruleName = `Pixcode-${port}`;
92
- const cmd = `netsh advfirewall firewall add rule name="${ruleName}" dir=in action=allow protocol=TCP localport=${port}`;
93
- try {
94
- execSync(cmd, { stdio: 'pipe' });
95
- return { ok: true, cmd, ruleName };
96
- } catch (error) {
97
- return { ok: false, cmd, ruleName, error: error.message };
98
- }
99
- }
100
-
101
- // ---------------- macOS ----------------
102
-
103
- function macFirewallHint(port) {
104
- return [
105
- `${c.tip('[TIP]')} macOS Application Firewall is per-app, not per-port.`,
106
- ' If other devices can\'t connect, open:',
107
- ' System Settings > Network > Firewall > Options',
108
- ` and add Node.js to "Allow incoming connections" (port ${port}).`,
109
- ].join('\n');
110
- }
111
-
112
- // ---------------- Main entry ----------------
113
-
114
- /**
115
- * Make sure inbound traffic can reach `port` from the local network.
116
- *
117
- * - Linux: silently try ufw/firewalld with `sudo -n` (passwordless). Skips
118
- * cleanly when no firewall is running or sudo is gated — LAN access
119
- * already works on most desktop distros.
120
- * - Windows/macOS: ask the user once; remember the decision in
121
- * ~/.pixcode/port-access.json so subsequent starts stay quiet.
122
- *
123
- * All failure paths are non-fatal: the server is already listening when
124
- * we get here, and LAN clients on the same subnet often can reach it
125
- * without any firewall change.
126
- */
127
- export async function ensurePortOpen(port) {
128
- const state = loadState();
129
- const key = `port:${port}`;
130
- const entry = state[key];
131
-
132
- const lanIps = getLanIps();
133
- if (lanIps.length) {
134
- console.log(`${c.info('[INFO]')} LAN access: ${c.bright(`http://${lanIps[0]}:${port}`)}`);
135
- if (lanIps.length > 1) {
136
- for (const extra of lanIps.slice(1)) {
137
- console.log(`${c.dim(' also:')} http://${extra}:${port}`);
138
- }
139
- }
140
- }
141
-
142
- if (entry && entry.decision === 'deny') {
143
- console.log(`${c.dim('[INFO]')} Firewall prompt suppressed (previously declined). Re-enable via ~/.pixcode/port-access.json`);
144
- return;
145
- }
146
-
147
- const platform = process.platform;
148
-
149
- if (platform === 'linux') {
150
- if (entry && entry.status === 'applied') return;
151
- const result = tryUfw(port) || tryFirewalld(port);
152
- if (result === 'applied') {
153
- console.log(`${c.ok('[OK]')} Inbound firewall rule added for port ${port}.`);
154
- saveState({ ...state, [key]: { decision: 'allow', status: 'applied', via: 'linux' } });
155
- } else if (result === 'inactive') {
156
- console.log(`${c.dim('[INFO]')} No active firewall detected — port ${port} should be reachable.`);
157
- } else {
158
- console.log(`${c.tip('[TIP]')} Couldn't auto-open port (no sudo / unsupported firewall).`);
159
- console.log(` Manual: ${c.bright(`sudo ufw allow ${port}/tcp`)} ${c.dim('(or firewall-cmd equivalent)')}`);
160
- }
161
- return;
162
- }
163
-
164
- if (platform === 'win32') {
165
- if (entry && entry.status === 'applied') return;
166
- const approved = await askYN(
167
- `${c.tip('[?]')} Open port ${port} in Windows Firewall so other devices on your network can connect? [y/N] `,
168
- );
169
- if (approved === null) {
170
- // No TTY — just show the manual command and move on.
171
- console.log(
172
- `${c.tip('[TIP]')} To allow LAN access, run this in an elevated PowerShell:\n ${c.bright(
173
- `netsh advfirewall firewall add rule name="Pixcode-${port}" dir=in action=allow protocol=TCP localport=${port}`,
174
- )}`,
175
- );
176
- return;
177
- }
178
- if (!approved) {
179
- console.log(`${c.dim('[INFO]')} Skipping firewall change.`);
180
- saveState({ ...state, [key]: { decision: 'deny' } });
181
- return;
182
- }
183
- const result = applyWindowsRule(port);
184
- if (result.ok) {
185
- console.log(`${c.ok('[OK]')} Firewall rule "${result.ruleName}" added.`);
186
- saveState({ ...state, [key]: { decision: 'allow', status: 'applied', via: 'windows' } });
187
- } else {
188
- console.log(`${c.tip('[TIP]')} Adding the rule needs Administrator. Run this in an elevated PowerShell:`);
189
- console.log(` ${c.bright(result.cmd)}`);
190
- saveState({ ...state, [key]: { decision: 'allow', status: 'manual' } });
191
- }
192
- return;
193
- }
194
-
195
- if (platform === 'darwin') {
196
- if (entry && entry.status) return;
197
- const approved = await askYN(
198
- `${c.tip('[?]')} Allow inbound connections on port ${port} through macOS firewall? [y/N] `,
199
- );
200
- if (approved === null) return;
201
- if (!approved) {
202
- console.log(`${c.dim('[INFO]')} Skipping firewall hint.`);
203
- saveState({ ...state, [key]: { decision: 'deny' } });
204
- return;
205
- }
206
- console.log(macFirewallHint(port));
207
- saveState({ ...state, [key]: { decision: 'allow', status: 'manual', via: 'macos' } });
208
- }
209
- }
1
+ import os from 'os';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import readline from 'readline';
5
+ import { execSync } from 'child_process';
6
+
7
+ import { c } from './colors.js';
8
+
9
+ /**
10
+ * Tracks inbound port access decisions across runs so the server doesn't
11
+ * re-prompt the user (on Windows/macOS) every start, and can skip work on
12
+ * Linux where a rule has already been applied.
13
+ */
14
+ const STATE_FILE = path.join(os.homedir(), '.pixcode', 'port-access.json');
15
+
16
+ function loadState() {
17
+ try {
18
+ return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
19
+ } catch {
20
+ return {};
21
+ }
22
+ }
23
+
24
+ function saveState(state) {
25
+ try {
26
+ fs.mkdirSync(path.dirname(STATE_FILE), { recursive: true });
27
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
28
+ } catch {
29
+ // Persisting the decision is a nice-to-have; failure shouldn't block start.
30
+ }
31
+ }
32
+
33
+ /** Return all non-loopback IPv4 addresses assigned to this host. */
34
+ export function getLanIps() {
35
+ const ifs = os.networkInterfaces();
36
+ const ips = [];
37
+ for (const name of Object.keys(ifs)) {
38
+ for (const ni of ifs[name] || []) {
39
+ if (ni.family === 'IPv4' && !ni.internal) ips.push(ni.address);
40
+ }
41
+ }
42
+ return ips;
43
+ }
44
+
45
+ function askYN(question) {
46
+ return new Promise((resolve) => {
47
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
48
+ resolve(null); // headless / daemon context — skip
49
+ return;
50
+ }
51
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
52
+ rl.question(question, (answer) => {
53
+ rl.close();
54
+ const normalized = answer.trim().toLowerCase();
55
+ resolve(['y', 'yes', 'e', 'evet'].includes(normalized));
56
+ });
57
+ });
58
+ }
59
+
60
+ // ---------------- Linux ----------------
61
+
62
+ function tryUfw(port) {
63
+ try {
64
+ execSync('command -v ufw', { stdio: 'pipe' });
65
+ const status = execSync('ufw status', { stdio: 'pipe', encoding: 'utf8' });
66
+ // UFW inactive = no rule needed; the port is already reachable.
67
+ if (!/active/i.test(status)) return 'inactive';
68
+ execSync(`sudo -n ufw allow ${port}/tcp`, { stdio: 'pipe' });
69
+ return 'applied';
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+
75
+ function tryFirewalld(port) {
76
+ try {
77
+ execSync('command -v firewall-cmd', { stdio: 'pipe' });
78
+ const state = execSync('firewall-cmd --state', { stdio: 'pipe', encoding: 'utf8' });
79
+ if (!/running/i.test(state)) return 'inactive';
80
+ execSync(`sudo -n firewall-cmd --add-port=${port}/tcp --permanent`, { stdio: 'pipe' });
81
+ execSync('sudo -n firewall-cmd --reload', { stdio: 'pipe' });
82
+ return 'applied';
83
+ } catch {
84
+ return null;
85
+ }
86
+ }
87
+
88
+ // ---------------- Windows ----------------
89
+
90
+ function applyWindowsRule(port) {
91
+ const ruleName = `Pixcode-${port}`;
92
+ const cmd = `netsh advfirewall firewall add rule name="${ruleName}" dir=in action=allow protocol=TCP localport=${port}`;
93
+ try {
94
+ execSync(cmd, { stdio: 'pipe' });
95
+ return { ok: true, cmd, ruleName };
96
+ } catch (error) {
97
+ return { ok: false, cmd, ruleName, error: error.message };
98
+ }
99
+ }
100
+
101
+ // ---------------- macOS ----------------
102
+
103
+ function macFirewallHint(port) {
104
+ return [
105
+ `${c.tip('[TIP]')} macOS Application Firewall is per-app, not per-port.`,
106
+ ' If other devices can\'t connect, open:',
107
+ ' System Settings > Network > Firewall > Options',
108
+ ` and add Node.js to "Allow incoming connections" (port ${port}).`,
109
+ ].join('\n');
110
+ }
111
+
112
+ // ---------------- Main entry ----------------
113
+
114
+ /**
115
+ * Make sure inbound traffic can reach `port` from the local network.
116
+ *
117
+ * - Linux: silently try ufw/firewalld with `sudo -n` (passwordless). Skips
118
+ * cleanly when no firewall is running or sudo is gated — LAN access
119
+ * already works on most desktop distros.
120
+ * - Windows/macOS: ask the user once; remember the decision in
121
+ * ~/.pixcode/port-access.json so subsequent starts stay quiet.
122
+ *
123
+ * All failure paths are non-fatal: the server is already listening when
124
+ * we get here, and LAN clients on the same subnet often can reach it
125
+ * without any firewall change.
126
+ */
127
+ export async function ensurePortOpen(port) {
128
+ const state = loadState();
129
+ const key = `port:${port}`;
130
+ const entry = state[key];
131
+
132
+ const lanIps = getLanIps();
133
+ if (lanIps.length) {
134
+ console.log(`${c.info('[INFO]')} LAN access: ${c.bright(`http://${lanIps[0]}:${port}`)}`);
135
+ if (lanIps.length > 1) {
136
+ for (const extra of lanIps.slice(1)) {
137
+ console.log(`${c.dim(' also:')} http://${extra}:${port}`);
138
+ }
139
+ }
140
+ }
141
+
142
+ if (entry && entry.decision === 'deny') {
143
+ console.log(`${c.dim('[INFO]')} Firewall prompt suppressed (previously declined). Re-enable via ~/.pixcode/port-access.json`);
144
+ return;
145
+ }
146
+
147
+ const platform = process.platform;
148
+
149
+ if (platform === 'linux') {
150
+ if (entry && entry.status === 'applied') return;
151
+ const result = tryUfw(port) || tryFirewalld(port);
152
+ if (result === 'applied') {
153
+ console.log(`${c.ok('[OK]')} Inbound firewall rule added for port ${port}.`);
154
+ saveState({ ...state, [key]: { decision: 'allow', status: 'applied', via: 'linux' } });
155
+ } else if (result === 'inactive') {
156
+ console.log(`${c.dim('[INFO]')} No active firewall detected — port ${port} should be reachable.`);
157
+ } else {
158
+ console.log(`${c.tip('[TIP]')} Couldn't auto-open port (no sudo / unsupported firewall).`);
159
+ console.log(` Manual: ${c.bright(`sudo ufw allow ${port}/tcp`)} ${c.dim('(or firewall-cmd equivalent)')}`);
160
+ }
161
+ return;
162
+ }
163
+
164
+ if (platform === 'win32') {
165
+ if (entry && entry.status === 'applied') return;
166
+ const approved = await askYN(
167
+ `${c.tip('[?]')} Open port ${port} in Windows Firewall so other devices on your network can connect? [y/N] `,
168
+ );
169
+ if (approved === null) {
170
+ // No TTY — just show the manual command and move on.
171
+ console.log(
172
+ `${c.tip('[TIP]')} To allow LAN access, run this in an elevated PowerShell:\n ${c.bright(
173
+ `netsh advfirewall firewall add rule name="Pixcode-${port}" dir=in action=allow protocol=TCP localport=${port}`,
174
+ )}`,
175
+ );
176
+ return;
177
+ }
178
+ if (!approved) {
179
+ console.log(`${c.dim('[INFO]')} Skipping firewall change.`);
180
+ saveState({ ...state, [key]: { decision: 'deny' } });
181
+ return;
182
+ }
183
+ const result = applyWindowsRule(port);
184
+ if (result.ok) {
185
+ console.log(`${c.ok('[OK]')} Firewall rule "${result.ruleName}" added.`);
186
+ saveState({ ...state, [key]: { decision: 'allow', status: 'applied', via: 'windows' } });
187
+ } else {
188
+ console.log(`${c.tip('[TIP]')} Adding the rule needs Administrator. Run this in an elevated PowerShell:`);
189
+ console.log(` ${c.bright(result.cmd)}`);
190
+ saveState({ ...state, [key]: { decision: 'allow', status: 'manual' } });
191
+ }
192
+ return;
193
+ }
194
+
195
+ if (platform === 'darwin') {
196
+ if (entry && entry.status) return;
197
+ const approved = await askYN(
198
+ `${c.tip('[?]')} Allow inbound connections on port ${port} through macOS firewall? [y/N] `,
199
+ );
200
+ if (approved === null) return;
201
+ if (!approved) {
202
+ console.log(`${c.dim('[INFO]')} Skipping firewall hint.`);
203
+ saveState({ ...state, [key]: { decision: 'deny' } });
204
+ return;
205
+ }
206
+ console.log(macFirewallHint(port));
207
+ saveState({ ...state, [key]: { decision: 'allow', status: 'manual', via: 'macos' } });
208
+ }
209
+ }