@posthog/agent 1.20.0 → 1.22.0
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/claude-cli/cli.js +2251 -1888
- package/dist/src/adapters/claude/claude-adapter.d.ts +1 -1
- package/dist/src/adapters/claude/claude-adapter.d.ts.map +1 -1
- package/dist/src/adapters/claude/claude-adapter.js +141 -133
- package/dist/src/adapters/claude/claude-adapter.js.map +1 -1
- package/dist/src/adapters/types.d.ts +3 -3
- package/dist/src/adapters/types.d.ts.map +1 -1
- package/dist/src/agent.d.ts +1 -1
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +9 -8
- package/dist/src/agent.js.map +1 -1
- package/dist/src/file-manager.d.ts +10 -0
- package/dist/src/file-manager.d.ts.map +1 -1
- package/dist/src/file-manager.js +49 -10
- package/dist/src/file-manager.js.map +1 -1
- package/dist/src/git-manager.d.ts +1 -0
- package/dist/src/git-manager.d.ts.map +1 -1
- package/dist/src/git-manager.js +10 -3
- package/dist/src/git-manager.js.map +1 -1
- package/dist/src/posthog-api.d.ts +2 -1
- package/dist/src/posthog-api.d.ts.map +1 -1
- package/dist/src/posthog-api.js +11 -0
- package/dist/src/posthog-api.js.map +1 -1
- package/dist/src/task-progress-reporter.d.ts +12 -4
- package/dist/src/task-progress-reporter.d.ts.map +1 -1
- package/dist/src/task-progress-reporter.js +282 -117
- package/dist/src/task-progress-reporter.js.map +1 -1
- package/dist/src/types.d.ts +17 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/workflow/config.d.ts.map +1 -1
- package/dist/src/workflow/config.js +11 -0
- package/dist/src/workflow/config.js.map +1 -1
- package/dist/src/workflow/steps/build.js +3 -3
- package/dist/src/workflow/steps/build.js.map +1 -1
- package/dist/src/workflow/steps/finalize.d.ts +3 -0
- package/dist/src/workflow/steps/finalize.d.ts.map +1 -0
- package/dist/src/workflow/steps/finalize.js +182 -0
- package/dist/src/workflow/steps/finalize.js.map +1 -0
- package/dist/src/workflow/steps/plan.js +3 -3
- package/dist/src/workflow/steps/plan.js.map +1 -1
- package/dist/src/workflow/steps/research.js +3 -3
- package/dist/src/workflow/steps/research.js.map +1 -1
- package/package.json +2 -2
- package/src/adapters/claude/claude-adapter.ts +56 -46
- package/src/adapters/types.ts +3 -3
- package/src/agent.ts +17 -8
- package/src/file-manager.ts +59 -6
- package/src/git-manager.ts +11 -3
- package/src/posthog-api.ts +33 -1
- package/src/task-progress-reporter.ts +310 -138
- package/src/types.ts +20 -1
- package/src/workflow/config.ts +11 -0
- package/src/workflow/steps/build.ts +3 -3
- package/src/workflow/steps/finalize.ts +216 -0
- package/src/workflow/steps/plan.ts +3 -3
- package/src/workflow/steps/research.ts +3 -3
package/dist/src/posthog-api.js
CHANGED
|
@@ -112,6 +112,17 @@ class PostHogAPIClient {
|
|
|
112
112
|
body: JSON.stringify({ entries }),
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
|
+
async uploadTaskArtifacts(taskId, runId, artifacts) {
|
|
116
|
+
if (!artifacts.length) {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
const teamId = this.getTeamId();
|
|
120
|
+
const response = await this.apiRequest(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/artifacts/`, {
|
|
121
|
+
method: 'POST',
|
|
122
|
+
body: JSON.stringify({ artifacts }),
|
|
123
|
+
});
|
|
124
|
+
return response.artifacts ?? [];
|
|
125
|
+
}
|
|
115
126
|
/**
|
|
116
127
|
* Fetch logs from S3 using presigned URL from TaskRun
|
|
117
128
|
* @param taskRun - The task run containing the log_url
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posthog-api.js","sources":["../../src/posthog-api.ts"],"sourcesContent":["import type { Task, TaskRun, LogEntry, SupportingFile, PostHogAPIConfig, PostHogResource, ResourceType, UrlMention } from './types.js';\n\ninterface PostHogApiResponse<T> {\n results?: T[];\n count?: number;\n next?: string | null;\n previous?: string | null;\n}\n\nexport interface TaskRunUpdate {\n status?: TaskRun[\"status\"];\n branch?: string | null;\n current_stage?: string | null;\n error_message?: string | null;\n output?: Record<string, unknown> | null;\n state?: Record<string, unknown>;\n}\n\nexport class PostHogAPIClient {\n private config: PostHogAPIConfig;\n private _teamId: number | null = null;\n\n constructor(config: PostHogAPIConfig) {\n this.config = config;\n }\n\n private get baseUrl(): string {\n const host = this.config.apiUrl.endsWith(\"/\") \n ? this.config.apiUrl.slice(0, -1) \n : this.config.apiUrl;\n return host;\n }\n\n private get headers(): Record<string, string> {\n return {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'Content-Type': 'application/json',\n };\n }\n\n private async apiRequest<T>(\n endpoint: string, \n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n \n const response = await fetch(url, {\n ...options,\n headers: {\n ...this.headers,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n let errorMessage: string;\n try {\n const errorResponse = await response.json();\n errorMessage = `Failed request: [${response.status}] ${JSON.stringify(errorResponse)}`;\n } catch {\n errorMessage = `Failed request: [${response.status}] ${response.statusText}`;\n }\n throw new Error(errorMessage);\n }\n\n return response.json();\n }\n\n getTeamId(): number {\n return this.config.projectId;\n }\n\n getBaseUrl(): string {\n return this.baseUrl;\n }\n\n getApiKey(): string {\n return this.config.apiKey;\n }\n\n getLlmGatewayUrl(): string {\n const teamId = this.getTeamId();\n return `${this.baseUrl}/api/projects/${teamId}/llm_gateway`;\n }\n\n async fetchTask(taskId: string): Promise<Task> {\n const teamId = this.getTeamId();\n return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/`);\n }\n\n async listTasks(filters?: {\n repository?: string;\n organization?: string;\n origin_product?: string;\n }): Promise<Task[]> {\n const teamId = this.getTeamId();\n const url = new URL(`${this.baseUrl}/api/projects/${teamId}/tasks/`);\n \n if (filters) {\n Object.entries(filters).forEach(([key, value]) => {\n if (value) url.searchParams.append(key, value);\n });\n }\n\n const response = await this.apiRequest<PostHogApiResponse<Task>>(\n url.pathname + url.search\n );\n \n return response.results || [];\n }\n\n async updateTask(taskId: string, updates: Partial<Task>): Promise<Task> {\n const teamId = this.getTeamId();\n return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/`, {\n method: 'PATCH',\n body: JSON.stringify(updates),\n });\n }\n\n // TaskRun methods\n async listTaskRuns(taskId: string): Promise<TaskRun[]> {\n const teamId = this.getTeamId();\n const response = await this.apiRequest<PostHogApiResponse<TaskRun>>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/`\n );\n return response.results || [];\n }\n\n async getTaskRun(taskId: string, runId: string): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`);\n }\n\n async createTaskRun(\n taskId: string,\n payload?: Partial<Omit<TaskRun, 'id' | 'task' | 'team' | 'created_at' | 'updated_at' | 'completed_at'>>\n ): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/`, {\n method: \"POST\",\n body: JSON.stringify(payload || {}),\n });\n }\n\n async updateTaskRun(\n taskId: string,\n runId: string,\n payload: TaskRunUpdate\n ): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`, {\n method: \"PATCH\",\n body: JSON.stringify(payload),\n });\n }\n\n async setTaskRunOutput(taskId: string, runId: string, output: Record<string, unknown>): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/set_output/`, {\n method: 'PATCH',\n body: JSON.stringify({ output }),\n });\n }\n\n async appendTaskRunLog(taskId: string, runId: string, entries: LogEntry[]): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/append_log/`, {\n method: 'POST',\n body: JSON.stringify({ entries }),\n });\n }\n\n /**\n * Fetch logs from S3 using presigned URL from TaskRun\n * @param taskRun - The task run containing the log_url\n * @returns Array of log entries, or empty array if no logs available\n */\n async fetchTaskRunLogs(taskRun: TaskRun): Promise<LogEntry[]> {\n if (!taskRun.log_url) {\n return [];\n }\n\n try {\n const response = await fetch(taskRun.log_url);\n \n if (!response.ok) {\n throw new Error(`Failed to fetch logs: ${response.status} ${response.statusText}`);\n }\n\n const content = await response.text();\n \n if (!content.trim()) {\n return [];\n }\n\n // Parse newline-delimited JSON\n return content\n .trim()\n .split('\\n')\n .map(line => JSON.parse(line) as LogEntry);\n } catch (error) {\n throw new Error(`Failed to fetch task run logs: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Fetch error details from PostHog error tracking\n */\n async fetchErrorDetails(errorId: string, projectId?: string): Promise<PostHogResource> {\n const teamId = projectId ? parseInt(projectId) : this.getTeamId();\n \n try {\n const errorData = await this.apiRequest<any>(`/api/projects/${teamId}/error_tracking/${errorId}/`);\n \n // Format error details for agent consumption\n const content = this.formatErrorContent(errorData);\n \n return {\n type: 'error',\n id: errorId,\n url: `${this.baseUrl}/project/${teamId}/error_tracking/${errorId}`,\n title: errorData.exception_type || 'Unknown Error',\n content,\n metadata: {\n exception_type: errorData.exception_type,\n first_seen: errorData.first_seen,\n last_seen: errorData.last_seen,\n volume: errorData.volume,\n users_affected: errorData.users_affected,\n },\n };\n } catch (error) {\n throw new Error(`Failed to fetch error details for ${errorId}: ${error}`);\n }\n }\n\n /**\n * Generic resource fetcher by URL or ID\n */\n async fetchResourceByUrl(urlMention: UrlMention): Promise<PostHogResource> {\n switch (urlMention.type) {\n case 'error':\n if (!urlMention.id) {\n throw new Error('Error ID is required for error resources');\n }\n // Extract project ID from URL if available, otherwise use default team\n let projectId: string | undefined;\n if (urlMention.url) {\n const projectIdMatch = urlMention.url.match(/\\/project\\/(\\d+)\\//);\n projectId = projectIdMatch ? projectIdMatch[1] : undefined;\n }\n return this.fetchErrorDetails(urlMention.id, projectId);\n \n case 'experiment':\n case 'insight':\n case 'feature_flag':\n throw new Error(`Resource type '${urlMention.type}' not yet implemented`);\n \n case 'generic':\n // Return a minimal resource for generic URLs\n return {\n type: 'generic',\n id: '',\n url: urlMention.url,\n title: 'Generic Resource',\n content: `Generic resource: ${urlMention.url}`,\n metadata: {},\n };\n \n default:\n throw new Error(`Unknown resource type: ${urlMention.type}`);\n }\n }\n\n /**\n * Format error data for agent consumption\n */\n private formatErrorContent(errorData: any): string {\n const sections = [];\n \n if (errorData.exception_type) {\n sections.push(`**Error Type**: ${errorData.exception_type}`);\n }\n \n if (errorData.exception_message) {\n sections.push(`**Message**: ${errorData.exception_message}`);\n }\n \n if (errorData.stack_trace) {\n sections.push(`**Stack Trace**:\\n\\`\\`\\`\\n${errorData.stack_trace}\\n\\`\\`\\``);\n }\n \n if (errorData.volume) {\n sections.push(`**Volume**: ${errorData.volume} occurrences`);\n }\n \n if (errorData.users_affected) {\n sections.push(`**Users Affected**: ${errorData.users_affected}`);\n }\n \n if (errorData.first_seen && errorData.last_seen) {\n sections.push(`**First Seen**: ${errorData.first_seen}`);\n sections.push(`**Last Seen**: ${errorData.last_seen}`);\n }\n \n if (errorData.properties && Object.keys(errorData.properties).length > 0) {\n sections.push(`**Properties**: ${JSON.stringify(errorData.properties, null, 2)}`);\n }\n \n return sections.join('\\n\\n');\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"posthog-api.js","sources":["../../src/posthog-api.ts"],"sourcesContent":["import type {\n Task,\n TaskRun,\n LogEntry,\n SupportingFile,\n PostHogAPIConfig,\n PostHogResource,\n ResourceType,\n UrlMention,\n TaskRunArtifact,\n TaskArtifactUploadPayload,\n} from './types.js';\n\ninterface PostHogApiResponse<T> {\n results?: T[];\n count?: number;\n next?: string | null;\n previous?: string | null;\n}\n\nexport interface TaskRunUpdate {\n status?: TaskRun[\"status\"];\n branch?: string | null;\n current_stage?: string | null;\n error_message?: string | null;\n output?: Record<string, unknown> | null;\n state?: Record<string, unknown>;\n}\n\nexport class PostHogAPIClient {\n private config: PostHogAPIConfig;\n private _teamId: number | null = null;\n\n constructor(config: PostHogAPIConfig) {\n this.config = config;\n }\n\n private get baseUrl(): string {\n const host = this.config.apiUrl.endsWith(\"/\") \n ? this.config.apiUrl.slice(0, -1) \n : this.config.apiUrl;\n return host;\n }\n\n private get headers(): Record<string, string> {\n return {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'Content-Type': 'application/json',\n };\n }\n\n private async apiRequest<T>(\n endpoint: string, \n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n \n const response = await fetch(url, {\n ...options,\n headers: {\n ...this.headers,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n let errorMessage: string;\n try {\n const errorResponse = await response.json();\n errorMessage = `Failed request: [${response.status}] ${JSON.stringify(errorResponse)}`;\n } catch {\n errorMessage = `Failed request: [${response.status}] ${response.statusText}`;\n }\n throw new Error(errorMessage);\n }\n\n return response.json();\n }\n\n getTeamId(): number {\n return this.config.projectId;\n }\n\n getBaseUrl(): string {\n return this.baseUrl;\n }\n\n getApiKey(): string {\n return this.config.apiKey;\n }\n\n getLlmGatewayUrl(): string {\n const teamId = this.getTeamId();\n return `${this.baseUrl}/api/projects/${teamId}/llm_gateway`;\n }\n\n async fetchTask(taskId: string): Promise<Task> {\n const teamId = this.getTeamId();\n return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/`);\n }\n\n async listTasks(filters?: {\n repository?: string;\n organization?: string;\n origin_product?: string;\n }): Promise<Task[]> {\n const teamId = this.getTeamId();\n const url = new URL(`${this.baseUrl}/api/projects/${teamId}/tasks/`);\n \n if (filters) {\n Object.entries(filters).forEach(([key, value]) => {\n if (value) url.searchParams.append(key, value);\n });\n }\n\n const response = await this.apiRequest<PostHogApiResponse<Task>>(\n url.pathname + url.search\n );\n \n return response.results || [];\n }\n\n async updateTask(taskId: string, updates: Partial<Task>): Promise<Task> {\n const teamId = this.getTeamId();\n return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/`, {\n method: 'PATCH',\n body: JSON.stringify(updates),\n });\n }\n\n // TaskRun methods\n async listTaskRuns(taskId: string): Promise<TaskRun[]> {\n const teamId = this.getTeamId();\n const response = await this.apiRequest<PostHogApiResponse<TaskRun>>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/`\n );\n return response.results || [];\n }\n\n async getTaskRun(taskId: string, runId: string): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`);\n }\n\n async createTaskRun(\n taskId: string,\n payload?: Partial<Omit<TaskRun, 'id' | 'task' | 'team' | 'created_at' | 'updated_at' | 'completed_at'>>\n ): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/`, {\n method: \"POST\",\n body: JSON.stringify(payload || {}),\n });\n }\n\n async updateTaskRun(\n taskId: string,\n runId: string,\n payload: TaskRunUpdate\n ): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`, {\n method: \"PATCH\",\n body: JSON.stringify(payload),\n });\n }\n\n async setTaskRunOutput(taskId: string, runId: string, output: Record<string, unknown>): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/set_output/`, {\n method: 'PATCH',\n body: JSON.stringify({ output }),\n });\n }\n\n async appendTaskRunLog(taskId: string, runId: string, entries: LogEntry[]): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(`/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/append_log/`, {\n method: 'POST',\n body: JSON.stringify({ entries }),\n });\n }\n\n async uploadTaskArtifacts(\n taskId: string,\n runId: string,\n artifacts: TaskArtifactUploadPayload[]\n ): Promise<TaskRunArtifact[]> {\n if (!artifacts.length) {\n return [];\n }\n\n const teamId = this.getTeamId();\n const response = await this.apiRequest<{ artifacts: TaskRunArtifact[] }>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/artifacts/`,\n {\n method: 'POST',\n body: JSON.stringify({ artifacts }),\n }\n );\n\n return response.artifacts ?? [];\n }\n\n /**\n * Fetch logs from S3 using presigned URL from TaskRun\n * @param taskRun - The task run containing the log_url\n * @returns Array of log entries, or empty array if no logs available\n */\n async fetchTaskRunLogs(taskRun: TaskRun): Promise<LogEntry[]> {\n if (!taskRun.log_url) {\n return [];\n }\n\n try {\n const response = await fetch(taskRun.log_url);\n \n if (!response.ok) {\n throw new Error(`Failed to fetch logs: ${response.status} ${response.statusText}`);\n }\n\n const content = await response.text();\n \n if (!content.trim()) {\n return [];\n }\n\n // Parse newline-delimited JSON\n return content\n .trim()\n .split('\\n')\n .map(line => JSON.parse(line) as LogEntry);\n } catch (error) {\n throw new Error(`Failed to fetch task run logs: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Fetch error details from PostHog error tracking\n */\n async fetchErrorDetails(errorId: string, projectId?: string): Promise<PostHogResource> {\n const teamId = projectId ? parseInt(projectId) : this.getTeamId();\n \n try {\n const errorData = await this.apiRequest<any>(`/api/projects/${teamId}/error_tracking/${errorId}/`);\n \n // Format error details for agent consumption\n const content = this.formatErrorContent(errorData);\n \n return {\n type: 'error',\n id: errorId,\n url: `${this.baseUrl}/project/${teamId}/error_tracking/${errorId}`,\n title: errorData.exception_type || 'Unknown Error',\n content,\n metadata: {\n exception_type: errorData.exception_type,\n first_seen: errorData.first_seen,\n last_seen: errorData.last_seen,\n volume: errorData.volume,\n users_affected: errorData.users_affected,\n },\n };\n } catch (error) {\n throw new Error(`Failed to fetch error details for ${errorId}: ${error}`);\n }\n }\n\n /**\n * Generic resource fetcher by URL or ID\n */\n async fetchResourceByUrl(urlMention: UrlMention): Promise<PostHogResource> {\n switch (urlMention.type) {\n case 'error':\n if (!urlMention.id) {\n throw new Error('Error ID is required for error resources');\n }\n // Extract project ID from URL if available, otherwise use default team\n let projectId: string | undefined;\n if (urlMention.url) {\n const projectIdMatch = urlMention.url.match(/\\/project\\/(\\d+)\\//);\n projectId = projectIdMatch ? projectIdMatch[1] : undefined;\n }\n return this.fetchErrorDetails(urlMention.id, projectId);\n \n case 'experiment':\n case 'insight':\n case 'feature_flag':\n throw new Error(`Resource type '${urlMention.type}' not yet implemented`);\n \n case 'generic':\n // Return a minimal resource for generic URLs\n return {\n type: 'generic',\n id: '',\n url: urlMention.url,\n title: 'Generic Resource',\n content: `Generic resource: ${urlMention.url}`,\n metadata: {},\n };\n \n default:\n throw new Error(`Unknown resource type: ${urlMention.type}`);\n }\n }\n\n /**\n * Format error data for agent consumption\n */\n private formatErrorContent(errorData: any): string {\n const sections = [];\n \n if (errorData.exception_type) {\n sections.push(`**Error Type**: ${errorData.exception_type}`);\n }\n \n if (errorData.exception_message) {\n sections.push(`**Message**: ${errorData.exception_message}`);\n }\n \n if (errorData.stack_trace) {\n sections.push(`**Stack Trace**:\\n\\`\\`\\`\\n${errorData.stack_trace}\\n\\`\\`\\``);\n }\n \n if (errorData.volume) {\n sections.push(`**Volume**: ${errorData.volume} occurrences`);\n }\n \n if (errorData.users_affected) {\n sections.push(`**Users Affected**: ${errorData.users_affected}`);\n }\n \n if (errorData.first_seen && errorData.last_seen) {\n sections.push(`**First Seen**: ${errorData.first_seen}`);\n sections.push(`**Last Seen**: ${errorData.last_seen}`);\n }\n \n if (errorData.properties && Object.keys(errorData.properties).length > 0) {\n sections.push(`**Properties**: ${JSON.stringify(errorData.properties, null, 2)}`);\n }\n \n return sections.join('\\n\\n');\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -18,18 +18,26 @@ export declare class TaskProgressReporter {
|
|
|
18
18
|
private outputLog;
|
|
19
19
|
private totalSteps?;
|
|
20
20
|
private lastLogEntry?;
|
|
21
|
+
private tokenBuffer;
|
|
22
|
+
private tokenCount;
|
|
23
|
+
private tokenFlushTimer?;
|
|
24
|
+
private readonly TOKEN_BATCH_SIZE;
|
|
25
|
+
private readonly TOKEN_FLUSH_INTERVAL_MS;
|
|
26
|
+
private logWriteQueue;
|
|
27
|
+
private readonly LOG_APPEND_MAX_RETRIES;
|
|
28
|
+
private readonly LOG_APPEND_RETRY_BASE_DELAY_MS;
|
|
21
29
|
constructor(posthogAPI: PostHogAPIClient | undefined, logger: Logger);
|
|
22
30
|
get runId(): string | undefined;
|
|
23
31
|
start(taskId: string, metadata?: ProgressMetadata): Promise<void>;
|
|
24
32
|
complete(): Promise<void>;
|
|
25
33
|
fail(error: Error | string): Promise<void>;
|
|
26
34
|
appendLog(line: string): Promise<void>;
|
|
35
|
+
private flushTokens;
|
|
36
|
+
private scheduleTokenFlush;
|
|
37
|
+
private appendLogEntry;
|
|
38
|
+
private writeLogEntry;
|
|
27
39
|
recordEvent(event: AgentEvent): Promise<void>;
|
|
28
40
|
private update;
|
|
29
|
-
private summarizeUserMessage;
|
|
30
|
-
private truncateMultiline;
|
|
31
|
-
private formatToolCallEvent;
|
|
32
|
-
private formatToolResultEvent;
|
|
33
41
|
}
|
|
34
42
|
export {};
|
|
35
43
|
//# sourceMappingURL=task-progress-reporter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-progress-reporter.d.ts","sourceRoot":"","sources":["../../src/task-progress-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,kBAAkB,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"task-progress-reporter.d.ts","sourceRoot":"","sources":["../../src/task-progress-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,kBAAkB,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,YAAY,CAAC;AAEhE,UAAU,gBAAgB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,UAAU,CAAC,CAAmB;IACtC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAO;IACxC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAQ;IAChD,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAK;IAC5C,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CAAO;gBAE1C,UAAU,EAAE,gBAAgB,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM;IAKpE,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAEK,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBrE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAezB,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAI9B,WAAW;IAezB,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,cAAc;YAqBR,aAAa;IAiCrB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;YA0OrC,MAAM;CAoCrB"}
|
|
@@ -12,6 +12,14 @@ class TaskProgressReporter {
|
|
|
12
12
|
outputLog = [];
|
|
13
13
|
totalSteps;
|
|
14
14
|
lastLogEntry;
|
|
15
|
+
tokenBuffer = '';
|
|
16
|
+
tokenCount = 0;
|
|
17
|
+
tokenFlushTimer;
|
|
18
|
+
TOKEN_BATCH_SIZE = 100;
|
|
19
|
+
TOKEN_FLUSH_INTERVAL_MS = 1000;
|
|
20
|
+
logWriteQueue = Promise.resolve();
|
|
21
|
+
LOG_APPEND_MAX_RETRIES = 3;
|
|
22
|
+
LOG_APPEND_RETRY_BASE_DELAY_MS = 200;
|
|
15
23
|
constructor(posthogAPI, logger) {
|
|
16
24
|
this.posthogAPI = posthogAPI;
|
|
17
25
|
this.logger = logger.child('TaskProgressReporter');
|
|
@@ -38,69 +46,309 @@ class TaskProgressReporter {
|
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
48
|
async complete() {
|
|
49
|
+
await this.flushTokens(); // Flush any remaining tokens before completion
|
|
50
|
+
try {
|
|
51
|
+
await this.logWriteQueue;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
this.logger.debug('Pending logs failed to write during completion', { error });
|
|
55
|
+
}
|
|
56
|
+
if (this.tokenFlushTimer) {
|
|
57
|
+
clearTimeout(this.tokenFlushTimer);
|
|
58
|
+
this.tokenFlushTimer = undefined;
|
|
59
|
+
}
|
|
41
60
|
await this.update({ status: 'completed' }, 'Task execution completed');
|
|
42
61
|
}
|
|
43
62
|
async fail(error) {
|
|
63
|
+
try {
|
|
64
|
+
await this.logWriteQueue;
|
|
65
|
+
}
|
|
66
|
+
catch (logError) {
|
|
67
|
+
this.logger.debug('Pending logs failed to write during fail', { error: logError });
|
|
68
|
+
}
|
|
44
69
|
const message = typeof error === 'string' ? error : error.message;
|
|
45
70
|
await this.update({ status: 'failed', error_message: message }, `Task execution failed: ${message}`);
|
|
46
71
|
}
|
|
47
72
|
async appendLog(line) {
|
|
48
73
|
await this.update({}, line);
|
|
49
74
|
}
|
|
75
|
+
async flushTokens() {
|
|
76
|
+
if (!this.tokenBuffer || this.tokenCount === 0) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const buffer = this.tokenBuffer;
|
|
80
|
+
this.tokenBuffer = '';
|
|
81
|
+
this.tokenCount = 0;
|
|
82
|
+
await this.appendLogEntry({
|
|
83
|
+
type: 'token',
|
|
84
|
+
message: buffer,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
scheduleTokenFlush() {
|
|
88
|
+
if (this.tokenFlushTimer) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.tokenFlushTimer = setTimeout(() => {
|
|
92
|
+
this.tokenFlushTimer = undefined;
|
|
93
|
+
this.flushTokens().catch((err) => {
|
|
94
|
+
this.logger.warn('Failed to flush tokens', { error: err });
|
|
95
|
+
});
|
|
96
|
+
}, this.TOKEN_FLUSH_INTERVAL_MS);
|
|
97
|
+
}
|
|
98
|
+
appendLogEntry(entry) {
|
|
99
|
+
if (!this.posthogAPI || !this.runId || !this.taskId) {
|
|
100
|
+
return Promise.resolve();
|
|
101
|
+
}
|
|
102
|
+
const taskId = this.taskId;
|
|
103
|
+
const runId = this.runId;
|
|
104
|
+
this.logWriteQueue = this.logWriteQueue
|
|
105
|
+
.catch((error) => {
|
|
106
|
+
this.logger.debug('Previous log append failed', {
|
|
107
|
+
taskId,
|
|
108
|
+
runId,
|
|
109
|
+
error: error instanceof Error ? error.message : String(error),
|
|
110
|
+
});
|
|
111
|
+
})
|
|
112
|
+
.then(() => this.writeLogEntry(taskId, runId, entry));
|
|
113
|
+
return this.logWriteQueue;
|
|
114
|
+
}
|
|
115
|
+
async writeLogEntry(taskId, runId, entry) {
|
|
116
|
+
if (!this.posthogAPI) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
for (let attempt = 1; attempt <= this.LOG_APPEND_MAX_RETRIES; attempt++) {
|
|
120
|
+
try {
|
|
121
|
+
await this.posthogAPI.appendTaskRunLog(taskId, runId, [entry]);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
this.logger.warn('Failed to append log entry', {
|
|
126
|
+
taskId,
|
|
127
|
+
runId,
|
|
128
|
+
attempt,
|
|
129
|
+
maxAttempts: this.LOG_APPEND_MAX_RETRIES,
|
|
130
|
+
error: error.message,
|
|
131
|
+
});
|
|
132
|
+
if (attempt === this.LOG_APPEND_MAX_RETRIES) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const delayMs = this.LOG_APPEND_RETRY_BASE_DELAY_MS * Math.pow(2, attempt - 1);
|
|
136
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
50
140
|
async recordEvent(event) {
|
|
51
141
|
if (!this.posthogAPI || !this.runId || !this.taskId) {
|
|
52
142
|
return;
|
|
53
143
|
}
|
|
54
144
|
switch (event.type) {
|
|
55
|
-
case 'token':
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
145
|
+
case 'token': {
|
|
146
|
+
// Batch tokens for efficiency
|
|
147
|
+
this.tokenBuffer += event.content;
|
|
148
|
+
this.tokenCount++;
|
|
149
|
+
if (this.tokenCount >= this.TOKEN_BATCH_SIZE) {
|
|
150
|
+
await this.flushTokens();
|
|
151
|
+
if (this.tokenFlushTimer) {
|
|
152
|
+
clearTimeout(this.tokenFlushTimer);
|
|
153
|
+
this.tokenFlushTimer = undefined;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
this.scheduleTokenFlush();
|
|
158
|
+
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
case 'content_block_start': {
|
|
162
|
+
await this.appendLogEntry({
|
|
163
|
+
type: 'content_block_start',
|
|
164
|
+
message: JSON.stringify({
|
|
165
|
+
index: event.index,
|
|
166
|
+
contentType: event.contentType,
|
|
167
|
+
toolName: event.toolName,
|
|
168
|
+
toolId: event.toolId,
|
|
169
|
+
ts: event.ts,
|
|
170
|
+
}),
|
|
171
|
+
});
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
case 'content_block_stop': {
|
|
175
|
+
await this.appendLogEntry({
|
|
176
|
+
type: 'content_block_stop',
|
|
177
|
+
message: JSON.stringify({
|
|
178
|
+
index: event.index,
|
|
179
|
+
ts: event.ts,
|
|
180
|
+
}),
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
case 'message_start': {
|
|
185
|
+
await this.appendLogEntry({
|
|
186
|
+
type: 'message_start',
|
|
187
|
+
message: JSON.stringify({
|
|
188
|
+
messageId: event.messageId,
|
|
189
|
+
model: event.model,
|
|
190
|
+
ts: event.ts,
|
|
191
|
+
}),
|
|
192
|
+
});
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
case 'message_delta': {
|
|
196
|
+
await this.appendLogEntry({
|
|
197
|
+
type: 'message_delta',
|
|
198
|
+
message: JSON.stringify({
|
|
199
|
+
stopReason: event.stopReason,
|
|
200
|
+
stopSequence: event.stopSequence,
|
|
201
|
+
usage: event.usage,
|
|
202
|
+
ts: event.ts,
|
|
203
|
+
}),
|
|
204
|
+
});
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
case 'message_stop': {
|
|
208
|
+
await this.appendLogEntry({
|
|
209
|
+
type: 'message_stop',
|
|
210
|
+
message: JSON.stringify({ ts: event.ts }),
|
|
211
|
+
});
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
case 'status': {
|
|
215
|
+
await this.appendLogEntry({
|
|
216
|
+
type: 'status',
|
|
217
|
+
message: JSON.stringify({
|
|
218
|
+
phase: event.phase,
|
|
219
|
+
kind: event.kind,
|
|
220
|
+
branch: event.branch,
|
|
221
|
+
prUrl: event.prUrl,
|
|
222
|
+
taskId: event.taskId,
|
|
223
|
+
messageId: event.messageId,
|
|
224
|
+
model: event.model,
|
|
225
|
+
ts: event.ts,
|
|
226
|
+
}),
|
|
227
|
+
});
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
case 'artifact': {
|
|
231
|
+
await this.appendLogEntry({
|
|
232
|
+
type: 'artifact',
|
|
233
|
+
message: JSON.stringify({
|
|
234
|
+
kind: event.kind,
|
|
235
|
+
content: event.content,
|
|
236
|
+
ts: event.ts,
|
|
237
|
+
}),
|
|
238
|
+
});
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
case 'init': {
|
|
242
|
+
await this.appendLogEntry({
|
|
243
|
+
type: 'init',
|
|
244
|
+
message: JSON.stringify({
|
|
245
|
+
model: event.model,
|
|
246
|
+
tools: event.tools,
|
|
247
|
+
permissionMode: event.permissionMode,
|
|
248
|
+
cwd: event.cwd,
|
|
249
|
+
apiKeySource: event.apiKeySource,
|
|
250
|
+
ts: event.ts,
|
|
251
|
+
}),
|
|
252
|
+
});
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
case 'metric': {
|
|
256
|
+
await this.appendLogEntry({
|
|
257
|
+
type: 'metric',
|
|
258
|
+
message: JSON.stringify({
|
|
259
|
+
key: event.key,
|
|
260
|
+
value: event.value,
|
|
261
|
+
unit: event.unit,
|
|
262
|
+
ts: event.ts,
|
|
263
|
+
}),
|
|
264
|
+
});
|
|
66
265
|
return;
|
|
266
|
+
}
|
|
267
|
+
case 'compact_boundary': {
|
|
268
|
+
await this.appendLogEntry({
|
|
269
|
+
type: 'compact_boundary',
|
|
270
|
+
message: JSON.stringify({
|
|
271
|
+
trigger: event.trigger,
|
|
272
|
+
preTokens: event.preTokens,
|
|
273
|
+
ts: event.ts,
|
|
274
|
+
}),
|
|
275
|
+
});
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
67
278
|
case 'tool_call': {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
279
|
+
await this.appendLogEntry({
|
|
280
|
+
type: 'tool_call',
|
|
281
|
+
message: JSON.stringify({
|
|
282
|
+
toolName: event.toolName,
|
|
283
|
+
callId: event.callId,
|
|
284
|
+
args: event.args,
|
|
285
|
+
parentToolUseId: event.parentToolUseId,
|
|
286
|
+
ts: event.ts,
|
|
287
|
+
}),
|
|
288
|
+
});
|
|
72
289
|
return;
|
|
73
290
|
}
|
|
74
291
|
case 'tool_result': {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
292
|
+
await this.appendLogEntry({
|
|
293
|
+
type: 'tool_result',
|
|
294
|
+
message: JSON.stringify({
|
|
295
|
+
toolName: event.toolName,
|
|
296
|
+
callId: event.callId,
|
|
297
|
+
result: event.result,
|
|
298
|
+
isError: event.isError,
|
|
299
|
+
parentToolUseId: event.parentToolUseId,
|
|
300
|
+
ts: event.ts,
|
|
301
|
+
}),
|
|
302
|
+
});
|
|
79
303
|
return;
|
|
80
304
|
}
|
|
81
|
-
case '
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
305
|
+
case 'error': {
|
|
306
|
+
await this.appendLogEntry({
|
|
307
|
+
type: 'error',
|
|
308
|
+
message: JSON.stringify({
|
|
309
|
+
message: event.message,
|
|
310
|
+
errorType: event.errorType,
|
|
311
|
+
context: event.context,
|
|
312
|
+
ts: event.ts,
|
|
313
|
+
}),
|
|
314
|
+
});
|
|
86
315
|
return;
|
|
316
|
+
}
|
|
87
317
|
case 'done': {
|
|
88
|
-
|
|
89
|
-
|
|
318
|
+
await this.appendLogEntry({
|
|
319
|
+
type: 'done',
|
|
320
|
+
message: JSON.stringify({
|
|
321
|
+
result: event.result,
|
|
322
|
+
durationMs: event.durationMs,
|
|
323
|
+
durationApiMs: event.durationApiMs,
|
|
324
|
+
numTurns: event.numTurns,
|
|
325
|
+
totalCostUsd: event.totalCostUsd,
|
|
326
|
+
usage: event.usage,
|
|
327
|
+
modelUsage: event.modelUsage,
|
|
328
|
+
permissionDenials: event.permissionDenials,
|
|
329
|
+
ts: event.ts,
|
|
330
|
+
}),
|
|
331
|
+
});
|
|
90
332
|
return;
|
|
91
333
|
}
|
|
92
|
-
case 'init':
|
|
93
|
-
// Omit verbose init messages from persisted log
|
|
94
|
-
return;
|
|
95
334
|
case 'user_message': {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
335
|
+
await this.appendLogEntry({
|
|
336
|
+
type: 'user_message',
|
|
337
|
+
message: JSON.stringify({
|
|
338
|
+
content: event.content,
|
|
339
|
+
isSynthetic: event.isSynthetic,
|
|
340
|
+
ts: event.ts,
|
|
341
|
+
}),
|
|
342
|
+
});
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
case 'raw_sdk_event': {
|
|
346
|
+
// Skip raw SDK events - too verbose for persistence
|
|
100
347
|
return;
|
|
101
348
|
}
|
|
102
349
|
default:
|
|
103
|
-
// For any unfamiliar event types,
|
|
350
|
+
// For any unfamiliar event types, log them as-is
|
|
351
|
+
this.logger.debug('Unknown event type', { type: event.type });
|
|
104
352
|
return;
|
|
105
353
|
}
|
|
106
354
|
}
|
|
@@ -139,89 +387,6 @@ class TaskProgressReporter {
|
|
|
139
387
|
}
|
|
140
388
|
}
|
|
141
389
|
}
|
|
142
|
-
summarizeUserMessage(content) {
|
|
143
|
-
if (!content) {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
const trimmed = content.trim();
|
|
147
|
-
if (!trimmed) {
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
const fileUpdateMatch = trimmed.match(/The file\s+([^\s]+)\s+has been updated/i);
|
|
151
|
-
if (fileUpdateMatch) {
|
|
152
|
-
return `[user] file updated: ${fileUpdateMatch[1]}`;
|
|
153
|
-
}
|
|
154
|
-
if (/Todos have been modified/i.test(trimmed)) {
|
|
155
|
-
return '[todo] list updated';
|
|
156
|
-
}
|
|
157
|
-
const diffMatch = trimmed.match(/diff --git a\/([^\s]+) b\/([^\s]+)/);
|
|
158
|
-
if (diffMatch) {
|
|
159
|
-
return `[diff] ${diffMatch[2] ?? diffMatch[1]}`;
|
|
160
|
-
}
|
|
161
|
-
const gitStatusMatch = trimmed.match(/^On branch ([^\n]+)/);
|
|
162
|
-
if (gitStatusMatch) {
|
|
163
|
-
return `[git] status ${gitStatusMatch[1]}`;
|
|
164
|
-
}
|
|
165
|
-
if (/This Bash command contains multiple operations/i.test(trimmed)) {
|
|
166
|
-
return '[approval] multi-step command pending';
|
|
167
|
-
}
|
|
168
|
-
if (/This command requires approval/i.test(trimmed)) {
|
|
169
|
-
return '[approval] command awaiting approval';
|
|
170
|
-
}
|
|
171
|
-
if (/^Exit plan mode\?/i.test(trimmed)) {
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
if (trimmed.includes('node_modules')) {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
if (trimmed.includes('total ') && trimmed.includes('drwx')) {
|
|
178
|
-
return null;
|
|
179
|
-
}
|
|
180
|
-
if (trimmed.includes('→')) {
|
|
181
|
-
return null;
|
|
182
|
-
}
|
|
183
|
-
if (trimmed.split('\n').length > 2) {
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
const normalized = trimmed.replace(/\s+/g, ' ');
|
|
187
|
-
const maxLen = 120;
|
|
188
|
-
if (!normalized) {
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
const preview = normalized.length > maxLen ? `${normalized.slice(0, maxLen)}…` : normalized;
|
|
192
|
-
return `[user] ${preview}`;
|
|
193
|
-
}
|
|
194
|
-
truncateMultiline(text, max = 160) {
|
|
195
|
-
if (!text) {
|
|
196
|
-
return '';
|
|
197
|
-
}
|
|
198
|
-
const compact = text.replace(/\s+/g, ' ').trim();
|
|
199
|
-
return compact.length > max ? `${compact.slice(0, max)}…` : compact;
|
|
200
|
-
}
|
|
201
|
-
formatToolCallEvent(event) {
|
|
202
|
-
// File operations to track
|
|
203
|
-
const fileOps = ['read_file', 'write', 'search_replace', 'delete_file', 'glob_file_search', 'file_search', 'list_dir', 'edit_notebook'];
|
|
204
|
-
// Terminal commands to track
|
|
205
|
-
const terminalOps = ['run_terminal_cmd', 'bash', 'shell'];
|
|
206
|
-
if (fileOps.includes(event.toolName)) {
|
|
207
|
-
// Extract file path from args
|
|
208
|
-
const path = event.args?.target_file || event.args?.file_path || event.args?.target_notebook || event.args?.target_directory || '';
|
|
209
|
-
return `[tool] ${event.toolName}${path ? `: ${path}` : ''}`;
|
|
210
|
-
}
|
|
211
|
-
else if (terminalOps.includes(event.toolName)) {
|
|
212
|
-
// Extract command from args
|
|
213
|
-
const cmd = event.args?.command || '';
|
|
214
|
-
const truncated = cmd.length > 80 ? `${cmd.slice(0, 80)}…` : cmd;
|
|
215
|
-
return `[cmd] ${truncated}`;
|
|
216
|
-
}
|
|
217
|
-
// Skip other tools from persistence
|
|
218
|
-
return null;
|
|
219
|
-
}
|
|
220
|
-
formatToolResultEvent(event) {
|
|
221
|
-
// We don't need to log tool results separately - tool calls are sufficient
|
|
222
|
-
// This keeps the log concise
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
390
|
}
|
|
226
391
|
|
|
227
392
|
export { TaskProgressReporter };
|