Compare commits

...

1 Commits

Author SHA1 Message Date
shivammittal274
26b402d197 feat: add source tag to tool_executed PostHog events
Add `source: 'mcp' | 'chat'` property to all `tool_executed` metrics
events so we can distinguish tool calls from external MCP clients
(Claude Code, Cursor) vs the built-in BrowserOS agent in PostHog.

- register-mcp.ts: source='mcp' (browser tools via MCP endpoint)
- register-klavis-mcp.ts: source='mcp' (Klavis tools via MCP endpoint)
- tool-adapter.ts: source='chat' (browser tools via chat agent)
- ai-sdk-agent.ts: source='chat' (Klavis/external MCP tools via chat agent, previously untracked)
- filesystem/utils.ts: source='chat' (filesystem tools via chat agent)
2026-03-24 00:46:58 +05:30
5 changed files with 48 additions and 3 deletions

View File

@@ -11,12 +11,14 @@ import {
type ModelMessage,
stepCountIs,
ToolLoopAgent,
type ToolSet,
type UIMessage,
wrapLanguageModel,
} from 'ai'
import type { Browser } from '../browser/browser'
import type { KlavisClient } from '../lib/clients/klavis/klavis-client'
import { logger } from '../lib/logger'
import { metrics } from '../lib/metrics'
import { isSoulBootstrap, readSoul } from '../lib/soul'
import { buildSkillsCatalog } from '../skills/catalog'
import { loadSkills } from '../skills/loader'
@@ -114,7 +116,44 @@ export class AiSdkAgent {
klavisClient: config.klavisClient,
browserosId: config.browserosId,
})
const { clients, tools: externalMcpTools } = await createMcpClients(specs)
const { clients, tools: rawExternalMcpTools } =
await createMcpClients(specs)
// Wrap external MCP tools (Klavis, custom) with metrics
const externalMcpTools: ToolSet = {}
for (const [name, t] of Object.entries(rawExternalMcpTools)) {
const originalExecute = t.execute
externalMcpTools[name] = {
...t,
execute: originalExecute
? async (
...args: Parameters<NonNullable<typeof originalExecute>>
) => {
const startTime = performance.now()
try {
const result = await originalExecute(...args)
metrics.log('tool_executed', {
tool_name: name,
duration_ms: Math.round(performance.now() - startTime),
success: true,
source: 'chat',
})
return result
} catch (error) {
metrics.log('tool_executed', {
tool_name: name,
duration_ms: Math.round(performance.now() - startTime),
success: false,
error_message:
error instanceof Error ? error.message : String(error),
source: 'chat',
})
throw error
}
}
: undefined,
}
}
// Add filesystem tools (Pi coding agent) — skip in chat mode (read-only)
const filesystemTools = config.resolvedConfig.chatMode

View File

@@ -64,6 +64,7 @@ export function buildBrowserToolSet(
tool_name: def.name,
duration_ms: Math.round(performance.now() - startTime),
success: !result.isError,
source: 'chat',
})
return {
@@ -85,6 +86,7 @@ export function buildBrowserToolSet(
success: false,
error_message:
error instanceof Error ? error.message : 'Unknown error',
source: 'chat',
})
return {

View File

@@ -111,7 +111,7 @@ export function registerKlavisTools(
metrics.log('tool_executed', {
tool_name: tool.name,
source: 'klavis',
source: 'mcp',
duration_ms: Math.round(performance.now() - startTime),
success: !result.isError,
})
@@ -123,7 +123,7 @@ export function registerKlavisTools(
metrics.log('tool_executed', {
tool_name: tool.name,
source: 'klavis',
source: 'mcp',
duration_ms: Math.round(performance.now() - startTime),
success: false,
error_message: errorText,

View File

@@ -25,6 +25,7 @@ export function registerTools(
tool_name: tool.name,
duration_ms: Math.round(performance.now() - startTime),
success: !result.isError,
source: 'mcp',
})
return {
@@ -40,6 +41,7 @@ export function registerTools(
duration_ms: Math.round(performance.now() - startTime),
success: false,
error_message: errorText,
source: 'mcp',
})
return {

View File

@@ -264,6 +264,7 @@ export function executeWithMetrics(
tool_name: toolName,
duration_ms: Math.round(performance.now() - startTime),
success: !result.isError,
source: 'chat',
})
return result
},
@@ -278,6 +279,7 @@ export function executeWithMetrics(
duration_ms: Math.round(performance.now() - startTime),
success: false,
error_message: errorText,
source: 'chat',
})
return { text: errorText, isError: true }
},