@qelos/aidev 0.7.2 → 0.7.3
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/.aidev/assets/86c8yjxrr/9ea11c36-311c-4022-889c-1bb0915122dc.jpg-40e6939e3b68e864260f7ae7e85bd623_exif.jpg +0 -0
- package/.aidev/assets/86c9n1mkf/65d079a2-dc39-4c4e-9ea9-964d37e0402c.jpg-a639447a10296e31cd4c85d521e9705e_exif.jpg +0 -0
- package/.env.aidev.example +105 -105
- package/CONTRIBUTING.md +78 -78
- package/LICENSE +21 -21
- package/README.md +755 -755
- package/aidev.tasks.json +1 -0
- package/dist/autoCompress.d.ts +54 -0
- package/dist/autoCompress.d.ts.map +1 -0
- package/dist/autoCompress.js +300 -0
- package/dist/autoCompress.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/cli.js.map +1 -1
- package/dist/commands/help.js +80 -80
- package/dist/commands/init.js +105 -105
- package/dist/commands/run.js +146 -146
- package/dist/github.js +27 -27
- package/dist/providers/linear.js +106 -106
- package/dist/providers/monday.js +45 -45
- package/package.json +51 -51
- package/scripts/run-tests.cjs +18 -18
package/dist/commands/init.js
CHANGED
|
@@ -367,111 +367,111 @@ function printGhSuggestion(remote) {
|
|
|
367
367
|
console.log(` PRs will be created automatically after pushing branches.`);
|
|
368
368
|
console.log();
|
|
369
369
|
}
|
|
370
|
-
const HOOKS_BOILERPLATE = `// aidev hooks — customize the AI task automation pipeline
|
|
371
|
-
//
|
|
372
|
-
// Each export below is an async (context, vm) hook. Return a new/updated context object to
|
|
373
|
-
// change prompts, subtasks, etc.; return nothing to keep the incoming context. Throw to abort
|
|
374
|
-
// the current step (whole run, single task, conflict resolution, etc., depending on the hook).
|
|
375
|
-
//
|
|
376
|
-
// vm: run AI (first available agent), postComment, updateStatus, getComments, log.info/warn/error
|
|
377
|
-
//
|
|
378
|
-
// .ts files are loaded via jiti — no TypeScript compiler or toolchain needed.
|
|
379
|
-
|
|
380
|
-
// ─── Context types (mirror aidev's internal shapes — tweak here for editor hints) ─
|
|
381
|
-
|
|
382
|
-
interface RunContext {
|
|
383
|
-
config: Record<string, unknown>;
|
|
384
|
-
filter: string;
|
|
385
|
-
taskCount: number;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
interface TaskContext {
|
|
389
|
-
task: { id: string; name: string; description: string; status: string; url: string; tags: string[] };
|
|
390
|
-
config: Record<string, unknown>;
|
|
391
|
-
branchName: string;
|
|
392
|
-
prompt: string;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
interface ResolveConflictsContext {
|
|
396
|
-
task: { id: string; name: string; description: string; status: string; url: string; tags: string[] };
|
|
397
|
-
config: Record<string, unknown>;
|
|
398
|
-
branchName: string;
|
|
399
|
-
conflictFiles: string[];
|
|
400
|
-
prompt: string;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
interface NonCodeTaskContext {
|
|
404
|
-
task: { id: string; name: string; description: string; status: string; url: string; tags: string[] };
|
|
405
|
-
config: Record<string, unknown>;
|
|
406
|
-
prompt: string;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
interface ThinkingTaskContext {
|
|
410
|
-
task: { id: string; name: string; description: string; status: string; url: string; tags: string[] };
|
|
411
|
-
config: Record<string, unknown>;
|
|
412
|
-
branchName: string;
|
|
413
|
-
subtasks: Array<{ id: number; title: string; description: string; status: string }>;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
interface HookVM {
|
|
417
|
-
runAI(prompt: string): Promise<{ success: boolean; output: string; error: string }>;
|
|
418
|
-
postComment(taskId: string, text: string): Promise<void>;
|
|
419
|
-
updateStatus(taskId: string, status: string): Promise<void>;
|
|
420
|
-
getComments(taskId: string): Promise<Array<{ id: string; text: string; author: string }>>;
|
|
421
|
-
log: { info(msg: string): void; warn(msg: string): void; error(msg: string): void };
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// ─── Hooks (fill in — ask an AI: "implement beforeEachTask to append X to the prompt") ─
|
|
425
|
-
|
|
426
|
-
/** Once before any task. AI idea: log counts, or throw if CI env var is missing. */
|
|
427
|
-
export async function beforeRun(_context: RunContext, _vm: HookVM): Promise<RunContext | void> {
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/** After all tasks in this run. AI idea: post a summary comment or call an external webhook. */
|
|
432
|
-
export async function afterRun(_context: RunContext & { processed: number; skipped: number }, _vm: HookVM): Promise<void> {
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/** Before each code task AI run. AI idea: append coding standards or repo-specific rules to context.prompt. */
|
|
437
|
-
export async function beforeEachTask(_context: TaskContext, _vm: HookVM): Promise<TaskContext | void> {
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/** After a code task completes the success path (push + review). */
|
|
442
|
-
export async function afterEachTask(_context: TaskContext & { success: boolean }, _vm: HookVM): Promise<void> {
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/** Before AI-driven merge conflict resolution. AI idea: tighten context.prompt for your stack. */
|
|
447
|
-
export async function beforeResolveConflicts(_context: ResolveConflictsContext, _vm: HookVM): Promise<ResolveConflictsContext | void> {
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/** After conflict resolution; context.resolved is false when all runners failed. */
|
|
452
|
-
export async function afterResolveConflicts(_context: ResolveConflictsContext & { resolved: boolean }, _vm: HookVM): Promise<void> {
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/** Before non-code task AI run. AI idea: format context.prompt for ticket-style replies. */
|
|
457
|
-
export async function beforeNonCodeTask(_context: NonCodeTaskContext, _vm: HookVM): Promise<NonCodeTaskContext | void> {
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
/** After non-code task; context.output is the agent response text posted to the ticket. */
|
|
462
|
-
export async function afterNonCodeTask(_context: NonCodeTaskContext & { success: boolean; output: string }, _vm: HookVM): Promise<void> {
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/** After the plan exists, before subtasks run. AI idea: rewrite subtask descriptions for clarity. */
|
|
467
|
-
export async function beforeThinkingTask(_context: ThinkingTaskContext, _vm: HookVM): Promise<ThinkingTaskContext | void> {
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
/** After all thinking-task subtasks complete. AI idea: notify or archive artifacts. */
|
|
472
|
-
export async function afterThinkingTask(_context: ThinkingTaskContext & { success: boolean }, _vm: HookVM): Promise<void> {
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
370
|
+
const HOOKS_BOILERPLATE = `// aidev hooks — customize the AI task automation pipeline
|
|
371
|
+
//
|
|
372
|
+
// Each export below is an async (context, vm) hook. Return a new/updated context object to
|
|
373
|
+
// change prompts, subtasks, etc.; return nothing to keep the incoming context. Throw to abort
|
|
374
|
+
// the current step (whole run, single task, conflict resolution, etc., depending on the hook).
|
|
375
|
+
//
|
|
376
|
+
// vm: run AI (first available agent), postComment, updateStatus, getComments, log.info/warn/error
|
|
377
|
+
//
|
|
378
|
+
// .ts files are loaded via jiti — no TypeScript compiler or toolchain needed.
|
|
379
|
+
|
|
380
|
+
// ─── Context types (mirror aidev's internal shapes — tweak here for editor hints) ─
|
|
381
|
+
|
|
382
|
+
interface RunContext {
|
|
383
|
+
config: Record<string, unknown>;
|
|
384
|
+
filter: string;
|
|
385
|
+
taskCount: number;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
interface TaskContext {
|
|
389
|
+
task: { id: string; name: string; description: string; status: string; url: string; tags: string[] };
|
|
390
|
+
config: Record<string, unknown>;
|
|
391
|
+
branchName: string;
|
|
392
|
+
prompt: string;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
interface ResolveConflictsContext {
|
|
396
|
+
task: { id: string; name: string; description: string; status: string; url: string; tags: string[] };
|
|
397
|
+
config: Record<string, unknown>;
|
|
398
|
+
branchName: string;
|
|
399
|
+
conflictFiles: string[];
|
|
400
|
+
prompt: string;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
interface NonCodeTaskContext {
|
|
404
|
+
task: { id: string; name: string; description: string; status: string; url: string; tags: string[] };
|
|
405
|
+
config: Record<string, unknown>;
|
|
406
|
+
prompt: string;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
interface ThinkingTaskContext {
|
|
410
|
+
task: { id: string; name: string; description: string; status: string; url: string; tags: string[] };
|
|
411
|
+
config: Record<string, unknown>;
|
|
412
|
+
branchName: string;
|
|
413
|
+
subtasks: Array<{ id: number; title: string; description: string; status: string }>;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
interface HookVM {
|
|
417
|
+
runAI(prompt: string): Promise<{ success: boolean; output: string; error: string }>;
|
|
418
|
+
postComment(taskId: string, text: string): Promise<void>;
|
|
419
|
+
updateStatus(taskId: string, status: string): Promise<void>;
|
|
420
|
+
getComments(taskId: string): Promise<Array<{ id: string; text: string; author: string }>>;
|
|
421
|
+
log: { info(msg: string): void; warn(msg: string): void; error(msg: string): void };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// ─── Hooks (fill in — ask an AI: "implement beforeEachTask to append X to the prompt") ─
|
|
425
|
+
|
|
426
|
+
/** Once before any task. AI idea: log counts, or throw if CI env var is missing. */
|
|
427
|
+
export async function beforeRun(_context: RunContext, _vm: HookVM): Promise<RunContext | void> {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** After all tasks in this run. AI idea: post a summary comment or call an external webhook. */
|
|
432
|
+
export async function afterRun(_context: RunContext & { processed: number; skipped: number }, _vm: HookVM): Promise<void> {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/** Before each code task AI run. AI idea: append coding standards or repo-specific rules to context.prompt. */
|
|
437
|
+
export async function beforeEachTask(_context: TaskContext, _vm: HookVM): Promise<TaskContext | void> {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/** After a code task completes the success path (push + review). */
|
|
442
|
+
export async function afterEachTask(_context: TaskContext & { success: boolean }, _vm: HookVM): Promise<void> {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/** Before AI-driven merge conflict resolution. AI idea: tighten context.prompt for your stack. */
|
|
447
|
+
export async function beforeResolveConflicts(_context: ResolveConflictsContext, _vm: HookVM): Promise<ResolveConflictsContext | void> {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/** After conflict resolution; context.resolved is false when all runners failed. */
|
|
452
|
+
export async function afterResolveConflicts(_context: ResolveConflictsContext & { resolved: boolean }, _vm: HookVM): Promise<void> {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** Before non-code task AI run. AI idea: format context.prompt for ticket-style replies. */
|
|
457
|
+
export async function beforeNonCodeTask(_context: NonCodeTaskContext, _vm: HookVM): Promise<NonCodeTaskContext | void> {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** After non-code task; context.output is the agent response text posted to the ticket. */
|
|
462
|
+
export async function afterNonCodeTask(_context: NonCodeTaskContext & { success: boolean; output: string }, _vm: HookVM): Promise<void> {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** After the plan exists, before subtasks run. AI idea: rewrite subtask descriptions for clarity. */
|
|
467
|
+
export async function beforeThinkingTask(_context: ThinkingTaskContext, _vm: HookVM): Promise<ThinkingTaskContext | void> {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/** After all thinking-task subtasks complete. AI idea: notify or archive artifacts. */
|
|
472
|
+
export async function afterThinkingTask(_context: ThinkingTaskContext & { success: boolean }, _vm: HookVM): Promise<void> {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
475
|
`;
|
|
476
476
|
function ensureHooksBoilerplate(dir = process.cwd()) {
|
|
477
477
|
const aidevDir = path.join(dir, '.aidev');
|
package/dist/commands/run.js
CHANGED
|
@@ -403,16 +403,16 @@ async function checkNeedsClarification(task, config, provider, runners) {
|
|
|
403
403
|
logger_1.logger.warn('No AI runner available — skipping clarification check');
|
|
404
404
|
return null;
|
|
405
405
|
}
|
|
406
|
-
const clarificationPrompt = `You are a senior software developer reviewing a task.
|
|
407
|
-
Determine if the following task has enough information to implement without further clarification.
|
|
408
|
-
|
|
409
|
-
Task name: ${task.name}
|
|
410
|
-
Task description: ${task.description || '(no description)'}
|
|
411
|
-
|
|
412
|
-
Respond with valid JSON only:
|
|
413
|
-
{
|
|
414
|
-
"clear": true|false,
|
|
415
|
-
"question": "question to ask if not clear, or null"
|
|
406
|
+
const clarificationPrompt = `You are a senior software developer reviewing a task.
|
|
407
|
+
Determine if the following task has enough information to implement without further clarification.
|
|
408
|
+
|
|
409
|
+
Task name: ${task.name}
|
|
410
|
+
Task description: ${task.description || '(no description)'}
|
|
411
|
+
|
|
412
|
+
Respond with valid JSON only:
|
|
413
|
+
{
|
|
414
|
+
"clear": true|false,
|
|
415
|
+
"question": "question to ask if not clear, or null"
|
|
416
416
|
}`;
|
|
417
417
|
for (const runner of availableRunners) {
|
|
418
418
|
const result = await runner.run(clarificationPrompt);
|
|
@@ -440,30 +440,30 @@ Respond with valid JSON only:
|
|
|
440
440
|
return null;
|
|
441
441
|
}
|
|
442
442
|
function buildConflictResolutionPrompt(task, conflictFiles, context) {
|
|
443
|
-
return `You are resolving merge conflicts in a software development task branch.
|
|
444
|
-
|
|
445
|
-
The task branch has fallen behind the base branch and has merge conflicts that need to be resolved.
|
|
446
|
-
|
|
447
|
-
## Task context (DO NOT break this — the task must still work after conflict resolution)
|
|
448
|
-
|
|
449
|
-
Task: ${task.name}
|
|
450
|
-
|
|
451
|
-
Description:
|
|
452
|
-
${task.description || '(no description provided)'}
|
|
453
|
-
${context}
|
|
454
|
-
|
|
455
|
-
## Merge conflicts
|
|
456
|
-
|
|
457
|
-
The following files have merge conflicts with conflict markers (<<<<<<< HEAD, =======, >>>>>>> ...):
|
|
458
|
-
${conflictFiles.map((f) => `- ${f}`).join('\n')}
|
|
459
|
-
|
|
460
|
-
## Instructions
|
|
461
|
-
|
|
462
|
-
1. Open each conflicting file and resolve the conflict markers
|
|
463
|
-
2. Keep BOTH the task's changes AND the base branch updates where possible
|
|
464
|
-
3. If the base branch changed something the task also changed, prefer the task's intent but make sure it works with the new base branch code
|
|
465
|
-
4. Remove all conflict markers (<<<<<<< HEAD, =======, >>>>>>> ...)
|
|
466
|
-
5. Make sure the code compiles and is consistent after resolution
|
|
443
|
+
return `You are resolving merge conflicts in a software development task branch.
|
|
444
|
+
|
|
445
|
+
The task branch has fallen behind the base branch and has merge conflicts that need to be resolved.
|
|
446
|
+
|
|
447
|
+
## Task context (DO NOT break this — the task must still work after conflict resolution)
|
|
448
|
+
|
|
449
|
+
Task: ${task.name}
|
|
450
|
+
|
|
451
|
+
Description:
|
|
452
|
+
${task.description || '(no description provided)'}
|
|
453
|
+
${context}
|
|
454
|
+
|
|
455
|
+
## Merge conflicts
|
|
456
|
+
|
|
457
|
+
The following files have merge conflicts with conflict markers (<<<<<<< HEAD, =======, >>>>>>> ...):
|
|
458
|
+
${conflictFiles.map((f) => `- ${f}`).join('\n')}
|
|
459
|
+
|
|
460
|
+
## Instructions
|
|
461
|
+
|
|
462
|
+
1. Open each conflicting file and resolve the conflict markers
|
|
463
|
+
2. Keep BOTH the task's changes AND the base branch updates where possible
|
|
464
|
+
3. If the base branch changed something the task also changed, prefer the task's intent but make sure it works with the new base branch code
|
|
465
|
+
4. Remove all conflict markers (<<<<<<< HEAD, =======, >>>>>>> ...)
|
|
466
|
+
5. Make sure the code compiles and is consistent after resolution
|
|
467
467
|
6. Do NOT make any changes beyond what is needed to resolve the conflicts`;
|
|
468
468
|
}
|
|
469
469
|
async function resolveConflictsWithAI(task, config, provider, runners, context, hooks, vm, branchName) {
|
|
@@ -731,14 +731,14 @@ async function implementTask(task, branchName, branchExists, config, provider, r
|
|
|
731
731
|
logger_1.logger.success(`Task implemented: branch ${branchName} pushed`);
|
|
732
732
|
}
|
|
733
733
|
function buildImplementPrompt(task, context) {
|
|
734
|
-
return `You are implementing a software development task. Make the necessary code changes to complete the task described below.
|
|
735
|
-
|
|
736
|
-
Task: ${task.name}
|
|
737
|
-
|
|
738
|
-
Description:
|
|
739
|
-
${task.description || '(no description provided)'}
|
|
740
|
-
${context}
|
|
741
|
-
|
|
734
|
+
return `You are implementing a software development task. Make the necessary code changes to complete the task described below.
|
|
735
|
+
|
|
736
|
+
Task: ${task.name}
|
|
737
|
+
|
|
738
|
+
Description:
|
|
739
|
+
${task.description || '(no description provided)'}
|
|
740
|
+
${context}
|
|
741
|
+
|
|
742
742
|
Please implement the required changes. Focus on correctness and follow the existing code style in the project.`;
|
|
743
743
|
}
|
|
744
744
|
async function analyzeAndPlan(task, context, runners) {
|
|
@@ -747,28 +747,28 @@ async function analyzeAndPlan(task, context, runners) {
|
|
|
747
747
|
logger_1.logger.error('No AI runner available for task analysis');
|
|
748
748
|
return null;
|
|
749
749
|
}
|
|
750
|
-
const analysisPrompt = `You are a senior software architect breaking down a development task into smaller, sequential implementation steps.
|
|
751
|
-
|
|
752
|
-
Task name: ${task.name}
|
|
753
|
-
|
|
754
|
-
Description:
|
|
755
|
-
${task.description || '(no description provided)'}
|
|
756
|
-
${context}
|
|
757
|
-
|
|
758
|
-
Analyze this task and break it into smaller, independently implementable sub-tasks that should be executed sequentially. Each sub-task should be a coherent unit of work that can be committed separately.
|
|
759
|
-
|
|
760
|
-
Respond with valid JSON only — no markdown fences, no extra text:
|
|
761
|
-
{
|
|
762
|
-
"instructions": "Detailed implementation instructions in markdown covering the full task — architecture decisions, key files to modify, edge cases to handle, testing approach",
|
|
763
|
-
"subtasks": [
|
|
764
|
-
{
|
|
765
|
-
"id": 1,
|
|
766
|
-
"title": "Short title for the sub-task",
|
|
767
|
-
"description": "Detailed description of what to implement in this step, including specific files and functions to change"
|
|
768
|
-
}
|
|
769
|
-
]
|
|
770
|
-
}
|
|
771
|
-
|
|
750
|
+
const analysisPrompt = `You are a senior software architect breaking down a development task into smaller, sequential implementation steps.
|
|
751
|
+
|
|
752
|
+
Task name: ${task.name}
|
|
753
|
+
|
|
754
|
+
Description:
|
|
755
|
+
${task.description || '(no description provided)'}
|
|
756
|
+
${context}
|
|
757
|
+
|
|
758
|
+
Analyze this task and break it into smaller, independently implementable sub-tasks that should be executed sequentially. Each sub-task should be a coherent unit of work that can be committed separately.
|
|
759
|
+
|
|
760
|
+
Respond with valid JSON only — no markdown fences, no extra text:
|
|
761
|
+
{
|
|
762
|
+
"instructions": "Detailed implementation instructions in markdown covering the full task — architecture decisions, key files to modify, edge cases to handle, testing approach",
|
|
763
|
+
"subtasks": [
|
|
764
|
+
{
|
|
765
|
+
"id": 1,
|
|
766
|
+
"title": "Short title for the sub-task",
|
|
767
|
+
"description": "Detailed description of what to implement in this step, including specific files and functions to change"
|
|
768
|
+
}
|
|
769
|
+
]
|
|
770
|
+
}
|
|
771
|
+
|
|
772
772
|
Keep sub-tasks focused: 2-6 sub-tasks is ideal. Order them by dependency (foundation first).`;
|
|
773
773
|
logger_1.logger.info('Analyzing task and creating implementation plan...');
|
|
774
774
|
const result = await runner.run(analysisPrompt);
|
|
@@ -820,31 +820,31 @@ async function splitFailedSubtask(parentTask, plan, failedSubtask, runners) {
|
|
|
820
820
|
const diagnostics = failedSubtask.lastError && failedSubtask.lastError !== '__git__'
|
|
821
821
|
? failedSubtask.lastError
|
|
822
822
|
: '(no diagnostics captured)';
|
|
823
|
-
const splitPrompt = `You are a senior software architect helping recover a stalled implementation step by splitting it into exactly two smaller, sequential sub-tasks.
|
|
824
|
-
|
|
825
|
-
Overall task: ${parentTask.name}
|
|
826
|
-
${parentTask.description ? `\nTask description:\n${parentTask.description}\n` : ''}
|
|
827
|
-
## Surrounding plan
|
|
828
|
-
${siblings || '(no sibling sub-tasks)'}
|
|
829
|
-
|
|
830
|
-
## Failed sub-task
|
|
831
|
-
ID: ${formatSubtaskId(failedSubtask.id)}
|
|
832
|
-
Title: ${failedSubtask.title}
|
|
833
|
-
Description: ${failedSubtask.description}
|
|
834
|
-
|
|
835
|
-
## Previous failure diagnostics
|
|
836
|
-
${diagnostics}
|
|
837
|
-
|
|
838
|
-
Split the failed sub-task above into exactly two smaller, independently implementable sub-tasks that together achieve the original goal. Each new sub-task should be a coherent unit of work that can be committed separately, ordered by dependency (foundation first). Take the diagnostics into account so the split actually addresses what broke.
|
|
839
|
-
|
|
840
|
-
Respond with valid JSON only — no markdown fences, no extra text:
|
|
841
|
-
{
|
|
842
|
-
"subtasks": [
|
|
843
|
-
{ "title": "Short title for the first new sub-task", "description": "Detailed description of what to implement in this step" },
|
|
844
|
-
{ "title": "Short title for the second new sub-task", "description": "Detailed description of what to implement in this step" }
|
|
845
|
-
]
|
|
846
|
-
}
|
|
847
|
-
|
|
823
|
+
const splitPrompt = `You are a senior software architect helping recover a stalled implementation step by splitting it into exactly two smaller, sequential sub-tasks.
|
|
824
|
+
|
|
825
|
+
Overall task: ${parentTask.name}
|
|
826
|
+
${parentTask.description ? `\nTask description:\n${parentTask.description}\n` : ''}
|
|
827
|
+
## Surrounding plan
|
|
828
|
+
${siblings || '(no sibling sub-tasks)'}
|
|
829
|
+
|
|
830
|
+
## Failed sub-task
|
|
831
|
+
ID: ${formatSubtaskId(failedSubtask.id)}
|
|
832
|
+
Title: ${failedSubtask.title}
|
|
833
|
+
Description: ${failedSubtask.description}
|
|
834
|
+
|
|
835
|
+
## Previous failure diagnostics
|
|
836
|
+
${diagnostics}
|
|
837
|
+
|
|
838
|
+
Split the failed sub-task above into exactly two smaller, independently implementable sub-tasks that together achieve the original goal. Each new sub-task should be a coherent unit of work that can be committed separately, ordered by dependency (foundation first). Take the diagnostics into account so the split actually addresses what broke.
|
|
839
|
+
|
|
840
|
+
Respond with valid JSON only — no markdown fences, no extra text:
|
|
841
|
+
{
|
|
842
|
+
"subtasks": [
|
|
843
|
+
{ "title": "Short title for the first new sub-task", "description": "Detailed description of what to implement in this step" },
|
|
844
|
+
{ "title": "Short title for the second new sub-task", "description": "Detailed description of what to implement in this step" }
|
|
845
|
+
]
|
|
846
|
+
}
|
|
847
|
+
|
|
848
848
|
Exactly two entries — no more, no fewer.`;
|
|
849
849
|
logger_1.logger.info(`Splitting failed sub-task ${formatSubtaskId(failedSubtask.id)} into two smaller steps...`);
|
|
850
850
|
const result = await runner.run(splitPrompt);
|
|
@@ -899,20 +899,20 @@ async function executeSubTask(subtask, task, plan, config, runners, reviewContex
|
|
|
899
899
|
const retrySection = previousError && previousError !== '__git__'
|
|
900
900
|
? `\n## Previous attempt failure diagnostics\nThis step failed on a previous attempt. Diagnostics below — please take them into account and avoid repeating the same failure.\n\n${previousError}\n`
|
|
901
901
|
: '';
|
|
902
|
-
const prompt = `You are implementing step ${subtask.id} of a multi-step task.
|
|
903
|
-
|
|
904
|
-
Overall task: ${task.name}
|
|
905
|
-
${task.description ? `\nTask description:\n${task.description}` : ''}
|
|
906
|
-
|
|
907
|
-
## Full implementation instructions
|
|
908
|
-
${instructions}
|
|
909
|
-
${reviewContext || ''}${retrySection}
|
|
910
|
-
## Progress
|
|
911
|
-
${completedSteps || '(no steps completed yet)'}
|
|
912
|
-
|
|
913
|
-
## Current step: ${subtask.id}. ${subtask.title}
|
|
914
|
-
${subtask.description}
|
|
915
|
-
|
|
902
|
+
const prompt = `You are implementing step ${subtask.id} of a multi-step task.
|
|
903
|
+
|
|
904
|
+
Overall task: ${task.name}
|
|
905
|
+
${task.description ? `\nTask description:\n${task.description}` : ''}
|
|
906
|
+
|
|
907
|
+
## Full implementation instructions
|
|
908
|
+
${instructions}
|
|
909
|
+
${reviewContext || ''}${retrySection}
|
|
910
|
+
## Progress
|
|
911
|
+
${completedSteps || '(no steps completed yet)'}
|
|
912
|
+
|
|
913
|
+
## Current step: ${subtask.id}. ${subtask.title}
|
|
914
|
+
${subtask.description}
|
|
915
|
+
|
|
916
916
|
Implement ONLY this step. Focus on correctness and follow the existing code style.`;
|
|
917
917
|
let implemented = false;
|
|
918
918
|
let previousNotes = '';
|
|
@@ -1199,29 +1199,29 @@ function buildCompletionComment(branch, prUrl, config) {
|
|
|
1199
1199
|
function buildNonCodePrompt(task, context) {
|
|
1200
1200
|
const hasComments = context.trim().length > 0;
|
|
1201
1201
|
if (hasComments) {
|
|
1202
|
-
return `Task: ${task.name}
|
|
1203
|
-
|
|
1204
|
-
Original description:
|
|
1205
|
-
${task.description || '(no description provided)'}
|
|
1206
|
-
${context}
|
|
1207
|
-
|
|
1208
|
-
⚠️ CRITICAL: This is a FOLLOW-UP request. The conversation above contains new comments from the user.
|
|
1209
|
-
YOUR PRIMARY TASK is to address the LATEST comment at the bottom of the conversation - this is the user's current request.
|
|
1210
|
-
The latest comment may:
|
|
1211
|
-
- Ask for something completely different from the original task
|
|
1212
|
-
- Request modifications to what was already done
|
|
1213
|
-
- Add new requirements
|
|
1214
|
-
|
|
1215
|
-
DO NOT repeat what was already done. DO NOT re-execute the original task unless explicitly asked.
|
|
1216
|
-
Focus ENTIRELY on addressing the latest comment as your main instruction.
|
|
1217
|
-
|
|
1202
|
+
return `Task: ${task.name}
|
|
1203
|
+
|
|
1204
|
+
Original description:
|
|
1205
|
+
${task.description || '(no description provided)'}
|
|
1206
|
+
${context}
|
|
1207
|
+
|
|
1208
|
+
⚠️ CRITICAL: This is a FOLLOW-UP request. The conversation above contains new comments from the user.
|
|
1209
|
+
YOUR PRIMARY TASK is to address the LATEST comment at the bottom of the conversation - this is the user's current request.
|
|
1210
|
+
The latest comment may:
|
|
1211
|
+
- Ask for something completely different from the original task
|
|
1212
|
+
- Request modifications to what was already done
|
|
1213
|
+
- Add new requirements
|
|
1214
|
+
|
|
1215
|
+
DO NOT repeat what was already done. DO NOT re-execute the original task unless explicitly asked.
|
|
1216
|
+
Focus ENTIRELY on addressing the latest comment as your main instruction.
|
|
1217
|
+
|
|
1218
1218
|
Please provide a clear, detailed response to the LATEST comment. Your response will be posted as a comment on the task ticket, so write it as a direct answer or explanation addressed to the person who wrote the latest comment.`;
|
|
1219
1219
|
}
|
|
1220
|
-
return `Task: ${task.name}
|
|
1221
|
-
|
|
1222
|
-
Description:
|
|
1223
|
-
${task.description || '(no description provided)'}
|
|
1224
|
-
|
|
1220
|
+
return `Task: ${task.name}
|
|
1221
|
+
|
|
1222
|
+
Description:
|
|
1223
|
+
${task.description || '(no description provided)'}
|
|
1224
|
+
|
|
1225
1225
|
Please provide a clear, detailed response to this task. Your response will be posted as a comment on the task ticket, so write it as a direct answer or explanation addressed to the person who created the task.`;
|
|
1226
1226
|
}
|
|
1227
1227
|
function buildNonCodeCompletionComment(config, agentResponse) {
|
|
@@ -1531,22 +1531,22 @@ async function implementReviewTask(task, branchName, config, provider, runners,
|
|
|
1531
1531
|
logger_1.logger.success(`Review comments addressed for: ${task.name}`);
|
|
1532
1532
|
}
|
|
1533
1533
|
function buildReviewPrompt(task, threads) {
|
|
1534
|
-
let prompt = `You are addressing code review comments on a pull request for a software development task.
|
|
1535
|
-
|
|
1536
|
-
Task: ${task.name}
|
|
1537
|
-
|
|
1538
|
-
Description:
|
|
1539
|
-
${task.description || '(no description provided)'}
|
|
1540
|
-
|
|
1541
|
-
## Unresolved Code Review Threads
|
|
1542
|
-
|
|
1543
|
-
The following review threads need to be addressed. For each thread, either:
|
|
1544
|
-
- Fix the code as requested (make the changes directly in the files)
|
|
1545
|
-
- Or, if it's a discussion/question that doesn't require code changes, output a REPLY block:
|
|
1546
|
-
<!-- AIDEV-REPLY thread_id -->Your reply here<!-- /AIDEV-REPLY -->
|
|
1547
|
-
|
|
1548
|
-
Replace "thread_id" with the actual thread ID shown below.
|
|
1549
|
-
|
|
1534
|
+
let prompt = `You are addressing code review comments on a pull request for a software development task.
|
|
1535
|
+
|
|
1536
|
+
Task: ${task.name}
|
|
1537
|
+
|
|
1538
|
+
Description:
|
|
1539
|
+
${task.description || '(no description provided)'}
|
|
1540
|
+
|
|
1541
|
+
## Unresolved Code Review Threads
|
|
1542
|
+
|
|
1543
|
+
The following review threads need to be addressed. For each thread, either:
|
|
1544
|
+
- Fix the code as requested (make the changes directly in the files)
|
|
1545
|
+
- Or, if it's a discussion/question that doesn't require code changes, output a REPLY block:
|
|
1546
|
+
<!-- AIDEV-REPLY thread_id -->Your reply here<!-- /AIDEV-REPLY -->
|
|
1547
|
+
|
|
1548
|
+
Replace "thread_id" with the actual thread ID shown below.
|
|
1549
|
+
|
|
1550
1550
|
`;
|
|
1551
1551
|
for (const thread of threads) {
|
|
1552
1552
|
const location = thread.line
|
|
@@ -1558,12 +1558,12 @@ Replace "thread_id" with the actual thread ID shown below.
|
|
|
1558
1558
|
}
|
|
1559
1559
|
prompt += '\n';
|
|
1560
1560
|
}
|
|
1561
|
-
prompt += `## Instructions
|
|
1562
|
-
|
|
1563
|
-
1. Read each review thread carefully
|
|
1564
|
-
2. For code change requests: make the fix directly in the relevant file(s)
|
|
1565
|
-
3. For questions or discussions: output a REPLY block with a clear, helpful response
|
|
1566
|
-
4. You may handle multiple threads — some with code fixes, others with replies
|
|
1561
|
+
prompt += `## Instructions
|
|
1562
|
+
|
|
1563
|
+
1. Read each review thread carefully
|
|
1564
|
+
2. For code change requests: make the fix directly in the relevant file(s)
|
|
1565
|
+
3. For questions or discussions: output a REPLY block with a clear, helpful response
|
|
1566
|
+
4. You may handle multiple threads — some with code fixes, others with replies
|
|
1567
1567
|
5. Focus on correctness and follow the existing code style`;
|
|
1568
1568
|
return prompt;
|
|
1569
1569
|
}
|
package/dist/github.js
CHANGED
|
@@ -86,25 +86,25 @@ function getPrNumberForBranch(branch) {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
function fetchUnresolvedReviewThreads(owner, repo, prNumber) {
|
|
89
|
-
const query = `query($owner: String!, $repo: String!, $prNumber: Int!) {
|
|
90
|
-
repository(owner: $owner, name: $repo) {
|
|
91
|
-
pullRequest(number: $prNumber) {
|
|
92
|
-
reviewThreads(first: 100) {
|
|
93
|
-
nodes {
|
|
94
|
-
id
|
|
95
|
-
isResolved
|
|
96
|
-
path
|
|
97
|
-
line
|
|
98
|
-
comments(first: 50) {
|
|
99
|
-
nodes {
|
|
100
|
-
body
|
|
101
|
-
author { login }
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
89
|
+
const query = `query($owner: String!, $repo: String!, $prNumber: Int!) {
|
|
90
|
+
repository(owner: $owner, name: $repo) {
|
|
91
|
+
pullRequest(number: $prNumber) {
|
|
92
|
+
reviewThreads(first: 100) {
|
|
93
|
+
nodes {
|
|
94
|
+
id
|
|
95
|
+
isResolved
|
|
96
|
+
path
|
|
97
|
+
line
|
|
98
|
+
comments(first: 50) {
|
|
99
|
+
nodes {
|
|
100
|
+
body
|
|
101
|
+
author { login }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
108
|
}`;
|
|
109
109
|
const result = gh([
|
|
110
110
|
'api', 'graphql',
|
|
@@ -173,10 +173,10 @@ function mergePullRequest(branch) {
|
|
|
173
173
|
return { success: true, error: '' };
|
|
174
174
|
}
|
|
175
175
|
function replyToReviewThread(threadId, body) {
|
|
176
|
-
const mutation = `mutation($threadId: ID!, $body: String!) {
|
|
177
|
-
addPullRequestReviewThreadReply(input: { pullRequestReviewThreadId: $threadId, body: $body }) {
|
|
178
|
-
comment { id }
|
|
179
|
-
}
|
|
176
|
+
const mutation = `mutation($threadId: ID!, $body: String!) {
|
|
177
|
+
addPullRequestReviewThreadReply(input: { pullRequestReviewThreadId: $threadId, body: $body }) {
|
|
178
|
+
comment { id }
|
|
179
|
+
}
|
|
180
180
|
}`;
|
|
181
181
|
const result = gh([
|
|
182
182
|
'api', 'graphql',
|
|
@@ -199,10 +199,10 @@ function filterUnresolvedByNonAidev(threads, commentPrefix) {
|
|
|
199
199
|
});
|
|
200
200
|
}
|
|
201
201
|
function resolveReviewThread(threadId) {
|
|
202
|
-
const mutation = `mutation($threadId: ID!) {
|
|
203
|
-
resolveReviewThread(input: { threadId: $threadId }) {
|
|
204
|
-
thread { isResolved }
|
|
205
|
-
}
|
|
202
|
+
const mutation = `mutation($threadId: ID!) {
|
|
203
|
+
resolveReviewThread(input: { threadId: $threadId }) {
|
|
204
|
+
thread { isResolved }
|
|
205
|
+
}
|
|
206
206
|
}`;
|
|
207
207
|
const result = gh([
|
|
208
208
|
'api', 'graphql',
|