lalph 0.3.85 → 0.3.87
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 +621 -95
- package/package.json +1 -1
- package/src/Agents/chooser.ts +1 -1
- package/src/Agents/chooserRalph.ts +57 -0
- package/src/Agents/planner.ts +4 -1
- package/src/Agents/reviewer.ts +3 -1
- package/src/Agents/timeout.ts +39 -11
- package/src/Agents/worker.ts +5 -1
- package/src/Clanka.ts +7 -2
- package/src/CurrentIssueSource.ts +31 -5
- package/src/GitFlow.ts +56 -0
- package/src/Prd.ts +9 -0
- package/src/Projects.ts +22 -16
- package/src/PromptGen.ts +57 -17
- package/src/Settings.ts +14 -1
- package/src/commands/plan.ts +35 -15
- package/src/commands/projects/rm.ts +2 -2
- package/src/commands/projects/toggle.ts +2 -2
- package/src/commands/root.ts +229 -21
- package/src/domain/CliAgent.ts +33 -15
- package/src/domain/Project.ts +10 -2
package/dist/cli.mjs
CHANGED
|
@@ -9478,6 +9478,23 @@ const forEachSequential = (iterable, f, options) => suspend$4(() => {
|
|
|
9478
9478
|
});
|
|
9479
9479
|
const filterOrElse$1 = /* @__PURE__ */ dual(3, (self, predicate, orElse) => flatMap$6(self, (a) => predicate(a) ? succeed$7(a) : orElse(a)));
|
|
9480
9480
|
/** @internal */
|
|
9481
|
+
const filter$6 = /* @__PURE__ */ dual((args) => isIterable(args[0]) && !isEffect$1(args[0]), (elements, predicate, options) => suspend$4(() => {
|
|
9482
|
+
const out = [];
|
|
9483
|
+
return as$2(forEach$5(elements, (a, i) => {
|
|
9484
|
+
const result = predicate(a, i);
|
|
9485
|
+
if (typeof result === "boolean") {
|
|
9486
|
+
if (result) out.push(a);
|
|
9487
|
+
return void_$4;
|
|
9488
|
+
}
|
|
9489
|
+
return map$12(result, (keep) => {
|
|
9490
|
+
if (keep) out.push(a);
|
|
9491
|
+
});
|
|
9492
|
+
}, {
|
|
9493
|
+
discard: true,
|
|
9494
|
+
concurrency: options?.concurrency
|
|
9495
|
+
}), out);
|
|
9496
|
+
}));
|
|
9497
|
+
/** @internal */
|
|
9481
9498
|
const filterMapEffect$2 = /* @__PURE__ */ dual((args) => isIterable(args[0]) && !isEffect$1(args[0]), (elements, filter, options) => suspend$4(() => {
|
|
9482
9499
|
const out = [];
|
|
9483
9500
|
return as$2(forEach$5(elements, (a) => map$12(filter(a), (result) => {
|
|
@@ -14539,6 +14556,28 @@ const withFiber = withFiber$1;
|
|
|
14539
14556
|
*/
|
|
14540
14557
|
const fromOption = fromOption$1;
|
|
14541
14558
|
/**
|
|
14559
|
+
* Converts a yieldable value to an Effect.
|
|
14560
|
+
*
|
|
14561
|
+
* @example
|
|
14562
|
+
* ```ts
|
|
14563
|
+
* import { Effect } from "effect"
|
|
14564
|
+
* import * as Option from "effect/Option"
|
|
14565
|
+
*
|
|
14566
|
+
* // Option is yieldable in Effect
|
|
14567
|
+
* const program = Effect.gen(function*() {
|
|
14568
|
+
* const value = yield* Effect.fromYieldable(Option.some(42))
|
|
14569
|
+
* return value * 2
|
|
14570
|
+
* })
|
|
14571
|
+
*
|
|
14572
|
+
* Effect.runPromise(program).then(console.log)
|
|
14573
|
+
* // Output: 84
|
|
14574
|
+
* ```
|
|
14575
|
+
*
|
|
14576
|
+
* @since 4.0.0
|
|
14577
|
+
* @category Conversions
|
|
14578
|
+
*/
|
|
14579
|
+
const fromYieldable = fromYieldable$1;
|
|
14580
|
+
/**
|
|
14542
14581
|
* Chains effects to produce new `Effect` instances, useful for combining
|
|
14543
14582
|
* operations that depend on previous results.
|
|
14544
14583
|
*
|
|
@@ -14996,6 +15035,53 @@ const asSome = asSome$1;
|
|
|
14996
15035
|
* @category Mapping
|
|
14997
15036
|
*/
|
|
14998
15037
|
const asVoid = asVoid$2;
|
|
15038
|
+
/**
|
|
15039
|
+
* Combines two effects sequentially and applies a function to their results to
|
|
15040
|
+
* produce a single value.
|
|
15041
|
+
*
|
|
15042
|
+
* **When to Use**
|
|
15043
|
+
*
|
|
15044
|
+
* The `zipWith` function is similar to {@link zip}, but instead of returning a
|
|
15045
|
+
* tuple of results, it applies a provided function to the results of the two
|
|
15046
|
+
* effects, combining them into a single value.
|
|
15047
|
+
*
|
|
15048
|
+
* **Concurrency**
|
|
15049
|
+
*
|
|
15050
|
+
* By default, the effects are run sequentially. To execute them concurrently,
|
|
15051
|
+
* use the `{ concurrent: true }` option.
|
|
15052
|
+
*
|
|
15053
|
+
* @example
|
|
15054
|
+
* ```ts
|
|
15055
|
+
* // Title: Combining Effects with a Custom Function
|
|
15056
|
+
* import { Effect } from "effect"
|
|
15057
|
+
*
|
|
15058
|
+
* const task1 = Effect.succeed(1).pipe(
|
|
15059
|
+
* Effect.delay("200 millis"),
|
|
15060
|
+
* Effect.tap(Effect.log("task1 done"))
|
|
15061
|
+
* )
|
|
15062
|
+
* const task2 = Effect.succeed("hello").pipe(
|
|
15063
|
+
* Effect.delay("100 millis"),
|
|
15064
|
+
* Effect.tap(Effect.log("task2 done"))
|
|
15065
|
+
* )
|
|
15066
|
+
*
|
|
15067
|
+
* const task3 = Effect.zipWith(
|
|
15068
|
+
* task1,
|
|
15069
|
+
* task2,
|
|
15070
|
+
* // Combines results into a single value
|
|
15071
|
+
* (number, string) => number + string.length
|
|
15072
|
+
* )
|
|
15073
|
+
*
|
|
15074
|
+
* Effect.runPromise(task3).then(console.log)
|
|
15075
|
+
* // Output:
|
|
15076
|
+
* // timestamp=... level=INFO fiber=#3 message="task1 done"
|
|
15077
|
+
* // timestamp=... level=INFO fiber=#2 message="task2 done"
|
|
15078
|
+
* // 6
|
|
15079
|
+
* ```
|
|
15080
|
+
*
|
|
15081
|
+
* @since 2.0.0
|
|
15082
|
+
* @category Zipping
|
|
15083
|
+
*/
|
|
15084
|
+
const zipWith = zipWith$1;
|
|
14999
15085
|
const catch_$2 = catch_$3;
|
|
15000
15086
|
/**
|
|
15001
15087
|
* Catches and handles specific errors by their `_tag` field, which is used as a
|
|
@@ -15766,6 +15852,27 @@ const sleep = sleep$1;
|
|
|
15766
15852
|
*/
|
|
15767
15853
|
const raceFirst = raceFirst$1;
|
|
15768
15854
|
/**
|
|
15855
|
+
* Filters elements of an iterable using a predicate, refinement, or effectful
|
|
15856
|
+
* predicate.
|
|
15857
|
+
*
|
|
15858
|
+
* @example
|
|
15859
|
+
* ```ts
|
|
15860
|
+
* import { Effect } from "effect"
|
|
15861
|
+
*
|
|
15862
|
+
* // Sync predicate
|
|
15863
|
+
* const evens = Effect.filter([1, 2, 3, 4], (n) => n % 2 === 0)
|
|
15864
|
+
*
|
|
15865
|
+
* // Effectful predicate
|
|
15866
|
+
* const checked = Effect.filter([1, 2, 3], (n) => Effect.succeed(n > 1))
|
|
15867
|
+
*
|
|
15868
|
+
* // Use Effect.filterMapEffect for effectful Filter.Filter callbacks
|
|
15869
|
+
* ```
|
|
15870
|
+
*
|
|
15871
|
+
* @since 2.0.0
|
|
15872
|
+
* @category Filtering
|
|
15873
|
+
*/
|
|
15874
|
+
const filter$5 = filter$6;
|
|
15875
|
+
/**
|
|
15769
15876
|
* Effectfully filters and maps elements of an iterable with a `FilterEffect`.
|
|
15770
15877
|
*
|
|
15771
15878
|
* @since 4.0.0
|
|
@@ -49589,6 +49696,33 @@ const custom$1 = (initialState, handlers) => {
|
|
|
49589
49696
|
* @since 4.0.0
|
|
49590
49697
|
* @category constructors
|
|
49591
49698
|
*/
|
|
49699
|
+
const file$3 = (options = {}) => {
|
|
49700
|
+
const opts = {
|
|
49701
|
+
type: options.type ?? "file",
|
|
49702
|
+
message: options.message ?? `Choose a file`,
|
|
49703
|
+
startingPath: fromUndefinedOr(options.startingPath),
|
|
49704
|
+
maxPerPage: options.maxPerPage ?? 10,
|
|
49705
|
+
filter: options.filter ?? (() => succeed$3(true))
|
|
49706
|
+
};
|
|
49707
|
+
return custom$1(gen(function* () {
|
|
49708
|
+
const files = yield* getFileList(yield* resolveCurrentPath(none$4(), opts), opts);
|
|
49709
|
+
const confirm = Confirm.Hide();
|
|
49710
|
+
return {
|
|
49711
|
+
cursor: 0,
|
|
49712
|
+
files,
|
|
49713
|
+
path: none$4(),
|
|
49714
|
+
confirm
|
|
49715
|
+
};
|
|
49716
|
+
}), {
|
|
49717
|
+
render: handleFileRender(opts),
|
|
49718
|
+
process: handleFileProcess(opts),
|
|
49719
|
+
clear: handleFileClear(opts)
|
|
49720
|
+
});
|
|
49721
|
+
};
|
|
49722
|
+
/**
|
|
49723
|
+
* @since 4.0.0
|
|
49724
|
+
* @category constructors
|
|
49725
|
+
*/
|
|
49592
49726
|
const integer$3 = (options) => {
|
|
49593
49727
|
const opts = {
|
|
49594
49728
|
min: Number.NEGATIVE_INFINITY,
|
|
@@ -49793,6 +49927,41 @@ const clearOutputWithError = (outputText, columns, errorText) => {
|
|
|
49793
49927
|
};
|
|
49794
49928
|
const renderBeep = "\x07";
|
|
49795
49929
|
const NEWLINE_REGEXP = /\r?\n/;
|
|
49930
|
+
const CONFIRM_MESSAGE = "The selected directory contains files. Would you like to traverse the selected directory?";
|
|
49931
|
+
const Confirm = /* @__PURE__ */ taggedEnum();
|
|
49932
|
+
const showConfirmation = /* @__PURE__ */ Confirm.$is("Show");
|
|
49933
|
+
const resolveCurrentPath = (path, options) => {
|
|
49934
|
+
if (isSome(path)) return succeed$3(path.value);
|
|
49935
|
+
if (isSome(options.startingPath)) {
|
|
49936
|
+
const startingPath = options.startingPath.value;
|
|
49937
|
+
return flatMap$4(FileSystem.asEffect(), (fs) => orDie$2(fs.exists(startingPath)).pipe(flatMap$4((exists) => exists ? void_$2 : die$2(`The provided starting path '${startingPath}' does not exist`)), as$1(startingPath)));
|
|
49938
|
+
}
|
|
49939
|
+
return sync(() => process.cwd());
|
|
49940
|
+
};
|
|
49941
|
+
const getFileList = /* @__PURE__ */ fnUntraced(function* (directory, options) {
|
|
49942
|
+
const fs = yield* FileSystem;
|
|
49943
|
+
const path = yield* Path$1;
|
|
49944
|
+
const files = yield* orDie$2(fs.readDirectory(directory)).pipe(map$9((files) => ["..", ...files]));
|
|
49945
|
+
return yield* filter$5(files, (file) => {
|
|
49946
|
+
const result = options.filter(file);
|
|
49947
|
+
return zipWith(isEffect(result) ? result : succeed$3(result), options.type === "directory" ? map$9(orDie$2(fs.stat(path.join(directory, file))), (info) => info.type === "Directory") : succeed$3(true), (a, b) => a && b);
|
|
49948
|
+
}, { concurrency: files.length });
|
|
49949
|
+
});
|
|
49950
|
+
const handleFileClear = (options) => {
|
|
49951
|
+
return fnUntraced(function* (state, _) {
|
|
49952
|
+
const columns = yield* (yield* Terminal).columns;
|
|
49953
|
+
const path = yield* Path$1;
|
|
49954
|
+
const figures = yield* platformFigures;
|
|
49955
|
+
const currentPath = yield* resolveCurrentPath(state.path, options);
|
|
49956
|
+
const selectedPath = state.files[state.cursor];
|
|
49957
|
+
const resolvedPath = path.resolve(currentPath, selectedPath);
|
|
49958
|
+
const resolvedPathText = `${figures.pointerSmall} ${resolvedPath}`;
|
|
49959
|
+
const isConfirming = showConfirmation(state.confirm);
|
|
49960
|
+
const promptText = isConfirming ? renderPrompt("(Y/n)", CONFIRM_MESSAGE, "?", figures.pointerSmall, { plain: true }) : renderPrompt("", options.message, figures.tick, figures.ellipsis, { plain: true });
|
|
49961
|
+
const filesText = isConfirming ? "" : renderFiles(state, state.files, figures, options, { plain: true });
|
|
49962
|
+
return eraseText(isConfirming ? `${promptText}\n${resolvedPathText}` : `${promptText}\n${resolvedPathText}\n${filesText}`, columns) + (eraseLine + cursorLeft);
|
|
49963
|
+
});
|
|
49964
|
+
};
|
|
49796
49965
|
const renderPrompt = (confirm, message, leadingSymbol, trailingSymbol, options) => {
|
|
49797
49966
|
const prefix = leadingSymbol + " ";
|
|
49798
49967
|
const annotate = options?.plain === true ? (line) => line : annotateLine;
|
|
@@ -49803,6 +49972,137 @@ const renderPrompt = (confirm, message, leadingSymbol, trailingSymbol, options)
|
|
|
49803
49972
|
}
|
|
49804
49973
|
});
|
|
49805
49974
|
};
|
|
49975
|
+
const renderPrefix = (state, toDisplay, currentIndex, length, figures, renderOptions) => {
|
|
49976
|
+
let prefix = " ";
|
|
49977
|
+
if (currentIndex === toDisplay.startIndex && toDisplay.startIndex > 0) prefix = figures.arrowUp;
|
|
49978
|
+
else if (currentIndex === toDisplay.endIndex - 1 && toDisplay.endIndex < length) prefix = figures.arrowDown;
|
|
49979
|
+
if (state.cursor === currentIndex) return renderOptions?.plain === true ? figures.pointer + prefix : annotate(figures.pointer, cyanBright) + prefix;
|
|
49980
|
+
return prefix + " ";
|
|
49981
|
+
};
|
|
49982
|
+
const renderFileName = (file, isSelected, renderOptions) => {
|
|
49983
|
+
if (renderOptions?.plain === true) return file;
|
|
49984
|
+
return isSelected ? annotate(file, combine(underlined, cyanBright)) : file;
|
|
49985
|
+
};
|
|
49986
|
+
const renderFiles = (state, files, figures, options, renderOptions) => {
|
|
49987
|
+
const length = files.length;
|
|
49988
|
+
const toDisplay = entriesToDisplay(state.cursor, length, options.maxPerPage);
|
|
49989
|
+
const documents = [];
|
|
49990
|
+
for (let index = toDisplay.startIndex; index < toDisplay.endIndex; index++) {
|
|
49991
|
+
const isSelected = state.cursor === index;
|
|
49992
|
+
const prefix = renderPrefix(state, toDisplay, index, length, figures, renderOptions);
|
|
49993
|
+
const fileName = renderFileName(files[index], isSelected, renderOptions);
|
|
49994
|
+
documents.push(prefix + fileName);
|
|
49995
|
+
}
|
|
49996
|
+
return documents.join("\n");
|
|
49997
|
+
};
|
|
49998
|
+
const renderFileNextFrame = /* @__PURE__ */ fnUntraced(function* (state, options) {
|
|
49999
|
+
const path = yield* Path$1;
|
|
50000
|
+
const figures = yield* platformFigures;
|
|
50001
|
+
const currentPath = yield* resolveCurrentPath(state.path, options);
|
|
50002
|
+
const selectedPath = state.files[state.cursor];
|
|
50003
|
+
const resolvedPath = path.resolve(currentPath, selectedPath);
|
|
50004
|
+
const resolvedPathMsg = annotate(figures.pointerSmall + " " + resolvedPath, blackBright);
|
|
50005
|
+
if (showConfirmation(state.confirm)) {
|
|
50006
|
+
const leadingSymbol = annotate("?", cyanBright);
|
|
50007
|
+
const trailingSymbol = annotate(figures.pointerSmall, blackBright);
|
|
50008
|
+
return cursorHide + renderPrompt(annotate("(Y/n)", blackBright), CONFIRM_MESSAGE, leadingSymbol, trailingSymbol) + "\n" + resolvedPathMsg;
|
|
50009
|
+
}
|
|
50010
|
+
const leadingSymbol = annotate(figures.tick, green$1);
|
|
50011
|
+
const trailingSymbol = annotate(figures.ellipsis, blackBright);
|
|
50012
|
+
const promptMsg = renderPrompt("", options.message, leadingSymbol, trailingSymbol);
|
|
50013
|
+
const files = renderFiles(state, state.files, figures, options);
|
|
50014
|
+
return cursorHide + promptMsg + "\n" + resolvedPathMsg + "\n" + files;
|
|
50015
|
+
});
|
|
50016
|
+
const renderFileSubmission = /* @__PURE__ */ fnUntraced(function* (value, options) {
|
|
50017
|
+
const figures = yield* platformFigures;
|
|
50018
|
+
const leadingSymbol = annotate(figures.tick, green$1);
|
|
50019
|
+
const trailingSymbol = annotate(figures.ellipsis, blackBright);
|
|
50020
|
+
return renderPrompt("", options.message, leadingSymbol, trailingSymbol) + " " + annotate(value, white) + "\n";
|
|
50021
|
+
});
|
|
50022
|
+
const handleFileRender = (options) => {
|
|
50023
|
+
return (_, action) => {
|
|
50024
|
+
return Action.$match(action, {
|
|
50025
|
+
Beep: () => succeed$3(renderBeep),
|
|
50026
|
+
NextFrame: ({ state }) => renderFileNextFrame(state, options),
|
|
50027
|
+
Submit: ({ value }) => renderFileSubmission(value, options)
|
|
50028
|
+
});
|
|
50029
|
+
};
|
|
50030
|
+
};
|
|
50031
|
+
const processFileCursorUp = (state) => {
|
|
50032
|
+
const cursor = state.cursor - 1;
|
|
50033
|
+
return succeed$3(Action.NextFrame({ state: {
|
|
50034
|
+
...state,
|
|
50035
|
+
cursor: cursor < 0 ? state.files.length - 1 : cursor
|
|
50036
|
+
} }));
|
|
50037
|
+
};
|
|
50038
|
+
const processFileCursorDown = (state) => {
|
|
50039
|
+
return succeed$3(Action.NextFrame({ state: {
|
|
50040
|
+
...state,
|
|
50041
|
+
cursor: (state.cursor + 1) % state.files.length
|
|
50042
|
+
} }));
|
|
50043
|
+
};
|
|
50044
|
+
const processSelection = /* @__PURE__ */ fnUntraced(function* (state, options) {
|
|
50045
|
+
const fs = yield* FileSystem;
|
|
50046
|
+
const path = yield* Path$1;
|
|
50047
|
+
const currentPath = yield* resolveCurrentPath(state.path, options);
|
|
50048
|
+
const selectedPath = state.files[state.cursor];
|
|
50049
|
+
const resolvedPath = path.resolve(currentPath, selectedPath);
|
|
50050
|
+
if ((yield* orDie$2(fs.stat(resolvedPath))).type === "Directory") {
|
|
50051
|
+
const files = yield* getFileList(resolvedPath, options);
|
|
50052
|
+
const filesWithoutParent = files.filter((file) => file !== "..");
|
|
50053
|
+
if (options.type === "directory" || options.type === "either") return filesWithoutParent.length === 0 ? Action.Submit({ value: resolvedPath }) : Action.NextFrame({ state: {
|
|
50054
|
+
...state,
|
|
50055
|
+
confirm: Confirm.Show()
|
|
50056
|
+
} });
|
|
50057
|
+
return Action.NextFrame({ state: {
|
|
50058
|
+
cursor: 0,
|
|
50059
|
+
files,
|
|
50060
|
+
path: some$2(resolvedPath),
|
|
50061
|
+
confirm: Confirm.Hide()
|
|
50062
|
+
} });
|
|
50063
|
+
}
|
|
50064
|
+
return Action.Submit({ value: resolvedPath });
|
|
50065
|
+
});
|
|
50066
|
+
const handleFileProcess = (options) => {
|
|
50067
|
+
return fnUntraced(function* (input, state) {
|
|
50068
|
+
switch (input.key.name) {
|
|
50069
|
+
case "k":
|
|
50070
|
+
case "up": return yield* processFileCursorUp(state);
|
|
50071
|
+
case "j":
|
|
50072
|
+
case "down":
|
|
50073
|
+
case "tab": return yield* processFileCursorDown(state);
|
|
50074
|
+
case "enter":
|
|
50075
|
+
case "return": return yield* processSelection(state, options);
|
|
50076
|
+
case "y":
|
|
50077
|
+
case "t":
|
|
50078
|
+
if (showConfirmation(state.confirm)) {
|
|
50079
|
+
const path = yield* Path$1;
|
|
50080
|
+
const currentPath = yield* resolveCurrentPath(state.path, options);
|
|
50081
|
+
const selectedPath = state.files[state.cursor];
|
|
50082
|
+
const resolvedPath = path.resolve(currentPath, selectedPath);
|
|
50083
|
+
const files = yield* getFileList(resolvedPath, options);
|
|
50084
|
+
return Action.NextFrame({ state: {
|
|
50085
|
+
cursor: 0,
|
|
50086
|
+
files,
|
|
50087
|
+
path: some$2(resolvedPath),
|
|
50088
|
+
confirm: Confirm.Hide()
|
|
50089
|
+
} });
|
|
50090
|
+
}
|
|
50091
|
+
return Action.Beep();
|
|
50092
|
+
case "n":
|
|
50093
|
+
case "f":
|
|
50094
|
+
if (showConfirmation(state.confirm)) {
|
|
50095
|
+
const path = yield* Path$1;
|
|
50096
|
+
const currentPath = yield* resolveCurrentPath(state.path, options);
|
|
50097
|
+
const selectedPath = state.files[state.cursor];
|
|
50098
|
+
const resolvedPath = path.resolve(currentPath, selectedPath);
|
|
50099
|
+
return Action.Submit({ value: resolvedPath });
|
|
50100
|
+
}
|
|
50101
|
+
return Action.Beep();
|
|
50102
|
+
default: return Action.Beep();
|
|
50103
|
+
}
|
|
50104
|
+
});
|
|
50105
|
+
};
|
|
49806
50106
|
const renderMultiSelectError = (state, pointer, renderOptions) => {
|
|
49807
50107
|
if (isSome(state.error)) return match$7(state.error.value.split(NEWLINE_REGEXP), {
|
|
49808
50108
|
onEmpty: () => "",
|
|
@@ -90884,15 +91184,27 @@ const PlatformServices = layer$16;
|
|
|
90884
91184
|
//#endregion
|
|
90885
91185
|
//#region src/domain/Project.ts
|
|
90886
91186
|
const ProjectId = String$1.pipe(brand("lalph/ProjectId"));
|
|
90887
|
-
var Project$2 = class extends Class$2("lalph/Project")({
|
|
91187
|
+
var Project$2 = class Project$2 extends Class$2("lalph/Project")({
|
|
90888
91188
|
id: ProjectId,
|
|
90889
91189
|
enabled: Boolean$2,
|
|
90890
91190
|
targetBranch: Option(String$1),
|
|
90891
91191
|
concurrency: Int.check(isGreaterThanOrEqualTo(1)),
|
|
90892
|
-
gitFlow: Literals([
|
|
91192
|
+
gitFlow: Literals([
|
|
91193
|
+
"pr",
|
|
91194
|
+
"commit",
|
|
91195
|
+
"ralph"
|
|
91196
|
+
]),
|
|
91197
|
+
ralphSpec: optional$3(String$1),
|
|
90893
91198
|
researchAgent: Boolean$2.pipe(withDecodingDefault(() => false)),
|
|
90894
91199
|
reviewAgent: Boolean$2
|
|
90895
|
-
}) {
|
|
91200
|
+
}) {
|
|
91201
|
+
update(updates) {
|
|
91202
|
+
return new Project$2({
|
|
91203
|
+
...this,
|
|
91204
|
+
...updates
|
|
91205
|
+
});
|
|
91206
|
+
}
|
|
91207
|
+
};
|
|
90896
91208
|
//#endregion
|
|
90897
91209
|
//#region src/shared/lalphDirectory.ts
|
|
90898
91210
|
const findProjectRoot = fnUntraced(function* (cwd) {
|
|
@@ -91113,9 +91425,9 @@ const allCliAgents = [
|
|
|
91113
91425
|
new CliAgent({
|
|
91114
91426
|
id: "clanka",
|
|
91115
91427
|
name: "clanka",
|
|
91116
|
-
commandPlan: ({ prompt, prdFilePath, dangerous }) => make$45("opencode", ["--prompt", `@${prdFilePath}
|
|
91428
|
+
commandPlan: ({ prompt, prdFilePath, dangerous }) => make$45("opencode", ["--prompt", prdFilePath ? `@${prdFilePath}
|
|
91117
91429
|
|
|
91118
|
-
${prompt}`], {
|
|
91430
|
+
${prompt}` : prompt], {
|
|
91119
91431
|
extendEnv: true,
|
|
91120
91432
|
...dangerous ? { env: { OPENCODE_PERMISSION: "{\"*\":\"allow\"}" } } : {},
|
|
91121
91433
|
stdout: "inherit",
|
|
@@ -91131,8 +91443,7 @@ ${prompt}`], {
|
|
|
91131
91443
|
prompt,
|
|
91132
91444
|
"--thinking",
|
|
91133
91445
|
...extraArgs,
|
|
91134
|
-
"-f",
|
|
91135
|
-
prdFilePath
|
|
91446
|
+
...prdFilePath ? ["-f", prdFilePath] : []
|
|
91136
91447
|
], {
|
|
91137
91448
|
extendEnv: true,
|
|
91138
91449
|
env: { OPENCODE_PERMISSION: "{\"*\":\"allow\", \"question\":\"deny\"}" },
|
|
@@ -91140,9 +91451,9 @@ ${prompt}`], {
|
|
|
91140
91451
|
stderr: "pipe",
|
|
91141
91452
|
stdin: "inherit"
|
|
91142
91453
|
}),
|
|
91143
|
-
commandPlan: ({ prompt, prdFilePath, dangerous }) => make$45("opencode", ["--prompt", `@${prdFilePath}
|
|
91454
|
+
commandPlan: ({ prompt, prdFilePath, dangerous }) => make$45("opencode", ["--prompt", prdFilePath ? `@${prdFilePath}
|
|
91144
91455
|
|
|
91145
|
-
${prompt}`], {
|
|
91456
|
+
${prompt}` : prompt], {
|
|
91146
91457
|
extendEnv: true,
|
|
91147
91458
|
...dangerous ? { env: { OPENCODE_PERMISSION: "{\"*\":\"allow\"}" } } : {},
|
|
91148
91459
|
stdout: "inherit",
|
|
@@ -91162,9 +91473,9 @@ ${prompt}`], {
|
|
|
91162
91473
|
"AskUserQuestion",
|
|
91163
91474
|
...extraArgs,
|
|
91164
91475
|
"--",
|
|
91165
|
-
`@${prdFilePath}
|
|
91476
|
+
prdFilePath ? `@${prdFilePath}
|
|
91166
91477
|
|
|
91167
|
-
${prompt}`
|
|
91478
|
+
${prompt}` : prompt
|
|
91168
91479
|
], {
|
|
91169
91480
|
stdout: "pipe",
|
|
91170
91481
|
stderr: "pipe",
|
|
@@ -91186,17 +91497,17 @@ ${prompt}`], {
|
|
|
91186
91497
|
"exec",
|
|
91187
91498
|
"--dangerously-bypass-approvals-and-sandbox",
|
|
91188
91499
|
...extraArgs,
|
|
91189
|
-
`@${prdFilePath}
|
|
91500
|
+
prdFilePath ? `@${prdFilePath}
|
|
91190
91501
|
|
|
91191
|
-
${prompt}`
|
|
91502
|
+
${prompt}` : prompt
|
|
91192
91503
|
], {
|
|
91193
91504
|
stdout: "pipe",
|
|
91194
91505
|
stderr: "pipe",
|
|
91195
91506
|
stdin: "inherit"
|
|
91196
91507
|
}),
|
|
91197
|
-
commandPlan: ({ prompt, prdFilePath, dangerous }) => make$45("codex", [...dangerous ? ["--dangerously-bypass-approvals-and-sandbox"] : [], `@${prdFilePath}
|
|
91508
|
+
commandPlan: ({ prompt, prdFilePath, dangerous }) => make$45("codex", [...dangerous ? ["--dangerously-bypass-approvals-and-sandbox"] : [], prdFilePath ? `@${prdFilePath}
|
|
91198
91509
|
|
|
91199
|
-
${prompt}`], {
|
|
91510
|
+
${prompt}` : prompt], {
|
|
91200
91511
|
stdout: "inherit",
|
|
91201
91512
|
stderr: "inherit",
|
|
91202
91513
|
stdin: "inherit"
|
|
@@ -91209,9 +91520,9 @@ ${prompt}`], {
|
|
|
91209
91520
|
"--dangerously-allow-all",
|
|
91210
91521
|
"--stream-json-thinking",
|
|
91211
91522
|
...extraArgs,
|
|
91212
|
-
`@${prdFilePath}
|
|
91523
|
+
prdFilePath ? `@${prdFilePath}
|
|
91213
91524
|
|
|
91214
|
-
${prompt}`
|
|
91525
|
+
${prompt}` : prompt
|
|
91215
91526
|
], {
|
|
91216
91527
|
stdout: "pipe",
|
|
91217
91528
|
stderr: "pipe",
|
|
@@ -92548,6 +92859,9 @@ var Settings = class Settings extends Service$1()("lalph/Settings", { make: gen(
|
|
|
92548
92859
|
static set(setting, value) {
|
|
92549
92860
|
return Settings.use((_) => _.set(setting, value));
|
|
92550
92861
|
}
|
|
92862
|
+
static update(setting, f) {
|
|
92863
|
+
return Settings.use((_) => _.get(setting).pipe(map$9(f), flatMap$4((v) => _.set(setting, v))));
|
|
92864
|
+
}
|
|
92551
92865
|
static getProject(setting) {
|
|
92552
92866
|
return Settings.use((_) => _.getProject(setting));
|
|
92553
92867
|
}
|
|
@@ -92575,6 +92889,7 @@ var ProjectSetting = class {
|
|
|
92575
92889
|
}
|
|
92576
92890
|
};
|
|
92577
92891
|
new Setting("selectedCliAgentId", Literals(allCliAgents.map((a) => a.id)));
|
|
92892
|
+
const allProjects = new Setting("projects", Array$1(Project$2));
|
|
92578
92893
|
//#endregion
|
|
92579
92894
|
//#region src/shared/schema.ts
|
|
92580
92895
|
const withEncodeDefault = (defaultValue) => (schema) => optionalKey(schema).pipe(decodeTo(toType(schema), {
|
|
@@ -239422,23 +239737,28 @@ const getOrSelectIssueSource = gen(function* () {
|
|
|
239422
239737
|
});
|
|
239423
239738
|
var CurrentIssueSource = class CurrentIssueSource extends Service$1()("lalph/CurrentIssueSource") {
|
|
239424
239739
|
static layer = effectServices(gen(function* () {
|
|
239740
|
+
const settings = yield* Settings;
|
|
239425
239741
|
const source = yield* getOrSelectIssueSource;
|
|
239426
239742
|
const build$1 = build(source.layer).pipe(map$9(get$15(IssueSource)), withSpan$1("CurrentIssueSource.build"));
|
|
239427
239743
|
const ref = yield* fromAcquire(build$1);
|
|
239428
239744
|
const services$2 = yield* services();
|
|
239429
239745
|
const refresh = set$4(ref, build$1).pipe(provideServices$2(services$2));
|
|
239746
|
+
const unlessRalph = (projectId, orElse) => (effect) => settings.get(allProjects).pipe(map$9(filter$10((projects) => projects.some((p) => p.id === projectId && p.gitFlow === "ralph"))), flatMap$4(match$10({
|
|
239747
|
+
onNone: () => effect,
|
|
239748
|
+
onSome: () => orElse
|
|
239749
|
+
})));
|
|
239430
239750
|
const proxy = IssueSource.of({
|
|
239431
|
-
issues: (projectId) => get$6(ref).pipe(flatMap$4((source) => source.issues(projectId)), tapErrorTag("IssueSourceError", (e) => logWarning("Rebuilding issue source due to error", fail$7(e)).pipe(andThen(ignore$1(refresh)))), retry$3(refreshSchedule)),
|
|
239432
|
-
createIssue: (projectId, options) => get$6(ref).pipe(flatMap$4((source) => source.createIssue(projectId, options))),
|
|
239433
|
-
updateIssue: (options) => get$6(ref).pipe(flatMap$4((source) => source.updateIssue(options))),
|
|
239434
|
-
cancelIssue: (projectId, issueId) => get$6(ref).pipe(flatMap$4((source) => source.cancelIssue(projectId, issueId))),
|
|
239751
|
+
issues: (projectId) => get$6(ref).pipe(flatMap$4((source) => source.issues(projectId)), tapErrorTag("IssueSourceError", (e) => logWarning("Rebuilding issue source due to error", fail$7(e)).pipe(andThen(ignore$1(refresh)))), retry$3(refreshSchedule), unlessRalph(projectId, succeed$3([]))),
|
|
239752
|
+
createIssue: (projectId, options) => get$6(ref).pipe(flatMap$4((source) => source.createIssue(projectId, options)), unlessRalph(projectId, interrupt$1)),
|
|
239753
|
+
updateIssue: (options) => get$6(ref).pipe(flatMap$4((source) => source.updateIssue(options)), unlessRalph(options.projectId, void_$2)),
|
|
239754
|
+
cancelIssue: (projectId, issueId) => get$6(ref).pipe(flatMap$4((source) => source.cancelIssue(projectId, issueId)), unlessRalph(projectId, void_$2)),
|
|
239435
239755
|
reset: get$6(ref).pipe(flatMap$4((source) => source.reset)),
|
|
239436
|
-
settings: (projectId) => get$6(ref).pipe(flatMap$4((source) => source.settings(projectId))),
|
|
239437
|
-
info: (projectId) => get$6(ref).pipe(flatMap$4((source) => source.info(projectId))),
|
|
239756
|
+
settings: (projectId) => get$6(ref).pipe(flatMap$4((source) => source.settings(projectId)), unlessRalph(projectId, void_$2)),
|
|
239757
|
+
info: (projectId) => get$6(ref).pipe(flatMap$4((source) => source.info(projectId)), unlessRalph(projectId, void_$2)),
|
|
239438
239758
|
issueCliAgentPreset: (issue) => get$6(ref).pipe(flatMap$4((source) => source.issueCliAgentPreset(issue))),
|
|
239439
239759
|
updateCliAgentPreset: (preset) => get$6(ref).pipe(flatMap$4((source) => source.updateCliAgentPreset(preset))),
|
|
239440
239760
|
cliAgentPresetInfo: (preset) => get$6(ref).pipe(flatMap$4((source) => source.cliAgentPresetInfo(preset))),
|
|
239441
|
-
ensureInProgress: (projectId, issueId) => get$6(ref).pipe(flatMap$4((source) => source.ensureInProgress(projectId, issueId)))
|
|
239761
|
+
ensureInProgress: (projectId, issueId) => get$6(ref).pipe(flatMap$4((source) => source.ensureInProgress(projectId, issueId)), unlessRalph(projectId, void_$2))
|
|
239442
239762
|
});
|
|
239443
239763
|
return IssueSource.serviceMap(proxy).pipe(add$3(CurrentIssueSource, source));
|
|
239444
239764
|
})).pipe(provide$3([Settings.layer, PlatformServices]));
|
|
@@ -239447,8 +239767,9 @@ const refreshSchedule = exponential(100, 1.5).pipe(either(spaced("30 seconds")))
|
|
|
239447
239767
|
const issueSourceRuntime = atomRuntime(CurrentIssueSource.layer.pipe(orDie$3));
|
|
239448
239768
|
const currentIssuesAtom = family((projectId) => pipe$1(issueSourceRuntime.atom(IssueSource.use((s) => s.issues(projectId)).pipe(withSpan$1("currentIssuesAtom"))), atomRuntime.withReactivity([`issues:${projectId}`]), withRefresh("30 seconds"), keepAlive));
|
|
239449
239769
|
const getCurrentIssues = (projectId) => getResult$1(currentIssuesAtom(projectId), { suspendOnWaiting: true });
|
|
239450
|
-
const checkForWork =
|
|
239451
|
-
if (
|
|
239770
|
+
const checkForWork = fnUntraced(function* (project) {
|
|
239771
|
+
if (project.gitFlow === "ralph") return;
|
|
239772
|
+
if (!(yield* getCurrentIssues(project.id)).some((issue) => issue.state === "todo" && issue.blockedBy.length === 0)) return yield* new NoMoreWork({});
|
|
239452
239773
|
});
|
|
239453
239774
|
const resetInProgress = gen(function* () {
|
|
239454
239775
|
const source = yield* IssueSource;
|
|
@@ -239552,14 +239873,13 @@ Set \`githubPrNumber\` to the PR number if one exists, otherwise use \`null\`.
|
|
|
239552
239873
|
- Use the "chooseTask" function to select the task you have chosen.
|
|
239553
239874
|
${options.gitFlow.requiresGithubPr ? `\n - Set \`githubPrNumber\` to the PR number if one exists, otherwise use \`null\`.` : "\n Leave `githubPrNumber` as null."}
|
|
239554
239875
|
`;
|
|
239555
|
-
const
|
|
239556
|
-
|
|
239557
|
-
|
|
239558
|
-
that needs doing, immediately add it to the prd.yml file as a new task.
|
|
239876
|
+
const promptChooseRalph = (options) => `- Read the spec file at \`${options.specFile}\` to understand the current project.
|
|
239877
|
+
- Choose the next most important task to work on from the specification.
|
|
239878
|
+
- If all of the tasks are complete then do nothing more. Otherwise, write the chosen task in a ".lalph/task.md" file.
|
|
239559
239879
|
|
|
239560
|
-
|
|
239561
|
-
|
|
239562
|
-
|
|
239880
|
+
Note: The task should be a specific, actionable item that can be completed in a reasonable amount of time.
|
|
239881
|
+
`;
|
|
239882
|
+
const keyInformation = (options) => `## Important: Recording key information
|
|
239563
239883
|
|
|
239564
239884
|
This session will time out after a certain period, so make sure to record
|
|
239565
239885
|
key information that could speed up future work on the task in the description.
|
|
@@ -239579,12 +239899,7 @@ If for any reason you get stuck on a task, mark the task back as "todo" by updat
|
|
|
239579
239899
|
challenges faced.
|
|
239580
239900
|
|
|
239581
239901
|
${prdNotes(options)}`;
|
|
239582
|
-
const systemClanka = (options) => `## Important:
|
|
239583
|
-
|
|
239584
|
-
**If at any point** you discover something that needs fixing, or another task
|
|
239585
|
-
that needs doing, immediately add it as a new task.
|
|
239586
|
-
|
|
239587
|
-
## Important: Recording key information
|
|
239902
|
+
const systemClanka = (options) => `## Important: Recording key information
|
|
239588
239903
|
|
|
239589
239904
|
This session will time out after a certain period, so make sure to record
|
|
239590
239905
|
key information that could speed up future work on the task in the description.
|
|
@@ -239649,9 +239964,6 @@ All steps must be done before the task can be considered complete.${options.task
|
|
|
239649
239964
|
2. Implement the task.
|
|
239650
239965
|
- If this task is a research task, **do not** make any code changes yet.
|
|
239651
239966
|
- If this task is a research task and you add follow-up tasks, include (at least) "${options.task.id}" in the new task's \`blockedBy\` field.
|
|
239652
|
-
- **If at any point** you discover something that needs fixing, or another task
|
|
239653
|
-
that needs doing, immediately add it as a new task unless you plan to fix it
|
|
239654
|
-
as part of this task.
|
|
239655
239967
|
- Add important discoveries about the codebase, or challenges faced to the task's
|
|
239656
239968
|
\`description\`. More details below.
|
|
239657
239969
|
3. Run any checks / feedback loops, such as type checks, unit tests, or linting.
|
|
@@ -239664,6 +239976,28 @@ All steps must be done before the task can be considered complete.${options.task
|
|
|
239664
239976
|
5. **After ${options.gitFlow.requiresGithubPr ? "pushing" : "committing"}** your changes, update current task to reflect any changes in the task state.
|
|
239665
239977
|
- Rewrite the notes in the description to include only the key discoveries and information that could speed up future work on other tasks. Make sure to preserve important information such as specification file references.
|
|
239666
239978
|
- If you believe the task is complete, update the \`state\` to "in-review".`;
|
|
239979
|
+
const promptRalph = (options) => `${options.task}
|
|
239980
|
+
|
|
239981
|
+
## Project specification
|
|
239982
|
+
|
|
239983
|
+
Make sure to review the project specification at \`${options.specFile}\` for any key information that may help you with this task.
|
|
239984
|
+
|
|
239985
|
+
### Instructions
|
|
239986
|
+
|
|
239987
|
+
All steps must be done before the task can be considered complete.
|
|
239988
|
+
|
|
239989
|
+
1. ${options.gitFlow.setupInstructions({ githubPrNumber: void 0 })}
|
|
239990
|
+
2. Implement the task.
|
|
239991
|
+
- Along the way, update the specification file with any important discoveries or issues found.
|
|
239992
|
+
3. Run any checks / feedback loops, such as type checks, unit tests, or linting.
|
|
239993
|
+
4. Update the specification implementation plan at \`${options.specFile}\` to reflect changes to task states.
|
|
239994
|
+
4. ${options.gitFlow.commitInstructions({
|
|
239995
|
+
githubPrInstructions: sourceMeta.githubPrInstructions,
|
|
239996
|
+
githubPrNumber: void 0,
|
|
239997
|
+
taskId: "unknown",
|
|
239998
|
+
targetBranch: options.targetBranch
|
|
239999
|
+
})}
|
|
240000
|
+
`;
|
|
239667
240001
|
const promptResearch = (options) => `Your job is to gather all the necessary information and details to complete the task described below. Do not make any code changes yet, your job is just to research and gather information.
|
|
239668
240002
|
|
|
239669
240003
|
In the final report:
|
|
@@ -239717,6 +240051,18 @@ permission.
|
|
|
239717
240051
|
5. If any specifications need updating based on your new understanding, update them.
|
|
239718
240052
|
|
|
239719
240053
|
${prdNotes(options)}`;
|
|
240054
|
+
const promptTimeoutRalph = (options) => `Your earlier attempt to complete the following task took too
|
|
240055
|
+
long and has timed out.
|
|
240056
|
+
|
|
240057
|
+
The following instructions should be done without interaction or asking for
|
|
240058
|
+
permission.
|
|
240059
|
+
|
|
240060
|
+
1. Investigate why you think the task took too long. Research the codebase
|
|
240061
|
+
further to understand what is needed to complete the task.
|
|
240062
|
+
2. Update the specification file at \`${options.specFile}\` to break the task
|
|
240063
|
+
down into smaller tasks, and include any important discoveries from your research.
|
|
240064
|
+
3. Commit the changes to the specification file without pushing.
|
|
240065
|
+
`;
|
|
239720
240066
|
const promptTimeoutClanka = (options) => `Your earlier attempt to complete the task with id \`${options.taskId}\` took too
|
|
239721
240067
|
long and has timed out.
|
|
239722
240068
|
|
|
@@ -239822,13 +240168,16 @@ Make sure to setup dependencies between the tasks using the \`blockedBy\` field.
|
|
|
239822
240168
|
return {
|
|
239823
240169
|
promptChoose,
|
|
239824
240170
|
promptChooseClanka,
|
|
240171
|
+
promptChooseRalph,
|
|
239825
240172
|
prompt,
|
|
240173
|
+
promptRalph,
|
|
239826
240174
|
promptClanka,
|
|
239827
240175
|
promptResearch,
|
|
239828
240176
|
promptReview,
|
|
239829
240177
|
promptReviewCustom,
|
|
239830
240178
|
promptTimeout,
|
|
239831
240179
|
promptTimeoutClanka,
|
|
240180
|
+
promptTimeoutRalph,
|
|
239832
240181
|
planPrompt,
|
|
239833
240182
|
promptPlanTasks,
|
|
239834
240183
|
promptPlanTasksClanka,
|
|
@@ -239927,7 +240276,6 @@ const withWorkerState = (projectId) => (effect) => AtomRegistry.use((registry) =
|
|
|
239927
240276
|
const layerProjectIdPrompt = effect$1(CurrentProjectId, gen(function* () {
|
|
239928
240277
|
return (yield* selectProject).id;
|
|
239929
240278
|
})).pipe(provide$3(Settings.layer), provide$3(CurrentIssueSource.layer));
|
|
239930
|
-
const allProjects = new Setting("projects", Array$1(Project$2));
|
|
239931
240279
|
const getAllProjects = Settings.get(allProjects).pipe(map$9(getOrElse$2(() => [])));
|
|
239932
240280
|
const projectById = fnUntraced(function* (projectId) {
|
|
239933
240281
|
return findFirst$5(yield* getAllProjects, (p) => p.id === projectId);
|
|
@@ -239961,7 +240309,7 @@ const welcomeWizard = gen(function* () {
|
|
|
239961
240309
|
console.log(welcome);
|
|
239962
240310
|
return yield* addOrUpdateProject();
|
|
239963
240311
|
});
|
|
239964
|
-
const addOrUpdateProject = fnUntraced(function* (existing) {
|
|
240312
|
+
const addOrUpdateProject = fnUntraced(function* (existing, fromPlanMode = false) {
|
|
239965
240313
|
const projects = yield* getAllProjects;
|
|
239966
240314
|
const id = existing ? existing.id : yield* text$2({
|
|
239967
240315
|
message: "Project name",
|
|
@@ -239982,25 +240330,36 @@ const addOrUpdateProject = fnUntraced(function* (existing) {
|
|
|
239982
240330
|
}), trim, liftPredicate(isNonEmpty$1));
|
|
239983
240331
|
const gitFlow = yield* select({
|
|
239984
240332
|
message: "Git flow",
|
|
239985
|
-
choices: [
|
|
239986
|
-
|
|
239987
|
-
|
|
239988
|
-
|
|
239989
|
-
|
|
239990
|
-
|
|
239991
|
-
|
|
239992
|
-
|
|
239993
|
-
|
|
239994
|
-
|
|
239995
|
-
|
|
240333
|
+
choices: [
|
|
240334
|
+
{
|
|
240335
|
+
title: "Pull Request",
|
|
240336
|
+
description: "Create a pull request for each task",
|
|
240337
|
+
value: "pr",
|
|
240338
|
+
selected: existing ? existing.gitFlow === "pr" : false
|
|
240339
|
+
},
|
|
240340
|
+
{
|
|
240341
|
+
title: "Commit",
|
|
240342
|
+
description: "Tasks are committed directly to the target branch",
|
|
240343
|
+
value: "commit",
|
|
240344
|
+
selected: existing ? existing.gitFlow === "commit" : false
|
|
240345
|
+
},
|
|
240346
|
+
{
|
|
240347
|
+
title: "Ralph",
|
|
240348
|
+
description: "Tasks are determined from a spec file",
|
|
240349
|
+
value: "ralph",
|
|
240350
|
+
selected: existing ? existing.gitFlow === "ralph" : false
|
|
240351
|
+
}
|
|
240352
|
+
]
|
|
239996
240353
|
});
|
|
240354
|
+
let ralphSpec = none$4();
|
|
240355
|
+
if (gitFlow === "ralph" && !fromPlanMode) ralphSpec = yield* file$3({ message: "Path to Ralph spec file" }).pipe(fromYieldable, map$9(some$2));
|
|
239997
240356
|
const researchAgent = yield* toggle({
|
|
239998
240357
|
message: "Enable research agent?",
|
|
239999
|
-
initial: existing ? existing.researchAgent :
|
|
240358
|
+
initial: existing ? existing.researchAgent : false
|
|
240000
240359
|
});
|
|
240001
240360
|
const reviewAgent = yield* toggle({
|
|
240002
240361
|
message: "Enable review agent?",
|
|
240003
|
-
initial: existing ? existing.reviewAgent :
|
|
240362
|
+
initial: existing ? existing.reviewAgent : false
|
|
240004
240363
|
});
|
|
240005
240364
|
const project = new Project$2({
|
|
240006
240365
|
id: ProjectId.makeUnsafe(id),
|
|
@@ -240008,13 +240367,14 @@ const addOrUpdateProject = fnUntraced(function* (existing) {
|
|
|
240008
240367
|
concurrency,
|
|
240009
240368
|
targetBranch,
|
|
240010
240369
|
gitFlow,
|
|
240370
|
+
ralphSpec: getOrUndefined$2(ralphSpec),
|
|
240011
240371
|
researchAgent,
|
|
240012
240372
|
reviewAgent
|
|
240013
240373
|
});
|
|
240014
240374
|
yield* Settings.set(allProjects, some$2(existing ? projects.map((p) => p.id === project.id ? project : p) : [...projects, project]));
|
|
240015
240375
|
const source = yield* IssueSource;
|
|
240016
240376
|
yield* source.reset.pipe(provideService$2(CurrentProjectId, project.id));
|
|
240017
|
-
yield* source.settings(project.id);
|
|
240377
|
+
if (gitFlow !== "ralph") yield* source.settings(project.id);
|
|
240018
240378
|
return project;
|
|
240019
240379
|
});
|
|
240020
240380
|
//#endregion
|
|
@@ -240350,6 +240710,15 @@ var Prd = class extends Service$1()("lalph/Prd", { make: gen(function* () {
|
|
|
240350
240710
|
layer$32,
|
|
240351
240711
|
CurrentIssueSource.layer
|
|
240352
240712
|
]));
|
|
240713
|
+
static layerNoop = succeed$4(this, {
|
|
240714
|
+
path: "",
|
|
240715
|
+
maybeRevertIssue: () => void_$2,
|
|
240716
|
+
revertUpdatedIssues: void_$2,
|
|
240717
|
+
flagUnmergable: () => void_$2,
|
|
240718
|
+
findById: () => succeed$3(null),
|
|
240719
|
+
setChosenIssueId: () => void_$2,
|
|
240720
|
+
setAutoMerge: () => void_$2
|
|
240721
|
+
});
|
|
240353
240722
|
};
|
|
240354
240723
|
//#endregion
|
|
240355
240724
|
//#region src/TaskTools.ts
|
|
@@ -240497,7 +240866,7 @@ const runClanka = fnUntraced(function* (options) {
|
|
|
240497
240866
|
return yield* stream.pipe(runDrain, as$1(""), catchTag$1("AgentFinished", (e) => succeed$3(e.summary)));
|
|
240498
240867
|
}, scoped$1, (effect, options) => provide$1(effect, layerLocal({
|
|
240499
240868
|
directory: options.directory,
|
|
240500
|
-
tools: options.
|
|
240869
|
+
tools: options.mode === "ralph" ? void 0 : options.mode === "choose" ? TaskChooseTools : TaskTools
|
|
240501
240870
|
}).pipe(merge$6(ClankaModels.get(options.model)))), provide$1([layerUndici, TaskToolsHandlers]));
|
|
240502
240871
|
//#endregion
|
|
240503
240872
|
//#region src/Agents/worker.ts
|
|
@@ -240523,13 +240892,14 @@ ${research}`
|
|
|
240523
240892
|
}])
|
|
240524
240893
|
}),
|
|
240525
240894
|
stallTimeout: options.stallTimeout,
|
|
240526
|
-
steer: options.steer
|
|
240895
|
+
steer: options.steer,
|
|
240896
|
+
mode: options.ralph ? "ralph" : "default"
|
|
240527
240897
|
});
|
|
240528
240898
|
return ExitCode(0);
|
|
240529
240899
|
}
|
|
240530
240900
|
return yield* pipe$1(options.preset.cliAgent.command({
|
|
240531
240901
|
prompt: options.prompt,
|
|
240532
|
-
prdFilePath: pathService.join(".lalph", "prd.yml"),
|
|
240902
|
+
prdFilePath: options.ralph ? void 0 : pathService.join(".lalph", "prd.yml"),
|
|
240533
240903
|
extraArgs: options.preset.extraArgs
|
|
240534
240904
|
}), setCwd(worktree.directory), options.preset.withCommandPrefix).pipe(worktree.execWithStallTimeout({
|
|
240535
240905
|
cliAgent: options.preset.cliAgent,
|
|
@@ -240633,6 +241003,31 @@ But you **do not** need to git push your changes or switch branches.
|
|
|
240633
241003
|
})
|
|
240634
241004
|
});
|
|
240635
241005
|
})).pipe(provide$3(layer$14));
|
|
241006
|
+
const GitFlowRalph = effect$1(GitFlow, gen(function* () {
|
|
241007
|
+
const workerState = yield* get$3((yield* CurrentWorkerState).state);
|
|
241008
|
+
return GitFlow.of({
|
|
241009
|
+
requiresGithubPr: false,
|
|
241010
|
+
branch: `lalph/worker-${workerState.id}`,
|
|
241011
|
+
setupInstructions: () => `You are already on a new branch for this task. You do not need to checkout any other branches.`,
|
|
241012
|
+
commitInstructions: () => `When you have completed your changes, **you must** commit them to the current local branch. Do not git push your changes or switch branches.
|
|
241013
|
+
- **DO NOT** commit any of the files in the \`.lalph\` directory.`,
|
|
241014
|
+
reviewInstructions: `You are already on the branch with their changes.
|
|
241015
|
+
After making any changes, **you must** commit them to the same branch.
|
|
241016
|
+
But you **do not** need to git push your changes or switch branches.
|
|
241017
|
+
|
|
241018
|
+
- **DO NOT** commit any of the files in the \`.lalph\` directory.
|
|
241019
|
+
- You have full permission to create git commits.`,
|
|
241020
|
+
postWork: fnUntraced(function* ({ worktree, targetBranch }) {
|
|
241021
|
+
if (!targetBranch) return yield* logWarning("GitFlowRalph: No target branch specified, skipping postWork.");
|
|
241022
|
+
const parsed = parseBranch(targetBranch);
|
|
241023
|
+
yield* worktree.exec`git fetch ${parsed.remote}`;
|
|
241024
|
+
yield* worktree.exec`git restore --worktree .`;
|
|
241025
|
+
if ((yield* worktree.exec`git rebase ${parsed.branchWithRemote}`) !== 0) return yield* new GitFlowError({ message: `Failed to rebase onto ${parsed.branchWithRemote}. Aborting task.` });
|
|
241026
|
+
if ((yield* worktree.exec`git push ${parsed.remote} ${`HEAD:${parsed.branch}`}`) !== 0) return yield* new GitFlowError({ message: `Failed to push changes to ${parsed.branchWithRemote}. Aborting task.` });
|
|
241027
|
+
}),
|
|
241028
|
+
autoMerge: () => void_$2
|
|
241029
|
+
});
|
|
241030
|
+
})).pipe(provide$3(layer$14));
|
|
240636
241031
|
var GitFlowError = class extends TaggedError("GitFlowError") {};
|
|
240637
241032
|
//#endregion
|
|
240638
241033
|
//#region src/Agents/chooser.ts
|
|
@@ -240651,10 +241046,10 @@ const agentChooser = fnUntraced(function* (options) {
|
|
|
240651
241046
|
model: options.preset.extraArgs.join(" "),
|
|
240652
241047
|
prompt: promptGen.promptChooseClanka({ gitFlow }),
|
|
240653
241048
|
stallTimeout: options.stallTimeout,
|
|
240654
|
-
|
|
240655
|
-
}).pipe(provideService$2(ChosenTaskDeferred, deferred), flatMap$4(() => fail$6(new ChosenTaskNotFound())), raceFirst(_await(deferred)));
|
|
241049
|
+
mode: "choose"
|
|
241050
|
+
}).pipe(provideService$2(ChosenTaskDeferred, deferred), flatMap$4(() => fail$6(new ChosenTaskNotFound$1())), raceFirst(_await(deferred)));
|
|
240656
241051
|
const prdTask = yield* prd.findById(result.taskId);
|
|
240657
|
-
if (!prdTask) return yield* new ChosenTaskNotFound();
|
|
241052
|
+
if (!prdTask) return yield* new ChosenTaskNotFound$1();
|
|
240658
241053
|
return {
|
|
240659
241054
|
id: result.taskId,
|
|
240660
241055
|
githubPrNumber: result.githubPrNumber ?? null,
|
|
@@ -240670,16 +241065,16 @@ const agentChooser = fnUntraced(function* (options) {
|
|
|
240670
241065
|
duration: options.stallTimeout,
|
|
240671
241066
|
onTimeout: () => fail$6(new RunnerStalled())
|
|
240672
241067
|
}), raceFirst(taskJsonCreated));
|
|
240673
|
-
return yield* pipe$1(fs.readFileString(pathService.join(worktree.directory, ".lalph", "task.json")), flatMap$4(decodeEffect(ChosenTask)), mapError$2((_) => new ChosenTaskNotFound()), flatMap$4(fnUntraced(function* (task) {
|
|
241068
|
+
return yield* pipe$1(fs.readFileString(pathService.join(worktree.directory, ".lalph", "task.json")), flatMap$4(decodeEffect(ChosenTask)), mapError$2((_) => new ChosenTaskNotFound$1()), flatMap$4(fnUntraced(function* (task) {
|
|
240674
241069
|
const prdTask = yield* prd.findById(task.id);
|
|
240675
241070
|
if (prdTask) return {
|
|
240676
241071
|
...task,
|
|
240677
241072
|
prd: prdTask
|
|
240678
241073
|
};
|
|
240679
|
-
return yield* new ChosenTaskNotFound();
|
|
241074
|
+
return yield* new ChosenTaskNotFound$1();
|
|
240680
241075
|
})));
|
|
240681
241076
|
});
|
|
240682
|
-
var ChosenTaskNotFound = class extends TaggedError("ChosenTaskNotFound") {
|
|
241077
|
+
var ChosenTaskNotFound$1 = class extends TaggedError("ChosenTaskNotFound") {
|
|
240683
241078
|
message = "The AI agent failed to choose a task.";
|
|
240684
241079
|
};
|
|
240685
241080
|
const ChosenTask = fromJsonString(Struct$2({
|
|
@@ -240699,7 +241094,7 @@ const agentReviewer = fnUntraced(function* (options) {
|
|
|
240699
241094
|
yield* runClanka({
|
|
240700
241095
|
directory: worktree.directory,
|
|
240701
241096
|
model: options.preset.extraArgs.join(" "),
|
|
240702
|
-
system: promptGen.systemClanka(options),
|
|
241097
|
+
system: options.ralph ? void 0 : promptGen.systemClanka(options),
|
|
240703
241098
|
prompt: match$10(customInstructions, {
|
|
240704
241099
|
onNone: () => promptGen.promptReview({
|
|
240705
241100
|
prompt: options.instructions,
|
|
@@ -240711,7 +241106,8 @@ const agentReviewer = fnUntraced(function* (options) {
|
|
|
240711
241106
|
removePrdNotes: true
|
|
240712
241107
|
})
|
|
240713
241108
|
}),
|
|
240714
|
-
stallTimeout: options.stallTimeout
|
|
241109
|
+
stallTimeout: options.stallTimeout,
|
|
241110
|
+
mode: options.ralph ? "ralph" : "default"
|
|
240715
241111
|
});
|
|
240716
241112
|
return ExitCode(0);
|
|
240717
241113
|
}
|
|
@@ -240744,21 +241140,28 @@ const agentTimeout = fnUntraced(function* (options) {
|
|
|
240744
241140
|
yield* runClanka({
|
|
240745
241141
|
directory: worktree.directory,
|
|
240746
241142
|
model: options.preset.extraArgs.join(" "),
|
|
240747
|
-
system: promptGen.systemClanka(options),
|
|
240748
|
-
prompt: promptGen.
|
|
240749
|
-
|
|
241143
|
+
system: options.task._tag === "ralph" ? void 0 : promptGen.systemClanka(options),
|
|
241144
|
+
prompt: options.task._tag === "ralph" ? promptGen.promptTimeoutRalph({
|
|
241145
|
+
task: options.task.task,
|
|
241146
|
+
specFile: options.task.specFile
|
|
241147
|
+
}) : promptGen.promptTimeoutClanka({
|
|
241148
|
+
taskId: options.task.task.id,
|
|
240750
241149
|
specsDirectory: options.specsDirectory
|
|
240751
241150
|
}),
|
|
240752
|
-
stallTimeout: options.stallTimeout
|
|
241151
|
+
stallTimeout: options.stallTimeout,
|
|
241152
|
+
mode: options.task._tag === "ralph" ? "ralph" : "default"
|
|
240753
241153
|
});
|
|
240754
241154
|
return ExitCode(0);
|
|
240755
241155
|
}
|
|
240756
241156
|
return yield* pipe$1(options.preset.cliAgent.command({
|
|
240757
|
-
prompt: promptGen.
|
|
240758
|
-
|
|
241157
|
+
prompt: options.task._tag === "ralph" ? promptGen.promptTimeoutRalph({
|
|
241158
|
+
task: options.task.task,
|
|
241159
|
+
specFile: options.task.specFile
|
|
241160
|
+
}) : promptGen.promptTimeout({
|
|
241161
|
+
taskId: options.task.task.id,
|
|
240759
241162
|
specsDirectory: options.specsDirectory
|
|
240760
241163
|
}),
|
|
240761
|
-
prdFilePath: pathService.join(".lalph", "prd.yml"),
|
|
241164
|
+
prdFilePath: options.task._tag === "ralph" ? void 0 : pathService.join(".lalph", "prd.yml"),
|
|
240762
241165
|
extraArgs: options.preset.extraArgs
|
|
240763
241166
|
}), setCwd(worktree.directory), options.preset.withCommandPrefix).pipe(worktree.execWithStallTimeout({
|
|
240764
241167
|
cliAgent: options.preset.cliAgent,
|
|
@@ -240780,6 +241183,33 @@ const agentResearcher = fnUntraced(function* (options) {
|
|
|
240780
241183
|
}).pipe(asSome);
|
|
240781
241184
|
});
|
|
240782
241185
|
//#endregion
|
|
241186
|
+
//#region src/Agents/chooserRalph.ts
|
|
241187
|
+
const agentChooserRalph = fnUntraced(function* (options) {
|
|
241188
|
+
const fs = yield* FileSystem;
|
|
241189
|
+
const pathService = yield* Path$1;
|
|
241190
|
+
const worktree = yield* Worktree;
|
|
241191
|
+
const promptGen = yield* PromptGen;
|
|
241192
|
+
if (!options.preset.cliAgent.command) yield* runClanka({
|
|
241193
|
+
directory: worktree.directory,
|
|
241194
|
+
model: options.preset.extraArgs.join(" "),
|
|
241195
|
+
prompt: promptGen.promptChooseRalph({ specFile: options.specFile }),
|
|
241196
|
+
stallTimeout: options.stallTimeout,
|
|
241197
|
+
mode: "ralph"
|
|
241198
|
+
});
|
|
241199
|
+
else yield* pipe$1(options.preset.cliAgent.command({
|
|
241200
|
+
prompt: promptGen.promptChooseRalph({ specFile: options.specFile }),
|
|
241201
|
+
prdFilePath: void 0,
|
|
241202
|
+
extraArgs: options.preset.extraArgs
|
|
241203
|
+
}), setCwd(worktree.directory), options.preset.withCommandPrefix, worktree.execWithWorkerOutput({ cliAgent: options.preset.cliAgent }), timeoutOrElse({
|
|
241204
|
+
duration: options.stallTimeout,
|
|
241205
|
+
onTimeout: () => fail$6(new RunnerStalled())
|
|
241206
|
+
}));
|
|
241207
|
+
return yield* pipe$1(fs.readFileString(pathService.join(worktree.directory, ".lalph", "task.md")), mapError$2((_) => new ChosenTaskNotFound()));
|
|
241208
|
+
});
|
|
241209
|
+
var ChosenTaskNotFound = class extends TaggedError("ChosenTaskNotFound") {
|
|
241210
|
+
message = "The AI agent failed to choose a task.";
|
|
241211
|
+
};
|
|
241212
|
+
//#endregion
|
|
240783
241213
|
//#region src/commands/root.ts
|
|
240784
241214
|
const run = fnUntraced(function* (options) {
|
|
240785
241215
|
const projectId = yield* CurrentProjectId;
|
|
@@ -240871,10 +241301,12 @@ const run = fnUntraced(function* (options) {
|
|
|
240871
241301
|
});
|
|
240872
241302
|
yield* log$1(`Agent exited with code: ${yield* agentWorker({
|
|
240873
241303
|
stallTimeout: options.stallTimeout,
|
|
241304
|
+
system: promptGen.systemClanka(options),
|
|
240874
241305
|
preset: taskPreset,
|
|
240875
241306
|
prompt: instructions,
|
|
240876
241307
|
research: researchResult,
|
|
240877
|
-
steer
|
|
241308
|
+
steer,
|
|
241309
|
+
ralph: false
|
|
240878
241310
|
}).pipe(provideService$2(CurrentTaskRef, issueRef), catchStallInReview, withSpan$1("Main.agentWorker"))}`);
|
|
240879
241311
|
if (options.review) {
|
|
240880
241312
|
yield* source.updateIssue({
|
|
@@ -240887,7 +241319,8 @@ const run = fnUntraced(function* (options) {
|
|
|
240887
241319
|
specsDirectory: options.specsDirectory,
|
|
240888
241320
|
stallTimeout: options.stallTimeout,
|
|
240889
241321
|
preset: taskPreset,
|
|
240890
|
-
instructions
|
|
241322
|
+
instructions,
|
|
241323
|
+
ralph: false
|
|
240891
241324
|
}).pipe(catchStallInReview, withSpan$1("Main.agentReviewer"));
|
|
240892
241325
|
yield* source.updateIssue({
|
|
240893
241326
|
projectId,
|
|
@@ -240899,7 +241332,10 @@ const run = fnUntraced(function* (options) {
|
|
|
240899
241332
|
specsDirectory: options.specsDirectory,
|
|
240900
241333
|
stallTimeout: options.stallTimeout,
|
|
240901
241334
|
preset: taskPreset,
|
|
240902
|
-
task:
|
|
241335
|
+
task: {
|
|
241336
|
+
_tag: "task",
|
|
241337
|
+
task: chosenTask.prd
|
|
241338
|
+
}
|
|
240903
241339
|
})), raceFirst(watchTaskState({ issueId: taskId })), as$1(false), catchTag$1("TaskStateChanged", (error) => log$1(`Task ${error.issueId} moved to ${error.state}; cancelling run.`).pipe(as$1(true))))) return;
|
|
240904
241340
|
yield* gitFlow.postWork({
|
|
240905
241341
|
worktree,
|
|
@@ -240913,6 +241349,69 @@ const run = fnUntraced(function* (options) {
|
|
|
240913
241349
|
});
|
|
240914
241350
|
else yield* prd.maybeRevertIssue({ issueId: taskId });
|
|
240915
241351
|
}, scoped$1, provide$1(SemanticSearchLayer.pipe(provideMerge(Prd.layer)), { local: true }));
|
|
241352
|
+
const runRalph = fnUntraced(function* (options) {
|
|
241353
|
+
const worktree = yield* Worktree;
|
|
241354
|
+
const gitFlow = yield* GitFlow;
|
|
241355
|
+
const currentWorker = yield* CurrentWorkerState;
|
|
241356
|
+
const registry = yield* AtomRegistry;
|
|
241357
|
+
const projectId = yield* CurrentProjectId;
|
|
241358
|
+
const preset = yield* getDefaultCliAgentPreset;
|
|
241359
|
+
yield* addFinalizer(fnUntraced(function* () {
|
|
241360
|
+
const currentBranchName = yield* worktree.currentBranch(worktree.directory).pipe(option$1, map$9(getOrUndefined$2));
|
|
241361
|
+
if (!currentBranchName) return;
|
|
241362
|
+
yield* worktree.exec`git checkout --detach ${currentBranchName}`;
|
|
241363
|
+
yield* worktree.exec`git branch -D ${currentBranchName}`;
|
|
241364
|
+
}, ignore$1()));
|
|
241365
|
+
registry.update(currentWorker.state, (s) => s.transitionTo(WorkerStatus.ChoosingTask()));
|
|
241366
|
+
const chosenTask = yield* agentChooserRalph({
|
|
241367
|
+
stallTimeout: options.stallTimeout,
|
|
241368
|
+
preset,
|
|
241369
|
+
specFile: options.specFile
|
|
241370
|
+
}).pipe(tapErrorTag("ChosenTaskNotFound", fnUntraced(function* () {
|
|
241371
|
+
yield* Settings.update(allProjects, map$16((projects) => projects.map((p) => p.id === projectId ? p.update({ enabled: false }) : p)));
|
|
241372
|
+
})), withSpan$1("Main.chooser"));
|
|
241373
|
+
yield* gen(function* () {
|
|
241374
|
+
registry.update(currentWorker.state, (s) => s.transitionTo(WorkerStatus.Working({ issueId: "ralph" })));
|
|
241375
|
+
let researchResult = none$4();
|
|
241376
|
+
const instructions = (yield* PromptGen).promptRalph({
|
|
241377
|
+
task: chosenTask,
|
|
241378
|
+
specFile: options.specFile,
|
|
241379
|
+
targetBranch: getOrUndefined$2(options.targetBranch),
|
|
241380
|
+
gitFlow
|
|
241381
|
+
});
|
|
241382
|
+
yield* log$1(`Agent exited with code: ${yield* agentWorker({
|
|
241383
|
+
stallTimeout: options.stallTimeout,
|
|
241384
|
+
preset,
|
|
241385
|
+
prompt: instructions,
|
|
241386
|
+
research: researchResult,
|
|
241387
|
+
ralph: true
|
|
241388
|
+
}).pipe(withSpan$1("Main.worker"))}`);
|
|
241389
|
+
if (options.review) {
|
|
241390
|
+
registry.update(currentWorker.state, (s) => s.transitionTo(WorkerStatus.Reviewing({ issueId: "ralph" })));
|
|
241391
|
+
yield* agentReviewer({
|
|
241392
|
+
specsDirectory: "",
|
|
241393
|
+
stallTimeout: options.stallTimeout,
|
|
241394
|
+
preset,
|
|
241395
|
+
instructions,
|
|
241396
|
+
ralph: true
|
|
241397
|
+
}).pipe(withSpan$1("Main.review"));
|
|
241398
|
+
}
|
|
241399
|
+
}).pipe(timeout(options.runTimeout), tapErrorTag("TimeoutError", () => agentTimeout({
|
|
241400
|
+
specsDirectory: "",
|
|
241401
|
+
stallTimeout: options.stallTimeout,
|
|
241402
|
+
preset,
|
|
241403
|
+
task: {
|
|
241404
|
+
_tag: "ralph",
|
|
241405
|
+
task: chosenTask,
|
|
241406
|
+
specFile: options.specFile
|
|
241407
|
+
}
|
|
241408
|
+
})));
|
|
241409
|
+
yield* gitFlow.postWork({
|
|
241410
|
+
worktree,
|
|
241411
|
+
targetBranch: getOrUndefined$2(options.targetBranch),
|
|
241412
|
+
issueId: ""
|
|
241413
|
+
});
|
|
241414
|
+
}, scoped$1, provide$1(SemanticSearchLayer.pipe(provideMerge([Prd.layerNoop, Worktree.layer])), { local: true }));
|
|
240916
241415
|
const runProject = fnUntraced(function* (options) {
|
|
240917
241416
|
const isFinite = Number.isFinite(options.iterations);
|
|
240918
241417
|
const iterationsDisplay = isFinite ? options.iterations : "unlimited";
|
|
@@ -240929,7 +241428,18 @@ const runProject = fnUntraced(function* (options) {
|
|
|
240929
241428
|
if (quit || isFinite && iteration >= iterations) break;
|
|
240930
241429
|
const currentIteration = iteration;
|
|
240931
241430
|
const startedDeferred = yield* make$85();
|
|
240932
|
-
|
|
241431
|
+
let ralphDone = false;
|
|
241432
|
+
const gitFlow = options.project.gitFlow;
|
|
241433
|
+
const isRalph = gitFlow === "ralph";
|
|
241434
|
+
const gitFlowLayer = gitFlow === "commit" ? GitFlowCommit : gitFlow === "ralph" ? GitFlowRalph : GitFlowPR;
|
|
241435
|
+
const fiber = yield* checkForWork(options.project).pipe(andThen(unify(isRalph ? runRalph({
|
|
241436
|
+
targetBranch: options.project.targetBranch,
|
|
241437
|
+
stallTimeout: options.stallTimeout,
|
|
241438
|
+
runTimeout: options.runTimeout,
|
|
241439
|
+
review: options.project.reviewAgent,
|
|
241440
|
+
research: options.project.researchAgent,
|
|
241441
|
+
specFile: options.project.ralphSpec
|
|
241442
|
+
}) : run({
|
|
240933
241443
|
startedDeferred,
|
|
240934
241444
|
targetBranch: options.project.targetBranch,
|
|
240935
241445
|
specsDirectory: options.specsDirectory,
|
|
@@ -240937,7 +241447,14 @@ const runProject = fnUntraced(function* (options) {
|
|
|
240937
241447
|
runTimeout: options.runTimeout,
|
|
240938
241448
|
review: options.project.reviewAgent,
|
|
240939
241449
|
research: options.project.researchAgent
|
|
240940
|
-
}).pipe(provide$1(
|
|
241450
|
+
})).pipe(provide$1(gitFlowLayer, { local: true }), withWorkerState(options.project.id))), catchTags$1({
|
|
241451
|
+
ChosenTaskNotFound(_error) {
|
|
241452
|
+
if (isRalph) {
|
|
241453
|
+
ralphDone = true;
|
|
241454
|
+
return log$1(`No more work to process for Ralph, ending after ${currentIteration + 1} iteration(s).`);
|
|
241455
|
+
}
|
|
241456
|
+
return void_$2;
|
|
241457
|
+
},
|
|
240941
241458
|
NoMoreWork(_error) {
|
|
240942
241459
|
if (isFinite) {
|
|
240943
241460
|
iterations = currentIteration;
|
|
@@ -240950,7 +241467,10 @@ const runProject = fnUntraced(function* (options) {
|
|
|
240950
241467
|
return void_$2;
|
|
240951
241468
|
}
|
|
240952
241469
|
}), catchCause$1((cause) => logWarning(cause).pipe(andThen(sleep(seconds(10))))), ensuring$2(semaphore.release(1)), ensuring$2(completeWith(startedDeferred, void_$2)), run$2(fibers));
|
|
240953
|
-
|
|
241470
|
+
if (isRalph) {
|
|
241471
|
+
yield* await_(fiber);
|
|
241472
|
+
if (ralphDone) break;
|
|
241473
|
+
} else yield* _await(startedDeferred);
|
|
240954
241474
|
iteration++;
|
|
240955
241475
|
}
|
|
240956
241476
|
yield* awaitEmpty(fibers);
|
|
@@ -241027,7 +241547,7 @@ const agentPlanner = fnUntraced(function* (options) {
|
|
|
241027
241547
|
const spawner = yield* ChildProcessSpawner;
|
|
241028
241548
|
yield* pipe$1(options.preset.cliAgent.commandPlan({
|
|
241029
241549
|
prompt: promptGen.planPrompt(options),
|
|
241030
|
-
prdFilePath: pathService.join(".lalph", "prd.yml"),
|
|
241550
|
+
prdFilePath: options.ralph ? void 0 : pathService.join(".lalph", "prd.yml"),
|
|
241031
241551
|
dangerous: options.dangerous
|
|
241032
241552
|
}), setCwd(worktree.directory), options.preset.withCommandPrefix, spawner.exitCode);
|
|
241033
241553
|
});
|
|
@@ -241144,7 +241664,7 @@ const commandPlan = make$58("plan", {
|
|
|
241144
241664
|
return pipe$1(editor.saveTemp(thePlan.value, { suffix: ".md" }), flatMap$4((file) => log$1(`Saved your plan to: ${file}`)), ignore$1);
|
|
241145
241665
|
});
|
|
241146
241666
|
yield* gen(function* () {
|
|
241147
|
-
const project = withNewProject ? yield* addOrUpdateProject() : yield* selectProject;
|
|
241667
|
+
const project = withNewProject ? yield* addOrUpdateProject(void 0, true) : yield* selectProject;
|
|
241148
241668
|
const { specsDirectory } = yield* commandRoot;
|
|
241149
241669
|
const preset = yield* selectCliAgentPreset;
|
|
241150
241670
|
yield* plan({
|
|
@@ -241152,7 +241672,8 @@ const commandPlan = make$58("plan", {
|
|
|
241152
241672
|
specsDirectory,
|
|
241153
241673
|
targetBranch: project.targetBranch,
|
|
241154
241674
|
dangerous,
|
|
241155
|
-
preset
|
|
241675
|
+
preset,
|
|
241676
|
+
ralph: project.gitFlow === "ralph"
|
|
241156
241677
|
}).pipe(provideService$2(CurrentProjectId, project.id));
|
|
241157
241678
|
}).pipe(provide$1([
|
|
241158
241679
|
Settings.layer,
|
|
@@ -241164,27 +241685,32 @@ const plan = fnUntraced(function* (options) {
|
|
|
241164
241685
|
const fs = yield* FileSystem;
|
|
241165
241686
|
const pathService = yield* Path$1;
|
|
241166
241687
|
const worktree = yield* Worktree;
|
|
241688
|
+
const projectId = yield* CurrentProjectId;
|
|
241167
241689
|
yield* agentPlanner({
|
|
241168
241690
|
plan: options.plan,
|
|
241169
241691
|
specsDirectory: options.specsDirectory,
|
|
241170
241692
|
dangerous: options.dangerous,
|
|
241171
|
-
preset: options.preset
|
|
241693
|
+
preset: options.preset,
|
|
241694
|
+
ralph: options.ralph
|
|
241172
241695
|
});
|
|
241173
241696
|
const planDetails = yield* pipe$1(fs.readFileString(pathService.join(worktree.directory, ".lalph", "plan.json")), flatMap$4(decodeEffect(PlanDetails)), mapError$2(() => new SpecNotFound()));
|
|
241697
|
+
if (options.ralph) yield* Settings.update(allProjects, map$16((projects) => projects.map((p) => p.id === projectId ? p.update({ ralphSpec: planDetails.specification }) : p)));
|
|
241174
241698
|
if (isSome(options.targetBranch)) yield* commitAndPushSpecification({
|
|
241175
241699
|
specsDirectory: options.specsDirectory,
|
|
241176
241700
|
targetBranch: options.targetBranch.value
|
|
241177
241701
|
});
|
|
241178
|
-
|
|
241179
|
-
|
|
241180
|
-
|
|
241181
|
-
|
|
241182
|
-
|
|
241183
|
-
|
|
241702
|
+
if (!options.ralph) {
|
|
241703
|
+
yield* log$1("Converting specification into tasks");
|
|
241704
|
+
yield* agentTasker({
|
|
241705
|
+
specificationPath: planDetails.specification,
|
|
241706
|
+
specsDirectory: options.specsDirectory,
|
|
241707
|
+
preset: options.preset
|
|
241708
|
+
});
|
|
241709
|
+
}
|
|
241184
241710
|
if (!worktree.inExisting) yield* pipe$1(fs.copy(pathService.join(worktree.directory, options.specsDirectory), options.specsDirectory, { overwrite: true }), ignore$1);
|
|
241185
|
-
}, scoped$1, provide$1([
|
|
241711
|
+
}, scoped$1, (effect, options) => provide$1(effect, [
|
|
241186
241712
|
PromptGen.layer,
|
|
241187
|
-
Prd.layerProvided,
|
|
241713
|
+
options.ralph ? Prd.layerNoop : Prd.layerProvided,
|
|
241188
241714
|
Worktree.layer,
|
|
241189
241715
|
Settings.layer,
|
|
241190
241716
|
CurrentIssueSource.layer
|
|
@@ -241289,7 +241815,7 @@ const commandEdit = make$58("edit").pipe(withDescription("Open the selected proj
|
|
|
241289
241815
|
const commandSource = make$58("source").pipe(withDescription("Select the issue source to use (e.g. GitHub Issues or Linear). This applies to all projects."), withHandler(() => selectIssueSource), provide(Settings.layer));
|
|
241290
241816
|
//#endregion
|
|
241291
241817
|
//#region package.json
|
|
241292
|
-
var version = "0.3.
|
|
241818
|
+
var version = "0.3.87";
|
|
241293
241819
|
//#endregion
|
|
241294
241820
|
//#region src/commands/projects/ls.ts
|
|
241295
241821
|
const commandProjectsLs = make$58("ls").pipe(withDescription("List configured projects and how they run (enabled state, concurrency, branch, git flow, review agent)."), withHandler(fnUntraced(function* () {
|