@pixelbyte-software/pixcode 1.53.6 → 1.53.7

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 (30) hide show
  1. package/dist/assets/{index-DP7jnMyc.js → index-DM-KfWAm.js} +1 -1
  2. package/dist/index.html +1 -1
  3. package/dist-server/server/claude-sdk.js +17 -15
  4. package/dist-server/server/claude-sdk.js.map +1 -1
  5. package/dist-server/server/cursor-cli.js +14 -12
  6. package/dist-server/server/cursor-cli.js.map +1 -1
  7. package/dist-server/server/gemini-cli.js +14 -12
  8. package/dist-server/server/gemini-cli.js.map +1 -1
  9. package/dist-server/server/openai-codex.js +25 -22
  10. package/dist-server/server/openai-codex.js.map +1 -1
  11. package/dist-server/server/opencode-cli.js +14 -12
  12. package/dist-server/server/opencode-cli.js.map +1 -1
  13. package/dist-server/server/qwen-code-cli.js +14 -12
  14. package/dist-server/server/qwen-code-cli.js.map +1 -1
  15. package/dist-server/server/routes/agent.js +11 -4
  16. package/dist-server/server/routes/agent.js.map +1 -1
  17. package/dist-server/server/services/telegram/control-center.js +18 -0
  18. package/dist-server/server/services/telegram/control-center.js.map +1 -1
  19. package/dist-server/server/services/telegram/translations.js +6 -0
  20. package/dist-server/server/services/telegram/translations.js.map +1 -1
  21. package/package.json +1 -1
  22. package/server/claude-sdk.js +3 -3
  23. package/server/cursor-cli.js +3 -3
  24. package/server/gemini-cli.js +3 -3
  25. package/server/openai-codex.js +5 -4
  26. package/server/opencode-cli.js +3 -3
  27. package/server/qwen-code-cli.js +3 -3
  28. package/server/routes/agent.js +11 -4
  29. package/server/services/telegram/control-center.js +28 -0
  30. package/server/services/telegram/translations.js +6 -0
@@ -34,7 +34,7 @@ function readCliIdleTimeoutMs() {
34
34
  }
35
35
 
36
36
  async function spawnQwen(command, options = {}, ws) {
37
- const { sessionId, projectPath, cwd, toolsSettings, permissionMode, images, sessionSummary } = options;
37
+ const { sessionId, projectPath, cwd, toolsSettings, permissionMode, images, sessionSummary, suppressNotifications = false } = options;
38
38
  let capturedSessionId = sessionId;
39
39
  let sessionCreatedSent = false;
40
40
  let assistantBlocks = [];
@@ -154,7 +154,7 @@ async function spawnQwen(command, options = {}, ws) {
154
154
 
155
155
  const finalSessionId = capturedSessionId || sessionId || processKey;
156
156
  if (code === 0 && !error) {
157
- notifyRunStopped({
157
+ if (!suppressNotifications) notifyRunStopped({
158
158
  userId: ws?.userId || null,
159
159
  provider: 'qwen',
160
160
  sessionId: finalSessionId,
@@ -164,7 +164,7 @@ async function spawnQwen(command, options = {}, ws) {
164
164
  return;
165
165
  }
166
166
 
167
- notifyRunFailed({
167
+ if (!suppressNotifications) notifyRunFailed({
168
168
  userId: ws?.userId || null,
169
169
  provider: 'qwen',
170
170
  sessionId: finalSessionId,
@@ -968,6 +968,7 @@ router.post('/', validateExternalApiKey, async (req, res) => {
968
968
  const permissionMode = ['default', 'acceptEdits', 'bypassPermissions', 'plan', 'auto_edit', 'yolo'].includes(requestedPermissionMode)
969
969
  ? requestedPermissionMode
970
970
  : null;
971
+ const suppressNotifications = req.body.suppressNotifications === true || req.body.suppressNotifications === 'true';
971
972
 
972
973
  // Parse stream and cleanup as booleans (handle string "true"/"false" from curl)
973
974
  const stream = req.body.stream === undefined ? true : (req.body.stream === true || req.body.stream === 'true');
@@ -1079,7 +1080,8 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1079
1080
  cwd: finalProjectPath,
1080
1081
  sessionId: sessionId || null,
1081
1082
  model: model,
1082
- permissionMode: permissionMode || 'bypassPermissions' // Bypass all permissions for API calls unless explicitly restricted
1083
+ permissionMode: permissionMode || 'bypassPermissions', // Bypass all permissions for API calls unless explicitly restricted
1084
+ suppressNotifications,
1083
1085
  }, writer);
1084
1086
 
1085
1087
  } else if (provider === 'cursor') {
@@ -1090,7 +1092,8 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1090
1092
  cwd: finalProjectPath,
1091
1093
  sessionId: sessionId || null,
1092
1094
  model: model || undefined,
1093
- skipPermissions: permissionMode ? permissionMode === 'bypassPermissions' || permissionMode === 'acceptEdits' || permissionMode === 'yolo' : true
1095
+ skipPermissions: permissionMode ? permissionMode === 'bypassPermissions' || permissionMode === 'acceptEdits' || permissionMode === 'yolo' : true,
1096
+ suppressNotifications,
1094
1097
  }, writer);
1095
1098
  } else if (provider === 'codex') {
1096
1099
  console.log('🤖 Starting Codex SDK session');
@@ -1100,7 +1103,8 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1100
1103
  cwd: finalProjectPath,
1101
1104
  sessionId: sessionId || null,
1102
1105
  model: model || getDefaultProviderModel('codex'),
1103
- permissionMode: permissionMode || 'bypassPermissions'
1106
+ permissionMode: permissionMode || 'bypassPermissions',
1107
+ suppressNotifications,
1104
1108
  }, writer);
1105
1109
  } else if (provider === 'gemini') {
1106
1110
  console.log('✨ Starting Gemini CLI session');
@@ -1111,7 +1115,8 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1111
1115
  sessionId: sessionId || null,
1112
1116
  model: model,
1113
1117
  permissionMode: permissionMode || undefined,
1114
- skipPermissions: permissionMode ? permissionMode === 'bypassPermissions' || permissionMode === 'acceptEdits' || permissionMode === 'yolo' : true
1118
+ skipPermissions: permissionMode ? permissionMode === 'bypassPermissions' || permissionMode === 'acceptEdits' || permissionMode === 'yolo' : true,
1119
+ suppressNotifications,
1115
1120
  }, writer);
1116
1121
  } else if (provider === 'qwen') {
1117
1122
  console.log('🐉 Starting Qwen Code CLI session');
@@ -1123,6 +1128,7 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1123
1128
  model: model,
1124
1129
  permissionMode: permissionMode || undefined,
1125
1130
  skipPermissions: permissionMode ? permissionMode === 'bypassPermissions' || permissionMode === 'acceptEdits' || permissionMode === 'yolo' : true,
1131
+ suppressNotifications,
1126
1132
  }, writer);
1127
1133
  } else if (provider === 'opencode') {
1128
1134
  console.log('🅾️ Starting OpenCode CLI session');
@@ -1138,6 +1144,7 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1138
1144
  denyPatterns: [],
1139
1145
  skipPermissions: permissionMode ? permissionMode === 'bypassPermissions' || permissionMode === 'acceptEdits' || permissionMode === 'yolo' : true,
1140
1146
  },
1147
+ suppressNotifications,
1141
1148
  }, writer);
1142
1149
  }
1143
1150
 
@@ -378,8 +378,34 @@ function activityTitle(activity) {
378
378
  return t(activity.lang, 'control.activity.agentTitle');
379
379
  }
380
380
 
381
+ function trimTelegramOutput(text, max, suffix = '') {
382
+ const value = String(text || '').trim();
383
+ const ending = String(suffix || '').trim();
384
+ if (value.length <= max) return value;
385
+ const room = Math.max(300, max - ending.length - 4);
386
+ return `${value.slice(0, room).trim()}\n\n${ending}`;
387
+ }
388
+
381
389
  function renderActivity(activity, { finalText = null } = {}) {
382
390
  const output = finalText || activity.output;
391
+ if (activity.type === 'agent' && output && !activity.error) {
392
+ if (activity.status === 'done') {
393
+ return trimTelegramOutput(
394
+ output,
395
+ 3400,
396
+ t(activity.lang, 'control.activity.outputTooLong'),
397
+ );
398
+ }
399
+
400
+ const footer = `⏳ ${t(activity.lang, 'control.activity.liveFooter', { elapsed: formatElapsed(activity.startedAt) })}`;
401
+ const body = trimTelegramOutput(
402
+ output,
403
+ 3200,
404
+ t(activity.lang, 'control.activity.outputShortened'),
405
+ );
406
+ return truncate(`${body}\n\n${footer}`, 3400);
407
+ }
408
+
383
409
  const lines = [
384
410
  `${activity.status === 'failed' ? '❌' : activity.status === 'done' ? '✅' : activity.status === 'running' ? '🔧' : '⏳'} ${activityTitle(activity)}`,
385
411
  '',
@@ -924,6 +950,7 @@ async function runAgent({ bot, chatId, link, prompt, activity = null }) {
924
950
  message: buildTelegramAgentPrompt(prompt, state),
925
951
  cleanup: false,
926
952
  permissionMode: 'default',
953
+ suppressNotifications: true,
927
954
  }, async (event) => {
928
955
  applyAgentStreamEvent(active, event);
929
956
  await editTelegramActivity({ bot, chatId, activity: active });
@@ -1136,6 +1163,7 @@ async function resolveTelegramAiIntent({ bot, chatId, link, text, activity }) {
1136
1163
  cleanup: false,
1137
1164
  stream: false,
1138
1165
  permissionMode: 'plan',
1166
+ suppressNotifications: true,
1139
1167
  },
1140
1168
  });
1141
1169
  const assistantText = extractAssistantText(response);
@@ -138,6 +138,9 @@ const EN = {
138
138
  'control.activity.toolDone': 'Tool completed',
139
139
  'control.activity.toolFailed': 'Tool failed',
140
140
  'control.activity.tokens': 'Tokens',
141
+ 'control.activity.liveFooter': 'Response is still streaming · {{elapsed}}',
142
+ 'control.activity.outputShortened': 'Telegram output was shortened while the run continues.',
143
+ 'control.activity.outputTooLong': 'Long response shortened for Telegram. Open the session in Pixcode for the full output.',
141
144
  'notification.taskDone': '✅ {{title}} — task completed.',
142
145
  'notification.taskFailed': '⚠️ {{title}} — task failed: {{error}}',
143
146
  'notification.actionRequired': '❗ {{title}} — action required.',
@@ -276,6 +279,9 @@ const TR = {
276
279
  'control.activity.toolDone': 'Tool tamamlandı',
277
280
  'control.activity.toolFailed': 'Tool başarısız',
278
281
  'control.activity.tokens': 'Token',
282
+ 'control.activity.liveFooter': 'Yanıt devam ediyor · {{elapsed}}',
283
+ 'control.activity.outputShortened': 'Telegram çıktısı çalışma devam ederken kısaltıldı.',
284
+ 'control.activity.outputTooLong': 'Uzun yanıt Telegram için kısaltıldı. Tam çıktı için Pixcode oturumunu aç.',
279
285
  'notification.taskDone': '✅ {{title}} — görev tamamlandı.',
280
286
  'notification.taskFailed': '⚠️ {{title}} — görev başarısız: {{error}}',
281
287
  'notification.actionRequired': '❗ {{title}} — işlem gerekli.',