@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.
- package/dist/_virtual/_commonjsHelpers.js +6 -0
- package/dist/_virtual/_commonjsHelpers.js.map +1 -0
- package/dist/_virtual/index.js +4 -0
- package/dist/_virtual/index.js.map +1 -0
- package/dist/node_modules/@ai-sdk/anthropic/dist/index.js +1154 -0
- package/dist/node_modules/@ai-sdk/anthropic/dist/index.js.map +1 -0
- package/dist/node_modules/@ai-sdk/provider/dist/index.js +296 -0
- package/dist/node_modules/@ai-sdk/provider/dist/index.js.map +1 -0
- package/dist/node_modules/@ai-sdk/provider-utils/dist/index.js +576 -0
- package/dist/node_modules/@ai-sdk/provider-utils/dist/index.js.map +1 -0
- package/dist/node_modules/@ai-sdk/ui-utils/dist/index.js +741 -0
- package/dist/node_modules/@ai-sdk/ui-utils/dist/index.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/context.js +112 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/context.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/diag.js +123 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/diag.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/metrics.js +62 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/metrics.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/propagation.js +91 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/propagation.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/trace.js +79 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/api/trace.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/context-helpers.js +59 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/context-helpers.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js +99 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/utils.js +31 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/utils.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js +69 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/context/context.js +54 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/context/context.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/context-api.js +22 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/context-api.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/ComponentLogger.js +104 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/ComponentLogger.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/internal/logLevelLogger.js +44 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/internal/logLevelLogger.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/types.js +43 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/types.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/diag-api.js +27 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/diag-api.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js +62 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/internal/semver.js +121 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/internal/semver.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js +167 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js +33 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics-api.js +22 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics-api.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/platform/node/globalThis.js +21 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/platform/node/globalThis.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation/NoopTextMapPropagator.js +35 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation/NoopTextMapPropagator.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation/TextMapPropagator.js +40 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation/TextMapPropagator.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation-api.js +22 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation-api.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NonRecordingSpan.js +70 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NonRecordingSpan.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracer.js +78 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracer.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js +34 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracer.js +55 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracer.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracerProvider.js +56 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracerProvider.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/context-utils.js +76 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/context-utils.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/invalid-span-constants.js +27 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/invalid-span-constants.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/spancontext-utils.js +45 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/spancontext-utils.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/status.js +22 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/status.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/trace_flags.js +25 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/trace_flags.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace-api.js +24 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/trace-api.js.map +1 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/version.js +20 -0
- package/dist/node_modules/@opentelemetry/api/build/esm/version.js.map +1 -0
- package/dist/node_modules/ai/dist/index.js +2870 -0
- package/dist/node_modules/ai/dist/index.js.map +1 -0
- package/dist/node_modules/nanoid/non-secure/index.js +13 -0
- package/dist/node_modules/nanoid/non-secure/index.js.map +1 -0
- package/dist/node_modules/secure-json-parse/index.js +133 -0
- package/dist/node_modules/secure-json-parse/index.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/Options.js +37 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/Options.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/Refs.js +26 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/Refs.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/errorMessages.js +17 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/errorMessages.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js +11 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/index.js +8 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/index.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parseDef.js +66 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parseDef.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/any.js +21 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/any.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/array.js +30 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/array.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js +53 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js +8 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/branded.js +8 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/branded.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/catch.js +8 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/catch.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/date.js +50 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/date.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/default.js +11 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/default.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/effects.js +11 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/effects.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/enum.js +9 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/enum.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js +56 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/literal.js +24 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/literal.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/map.js +30 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/map.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js +19 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/never.js +15 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/never.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/null.js +13 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/null.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js +37 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/number.js +56 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/number.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/object.js +76 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/object.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/optional.js +25 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/optional.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js +24 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/promise.js +8 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/promise.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js +8 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/record.js +65 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/record.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/set.js +24 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/set.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/string.js +350 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/string.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js +36 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js +10 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/union.js +84 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/union.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js +8 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/selectParser.js +110 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/selectParser.js.map +1 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js +90 -0
- package/dist/node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js.map +1 -0
- package/dist/src/agent.d.ts +3 -0
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +93 -291
- package/dist/src/agent.js.map +1 -1
- package/dist/src/agents/planning.d.ts +1 -1
- package/dist/src/agents/planning.d.ts.map +1 -1
- package/dist/src/agents/planning.js +1 -2
- package/dist/src/agents/planning.js.map +1 -1
- package/dist/src/agents/research.d.ts +1 -1
- package/dist/src/agents/research.d.ts.map +1 -1
- package/dist/src/agents/research.js +3 -6
- package/dist/src/agents/research.js.map +1 -1
- package/dist/src/prompt-builder.d.ts.map +1 -1
- package/dist/src/prompt-builder.js +0 -1
- package/dist/src/prompt-builder.js.map +1 -1
- package/dist/src/structured-extraction.d.ts +2 -2
- package/dist/src/structured-extraction.d.ts.map +1 -1
- package/dist/src/structured-extraction.js +51 -110
- package/dist/src/structured-extraction.js.map +1 -1
- package/dist/src/workflow/config.d.ts +3 -0
- package/dist/src/workflow/config.d.ts.map +1 -0
- package/dist/src/workflow/config.js +43 -0
- package/dist/src/workflow/config.js.map +1 -0
- package/dist/src/workflow/steps/build.d.ts +3 -0
- package/dist/src/workflow/steps/build.d.ts.map +1 -0
- package/dist/src/workflow/steps/build.js +64 -0
- package/dist/src/workflow/steps/build.js.map +1 -0
- package/dist/src/workflow/steps/plan.d.ts +3 -0
- package/dist/src/workflow/steps/plan.d.ts.map +1 -0
- package/dist/src/workflow/steps/plan.js +86 -0
- package/dist/src/workflow/steps/plan.js.map +1 -0
- package/dist/src/workflow/steps/research.d.ts +3 -0
- package/dist/src/workflow/steps/research.d.ts.map +1 -0
- package/dist/src/workflow/steps/research.js +124 -0
- package/dist/src/workflow/steps/research.js.map +1 -0
- package/dist/src/workflow/types.d.ts +48 -0
- package/dist/src/workflow/types.d.ts.map +1 -0
- package/dist/src/workflow/utils.d.ts +12 -0
- package/dist/src/workflow/utils.d.ts.map +1 -0
- package/dist/src/workflow/utils.js +38 -0
- package/dist/src/workflow/utils.js.map +1 -0
- package/package.json +5 -2
- package/src/agent.ts +112 -321
- package/src/agents/planning.ts +1 -2
- package/src/agents/research.ts +3 -6
- package/src/prompt-builder.ts +0 -2
- package/src/structured-extraction.ts +58 -115
- package/src/workflow/config.ts +42 -0
- package/src/workflow/steps/build.ts +87 -0
- package/src/workflow/steps/plan.ts +112 -0
- package/src/workflow/steps/research.ts +156 -0
- package/src/workflow/types.ts +53 -0
- package/src/workflow/utils.ts +50 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { generateObject } from 'ai';
|
|
2
|
+
import { anthropic } from '@ai-sdk/anthropic';
|
|
3
|
+
import { z } from 'zod';
|
|
2
4
|
import { Logger } from './utils/logger.js';
|
|
3
5
|
|
|
4
6
|
export interface ExtractedQuestion {
|
|
@@ -12,73 +14,54 @@ export interface ExtractedQuestionWithAnswer extends ExtractedQuestion {
|
|
|
12
14
|
justification: string;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
const questionsOnlySchema = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
additionalProperties: false
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const questionsWithAnswersSchema = {
|
|
40
|
-
type: 'object',
|
|
41
|
-
properties: {
|
|
42
|
-
questions: {
|
|
43
|
-
type: 'array',
|
|
44
|
-
items: {
|
|
45
|
-
type: 'object',
|
|
46
|
-
properties: {
|
|
47
|
-
id: { type: 'string' },
|
|
48
|
-
question: { type: 'string' },
|
|
49
|
-
options: {
|
|
50
|
-
type: 'array',
|
|
51
|
-
items: { type: 'string' }
|
|
52
|
-
},
|
|
53
|
-
recommendedAnswer: { type: 'string' },
|
|
54
|
-
justification: { type: 'string' }
|
|
55
|
-
},
|
|
56
|
-
required: ['id', 'question', 'options', 'recommendedAnswer', 'justification'],
|
|
57
|
-
additionalProperties: false
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
required: ['questions'],
|
|
62
|
-
additionalProperties: false
|
|
63
|
-
};
|
|
17
|
+
const questionsOnlySchema = z.object({
|
|
18
|
+
questions: z.array(
|
|
19
|
+
z.object({
|
|
20
|
+
id: z.string(),
|
|
21
|
+
question: z.string(),
|
|
22
|
+
options: z.array(z.string()),
|
|
23
|
+
})
|
|
24
|
+
),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const questionsWithAnswersSchema = z.object({
|
|
28
|
+
questions: z.array(
|
|
29
|
+
z.object({
|
|
30
|
+
id: z.string(),
|
|
31
|
+
question: z.string(),
|
|
32
|
+
options: z.array(z.string()),
|
|
33
|
+
recommendedAnswer: z.string().describe('The letter of the recommended option (e.g., "a", "b", "c")'),
|
|
34
|
+
justification: z.string().describe('Brief explanation for the recommended answer'),
|
|
35
|
+
})
|
|
36
|
+
),
|
|
37
|
+
});
|
|
64
38
|
|
|
65
39
|
export interface StructuredExtractor {
|
|
66
40
|
extractQuestions(researchContent: string): Promise<ExtractedQuestion[]>;
|
|
67
41
|
extractQuestionsWithAnswers(researchContent: string): Promise<ExtractedQuestionWithAnswer[]>;
|
|
68
42
|
}
|
|
69
43
|
|
|
70
|
-
export class
|
|
71
|
-
private client: OpenAI;
|
|
44
|
+
export class AISDKExtractor implements StructuredExtractor {
|
|
72
45
|
private logger: Logger;
|
|
46
|
+
private model: any;
|
|
73
47
|
|
|
74
48
|
constructor(logger?: Logger) {
|
|
75
|
-
|
|
49
|
+
this.logger = logger || new Logger({ debug: false, prefix: '[AISDKExtractor]' });
|
|
50
|
+
|
|
51
|
+
// Determine which provider to use based on environment variables
|
|
52
|
+
// Priority: Anthropic (if ANTHROPIC_BASE_URL is set) > OpenAI
|
|
53
|
+
const apiKey = process.env.ANTHROPIC_AUTH_TOKEN
|
|
54
|
+
|| process.env.ANTHROPIC_API_KEY
|
|
55
|
+
|| process.env.OPENAI_API_KEY;
|
|
56
|
+
|
|
76
57
|
if (!apiKey) {
|
|
77
|
-
throw new Error('
|
|
58
|
+
throw new Error('Missing API key for structured extraction. Ensure the LLM gateway is configured.');
|
|
78
59
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
60
|
+
|
|
61
|
+
const baseURL = process.env.ANTHROPIC_BASE_URL || process.env.OPENAI_BASE_URL;
|
|
62
|
+
const modelName = 'claude-haiku-4-5';
|
|
63
|
+
this.model = anthropic(modelName);
|
|
64
|
+
this.logger.debug('Using Anthropic provider for structured extraction', { modelName, baseURL });
|
|
82
65
|
}
|
|
83
66
|
|
|
84
67
|
async extractQuestions(researchContent: string): Promise<ExtractedQuestion[]> {
|
|
@@ -86,40 +69,20 @@ export class OpenAIExtractor implements StructuredExtractor {
|
|
|
86
69
|
contentLength: researchContent.length,
|
|
87
70
|
});
|
|
88
71
|
|
|
89
|
-
const
|
|
90
|
-
model:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
role: 'user',
|
|
98
|
-
content: researchContent,
|
|
99
|
-
},
|
|
100
|
-
],
|
|
101
|
-
response_format: {
|
|
102
|
-
type: 'json_schema',
|
|
103
|
-
json_schema: {
|
|
104
|
-
name: 'questions',
|
|
105
|
-
strict: true,
|
|
106
|
-
schema: questionsOnlySchema,
|
|
107
|
-
},
|
|
108
|
-
},
|
|
72
|
+
const { object } = await generateObject({
|
|
73
|
+
model: this.model,
|
|
74
|
+
schema: questionsOnlySchema,
|
|
75
|
+
schemaName: 'ResearchQuestions',
|
|
76
|
+
schemaDescription: 'Research questions extracted from markdown content',
|
|
77
|
+
system: 'Extract the research questions from the provided markdown. Return a JSON object matching the schema.',
|
|
78
|
+
prompt: researchContent,
|
|
109
79
|
});
|
|
110
80
|
|
|
111
|
-
const content = completion.choices[0].message.content;
|
|
112
|
-
if (!content) {
|
|
113
|
-
throw new Error('No content in OpenAI response');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const parsed = JSON.parse(content) as { questions: ExtractedQuestion[] };
|
|
117
|
-
|
|
118
81
|
this.logger.info('Successfully extracted questions', {
|
|
119
|
-
questionCount:
|
|
82
|
+
questionCount: object.questions.length,
|
|
120
83
|
});
|
|
121
84
|
|
|
122
|
-
return
|
|
85
|
+
return object.questions;
|
|
123
86
|
}
|
|
124
87
|
|
|
125
88
|
async extractQuestionsWithAnswers(
|
|
@@ -129,39 +92,19 @@ export class OpenAIExtractor implements StructuredExtractor {
|
|
|
129
92
|
contentLength: researchContent.length,
|
|
130
93
|
});
|
|
131
94
|
|
|
132
|
-
const
|
|
133
|
-
model:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
role: 'user',
|
|
141
|
-
content: researchContent,
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
response_format: {
|
|
145
|
-
type: 'json_schema',
|
|
146
|
-
json_schema: {
|
|
147
|
-
name: 'questions_with_answers',
|
|
148
|
-
strict: true,
|
|
149
|
-
schema: questionsWithAnswersSchema,
|
|
150
|
-
},
|
|
151
|
-
},
|
|
95
|
+
const { object } = await generateObject({
|
|
96
|
+
model: this.model,
|
|
97
|
+
schema: questionsWithAnswersSchema,
|
|
98
|
+
schemaName: 'ResearchQuestionsWithAnswers',
|
|
99
|
+
schemaDescription: 'Research questions with recommended answers extracted from markdown',
|
|
100
|
+
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.',
|
|
101
|
+
prompt: researchContent,
|
|
152
102
|
});
|
|
153
103
|
|
|
154
|
-
const content = completion.choices[0].message.content;
|
|
155
|
-
if (!content) {
|
|
156
|
-
throw new Error('No content in OpenAI response');
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const parsed = JSON.parse(content) as { questions: ExtractedQuestionWithAnswer[] };
|
|
160
|
-
|
|
161
104
|
this.logger.info('Successfully extracted questions with answers', {
|
|
162
|
-
questionCount:
|
|
105
|
+
questionCount: object.questions.length,
|
|
163
106
|
});
|
|
164
107
|
|
|
165
|
-
return
|
|
108
|
+
return object.questions;
|
|
166
109
|
}
|
|
167
110
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { WorkflowDefinition } from './types.js';
|
|
2
|
+
import { researchStep } from './steps/research.js';
|
|
3
|
+
import { planStep } from './steps/plan.js';
|
|
4
|
+
import { buildStep } from './steps/build.js';
|
|
5
|
+
|
|
6
|
+
const MODELS = {
|
|
7
|
+
SONNET: "claude-sonnet-4-5",
|
|
8
|
+
HAIKU: "claude-haiku-4-5",
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const TASK_WORKFLOW: WorkflowDefinition = [
|
|
12
|
+
{
|
|
13
|
+
id: 'research',
|
|
14
|
+
name: 'Research',
|
|
15
|
+
agent: 'research',
|
|
16
|
+
model: MODELS.HAIKU,
|
|
17
|
+
permissionMode: 'plan',
|
|
18
|
+
commit: true,
|
|
19
|
+
push: true,
|
|
20
|
+
run: researchStep,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 'plan',
|
|
24
|
+
name: 'Plan',
|
|
25
|
+
agent: 'planning',
|
|
26
|
+
model: MODELS.SONNET,
|
|
27
|
+
permissionMode: 'plan',
|
|
28
|
+
commit: true,
|
|
29
|
+
push: true,
|
|
30
|
+
run: planStep,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: 'build',
|
|
34
|
+
name: 'Build',
|
|
35
|
+
agent: 'execution',
|
|
36
|
+
model: MODELS.SONNET,
|
|
37
|
+
permissionMode: 'acceptEdits',
|
|
38
|
+
commit: true,
|
|
39
|
+
push: true,
|
|
40
|
+
run: buildStep,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
@@ -0,0 +1,87 @@
|
|
|
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 type { WorkflowStepRunner } from '../types.js';
|
|
5
|
+
import { finalizeStepGitActions } from '../utils.js';
|
|
6
|
+
|
|
7
|
+
export const buildStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
8
|
+
const {
|
|
9
|
+
task,
|
|
10
|
+
cwd,
|
|
11
|
+
options,
|
|
12
|
+
logger,
|
|
13
|
+
promptBuilder,
|
|
14
|
+
adapter,
|
|
15
|
+
mcpServers,
|
|
16
|
+
gitManager,
|
|
17
|
+
emitEvent,
|
|
18
|
+
} = context;
|
|
19
|
+
|
|
20
|
+
const stepLogger = logger.child('BuildStep');
|
|
21
|
+
|
|
22
|
+
const latestRun = task.latest_run;
|
|
23
|
+
const prExists =
|
|
24
|
+
latestRun?.output && typeof latestRun.output === 'object'
|
|
25
|
+
? (latestRun.output as any).pr_url
|
|
26
|
+
: null;
|
|
27
|
+
|
|
28
|
+
if (prExists) {
|
|
29
|
+
stepLogger.info('PR already exists, skipping build phase', { taskId: task.id });
|
|
30
|
+
return { status: 'skipped' };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
stepLogger.info('Starting build phase', { taskId: task.id });
|
|
34
|
+
emitEvent(adapter.createStatusEvent('phase_start', { phase: 'build' }));
|
|
35
|
+
|
|
36
|
+
const executionPrompt = await promptBuilder.buildExecutionPrompt(task, cwd);
|
|
37
|
+
const fullPrompt = `${EXECUTION_SYSTEM_PROMPT}\n\n${executionPrompt}`;
|
|
38
|
+
|
|
39
|
+
const configuredPermissionMode =
|
|
40
|
+
options.permissionMode ??
|
|
41
|
+
(typeof step.permissionMode === 'string'
|
|
42
|
+
? (step.permissionMode as PermissionMode)
|
|
43
|
+
: step.permissionMode) ??
|
|
44
|
+
PermissionMode.ACCEPT_EDITS;
|
|
45
|
+
|
|
46
|
+
const baseOptions: Record<string, any> = {
|
|
47
|
+
model: step.model,
|
|
48
|
+
cwd,
|
|
49
|
+
permissionMode: configuredPermissionMode,
|
|
50
|
+
settingSources: ['local'],
|
|
51
|
+
mcpServers,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const response = query({
|
|
55
|
+
prompt: fullPrompt,
|
|
56
|
+
options: { ...baseOptions, ...(options.queryOverrides || {}) },
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
for await (const message of response) {
|
|
60
|
+
emitEvent(adapter.createRawSDKEvent(message));
|
|
61
|
+
const transformed = adapter.transform(message);
|
|
62
|
+
if (transformed) {
|
|
63
|
+
emitEvent(transformed);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const hasChanges = await gitManager.hasChanges();
|
|
68
|
+
context.stepResults[step.id] = { commitCreated: false };
|
|
69
|
+
if (!hasChanges) {
|
|
70
|
+
stepLogger.warn('No changes to commit in build phase', { taskId: task.id });
|
|
71
|
+
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));
|
|
72
|
+
return { status: 'completed' };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
await gitManager.addFiles(['.']);
|
|
76
|
+
const commitCreated = await finalizeStepGitActions(context, step, {
|
|
77
|
+
commitMessage: `Implementation for ${task.title}`,
|
|
78
|
+
});
|
|
79
|
+
context.stepResults[step.id] = { commitCreated };
|
|
80
|
+
|
|
81
|
+
if (!commitCreated) {
|
|
82
|
+
stepLogger.warn('No commit created during build step', { taskId: task.id });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));
|
|
86
|
+
return { status: 'completed' };
|
|
87
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import { PLANNING_SYSTEM_PROMPT } from '../../agents/planning.js';
|
|
3
|
+
import type { WorkflowStepRunner } from '../types.js';
|
|
4
|
+
import { finalizeStepGitActions } from '../utils.js';
|
|
5
|
+
|
|
6
|
+
export const planStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
7
|
+
const {
|
|
8
|
+
task,
|
|
9
|
+
cwd,
|
|
10
|
+
isCloudMode,
|
|
11
|
+
options,
|
|
12
|
+
logger,
|
|
13
|
+
fileManager,
|
|
14
|
+
gitManager,
|
|
15
|
+
promptBuilder,
|
|
16
|
+
adapter,
|
|
17
|
+
mcpServers,
|
|
18
|
+
emitEvent,
|
|
19
|
+
} = context;
|
|
20
|
+
|
|
21
|
+
const stepLogger = logger.child('PlanStep');
|
|
22
|
+
|
|
23
|
+
const existingPlan = await fileManager.readPlan(task.id);
|
|
24
|
+
if (existingPlan) {
|
|
25
|
+
stepLogger.info('Plan already exists, skipping step', { taskId: task.id });
|
|
26
|
+
return { status: 'skipped' };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const questionsData = await fileManager.readQuestions(task.id);
|
|
30
|
+
if (!questionsData || !questionsData.answered) {
|
|
31
|
+
stepLogger.info('Waiting for answered research questions', { taskId: task.id });
|
|
32
|
+
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'research_questions' }));
|
|
33
|
+
return { status: 'skipped', halt: true };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
stepLogger.info('Starting planning phase', { taskId: task.id });
|
|
37
|
+
emitEvent(adapter.createStatusEvent('phase_start', { phase: 'planning' }));
|
|
38
|
+
|
|
39
|
+
const researchContent = await fileManager.readResearch(task.id);
|
|
40
|
+
let researchContext = '';
|
|
41
|
+
if (researchContent) {
|
|
42
|
+
researchContext += `## Research Analysis\n\n${researchContent}\n\n`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
researchContext += `## Implementation Decisions\n\n`;
|
|
46
|
+
for (const question of questionsData.questions) {
|
|
47
|
+
const answer = questionsData.answers?.find(
|
|
48
|
+
(a: any) => a.questionId === question.id
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
researchContext += `### ${question.question}\n\n`;
|
|
52
|
+
if (answer) {
|
|
53
|
+
researchContext += `**Selected:** ${answer.selectedOption}\n`;
|
|
54
|
+
if (answer.customInput) {
|
|
55
|
+
researchContext += `**Details:** ${answer.customInput}\n`;
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
researchContext += `**Selected:** Not answered\n`;
|
|
59
|
+
}
|
|
60
|
+
researchContext += `\n`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const planningPrompt = await promptBuilder.buildPlanningPrompt(task, cwd);
|
|
64
|
+
const fullPrompt = `${PLANNING_SYSTEM_PROMPT}\n\n${planningPrompt}\n\n${researchContext}`;
|
|
65
|
+
|
|
66
|
+
const baseOptions: Record<string, any> = {
|
|
67
|
+
model: step.model,
|
|
68
|
+
cwd,
|
|
69
|
+
permissionMode: 'plan',
|
|
70
|
+
settingSources: ['local'],
|
|
71
|
+
mcpServers,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const response = query({
|
|
75
|
+
prompt: fullPrompt,
|
|
76
|
+
options: { ...baseOptions, ...(options.queryOverrides || {}) },
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
let planContent = '';
|
|
80
|
+
for await (const message of response) {
|
|
81
|
+
emitEvent(adapter.createRawSDKEvent(message));
|
|
82
|
+
const transformed = adapter.transform(message);
|
|
83
|
+
if (transformed) {
|
|
84
|
+
emitEvent(transformed);
|
|
85
|
+
}
|
|
86
|
+
if (message.type === 'assistant' && message.message?.content) {
|
|
87
|
+
for (const c of message.message.content) {
|
|
88
|
+
if (c.type === 'text' && c.text) {
|
|
89
|
+
planContent += `${c.text}\n`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (planContent.trim()) {
|
|
96
|
+
await fileManager.writePlan(task.id, planContent.trim());
|
|
97
|
+
stepLogger.info('Plan completed', { taskId: task.id });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
await gitManager.addAllPostHogFiles();
|
|
101
|
+
await finalizeStepGitActions(context, step, {
|
|
102
|
+
commitMessage: `Planning phase for ${task.title}`,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (!isCloudMode) {
|
|
106
|
+
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'planning' }));
|
|
107
|
+
return { status: 'completed', halt: true };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'planning' }));
|
|
111
|
+
return { status: 'completed' };
|
|
112
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import { RESEARCH_SYSTEM_PROMPT } from '../../agents/research.js';
|
|
3
|
+
import type { ExtractedQuestionWithAnswer } from '../../structured-extraction.js';
|
|
4
|
+
import type { WorkflowStepRunner } from '../types.js';
|
|
5
|
+
import { finalizeStepGitActions } from '../utils.js';
|
|
6
|
+
|
|
7
|
+
export const researchStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
8
|
+
const {
|
|
9
|
+
task,
|
|
10
|
+
cwd,
|
|
11
|
+
isCloudMode,
|
|
12
|
+
options,
|
|
13
|
+
logger,
|
|
14
|
+
fileManager,
|
|
15
|
+
gitManager,
|
|
16
|
+
promptBuilder,
|
|
17
|
+
adapter,
|
|
18
|
+
mcpServers,
|
|
19
|
+
extractor,
|
|
20
|
+
emitEvent,
|
|
21
|
+
} = context;
|
|
22
|
+
|
|
23
|
+
const stepLogger = logger.child('ResearchStep');
|
|
24
|
+
|
|
25
|
+
const existingResearch = await fileManager.readResearch(task.id);
|
|
26
|
+
if (existingResearch) {
|
|
27
|
+
stepLogger.info('Research already exists, skipping step', { taskId: task.id });
|
|
28
|
+
return { status: 'skipped' };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
stepLogger.info('Starting research phase', { taskId: task.id });
|
|
32
|
+
emitEvent(adapter.createStatusEvent('phase_start', { phase: 'research' }));
|
|
33
|
+
|
|
34
|
+
const researchPrompt = await promptBuilder.buildResearchPrompt(task, cwd);
|
|
35
|
+
const fullPrompt = `${RESEARCH_SYSTEM_PROMPT}\n\n${researchPrompt}`;
|
|
36
|
+
|
|
37
|
+
const baseOptions: Record<string, any> = {
|
|
38
|
+
model: step.model,
|
|
39
|
+
cwd,
|
|
40
|
+
permissionMode: 'plan',
|
|
41
|
+
settingSources: ['local'],
|
|
42
|
+
mcpServers,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const response = query({
|
|
46
|
+
prompt: fullPrompt,
|
|
47
|
+
options: { ...baseOptions, ...(options.queryOverrides || {}) },
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
let researchContent = '';
|
|
51
|
+
for await (const message of response) {
|
|
52
|
+
emitEvent(adapter.createRawSDKEvent(message));
|
|
53
|
+
const transformed = adapter.transform(message);
|
|
54
|
+
if (transformed) {
|
|
55
|
+
emitEvent(transformed);
|
|
56
|
+
}
|
|
57
|
+
if (message.type === 'assistant' && message.message?.content) {
|
|
58
|
+
for (const c of message.message.content) {
|
|
59
|
+
if (c.type === 'text' && c.text) {
|
|
60
|
+
researchContent += `${c.text}\n`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (researchContent.trim()) {
|
|
67
|
+
await fileManager.writeResearch(task.id, researchContent.trim());
|
|
68
|
+
stepLogger.info('Research completed', { taskId: task.id });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
await gitManager.addAllPostHogFiles();
|
|
72
|
+
await finalizeStepGitActions(context, step, {
|
|
73
|
+
commitMessage: `Research phase for ${task.title}`,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (extractor && researchContent.trim()) {
|
|
77
|
+
try {
|
|
78
|
+
stepLogger.info('Extracting questions from research.md', { taskId: task.id });
|
|
79
|
+
const parsedQuestions = await extractor.extractQuestions(researchContent);
|
|
80
|
+
|
|
81
|
+
await fileManager.writeQuestions(task.id, {
|
|
82
|
+
questions: parsedQuestions,
|
|
83
|
+
answered: false,
|
|
84
|
+
answers: null,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
emitEvent({
|
|
88
|
+
type: 'artifact',
|
|
89
|
+
ts: Date.now(),
|
|
90
|
+
kind: 'research_questions',
|
|
91
|
+
content: parsedQuestions,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
stepLogger.info('Questions extracted successfully', {
|
|
95
|
+
taskId: task.id,
|
|
96
|
+
count: parsedQuestions.length,
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
stepLogger.error('Failed to extract questions', {
|
|
100
|
+
taskId: task.id,
|
|
101
|
+
error: error instanceof Error ? error.message : String(error),
|
|
102
|
+
});
|
|
103
|
+
emitEvent({
|
|
104
|
+
type: 'error',
|
|
105
|
+
ts: Date.now(),
|
|
106
|
+
message: `Failed to extract questions: ${
|
|
107
|
+
error instanceof Error ? error.message : String(error)
|
|
108
|
+
}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
} else if (!extractor) {
|
|
112
|
+
stepLogger.warn(
|
|
113
|
+
'Question extractor not available, skipping question extraction. Ensure LLM gateway is configured.'
|
|
114
|
+
);
|
|
115
|
+
emitEvent({
|
|
116
|
+
type: 'status',
|
|
117
|
+
ts: Date.now(),
|
|
118
|
+
phase: 'extraction_skipped',
|
|
119
|
+
message: 'Question extraction skipped - extractor not configured',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!isCloudMode) {
|
|
124
|
+
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'research' }));
|
|
125
|
+
return { status: 'completed', halt: true };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const questionsData = await fileManager.readQuestions(task.id);
|
|
129
|
+
if (questionsData && !questionsData.answered && extractor && researchContent.trim()) {
|
|
130
|
+
const researchQuestions = await extractor.extractQuestionsWithAnswers(researchContent);
|
|
131
|
+
const answers = (researchQuestions as ExtractedQuestionWithAnswer[]).map((qa) => ({
|
|
132
|
+
questionId: qa.id,
|
|
133
|
+
selectedOption: qa.recommendedAnswer,
|
|
134
|
+
customInput: qa.justification,
|
|
135
|
+
}));
|
|
136
|
+
|
|
137
|
+
await fileManager.writeQuestions(task.id, {
|
|
138
|
+
questions: researchQuestions.map((qa) => ({
|
|
139
|
+
id: qa.id,
|
|
140
|
+
question: qa.question,
|
|
141
|
+
options: qa.options,
|
|
142
|
+
})),
|
|
143
|
+
answered: true,
|
|
144
|
+
answers,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
await gitManager.addAllPostHogFiles();
|
|
148
|
+
await finalizeStepGitActions(context, step, {
|
|
149
|
+
commitMessage: `Answer research questions for ${task.title}`,
|
|
150
|
+
});
|
|
151
|
+
stepLogger.info('Auto-answered research questions', { taskId: task.id });
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'research' }));
|
|
155
|
+
return { status: 'completed' };
|
|
156
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Task, TaskExecutionOptions, PermissionMode } from '../types.js';
|
|
2
|
+
import type { Logger } from '../utils/logger.js';
|
|
3
|
+
import type { PostHogFileManager } from '../file-manager.js';
|
|
4
|
+
import type { GitManager } from '../git-manager.js';
|
|
5
|
+
import type { PromptBuilder } from '../prompt-builder.js';
|
|
6
|
+
import type { TaskProgressReporter } from '../task-progress-reporter.js';
|
|
7
|
+
import type { ProviderAdapter } from '../adapters/types.js';
|
|
8
|
+
import type { PostHogAPIClient } from '../posthog-api.js';
|
|
9
|
+
import type { StructuredExtractor } from '../structured-extraction.js';
|
|
10
|
+
|
|
11
|
+
export interface WorkflowRuntime {
|
|
12
|
+
task: Task;
|
|
13
|
+
taskSlug: string;
|
|
14
|
+
cwd: string;
|
|
15
|
+
isCloudMode: boolean;
|
|
16
|
+
options: TaskExecutionOptions;
|
|
17
|
+
logger: Logger;
|
|
18
|
+
fileManager: PostHogFileManager;
|
|
19
|
+
gitManager: GitManager;
|
|
20
|
+
promptBuilder: PromptBuilder;
|
|
21
|
+
progressReporter: TaskProgressReporter;
|
|
22
|
+
adapter: ProviderAdapter;
|
|
23
|
+
mcpServers?: Record<string, any>;
|
|
24
|
+
posthogAPI?: PostHogAPIClient;
|
|
25
|
+
extractor?: StructuredExtractor;
|
|
26
|
+
emitEvent: (event: any) => void;
|
|
27
|
+
stepResults: Record<string, any>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface WorkflowStepDefinition {
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
agent: string;
|
|
34
|
+
model: string;
|
|
35
|
+
permissionMode?: PermissionMode | string;
|
|
36
|
+
commit?: boolean;
|
|
37
|
+
push?: boolean;
|
|
38
|
+
run: WorkflowStepRunner;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface WorkflowStepRuntime {
|
|
42
|
+
step: WorkflowStepDefinition;
|
|
43
|
+
context: WorkflowRuntime;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface WorkflowStepResult {
|
|
47
|
+
status: 'completed' | 'skipped';
|
|
48
|
+
halt?: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type WorkflowStepRunner = (runtime: WorkflowStepRuntime) => Promise<WorkflowStepResult>;
|
|
52
|
+
|
|
53
|
+
export type WorkflowDefinition = WorkflowStepDefinition[];
|