feat(analytics): add top tools and topics to session analytics

This commit is contained in:
William Valentin
2026-02-16 14:11:50 -08:00
parent 3d7144b2c5
commit 93621bbe6e
10 changed files with 173 additions and 8 deletions
+40
View File
@@ -15,12 +15,20 @@ export interface ToolExecutorConfig {
maxOutputBytes?: number;
}
export interface ToolExecutionObserverEvent {
toolName: string;
sessionId?: string;
success: boolean;
timestampSeconds: number;
}
export class ToolExecutor {
private registry: ToolRegistry;
private hooks: HookEngine;
private defaultTimeoutMs: number;
private maxOutputBytes: number;
private sandboxManager?: SandboxManager;
private executionObserver?: (event: ToolExecutionObserverEvent) => void;
constructor(registry: ToolRegistry, hooks: HookEngine, config?: ToolExecutorConfig) {
this.registry = registry;
@@ -33,6 +41,10 @@ export class ToolExecutor {
this.sandboxManager = manager;
}
setExecutionObserver(observer?: (event: ToolExecutionObserverEvent) => void): void {
this.executionObserver = observer;
}
private isElevationActive(context?: ToolPolicyContext): boolean {
const untilMs = context?.elevatedHostUntilMs;
return typeof untilMs === 'number' && Number.isFinite(untilMs) && untilMs > Date.now();
@@ -271,6 +283,13 @@ export class ToolExecutor {
session_id: context?.sessionId,
});
this.notifyExecutionObserver({
toolName,
sessionId: context?.sessionId,
success: result.success,
timestampSeconds: Math.floor(Date.now() / 1000),
});
return result;
} catch (error) {
const duration = Date.now() - startTime;
@@ -289,6 +308,13 @@ export class ToolExecutor {
redactions_applied: argsRedaction.redactions + errorRedaction.redactions,
});
this.notifyExecutionObserver({
toolName,
sessionId: context?.sessionId,
success: false,
timestampSeconds: Math.floor(Date.now() / 1000),
});
return {
success: false,
output: '',
@@ -301,6 +327,20 @@ export class ToolExecutor {
}
}
private notifyExecutionObserver(event: ToolExecutionObserverEvent): void {
if (!this.executionObserver) {
return;
}
try {
this.executionObserver(event);
} catch (error) {
console.warn(
'ToolExecutor: execution observer failed:',
error instanceof Error ? error.message : String(error),
);
}
}
private resolveAllowedSecretScopes(context?: ToolPolicyContext): string[] {
if (context?.allowedSecretScopes) {
return context.allowedSecretScopes;