@hatchway/cli 0.50.63 → 0.50.64
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 +59 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4335,9 +4335,10 @@ function buildPromptWithImages(prompt, messageParts) {
|
|
|
4335
4335
|
* query() SDK function -> minimal transformation -> output
|
|
4336
4336
|
*
|
|
4337
4337
|
* Sentry Integration:
|
|
4338
|
-
* -
|
|
4339
|
-
* -
|
|
4340
|
-
* -
|
|
4338
|
+
* - Manual gen_ai.* spans for AI Agent Monitoring in Sentry
|
|
4339
|
+
* - gen_ai.invoke_agent wraps the full query lifecycle
|
|
4340
|
+
* - gen_ai.execute_tool spans are emitted per tool call
|
|
4341
|
+
* - Token usage and cost are captured from the SDK result message
|
|
4341
4342
|
*/
|
|
4342
4343
|
function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortController) {
|
|
4343
4344
|
return async function* nativeClaudeQuery(prompt, workingDirectory, systemPrompt, _agent, _codexThreadId, messageParts) {
|
|
@@ -4423,20 +4424,44 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
|
|
|
4423
4424
|
let messageCount = 0;
|
|
4424
4425
|
let toolCallCount = 0;
|
|
4425
4426
|
let textBlockCount = 0;
|
|
4427
|
+
// Wrap the entire agent execution in a gen_ai.invoke_agent span for Sentry AI monitoring
|
|
4428
|
+
const agentSpan = Sentry.startInactiveSpan({
|
|
4429
|
+
op: 'gen_ai.invoke_agent',
|
|
4430
|
+
name: `Claude Agent (${modelId})`,
|
|
4431
|
+
attributes: {
|
|
4432
|
+
'gen_ai.agent.name': 'hatchway-builder',
|
|
4433
|
+
'gen_ai.request.model': modelId,
|
|
4434
|
+
'gen_ai.agent.input': finalPrompt.substring(0, 500),
|
|
4435
|
+
'gen_ai.system_prompt.length': appendedSystemPrompt.length,
|
|
4436
|
+
'gen_ai.agent.available_tools': JSON.stringify(['Bash', 'Read', 'Write', 'Edit', 'Glob', 'Grep', 'Task', 'TodoWrite', 'WebFetch']),
|
|
4437
|
+
},
|
|
4438
|
+
});
|
|
4426
4439
|
try {
|
|
4427
4440
|
// Stream messages directly from the SDK
|
|
4428
|
-
// NOTE: query() is auto-instrumented by Sentry's claudeCodeAgentSdkIntegration
|
|
4429
4441
|
for await (const sdkMessage of query({ prompt: finalPrompt, options })) {
|
|
4430
4442
|
messageCount++;
|
|
4431
4443
|
// Transform SDK message to our internal format
|
|
4432
4444
|
const transformed = transformSDKMessage(sdkMessage);
|
|
4433
4445
|
if (transformed) {
|
|
4434
|
-
// Track stats for
|
|
4446
|
+
// Track stats and emit gen_ai.execute_tool spans for tool calls
|
|
4435
4447
|
if (transformed.type === 'assistant' && transformed.message?.content) {
|
|
4436
4448
|
for (const block of transformed.message.content) {
|
|
4437
4449
|
if (block.type === 'tool_use') {
|
|
4438
4450
|
toolCallCount++;
|
|
4439
4451
|
debugLog$4(`[runner] [native-sdk] 🔧 Tool call: ${block.name}\n`);
|
|
4452
|
+
// Emit a gen_ai.execute_tool span for each tool invocation
|
|
4453
|
+
const toolSpan = Sentry.startInactiveSpan({
|
|
4454
|
+
op: 'gen_ai.execute_tool',
|
|
4455
|
+
name: `Tool: ${block.name}`,
|
|
4456
|
+
attributes: {
|
|
4457
|
+
'gen_ai.tool.name': block.name,
|
|
4458
|
+
'gen_ai.tool.call_id': block.id,
|
|
4459
|
+
'gen_ai.tool.input': JSON.stringify(block.input).substring(0, 1000),
|
|
4460
|
+
},
|
|
4461
|
+
});
|
|
4462
|
+
// Tool spans are completed immediately since we get input and output
|
|
4463
|
+
// as separate messages — the output is captured in the tool_result handler below
|
|
4464
|
+
toolSpan?.end();
|
|
4440
4465
|
}
|
|
4441
4466
|
else if (block.type === 'text') {
|
|
4442
4467
|
textBlockCount++;
|
|
@@ -4485,13 +4510,31 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
|
|
|
4485
4510
|
process.stderr.write(`[native-sdk] Tool use summary: ${summaryMsg.summary}\n`);
|
|
4486
4511
|
}
|
|
4487
4512
|
}
|
|
4488
|
-
//
|
|
4513
|
+
// Capture result messages — record token usage and cost on the agent span
|
|
4489
4514
|
if (sdkMessage.type === 'result') {
|
|
4490
|
-
|
|
4491
|
-
|
|
4515
|
+
const resultMsg = sdkMessage;
|
|
4516
|
+
if (agentSpan) {
|
|
4517
|
+
agentSpan.setAttribute('gen_ai.usage.input_tokens', resultMsg.usage?.input_tokens ?? 0);
|
|
4518
|
+
agentSpan.setAttribute('gen_ai.usage.output_tokens', resultMsg.usage?.output_tokens ?? 0);
|
|
4519
|
+
agentSpan.setAttribute('gen_ai.usage.total_tokens', (resultMsg.usage?.input_tokens ?? 0) + (resultMsg.usage?.output_tokens ?? 0));
|
|
4520
|
+
agentSpan.setAttribute('gen_ai.usage.cost_usd', resultMsg.total_cost_usd ?? 0);
|
|
4521
|
+
agentSpan.setAttribute('gen_ai.agent.num_turns', resultMsg.num_turns ?? 0);
|
|
4522
|
+
agentSpan.setAttribute('gen_ai.agent.num_tool_calls', toolCallCount);
|
|
4523
|
+
agentSpan.setAttribute('gen_ai.agent.result', resultMsg.subtype ?? 'unknown');
|
|
4524
|
+
agentSpan.setAttribute('gen_ai.agent.duration_ms', resultMsg.duration_ms ?? 0);
|
|
4525
|
+
agentSpan.setAttribute('gen_ai.agent.duration_api_ms', resultMsg.duration_api_ms ?? 0);
|
|
4526
|
+
if (resultMsg.usage?.cache_read_input_tokens) {
|
|
4527
|
+
agentSpan.setAttribute('gen_ai.usage.cache_read_tokens', resultMsg.usage.cache_read_input_tokens);
|
|
4528
|
+
}
|
|
4529
|
+
if (resultMsg.usage?.cache_creation_input_tokens) {
|
|
4530
|
+
agentSpan.setAttribute('gen_ai.usage.cache_creation_tokens', resultMsg.usage.cache_creation_input_tokens);
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4533
|
+
if (resultMsg.subtype === 'success') {
|
|
4534
|
+
debugLog$4(`[runner] [native-sdk] ✅ Query complete - ${resultMsg.num_turns} turns, $${resultMsg.total_cost_usd?.toFixed(4)} USD\n`);
|
|
4492
4535
|
}
|
|
4493
4536
|
else {
|
|
4494
|
-
debugLog$4(`[runner] [native-sdk] ⚠️ Query ended with: ${
|
|
4537
|
+
debugLog$4(`[runner] [native-sdk] ⚠️ Query ended with: ${resultMsg.subtype}\n`);
|
|
4495
4538
|
}
|
|
4496
4539
|
}
|
|
4497
4540
|
}
|
|
@@ -4499,9 +4542,16 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
|
|
|
4499
4542
|
}
|
|
4500
4543
|
catch (error) {
|
|
4501
4544
|
debugLog$4(`[runner] [native-sdk] ❌ Error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
4545
|
+
if (agentSpan) {
|
|
4546
|
+
agentSpan.setStatus({ code: 2, message: error instanceof Error ? error.message : String(error) });
|
|
4547
|
+
}
|
|
4502
4548
|
Sentry.captureException(error);
|
|
4503
4549
|
throw error;
|
|
4504
4550
|
}
|
|
4551
|
+
finally {
|
|
4552
|
+
// End the agent span regardless of success/failure
|
|
4553
|
+
agentSpan?.end();
|
|
4554
|
+
}
|
|
4505
4555
|
};
|
|
4506
4556
|
}
|
|
4507
4557
|
|