@posthog/agent 1.16.0 → 1.16.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/dist/node_modules/@ai-sdk/anthropic/dist/index.js +2 -2
- package/dist/node_modules/@ai-sdk/anthropic/dist/index.js.map +1 -1
- package/dist/node_modules/@ai-sdk/provider-utils/dist/index.js +1 -1
- package/dist/src/agent.d.ts +1 -1
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +4 -6
- package/dist/src/agent.js.map +1 -1
- package/dist/src/git-manager.d.ts +23 -0
- package/dist/src/git-manager.d.ts.map +1 -1
- package/dist/src/git-manager.js +110 -52
- package/dist/src/git-manager.js.map +1 -1
- package/dist/src/structured-extraction.d.ts +7 -1
- package/dist/src/structured-extraction.d.ts.map +1 -1
- package/dist/src/structured-extraction.js +13 -13
- package/dist/src/structured-extraction.js.map +1 -1
- package/dist/src/types.d.ts +2 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/ai-sdk.d.ts +14 -0
- package/dist/src/utils/ai-sdk.d.ts.map +1 -0
- package/dist/src/utils/ai-sdk.js +38 -0
- package/dist/src/utils/ai-sdk.js.map +1 -0
- package/dist/src/workflow/steps/build.d.ts.map +1 -1
- package/dist/src/workflow/steps/build.js +11 -16
- package/dist/src/workflow/steps/build.js.map +1 -1
- package/package.json +1 -1
- package/src/agent.ts +4 -6
- package/src/git-manager.ts +142 -64
- package/src/structured-extraction.ts +21 -14
- package/src/types.ts +2 -2
- package/src/utils/ai-sdk.ts +47 -0
- package/src/workflow/steps/build.ts +13 -18
package/src/git-manager.ts
CHANGED
|
@@ -97,6 +97,8 @@ export class GitManager {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
async createOrSwitchToBranch(branchName: string, baseBranch?: string): Promise<void> {
|
|
100
|
+
await this.ensureCleanWorkingDirectory('switching branches');
|
|
101
|
+
|
|
100
102
|
const exists = await this.branchExists(branchName);
|
|
101
103
|
if (exists) {
|
|
102
104
|
await this.switchToBranch(branchName);
|
|
@@ -118,15 +120,7 @@ export class GitManager {
|
|
|
118
120
|
authorName?: string;
|
|
119
121
|
authorEmail?: string;
|
|
120
122
|
}): Promise<string> {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const authorName = options?.authorName || this.authorName;
|
|
124
|
-
const authorEmail = options?.authorEmail || this.authorEmail;
|
|
125
|
-
|
|
126
|
-
if (authorName && authorEmail) {
|
|
127
|
-
command += ` --author="${authorName} <${authorEmail}>"`;
|
|
128
|
-
}
|
|
129
|
-
|
|
123
|
+
const command = this.buildCommitCommand(message, options);
|
|
130
124
|
return await this.runGitCommand(command);
|
|
131
125
|
}
|
|
132
126
|
|
|
@@ -148,6 +142,56 @@ export class GitManager {
|
|
|
148
142
|
}
|
|
149
143
|
}
|
|
150
144
|
|
|
145
|
+
// Helper: Centralized safety check for uncommitted changes
|
|
146
|
+
private async ensureCleanWorkingDirectory(operation: string): Promise<void> {
|
|
147
|
+
if (await this.hasChanges()) {
|
|
148
|
+
throw new Error(`Uncommitted changes detected. Please commit or stash changes before ${operation}.`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private async generateUniqueBranchName(baseName: string): Promise<string> {
|
|
153
|
+
if (!await this.branchExists(baseName)) {
|
|
154
|
+
return baseName;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let counter = 1;
|
|
158
|
+
let uniqueName = `${baseName}-${counter}`;
|
|
159
|
+
while (await this.branchExists(uniqueName)) {
|
|
160
|
+
counter++;
|
|
161
|
+
uniqueName = `${baseName}-${counter}`;
|
|
162
|
+
}
|
|
163
|
+
return uniqueName;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private async ensureOnDefaultBranch(): Promise<string> {
|
|
167
|
+
const defaultBranch = await this.getDefaultBranch();
|
|
168
|
+
const currentBranch = await this.getCurrentBranch();
|
|
169
|
+
|
|
170
|
+
if (currentBranch !== defaultBranch) {
|
|
171
|
+
await this.ensureCleanWorkingDirectory('switching to default branch');
|
|
172
|
+
await this.switchToBranch(defaultBranch);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return defaultBranch;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private buildCommitCommand(message: string, options?: { allowEmpty?: boolean; authorName?: string; authorEmail?: string }): string {
|
|
179
|
+
let command = `commit -m "${message.replace(/"/g, '\\"')}"`;
|
|
180
|
+
|
|
181
|
+
if (options?.allowEmpty) {
|
|
182
|
+
command += ' --allow-empty';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const authorName = options?.authorName || this.authorName;
|
|
186
|
+
const authorEmail = options?.authorEmail || this.authorEmail;
|
|
187
|
+
|
|
188
|
+
if (authorName && authorEmail) {
|
|
189
|
+
command += ` --author="${authorName} <${authorEmail}>"`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return command;
|
|
193
|
+
}
|
|
194
|
+
|
|
151
195
|
async getRemoteUrl(): Promise<string | null> {
|
|
152
196
|
try {
|
|
153
197
|
return await this.runGitCommand('remote get-url origin');
|
|
@@ -161,75 +205,120 @@ export class GitManager {
|
|
|
161
205
|
await this.runGitCommand(`push ${forceFlag} -u origin ${branchName}`);
|
|
162
206
|
}
|
|
163
207
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Tracks whether commits were made during an operation by comparing HEAD SHA
|
|
210
|
+
* before and after. Returns an object with methods to finalize the operation.
|
|
211
|
+
*
|
|
212
|
+
* Usage:
|
|
213
|
+
* const tracker = await gitManager.trackCommitsDuring();
|
|
214
|
+
* // ... do work that might create commits ...
|
|
215
|
+
* const result = await tracker.finalize({ commitMessage: 'fallback message', push: true });
|
|
216
|
+
*/
|
|
217
|
+
async trackCommitsDuring(): Promise<{
|
|
218
|
+
finalize: (options: {
|
|
219
|
+
commitMessage: string;
|
|
220
|
+
push?: boolean;
|
|
221
|
+
}) => Promise<{ commitCreated: boolean; pushedBranch: boolean }>;
|
|
222
|
+
}> {
|
|
223
|
+
const initialSha = await this.getCommitSha('HEAD');
|
|
168
224
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
225
|
+
return {
|
|
226
|
+
finalize: async (options) => {
|
|
227
|
+
const currentSha = await this.getCommitSha('HEAD');
|
|
228
|
+
const externalCommitsCreated = initialSha !== currentSha;
|
|
229
|
+
const hasUncommittedChanges = await this.hasChanges();
|
|
230
|
+
|
|
231
|
+
// If no commits and no changes, nothing to do
|
|
232
|
+
if (!externalCommitsCreated && !hasUncommittedChanges) {
|
|
233
|
+
return { commitCreated: false, pushedBranch: false };
|
|
234
|
+
}
|
|
174
235
|
|
|
175
|
-
|
|
236
|
+
let commitCreated = externalCommitsCreated;
|
|
176
237
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
238
|
+
// Commit any remaining uncommitted changes
|
|
239
|
+
if (hasUncommittedChanges) {
|
|
240
|
+
await this.runGitCommand('add .');
|
|
241
|
+
const hasStagedChanges = await this.hasStagedChanges();
|
|
181
242
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
243
|
+
if (hasStagedChanges) {
|
|
244
|
+
await this.commitChanges(options.commitMessage);
|
|
245
|
+
commitCreated = true;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Push if requested and commits were made
|
|
250
|
+
let pushedBranch = false;
|
|
251
|
+
if (options.push && commitCreated) {
|
|
252
|
+
const currentBranch = await this.getCurrentBranch();
|
|
253
|
+
await this.pushBranch(currentBranch);
|
|
254
|
+
pushedBranch = true;
|
|
255
|
+
this.logger.info('Pushed branch after operation', { branch: currentBranch });
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return { commitCreated, pushedBranch };
|
|
185
259
|
}
|
|
186
|
-
}
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async createTaskBranch(taskSlug: string): Promise<string> {
|
|
264
|
+
const branchName = `posthog/task-${taskSlug}`;
|
|
265
|
+
|
|
266
|
+
// Ensure we're on default branch before creating task branch
|
|
267
|
+
const defaultBranch = await this.ensureOnDefaultBranch();
|
|
268
|
+
|
|
269
|
+
this.logger.info('Creating task branch from default branch', {
|
|
270
|
+
branchName,
|
|
271
|
+
taskSlug,
|
|
272
|
+
baseBranch: defaultBranch
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
await this.createOrSwitchToBranch(branchName, defaultBranch);
|
|
187
276
|
|
|
188
|
-
await this.createBranch(branchName, baseBranch); // Use createBranch instead of createOrSwitchToBranch for new branches
|
|
189
277
|
return branchName;
|
|
190
278
|
}
|
|
191
279
|
|
|
192
|
-
async
|
|
193
|
-
|
|
194
|
-
|
|
280
|
+
async createTaskPlanningBranch(taskId: string, baseBranch?: string): Promise<string> {
|
|
281
|
+
const baseName = `posthog/task-${taskId}-planning`;
|
|
282
|
+
const branchName = await this.generateUniqueBranchName(baseName);
|
|
195
283
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
284
|
+
this.logger.debug('Creating unique planning branch', { branchName, taskId });
|
|
285
|
+
|
|
286
|
+
const base = baseBranch || await this.ensureOnDefaultBranch();
|
|
287
|
+
await this.createBranch(branchName, base);
|
|
288
|
+
|
|
289
|
+
return branchName;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async createTaskImplementationBranch(taskId: string, planningBranchName?: string): Promise<string> {
|
|
293
|
+
const baseName = `posthog/task-${taskId}-implementation`;
|
|
294
|
+
const branchName = await this.generateUniqueBranchName(baseName);
|
|
201
295
|
|
|
202
|
-
const currentBranchBefore = await this.getCurrentBranch();
|
|
203
296
|
this.logger.debug('Creating unique implementation branch', {
|
|
204
297
|
branchName,
|
|
205
298
|
taskId,
|
|
206
|
-
currentBranch:
|
|
299
|
+
currentBranch: await this.getCurrentBranch()
|
|
207
300
|
});
|
|
208
301
|
|
|
209
|
-
//
|
|
302
|
+
// Determine base branch: explicit param > current planning branch > default
|
|
210
303
|
let baseBranch = planningBranchName;
|
|
211
304
|
|
|
212
305
|
if (!baseBranch) {
|
|
213
|
-
// Try to find the corresponding planning branch
|
|
214
306
|
const currentBranch = await this.getCurrentBranch();
|
|
215
307
|
if (currentBranch.includes('-planning')) {
|
|
216
|
-
baseBranch = currentBranch;
|
|
308
|
+
baseBranch = currentBranch;
|
|
217
309
|
this.logger.debug('Using current planning branch', { baseBranch });
|
|
218
310
|
} else {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
this.logger.debug('No planning branch found, using default', { baseBranch });
|
|
222
|
-
await this.switchToBranch(baseBranch);
|
|
311
|
+
baseBranch = await this.ensureOnDefaultBranch();
|
|
312
|
+
this.logger.debug('Using default branch', { baseBranch });
|
|
223
313
|
}
|
|
224
314
|
}
|
|
225
315
|
|
|
226
316
|
this.logger.debug('Creating implementation branch from base', { baseBranch, branchName });
|
|
227
|
-
await this.createBranch(branchName, baseBranch);
|
|
317
|
+
await this.createBranch(branchName, baseBranch);
|
|
228
318
|
|
|
229
|
-
const currentBranchAfter = await this.getCurrentBranch();
|
|
230
319
|
this.logger.info('Implementation branch created', {
|
|
231
320
|
branchName,
|
|
232
|
-
currentBranch:
|
|
321
|
+
currentBranch: await this.getCurrentBranch()
|
|
233
322
|
});
|
|
234
323
|
|
|
235
324
|
return branchName;
|
|
@@ -323,6 +412,7 @@ Generated by PostHog Agent`;
|
|
|
323
412
|
): Promise<string> {
|
|
324
413
|
const currentBranch = await this.getCurrentBranch();
|
|
325
414
|
if (currentBranch !== branchName) {
|
|
415
|
+
await this.ensureCleanWorkingDirectory('creating PR');
|
|
326
416
|
await this.switchToBranch(branchName);
|
|
327
417
|
}
|
|
328
418
|
|
|
@@ -366,31 +456,19 @@ Generated by PostHog Agent`;
|
|
|
366
456
|
|
|
367
457
|
async commitAndPush(message: string, options?: { allowEmpty?: boolean }): Promise<void> {
|
|
368
458
|
const hasChanges = await this.hasStagedChanges();
|
|
369
|
-
|
|
459
|
+
|
|
370
460
|
if (!hasChanges && !options?.allowEmpty) {
|
|
371
461
|
this.logger.debug('No changes to commit, skipping');
|
|
372
462
|
return;
|
|
373
463
|
}
|
|
374
464
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (options?.allowEmpty) {
|
|
378
|
-
command += ' --allow-empty';
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
const authorName = this.authorName;
|
|
382
|
-
const authorEmail = this.authorEmail;
|
|
383
|
-
|
|
384
|
-
if (authorName && authorEmail) {
|
|
385
|
-
command += ` --author="${authorName} <${authorEmail}>"`;
|
|
386
|
-
}
|
|
387
|
-
|
|
465
|
+
const command = this.buildCommitCommand(message, options);
|
|
388
466
|
await this.runGitCommand(command);
|
|
389
|
-
|
|
467
|
+
|
|
390
468
|
// Push to origin
|
|
391
469
|
const currentBranch = await this.getCurrentBranch();
|
|
392
470
|
await this.pushBranch(currentBranch);
|
|
393
|
-
|
|
471
|
+
|
|
394
472
|
this.logger.info('Committed and pushed changes', { branch: currentBranch, message });
|
|
395
473
|
}
|
|
396
474
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { generateObject } from 'ai';
|
|
2
|
-
import { anthropic } from '@ai-sdk/anthropic';
|
|
3
2
|
import { z } from 'zod';
|
|
4
3
|
import { Logger } from './utils/logger.js';
|
|
4
|
+
import { getAnthropicModel } from './utils/ai-sdk.js';
|
|
5
5
|
|
|
6
6
|
export interface ExtractedQuestion {
|
|
7
7
|
id: string;
|
|
@@ -41,27 +41,34 @@ export interface StructuredExtractor {
|
|
|
41
41
|
extractQuestionsWithAnswers(researchContent: string): Promise<ExtractedQuestionWithAnswer[]>;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
export type StructuredExtractorConfig = {
|
|
45
|
+
apiKey: string;
|
|
46
|
+
baseURL: string;
|
|
47
|
+
modelName?: string;
|
|
48
|
+
logger?: Logger;
|
|
49
|
+
}
|
|
50
|
+
|
|
44
51
|
export class AISDKExtractor implements StructuredExtractor {
|
|
45
52
|
private logger: Logger;
|
|
46
53
|
private model: any;
|
|
47
54
|
|
|
48
|
-
constructor(
|
|
49
|
-
this.logger = logger || new Logger({ debug: false, prefix: '[AISDKExtractor]' });
|
|
50
|
-
|
|
51
|
-
// Determine which provider to use based on environment variables
|
|
52
|
-
// Priority: Anthropic (if ANTHROPIC_BASE_URL is set) > OpenAI
|
|
53
|
-
const apiKey = process.env.ANTHROPIC_AUTH_TOKEN
|
|
54
|
-
|| process.env.ANTHROPIC_API_KEY
|
|
55
|
-
|| process.env.OPENAI_API_KEY;
|
|
55
|
+
constructor(config: StructuredExtractorConfig) {
|
|
56
|
+
this.logger = config.logger || new Logger({ debug: false, prefix: '[AISDKExtractor]' });
|
|
56
57
|
|
|
57
|
-
if (!apiKey) {
|
|
58
|
+
if (!config.apiKey) {
|
|
58
59
|
throw new Error('Missing API key for structured extraction. Ensure the LLM gateway is configured.');
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
this.model = getAnthropicModel({
|
|
63
|
+
apiKey: config.apiKey,
|
|
64
|
+
baseURL: config.baseURL,
|
|
65
|
+
modelName: config.modelName || 'claude-haiku-4-5',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
this.logger.debug('Using PostHog LLM gateway for structured extraction', {
|
|
69
|
+
modelName: config.modelName || 'claude-haiku-4-5',
|
|
70
|
+
baseURL: config.baseURL
|
|
71
|
+
});
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
async extractQuestions(researchContent: string): Promise<ExtractedQuestion[]> {
|
package/src/types.ts
CHANGED
|
@@ -301,8 +301,8 @@ export interface AgentConfig {
|
|
|
301
301
|
onEvent?: (event: AgentEvent) => void;
|
|
302
302
|
|
|
303
303
|
// PostHog API configuration
|
|
304
|
-
posthogApiUrl
|
|
305
|
-
posthogApiKey
|
|
304
|
+
posthogApiUrl: string;
|
|
305
|
+
posthogApiKey: string;
|
|
306
306
|
|
|
307
307
|
// PostHog MCP configuration
|
|
308
308
|
posthogMcpUrl?: string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
2
|
+
|
|
3
|
+
export interface PostHogGatewayConfig {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
baseURL: string;
|
|
6
|
+
modelName?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates an Anthropic model configured for PostHog LLM gateway.
|
|
11
|
+
*
|
|
12
|
+
* Handles two key differences between AI SDK and PostHog gateway:
|
|
13
|
+
* 1. Appends /v1 to baseURL (gateway expects /v1/messages, SDK appends /messages)
|
|
14
|
+
* 2. Converts x-api-key header to Authorization Bearer token
|
|
15
|
+
*/
|
|
16
|
+
export function getAnthropicModel(config: PostHogGatewayConfig) {
|
|
17
|
+
const modelName = config.modelName || 'claude-haiku-4-5';
|
|
18
|
+
|
|
19
|
+
// PostHog gateway expects /v1/messages, but AI SDK appends /messages
|
|
20
|
+
// So we need to append /v1 to the baseURL
|
|
21
|
+
const baseURL = config.baseURL ? `${config.baseURL}/v1` : undefined;
|
|
22
|
+
|
|
23
|
+
// Custom fetch to convert x-api-key header to Authorization Bearer
|
|
24
|
+
// PostHog gateway expects Bearer token, but Anthropic SDK sends x-api-key
|
|
25
|
+
const customFetch = async (url: RequestInfo, init?: RequestInit): Promise<Response> => {
|
|
26
|
+
const headers = new Headers(init?.headers);
|
|
27
|
+
|
|
28
|
+
if (headers.has('x-api-key')) {
|
|
29
|
+
headers.delete('x-api-key');
|
|
30
|
+
headers.set('Authorization', `Bearer ${config.apiKey}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return fetch(url, {
|
|
34
|
+
...init,
|
|
35
|
+
headers,
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const anthropic = createAnthropic({
|
|
40
|
+
apiKey: config.apiKey,
|
|
41
|
+
baseURL,
|
|
42
|
+
//@ts-ignore
|
|
43
|
+
fetch: customFetch,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return anthropic(modelName);
|
|
47
|
+
}
|
|
@@ -79,6 +79,9 @@ export const buildStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
|
79
79
|
options: { ...baseOptions, ...(options.queryOverrides || {}) },
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
+
// Track commits made during Claude Code execution
|
|
83
|
+
const commitTracker = await gitManager.trackCommitsDuring();
|
|
84
|
+
|
|
82
85
|
for await (const message of response) {
|
|
83
86
|
emitEvent(adapter.createRawSDKEvent(message));
|
|
84
87
|
const transformed = adapter.transform(message);
|
|
@@ -87,29 +90,21 @@ export const buildStep: WorkflowStepRunner = async ({ step, context }) => {
|
|
|
87
90
|
}
|
|
88
91
|
}
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (!hasChanges) {
|
|
93
|
-
stepLogger.warn('No changes to commit in build phase', { taskId: task.id });
|
|
94
|
-
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));
|
|
95
|
-
return { status: 'completed' };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
await gitManager.addFiles(['.']);
|
|
99
|
-
const commitCreated = await finalizeStepGitActions(context, step, {
|
|
93
|
+
// Finalize: commit any remaining changes and optionally push
|
|
94
|
+
const { commitCreated, pushedBranch } = await commitTracker.finalize({
|
|
100
95
|
commitMessage: `Implementation for ${task.title}`,
|
|
96
|
+
push: step.push,
|
|
101
97
|
});
|
|
98
|
+
|
|
102
99
|
context.stepResults[step.id] = { commitCreated };
|
|
103
100
|
|
|
104
101
|
if (!commitCreated) {
|
|
105
|
-
stepLogger.warn('No commit
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
await gitManager.pushBranch(branchName);
|
|
112
|
-
stepLogger.info('Pushed branch after build', { branch: branchName });
|
|
102
|
+
stepLogger.warn('No changes to commit in build phase', { taskId: task.id });
|
|
103
|
+
} else {
|
|
104
|
+
stepLogger.info('Build commits finalized', {
|
|
105
|
+
taskId: task.id,
|
|
106
|
+
pushedBranch
|
|
107
|
+
});
|
|
113
108
|
}
|
|
114
109
|
|
|
115
110
|
emitEvent(adapter.createStatusEvent('phase_complete', { phase: 'build' }));
|