crewly 1.2.7 → 1.2.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 (83) hide show
  1. package/dist/backend/backend/src/constants.d.ts +9 -0
  2. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  3. package/dist/backend/backend/src/constants.js +9 -0
  4. package/dist/backend/backend/src/constants.js.map +1 -1
  5. package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
  6. package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +6 -3
  7. package/dist/backend/backend/src/controllers/messaging/messenger.routes.js.map +1 -1
  8. package/dist/backend/backend/src/controllers/settings/settings.controller.d.ts.map +1 -1
  9. package/dist/backend/backend/src/controllers/settings/settings.controller.js +97 -2
  10. package/dist/backend/backend/src/controllers/settings/settings.controller.js.map +1 -1
  11. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
  12. package/dist/backend/backend/src/controllers/team/team.controller.js +149 -1
  13. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
  14. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  15. package/dist/backend/backend/src/services/agent/agent-registration.service.js +111 -82
  16. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  17. package/dist/backend/backend/src/services/agent/auditor-scheduler.service.d.ts.map +1 -1
  18. package/dist/backend/backend/src/services/agent/auditor-scheduler.service.js +14 -3
  19. package/dist/backend/backend/src/services/agent/auditor-scheduler.service.js.map +1 -1
  20. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +16 -2
  21. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +1 -1
  22. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +52 -5
  23. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +1 -1
  24. package/dist/backend/backend/src/services/agent/gemini-runtime.service.d.ts.map +1 -1
  25. package/dist/backend/backend/src/services/agent/gemini-runtime.service.js +22 -9
  26. package/dist/backend/backend/src/services/agent/gemini-runtime.service.js.map +1 -1
  27. package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -1
  28. package/dist/backend/backend/src/services/event-bus/event-bus.service.js +4 -3
  29. package/dist/backend/backend/src/services/event-bus/event-bus.service.js.map +1 -1
  30. package/dist/backend/backend/src/services/messaging/adapters/google-chat-messenger.adapter.d.ts +58 -2
  31. package/dist/backend/backend/src/services/messaging/adapters/google-chat-messenger.adapter.d.ts.map +1 -1
  32. package/dist/backend/backend/src/services/messaging/adapters/google-chat-messenger.adapter.js +158 -7
  33. package/dist/backend/backend/src/services/messaging/adapters/google-chat-messenger.adapter.js.map +1 -1
  34. package/dist/backend/backend/src/services/messaging/response-router.service.d.ts +12 -0
  35. package/dist/backend/backend/src/services/messaging/response-router.service.d.ts.map +1 -1
  36. package/dist/backend/backend/src/services/messaging/response-router.service.js +27 -42
  37. package/dist/backend/backend/src/services/messaging/response-router.service.js.map +1 -1
  38. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.d.ts.map +1 -1
  39. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js +12 -3
  40. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js.map +1 -1
  41. package/dist/backend/backend/src/services/settings/settings.service.d.ts +9 -1
  42. package/dist/backend/backend/src/services/settings/settings.service.d.ts.map +1 -1
  43. package/dist/backend/backend/src/services/settings/settings.service.js +12 -1
  44. package/dist/backend/backend/src/services/settings/settings.service.js.map +1 -1
  45. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.d.ts.map +1 -1
  46. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.js +13 -0
  47. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.js.map +1 -1
  48. package/dist/backend/backend/src/types/chat.types.d.ts +1 -1
  49. package/dist/backend/backend/src/types/chat.types.d.ts.map +1 -1
  50. package/dist/backend/backend/src/types/chat.types.js +1 -1
  51. package/dist/backend/backend/src/types/chat.types.js.map +1 -1
  52. package/dist/backend/backend/src/types/settings.types.d.ts +93 -0
  53. package/dist/backend/backend/src/types/settings.types.d.ts.map +1 -1
  54. package/dist/backend/backend/src/types/settings.types.js +131 -0
  55. package/dist/backend/backend/src/types/settings.types.js.map +1 -1
  56. package/dist/backend/backend/src/types/skill.types.js +2 -2
  57. package/dist/backend/backend/src/types/skill.types.js.map +1 -1
  58. package/dist/backend/backend/src/utils/format-error.d.ts +8 -0
  59. package/dist/backend/backend/src/utils/format-error.d.ts.map +1 -0
  60. package/dist/backend/backend/src/utils/format-error.js +10 -0
  61. package/dist/backend/backend/src/utils/format-error.js.map +1 -0
  62. package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
  63. package/dist/backend/backend/src/websocket/terminal.gateway.js +8 -6
  64. package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
  65. package/dist/cli/backend/src/constants.d.ts +9 -0
  66. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  67. package/dist/cli/backend/src/constants.js +9 -0
  68. package/dist/cli/backend/src/constants.js.map +1 -1
  69. package/dist/cli/backend/src/types/chat.types.d.ts +1 -1
  70. package/dist/cli/backend/src/types/chat.types.d.ts.map +1 -1
  71. package/dist/cli/backend/src/types/chat.types.js +1 -1
  72. package/dist/cli/backend/src/types/chat.types.js.map +1 -1
  73. package/dist/cli/backend/src/types/settings.types.d.ts +93 -0
  74. package/dist/cli/backend/src/types/settings.types.d.ts.map +1 -1
  75. package/dist/cli/backend/src/types/settings.types.js +131 -0
  76. package/dist/cli/backend/src/types/settings.types.js.map +1 -1
  77. package/dist/cli/backend/src/types/skill.types.js +2 -2
  78. package/dist/cli/backend/src/types/skill.types.js.map +1 -1
  79. package/frontend/dist/assets/index-58509b6a.js +4919 -0
  80. package/frontend/dist/assets/{index-dee3a3a9.css → index-ddb38eb0.css} +1 -1
  81. package/frontend/dist/index.html +2 -2
  82. package/package.json +1 -1
  83. package/frontend/dist/assets/index-5cf8820f.js +0 -4919
@@ -16,7 +16,7 @@ import { SubAgentMessageQueue } from '../messaging/sub-agent-message-queue.servi
16
16
  import { AgentSuspendService } from './agent-suspend.service.js';
17
17
  import { PromptBuilderService } from '../ai/prompt-builder.service.js';
18
18
  import { stripAnsiCodes } from '../../utils/terminal-output.utils.js';
19
- import { isPromptLine, containsSpinnerOrWorkingIndicator, containsProcessingIndicator, containsBusyStatusBar, containsRewindMode, containsGeminiProcessingKeywords, extractChatPrefix, stripTuiLineBorders, matchTuiPromptLine, } from '../../utils/terminal-string-ops.js';
19
+ import { isPromptLine, containsSpinnerOrWorkingIndicator, containsProcessingIndicator, containsBusyStatusBar, containsRewindMode, extractChatPrefix, stripTuiLineBorders, matchTuiPromptLine, } from '../../utils/terminal-string-ops.js';
20
20
  import { PtyActivityTrackerService } from './pty-activity-tracker.service.js';
21
21
  /**
22
22
  * Service responsible for the complex, multi-step process of agent initialization and registration.
@@ -1617,13 +1617,24 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
1617
1617
  await sessionHelper.setEnvironmentVariable(sessionName, ENV_CONSTANTS.CREWLY_SESSION_NAME, sessionName);
1618
1618
  await sessionHelper.setEnvironmentVariable(sessionName, ENV_CONSTANTS.CREWLY_ROLE, role);
1619
1619
  await sessionHelper.setEnvironmentVariable(sessionName, ENV_CONSTANTS.CREWLY_API_URL, `http://localhost:${WEB_CONSTANTS.PORTS.BACKEND}`);
1620
- // Pass Gemini API key to gemini-cli agents so they authenticate
1621
- // with the paid API key instead of the free-tier Google login.
1622
- if (runtimeType === RUNTIME_TYPES.GEMINI_CLI) {
1623
- const geminiApiKey = process.env[ENV_CONSTANTS.GEMINI_API_KEY];
1624
- if (geminiApiKey) {
1625
- await sessionHelper.setEnvironmentVariable(sessionName, ENV_CONSTANTS.GEMINI_API_KEY, geminiApiKey);
1626
- }
1620
+ // Inject API keys from settings (with override chain) for all runtimes
1621
+ const settingsService = getSettingsService();
1622
+ const runtimeContext = { runtime: runtimeType };
1623
+ // Gemini key — needed by gemini-cli and crewly-agent
1624
+ const geminiKey = await settingsService.getApiKey('gemini', runtimeContext);
1625
+ if (geminiKey) {
1626
+ await sessionHelper.setEnvironmentVariable(sessionName, 'GOOGLE_GENERATIVE_AI_API_KEY', geminiKey);
1627
+ await sessionHelper.setEnvironmentVariable(sessionName, ENV_CONSTANTS.GEMINI_API_KEY, geminiKey);
1628
+ }
1629
+ // Anthropic key — needed by claude-code and crewly-agent
1630
+ const anthropicKey = await settingsService.getApiKey('anthropic', runtimeContext);
1631
+ if (anthropicKey) {
1632
+ await sessionHelper.setEnvironmentVariable(sessionName, 'ANTHROPIC_API_KEY', anthropicKey);
1633
+ }
1634
+ // OpenAI key — needed by codex-cli and crewly-agent
1635
+ const openaiKey = await settingsService.getApiKey('openai', runtimeContext);
1636
+ if (openaiKey) {
1637
+ await sessionHelper.setEnvironmentVariable(sessionName, 'OPENAI_API_KEY', openaiKey);
1627
1638
  }
1628
1639
  this.logger.info('Agent session created and environment variables set, initializing with registration', {
1629
1640
  sessionName,
@@ -1849,8 +1860,13 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
1849
1860
  error: 'Runtime has exited — no child process in session',
1850
1861
  };
1851
1862
  }
1852
- // Use robust message delivery with proper waiting mechanism
1853
- const delivered = await this.sendMessageWithRetry(sessionName, message, 3, runtimeType);
1863
+ // Use robust message delivery with proper waiting mechanism.
1864
+ // Gemini CLI: reduce maxAttempts to 1 — the heavy retry loop with
1865
+ // Tab+Enter recovery causes visible error spam while messages are
1866
+ // actually delivered successfully. The PTY write is reliable; it's
1867
+ // the verification that misjudges delivery as failed.
1868
+ const maxDeliveryAttempts = runtimeType === RUNTIME_TYPES.GEMINI_CLI ? 1 : 3;
1869
+ const delivered = await this.sendMessageWithRetry(sessionName, message, maxDeliveryAttempts, runtimeType);
1854
1870
  if (!delivered) {
1855
1871
  // Check if the agent is actively processing (busy) — the queue
1856
1872
  // processor can re-queue instead of permanently failing the message.
@@ -2462,94 +2478,107 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
2462
2478
  }
2463
2479
  }
2464
2480
  else {
2465
- // --- Phase 1: Direct stuck-at-prompt detection ---
2466
- // Check if our message text is literally sitting on the `> ` prompt
2467
- // line. This is the definitive signal that Enter was not pressed or
2468
- // was silently consumed by the TUI. Unlike output-change detection,
2469
- // this has no false positives from TUI redraws or historical text.
2470
- const stuckAtPrompt = this.isTextStuckAtTuiPrompt(sessionName, message);
2471
- if (stuckAtPrompt) {
2472
- // Attempt immediate recovery: press Enter to submit the text
2473
- const recovered = await this.recoverStuckTuiMessage(sessionName, message);
2474
- if (recovered) {
2475
- this.logger.info('Message recovered via Enter re-press', {
2481
+ // --- Gemini CLI: lightweight verification ---
2482
+ // Gemini CLI's PTY write is reliable. The aggressive verification
2483
+ // (stuck detection + Tab+Enter recovery + output-change diff) causes
2484
+ // false "stuck" judgments that trigger visible retry error spam even
2485
+ // when the message was successfully delivered (#retry-storm fix).
2486
+ //
2487
+ // Strategy: only check for the definitive stuck signal (message text
2488
+ // literally sitting on the `> ` prompt line). If not stuck, trust the
2489
+ // write. Skip the output-change heuristics that cause false negatives.
2490
+ const isGemini = runtimeType === RUNTIME_TYPES.GEMINI_CLI;
2491
+ if (isGemini) {
2492
+ // Single stuck-at-prompt check — the only reliable failure signal
2493
+ const stuckAtPrompt = this.isTextStuckAtTuiPrompt(sessionName, message);
2494
+ if (stuckAtPrompt) {
2495
+ const recovered = await this.recoverStuckTuiMessage(sessionName, message);
2496
+ if (recovered) {
2497
+ this.logger.info('Gemini CLI: message recovered via Enter re-press', {
2498
+ sessionName,
2499
+ attempt,
2500
+ });
2501
+ return true;
2502
+ }
2503
+ this.logger.warn('Gemini CLI: message still stuck after Enter recovery', {
2504
+ sessionName,
2505
+ attempt,
2506
+ });
2507
+ // Fall through to retry cleanup below
2508
+ }
2509
+ else {
2510
+ // Not stuck at prompt — PTY write succeeded, trust delivery.
2511
+ // The old code did output-change detection here, but TUI redraws
2512
+ // and minimal length diffs caused false "not delivered" verdicts.
2513
+ this.logger.debug('Gemini CLI: message not stuck at prompt — delivery trusted', {
2476
2514
  sessionName,
2477
2515
  attempt,
2478
2516
  });
2479
2517
  return true;
2480
2518
  }
2481
- // Still stuck after recovery — fall through to retry with cleanup
2482
- this.logger.warn('Message still stuck after Enter recovery, will retry', {
2483
- sessionName,
2484
- attempt,
2485
- });
2486
- // Skip the output-change check — we know it's stuck
2487
2519
  }
2488
2520
  else {
2489
- // --- Phase 2: Output-change detection ---
2490
- // Text is NOT on the prompt line. Either it was delivered (Enter
2491
- // worked) or it was never written (TUI was defocused and the Ink
2492
- // framework consumed the text silently). Compare output snapshots.
2493
- const afterOutput = sessionHelper.capturePane(sessionName, 20);
2494
- const lengthDiff = afterOutput.length - beforeLength;
2495
- const contentChanged = beforeOutput !== afterOutput;
2496
- // CRITICAL: Only check for processing indicators in NEW content
2497
- // (the diff between before and after). Checking the full afterOutput
2498
- // causes false positives because words like "generating", "searching"
2499
- // commonly appear in the agent's previous response text visible in
2500
- // the 20-line capture.
2501
- let newContent = '';
2502
- if (contentChanged && afterOutput.length > beforeOutput.length) {
2503
- newContent = afterOutput.slice(beforeLength);
2504
- }
2505
- else if (contentChanged) {
2506
- const beforeLines = new Set(beforeOutput.split('\n'));
2507
- newContent = afterOutput
2508
- .split('\n')
2509
- .filter((line) => !beforeLines.has(line))
2510
- .join('\n');
2521
+ // --- Non-Gemini TUI runtimes: full verification ---
2522
+ // Phase 1: Direct stuck-at-prompt detection
2523
+ const stuckAtPrompt = this.isTextStuckAtTuiPrompt(sessionName, message);
2524
+ if (stuckAtPrompt) {
2525
+ const recovered = await this.recoverStuckTuiMessage(sessionName, message);
2526
+ if (recovered) {
2527
+ this.logger.info('Message recovered via Enter re-press', {
2528
+ sessionName,
2529
+ attempt,
2530
+ });
2531
+ return true;
2532
+ }
2533
+ this.logger.warn('Message still stuck after Enter recovery, will retry', {
2534
+ sessionName,
2535
+ attempt,
2536
+ });
2511
2537
  }
2512
- const hasProcessingIndicators = containsProcessingIndicator(newContent || afterOutput.slice(-500));
2513
- const hasGeminiIndicators = newContent.length > 0
2514
- && containsGeminiProcessingKeywords(newContent);
2515
- const significantLengthChange = Math.abs(lengthDiff) > 10;
2516
- // For Gemini CLI, contentChanged alone is sufficient evidence of
2517
- // delivery. The TUI redraws minimally (lengthDiff can be as low as
2518
- // 1-2 chars) when processing starts, so requiring significantLengthChange
2519
- // causes false "stuck" detection. False "stuck" + Ctrl+C kills the CLI.
2520
- const isGemini = runtimeType === RUNTIME_TYPES.GEMINI_CLI;
2521
- const delivered = (lengthDiff > 20)
2522
- || (contentChanged && significantLengthChange)
2523
- || (contentChanged && isGemini)
2524
- || hasProcessingIndicators
2525
- || hasGeminiIndicators;
2526
- if (delivered) {
2527
- // Log at warn level when verification passed on weak signals
2528
- // (output length change only, no explicit processing indicators)
2529
- // so future false positives are traceable in logs.
2530
- const hasStrongSignal = hasProcessingIndicators || hasGeminiIndicators;
2531
- const logLevel = hasStrongSignal ? 'debug' : 'warn';
2532
- this.logger[logLevel](`Message delivery verified (${hasStrongSignal ? 'strong' : 'weak'} signal)`, {
2538
+ else {
2539
+ // Phase 2: Output-change detection
2540
+ const afterOutput = sessionHelper.capturePane(sessionName, 20);
2541
+ const lengthDiff = afterOutput.length - beforeLength;
2542
+ const contentChanged = beforeOutput !== afterOutput;
2543
+ let newContent = '';
2544
+ if (contentChanged && afterOutput.length > beforeOutput.length) {
2545
+ newContent = afterOutput.slice(beforeLength);
2546
+ }
2547
+ else if (contentChanged) {
2548
+ const beforeLines = new Set(beforeOutput.split('\n'));
2549
+ newContent = afterOutput
2550
+ .split('\n')
2551
+ .filter((line) => !beforeLines.has(line))
2552
+ .join('\n');
2553
+ }
2554
+ const hasProcessingIndicators = containsProcessingIndicator(newContent || afterOutput.slice(-500));
2555
+ const significantLengthChange = Math.abs(lengthDiff) > 10;
2556
+ const delivered = (lengthDiff > 20)
2557
+ || (contentChanged && significantLengthChange)
2558
+ || hasProcessingIndicators;
2559
+ if (delivered) {
2560
+ const hasStrongSignal = hasProcessingIndicators;
2561
+ const logLevel = hasStrongSignal ? 'debug' : 'warn';
2562
+ this.logger[logLevel](`Message delivery verified (${hasStrongSignal ? 'strong' : 'weak'} signal)`, {
2563
+ sessionName,
2564
+ attempt,
2565
+ lengthDiff,
2566
+ contentChanged,
2567
+ hasProcessingIndicators,
2568
+ newContentLength: newContent.length,
2569
+ signal: hasStrongSignal ? 'processing-indicators' : 'output-length-change-only',
2570
+ });
2571
+ return true;
2572
+ }
2573
+ this.logger.warn('TUI output did not change after send — message may not have been accepted', {
2533
2574
  sessionName,
2534
2575
  attempt,
2535
2576
  lengthDiff,
2536
2577
  contentChanged,
2537
2578
  hasProcessingIndicators,
2538
- hasGeminiIndicators,
2539
2579
  newContentLength: newContent.length,
2540
- signal: hasStrongSignal ? 'processing-indicators' : 'output-length-change-only',
2541
2580
  });
2542
- return true;
2543
2581
  }
2544
- this.logger.warn('TUI output did not change after send — message may not have been accepted', {
2545
- sessionName,
2546
- attempt,
2547
- lengthDiff,
2548
- contentChanged,
2549
- hasProcessingIndicators,
2550
- hasGeminiIndicators,
2551
- newContentLength: newContent.length,
2552
- });
2553
2582
  }
2554
2583
  }
2555
2584
  // Message stuck at prompt — clear line and retry.