@bubblelab/bubble-core 0.1.212 → 0.1.213

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 (95) hide show
  1. package/dist/bubble-bundle.d.ts +150 -150
  2. package/dist/bubbles/service-bubble/agi-inc.d.ts +112 -112
  3. package/dist/bubbles/service-bubble/ai-agent.d.ts +72 -72
  4. package/dist/bubbles/service-bubble/ai-agent.d.ts.map +1 -1
  5. package/dist/bubbles/service-bubble/ai-agent.js +192 -25
  6. package/dist/bubbles/service-bubble/ai-agent.js.map +1 -1
  7. package/dist/bubbles/service-bubble/airtable.d.ts +158 -158
  8. package/dist/bubbles/service-bubble/apify/apify.d.ts +26 -26
  9. package/dist/bubbles/service-bubble/ashby/ashby.d.ts +90 -90
  10. package/dist/bubbles/service-bubble/ashby/ashby.schema.d.ts +70 -70
  11. package/dist/bubbles/service-bubble/assembled/assembled.d.ts +55 -55
  12. package/dist/bubbles/service-bubble/assembled/assembled.schema.d.ts +24 -24
  13. package/dist/bubbles/service-bubble/attio/attio.d.ts +66 -66
  14. package/dist/bubbles/service-bubble/attio/attio.schema.d.ts +2 -2
  15. package/dist/bubbles/service-bubble/browserbase/browserbase.d.ts +58 -58
  16. package/dist/bubbles/service-bubble/browserbase/browserbase.schema.d.ts +12 -12
  17. package/dist/bubbles/service-bubble/confluence/confluence.d.ts +43 -43
  18. package/dist/bubbles/service-bubble/confluence/confluence.schema.d.ts +4 -4
  19. package/dist/bubbles/service-bubble/crustdata/crustdata.d.ts +94 -94
  20. package/dist/bubbles/service-bubble/crustdata/crustdata.schema.d.ts +158 -158
  21. package/dist/bubbles/service-bubble/eleven-labs.d.ts +48 -48
  22. package/dist/bubbles/service-bubble/firecrawl.d.ts +284 -284
  23. package/dist/bubbles/service-bubble/followupboss.d.ts +260 -260
  24. package/dist/bubbles/service-bubble/fullenrich/fullenrich.d.ts +44 -44
  25. package/dist/bubbles/service-bubble/fullenrich/fullenrich.schema.d.ts +124 -124
  26. package/dist/bubbles/service-bubble/github.d.ts +102 -102
  27. package/dist/bubbles/service-bubble/gmail.d.ts +238 -238
  28. package/dist/bubbles/service-bubble/google-calendar.d.ts +132 -132
  29. package/dist/bubbles/service-bubble/google-drive.d.ts +146 -146
  30. package/dist/bubbles/service-bubble/google-sheets/google-sheets.d.ts +52 -52
  31. package/dist/bubbles/service-bubble/google-sheets/google-sheets.schema.d.ts +26 -26
  32. package/dist/bubbles/service-bubble/hello-world.d.ts +4 -4
  33. package/dist/bubbles/service-bubble/http.d.ts +10 -10
  34. package/dist/bubbles/service-bubble/hubspot/hubspot.d.ts +20 -20
  35. package/dist/bubbles/service-bubble/insforge-db.d.ts +12 -12
  36. package/dist/bubbles/service-bubble/jira/jira.d.ts +62 -62
  37. package/dist/bubbles/service-bubble/jira/jira.schema.d.ts +31 -31
  38. package/dist/bubbles/service-bubble/linear/linear.d.ts +44 -44
  39. package/dist/bubbles/service-bubble/linear/linear.schema.d.ts +15 -15
  40. package/dist/bubbles/service-bubble/notion/notion.d.ts +184 -184
  41. package/dist/bubbles/service-bubble/postgresql.d.ts +12 -12
  42. package/dist/bubbles/service-bubble/posthog/posthog.d.ts +33 -33
  43. package/dist/bubbles/service-bubble/posthog/posthog.schema.d.ts +30 -30
  44. package/dist/bubbles/service-bubble/resend.d.ts +24 -24
  45. package/dist/bubbles/service-bubble/s3/s3.d.ts +44 -44
  46. package/dist/bubbles/service-bubble/s3/s3.schema.d.ts +14 -14
  47. package/dist/bubbles/service-bubble/sendsafely/sendsafely.d.ts +18 -18
  48. package/dist/bubbles/service-bubble/sendsafely/sendsafely.schema.d.ts +6 -6
  49. package/dist/bubbles/service-bubble/slack/slack.d.ts +224 -224
  50. package/dist/bubbles/service-bubble/storage.d.ts +88 -88
  51. package/dist/bubbles/service-bubble/stripe/stripe.d.ts +123 -123
  52. package/dist/bubbles/service-bubble/stripe/stripe.schema.d.ts +87 -87
  53. package/dist/bubbles/service-bubble/telegram.d.ts +120 -120
  54. package/dist/bubbles/tool-bubble/amazon-shopping-tool/amazon-shopping-tool.d.ts +28 -28
  55. package/dist/bubbles/tool-bubble/amazon-shopping-tool/amazon-shopping-tool.schema.d.ts +5 -5
  56. package/dist/bubbles/tool-bubble/browser-tools/linkedin-accept-invitations/tool.d.ts +4 -4
  57. package/dist/bubbles/tool-bubble/browser-tools/linkedin-connection/tool.d.ts +4 -4
  58. package/dist/bubbles/tool-bubble/browser-tools/linkedin-received-invitations/tool.d.ts +4 -4
  59. package/dist/bubbles/tool-bubble/browser-tools/linkedin-sent-invitations/tool.d.ts +4 -4
  60. package/dist/bubbles/tool-bubble/bubbleflow-validation-tool.d.ts +4 -4
  61. package/dist/bubbles/tool-bubble/chart-js-tool.d.ts +8 -8
  62. package/dist/bubbles/tool-bubble/code-edit-tool.d.ts +4 -4
  63. package/dist/bubbles/tool-bubble/company-enrichment-tool.d.ts +4 -4
  64. package/dist/bubbles/tool-bubble/get-bubble-details-tool.d.ts +4 -4
  65. package/dist/bubbles/tool-bubble/get-trigger-detail-tool.d.ts +4 -4
  66. package/dist/bubbles/tool-bubble/google-maps-tool.d.ts +8 -8
  67. package/dist/bubbles/tool-bubble/instagram-tool.d.ts +8 -8
  68. package/dist/bubbles/tool-bubble/linkedin-tool.d.ts +345 -345
  69. package/dist/bubbles/tool-bubble/list-airtable-bases-tool.d.ts +4 -4
  70. package/dist/bubbles/tool-bubble/list-airtable-tables-tool.d.ts +4 -4
  71. package/dist/bubbles/tool-bubble/list-bubbles-tool.d.ts +4 -4
  72. package/dist/bubbles/tool-bubble/list-capabilities-tool.d.ts +4 -4
  73. package/dist/bubbles/tool-bubble/people-search-tool.d.ts +4 -4
  74. package/dist/bubbles/tool-bubble/reddit-scrape-tool.d.ts +4 -4
  75. package/dist/bubbles/tool-bubble/research-agent-tool.d.ts +4 -4
  76. package/dist/bubbles/tool-bubble/sql-query-tool.d.ts +8 -8
  77. package/dist/bubbles/tool-bubble/tiktok-tool.d.ts +60 -60
  78. package/dist/bubbles/tool-bubble/tool-template.d.ts +4 -4
  79. package/dist/bubbles/tool-bubble/twitter-tool.d.ts +132 -132
  80. package/dist/bubbles/tool-bubble/web-crawl-tool.d.ts +8 -8
  81. package/dist/bubbles/tool-bubble/web-extract-tool.d.ts +8 -8
  82. package/dist/bubbles/tool-bubble/web-scrape-tool.d.ts +8 -8
  83. package/dist/bubbles/tool-bubble/web-search-tool.d.ts +8 -8
  84. package/dist/bubbles/tool-bubble/yc-scraper-tool.d.ts +12 -12
  85. package/dist/bubbles/tool-bubble/youtube-tool.d.ts +28 -28
  86. package/dist/bubbles/workflow-bubble/database-analyzer.workflow.d.ts +4 -4
  87. package/dist/bubbles/workflow-bubble/generate-document.workflow.d.ts +16 -16
  88. package/dist/bubbles/workflow-bubble/parse-document.workflow.d.ts +8 -8
  89. package/dist/bubbles/workflow-bubble/pdf-form-operations.workflow.d.ts +58 -58
  90. package/dist/bubbles/workflow-bubble/pdf-ocr.workflow.d.ts +8 -8
  91. package/dist/bubbles/workflow-bubble/slack-data-assistant.workflow.d.ts +4 -4
  92. package/dist/bubbles/workflow-bubble/slack-formatter-agent.d.ts +12 -12
  93. package/dist/bubbles/workflow-bubble/slack-notifier.workflow.d.ts +4 -4
  94. package/dist/bubbles.json +1 -1
  95. package/package.json +2 -2
@@ -1163,8 +1163,9 @@ export class AIAgentBubble extends ServiceBubble {
1163
1163
  capabilityTask: task,
1164
1164
  };
1165
1165
  this._trace('use-capability', `snapshotted master state before delegating`, {
1166
- masterMsgCount: this._currentGraphMessages.length,
1166
+ masterMessageCount: this._currentGraphMessages.length,
1167
1167
  capabilityId,
1168
+ capabilityTask: task,
1168
1169
  });
1169
1170
  }
1170
1171
  const subAgent = new AIAgentBubble({
@@ -1460,6 +1461,19 @@ export class AIAgentBubble extends ServiceBubble {
1460
1461
  messages: currentMessages,
1461
1462
  bubbleContext: this.context,
1462
1463
  });
1464
+ // Trace hook result
1465
+ if (beforeHook) {
1466
+ this._trace('hook', `beforeToolCall:${toolCall.name}`, {
1467
+ toolName: toolCall.name,
1468
+ shouldSkip: hookResult_before?.shouldSkip ?? false,
1469
+ messagesModified: !!hookResult_before?.messages,
1470
+ });
1471
+ }
1472
+ this._trace('tool', `start:${toolCall.name}`, {
1473
+ toolName: toolCall.name,
1474
+ toolCallId: toolCall.id ?? '',
1475
+ input: toolCall.args,
1476
+ });
1463
1477
  this.streamingCallback?.({
1464
1478
  type: 'tool_call_start',
1465
1479
  data: {
@@ -1480,6 +1494,13 @@ export class AIAgentBubble extends ServiceBubble {
1480
1494
  toolCall.args = hookResult_before.toolInput;
1481
1495
  // If hook requests skipping, create synthetic ToolMessage and stop agent loop
1482
1496
  if (hookResult_before.shouldSkip) {
1497
+ this._trace('tool', `skipped:${toolCall.name}`, {
1498
+ toolName: toolCall.name,
1499
+ toolCallId: toolCall.id ?? '',
1500
+ input: toolCall.args,
1501
+ skipMessage: hookResult_before.skipMessage || 'Tool execution was skipped.',
1502
+ reason: 'beforeToolCall hook requested skip',
1503
+ });
1483
1504
  const skipMsg = new ToolMessage({
1484
1505
  content: hookResult_before.skipMessage || 'Tool execution was skipped.',
1485
1506
  tool_call_id: toolCall.id,
@@ -1507,6 +1528,14 @@ export class AIAgentBubble extends ServiceBubble {
1507
1528
  });
1508
1529
  toolMessages.push(toolMessage);
1509
1530
  currentMessages = [...currentMessages, toolMessage];
1531
+ const toolDurationMs = Date.now() - startTime;
1532
+ this._trace('tool', `complete:${toolCall.name}`, {
1533
+ toolName: toolCall.name,
1534
+ toolCallId: toolCall.id ?? '',
1535
+ input: toolCall.args,
1536
+ output: toolOutput,
1537
+ durationMs: toolDurationMs,
1538
+ });
1510
1539
  // Call afterToolCall hook — capability-scoped hook takes priority, then global
1511
1540
  const afterHook = this.capabilityAfterHooks.get(toolCall.name) ??
1512
1541
  this.afterToolCallHook;
@@ -1517,6 +1546,14 @@ export class AIAgentBubble extends ServiceBubble {
1517
1546
  messages: currentMessages,
1518
1547
  bubbleContext: this.context,
1519
1548
  });
1549
+ // Trace hook result
1550
+ if (afterHook) {
1551
+ this._trace('hook', `afterToolCall:${toolCall.name}`, {
1552
+ toolName: toolCall.name,
1553
+ shouldStop: hookResult_after?.shouldStop ?? false,
1554
+ messagesModified: !!hookResult_after?.messages,
1555
+ });
1556
+ }
1520
1557
  // If hook returns modified messages, update current messages
1521
1558
  if (hookResult_after) {
1522
1559
  if (hookResult_after.messages) {
@@ -1535,7 +1572,7 @@ export class AIAgentBubble extends ServiceBubble {
1535
1572
  input: toolCall.args,
1536
1573
  tool: toolCall.name,
1537
1574
  output: toolOutput,
1538
- duration: Date.now() - startTime,
1575
+ duration: toolDurationMs,
1539
1576
  variableId: this.context?.variableId,
1540
1577
  },
1541
1578
  });
@@ -1543,6 +1580,13 @@ export class AIAgentBubble extends ServiceBubble {
1543
1580
  catch (error) {
1544
1581
  console.error(`Error executing tool ${toolCall.name}:`, error);
1545
1582
  const errorContent = `Error: ${error instanceof Error ? error.message : 'Unknown error'}`;
1583
+ this._trace('tool', `error:${toolCall.name}`, {
1584
+ toolName: toolCall.name,
1585
+ toolCallId: toolCall.id ?? '',
1586
+ input: toolCall.args,
1587
+ error: errorContent,
1588
+ durationMs: Date.now() - startTime,
1589
+ });
1546
1590
  const errorMessage = new ToolMessage({
1547
1591
  content: errorContent,
1548
1592
  tool_call_id: toolCall.id,
@@ -1584,17 +1628,27 @@ export class AIAgentBubble extends ServiceBubble {
1584
1628
  // Define the agent node
1585
1629
  const agentNode = async ({ messages }) => {
1586
1630
  this._trace('agentNode', `LLM CALL`, {
1587
- msgCount: messages.length,
1588
- lastMsgType: messages[messages.length - 1]?._getType(),
1589
- lastMsgPreview: (() => {
1590
- const last = messages[messages.length - 1];
1591
- if (!last)
1592
- return '';
1593
- const content = typeof last.content === 'string'
1594
- ? last.content
1595
- : JSON.stringify(last.content);
1596
- return content.slice(0, 120);
1597
- })(),
1631
+ model: this.params.model.model,
1632
+ temperature: this.params.model.temperature,
1633
+ messageCount: messages.length,
1634
+ messages: messages.map((m) => {
1635
+ const role = m._getType();
1636
+ const content = typeof m.content === 'string'
1637
+ ? m.content
1638
+ : JSON.stringify(m.content);
1639
+ const entry = { role, content };
1640
+ if ('tool_calls' in m && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
1641
+ entry.toolCalls = m.tool_calls.map((tc) => ({
1642
+ name: tc.name,
1643
+ id: tc.id,
1644
+ args: tc.args,
1645
+ }));
1646
+ }
1647
+ if ('tool_call_id' in m) {
1648
+ entry.toolCallId = m.tool_call_id;
1649
+ }
1650
+ return entry;
1651
+ }),
1598
1652
  });
1599
1653
  // systemPrompt is already enhanced by beforeAction() if expectedOutputSchema was provided
1600
1654
  // Use cache_control for Anthropic models to cache the system prompt across iterations
@@ -1702,11 +1756,45 @@ export class AIAgentBubble extends ServiceBubble {
1702
1756
  },
1703
1757
  ],
1704
1758
  });
1759
+ this._trace('agentNode', 'LLM RESPONSE', {
1760
+ content: typeof response.content === 'string'
1761
+ ? response.content
1762
+ : JSON.stringify(response.content),
1763
+ toolCalls: ('tool_calls' in response && Array.isArray(response.tool_calls))
1764
+ ? response.tool_calls.map((tc) => ({
1765
+ name: tc.name, id: tc.id, args: tc.args,
1766
+ }))
1767
+ : undefined,
1768
+ tokenUsage: response.usage_metadata
1769
+ ? {
1770
+ inputTokens: response.usage_metadata.input_tokens,
1771
+ outputTokens: response.usage_metadata.output_tokens,
1772
+ totalTokens: response.usage_metadata.total_tokens,
1773
+ }
1774
+ : undefined,
1775
+ });
1705
1776
  return { messages: [response] };
1706
1777
  }
1707
1778
  else {
1708
1779
  // Non-streaming fallback
1709
1780
  const response = await modelWithTools.invoke(allMessages);
1781
+ this._trace('agentNode', 'LLM RESPONSE', {
1782
+ content: typeof response.content === 'string'
1783
+ ? response.content
1784
+ : JSON.stringify(response.content),
1785
+ toolCalls: ('tool_calls' in response && Array.isArray(response.tool_calls))
1786
+ ? response.tool_calls.map((tc) => ({
1787
+ name: tc.name, id: tc.id, args: tc.args,
1788
+ }))
1789
+ : undefined,
1790
+ tokenUsage: response.usage_metadata
1791
+ ? {
1792
+ inputTokens: response.usage_metadata.input_tokens,
1793
+ outputTokens: response.usage_metadata.output_tokens,
1794
+ totalTokens: response.usage_metadata.total_tokens,
1795
+ }
1796
+ : undefined,
1797
+ });
1710
1798
  return { messages: [response] };
1711
1799
  }
1712
1800
  }
@@ -1798,37 +1886,46 @@ export class AIAgentBubble extends ServiceBubble {
1798
1886
  // Check if the last AI message has tool calls
1799
1887
  if (lastAIMessage?.tool_calls && lastAIMessage.tool_calls.length > 0) {
1800
1888
  this._trace('afterLLMCheck', `→ tools`, {
1889
+ result: 'tools',
1890
+ toolCallCount: lastAIMessage.tool_calls.length,
1801
1891
  toolCalls: lastAIMessage.tool_calls
1802
1892
  .map((tc) => `${tc.name}(${tc.id?.slice(-8)})`)
1803
1893
  .join(', '),
1804
1894
  });
1805
1895
  return 'tools';
1806
1896
  }
1807
- this._trace('afterLLMCheck', `→ __end__ (no tool calls)`);
1897
+ this._trace('afterLLMCheck', `→ __end__ (no tool calls)`, {
1898
+ result: '__end__',
1899
+ reason: 'no tool calls',
1900
+ });
1808
1901
  return '__end__';
1809
1902
  };
1810
1903
  // Define conditional edge after tools to check if we should stop
1811
1904
  const shouldContinueAfterTools = () => {
1812
1905
  const execMeta = this.context?.executionMeta;
1813
1906
  this._trace('shouldContinueAfterTools', `CHECK`, {
1814
- shouldStop: this.shouldStopAfterTools,
1907
+ shouldStopAfterTools: this.shouldStopAfterTools,
1815
1908
  pendingApproval: !!execMeta?._pendingApproval,
1816
1909
  });
1817
1910
  // Check if the afterToolCall hook requested stopping
1818
1911
  if (this.shouldStopAfterTools) {
1819
- this._trace('shouldContinueAfterTools', `→ __end__ (shouldStopAfterTools)`);
1912
+ this._trace('shouldContinueAfterTools', `→ __end__ (shouldStopAfterTools)`, { result: '__end__', reason: 'shouldStopAfterTools', shouldStopAfterTools: true });
1820
1913
  return '__end__';
1821
1914
  }
1822
1915
  // Check for pending approval signal from sub-agent (shared via executionMeta).
1823
1916
  // In multi-capability mode the master and sub-agent share the same BubbleContext,
1824
1917
  // so a sub-agent setting _pendingApproval is visible here.
1825
1918
  if (execMeta?._pendingApproval) {
1826
- this._trace('shouldContinueAfterTools', `→ __end__ (pendingApproval)`);
1919
+ this._trace('shouldContinueAfterTools', `→ __end__ (pendingApproval)`, {
1920
+ result: '__end__', reason: 'pendingApproval', pendingApproval: true,
1921
+ });
1827
1922
  this.shouldStopAfterTools = true;
1828
1923
  return '__end__';
1829
1924
  }
1830
1925
  // Otherwise continue back to agent
1831
- this._trace('shouldContinueAfterTools', `→ agent (continue)`);
1926
+ this._trace('shouldContinueAfterTools', `→ agent (continue)`, {
1927
+ result: 'agent',
1928
+ });
1832
1929
  return 'agent';
1833
1930
  };
1834
1931
  // Build the graph
@@ -1976,19 +2073,62 @@ export class AIAgentBubble extends ServiceBubble {
1976
2073
  shouldStopAfterTools: this.shouldStopAfterTools,
1977
2074
  });
1978
2075
  // If a new approval was triggered during V2 resume (subagent set _pendingApproval),
1979
- // we should stop the master loop immediately to avoid re-executing.
2076
+ // skip the agent loop entirely. The subagent is blocked on approval — running the
2077
+ // master LLM would just see an empty response and re-delegate, creating duplicate
2078
+ // approvals. Return the last AI message from the repaired messages as the response.
1980
2079
  if (resumeExecMeta?._pendingApproval) {
1981
- this._trace('v2-resume', `_pendingApproval detected — will stop master loop`);
1982
- this.shouldStopAfterTools = true;
2080
+ const approval = resumeExecMeta._pendingApproval;
2081
+ this._trace('v2-resume', `_pendingApproval detected — skipping agent loop`, {
2082
+ action: approval.action,
2083
+ targetFlowName: approval.targetFlowName,
2084
+ });
2085
+ // Use the subagent's last AI text (captured in _pendingApproval)
2086
+ // as the response. Do NOT use the master's original AI text — that
2087
+ // would cause the same stale message to be posted to Slack on every resume.
2088
+ const lastAIText = resumeExecMeta._pendingApproval.lastAIText;
2089
+ const action = approval.action ?? 'proceed';
2090
+ const flowName = approval.targetFlowName;
2091
+ const resumeResponse = lastAIText
2092
+ ? lastAIText
2093
+ : flowName
2094
+ ? `Requesting approval to **${action}** "${flowName}".`
2095
+ : `Requesting approval to **${action}**.`;
2096
+ const formattedResult = formatFinalResponse(resumeResponse, modelConfig.model, jsonMode);
2097
+ return {
2098
+ response: formattedResult.response,
2099
+ toolCalls: [],
2100
+ iterations: 0,
2101
+ error: '',
2102
+ success: true,
2103
+ };
1983
2104
  }
1984
2105
  initialMessages.push(...repairedMessages);
1985
2106
  }
1986
2107
  else if (resumeState &&
1987
2108
  Array.isArray(resumeState) &&
1988
2109
  resumeState.length > 0) {
1989
- this._trace('v1-resume', `restoring ${resumeState.length} messages (single-cap/subagent path)`);
1990
2110
  const { mapStoredMessagesToChatMessages } = await import('@langchain/core/messages');
1991
2111
  const restored = mapStoredMessagesToChatMessages(resumeState);
2112
+ this._trace('v1-resume', `START`, {
2113
+ savedMessageCount: resumeState.length,
2114
+ restoredMessageCount: restored.length,
2115
+ restoredMessages: restored.map((m) => {
2116
+ const role = m._getType();
2117
+ const content = typeof m.content === 'string'
2118
+ ? m.content
2119
+ : JSON.stringify(m.content);
2120
+ const entry = { role, content };
2121
+ if ('tool_calls' in m && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
2122
+ entry.toolCalls = m.tool_calls.map((tc) => ({
2123
+ name: tc.name, id: tc.id, args: tc.args,
2124
+ }));
2125
+ }
2126
+ if ('tool_call_id' in m) {
2127
+ entry.toolCallId = m.tool_call_id;
2128
+ }
2129
+ return entry;
2130
+ }),
2131
+ });
1992
2132
  // Collect existing tool_call_ids that already have ToolMessage responses
1993
2133
  const existingToolResultIds = new Set();
1994
2134
  for (const msg of restored) {
@@ -2034,6 +2174,13 @@ export class AIAgentBubble extends ServiceBubble {
2034
2174
  if (i === approvalAiMsgIndex && toolsByName.has(tc.name)) {
2035
2175
  // This is the approval-triggering AIMessage — execute the tool directly
2036
2176
  // This bypasses beforeToolCall (no re-approval check) and gives real results
2177
+ const resumeStartTime = Date.now();
2178
+ this._trace('tool', `start:${tc.name}`, {
2179
+ toolName: tc.name,
2180
+ toolCallId: tc.id ?? '',
2181
+ input: tc.args,
2182
+ resumeDirect: true,
2183
+ });
2037
2184
  try {
2038
2185
  console.log(`[AIAgent] Resume: executing approved tool "${tc.name}" directly`);
2039
2186
  const tool = toolsByName.get(tc.name);
@@ -2044,10 +2191,26 @@ export class AIAgentBubble extends ServiceBubble {
2044
2191
  content.slice(0, AIAgentBubble.MAX_TOOL_RESULT_CHARS) +
2045
2192
  `\n\n[... truncated — result was ${content.length} chars, limit is ${AIAgentBubble.MAX_TOOL_RESULT_CHARS}]`;
2046
2193
  }
2194
+ this._trace('tool', `complete:${tc.name}`, {
2195
+ toolName: tc.name,
2196
+ toolCallId: tc.id ?? '',
2197
+ input: tc.args,
2198
+ output: result,
2199
+ durationMs: Date.now() - resumeStartTime,
2200
+ resumeDirect: true,
2201
+ });
2047
2202
  repairedMessages.push(new ToolMessage({ content, tool_call_id: tc.id }));
2048
2203
  }
2049
2204
  catch (err) {
2050
2205
  console.warn(`[AIAgent] Resume: direct tool execution failed for "${tc.name}":`, err);
2206
+ this._trace('tool', `error:${tc.name}`, {
2207
+ toolName: tc.name,
2208
+ toolCallId: tc.id ?? '',
2209
+ input: tc.args,
2210
+ error: err instanceof Error ? err.message : String(err),
2211
+ durationMs: Date.now() - resumeStartTime,
2212
+ resumeDirect: true,
2213
+ });
2051
2214
  repairedMessages.push(new ToolMessage({
2052
2215
  content: `Tool execution failed: ${err instanceof Error ? err.message : String(err)}`,
2053
2216
  tool_call_id: tc.id,
@@ -2070,6 +2233,10 @@ export class AIAgentBubble extends ServiceBubble {
2070
2233
  if (approvalAiMsgIndex >= 0 && resumeExecMeta?._approvedAction) {
2071
2234
  delete resumeExecMeta._approvedAction;
2072
2235
  }
2236
+ this._trace('v1-resume', `DONE`, {
2237
+ repairedMessageCount: repairedMessages.length,
2238
+ types: repairedMessages.map((m) => m._getType()).join(','),
2239
+ });
2073
2240
  initialMessages.push(...repairedMessages);
2074
2241
  }
2075
2242
  else if (conversationHistory && conversationHistory.length > 0) {
@@ -2164,15 +2331,15 @@ export class AIAgentBubble extends ServiceBubble {
2164
2331
  initialMessages.push(humanMessage);
2165
2332
  }
2166
2333
  this._trace('agent-loop', `STARTING graph.invoke`, {
2167
- initialMsgCount: initialMessages.length,
2168
- initialMsgTypes: initialMessages.map((m) => m._getType()).join(','),
2169
- shouldStopAfterTools: this.shouldStopAfterTools,
2334
+ initialMessageCount: initialMessages.length,
2170
2335
  maxIterations,
2336
+ model: this.params.model.model,
2171
2337
  });
2172
2338
  const result = await graph.invoke({ messages: initialMessages }, { recursionLimit: maxIterations });
2173
2339
  this._trace('agent-loop', `graph.invoke COMPLETED`, {
2174
2340
  totalMessages: result.messages.length,
2175
2341
  pendingApproval: !!this.context?.executionMeta?._pendingApproval,
2342
+ model: this.params.model.model,
2176
2343
  });
2177
2344
  console.log('[AIAgent] Graph execution completed');
2178
2345
  console.log('[AIAgent] Total messages:', result.messages.length);