@posthog/agent 1.16.6 → 1.18.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/README.md +6 -2
- package/dist/claude-cli/cli.js +3617 -0
- package/dist/claude-cli/package.json +3 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/src/agent.d.ts +0 -3
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +6 -27
- package/dist/src/agent.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 +84 -53
- package/dist/src/agents/research.js.map +1 -1
- package/dist/src/file-manager.d.ts +3 -21
- package/dist/src/file-manager.d.ts.map +1 -1
- package/dist/src/file-manager.js +15 -47
- package/dist/src/file-manager.js.map +1 -1
- package/dist/src/git-manager.d.ts.map +1 -1
- package/dist/src/git-manager.js +8 -1
- package/dist/src/git-manager.js.map +1 -1
- package/dist/src/posthog-api.d.ts +6 -1
- package/dist/src/posthog-api.d.ts.map +1 -1
- package/dist/src/posthog-api.js +28 -0
- package/dist/src/posthog-api.js.map +1 -1
- package/dist/src/task-progress-reporter.d.ts.map +1 -1
- package/dist/src/task-progress-reporter.js +0 -1
- package/dist/src/task-progress-reporter.js.map +1 -1
- package/dist/src/types.d.ts +21 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/workflow/steps/plan.d.ts.map +1 -1
- package/dist/src/workflow/steps/plan.js +26 -18
- package/dist/src/workflow/steps/plan.js.map +1 -1
- package/dist/src/workflow/steps/research.d.ts.map +1 -1
- package/dist/src/workflow/steps/research.js +100 -66
- package/dist/src/workflow/steps/research.js.map +1 -1
- package/dist/src/workflow/types.d.ts +0 -2
- package/dist/src/workflow/types.d.ts.map +1 -1
- package/dist/templates/plan-template.md +1 -5
- package/package.json +2 -6
- package/src/agent.ts +7 -31
- package/src/agents/research.ts +84 -53
- package/src/file-manager.ts +18 -73
- package/src/git-manager.ts +7 -1
- package/src/posthog-api.ts +33 -1
- package/src/task-progress-reporter.ts +0 -1
- package/src/templates/plan-template.md +1 -5
- package/src/types.ts +25 -2
- package/src/workflow/steps/plan.ts +28 -21
- package/src/workflow/steps/research.ts +109 -74
- package/src/workflow/types.ts +0 -2
- package/dist/_virtual/_commonjsHelpers.js +0 -6
- package/dist/_virtual/_commonjsHelpers.js.map +0 -1
- package/dist/_virtual/index.js +0 -4
- package/dist/_virtual/index.js.map +0 -1
- package/dist/node_modules/@ai-sdk/anthropic/dist/index.js +0 -1154
- package/dist/node_modules/@ai-sdk/anthropic/dist/index.js.map +0 -1
- package/dist/node_modules/@ai-sdk/provider/dist/index.js +0 -296
- package/dist/node_modules/@ai-sdk/provider/dist/index.js.map +0 -1
- package/dist/node_modules/@ai-sdk/provider-utils/dist/index.js +0 -576
- package/dist/node_modules/@ai-sdk/provider-utils/dist/index.js.map +0 -1
- package/dist/node_modules/@ai-sdk/ui-utils/dist/index.js +0 -741
- package/dist/node_modules/@ai-sdk/ui-utils/dist/index.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/api/context.js +0 -112
- package/dist/node_modules/@opentelemetry/api/build/esm/api/context.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/api/diag.js +0 -123
- package/dist/node_modules/@opentelemetry/api/build/esm/api/diag.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/api/metrics.js +0 -62
- package/dist/node_modules/@opentelemetry/api/build/esm/api/metrics.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/api/propagation.js +0 -91
- package/dist/node_modules/@opentelemetry/api/build/esm/api/propagation.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/api/trace.js +0 -79
- package/dist/node_modules/@opentelemetry/api/build/esm/api/trace.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/context-helpers.js +0 -59
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/context-helpers.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js +0 -99
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/utils.js +0 -31
- package/dist/node_modules/@opentelemetry/api/build/esm/baggage/utils.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js +0 -69
- package/dist/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/context/context.js +0 -54
- package/dist/node_modules/@opentelemetry/api/build/esm/context/context.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/context-api.js +0 -22
- package/dist/node_modules/@opentelemetry/api/build/esm/context-api.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/ComponentLogger.js +0 -104
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/ComponentLogger.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/internal/logLevelLogger.js +0 -44
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/internal/logLevelLogger.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/types.js +0 -43
- package/dist/node_modules/@opentelemetry/api/build/esm/diag/types.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/diag-api.js +0 -27
- package/dist/node_modules/@opentelemetry/api/build/esm/diag-api.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js +0 -62
- package/dist/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/internal/semver.js +0 -121
- package/dist/node_modules/@opentelemetry/api/build/esm/internal/semver.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js +0 -167
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js +0 -33
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics-api.js +0 -22
- package/dist/node_modules/@opentelemetry/api/build/esm/metrics-api.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/platform/node/globalThis.js +0 -21
- package/dist/node_modules/@opentelemetry/api/build/esm/platform/node/globalThis.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation/NoopTextMapPropagator.js +0 -35
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation/NoopTextMapPropagator.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation/TextMapPropagator.js +0 -40
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation/TextMapPropagator.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation-api.js +0 -22
- package/dist/node_modules/@opentelemetry/api/build/esm/propagation-api.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NonRecordingSpan.js +0 -70
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NonRecordingSpan.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracer.js +0 -78
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracer.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js +0 -34
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracer.js +0 -55
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracer.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracerProvider.js +0 -56
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracerProvider.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/context-utils.js +0 -76
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/context-utils.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/invalid-span-constants.js +0 -27
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/invalid-span-constants.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/spancontext-utils.js +0 -45
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/spancontext-utils.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/status.js +0 -22
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/status.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/trace_flags.js +0 -25
- package/dist/node_modules/@opentelemetry/api/build/esm/trace/trace_flags.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/trace-api.js +0 -24
- package/dist/node_modules/@opentelemetry/api/build/esm/trace-api.js.map +0 -1
- package/dist/node_modules/@opentelemetry/api/build/esm/version.js +0 -20
- package/dist/node_modules/@opentelemetry/api/build/esm/version.js.map +0 -1
- package/dist/node_modules/ai/dist/index.js +0 -2870
- package/dist/node_modules/ai/dist/index.js.map +0 -1
- package/dist/node_modules/nanoid/non-secure/index.js +0 -13
- package/dist/node_modules/nanoid/non-secure/index.js.map +0 -1
- package/dist/node_modules/secure-json-parse/index.js +0 -133
- package/dist/node_modules/secure-json-parse/index.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/Options.js +0 -37
- package/dist/node_modules/zod-to-json-schema/dist/esm/Options.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/Refs.js +0 -26
- package/dist/node_modules/zod-to-json-schema/dist/esm/Refs.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/errorMessages.js +0 -17
- package/dist/node_modules/zod-to-json-schema/dist/esm/errorMessages.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js +0 -11
- package/dist/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/index.js +0 -8
- package/dist/node_modules/zod-to-json-schema/dist/esm/index.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parseDef.js +0 -66
- package/dist/node_modules/zod-to-json-schema/dist/esm/parseDef.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/any.js +0 -21
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/any.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/array.js +0 -30
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/array.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js +0 -53
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js +0 -8
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/branded.js +0 -8
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/branded.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/catch.js +0 -8
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/catch.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/date.js +0 -50
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/date.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/default.js +0 -11
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/default.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/effects.js +0 -11
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/effects.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/enum.js +0 -9
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/enum.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js +0 -56
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/literal.js +0 -24
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/literal.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/map.js +0 -30
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/map.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js +0 -19
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/never.js +0 -15
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/never.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/null.js +0 -13
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/null.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js +0 -37
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/number.js +0 -56
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/number.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/object.js +0 -76
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/object.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/optional.js +0 -25
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/optional.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js +0 -24
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/promise.js +0 -8
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/promise.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js +0 -8
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/record.js +0 -65
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/record.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/set.js +0 -24
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/set.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/string.js +0 -350
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/string.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js +0 -36
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js +0 -10
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/union.js +0 -84
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/union.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js +0 -8
- package/dist/node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/selectParser.js +0 -110
- package/dist/node_modules/zod-to-json-schema/dist/esm/selectParser.js.map +0 -1
- package/dist/node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js +0 -90
- package/dist/node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js.map +0 -1
- package/dist/src/structured-extraction.d.ts +0 -28
- package/dist/src/structured-extraction.d.ts.map +0 -1
- package/dist/src/structured-extraction.js +0 -77
- package/dist/src/structured-extraction.js.map +0 -1
- package/dist/src/utils/ai-sdk.d.ts +0 -14
- package/dist/src/utils/ai-sdk.d.ts.map +0 -1
- package/dist/src/utils/ai-sdk.js +0 -38
- package/dist/src/utils/ai-sdk.js.map +0 -1
- package/src/structured-extraction.ts +0 -117
- package/src/utils/ai-sdk.ts +0 -47
package/src/agent.ts
CHANGED
|
@@ -10,7 +10,6 @@ import type { ProviderAdapter } from './adapters/types.js';
|
|
|
10
10
|
import { Logger } from './utils/logger.js';
|
|
11
11
|
import { PromptBuilder } from './prompt-builder.js';
|
|
12
12
|
import { TaskProgressReporter } from './task-progress-reporter.js';
|
|
13
|
-
import { AISDKExtractor, type StructuredExtractor, type ExtractedQuestion, type ExtractedQuestionWithAnswer } from './structured-extraction.js';
|
|
14
13
|
import { TASK_WORKFLOW } from './workflow/config.js';
|
|
15
14
|
import type { WorkflowRuntime } from './workflow/types.js';
|
|
16
15
|
|
|
@@ -26,7 +25,6 @@ export class Agent {
|
|
|
26
25
|
private logger: Logger;
|
|
27
26
|
private progressReporter: TaskProgressReporter;
|
|
28
27
|
private promptBuilder: PromptBuilder;
|
|
29
|
-
private extractor?: StructuredExtractor;
|
|
30
28
|
private mcpServers?: Record<string, any>;
|
|
31
29
|
private canUseTool?: CanUseTool;
|
|
32
30
|
public debug: boolean;
|
|
@@ -92,7 +90,6 @@ export class Agent {
|
|
|
92
90
|
logger: this.logger.child('PromptBuilder')
|
|
93
91
|
});
|
|
94
92
|
this.progressReporter = new TaskProgressReporter(this.posthogAPI, this.logger);
|
|
95
|
-
this.extractor = new AISDKExtractor({apiKey: config.posthogApiKey, gatewayUrl: this.posthogAPI?.getLlmGatewayUrl() ?? '', logger: this.logger.child('AISDKExtractor')});
|
|
96
93
|
}
|
|
97
94
|
|
|
98
95
|
/**
|
|
@@ -159,7 +156,6 @@ export class Agent {
|
|
|
159
156
|
adapter: this.adapter,
|
|
160
157
|
mcpServers: this.mcpServers,
|
|
161
158
|
posthogAPI: this.posthogAPI,
|
|
162
|
-
extractor: this.extractor,
|
|
163
159
|
emitEvent: (event: any) => this.emitEvent(event),
|
|
164
160
|
stepResults: {},
|
|
165
161
|
};
|
|
@@ -283,32 +279,11 @@ export class Agent {
|
|
|
283
279
|
return await this.fileManager.readPlan(taskId);
|
|
284
280
|
}
|
|
285
281
|
|
|
286
|
-
async extractQuestionsFromResearch(taskId: string, includeAnswers: boolean = false): Promise<ExtractedQuestion[] | ExtractedQuestionWithAnswer[]> {
|
|
287
|
-
this.logger.info('Extracting questions from research.md', { taskId, includeAnswers });
|
|
288
|
-
|
|
289
|
-
if (!this.extractor) {
|
|
290
|
-
throw new Error('OpenAI extractor not initialized. Ensure the LLM gateway is configured.');
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const researchContent = await this.fileManager.readResearch(taskId);
|
|
294
|
-
if (!researchContent) {
|
|
295
|
-
throw new Error('research.md not found for task ' + taskId);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (includeAnswers) {
|
|
299
|
-
return await this.extractor.extractQuestionsWithAnswers(researchContent);
|
|
300
|
-
} else {
|
|
301
|
-
return await this.extractor.extractQuestions(researchContent);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
282
|
// Git operations for task execution
|
|
306
283
|
async createPlanningBranch(taskId: string): Promise<string> {
|
|
307
284
|
this.logger.info('Creating planning branch', { taskId });
|
|
308
285
|
const branchName = await this.gitManager.createTaskPlanningBranch(taskId);
|
|
309
286
|
this.logger.debug('Planning branch created', { taskId, branchName });
|
|
310
|
-
// Only create gitignore after we're on the new branch
|
|
311
|
-
await this.fileManager.ensureGitignore();
|
|
312
287
|
return branchName;
|
|
313
288
|
}
|
|
314
289
|
|
|
@@ -422,12 +397,17 @@ Generated by PostHog Agent`;
|
|
|
422
397
|
const branchName = await this.gitManager.createTaskBranch(taskSlug);
|
|
423
398
|
this.emitEvent(this.adapter.createStatusEvent('branch_created', { branch: branchName }));
|
|
424
399
|
|
|
425
|
-
await this.fileManager.ensureGitignore();
|
|
426
400
|
await this.gitManager.addAllPostHogFiles();
|
|
401
|
+
|
|
402
|
+
// Only commit if there are changes or we're in cloud mode
|
|
427
403
|
if (isCloudMode) {
|
|
428
404
|
await this.gitManager.commitAndPush(`Initialize task ${taskSlug}`, { allowEmpty: true });
|
|
429
405
|
} else {
|
|
430
|
-
|
|
406
|
+
// Check if there are any changes before committing
|
|
407
|
+
const hasChanges = await this.gitManager.hasStagedChanges();
|
|
408
|
+
if (hasChanges) {
|
|
409
|
+
await this.gitManager.commitChanges(`Initialize task ${taskSlug}`);
|
|
410
|
+
}
|
|
431
411
|
}
|
|
432
412
|
} else {
|
|
433
413
|
this.logger.info('Switching to existing task branch', { branch: existingBranch });
|
|
@@ -446,10 +426,6 @@ Generated by PostHog Agent`;
|
|
|
446
426
|
if (resolvedToken) {
|
|
447
427
|
process.env.OPENAI_API_KEY = resolvedToken;
|
|
448
428
|
}
|
|
449
|
-
|
|
450
|
-
if (!this.extractor) {
|
|
451
|
-
this.extractor = new AISDKExtractor({apiKey: resolvedToken || '', gatewayUrl: resolvedGatewayUrl || '', logger: this.logger.child('AISDKExtractor')});
|
|
452
|
-
}
|
|
453
429
|
}
|
|
454
430
|
|
|
455
431
|
private async ensurePullRequest(task: Task, stepResults: Record<string, any>): Promise<void> {
|
package/src/agents/research.ts
CHANGED
|
@@ -1,80 +1,111 @@
|
|
|
1
1
|
export const RESEARCH_SYSTEM_PROMPT = `<role>
|
|
2
|
-
PostHog AI Research Agent — analyze codebases to
|
|
2
|
+
PostHog AI Research Agent — analyze codebases to evaluate task actionability and identify missing information.
|
|
3
3
|
</role>
|
|
4
4
|
|
|
5
5
|
<constraints>
|
|
6
6
|
- Read-only: analyze files, search code, explore structure
|
|
7
7
|
- No modifications or code changes
|
|
8
|
+
- Output structured JSON only
|
|
8
9
|
</constraints>
|
|
9
10
|
|
|
10
11
|
<objective>
|
|
11
|
-
Your PRIMARY goal is to
|
|
12
|
+
Your PRIMARY goal is to evaluate whether a task is actionable and assign an actionability score.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
14
|
+
Calculate an actionabilityScore (0-1) based on:
|
|
15
|
+
- **Task clarity** (0.4 weight): Is the task description specific and unambiguous?
|
|
16
|
+
- **Codebase context** (0.3 weight): Can you locate the relevant code and patterns?
|
|
17
|
+
- **Architectural decisions** (0.2 weight): Are the implementation approaches clear?
|
|
18
|
+
- **Dependencies** (0.1 weight): Are required dependencies and constraints understood?
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
If actionabilityScore < 0.7, generate specific clarifying questions to increase confidence.
|
|
21
|
+
|
|
22
|
+
DO NOT ask questions like "how should I fix this" — focus on missing information that prevents confident planning.
|
|
19
23
|
</objective>
|
|
20
24
|
|
|
21
25
|
<process>
|
|
22
26
|
1. Explore repository structure and identify relevant files/components
|
|
23
27
|
2. Understand existing patterns, conventions, and dependencies
|
|
24
|
-
3.
|
|
25
|
-
4. Identify
|
|
26
|
-
5.
|
|
27
|
-
6.
|
|
28
|
+
3. Calculate actionabilityScore based on clarity, context, architecture, and dependencies
|
|
29
|
+
4. Identify key files that will need modification
|
|
30
|
+
5. If score < 0.7: generate 2-4 specific questions to resolve blockers
|
|
31
|
+
6. Output JSON matching ResearchEvaluation schema
|
|
28
32
|
</process>
|
|
29
33
|
|
|
30
34
|
<output_format>
|
|
31
|
-
Output ONLY
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
[
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
- Always include "c) Something else (please specify)"
|
|
60
|
-
- Max 4 questions total
|
|
35
|
+
Output ONLY valid JSON with no markdown wrappers, no preamble, no explanation:
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
"actionabilityScore": 0.85,
|
|
39
|
+
"context": "Brief 2-3 sentence summary of the task and implementation approach",
|
|
40
|
+
"keyFiles": ["path/to/file1.ts", "path/to/file2.ts"],
|
|
41
|
+
"blockers": ["Optional: what's preventing full confidence"],
|
|
42
|
+
"questions": [
|
|
43
|
+
{
|
|
44
|
+
"id": "q1",
|
|
45
|
+
"question": "Specific architectural decision needed?",
|
|
46
|
+
"options": [
|
|
47
|
+
"First approach with concrete details",
|
|
48
|
+
"Alternative approach with concrete details",
|
|
49
|
+
"Third option if needed"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
Rules:
|
|
56
|
+
- actionabilityScore: number between 0 and 1
|
|
57
|
+
- context: concise summary for planning phase
|
|
58
|
+
- keyFiles: array of file paths that need modification
|
|
59
|
+
- blockers: optional array explaining confidence gaps
|
|
60
|
+
- questions: ONLY include if actionabilityScore < 0.7
|
|
61
|
+
- Each question must have 2-3 options (maximum 3)
|
|
62
|
+
- Max 3 questions total
|
|
61
63
|
</output_format>
|
|
62
64
|
|
|
63
|
-
<
|
|
65
|
+
<scoring_examples>
|
|
66
|
+
<example score="0.9">
|
|
67
|
+
Task: "Fix typo in login button text"
|
|
68
|
+
Reasoning: Completely clear task, found exact component, no architectural decisions
|
|
69
|
+
</example>
|
|
70
|
+
|
|
71
|
+
<example score="0.75">
|
|
72
|
+
Task: "Add caching to API endpoints"
|
|
73
|
+
Reasoning: Clear goal, found endpoints, but multiple caching strategies possible
|
|
74
|
+
</example>
|
|
75
|
+
|
|
76
|
+
<example score="0.55">
|
|
77
|
+
Task: "Improve performance"
|
|
78
|
+
Reasoning: Vague task, unclear scope, needs questions about which areas to optimize
|
|
79
|
+
Questions needed: Which features are slow? What metrics define success?
|
|
80
|
+
</example>
|
|
81
|
+
|
|
82
|
+
<example score="0.3">
|
|
83
|
+
Task: "Add the new feature"
|
|
84
|
+
Reasoning: Extremely vague, no context, cannot locate relevant code
|
|
85
|
+
Questions needed: What feature? Which product area? What should it do?
|
|
86
|
+
</example>
|
|
87
|
+
</scoring_examples>
|
|
88
|
+
|
|
89
|
+
<question_examples>
|
|
64
90
|
<good_example>
|
|
65
|
-
|
|
66
|
-
|
|
91
|
+
{
|
|
92
|
+
"id": "q1",
|
|
93
|
+
"question": "Which caching layer should we use for API responses?",
|
|
94
|
+
"options": [
|
|
95
|
+
"Redis (existing infrastructure, requires setup)",
|
|
96
|
+
"In-memory cache (simpler, but not distributed)",
|
|
97
|
+
"Browser-side caching only (minimal backend changes)"
|
|
98
|
+
]
|
|
99
|
+
}
|
|
67
100
|
</good_example>
|
|
68
101
|
|
|
69
102
|
<bad_example>
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
{
|
|
104
|
+
"id": "q1",
|
|
105
|
+
"question": "How should I implement this?",
|
|
106
|
+
"options": ["One way", "Another way"]
|
|
107
|
+
}
|
|
108
|
+
Reason: Too vague, doesn't explain the tradeoffs
|
|
73
109
|
</bad_example>
|
|
74
|
-
|
|
75
|
-
<good_example>
|
|
76
|
-
Task: "Add caching to API endpoints"
|
|
77
|
-
Output: Research showing existing cache implementations, question about cache backend choice IF multiple production systems are already in use
|
|
78
|
-
</good_example>
|
|
79
|
-
</examples>`;
|
|
110
|
+
</question_examples>`;
|
|
80
111
|
|
package/src/file-manager.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
|
-
import { join
|
|
3
|
-
import type { SupportingFile } from './types.js';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import type { SupportingFile, ResearchEvaluation } from './types.js';
|
|
4
4
|
import { Logger } from './utils/logger.js';
|
|
5
5
|
|
|
6
6
|
export interface TaskFile {
|
|
@@ -9,24 +9,6 @@ export interface TaskFile {
|
|
|
9
9
|
type: 'plan' | 'context' | 'reference' | 'output' | 'artifact';
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export interface QuestionData {
|
|
13
|
-
id: string;
|
|
14
|
-
question: string;
|
|
15
|
-
options: string[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface AnswerData {
|
|
19
|
-
questionId: string;
|
|
20
|
-
selectedOption: string;
|
|
21
|
-
customInput?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface QuestionsFile {
|
|
25
|
-
questions: QuestionData[];
|
|
26
|
-
answered: boolean;
|
|
27
|
-
answers: AnswerData[] | null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
12
|
export class PostHogFileManager {
|
|
31
13
|
private repositoryPath: string;
|
|
32
14
|
private logger: Logger;
|
|
@@ -170,48 +152,35 @@ export class PostHogFileManager {
|
|
|
170
152
|
return await this.readTaskFile(taskId, 'requirements.md');
|
|
171
153
|
}
|
|
172
154
|
|
|
173
|
-
async writeResearch(taskId: string,
|
|
155
|
+
async writeResearch(taskId: string, data: ResearchEvaluation): Promise<void> {
|
|
174
156
|
this.logger.debug('Writing research', {
|
|
175
157
|
taskId,
|
|
176
|
-
|
|
177
|
-
|
|
158
|
+
score: data.actionabilityScore,
|
|
159
|
+
hasQuestions: !!data.questions,
|
|
160
|
+
questionCount: data.questions?.length ?? 0,
|
|
161
|
+
answered: data.answered ?? false,
|
|
178
162
|
});
|
|
179
163
|
|
|
180
164
|
await this.writeTaskFile(taskId, {
|
|
181
|
-
name: 'research.
|
|
182
|
-
content: content,
|
|
183
|
-
type: 'artifact'
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
this.logger.info('Research file written', { taskId });
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async readResearch(taskId: string): Promise<string | null> {
|
|
190
|
-
return await this.readTaskFile(taskId, 'research.md');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async writeQuestions(taskId: string, data: QuestionsFile): Promise<void> {
|
|
194
|
-
this.logger.debug('Writing questions', {
|
|
195
|
-
taskId,
|
|
196
|
-
questionCount: data.questions.length,
|
|
197
|
-
answered: data.answered,
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
await this.writeTaskFile(taskId, {
|
|
201
|
-
name: 'questions.json',
|
|
165
|
+
name: 'research.json',
|
|
202
166
|
content: JSON.stringify(data, null, 2),
|
|
203
167
|
type: 'artifact'
|
|
204
168
|
});
|
|
205
169
|
|
|
206
|
-
this.logger.info('
|
|
170
|
+
this.logger.info('Research file written', {
|
|
171
|
+
taskId,
|
|
172
|
+
score: data.actionabilityScore,
|
|
173
|
+
hasQuestions: !!data.questions,
|
|
174
|
+
answered: data.answered ?? false,
|
|
175
|
+
});
|
|
207
176
|
}
|
|
208
177
|
|
|
209
|
-
async
|
|
178
|
+
async readResearch(taskId: string): Promise<ResearchEvaluation | null> {
|
|
210
179
|
try {
|
|
211
|
-
const content = await this.readTaskFile(taskId, '
|
|
212
|
-
return content ? JSON.parse(content) as
|
|
180
|
+
const content = await this.readTaskFile(taskId, 'research.json');
|
|
181
|
+
return content ? JSON.parse(content) as ResearchEvaluation : null;
|
|
213
182
|
} catch (error) {
|
|
214
|
-
this.logger.debug('Failed to parse
|
|
183
|
+
this.logger.debug('Failed to parse research.json', { error });
|
|
215
184
|
return null;
|
|
216
185
|
}
|
|
217
186
|
}
|
|
@@ -241,28 +210,4 @@ export class PostHogFileManager {
|
|
|
241
210
|
|
|
242
211
|
return files;
|
|
243
212
|
}
|
|
244
|
-
|
|
245
|
-
async ensureGitignore(): Promise<void> {
|
|
246
|
-
const gitignorePath = join(this.repositoryPath, '.posthog', '.gitignore');
|
|
247
|
-
const gitignoreContent = `# PostHog task artifacts - customize as needed
|
|
248
|
-
# Exclude temporary files
|
|
249
|
-
*/temp/
|
|
250
|
-
*/cache/
|
|
251
|
-
*/.env
|
|
252
|
-
*/.secrets
|
|
253
|
-
|
|
254
|
-
# Include plans and documentation by default
|
|
255
|
-
!*/plan.md
|
|
256
|
-
!*/context.md
|
|
257
|
-
!*/requirements.md
|
|
258
|
-
!*/README.md
|
|
259
|
-
`;
|
|
260
|
-
|
|
261
|
-
try {
|
|
262
|
-
await fs.access(gitignorePath);
|
|
263
|
-
} catch {
|
|
264
|
-
await fs.mkdir(dirname(gitignorePath), { recursive: true });
|
|
265
|
-
await fs.writeFile(gitignorePath, gitignoreContent, 'utf8');
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
213
|
}
|
package/src/git-manager.ts
CHANGED
|
@@ -135,7 +135,13 @@ export class GitManager {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
async addAllPostHogFiles(): Promise<void> {
|
|
138
|
-
|
|
138
|
+
try {
|
|
139
|
+
// Use -A flag to add all changes (including new files) and ignore errors if directory is empty
|
|
140
|
+
await this.runGitCommand('add -A .posthog/');
|
|
141
|
+
} catch (error) {
|
|
142
|
+
// If the directory doesn't exist or has no files, that's fine - just log and continue
|
|
143
|
+
this.logger.debug('No PostHog files to add', { error });
|
|
144
|
+
}
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
async commitChanges(message: string, options?: {
|
package/src/posthog-api.ts
CHANGED
|
@@ -11,7 +11,6 @@ export interface TaskRunUpdate {
|
|
|
11
11
|
status?: TaskRun["status"];
|
|
12
12
|
branch?: string | null;
|
|
13
13
|
current_stage?: string | null;
|
|
14
|
-
log?: LogEntry[];
|
|
15
14
|
error_message?: string | null;
|
|
16
15
|
output?: Record<string, unknown> | null;
|
|
17
16
|
state?: Record<string, unknown>;
|
|
@@ -171,6 +170,39 @@ export class PostHogAPIClient {
|
|
|
171
170
|
});
|
|
172
171
|
}
|
|
173
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Fetch logs from S3 using presigned URL from TaskRun
|
|
175
|
+
* @param taskRun - The task run containing the log_url
|
|
176
|
+
* @returns Array of log entries, or empty array if no logs available
|
|
177
|
+
*/
|
|
178
|
+
async fetchTaskRunLogs(taskRun: TaskRun): Promise<LogEntry[]> {
|
|
179
|
+
if (!taskRun.log_url) {
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const response = await fetch(taskRun.log_url);
|
|
185
|
+
|
|
186
|
+
if (!response.ok) {
|
|
187
|
+
throw new Error(`Failed to fetch logs: ${response.status} ${response.statusText}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const content = await response.text();
|
|
191
|
+
|
|
192
|
+
if (!content.trim()) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Parse newline-delimited JSON
|
|
197
|
+
return content
|
|
198
|
+
.trim()
|
|
199
|
+
.split('\n')
|
|
200
|
+
.map(line => JSON.parse(line) as LogEntry);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
throw new Error(`Failed to fetch task run logs: ${error instanceof Error ? error.message : String(error)}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
174
206
|
/**
|
|
175
207
|
* Fetch error details from PostHog error tracking
|
|
176
208
|
*/
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
// import and export to keep a single type file
|
|
3
|
-
import type { CanUseTool, PermissionResult } from '@anthropic-ai/claude-agent-sdk
|
|
3
|
+
import type { CanUseTool, PermissionResult } from '@anthropic-ai/claude-agent-sdk';
|
|
4
4
|
export type { CanUseTool, PermissionResult };
|
|
5
5
|
|
|
6
6
|
// PostHog Task model (matches Array's OpenAPI schema)
|
|
@@ -39,7 +39,7 @@ export interface TaskRun {
|
|
|
39
39
|
team: number;
|
|
40
40
|
branch: string | null;
|
|
41
41
|
status: 'started' | 'in_progress' | 'completed' | 'failed';
|
|
42
|
-
|
|
42
|
+
log_url?: string; // Presigned S3 URL for log access (valid for 1 hour)
|
|
43
43
|
error_message: string | null;
|
|
44
44
|
output: Record<string, unknown> | null; // Structured output (PR URL, commit SHA, etc.)
|
|
45
45
|
state: Record<string, unknown>; // Intermediate run state (defaults to {}, never null)
|
|
@@ -345,4 +345,27 @@ export interface UrlMention {
|
|
|
345
345
|
type: ResourceType;
|
|
346
346
|
id?: string;
|
|
347
347
|
label?: string;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Research evaluation types
|
|
351
|
+
export interface ResearchQuestion {
|
|
352
|
+
id: string;
|
|
353
|
+
question: string;
|
|
354
|
+
options: string[];
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export interface ResearchAnswer {
|
|
358
|
+
questionId: string;
|
|
359
|
+
selectedOption: string;
|
|
360
|
+
customInput?: string;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export interface ResearchEvaluation {
|
|
364
|
+
actionabilityScore: number; // 0-1 confidence score
|
|
365
|
+
context: string; // brief summary for planning
|
|
366
|
+
keyFiles: string[]; // files needing modification
|
|
367
|
+
blockers?: string[]; // what's preventing full confidence
|
|
368
|
+
questions?: ResearchQuestion[]; // only if score < 0.7
|
|
369
|
+
answered?: boolean; // whether questions have been answered
|
|
370
|
+
answers?: ResearchAnswer[]; // user's answers to questions
|
|
348
371
|
}
|
|
@@ -26,8 +26,8 @@ export const planStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
|
26
26
|
return { status: 'skipped' };
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
29
|
+
const researchData = await fileManager.readResearch(task.id);
|
|
30
|
+
if (researchData?.questions && !researchData.answered) {
|
|
31
31
|
stepLogger.info('Waiting for answered research questions', { taskId: task.id });
|
|
32
32
|
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'research_questions' }));
|
|
33
33
|
return { status: 'skipped', halt: true };
|
|
@@ -35,29 +35,36 @@ export const planStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
|
35
35
|
|
|
36
36
|
stepLogger.info('Starting planning phase', { taskId: task.id });
|
|
37
37
|
emitEvent(adapter.createStatusEvent('phase_start', { phase: 'planning' }));
|
|
38
|
-
|
|
39
|
-
const researchContent = await fileManager.readResearch(task.id);
|
|
40
38
|
let researchContext = '';
|
|
41
|
-
if (
|
|
42
|
-
researchContext += `## Research
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
39
|
+
if (researchData) {
|
|
40
|
+
researchContext += `## Research Context\n\n${researchData.context}\n\n`;
|
|
41
|
+
if (researchData.keyFiles.length > 0) {
|
|
42
|
+
researchContext += `**Key Files:**\n${researchData.keyFiles.map(f => `- ${f}`).join('\n')}\n\n`;
|
|
43
|
+
}
|
|
44
|
+
if (researchData.blockers && researchData.blockers.length > 0) {
|
|
45
|
+
researchContext += `**Considerations:**\n${researchData.blockers.map(b => `- ${b}`).join('\n')}\n\n`;
|
|
46
|
+
}
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
researchContext +=
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
// Add answered questions if they exist
|
|
49
|
+
if (researchData.questions && researchData.answers && researchData.answered) {
|
|
50
|
+
researchContext += `## Implementation Decisions\n\n`;
|
|
51
|
+
for (const question of researchData.questions) {
|
|
52
|
+
const answer = researchData.answers.find(
|
|
53
|
+
(a) => a.questionId === question.id
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
researchContext += `### ${question.question}\n\n`;
|
|
57
|
+
if (answer) {
|
|
58
|
+
researchContext += `**Selected:** ${answer.selectedOption}\n`;
|
|
59
|
+
if (answer.customInput) {
|
|
60
|
+
researchContext += `**Details:** ${answer.customInput}\n`;
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
researchContext += `**Selected:** Not answered\n`;
|
|
64
|
+
}
|
|
65
|
+
researchContext += `\n`;
|
|
56
66
|
}
|
|
57
|
-
} else {
|
|
58
|
-
researchContext += `**Selected:** Not answered\n`;
|
|
59
67
|
}
|
|
60
|
-
researchContext += `\n`;
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
const planningPrompt = await promptBuilder.buildPlanningPrompt(task, cwd);
|