Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Added `thinkingLevel` and `thinkingBudget` configuration options for Google Generative AI and Google Vertex providers. [#1110](https://github.com/sourcebot-dev/sourcebot/pull/1110)
- Added unified `tool_used` PostHog event tracking for all tool calls across the ask agent and MCP server. [#1111](https://github.com/sourcebot-dev/sourcebot/pull/1111)
- Added client-side `wa_ask_thread_created` and `wa_ask_message_sent` PostHog events for web-only ask usage tracking. [#1111](https://github.com/sourcebot-dev/sourcebot/pull/1111)

### Changed
- Deprecated `GOOGLE_VERTEX_THINKING_BUDGET_TOKENS` environment variable in favor of per-model `thinkingBudget` config. [#1110](https://github.com/sourcebot-dev/sourcebot/pull/1110)
- Removed `GOOGLE_VERTEX_INCLUDE_THOUGHTS` environment variable. Thoughts are now always included. [#1110](https://github.com/sourcebot-dev/sourcebot/pull/1110)
- Renamed PostHog events: `wa_chat_thread_created` → `ask_thread_created`, `wa_chat_message_sent` → `ask_message_sent`, `wa_chat_tool_used` → `tool_used`. [#1111](https://github.com/sourcebot-dev/sourcebot/pull/1111)

## [4.16.8] - 2026-04-09

Expand Down
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ if (!value) { return; }
if (condition) doSomething();
```

## PostHog Event Naming

- The `wa_` prefix is reserved for events that can ONLY be fired from the web app (e.g., `wa_login_with_github`, `wa_chat_feedback_submitted`).
- Events fired from multiple sources (web app, MCP server, API) must NOT use the `wa_` prefix (e.g., `ask_message_sent`, `tool_used`).
- Multi-source events should include a `source` property to identify the origin (e.g., `'sourcebot-web-client'`, `'sourcebot-mcp-server'`, `'sourcebot-ask-agent'`).

## Tailwind CSS

Use Tailwind color classes directly instead of CSS variable syntax:
Expand Down
7 changes: 5 additions & 2 deletions packages/web/src/app/api/(server)/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,15 @@ export const POST = apiHandler(async (req: NextRequest) => {
return [];
}))).flat();

await captureEvent('wa_chat_message_sent', {
const source = req.headers.get('X-Sourcebot-Client-Source') ?? undefined;

await captureEvent('ask_message_sent', {
chatId: id,
messageCount: messages.length,
selectedReposCount: expandedRepos.length,
source,
...(env.EXPERIMENT_ASK_GH_ENABLED === 'true' ? { selectedRepos: expandedRepos } : {}),
} );
});
Comment thread
msukkari marked this conversation as resolved.

const stream = await createMessageStream({
chatId: id,
Expand Down
7 changes: 0 additions & 7 deletions packages/web/src/app/api/(server)/search/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { search, searchRequestSchema } from "@/features/search";
import { apiHandler } from "@/lib/apiHandler";
import { captureEvent } from "@/lib/posthog";
import { requestBodySchemaValidationError, serviceErrorResponse } from "@/lib/serviceError";
import { isServiceError } from "@/lib/utils";
import { NextRequest } from "next/server";
Expand All @@ -21,12 +20,6 @@ export const POST = apiHandler(async (request: NextRequest) => {
...options
} = parsed.data;

const source = request.headers.get('X-Sourcebot-Client-Source') ?? 'unknown';
await captureEvent('api_code_search_request', {
source,
type: 'blocking',
});

const response = await search({
queryType: 'string',
query,
Expand Down
7 changes: 0 additions & 7 deletions packages/web/src/app/api/(server)/stream_search/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { streamSearch, searchRequestSchema } from '@/features/search';
import { apiHandler } from '@/lib/apiHandler';
import { captureEvent } from '@/lib/posthog';
import { requestBodySchemaValidationError, serviceErrorResponse } from '@/lib/serviceError';
import { isServiceError } from '@/lib/utils';
import { NextRequest } from 'next/server';
Expand All @@ -20,12 +19,6 @@ export const POST = apiHandler(async (request: NextRequest) => {
...options
} = parsed.data;

const source = request.headers.get('X-Sourcebot-Client-Source') ?? 'unknown';
await captureEvent('api_code_search_request', {
source,
type: 'streamed',
});

const stream = await streamSearch({
queryType: 'string',
query,
Expand Down
3 changes: 2 additions & 1 deletion packages/web/src/features/chat/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ export const createChat = async ({ source }: { source?: string } = {}) => sew(()
});
}

await captureEvent('wa_chat_thread_created', {
await captureEvent('ask_thread_created', {
chatId: chat.id,
isAnonymous: isGuestUser,
source,
});
Comment thread
msukkari marked this conversation as resolved.

return {
Expand Down
9 changes: 1 addition & 8 deletions packages/web/src/features/chat/agent.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { SBChatMessage, SBChatMessageMetadata } from "@/features/chat/types";
import { getAnswerPartFromAssistantMessage } from "@/features/chat/utils";
import { getFileSource } from '@/features/git';
import { captureEvent } from "@/lib/posthog";
import { isServiceError } from "@/lib/utils";
import { LanguageModelV3 as AISDKLanguageModelV3 } from "@ai-sdk/provider";
import { ProviderOptions } from "@ai-sdk/provider-utils";
Expand Down Expand Up @@ -210,13 +209,7 @@ const createAgentStream = async ({
],
toolChoice: "auto",
onStepFinish: ({ toolResults }) => {
toolResults.forEach(({ toolName, output, dynamic }) => {
captureEvent('wa_chat_tool_used', {
chatId,
toolName,
success: !isServiceError(output),
});

toolResults.forEach(({ output, dynamic }) => {
if (dynamic || isServiceError(output)) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ export const ChatThread = ({
.map((part) => part.data);
setSources((prev) => [...prev, ...sources]);

captureEvent('wa_ask_message_sent', {
chatId,
messageCount: messages.length + 1,
selectedReposCount: selectedSearchScopes.length,
});

_sendMessage(message, {
body: {
selectedSearchScopes,
Expand Down
5 changes: 5 additions & 0 deletions packages/web/src/features/chat/useCreateNewChatThread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export const useCreateNewChatThread = ({ isAuthenticated = false }: UseCreateNew
return;
}

captureEvent('wa_ask_thread_created', {
chatId: response.id,
isAnonymous: response.isAnonymous,
});

setChatState({
inputMessage,
selectedSearchScopes,
Expand Down
6 changes: 4 additions & 2 deletions packages/web/src/features/mcp/askCodebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ export const askCodebase = (params: AskCodebaseParams): Promise<AskCodebaseResul
},
});

await captureEvent('wa_chat_thread_created', {
await captureEvent('ask_thread_created', {
chatId: chat.id,
isAnonymous: !user,
source,
});
Comment thread
msukkari marked this conversation as resolved.

if (user) {
Expand Down Expand Up @@ -137,10 +138,11 @@ export const askCodebase = (params: AskCodebaseParams): Promise<AskCodebaseResul

let finalMessages: SBChatMessage[] = [];

await captureEvent('wa_chat_message_sent', {
await captureEvent('ask_message_sent', {
chatId: chat.id,
messageCount: 1,
selectedReposCount: selectedRepos.length,
source,
...(env.EXPERIMENT_ASK_GH_ENABLED === 'true' ? {
selectedRepos: selectedRepos.map(r => r.value)
} : {}),
Expand Down
17 changes: 17 additions & 0 deletions packages/web/src/features/mcp/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
languageModelInfoSchema,
} from '@/features/chat/types';
import { askCodebase } from '@/features/mcp/askCodebase';
import { captureEvent } from '@/lib/posthog';
import { isServiceError } from '@/lib/utils';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { ChatVisibility } from '@sourcebot/db';
Expand Down Expand Up @@ -57,6 +58,11 @@ export async function createMcpServer(): Promise<McpServer> {
},
async () => {
const models = await getConfiguredLanguageModelsInfo();
captureEvent('tool_used', {
toolName: 'list_language_models',
source: 'sourcebot-mcp-server',
success: true,
});
return { content: [{ type: "text", text: JSON.stringify(models) }] };
}
);
Expand Down Expand Up @@ -101,11 +107,22 @@ export async function createMcpServer(): Promise<McpServer> {
});

if (isServiceError(result)) {
captureEvent('tool_used', {
toolName: 'ask_codebase',
source: 'sourcebot-mcp-server',
success: false,
});
return {
content: [{ type: "text", text: `Failed to ask codebase: ${result.message}` }],
};
}

captureEvent('tool_used', {
toolName: 'ask_codebase',
source: 'sourcebot-mcp-server',
success: true,
});

const formattedResponse = dedent`
${result.answer}

Expand Down
27 changes: 26 additions & 1 deletion packages/web/src/features/tools/adapters.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { tool } from "ai";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { captureEvent } from "@/lib/posthog";
import { ToolContext, ToolDefinition } from "./types";

export function toVercelAITool<TName extends string, TShape extends z.ZodRawShape, TMetadata>(
Expand All @@ -11,7 +12,21 @@ export function toVercelAITool<TName extends string, TShape extends z.ZodRawShap
description: def.description,
inputSchema: def.inputSchema,
title: def.title,
execute: (input) => def.execute(input, context),
execute: async (input) => {
let success = true;
try {
return await def.execute(input, context);
} catch (error) {
success = false;
throw error;
} finally {
captureEvent('tool_used', {
toolName: def.name,
source: context.source ?? 'unknown',
success,
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
},
toModelOutput: ({ output }) => ({
type: "content",
value: [{ type: "text", text: output.output }],
Expand Down Expand Up @@ -41,8 +56,18 @@ export function registerMcpTool<TName extends string, TShape extends z.ZodRawSha
try {
const parsed = def.inputSchema.parse(input);
const result = await def.execute(parsed, context);
captureEvent('tool_used', {
Comment thread
msukkari marked this conversation as resolved.
Outdated
toolName: def.name,
source: context.source ?? 'unknown',
success: true,
});
return { content: [{ type: "text" as const, text: result.output }] };
} catch (error) {
captureEvent('tool_used', {
toolName: def.name,
source: context.source ?? 'unknown',
success: false,
});
const message = error instanceof Error ? error.message : String(error);
return { content: [{ type: "text" as const, text: `Tool "${def.name}" failed: ${message}` }], isError: true };
}
Expand Down
23 changes: 15 additions & 8 deletions packages/web/src/lib/posthogEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,24 +159,35 @@ export type PosthogEventMap = {
chatId: string,
messageId: string,
},
wa_chat_thread_created: {
wa_ask_thread_created: {
chatId: string,
isAnonymous: boolean,
},
wa_chat_message_sent: {
wa_ask_message_sent: {
chatId: string,
messageCount: number,
selectedReposCount: number,
},
ask_thread_created: {
Comment thread
msukkari marked this conversation as resolved.
chatId: string,
isAnonymous: boolean,
source?: string,
},
ask_message_sent: {
chatId: string,
messageCount: number,
selectedReposCount: number,
source?: string,
/**
Comment thread
msukkari marked this conversation as resolved.
* @note this field will only be populated when
* the EXPERIMENT_ASK_GH_ENABLED environment variable
* is set to true.
*/
selectedRepos?: string[],
},
wa_chat_tool_used: {
chatId: string,
tool_used: {
toolName: string,
source: string,
success: boolean,
},
wa_chat_share_dialog_opened: {
Expand Down Expand Up @@ -286,10 +297,6 @@ export type PosthogEventMap = {
//////////////////////////////////////////////////////////////////
wa_repo_not_found_for_zoekt_file: {},
//////////////////////////////////////////////////////////////////
api_code_search_request: {
Comment thread
brendan-kellam marked this conversation as resolved.
source: string;
type: 'streamed' | 'blocking';
},
api_request: {
path: string;
source: string;
Expand Down
Loading