ralphctl 0.8.4 → 0.8.6
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/cli.mjs +291 -246
- package/dist/manifest.json +1 -1
- package/package.json +3 -1
package/dist/cli.mjs
CHANGED
|
@@ -778,8 +778,11 @@ var createJsonSettingsRepository = (deps) => {
|
|
|
778
778
|
};
|
|
779
779
|
};
|
|
780
780
|
|
|
781
|
+
// src/integration/io/cross-platform-spawn.ts
|
|
782
|
+
import spawn from "cross-spawn";
|
|
783
|
+
var crossPlatformSpawn = (command, args, options) => spawn(command, [...args], options);
|
|
784
|
+
|
|
781
785
|
// src/integration/io/git-runner.ts
|
|
782
|
-
import { spawn as nodeSpawn } from "child_process";
|
|
783
786
|
var DEFAULT_GIT_TIMEOUT_MS = 3e4;
|
|
784
787
|
var createGitRunner = (deps = {}) => {
|
|
785
788
|
const spawn3 = deps.spawn ?? defaultSpawn;
|
|
@@ -857,11 +860,11 @@ var createGitRunner = (deps = {}) => {
|
|
|
857
860
|
});
|
|
858
861
|
return { run };
|
|
859
862
|
};
|
|
860
|
-
var defaultSpawn = (command, args, options) =>
|
|
863
|
+
var defaultSpawn = (command, args, options) => crossPlatformSpawn(command, args, { ...options, stdio: [...options.stdio] });
|
|
861
864
|
var stringifyError = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
862
865
|
|
|
863
866
|
// src/integration/io/shell-script-runner.ts
|
|
864
|
-
import { spawn as
|
|
867
|
+
import { spawn as nodeSpawn } from "child_process";
|
|
865
868
|
var DEFAULT_SHELL_TIMEOUT_MS = 5 * 6e4;
|
|
866
869
|
var MAX_OUTPUT_BYTES = 50 * 1024 * 1024;
|
|
867
870
|
var createShellScriptRunner = (deps = {}) => {
|
|
@@ -987,7 +990,7 @@ ${marker}` : marker : base;
|
|
|
987
990
|
});
|
|
988
991
|
return { run };
|
|
989
992
|
};
|
|
990
|
-
var defaultSpawn2 = (command, args, options) =>
|
|
993
|
+
var defaultSpawn2 = (command, args, options) => nodeSpawn(command, [...args], { ...options, stdio: [...options.stdio] });
|
|
991
994
|
var stringifyError2 = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
992
995
|
|
|
993
996
|
// src/integration/persistence/project/project.schema.ts
|
|
@@ -2217,12 +2220,6 @@ var createAppendFile = () => {
|
|
|
2217
2220
|
};
|
|
2218
2221
|
};
|
|
2219
2222
|
|
|
2220
|
-
// src/application/bootstrap/wire.ts
|
|
2221
|
-
import { spawn as nodeSpawn9 } from "child_process";
|
|
2222
|
-
|
|
2223
|
-
// src/integration/ai/providers/claude/headless.ts
|
|
2224
|
-
import { spawn as nodeSpawn3 } from "child_process";
|
|
2225
|
-
|
|
2226
2223
|
// src/integration/ai/providers/_engine/resolve-roots.ts
|
|
2227
2224
|
var resolveWritableRoots = (session) => {
|
|
2228
2225
|
const declared = session.additionalRoots ?? [];
|
|
@@ -2908,13 +2905,12 @@ var spawnAttempt = async (input) => {
|
|
|
2908
2905
|
onSuccess
|
|
2909
2906
|
});
|
|
2910
2907
|
};
|
|
2911
|
-
var defaultSpawn3 = (command, args, options) =>
|
|
2908
|
+
var defaultSpawn3 = (command, args, options) => crossPlatformSpawn(command, args, {
|
|
2912
2909
|
stdio: [...options.stdio],
|
|
2913
2910
|
...options.cwd !== void 0 ? { cwd: options.cwd } : {}
|
|
2914
2911
|
});
|
|
2915
2912
|
|
|
2916
2913
|
// src/integration/ai/providers/codex/headless.ts
|
|
2917
|
-
import { spawn as nodeSpawn4 } from "child_process";
|
|
2918
2914
|
import { promises as fs6 } from "fs";
|
|
2919
2915
|
import { tmpdir } from "os";
|
|
2920
2916
|
import { join as join6 } from "path";
|
|
@@ -3291,14 +3287,11 @@ var spawnAttempt2 = async (input) => {
|
|
|
3291
3287
|
onSuccess
|
|
3292
3288
|
});
|
|
3293
3289
|
};
|
|
3294
|
-
var defaultSpawn4 = (command, args, options) =>
|
|
3290
|
+
var defaultSpawn4 = (command, args, options) => crossPlatformSpawn(command, args, {
|
|
3295
3291
|
stdio: [...options.stdio],
|
|
3296
3292
|
...options.cwd !== void 0 ? { cwd: options.cwd } : {}
|
|
3297
3293
|
});
|
|
3298
3294
|
|
|
3299
|
-
// src/integration/ai/providers/copilot/headless.ts
|
|
3300
|
-
import { spawn as nodeSpawn5 } from "child_process";
|
|
3301
|
-
|
|
3302
3295
|
// src/integration/ai/providers/copilot/parse-stream.ts
|
|
3303
3296
|
var stringField3 = (obj, ...names) => {
|
|
3304
3297
|
for (const name of names) {
|
|
@@ -3650,7 +3643,7 @@ var spawnAttempt3 = async (input) => {
|
|
|
3650
3643
|
onSuccess
|
|
3651
3644
|
});
|
|
3652
3645
|
};
|
|
3653
|
-
var defaultSpawn5 = (command, args, options) =>
|
|
3646
|
+
var defaultSpawn5 = (command, args, options) => crossPlatformSpawn(command, args, {
|
|
3654
3647
|
stdio: [...options.stdio],
|
|
3655
3648
|
...options.cwd !== void 0 ? { cwd: options.cwd } : {}
|
|
3656
3649
|
});
|
|
@@ -3689,12 +3682,20 @@ var createAiProvider = (deps) => {
|
|
|
3689
3682
|
};
|
|
3690
3683
|
|
|
3691
3684
|
// src/integration/ai/providers/claude/interactive.ts
|
|
3692
|
-
import {
|
|
3685
|
+
import { promises as fs7 } from "fs";
|
|
3686
|
+
import "child_process";
|
|
3693
3687
|
import { dirname as dirname5 } from "path";
|
|
3694
|
-
var defaultSpawn6 = (command, args, options) =>
|
|
3688
|
+
var defaultSpawn6 = (command, args, options) => (
|
|
3689
|
+
// Route through the shared cross-platform primitive so `claude.cmd` shims resolve on
|
|
3690
|
+
// Windows and the positional prompt argument (which may contain spaces or shell
|
|
3691
|
+
// metacharacters) is escaped correctly — without a shell. See cross-platform-spawn.ts.
|
|
3692
|
+
crossPlatformSpawn(command, args, { stdio: options.stdio, cwd: options.cwd })
|
|
3693
|
+
);
|
|
3694
|
+
var defaultReadFile = (path) => fs7.readFile(path, "utf8");
|
|
3695
3695
|
var createInteractiveClaudeProvider = (deps) => {
|
|
3696
3696
|
const spawnFn = deps.spawn ?? defaultSpawn6;
|
|
3697
|
-
const command = deps.command ?? "
|
|
3697
|
+
const command = deps.command ?? "claude";
|
|
3698
|
+
const readFile2 = deps.readFile ?? defaultReadFile;
|
|
3698
3699
|
const newSessionId = deps.newSessionId ?? uuidv7;
|
|
3699
3700
|
return {
|
|
3700
3701
|
async run(input) {
|
|
@@ -3708,6 +3709,18 @@ var createInteractiveClaudeProvider = (deps) => {
|
|
|
3708
3709
|
})
|
|
3709
3710
|
);
|
|
3710
3711
|
}
|
|
3712
|
+
let prompt;
|
|
3713
|
+
try {
|
|
3714
|
+
prompt = await readFile2(String(input.promptFile));
|
|
3715
|
+
} catch (cause) {
|
|
3716
|
+
return Result.error(
|
|
3717
|
+
new StorageError({
|
|
3718
|
+
subCode: "io",
|
|
3719
|
+
message: `interactive-claude: failed to read prompt file ${String(input.promptFile)} \u2014 ${stringifyError4(cause)}`,
|
|
3720
|
+
cause
|
|
3721
|
+
})
|
|
3722
|
+
);
|
|
3723
|
+
}
|
|
3711
3724
|
const allRoots = [
|
|
3712
3725
|
String(input.cwd),
|
|
3713
3726
|
...input.additionalRoots?.map((r) => String(r)) ?? [],
|
|
@@ -3719,19 +3732,18 @@ var createInteractiveClaudeProvider = (deps) => {
|
|
|
3719
3732
|
if (seen.has(p)) return false;
|
|
3720
3733
|
seen.add(p);
|
|
3721
3734
|
return true;
|
|
3722
|
-
}).flatMap((p) => ["--add-dir",
|
|
3735
|
+
}).flatMap((p) => ["--add-dir", p]);
|
|
3723
3736
|
const sessionId2 = newSessionId();
|
|
3724
|
-
const
|
|
3725
|
-
"claude",
|
|
3737
|
+
const args = [
|
|
3726
3738
|
...dirFlags,
|
|
3727
3739
|
"--model",
|
|
3728
|
-
|
|
3740
|
+
input.model,
|
|
3729
3741
|
"--permission-mode",
|
|
3730
3742
|
"acceptEdits",
|
|
3731
3743
|
"--session-id",
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
]
|
|
3744
|
+
sessionId2,
|
|
3745
|
+
prompt
|
|
3746
|
+
];
|
|
3735
3747
|
deps.eventBus.publish({
|
|
3736
3748
|
type: "log",
|
|
3737
3749
|
level: "info",
|
|
@@ -3741,7 +3753,7 @@ var createInteractiveClaudeProvider = (deps) => {
|
|
|
3741
3753
|
});
|
|
3742
3754
|
let child;
|
|
3743
3755
|
try {
|
|
3744
|
-
child = spawnFn(command,
|
|
3756
|
+
child = spawnFn(command, args, { stdio: "inherit", cwd: String(input.cwd) });
|
|
3745
3757
|
} catch (cause) {
|
|
3746
3758
|
return Result.error(
|
|
3747
3759
|
new StorageError({
|
|
@@ -3785,16 +3797,23 @@ var createInteractiveClaudeProvider = (deps) => {
|
|
|
3785
3797
|
}
|
|
3786
3798
|
};
|
|
3787
3799
|
};
|
|
3788
|
-
var shellQuote = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
3789
3800
|
var stringifyError4 = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
3790
3801
|
|
|
3791
3802
|
// src/integration/ai/providers/codex/interactive.ts
|
|
3792
|
-
import {
|
|
3803
|
+
import { promises as fs8 } from "fs";
|
|
3804
|
+
import "child_process";
|
|
3793
3805
|
import { dirname as dirname6 } from "path";
|
|
3794
|
-
var defaultSpawn7 = (command, args, options) =>
|
|
3806
|
+
var defaultSpawn7 = (command, args, options) => (
|
|
3807
|
+
// Route through the shared cross-platform primitive so `codex.cmd` shims resolve on
|
|
3808
|
+
// Windows and the positional prompt argument is escaped correctly — without a shell.
|
|
3809
|
+
// See cross-platform-spawn.ts.
|
|
3810
|
+
crossPlatformSpawn(command, args, { stdio: options.stdio, cwd: options.cwd })
|
|
3811
|
+
);
|
|
3812
|
+
var defaultReadFile2 = (path) => fs8.readFile(path, "utf8");
|
|
3795
3813
|
var createInteractiveCodexProvider = (deps) => {
|
|
3796
3814
|
const spawnFn = deps.spawn ?? defaultSpawn7;
|
|
3797
|
-
const command = deps.command ?? "
|
|
3815
|
+
const command = deps.command ?? "codex";
|
|
3816
|
+
const readFile2 = deps.readFile ?? defaultReadFile2;
|
|
3798
3817
|
return {
|
|
3799
3818
|
async run(input) {
|
|
3800
3819
|
if (!isCodexModel(input.model)) {
|
|
@@ -3807,6 +3826,18 @@ var createInteractiveCodexProvider = (deps) => {
|
|
|
3807
3826
|
})
|
|
3808
3827
|
);
|
|
3809
3828
|
}
|
|
3829
|
+
let prompt;
|
|
3830
|
+
try {
|
|
3831
|
+
prompt = await readFile2(String(input.promptFile));
|
|
3832
|
+
} catch (cause) {
|
|
3833
|
+
return Result.error(
|
|
3834
|
+
new StorageError({
|
|
3835
|
+
subCode: "io",
|
|
3836
|
+
message: `interactive-codex: failed to read prompt file ${String(input.promptFile)} \u2014 ${stringifyError5(cause)}`,
|
|
3837
|
+
cause
|
|
3838
|
+
})
|
|
3839
|
+
);
|
|
3840
|
+
}
|
|
3810
3841
|
const allRoots = [
|
|
3811
3842
|
String(input.cwd),
|
|
3812
3843
|
...input.additionalRoots?.map((r) => String(r)) ?? [],
|
|
@@ -3818,20 +3849,19 @@ var createInteractiveCodexProvider = (deps) => {
|
|
|
3818
3849
|
if (seen.has(p)) return false;
|
|
3819
3850
|
seen.add(p);
|
|
3820
3851
|
return true;
|
|
3821
|
-
}).flatMap((p) => ["--add-dir",
|
|
3822
|
-
const
|
|
3823
|
-
"codex",
|
|
3852
|
+
}).flatMap((p) => ["--add-dir", p]);
|
|
3853
|
+
const args = [
|
|
3824
3854
|
"--cd",
|
|
3825
|
-
|
|
3855
|
+
String(input.cwd),
|
|
3826
3856
|
...dirFlags,
|
|
3827
3857
|
"--model",
|
|
3828
|
-
|
|
3858
|
+
input.model,
|
|
3829
3859
|
"-s",
|
|
3830
3860
|
"workspace-write",
|
|
3831
3861
|
"-a",
|
|
3832
3862
|
"never",
|
|
3833
|
-
|
|
3834
|
-
]
|
|
3863
|
+
prompt
|
|
3864
|
+
];
|
|
3835
3865
|
deps.eventBus.publish({
|
|
3836
3866
|
type: "log",
|
|
3837
3867
|
level: "info",
|
|
@@ -3841,7 +3871,7 @@ var createInteractiveCodexProvider = (deps) => {
|
|
|
3841
3871
|
});
|
|
3842
3872
|
let child;
|
|
3843
3873
|
try {
|
|
3844
|
-
child = spawnFn(command,
|
|
3874
|
+
child = spawnFn(command, args, { stdio: "inherit", cwd: String(input.cwd) });
|
|
3845
3875
|
} catch (cause) {
|
|
3846
3876
|
return Result.error(
|
|
3847
3877
|
new StorageError({
|
|
@@ -3873,19 +3903,23 @@ var createInteractiveCodexProvider = (deps) => {
|
|
|
3873
3903
|
}
|
|
3874
3904
|
};
|
|
3875
3905
|
};
|
|
3876
|
-
var shellQuote2 = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
3877
3906
|
var stringifyError5 = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
3878
3907
|
|
|
3879
3908
|
// src/integration/ai/providers/copilot/interactive.ts
|
|
3880
|
-
import { promises as
|
|
3881
|
-
import
|
|
3909
|
+
import { promises as fs9 } from "fs";
|
|
3910
|
+
import "child_process";
|
|
3882
3911
|
import { dirname as dirname7 } from "path";
|
|
3883
|
-
var defaultSpawn8 = (command, args, options) =>
|
|
3884
|
-
|
|
3912
|
+
var defaultSpawn8 = (command, args, options) => (
|
|
3913
|
+
// Route through the shared cross-platform primitive so `copilot.cmd` shims resolve on
|
|
3914
|
+
// Windows and the seeded prompt argument is escaped correctly — without a shell.
|
|
3915
|
+
// See cross-platform-spawn.ts.
|
|
3916
|
+
crossPlatformSpawn(command, args, { stdio: options.stdio, cwd: options.cwd })
|
|
3917
|
+
);
|
|
3918
|
+
var defaultReadFile3 = (path) => fs9.readFile(path, "utf8");
|
|
3885
3919
|
var createInteractiveCopilotProvider = (deps) => {
|
|
3886
3920
|
const spawnFn = deps.spawn ?? defaultSpawn8;
|
|
3887
3921
|
const command = deps.command ?? "copilot";
|
|
3888
|
-
const readFile2 = deps.readFile ??
|
|
3922
|
+
const readFile2 = deps.readFile ?? defaultReadFile3;
|
|
3889
3923
|
const newSessionId = deps.newSessionId ?? uuidv7;
|
|
3890
3924
|
return {
|
|
3891
3925
|
async run(input) {
|
|
@@ -4512,7 +4546,7 @@ var createPullRequestCreator = (deps) => async (input) => {
|
|
|
4512
4546
|
};
|
|
4513
4547
|
|
|
4514
4548
|
// src/integration/ai/prompts/_engine/fs-template-loader.ts
|
|
4515
|
-
import { promises as
|
|
4549
|
+
import { promises as fs10 } from "fs";
|
|
4516
4550
|
import { dirname as dirname8, join as join7 } from "path";
|
|
4517
4551
|
import { fileURLToPath } from "url";
|
|
4518
4552
|
var createFsTemplateLoader = (templatesDir) => ({
|
|
@@ -4536,7 +4570,7 @@ var createFsTemplateLoader = (templatesDir) => ({
|
|
|
4536
4570
|
});
|
|
4537
4571
|
var tryRead = async (path) => {
|
|
4538
4572
|
try {
|
|
4539
|
-
const content = await
|
|
4573
|
+
const content = await fs10.readFile(path, "utf8");
|
|
4540
4574
|
return { kind: "ok", value: content };
|
|
4541
4575
|
} catch (cause) {
|
|
4542
4576
|
if (isNodeErrnoCode2(cause, "ENOENT")) return { kind: "missing" };
|
|
@@ -4582,7 +4616,7 @@ var ProbeError = class extends Error {
|
|
|
4582
4616
|
};
|
|
4583
4617
|
|
|
4584
4618
|
// src/integration/ai/readiness/_engine/probe-fs.ts
|
|
4585
|
-
import { promises as
|
|
4619
|
+
import { promises as fs11 } from "fs";
|
|
4586
4620
|
import { basename, join as join8 } from "path";
|
|
4587
4621
|
|
|
4588
4622
|
// src/domain/value/kebab-case.ts
|
|
@@ -4591,7 +4625,7 @@ var toKebabCase = (input) => input.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").
|
|
|
4591
4625
|
// src/integration/ai/readiness/_engine/probe-fs.ts
|
|
4592
4626
|
var probeFile = async (path) => {
|
|
4593
4627
|
try {
|
|
4594
|
-
const stat = await
|
|
4628
|
+
const stat = await fs11.stat(path);
|
|
4595
4629
|
if (!stat.isFile()) return Result.ok(void 0);
|
|
4596
4630
|
return Result.ok({ path });
|
|
4597
4631
|
} catch (cause) {
|
|
@@ -4642,7 +4676,7 @@ var probeNamedFileCollection = async (dir) => {
|
|
|
4642
4676
|
};
|
|
4643
4677
|
var listDir2 = async (dir) => {
|
|
4644
4678
|
try {
|
|
4645
|
-
return Result.ok(await
|
|
4679
|
+
return Result.ok(await fs11.readdir(dir));
|
|
4646
4680
|
} catch (cause) {
|
|
4647
4681
|
if (isNodeErrnoCode(cause, "ENOENT") || isNodeErrnoCode(cause, "ENOTDIR")) return Result.ok([]);
|
|
4648
4682
|
if (isNodeErrnoCode(cause, "EACCES")) {
|
|
@@ -4655,7 +4689,7 @@ var listDir2 = async (dir) => {
|
|
|
4655
4689
|
};
|
|
4656
4690
|
var statSafely = async (path) => {
|
|
4657
4691
|
try {
|
|
4658
|
-
return Result.ok(await
|
|
4692
|
+
return Result.ok(await fs11.stat(path));
|
|
4659
4693
|
} catch (cause) {
|
|
4660
4694
|
if (isNodeErrnoCode(cause, "ENOENT")) return Result.ok(void 0);
|
|
4661
4695
|
if (isNodeErrnoCode(cause, "EACCES")) {
|
|
@@ -4668,7 +4702,7 @@ var statSafely = async (path) => {
|
|
|
4668
4702
|
};
|
|
4669
4703
|
var readFileSafely = async (path) => {
|
|
4670
4704
|
try {
|
|
4671
|
-
return Result.ok(await
|
|
4705
|
+
return Result.ok(await fs11.readFile(path, "utf8"));
|
|
4672
4706
|
} catch (cause) {
|
|
4673
4707
|
if (isNodeErrnoCode(cause, "ENOENT")) return Result.ok(void 0);
|
|
4674
4708
|
if (isNodeErrnoCode(cause, "EACCES")) {
|
|
@@ -4793,14 +4827,14 @@ var codexProbe = {
|
|
|
4793
4827
|
};
|
|
4794
4828
|
|
|
4795
4829
|
// src/integration/ai/readiness/copilot/probe.ts
|
|
4796
|
-
import { promises as
|
|
4830
|
+
import { promises as fs12 } from "fs";
|
|
4797
4831
|
import { join as join11 } from "path";
|
|
4798
4832
|
var copilotProbe = {
|
|
4799
4833
|
tool: "copilot",
|
|
4800
4834
|
async evaluate(repository, now) {
|
|
4801
4835
|
const path = join11(repository.path, ".github/copilot-instructions.md");
|
|
4802
4836
|
try {
|
|
4803
|
-
const stat = await
|
|
4837
|
+
const stat = await fs12.stat(path);
|
|
4804
4838
|
if (!stat.isFile()) return Result.ok(absentState(now));
|
|
4805
4839
|
const artifacts = { tool: "copilot", copilotInstructions: { path } };
|
|
4806
4840
|
return Result.ok(hasAnyCopilotArtifact(artifacts) ? presentState(now, artifacts) : absentState(now));
|
|
@@ -4958,7 +4992,7 @@ var createNpmVersionChecker = (deps) => {
|
|
|
4958
4992
|
// package.json
|
|
4959
4993
|
var package_default = {
|
|
4960
4994
|
name: "ralphctl",
|
|
4961
|
-
version: "0.8.
|
|
4995
|
+
version: "0.8.6",
|
|
4962
4996
|
description: "Agent harness for long-running AI coding tasks \u2014 orchestrates Claude Code, GitHub Copilot, and OpenAI Codex across repositories",
|
|
4963
4997
|
homepage: "https://github.com/lukas-grigis/ralphctl",
|
|
4964
4998
|
type: "module",
|
|
@@ -5019,6 +5053,7 @@ var package_default = {
|
|
|
5019
5053
|
},
|
|
5020
5054
|
dependencies: {
|
|
5021
5055
|
commander: "^14.0.3",
|
|
5056
|
+
"cross-spawn": "^7.0.6",
|
|
5022
5057
|
ink: "^7.0.3",
|
|
5023
5058
|
react: "^19.2.6",
|
|
5024
5059
|
"typescript-result": "^3.5.2",
|
|
@@ -5026,6 +5061,7 @@ var package_default = {
|
|
|
5026
5061
|
},
|
|
5027
5062
|
devDependencies: {
|
|
5028
5063
|
"@eslint/js": "^10.0.1",
|
|
5064
|
+
"@types/cross-spawn": "^6.0.6",
|
|
5029
5065
|
"@types/node": "^25.8.0",
|
|
5030
5066
|
"@types/react": "^19.2.14",
|
|
5031
5067
|
"@vitest/coverage-v8": "^4.1.6",
|
|
@@ -5087,14 +5123,14 @@ import { mkdir, rm, rmdir, writeFile } from "fs/promises";
|
|
|
5087
5123
|
import { join as join14 } from "path";
|
|
5088
5124
|
|
|
5089
5125
|
// src/integration/io/git-exclude.ts
|
|
5090
|
-
import { promises as
|
|
5126
|
+
import { promises as fs13 } from "fs";
|
|
5091
5127
|
import { isAbsolute as isAbsolute2, join as join13 } from "path";
|
|
5092
5128
|
var ensureGitExcludeWildcard = async (repoRoot, pattern) => {
|
|
5093
5129
|
const resolved = await resolveExcludePath(String(repoRoot));
|
|
5094
5130
|
if (resolved === void 0) return Result.ok(void 0);
|
|
5095
5131
|
let existing = "";
|
|
5096
5132
|
try {
|
|
5097
|
-
existing = await
|
|
5133
|
+
existing = await fs13.readFile(resolved, "utf8");
|
|
5098
5134
|
} catch (cause) {
|
|
5099
5135
|
if (isNodeErrnoCode3(cause, "ENOENT")) {
|
|
5100
5136
|
} else {
|
|
@@ -5120,7 +5156,7 @@ var resolveExcludePath = async (repoRoot) => {
|
|
|
5120
5156
|
const gitMarker = join13(repoRoot, ".git");
|
|
5121
5157
|
let stat;
|
|
5122
5158
|
try {
|
|
5123
|
-
stat = await
|
|
5159
|
+
stat = await fs13.stat(gitMarker);
|
|
5124
5160
|
} catch (cause) {
|
|
5125
5161
|
if (isNodeErrnoCode3(cause, "ENOENT") || isNodeErrnoCode3(cause, "ENOTDIR")) return void 0;
|
|
5126
5162
|
throw cause;
|
|
@@ -5131,7 +5167,7 @@ var resolveExcludePath = async (repoRoot) => {
|
|
|
5131
5167
|
if (!stat.isFile()) return void 0;
|
|
5132
5168
|
let pointer;
|
|
5133
5169
|
try {
|
|
5134
|
-
pointer = await
|
|
5170
|
+
pointer = await fs13.readFile(gitMarker, "utf8");
|
|
5135
5171
|
} catch {
|
|
5136
5172
|
return void 0;
|
|
5137
5173
|
}
|
|
@@ -5582,7 +5618,7 @@ var NOOP_CHAIN_LOG_SINK = {
|
|
|
5582
5618
|
}
|
|
5583
5619
|
};
|
|
5584
5620
|
var isTruthyEnvFlag = (value) => typeof value === "string" && value.length > 0;
|
|
5585
|
-
var defaultPipeSpawn = (command, args, options) =>
|
|
5621
|
+
var defaultPipeSpawn = (command, args, options) => crossPlatformSpawn(command, args, {
|
|
5586
5622
|
...options,
|
|
5587
5623
|
stdio: [...options.stdio]
|
|
5588
5624
|
});
|
|
@@ -6626,6 +6662,103 @@ var UnknownViewFallback = ({ id }) => /* @__PURE__ */ jsxs(Box, { flexDirection:
|
|
|
6626
6662
|
// src/application/ui/tui/runtime/system-status-context.tsx
|
|
6627
6663
|
import { createContext as createContext10, useCallback as useCallback5, useContext as useContext10, useEffect as useEffect4, useState as useState6 } from "react";
|
|
6628
6664
|
|
|
6665
|
+
// src/integration/io/command-exists.ts
|
|
6666
|
+
import { spawn as spawn2 } from "child_process";
|
|
6667
|
+
var commandExists = (name) => new Promise((resolve) => {
|
|
6668
|
+
const child = process.platform === "win32" ? spawn2("where", [name], { stdio: "ignore" }) : spawn2("command", ["-v", name], { stdio: "ignore", shell: true });
|
|
6669
|
+
let settled = false;
|
|
6670
|
+
const settle = (value) => {
|
|
6671
|
+
if (settled) return;
|
|
6672
|
+
settled = true;
|
|
6673
|
+
resolve(value);
|
|
6674
|
+
};
|
|
6675
|
+
child.on("error", () => settle(false));
|
|
6676
|
+
child.on("exit", (code) => settle(code === 0));
|
|
6677
|
+
});
|
|
6678
|
+
|
|
6679
|
+
// src/integration/system/detect-cli.ts
|
|
6680
|
+
var PROVIDER_BINARY = {
|
|
6681
|
+
"claude-code": "claude",
|
|
6682
|
+
"github-copilot": "copilot",
|
|
6683
|
+
"openai-codex": "codex"
|
|
6684
|
+
};
|
|
6685
|
+
var PROVIDER_INSTALL_GUIDANCE = {
|
|
6686
|
+
"claude-code": {
|
|
6687
|
+
docsUrl: "https://docs.claude.com/en/docs/claude-code/setup",
|
|
6688
|
+
commandsByPlatform: {
|
|
6689
|
+
darwin: [
|
|
6690
|
+
"brew install --cask claude-code",
|
|
6691
|
+
"curl -fsSL https://claude.ai/install.sh | bash",
|
|
6692
|
+
"npm install -g @anthropic-ai/claude-code"
|
|
6693
|
+
],
|
|
6694
|
+
linux: ["curl -fsSL https://claude.ai/install.sh | bash", "npm install -g @anthropic-ai/claude-code"],
|
|
6695
|
+
win32: [
|
|
6696
|
+
"winget install Anthropic.ClaudeCode",
|
|
6697
|
+
"irm https://claude.ai/install.ps1 | iex",
|
|
6698
|
+
"npm install -g @anthropic-ai/claude-code"
|
|
6699
|
+
]
|
|
6700
|
+
}
|
|
6701
|
+
},
|
|
6702
|
+
"github-copilot": {
|
|
6703
|
+
docsUrl: "https://docs.github.com/en/copilot/how-tos/copilot-cli/set-up-copilot-cli/install-copilot-cli",
|
|
6704
|
+
commandsByPlatform: {
|
|
6705
|
+
darwin: ["brew install copilot-cli", "npm install -g @github/copilot"],
|
|
6706
|
+
linux: ["npm install -g @github/copilot", "brew install copilot-cli"],
|
|
6707
|
+
win32: ["winget install GitHub.Copilot", "npm install -g @github/copilot"]
|
|
6708
|
+
}
|
|
6709
|
+
},
|
|
6710
|
+
"openai-codex": {
|
|
6711
|
+
docsUrl: "https://github.com/openai/codex",
|
|
6712
|
+
commandsByPlatform: {
|
|
6713
|
+
darwin: [
|
|
6714
|
+
"brew install --cask codex",
|
|
6715
|
+
"curl -fsSL https://chatgpt.com/codex/install.sh | sh",
|
|
6716
|
+
"npm install -g @openai/codex"
|
|
6717
|
+
],
|
|
6718
|
+
linux: ["curl -fsSL https://chatgpt.com/codex/install.sh | sh", "npm install -g @openai/codex"],
|
|
6719
|
+
win32: [
|
|
6720
|
+
'powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"',
|
|
6721
|
+
"npm install -g @openai/codex"
|
|
6722
|
+
]
|
|
6723
|
+
}
|
|
6724
|
+
}
|
|
6725
|
+
};
|
|
6726
|
+
var resolveInstallPlatform = (platform = process.platform) => {
|
|
6727
|
+
if (platform === "darwin" || platform === "win32") return platform;
|
|
6728
|
+
return "linux";
|
|
6729
|
+
};
|
|
6730
|
+
var primaryInstallCommand = (provider, platform = process.platform) => {
|
|
6731
|
+
const os = resolveInstallPlatform(platform);
|
|
6732
|
+
const list = PROVIDER_INSTALL_GUIDANCE[provider].commandsByPlatform[os];
|
|
6733
|
+
const first = list[0];
|
|
6734
|
+
if (first === void 0) {
|
|
6735
|
+
throw new Error(`No install command registered for ${provider} on ${os}`);
|
|
6736
|
+
}
|
|
6737
|
+
return first;
|
|
6738
|
+
};
|
|
6739
|
+
var renderProviderInstallGuidance = (provider, platform = process.platform) => {
|
|
6740
|
+
const os = resolveInstallPlatform(platform);
|
|
6741
|
+
const guidance = PROVIDER_INSTALL_GUIDANCE[provider];
|
|
6742
|
+
const commands = guidance.commandsByPlatform[os];
|
|
6743
|
+
const header = `${provider} CLI (${PROVIDER_BINARY[provider]}) not on PATH`;
|
|
6744
|
+
const bullets = commands.map((c) => ` \u2022 ${c}`).join("\n");
|
|
6745
|
+
return `${header}
|
|
6746
|
+
Install options (${os}):
|
|
6747
|
+
${bullets}
|
|
6748
|
+
Docs: ${guidance.docsUrl}`;
|
|
6749
|
+
};
|
|
6750
|
+
var defaultWhich = commandExists;
|
|
6751
|
+
var detectInstalledProviders = async (options = {}) => {
|
|
6752
|
+
const which = options.which ?? defaultWhich;
|
|
6753
|
+
const providers = Object.keys(PROVIDER_BINARY);
|
|
6754
|
+
const results = await Promise.all(providers.map(async (p) => [p, await which(PROVIDER_BINARY[p])]));
|
|
6755
|
+
const installed = /* @__PURE__ */ new Set();
|
|
6756
|
+
for (const [provider, present] of results) {
|
|
6757
|
+
if (present) installed.add(provider);
|
|
6758
|
+
}
|
|
6759
|
+
return installed;
|
|
6760
|
+
};
|
|
6761
|
+
|
|
6629
6762
|
// src/application/chain/trace.ts
|
|
6630
6763
|
var abortedEntry = (elementName, reason) => ({
|
|
6631
6764
|
elementName,
|
|
@@ -6707,11 +6840,6 @@ var isDomainError = (cause) => cause instanceof Error && typeof cause.code === "
|
|
|
6707
6840
|
var MIN_NODE_MAJOR = 24;
|
|
6708
6841
|
|
|
6709
6842
|
// src/application/flows/doctor/flow.ts
|
|
6710
|
-
var PROVIDER_BINARY = {
|
|
6711
|
-
"claude-code": "claude",
|
|
6712
|
-
"github-copilot": "copilot",
|
|
6713
|
-
"openai-codex": "codex"
|
|
6714
|
-
};
|
|
6715
6843
|
var PROVIDER_LABEL = {
|
|
6716
6844
|
"claude-code": "Claude Code",
|
|
6717
6845
|
"github-copilot": "GitHub Copilot",
|
|
@@ -7066,30 +7194,47 @@ var probeSprintExecutionPairing = async (sprints, sprintExecutionRepo) => {
|
|
|
7066
7194
|
};
|
|
7067
7195
|
};
|
|
7068
7196
|
|
|
7069
|
-
// src/integration/io/command
|
|
7070
|
-
|
|
7071
|
-
var
|
|
7072
|
-
|
|
7197
|
+
// src/integration/io/run-command.ts
|
|
7198
|
+
var PROBE_TIMEOUT_MS = 5e3;
|
|
7199
|
+
var runCommand = (name, args) => new Promise((resolve) => {
|
|
7200
|
+
let child;
|
|
7201
|
+
try {
|
|
7202
|
+
child = crossPlatformSpawn(name, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
7203
|
+
} catch {
|
|
7204
|
+
resolve({ ok: false, code: null, stdout: "", stderr: "" });
|
|
7205
|
+
return;
|
|
7206
|
+
}
|
|
7207
|
+
const stdoutChunks = [];
|
|
7208
|
+
const stderrChunks = [];
|
|
7073
7209
|
let settled = false;
|
|
7074
|
-
const settle = (
|
|
7210
|
+
const settle = (result) => {
|
|
7075
7211
|
if (settled) return;
|
|
7076
7212
|
settled = true;
|
|
7077
|
-
|
|
7213
|
+
clearTimeout(timer);
|
|
7214
|
+
resolve(result);
|
|
7078
7215
|
};
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
// src/integration/io/run-command.ts
|
|
7084
|
-
import { execFile } from "child_process";
|
|
7085
|
-
var runCommand = (name, args) => new Promise((resolve) => {
|
|
7086
|
-
execFile(name, [...args], { timeout: 5e3, encoding: "utf8" }, (err, stdout, stderr) => {
|
|
7087
|
-
if (err === null) {
|
|
7088
|
-
resolve({ ok: true, code: 0, stdout, stderr });
|
|
7089
|
-
return;
|
|
7216
|
+
const timer = setTimeout(() => {
|
|
7217
|
+
try {
|
|
7218
|
+
child.kill("SIGTERM");
|
|
7219
|
+
} catch {
|
|
7090
7220
|
}
|
|
7091
|
-
|
|
7092
|
-
|
|
7221
|
+
settle({
|
|
7222
|
+
ok: false,
|
|
7223
|
+
code: null,
|
|
7224
|
+
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
7225
|
+
stderr: Buffer.concat(stderrChunks).toString("utf8")
|
|
7226
|
+
});
|
|
7227
|
+
}, PROBE_TIMEOUT_MS);
|
|
7228
|
+
child.stdout?.on("data", (c) => stdoutChunks.push(c));
|
|
7229
|
+
child.stderr?.on("data", (c) => stderrChunks.push(c));
|
|
7230
|
+
child.on("error", () => settle({ ok: false, code: null, stdout: "", stderr: "" }));
|
|
7231
|
+
child.on("close", (code) => {
|
|
7232
|
+
settle({
|
|
7233
|
+
ok: code === 0,
|
|
7234
|
+
code,
|
|
7235
|
+
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
7236
|
+
stderr: Buffer.concat(stderrChunks).toString("utf8")
|
|
7237
|
+
});
|
|
7093
7238
|
});
|
|
7094
7239
|
});
|
|
7095
7240
|
|
|
@@ -11206,16 +11351,16 @@ import { join as join23 } from "path";
|
|
|
11206
11351
|
|
|
11207
11352
|
// src/application/flows/refine/flow.ts
|
|
11208
11353
|
import { dirname as dirname11, join as join22 } from "path";
|
|
11209
|
-
import { promises as
|
|
11354
|
+
import { promises as fs17 } from "fs";
|
|
11210
11355
|
|
|
11211
11356
|
// src/application/flows/_shared/build-unit.ts
|
|
11212
|
-
import { promises as
|
|
11357
|
+
import { promises as fs14 } from "fs";
|
|
11213
11358
|
import { join as join17 } from "path";
|
|
11214
11359
|
var buildUnitLeaf = (opts) => leaf(opts.name, {
|
|
11215
11360
|
useCase: {
|
|
11216
11361
|
execute: async (input) => {
|
|
11217
11362
|
try {
|
|
11218
|
-
await
|
|
11363
|
+
await fs14.mkdir(input.path, { recursive: true });
|
|
11219
11364
|
} catch (cause) {
|
|
11220
11365
|
return Result.error(
|
|
11221
11366
|
new StorageError({
|
|
@@ -11327,7 +11472,7 @@ var fetchIssueContextLeaf = (deps, ticket) => leaf(`fetch-issue-context-${String
|
|
|
11327
11472
|
});
|
|
11328
11473
|
|
|
11329
11474
|
// src/application/flows/refine/leaves/refine-ticket-interactive.ts
|
|
11330
|
-
import { promises as
|
|
11475
|
+
import { promises as fs16 } from "fs";
|
|
11331
11476
|
import { dirname as dirname10, join as join20 } from "path";
|
|
11332
11477
|
|
|
11333
11478
|
// src/business/ticket/refine-ticket.ts
|
|
@@ -11425,14 +11570,14 @@ var renderFilename = (filename, index, multiplicity) => {
|
|
|
11425
11570
|
};
|
|
11426
11571
|
|
|
11427
11572
|
// src/integration/ai/contract/_engine/validate-signals-file.ts
|
|
11428
|
-
import { promises as
|
|
11573
|
+
import { promises as fs15 } from "fs";
|
|
11429
11574
|
import { join as join19 } from "path";
|
|
11430
11575
|
var SIGNALS_FILENAME = "signals.json";
|
|
11431
11576
|
var validateSignalsFile = async (outputDir, contract) => {
|
|
11432
11577
|
const path = join19(String(outputDir), SIGNALS_FILENAME);
|
|
11433
11578
|
let bytes;
|
|
11434
11579
|
try {
|
|
11435
|
-
bytes = await
|
|
11580
|
+
bytes = await fs15.readFile(path, "utf8");
|
|
11436
11581
|
} catch (cause) {
|
|
11437
11582
|
if (isNodeErrnoCode(cause, "ENOENT") || isNodeErrnoCode(cause, "ENOTDIR")) {
|
|
11438
11583
|
return Result.error(
|
|
@@ -11608,7 +11753,7 @@ var remapRefineSignalsError = (error) => {
|
|
|
11608
11753
|
};
|
|
11609
11754
|
var warnDroppedSignals = async (deps, outputDir) => {
|
|
11610
11755
|
try {
|
|
11611
|
-
const bytes = await
|
|
11756
|
+
const bytes = await fs16.readFile(join20(String(outputDir), "signals.json"), "utf8");
|
|
11612
11757
|
const raw = JSON.parse(bytes);
|
|
11613
11758
|
const inner = Array.isArray(raw) ? raw : raw.signals;
|
|
11614
11759
|
if (!Array.isArray(inner)) return;
|
|
@@ -11999,7 +12144,7 @@ var stampSessionMetaLeaf = (deps, opts) => leaf(opts.name, {
|
|
|
11999
12144
|
var readSprintProgress = async (refinementRoot) => {
|
|
12000
12145
|
const sprintDir2 = dirname11(String(refinementRoot));
|
|
12001
12146
|
try {
|
|
12002
|
-
return await
|
|
12147
|
+
return await fs17.readFile(join22(sprintDir2, "progress.md"), "utf8");
|
|
12003
12148
|
} catch {
|
|
12004
12149
|
return "";
|
|
12005
12150
|
}
|
|
@@ -12138,106 +12283,6 @@ var createRefineFlow = (deps, opts) => {
|
|
|
12138
12283
|
]);
|
|
12139
12284
|
};
|
|
12140
12285
|
|
|
12141
|
-
// src/integration/system/detect-cli.ts
|
|
12142
|
-
import { spawn as spawn2 } from "child_process";
|
|
12143
|
-
var PROVIDER_BINARY2 = {
|
|
12144
|
-
"claude-code": "claude",
|
|
12145
|
-
"github-copilot": "gh",
|
|
12146
|
-
"openai-codex": "codex"
|
|
12147
|
-
};
|
|
12148
|
-
var PROVIDER_INSTALL_GUIDANCE = {
|
|
12149
|
-
"claude-code": {
|
|
12150
|
-
docsUrl: "https://docs.claude.com/en/docs/claude-code/setup",
|
|
12151
|
-
commandsByPlatform: {
|
|
12152
|
-
darwin: [
|
|
12153
|
-
"brew install --cask claude-code",
|
|
12154
|
-
"curl -fsSL https://claude.ai/install.sh | bash",
|
|
12155
|
-
"npm install -g @anthropic-ai/claude-code"
|
|
12156
|
-
],
|
|
12157
|
-
linux: ["curl -fsSL https://claude.ai/install.sh | bash", "npm install -g @anthropic-ai/claude-code"],
|
|
12158
|
-
win32: [
|
|
12159
|
-
"winget install Anthropic.ClaudeCode",
|
|
12160
|
-
"irm https://claude.ai/install.ps1 | iex",
|
|
12161
|
-
"npm install -g @anthropic-ai/claude-code"
|
|
12162
|
-
]
|
|
12163
|
-
}
|
|
12164
|
-
},
|
|
12165
|
-
"github-copilot": {
|
|
12166
|
-
docsUrl: "https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-in-the-cli",
|
|
12167
|
-
commandsByPlatform: {
|
|
12168
|
-
darwin: ["brew install gh && gh extension install github/gh-copilot", "gh extension install github/gh-copilot"],
|
|
12169
|
-
linux: [
|
|
12170
|
-
"install gh from https://github.com/cli/cli/blob/trunk/docs/install_linux.md, then: gh extension install github/gh-copilot",
|
|
12171
|
-
"gh extension install github/gh-copilot"
|
|
12172
|
-
],
|
|
12173
|
-
win32: [
|
|
12174
|
-
"winget install --id GitHub.cli && gh extension install github/gh-copilot",
|
|
12175
|
-
"gh extension install github/gh-copilot"
|
|
12176
|
-
]
|
|
12177
|
-
}
|
|
12178
|
-
},
|
|
12179
|
-
"openai-codex": {
|
|
12180
|
-
docsUrl: "https://github.com/openai/codex",
|
|
12181
|
-
commandsByPlatform: {
|
|
12182
|
-
darwin: [
|
|
12183
|
-
"brew install --cask codex",
|
|
12184
|
-
"curl -fsSL https://chatgpt.com/codex/install.sh | sh",
|
|
12185
|
-
"npm install -g @openai/codex"
|
|
12186
|
-
],
|
|
12187
|
-
linux: ["curl -fsSL https://chatgpt.com/codex/install.sh | sh", "npm install -g @openai/codex"],
|
|
12188
|
-
win32: [
|
|
12189
|
-
'powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"',
|
|
12190
|
-
"npm install -g @openai/codex"
|
|
12191
|
-
]
|
|
12192
|
-
}
|
|
12193
|
-
}
|
|
12194
|
-
};
|
|
12195
|
-
var resolveInstallPlatform = (platform = process.platform) => {
|
|
12196
|
-
if (platform === "darwin" || platform === "win32") return platform;
|
|
12197
|
-
return "linux";
|
|
12198
|
-
};
|
|
12199
|
-
var primaryInstallCommand = (provider, platform = process.platform) => {
|
|
12200
|
-
const os = resolveInstallPlatform(platform);
|
|
12201
|
-
const list = PROVIDER_INSTALL_GUIDANCE[provider].commandsByPlatform[os];
|
|
12202
|
-
const first = list[0];
|
|
12203
|
-
if (first === void 0) {
|
|
12204
|
-
throw new Error(`No install command registered for ${provider} on ${os}`);
|
|
12205
|
-
}
|
|
12206
|
-
return first;
|
|
12207
|
-
};
|
|
12208
|
-
var renderProviderInstallGuidance = (provider, platform = process.platform) => {
|
|
12209
|
-
const os = resolveInstallPlatform(platform);
|
|
12210
|
-
const guidance = PROVIDER_INSTALL_GUIDANCE[provider];
|
|
12211
|
-
const commands = guidance.commandsByPlatform[os];
|
|
12212
|
-
const header = `${provider} CLI (${PROVIDER_BINARY2[provider]}) not on PATH`;
|
|
12213
|
-
const bullets = commands.map((c) => ` \u2022 ${c}`).join("\n");
|
|
12214
|
-
return `${header}
|
|
12215
|
-
Install options (${os}):
|
|
12216
|
-
${bullets}
|
|
12217
|
-
Docs: ${guidance.docsUrl}`;
|
|
12218
|
-
};
|
|
12219
|
-
var defaultWhich = (binary) => new Promise((resolve) => {
|
|
12220
|
-
const child = spawn2("command", ["-v", binary], { stdio: "pipe", shell: true });
|
|
12221
|
-
let settled = false;
|
|
12222
|
-
const settle = (value) => {
|
|
12223
|
-
if (settled) return;
|
|
12224
|
-
settled = true;
|
|
12225
|
-
resolve(value);
|
|
12226
|
-
};
|
|
12227
|
-
child.on("error", () => settle(false));
|
|
12228
|
-
child.on("exit", (code) => settle(code === 0));
|
|
12229
|
-
});
|
|
12230
|
-
var detectInstalledProviders = async (options = {}) => {
|
|
12231
|
-
const which = options.which ?? defaultWhich;
|
|
12232
|
-
const providers = Object.keys(PROVIDER_BINARY2);
|
|
12233
|
-
const results = await Promise.all(providers.map(async (p) => [p, await which(PROVIDER_BINARY2[p])]));
|
|
12234
|
-
const installed = /* @__PURE__ */ new Set();
|
|
12235
|
-
for (const [provider, present] of results) {
|
|
12236
|
-
if (present) installed.add(provider);
|
|
12237
|
-
}
|
|
12238
|
-
return installed;
|
|
12239
|
-
};
|
|
12240
|
-
|
|
12241
12286
|
// src/application/ui/shared/launch/check-cli.ts
|
|
12242
12287
|
var aiFlowIdForCheck = (flowId) => {
|
|
12243
12288
|
switch (flowId) {
|
|
@@ -12283,7 +12328,7 @@ var rowExpectationsFor = (aiFlow, settings, options) => {
|
|
|
12283
12328
|
};
|
|
12284
12329
|
var renderMissing = (missing, aiFlow) => {
|
|
12285
12330
|
const formatOne = (m) => {
|
|
12286
|
-
const binary =
|
|
12331
|
+
const binary = PROVIDER_BINARY[m.provider];
|
|
12287
12332
|
const installHint = primaryInstallCommand(m.provider);
|
|
12288
12333
|
const docsUrl = PROVIDER_INSTALL_GUIDANCE[m.provider].docsUrl;
|
|
12289
12334
|
const roleSuffix = m.role !== void 0 ? ` (${m.role})` : "";
|
|
@@ -12402,7 +12447,7 @@ import { join as join25 } from "path";
|
|
|
12402
12447
|
|
|
12403
12448
|
// src/application/flows/plan/flow.ts
|
|
12404
12449
|
import { dirname as dirname13, join as join24 } from "path";
|
|
12405
|
-
import { promises as
|
|
12450
|
+
import { promises as fs18 } from "fs";
|
|
12406
12451
|
|
|
12407
12452
|
// src/application/flows/_shared/sprint/load-execution.ts
|
|
12408
12453
|
var loadSprintExecutionLeaf = (deps, name = "load-sprint-execution") => leaf(name, {
|
|
@@ -13183,7 +13228,7 @@ var callPlannerInteractiveLeaf = (deps) => leaf("call-planner-interactive", {
|
|
|
13183
13228
|
var readSprintProgress2 = async (planRoot) => {
|
|
13184
13229
|
const sprintDir2 = dirname13(String(planRoot));
|
|
13185
13230
|
try {
|
|
13186
|
-
return await
|
|
13231
|
+
return await fs18.readFile(join24(sprintDir2, "progress.md"), "utf8");
|
|
13187
13232
|
} catch {
|
|
13188
13233
|
return "";
|
|
13189
13234
|
}
|
|
@@ -13688,7 +13733,7 @@ var branchPreflightLeaf = (deps, opts, name = "branch-preflight") => leaf(name,
|
|
|
13688
13733
|
});
|
|
13689
13734
|
|
|
13690
13735
|
// src/application/flows/implement/leaves/build-task-workspace.ts
|
|
13691
|
-
import { promises as
|
|
13736
|
+
import { promises as fs19 } from "fs";
|
|
13692
13737
|
import { join as join26 } from "path";
|
|
13693
13738
|
|
|
13694
13739
|
// src/integration/ai/prompts/_engine/renderers/task.ts
|
|
@@ -13998,8 +14043,8 @@ ${body}
|
|
|
13998
14043
|
// src/application/flows/implement/leaves/build-task-workspace.ts
|
|
13999
14044
|
var writeOrError = async (path, content) => {
|
|
14000
14045
|
try {
|
|
14001
|
-
await
|
|
14002
|
-
await
|
|
14046
|
+
await fs19.mkdir(path.slice(0, path.lastIndexOf("/")), { recursive: true });
|
|
14047
|
+
await fs19.writeFile(path, content, "utf8");
|
|
14003
14048
|
return Result.ok(void 0);
|
|
14004
14049
|
} catch (cause) {
|
|
14005
14050
|
return Result.error(
|
|
@@ -14723,7 +14768,7 @@ var loop = (name, body, opts = {}) => ({
|
|
|
14723
14768
|
|
|
14724
14769
|
// src/application/flows/implement/leaves/evaluator.ts
|
|
14725
14770
|
import { dirname as dirname15, join as join28 } from "path";
|
|
14726
|
-
import { promises as
|
|
14771
|
+
import { promises as fs21 } from "fs";
|
|
14727
14772
|
|
|
14728
14773
|
// src/business/task/plateau-detection.ts
|
|
14729
14774
|
var failedDimensions = (signal) => {
|
|
@@ -15174,7 +15219,7 @@ var evaluatorOutputContract = {
|
|
|
15174
15219
|
};
|
|
15175
15220
|
|
|
15176
15221
|
// src/application/flows/implement/leaves/round-artifacts.ts
|
|
15177
|
-
import { promises as
|
|
15222
|
+
import { promises as fs20 } from "fs";
|
|
15178
15223
|
import { join as join27 } from "path";
|
|
15179
15224
|
var nextRoundNum = async (workspaceRoot) => {
|
|
15180
15225
|
const entries = await listDir(join27(String(workspaceRoot), "rounds"));
|
|
@@ -15191,7 +15236,7 @@ var readRoundSessionId = async (workspaceRoot, round, role) => {
|
|
|
15191
15236
|
const path = join27(String(workspaceRoot), "rounds", String(round), role, "session-id.txt");
|
|
15192
15237
|
let content;
|
|
15193
15238
|
try {
|
|
15194
|
-
content = await
|
|
15239
|
+
content = await fs20.readFile(path, "utf8");
|
|
15195
15240
|
} catch {
|
|
15196
15241
|
return void 0;
|
|
15197
15242
|
}
|
|
@@ -15211,7 +15256,7 @@ var writeRoundPrompt = async (workspaceRoot, round, role, prompt, logger) => {
|
|
|
15211
15256
|
// src/application/flows/implement/leaves/evaluator.ts
|
|
15212
15257
|
var readProgressFile = async (path) => {
|
|
15213
15258
|
try {
|
|
15214
|
-
return await
|
|
15259
|
+
return await fs21.readFile(path, "utf8");
|
|
15215
15260
|
} catch {
|
|
15216
15261
|
return "";
|
|
15217
15262
|
}
|
|
@@ -15335,7 +15380,7 @@ var evaluatorLeaf = (deps, taskId) => leaf(`evaluator-${String(taskId)}`, {
|
|
|
15335
15380
|
|
|
15336
15381
|
// src/application/flows/implement/leaves/generator.ts
|
|
15337
15382
|
import { dirname as dirname16, join as join29 } from "path";
|
|
15338
|
-
import { promises as
|
|
15383
|
+
import { promises as fs22 } from "fs";
|
|
15339
15384
|
|
|
15340
15385
|
// src/business/task/run-generator-turn.ts
|
|
15341
15386
|
var findTaskBlocked = (signals) => signals.find((s) => s.type === "task-blocked")?.reason;
|
|
@@ -15402,7 +15447,7 @@ var latestCritique = (task) => {
|
|
|
15402
15447
|
// src/application/flows/implement/leaves/generator.ts
|
|
15403
15448
|
var readProgressFile2 = async (path) => {
|
|
15404
15449
|
try {
|
|
15405
|
-
return await
|
|
15450
|
+
return await fs22.readFile(path, "utf8");
|
|
15406
15451
|
} catch {
|
|
15407
15452
|
return "";
|
|
15408
15453
|
}
|
|
@@ -18036,7 +18081,7 @@ var launchImplement = async (ctx) => {
|
|
|
18036
18081
|
import { join as join38 } from "path";
|
|
18037
18082
|
|
|
18038
18083
|
// src/application/flows/review/leaves/ensure-feedback-file.ts
|
|
18039
|
-
import { promises as
|
|
18084
|
+
import { promises as fs23 } from "fs";
|
|
18040
18085
|
|
|
18041
18086
|
// src/business/feedback/md-parser.ts
|
|
18042
18087
|
var ROUND_HEADING_RE = /^##\s+Round\s+(\d+)\s*$/;
|
|
@@ -18096,12 +18141,12 @@ var ensureFeedbackFileLeaf = (feedbackFile) => leaf("ensure-feedback-file", {
|
|
|
18096
18141
|
useCase: {
|
|
18097
18142
|
execute: async (path) => {
|
|
18098
18143
|
try {
|
|
18099
|
-
await
|
|
18144
|
+
await fs23.access(String(path));
|
|
18100
18145
|
return Result.ok(void 0);
|
|
18101
18146
|
} catch {
|
|
18102
18147
|
}
|
|
18103
18148
|
try {
|
|
18104
|
-
await
|
|
18149
|
+
await fs23.writeFile(String(path), TEMPLATE, { flag: "wx" });
|
|
18105
18150
|
return Result.ok(void 0);
|
|
18106
18151
|
} catch (cause) {
|
|
18107
18152
|
if (typeof cause === "object" && cause !== null && cause.code === "EEXIST") {
|
|
@@ -18123,7 +18168,7 @@ var ensureFeedbackFileLeaf = (feedbackFile) => leaf("ensure-feedback-file", {
|
|
|
18123
18168
|
});
|
|
18124
18169
|
|
|
18125
18170
|
// src/application/flows/review/leaves/review-round.ts
|
|
18126
|
-
import { promises as
|
|
18171
|
+
import { promises as fs24 } from "fs";
|
|
18127
18172
|
import { join as join37 } from "path";
|
|
18128
18173
|
|
|
18129
18174
|
// src/business/feedback/apply-feedback.ts
|
|
@@ -18306,7 +18351,7 @@ var reviewRoundOutputContract = {
|
|
|
18306
18351
|
var readProgressSnippet = async (path) => {
|
|
18307
18352
|
if (path === void 0) return "_(no progress file)_";
|
|
18308
18353
|
try {
|
|
18309
|
-
const content = await
|
|
18354
|
+
const content = await fs24.readFile(String(path), "utf8");
|
|
18310
18355
|
return content.length > 4e3 ? `${content.slice(0, 4e3)}
|
|
18311
18356
|
[truncated]` : content;
|
|
18312
18357
|
} catch {
|
|
@@ -18322,7 +18367,7 @@ ${renderEmptyRound(nextIndex)}${ROUND_SEPARATOR}
|
|
|
18322
18367
|
};
|
|
18323
18368
|
var writeRoundBody = async (path, body) => {
|
|
18324
18369
|
try {
|
|
18325
|
-
const content = await
|
|
18370
|
+
const content = await fs24.readFile(String(path), "utf8");
|
|
18326
18371
|
const lastMarker = content.lastIndexOf(MARKER_COMMENT);
|
|
18327
18372
|
if (lastMarker === -1) {
|
|
18328
18373
|
return Result.error(
|
|
@@ -18339,7 +18384,7 @@ var writeRoundBody = async (path, body) => {
|
|
|
18339
18384
|
const next = `${head}
|
|
18340
18385
|
${body.replace(/\s+$/u, "")}
|
|
18341
18386
|
${tail}`;
|
|
18342
|
-
await
|
|
18387
|
+
await fs24.writeFile(String(path), next, "utf8");
|
|
18343
18388
|
return Result.ok(void 0);
|
|
18344
18389
|
} catch (cause) {
|
|
18345
18390
|
return Result.error(
|
|
@@ -18363,7 +18408,7 @@ var allocateRoundPaths = (reviewRoot, roundIndex) => {
|
|
|
18363
18408
|
};
|
|
18364
18409
|
var ensureRoundDir = async (dir) => {
|
|
18365
18410
|
try {
|
|
18366
|
-
await
|
|
18411
|
+
await fs24.mkdir(String(dir), { recursive: true });
|
|
18367
18412
|
return Result.ok(void 0);
|
|
18368
18413
|
} catch (cause) {
|
|
18369
18414
|
return Result.error(
|
|
@@ -18397,7 +18442,7 @@ var reviewRoundLeaf = (deps, opts) => leaf("review-round", {
|
|
|
18397
18442
|
if (!wrote.ok) return Result.error(wrote.error);
|
|
18398
18443
|
return Result.ok(void 0);
|
|
18399
18444
|
},
|
|
18400
|
-
readFeedbackFile: () =>
|
|
18445
|
+
readFeedbackFile: () => fs24.readFile(String(input.feedbackFile), "utf8"),
|
|
18401
18446
|
readProgressSnippet: () => readProgressSnippet(input.progressFile),
|
|
18402
18447
|
buildPrompt: async (params) => {
|
|
18403
18448
|
const outputContractSection = renderContractSectionFor(reviewRoundOutputContract, paths.value.outputDir);
|
|
@@ -18875,7 +18920,7 @@ var probeReadinessLeaf = (deps, tool) => leaf(`probe-${tool}`, {
|
|
|
18875
18920
|
});
|
|
18876
18921
|
|
|
18877
18922
|
// src/application/flows/readiness/leaves/propose.ts
|
|
18878
|
-
import { promises as
|
|
18923
|
+
import { promises as fs25 } from "fs";
|
|
18879
18924
|
|
|
18880
18925
|
// src/integration/ai/readiness/_engine/setup.ts
|
|
18881
18926
|
import { join as join40 } from "path";
|
|
@@ -19174,7 +19219,7 @@ var proposeReadinessUseCase = async (deps, tool, input) => {
|
|
|
19174
19219
|
let existingBody;
|
|
19175
19220
|
if (existingPath !== void 0) {
|
|
19176
19221
|
try {
|
|
19177
|
-
existingBody = await
|
|
19222
|
+
existingBody = await fs25.readFile(existingPath, "utf8");
|
|
19178
19223
|
} catch {
|
|
19179
19224
|
existingBody = void 0;
|
|
19180
19225
|
}
|
|
@@ -19292,7 +19337,7 @@ var proposeReadinessLeaf = (deps, tool) => leaf(`propose-${tool}`, {
|
|
|
19292
19337
|
});
|
|
19293
19338
|
|
|
19294
19339
|
// src/application/flows/readiness/leaves/write.ts
|
|
19295
|
-
import { promises as
|
|
19340
|
+
import { promises as fs26 } from "fs";
|
|
19296
19341
|
var writeReadinessUseCase = async (deps, tool, input) => {
|
|
19297
19342
|
const log = deps.logger.named(`readiness.write-${tool}`);
|
|
19298
19343
|
if (!input.accepted || input.proposal === void 0) {
|
|
@@ -19326,7 +19371,7 @@ var makeBackupPath = (targetPath, now) => {
|
|
|
19326
19371
|
};
|
|
19327
19372
|
var fileExists = async (path) => {
|
|
19328
19373
|
try {
|
|
19329
|
-
const stat = await
|
|
19374
|
+
const stat = await fs26.stat(path);
|
|
19330
19375
|
return stat.isFile();
|
|
19331
19376
|
} catch {
|
|
19332
19377
|
return false;
|
|
@@ -19334,7 +19379,7 @@ var fileExists = async (path) => {
|
|
|
19334
19379
|
};
|
|
19335
19380
|
var safeReadText = async (path) => {
|
|
19336
19381
|
try {
|
|
19337
|
-
return await
|
|
19382
|
+
return await fs26.readFile(path, "utf8");
|
|
19338
19383
|
} catch {
|
|
19339
19384
|
return void 0;
|
|
19340
19385
|
}
|
|
@@ -19359,11 +19404,11 @@ var writeReadinessLeaf = (deps, tool) => leaf(`write-${tool}`, {
|
|
|
19359
19404
|
});
|
|
19360
19405
|
|
|
19361
19406
|
// src/application/flows/_shared/allocate-run-dir.ts
|
|
19362
|
-
import { promises as
|
|
19407
|
+
import { promises as fs28 } from "fs";
|
|
19363
19408
|
import { join as join42 } from "path";
|
|
19364
19409
|
|
|
19365
19410
|
// src/integration/ai/runs/_engine/run-artifacts.ts
|
|
19366
|
-
import { promises as
|
|
19411
|
+
import { promises as fs27 } from "fs";
|
|
19367
19412
|
import { join as join41 } from "path";
|
|
19368
19413
|
var BODY_PREVIEW_LIMIT = 800;
|
|
19369
19414
|
var buildRunDirName = () => {
|
|
@@ -19374,7 +19419,7 @@ var buildRunDirName = () => {
|
|
|
19374
19419
|
var readRunBodyPreview = async (runDir, options) => {
|
|
19375
19420
|
let raw;
|
|
19376
19421
|
try {
|
|
19377
|
-
raw = await
|
|
19422
|
+
raw = await fs27.readFile(join41(String(runDir), "body.txt"), "utf8");
|
|
19378
19423
|
} catch (cause) {
|
|
19379
19424
|
if (isErrnoException(cause) && cause.code === "ENOENT") return void 0;
|
|
19380
19425
|
const code = isErrnoException(cause) ? cause.code : "unknown";
|
|
@@ -19394,7 +19439,7 @@ var allocateRunDirLeaf = (opts) => leaf(opts.name, {
|
|
|
19394
19439
|
useCase: {
|
|
19395
19440
|
execute: async (input) => {
|
|
19396
19441
|
try {
|
|
19397
|
-
await
|
|
19442
|
+
await fs28.mkdir(input.path, { recursive: true });
|
|
19398
19443
|
} catch (cause) {
|
|
19399
19444
|
return Result.error(
|
|
19400
19445
|
new StorageError({
|
|
@@ -20868,7 +20913,7 @@ import { join as join46 } from "path";
|
|
|
20868
20913
|
|
|
20869
20914
|
// src/application/flows/ideate/flow.ts
|
|
20870
20915
|
import { dirname as dirname19, join as join45 } from "path";
|
|
20871
|
-
import { promises as
|
|
20916
|
+
import { promises as fs29 } from "fs";
|
|
20872
20917
|
|
|
20873
20918
|
// src/integration/ai/prompts/ideate/definition.ts
|
|
20874
20919
|
var nonEmpty2 = (field) => (v) => v.trim().length === 0 ? Result.error(new ValidationError({ field, value: v, message: `${field} must not be empty` })) : Result.ok(v);
|
|
@@ -21143,7 +21188,7 @@ var ideateAndPlanLeaf = (deps) => leaf("ideate-and-plan", {
|
|
|
21143
21188
|
var readSprintProgress3 = async (ideateRoot) => {
|
|
21144
21189
|
const sprintDir2 = dirname19(String(ideateRoot));
|
|
21145
21190
|
try {
|
|
21146
|
-
return await
|
|
21191
|
+
return await fs29.readFile(join45(sprintDir2, "progress.md"), "utf8");
|
|
21147
21192
|
} catch {
|
|
21148
21193
|
return "";
|
|
21149
21194
|
}
|
|
@@ -27087,7 +27132,7 @@ var createSettingsSetProviderFlow = (deps) => leaf("settings-set-provider", {
|
|
|
27087
27132
|
new ValidationError({
|
|
27088
27133
|
field: settingsKey,
|
|
27089
27134
|
value: input.provider,
|
|
27090
|
-
message: `${input.provider} CLI (${
|
|
27135
|
+
message: `${input.provider} CLI (${PROVIDER_BINARY[input.provider]}) not on PATH \u2014 cannot set ${settingsKey}`,
|
|
27091
27136
|
hint: renderProviderInstallGuidance(input.provider)
|
|
27092
27137
|
})
|
|
27093
27138
|
);
|
|
@@ -28788,7 +28833,7 @@ import { basename as basename5, join as join52 } from "path";
|
|
|
28788
28833
|
|
|
28789
28834
|
// src/application/ui/tui/prompts/path-picker-prompt.tsx
|
|
28790
28835
|
import { useEffect as useEffect38, useState as useState44 } from "react";
|
|
28791
|
-
import { promises as
|
|
28836
|
+
import { promises as fs30 } from "fs";
|
|
28792
28837
|
import { dirname as dirname20, join as join51 } from "path";
|
|
28793
28838
|
import { homedir } from "os";
|
|
28794
28839
|
import { Box as Box70, Text as Text69, useInput as useInput28 } from "ink";
|
|
@@ -28815,7 +28860,7 @@ var PathPickerPrompt = ({
|
|
|
28815
28860
|
useEffect38(() => {
|
|
28816
28861
|
const load = async () => {
|
|
28817
28862
|
try {
|
|
28818
|
-
const items = await
|
|
28863
|
+
const items = await fs30.readdir(cwd, { withFileTypes: true });
|
|
28819
28864
|
const filtered = items.filter((d) => showHidden || !d.name.startsWith(".")).filter((d) => d.isDirectory()).map((d) => ({ name: d.name, isDirectory: true })).sort((a, b) => a.name.localeCompare(b.name));
|
|
28820
28865
|
setEntries(filtered);
|
|
28821
28866
|
setError(void 0);
|
|
@@ -28898,7 +28943,7 @@ var PathPickerPrompt = ({
|
|
|
28898
28943
|
return;
|
|
28899
28944
|
}
|
|
28900
28945
|
try {
|
|
28901
|
-
const stat = await
|
|
28946
|
+
const stat = await fs30.stat(expanded);
|
|
28902
28947
|
if (!stat.isDirectory()) {
|
|
28903
28948
|
setError(`${expanded} is not a directory`);
|
|
28904
28949
|
setTyping(false);
|
|
@@ -30225,7 +30270,7 @@ import { useEffect as useEffect45, useMemo as useMemo26, useRef as useRef13 } fr
|
|
|
30225
30270
|
import { useApp, useInput as useInput32 } from "ink";
|
|
30226
30271
|
|
|
30227
30272
|
// src/integration/io/clipboard.ts
|
|
30228
|
-
import { spawn as
|
|
30273
|
+
import { spawn as nodeSpawn2 } from "child_process";
|
|
30229
30274
|
var resolveHelpers = ({ platform, env }) => {
|
|
30230
30275
|
if (platform === "darwin") return [{ cmd: "pbcopy", args: [] }];
|
|
30231
30276
|
if (platform === "win32") return [{ cmd: "clip.exe", args: [] }];
|
|
@@ -30290,7 +30335,7 @@ var runHelper = (spawn3, helper, text) => new Promise((resolve) => {
|
|
|
30290
30335
|
}
|
|
30291
30336
|
});
|
|
30292
30337
|
var createCopyToClipboard = (opts = {}) => {
|
|
30293
|
-
const spawn3 = opts.spawn ??
|
|
30338
|
+
const spawn3 = opts.spawn ?? nodeSpawn2;
|
|
30294
30339
|
const platform = opts.platform ?? process.platform;
|
|
30295
30340
|
const env = opts.env ?? process.env;
|
|
30296
30341
|
const helpers = resolveHelpers({ platform, env });
|
|
@@ -30497,7 +30542,7 @@ var ChainLogDegradedBanner = () => {
|
|
|
30497
30542
|
};
|
|
30498
30543
|
|
|
30499
30544
|
// src/application/ui/tui/components/progress-overlay.tsx
|
|
30500
|
-
import { promises as
|
|
30545
|
+
import { promises as fs31 } from "fs";
|
|
30501
30546
|
import { join as join54 } from "path";
|
|
30502
30547
|
import { useEffect as useEffect48, useMemo as useMemo27, useState as useState53 } from "react";
|
|
30503
30548
|
import { Box as Box82, Text as Text80, useInput as useInput33 } from "ink";
|
|
@@ -30528,7 +30573,7 @@ var ProgressOverlay = () => {
|
|
|
30528
30573
|
}
|
|
30529
30574
|
const load = async () => {
|
|
30530
30575
|
try {
|
|
30531
|
-
const [stat, content] = await Promise.all([
|
|
30576
|
+
const [stat, content] = await Promise.all([fs31.stat(progressPath), fs31.readFile(progressPath, "utf8")]);
|
|
30532
30577
|
if (cancelled) return;
|
|
30533
30578
|
const modifiedAtMs = stat.mtimeMs;
|
|
30534
30579
|
if (content.trim().length === 0) {
|
|
@@ -30733,7 +30778,7 @@ var resolveInitialState = ({
|
|
|
30733
30778
|
};
|
|
30734
30779
|
|
|
30735
30780
|
// src/integration/persistence/selection/last-selection-store.ts
|
|
30736
|
-
import { promises as
|
|
30781
|
+
import { promises as fs32 } from "fs";
|
|
30737
30782
|
import { join as join55 } from "path";
|
|
30738
30783
|
var FILE_NAME = "last-selection.json";
|
|
30739
30784
|
var createLastSelectionStore = (stateRoot) => {
|
|
@@ -30741,7 +30786,7 @@ var createLastSelectionStore = (stateRoot) => {
|
|
|
30741
30786
|
return {
|
|
30742
30787
|
async read() {
|
|
30743
30788
|
try {
|
|
30744
|
-
const raw = await
|
|
30789
|
+
const raw = await fs32.readFile(path, "utf8");
|
|
30745
30790
|
const parsed = JSON.parse(raw);
|
|
30746
30791
|
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
30747
30792
|
const rec = parsed;
|
|
@@ -30759,10 +30804,10 @@ var createLastSelectionStore = (stateRoot) => {
|
|
|
30759
30804
|
async write(value) {
|
|
30760
30805
|
try {
|
|
30761
30806
|
if (value === void 0) {
|
|
30762
|
-
await
|
|
30807
|
+
await fs32.rm(path, { force: true });
|
|
30763
30808
|
return;
|
|
30764
30809
|
}
|
|
30765
|
-
await
|
|
30810
|
+
await fs32.writeFile(path, JSON.stringify(value, null, 2), "utf8");
|
|
30766
30811
|
} catch {
|
|
30767
30812
|
}
|
|
30768
30813
|
}
|
|
@@ -30858,7 +30903,7 @@ var startHeapWatchdog = (deps) => {
|
|
|
30858
30903
|
import { execFile as execFileCb } from "child_process";
|
|
30859
30904
|
import { promisify } from "util";
|
|
30860
30905
|
import { platform as osPlatform } from "os";
|
|
30861
|
-
var
|
|
30906
|
+
var execFile = promisify(execFileCb);
|
|
30862
30907
|
var SHELL_TIMEOUT_MS = 5e3;
|
|
30863
30908
|
var BELL = "\x07";
|
|
30864
30909
|
var defaultEmitBell = () => {
|
|
@@ -30867,7 +30912,7 @@ var defaultEmitBell = () => {
|
|
|
30867
30912
|
} catch {
|
|
30868
30913
|
}
|
|
30869
30914
|
};
|
|
30870
|
-
var defaultExecFile = (command, args, options) =>
|
|
30915
|
+
var defaultExecFile = (command, args, options) => execFile(command, [...args], { timeout: options.timeout }).then((r) => ({
|
|
30871
30916
|
stdout: r.stdout.toString(),
|
|
30872
30917
|
stderr: r.stderr.toString()
|
|
30873
30918
|
}));
|
|
@@ -31987,11 +32032,11 @@ var formatTaskLine = (t) => {
|
|
|
31987
32032
|
};
|
|
31988
32033
|
|
|
31989
32034
|
// src/application/ui/cli/commands/runs.ts
|
|
31990
|
-
import { promises as
|
|
32035
|
+
import { promises as fs34 } from "fs";
|
|
31991
32036
|
import { createInterface } from "readline";
|
|
31992
32037
|
|
|
31993
32038
|
// src/integration/ai/runs/_engine/run-enumeration.ts
|
|
31994
|
-
import { promises as
|
|
32039
|
+
import { promises as fs33 } from "fs";
|
|
31995
32040
|
import { join as join57 } from "path";
|
|
31996
32041
|
var parseRunTimestamp = (runDirName) => {
|
|
31997
32042
|
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z-/.exec(runDirName);
|
|
@@ -32091,7 +32136,7 @@ var listRuns = async (runsRoot) => {
|
|
|
32091
32136
|
const root = String(runsRoot);
|
|
32092
32137
|
let flowDirs;
|
|
32093
32138
|
try {
|
|
32094
|
-
flowDirs = await
|
|
32139
|
+
flowDirs = await fs33.readdir(root, { withFileTypes: true });
|
|
32095
32140
|
} catch (cause) {
|
|
32096
32141
|
if (isErrnoException2(cause) && cause.code === "ENOENT") return Result.ok([]);
|
|
32097
32142
|
return Result.error(
|
|
@@ -32108,7 +32153,7 @@ var listRuns = async (runsRoot) => {
|
|
|
32108
32153
|
const flowPath = join57(root, flowDir.name);
|
|
32109
32154
|
let runDirs;
|
|
32110
32155
|
try {
|
|
32111
|
-
runDirs = await
|
|
32156
|
+
runDirs = await fs33.readdir(flowPath, { withFileTypes: true });
|
|
32112
32157
|
} catch (cause) {
|
|
32113
32158
|
if (isErrnoException2(cause) && cause.code === "ENOENT") continue;
|
|
32114
32159
|
return Result.error(
|
|
@@ -32153,7 +32198,7 @@ var computeDirSize = async (dir) => {
|
|
|
32153
32198
|
let total = 0;
|
|
32154
32199
|
let entries;
|
|
32155
32200
|
try {
|
|
32156
|
-
entries = await
|
|
32201
|
+
entries = await fs33.readdir(dir, { withFileTypes: true });
|
|
32157
32202
|
} catch {
|
|
32158
32203
|
return 0;
|
|
32159
32204
|
}
|
|
@@ -32164,7 +32209,7 @@ var computeDirSize = async (dir) => {
|
|
|
32164
32209
|
continue;
|
|
32165
32210
|
}
|
|
32166
32211
|
try {
|
|
32167
|
-
const stat = await
|
|
32212
|
+
const stat = await fs33.lstat(entryPath);
|
|
32168
32213
|
if (stat.isFile()) total += stat.size;
|
|
32169
32214
|
} catch {
|
|
32170
32215
|
}
|
|
@@ -32459,7 +32504,7 @@ var performPrune = async (candidates) => {
|
|
|
32459
32504
|
let freedCount = 0;
|
|
32460
32505
|
for (const candidate of candidates) {
|
|
32461
32506
|
try {
|
|
32462
|
-
await
|
|
32507
|
+
await fs34.rm(String(candidate.path), { recursive: true, force: false });
|
|
32463
32508
|
freedBytes += candidate.sizeBytes;
|
|
32464
32509
|
freedCount += 1;
|
|
32465
32510
|
} catch (cause) {
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ralphctl",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"description": "Agent harness for long-running AI coding tasks — orchestrates Claude Code, GitHub Copilot, and OpenAI Codex across repositories",
|
|
5
5
|
"homepage": "https://github.com/lukas-grigis/ralphctl",
|
|
6
6
|
"type": "module",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"commander": "^14.0.3",
|
|
42
|
+
"cross-spawn": "^7.0.6",
|
|
42
43
|
"ink": "^7.0.3",
|
|
43
44
|
"react": "^19.2.6",
|
|
44
45
|
"typescript-result": "^3.5.2",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@eslint/js": "^10.0.1",
|
|
50
|
+
"@types/cross-spawn": "^6.0.6",
|
|
49
51
|
"@types/node": "^25.8.0",
|
|
50
52
|
"@types/react": "^19.2.14",
|
|
51
53
|
"@vitest/coverage-v8": "^4.1.6",
|