@posthog/agent 1.13.0 → 1.14.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.
@@ -1,100 +1,80 @@
1
- export const RESEARCH_SYSTEM_PROMPT = `# PostHog AI Coding Agent - Research Mode
2
-
3
- You are a PostHog AI Coding Agent operating in RESEARCH mode.
4
-
5
- ## Your Role
6
-
7
- You are a research agent that explores codebases to understand implementation context and generate clarifying questions for development tasks.
8
-
9
- ## Important Constraints
10
-
11
- - **Read-Only Mode**: You can only read files, search code, and analyze the codebase
12
- - **No Modifications**: You cannot make any changes or edits to code files
13
- - **Research Focus**: Your goal is understanding and asking the right questions
14
-
15
- ## Available Tools
16
-
17
- - File reading and exploration
18
- - Code search and analysis
19
- - Repository structure analysis
20
- - Documentation review
21
-
22
- ## Research Process
23
-
24
- When given a task, follow this systematic approach:
25
-
26
- 1. **Codebase Analysis**
27
- - Explore the repository structure
28
- - Identify relevant files and components
29
- - Understand existing patterns and conventions
30
- - Review related code and dependencies
31
- - Look for similar implementations or patterns
32
-
33
- 2. **Decision Point Identification**
34
- - Identify areas where implementation decisions need to be made
35
- - Find multiple viable approaches in the codebase
36
- - Note where user preferences would affect the implementation
37
- - Consider architectural or design pattern choices
38
-
39
- 3. **Question Generation**
40
- - Generate 3-5 clarifying questions
41
- - Each question should offer 2-3 concrete options based on codebase analysis
42
- - Options should reference actual patterns/approaches found in the code
43
- - Always include option c) as "Something else (please specify)" for flexibility
44
- - Focus on high-impact decisions that affect the implementation approach
45
-
46
- ## Output Format
47
-
48
- The artifact MUST follow this EXACT markdown format (this is critical for parsing):
1
+ export const RESEARCH_SYSTEM_PROMPT = `<role>
2
+ PostHog AI Research Agent — analyze codebases to understand implementation context and identify areas of focus for development tasks.
3
+ </role>
4
+
5
+ <constraints>
6
+ - Read-only: analyze files, search code, explore structure
7
+ - No modifications or code changes
8
+ </constraints>
9
+
10
+ <objective>
11
+ Your PRIMARY goal is to understand the codebase thoroughly and provide context for the planning phase.
12
+
13
+ ONLY generate clarifying questions if:
14
+ - The task description is genuinely vague or ambiguous
15
+ - There are multiple valid architectural approaches with significant tradeoffs
16
+ - Critical information is missing that cannot be inferred from the codebase
17
+
18
+ DO NOT ask questions like "how should I fix this" or "what approach do you prefer" — that defeats the purpose of autonomous task execution. The user has already specified what they want done.
19
+ </objective>
20
+
21
+ <process>
22
+ 1. Explore repository structure and identify relevant files/components
23
+ 2. Understand existing patterns, conventions, and dependencies
24
+ 3. Locate similar implementations or related code
25
+ 4. Identify the key areas of the codebase that will be affected
26
+ 5. Document your findings to provide context for planning
27
+ 6. ONLY if genuinely needed: generate 2-3 specific clarification questions
28
+ </process>
29
+
30
+ <output_format>
31
+ Output ONLY the markdown artifact with no preamble:
49
32
 
50
33
  \`\`\`markdown
51
- # Research Questions
52
-
53
- Based on my analysis of the codebase, here are the key questions to guide implementation:
54
-
55
- ## Question 1: [Question text - be specific and clear]
34
+ # Research Findings
56
35
 
57
- **Options:**
58
- - a) [Concrete option based on existing pattern - reference specific files/components]
59
- - b) [Alternative approach based on another pattern - reference specific files/components]
60
- - c) Something else (please specify)
36
+ ## Codebase Analysis
37
+ [Brief summary of relevant code structure, patterns, and files]
61
38
 
62
- ## Question 2: [Next question - be specific and clear]
39
+ ## Key Areas of Focus
40
+ [List specific files/components that need modification]
63
41
 
64
- **Options:**
65
- - a) [Option with specific code references]
66
- - b) [Alternative with specific code references]
67
- - c) Something else (please specify)
42
+ ## Implementation Context
43
+ [Important patterns, dependencies, or constraints found in the code]
68
44
 
69
- ## Question 3: [Continue with 3-5 questions total]
45
+ ## Clarifying Questions
46
+ [ONLY include this section if it will increase the quality of the plan]
70
47
 
48
+ ## Question 1: [Specific architectural decision]
71
49
  **Options:**
72
- - a) [Option]
73
- - b) [Alternative]
50
+ - a) [Concrete option with file references]
51
+ - b) [Alternative with file references]
74
52
  - c) Something else (please specify)
75
53
  \`\`\`
76
54
 
77
- ## CRITICAL FORMAT REQUIREMENTS
78
-
79
- - Use EXACTLY "## Question N:" format for question headers (h2 level, not h3)
80
- - Each question MUST be followed by "**Options:**" on its own line
81
- - Each option MUST start with "- a)", "- b)", "- c)", etc.
82
- - Always include "c) Something else (please specify)" as the last option
83
- - Do NOT add extra sections between questions
84
- - Keep context and analysis BEFORE the questions section, not mixed in
85
-
86
- ## Important Requirements
87
-
88
- - DO NOT GENERATE ANY QUESTIONS IF YOU DON'T HAVE ANY (instead say "No questions required")
89
- - Generate up to 5 questions (no more)
90
- - Make options specific and reference actual code/patterns you find
91
- - Each question must have at least 2 concrete options plus "Something else"
92
- - Focus on architectural and implementation approach decisions
93
- - Reference specific files, components, or patterns in your options
94
- - Make sure the questions help guide a clear implementation path
95
- - Respond only with the markdown content above, no other text or formatting, no acknowledgement, no explanation, no nothing.
96
-
97
- ## Final Step
98
-
99
- Your research should be thorough enough that the questions help clarify the user's preferences and guide the planning phase effectively.`;
55
+ Format requirements:
56
+ - Use "## Question N:" for question headers (h2)
57
+ - Follow with "**Options:**" on its own line
58
+ - Start options with "- a)", "- b)", "- c)"
59
+ - Always include "c) Something else (please specify)"
60
+ - Max 3 questions total
61
+ </output_format>
62
+
63
+ <examples>
64
+ <good_example>
65
+ Task: "Fix authentication bug in login flow"
66
+ Output: Research findings showing auth flow files, patterns used, NO questions needed
67
+ </good_example>
68
+
69
+ <bad_example>
70
+ Task: "Fix authentication bug"
71
+ Output: "How should I fix the authentication? a) Fix it one way b) Fix it another way"
72
+ Reason: Don't ask HOW to do the task that's what the agent is for
73
+ </bad_example>
74
+
75
+ <good_example>
76
+ Task: "Add caching to API endpoints"
77
+ Output: Research showing existing cache implementations, question about cache backend choice IF multiple production systems are already in use
78
+ </good_example>
79
+ </examples>`;
100
80
 
@@ -213,42 +213,50 @@ export class PromptBuilder {
213
213
  repositoryPath
214
214
  );
215
215
 
216
- // Process URL references in description
216
+ // Process URL references in description
217
217
  const { description: processedDescription, referencedResources } = await this.processUrlReferences(
218
218
  descriptionAfterFiles
219
219
  );
220
220
 
221
- let prompt = '';
222
- prompt += `## Current Task\n\n**Task**: ${task.title}\n**Description**: ${processedDescription}`;
221
+ let prompt = '<task>\n';
222
+ prompt += `<title>${task.title}</title>\n`;
223
+ prompt += `<description>${processedDescription}</description>\n`;
223
224
 
224
225
  if ((task as any).primary_repository) {
225
- prompt += `\n**Repository**: ${(task as any).primary_repository}`;
226
+ prompt += `<repository>${(task as any).primary_repository}</repository>\n`;
226
227
  }
228
+ prompt += '</task>\n';
227
229
 
228
230
  // Add referenced files from @ mentions
229
231
  if (referencedFiles.length > 0) {
230
- prompt += `\n\n## Referenced Files\n\n`;
232
+ prompt += '\n<referenced_files>\n';
231
233
  for (const file of referencedFiles) {
232
- prompt += `### ${file.path}\n\`\`\`\n${file.content}\n\`\`\`\n\n`;
234
+ prompt += `<file path="${file.path}">\n\`\`\`\n${file.content}\n\`\`\`\n</file>\n`;
233
235
  }
236
+ prompt += '</referenced_files>\n';
234
237
  }
235
238
 
236
239
  // Add referenced resources from URL mentions
237
240
  if (referencedResources.length > 0) {
238
- prompt += `\n\n## Referenced Resources\n\n`;
241
+ prompt += '\n<referenced_resources>\n';
239
242
  for (const resource of referencedResources) {
240
- prompt += `### ${resource.title} (${resource.type})\n**URL**: ${resource.url}\n\n${resource.content}\n\n`;
243
+ prompt += `<resource type="${resource.type}" url="${resource.url}">\n`;
244
+ prompt += `<title>${resource.title}</title>\n`;
245
+ prompt += `<content>${resource.content}</content>\n`;
246
+ prompt += '</resource>\n';
241
247
  }
248
+ prompt += '</referenced_resources>\n';
242
249
  }
243
250
 
244
251
  try {
245
252
  const taskFiles = await this.getTaskFiles(task.id);
246
253
  const contextFiles = taskFiles.filter((f: any) => f.type === 'context' || f.type === 'reference');
247
254
  if (contextFiles.length > 0) {
248
- prompt += `\n\n## Supporting Files`;
255
+ prompt += '\n<supporting_files>\n';
249
256
  for (const file of contextFiles) {
250
- prompt += `\n\n### ${file.name} (${file.type})\n${file.content}`;
257
+ prompt += `<file name="${file.name}" type="${file.type}">\n${file.content}\n</file>\n`;
251
258
  }
259
+ prompt += '</supporting_files>\n';
252
260
  }
253
261
  } catch (error) {
254
262
  this.logger.debug('No existing task files found for research', { taskId: task.id });
@@ -264,42 +272,50 @@ export class PromptBuilder {
264
272
  repositoryPath
265
273
  );
266
274
 
267
- // Process URL references in description
275
+ // Process URL references in description
268
276
  const { description: processedDescription, referencedResources } = await this.processUrlReferences(
269
277
  descriptionAfterFiles
270
278
  );
271
279
 
272
- let prompt = '';
273
- prompt += `## Current Task\n\n**Task**: ${task.title}\n**Description**: ${processedDescription}`;
280
+ let prompt = '<task>\n';
281
+ prompt += `<title>${task.title}</title>\n`;
282
+ prompt += `<description>${processedDescription}</description>\n`;
274
283
 
275
284
  if ((task as any).primary_repository) {
276
- prompt += `\n**Repository**: ${(task as any).primary_repository}`;
285
+ prompt += `<repository>${(task as any).primary_repository}</repository>\n`;
277
286
  }
287
+ prompt += '</task>\n';
278
288
 
279
289
  // Add referenced files from @ mentions
280
290
  if (referencedFiles.length > 0) {
281
- prompt += `\n\n## Referenced Files\n\n`;
291
+ prompt += '\n<referenced_files>\n';
282
292
  for (const file of referencedFiles) {
283
- prompt += `### ${file.path}\n\`\`\`\n${file.content}\n\`\`\`\n\n`;
293
+ prompt += `<file path="${file.path}">\n\`\`\`\n${file.content}\n\`\`\`\n</file>\n`;
284
294
  }
295
+ prompt += '</referenced_files>\n';
285
296
  }
286
297
 
287
298
  // Add referenced resources from URL mentions
288
299
  if (referencedResources.length > 0) {
289
- prompt += `\n\n## Referenced Resources\n\n`;
300
+ prompt += '\n<referenced_resources>\n';
290
301
  for (const resource of referencedResources) {
291
- prompt += `### ${resource.title} (${resource.type})\n**URL**: ${resource.url}\n\n${resource.content}\n\n`;
302
+ prompt += `<resource type="${resource.type}" url="${resource.url}">\n`;
303
+ prompt += `<title>${resource.title}</title>\n`;
304
+ prompt += `<content>${resource.content}</content>\n`;
305
+ prompt += '</resource>\n';
292
306
  }
307
+ prompt += '</referenced_resources>\n';
293
308
  }
294
309
 
295
310
  try {
296
311
  const taskFiles = await this.getTaskFiles(task.id);
297
312
  const contextFiles = taskFiles.filter((f: any) => f.type === 'context' || f.type === 'reference');
298
313
  if (contextFiles.length > 0) {
299
- prompt += `\n\n## Supporting Files`;
314
+ prompt += '\n<supporting_files>\n';
300
315
  for (const file of contextFiles) {
301
- prompt += `\n\n### ${file.name} (${file.type})\n${file.content}`;
316
+ prompt += `<file name="${file.name}" type="${file.type}">\n${file.content}\n</file>\n`;
302
317
  }
318
+ prompt += '</supporting_files>\n';
303
319
  }
304
320
  } catch (error) {
305
321
  this.logger.debug('No existing task files found for planning', { taskId: task.id });
@@ -315,7 +331,12 @@ export class PromptBuilder {
315
331
 
316
332
  const planTemplate = await this.generatePlanTemplate(templateVariables);
317
333
 
318
- prompt += `\n\nPlease analyze the codebase and create a detailed implementation plan for this task. Use the following template structure for your plan:\n\n${planTemplate}\n\nFill in each section with specific, actionable information based on your analysis. Replace all placeholder content with actual details about this task.`;
334
+ prompt += '\n<instructions>\n';
335
+ prompt += 'Analyze the codebase and create a detailed implementation plan. Use the template structure below, filling each section with specific, actionable information.\n';
336
+ prompt += '</instructions>\n\n';
337
+ prompt += '<plan_template>\n';
338
+ prompt += planTemplate;
339
+ prompt += '\n</plan_template>';
319
340
 
320
341
  return prompt;
321
342
  }
@@ -327,56 +348,71 @@ export class PromptBuilder {
327
348
  repositoryPath
328
349
  );
329
350
 
330
- // Process URL references in description
351
+ // Process URL references in description
331
352
  const { description: processedDescription, referencedResources } = await this.processUrlReferences(
332
353
  descriptionAfterFiles
333
354
  );
334
355
 
335
- let prompt = '';
336
- prompt += `## Current Task\n\n**Task**: ${task.title}\n**Description**: ${processedDescription}`;
356
+ let prompt = '<task>\n';
357
+ prompt += `<title>${task.title}</title>\n`;
358
+ prompt += `<description>${processedDescription}</description>\n`;
337
359
 
338
360
  if ((task as any).primary_repository) {
339
- prompt += `\n**Repository**: ${(task as any).primary_repository}`;
361
+ prompt += `<repository>${(task as any).primary_repository}</repository>\n`;
340
362
  }
363
+ prompt += '</task>\n';
341
364
 
342
365
  // Add referenced files from @ mentions
343
366
  if (referencedFiles.length > 0) {
344
- prompt += `\n\n## Referenced Files\n\n`;
367
+ prompt += '\n<referenced_files>\n';
345
368
  for (const file of referencedFiles) {
346
- prompt += `### ${file.path}\n\`\`\`\n${file.content}\n\`\`\`\n\n`;
369
+ prompt += `<file path="${file.path}">\n\`\`\`\n${file.content}\n\`\`\`\n</file>\n`;
347
370
  }
371
+ prompt += '</referenced_files>\n';
348
372
  }
349
373
 
350
374
  // Add referenced resources from URL mentions
351
375
  if (referencedResources.length > 0) {
352
- prompt += `\n\n## Referenced Resources\n\n`;
376
+ prompt += '\n<referenced_resources>\n';
353
377
  for (const resource of referencedResources) {
354
- prompt += `### ${resource.title} (${resource.type})\n**URL**: ${resource.url}\n\n${resource.content}\n\n`;
378
+ prompt += `<resource type="${resource.type}" url="${resource.url}">\n`;
379
+ prompt += `<title>${resource.title}</title>\n`;
380
+ prompt += `<content>${resource.content}</content>\n`;
381
+ prompt += '</resource>\n';
355
382
  }
383
+ prompt += '</referenced_resources>\n';
356
384
  }
357
385
 
358
386
  try {
359
387
  const taskFiles = await this.getTaskFiles(task.id);
360
388
  const hasPlan = taskFiles.some((f: any) => f.type === 'plan');
389
+
361
390
  if (taskFiles.length > 0) {
362
- prompt += `\n\n## Context and Supporting Information`;
391
+ prompt += '\n<context>\n';
363
392
  for (const file of taskFiles) {
364
393
  if (file.type === 'plan') {
365
- prompt += `\n\n### Execution Plan\n${file.content}`;
394
+ prompt += `<plan>\n${file.content}\n</plan>\n`;
366
395
  } else {
367
- prompt += `\n\n### ${file.name} (${file.type})\n${file.content}`;
396
+ prompt += `<file name="${file.name}" type="${file.type}">\n${file.content}\n</file>\n`;
368
397
  }
369
398
  }
399
+ prompt += '</context>\n';
370
400
  }
401
+
402
+ prompt += '\n<instructions>\n';
371
403
  if (hasPlan) {
372
- prompt += `\n\nPlease implement the changes described in the execution plan above. Follow the plan step-by-step and make the necessary file modifications. You must actually edit files and make changes - do not just analyze or review.`;
404
+ prompt += 'Implement the changes described in the execution plan. Follow the plan step-by-step and make the necessary file modifications.\n';
373
405
  } else {
374
- prompt += `\n\nPlease implement the changes described in the task above. You must actually edit files and make changes - do not just analyze or review.`;
406
+ prompt += 'Implement the changes described in the task. Make the necessary file modifications to complete the task.\n';
375
407
  }
408
+ prompt += '</instructions>';
376
409
  } catch (error) {
377
410
  this.logger.debug('No supporting files found for execution', { taskId: task.id });
378
- prompt += `\n\nPlease implement the changes described in the task above.`;
411
+ prompt += '\n<instructions>\n';
412
+ prompt += 'Implement the changes described in the task.\n';
413
+ prompt += '</instructions>';
379
414
  }
415
+
380
416
  return prompt;
381
417
  }
382
418
  }