daedalus-cli 3.28.7 → 3.28.9
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/CHANGELOG.md +14 -0
- package/dist/agents/orchestrator-verification.js +1 -1
- package/dist/agents/orchestrator-verification.js.map +1 -1
- package/dist/agents/orchestrator.d.ts +1 -0
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +16 -2
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/commands/agents-manifest.test.d.ts +2 -0
- package/dist/commands/agents-manifest.test.d.ts.map +1 -0
- package/dist/commands/agents-manifest.test.js +53 -0
- package/dist/commands/agents-manifest.test.js.map +1 -0
- package/dist/commands/agents.d.ts +18 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +202 -156
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/config.js +5 -5
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/context.js +2 -2
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/spinner.js +2 -2
- package/dist/commands/spinner.js.map +1 -1
- package/dist/model.js +2 -2
- package/dist/model.js.map +1 -1
- package/dist/repl.js +1 -1
- package/dist/repl.js.map +1 -1
- package/dist/tools/builtin/patch-utils.d.ts.map +1 -1
- package/dist/tools/builtin/patch-utils.js +1 -0
- package/dist/tools/builtin/patch-utils.js.map +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/tui/index.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/emit.d.ts +6 -0
- package/dist/ui/emit.d.ts.map +1 -0
- package/dist/ui/emit.js +41 -0
- package/dist/ui/emit.js.map +1 -0
- package/dist/ui/emit.test.d.ts +2 -0
- package/dist/ui/emit.test.d.ts.map +1 -0
- package/dist/ui/emit.test.js +108 -0
- package/dist/ui/emit.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,3 +1,21 @@
|
|
|
1
1
|
import type { Command } from './types.js';
|
|
2
|
+
interface AutopilotManifest {
|
|
3
|
+
feature: string;
|
|
4
|
+
branch: string;
|
|
5
|
+
remote: string | null;
|
|
6
|
+
mode: 'git' | 'local-only' | 'non-git';
|
|
7
|
+
outcome: 'committed' | 'committed-local' | 'pr-opened' | 'stopped-verify' | 'stopped-error' | 'no-changes';
|
|
8
|
+
tasksPlanned: number;
|
|
9
|
+
tasksDone: number;
|
|
10
|
+
filesChanged: string[];
|
|
11
|
+
testResult: {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
detail: string;
|
|
14
|
+
} | null;
|
|
15
|
+
finishedAt: string;
|
|
16
|
+
}
|
|
17
|
+
declare function writeAutopilotManifest(m: AutopilotManifest): void;
|
|
18
|
+
export { writeAutopilotManifest };
|
|
19
|
+
export type { AutopilotManifest };
|
|
2
20
|
export declare const agentCommands: Command[];
|
|
3
21
|
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAoE1C,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,KAAK,GAAG,YAAY,GAAG,SAAS,CAAC;IACvC,OAAO,EAAE,WAAW,GAAG,iBAAiB,GAAG,WAAW,GAAG,gBAAgB,GAAG,eAAe,GAAG,YAAY,CAAC;IAC3G,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,sBAAsB,CAAC,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAU1D;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAClC,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAElC,eAAO,MAAM,aAAa,EAAE,OAAO,EA0uClC,CAAA"}
|
package/dist/commands/agents.js
CHANGED
|
@@ -39,7 +39,7 @@ function safeGitAdd(cwd) {
|
|
|
39
39
|
const exclude = staged.filter((f) => SECRET_FILE_PATTERN.test(f) || isGitIgnored(cwd, f));
|
|
40
40
|
if (exclude.length > 0) {
|
|
41
41
|
execSync(`git reset -q -- ${exclude.map((f) => JSON.stringify(f)).join(' ')}`, { cwd, stdio: 'ignore' });
|
|
42
|
-
console.log(pc.
|
|
42
|
+
console.log(pc.dim(`[CHECK] Excluded ${exclude.length} secret/ignored file(s) from commit (e.g. .env) — not staged.`));
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
catch {
|
|
@@ -75,6 +75,19 @@ async function runAutopilotVerify(cwd) {
|
|
|
75
75
|
}
|
|
76
76
|
return { ok: true, detail: '' };
|
|
77
77
|
}
|
|
78
|
+
function writeAutopilotManifest(m) {
|
|
79
|
+
try {
|
|
80
|
+
const dir = path.join(process.cwd(), '.daedalus');
|
|
81
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
82
|
+
const file = path.join(dir, `run-${Date.now()}.json`);
|
|
83
|
+
fs.writeFileSync(file, JSON.stringify(m, null, 2), 'utf8');
|
|
84
|
+
console.log(pc.dim(`[INFO] Run manifest written to ${file}`));
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// best-effort — manifest is a convenience, never block the session on it
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export { writeAutopilotManifest };
|
|
78
91
|
export const agentCommands = [
|
|
79
92
|
{
|
|
80
93
|
name: '/spawn',
|
|
@@ -828,186 +841,219 @@ export const agentCommands = [
|
|
|
828
841
|
console.log(pc.yellow('[WARN] Usage: /autopilot <feature description>'));
|
|
829
842
|
return;
|
|
830
843
|
}
|
|
831
|
-
|
|
844
|
+
const manifest = {
|
|
845
|
+
feature: idea,
|
|
846
|
+
branch: '',
|
|
847
|
+
remote: null,
|
|
848
|
+
mode: 'non-git',
|
|
849
|
+
outcome: 'stopped-error',
|
|
850
|
+
tasksPlanned: 0,
|
|
851
|
+
tasksDone: 0,
|
|
852
|
+
filesChanged: [],
|
|
853
|
+
testResult: null,
|
|
854
|
+
finishedAt: '',
|
|
855
|
+
};
|
|
856
|
+
const emitManifest = () => {
|
|
857
|
+
manifest.finishedAt = new Date().toISOString();
|
|
858
|
+
writeAutopilotManifest(manifest);
|
|
859
|
+
};
|
|
832
860
|
try {
|
|
833
|
-
|
|
834
|
-
}
|
|
835
|
-
catch {
|
|
836
|
-
isGitRepo = false;
|
|
837
|
-
}
|
|
838
|
-
if (!isGitRepo) {
|
|
839
|
-
console.log(pc.cyan('[INFO] Non-git directory detected. Auto-initializing Git repository for autonomous branch safety...'));
|
|
861
|
+
let isGitRepo = true;
|
|
840
862
|
try {
|
|
841
|
-
|
|
842
|
-
execSync('git init', { cwd });
|
|
843
|
-
const gitIgnorePath = path.join(cwd, '.gitignore');
|
|
844
|
-
if (!fs.existsSync(gitIgnorePath)) {
|
|
845
|
-
fs.writeFileSync(gitIgnorePath, "node_modules/\ndist/\n.daedalus/\n", 'utf8');
|
|
846
|
-
}
|
|
847
|
-
safeGitAdd(cwd);
|
|
848
|
-
execSync('git commit -m "initial clean setup"', { cwd });
|
|
849
|
-
isGitRepo = true;
|
|
850
|
-
console.log(pc.green('[OK] Git repository initialized with tracking branch support.'));
|
|
863
|
+
execSync('git rev-parse --is-inside-work-tree', { cwd: ctx.toolContext.projectRoot, stdio: 'ignore' });
|
|
851
864
|
}
|
|
852
865
|
catch {
|
|
853
|
-
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
const repoInfo = isGitRepo ? getGitRepoInfo(ctx.toolContext.projectRoot) : null;
|
|
857
|
-
if (!repoInfo) {
|
|
858
|
-
console.log(pc.yellow('[INFO] No GitHub remote found. Running in local-only mode (no PR will be created).'));
|
|
859
|
-
}
|
|
860
|
-
const slug = idea.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 40);
|
|
861
|
-
const branchName = `daedalus-autopilot-${slug}`;
|
|
862
|
-
if (isGitRepo) {
|
|
863
|
-
try {
|
|
864
|
-
execSync(`git checkout -B ${branchName}`, { cwd: ctx.toolContext.projectRoot });
|
|
865
|
-
console.log(pc.green(`[OK] Created branch: ${branchName}`));
|
|
866
|
+
isGitRepo = false;
|
|
866
867
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const result = await orchestrator.run(goal);
|
|
881
|
-
console.log(pc.white(`\n${result}`));
|
|
882
|
-
const orchestrationFailed = result.startsWith('Orchestration failed') || result.includes('## Orchestration Hit Verification Failures');
|
|
883
|
-
const wasAborted = result.includes('## Orchestration Paused');
|
|
884
|
-
if (orchestrationFailed || wasAborted) {
|
|
885
|
-
// Print Self-Evaluating Autopilot Post-Mortem Report before rolling back
|
|
886
|
-
const cols = process.stdout.columns || 80;
|
|
887
|
-
const lineLen = Math.max(20, Math.min(70, cols - 6));
|
|
888
|
-
console.log(`\n ${pc.bold(pc.red('─ Autopilot Post-Mortem ─'))} ${pc.dim('─'.repeat(Math.max(10, lineLen - 25)))}`);
|
|
889
|
-
const failed = orchestrator.results?.filter((r) => !r.success) || [];
|
|
890
|
-
if (failed.length > 0) {
|
|
891
|
-
failed.forEach((f, idx) => {
|
|
892
|
-
console.log(` ${pc.bold(pc.red(`❌ Failed Step ${idx + 1}:`))} ${pc.bold(`[${f.role}]`)} ${f.goal}`);
|
|
893
|
-
console.log(` ${pc.yellow(`📌 Diagnostic:`)} ${f.summary.split('\n')[0]}`);
|
|
894
|
-
});
|
|
868
|
+
if (!isGitRepo) {
|
|
869
|
+
console.log(pc.cyan('[INFO] Non-git directory detected. Auto-initializing Git repository for autonomous branch safety...'));
|
|
870
|
+
try {
|
|
871
|
+
const cwd = ctx.toolContext.projectRoot || process.cwd();
|
|
872
|
+
execSync('git init', { cwd });
|
|
873
|
+
const gitIgnorePath = path.join(cwd, '.gitignore');
|
|
874
|
+
if (!fs.existsSync(gitIgnorePath)) {
|
|
875
|
+
fs.writeFileSync(gitIgnorePath, "node_modules/\ndist/\n.daedalus/\n", 'utf8');
|
|
876
|
+
}
|
|
877
|
+
safeGitAdd(cwd);
|
|
878
|
+
execSync('git commit -m "initial clean setup"', { cwd });
|
|
879
|
+
isGitRepo = true;
|
|
880
|
+
console.log(pc.green('[OK] Git repository initialized with tracking branch support.'));
|
|
895
881
|
}
|
|
896
|
-
|
|
897
|
-
console.log(
|
|
882
|
+
catch {
|
|
883
|
+
console.log(pc.yellow('[WARNING] Working directory is not a git repository. Autonomous changes will NOT be tracked in a git branch.'));
|
|
898
884
|
}
|
|
899
|
-
console.log(`\n ${pc.cyan('💡 Recommendations:')}`);
|
|
900
|
-
console.log(` - Target missing file: ${pc.bold(`/task create <file>`)}`);
|
|
901
|
-
console.log(` - Re-run autopilot: ${pc.bold(`/autopilot ${idea}`)}`);
|
|
902
|
-
console.log(` ${pc.dim('─'.repeat(lineLen + 2))}\n`);
|
|
903
|
-
throw new Error(orchestrationFailed ? 'Orchestration reported failure' : 'Orchestration was paused/aborted');
|
|
904
885
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
886
|
+
const repoInfo = isGitRepo ? getGitRepoInfo(ctx.toolContext.projectRoot) : null;
|
|
887
|
+
if (!repoInfo) {
|
|
888
|
+
console.log(pc.yellow('[INFO] No GitHub remote found. Running in local-only mode (no PR will be created).'));
|
|
889
|
+
}
|
|
890
|
+
const slug = idea.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 40);
|
|
891
|
+
const branchName = `daedalus-autopilot-${slug}`;
|
|
892
|
+
manifest.remote = repoInfo ? `${repoInfo.owner}/${repoInfo.repo}` : null;
|
|
893
|
+
manifest.mode = !isGitRepo ? 'non-git' : repoInfo ? 'git' : 'local-only';
|
|
894
|
+
manifest.branch = branchName;
|
|
909
895
|
if (isGitRepo) {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
// inspect and fix the work instead of losing it.
|
|
914
|
-
if (repoInfo) {
|
|
915
|
-
try {
|
|
916
|
-
execSync('git reset --hard', { cwd: ctx.toolContext.projectRoot });
|
|
917
|
-
execSync('git checkout main', { cwd: ctx.toolContext.projectRoot });
|
|
918
|
-
execSync(`git branch -D ${branchName}`, { cwd: ctx.toolContext.projectRoot });
|
|
919
|
-
console.log(pc.green('[OK] Rolled back to main. Branch deleted.'));
|
|
920
|
-
}
|
|
921
|
-
catch (rollbackErr) {
|
|
922
|
-
const rbMsg = rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr);
|
|
923
|
-
console.log(pc.red(`[ERROR] Rollback failed: ${rbMsg}. Manual cleanup may be needed.`));
|
|
924
|
-
}
|
|
896
|
+
try {
|
|
897
|
+
execSync(`git checkout -B ${branchName}`, { cwd: ctx.toolContext.projectRoot });
|
|
898
|
+
console.log(pc.green(`[OK] Created branch: ${branchName}`));
|
|
925
899
|
}
|
|
926
|
-
|
|
927
|
-
|
|
900
|
+
catch (err) {
|
|
901
|
+
const msg = err instanceof Error ? errMessage(err) : String(err);
|
|
902
|
+
console.log(pc.red(`[ERROR] Failed to create branch: ${msg}`));
|
|
903
|
+
return;
|
|
928
904
|
}
|
|
929
905
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
const verify = await runAutopilotVerify(ctx.toolContext.projectRoot);
|
|
935
|
-
if (!verify.ok) {
|
|
936
|
-
console.log(pc.red(`\n[ERROR] Verification failed — not committing. ${verify.detail}`));
|
|
937
|
-
console.log(pc.cyan(`[INFO] Branch '${branchName}' is kept with the implemented changes for inspection.`));
|
|
938
|
-
return;
|
|
939
|
-
}
|
|
940
|
-
console.log(pc.green('[OK] Build & tests passed.'));
|
|
941
|
-
console.log(pc.cyan('\n[AUTOPILOT] Committing changes...'));
|
|
906
|
+
const goal = `Implement the following feature: ${idea}`;
|
|
907
|
+
console.log(pc.cyan(`\n[AUTOPILOT] Starting autonomous implementation...`));
|
|
908
|
+
process.env.DAEDALUS_AUTO_APPROVE = 'true';
|
|
909
|
+
process.env.DAEDALUS_ALLOW_INSTALL = 'true';
|
|
942
910
|
try {
|
|
943
|
-
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
console.log(pc.
|
|
911
|
+
const { Orchestrator } = await import('../agents/orchestrator.js');
|
|
912
|
+
const orchestrator = new Orchestrator(ctx.router, ctx.messages, ctx.toolContext, ctx.sessionManager, ctx.config?.modelOverride);
|
|
913
|
+
const result = await orchestrator.run(goal);
|
|
914
|
+
console.log(pc.white(`\n${result}`));
|
|
915
|
+
const orchestrationFailed = result.startsWith('Orchestration failed') || result.includes('## Orchestration Hit Verification Failures');
|
|
916
|
+
const wasAborted = result.includes('## Orchestration Paused');
|
|
917
|
+
if (orchestrationFailed || wasAborted) {
|
|
918
|
+
// Print Self-Evaluating Autopilot Post-Mortem Report before rolling back
|
|
919
|
+
const cols = process.stdout.columns || 80;
|
|
920
|
+
const lineLen = Math.max(20, Math.min(70, cols - 6));
|
|
921
|
+
console.log(`\n ${pc.bold(pc.red('─ Autopilot Post-Mortem ─'))} ${pc.dim('─'.repeat(Math.max(10, lineLen - 25)))}`);
|
|
922
|
+
const failed = orchestrator.results?.filter((r) => !r.success) || [];
|
|
923
|
+
if (failed.length > 0) {
|
|
924
|
+
failed.forEach((f, idx) => {
|
|
925
|
+
console.log(` ${pc.bold(pc.red(`❌ Failed Step ${idx + 1}:`))} ${pc.bold(`[${f.role}]`)} ${f.goal}`);
|
|
926
|
+
console.log(` ${pc.yellow(`📌 Diagnostic:`)} ${f.summary.split('\n')[0]}`);
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
else {
|
|
930
|
+
console.log(` ${pc.yellow('❌ Verification check failed — required files failed artifact or build checks.')}`);
|
|
931
|
+
}
|
|
932
|
+
console.log(`\n ${pc.cyan('💡 Recommendations:')}`);
|
|
933
|
+
console.log(` - Target missing file: ${pc.bold(`/task create <file>`)}`);
|
|
934
|
+
console.log(` - Re-run autopilot: ${pc.bold(`/autopilot ${idea}`)}`);
|
|
935
|
+
console.log(` ${pc.dim('─'.repeat(lineLen + 2))}\n`);
|
|
936
|
+
throw new Error(orchestrationFailed ? 'Orchestration reported failure' : 'Orchestration was paused/aborted');
|
|
937
|
+
}
|
|
947
938
|
}
|
|
948
939
|
catch (err) {
|
|
949
940
|
const msg = err instanceof Error ? errMessage(err) : String(err);
|
|
950
|
-
|
|
951
|
-
|
|
941
|
+
console.log(pc.red(`\n[ERROR] Run stopped: ${msg}`));
|
|
942
|
+
manifest.outcome = 'stopped-error';
|
|
943
|
+
if (isGitRepo) {
|
|
944
|
+
console.log(pc.dim('[CHECK] Verification did not pass — keeping the implemented changes on the branch for review.'));
|
|
945
|
+
// In remote-backed repos, discard the failed branch to keep main clean.
|
|
946
|
+
// In local-only mode (no remote), keep the branch so the user can
|
|
947
|
+
// inspect and fix the work instead of losing it.
|
|
948
|
+
if (repoInfo) {
|
|
949
|
+
try {
|
|
950
|
+
execSync('git reset --hard', { cwd: ctx.toolContext.projectRoot });
|
|
951
|
+
execSync('git checkout main', { cwd: ctx.toolContext.projectRoot });
|
|
952
|
+
execSync(`git branch -D ${branchName}`, { cwd: ctx.toolContext.projectRoot });
|
|
953
|
+
console.log(pc.green('[OK] Branch cleaned up; main is untouched.'));
|
|
954
|
+
}
|
|
955
|
+
catch (rollbackErr) {
|
|
956
|
+
const rbMsg = rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr);
|
|
957
|
+
console.log(pc.red(`[ERROR] Cleanup failed: ${rbMsg}. Manual cleanup may be needed.`));
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
console.log(pc.cyan(`[INFO] Local-only mode: keeping branch '${branchName}' with the implemented changes for inspection. Fix and commit manually.`));
|
|
962
|
+
}
|
|
952
963
|
}
|
|
953
|
-
|
|
954
|
-
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
if (isGitRepo) {
|
|
967
|
+
console.log(pc.cyan('\n[AUTOPILOT] Verifying build & tests before commit...'));
|
|
968
|
+
const verify = await runAutopilotVerify(ctx.toolContext.projectRoot);
|
|
969
|
+
if (!verify.ok) {
|
|
970
|
+
console.log(pc.red(`\n[ERROR] Verification did not pass — holding the changes on the branch instead of committing. ${verify.detail}`));
|
|
971
|
+
console.log(pc.cyan(`[INFO] Branch '${branchName}' is kept with the implemented changes for inspection.`));
|
|
972
|
+
manifest.outcome = 'stopped-verify';
|
|
973
|
+
manifest.testResult = verify;
|
|
955
974
|
return;
|
|
956
975
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
else {
|
|
960
|
-
console.log(pc.yellow('\n[INFO] Non-git working directory. Autonomous implementation completed directly on files.'));
|
|
961
|
-
}
|
|
962
|
-
if (repoInfo) {
|
|
963
|
-
console.log(pc.cyan('\n[AUTOPILOT] Pushing branch and creating PR...'));
|
|
964
|
-
let token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
965
|
-
if (!token) {
|
|
976
|
+
console.log(pc.green('[OK] Build & tests passed.'));
|
|
977
|
+
console.log(pc.cyan('\n[AUTOPILOT] Committing changes...'));
|
|
966
978
|
try {
|
|
967
|
-
|
|
979
|
+
safeGitAdd(ctx.toolContext.projectRoot);
|
|
980
|
+
const cleanTitle = idea.replace(/[^a-zA-Z0-9 ]/g, '').trim();
|
|
981
|
+
execSync(`git commit -m "feat: ${cleanTitle}"`, { cwd: ctx.toolContext.projectRoot });
|
|
982
|
+
console.log(pc.green('[OK] Changes committed.'));
|
|
983
|
+
try {
|
|
984
|
+
const diff = execSync(`git diff --name-only HEAD~1 HEAD`, { cwd: ctx.toolContext.projectRoot, encoding: 'utf8' });
|
|
985
|
+
manifest.filesChanged = diff.split('\n').map((s) => s.trim()).filter(Boolean);
|
|
986
|
+
}
|
|
987
|
+
catch { /* best-effort */ }
|
|
968
988
|
}
|
|
969
|
-
catch {
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
989
|
+
catch (err) {
|
|
990
|
+
const msg = err instanceof Error ? errMessage(err) : String(err);
|
|
991
|
+
if (msg.includes('nothing to commit')) {
|
|
992
|
+
console.log(pc.yellow('[INFO] No changes to commit.'));
|
|
993
|
+
}
|
|
994
|
+
else {
|
|
995
|
+
console.log(pc.red(`[ERROR] Failed to commit: ${msg}`));
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
973
998
|
}
|
|
974
999
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
if (prResponse.ok) {
|
|
991
|
-
const pr = await prResponse.json();
|
|
992
|
-
console.log(pc.green(`\n[OK] Pull Request created: ${pr.html_url}`));
|
|
1000
|
+
else {
|
|
1001
|
+
console.log(pc.yellow('\n[INFO] Non-git working directory. Autonomous implementation completed directly on files.'));
|
|
1002
|
+
}
|
|
1003
|
+
if (repoInfo) {
|
|
1004
|
+
console.log(pc.cyan('\n[AUTOPILOT] Pushing branch and creating PR...'));
|
|
1005
|
+
let token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
1006
|
+
if (!token) {
|
|
1007
|
+
try {
|
|
1008
|
+
token = execSync('gh auth token', { encoding: 'utf8' }).trim();
|
|
1009
|
+
}
|
|
1010
|
+
catch {
|
|
1011
|
+
console.log(pc.yellow('[INFO] No GitHub token found. Run `gh auth login` or set GITHUB_TOKEN.'));
|
|
1012
|
+
console.log(pc.yellow(`[INFO] Branch ${branchName} is ready locally. Push manually.`));
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
993
1015
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1016
|
+
try {
|
|
1017
|
+
execSync(`git push -u origin ${branchName} --force`, { cwd: ctx.toolContext.projectRoot });
|
|
1018
|
+
const prResponse = await fetch(`https://api.github.com/repos/${repoInfo.owner}/${repoInfo.repo}/pulls`, {
|
|
1019
|
+
method: 'POST',
|
|
1020
|
+
headers: {
|
|
1021
|
+
'Authorization': `Bearer ${token}`,
|
|
1022
|
+
'Content-Type': 'application/json',
|
|
1023
|
+
},
|
|
1024
|
+
body: JSON.stringify({
|
|
1025
|
+
title: `[Autopilot] ${idea}`,
|
|
1026
|
+
head: branchName,
|
|
1027
|
+
base: 'main',
|
|
1028
|
+
body: `## Description\n\nAutonomously implemented by Daedalus Autopilot.\n\n**Feature:** ${idea}\n\n---\n_Generated by \`/autopilot\`_`,
|
|
1029
|
+
}),
|
|
1030
|
+
});
|
|
1031
|
+
if (prResponse.ok) {
|
|
1032
|
+
const pr = await prResponse.json();
|
|
1033
|
+
console.log(pc.green(`\n[OK] Pull Request created: ${pr.html_url}`));
|
|
1034
|
+
}
|
|
1035
|
+
else {
|
|
1036
|
+
const errText = await prResponse.text();
|
|
1037
|
+
console.log(pc.red(`[ERROR] Failed to create PR: ${prResponse.status} ${errText}`));
|
|
1038
|
+
console.log(pc.yellow(`[INFO] Branch ${branchName} is pushed. Create PR manually.`));
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
catch (err) {
|
|
1042
|
+
const msg = err instanceof Error ? errMessage(err) : String(err);
|
|
1043
|
+
console.log(pc.red(`[ERROR] Push/PR failed: ${msg}`));
|
|
1044
|
+
console.log(pc.yellow(`[INFO] Branch ${branchName} is ready locally.`));
|
|
998
1045
|
}
|
|
999
1046
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
console.log(pc.
|
|
1003
|
-
console.log(pc.yellow(`[INFO] Branch ${branchName} is ready locally.`));
|
|
1047
|
+
else {
|
|
1048
|
+
console.log(pc.yellow('\n[INFO] No GitHub remote configured. Implementation is committed locally.'));
|
|
1049
|
+
console.log(pc.yellow(`[INFO] Branch: ${branchName}`));
|
|
1004
1050
|
}
|
|
1051
|
+
console.log(pc.cyan(`\n[AUTOPILOT] Done! Run 'git checkout main' to return to main branch.`));
|
|
1052
|
+
manifest.outcome = repoInfo ? 'pr-opened' : 'committed-local';
|
|
1005
1053
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
console.log(pc.yellow(`[INFO] Branch: ${branchName}`));
|
|
1054
|
+
finally {
|
|
1055
|
+
emitManifest();
|
|
1009
1056
|
}
|
|
1010
|
-
console.log(pc.cyan(`\n[AUTOPILOT] Done! Run 'git checkout main' to return to main branch.`));
|
|
1011
1057
|
}
|
|
1012
1058
|
},
|
|
1013
1059
|
{
|
|
@@ -1080,17 +1126,17 @@ export const agentCommands = [
|
|
|
1080
1126
|
}
|
|
1081
1127
|
catch (err) {
|
|
1082
1128
|
const msg = err instanceof Error ? errMessage(err) : String(err);
|
|
1083
|
-
console.log(pc.red(`\n[ERROR] Bug hunt
|
|
1084
|
-
console.log(pc.dim('[
|
|
1129
|
+
console.log(pc.red(`\n[ERROR] Bug hunt stopped: ${msg}`));
|
|
1130
|
+
console.log(pc.dim('[CHECK] Fix did not verify — discarding the attempt to keep main clean.'));
|
|
1085
1131
|
try {
|
|
1086
1132
|
execSync('git reset --hard', { cwd: ctx.toolContext.projectRoot });
|
|
1087
1133
|
execSync('git checkout main', { cwd: ctx.toolContext.projectRoot });
|
|
1088
1134
|
execSync(`git branch -D ${branchName}`, { cwd: ctx.toolContext.projectRoot });
|
|
1089
|
-
console.log(pc.green('[OK]
|
|
1135
|
+
console.log(pc.green('[OK] Branch cleaned up; main is untouched.'));
|
|
1090
1136
|
}
|
|
1091
1137
|
catch (rollbackErr) {
|
|
1092
1138
|
const rbMsg = rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr);
|
|
1093
|
-
console.log(pc.red(`[ERROR]
|
|
1139
|
+
console.log(pc.red(`[ERROR] Cleanup failed: ${rbMsg}. Manual cleanup may be needed.`));
|
|
1094
1140
|
}
|
|
1095
1141
|
return;
|
|
1096
1142
|
}
|