@posthog/agent 1.10.0 → 1.11.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.
Files changed (49) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/src/agent-registry.d.ts.map +1 -1
  4. package/dist/src/agent-registry.js +6 -0
  5. package/dist/src/agent-registry.js.map +1 -1
  6. package/dist/src/agent.d.ts +5 -0
  7. package/dist/src/agent.d.ts.map +1 -1
  8. package/dist/src/agent.js +327 -2
  9. package/dist/src/agent.js.map +1 -1
  10. package/dist/src/agents/research.d.ts +2 -0
  11. package/dist/src/agents/research.d.ts.map +1 -0
  12. package/dist/src/agents/research.js +105 -0
  13. package/dist/src/agents/research.js.map +1 -0
  14. package/dist/src/file-manager.d.ts +19 -0
  15. package/dist/src/file-manager.d.ts.map +1 -1
  16. package/dist/src/file-manager.js +39 -0
  17. package/dist/src/file-manager.js.map +1 -1
  18. package/dist/src/git-manager.d.ts +4 -0
  19. package/dist/src/git-manager.d.ts.map +1 -1
  20. package/dist/src/git-manager.js +41 -0
  21. package/dist/src/git-manager.js.map +1 -1
  22. package/dist/src/prompt-builder.d.ts +1 -0
  23. package/dist/src/prompt-builder.d.ts.map +1 -1
  24. package/dist/src/prompt-builder.js +40 -0
  25. package/dist/src/prompt-builder.js.map +1 -1
  26. package/dist/src/stage-executor.d.ts +1 -0
  27. package/dist/src/stage-executor.d.ts.map +1 -1
  28. package/dist/src/stage-executor.js +43 -0
  29. package/dist/src/stage-executor.js.map +1 -1
  30. package/dist/src/structured-extraction.d.ts +22 -0
  31. package/dist/src/structured-extraction.d.ts.map +1 -0
  32. package/dist/src/structured-extraction.js +136 -0
  33. package/dist/src/structured-extraction.js.map +1 -0
  34. package/dist/src/types.d.ts +7 -0
  35. package/dist/src/types.d.ts.map +1 -1
  36. package/dist/src/types.js.map +1 -1
  37. package/dist/src/workflow-types.d.ts +1 -1
  38. package/dist/src/workflow-types.d.ts.map +1 -1
  39. package/package.json +4 -3
  40. package/src/agent-registry.ts +6 -0
  41. package/src/agent.ts +364 -2
  42. package/src/agents/research.ts +103 -0
  43. package/src/file-manager.ts +64 -0
  44. package/src/git-manager.ts +52 -0
  45. package/src/prompt-builder.ts +53 -0
  46. package/src/stage-executor.ts +50 -0
  47. package/src/structured-extraction.ts +167 -0
  48. package/src/types.ts +8 -0
  49. package/src/workflow-types.ts +1 -1
package/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@ export type { Task, TaskRun, SupportingFile, ExecutionResult, AgentConfig, McpSe
4
4
  export type { WorkflowDefinition, WorkflowStage, WorkflowExecutionOptions, AgentDefinition } from './src/workflow-types.js';
5
5
  export { Logger, LogLevel, } from './src/utils/logger.js';
6
6
  export type { LoggerConfig } from './src/utils/logger.js';
7
+ export type { ExtractedQuestion, ExtractedQuestionWithAnswer, StructuredExtractor } from './src/structured-extraction.js';
8
+ export type { QuestionData, AnswerData, QuestionsFile } from './src/file-manager.js';
7
9
  export type { ProviderAdapter } from './src/adapters/types.js';
8
10
  export { ClaudeAdapter } from './src/adapters/claude/claude-adapter.js';
9
11
  export type { Tool, ToolCategory, KnownTool, ReadTool, WriteTool, EditTool, GlobTool, NotebookEditTool, BashTool, BashOutputTool, KillShellTool, WebFetchTool, WebSearchTool, GrepTool, TaskTool, TodoWriteTool, ExitPlanModeTool, SlashCommandTool, } from './src/tools/types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,KAAK,GACR,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,cAAc,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACR,IAAI,EACJ,OAAO,EACP,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,UAAU,EACb,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,kBAAkB,EAClB,aAAa,EACb,wBAAwB,EACxB,eAAe,EAChB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACH,MAAM,EACN,QAAQ,GACX,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACR,YAAY,EACf,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAGxE,YAAY,EACR,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,aAAa,EACb,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,KAAK,GACR,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,cAAc,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACR,IAAI,EACJ,OAAO,EACP,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,UAAU,EACb,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,kBAAkB,EAClB,aAAa,EACb,wBAAwB,EACxB,eAAe,EAChB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACH,MAAM,EACN,QAAQ,GACX,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACR,YAAY,EACf,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACR,iBAAiB,EACjB,2BAA2B,EAC3B,mBAAmB,EACtB,MAAM,gCAAgC,CAAC;AAGxC,YAAY,EACR,YAAY,EACZ,UAAU,EACV,aAAa,EAChB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAGxE,YAAY,EACR,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,aAAa,EACb,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-registry.d.ts","sourceRoot":"","sources":["../../src/agent-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEtE,qBAAa,aAAa;IACxB,OAAO,CAAC,YAAY,CAA2C;gBAEnD,WAAW,CAAC,EAAE,eAAe,EAAE;IAQ3C,MAAM,CAAC,gBAAgB,IAAI,eAAe,EAAE;IA6B5C,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAIpC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAInD,UAAU,IAAI,eAAe,EAAE;IAI/B,gBAAgB,IAAI;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,SAAS,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE;CAGhG"}
1
+ {"version":3,"file":"agent-registry.d.ts","sourceRoot":"","sources":["../../src/agent-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEtE,qBAAa,aAAa;IACxB,OAAO,CAAC,YAAY,CAA2C;gBAEnD,WAAW,CAAC,EAAE,eAAe,EAAE;IAQ3C,MAAM,CAAC,gBAAgB,IAAI,eAAe,EAAE;IAmC5C,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAIpC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAInD,UAAU,IAAI,eAAe,EAAE;IAI/B,gBAAgB,IAAI;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,SAAS,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE;CAGhG"}
@@ -12,6 +12,12 @@ class AgentRegistry {
12
12
  }
13
13
  static getDefaultAgents() {
14
14
  return [
15
+ {
16
+ id: 'research',
17
+ name: 'research',
18
+ agent_type: 'research',
19
+ description: 'Explore codebase and generate clarifying questions',
20
+ },
15
21
  {
16
22
  id: 'planning',
17
23
  name: 'planning',
@@ -1 +1 @@
1
- {"version":3,"file":"agent-registry.js","sources":["../../src/agent-registry.ts"],"sourcesContent":["import type { AgentDefinition, AgentType } from './workflow-types.js';\n\nexport class AgentRegistry {\n private agentsByName: Map<string, AgentDefinition> = new Map();\n\n constructor(definitions?: AgentDefinition[]) {\n if (definitions) {\n for (const def of definitions) this.register(def);\n } else {\n for (const def of AgentRegistry.getDefaultAgents()) this.register(def);\n }\n }\n\n static getDefaultAgents(): AgentDefinition[] {\n return [\n {\n id: 'planning',\n name: 'planning',\n agent_type: 'planning',\n description: 'Analyze repo and produce implementation plan',\n },\n {\n id: 'code_generation',\n name: 'code_generation',\n agent_type: 'execution',\n description: 'Implements code changes using Claude SDK',\n },\n {\n id: 'review',\n name: 'review',\n agent_type: 'review',\n description: 'Reviews changes and suggests fixes',\n },\n {\n id: 'testing',\n name: 'testing',\n agent_type: 'testing',\n description: 'Runs tests and reports results',\n },\n ];\n }\n\n register(def: AgentDefinition): void {\n this.agentsByName.set(def.name, def);\n }\n\n getAgent(name: string): AgentDefinition | undefined {\n return this.agentsByName.get(name);\n }\n\n listAgents(): AgentDefinition[] {\n return Array.from(this.agentsByName.values());\n }\n\n exportForPostHog(): { id: string; name: string; agent_type: AgentType; description?: string }[] {\n return this.listAgents().map(({ id, name, agent_type, description }) => ({ id, name, agent_type, description }));\n }\n}\n\n"],"names":[],"mappings":"MAEa,aAAa,CAAA;AAChB,IAAA,YAAY,GAAiC,IAAI,GAAG,EAAE;AAE9D,IAAA,WAAA,CAAY,WAA+B,EAAA;QACzC,IAAI,WAAW,EAAE;YACf,KAAK,MAAM,GAAG,IAAI,WAAW;AAAE,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACnD;aAAO;AACL,YAAA,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,gBAAgB,EAAE;AAAE,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACxE;IACF;AAEA,IAAA,OAAO,gBAAgB,GAAA;QACrB,OAAO;AACL,YAAA;AACE,gBAAA,EAAE,EAAE,UAAU;AACd,gBAAA,IAAI,EAAE,UAAU;AAChB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,WAAW,EAAE,8CAA8C;AAC5D,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,iBAAiB;AACrB,gBAAA,IAAI,EAAE,iBAAiB;AACvB,gBAAA,UAAU,EAAE,WAAW;AACvB,gBAAA,WAAW,EAAE,0CAA0C;AACxD,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,UAAU,EAAE,QAAQ;AACpB,gBAAA,WAAW,EAAE,oCAAoC;AAClD,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,IAAI,EAAE,SAAS;AACf,gBAAA,UAAU,EAAE,SAAS;AACrB,gBAAA,WAAW,EAAE,gCAAgC;AAC9C,aAAA;SACF;IACH;AAEA,IAAA,QAAQ,CAAC,GAAoB,EAAA;QAC3B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;IACtC;AAEA,IAAA,QAAQ,CAAC,IAAY,EAAA;QACnB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;IACpC;IAEA,UAAU,GAAA;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;IAC/C;IAEA,gBAAgB,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;IAClH;AACD;;;;"}
1
+ {"version":3,"file":"agent-registry.js","sources":["../../src/agent-registry.ts"],"sourcesContent":["import type { AgentDefinition, AgentType } from './workflow-types.js';\n\nexport class AgentRegistry {\n private agentsByName: Map<string, AgentDefinition> = new Map();\n\n constructor(definitions?: AgentDefinition[]) {\n if (definitions) {\n for (const def of definitions) this.register(def);\n } else {\n for (const def of AgentRegistry.getDefaultAgents()) this.register(def);\n }\n }\n\n static getDefaultAgents(): AgentDefinition[] {\n return [\n {\n id: 'research',\n name: 'research',\n agent_type: 'research',\n description: 'Explore codebase and generate clarifying questions',\n },\n {\n id: 'planning',\n name: 'planning',\n agent_type: 'planning',\n description: 'Analyze repo and produce implementation plan',\n },\n {\n id: 'code_generation',\n name: 'code_generation',\n agent_type: 'execution',\n description: 'Implements code changes using Claude SDK',\n },\n {\n id: 'review',\n name: 'review',\n agent_type: 'review',\n description: 'Reviews changes and suggests fixes',\n },\n {\n id: 'testing',\n name: 'testing',\n agent_type: 'testing',\n description: 'Runs tests and reports results',\n },\n ];\n }\n\n register(def: AgentDefinition): void {\n this.agentsByName.set(def.name, def);\n }\n\n getAgent(name: string): AgentDefinition | undefined {\n return this.agentsByName.get(name);\n }\n\n listAgents(): AgentDefinition[] {\n return Array.from(this.agentsByName.values());\n }\n\n exportForPostHog(): { id: string; name: string; agent_type: AgentType; description?: string }[] {\n return this.listAgents().map(({ id, name, agent_type, description }) => ({ id, name, agent_type, description }));\n }\n}\n\n"],"names":[],"mappings":"MAEa,aAAa,CAAA;AAChB,IAAA,YAAY,GAAiC,IAAI,GAAG,EAAE;AAE9D,IAAA,WAAA,CAAY,WAA+B,EAAA;QACzC,IAAI,WAAW,EAAE;YACf,KAAK,MAAM,GAAG,IAAI,WAAW;AAAE,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACnD;aAAO;AACL,YAAA,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,gBAAgB,EAAE;AAAE,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACxE;IACF;AAEA,IAAA,OAAO,gBAAgB,GAAA;QACrB,OAAO;AACL,YAAA;AACE,gBAAA,EAAE,EAAE,UAAU;AACd,gBAAA,IAAI,EAAE,UAAU;AAChB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,WAAW,EAAE,oDAAoD;AAClE,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,UAAU;AACd,gBAAA,IAAI,EAAE,UAAU;AAChB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,WAAW,EAAE,8CAA8C;AAC5D,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,iBAAiB;AACrB,gBAAA,IAAI,EAAE,iBAAiB;AACvB,gBAAA,UAAU,EAAE,WAAW;AACvB,gBAAA,WAAW,EAAE,0CAA0C;AACxD,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,UAAU,EAAE,QAAQ;AACpB,gBAAA,WAAW,EAAE,oCAAoC;AAClD,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,IAAI,EAAE,SAAS;AACf,gBAAA,UAAU,EAAE,SAAS;AACrB,gBAAA,WAAW,EAAE,gCAAgC;AAC9C,aAAA;SACF;IACH;AAEA,IAAA,QAAQ,CAAC,GAAoB,EAAA;QAC3B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;IACtC;AAEA,IAAA,QAAQ,CAAC,IAAY,EAAA;QACnB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;IACpC;IAEA,UAAU,GAAA;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;IAC/C;IAEA,gBAAgB,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;IAClH;AACD;;;;"}
@@ -1,6 +1,7 @@
1
1
  import type { Task, ExecutionResult, AgentConfig } from './types.js';
2
2
  import type { WorkflowDefinition, WorkflowStage, WorkflowExecutionOptions } from './workflow-types.js';
3
3
  import { PostHogAPIClient } from './posthog-api.js';
4
+ import { type ExtractedQuestion, type ExtractedQuestionWithAnswer } from './structured-extraction.js';
4
5
  export declare class Agent {
5
6
  private workingDirectory;
6
7
  private onEvent?;
@@ -15,6 +16,8 @@ export declare class Agent {
15
16
  private workflowRegistry;
16
17
  private stageExecutor;
17
18
  private progressReporter;
19
+ private promptBuilder;
20
+ private extractor?;
18
21
  private mcpServers?;
19
22
  debug: boolean;
20
23
  constructor(config?: AgentConfig);
@@ -31,6 +34,7 @@ export declare class Agent {
31
34
  workflow: WorkflowDefinition;
32
35
  }>;
33
36
  executeStage(task: Task, stage: WorkflowStage, options?: WorkflowExecutionOptions): Promise<void>;
37
+ runTask(taskOrId: Task | string, options?: import('./types.js').TaskExecutionOptions): Promise<void>;
34
38
  progressToNextStage(taskId: string, currentStageKey?: string): Promise<void>;
35
39
  run(prompt: string, options?: {
36
40
  repositoryPath?: string;
@@ -51,6 +55,7 @@ export declare class Agent {
51
55
  getTaskFiles(taskId: string): Promise<any[]>;
52
56
  writePlan(taskId: string, plan: string): Promise<void>;
53
57
  readPlan(taskId: string): Promise<string | null>;
58
+ extractQuestionsFromResearch(taskId: string, includeAnswers?: boolean): Promise<ExtractedQuestion[] | ExtractedQuestionWithAnswer[]>;
54
59
  createPlanningBranch(taskId: string): Promise<string>;
55
60
  commitPlan(taskId: string, taskTitle: string): Promise<string>;
56
61
  createImplementationBranch(taskId: string, planningBranchName?: string): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"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"}
package/dist/src/agent.js CHANGED
@@ -11,6 +11,7 @@ import { WorkflowRegistry } from './workflow-registry.js';
11
11
  import { StageExecutor } from './stage-executor.js';
12
12
  import { PromptBuilder } from './prompt-builder.js';
13
13
  import { TaskProgressReporter } from './task-progress-reporter.js';
14
+ import { OpenAIExtractor } from './structured-extraction.js';
14
15
  export { PermissionMode } from './types.js';
15
16
 
16
17
  class Agent {
@@ -27,6 +28,8 @@ class Agent {
27
28
  workflowRegistry;
28
29
  stageExecutor;
29
30
  progressReporter;
31
+ promptBuilder;
32
+ extractor;
30
33
  mcpServers;
31
34
  debug;
32
35
  constructor(config = {}) {
@@ -73,16 +76,20 @@ class Agent {
73
76
  });
74
77
  }
75
78
  this.workflowRegistry = new WorkflowRegistry(this.posthogAPI);
76
- const promptBuilder = new PromptBuilder({
79
+ this.promptBuilder = new PromptBuilder({
77
80
  getTaskFiles: (taskId) => this.getTaskFiles(taskId),
78
81
  generatePlanTemplate: (vars) => this.templateManager.generatePlan(vars),
79
82
  posthogClient: this.posthogAPI,
80
83
  logger: this.logger.child('PromptBuilder')
81
84
  });
82
- this.stageExecutor = new StageExecutor(this.agentRegistry, this.logger, promptBuilder, undefined, // eventHandler set via setEventHandler below
85
+ this.stageExecutor = new StageExecutor(this.agentRegistry, this.logger, this.promptBuilder, undefined, // eventHandler set via setEventHandler below
83
86
  this.mcpServers);
84
87
  this.stageExecutor.setEventHandler((event) => this.emitEvent(event));
85
88
  this.progressReporter = new TaskProgressReporter(this.posthogAPI, this.logger);
89
+ // Initialize OpenAI extractor if API key is available
90
+ if (process.env.OPENAI_API_KEY) {
91
+ this.extractor = new OpenAIExtractor(this.logger.child('OpenAIExtractor'));
92
+ }
86
93
  }
87
94
  /**
88
95
  * Enable or disable debug logging
@@ -292,6 +299,308 @@ class Agent {
292
299
  }
293
300
  this.emitEvent(this.adapter.createStatusEvent('stage_complete', { stage: stage.key }));
294
301
  }
302
+ // Adaptive task execution - 3-phase workflow (research → plan → build)
303
+ async runTask(taskOrId, options = {}) {
304
+ await this._configureLlmGateway();
305
+ const task = typeof taskOrId === 'string' ? await this.fetchTask(taskOrId) : taskOrId;
306
+ const cwd = options.repositoryPath || this.workingDirectory;
307
+ const isCloudMode = options.isCloudMode ?? false;
308
+ const taskSlug = task.slug || task.id;
309
+ this.logger.info('Starting adaptive task execution', { taskId: task.id, taskSlug, isCloudMode });
310
+ // Initialize progress reporter for task run tracking (needed for PR attachment)
311
+ await this.progressReporter.start(task.id, { totalSteps: 3 }); // 3 phases: research, plan, build
312
+ this.emitEvent(this.adapter.createStatusEvent('run_started', { runId: this.progressReporter.runId }));
313
+ // Phase 1: Branch check
314
+ const existingBranch = await this.gitManager.getTaskBranch(taskSlug);
315
+ if (!existingBranch) {
316
+ this.logger.info('Creating task branch', { taskSlug });
317
+ const branchName = `posthog/task-${taskSlug}`;
318
+ await this.gitManager.createOrSwitchToBranch(branchName);
319
+ this.emitEvent(this.adapter.createStatusEvent('branch_created', { branch: branchName }));
320
+ // Initial commit
321
+ await this.fileManager.ensureGitignore();
322
+ await this.gitManager.addAllPostHogFiles();
323
+ if (isCloudMode) {
324
+ await this.gitManager.commitAndPush(`Initialize task ${taskSlug}`, { allowEmpty: true });
325
+ }
326
+ else {
327
+ await this.gitManager.commitChanges(`Initialize task ${taskSlug}`);
328
+ }
329
+ }
330
+ else {
331
+ this.logger.info('Switching to existing task branch', { branch: existingBranch });
332
+ await this.gitManager.switchToBranch(existingBranch);
333
+ }
334
+ // Phase 2: Research
335
+ const researchExists = await this.fileManager.readResearch(task.id);
336
+ if (!researchExists) {
337
+ this.logger.info('Starting research phase', { taskId: task.id });
338
+ this.emitEvent(this.adapter.createStatusEvent('phase_start', { phase: 'research' }));
339
+ // Run research agent
340
+ const researchPrompt = await this.promptBuilder.buildResearchPrompt(task, cwd);
341
+ const { RESEARCH_SYSTEM_PROMPT } = await import('./agents/research.js');
342
+ const fullPrompt = RESEARCH_SYSTEM_PROMPT + '\n\n' + researchPrompt;
343
+ const baseOptions = {
344
+ model: 'claude-sonnet-4-5-20250929',
345
+ cwd,
346
+ permissionMode: 'plan',
347
+ settingSources: ['local'],
348
+ mcpServers: this.mcpServers,
349
+ };
350
+ const response = query({
351
+ prompt: fullPrompt,
352
+ options: { ...baseOptions, ...(options.queryOverrides || {}) },
353
+ });
354
+ let researchContent = '';
355
+ for await (const message of response) {
356
+ this.emitEvent(this.adapter.createRawSDKEvent(message));
357
+ const transformed = this.adapter.transform(message);
358
+ if (transformed) {
359
+ this.emitEvent(transformed);
360
+ }
361
+ if (message.type === 'assistant' && message.message?.content) {
362
+ for (const c of message.message.content) {
363
+ if (c.type === 'text' && c.text)
364
+ researchContent += c.text + '\n';
365
+ }
366
+ }
367
+ }
368
+ // Write research.md
369
+ if (researchContent.trim()) {
370
+ await this.fileManager.writeResearch(task.id, researchContent.trim());
371
+ this.logger.info('Research completed', { taskId: task.id });
372
+ }
373
+ // Commit research
374
+ await this.gitManager.addAllPostHogFiles();
375
+ // Extract questions using structured output and save to questions.json
376
+ if (this.extractor) {
377
+ try {
378
+ this.logger.info('Extracting questions from research.md', { taskId: task.id });
379
+ const questions = await this.extractQuestionsFromResearch(task.id, false);
380
+ this.logger.info('Questions extracted successfully', { taskId: task.id, count: questions.length });
381
+ // Save questions.json
382
+ await this.fileManager.writeQuestions(task.id, {
383
+ questions,
384
+ answered: false,
385
+ answers: null,
386
+ });
387
+ this.logger.info('Questions saved to questions.json', { taskId: task.id });
388
+ // Emit event for Array to pick up (local mode)
389
+ if (!isCloudMode) {
390
+ this.emitEvent({
391
+ type: 'artifact',
392
+ ts: Date.now(),
393
+ kind: 'research_questions',
394
+ content: questions,
395
+ });
396
+ this.logger.info('Emitted research_questions artifact event', { taskId: task.id });
397
+ }
398
+ }
399
+ catch (error) {
400
+ this.logger.error('Failed to extract questions', { error: error instanceof Error ? error.message : String(error) });
401
+ this.emitEvent({
402
+ type: 'error',
403
+ ts: Date.now(),
404
+ message: `Failed to extract questions: ${error instanceof Error ? error.message : String(error)}`,
405
+ });
406
+ }
407
+ }
408
+ else {
409
+ this.logger.warn('OpenAI extractor not available (OPENAI_API_KEY not set), skipping question extraction');
410
+ this.emitEvent({
411
+ type: 'status',
412
+ ts: Date.now(),
413
+ phase: 'extraction_skipped',
414
+ message: 'Question extraction skipped - OPENAI_API_KEY not configured',
415
+ });
416
+ }
417
+ if (isCloudMode) {
418
+ await this.gitManager.commitAndPush(`Research phase for ${task.title}`);
419
+ }
420
+ else {
421
+ await this.gitManager.commitChanges(`Research phase for ${task.title}`);
422
+ this.emitEvent(this.adapter.createStatusEvent('phase_complete', { phase: 'research' }));
423
+ return; // Local mode: return to user
424
+ }
425
+ }
426
+ // Phase 3: Auto-answer questions (cloud mode only)
427
+ if (isCloudMode) {
428
+ const questionsData = await this.fileManager.readQuestions(task.id);
429
+ if (questionsData && !questionsData.answered) {
430
+ this.logger.info('Auto-answering research questions', { taskId: task.id });
431
+ // Extract questions with recommended answers using structured output
432
+ if (this.extractor) {
433
+ const questionsWithAnswers = await this.extractQuestionsFromResearch(task.id, true);
434
+ // Save answers to questions.json
435
+ await this.fileManager.writeQuestions(task.id, {
436
+ questions: questionsWithAnswers.map(qa => ({
437
+ id: qa.id,
438
+ question: qa.question,
439
+ options: qa.options,
440
+ })),
441
+ answered: true,
442
+ answers: questionsWithAnswers.map(qa => ({
443
+ questionId: qa.id,
444
+ selectedOption: qa.recommendedAnswer,
445
+ customInput: qa.justification,
446
+ })),
447
+ });
448
+ this.logger.info('Auto-answers saved to questions.json', { taskId: task.id });
449
+ await this.gitManager.addAllPostHogFiles();
450
+ await this.gitManager.commitAndPush(`Answer research questions for ${task.title}`);
451
+ }
452
+ else {
453
+ this.logger.warn('OpenAI extractor not available, skipping auto-answer');
454
+ }
455
+ }
456
+ }
457
+ // Phase 4: Plan
458
+ const planExists = await this.readPlan(task.id);
459
+ if (!planExists) {
460
+ // Check if questions have been answered
461
+ const questionsData = await this.fileManager.readQuestions(task.id);
462
+ if (!questionsData || !questionsData.answered) {
463
+ this.logger.info('Waiting for user answers to research questions');
464
+ this.emitEvent(this.adapter.createStatusEvent('phase_complete', { phase: 'research_questions' }));
465
+ return; // Wait for user to answer questions
466
+ }
467
+ this.logger.info('Starting planning phase', { taskId: task.id });
468
+ this.emitEvent(this.adapter.createStatusEvent('phase_start', { phase: 'planning' }));
469
+ // Build context with research + questions + answers
470
+ const research = await this.fileManager.readResearch(task.id);
471
+ let researchContext = '';
472
+ if (research) {
473
+ researchContext += `## Research Analysis\n\n${research}\n\n`;
474
+ }
475
+ // Add questions and answers
476
+ researchContext += `## Implementation Decisions\n\n`;
477
+ const answers = questionsData.answers || [];
478
+ for (const question of questionsData.questions) {
479
+ const answer = answers.find((a) => a.questionId === question.id);
480
+ researchContext += `### ${question.question}\n\n`;
481
+ if (answer) {
482
+ researchContext += `**Selected:** ${answer.selectedOption}\n`;
483
+ if (answer.customInput) {
484
+ researchContext += `**Details:** ${answer.customInput}\n`;
485
+ }
486
+ }
487
+ else {
488
+ this.logger.warn('No answer found for question', { questionId: question.id });
489
+ researchContext += `**Selected:** Not answered\n`;
490
+ }
491
+ researchContext += '\n';
492
+ }
493
+ // Run planning agent with full context
494
+ const planningPrompt = await this.promptBuilder.buildPlanningPrompt(task, cwd);
495
+ const { PLANNING_SYSTEM_PROMPT } = await import('./agents/planning.js');
496
+ const fullPrompt = PLANNING_SYSTEM_PROMPT + '\n\n' + planningPrompt + '\n\n' + researchContext;
497
+ const baseOptions = {
498
+ model: 'claude-sonnet-4-5-20250929',
499
+ cwd,
500
+ permissionMode: 'plan',
501
+ settingSources: ['local'],
502
+ mcpServers: this.mcpServers,
503
+ };
504
+ const response = query({
505
+ prompt: fullPrompt,
506
+ options: { ...baseOptions, ...(options.queryOverrides || {}) },
507
+ });
508
+ let planContent = '';
509
+ for await (const message of response) {
510
+ this.emitEvent(this.adapter.createRawSDKEvent(message));
511
+ const transformed = this.adapter.transform(message);
512
+ if (transformed) {
513
+ this.emitEvent(transformed);
514
+ }
515
+ if (message.type === 'assistant' && message.message?.content) {
516
+ for (const c of message.message.content) {
517
+ if (c.type === 'text' && c.text)
518
+ planContent += c.text + '\n';
519
+ }
520
+ }
521
+ }
522
+ // Write plan.md
523
+ if (planContent.trim()) {
524
+ await this.writePlan(task.id, planContent.trim());
525
+ this.logger.info('Plan completed', { taskId: task.id });
526
+ }
527
+ // Commit plan
528
+ await this.gitManager.addAllPostHogFiles();
529
+ if (isCloudMode) {
530
+ await this.gitManager.commitAndPush(`Planning phase for ${task.title}`);
531
+ }
532
+ else {
533
+ await this.gitManager.commitChanges(`Planning phase for ${task.title}`);
534
+ this.emitEvent(this.adapter.createStatusEvent('phase_complete', { phase: 'planning' }));
535
+ return; // Local mode: return to user
536
+ }
537
+ }
538
+ // Phase 5: Build
539
+ const latestRun = task.latest_run;
540
+ const prExists = latestRun?.output && latestRun.output.pr_url;
541
+ if (!prExists) {
542
+ this.logger.info('Starting build phase', { taskId: task.id });
543
+ this.emitEvent(this.adapter.createStatusEvent('phase_start', { phase: 'build' }));
544
+ // Run execution agent
545
+ const executionPrompt = await this.promptBuilder.buildExecutionPrompt(task, cwd);
546
+ const { EXECUTION_SYSTEM_PROMPT } = await import('./agents/execution.js');
547
+ const fullPrompt = EXECUTION_SYSTEM_PROMPT + '\n\n' + executionPrompt;
548
+ const { PermissionMode } = await import('./types.js');
549
+ const permissionMode = options.permissionMode || PermissionMode.ACCEPT_EDITS;
550
+ const baseOptions = {
551
+ model: 'claude-sonnet-4-5-20250929',
552
+ cwd,
553
+ permissionMode,
554
+ settingSources: ['local'],
555
+ mcpServers: this.mcpServers,
556
+ };
557
+ const response = query({
558
+ prompt: fullPrompt,
559
+ options: { ...baseOptions, ...(options.queryOverrides || {}) },
560
+ });
561
+ for await (const message of response) {
562
+ this.emitEvent(this.adapter.createRawSDKEvent(message));
563
+ const transformed = this.adapter.transform(message);
564
+ if (transformed) {
565
+ this.emitEvent(transformed);
566
+ }
567
+ }
568
+ // Commit and push implementation
569
+ // Stage ALL changes (not just .posthog/)
570
+ const hasChanges = await this.gitManager.hasChanges();
571
+ if (hasChanges) {
572
+ await this.gitManager.addFiles(['.']); // Stage all changes
573
+ await this.gitManager.commitChanges(`Implementation for ${task.title}`);
574
+ // Push to origin
575
+ const branchName = await this.gitManager.getCurrentBranch();
576
+ await this.gitManager.pushBranch(branchName);
577
+ this.logger.info('Implementation committed and pushed', { taskId: task.id });
578
+ }
579
+ else {
580
+ this.logger.warn('No changes to commit in build phase', { taskId: task.id });
581
+ }
582
+ // Create PR
583
+ const branchName = await this.gitManager.getCurrentBranch();
584
+ const prUrl = await this.createPullRequest(task.id, branchName, task.title, task.description);
585
+ this.logger.info('Pull request created', { taskId: task.id, prUrl });
586
+ this.emitEvent(this.adapter.createStatusEvent('pr_created', { prUrl }));
587
+ // Attach PR to task run
588
+ try {
589
+ await this.attachPullRequestToTask(task.id, prUrl, branchName);
590
+ this.logger.info('PR attached to task successfully', { taskId: task.id, prUrl });
591
+ }
592
+ catch (error) {
593
+ this.logger.warn('Could not attach PR to task', { error: error instanceof Error ? error.message : String(error) });
594
+ }
595
+ }
596
+ else {
597
+ this.logger.info('PR already exists, skipping build phase', { taskId: task.id });
598
+ }
599
+ // Phase 6: Complete
600
+ await this.progressReporter.complete();
601
+ this.logger.info('Task execution complete', { taskId: task.id });
602
+ this.emitEvent(this.adapter.createStatusEvent('task_complete', { taskId: task.id }));
603
+ }
295
604
  async progressToNextStage(taskId, currentStageKey) {
296
605
  if (!this.posthogAPI || !this.progressReporter.runId) {
297
606
  throw new Error('PostHog API not configured or no active run. Cannot progress stage.');
@@ -384,6 +693,22 @@ class Agent {
384
693
  this.logger.debug('Reading plan', { taskId });
385
694
  return await this.fileManager.readPlan(taskId);
386
695
  }
696
+ async extractQuestionsFromResearch(taskId, includeAnswers = false) {
697
+ this.logger.info('Extracting questions from research.md', { taskId, includeAnswers });
698
+ if (!this.extractor) {
699
+ throw new Error('OpenAI extractor not initialized. Set OPENAI_API_KEY environment variable.');
700
+ }
701
+ const researchContent = await this.fileManager.readResearch(taskId);
702
+ if (!researchContent) {
703
+ throw new Error('research.md not found for task ' + taskId);
704
+ }
705
+ if (includeAnswers) {
706
+ return await this.extractor.extractQuestionsWithAnswers(researchContent);
707
+ }
708
+ else {
709
+ return await this.extractor.extractQuestions(researchContent);
710
+ }
711
+ }
387
712
  // Git operations for task workflow
388
713
  async createPlanningBranch(taskId) {
389
714
  this.logger.info('Creating planning branch', { taskId });