@posthog/agent 1.12.0 → 1.13.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 (219) hide show
  1. package/dist/_virtual/_commonjsHelpers.js +6 -0
  2. package/dist/_virtual/_commonjsHelpers.js.map +1 -0
  3. package/dist/_virtual/index.js +4 -0
  4. package/dist/_virtual/index.js.map +1 -0
  5. package/dist/node_modules/@ai-sdk/anthropic/dist/index.js +1154 -0
  6. package/dist/node_modules/@ai-sdk/anthropic/dist/index.js.map +1 -0
  7. package/dist/node_modules/@ai-sdk/provider/dist/index.js +296 -0
  8. package/dist/node_modules/@ai-sdk/provider/dist/index.js.map +1 -0
  9. package/dist/node_modules/@ai-sdk/provider-utils/dist/index.js +576 -0
  10. package/dist/node_modules/@ai-sdk/provider-utils/dist/index.js.map +1 -0
  11. package/dist/node_modules/@ai-sdk/ui-utils/dist/index.js +741 -0
  12. package/dist/node_modules/@ai-sdk/ui-utils/dist/index.js.map +1 -0
  13. package/dist/node_modules/@opentelemetry/api/build/esm/api/context.js +112 -0
  14. package/dist/node_modules/@opentelemetry/api/build/esm/api/context.js.map +1 -0
  15. package/dist/node_modules/@opentelemetry/api/build/esm/api/diag.js +123 -0
  16. package/dist/node_modules/@opentelemetry/api/build/esm/api/diag.js.map +1 -0
  17. package/dist/node_modules/@opentelemetry/api/build/esm/api/metrics.js +62 -0
  18. package/dist/node_modules/@opentelemetry/api/build/esm/api/metrics.js.map +1 -0
  19. package/dist/node_modules/@opentelemetry/api/build/esm/api/propagation.js +91 -0
  20. package/dist/node_modules/@opentelemetry/api/build/esm/api/propagation.js.map +1 -0
  21. package/dist/node_modules/@opentelemetry/api/build/esm/api/trace.js +79 -0
  22. package/dist/node_modules/@opentelemetry/api/build/esm/api/trace.js.map +1 -0
  23. package/dist/node_modules/@opentelemetry/api/build/esm/baggage/context-helpers.js +59 -0
  24. package/dist/node_modules/@opentelemetry/api/build/esm/baggage/context-helpers.js.map +1 -0
  25. package/dist/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js +99 -0
  26. package/dist/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js.map +1 -0
  27. package/dist/node_modules/@opentelemetry/api/build/esm/baggage/utils.js +31 -0
  28. package/dist/node_modules/@opentelemetry/api/build/esm/baggage/utils.js.map +1 -0
  29. package/dist/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js +69 -0
  30. package/dist/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js.map +1 -0
  31. package/dist/node_modules/@opentelemetry/api/build/esm/context/context.js +54 -0
  32. package/dist/node_modules/@opentelemetry/api/build/esm/context/context.js.map +1 -0
  33. package/dist/node_modules/@opentelemetry/api/build/esm/context-api.js +22 -0
  34. package/dist/node_modules/@opentelemetry/api/build/esm/context-api.js.map +1 -0
  35. package/dist/node_modules/@opentelemetry/api/build/esm/diag/ComponentLogger.js +104 -0
  36. package/dist/node_modules/@opentelemetry/api/build/esm/diag/ComponentLogger.js.map +1 -0
  37. package/dist/node_modules/@opentelemetry/api/build/esm/diag/internal/logLevelLogger.js +44 -0
  38. package/dist/node_modules/@opentelemetry/api/build/esm/diag/internal/logLevelLogger.js.map +1 -0
  39. package/dist/node_modules/@opentelemetry/api/build/esm/diag/types.js +43 -0
  40. package/dist/node_modules/@opentelemetry/api/build/esm/diag/types.js.map +1 -0
  41. package/dist/node_modules/@opentelemetry/api/build/esm/diag-api.js +27 -0
  42. package/dist/node_modules/@opentelemetry/api/build/esm/diag-api.js.map +1 -0
  43. package/dist/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js +62 -0
  44. package/dist/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js.map +1 -0
  45. package/dist/node_modules/@opentelemetry/api/build/esm/internal/semver.js +121 -0
  46. package/dist/node_modules/@opentelemetry/api/build/esm/internal/semver.js.map +1 -0
  47. package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js +167 -0
  48. package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js.map +1 -0
  49. package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js +33 -0
  50. package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js.map +1 -0
  51. package/dist/node_modules/@opentelemetry/api/build/esm/metrics-api.js +22 -0
  52. package/dist/node_modules/@opentelemetry/api/build/esm/metrics-api.js.map +1 -0
  53. package/dist/node_modules/@opentelemetry/api/build/esm/platform/node/globalThis.js +21 -0
  54. package/dist/node_modules/@opentelemetry/api/build/esm/platform/node/globalThis.js.map +1 -0
  55. package/dist/node_modules/@opentelemetry/api/build/esm/propagation/NoopTextMapPropagator.js +35 -0
  56. package/dist/node_modules/@opentelemetry/api/build/esm/propagation/NoopTextMapPropagator.js.map +1 -0
  57. package/dist/node_modules/@opentelemetry/api/build/esm/propagation/TextMapPropagator.js +40 -0
  58. package/dist/node_modules/@opentelemetry/api/build/esm/propagation/TextMapPropagator.js.map +1 -0
  59. package/dist/node_modules/@opentelemetry/api/build/esm/propagation-api.js +22 -0
  60. package/dist/node_modules/@opentelemetry/api/build/esm/propagation-api.js.map +1 -0
  61. package/dist/node_modules/@opentelemetry/api/build/esm/trace/NonRecordingSpan.js +70 -0
  62. package/dist/node_modules/@opentelemetry/api/build/esm/trace/NonRecordingSpan.js.map +1 -0
  63. package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracer.js +78 -0
  64. package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracer.js.map +1 -0
  65. package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js +34 -0
  66. package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js.map +1 -0
  67. package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracer.js +55 -0
  68. package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracer.js.map +1 -0
  69. package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracerProvider.js +56 -0
  70. package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracerProvider.js.map +1 -0
  71. package/dist/node_modules/@opentelemetry/api/build/esm/trace/context-utils.js +76 -0
  72. package/dist/node_modules/@opentelemetry/api/build/esm/trace/context-utils.js.map +1 -0
  73. package/dist/node_modules/@opentelemetry/api/build/esm/trace/invalid-span-constants.js +27 -0
  74. package/dist/node_modules/@opentelemetry/api/build/esm/trace/invalid-span-constants.js.map +1 -0
  75. package/dist/node_modules/@opentelemetry/api/build/esm/trace/spancontext-utils.js +45 -0
  76. package/dist/node_modules/@opentelemetry/api/build/esm/trace/spancontext-utils.js.map +1 -0
  77. package/dist/node_modules/@opentelemetry/api/build/esm/trace/status.js +22 -0
  78. package/dist/node_modules/@opentelemetry/api/build/esm/trace/status.js.map +1 -0
  79. package/dist/node_modules/@opentelemetry/api/build/esm/trace/trace_flags.js +25 -0
  80. package/dist/node_modules/@opentelemetry/api/build/esm/trace/trace_flags.js.map +1 -0
  81. package/dist/node_modules/@opentelemetry/api/build/esm/trace-api.js +24 -0
  82. package/dist/node_modules/@opentelemetry/api/build/esm/trace-api.js.map +1 -0
  83. package/dist/node_modules/@opentelemetry/api/build/esm/version.js +20 -0
  84. package/dist/node_modules/@opentelemetry/api/build/esm/version.js.map +1 -0
  85. package/dist/node_modules/ai/dist/index.js +2870 -0
  86. package/dist/node_modules/ai/dist/index.js.map +1 -0
  87. package/dist/node_modules/nanoid/non-secure/index.js +13 -0
  88. package/dist/node_modules/nanoid/non-secure/index.js.map +1 -0
  89. package/dist/node_modules/secure-json-parse/index.js +133 -0
  90. package/dist/node_modules/secure-json-parse/index.js.map +1 -0
  91. package/dist/node_modules/zod-to-json-schema/dist/esm/Options.js +37 -0
  92. package/dist/node_modules/zod-to-json-schema/dist/esm/Options.js.map +1 -0
  93. package/dist/node_modules/zod-to-json-schema/dist/esm/Refs.js +26 -0
  94. package/dist/node_modules/zod-to-json-schema/dist/esm/Refs.js.map +1 -0
  95. package/dist/node_modules/zod-to-json-schema/dist/esm/errorMessages.js +17 -0
  96. package/dist/node_modules/zod-to-json-schema/dist/esm/errorMessages.js.map +1 -0
  97. package/dist/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js +11 -0
  98. package/dist/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js.map +1 -0
  99. package/dist/node_modules/zod-to-json-schema/dist/esm/index.js +8 -0
  100. package/dist/node_modules/zod-to-json-schema/dist/esm/index.js.map +1 -0
  101. package/dist/node_modules/zod-to-json-schema/dist/esm/parseDef.js +66 -0
  102. package/dist/node_modules/zod-to-json-schema/dist/esm/parseDef.js.map +1 -0
  103. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/any.js +21 -0
  104. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/any.js.map +1 -0
  105. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/array.js +30 -0
  106. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/array.js.map +1 -0
  107. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js +53 -0
  108. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js.map +1 -0
  109. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js +8 -0
  110. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js.map +1 -0
  111. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/branded.js +8 -0
  112. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/branded.js.map +1 -0
  113. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/catch.js +8 -0
  114. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/catch.js.map +1 -0
  115. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/date.js +50 -0
  116. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/date.js.map +1 -0
  117. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/default.js +11 -0
  118. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/default.js.map +1 -0
  119. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/effects.js +11 -0
  120. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/effects.js.map +1 -0
  121. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/enum.js +9 -0
  122. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/enum.js.map +1 -0
  123. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js +56 -0
  124. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js.map +1 -0
  125. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/literal.js +24 -0
  126. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/literal.js.map +1 -0
  127. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/map.js +30 -0
  128. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/map.js.map +1 -0
  129. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js +19 -0
  130. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js.map +1 -0
  131. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/never.js +15 -0
  132. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/never.js.map +1 -0
  133. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/null.js +13 -0
  134. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/null.js.map +1 -0
  135. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js +37 -0
  136. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js.map +1 -0
  137. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/number.js +56 -0
  138. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/number.js.map +1 -0
  139. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/object.js +76 -0
  140. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/object.js.map +1 -0
  141. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/optional.js +25 -0
  142. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/optional.js.map +1 -0
  143. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js +24 -0
  144. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js.map +1 -0
  145. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/promise.js +8 -0
  146. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/promise.js.map +1 -0
  147. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js +8 -0
  148. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js.map +1 -0
  149. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/record.js +65 -0
  150. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/record.js.map +1 -0
  151. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/set.js +24 -0
  152. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/set.js.map +1 -0
  153. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/string.js +350 -0
  154. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/string.js.map +1 -0
  155. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js +36 -0
  156. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js.map +1 -0
  157. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js +10 -0
  158. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js.map +1 -0
  159. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/union.js +84 -0
  160. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/union.js.map +1 -0
  161. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js +8 -0
  162. package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js.map +1 -0
  163. package/dist/node_modules/zod-to-json-schema/dist/esm/selectParser.js +110 -0
  164. package/dist/node_modules/zod-to-json-schema/dist/esm/selectParser.js.map +1 -0
  165. package/dist/node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js +90 -0
  166. package/dist/node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js.map +1 -0
  167. package/dist/src/agent.d.ts +3 -0
  168. package/dist/src/agent.d.ts.map +1 -1
  169. package/dist/src/agent.js +93 -291
  170. package/dist/src/agent.js.map +1 -1
  171. package/dist/src/agents/planning.d.ts +1 -1
  172. package/dist/src/agents/planning.d.ts.map +1 -1
  173. package/dist/src/agents/planning.js +1 -2
  174. package/dist/src/agents/planning.js.map +1 -1
  175. package/dist/src/agents/research.d.ts +1 -1
  176. package/dist/src/agents/research.d.ts.map +1 -1
  177. package/dist/src/agents/research.js +3 -6
  178. package/dist/src/agents/research.js.map +1 -1
  179. package/dist/src/prompt-builder.d.ts.map +1 -1
  180. package/dist/src/prompt-builder.js +0 -1
  181. package/dist/src/prompt-builder.js.map +1 -1
  182. package/dist/src/structured-extraction.d.ts +2 -2
  183. package/dist/src/structured-extraction.d.ts.map +1 -1
  184. package/dist/src/structured-extraction.js +51 -110
  185. package/dist/src/structured-extraction.js.map +1 -1
  186. package/dist/src/workflow/config.d.ts +3 -0
  187. package/dist/src/workflow/config.d.ts.map +1 -0
  188. package/dist/src/workflow/config.js +43 -0
  189. package/dist/src/workflow/config.js.map +1 -0
  190. package/dist/src/workflow/steps/build.d.ts +3 -0
  191. package/dist/src/workflow/steps/build.d.ts.map +1 -0
  192. package/dist/src/workflow/steps/build.js +64 -0
  193. package/dist/src/workflow/steps/build.js.map +1 -0
  194. package/dist/src/workflow/steps/plan.d.ts +3 -0
  195. package/dist/src/workflow/steps/plan.d.ts.map +1 -0
  196. package/dist/src/workflow/steps/plan.js +86 -0
  197. package/dist/src/workflow/steps/plan.js.map +1 -0
  198. package/dist/src/workflow/steps/research.d.ts +3 -0
  199. package/dist/src/workflow/steps/research.d.ts.map +1 -0
  200. package/dist/src/workflow/steps/research.js +124 -0
  201. package/dist/src/workflow/steps/research.js.map +1 -0
  202. package/dist/src/workflow/types.d.ts +48 -0
  203. package/dist/src/workflow/types.d.ts.map +1 -0
  204. package/dist/src/workflow/utils.d.ts +12 -0
  205. package/dist/src/workflow/utils.d.ts.map +1 -0
  206. package/dist/src/workflow/utils.js +38 -0
  207. package/dist/src/workflow/utils.js.map +1 -0
  208. package/package.json +5 -2
  209. package/src/agent.ts +112 -321
  210. package/src/agents/planning.ts +1 -2
  211. package/src/agents/research.ts +3 -6
  212. package/src/prompt-builder.ts +0 -2
  213. package/src/structured-extraction.ts +58 -115
  214. package/src/workflow/config.ts +42 -0
  215. package/src/workflow/steps/build.ts +87 -0
  216. package/src/workflow/steps/plan.ts +112 -0
  217. package/src/workflow/steps/research.ts +156 -0
  218. package/src/workflow/types.ts +53 -0
  219. package/src/workflow/utils.ts +50 -0
@@ -1,136 +1,77 @@
1
- import OpenAI from 'openai';
1
+ import { generateObject } from '../node_modules/ai/dist/index.js';
2
+ import { anthropic } from '../node_modules/@ai-sdk/anthropic/dist/index.js';
3
+ import { z } from 'zod';
2
4
  import { Logger } from './utils/logger.js';
3
5
 
4
- const questionsOnlySchema = {
5
- type: 'object',
6
- properties: {
7
- questions: {
8
- type: 'array',
9
- items: {
10
- type: 'object',
11
- properties: {
12
- id: { type: 'string' },
13
- question: { type: 'string' },
14
- options: {
15
- type: 'array',
16
- items: { type: 'string' }
17
- }
18
- },
19
- required: ['id', 'question', 'options'],
20
- additionalProperties: false
21
- }
22
- }
23
- },
24
- required: ['questions'],
25
- additionalProperties: false
26
- };
27
- const questionsWithAnswersSchema = {
28
- type: 'object',
29
- properties: {
30
- questions: {
31
- type: 'array',
32
- items: {
33
- type: 'object',
34
- properties: {
35
- id: { type: 'string' },
36
- question: { type: 'string' },
37
- options: {
38
- type: 'array',
39
- items: { type: 'string' }
40
- },
41
- recommendedAnswer: { type: 'string' },
42
- justification: { type: 'string' }
43
- },
44
- required: ['id', 'question', 'options', 'recommendedAnswer', 'justification'],
45
- additionalProperties: false
46
- }
47
- }
48
- },
49
- required: ['questions'],
50
- additionalProperties: false
51
- };
52
- class OpenAIExtractor {
53
- client;
6
+ const questionsOnlySchema = z.object({
7
+ questions: z.array(z.object({
8
+ id: z.string(),
9
+ question: z.string(),
10
+ options: z.array(z.string()),
11
+ })),
12
+ });
13
+ const questionsWithAnswersSchema = z.object({
14
+ questions: z.array(z.object({
15
+ id: z.string(),
16
+ question: z.string(),
17
+ options: z.array(z.string()),
18
+ recommendedAnswer: z.string().describe('The letter of the recommended option (e.g., "a", "b", "c")'),
19
+ justification: z.string().describe('Brief explanation for the recommended answer'),
20
+ })),
21
+ });
22
+ class AISDKExtractor {
54
23
  logger;
24
+ model;
55
25
  constructor(logger) {
56
- const apiKey = process.env.OPENAI_API_KEY;
26
+ this.logger = logger || new Logger({ debug: false, prefix: '[AISDKExtractor]' });
27
+ // Determine which provider to use based on environment variables
28
+ // Priority: Anthropic (if ANTHROPIC_BASE_URL is set) > OpenAI
29
+ const apiKey = process.env.ANTHROPIC_AUTH_TOKEN
30
+ || process.env.ANTHROPIC_API_KEY
31
+ || process.env.OPENAI_API_KEY;
57
32
  if (!apiKey) {
58
- throw new Error('OPENAI_API_KEY environment variable is required for structured extraction');
33
+ throw new Error('Missing API key for structured extraction. Ensure the LLM gateway is configured.');
59
34
  }
60
- this.client = new OpenAI({ apiKey });
61
- this.logger = logger || new Logger({ debug: false, prefix: '[OpenAIExtractor]' });
35
+ const baseURL = process.env.ANTHROPIC_BASE_URL || process.env.OPENAI_BASE_URL;
36
+ const modelName = 'claude-haiku-4-5';
37
+ this.model = anthropic(modelName);
38
+ this.logger.debug('Using Anthropic provider for structured extraction', { modelName, baseURL });
62
39
  }
63
40
  async extractQuestions(researchContent) {
64
41
  this.logger.debug('Extracting questions from research content', {
65
42
  contentLength: researchContent.length,
66
43
  });
67
- const completion = await this.client.chat.completions.create({
68
- model: 'gpt-4o-mini',
69
- messages: [
70
- {
71
- role: 'system',
72
- content: 'Extract the research questions from the provided markdown. Return a JSON object matching the schema.',
73
- },
74
- {
75
- role: 'user',
76
- content: researchContent,
77
- },
78
- ],
79
- response_format: {
80
- type: 'json_schema',
81
- json_schema: {
82
- name: 'questions',
83
- strict: true,
84
- schema: questionsOnlySchema,
85
- },
86
- },
44
+ const { object } = await generateObject({
45
+ model: this.model,
46
+ schema: questionsOnlySchema,
47
+ schemaName: 'ResearchQuestions',
48
+ schemaDescription: 'Research questions extracted from markdown content',
49
+ system: 'Extract the research questions from the provided markdown. Return a JSON object matching the schema.',
50
+ prompt: researchContent,
87
51
  });
88
- const content = completion.choices[0].message.content;
89
- if (!content) {
90
- throw new Error('No content in OpenAI response');
91
- }
92
- const parsed = JSON.parse(content);
93
52
  this.logger.info('Successfully extracted questions', {
94
- questionCount: parsed.questions.length,
53
+ questionCount: object.questions.length,
95
54
  });
96
- return parsed.questions;
55
+ return object.questions;
97
56
  }
98
57
  async extractQuestionsWithAnswers(researchContent) {
99
58
  this.logger.debug('Extracting questions with recommended answers', {
100
59
  contentLength: researchContent.length,
101
60
  });
102
- const completion = await this.client.chat.completions.create({
103
- model: 'gpt-4o-mini',
104
- messages: [
105
- {
106
- role: 'system',
107
- content: 'Extract the research questions from the markdown and provide recommended answers based on the analysis. For each question, include a recommendedAnswer (the letter: a, b, c, etc.) and a brief justification. Return a JSON object matching the schema.',
108
- },
109
- {
110
- role: 'user',
111
- content: researchContent,
112
- },
113
- ],
114
- response_format: {
115
- type: 'json_schema',
116
- json_schema: {
117
- name: 'questions_with_answers',
118
- strict: true,
119
- schema: questionsWithAnswersSchema,
120
- },
121
- },
61
+ const { object } = await generateObject({
62
+ model: this.model,
63
+ schema: questionsWithAnswersSchema,
64
+ schemaName: 'ResearchQuestionsWithAnswers',
65
+ schemaDescription: 'Research questions with recommended answers extracted from markdown',
66
+ system: 'Extract the research questions from the markdown and provide recommended answers based on the analysis. For each question, include a recommendedAnswer (the letter: a, b, c, etc.) and a brief justification. Return a JSON object matching the schema.',
67
+ prompt: researchContent,
122
68
  });
123
- const content = completion.choices[0].message.content;
124
- if (!content) {
125
- throw new Error('No content in OpenAI response');
126
- }
127
- const parsed = JSON.parse(content);
128
69
  this.logger.info('Successfully extracted questions with answers', {
129
- questionCount: parsed.questions.length,
70
+ questionCount: object.questions.length,
130
71
  });
131
- return parsed.questions;
72
+ return object.questions;
132
73
  }
133
74
  }
134
75
 
135
- export { OpenAIExtractor };
76
+ export { AISDKExtractor };
136
77
  //# sourceMappingURL=structured-extraction.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"structured-extraction.js","sources":["../../src/structured-extraction.ts"],"sourcesContent":["import OpenAI from 'openai';\nimport { Logger } from './utils/logger.js';\n\nexport interface ExtractedQuestion {\n id: string;\n question: string;\n options: string[];\n}\n\nexport interface ExtractedQuestionWithAnswer extends ExtractedQuestion {\n recommendedAnswer: string;\n justification: string;\n}\n\nconst questionsOnlySchema = {\n type: 'object',\n properties: {\n questions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n question: { type: 'string' },\n options: {\n type: 'array',\n items: { type: 'string' }\n }\n },\n required: ['id', 'question', 'options'],\n additionalProperties: false\n }\n }\n },\n required: ['questions'],\n additionalProperties: false\n};\n\nconst questionsWithAnswersSchema = {\n type: 'object',\n properties: {\n questions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n question: { type: 'string' },\n options: {\n type: 'array',\n items: { type: 'string' }\n },\n recommendedAnswer: { type: 'string' },\n justification: { type: 'string' }\n },\n required: ['id', 'question', 'options', 'recommendedAnswer', 'justification'],\n additionalProperties: false\n }\n }\n },\n required: ['questions'],\n additionalProperties: false\n};\n\nexport interface StructuredExtractor {\n extractQuestions(researchContent: string): Promise<ExtractedQuestion[]>;\n extractQuestionsWithAnswers(researchContent: string): Promise<ExtractedQuestionWithAnswer[]>;\n}\n\nexport class OpenAIExtractor implements StructuredExtractor {\n private client: OpenAI;\n private logger: Logger;\n\n constructor(logger?: Logger) {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error('OPENAI_API_KEY environment variable is required for structured extraction');\n }\n \n this.client = new OpenAI({ apiKey });\n this.logger = logger || new Logger({ debug: false, prefix: '[OpenAIExtractor]' });\n }\n\n async extractQuestions(researchContent: string): Promise<ExtractedQuestion[]> {\n this.logger.debug('Extracting questions from research content', {\n contentLength: researchContent.length,\n });\n\n const completion = await this.client.chat.completions.create({\n model: 'gpt-4o-mini',\n messages: [\n {\n role: 'system',\n content: 'Extract the research questions from the provided markdown. Return a JSON object matching the schema.',\n },\n {\n role: 'user',\n content: researchContent,\n },\n ],\n response_format: {\n type: 'json_schema',\n json_schema: {\n name: 'questions',\n strict: true,\n schema: questionsOnlySchema,\n },\n },\n });\n\n const content = completion.choices[0].message.content;\n if (!content) {\n throw new Error('No content in OpenAI response');\n }\n\n const parsed = JSON.parse(content) as { questions: ExtractedQuestion[] };\n \n this.logger.info('Successfully extracted questions', {\n questionCount: parsed.questions.length,\n });\n\n return parsed.questions;\n }\n\n async extractQuestionsWithAnswers(\n researchContent: string,\n ): Promise<ExtractedQuestionWithAnswer[]> {\n this.logger.debug('Extracting questions with recommended answers', {\n contentLength: researchContent.length,\n });\n\n const completion = await this.client.chat.completions.create({\n model: 'gpt-4o-mini',\n messages: [\n {\n role: 'system',\n content: 'Extract the research questions from the markdown and provide recommended answers based on the analysis. For each question, include a recommendedAnswer (the letter: a, b, c, etc.) and a brief justification. Return a JSON object matching the schema.',\n },\n {\n role: 'user',\n content: researchContent,\n },\n ],\n response_format: {\n type: 'json_schema',\n json_schema: {\n name: 'questions_with_answers',\n strict: true,\n schema: questionsWithAnswersSchema,\n },\n },\n });\n\n const content = completion.choices[0].message.content;\n if (!content) {\n throw new Error('No content in OpenAI response');\n }\n\n const parsed = JSON.parse(content) as { questions: ExtractedQuestionWithAnswer[] };\n \n this.logger.info('Successfully extracted questions with answers', {\n questionCount: parsed.questions.length,\n });\n\n return parsed.questions;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"structured-extraction.js","sources":["../../src/structured-extraction.ts"],"sourcesContent":["import { generateObject } from 'ai';\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { z } from 'zod';\nimport { Logger } from './utils/logger.js';\n\nexport interface ExtractedQuestion {\n id: string;\n question: string;\n options: string[];\n}\n\nexport interface ExtractedQuestionWithAnswer extends ExtractedQuestion {\n recommendedAnswer: string;\n justification: string;\n}\n\nconst questionsOnlySchema = z.object({\n questions: z.array(\n z.object({\n id: z.string(),\n question: z.string(),\n options: z.array(z.string()),\n })\n ),\n});\n\nconst questionsWithAnswersSchema = z.object({\n questions: z.array(\n z.object({\n id: z.string(),\n question: z.string(),\n options: z.array(z.string()),\n recommendedAnswer: z.string().describe('The letter of the recommended option (e.g., \"a\", \"b\", \"c\")'),\n justification: z.string().describe('Brief explanation for the recommended answer'),\n })\n ),\n});\n\nexport interface StructuredExtractor {\n extractQuestions(researchContent: string): Promise<ExtractedQuestion[]>;\n extractQuestionsWithAnswers(researchContent: string): Promise<ExtractedQuestionWithAnswer[]>;\n}\n\nexport class AISDKExtractor implements StructuredExtractor {\n private logger: Logger;\n private model: any;\n\n constructor(logger?: Logger) {\n this.logger = logger || new Logger({ debug: false, prefix: '[AISDKExtractor]' });\n\n // Determine which provider to use based on environment variables\n // Priority: Anthropic (if ANTHROPIC_BASE_URL is set) > OpenAI\n const apiKey = process.env.ANTHROPIC_AUTH_TOKEN\n || process.env.ANTHROPIC_API_KEY\n || process.env.OPENAI_API_KEY;\n\n if (!apiKey) {\n throw new Error('Missing API key for structured extraction. Ensure the LLM gateway is configured.');\n }\n\n const baseURL = process.env.ANTHROPIC_BASE_URL || process.env.OPENAI_BASE_URL;\n const modelName = 'claude-haiku-4-5';\n this.model = anthropic(modelName);\n this.logger.debug('Using Anthropic provider for structured extraction', { modelName, baseURL });\n }\n\n async extractQuestions(researchContent: string): Promise<ExtractedQuestion[]> {\n this.logger.debug('Extracting questions from research content', {\n contentLength: researchContent.length,\n });\n\n const { object } = await generateObject({\n model: this.model,\n schema: questionsOnlySchema,\n schemaName: 'ResearchQuestions',\n schemaDescription: 'Research questions extracted from markdown content',\n system: 'Extract the research questions from the provided markdown. Return a JSON object matching the schema.',\n prompt: researchContent,\n });\n\n this.logger.info('Successfully extracted questions', {\n questionCount: object.questions.length,\n });\n\n return object.questions;\n }\n\n async extractQuestionsWithAnswers(\n researchContent: string,\n ): Promise<ExtractedQuestionWithAnswer[]> {\n this.logger.debug('Extracting questions with recommended answers', {\n contentLength: researchContent.length,\n });\n\n const { object } = await generateObject({\n model: this.model,\n schema: questionsWithAnswersSchema,\n schemaName: 'ResearchQuestionsWithAnswers',\n schemaDescription: 'Research questions with recommended answers extracted from markdown',\n system: 'Extract the research questions from the markdown and provide recommended answers based on the analysis. For each question, include a recommendedAnswer (the letter: a, b, c, etc.) and a brief justification. Return a JSON object matching the schema.',\n prompt: researchContent,\n });\n\n this.logger.info('Successfully extracted questions with answers', {\n questionCount: object.questions.length,\n });\n\n return object.questions;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { WorkflowDefinition } from './types.js';
2
+ export declare const TASK_WORKFLOW: WorkflowDefinition;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/workflow/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAUrD,eAAO,MAAM,aAAa,EAAE,kBA+B3B,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { researchStep } from './steps/research.js';
2
+ import { planStep } from './steps/plan.js';
3
+ import { buildStep } from './steps/build.js';
4
+
5
+ const MODELS = {
6
+ SONNET: "claude-sonnet-4-5",
7
+ HAIKU: "claude-haiku-4-5",
8
+ };
9
+ const TASK_WORKFLOW = [
10
+ {
11
+ id: 'research',
12
+ name: 'Research',
13
+ agent: 'research',
14
+ model: MODELS.HAIKU,
15
+ permissionMode: 'plan',
16
+ commit: true,
17
+ push: true,
18
+ run: researchStep,
19
+ },
20
+ {
21
+ id: 'plan',
22
+ name: 'Plan',
23
+ agent: 'planning',
24
+ model: MODELS.SONNET,
25
+ permissionMode: 'plan',
26
+ commit: true,
27
+ push: true,
28
+ run: planStep,
29
+ },
30
+ {
31
+ id: 'build',
32
+ name: 'Build',
33
+ agent: 'execution',
34
+ model: MODELS.SONNET,
35
+ permissionMode: 'acceptEdits',
36
+ commit: true,
37
+ push: true,
38
+ run: buildStep,
39
+ },
40
+ ];
41
+
42
+ export { TASK_WORKFLOW };
43
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sources":["../../../src/workflow/config.ts"],"sourcesContent":["import type { WorkflowDefinition } from './types.js';\nimport { researchStep } from './steps/research.js';\nimport { planStep } from './steps/plan.js';\nimport { buildStep } from './steps/build.js';\n\nconst MODELS = {\n SONNET: \"claude-sonnet-4-5\",\n HAIKU: \"claude-haiku-4-5\",\n}\n\nexport const TASK_WORKFLOW: WorkflowDefinition = [\n {\n id: 'research',\n name: 'Research',\n agent: 'research',\n model: MODELS.HAIKU,\n permissionMode: 'plan',\n commit: true,\n push: true,\n run: researchStep,\n },\n {\n id: 'plan',\n name: 'Plan',\n agent: 'planning',\n model: MODELS.SONNET,\n permissionMode: 'plan',\n commit: true,\n push: true,\n run: planStep,\n },\n {\n id: 'build',\n name: 'Build',\n agent: 'execution',\n model: MODELS.SONNET,\n permissionMode: 'acceptEdits',\n commit: true,\n push: true,\n run: buildStep,\n },\n];\n"],"names":[],"mappings":";;;;AAKA,MAAM,MAAM,GAAG;AACX,IAAA,MAAM,EAAE,mBAAmB;AAC3B,IAAA,KAAK,EAAE,kBAAkB;CAC5B;AAEM,MAAM,aAAa,GAAuB;AAC7C,IAAA;AACI,QAAA,EAAE,EAAE,UAAU;AACd,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE,MAAM,CAAC,KAAK;AACnB,QAAA,cAAc,EAAE,MAAM;AACtB,QAAA,MAAM,EAAE,IAAI;AACZ,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,GAAG,EAAE,YAAY;AACpB,KAAA;AACD,IAAA;AACI,QAAA,EAAE,EAAE,MAAM;AACV,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE,MAAM,CAAC,MAAM;AACpB,QAAA,cAAc,EAAE,MAAM;AACtB,QAAA,MAAM,EAAE,IAAI;AACZ,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,GAAG,EAAE,QAAQ;AAChB,KAAA;AACD,IAAA;AACI,QAAA,EAAE,EAAE,OAAO;AACX,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,WAAW;QAClB,KAAK,EAAE,MAAM,CAAC,MAAM;AACpB,QAAA,cAAc,EAAE,aAAa;AAC7B,QAAA,MAAM,EAAE,IAAI;AACZ,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,GAAG,EAAE,SAAS;AACjB,KAAA;;;;;"}
@@ -0,0 +1,3 @@
1
+ import type { WorkflowStepRunner } from '../types.js';
2
+ export declare const buildStep: WorkflowStepRunner;
3
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../../src/workflow/steps/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,eAAO,MAAM,SAAS,EAAE,kBAgFvB,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { query } from '@anthropic-ai/claude-agent-sdk';
2
+ import { EXECUTION_SYSTEM_PROMPT } from '../../agents/execution.js';
3
+ import { PermissionMode } from '../../types.js';
4
+ import { finalizeStepGitActions } from '../utils.js';
5
+
6
+ const buildStep = async ({ step, context }) => {
7
+ const { task, cwd, options, logger, promptBuilder, adapter, mcpServers, gitManager, emitEvent, } = context;
8
+ const stepLogger = logger.child('BuildStep');
9
+ const latestRun = task.latest_run;
10
+ const prExists = latestRun?.output && typeof latestRun.output === 'object'
11
+ ? latestRun.output.pr_url
12
+ : null;
13
+ if (prExists) {
14
+ stepLogger.info('PR already exists, skipping build phase', { taskId: task.id });
15
+ return { status: 'skipped' };
16
+ }
17
+ stepLogger.info('Starting build phase', { taskId: task.id });
18
+ emitEvent(adapter.createStatusEvent('phase_start', { phase: 'build' }));
19
+ const executionPrompt = await promptBuilder.buildExecutionPrompt(task, cwd);
20
+ const fullPrompt = `${EXECUTION_SYSTEM_PROMPT}\n\n${executionPrompt}`;
21
+ const configuredPermissionMode = options.permissionMode ??
22
+ (typeof step.permissionMode === 'string'
23
+ ? step.permissionMode
24
+ : step.permissionMode) ??
25
+ PermissionMode.ACCEPT_EDITS;
26
+ const baseOptions = {
27
+ model: step.model,
28
+ cwd,
29
+ permissionMode: configuredPermissionMode,
30
+ settingSources: ['local'],
31
+ mcpServers,
32
+ };
33
+ const response = query({
34
+ prompt: fullPrompt,
35
+ options: { ...baseOptions, ...(options.queryOverrides || {}) },
36
+ });
37
+ for await (const message of response) {
38
+ emitEvent(adapter.createRawSDKEvent(message));
39
+ const transformed = adapter.transform(message);
40
+ if (transformed) {
41
+ emitEvent(transformed);
42
+ }
43
+ }
44
+ const hasChanges = await gitManager.hasChanges();
45
+ context.stepResults[step.id] = { commitCreated: false };
46
+ if (!hasChanges) {
47
+ stepLogger.warn('No changes to commit in build phase', { taskId: task.id });
48
+ emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));
49
+ return { status: 'completed' };
50
+ }
51
+ await gitManager.addFiles(['.']);
52
+ const commitCreated = await finalizeStepGitActions(context, step, {
53
+ commitMessage: `Implementation for ${task.title}`,
54
+ });
55
+ context.stepResults[step.id] = { commitCreated };
56
+ if (!commitCreated) {
57
+ stepLogger.warn('No commit created during build step', { taskId: task.id });
58
+ }
59
+ emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));
60
+ return { status: 'completed' };
61
+ };
62
+
63
+ export { buildStep };
64
+ //# sourceMappingURL=build.js.map
@@ -0,0 +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';\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 };\n\n const response = query({\n prompt: fullPrompt,\n options: { ...baseOptions, ...(options.queryOverrides || {}) },\n });\n\n for await (const message of response) {\n emitEvent(adapter.createRawSDKEvent(message));\n const transformed = adapter.transform(message);\n if (transformed) {\n emitEvent(transformed);\n }\n }\n\n const hasChanges = await gitManager.hasChanges();\n context.stepResults[step.id] = { commitCreated: false };\n if (!hasChanges) {\n stepLogger.warn('No changes to commit in build phase', { taskId: task.id });\n emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));\n return { status: 'completed' };\n }\n\n await gitManager.addFiles(['.']);\n const commitCreated = await finalizeStepGitActions(context, step, {\n commitMessage: `Implementation for ${task.title}`,\n });\n context.stepResults[step.id] = { commitCreated };\n\n if (!commitCreated) {\n stepLogger.warn('No commit created during build step', { taskId: task.id });\n }\n\n emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));\n return { status: 'completed' };\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { WorkflowStepRunner } from '../types.js';
2
+ export declare const planStep: WorkflowStepRunner;
3
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +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;AAGtD,eAAO,MAAM,QAAQ,EAAE,kBA0GtB,CAAC"}
@@ -0,0 +1,86 @@
1
+ import { query } from '@anthropic-ai/claude-agent-sdk';
2
+ import { PLANNING_SYSTEM_PROMPT } from '../../agents/planning.js';
3
+ import { finalizeStepGitActions } from '../utils.js';
4
+
5
+ const planStep = async ({ step, context }) => {
6
+ const { task, cwd, isCloudMode, options, logger, fileManager, gitManager, promptBuilder, adapter, mcpServers, emitEvent, } = context;
7
+ const stepLogger = logger.child('PlanStep');
8
+ const existingPlan = await fileManager.readPlan(task.id);
9
+ if (existingPlan) {
10
+ stepLogger.info('Plan already exists, skipping step', { taskId: task.id });
11
+ return { status: 'skipped' };
12
+ }
13
+ const questionsData = await fileManager.readQuestions(task.id);
14
+ if (!questionsData || !questionsData.answered) {
15
+ stepLogger.info('Waiting for answered research questions', { taskId: task.id });
16
+ emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'research_questions' }));
17
+ return { status: 'skipped', halt: true };
18
+ }
19
+ stepLogger.info('Starting planning phase', { taskId: task.id });
20
+ emitEvent(adapter.createStatusEvent('phase_start', { phase: 'planning' }));
21
+ const researchContent = await fileManager.readResearch(task.id);
22
+ let researchContext = '';
23
+ if (researchContent) {
24
+ researchContext += `## Research Analysis\n\n${researchContent}\n\n`;
25
+ }
26
+ researchContext += `## Implementation Decisions\n\n`;
27
+ for (const question of questionsData.questions) {
28
+ const answer = questionsData.answers?.find((a) => a.questionId === question.id);
29
+ researchContext += `### ${question.question}\n\n`;
30
+ if (answer) {
31
+ researchContext += `**Selected:** ${answer.selectedOption}\n`;
32
+ if (answer.customInput) {
33
+ researchContext += `**Details:** ${answer.customInput}\n`;
34
+ }
35
+ }
36
+ else {
37
+ researchContext += `**Selected:** Not answered\n`;
38
+ }
39
+ researchContext += `\n`;
40
+ }
41
+ const planningPrompt = await promptBuilder.buildPlanningPrompt(task, cwd);
42
+ const fullPrompt = `${PLANNING_SYSTEM_PROMPT}\n\n${planningPrompt}\n\n${researchContext}`;
43
+ const baseOptions = {
44
+ model: step.model,
45
+ cwd,
46
+ permissionMode: 'plan',
47
+ settingSources: ['local'],
48
+ mcpServers,
49
+ };
50
+ const response = query({
51
+ prompt: fullPrompt,
52
+ options: { ...baseOptions, ...(options.queryOverrides || {}) },
53
+ });
54
+ let planContent = '';
55
+ for await (const message of response) {
56
+ emitEvent(adapter.createRawSDKEvent(message));
57
+ const transformed = adapter.transform(message);
58
+ if (transformed) {
59
+ emitEvent(transformed);
60
+ }
61
+ if (message.type === 'assistant' && message.message?.content) {
62
+ for (const c of message.message.content) {
63
+ if (c.type === 'text' && c.text) {
64
+ planContent += `${c.text}\n`;
65
+ }
66
+ }
67
+ }
68
+ }
69
+ if (planContent.trim()) {
70
+ await fileManager.writePlan(task.id, planContent.trim());
71
+ stepLogger.info('Plan completed', { taskId: task.id });
72
+ }
73
+ await gitManager.addAllPostHogFiles();
74
+ await finalizeStepGitActions(context, step, {
75
+ commitMessage: `Planning phase for ${task.title}`,
76
+ });
77
+ if (!isCloudMode) {
78
+ emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'planning' }));
79
+ return { status: 'completed', halt: true };
80
+ }
81
+ emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'planning' }));
82
+ return { status: 'completed' };
83
+ };
84
+
85
+ export { planStep };
86
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sources":["../../../../src/workflow/steps/plan.ts"],"sourcesContent":["import { query } from '@anthropic-ai/claude-agent-sdk';\nimport { PLANNING_SYSTEM_PROMPT } from '../../agents/planning.js';\nimport type { WorkflowStepRunner } from '../types.js';\nimport { finalizeStepGitActions } from '../utils.js';\n\nexport const planStep: WorkflowStepRunner = async ({ step, context }) => {\n const {\n task,\n cwd,\n isCloudMode,\n options,\n logger,\n fileManager,\n gitManager,\n promptBuilder,\n adapter,\n mcpServers,\n emitEvent,\n } = context;\n\n const stepLogger = logger.child('PlanStep');\n\n const existingPlan = await fileManager.readPlan(task.id);\n if (existingPlan) {\n stepLogger.info('Plan already exists, skipping step', { taskId: task.id });\n return { status: 'skipped' };\n }\n\n const questionsData = await fileManager.readQuestions(task.id);\n if (!questionsData || !questionsData.answered) {\n stepLogger.info('Waiting for answered research questions', { taskId: task.id });\n emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'research_questions' }));\n return { status: 'skipped', halt: true };\n }\n\n stepLogger.info('Starting planning phase', { taskId: task.id });\n emitEvent(adapter.createStatusEvent('phase_start', { phase: 'planning' }));\n\n const researchContent = await fileManager.readResearch(task.id);\n let researchContext = '';\n if (researchContent) {\n researchContext += `## Research Analysis\\n\\n${researchContent}\\n\\n`;\n }\n\n researchContext += `## Implementation Decisions\\n\\n`;\n for (const question of questionsData.questions) {\n const answer = questionsData.answers?.find(\n (a: any) => a.questionId === question.id\n );\n\n researchContext += `### ${question.question}\\n\\n`;\n if (answer) {\n researchContext += `**Selected:** ${answer.selectedOption}\\n`;\n if (answer.customInput) {\n researchContext += `**Details:** ${answer.customInput}\\n`;\n }\n } else {\n researchContext += `**Selected:** Not answered\\n`;\n }\n researchContext += `\\n`;\n }\n\n const planningPrompt = await promptBuilder.buildPlanningPrompt(task, cwd);\n const fullPrompt = `${PLANNING_SYSTEM_PROMPT}\\n\\n${planningPrompt}\\n\\n${researchContext}`;\n\n const baseOptions: Record<string, any> = {\n model: step.model,\n cwd,\n permissionMode: 'plan',\n settingSources: ['local'],\n mcpServers,\n };\n\n const response = query({\n prompt: fullPrompt,\n options: { ...baseOptions, ...(options.queryOverrides || {}) },\n });\n\n let planContent = '';\n for await (const message of response) {\n emitEvent(adapter.createRawSDKEvent(message));\n const transformed = adapter.transform(message);\n if (transformed) {\n emitEvent(transformed);\n }\n if (message.type === 'assistant' && message.message?.content) {\n for (const c of message.message.content) {\n if (c.type === 'text' && c.text) {\n planContent += `${c.text}\\n`;\n }\n }\n }\n }\n\n if (planContent.trim()) {\n await fileManager.writePlan(task.id, planContent.trim());\n stepLogger.info('Plan completed', { taskId: task.id });\n }\n\n await gitManager.addAllPostHogFiles();\n await finalizeStepGitActions(context, step, {\n commitMessage: `Planning phase for ${task.title}`,\n });\n\n if (!isCloudMode) {\n emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'planning' }));\n return { status: 'completed', halt: true };\n }\n\n emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'planning' }));\n return { status: 'completed' };\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { WorkflowStepRunner } from '../types.js';
2
+ export declare const researchStep: WorkflowStepRunner;
3
+ //# sourceMappingURL=research.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../../../src/workflow/steps/research.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,eAAO,MAAM,YAAY,EAAE,kBAqJ1B,CAAC"}
@@ -0,0 +1,124 @@
1
+ import { query } from '@anthropic-ai/claude-agent-sdk';
2
+ import { RESEARCH_SYSTEM_PROMPT } from '../../agents/research.js';
3
+ import { finalizeStepGitActions } from '../utils.js';
4
+
5
+ const researchStep = async ({ step, context }) => {
6
+ const { task, cwd, isCloudMode, options, logger, fileManager, gitManager, promptBuilder, adapter, mcpServers, extractor, emitEvent, } = context;
7
+ const stepLogger = logger.child('ResearchStep');
8
+ const existingResearch = await fileManager.readResearch(task.id);
9
+ if (existingResearch) {
10
+ stepLogger.info('Research already exists, skipping step', { taskId: task.id });
11
+ return { status: 'skipped' };
12
+ }
13
+ stepLogger.info('Starting research phase', { taskId: task.id });
14
+ emitEvent(adapter.createStatusEvent('phase_start', { phase: 'research' }));
15
+ const researchPrompt = await promptBuilder.buildResearchPrompt(task, cwd);
16
+ const fullPrompt = `${RESEARCH_SYSTEM_PROMPT}\n\n${researchPrompt}`;
17
+ const baseOptions = {
18
+ model: step.model,
19
+ cwd,
20
+ permissionMode: 'plan',
21
+ settingSources: ['local'],
22
+ mcpServers,
23
+ };
24
+ const response = query({
25
+ prompt: fullPrompt,
26
+ options: { ...baseOptions, ...(options.queryOverrides || {}) },
27
+ });
28
+ let researchContent = '';
29
+ for await (const message of response) {
30
+ emitEvent(adapter.createRawSDKEvent(message));
31
+ const transformed = adapter.transform(message);
32
+ if (transformed) {
33
+ emitEvent(transformed);
34
+ }
35
+ if (message.type === 'assistant' && message.message?.content) {
36
+ for (const c of message.message.content) {
37
+ if (c.type === 'text' && c.text) {
38
+ researchContent += `${c.text}\n`;
39
+ }
40
+ }
41
+ }
42
+ }
43
+ if (researchContent.trim()) {
44
+ await fileManager.writeResearch(task.id, researchContent.trim());
45
+ stepLogger.info('Research completed', { taskId: task.id });
46
+ }
47
+ await gitManager.addAllPostHogFiles();
48
+ await finalizeStepGitActions(context, step, {
49
+ commitMessage: `Research phase for ${task.title}`,
50
+ });
51
+ if (extractor && researchContent.trim()) {
52
+ try {
53
+ stepLogger.info('Extracting questions from research.md', { taskId: task.id });
54
+ const parsedQuestions = await extractor.extractQuestions(researchContent);
55
+ await fileManager.writeQuestions(task.id, {
56
+ questions: parsedQuestions,
57
+ answered: false,
58
+ answers: null,
59
+ });
60
+ emitEvent({
61
+ type: 'artifact',
62
+ ts: Date.now(),
63
+ kind: 'research_questions',
64
+ content: parsedQuestions,
65
+ });
66
+ stepLogger.info('Questions extracted successfully', {
67
+ taskId: task.id,
68
+ count: parsedQuestions.length,
69
+ });
70
+ }
71
+ catch (error) {
72
+ stepLogger.error('Failed to extract questions', {
73
+ taskId: task.id,
74
+ error: error instanceof Error ? error.message : String(error),
75
+ });
76
+ emitEvent({
77
+ type: 'error',
78
+ ts: Date.now(),
79
+ message: `Failed to extract questions: ${error instanceof Error ? error.message : String(error)}`,
80
+ });
81
+ }
82
+ }
83
+ else if (!extractor) {
84
+ stepLogger.warn('Question extractor not available, skipping question extraction. Ensure LLM gateway is configured.');
85
+ emitEvent({
86
+ type: 'status',
87
+ ts: Date.now(),
88
+ phase: 'extraction_skipped',
89
+ message: 'Question extraction skipped - extractor not configured',
90
+ });
91
+ }
92
+ if (!isCloudMode) {
93
+ emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'research' }));
94
+ return { status: 'completed', halt: true };
95
+ }
96
+ const questionsData = await fileManager.readQuestions(task.id);
97
+ if (questionsData && !questionsData.answered && extractor && researchContent.trim()) {
98
+ const researchQuestions = await extractor.extractQuestionsWithAnswers(researchContent);
99
+ const answers = researchQuestions.map((qa) => ({
100
+ questionId: qa.id,
101
+ selectedOption: qa.recommendedAnswer,
102
+ customInput: qa.justification,
103
+ }));
104
+ await fileManager.writeQuestions(task.id, {
105
+ questions: researchQuestions.map((qa) => ({
106
+ id: qa.id,
107
+ question: qa.question,
108
+ options: qa.options,
109
+ })),
110
+ answered: true,
111
+ answers,
112
+ });
113
+ await gitManager.addAllPostHogFiles();
114
+ await finalizeStepGitActions(context, step, {
115
+ commitMessage: `Answer research questions for ${task.title}`,
116
+ });
117
+ stepLogger.info('Auto-answered research questions', { taskId: task.id });
118
+ }
119
+ emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'research' }));
120
+ return { status: 'completed' };
121
+ };
122
+
123
+ export { researchStep };
124
+ //# sourceMappingURL=research.js.map