@pixelbyte-software/pixcode 1.53.11 โ 1.53.12
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-BEyC4q_s.css +32 -0
- package/dist/assets/{index-Bo8oVc2f.js โ index-kP_gZ-wL.js} +178 -178
- package/dist/index.html +2 -2
- package/dist-server/server/database/db.js +26 -0
- package/dist-server/server/database/db.js.map +1 -1
- package/dist-server/server/index.js +258 -52
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/projects.js +126 -43
- package/dist-server/server/projects.js.map +1 -1
- package/dist-server/server/routes/plugins.js +364 -0
- package/dist-server/server/routes/plugins.js.map +1 -1
- package/dist-server/server/services/telegram/control-center.js +169 -5
- package/dist-server/server/services/telegram/control-center.js.map +1 -1
- package/dist-server/server/services/telegram/translations.js +28 -2
- package/dist-server/server/services/telegram/translations.js.map +1 -1
- package/package.json +1 -1
- package/server/database/db.js +26 -0
- package/server/index.js +280 -57
- package/server/projects.js +128 -41
- package/server/routes/plugins.js +370 -0
- package/server/services/telegram/control-center.js +173 -5
- package/server/services/telegram/translations.js +28 -2
- package/dist/assets/index-FhOsv2Yy.css +0 -32
|
@@ -52,6 +52,8 @@ const CONTROL_COMMANDS = new Set([
|
|
|
52
52
|
'/workflow',
|
|
53
53
|
'/orchestrate',
|
|
54
54
|
'/cancel',
|
|
55
|
+
'/terminal',
|
|
56
|
+
'/detach',
|
|
55
57
|
'menu',
|
|
56
58
|
]);
|
|
57
59
|
function compact(text, max = 80) {
|
|
@@ -466,15 +468,25 @@ function startActivityHeartbeat({ bot, chatId, activity }) {
|
|
|
466
468
|
}, ACTIVITY_HEARTBEAT_MS);
|
|
467
469
|
}
|
|
468
470
|
function stateSummary(lang, state) {
|
|
469
|
-
|
|
471
|
+
const lines = [
|
|
470
472
|
`${t(lang, 'control.summary.project')}: ${state.selectedProjectName || t(lang, 'control.notSelected')}`,
|
|
471
473
|
`${t(lang, 'control.summary.provider')}: ${state.selectedProvider}${state.selectedModel ? ` / ${state.selectedModel}` : ''}`,
|
|
472
474
|
`${t(lang, 'control.summary.workflow')}: ${state.selectedWorkflowId || t(lang, 'control.notSelected')}`,
|
|
473
475
|
`${t(lang, 'control.summary.progress')}: ${state.progressMode}`,
|
|
474
|
-
]
|
|
476
|
+
];
|
|
477
|
+
if (state.activeTerminal) {
|
|
478
|
+
lines.push(`${t(lang, 'control.summary.terminal')}: ${state.activeTerminal.provider} / ${state.activeTerminal.projectLabel || state.activeTerminal.projectName || compact(state.activeTerminal.projectPath, 50)}`);
|
|
479
|
+
}
|
|
480
|
+
return lines.join('\n');
|
|
475
481
|
}
|
|
476
|
-
function
|
|
482
|
+
function terminalControlKeyboard(lang) {
|
|
477
483
|
return [
|
|
484
|
+
[button(t(lang, 'control.button.terminalRefresh'), 'terminal_status'), button(t(lang, 'control.button.detachTerminal'), 'detach_terminal')],
|
|
485
|
+
[button(t(lang, 'control.button.mainMenu'), 'menu')],
|
|
486
|
+
];
|
|
487
|
+
}
|
|
488
|
+
function mainMenuKeyboard(lang, state = null) {
|
|
489
|
+
const keyboard = [
|
|
478
490
|
[button(t(lang, 'control.button.projects'), 'projects'), button(t(lang, 'control.button.provider'), 'providers')],
|
|
479
491
|
[button(t(lang, 'control.button.models'), 'models'), button(t(lang, 'control.button.workflows'), 'workflows')],
|
|
480
492
|
[button(t(lang, 'control.button.runs'), 'runs'), button(t(lang, 'control.button.approvals'), 'approvals')],
|
|
@@ -483,6 +495,10 @@ function mainMenuKeyboard(lang) {
|
|
|
483
495
|
[button(t(lang, 'control.button.install'), 'install_menu'), button(t(lang, 'control.button.auth'), 'auth_menu')],
|
|
484
496
|
[button(t(lang, 'control.button.settings'), 'settings')],
|
|
485
497
|
];
|
|
498
|
+
if (state?.activeTerminal) {
|
|
499
|
+
keyboard.splice(1, 0, [button(t(lang, 'control.button.terminal'), 'terminal_status'), button(t(lang, 'control.button.detachTerminal'), 'detach_terminal')]);
|
|
500
|
+
}
|
|
501
|
+
return keyboard;
|
|
486
502
|
}
|
|
487
503
|
export async function showMainMenu({ bot, chatId, link, editMessageId, notice }) {
|
|
488
504
|
const lang = languageFor(link);
|
|
@@ -490,7 +506,7 @@ export async function showMainMenu({ bot, chatId, link, editMessageId, notice })
|
|
|
490
506
|
const prefix = notice ? `${notice}\n\n` : '';
|
|
491
507
|
await send(bot, chatId, `${prefix}${t(lang, 'control.menu')}\n\n${stateSummary(lang, state)}`, {
|
|
492
508
|
editMessageId,
|
|
493
|
-
reply_markup: { inline_keyboard: mainMenuKeyboard(lang) },
|
|
509
|
+
reply_markup: { inline_keyboard: mainMenuKeyboard(lang, state) },
|
|
494
510
|
});
|
|
495
511
|
}
|
|
496
512
|
async function showHelp({ bot, chatId, link }) {
|
|
@@ -502,8 +518,141 @@ async function showCommandPalette({ bot, chatId, link, editMessageId, unknown =
|
|
|
502
518
|
const prefix = unknown ? `${t(lang, 'control.unknownCommand')}\n\n` : '';
|
|
503
519
|
await send(bot, chatId, `${prefix}${t(lang, 'control.help')}\n\n${t(lang, 'control.examples')}`, {
|
|
504
520
|
editMessageId,
|
|
505
|
-
reply_markup: { inline_keyboard: mainMenuKeyboard(lang) },
|
|
521
|
+
reply_markup: { inline_keyboard: mainMenuKeyboard(lang, getState(link.user_id)) },
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
function getActiveTerminal(state) {
|
|
525
|
+
const terminal = state?.activeTerminal;
|
|
526
|
+
if (!terminal ||
|
|
527
|
+
!PROVIDERS.includes(terminal.provider) ||
|
|
528
|
+
typeof terminal.projectPath !== 'string' ||
|
|
529
|
+
!terminal.projectPath.trim()) {
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
return terminal;
|
|
533
|
+
}
|
|
534
|
+
function terminalProjectLabel(terminal) {
|
|
535
|
+
return terminal?.projectLabel || terminal?.projectName || terminal?.projectPath || '-';
|
|
536
|
+
}
|
|
537
|
+
function terminalOutputUrl(terminal, maxChars = 3200) {
|
|
538
|
+
const params = new URLSearchParams({
|
|
539
|
+
provider: terminal.provider,
|
|
540
|
+
projectPath: terminal.projectPath,
|
|
541
|
+
maxChars: String(maxChars),
|
|
542
|
+
});
|
|
543
|
+
if (terminal.tabId)
|
|
544
|
+
params.set('tabId', terminal.tabId);
|
|
545
|
+
if (terminal.sessionId)
|
|
546
|
+
params.set('sessionId', terminal.sessionId);
|
|
547
|
+
return `/api/shell/sessions/provider-output?${params.toString()}`;
|
|
548
|
+
}
|
|
549
|
+
function renderTerminalSnapshot(lang, terminal, data, { prefix = '' } = {}) {
|
|
550
|
+
const active = data?.active !== false;
|
|
551
|
+
const lifecycle = data?.terminalState || data?.lifecycleState || (active ? 'running' : 'not running');
|
|
552
|
+
const output = String(data?.output || '').trim();
|
|
553
|
+
const lines = [
|
|
554
|
+
prefix || t(lang, active ? 'control.terminalAttached' : 'control.terminalNotRunning'),
|
|
555
|
+
'',
|
|
556
|
+
`๐ค ${t(lang, 'control.activity.provider')}: ${terminal.provider}`,
|
|
557
|
+
`๐ ${t(lang, 'control.activity.project')}: ${compact(terminalProjectLabel(terminal), 90)}`,
|
|
558
|
+
`๐ ${t(lang, 'control.activity.status')}: ${lifecycle}`,
|
|
559
|
+
];
|
|
560
|
+
if (terminal.sessionId || data?.sessionId) {
|
|
561
|
+
lines.push(`๐งต ${t(lang, 'control.activity.session')}: ${terminal.sessionId || data.sessionId}`);
|
|
562
|
+
}
|
|
563
|
+
if (output) {
|
|
564
|
+
lines.push('', `๐ฌ ${t(lang, 'control.activity.output')}:`);
|
|
565
|
+
lines.push(truncate(output, 2400));
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
lines.push('', t(lang, 'control.terminalNoOutput'));
|
|
569
|
+
}
|
|
570
|
+
return truncate(lines.join('\n'), 3400);
|
|
571
|
+
}
|
|
572
|
+
async function showActiveTerminalStatus({ bot, chatId, link, editMessageId }) {
|
|
573
|
+
const lang = languageFor(link);
|
|
574
|
+
const state = getState(link.user_id);
|
|
575
|
+
const terminal = getActiveTerminal(state);
|
|
576
|
+
if (!terminal) {
|
|
577
|
+
await send(bot, chatId, t(lang, 'control.noActiveTerminal'), {
|
|
578
|
+
editMessageId,
|
|
579
|
+
reply_markup: { inline_keyboard: [[button(t(lang, 'control.button.mainMenu'), 'menu')]] },
|
|
580
|
+
});
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const data = await localApi(link.user_id, terminalOutputUrl(terminal), { timeoutMs: 12_000 });
|
|
585
|
+
await send(bot, chatId, renderTerminalSnapshot(lang, terminal, data), {
|
|
586
|
+
editMessageId,
|
|
587
|
+
parse_mode: undefined,
|
|
588
|
+
reply_markup: { inline_keyboard: terminalControlKeyboard(lang) },
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
catch (error) {
|
|
592
|
+
await send(bot, chatId, t(lang, 'control.terminalStatusFailed', { error: error?.message || String(error) }), {
|
|
593
|
+
editMessageId,
|
|
594
|
+
reply_markup: { inline_keyboard: terminalControlKeyboard(lang) },
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
async function detachActiveTerminal({ bot, chatId, link, editMessageId }) {
|
|
599
|
+
const lang = languageFor(link);
|
|
600
|
+
updateTelegramControlState(link.user_id, { activeTerminal: null });
|
|
601
|
+
await send(bot, chatId, t(lang, 'control.terminalDetached'), {
|
|
602
|
+
editMessageId,
|
|
603
|
+
reply_markup: { inline_keyboard: [[button(t(lang, 'control.button.mainMenu'), 'menu')]] },
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
async function sendToActiveTerminal({ bot, chatId, link, text }) {
|
|
607
|
+
const lang = languageFor(link);
|
|
608
|
+
const state = getState(link.user_id);
|
|
609
|
+
const terminal = getActiveTerminal(state);
|
|
610
|
+
if (!terminal)
|
|
611
|
+
return false;
|
|
612
|
+
if (state.remoteControlEnabled === false) {
|
|
613
|
+
await send(bot, chatId, t(lang, 'control.disabled'));
|
|
614
|
+
return true;
|
|
615
|
+
}
|
|
616
|
+
const sent = await send(bot, chatId, t(lang, 'control.terminalSending', {
|
|
617
|
+
provider: terminal.provider,
|
|
618
|
+
project: terminalProjectLabel(terminal),
|
|
619
|
+
}), {
|
|
620
|
+
parse_mode: undefined,
|
|
621
|
+
reply_markup: { inline_keyboard: terminalControlKeyboard(lang) },
|
|
506
622
|
});
|
|
623
|
+
const editMessageId = sent?.message_id || sent?.message?.message_id || null;
|
|
624
|
+
try {
|
|
625
|
+
await localApi(link.user_id, '/api/shell/sessions/provider-input', {
|
|
626
|
+
method: 'POST',
|
|
627
|
+
timeoutMs: 15_000,
|
|
628
|
+
body: {
|
|
629
|
+
provider: terminal.provider,
|
|
630
|
+
projectPath: terminal.projectPath,
|
|
631
|
+
tabId: terminal.tabId,
|
|
632
|
+
sessionId: terminal.sessionId,
|
|
633
|
+
input: text,
|
|
634
|
+
submit: true,
|
|
635
|
+
},
|
|
636
|
+
});
|
|
637
|
+
await new Promise((resolve) => setTimeout(resolve, 700));
|
|
638
|
+
const data = await localApi(link.user_id, terminalOutputUrl(terminal), { timeoutMs: 12_000 });
|
|
639
|
+
await send(bot, chatId, renderTerminalSnapshot(lang, terminal, data, {
|
|
640
|
+
prefix: t(lang, 'control.terminalSent'),
|
|
641
|
+
}), {
|
|
642
|
+
editMessageId,
|
|
643
|
+
parse_mode: undefined,
|
|
644
|
+
reply_markup: { inline_keyboard: terminalControlKeyboard(lang) },
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
catch (error) {
|
|
648
|
+
await send(bot, chatId, t(lang, 'control.terminalSendFailed', {
|
|
649
|
+
error: error?.message || String(error),
|
|
650
|
+
}), {
|
|
651
|
+
editMessageId,
|
|
652
|
+
reply_markup: { inline_keyboard: terminalControlKeyboard(lang) },
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
return true;
|
|
507
656
|
}
|
|
508
657
|
async function listProjects() {
|
|
509
658
|
const projects = await getProjects();
|
|
@@ -1541,6 +1690,14 @@ async function handleCommand({ bot, chatId, link, text }) {
|
|
|
1541
1690
|
await showSessions({ bot, chatId, link });
|
|
1542
1691
|
return true;
|
|
1543
1692
|
}
|
|
1693
|
+
if (command === '/terminal') {
|
|
1694
|
+
await showActiveTerminalStatus({ bot, chatId, link });
|
|
1695
|
+
return true;
|
|
1696
|
+
}
|
|
1697
|
+
if (command === '/detach') {
|
|
1698
|
+
await detachActiveTerminal({ bot, chatId, link });
|
|
1699
|
+
return true;
|
|
1700
|
+
}
|
|
1544
1701
|
if (command === '/newchat') {
|
|
1545
1702
|
await startNewChat({ bot, chatId, link });
|
|
1546
1703
|
return true;
|
|
@@ -1634,6 +1791,9 @@ async function handleTelegramControlMessageInternal({ bot, msg, link }) {
|
|
|
1634
1791
|
if (await handleCommand({ bot, chatId, link, text }))
|
|
1635
1792
|
return true;
|
|
1636
1793
|
const state = getState(link.user_id);
|
|
1794
|
+
if (getActiveTerminal(state)) {
|
|
1795
|
+
return sendToActiveTerminal({ bot, chatId, link, text });
|
|
1796
|
+
}
|
|
1637
1797
|
if (state.routerEnabled === false)
|
|
1638
1798
|
return false;
|
|
1639
1799
|
if (!state.remoteControlEnabled) {
|
|
@@ -1745,6 +1905,10 @@ async function handleTelegramControlCallbackInternal({ bot, query, link }) {
|
|
|
1745
1905
|
return showWebhookMenu({ bot, chatId, link, editMessageId });
|
|
1746
1906
|
if (action === 'sessions')
|
|
1747
1907
|
return showSessions({ bot, chatId, link, editMessageId });
|
|
1908
|
+
if (action === 'terminal_status')
|
|
1909
|
+
return showActiveTerminalStatus({ bot, chatId, link, editMessageId });
|
|
1910
|
+
if (action === 'detach_terminal')
|
|
1911
|
+
return detachActiveTerminal({ bot, chatId, link, editMessageId });
|
|
1748
1912
|
if (action === 'new_chat')
|
|
1749
1913
|
return startNewChat({ bot, chatId, link, editMessageId });
|
|
1750
1914
|
if (action === 'install_menu')
|