@posthog/agent 1.22.0 → 1.24.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 (118) hide show
  1. package/CLAUDE.md +3 -3
  2. package/README.md +3 -3
  3. package/dist/index.d.ts +11 -11
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +3 -3
  6. package/dist/src/adapters/claude/claude-adapter.d.ts +3 -3
  7. package/dist/src/adapters/claude/claude-adapter.d.ts.map +1 -1
  8. package/dist/src/adapters/claude/claude-adapter.js +156 -111
  9. package/dist/src/adapters/claude/claude-adapter.js.map +1 -1
  10. package/dist/src/adapters/claude/tool-mapper.d.ts +1 -1
  11. package/dist/src/adapters/claude/tool-mapper.d.ts.map +1 -1
  12. package/dist/src/adapters/claude/tool-mapper.js.map +1 -1
  13. package/dist/src/adapters/types.d.ts +1 -1
  14. package/dist/src/adapters/types.d.ts.map +1 -1
  15. package/dist/src/agent.d.ts +7 -7
  16. package/dist/src/agent.d.ts.map +1 -1
  17. package/dist/src/agent.js +143 -85
  18. package/dist/src/agent.js.map +1 -1
  19. package/dist/src/agents/execution.js.map +1 -1
  20. package/dist/src/agents/planning.js.map +1 -1
  21. package/dist/src/agents/research.js.map +1 -1
  22. package/dist/src/file-manager.d.ts +4 -4
  23. package/dist/src/file-manager.d.ts.map +1 -1
  24. package/dist/src/file-manager.js +59 -58
  25. package/dist/src/file-manager.js.map +1 -1
  26. package/dist/src/git-manager.d.ts +1 -1
  27. package/dist/src/git-manager.d.ts.map +1 -1
  28. package/dist/src/git-manager.js +93 -69
  29. package/dist/src/git-manager.js.map +1 -1
  30. package/dist/src/posthog-api.d.ts +2 -3
  31. package/dist/src/posthog-api.d.ts.map +1 -1
  32. package/dist/src/posthog-api.js +22 -22
  33. package/dist/src/posthog-api.js.map +1 -1
  34. package/dist/src/prompt-builder.d.ts +3 -3
  35. package/dist/src/prompt-builder.d.ts.map +1 -1
  36. package/dist/src/prompt-builder.js +123 -93
  37. package/dist/src/prompt-builder.js.map +1 -1
  38. package/dist/src/task-manager.d.ts +4 -4
  39. package/dist/src/task-manager.d.ts.map +1 -1
  40. package/dist/src/task-manager.js +19 -18
  41. package/dist/src/task-manager.js.map +1 -1
  42. package/dist/src/task-progress-reporter.d.ts +3 -4
  43. package/dist/src/task-progress-reporter.d.ts.map +1 -1
  44. package/dist/src/task-progress-reporter.js +59 -54
  45. package/dist/src/task-progress-reporter.js.map +1 -1
  46. package/dist/src/template-manager.d.ts +1 -1
  47. package/dist/src/template-manager.d.ts.map +1 -1
  48. package/dist/src/template-manager.js +30 -28
  49. package/dist/src/template-manager.js.map +1 -1
  50. package/dist/src/todo-manager.d.ts +3 -3
  51. package/dist/src/todo-manager.d.ts.map +1 -1
  52. package/dist/src/todo-manager.js +29 -24
  53. package/dist/src/todo-manager.js.map +1 -1
  54. package/dist/src/tools/registry.d.ts +1 -1
  55. package/dist/src/tools/registry.js +60 -60
  56. package/dist/src/tools/registry.js.map +1 -1
  57. package/dist/src/tools/types.d.ts +31 -31
  58. package/dist/src/types.d.ts +33 -33
  59. package/dist/src/types.d.ts.map +1 -1
  60. package/dist/src/types.js.map +1 -1
  61. package/dist/src/utils/logger.d.ts +4 -4
  62. package/dist/src/utils/logger.d.ts.map +1 -1
  63. package/dist/src/utils/logger.js +8 -8
  64. package/dist/src/utils/logger.js.map +1 -1
  65. package/dist/src/workflow/config.d.ts +1 -1
  66. package/dist/src/workflow/config.d.ts.map +1 -1
  67. package/dist/src/workflow/config.js +18 -18
  68. package/dist/src/workflow/config.js.map +1 -1
  69. package/dist/src/workflow/steps/build.d.ts +1 -1
  70. package/dist/src/workflow/steps/build.d.ts.map +1 -1
  71. package/dist/src/workflow/steps/build.js +46 -38
  72. package/dist/src/workflow/steps/build.js.map +1 -1
  73. package/dist/src/workflow/steps/finalize.d.ts +1 -1
  74. package/dist/src/workflow/steps/finalize.d.ts.map +1 -1
  75. package/dist/src/workflow/steps/finalize.js +54 -48
  76. package/dist/src/workflow/steps/finalize.js.map +1 -1
  77. package/dist/src/workflow/steps/plan.d.ts +1 -1
  78. package/dist/src/workflow/steps/plan.d.ts.map +1 -1
  79. package/dist/src/workflow/steps/plan.js +58 -46
  80. package/dist/src/workflow/steps/plan.js.map +1 -1
  81. package/dist/src/workflow/steps/research.d.ts +1 -1
  82. package/dist/src/workflow/steps/research.d.ts.map +1 -1
  83. package/dist/src/workflow/steps/research.js +68 -56
  84. package/dist/src/workflow/steps/research.js.map +1 -1
  85. package/dist/src/workflow/types.d.ts +12 -12
  86. package/dist/src/workflow/types.d.ts.map +1 -1
  87. package/dist/src/workflow/utils.d.ts +1 -1
  88. package/dist/src/workflow/utils.d.ts.map +1 -1
  89. package/dist/src/workflow/utils.js +7 -4
  90. package/dist/src/workflow/utils.js.map +1 -1
  91. package/package.json +8 -8
  92. package/src/adapters/claude/claude-adapter.ts +220 -168
  93. package/src/adapters/claude/tool-mapper.ts +2 -2
  94. package/src/adapters/types.ts +1 -1
  95. package/src/agent.ts +579 -444
  96. package/src/agents/execution.ts +1 -1
  97. package/src/agents/planning.ts +1 -1
  98. package/src/agents/research.ts +0 -1
  99. package/src/file-manager.ts +64 -63
  100. package/src/git-manager.ts +152 -87
  101. package/src/posthog-api.ts +122 -82
  102. package/src/prompt-builder.ts +180 -135
  103. package/src/task-manager.ts +38 -30
  104. package/src/task-progress-reporter.ts +70 -59
  105. package/src/template-manager.ts +98 -45
  106. package/src/todo-manager.ts +35 -30
  107. package/src/tools/registry.ts +62 -62
  108. package/src/tools/types.ts +36 -36
  109. package/src/types.ts +93 -71
  110. package/src/utils/logger.ts +62 -56
  111. package/src/workflow/config.ts +48 -48
  112. package/src/workflow/steps/build.ts +122 -113
  113. package/src/workflow/steps/finalize.ts +214 -182
  114. package/src/workflow/steps/plan.ts +151 -131
  115. package/src/workflow/steps/research.ts +205 -186
  116. package/src/workflow/types.ts +38 -36
  117. package/src/workflow/utils.ts +37 -34
  118. package/LICENSE +0 -33
@@ -1,25 +1,27 @@
1
1
  import { query } from '@anthropic-ai/claude-agent-sdk';
2
2
  import { EXECUTION_SYSTEM_PROMPT } from '../../agents/execution.js';
3
- import { PermissionMode } from '../../types.js';
4
3
  import { TodoManager } from '../../todo-manager.js';
4
+ import { PermissionMode } from '../../types.js';
5
5
 
6
6
  const buildStep = async ({ step, context }) => {
7
7
  const { task, cwd, options, logger, promptBuilder, adapter, mcpServers, gitManager, emitEvent, } = context;
8
- const stepLogger = logger.child('BuildStep');
8
+ const stepLogger = logger.child("BuildStep");
9
9
  const latestRun = task.latest_run;
10
- const prExists = latestRun?.output && typeof latestRun.output === 'object'
10
+ const prExists = latestRun?.output && typeof latestRun.output === "object"
11
11
  ? latestRun.output.pr_url
12
12
  : null;
13
13
  if (prExists) {
14
- stepLogger.info('PR already exists, skipping build phase', { taskId: task.id });
15
- return { status: 'skipped' };
14
+ stepLogger.info("PR already exists, skipping build phase", {
15
+ taskId: task.id,
16
+ });
17
+ return { status: "skipped" };
16
18
  }
17
- stepLogger.info('Starting build phase', { taskId: task.id });
18
- emitEvent(adapter.createStatusEvent('phase_start', { phase: 'build' }));
19
+ stepLogger.info("Starting build phase", { taskId: task.id });
20
+ emitEvent(adapter.createStatusEvent("phase_start", { phase: "build" }));
19
21
  const executionPrompt = await promptBuilder.buildExecutionPrompt(task, cwd);
20
22
  const fullPrompt = `${EXECUTION_SYSTEM_PROMPT}\n\n${executionPrompt}`;
21
23
  const configuredPermissionMode = options.permissionMode ??
22
- (typeof step.permissionMode === 'string'
24
+ (typeof step.permissionMode === "string"
23
25
  ? step.permissionMode
24
26
  : step.permissionMode) ??
25
27
  PermissionMode.ACCEPT_EDITS;
@@ -27,25 +29,25 @@ const buildStep = async ({ step, context }) => {
27
29
  model: step.model,
28
30
  cwd,
29
31
  permissionMode: configuredPermissionMode,
30
- settingSources: ['local'],
32
+ settingSources: ["local"],
31
33
  mcpServers,
32
34
  // Allow all tools for build phase - full read/write access needed for implementation
33
35
  allowedTools: [
34
- 'Task',
35
- 'Bash',
36
- 'BashOutput',
37
- 'KillBash',
38
- 'Edit',
39
- 'Read',
40
- 'Write',
41
- 'Glob',
42
- 'Grep',
43
- 'NotebookEdit',
44
- 'WebFetch',
45
- 'WebSearch',
46
- 'ListMcpResources',
47
- 'ReadMcpResource',
48
- 'TodoWrite',
36
+ "Task",
37
+ "Bash",
38
+ "BashOutput",
39
+ "KillBash",
40
+ "Edit",
41
+ "Read",
42
+ "Write",
43
+ "Glob",
44
+ "Grep",
45
+ "NotebookEdit",
46
+ "WebFetch",
47
+ "WebSearch",
48
+ "ListMcpResources",
49
+ "ReadMcpResource",
50
+ "TodoWrite",
49
51
  ],
50
52
  };
51
53
  // Add fine-grained permission hook if provided
@@ -60,17 +62,23 @@ const buildStep = async ({ step, context }) => {
60
62
  const commitTracker = await gitManager.trackCommitsDuring();
61
63
  // Track todos from TodoWrite tool calls
62
64
  const todoManager = new TodoManager(context.fileManager, stepLogger);
63
- for await (const message of response) {
64
- emitEvent(adapter.createRawSDKEvent(message));
65
- const transformedEvents = adapter.transform(message);
66
- for (const event of transformedEvents) {
67
- emitEvent(event);
68
- }
69
- const todoList = await todoManager.checkAndPersistFromMessage(message, task.id);
70
- if (todoList) {
71
- emitEvent(adapter.createArtifactEvent('todos', todoList));
65
+ try {
66
+ for await (const message of response) {
67
+ emitEvent(adapter.createRawSDKEvent(message));
68
+ const transformedEvents = adapter.transform(message);
69
+ for (const event of transformedEvents) {
70
+ emitEvent(event);
71
+ }
72
+ const todoList = await todoManager.checkAndPersistFromMessage(message, task.id);
73
+ if (todoList) {
74
+ emitEvent(adapter.createArtifactEvent("todos", todoList));
75
+ }
72
76
  }
73
77
  }
78
+ catch (error) {
79
+ stepLogger.error("Error during build step query", error);
80
+ throw error;
81
+ }
74
82
  // Finalize: commit any remaining changes and optionally push
75
83
  const { commitCreated, pushedBranch } = await commitTracker.finalize({
76
84
  commitMessage: `Implementation for ${task.title}`,
@@ -78,16 +86,16 @@ const buildStep = async ({ step, context }) => {
78
86
  });
79
87
  context.stepResults[step.id] = { commitCreated };
80
88
  if (!commitCreated) {
81
- stepLogger.warn('No changes to commit in build phase', { taskId: task.id });
89
+ stepLogger.warn("No changes to commit in build phase", { taskId: task.id });
82
90
  }
83
91
  else {
84
- stepLogger.info('Build commits finalized', {
92
+ stepLogger.info("Build commits finalized", {
85
93
  taskId: task.id,
86
- pushedBranch
94
+ pushedBranch,
87
95
  });
88
96
  }
89
- emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));
90
- return { status: 'completed' };
97
+ emitEvent(adapter.createStatusEvent("phase_complete", { phase: "build" }));
98
+ return { status: "completed" };
91
99
  };
92
100
 
93
101
  export { buildStep };
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sources":["../../../../src/workflow/steps/build.ts"],"sourcesContent":["import { query } from '@anthropic-ai/claude-agent-sdk';\nimport { EXECUTION_SYSTEM_PROMPT } from '../../agents/execution.js';\nimport { PermissionMode } from '../../types.js';\nimport type { WorkflowStepRunner } from '../types.js';\nimport { finalizeStepGitActions } from '../utils.js';\nimport { TodoManager } from '../../todo-manager.js';\n\nexport const buildStep: WorkflowStepRunner = async ({ step, context }) => {\n const {\n task,\n cwd,\n options,\n logger,\n promptBuilder,\n adapter,\n mcpServers,\n gitManager,\n emitEvent,\n } = context;\n\n const stepLogger = logger.child('BuildStep');\n\n const latestRun = task.latest_run;\n const prExists =\n latestRun?.output && typeof latestRun.output === 'object'\n ? (latestRun.output as any).pr_url\n : null;\n\n if (prExists) {\n stepLogger.info('PR already exists, skipping build phase', { taskId: task.id });\n return { status: 'skipped' };\n }\n\n stepLogger.info('Starting build phase', { taskId: task.id });\n emitEvent(adapter.createStatusEvent('phase_start', { phase: 'build' }));\n\n const executionPrompt = await promptBuilder.buildExecutionPrompt(task, cwd);\n const fullPrompt = `${EXECUTION_SYSTEM_PROMPT}\\n\\n${executionPrompt}`;\n\n const configuredPermissionMode =\n options.permissionMode ??\n (typeof step.permissionMode === 'string'\n ? (step.permissionMode as PermissionMode)\n : step.permissionMode) ??\n PermissionMode.ACCEPT_EDITS;\n\n const baseOptions: Record<string, any> = {\n model: step.model,\n cwd,\n permissionMode: configuredPermissionMode,\n settingSources: ['local'],\n mcpServers,\n // Allow all tools for build phase - full read/write access needed for implementation\n allowedTools: [\n 'Task',\n 'Bash',\n 'BashOutput',\n 'KillBash',\n 'Edit',\n 'Read',\n 'Write',\n 'Glob',\n 'Grep',\n 'NotebookEdit',\n 'WebFetch',\n 'WebSearch',\n 'ListMcpResources',\n 'ReadMcpResource',\n 'TodoWrite',\n ],\n };\n\n // Add fine-grained permission hook if provided\n if (options.canUseTool) {\n baseOptions.canUseTool = options.canUseTool;\n }\n\n const response = query({\n prompt: fullPrompt,\n options: { ...baseOptions, ...(options.queryOverrides || {}) },\n });\n\n // Track commits made during Claude Code execution\n const commitTracker = await gitManager.trackCommitsDuring();\n\n // Track todos from TodoWrite tool calls\n const todoManager = new TodoManager(context.fileManager, stepLogger);\n\n for await (const message of response) {\n emitEvent(adapter.createRawSDKEvent(message));\n const transformedEvents = adapter.transform(message);\n for (const event of transformedEvents) {\n emitEvent(event);\n }\n\n const todoList = await todoManager.checkAndPersistFromMessage(message, task.id);\n if (todoList) {\n emitEvent(adapter.createArtifactEvent('todos', todoList));\n }\n }\n\n // Finalize: commit any remaining changes and optionally push\n const { commitCreated, pushedBranch } = await commitTracker.finalize({\n commitMessage: `Implementation for ${task.title}`,\n push: step.push,\n });\n\n context.stepResults[step.id] = { commitCreated };\n\n if (!commitCreated) {\n stepLogger.warn('No changes to commit in build phase', { taskId: task.id });\n } else {\n stepLogger.info('Build commits finalized', {\n taskId: task.id,\n pushedBranch\n });\n }\n\n emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));\n return { status: 'completed' };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.js","sources":["../../../../src/workflow/steps/build.ts"],"sourcesContent":["import { query } from \"@anthropic-ai/claude-agent-sdk\";\nimport { EXECUTION_SYSTEM_PROMPT } from \"../../agents/execution.js\";\nimport { TodoManager } from \"../../todo-manager.js\";\nimport { PermissionMode } from \"../../types.js\";\nimport type { WorkflowStepRunner } from \"../types.js\";\n\nexport const buildStep: WorkflowStepRunner = async ({ step, context }) => {\n const {\n task,\n cwd,\n options,\n logger,\n promptBuilder,\n adapter,\n mcpServers,\n gitManager,\n emitEvent,\n } = context;\n\n const stepLogger = logger.child(\"BuildStep\");\n\n const latestRun = task.latest_run;\n const prExists =\n latestRun?.output && typeof latestRun.output === \"object\"\n ? (latestRun.output as Record<string, unknown>).pr_url\n : null;\n\n if (prExists) {\n stepLogger.info(\"PR already exists, skipping build phase\", {\n taskId: task.id,\n });\n return { status: \"skipped\" };\n }\n\n stepLogger.info(\"Starting build phase\", { taskId: task.id });\n emitEvent(adapter.createStatusEvent(\"phase_start\", { phase: \"build\" }));\n\n const executionPrompt = await promptBuilder.buildExecutionPrompt(task, cwd);\n const fullPrompt = `${EXECUTION_SYSTEM_PROMPT}\\n\\n${executionPrompt}`;\n\n const configuredPermissionMode =\n options.permissionMode ??\n (typeof step.permissionMode === \"string\"\n ? (step.permissionMode as PermissionMode)\n : step.permissionMode) ??\n PermissionMode.ACCEPT_EDITS;\n\n const baseOptions: Record<string, unknown> = {\n model: step.model,\n cwd,\n permissionMode: configuredPermissionMode,\n settingSources: [\"local\"],\n mcpServers,\n // Allow all tools for build phase - full read/write access needed for implementation\n allowedTools: [\n \"Task\",\n \"Bash\",\n \"BashOutput\",\n \"KillBash\",\n \"Edit\",\n \"Read\",\n \"Write\",\n \"Glob\",\n \"Grep\",\n \"NotebookEdit\",\n \"WebFetch\",\n \"WebSearch\",\n \"ListMcpResources\",\n \"ReadMcpResource\",\n \"TodoWrite\",\n ],\n };\n\n // Add fine-grained permission hook if provided\n if (options.canUseTool) {\n baseOptions.canUseTool = options.canUseTool;\n }\n\n const response = query({\n prompt: fullPrompt,\n options: { ...baseOptions, ...(options.queryOverrides || {}) },\n });\n\n // Track commits made during Claude Code execution\n const commitTracker = await gitManager.trackCommitsDuring();\n\n // Track todos from TodoWrite tool calls\n const todoManager = new TodoManager(context.fileManager, stepLogger);\n\n try {\n for await (const message of response) {\n emitEvent(adapter.createRawSDKEvent(message));\n const transformedEvents = adapter.transform(message);\n for (const event of transformedEvents) {\n emitEvent(event);\n }\n\n const todoList = await todoManager.checkAndPersistFromMessage(\n message,\n task.id,\n );\n if (todoList) {\n emitEvent(adapter.createArtifactEvent(\"todos\", todoList));\n }\n }\n } catch (error) {\n stepLogger.error(\"Error during build step query\", error);\n throw error;\n }\n\n // Finalize: commit any remaining changes and optionally push\n const { commitCreated, pushedBranch } = await commitTracker.finalize({\n commitMessage: `Implementation for ${task.title}`,\n push: step.push,\n });\n\n context.stepResults[step.id] = { commitCreated };\n\n if (!commitCreated) {\n stepLogger.warn(\"No changes to commit in build phase\", { taskId: task.id });\n } else {\n stepLogger.info(\"Build commits finalized\", {\n taskId: task.id,\n pushedBranch,\n });\n }\n\n emitEvent(adapter.createStatusEvent(\"phase_complete\", { phase: \"build\" }));\n return { status: \"completed\" };\n};\n"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import type { WorkflowStepRunner } from '../types.js';
1
+ import type { WorkflowStepRunner } from "../types.js";
2
2
  export declare const finalizeStep: WorkflowStepRunner;
3
3
  //# sourceMappingURL=finalize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"finalize.d.ts","sourceRoot":"","sources":["../../../../src/workflow/steps/finalize.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAKtD,eAAO,MAAM,YAAY,EAAE,kBA0D1B,CAAC"}
1
+ {"version":3,"file":"finalize.d.ts","sourceRoot":"","sources":["../../../../src/workflow/steps/finalize.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAKtD,eAAO,MAAM,YAAY,EAAE,kBA8D1B,CAAC"}
@@ -3,7 +3,7 @@ import { finalizeStepGitActions } from '../utils.js';
3
3
  const MAX_SNIPPET_LENGTH = 1200;
4
4
  const finalizeStep = async ({ step, context }) => {
5
5
  const { task, logger, fileManager, gitManager, posthogAPI, progressReporter, } = context;
6
- const stepLogger = logger.child('FinalizeStep');
6
+ const stepLogger = logger.child("FinalizeStep");
7
7
  const artifacts = await fileManager.collectTaskArtifacts(task.id);
8
8
  let uploadedArtifacts;
9
9
  if (artifacts.length && posthogAPI && progressReporter.runId) {
@@ -15,20 +15,20 @@ const finalizeStep = async ({ step, context }) => {
15
15
  content_type: artifact.contentType,
16
16
  }));
17
17
  uploadedArtifacts = await posthogAPI.uploadTaskArtifacts(task.id, progressReporter.runId, payload);
18
- stepLogger.info('Uploaded task artifacts to PostHog', {
18
+ stepLogger.info("Uploaded task artifacts to PostHog", {
19
19
  taskId: task.id,
20
20
  uploadedCount: uploadedArtifacts.length,
21
21
  });
22
22
  }
23
23
  catch (error) {
24
- stepLogger.warn('Failed to upload task artifacts', {
24
+ stepLogger.warn("Failed to upload task artifacts", {
25
25
  taskId: task.id,
26
26
  error: error instanceof Error ? error.message : String(error),
27
27
  });
28
28
  }
29
29
  }
30
30
  else {
31
- stepLogger.debug('Skipping artifact upload', {
31
+ stepLogger.debug("Skipping artifact upload", {
32
32
  hasArtifacts: artifacts.length > 0,
33
33
  hasPostHogApi: Boolean(posthogAPI),
34
34
  runId: progressReporter.runId,
@@ -40,88 +40,93 @@ const finalizeStep = async ({ step, context }) => {
40
40
  // Commit the deletion of artifacts
41
41
  await finalizeStepGitActions(context, step, {
42
42
  commitMessage: `Cleanup task artifacts for ${task.title}`,
43
- allowEmptyCommit: true
43
+ allowEmptyCommit: true,
44
44
  });
45
45
  context.stepResults[step.id] = {
46
46
  prBody,
47
47
  uploadedArtifacts,
48
48
  artifactCount: artifacts.length,
49
49
  };
50
- return { status: 'completed' };
50
+ return { status: "completed" };
51
51
  };
52
52
  function buildPullRequestBody(task, artifacts, uploaded) {
53
53
  const lines = [];
54
54
  const taskSlug = task.slug || task.id;
55
- lines.push('## Task context');
55
+ lines.push("## Task context");
56
56
  lines.push(`- **Task**: ${taskSlug}`);
57
57
  lines.push(`- **Title**: ${task.title}`);
58
58
  lines.push(`- **Origin**: ${task.origin_product}`);
59
59
  if (task.description) {
60
- lines.push('');
61
- lines.push('> ' + task.description.trim().split('\n').join('\n> '));
60
+ lines.push("");
61
+ lines.push(`> ${task.description.trim().split("\n").join("\n> ")}`);
62
62
  }
63
63
  const usedFiles = new Set();
64
- const contextArtifact = artifacts.find((artifact) => artifact.name === 'context.md');
64
+ const contextArtifact = artifacts.find((artifact) => artifact.name === "context.md");
65
65
  if (contextArtifact) {
66
- lines.push('');
67
- lines.push('### Task prompt');
66
+ lines.push("");
67
+ lines.push("### Task prompt");
68
68
  lines.push(contextArtifact.content);
69
69
  usedFiles.add(contextArtifact.name);
70
70
  }
71
- const researchArtifact = artifacts.find((artifact) => artifact.name === 'research.json');
71
+ const researchArtifact = artifacts.find((artifact) => artifact.name === "research.json");
72
72
  if (researchArtifact) {
73
73
  usedFiles.add(researchArtifact.name);
74
74
  const researchSection = formatResearchSection(researchArtifact.content);
75
75
  if (researchSection) {
76
- lines.push('');
76
+ lines.push("");
77
77
  lines.push(researchSection);
78
78
  }
79
79
  }
80
- const planArtifact = artifacts.find((artifact) => artifact.name === 'plan.md');
80
+ const planArtifact = artifacts.find((artifact) => artifact.name === "plan.md");
81
81
  if (planArtifact) {
82
- lines.push('');
83
- lines.push('### Implementation plan');
82
+ lines.push("");
83
+ lines.push("### Implementation plan");
84
84
  lines.push(planArtifact.content);
85
85
  usedFiles.add(planArtifact.name);
86
86
  }
87
- const todoArtifact = artifacts.find((artifact) => artifact.name === 'todos.json');
87
+ const todoArtifact = artifacts.find((artifact) => artifact.name === "todos.json");
88
88
  if (todoArtifact) {
89
89
  const summary = summarizeTodos(todoArtifact.content);
90
90
  if (summary) {
91
- lines.push('');
92
- lines.push('### Todo list');
91
+ lines.push("");
92
+ lines.push("### Todo list");
93
93
  lines.push(summary);
94
94
  }
95
95
  usedFiles.add(todoArtifact.name);
96
96
  }
97
97
  const remainingArtifacts = artifacts.filter((artifact) => !usedFiles.has(artifact.name));
98
98
  if (remainingArtifacts.length) {
99
- lines.push('');
100
- lines.push('### Additional artifacts');
99
+ lines.push("");
100
+ lines.push("### Additional artifacts");
101
101
  for (const artifact of remainingArtifacts) {
102
102
  lines.push(`#### ${artifact.name}`);
103
103
  lines.push(renderCodeFence(artifact.content));
104
104
  }
105
105
  }
106
- const artifactList = uploaded ?? artifacts.map((artifact) => ({
107
- name: artifact.name,
108
- type: artifact.type,
109
- }));
106
+ const artifactList = uploaded ??
107
+ artifacts.map((artifact) => ({
108
+ name: artifact.name,
109
+ type: artifact.type,
110
+ }));
110
111
  if (artifactList.length) {
111
- lines.push('');
112
- lines.push('### Uploaded artifacts');
112
+ lines.push("");
113
+ lines.push("### Uploaded artifacts");
113
114
  for (const artifact of artifactList) {
114
- const rawStoragePath = 'storage_path' in artifact ? artifact.storage_path : undefined;
115
- const storagePath = typeof rawStoragePath === 'string' ? rawStoragePath : undefined;
116
- const storage = storagePath && storagePath.trim().length > 0 ? ` – \`${storagePath.trim()}\`` : '';
115
+ const rawStoragePath = "storage_path" in artifact
116
+ ? artifact.storage_path
117
+ : undefined;
118
+ const storagePath = typeof rawStoragePath === "string" ? rawStoragePath : undefined;
119
+ const storage = storagePath && storagePath.trim().length > 0
120
+ ? ` – \`${storagePath.trim()}\``
121
+ : "";
117
122
  lines.push(`- ${artifact.name} (${artifact.type})${storage}`);
118
123
  }
119
124
  }
120
- return lines.join('\n\n');
125
+ return lines.join("\n\n");
121
126
  }
122
127
  function renderCodeFence(content) {
123
128
  const snippet = truncate(content, MAX_SNIPPET_LENGTH);
124
- return ['```', snippet, '```'].join('\n');
129
+ return ["```", snippet, "```"].join("\n");
125
130
  }
126
131
  function truncate(value, maxLength) {
127
132
  if (value.length <= maxLength) {
@@ -134,25 +139,27 @@ function formatResearchSection(content) {
134
139
  const parsed = JSON.parse(content);
135
140
  const sections = [];
136
141
  if (parsed.context) {
137
- sections.push('### Research summary');
142
+ sections.push("### Research summary");
138
143
  sections.push(parsed.context);
139
144
  }
140
- if (parsed.questions && parsed.questions.length) {
141
- sections.push('');
142
- sections.push('### Questions needing answers');
145
+ if (parsed.questions?.length) {
146
+ sections.push("");
147
+ sections.push("### Questions needing answers");
143
148
  for (const question of parsed.questions) {
144
149
  sections.push(`- ${question.question ?? question}`);
145
150
  }
146
151
  }
147
- if (parsed.answers && parsed.answers.length) {
148
- sections.push('');
149
- sections.push('### Answers provided');
152
+ if (parsed.answers?.length) {
153
+ sections.push("");
154
+ sections.push("### Answers provided");
150
155
  for (const answer of parsed.answers) {
151
- const questionId = answer.questionId ? ` (Q: ${answer.questionId})` : '';
152
- sections.push(`- ${answer.selectedOption || answer.customInput || 'answer'}${questionId}`);
156
+ const questionId = answer.questionId
157
+ ? ` (Q: ${answer.questionId})`
158
+ : "";
159
+ sections.push(`- ${answer.selectedOption || answer.customInput || "answer"}${questionId}`);
153
160
  }
154
161
  }
155
- return sections.length ? sections.join('\n') : null;
162
+ return sections.length ? sections.join("\n") : null;
156
163
  }
157
164
  catch {
158
165
  return null;
@@ -162,16 +169,15 @@ function summarizeTodos(content) {
162
169
  try {
163
170
  const data = JSON.parse(content);
164
171
  const total = data?.metadata?.total ?? data?.items?.length;
165
- const completed = data?.metadata?.completed ?? data?.items?.filter((item) => item.status === 'completed').length;
166
- const lines = [
167
- `Progress: ${completed}/${total} completed`,
168
- ];
172
+ const completed = data?.metadata?.completed ??
173
+ data?.items?.filter((item) => item.status === "completed").length;
174
+ const lines = [`Progress: ${completed}/${total} completed`];
169
175
  if (data?.items?.length) {
170
176
  for (const item of data.items) {
171
177
  lines.push(`- [${item.status}] ${item.content}`);
172
178
  }
173
179
  }
174
- return lines.join('\n');
180
+ return lines.join("\n");
175
181
  }
176
182
  catch {
177
183
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"finalize.js","sources":["../../../../src/workflow/steps/finalize.ts"],"sourcesContent":["import type { LocalArtifact } from '../../file-manager.js';\nimport type { Task, TaskRunArtifact } from '../../types.js';\nimport type { WorkflowStepRunner } from '../types.js';\nimport { finalizeStepGitActions } from '../utils.js';\n\nconst MAX_SNIPPET_LENGTH = 1200;\n\nexport const finalizeStep: WorkflowStepRunner = async ({ step, context }) => {\n const {\n task,\n logger,\n fileManager,\n gitManager,\n posthogAPI,\n progressReporter,\n } = context;\n\n const stepLogger = logger.child('FinalizeStep');\n const artifacts = await fileManager.collectTaskArtifacts(task.id);\n let uploadedArtifacts: TaskRunArtifact[] | undefined;\n\n if (artifacts.length && posthogAPI && progressReporter.runId) {\n try {\n const payload = artifacts.map((artifact) => ({\n name: artifact.name,\n type: artifact.type,\n content: artifact.content,\n content_type: artifact.contentType,\n }));\n uploadedArtifacts = await posthogAPI.uploadTaskArtifacts(task.id, progressReporter.runId, payload);\n stepLogger.info('Uploaded task artifacts to PostHog', {\n taskId: task.id,\n uploadedCount: uploadedArtifacts.length,\n });\n } catch (error) {\n stepLogger.warn('Failed to upload task artifacts', {\n taskId: task.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n } else {\n stepLogger.debug('Skipping artifact upload', {\n hasArtifacts: artifacts.length > 0,\n hasPostHogApi: Boolean(posthogAPI),\n runId: progressReporter.runId,\n });\n }\n\n const prBody = buildPullRequestBody(task, artifacts, uploadedArtifacts);\n await fileManager.cleanupTaskDirectory(task.id);\n await gitManager.addAllPostHogFiles();\n \n // Commit the deletion of artifacts\n await finalizeStepGitActions(context, step, {\n commitMessage: `Cleanup task artifacts for ${task.title}`,\n allowEmptyCommit: true\n });\n\n context.stepResults[step.id] = {\n prBody,\n uploadedArtifacts,\n artifactCount: artifacts.length,\n };\n\n return { status: 'completed' };\n};\n\nfunction buildPullRequestBody(task: Task, artifacts: LocalArtifact[], uploaded?: TaskRunArtifact[]): string {\n const lines: string[] = [];\n const taskSlug = (task as any).slug || task.id;\n\n lines.push('## Task context');\n lines.push(`- **Task**: ${taskSlug}`);\n lines.push(`- **Title**: ${task.title}`);\n lines.push(`- **Origin**: ${task.origin_product}`);\n\n if (task.description) {\n lines.push('');\n lines.push('> ' + task.description.trim().split('\\n').join('\\n> '));\n }\n\n const usedFiles = new Set<string>();\n\n const contextArtifact = artifacts.find((artifact) => artifact.name === 'context.md');\n if (contextArtifact) {\n lines.push('');\n lines.push('### Task prompt');\n lines.push(contextArtifact.content);\n usedFiles.add(contextArtifact.name);\n }\n\n const researchArtifact = artifacts.find((artifact) => artifact.name === 'research.json');\n if (researchArtifact) {\n usedFiles.add(researchArtifact.name);\n const researchSection = formatResearchSection(researchArtifact.content);\n if (researchSection) {\n lines.push('');\n lines.push(researchSection);\n }\n }\n\n const planArtifact = artifacts.find((artifact) => artifact.name === 'plan.md');\n if (planArtifact) {\n lines.push('');\n lines.push('### Implementation plan');\n lines.push(planArtifact.content);\n usedFiles.add(planArtifact.name);\n }\n\n const todoArtifact = artifacts.find((artifact) => artifact.name === 'todos.json');\n if (todoArtifact) {\n const summary = summarizeTodos(todoArtifact.content);\n if (summary) {\n lines.push('');\n lines.push('### Todo list');\n lines.push(summary);\n }\n usedFiles.add(todoArtifact.name);\n }\n\n const remainingArtifacts = artifacts.filter((artifact) => !usedFiles.has(artifact.name));\n if (remainingArtifacts.length) {\n lines.push('');\n lines.push('### Additional artifacts');\n for (const artifact of remainingArtifacts) {\n lines.push(`#### ${artifact.name}`);\n lines.push(renderCodeFence(artifact.content));\n }\n }\n\n const artifactList = uploaded ?? artifacts.map((artifact) => ({\n name: artifact.name,\n type: artifact.type,\n }));\n\n if (artifactList.length) {\n lines.push('');\n lines.push('### Uploaded artifacts');\n for (const artifact of artifactList) {\n const rawStoragePath = 'storage_path' in artifact ? (artifact as any).storage_path : undefined;\n const storagePath = typeof rawStoragePath === 'string' ? rawStoragePath : undefined;\n const storage = storagePath && storagePath.trim().length > 0 ? ` – \\`${storagePath.trim()}\\`` : '';\n lines.push(`- ${artifact.name} (${artifact.type})${storage}`);\n }\n }\n\n return lines.join('\\n\\n');\n}\n\nfunction renderCodeFence(content: string): string {\n const snippet = truncate(content, MAX_SNIPPET_LENGTH);\n return ['```', snippet, '```'].join('\\n');\n}\n\nfunction truncate(value: string, maxLength: number): string {\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, maxLength)}\\n…`;\n}\n\nfunction formatResearchSection(content: string): string | null {\n try {\n const parsed = JSON.parse(content);\n const sections: string[] = [];\n\n if (parsed.context) {\n sections.push('### Research summary');\n sections.push(parsed.context);\n }\n\n if (parsed.questions && parsed.questions.length) {\n sections.push('');\n sections.push('### Questions needing answers');\n for (const question of parsed.questions) {\n sections.push(`- ${question.question ?? question}`);\n }\n }\n\n if (parsed.answers && parsed.answers.length) {\n sections.push('');\n sections.push('### Answers provided');\n for (const answer of parsed.answers) {\n const questionId = answer.questionId ? ` (Q: ${answer.questionId})` : '';\n sections.push(`- ${answer.selectedOption || answer.customInput || 'answer'}${questionId}`);\n }\n }\n\n return sections.length ? sections.join('\\n') : null;\n } catch {\n return null;\n }\n}\n\nfunction summarizeTodos(content: string): string | null {\n try {\n const data = JSON.parse(content);\n const total = data?.metadata?.total ?? data?.items?.length;\n const completed = data?.metadata?.completed ?? data?.items?.filter((item: any) => item.status === 'completed').length;\n\n const lines = [\n `Progress: ${completed}/${total} completed`,\n ];\n\n if (data?.items?.length) {\n for (const item of data.items) {\n lines.push(`- [${item.status}] ${item.content}`);\n }\n }\n\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"finalize.js","sources":["../../../../src/workflow/steps/finalize.ts"],"sourcesContent":["import type { LocalArtifact } from \"../../file-manager.js\";\nimport type { Task, TaskRunArtifact } from \"../../types.js\";\nimport type { WorkflowStepRunner } from \"../types.js\";\nimport { finalizeStepGitActions } from \"../utils.js\";\n\nconst MAX_SNIPPET_LENGTH = 1200;\n\nexport const finalizeStep: WorkflowStepRunner = async ({ step, context }) => {\n const {\n task,\n logger,\n fileManager,\n gitManager,\n posthogAPI,\n progressReporter,\n } = context;\n\n const stepLogger = logger.child(\"FinalizeStep\");\n const artifacts = await fileManager.collectTaskArtifacts(task.id);\n let uploadedArtifacts: TaskRunArtifact[] | undefined;\n\n if (artifacts.length && posthogAPI && progressReporter.runId) {\n try {\n const payload = artifacts.map((artifact) => ({\n name: artifact.name,\n type: artifact.type,\n content: artifact.content,\n content_type: artifact.contentType,\n }));\n uploadedArtifacts = await posthogAPI.uploadTaskArtifacts(\n task.id,\n progressReporter.runId,\n payload,\n );\n stepLogger.info(\"Uploaded task artifacts to PostHog\", {\n taskId: task.id,\n uploadedCount: uploadedArtifacts.length,\n });\n } catch (error) {\n stepLogger.warn(\"Failed to upload task artifacts\", {\n taskId: task.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n } else {\n stepLogger.debug(\"Skipping artifact upload\", {\n hasArtifacts: artifacts.length > 0,\n hasPostHogApi: Boolean(posthogAPI),\n runId: progressReporter.runId,\n });\n }\n\n const prBody = buildPullRequestBody(task, artifacts, uploadedArtifacts);\n await fileManager.cleanupTaskDirectory(task.id);\n await gitManager.addAllPostHogFiles();\n\n // Commit the deletion of artifacts\n await finalizeStepGitActions(context, step, {\n commitMessage: `Cleanup task artifacts for ${task.title}`,\n allowEmptyCommit: true,\n });\n\n context.stepResults[step.id] = {\n prBody,\n uploadedArtifacts,\n artifactCount: artifacts.length,\n };\n\n return { status: \"completed\" };\n};\n\nfunction buildPullRequestBody(\n task: Task,\n artifacts: LocalArtifact[],\n uploaded?: TaskRunArtifact[],\n): string {\n const lines: string[] = [];\n const taskSlug = (task as unknown as Record<string, unknown>).slug || task.id;\n\n lines.push(\"## Task context\");\n lines.push(`- **Task**: ${taskSlug}`);\n lines.push(`- **Title**: ${task.title}`);\n lines.push(`- **Origin**: ${task.origin_product}`);\n\n if (task.description) {\n lines.push(\"\");\n lines.push(`> ${task.description.trim().split(\"\\n\").join(\"\\n> \")}`);\n }\n\n const usedFiles = new Set<string>();\n\n const contextArtifact = artifacts.find(\n (artifact) => artifact.name === \"context.md\",\n );\n if (contextArtifact) {\n lines.push(\"\");\n lines.push(\"### Task prompt\");\n lines.push(contextArtifact.content);\n usedFiles.add(contextArtifact.name);\n }\n\n const researchArtifact = artifacts.find(\n (artifact) => artifact.name === \"research.json\",\n );\n if (researchArtifact) {\n usedFiles.add(researchArtifact.name);\n const researchSection = formatResearchSection(researchArtifact.content);\n if (researchSection) {\n lines.push(\"\");\n lines.push(researchSection);\n }\n }\n\n const planArtifact = artifacts.find(\n (artifact) => artifact.name === \"plan.md\",\n );\n if (planArtifact) {\n lines.push(\"\");\n lines.push(\"### Implementation plan\");\n lines.push(planArtifact.content);\n usedFiles.add(planArtifact.name);\n }\n\n const todoArtifact = artifacts.find(\n (artifact) => artifact.name === \"todos.json\",\n );\n if (todoArtifact) {\n const summary = summarizeTodos(todoArtifact.content);\n if (summary) {\n lines.push(\"\");\n lines.push(\"### Todo list\");\n lines.push(summary);\n }\n usedFiles.add(todoArtifact.name);\n }\n\n const remainingArtifacts = artifacts.filter(\n (artifact) => !usedFiles.has(artifact.name),\n );\n if (remainingArtifacts.length) {\n lines.push(\"\");\n lines.push(\"### Additional artifacts\");\n for (const artifact of remainingArtifacts) {\n lines.push(`#### ${artifact.name}`);\n lines.push(renderCodeFence(artifact.content));\n }\n }\n\n const artifactList =\n uploaded ??\n artifacts.map((artifact) => ({\n name: artifact.name,\n type: artifact.type,\n }));\n\n if (artifactList.length) {\n lines.push(\"\");\n lines.push(\"### Uploaded artifacts\");\n for (const artifact of artifactList) {\n const rawStoragePath =\n \"storage_path\" in artifact\n ? (artifact as Record<string, unknown>).storage_path\n : undefined;\n const storagePath =\n typeof rawStoragePath === \"string\" ? rawStoragePath : undefined;\n const storage =\n storagePath && storagePath.trim().length > 0\n ? ` – \\`${storagePath.trim()}\\``\n : \"\";\n lines.push(`- ${artifact.name} (${artifact.type})${storage}`);\n }\n }\n\n return lines.join(\"\\n\\n\");\n}\n\nfunction renderCodeFence(content: string): string {\n const snippet = truncate(content, MAX_SNIPPET_LENGTH);\n return [\"```\", snippet, \"```\"].join(\"\\n\");\n}\n\nfunction truncate(value: string, maxLength: number): string {\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, maxLength)}\\n…`;\n}\n\nfunction formatResearchSection(content: string): string | null {\n try {\n const parsed = JSON.parse(content);\n const sections: string[] = [];\n\n if (parsed.context) {\n sections.push(\"### Research summary\");\n sections.push(parsed.context);\n }\n\n if (parsed.questions?.length) {\n sections.push(\"\");\n sections.push(\"### Questions needing answers\");\n for (const question of parsed.questions) {\n sections.push(`- ${question.question ?? question}`);\n }\n }\n\n if (parsed.answers?.length) {\n sections.push(\"\");\n sections.push(\"### Answers provided\");\n for (const answer of parsed.answers) {\n const questionId = answer.questionId\n ? ` (Q: ${answer.questionId})`\n : \"\";\n sections.push(\n `- ${answer.selectedOption || answer.customInput || \"answer\"}${questionId}`,\n );\n }\n }\n\n return sections.length ? sections.join(\"\\n\") : null;\n } catch {\n return null;\n }\n}\n\nfunction summarizeTodos(content: string): string | null {\n try {\n const data = JSON.parse(content);\n const total = data?.metadata?.total ?? data?.items?.length;\n const completed =\n data?.metadata?.completed ??\n data?.items?.filter(\n (item: { status?: string }) => item.status === \"completed\",\n ).length;\n\n const lines = [`Progress: ${completed}/${total} completed`];\n\n if (data?.items?.length) {\n for (const item of data.items) {\n lines.push(`- [${item.status}] ${item.content}`);\n }\n }\n\n return lines.join(\"\\n\");\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import type { WorkflowStepRunner } from '../types.js';
1
+ import type { WorkflowStepRunner } from "../types.js";
2
2
  export declare const planStep: WorkflowStepRunner;
3
3
  //# sourceMappingURL=plan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../../src/workflow/steps/plan.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAItD,eAAO,MAAM,QAAQ,EAAE,kBAuItB,CAAC"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../../src/workflow/steps/plan.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,eAAO,MAAM,QAAQ,EAAE,kBA2JtB,CAAC"}