@posthog/agent 1.24.0 → 1.24.2
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/LICENSE +33 -0
- package/dist/index.d.ts +11 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/src/adapters/claude/claude-adapter.d.ts +3 -3
- package/dist/src/adapters/claude/claude-adapter.d.ts.map +1 -1
- package/dist/src/adapters/claude/claude-adapter.js +111 -156
- package/dist/src/adapters/claude/claude-adapter.js.map +1 -1
- package/dist/src/adapters/claude/tool-mapper.d.ts +1 -1
- package/dist/src/adapters/claude/tool-mapper.d.ts.map +1 -1
- package/dist/src/adapters/claude/tool-mapper.js.map +1 -1
- package/dist/src/adapters/types.d.ts +1 -1
- package/dist/src/adapters/types.d.ts.map +1 -1
- package/dist/src/agent.d.ts +7 -7
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +85 -143
- package/dist/src/agent.js.map +1 -1
- package/dist/src/agents/execution.js.map +1 -1
- package/dist/src/agents/planning.js.map +1 -1
- package/dist/src/agents/research.js.map +1 -1
- package/dist/src/file-manager.d.ts +4 -4
- package/dist/src/file-manager.d.ts.map +1 -1
- package/dist/src/file-manager.js +58 -59
- package/dist/src/file-manager.js.map +1 -1
- package/dist/src/git-manager.d.ts +1 -1
- package/dist/src/git-manager.d.ts.map +1 -1
- package/dist/src/git-manager.js +70 -87
- package/dist/src/git-manager.js.map +1 -1
- package/dist/src/posthog-api.d.ts +3 -2
- package/dist/src/posthog-api.d.ts.map +1 -1
- package/dist/src/posthog-api.js +22 -22
- package/dist/src/posthog-api.js.map +1 -1
- package/dist/src/prompt-builder.d.ts +3 -3
- package/dist/src/prompt-builder.d.ts.map +1 -1
- package/dist/src/prompt-builder.js +93 -123
- package/dist/src/prompt-builder.js.map +1 -1
- package/dist/src/task-manager.d.ts +4 -4
- package/dist/src/task-manager.d.ts.map +1 -1
- package/dist/src/task-manager.js +18 -19
- package/dist/src/task-manager.js.map +1 -1
- package/dist/src/task-progress-reporter.d.ts +4 -3
- package/dist/src/task-progress-reporter.d.ts.map +1 -1
- package/dist/src/task-progress-reporter.js +54 -59
- package/dist/src/task-progress-reporter.js.map +1 -1
- package/dist/src/template-manager.d.ts +1 -1
- package/dist/src/template-manager.d.ts.map +1 -1
- package/dist/src/template-manager.js +28 -30
- package/dist/src/template-manager.js.map +1 -1
- package/dist/src/todo-manager.d.ts +3 -3
- package/dist/src/todo-manager.d.ts.map +1 -1
- package/dist/src/todo-manager.js +24 -29
- package/dist/src/todo-manager.js.map +1 -1
- package/dist/src/tools/registry.d.ts +1 -1
- package/dist/src/tools/registry.js +60 -60
- package/dist/src/tools/registry.js.map +1 -1
- package/dist/src/tools/types.d.ts +31 -31
- package/dist/src/types.d.ts +33 -33
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.d.ts.map +1 -1
- package/dist/src/utils/logger.js +8 -8
- package/dist/src/utils/logger.js.map +1 -1
- package/dist/src/workflow/config.d.ts +1 -1
- package/dist/src/workflow/config.d.ts.map +1 -1
- package/dist/src/workflow/config.js +18 -18
- package/dist/src/workflow/config.js.map +1 -1
- package/dist/src/workflow/steps/build.d.ts +1 -1
- package/dist/src/workflow/steps/build.d.ts.map +1 -1
- package/dist/src/workflow/steps/build.js +38 -46
- package/dist/src/workflow/steps/build.js.map +1 -1
- package/dist/src/workflow/steps/finalize.d.ts +1 -1
- package/dist/src/workflow/steps/finalize.d.ts.map +1 -1
- package/dist/src/workflow/steps/finalize.js +48 -54
- package/dist/src/workflow/steps/finalize.js.map +1 -1
- package/dist/src/workflow/steps/plan.d.ts +1 -1
- package/dist/src/workflow/steps/plan.d.ts.map +1 -1
- package/dist/src/workflow/steps/plan.js +46 -58
- package/dist/src/workflow/steps/plan.js.map +1 -1
- package/dist/src/workflow/steps/research.d.ts +1 -1
- package/dist/src/workflow/steps/research.d.ts.map +1 -1
- package/dist/src/workflow/steps/research.js +56 -68
- package/dist/src/workflow/steps/research.js.map +1 -1
- package/dist/src/workflow/types.d.ts +12 -12
- package/dist/src/workflow/types.d.ts.map +1 -1
- package/dist/src/workflow/utils.d.ts +1 -1
- package/dist/src/workflow/utils.d.ts.map +1 -1
- package/dist/src/workflow/utils.js +4 -7
- package/dist/src/workflow/utils.js.map +1 -1
- package/package.json +6 -6
- package/src/adapters/claude/claude-adapter.ts +168 -220
- package/src/adapters/claude/tool-mapper.ts +2 -2
- package/src/adapters/types.ts +1 -1
- package/src/agent.ts +444 -579
- package/src/agents/execution.ts +1 -1
- package/src/agents/planning.ts +1 -1
- package/src/agents/research.ts +1 -0
- package/src/file-manager.ts +63 -64
- package/src/git-manager.ts +88 -144
- package/src/posthog-api.ts +82 -122
- package/src/prompt-builder.ts +135 -180
- package/src/task-manager.ts +30 -38
- package/src/task-progress-reporter.ts +59 -70
- package/src/template-manager.ts +45 -98
- package/src/todo-manager.ts +30 -35
- package/src/tools/registry.ts +62 -62
- package/src/tools/types.ts +36 -36
- package/src/types.ts +71 -93
- package/src/utils/logger.ts +56 -62
- package/src/workflow/config.ts +48 -48
- package/src/workflow/steps/build.ts +113 -122
- package/src/workflow/steps/finalize.ts +182 -214
- package/src/workflow/steps/plan.ts +131 -151
- package/src/workflow/steps/research.ts +186 -205
- package/src/workflow/types.ts +36 -38
- package/src/workflow/utils.ts +34 -37
package/src/git-manager.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { exec } from
|
|
2
|
-
import { promisify } from
|
|
3
|
-
import { Logger } from
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { Logger } from './utils/logger.js';
|
|
4
4
|
|
|
5
5
|
const execAsync = promisify(exec);
|
|
6
6
|
|
|
@@ -27,23 +27,20 @@ export class GitManager {
|
|
|
27
27
|
this.repositoryPath = config.repositoryPath;
|
|
28
28
|
this.authorName = config.authorName;
|
|
29
29
|
this.authorEmail = config.authorEmail;
|
|
30
|
-
this.logger =
|
|
31
|
-
config.logger || new Logger({ debug: false, prefix: "[GitManager]" });
|
|
30
|
+
this.logger = config.logger || new Logger({ debug: false, prefix: '[GitManager]' });
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
private escapeShellArg(str: string): string {
|
|
35
34
|
return str
|
|
36
|
-
.replace(/\\/g,
|
|
35
|
+
.replace(/\\/g, '\\\\')
|
|
37
36
|
.replace(/"/g, '\\"')
|
|
38
|
-
.replace(/`/g,
|
|
39
|
-
.replace(/\$/g,
|
|
37
|
+
.replace(/`/g, '\\`')
|
|
38
|
+
.replace(/\$/g, '\\$');
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
private async runGitCommand(command: string): Promise<string> {
|
|
43
42
|
try {
|
|
44
|
-
const { stdout } = await execAsync(
|
|
45
|
-
`cd "${this.repositoryPath}" && git ${command}`,
|
|
46
|
-
);
|
|
43
|
+
const { stdout } = await execAsync(`cd "${this.repositoryPath}" && git ${command}`);
|
|
47
44
|
return stdout.trim();
|
|
48
45
|
} catch (error) {
|
|
49
46
|
throw new Error(`Git command failed: ${command}\n${error}`);
|
|
@@ -52,9 +49,7 @@ export class GitManager {
|
|
|
52
49
|
|
|
53
50
|
private async runCommand(command: string): Promise<string> {
|
|
54
51
|
try {
|
|
55
|
-
const { stdout } = await execAsync(
|
|
56
|
-
`cd "${this.repositoryPath}" && ${command}`,
|
|
57
|
-
);
|
|
52
|
+
const { stdout } = await execAsync(`cd "${this.repositoryPath}" && ${command}`);
|
|
58
53
|
return stdout.trim();
|
|
59
54
|
} catch (error) {
|
|
60
55
|
throw new Error(`Command failed: ${command}\n${error}`);
|
|
@@ -63,7 +58,7 @@ export class GitManager {
|
|
|
63
58
|
|
|
64
59
|
async isGitRepository(): Promise<boolean> {
|
|
65
60
|
try {
|
|
66
|
-
await this.runGitCommand(
|
|
61
|
+
await this.runGitCommand('rev-parse --git-dir');
|
|
67
62
|
return true;
|
|
68
63
|
} catch {
|
|
69
64
|
return false;
|
|
@@ -71,26 +66,22 @@ export class GitManager {
|
|
|
71
66
|
}
|
|
72
67
|
|
|
73
68
|
async getCurrentBranch(): Promise<string> {
|
|
74
|
-
return await this.runGitCommand(
|
|
69
|
+
return await this.runGitCommand('branch --show-current');
|
|
75
70
|
}
|
|
76
71
|
|
|
77
72
|
async getDefaultBranch(): Promise<string> {
|
|
78
73
|
try {
|
|
79
74
|
// Try to get the default branch from remote
|
|
80
|
-
const remoteBranch = await this.runGitCommand(
|
|
81
|
-
|
|
82
|
-
);
|
|
83
|
-
return remoteBranch.replace("refs/remotes/origin/", "");
|
|
75
|
+
const remoteBranch = await this.runGitCommand('symbolic-ref refs/remotes/origin/HEAD');
|
|
76
|
+
return remoteBranch.replace('refs/remotes/origin/', '');
|
|
84
77
|
} catch {
|
|
85
78
|
// Fallback: check if main exists, otherwise use master
|
|
86
|
-
if (await this.branchExists(
|
|
87
|
-
return
|
|
88
|
-
} else if (await this.branchExists(
|
|
89
|
-
return
|
|
79
|
+
if (await this.branchExists('main')) {
|
|
80
|
+
return 'main';
|
|
81
|
+
} else if (await this.branchExists('master')) {
|
|
82
|
+
return 'master';
|
|
90
83
|
} else {
|
|
91
|
-
throw new Error(
|
|
92
|
-
"Cannot determine default branch. No main or master branch found.",
|
|
93
|
-
);
|
|
84
|
+
throw new Error('Cannot determine default branch. No main or master branch found.');
|
|
94
85
|
}
|
|
95
86
|
}
|
|
96
87
|
}
|
|
@@ -105,7 +96,7 @@ export class GitManager {
|
|
|
105
96
|
}
|
|
106
97
|
|
|
107
98
|
async createBranch(branchName: string, baseBranch?: string): Promise<void> {
|
|
108
|
-
const base = baseBranch ||
|
|
99
|
+
const base = baseBranch || await this.getCurrentBranch();
|
|
109
100
|
await this.runGitCommand(`checkout -b ${branchName} ${base}`);
|
|
110
101
|
}
|
|
111
102
|
|
|
@@ -118,31 +109,25 @@ export class GitManager {
|
|
|
118
109
|
const defaultBranch = await this.getDefaultBranch();
|
|
119
110
|
|
|
120
111
|
if (currentBranch === defaultBranch) {
|
|
121
|
-
this.logger.debug(
|
|
112
|
+
this.logger.debug('Already on default branch', { branch: defaultBranch });
|
|
122
113
|
return true;
|
|
123
114
|
}
|
|
124
115
|
|
|
125
116
|
if (await this.hasChanges()) {
|
|
126
|
-
this.logger.warn(
|
|
117
|
+
this.logger.warn('Skipping branch reset - uncommitted changes present', {
|
|
127
118
|
currentBranch,
|
|
128
|
-
defaultBranch
|
|
119
|
+
defaultBranch
|
|
129
120
|
});
|
|
130
121
|
return false;
|
|
131
122
|
}
|
|
132
123
|
|
|
133
124
|
await this.switchToBranch(defaultBranch);
|
|
134
|
-
this.logger.info(
|
|
135
|
-
from: currentBranch,
|
|
136
|
-
to: defaultBranch,
|
|
137
|
-
});
|
|
125
|
+
this.logger.info('Reset to default branch', { from: currentBranch, to: defaultBranch });
|
|
138
126
|
return true;
|
|
139
127
|
}
|
|
140
128
|
|
|
141
|
-
async createOrSwitchToBranch(
|
|
142
|
-
|
|
143
|
-
baseBranch?: string,
|
|
144
|
-
): Promise<void> {
|
|
145
|
-
await this.ensureCleanWorkingDirectory("switching branches");
|
|
129
|
+
async createOrSwitchToBranch(branchName: string, baseBranch?: string): Promise<void> {
|
|
130
|
+
await this.ensureCleanWorkingDirectory('switching branches');
|
|
146
131
|
|
|
147
132
|
const exists = await this.branchExists(branchName);
|
|
148
133
|
if (exists) {
|
|
@@ -153,41 +138,38 @@ export class GitManager {
|
|
|
153
138
|
}
|
|
154
139
|
|
|
155
140
|
async addFiles(paths: string[]): Promise<void> {
|
|
156
|
-
const pathList = paths.map(
|
|
141
|
+
const pathList = paths.map(p => `"${this.escapeShellArg(p)}"`).join(' ');
|
|
157
142
|
await this.runGitCommand(`add ${pathList}`);
|
|
158
143
|
}
|
|
159
144
|
|
|
160
145
|
async addAllPostHogFiles(): Promise<void> {
|
|
161
146
|
try {
|
|
162
147
|
// Use -A flag to add all changes (including new files) and ignore errors if directory is empty
|
|
163
|
-
await this.runGitCommand(
|
|
148
|
+
await this.runGitCommand('add -A .posthog/');
|
|
164
149
|
} catch (error) {
|
|
165
150
|
// If the directory doesn't exist or has no files, that's fine - just log and continue
|
|
166
|
-
this.logger.debug(
|
|
151
|
+
this.logger.debug('No PostHog files to add', { error });
|
|
167
152
|
}
|
|
168
153
|
}
|
|
169
154
|
|
|
170
|
-
async commitChanges(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
authorEmail?: string;
|
|
175
|
-
},
|
|
176
|
-
): Promise<string> {
|
|
155
|
+
async commitChanges(message: string, options?: {
|
|
156
|
+
authorName?: string;
|
|
157
|
+
authorEmail?: string;
|
|
158
|
+
}): Promise<string> {
|
|
177
159
|
const command = this.buildCommitCommand(message, options);
|
|
178
160
|
return await this.runGitCommand(command);
|
|
179
161
|
}
|
|
180
162
|
|
|
181
163
|
async hasChanges(): Promise<boolean> {
|
|
182
164
|
try {
|
|
183
|
-
const status = await this.runGitCommand(
|
|
165
|
+
const status = await this.runGitCommand('status --porcelain');
|
|
184
166
|
if (!status || status.trim().length === 0) {
|
|
185
167
|
return false;
|
|
186
168
|
}
|
|
187
169
|
|
|
188
|
-
const lines = status.split(
|
|
170
|
+
const lines = status.split('\n').filter(line => {
|
|
189
171
|
const trimmed = line.trim();
|
|
190
|
-
return trimmed.length > 0 && !trimmed.includes(
|
|
172
|
+
return trimmed.length > 0 && !trimmed.includes('.posthog/');
|
|
191
173
|
});
|
|
192
174
|
|
|
193
175
|
return lines.length > 0;
|
|
@@ -198,7 +180,7 @@ export class GitManager {
|
|
|
198
180
|
|
|
199
181
|
async hasStagedChanges(): Promise<boolean> {
|
|
200
182
|
try {
|
|
201
|
-
const status = await this.runGitCommand(
|
|
183
|
+
const status = await this.runGitCommand('diff --cached --name-only');
|
|
202
184
|
return status.length > 0;
|
|
203
185
|
} catch {
|
|
204
186
|
return false;
|
|
@@ -208,14 +190,12 @@ export class GitManager {
|
|
|
208
190
|
// Helper: Centralized safety check for uncommitted changes
|
|
209
191
|
private async ensureCleanWorkingDirectory(operation: string): Promise<void> {
|
|
210
192
|
if (await this.hasChanges()) {
|
|
211
|
-
throw new Error(
|
|
212
|
-
`Uncommitted changes detected. Please commit or stash changes before ${operation}.`,
|
|
213
|
-
);
|
|
193
|
+
throw new Error(`Uncommitted changes detected. Please commit or stash changes before ${operation}.`);
|
|
214
194
|
}
|
|
215
195
|
}
|
|
216
196
|
|
|
217
197
|
private async generateUniqueBranchName(baseName: string): Promise<string> {
|
|
218
|
-
if (!
|
|
198
|
+
if (!await this.branchExists(baseName)) {
|
|
219
199
|
return baseName;
|
|
220
200
|
}
|
|
221
201
|
|
|
@@ -233,25 +213,18 @@ export class GitManager {
|
|
|
233
213
|
const currentBranch = await this.getCurrentBranch();
|
|
234
214
|
|
|
235
215
|
if (currentBranch !== defaultBranch) {
|
|
236
|
-
await this.ensureCleanWorkingDirectory(
|
|
216
|
+
await this.ensureCleanWorkingDirectory('switching to default branch');
|
|
237
217
|
await this.switchToBranch(defaultBranch);
|
|
238
218
|
}
|
|
239
219
|
|
|
240
220
|
return defaultBranch;
|
|
241
221
|
}
|
|
242
222
|
|
|
243
|
-
private buildCommitCommand(
|
|
244
|
-
message: string,
|
|
245
|
-
options?: {
|
|
246
|
-
allowEmpty?: boolean;
|
|
247
|
-
authorName?: string;
|
|
248
|
-
authorEmail?: string;
|
|
249
|
-
},
|
|
250
|
-
): string {
|
|
223
|
+
private buildCommitCommand(message: string, options?: { allowEmpty?: boolean; authorName?: string; authorEmail?: string }): string {
|
|
251
224
|
let command = `commit -m "${this.escapeShellArg(message)}"`;
|
|
252
225
|
|
|
253
226
|
if (options?.allowEmpty) {
|
|
254
|
-
command +=
|
|
227
|
+
command += ' --allow-empty';
|
|
255
228
|
}
|
|
256
229
|
|
|
257
230
|
const authorName = options?.authorName || this.authorName;
|
|
@@ -266,14 +239,14 @@ export class GitManager {
|
|
|
266
239
|
|
|
267
240
|
async getRemoteUrl(): Promise<string | null> {
|
|
268
241
|
try {
|
|
269
|
-
return await this.runGitCommand(
|
|
242
|
+
return await this.runGitCommand('remote get-url origin');
|
|
270
243
|
} catch {
|
|
271
244
|
return null;
|
|
272
245
|
}
|
|
273
246
|
}
|
|
274
247
|
|
|
275
248
|
async pushBranch(branchName: string, force: boolean = false): Promise<void> {
|
|
276
|
-
const forceFlag = force ?
|
|
249
|
+
const forceFlag = force ? '--force' : '';
|
|
277
250
|
await this.runGitCommand(`push ${forceFlag} -u origin ${branchName}`);
|
|
278
251
|
}
|
|
279
252
|
|
|
@@ -292,11 +265,11 @@ export class GitManager {
|
|
|
292
265
|
push?: boolean;
|
|
293
266
|
}) => Promise<{ commitCreated: boolean; pushedBranch: boolean }>;
|
|
294
267
|
}> {
|
|
295
|
-
const initialSha = await this.getCommitSha(
|
|
268
|
+
const initialSha = await this.getCommitSha('HEAD');
|
|
296
269
|
|
|
297
270
|
return {
|
|
298
271
|
finalize: async (options) => {
|
|
299
|
-
const currentSha = await this.getCommitSha(
|
|
272
|
+
const currentSha = await this.getCommitSha('HEAD');
|
|
300
273
|
const externalCommitsCreated = initialSha !== currentSha;
|
|
301
274
|
const hasUncommittedChanges = await this.hasChanges();
|
|
302
275
|
|
|
@@ -309,7 +282,7 @@ export class GitManager {
|
|
|
309
282
|
|
|
310
283
|
// Commit any remaining uncommitted changes
|
|
311
284
|
if (hasUncommittedChanges) {
|
|
312
|
-
await this.runGitCommand(
|
|
285
|
+
await this.runGitCommand('add .');
|
|
313
286
|
const hasStagedChanges = await this.hasStagedChanges();
|
|
314
287
|
|
|
315
288
|
if (hasStagedChanges) {
|
|
@@ -324,13 +297,11 @@ export class GitManager {
|
|
|
324
297
|
const currentBranch = await this.getCurrentBranch();
|
|
325
298
|
await this.pushBranch(currentBranch);
|
|
326
299
|
pushedBranch = true;
|
|
327
|
-
this.logger.info(
|
|
328
|
-
branch: currentBranch,
|
|
329
|
-
});
|
|
300
|
+
this.logger.info('Pushed branch after operation', { branch: currentBranch });
|
|
330
301
|
}
|
|
331
302
|
|
|
332
303
|
return { commitCreated, pushedBranch };
|
|
333
|
-
}
|
|
304
|
+
}
|
|
334
305
|
};
|
|
335
306
|
}
|
|
336
307
|
|
|
@@ -340,10 +311,10 @@ export class GitManager {
|
|
|
340
311
|
// Ensure we're on default branch before creating task branch
|
|
341
312
|
const defaultBranch = await this.ensureOnDefaultBranch();
|
|
342
313
|
|
|
343
|
-
this.logger.info(
|
|
314
|
+
this.logger.info('Creating task branch from default branch', {
|
|
344
315
|
branchName,
|
|
345
316
|
taskSlug,
|
|
346
|
-
baseBranch: defaultBranch
|
|
317
|
+
baseBranch: defaultBranch
|
|
347
318
|
});
|
|
348
319
|
|
|
349
320
|
await this.createOrSwitchToBranch(branchName, defaultBranch);
|
|
@@ -351,35 +322,26 @@ export class GitManager {
|
|
|
351
322
|
return branchName;
|
|
352
323
|
}
|
|
353
324
|
|
|
354
|
-
async createTaskPlanningBranch(
|
|
355
|
-
taskId: string,
|
|
356
|
-
baseBranch?: string,
|
|
357
|
-
): Promise<string> {
|
|
325
|
+
async createTaskPlanningBranch(taskId: string, baseBranch?: string): Promise<string> {
|
|
358
326
|
const baseName = `posthog/task-${taskId}-planning`;
|
|
359
327
|
const branchName = await this.generateUniqueBranchName(baseName);
|
|
360
328
|
|
|
361
|
-
this.logger.debug(
|
|
362
|
-
branchName,
|
|
363
|
-
taskId,
|
|
364
|
-
});
|
|
329
|
+
this.logger.debug('Creating unique planning branch', { branchName, taskId });
|
|
365
330
|
|
|
366
|
-
const base = baseBranch ||
|
|
331
|
+
const base = baseBranch || await this.ensureOnDefaultBranch();
|
|
367
332
|
await this.createBranch(branchName, base);
|
|
368
333
|
|
|
369
334
|
return branchName;
|
|
370
335
|
}
|
|
371
336
|
|
|
372
|
-
async createTaskImplementationBranch(
|
|
373
|
-
taskId: string,
|
|
374
|
-
planningBranchName?: string,
|
|
375
|
-
): Promise<string> {
|
|
337
|
+
async createTaskImplementationBranch(taskId: string, planningBranchName?: string): Promise<string> {
|
|
376
338
|
const baseName = `posthog/task-${taskId}-implementation`;
|
|
377
339
|
const branchName = await this.generateUniqueBranchName(baseName);
|
|
378
340
|
|
|
379
|
-
this.logger.debug(
|
|
341
|
+
this.logger.debug('Creating unique implementation branch', {
|
|
380
342
|
branchName,
|
|
381
343
|
taskId,
|
|
382
|
-
currentBranch: await this.getCurrentBranch()
|
|
344
|
+
currentBranch: await this.getCurrentBranch()
|
|
383
345
|
});
|
|
384
346
|
|
|
385
347
|
// Determine base branch: explicit param > current planning branch > default
|
|
@@ -387,24 +349,21 @@ export class GitManager {
|
|
|
387
349
|
|
|
388
350
|
if (!baseBranch) {
|
|
389
351
|
const currentBranch = await this.getCurrentBranch();
|
|
390
|
-
if (currentBranch.includes(
|
|
352
|
+
if (currentBranch.includes('-planning')) {
|
|
391
353
|
baseBranch = currentBranch;
|
|
392
|
-
this.logger.debug(
|
|
354
|
+
this.logger.debug('Using current planning branch', { baseBranch });
|
|
393
355
|
} else {
|
|
394
356
|
baseBranch = await this.ensureOnDefaultBranch();
|
|
395
|
-
this.logger.debug(
|
|
357
|
+
this.logger.debug('Using default branch', { baseBranch });
|
|
396
358
|
}
|
|
397
359
|
}
|
|
398
360
|
|
|
399
|
-
this.logger.debug(
|
|
400
|
-
baseBranch,
|
|
401
|
-
branchName,
|
|
402
|
-
});
|
|
361
|
+
this.logger.debug('Creating implementation branch from base', { baseBranch, branchName });
|
|
403
362
|
await this.createBranch(branchName, baseBranch);
|
|
404
363
|
|
|
405
|
-
this.logger.info(
|
|
364
|
+
this.logger.info('Implementation branch created', {
|
|
406
365
|
branchName,
|
|
407
|
-
currentBranch: await this.getCurrentBranch()
|
|
366
|
+
currentBranch: await this.getCurrentBranch()
|
|
408
367
|
});
|
|
409
368
|
|
|
410
369
|
return branchName;
|
|
@@ -412,16 +371,16 @@ export class GitManager {
|
|
|
412
371
|
|
|
413
372
|
async commitPlan(taskId: string, taskTitle: string): Promise<string> {
|
|
414
373
|
const currentBranch = await this.getCurrentBranch();
|
|
415
|
-
this.logger.debug(
|
|
374
|
+
this.logger.debug('Committing plan', { taskId, currentBranch });
|
|
416
375
|
|
|
417
376
|
await this.addAllPostHogFiles();
|
|
418
377
|
|
|
419
378
|
const hasChanges = await this.hasStagedChanges();
|
|
420
|
-
this.logger.debug(
|
|
379
|
+
this.logger.debug('Checking for staged changes', { hasChanges });
|
|
421
380
|
|
|
422
381
|
if (!hasChanges) {
|
|
423
|
-
this.logger.info(
|
|
424
|
-
return
|
|
382
|
+
this.logger.info('No plan changes to commit', { taskId });
|
|
383
|
+
return 'No changes to commit';
|
|
425
384
|
}
|
|
426
385
|
|
|
427
386
|
const message = `📋 Add plan for task: ${taskTitle}
|
|
@@ -433,21 +392,17 @@ This commit contains the implementation plan and supporting documentation
|
|
|
433
392
|
for the task. Review the plan before proceeding with implementation.`;
|
|
434
393
|
|
|
435
394
|
const result = await this.commitChanges(message);
|
|
436
|
-
this.logger.info(
|
|
395
|
+
this.logger.info('Plan committed', { taskId, taskTitle });
|
|
437
396
|
return result;
|
|
438
397
|
}
|
|
439
398
|
|
|
440
|
-
async commitImplementation(
|
|
441
|
-
|
|
442
|
-
taskTitle: string,
|
|
443
|
-
planSummary?: string,
|
|
444
|
-
): Promise<string> {
|
|
445
|
-
await this.runGitCommand("add .");
|
|
399
|
+
async commitImplementation(taskId: string, taskTitle: string, planSummary?: string): Promise<string> {
|
|
400
|
+
await this.runGitCommand('add .');
|
|
446
401
|
|
|
447
402
|
const hasChanges = await this.hasStagedChanges();
|
|
448
403
|
if (!hasChanges) {
|
|
449
|
-
this.logger.warn(
|
|
450
|
-
return
|
|
404
|
+
this.logger.warn('No implementation changes to commit', { taskId });
|
|
405
|
+
return 'No changes to commit';
|
|
451
406
|
}
|
|
452
407
|
|
|
453
408
|
let message = `✨ Implement task: ${taskTitle}
|
|
@@ -462,15 +417,12 @@ Generated by PostHog Agent`;
|
|
|
462
417
|
message += `\n\nThis commit implements the changes described in the task plan.`;
|
|
463
418
|
|
|
464
419
|
const result = await this.commitChanges(message);
|
|
465
|
-
this.logger.info(
|
|
420
|
+
this.logger.info('Implementation committed', { taskId, taskTitle });
|
|
466
421
|
return result;
|
|
467
422
|
}
|
|
468
423
|
|
|
469
|
-
async deleteBranch(
|
|
470
|
-
|
|
471
|
-
force: boolean = false,
|
|
472
|
-
): Promise<void> {
|
|
473
|
-
const forceFlag = force ? "-D" : "-d";
|
|
424
|
+
async deleteBranch(branchName: string, force: boolean = false): Promise<void> {
|
|
425
|
+
const forceFlag = force ? '-D' : '-d';
|
|
474
426
|
await this.runGitCommand(`branch ${forceFlag} ${branchName}`);
|
|
475
427
|
}
|
|
476
428
|
|
|
@@ -485,15 +437,15 @@ Generated by PostHog Agent`;
|
|
|
485
437
|
return {
|
|
486
438
|
name: branchName,
|
|
487
439
|
exists,
|
|
488
|
-
isCurrentBranch: branchName === currentBranch
|
|
440
|
+
isCurrentBranch: branchName === currentBranch
|
|
489
441
|
};
|
|
490
442
|
}
|
|
491
443
|
|
|
492
|
-
async getCommitSha(ref: string =
|
|
444
|
+
async getCommitSha(ref: string = 'HEAD'): Promise<string> {
|
|
493
445
|
return await this.runGitCommand(`rev-parse ${ref}`);
|
|
494
446
|
}
|
|
495
447
|
|
|
496
|
-
async getCommitMessage(ref: string =
|
|
448
|
+
async getCommitMessage(ref: string = 'HEAD'): Promise<string> {
|
|
497
449
|
return await this.runGitCommand(`log -1 --pretty=%B ${ref}`);
|
|
498
450
|
}
|
|
499
451
|
|
|
@@ -501,11 +453,11 @@ Generated by PostHog Agent`;
|
|
|
501
453
|
branchName: string,
|
|
502
454
|
title: string,
|
|
503
455
|
body: string,
|
|
504
|
-
baseBranch?: string
|
|
456
|
+
baseBranch?: string
|
|
505
457
|
): Promise<string> {
|
|
506
458
|
const currentBranch = await this.getCurrentBranch();
|
|
507
459
|
if (currentBranch !== branchName) {
|
|
508
|
-
await this.ensureCleanWorkingDirectory(
|
|
460
|
+
await this.ensureCleanWorkingDirectory('creating PR');
|
|
509
461
|
await this.switchToBranch(branchName);
|
|
510
462
|
}
|
|
511
463
|
|
|
@@ -528,35 +480,30 @@ Generated by PostHog Agent`;
|
|
|
528
480
|
async getTaskBranch(taskSlug: string): Promise<string | null> {
|
|
529
481
|
try {
|
|
530
482
|
// Get all branches matching the task slug pattern
|
|
531
|
-
const branches = await this.runGitCommand(
|
|
483
|
+
const branches = await this.runGitCommand('branch --list --all');
|
|
532
484
|
const branchPattern = `posthog/task-${taskSlug}`;
|
|
533
|
-
|
|
485
|
+
|
|
534
486
|
// Look for exact match or with counter suffix
|
|
535
|
-
const lines = branches
|
|
536
|
-
.split("\n")
|
|
537
|
-
.map((l) => l.trim().replace(/^\*\s+/, ""));
|
|
487
|
+
const lines = branches.split('\n').map(l => l.trim().replace(/^\*\s+/, ''));
|
|
538
488
|
for (const line of lines) {
|
|
539
|
-
const cleanBranch = line.replace(
|
|
489
|
+
const cleanBranch = line.replace('remotes/origin/', '');
|
|
540
490
|
if (cleanBranch.startsWith(branchPattern)) {
|
|
541
491
|
return cleanBranch;
|
|
542
492
|
}
|
|
543
493
|
}
|
|
544
|
-
|
|
494
|
+
|
|
545
495
|
return null;
|
|
546
496
|
} catch (error) {
|
|
547
|
-
this.logger.debug(
|
|
497
|
+
this.logger.debug('Failed to get task branch', { taskSlug, error });
|
|
548
498
|
return null;
|
|
549
499
|
}
|
|
550
500
|
}
|
|
551
501
|
|
|
552
|
-
async commitAndPush(
|
|
553
|
-
message: string,
|
|
554
|
-
options?: { allowEmpty?: boolean },
|
|
555
|
-
): Promise<void> {
|
|
502
|
+
async commitAndPush(message: string, options?: { allowEmpty?: boolean }): Promise<void> {
|
|
556
503
|
const hasChanges = await this.hasStagedChanges();
|
|
557
504
|
|
|
558
505
|
if (!hasChanges && !options?.allowEmpty) {
|
|
559
|
-
this.logger.debug(
|
|
506
|
+
this.logger.debug('No changes to commit, skipping');
|
|
560
507
|
return;
|
|
561
508
|
}
|
|
562
509
|
|
|
@@ -567,9 +514,6 @@ Generated by PostHog Agent`;
|
|
|
567
514
|
const currentBranch = await this.getCurrentBranch();
|
|
568
515
|
await this.pushBranch(currentBranch);
|
|
569
516
|
|
|
570
|
-
this.logger.info(
|
|
571
|
-
branch: currentBranch,
|
|
572
|
-
message,
|
|
573
|
-
});
|
|
517
|
+
this.logger.info('Committed and pushed changes', { branch: currentBranch, message });
|
|
574
518
|
}
|
|
575
519
|
}
|