@pixelbyte-software/pixcode 1.53.7 → 1.53.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/dist/assets/{index-DM-KfWAm.js → index-nl5YZ8Wr.js} +142 -142
- package/dist/index.html +1 -1
- package/dist-server/server/index.js +128 -21
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/services/telegram/control-center.js +126 -17
- package/dist-server/server/services/telegram/control-center.js.map +1 -1
- package/dist-server/server/services/telegram/translations.js +6 -0
- package/dist-server/server/services/telegram/translations.js.map +1 -1
- package/package.json +1 -1
- package/server/index.js +132 -17
- package/server/services/telegram/control-center.js +129 -17
- package/server/services/telegram/translations.js +6 -0
package/dist/index.html
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
|
|
36
36
|
<!-- Prevent zoom on iOS -->
|
|
37
37
|
<meta name="format-detection" content="telephone=no" />
|
|
38
|
-
<script type="module" crossorigin src="/assets/index-
|
|
38
|
+
<script type="module" crossorigin src="/assets/index-nl5YZ8Wr.js"></script>
|
|
39
39
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DB6V5Fl1.js">
|
|
40
40
|
<link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-CIYNS698.js">
|
|
41
41
|
<link rel="modulepreload" crossorigin href="/assets/vendor-xterm-C7tpxJl7.js">
|
|
@@ -37,12 +37,18 @@ const DAEMON_COMMAND_CONTEXT = {
|
|
|
37
37
|
nodeExecPath: process.execPath,
|
|
38
38
|
};
|
|
39
39
|
function resolveMonacoAssetsPath() {
|
|
40
|
+
const appParent = path.dirname(APP_ROOT);
|
|
41
|
+
const appGrandparent = path.dirname(appParent);
|
|
40
42
|
const candidates = [
|
|
41
43
|
path.join(APP_ROOT, 'node_modules', 'monaco-editor', 'min', 'vs'),
|
|
44
|
+
path.join(appParent, 'node_modules', 'monaco-editor', 'min', 'vs'),
|
|
45
|
+
path.join(appParent, 'monaco-editor', 'min', 'vs'),
|
|
46
|
+
path.join(appGrandparent, 'node_modules', 'monaco-editor', 'min', 'vs'),
|
|
47
|
+
path.join(appGrandparent, 'monaco-editor', 'min', 'vs'),
|
|
42
48
|
];
|
|
43
49
|
try {
|
|
44
50
|
const monacoPackagePath = require.resolve('monaco-editor/package.json', {
|
|
45
|
-
paths: [APP_ROOT, __dirname],
|
|
51
|
+
paths: [APP_ROOT, appParent, appGrandparent, __dirname, process.cwd()],
|
|
46
52
|
});
|
|
47
53
|
candidates.push(path.join(path.dirname(monacoPackagePath), 'min', 'vs'));
|
|
48
54
|
}
|
|
@@ -909,6 +915,11 @@ const ptySessionsMap = new Map();
|
|
|
909
915
|
const PTY_SESSION_TIMEOUT = 30 * 60 * 1000;
|
|
910
916
|
const COMPLETED_PTY_SESSION_TTL = 5 * 60 * 1000;
|
|
911
917
|
const SHELL_URL_PARSE_BUFFER_LIMIT = 32768;
|
|
918
|
+
const SHELL_OUTPUT_FLUSH_MAX_CHARS = 128 * 1024;
|
|
919
|
+
const SHELL_WS_BACKPRESSURE_LIMIT = 8 * 1024 * 1024;
|
|
920
|
+
const PTY_SESSION_BUFFER_MAX_BYTES = Number.parseInt(process.env.PIXCODE_PTY_BUFFER_MAX_BYTES || '', 10) || (2 * 1024 * 1024);
|
|
921
|
+
const SHELL_INPUT_CHUNK_CHARS = 4096;
|
|
922
|
+
const SHELL_PENDING_INPUT_MAX_BYTES = 2 * 1024 * 1024;
|
|
912
923
|
const SHELL_CLI_PROVIDERS = new Set(['claude', 'codex', 'cursor', 'gemini', 'qwen', 'opencode']);
|
|
913
924
|
import { stripAnsiSequences, normalizeDetectedUrl, extractUrlsFromText, shouldAutoOpenUrlFromOutput } from './utils/url-detection.js';
|
|
914
925
|
function terminatePtySession(sessionKey, session, reason) {
|
|
@@ -1030,13 +1041,22 @@ function resolveProviderTerminalState(session, provider, output) {
|
|
|
1030
1041
|
function appendPtySessionBuffer(session, data) {
|
|
1031
1042
|
if (!session)
|
|
1032
1043
|
return;
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1044
|
+
let value = String(data || '');
|
|
1045
|
+
if (!value)
|
|
1046
|
+
return;
|
|
1047
|
+
let valueBytes = Buffer.byteLength(value, 'utf8');
|
|
1048
|
+
if (valueBytes > PTY_SESSION_BUFFER_MAX_BYTES) {
|
|
1049
|
+
value = value.slice(-PTY_SESSION_BUFFER_MAX_BYTES);
|
|
1050
|
+
valueBytes = Buffer.byteLength(value, 'utf8');
|
|
1051
|
+
}
|
|
1052
|
+
session.buffer.push(value);
|
|
1053
|
+
session.bufferBytes = (session.bufferBytes || 0) + valueBytes;
|
|
1054
|
+
while (session.buffer.length > 0 && session.bufferBytes > PTY_SESSION_BUFFER_MAX_BYTES) {
|
|
1055
|
+
const removed = session.buffer.shift();
|
|
1056
|
+
session.bufferBytes -= Buffer.byteLength(String(removed || ''), 'utf8');
|
|
1057
|
+
}
|
|
1058
|
+
if (session.bufferBytes < 0)
|
|
1059
|
+
session.bufferBytes = 0;
|
|
1040
1060
|
}
|
|
1041
1061
|
function normalizeTerminalStartupInput(input) {
|
|
1042
1062
|
return `\x15${String(input || '').replace(/(?:\r\n|\r|\n)+$/u, '')}\r`;
|
|
@@ -1120,6 +1140,27 @@ function queueTerminalStartupInput(session, startupInput, reason, delayMs = 500)
|
|
|
1120
1140
|
function writeTerminalStartupInput(session, startupInput, reason, delayMs = 500) {
|
|
1121
1141
|
queueTerminalStartupInput(session, startupInput, reason, delayMs);
|
|
1122
1142
|
}
|
|
1143
|
+
function splitTerminalInput(data) {
|
|
1144
|
+
const value = String(data || '');
|
|
1145
|
+
if (!value)
|
|
1146
|
+
return [];
|
|
1147
|
+
const chunks = [];
|
|
1148
|
+
for (let index = 0; index < value.length; index += SHELL_INPUT_CHUNK_CHARS) {
|
|
1149
|
+
chunks.push(value.slice(index, index + SHELL_INPUT_CHUNK_CHARS));
|
|
1150
|
+
}
|
|
1151
|
+
return chunks;
|
|
1152
|
+
}
|
|
1153
|
+
function writeTerminalInputChunks(ptyProcess, data) {
|
|
1154
|
+
if (!ptyProcess?.write)
|
|
1155
|
+
return false;
|
|
1156
|
+
const chunks = splitTerminalInput(data);
|
|
1157
|
+
if (chunks.length === 0)
|
|
1158
|
+
return false;
|
|
1159
|
+
for (const chunk of chunks) {
|
|
1160
|
+
ptyProcess.write(chunk);
|
|
1161
|
+
}
|
|
1162
|
+
return true;
|
|
1163
|
+
}
|
|
1123
1164
|
function normalizeShellPermissionMode(value) {
|
|
1124
1165
|
return typeof value === 'string' ? value.trim() : '';
|
|
1125
1166
|
}
|
|
@@ -1356,7 +1397,7 @@ app.post('/api/shell/sessions/provider-input', authenticateToken, requireProject
|
|
|
1356
1397
|
}
|
|
1357
1398
|
const data = submit ? normalizeTerminalStartupInput(input) : input;
|
|
1358
1399
|
try {
|
|
1359
|
-
matchedSession.pty
|
|
1400
|
+
writeTerminalInputChunks(matchedSession.pty, data);
|
|
1360
1401
|
matchedSession.updatedAt = Date.now();
|
|
1361
1402
|
res.json({
|
|
1362
1403
|
ok: true,
|
|
@@ -3135,7 +3176,58 @@ function handleShellConnection(ws, request) {
|
|
|
3135
3176
|
let urlDetectionBuffer = '';
|
|
3136
3177
|
let outputBuffer = '';
|
|
3137
3178
|
let outputFlushTimer = null;
|
|
3179
|
+
let inputFlushTimer = null;
|
|
3180
|
+
let pendingInputBytes = 0;
|
|
3181
|
+
const pendingInputQueue = [];
|
|
3138
3182
|
const announcedAuthUrls = new Set();
|
|
3183
|
+
function getActiveShellPty() {
|
|
3184
|
+
const session = ptySessionKey ? ptySessionsMap.get(ptySessionKey) : null;
|
|
3185
|
+
return session?.pty || shellProcess;
|
|
3186
|
+
}
|
|
3187
|
+
function scheduleInputFlush(delayMs = 0) {
|
|
3188
|
+
if (inputFlushTimer)
|
|
3189
|
+
return;
|
|
3190
|
+
inputFlushTimer = setTimeout(flushPendingInput, delayMs);
|
|
3191
|
+
}
|
|
3192
|
+
function flushPendingInput() {
|
|
3193
|
+
inputFlushTimer = null;
|
|
3194
|
+
if (pendingInputQueue.length === 0)
|
|
3195
|
+
return;
|
|
3196
|
+
const activePty = getActiveShellPty();
|
|
3197
|
+
if (!activePty?.write) {
|
|
3198
|
+
scheduleInputFlush(100);
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
const chunk = pendingInputQueue.shift();
|
|
3202
|
+
pendingInputBytes = Math.max(0, pendingInputBytes - Buffer.byteLength(chunk, 'utf8'));
|
|
3203
|
+
try {
|
|
3204
|
+
activePty.write(chunk);
|
|
3205
|
+
}
|
|
3206
|
+
catch (error) {
|
|
3207
|
+
console.error('Error writing to shell:', error);
|
|
3208
|
+
pendingInputQueue.length = 0;
|
|
3209
|
+
pendingInputBytes = 0;
|
|
3210
|
+
return;
|
|
3211
|
+
}
|
|
3212
|
+
if (pendingInputQueue.length > 0)
|
|
3213
|
+
scheduleInputFlush(1);
|
|
3214
|
+
}
|
|
3215
|
+
function enqueueShellInput(data) {
|
|
3216
|
+
const chunks = splitTerminalInput(data);
|
|
3217
|
+
if (chunks.length === 0)
|
|
3218
|
+
return;
|
|
3219
|
+
for (const chunk of chunks) {
|
|
3220
|
+
pendingInputQueue.push(chunk);
|
|
3221
|
+
pendingInputBytes += Buffer.byteLength(chunk, 'utf8');
|
|
3222
|
+
}
|
|
3223
|
+
while (pendingInputQueue.length > 0 && pendingInputBytes > SHELL_PENDING_INPUT_MAX_BYTES) {
|
|
3224
|
+
const dropped = pendingInputQueue.shift();
|
|
3225
|
+
pendingInputBytes -= Buffer.byteLength(String(dropped || ''), 'utf8');
|
|
3226
|
+
}
|
|
3227
|
+
if (pendingInputBytes < 0)
|
|
3228
|
+
pendingInputBytes = 0;
|
|
3229
|
+
scheduleInputFlush();
|
|
3230
|
+
}
|
|
3139
3231
|
function flushOutputBuffer() {
|
|
3140
3232
|
if (!outputBuffer || !ptySessionKey) {
|
|
3141
3233
|
outputFlushTimer = null;
|
|
@@ -3150,7 +3242,16 @@ function handleShellConnection(ws, request) {
|
|
|
3150
3242
|
session.updatedAt = Date.now();
|
|
3151
3243
|
appendPtySessionBuffer(session, rawData);
|
|
3152
3244
|
if (session.ws && session.ws.readyState === WebSocket.OPEN) {
|
|
3245
|
+
if (session.ws.bufferedAmount > SHELL_WS_BACKPRESSURE_LIMIT) {
|
|
3246
|
+
session.droppedOutputBytes = (session.droppedOutputBytes || 0) + Buffer.byteLength(rawData, 'utf8');
|
|
3247
|
+
return;
|
|
3248
|
+
}
|
|
3249
|
+
const droppedOutputBytes = session.droppedOutputBytes || 0;
|
|
3250
|
+
session.droppedOutputBytes = 0;
|
|
3153
3251
|
let outputData = rawData;
|
|
3252
|
+
if (droppedOutputBytes > 0) {
|
|
3253
|
+
outputData = `\r\n\x1b[33m[Pixcode] ${droppedOutputBytes} bytes of terminal output were skipped because the browser connection was backpressured.\x1b[0m\r\n${outputData}`;
|
|
3254
|
+
}
|
|
3154
3255
|
const cleanChunk = stripAnsiSequences(rawData);
|
|
3155
3256
|
urlDetectionBuffer = `${urlDetectionBuffer}${cleanChunk}`.slice(-SHELL_URL_PARSE_BUFFER_LIMIT);
|
|
3156
3257
|
outputData = outputData.replace(/OPEN_URL:\s*(https?:\/\/[^\s\x1b\x07]+)/g, '[INFO] Opening in browser: $1');
|
|
@@ -3491,6 +3592,8 @@ function handleShellConnection(ws, request) {
|
|
|
3491
3592
|
pty: shellProcess,
|
|
3492
3593
|
ws: ws,
|
|
3493
3594
|
buffer: [],
|
|
3595
|
+
bufferBytes: 0,
|
|
3596
|
+
droppedOutputBytes: 0,
|
|
3494
3597
|
timeoutId: null,
|
|
3495
3598
|
userId: ownerUserId,
|
|
3496
3599
|
projectPath,
|
|
@@ -3511,11 +3614,20 @@ function handleShellConnection(ws, request) {
|
|
|
3511
3614
|
if (terminalStartupInput && !isPlainShell) {
|
|
3512
3615
|
writeTerminalStartupInput(createdSession, terminalStartupInput, 'new provider session', 4500);
|
|
3513
3616
|
}
|
|
3617
|
+
scheduleInputFlush();
|
|
3514
3618
|
// Handle data output — batch rapid chunks so high-volume CLI
|
|
3515
3619
|
// output does not flood the WebSocket with one JSON frame per
|
|
3516
3620
|
// keystroke-sized chunk.
|
|
3517
3621
|
shellProcess.onData((data) => {
|
|
3518
3622
|
outputBuffer += data;
|
|
3623
|
+
if (outputBuffer.length >= SHELL_OUTPUT_FLUSH_MAX_CHARS) {
|
|
3624
|
+
if (outputFlushTimer) {
|
|
3625
|
+
clearTimeout(outputFlushTimer);
|
|
3626
|
+
outputFlushTimer = null;
|
|
3627
|
+
}
|
|
3628
|
+
flushOutputBuffer();
|
|
3629
|
+
return;
|
|
3630
|
+
}
|
|
3519
3631
|
if (!outputFlushTimer) {
|
|
3520
3632
|
outputFlushTimer = setTimeout(flushOutputBuffer, 8);
|
|
3521
3633
|
}
|
|
@@ -3581,18 +3693,7 @@ function handleShellConnection(ws, request) {
|
|
|
3581
3693
|
}
|
|
3582
3694
|
}
|
|
3583
3695
|
else if (data.type === 'input') {
|
|
3584
|
-
|
|
3585
|
-
if (shellProcess && shellProcess.write) {
|
|
3586
|
-
try {
|
|
3587
|
-
shellProcess.write(data.data);
|
|
3588
|
-
}
|
|
3589
|
-
catch (error) {
|
|
3590
|
-
console.error('Error writing to shell:', error);
|
|
3591
|
-
}
|
|
3592
|
-
}
|
|
3593
|
-
else {
|
|
3594
|
-
console.warn('No active shell process to send input to');
|
|
3595
|
-
}
|
|
3696
|
+
enqueueShellInput(data.data);
|
|
3596
3697
|
}
|
|
3597
3698
|
else if (data.type === 'resize') {
|
|
3598
3699
|
// Handle terminal resize
|
|
@@ -3627,6 +3728,12 @@ function handleShellConnection(ws, request) {
|
|
|
3627
3728
|
clearTimeout(outputFlushTimer);
|
|
3628
3729
|
outputFlushTimer = null;
|
|
3629
3730
|
}
|
|
3731
|
+
if (inputFlushTimer) {
|
|
3732
|
+
clearTimeout(inputFlushTimer);
|
|
3733
|
+
inputFlushTimer = null;
|
|
3734
|
+
}
|
|
3735
|
+
pendingInputQueue.length = 0;
|
|
3736
|
+
pendingInputBytes = 0;
|
|
3630
3737
|
if (ptySessionKey) {
|
|
3631
3738
|
const session = ptySessionsMap.get(ptySessionKey);
|
|
3632
3739
|
if (session) {
|