@hatchway/cli 0.50.66 → 0.50.68

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/index.js CHANGED
@@ -4424,6 +4424,12 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
4424
4424
  let messageCount = 0;
4425
4425
  let toolCallCount = 0;
4426
4426
  let textBlockCount = 0;
4427
+ let turnCount = 0;
4428
+ // Track messages fed into the next LLM turn so we can attach them to gen_ai.request spans.
4429
+ // For turn 1, this is the user prompt; for subsequent turns it's the tool_result messages.
4430
+ let pendingRequestMessages = [
4431
+ { role: 'user', content: finalPrompt.substring(0, 1000) },
4432
+ ];
4427
4433
  // Create the gen_ai.invoke_agent span as a child of the current active span.
4428
4434
  //
4429
4435
  // We use startInactiveSpan because this is an async generator — we can't use
@@ -4453,15 +4459,55 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
4453
4459
  // Transform SDK message to our internal format
4454
4460
  const transformed = transformSDKMessage(sdkMessage);
4455
4461
  if (transformed) {
4456
- // Track stats and emit gen_ai.execute_tool spans for tool calls
4462
+ // --- gen_ai.request span for each LLM turn ---
4463
+ // Each 'assistant' message represents one LLM API call response.
4464
+ // We emit a gen_ai.request span capturing the input messages (from
4465
+ // pendingRequestMessages) and the response text / tool calls.
4457
4466
  if (transformed.type === 'assistant' && transformed.message?.content) {
4467
+ turnCount++;
4468
+ // Collect response text and tool calls from this turn
4469
+ const responseTexts = [];
4470
+ const responseToolCalls = [];
4458
4471
  for (const block of transformed.message.content) {
4459
4472
  if (block.type === 'tool_use') {
4460
4473
  toolCallCount++;
4461
4474
  debugLog$4(`[runner] [native-sdk] 🔧 Tool call: ${block.name}\n`);
4462
- // Emit a gen_ai.execute_tool span as a child of gen_ai.invoke_agent.
4463
- // withActiveSpan temporarily makes agentSpan the active span so
4464
- // the startSpan inside creates a proper child.
4475
+ responseToolCalls.push({
4476
+ name: block.name ?? 'unknown',
4477
+ type: 'function_call',
4478
+ arguments: JSON.stringify(block.input).substring(0, 500),
4479
+ });
4480
+ }
4481
+ else if (block.type === 'text' && block.text) {
4482
+ textBlockCount++;
4483
+ responseTexts.push(block.text);
4484
+ }
4485
+ }
4486
+ // Emit gen_ai.request span as a child of the agent span
4487
+ Sentry.withActiveSpan(agentSpan, () => {
4488
+ Sentry.startSpan({
4489
+ op: 'gen_ai.request',
4490
+ name: `request ${modelId}`,
4491
+ attributes: {
4492
+ 'gen_ai.request.model': modelId,
4493
+ 'gen_ai.operation.name': 'request',
4494
+ 'gen_ai.request.messages': JSON.stringify(pendingRequestMessages),
4495
+ ...(responseTexts.length > 0
4496
+ ? { 'gen_ai.response.text': JSON.stringify(responseTexts.map(t => t.substring(0, 500))) }
4497
+ : {}),
4498
+ ...(responseToolCalls.length > 0
4499
+ ? { 'gen_ai.response.tool_calls': JSON.stringify(responseToolCalls) }
4500
+ : {}),
4501
+ },
4502
+ }, () => {
4503
+ // Span marks the LLM request/response for this turn
4504
+ });
4505
+ });
4506
+ // Reset pending messages — the next turn's input will be tool results
4507
+ pendingRequestMessages = [];
4508
+ // Emit gen_ai.execute_tool spans for each tool call in this turn
4509
+ for (const block of transformed.message.content) {
4510
+ if (block.type === 'tool_use') {
4465
4511
  Sentry.withActiveSpan(agentSpan, () => {
4466
4512
  Sentry.startSpan({
4467
4513
  op: 'gen_ai.execute_tool',
@@ -4473,12 +4519,21 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
4473
4519
  'gen_ai.request.model': modelId,
4474
4520
  },
4475
4521
  }, () => {
4476
- // Span created and ended — marks the tool invocation point
4522
+ // Span marks the tool invocation point
4477
4523
  });
4478
4524
  });
4479
4525
  }
4480
- else if (block.type === 'text') {
4481
- textBlockCount++;
4526
+ }
4527
+ }
4528
+ // --- Accumulate tool results for the next gen_ai.request span ---
4529
+ // 'user' messages contain tool_result blocks that feed the next LLM turn.
4530
+ if (transformed.type === 'user' && transformed.message?.content) {
4531
+ for (const block of transformed.message.content) {
4532
+ if (block.type === 'tool_result') {
4533
+ pendingRequestMessages.push({
4534
+ role: 'tool',
4535
+ content: (typeof block.content === 'string' ? block.content : JSON.stringify(block.content) ?? '').substring(0, 500),
4536
+ });
4482
4537
  }
4483
4538
  }
4484
4539
  }