@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,136 +1,77 @@
|
|
|
1
|
-
import
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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('
|
|
33
|
+
throw new Error('Missing API key for structured extraction. Ensure the LLM gateway is configured.');
|
|
59
34
|
}
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
68
|
-
model:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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:
|
|
53
|
+
questionCount: object.questions.length,
|
|
95
54
|
});
|
|
96
|
-
return
|
|
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
|
|
103
|
-
model:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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:
|
|
70
|
+
questionCount: object.questions.length,
|
|
130
71
|
});
|
|
131
|
-
return
|
|
72
|
+
return object.questions;
|
|
132
73
|
}
|
|
133
74
|
}
|
|
134
75
|
|
|
135
|
-
export {
|
|
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
|
|
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":";;;;;AAgBA,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,SAAS,EAAE,CAAC,CAAC,KAAK,CAChB,CAAC,CAAC,MAAM,CAAC;AACP,QAAA,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;AACd,QAAA,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;AAC7B,KAAA,CAAC,CACH;AACF,CAAA,CAAC;AAEF,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,SAAS,EAAE,CAAC,CAAC,KAAK,CAChB,CAAC,CAAC,MAAM,CAAC;AACP,QAAA,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;AACd,QAAA,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC5B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4DAA4D,CAAC;QACpG,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;AACnF,KAAA,CAAC,CACH;AACF,CAAA,CAAC;MAOW,cAAc,CAAA;AACjB,IAAA,MAAM;AACN,IAAA,KAAK;AAEb,IAAA,WAAA,CAAY,MAAe,EAAA;AACzB,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;;;AAIhF,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;eACtB,OAAO,CAAC,GAAG,CAAC;AACZ,eAAA,OAAO,CAAC,GAAG,CAAC,cAAc;QAE/B,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC;QACrG;AAEA,QAAA,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe;QAC7E,MAAM,SAAS,GAAG,kBAAkB;AACpC,QAAA,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC;AACjC,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oDAAoD,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;IACjG;IAEA,MAAM,gBAAgB,CAAC,eAAuB,EAAA;AAC5C,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE;YAC9D,aAAa,EAAE,eAAe,CAAC,MAAM;AACtC,SAAA,CAAC;AAEF,QAAA,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,cAAc,CAAC;YACtC,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,YAAA,MAAM,EAAE,mBAAmB;AAC3B,YAAA,UAAU,EAAE,mBAAmB;AAC/B,YAAA,iBAAiB,EAAE,oDAAoD;AACvE,YAAA,MAAM,EAAE,sGAAsG;AAC9G,YAAA,MAAM,EAAE,eAAe;AACxB,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,EAAE;AACnD,YAAA,aAAa,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM;AACvC,SAAA,CAAC;QAEF,OAAO,MAAM,CAAC,SAAS;IACzB;IAEA,MAAM,2BAA2B,CAC/B,eAAuB,EAAA;AAEvB,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+CAA+C,EAAE;YACjE,aAAa,EAAE,eAAe,CAAC,MAAM;AACtC,SAAA,CAAC;AAEF,QAAA,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,cAAc,CAAC;YACtC,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,YAAA,MAAM,EAAE,0BAA0B;AAClC,YAAA,UAAU,EAAE,8BAA8B;AAC1C,YAAA,iBAAiB,EAAE,qEAAqE;AACxF,YAAA,MAAM,EAAE,yPAAyP;AACjQ,YAAA,MAAM,EAAE,eAAe;AACxB,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE;AAChE,YAAA,aAAa,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM;AACvC,SAAA,CAAC;QAEF,OAAO,MAAM,CAAC,SAAS;IACzB;AACD;;;;"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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":";;;;AAKO,MAAM,QAAQ,GAAuB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAI;IACpE,MAAM,EACF,IAAI,EACJ,GAAG,EACH,WAAW,EACX,OAAO,EACP,MAAM,EACN,WAAW,EACX,UAAU,EACV,aAAa,EACb,OAAO,EACP,UAAU,EACV,SAAS,GACZ,GAAG,OAAO;IAEX,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;IAE3C,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACxD,IAAI,YAAY,EAAE;AACd,QAAA,UAAU,CAAC,IAAI,CAAC,oCAAoC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;AAC1E,QAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE;IAChC;IAEA,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;IAC9D,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE;AAC3C,QAAA,UAAU,CAAC,IAAI,CAAC,yCAAyC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;AAC/E,QAAA,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QACvF,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE;IAC5C;AAEA,IAAA,UAAU,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;AAC/D,IAAA,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IAE1E,MAAM,eAAe,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;IAC/D,IAAI,eAAe,GAAG,EAAE;IACxB,IAAI,eAAe,EAAE;AACjB,QAAA,eAAe,IAAI,CAAA,wBAAA,EAA2B,eAAe,CAAA,IAAA,CAAM;IACvE;IAEA,eAAe,IAAI,iCAAiC;AACpD,IAAA,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,SAAS,EAAE;QAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,CACtC,CAAC,CAAM,KAAK,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,EAAE,CAC3C;AAED,QAAA,eAAe,IAAI,CAAA,IAAA,EAAO,QAAQ,CAAC,QAAQ,MAAM;QACjD,IAAI,MAAM,EAAE;AACR,YAAA,eAAe,IAAI,CAAA,cAAA,EAAiB,MAAM,CAAC,cAAc,IAAI;AAC7D,YAAA,IAAI,MAAM,CAAC,WAAW,EAAE;AACpB,gBAAA,eAAe,IAAI,CAAA,aAAA,EAAgB,MAAM,CAAC,WAAW,IAAI;YAC7D;QACJ;aAAO;YACH,eAAe,IAAI,8BAA8B;QACrD;QACA,eAAe,IAAI,IAAI;IAC3B;IAEA,MAAM,cAAc,GAAG,MAAM,aAAa,CAAC,mBAAmB,CAAC,IAAI,EAAE,GAAG,CAAC;IACzE,MAAM,UAAU,GAAG,CAAA,EAAG,sBAAsB,OAAO,cAAc,CAAA,IAAA,EAAO,eAAe,CAAA,CAAE;AAEzF,IAAA,MAAM,WAAW,GAAwB;QACrC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,GAAG;AACH,QAAA,cAAc,EAAE,MAAM;QACtB,cAAc,EAAE,CAAC,OAAO,CAAC;QACzB,UAAU;KACb;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC;AACnB,QAAA,MAAM,EAAE,UAAU;AAClB,QAAA,OAAO,EAAE,EAAE,GAAG,WAAW,EAAE,IAAI,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE;AACjE,KAAA,CAAC;IAEF,IAAI,WAAW,GAAG,EAAE;AACpB,IAAA,WAAW,MAAM,OAAO,IAAI,QAAQ,EAAE;QAClC,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;QAC9C,IAAI,WAAW,EAAE;YACb,SAAS,CAAC,WAAW,CAAC;QAC1B;AACA,QAAA,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE;YAC1D,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE;gBACrC,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE;AAC7B,oBAAA,WAAW,IAAI,CAAA,EAAG,CAAC,CAAC,IAAI,IAAI;gBAChC;YACJ;QACJ;IACJ;AAEA,IAAA,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE;AACpB,QAAA,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;AACxD,QAAA,UAAU,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;IAC1D;AAEA,IAAA,MAAM,UAAU,CAAC,kBAAkB,EAAE;AACrC,IAAA,MAAM,sBAAsB,CAAC,OAAO,EAAE,IAAI,EAAE;AACxC,QAAA,aAAa,EAAE,CAAA,mBAAA,EAAsB,IAAI,CAAC,KAAK,CAAA,CAAE;AACpD,KAAA,CAAC;IAEF,IAAI,CAAC,WAAW,EAAE;AACd,QAAA,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QAC7E,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;IAC9C;AAEA,IAAA,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;AAC7E,IAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE;AAClC;;;;"}
|
|
@@ -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
|