@posthog/agent 1.12.0 → 1.14.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/execution.d.ts +1 -1
- package/dist/src/agents/execution.d.ts.map +1 -1
- package/dist/src/agents/execution.js +28 -43
- package/dist/src/agents/execution.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 +60 -67
- 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 +68 -91
- 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 +68 -36
- 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/execution.ts +28 -43
- package/src/agents/planning.ts +60 -67
- package/src/agents/research.ts +68 -91
- package/src/prompt-builder.ts +71 -37
- 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
package/src/agent.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
-
import type { Task, ExecutionResult,
|
|
2
|
+
import type { Task, ExecutionResult, AgentConfig } from './types.js';
|
|
3
3
|
import { TaskManager } from './task-manager.js';
|
|
4
4
|
import { PostHogAPIClient } from './posthog-api.js';
|
|
5
5
|
import { PostHogFileManager } from './file-manager.js';
|
|
@@ -7,12 +7,12 @@ import { GitManager } from './git-manager.js';
|
|
|
7
7
|
import { TemplateManager } from './template-manager.js';
|
|
8
8
|
import { ClaudeAdapter } from './adapters/claude/claude-adapter.js';
|
|
9
9
|
import type { ProviderAdapter } from './adapters/types.js';
|
|
10
|
-
import { PLANNING_SYSTEM_PROMPT } from './agents/planning.js';
|
|
11
|
-
import { EXECUTION_SYSTEM_PROMPT } from './agents/execution.js';
|
|
12
10
|
import { Logger } from './utils/logger.js';
|
|
13
11
|
import { PromptBuilder } from './prompt-builder.js';
|
|
14
12
|
import { TaskProgressReporter } from './task-progress-reporter.js';
|
|
15
|
-
import {
|
|
13
|
+
import { AISDKExtractor, type StructuredExtractor, type ExtractedQuestion, type ExtractedQuestionWithAnswer } from './structured-extraction.js';
|
|
14
|
+
import { TASK_WORKFLOW } from './workflow/config.js';
|
|
15
|
+
import type { WorkflowRuntime } from './workflow/types.js';
|
|
16
16
|
|
|
17
17
|
export class Agent {
|
|
18
18
|
private workingDirectory: string;
|
|
@@ -26,7 +26,7 @@ export class Agent {
|
|
|
26
26
|
private logger: Logger;
|
|
27
27
|
private progressReporter: TaskProgressReporter;
|
|
28
28
|
private promptBuilder: PromptBuilder;
|
|
29
|
-
private extractor?:
|
|
29
|
+
private extractor?: StructuredExtractor;
|
|
30
30
|
private mcpServers?: Record<string, any>;
|
|
31
31
|
public debug: boolean;
|
|
32
32
|
|
|
@@ -89,11 +89,7 @@ export class Agent {
|
|
|
89
89
|
logger: this.logger.child('PromptBuilder')
|
|
90
90
|
});
|
|
91
91
|
this.progressReporter = new TaskProgressReporter(this.posthogAPI, this.logger);
|
|
92
|
-
|
|
93
|
-
// Initialize OpenAI extractor if API key is available
|
|
94
|
-
if (process.env.OPENAI_API_KEY) {
|
|
95
|
-
this.extractor = new OpenAIExtractor(this.logger.child('OpenAIExtractor'));
|
|
96
|
-
}
|
|
92
|
+
this.extractor = new AISDKExtractor(this.logger.child('AISDKExtractor'));
|
|
97
93
|
}
|
|
98
94
|
|
|
99
95
|
/**
|
|
@@ -113,6 +109,7 @@ export class Agent {
|
|
|
113
109
|
}
|
|
114
110
|
|
|
115
111
|
if (process.env.ANTHROPIC_BASE_URL && process.env.ANTHROPIC_AUTH_TOKEN) {
|
|
112
|
+
this.ensureOpenAIGatewayEnv();
|
|
116
113
|
return;
|
|
117
114
|
}
|
|
118
115
|
|
|
@@ -122,6 +119,7 @@ export class Agent {
|
|
|
122
119
|
|
|
123
120
|
process.env.ANTHROPIC_BASE_URL = gatewayUrl;
|
|
124
121
|
process.env.ANTHROPIC_AUTH_TOKEN = apiKey;
|
|
122
|
+
this.ensureOpenAIGatewayEnv(gatewayUrl, apiKey);
|
|
125
123
|
|
|
126
124
|
this.logger.debug('Configured LLM gateway', { gatewayUrl });
|
|
127
125
|
} catch (error) {
|
|
@@ -130,7 +128,7 @@ export class Agent {
|
|
|
130
128
|
}
|
|
131
129
|
}
|
|
132
130
|
|
|
133
|
-
// Adaptive task execution
|
|
131
|
+
// Adaptive task execution orchestrated via workflow steps
|
|
134
132
|
async runTask(taskOrId: Task | string, options: import('./types.js').TaskExecutionOptions = {}): Promise<void> {
|
|
135
133
|
await this._configureLlmGateway();
|
|
136
134
|
|
|
@@ -142,324 +140,41 @@ export class Agent {
|
|
|
142
140
|
this.logger.info('Starting adaptive task execution', { taskId: task.id, taskSlug, isCloudMode });
|
|
143
141
|
|
|
144
142
|
// Initialize progress reporter for task run tracking (needed for PR attachment)
|
|
145
|
-
await this.progressReporter.start(task.id, { totalSteps:
|
|
143
|
+
await this.progressReporter.start(task.id, { totalSteps: TASK_WORKFLOW.length });
|
|
146
144
|
this.emitEvent(this.adapter.createStatusEvent('run_started', { runId: this.progressReporter.runId }));
|
|
147
145
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Phase 2: Research
|
|
170
|
-
const researchExists = await this.fileManager.readResearch(task.id);
|
|
171
|
-
if (!researchExists) {
|
|
172
|
-
this.logger.info('Starting research phase', { taskId: task.id });
|
|
173
|
-
this.emitEvent(this.adapter.createStatusEvent('phase_start', { phase: 'research' }));
|
|
174
|
-
|
|
175
|
-
// Run research agent
|
|
176
|
-
const researchPrompt = await this.promptBuilder.buildResearchPrompt(task, cwd);
|
|
177
|
-
const { RESEARCH_SYSTEM_PROMPT } = await import('./agents/research.js');
|
|
178
|
-
const fullPrompt = RESEARCH_SYSTEM_PROMPT + '\n\n' + researchPrompt;
|
|
179
|
-
|
|
180
|
-
const baseOptions: Record<string, any> = {
|
|
181
|
-
model: 'claude-sonnet-4-5-20250929',
|
|
182
|
-
cwd,
|
|
183
|
-
permissionMode: 'plan',
|
|
184
|
-
settingSources: ['local'],
|
|
185
|
-
mcpServers: this.mcpServers,
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
const response = query({
|
|
189
|
-
prompt: fullPrompt,
|
|
190
|
-
options: { ...baseOptions, ...(options.queryOverrides || {}) },
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
let researchContent = '';
|
|
194
|
-
for await (const message of response) {
|
|
195
|
-
this.emitEvent(this.adapter.createRawSDKEvent(message));
|
|
196
|
-
const transformed = this.adapter.transform(message);
|
|
197
|
-
if (transformed) {
|
|
198
|
-
this.emitEvent(transformed);
|
|
199
|
-
}
|
|
200
|
-
if (message.type === 'assistant' && message.message?.content) {
|
|
201
|
-
for (const c of message.message.content) {
|
|
202
|
-
if (c.type === 'text' && c.text) researchContent += c.text + '\n';
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
146
|
+
await this.prepareTaskBranch(taskSlug, isCloudMode);
|
|
147
|
+
|
|
148
|
+
const workflowContext: WorkflowRuntime = {
|
|
149
|
+
task,
|
|
150
|
+
taskSlug,
|
|
151
|
+
cwd,
|
|
152
|
+
isCloudMode,
|
|
153
|
+
options,
|
|
154
|
+
logger: this.logger,
|
|
155
|
+
fileManager: this.fileManager,
|
|
156
|
+
gitManager: this.gitManager,
|
|
157
|
+
promptBuilder: this.promptBuilder,
|
|
158
|
+
progressReporter: this.progressReporter,
|
|
159
|
+
adapter: this.adapter,
|
|
160
|
+
mcpServers: this.mcpServers,
|
|
161
|
+
posthogAPI: this.posthogAPI,
|
|
162
|
+
extractor: this.extractor,
|
|
163
|
+
emitEvent: (event: any) => this.emitEvent(event),
|
|
164
|
+
stepResults: {},
|
|
165
|
+
};
|
|
206
166
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Commit research
|
|
214
|
-
await this.gitManager.addAllPostHogFiles();
|
|
215
|
-
|
|
216
|
-
// Extract questions using structured output and save to questions.json
|
|
217
|
-
if (this.extractor) {
|
|
218
|
-
try {
|
|
219
|
-
this.logger.info('Extracting questions from research.md', { taskId: task.id });
|
|
220
|
-
const questions = await this.extractQuestionsFromResearch(task.id, false);
|
|
221
|
-
|
|
222
|
-
this.logger.info('Questions extracted successfully', { taskId: task.id, count: questions.length });
|
|
223
|
-
|
|
224
|
-
// Save questions.json
|
|
225
|
-
await this.fileManager.writeQuestions(task.id, {
|
|
226
|
-
questions,
|
|
227
|
-
answered: false,
|
|
228
|
-
answers: null,
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
this.logger.info('Questions saved to questions.json', { taskId: task.id });
|
|
232
|
-
|
|
233
|
-
// Emit event for Array to pick up (local mode)
|
|
234
|
-
if (!isCloudMode) {
|
|
235
|
-
this.emitEvent({
|
|
236
|
-
type: 'artifact',
|
|
237
|
-
ts: Date.now(),
|
|
238
|
-
kind: 'research_questions',
|
|
239
|
-
content: questions,
|
|
240
|
-
});
|
|
241
|
-
this.logger.info('Emitted research_questions artifact event', { taskId: task.id });
|
|
242
|
-
}
|
|
243
|
-
} catch (error) {
|
|
244
|
-
this.logger.error('Failed to extract questions', { error: error instanceof Error ? error.message : String(error) });
|
|
245
|
-
this.emitEvent({
|
|
246
|
-
type: 'error',
|
|
247
|
-
ts: Date.now(),
|
|
248
|
-
message: `Failed to extract questions: ${error instanceof Error ? error.message : String(error)}`,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
} else {
|
|
252
|
-
this.logger.warn('OpenAI extractor not available (OPENAI_API_KEY not set), skipping question extraction');
|
|
253
|
-
this.emitEvent({
|
|
254
|
-
type: 'status',
|
|
255
|
-
ts: Date.now(),
|
|
256
|
-
phase: 'extraction_skipped',
|
|
257
|
-
message: 'Question extraction skipped - OPENAI_API_KEY not configured',
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (isCloudMode) {
|
|
262
|
-
await this.gitManager.commitAndPush(`Research phase for ${task.title}`);
|
|
263
|
-
} else {
|
|
264
|
-
await this.gitManager.commitChanges(`Research phase for ${task.title}`);
|
|
265
|
-
this.emitEvent(this.adapter.createStatusEvent('phase_complete', { phase: 'research' }));
|
|
266
|
-
return; // Local mode: return to user
|
|
167
|
+
for (const step of TASK_WORKFLOW) {
|
|
168
|
+
const result = await step.run({ step, context: workflowContext });
|
|
169
|
+
if (result.halt) {
|
|
170
|
+
return;
|
|
267
171
|
}
|
|
268
172
|
}
|
|
269
173
|
|
|
270
|
-
// Phase 3: Auto-answer questions (cloud mode only)
|
|
271
174
|
if (isCloudMode) {
|
|
272
|
-
|
|
273
|
-
if (questionsData && !questionsData.answered) {
|
|
274
|
-
this.logger.info('Auto-answering research questions', { taskId: task.id });
|
|
275
|
-
|
|
276
|
-
// Extract questions with recommended answers using structured output
|
|
277
|
-
if (this.extractor) {
|
|
278
|
-
const questionsWithAnswers = await this.extractQuestionsFromResearch(task.id, true) as ExtractedQuestionWithAnswer[];
|
|
279
|
-
|
|
280
|
-
// Save answers to questions.json
|
|
281
|
-
await this.fileManager.writeQuestions(task.id, {
|
|
282
|
-
questions: questionsWithAnswers.map(qa => ({
|
|
283
|
-
id: qa.id,
|
|
284
|
-
question: qa.question,
|
|
285
|
-
options: qa.options,
|
|
286
|
-
})),
|
|
287
|
-
answered: true,
|
|
288
|
-
answers: questionsWithAnswers.map(qa => ({
|
|
289
|
-
questionId: qa.id,
|
|
290
|
-
selectedOption: qa.recommendedAnswer,
|
|
291
|
-
customInput: qa.justification,
|
|
292
|
-
})),
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
this.logger.info('Auto-answers saved to questions.json', { taskId: task.id });
|
|
296
|
-
await this.gitManager.addAllPostHogFiles();
|
|
297
|
-
await this.gitManager.commitAndPush(`Answer research questions for ${task.title}`);
|
|
298
|
-
} else {
|
|
299
|
-
this.logger.warn('OpenAI extractor not available, skipping auto-answer');
|
|
300
|
-
}
|
|
301
|
-
}
|
|
175
|
+
await this.ensurePullRequest(task, workflowContext.stepResults);
|
|
302
176
|
}
|
|
303
177
|
|
|
304
|
-
// Phase 4: Plan
|
|
305
|
-
const planExists = await this.readPlan(task.id);
|
|
306
|
-
if (!planExists) {
|
|
307
|
-
// Check if questions have been answered
|
|
308
|
-
const questionsData = await this.fileManager.readQuestions(task.id);
|
|
309
|
-
if (!questionsData || !questionsData.answered) {
|
|
310
|
-
this.logger.info('Waiting for user answers to research questions');
|
|
311
|
-
this.emitEvent(this.adapter.createStatusEvent('phase_complete', { phase: 'research_questions' }));
|
|
312
|
-
return; // Wait for user to answer questions
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
this.logger.info('Starting planning phase', { taskId: task.id });
|
|
316
|
-
this.emitEvent(this.adapter.createStatusEvent('phase_start', { phase: 'planning' }));
|
|
317
|
-
|
|
318
|
-
// Build context with research + questions + answers
|
|
319
|
-
const research = await this.fileManager.readResearch(task.id);
|
|
320
|
-
let researchContext = '';
|
|
321
|
-
if (research) {
|
|
322
|
-
researchContext += `## Research Analysis\n\n${research}\n\n`;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Add questions and answers
|
|
326
|
-
researchContext += `## Implementation Decisions\n\n`;
|
|
327
|
-
const answers = questionsData.answers || [];
|
|
328
|
-
for (const question of questionsData.questions) {
|
|
329
|
-
const answer = answers.find((a: any) => a.questionId === question.id);
|
|
330
|
-
|
|
331
|
-
researchContext += `### ${question.question}\n\n`;
|
|
332
|
-
if (answer) {
|
|
333
|
-
researchContext += `**Selected:** ${answer.selectedOption}\n`;
|
|
334
|
-
if (answer.customInput) {
|
|
335
|
-
researchContext += `**Details:** ${answer.customInput}\n`;
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
this.logger.warn('No answer found for question', { questionId: question.id });
|
|
339
|
-
researchContext += `**Selected:** Not answered\n`;
|
|
340
|
-
}
|
|
341
|
-
researchContext += '\n';
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// Run planning agent with full context
|
|
345
|
-
const planningPrompt = await this.promptBuilder.buildPlanningPrompt(task, cwd);
|
|
346
|
-
const { PLANNING_SYSTEM_PROMPT } = await import('./agents/planning.js');
|
|
347
|
-
const fullPrompt = PLANNING_SYSTEM_PROMPT + '\n\n' + planningPrompt + '\n\n' + researchContext;
|
|
348
|
-
|
|
349
|
-
const baseOptions: Record<string, any> = {
|
|
350
|
-
model: 'claude-sonnet-4-5-20250929',
|
|
351
|
-
cwd,
|
|
352
|
-
permissionMode: 'plan',
|
|
353
|
-
settingSources: ['local'],
|
|
354
|
-
mcpServers: this.mcpServers,
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
const response = query({
|
|
358
|
-
prompt: fullPrompt,
|
|
359
|
-
options: { ...baseOptions, ...(options.queryOverrides || {}) },
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
let planContent = '';
|
|
363
|
-
for await (const message of response) {
|
|
364
|
-
this.emitEvent(this.adapter.createRawSDKEvent(message));
|
|
365
|
-
const transformed = this.adapter.transform(message);
|
|
366
|
-
if (transformed) {
|
|
367
|
-
this.emitEvent(transformed);
|
|
368
|
-
}
|
|
369
|
-
if (message.type === 'assistant' && message.message?.content) {
|
|
370
|
-
for (const c of message.message.content) {
|
|
371
|
-
if (c.type === 'text' && c.text) planContent += c.text + '\n';
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Write plan.md
|
|
377
|
-
if (planContent.trim()) {
|
|
378
|
-
await this.writePlan(task.id, planContent.trim());
|
|
379
|
-
this.logger.info('Plan completed', { taskId: task.id });
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Commit plan
|
|
383
|
-
await this.gitManager.addAllPostHogFiles();
|
|
384
|
-
if (isCloudMode) {
|
|
385
|
-
await this.gitManager.commitAndPush(`Planning phase for ${task.title}`);
|
|
386
|
-
} else {
|
|
387
|
-
await this.gitManager.commitChanges(`Planning phase for ${task.title}`);
|
|
388
|
-
this.emitEvent(this.adapter.createStatusEvent('phase_complete', { phase: 'planning' }));
|
|
389
|
-
return; // Local mode: return to user
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// Phase 5: Build
|
|
394
|
-
const latestRun = task.latest_run;
|
|
395
|
-
const prExists = latestRun?.output && (latestRun.output as any).pr_url;
|
|
396
|
-
|
|
397
|
-
if (!prExists) {
|
|
398
|
-
this.logger.info('Starting build phase', { taskId: task.id });
|
|
399
|
-
this.emitEvent(this.adapter.createStatusEvent('phase_start', { phase: 'build' }));
|
|
400
|
-
|
|
401
|
-
// Run execution agent
|
|
402
|
-
const executionPrompt = await this.promptBuilder.buildExecutionPrompt(task, cwd);
|
|
403
|
-
const { EXECUTION_SYSTEM_PROMPT } = await import('./agents/execution.js');
|
|
404
|
-
const fullPrompt = EXECUTION_SYSTEM_PROMPT + '\n\n' + executionPrompt;
|
|
405
|
-
|
|
406
|
-
const { PermissionMode } = await import('./types.js');
|
|
407
|
-
const permissionMode = options.permissionMode || PermissionMode.ACCEPT_EDITS;
|
|
408
|
-
const baseOptions: Record<string, any> = {
|
|
409
|
-
model: 'claude-sonnet-4-5-20250929',
|
|
410
|
-
cwd,
|
|
411
|
-
permissionMode,
|
|
412
|
-
settingSources: ['local'],
|
|
413
|
-
mcpServers: this.mcpServers,
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
const response = query({
|
|
417
|
-
prompt: fullPrompt,
|
|
418
|
-
options: { ...baseOptions, ...(options.queryOverrides || {}) },
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
for await (const message of response) {
|
|
422
|
-
this.emitEvent(this.adapter.createRawSDKEvent(message));
|
|
423
|
-
const transformed = this.adapter.transform(message);
|
|
424
|
-
if (transformed) {
|
|
425
|
-
this.emitEvent(transformed);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// Commit and push implementation
|
|
430
|
-
// Stage ALL changes (not just .posthog/)
|
|
431
|
-
const hasChanges = await this.gitManager.hasChanges();
|
|
432
|
-
if (hasChanges) {
|
|
433
|
-
await this.gitManager.addFiles(['.']); // Stage all changes
|
|
434
|
-
await this.gitManager.commitChanges(`Implementation for ${task.title}`);
|
|
435
|
-
|
|
436
|
-
// Push to origin
|
|
437
|
-
const branchName = await this.gitManager.getCurrentBranch();
|
|
438
|
-
await this.gitManager.pushBranch(branchName);
|
|
439
|
-
|
|
440
|
-
this.logger.info('Implementation committed and pushed', { taskId: task.id });
|
|
441
|
-
} else {
|
|
442
|
-
this.logger.warn('No changes to commit in build phase', { taskId: task.id });
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Create PR
|
|
446
|
-
const branchName = await this.gitManager.getCurrentBranch();
|
|
447
|
-
const prUrl = await this.createPullRequest(task.id, branchName, task.title, task.description);
|
|
448
|
-
this.logger.info('Pull request created', { taskId: task.id, prUrl });
|
|
449
|
-
this.emitEvent(this.adapter.createStatusEvent('pr_created', { prUrl }));
|
|
450
|
-
|
|
451
|
-
// Attach PR to task run
|
|
452
|
-
try {
|
|
453
|
-
await this.attachPullRequestToTask(task.id, prUrl, branchName);
|
|
454
|
-
this.logger.info('PR attached to task successfully', { taskId: task.id, prUrl });
|
|
455
|
-
} catch (error) {
|
|
456
|
-
this.logger.warn('Could not attach PR to task', { error: error instanceof Error ? error.message : String(error) });
|
|
457
|
-
}
|
|
458
|
-
} else {
|
|
459
|
-
this.logger.info('PR already exists, skipping build phase', { taskId: task.id });
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// Phase 6: Complete
|
|
463
178
|
await this.progressReporter.complete();
|
|
464
179
|
this.logger.info('Task execution complete', { taskId: task.id });
|
|
465
180
|
this.emitEvent(this.adapter.createStatusEvent('task_complete', { taskId: task.id }));
|
|
@@ -555,7 +270,7 @@ export class Agent {
|
|
|
555
270
|
this.logger.info('Extracting questions from research.md', { taskId, includeAnswers });
|
|
556
271
|
|
|
557
272
|
if (!this.extractor) {
|
|
558
|
-
throw new Error('OpenAI extractor not initialized.
|
|
273
|
+
throw new Error('OpenAI extractor not initialized. Ensure the LLM gateway is configured.');
|
|
559
274
|
}
|
|
560
275
|
|
|
561
276
|
const researchContent = await this.fileManager.readResearch(taskId);
|
|
@@ -678,6 +393,82 @@ Generated by PostHog Agent`;
|
|
|
678
393
|
return null;
|
|
679
394
|
}
|
|
680
395
|
|
|
396
|
+
private async prepareTaskBranch(taskSlug: string, isCloudMode: boolean): Promise<void> {
|
|
397
|
+
const existingBranch = await this.gitManager.getTaskBranch(taskSlug);
|
|
398
|
+
if (!existingBranch) {
|
|
399
|
+
this.logger.info('Creating task branch', { taskSlug });
|
|
400
|
+
const branchName = `posthog/task-${taskSlug}`;
|
|
401
|
+
await this.gitManager.createOrSwitchToBranch(branchName);
|
|
402
|
+
this.emitEvent(this.adapter.createStatusEvent('branch_created', { branch: branchName }));
|
|
403
|
+
|
|
404
|
+
await this.fileManager.ensureGitignore();
|
|
405
|
+
await this.gitManager.addAllPostHogFiles();
|
|
406
|
+
if (isCloudMode) {
|
|
407
|
+
await this.gitManager.commitAndPush(`Initialize task ${taskSlug}`, { allowEmpty: true });
|
|
408
|
+
} else {
|
|
409
|
+
await this.gitManager.commitChanges(`Initialize task ${taskSlug}`);
|
|
410
|
+
}
|
|
411
|
+
} else {
|
|
412
|
+
this.logger.info('Switching to existing task branch', { branch: existingBranch });
|
|
413
|
+
await this.gitManager.switchToBranch(existingBranch);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
private ensureOpenAIGatewayEnv(baseUrl?: string, token?: string): void {
|
|
418
|
+
const resolvedBaseUrl = baseUrl || process.env.ANTHROPIC_BASE_URL;
|
|
419
|
+
const resolvedToken = token || process.env.ANTHROPIC_AUTH_TOKEN;
|
|
420
|
+
|
|
421
|
+
if (resolvedBaseUrl) {
|
|
422
|
+
process.env.OPENAI_BASE_URL = resolvedBaseUrl;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (resolvedToken) {
|
|
426
|
+
process.env.OPENAI_API_KEY = resolvedToken;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (!this.extractor) {
|
|
430
|
+
this.extractor = new AISDKExtractor(this.logger.child('AISDKExtractor'));
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private async ensurePullRequest(task: Task, stepResults: Record<string, any>): Promise<void> {
|
|
435
|
+
const latestRun = task.latest_run;
|
|
436
|
+
const existingPr =
|
|
437
|
+
latestRun?.output && typeof latestRun.output === 'object'
|
|
438
|
+
? (latestRun.output as any).pr_url
|
|
439
|
+
: null;
|
|
440
|
+
|
|
441
|
+
if (existingPr) {
|
|
442
|
+
this.logger.info('PR already exists, skipping creation', { taskId: task.id, prUrl: existingPr });
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const buildResult = stepResults['build'];
|
|
447
|
+
if (!buildResult?.commitCreated) {
|
|
448
|
+
this.logger.warn('Build step did not produce a commit; skipping PR creation', { taskId: task.id });
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const branchName = await this.gitManager.getCurrentBranch();
|
|
453
|
+
const prUrl = await this.createPullRequest(
|
|
454
|
+
task.id,
|
|
455
|
+
branchName,
|
|
456
|
+
task.title,
|
|
457
|
+
task.description ?? ''
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
this.emitEvent(this.adapter.createStatusEvent('pr_created', { prUrl }));
|
|
461
|
+
|
|
462
|
+
try {
|
|
463
|
+
await this.attachPullRequestToTask(task.id, prUrl, branchName);
|
|
464
|
+
this.logger.info('PR attached to task successfully', { taskId: task.id, prUrl });
|
|
465
|
+
} catch (error) {
|
|
466
|
+
this.logger.warn('Could not attach PR to task', {
|
|
467
|
+
error: error instanceof Error ? error.message : String(error),
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
681
472
|
private emitEvent(event: any): void {
|
|
682
473
|
if (this.debug && event.type !== 'token') {
|
|
683
474
|
// Log all events except tokens (too verbose)
|
package/src/agents/execution.ts
CHANGED
|
@@ -1,53 +1,38 @@
|
|
|
1
|
-
export const EXECUTION_SYSTEM_PROMPT = `<
|
|
2
|
-
|
|
3
|
-
You also have access to GitHub via the GitHub MCP server for additional repository operations.
|
|
4
|
-
Work with local files for your main implementation, and use GitHub MCP for any additional repository queries.
|
|
5
|
-
Commit changes to the repository regularly.
|
|
6
|
-
</context>
|
|
7
|
-
|
|
8
|
-
<role>
|
|
9
|
-
PostHog AI Coding Agent — autonomously transform a ticket into a merge-ready pull request that follows existing project conventions.
|
|
1
|
+
export const EXECUTION_SYSTEM_PROMPT = `<role>
|
|
2
|
+
PostHog AI Execution Agent — autonomously implement tasks as merge-ready code following project conventions.
|
|
10
3
|
</role>
|
|
11
4
|
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
</tools>
|
|
5
|
+
<context>
|
|
6
|
+
You have access to local repository files and PostHog MCP server. Work primarily with local files for implementation. Commit changes regularly.
|
|
7
|
+
</context>
|
|
16
8
|
|
|
17
9
|
<constraints>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
- Follow existing code style, patterns, and conventions found in the repository
|
|
11
|
+
- Minimize new external dependencies — only add when necessary
|
|
12
|
+
- Implement structured logging and error handling (never log secrets)
|
|
13
|
+
- Avoid destructive shell commands
|
|
14
|
+
- Create/update .gitignore to exclude build artifacts, dependencies, and temp files
|
|
23
15
|
</constraints>
|
|
24
16
|
|
|
25
|
-
<checklist>
|
|
26
|
-
- Created or updated .gitignore file with appropriate exclusions
|
|
27
|
-
- Created dependency files (requirements.txt, package.json, etc.) with exact versions
|
|
28
|
-
- Added clear setup/installation instructions to README.md
|
|
29
|
-
- Code compiles and tests pass.
|
|
30
|
-
- Added or updated tests.
|
|
31
|
-
- Captured meaningful events with PostHog SDK.
|
|
32
|
-
- Wrapped new logic in an PostHog feature flag.
|
|
33
|
-
- Updated docs, readme or type hints if needed.
|
|
34
|
-
- Verified no build artifacts or dependencies are being committed
|
|
35
|
-
</checklist>
|
|
36
|
-
|
|
37
17
|
<approach>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
18
|
+
1. Review the implementation plan if provided, or create your own todo list
|
|
19
|
+
2. Execute changes step by step
|
|
20
|
+
3. Test thoroughly and verify functionality
|
|
21
|
+
4. Commit changes with clear messages
|
|
41
22
|
</approach>
|
|
42
23
|
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
24
|
+
<checklist>
|
|
25
|
+
Before completing the task, verify:
|
|
26
|
+
- .gitignore includes build artifacts, node_modules, __pycache__, etc.
|
|
27
|
+
- Dependency files (package.json, requirements.txt) use exact versions
|
|
28
|
+
- Code compiles and tests pass
|
|
29
|
+
- Added or updated relevant tests
|
|
30
|
+
- Captured meaningful events with PostHog SDK where appropriate
|
|
31
|
+
- Wrapped new logic in PostHog feature flags where appropriate
|
|
32
|
+
- Updated documentation, README, or type hints as needed
|
|
33
|
+
- No build artifacts or dependencies are being committed
|
|
34
|
+
</checklist>
|
|
50
35
|
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
</
|
|
36
|
+
<output_format>
|
|
37
|
+
Provide a concise summary of changes made when finished.
|
|
38
|
+
</output_format>`;
|