lalph 0.3.89 → 0.3.91
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 +286 -138
- package/package.json +2 -2
- package/src/Agents/reviewer.ts +14 -3
- package/src/Agents/timeout.ts +30 -40
- package/src/Agents/worker.ts +12 -5
- package/src/Clanka.ts +1 -0
- package/src/commands/root.ts +119 -55
- package/src/domain/CurrentTask.ts +14 -0
package/dist/cli.mjs
CHANGED
|
@@ -181596,7 +181596,7 @@ var ji = Bt, Ii = Object.assign(Qe, { sync: Bt }), zi = Ut, Bi = Object.assign(e
|
|
|
181596
181596
|
});
|
|
181597
181597
|
Ze.glob = Ze;
|
|
181598
181598
|
//#endregion
|
|
181599
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
181599
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/ApplyPatch.js
|
|
181600
181600
|
/**
|
|
181601
181601
|
* @since 1.0.0
|
|
181602
181602
|
*/
|
|
@@ -196469,7 +196469,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
196469
196469
|
}
|
|
196470
196470
|
};
|
|
196471
196471
|
//#endregion
|
|
196472
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
196472
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/McpClient.js
|
|
196473
196473
|
/**
|
|
196474
196474
|
* @since 1.0.0
|
|
196475
196475
|
*/
|
|
@@ -196514,7 +196514,7 @@ const layer$13 = effect$1(McpClient, gen(function* () {
|
|
|
196514
196514
|
});
|
|
196515
196515
|
}));
|
|
196516
196516
|
//#endregion
|
|
196517
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
196517
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/ExaSearch.js
|
|
196518
196518
|
/**
|
|
196519
196519
|
* @since 1.0.0
|
|
196520
196520
|
*/
|
|
@@ -211464,7 +211464,7 @@ var require_lib = /* @__PURE__ */ __commonJSMin$1(((exports) => {
|
|
|
211464
211464
|
exports.impl = impl;
|
|
211465
211465
|
}));
|
|
211466
211466
|
//#endregion
|
|
211467
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
211467
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/WebToMarkdown.js
|
|
211468
211468
|
/**
|
|
211469
211469
|
* @since 1.0.0
|
|
211470
211470
|
*/
|
|
@@ -215082,7 +215082,7 @@ const mapProviderResults = (inputLength, results) => {
|
|
|
215082
215082
|
return succeed$3(embeddings);
|
|
215083
215083
|
};
|
|
215084
215084
|
//#endregion
|
|
215085
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
215085
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/ChunkRepo.js
|
|
215086
215086
|
/**
|
|
215087
215087
|
* @since 1.0.0
|
|
215088
215088
|
* @category Models
|
|
@@ -215213,7 +215213,7 @@ const layer$10 = effect$1(ChunkRepo, gen(function* () {
|
|
|
215213
215213
|
});
|
|
215214
215214
|
}));
|
|
215215
215215
|
//#endregion
|
|
215216
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
215216
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/CodeChunker.js
|
|
215217
215217
|
/**
|
|
215218
215218
|
* @since 1.0.0
|
|
215219
215219
|
*/
|
|
@@ -215806,7 +215806,7 @@ const run$1 = /* @__PURE__ */ make$25({});
|
|
|
215806
215806
|
*/
|
|
215807
215807
|
const layer$7 = (options) => effectDiscard(run$1(options));
|
|
215808
215808
|
//#endregion
|
|
215809
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
215809
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/internal/sqlite-vector.js
|
|
215810
215810
|
/**
|
|
215811
215811
|
* Binary extension for each platform
|
|
215812
215812
|
*/
|
|
@@ -215923,7 +215923,7 @@ function getExtensionPath() {
|
|
|
215923
215923
|
throw new ExtensionNotFoundError(`SQLite Vector extension not found for platform: ${getCurrentPlatform()}\n\nThe platform-specific package "${getPlatformPackageName()}" is not installed.\nThis usually happens when:\n 1. Your platform is not supported\n 2. npm failed to install optional dependencies\n 3. You're installing with --no-optional flag\n\nTry running: npm install --force`);
|
|
215924
215924
|
}
|
|
215925
215925
|
//#endregion
|
|
215926
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
215926
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/Sqlite.js
|
|
215927
215927
|
/**
|
|
215928
215928
|
* @since 1.0.0
|
|
215929
215929
|
*/
|
|
@@ -215951,7 +215951,7 @@ const SqliteLayer = (database) => layer$7({ loader: fromRecord({ "0001_create_ch
|
|
|
215951
215951
|
yield* fs.makeDirectory(directory, { recursive: true });
|
|
215952
215952
|
}))));
|
|
215953
215953
|
//#endregion
|
|
215954
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
215954
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/SemanticSearch.js
|
|
215955
215955
|
/**
|
|
215956
215956
|
* @since 1.0.0
|
|
215957
215957
|
*/
|
|
@@ -216093,7 +216093,7 @@ const maybeRemoveFile = (path) => serviceOption(SemanticSearch).pipe(flatMap$4(m
|
|
|
216093
216093
|
onSome: (service) => service.removeFile(path)
|
|
216094
216094
|
})));
|
|
216095
216095
|
//#endregion
|
|
216096
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
216096
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/AgentTools.js
|
|
216097
216097
|
/**
|
|
216098
216098
|
* @since 1.0.0
|
|
216099
216099
|
*/
|
|
@@ -216444,7 +216444,7 @@ const AgentToolHandlers = AgentToolHandlersNoDeps.pipe(provide$3([layer$12, laye
|
|
|
216444
216444
|
AgentToolHandlersNoDeps.pipe(provide$3([mock(ExaSearch)({}), mock(WebToMarkdown)({})]));
|
|
216445
216445
|
var ApplyPatchError = class extends TaggedClass$2("ApplyPatchError") {};
|
|
216446
216446
|
//#endregion
|
|
216447
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
216447
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/TypeBuilder.js
|
|
216448
216448
|
const resolveDocumentation = resolveAt("documentation");
|
|
216449
216449
|
const identifierPattern = /^[$A-Z_a-z][$0-9A-Z_a-z]*$/u;
|
|
216450
216450
|
const Precedence = {
|
|
@@ -216717,7 +216717,7 @@ const render = (schema, options) => {
|
|
|
216717
216717
|
return printNode({ text: documentation === void 0 ? rendered.text : `${renderJsDoc(documentation, 0, printerOptions)}${printerOptions.newLine}${rendered.text}` }, printerOptions);
|
|
216718
216718
|
};
|
|
216719
216719
|
//#endregion
|
|
216720
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
216720
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/ToolkitRenderer.js
|
|
216721
216721
|
/**
|
|
216722
216722
|
* @since 1.0.0
|
|
216723
216723
|
*/
|
|
@@ -216739,7 +216739,7 @@ declare function ${name}(${params}): Promise<${render(tool.successSchema)}>`);
|
|
|
216739
216739
|
}) });
|
|
216740
216740
|
};
|
|
216741
216741
|
//#endregion
|
|
216742
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
216742
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/ScriptPreprocessing.js
|
|
216743
216743
|
const isIdentifierChar = (char) => char !== void 0 && /[A-Za-z0-9_$]/.test(char);
|
|
216744
216744
|
const isIdentifierStartChar = (char) => char !== void 0 && /[A-Za-z_$]/.test(char);
|
|
216745
216745
|
const hasIdentifierBoundary = (text, index, length) => !isIdentifierChar(text[index - 1]) && !isIdentifierChar(text[index + length]);
|
|
@@ -216765,6 +216765,76 @@ const parseIdentifier = (text, start) => {
|
|
|
216765
216765
|
end
|
|
216766
216766
|
};
|
|
216767
216767
|
};
|
|
216768
|
+
const findPreviousNonWhitespace = (text, from) => {
|
|
216769
|
+
let i = from;
|
|
216770
|
+
while (i >= 0 && /\s/.test(text[i])) i--;
|
|
216771
|
+
return i;
|
|
216772
|
+
};
|
|
216773
|
+
const findNextNonWhitespace = (text, from) => {
|
|
216774
|
+
let i = from;
|
|
216775
|
+
while (i < text.length && /\s/.test(text[i])) i++;
|
|
216776
|
+
return i;
|
|
216777
|
+
};
|
|
216778
|
+
const findObjectValueTerminator = (text, start) => {
|
|
216779
|
+
let parenDepth = 0;
|
|
216780
|
+
let bracketDepth = 0;
|
|
216781
|
+
let braceDepth = 0;
|
|
216782
|
+
let stringDelimiter;
|
|
216783
|
+
for (let i = start; i < text.length; i++) {
|
|
216784
|
+
const char = text[i];
|
|
216785
|
+
if (stringDelimiter !== void 0) {
|
|
216786
|
+
if (char === stringDelimiter && !isEscaped(text, i)) stringDelimiter = void 0;
|
|
216787
|
+
continue;
|
|
216788
|
+
}
|
|
216789
|
+
if (char === "\"" || char === "'" || char === "`") {
|
|
216790
|
+
stringDelimiter = char;
|
|
216791
|
+
continue;
|
|
216792
|
+
}
|
|
216793
|
+
if (char === "(") {
|
|
216794
|
+
parenDepth++;
|
|
216795
|
+
continue;
|
|
216796
|
+
}
|
|
216797
|
+
if (char === ")") {
|
|
216798
|
+
if (parenDepth > 0) parenDepth--;
|
|
216799
|
+
continue;
|
|
216800
|
+
}
|
|
216801
|
+
if (char === "[") {
|
|
216802
|
+
bracketDepth++;
|
|
216803
|
+
continue;
|
|
216804
|
+
}
|
|
216805
|
+
if (char === "]") {
|
|
216806
|
+
if (bracketDepth > 0) bracketDepth--;
|
|
216807
|
+
continue;
|
|
216808
|
+
}
|
|
216809
|
+
if (char === "{") {
|
|
216810
|
+
braceDepth++;
|
|
216811
|
+
continue;
|
|
216812
|
+
}
|
|
216813
|
+
if (char === "}") {
|
|
216814
|
+
if (parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) return i;
|
|
216815
|
+
if (braceDepth > 0) braceDepth--;
|
|
216816
|
+
continue;
|
|
216817
|
+
}
|
|
216818
|
+
if (char === "," && parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) return i;
|
|
216819
|
+
}
|
|
216820
|
+
return -1;
|
|
216821
|
+
};
|
|
216822
|
+
const collectExpressionIdentifiers = (text, start, end) => {
|
|
216823
|
+
const out = /* @__PURE__ */ new Set();
|
|
216824
|
+
let cursor = start;
|
|
216825
|
+
while (cursor < end) {
|
|
216826
|
+
const identifier = parseIdentifier(text, cursor);
|
|
216827
|
+
if (identifier === void 0) {
|
|
216828
|
+
cursor++;
|
|
216829
|
+
continue;
|
|
216830
|
+
}
|
|
216831
|
+
const previousNonWhitespace = findPreviousNonWhitespace(text, cursor - 1);
|
|
216832
|
+
const nextNonWhitespace = findNextNonWhitespace(text, identifier.end);
|
|
216833
|
+
if (text[previousNonWhitespace] !== "." && text[nextNonWhitespace] !== "." && text[nextNonWhitespace] !== "(") out.add(identifier.name);
|
|
216834
|
+
cursor = identifier.end;
|
|
216835
|
+
}
|
|
216836
|
+
return out;
|
|
216837
|
+
};
|
|
216768
216838
|
const isEscaped = (text, index) => {
|
|
216769
216839
|
let slashCount = 0;
|
|
216770
216840
|
let i = index - 1;
|
|
@@ -216782,14 +216852,26 @@ const needsTemplateEscaping = (text) => {
|
|
|
216782
216852
|
}
|
|
216783
216853
|
return false;
|
|
216784
216854
|
};
|
|
216785
|
-
const normalizePatchEscapedQuotes = (text) => text.includes("*** Begin Patch") ? text.replace(/\\"([A-Za-z0-9_$.-]+)\\"/g,
|
|
216855
|
+
const normalizePatchEscapedQuotes = (text) => text.includes("*** Begin Patch") ? text.replace(/\\"([A-Za-z0-9_$.-]+)\\"/g, (match, content, index) => {
|
|
216856
|
+
const previous = text[findPreviousNonWhitespace(text, index - 1)];
|
|
216857
|
+
const next = text[findNextNonWhitespace(text, index + match.length)];
|
|
216858
|
+
if (previous === "{" || previous === "[" || previous === ":" || previous === "," || next === ":" || next === "}" || next === "]" || next === ",") return match;
|
|
216859
|
+
return `"${content}"`;
|
|
216860
|
+
}) : text;
|
|
216861
|
+
const normalizeNonPatchEscapedTemplateMarkers = (text) => text.replace(/\\{2,}(?=`|\$\{)/g, "\\").replace(/(^|\s)\\+(?=\.[A-Za-z0-9_-]+\/)/g, "$1");
|
|
216786
216862
|
const escapeTemplateLiteralContent = (text) => {
|
|
216787
|
-
const
|
|
216788
|
-
|
|
216863
|
+
const normalizedPatchQuotes = normalizePatchEscapedQuotes(text);
|
|
216864
|
+
const isPatchContent = normalizedPatchQuotes.includes("*** Begin Patch");
|
|
216865
|
+
const normalized = isPatchContent ? normalizedPatchQuotes : normalizeNonPatchEscapedTemplateMarkers(normalizedPatchQuotes);
|
|
216866
|
+
if (!needsTemplateEscaping(normalized) && !(isPatchContent && normalized.includes("\\"))) return normalized;
|
|
216789
216867
|
let out = "";
|
|
216790
216868
|
for (let i = 0; i < normalized.length; i++) {
|
|
216791
216869
|
const char = normalized[i];
|
|
216792
216870
|
if (char === "\\") {
|
|
216871
|
+
if (!isPatchContent && (normalized[i + 1] === "`" || normalized[i + 1] === "$" && normalized[i + 2] === "{")) {
|
|
216872
|
+
out += "\\";
|
|
216873
|
+
continue;
|
|
216874
|
+
}
|
|
216793
216875
|
out += "\\\\";
|
|
216794
216876
|
continue;
|
|
216795
216877
|
}
|
|
@@ -216809,6 +216891,10 @@ const findTemplateEnd = (text, start, isTerminator) => {
|
|
|
216809
216891
|
let end = -1;
|
|
216810
216892
|
for (let i = start + 1; i < text.length; i++) {
|
|
216811
216893
|
if (text[i] !== "`" || isEscaped(text, i)) continue;
|
|
216894
|
+
if (isTerminator(text[i + 1])) {
|
|
216895
|
+
end = i;
|
|
216896
|
+
continue;
|
|
216897
|
+
}
|
|
216812
216898
|
if (isTerminator(text[skipWhitespace(text, i + 1)])) end = i;
|
|
216813
216899
|
}
|
|
216814
216900
|
return end;
|
|
@@ -216876,47 +216962,25 @@ const fixCallTemplateArgument = (script, functionName) => {
|
|
|
216876
216962
|
}
|
|
216877
216963
|
return out;
|
|
216878
216964
|
};
|
|
216879
|
-
const
|
|
216880
|
-
const out = /* @__PURE__ */ new Set();
|
|
216881
|
-
let cursor = 0;
|
|
216882
|
-
while (cursor < script.length) {
|
|
216883
|
-
const callStart = findNextIdentifier(script, functionName, cursor);
|
|
216884
|
-
if (callStart === -1) break;
|
|
216885
|
-
const openParen = skipWhitespace(script, callStart + functionName.length);
|
|
216886
|
-
if (script[openParen] !== "(") {
|
|
216887
|
-
cursor = callStart + functionName.length;
|
|
216888
|
-
continue;
|
|
216889
|
-
}
|
|
216890
|
-
const identifier = parseIdentifier(script, skipWhitespace(script, openParen + 1));
|
|
216891
|
-
if (identifier === void 0) {
|
|
216892
|
-
cursor = openParen + 1;
|
|
216893
|
-
continue;
|
|
216894
|
-
}
|
|
216895
|
-
const argumentEnd = skipWhitespace(script, identifier.end);
|
|
216896
|
-
if (script[argumentEnd] === ")" || script[argumentEnd] === ",") out.add(identifier.name);
|
|
216897
|
-
cursor = identifier.end;
|
|
216898
|
-
}
|
|
216899
|
-
return out;
|
|
216900
|
-
};
|
|
216901
|
-
const fixWriteFileContentTemplates = (script) => {
|
|
216965
|
+
const fixCallObjectPropertyTemplate = (script, functionName, propertyName) => {
|
|
216902
216966
|
let out = script;
|
|
216903
216967
|
let cursor = 0;
|
|
216904
216968
|
while (cursor < out.length) {
|
|
216905
|
-
const callStart = findNextIdentifier(out,
|
|
216969
|
+
const callStart = findNextIdentifier(out, functionName, cursor);
|
|
216906
216970
|
if (callStart === -1) break;
|
|
216907
|
-
const openParen = skipWhitespace(out, callStart +
|
|
216971
|
+
const openParen = skipWhitespace(out, callStart + functionName.length);
|
|
216908
216972
|
if (out[openParen] !== "(") {
|
|
216909
|
-
cursor = callStart +
|
|
216973
|
+
cursor = callStart + functionName.length;
|
|
216910
216974
|
continue;
|
|
216911
216975
|
}
|
|
216912
|
-
const
|
|
216913
|
-
if (
|
|
216976
|
+
const propertyKey = findNextIdentifier(out, propertyName, openParen + 1);
|
|
216977
|
+
if (propertyKey === -1) {
|
|
216914
216978
|
cursor = openParen + 1;
|
|
216915
216979
|
continue;
|
|
216916
216980
|
}
|
|
216917
|
-
const colon = skipWhitespace(out,
|
|
216981
|
+
const colon = skipWhitespace(out, propertyKey + propertyName.length);
|
|
216918
216982
|
if (out[colon] !== ":") {
|
|
216919
|
-
cursor =
|
|
216983
|
+
cursor = propertyKey + propertyName.length;
|
|
216920
216984
|
continue;
|
|
216921
216985
|
}
|
|
216922
216986
|
const templateStart = skipWhitespace(out, colon + 1);
|
|
@@ -216940,42 +217004,63 @@ const fixWriteFileContentTemplates = (script) => {
|
|
|
216940
217004
|
}
|
|
216941
217005
|
return out;
|
|
216942
217006
|
};
|
|
216943
|
-
const
|
|
217007
|
+
const collectCallArgumentIdentifiers = (script, functionName) => {
|
|
216944
217008
|
const out = /* @__PURE__ */ new Set();
|
|
216945
217009
|
let cursor = 0;
|
|
216946
217010
|
while (cursor < script.length) {
|
|
216947
|
-
const callStart = findNextIdentifier(script,
|
|
217011
|
+
const callStart = findNextIdentifier(script, functionName, cursor);
|
|
216948
217012
|
if (callStart === -1) break;
|
|
216949
|
-
const openParen = skipWhitespace(script, callStart +
|
|
217013
|
+
const openParen = skipWhitespace(script, callStart + functionName.length);
|
|
216950
217014
|
if (script[openParen] !== "(") {
|
|
216951
|
-
cursor = callStart +
|
|
217015
|
+
cursor = callStart + functionName.length;
|
|
216952
217016
|
continue;
|
|
216953
217017
|
}
|
|
216954
|
-
const
|
|
216955
|
-
if (
|
|
217018
|
+
const identifier = parseIdentifier(script, skipWhitespace(script, openParen + 1));
|
|
217019
|
+
if (identifier === void 0) {
|
|
216956
217020
|
cursor = openParen + 1;
|
|
216957
217021
|
continue;
|
|
216958
217022
|
}
|
|
216959
|
-
const
|
|
216960
|
-
if (script[
|
|
216961
|
-
|
|
216962
|
-
|
|
216963
|
-
|
|
216964
|
-
|
|
216965
|
-
|
|
216966
|
-
|
|
217023
|
+
const argumentEnd = skipWhitespace(script, identifier.end);
|
|
217024
|
+
if (script[argumentEnd] === ")" || script[argumentEnd] === ",") out.add(identifier.name);
|
|
217025
|
+
cursor = identifier.end;
|
|
217026
|
+
}
|
|
217027
|
+
return out;
|
|
217028
|
+
};
|
|
217029
|
+
const collectCallObjectPropertyIdentifiers = (script, functionName, propertyName) => {
|
|
217030
|
+
const out = /* @__PURE__ */ new Set();
|
|
217031
|
+
let cursor = 0;
|
|
217032
|
+
while (cursor < script.length) {
|
|
217033
|
+
const callStart = findNextIdentifier(script, functionName, cursor);
|
|
217034
|
+
if (callStart === -1) break;
|
|
217035
|
+
const openParen = skipWhitespace(script, callStart + functionName.length);
|
|
217036
|
+
if (script[openParen] !== "(") {
|
|
217037
|
+
cursor = callStart + functionName.length;
|
|
217038
|
+
continue;
|
|
217039
|
+
}
|
|
217040
|
+
const propertyKey = findNextIdentifier(script, propertyName, openParen + 1);
|
|
217041
|
+
if (propertyKey === -1) {
|
|
217042
|
+
cursor = openParen + 1;
|
|
217043
|
+
continue;
|
|
217044
|
+
}
|
|
217045
|
+
const afterProperty = skipWhitespace(script, propertyKey + propertyName.length);
|
|
217046
|
+
if (script[afterProperty] === ":") {
|
|
217047
|
+
const valueStart = skipWhitespace(script, afterProperty + 1);
|
|
217048
|
+
const valueEnd = findObjectValueTerminator(script, valueStart);
|
|
217049
|
+
if (valueEnd !== -1) for (const identifier of collectExpressionIdentifiers(script, valueStart, valueEnd)) out.add(identifier);
|
|
216967
217050
|
cursor = valueStart + 1;
|
|
216968
217051
|
continue;
|
|
216969
217052
|
}
|
|
216970
|
-
if (script[
|
|
216971
|
-
out.add(
|
|
216972
|
-
cursor =
|
|
217053
|
+
if (script[afterProperty] === "}" || script[afterProperty] === ",") {
|
|
217054
|
+
out.add(propertyName);
|
|
217055
|
+
cursor = afterProperty + 1;
|
|
216973
217056
|
continue;
|
|
216974
217057
|
}
|
|
216975
|
-
cursor =
|
|
217058
|
+
cursor = afterProperty + 1;
|
|
216976
217059
|
}
|
|
216977
217060
|
return out;
|
|
216978
217061
|
};
|
|
217062
|
+
const callObjectPropertyTargets = [["writeFile", "content"], ["updateTask", "description"]];
|
|
217063
|
+
const fixTargetCallObjectPropertyTemplates = (script) => callObjectPropertyTargets.reduce((current, [functionName, propertyName]) => fixCallObjectPropertyTemplate(current, functionName, propertyName), script);
|
|
216979
217064
|
const fixAssignedTemplate = (script, variableName) => {
|
|
216980
217065
|
let out = script;
|
|
216981
217066
|
let cursor = 0;
|
|
@@ -216999,7 +217084,7 @@ const fixAssignedTemplate = (script, variableName) => {
|
|
|
216999
217084
|
cursor = templateStart + 1;
|
|
217000
217085
|
continue;
|
|
217001
217086
|
}
|
|
217002
|
-
const templateEnd = findTemplateEnd(out, templateStart, (char) => char === void 0 || char === ";" || char === "," || char === ")" || char === "}" || char === "]");
|
|
217087
|
+
const templateEnd = findTemplateEnd(out, templateStart, (char) => char === void 0 || char === "\n" || char === "\r" || char === ";" || char === "," || char === ")" || char === "}" || char === "]");
|
|
217003
217088
|
if (templateEnd === -1) {
|
|
217004
217089
|
cursor = templateStart + 1;
|
|
217005
217090
|
continue;
|
|
@@ -217018,15 +217103,15 @@ const fixAssignedTemplate = (script, variableName) => {
|
|
|
217018
217103
|
const fixAssignedTemplatesForToolCalls = (script) => {
|
|
217019
217104
|
const identifiers = /* @__PURE__ */ new Set();
|
|
217020
217105
|
for (const functionName of ["applyPatch", "taskComplete"]) for (const identifier of collectCallArgumentIdentifiers(script, functionName)) identifiers.add(identifier);
|
|
217021
|
-
for (const identifier of
|
|
217106
|
+
for (const [functionName, propertyName] of callObjectPropertyTargets) for (const identifier of collectCallObjectPropertyIdentifiers(script, functionName, propertyName)) identifiers.add(identifier);
|
|
217022
217107
|
if (script.includes("*** Begin Patch")) identifiers.add("patch");
|
|
217023
217108
|
let out = script;
|
|
217024
217109
|
for (const identifier of identifiers) out = fixAssignedTemplate(out, identifier);
|
|
217025
217110
|
return out;
|
|
217026
217111
|
};
|
|
217027
|
-
const preprocessScript = (script) => fixAssignedTemplatesForToolCalls(["applyPatch", "taskComplete"].reduce((current, functionName) => fixCallTemplateArgument(current, functionName),
|
|
217112
|
+
const preprocessScript = (script) => fixAssignedTemplatesForToolCalls(["applyPatch", "taskComplete"].reduce((current, functionName) => fixCallTemplateArgument(current, functionName), fixTargetCallObjectPropertyTemplates(script)));
|
|
217028
217113
|
//#endregion
|
|
217029
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
217114
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/AgentExecutor.js
|
|
217030
217115
|
/**
|
|
217031
217116
|
* @since 1.0.0
|
|
217032
217117
|
*/
|
|
@@ -217211,7 +217296,7 @@ var QueueWriteStream = class extends Writable {
|
|
|
217211
217296
|
}
|
|
217212
217297
|
};
|
|
217213
217298
|
//#endregion
|
|
217214
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
217299
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/ScriptExtraction.js
|
|
217215
217300
|
const stripWrappingCodeFence = (script) => {
|
|
217216
217301
|
const lines = script.split(/\r?\n/);
|
|
217217
217302
|
if (lines.length < 2) return script;
|
|
@@ -218760,7 +218845,7 @@ const applySpanTransformer = (transformer, response, options) => {
|
|
|
218760
218845
|
});
|
|
218761
218846
|
};
|
|
218762
218847
|
//#endregion
|
|
218763
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
218848
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/Agent.js
|
|
218764
218849
|
/**
|
|
218765
218850
|
* @since 1.0.0
|
|
218766
218851
|
*/
|
|
@@ -230090,7 +230175,7 @@ const transformToolCallParams = /* @__PURE__ */ fnUntraced(function* (tools, too
|
|
|
230090
230175
|
})));
|
|
230091
230176
|
});
|
|
230092
230177
|
//#endregion
|
|
230093
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
230178
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/CodexAuth.js
|
|
230094
230179
|
/**
|
|
230095
230180
|
* @since 1.0.0
|
|
230096
230181
|
*/
|
|
@@ -230310,7 +230395,7 @@ var CodexAuth = class CodexAuth extends Service$1()("clanka/CodexAuth") {
|
|
|
230310
230395
|
static layerClient = this.layerClientNoDeps.pipe(provide$3(CodexAuth.layer));
|
|
230311
230396
|
};
|
|
230312
230397
|
//#endregion
|
|
230313
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
230398
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/Codex.js
|
|
230314
230399
|
/**
|
|
230315
230400
|
* @since 1.0.0
|
|
230316
230401
|
*/
|
|
@@ -231622,7 +231707,7 @@ const getUsageDetailNumber = (details, field) => {
|
|
|
231622
231707
|
return typeof value === "number" ? value : void 0;
|
|
231623
231708
|
};
|
|
231624
231709
|
//#endregion
|
|
231625
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
231710
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/CopilotAuth.js
|
|
231626
231711
|
/**
|
|
231627
231712
|
* @since 1.0.0
|
|
231628
231713
|
*/
|
|
@@ -231813,7 +231898,7 @@ var GithubCopilotAuth = class GithubCopilotAuth extends Service$1()("clanka/Gith
|
|
|
231813
231898
|
static layerClient = this.layerClientNoDeps.pipe(provide$3(GithubCopilotAuth.layer));
|
|
231814
231899
|
};
|
|
231815
231900
|
//#endregion
|
|
231816
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
231901
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/Copilot.js
|
|
231817
231902
|
/**
|
|
231818
231903
|
* @since 1.0.0
|
|
231819
231904
|
*/
|
|
@@ -232233,7 +232318,7 @@ Object.defineProperties(createChalk.prototype, styles);
|
|
|
232233
232318
|
const chalk = createChalk();
|
|
232234
232319
|
createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
232235
232320
|
//#endregion
|
|
232236
|
-
//#region node_modules/.pnpm/clanka@0.2.
|
|
232321
|
+
//#region node_modules/.pnpm/clanka@0.2.19_@effect+ai-openai-compat@4.0.0-beta.35_effect@https+++pkg.pr.new+Effect-T_3ecf2271901c4565ca12cd64815ad5c2/node_modules/clanka/dist/OutputFormatter.js
|
|
232237
232322
|
/**
|
|
232238
232323
|
* @since 1.0.0
|
|
232239
232324
|
*/
|
|
@@ -240890,12 +240975,19 @@ const runClanka = fnUntraced(function* (options) {
|
|
|
240890
240975
|
}, scoped$1, (effect, options) => provide$1(effect, layerLocal({
|
|
240891
240976
|
directory: options.directory,
|
|
240892
240977
|
tools: options.mode === "ralph" ? void 0 : options.mode === "choose" ? TaskChooseTools : TaskTools
|
|
240893
|
-
}).pipe(merge$6(ClankaModels.get(options.model)))), provide$1([layerUndici, TaskToolsHandlers]));
|
|
240978
|
+
}).pipe(merge$6(ClankaModels.get(options.model))), { local: true }), provide$1([layerUndici, TaskToolsHandlers]));
|
|
240979
|
+
//#endregion
|
|
240980
|
+
//#region src/domain/CurrentTask.ts
|
|
240981
|
+
const CurrentTask = taggedEnum();
|
|
240894
240982
|
//#endregion
|
|
240895
240983
|
//#region src/Agents/worker.ts
|
|
240896
240984
|
const agentWorker = fnUntraced(function* (options) {
|
|
240897
240985
|
const pathService = yield* Path$1;
|
|
240898
240986
|
const worktree = yield* Worktree;
|
|
240987
|
+
const prdFilePath = CurrentTask.$match(options.currentTask, {
|
|
240988
|
+
task: () => pathService.join(".lalph", "prd.yml"),
|
|
240989
|
+
ralph: () => void 0
|
|
240990
|
+
});
|
|
240899
240991
|
if (!options.preset.cliAgent.command) {
|
|
240900
240992
|
yield* runClanka({
|
|
240901
240993
|
directory: worktree.directory,
|
|
@@ -240917,13 +241009,16 @@ ${research}`
|
|
|
240917
241009
|
stallTimeout: options.stallTimeout,
|
|
240918
241010
|
maxContext: options.maxContext,
|
|
240919
241011
|
steer: options.steer,
|
|
240920
|
-
mode: options.
|
|
241012
|
+
mode: CurrentTask.$match(options.currentTask, {
|
|
241013
|
+
task: () => "default",
|
|
241014
|
+
ralph: () => "ralph"
|
|
241015
|
+
})
|
|
240921
241016
|
});
|
|
240922
241017
|
return ExitCode(0);
|
|
240923
241018
|
}
|
|
240924
241019
|
return yield* pipe$1(options.preset.cliAgent.command({
|
|
240925
241020
|
prompt: options.prompt,
|
|
240926
|
-
prdFilePath
|
|
241021
|
+
prdFilePath,
|
|
240927
241022
|
extraArgs: options.preset.extraArgs
|
|
240928
241023
|
}), setCwd(worktree.directory), options.preset.withCommandPrefix).pipe(worktree.execWithStallTimeout({
|
|
240929
241024
|
cliAgent: options.preset.cliAgent,
|
|
@@ -241113,12 +241208,20 @@ const agentReviewer = fnUntraced(function* (options) {
|
|
|
241113
241208
|
const worktree = yield* Worktree;
|
|
241114
241209
|
const promptGen = yield* PromptGen;
|
|
241115
241210
|
const gitFlow = yield* GitFlow;
|
|
241211
|
+
const mode = CurrentTask.$match(options.currentTask, {
|
|
241212
|
+
task: () => "default",
|
|
241213
|
+
ralph: () => "ralph"
|
|
241214
|
+
});
|
|
241215
|
+
const system = CurrentTask.$match(options.currentTask, {
|
|
241216
|
+
task: () => promptGen.systemClanka(options),
|
|
241217
|
+
ralph: () => void 0
|
|
241218
|
+
});
|
|
241116
241219
|
const customInstructions = yield* pipe$1(fs.readFileString(pathService.join(worktree.directory, "LALPH_REVIEW.md")), option$1);
|
|
241117
241220
|
if (!options.preset.cliAgent.command) {
|
|
241118
241221
|
yield* runClanka({
|
|
241119
241222
|
directory: worktree.directory,
|
|
241120
241223
|
model: options.preset.extraArgs.join(" "),
|
|
241121
|
-
system
|
|
241224
|
+
system,
|
|
241122
241225
|
prompt: match$10(customInstructions, {
|
|
241123
241226
|
onNone: () => promptGen.promptReview({
|
|
241124
241227
|
prompt: options.instructions,
|
|
@@ -241131,7 +241234,7 @@ const agentReviewer = fnUntraced(function* (options) {
|
|
|
241131
241234
|
})
|
|
241132
241235
|
}),
|
|
241133
241236
|
stallTimeout: options.stallTimeout,
|
|
241134
|
-
mode
|
|
241237
|
+
mode
|
|
241135
241238
|
});
|
|
241136
241239
|
return ExitCode(0);
|
|
241137
241240
|
}
|
|
@@ -241160,32 +241263,48 @@ const agentTimeout = fnUntraced(function* (options) {
|
|
|
241160
241263
|
const pathService = yield* Path$1;
|
|
241161
241264
|
const worktree = yield* Worktree;
|
|
241162
241265
|
const promptGen = yield* PromptGen;
|
|
241266
|
+
const timeoutMode = CurrentTask.$match(options.currentTask, {
|
|
241267
|
+
task: ({ task }) => ({
|
|
241268
|
+
mode: "default",
|
|
241269
|
+
system: promptGen.systemClanka(options),
|
|
241270
|
+
clankaPrompt: promptGen.promptTimeoutClanka({
|
|
241271
|
+
taskId: task.id,
|
|
241272
|
+
specsDirectory: options.specsDirectory
|
|
241273
|
+
}),
|
|
241274
|
+
cliPrompt: promptGen.promptTimeout({
|
|
241275
|
+
taskId: task.id,
|
|
241276
|
+
specsDirectory: options.specsDirectory
|
|
241277
|
+
}),
|
|
241278
|
+
prdFilePath: pathService.join(".lalph", "prd.yml")
|
|
241279
|
+
}),
|
|
241280
|
+
ralph: ({ task, specFile }) => ({
|
|
241281
|
+
mode: "ralph",
|
|
241282
|
+
system: void 0,
|
|
241283
|
+
clankaPrompt: promptGen.promptTimeoutRalph({
|
|
241284
|
+
task,
|
|
241285
|
+
specFile
|
|
241286
|
+
}),
|
|
241287
|
+
cliPrompt: promptGen.promptTimeoutRalph({
|
|
241288
|
+
task,
|
|
241289
|
+
specFile
|
|
241290
|
+
}),
|
|
241291
|
+
prdFilePath: void 0
|
|
241292
|
+
})
|
|
241293
|
+
});
|
|
241163
241294
|
if (!options.preset.cliAgent.command) {
|
|
241164
241295
|
yield* runClanka({
|
|
241165
241296
|
directory: worktree.directory,
|
|
241166
241297
|
model: options.preset.extraArgs.join(" "),
|
|
241167
|
-
system:
|
|
241168
|
-
prompt:
|
|
241169
|
-
task: options.task.task,
|
|
241170
|
-
specFile: options.task.specFile
|
|
241171
|
-
}) : promptGen.promptTimeoutClanka({
|
|
241172
|
-
taskId: options.task.task.id,
|
|
241173
|
-
specsDirectory: options.specsDirectory
|
|
241174
|
-
}),
|
|
241298
|
+
system: timeoutMode.system,
|
|
241299
|
+
prompt: timeoutMode.clankaPrompt,
|
|
241175
241300
|
stallTimeout: options.stallTimeout,
|
|
241176
|
-
mode:
|
|
241301
|
+
mode: timeoutMode.mode
|
|
241177
241302
|
});
|
|
241178
241303
|
return ExitCode(0);
|
|
241179
241304
|
}
|
|
241180
241305
|
return yield* pipe$1(options.preset.cliAgent.command({
|
|
241181
|
-
prompt:
|
|
241182
|
-
|
|
241183
|
-
specFile: options.task.specFile
|
|
241184
|
-
}) : promptGen.promptTimeout({
|
|
241185
|
-
taskId: options.task.task.id,
|
|
241186
|
-
specsDirectory: options.specsDirectory
|
|
241187
|
-
}),
|
|
241188
|
-
prdFilePath: options.task._tag === "ralph" ? void 0 : pathService.join(".lalph", "prd.yml"),
|
|
241306
|
+
prompt: timeoutMode.cliPrompt,
|
|
241307
|
+
prdFilePath: timeoutMode.prdFilePath,
|
|
241189
241308
|
extraArgs: options.preset.extraArgs
|
|
241190
241309
|
}), setCwd(worktree.directory), options.preset.withCommandPrefix).pipe(worktree.execWithStallTimeout({
|
|
241191
241310
|
cliAgent: options.preset.cliAgent,
|
|
@@ -241330,7 +241449,7 @@ const run = fnUntraced(function* (options) {
|
|
|
241330
241449
|
prompt: instructions,
|
|
241331
241450
|
research: researchResult,
|
|
241332
241451
|
steer,
|
|
241333
|
-
|
|
241452
|
+
currentTask: CurrentTask.task({ task: chosenTask.prd })
|
|
241334
241453
|
}).pipe(provideService$2(CurrentTaskRef, issueRef), catchStallInReview, withSpan$1("Main.agentWorker"))}`);
|
|
241335
241454
|
if (options.review) {
|
|
241336
241455
|
yield* source.updateIssue({
|
|
@@ -241344,7 +241463,7 @@ const run = fnUntraced(function* (options) {
|
|
|
241344
241463
|
stallTimeout: options.stallTimeout,
|
|
241345
241464
|
preset: taskPreset,
|
|
241346
241465
|
instructions,
|
|
241347
|
-
|
|
241466
|
+
currentTask: CurrentTask.task({ task: chosenTask.prd })
|
|
241348
241467
|
}).pipe(catchStallInReview, withSpan$1("Main.agentReviewer"));
|
|
241349
241468
|
yield* source.updateIssue({
|
|
241350
241469
|
projectId,
|
|
@@ -241356,10 +241475,7 @@ const run = fnUntraced(function* (options) {
|
|
|
241356
241475
|
specsDirectory: options.specsDirectory,
|
|
241357
241476
|
stallTimeout: options.stallTimeout,
|
|
241358
241477
|
preset: taskPreset,
|
|
241359
|
-
task:
|
|
241360
|
-
_tag: "task",
|
|
241361
|
-
task: chosenTask.prd
|
|
241362
|
-
}
|
|
241478
|
+
currentTask: CurrentTask.task({ task: chosenTask.prd })
|
|
241363
241479
|
})), 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;
|
|
241364
241480
|
yield* gitFlow.postWork({
|
|
241365
241481
|
worktree,
|
|
@@ -241409,7 +241525,10 @@ const runRalph = fnUntraced(function* (options) {
|
|
|
241409
241525
|
prompt: instructions,
|
|
241410
241526
|
research: researchResult,
|
|
241411
241527
|
maxContext: options.maxContext,
|
|
241412
|
-
|
|
241528
|
+
currentTask: CurrentTask.ralph({
|
|
241529
|
+
task: chosenTask,
|
|
241530
|
+
specFile: options.specFile
|
|
241531
|
+
})
|
|
241413
241532
|
}).pipe(withSpan$1("Main.worker"))}`);
|
|
241414
241533
|
if (options.review) {
|
|
241415
241534
|
registry.update(currentWorker.state, (s) => s.transitionTo(WorkerStatus.Reviewing({ issueId: "ralph" })));
|
|
@@ -241418,18 +241537,20 @@ const runRalph = fnUntraced(function* (options) {
|
|
|
241418
241537
|
stallTimeout: options.stallTimeout,
|
|
241419
241538
|
preset,
|
|
241420
241539
|
instructions,
|
|
241421
|
-
|
|
241540
|
+
currentTask: CurrentTask.ralph({
|
|
241541
|
+
task: chosenTask,
|
|
241542
|
+
specFile: options.specFile
|
|
241543
|
+
})
|
|
241422
241544
|
}).pipe(withSpan$1("Main.review"));
|
|
241423
241545
|
}
|
|
241424
241546
|
}).pipe(timeout(options.runTimeout), tapErrorTag("TimeoutError", () => agentTimeout({
|
|
241425
241547
|
specsDirectory: "",
|
|
241426
241548
|
stallTimeout: options.stallTimeout,
|
|
241427
241549
|
preset,
|
|
241428
|
-
|
|
241429
|
-
_tag: "ralph",
|
|
241550
|
+
currentTask: CurrentTask.ralph({
|
|
241430
241551
|
task: chosenTask,
|
|
241431
241552
|
specFile: options.specFile
|
|
241432
|
-
}
|
|
241553
|
+
})
|
|
241433
241554
|
})));
|
|
241434
241555
|
yield* gitFlow.postWork({
|
|
241435
241556
|
worktree,
|
|
@@ -241437,35 +241558,41 @@ const runRalph = fnUntraced(function* (options) {
|
|
|
241437
241558
|
issueId: ""
|
|
241438
241559
|
});
|
|
241439
241560
|
}, scoped$1, provide$1(SemanticSearchLayer.pipe(provideMerge([Prd.layerNoop, Worktree.layer])), { local: true }));
|
|
241561
|
+
var RalphSpecMissing = class extends TaggedError("RalphSpecMissing") {
|
|
241562
|
+
message = `Project "${this.projectId}" is configured with gitFlow="ralph" but is missing "ralphSpec". Run 'lalph projects edit' and set "Path to Ralph spec file".`;
|
|
241563
|
+
};
|
|
241440
241564
|
const runProject = fnUntraced(function* (options) {
|
|
241441
241565
|
const isFinite = Number.isFinite(options.iterations);
|
|
241442
241566
|
const iterationsDisplay = isFinite ? options.iterations : "unlimited";
|
|
241443
241567
|
const semaphore = makeUnsafe$9(options.project.concurrency);
|
|
241444
241568
|
const fibers = yield* make$54();
|
|
241445
|
-
|
|
241446
|
-
|
|
241447
|
-
|
|
241448
|
-
|
|
241449
|
-
|
|
241450
|
-
|
|
241451
|
-
|
|
241452
|
-
|
|
241453
|
-
|
|
241454
|
-
|
|
241455
|
-
|
|
241456
|
-
|
|
241457
|
-
|
|
241458
|
-
|
|
241459
|
-
|
|
241460
|
-
|
|
241569
|
+
let executionMode;
|
|
241570
|
+
if (options.project.gitFlow === "ralph") {
|
|
241571
|
+
if (!options.project.ralphSpec) return yield* new RalphSpecMissing({ projectId: options.project.id });
|
|
241572
|
+
executionMode = {
|
|
241573
|
+
_tag: "ralph",
|
|
241574
|
+
specFile: options.project.ralphSpec
|
|
241575
|
+
};
|
|
241576
|
+
} else executionMode = {
|
|
241577
|
+
_tag: "standard",
|
|
241578
|
+
gitFlow: options.project.gitFlow
|
|
241579
|
+
};
|
|
241580
|
+
const resolveGitFlowLayer = () => {
|
|
241581
|
+
if (executionMode._tag === "ralph") return GitFlowRalph;
|
|
241582
|
+
if (executionMode.gitFlow === "commit") return GitFlowCommit;
|
|
241583
|
+
return GitFlowPR;
|
|
241584
|
+
};
|
|
241585
|
+
const resolveRunEffect = (startedDeferred) => {
|
|
241586
|
+
if (executionMode._tag === "ralph") return runRalph({
|
|
241461
241587
|
targetBranch: options.project.targetBranch,
|
|
241462
241588
|
stallTimeout: options.stallTimeout,
|
|
241463
241589
|
runTimeout: options.runTimeout,
|
|
241464
|
-
maxContext: options.maxContext,
|
|
241465
241590
|
review: options.project.reviewAgent,
|
|
241466
241591
|
research: options.project.researchAgent,
|
|
241467
|
-
specFile:
|
|
241468
|
-
|
|
241592
|
+
specFile: executionMode.specFile,
|
|
241593
|
+
maxContext: options.maxContext
|
|
241594
|
+
});
|
|
241595
|
+
return run({
|
|
241469
241596
|
startedDeferred,
|
|
241470
241597
|
targetBranch: options.project.targetBranch,
|
|
241471
241598
|
specsDirectory: options.specsDirectory,
|
|
@@ -241473,27 +241600,48 @@ const runProject = fnUntraced(function* (options) {
|
|
|
241473
241600
|
runTimeout: options.runTimeout,
|
|
241474
241601
|
review: options.project.reviewAgent,
|
|
241475
241602
|
research: options.project.researchAgent
|
|
241476
|
-
})
|
|
241603
|
+
});
|
|
241604
|
+
};
|
|
241605
|
+
const handleNoMoreWork = (currentIteration, setIterations) => {
|
|
241606
|
+
if (executionMode._tag === "ralph") return void_$2;
|
|
241607
|
+
if (isFinite) {
|
|
241608
|
+
setIterations(currentIteration);
|
|
241609
|
+
return log$1(`No more work to process, ending after ${currentIteration} iteration(s).`);
|
|
241610
|
+
}
|
|
241611
|
+
return andThen(size$3(fibers) <= 1 ? log$1("No more work to process, waiting 30 seconds...") : void_$2, sleep(seconds(30)));
|
|
241612
|
+
};
|
|
241613
|
+
yield* resetInProgress.pipe(withSpan$1("Main.resetInProgress"));
|
|
241614
|
+
yield* log$1(`Executing ${iterationsDisplay} iteration(s) with concurrency ${options.project.concurrency}`);
|
|
241615
|
+
let iterations = options.iterations;
|
|
241616
|
+
let iteration = 0;
|
|
241617
|
+
let quit = false;
|
|
241618
|
+
yield* mount(activeWorkerLoggingAtom);
|
|
241619
|
+
while (true) {
|
|
241620
|
+
yield* semaphore.take(1);
|
|
241621
|
+
if (quit || isFinite && iteration >= iterations) break;
|
|
241622
|
+
const currentIteration = iteration;
|
|
241623
|
+
const startedDeferred = yield* make$85();
|
|
241624
|
+
let ralphDone = false;
|
|
241625
|
+
const gitFlowLayer = resolveGitFlowLayer();
|
|
241626
|
+
const fiber = yield* checkForWork(options.project).pipe(andThen(resolveRunEffect(startedDeferred).pipe(provide$1(gitFlowLayer, { local: true }), withWorkerState(options.project.id))), catchTags$1({
|
|
241477
241627
|
ChosenTaskNotFound(_error) {
|
|
241478
|
-
if (
|
|
241628
|
+
if (executionMode._tag !== "ralph") {
|
|
241479
241629
|
ralphDone = true;
|
|
241480
|
-
return
|
|
241630
|
+
return void_$2;
|
|
241481
241631
|
}
|
|
241482
|
-
return
|
|
241632
|
+
return log$1(`No more work to process for Ralph, ending after ${currentIteration + 1} iteration(s).`);
|
|
241483
241633
|
},
|
|
241484
241634
|
NoMoreWork(_error) {
|
|
241485
|
-
|
|
241486
|
-
iterations =
|
|
241487
|
-
|
|
241488
|
-
}
|
|
241489
|
-
return andThen(size$3(fibers) <= 1 ? log$1("No more work to process, waiting 30 seconds...") : void_$2, sleep(seconds(30)));
|
|
241635
|
+
return handleNoMoreWork(currentIteration, (newIterations) => {
|
|
241636
|
+
iterations = newIterations;
|
|
241637
|
+
});
|
|
241490
241638
|
},
|
|
241491
241639
|
QuitError(_error) {
|
|
241492
241640
|
quit = true;
|
|
241493
241641
|
return void_$2;
|
|
241494
241642
|
}
|
|
241495
241643
|
}), catchCause$1((cause) => logWarning(cause).pipe(andThen(sleep(seconds(10))))), ensuring$2(semaphore.release(1)), ensuring$2(completeWith(startedDeferred, void_$2)), run$2(fibers));
|
|
241496
|
-
if (
|
|
241644
|
+
if (executionMode._tag === "ralph") {
|
|
241497
241645
|
yield* await_(fiber);
|
|
241498
241646
|
if (ralphDone) break;
|
|
241499
241647
|
} else yield* _await(startedDeferred);
|
|
@@ -241844,7 +241992,7 @@ const commandEdit = make$58("edit").pipe(withDescription("Open the selected proj
|
|
|
241844
241992
|
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));
|
|
241845
241993
|
//#endregion
|
|
241846
241994
|
//#region package.json
|
|
241847
|
-
var version = "0.3.
|
|
241995
|
+
var version = "0.3.91";
|
|
241848
241996
|
//#endregion
|
|
241849
241997
|
//#region src/commands/projects/ls.ts
|
|
241850
241998
|
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* () {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lalph",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.91",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
|
46
46
|
"@octokit/types": "^16.0.0",
|
|
47
47
|
"@typescript/native-preview": "7.0.0-dev.20260319.1",
|
|
48
|
-
"clanka": "^0.2.
|
|
48
|
+
"clanka": "^0.2.19",
|
|
49
49
|
"concurrently": "^9.2.1",
|
|
50
50
|
"effect": "https://pkg.pr.new/Effect-TS/effect-smol/effect@89c3e98",
|
|
51
51
|
"husky": "^9.1.7",
|
package/src/Agents/reviewer.ts
CHANGED
|
@@ -6,13 +6,14 @@ import { GitFlow } from "../GitFlow.ts"
|
|
|
6
6
|
import type { CliAgentPreset } from "../domain/CliAgentPreset.ts"
|
|
7
7
|
import { ExitCode } from "effect/unstable/process/ChildProcessSpawner"
|
|
8
8
|
import { runClanka } from "../Clanka.ts"
|
|
9
|
+
import { CurrentTask } from "../domain/CurrentTask.ts"
|
|
9
10
|
|
|
10
11
|
export const agentReviewer = Effect.fnUntraced(function* (options: {
|
|
11
12
|
readonly specsDirectory: string
|
|
12
13
|
readonly stallTimeout: Duration.Duration
|
|
13
14
|
readonly preset: CliAgentPreset
|
|
14
15
|
readonly instructions: string
|
|
15
|
-
readonly
|
|
16
|
+
readonly currentTask: CurrentTask
|
|
16
17
|
}) {
|
|
17
18
|
const fs = yield* FileSystem.FileSystem
|
|
18
19
|
const pathService = yield* Path.Path
|
|
@@ -20,6 +21,16 @@ export const agentReviewer = Effect.fnUntraced(function* (options: {
|
|
|
20
21
|
const promptGen = yield* PromptGen
|
|
21
22
|
const gitFlow = yield* GitFlow
|
|
22
23
|
|
|
24
|
+
const mode = CurrentTask.$match(options.currentTask, {
|
|
25
|
+
task: () => "default" as const,
|
|
26
|
+
ralph: () => "ralph" as const,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const system = CurrentTask.$match(options.currentTask, {
|
|
30
|
+
task: () => promptGen.systemClanka(options),
|
|
31
|
+
ralph: () => undefined,
|
|
32
|
+
})
|
|
33
|
+
|
|
23
34
|
const customInstructions = yield* pipe(
|
|
24
35
|
fs.readFileString(pathService.join(worktree.directory, "LALPH_REVIEW.md")),
|
|
25
36
|
Effect.option,
|
|
@@ -30,7 +41,7 @@ export const agentReviewer = Effect.fnUntraced(function* (options: {
|
|
|
30
41
|
yield* runClanka({
|
|
31
42
|
directory: worktree.directory,
|
|
32
43
|
model: options.preset.extraArgs.join(" "),
|
|
33
|
-
system
|
|
44
|
+
system,
|
|
34
45
|
prompt: Option.match(customInstructions, {
|
|
35
46
|
onNone: () =>
|
|
36
47
|
promptGen.promptReview({
|
|
@@ -45,7 +56,7 @@ export const agentReviewer = Effect.fnUntraced(function* (options: {
|
|
|
45
56
|
}),
|
|
46
57
|
}),
|
|
47
58
|
stallTimeout: options.stallTimeout,
|
|
48
|
-
mode
|
|
59
|
+
mode,
|
|
49
60
|
})
|
|
50
61
|
return ExitCode(0)
|
|
51
62
|
}
|
package/src/Agents/timeout.ts
CHANGED
|
@@ -2,71 +2,61 @@ import { Duration, Effect, Path, pipe } from "effect"
|
|
|
2
2
|
import { PromptGen } from "../PromptGen.ts"
|
|
3
3
|
import { ChildProcess } from "effect/unstable/process"
|
|
4
4
|
import { Worktree } from "../Worktree.ts"
|
|
5
|
-
import type { PrdIssue } from "../domain/PrdIssue.ts"
|
|
6
5
|
import type { CliAgentPreset } from "../domain/CliAgentPreset.ts"
|
|
7
6
|
import { ExitCode } from "effect/unstable/process/ChildProcessSpawner"
|
|
8
7
|
import { runClanka } from "../Clanka.ts"
|
|
8
|
+
import { CurrentTask } from "../domain/CurrentTask.ts"
|
|
9
9
|
|
|
10
10
|
export const agentTimeout = Effect.fnUntraced(function* (options: {
|
|
11
11
|
readonly specsDirectory: string
|
|
12
12
|
readonly stallTimeout: Duration.Duration
|
|
13
13
|
readonly preset: CliAgentPreset
|
|
14
|
-
readonly
|
|
15
|
-
| {
|
|
16
|
-
readonly _tag: "task"
|
|
17
|
-
readonly task: PrdIssue
|
|
18
|
-
}
|
|
19
|
-
| {
|
|
20
|
-
readonly _tag: "ralph"
|
|
21
|
-
readonly task: string
|
|
22
|
-
readonly specFile: string
|
|
23
|
-
}
|
|
14
|
+
readonly currentTask: CurrentTask
|
|
24
15
|
}) {
|
|
25
16
|
const pathService = yield* Path.Path
|
|
26
17
|
const worktree = yield* Worktree
|
|
27
18
|
const promptGen = yield* PromptGen
|
|
28
19
|
|
|
20
|
+
const timeoutMode = CurrentTask.$match(options.currentTask, {
|
|
21
|
+
task: ({ task }) => ({
|
|
22
|
+
mode: "default" as const,
|
|
23
|
+
system: promptGen.systemClanka(options),
|
|
24
|
+
clankaPrompt: promptGen.promptTimeoutClanka({
|
|
25
|
+
taskId: task.id!,
|
|
26
|
+
specsDirectory: options.specsDirectory,
|
|
27
|
+
}),
|
|
28
|
+
cliPrompt: promptGen.promptTimeout({
|
|
29
|
+
taskId: task.id!,
|
|
30
|
+
specsDirectory: options.specsDirectory,
|
|
31
|
+
}),
|
|
32
|
+
prdFilePath: pathService.join(".lalph", "prd.yml"),
|
|
33
|
+
}),
|
|
34
|
+
ralph: ({ task, specFile }) => ({
|
|
35
|
+
mode: "ralph" as const,
|
|
36
|
+
system: undefined,
|
|
37
|
+
clankaPrompt: promptGen.promptTimeoutRalph({ task, specFile }),
|
|
38
|
+
cliPrompt: promptGen.promptTimeoutRalph({ task, specFile }),
|
|
39
|
+
prdFilePath: undefined,
|
|
40
|
+
}),
|
|
41
|
+
})
|
|
42
|
+
|
|
29
43
|
// use clanka
|
|
30
44
|
if (!options.preset.cliAgent.command) {
|
|
31
45
|
yield* runClanka({
|
|
32
46
|
directory: worktree.directory,
|
|
33
47
|
model: options.preset.extraArgs.join(" "),
|
|
34
|
-
system:
|
|
35
|
-
|
|
36
|
-
? undefined
|
|
37
|
-
: promptGen.systemClanka(options),
|
|
38
|
-
prompt:
|
|
39
|
-
options.task._tag === "ralph"
|
|
40
|
-
? promptGen.promptTimeoutRalph({
|
|
41
|
-
task: options.task.task,
|
|
42
|
-
specFile: options.task.specFile,
|
|
43
|
-
})
|
|
44
|
-
: promptGen.promptTimeoutClanka({
|
|
45
|
-
taskId: options.task.task.id!,
|
|
46
|
-
specsDirectory: options.specsDirectory,
|
|
47
|
-
}),
|
|
48
|
+
system: timeoutMode.system,
|
|
49
|
+
prompt: timeoutMode.clankaPrompt,
|
|
48
50
|
stallTimeout: options.stallTimeout,
|
|
49
|
-
mode:
|
|
51
|
+
mode: timeoutMode.mode,
|
|
50
52
|
})
|
|
51
53
|
return ExitCode(0)
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
const timeoutCommand = pipe(
|
|
55
57
|
options.preset.cliAgent.command({
|
|
56
|
-
prompt:
|
|
57
|
-
|
|
58
|
-
? promptGen.promptTimeoutRalph({
|
|
59
|
-
task: options.task.task,
|
|
60
|
-
specFile: options.task.specFile,
|
|
61
|
-
})
|
|
62
|
-
: promptGen.promptTimeout({
|
|
63
|
-
taskId: options.task.task.id!,
|
|
64
|
-
specsDirectory: options.specsDirectory,
|
|
65
|
-
}),
|
|
66
|
-
prdFilePath:
|
|
67
|
-
options.task._tag === "ralph"
|
|
68
|
-
? undefined
|
|
69
|
-
: pathService.join(".lalph", "prd.yml"),
|
|
58
|
+
prompt: timeoutMode.cliPrompt,
|
|
59
|
+
prdFilePath: timeoutMode.prdFilePath,
|
|
70
60
|
extraArgs: options.preset.extraArgs,
|
|
71
61
|
}),
|
|
72
62
|
ChildProcess.setCwd(worktree.directory),
|
package/src/Agents/worker.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { CliAgentPreset } from "../domain/CliAgentPreset.ts"
|
|
|
5
5
|
import { runClanka } from "../Clanka.ts"
|
|
6
6
|
import { ExitCode } from "effect/unstable/process/ChildProcessSpawner"
|
|
7
7
|
import { Prompt } from "effect/unstable/ai"
|
|
8
|
+
import { CurrentTask } from "../domain/CurrentTask.ts"
|
|
8
9
|
|
|
9
10
|
export const agentWorker = Effect.fnUntraced(function* (options: {
|
|
10
11
|
readonly stallTimeout: Duration.Duration
|
|
@@ -14,11 +15,16 @@ export const agentWorker = Effect.fnUntraced(function* (options: {
|
|
|
14
15
|
readonly research: Option.Option<string>
|
|
15
16
|
readonly steer?: Stream.Stream<string>
|
|
16
17
|
readonly maxContext?: number | undefined
|
|
17
|
-
readonly
|
|
18
|
+
readonly currentTask: CurrentTask
|
|
18
19
|
}) {
|
|
19
20
|
const pathService = yield* Path.Path
|
|
20
21
|
const worktree = yield* Worktree
|
|
21
22
|
|
|
23
|
+
const prdFilePath = CurrentTask.$match(options.currentTask, {
|
|
24
|
+
task: () => pathService.join(".lalph", "prd.yml"),
|
|
25
|
+
ralph: () => undefined,
|
|
26
|
+
})
|
|
27
|
+
|
|
22
28
|
// use clanka
|
|
23
29
|
if (!options.preset.cliAgent.command) {
|
|
24
30
|
yield* runClanka({
|
|
@@ -45,7 +51,10 @@ ${research}`,
|
|
|
45
51
|
stallTimeout: options.stallTimeout,
|
|
46
52
|
maxContext: options.maxContext,
|
|
47
53
|
steer: options.steer,
|
|
48
|
-
mode: options.
|
|
54
|
+
mode: CurrentTask.$match(options.currentTask, {
|
|
55
|
+
task: () => "default" as const,
|
|
56
|
+
ralph: () => "ralph" as const,
|
|
57
|
+
}),
|
|
49
58
|
})
|
|
50
59
|
return ExitCode(0)
|
|
51
60
|
}
|
|
@@ -53,9 +62,7 @@ ${research}`,
|
|
|
53
62
|
const cliCommand = pipe(
|
|
54
63
|
options.preset.cliAgent.command({
|
|
55
64
|
prompt: options.prompt,
|
|
56
|
-
prdFilePath
|
|
57
|
-
? undefined
|
|
58
|
-
: pathService.join(".lalph", "prd.yml"),
|
|
65
|
+
prdFilePath,
|
|
59
66
|
extraArgs: options.preset.extraArgs,
|
|
60
67
|
}),
|
|
61
68
|
ChildProcess.setCwd(worktree.directory),
|
package/src/Clanka.ts
CHANGED
package/src/commands/root.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Config,
|
|
3
|
+
Data,
|
|
3
4
|
Deferred,
|
|
4
5
|
Duration,
|
|
5
6
|
Effect,
|
|
@@ -18,7 +19,6 @@ import {
|
|
|
18
19
|
Scope,
|
|
19
20
|
Semaphore,
|
|
20
21
|
Stream,
|
|
21
|
-
Unify,
|
|
22
22
|
} from "effect"
|
|
23
23
|
import { PromptGen } from "../PromptGen.ts"
|
|
24
24
|
import { Prd } from "../Prd.ts"
|
|
@@ -66,6 +66,7 @@ import type { OutputFormatter } from "clanka"
|
|
|
66
66
|
import { ClankaMuxerLayer, SemanticSearchLayer } from "../Clanka.ts"
|
|
67
67
|
import { agentResearcher } from "../Agents/researcher.ts"
|
|
68
68
|
import { agentChooserRalph } from "../Agents/chooserRalph.ts"
|
|
69
|
+
import { CurrentTask } from "../domain/CurrentTask.ts"
|
|
69
70
|
|
|
70
71
|
// Main iteration run logic
|
|
71
72
|
|
|
@@ -268,7 +269,7 @@ const run = Effect.fnUntraced(
|
|
|
268
269
|
prompt: instructions,
|
|
269
270
|
research: researchResult,
|
|
270
271
|
steer,
|
|
271
|
-
|
|
272
|
+
currentTask: CurrentTask.task({ task: chosenTask.prd }),
|
|
272
273
|
}).pipe(
|
|
273
274
|
Effect.provideService(CurrentTaskRef, issueRef),
|
|
274
275
|
catchStallInReview,
|
|
@@ -295,7 +296,7 @@ const run = Effect.fnUntraced(
|
|
|
295
296
|
stallTimeout: options.stallTimeout,
|
|
296
297
|
preset: taskPreset,
|
|
297
298
|
instructions,
|
|
298
|
-
|
|
299
|
+
currentTask: CurrentTask.task({ task: chosenTask.prd }),
|
|
299
300
|
}).pipe(catchStallInReview, Effect.withSpan("Main.agentReviewer"))
|
|
300
301
|
|
|
301
302
|
yield* source.updateIssue({
|
|
@@ -311,7 +312,7 @@ const run = Effect.fnUntraced(
|
|
|
311
312
|
specsDirectory: options.specsDirectory,
|
|
312
313
|
stallTimeout: options.stallTimeout,
|
|
313
314
|
preset: taskPreset,
|
|
314
|
-
|
|
315
|
+
currentTask: CurrentTask.task({ task: chosenTask.prd }),
|
|
315
316
|
}),
|
|
316
317
|
),
|
|
317
318
|
Effect.raceFirst(watchTaskState({ issueId: taskId })),
|
|
@@ -470,7 +471,10 @@ const runRalph = Effect.fnUntraced(
|
|
|
470
471
|
prompt: instructions,
|
|
471
472
|
research: researchResult,
|
|
472
473
|
maxContext: options.maxContext,
|
|
473
|
-
|
|
474
|
+
currentTask: CurrentTask.ralph({
|
|
475
|
+
task: chosenTask,
|
|
476
|
+
specFile: options.specFile,
|
|
477
|
+
}),
|
|
474
478
|
}).pipe(Effect.withSpan("Main.worker"))
|
|
475
479
|
yield* Effect.log(`Agent exited with code: ${exitCode}`)
|
|
476
480
|
|
|
@@ -487,7 +491,10 @@ const runRalph = Effect.fnUntraced(
|
|
|
487
491
|
stallTimeout: options.stallTimeout,
|
|
488
492
|
preset,
|
|
489
493
|
instructions,
|
|
490
|
-
|
|
494
|
+
currentTask: CurrentTask.ralph({
|
|
495
|
+
task: chosenTask,
|
|
496
|
+
specFile: options.specFile,
|
|
497
|
+
}),
|
|
491
498
|
}).pipe(Effect.withSpan("Main.review"))
|
|
492
499
|
}
|
|
493
500
|
}).pipe(
|
|
@@ -497,7 +504,10 @@ const runRalph = Effect.fnUntraced(
|
|
|
497
504
|
specsDirectory: "",
|
|
498
505
|
stallTimeout: options.stallTimeout,
|
|
499
506
|
preset,
|
|
500
|
-
|
|
507
|
+
currentTask: CurrentTask.ralph({
|
|
508
|
+
task: chosenTask,
|
|
509
|
+
specFile: options.specFile,
|
|
510
|
+
}),
|
|
501
511
|
}),
|
|
502
512
|
),
|
|
503
513
|
)
|
|
@@ -517,6 +527,22 @@ const runRalph = Effect.fnUntraced(
|
|
|
517
527
|
),
|
|
518
528
|
)
|
|
519
529
|
|
|
530
|
+
class RalphSpecMissing extends Data.TaggedError("RalphSpecMissing")<{
|
|
531
|
+
readonly projectId: Project["id"]
|
|
532
|
+
}> {
|
|
533
|
+
readonly message = `Project "${this.projectId}" is configured with gitFlow="ralph" but is missing "ralphSpec". Run 'lalph projects edit' and set "Path to Ralph spec file".`
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
type ProjectExecutionMode =
|
|
537
|
+
| {
|
|
538
|
+
readonly _tag: "standard"
|
|
539
|
+
readonly gitFlow: "pr" | "commit"
|
|
540
|
+
}
|
|
541
|
+
| {
|
|
542
|
+
readonly _tag: "ralph"
|
|
543
|
+
readonly specFile: string
|
|
544
|
+
}
|
|
545
|
+
|
|
520
546
|
const runProject = Effect.fnUntraced(
|
|
521
547
|
function* (options: {
|
|
522
548
|
readonly iterations: number
|
|
@@ -531,6 +557,79 @@ const runProject = Effect.fnUntraced(
|
|
|
531
557
|
const semaphore = Semaphore.makeUnsafe(options.project.concurrency)
|
|
532
558
|
const fibers = yield* FiberSet.make()
|
|
533
559
|
|
|
560
|
+
let executionMode: ProjectExecutionMode
|
|
561
|
+
if (options.project.gitFlow === "ralph") {
|
|
562
|
+
if (!options.project.ralphSpec) {
|
|
563
|
+
return yield* new RalphSpecMissing({
|
|
564
|
+
projectId: options.project.id,
|
|
565
|
+
})
|
|
566
|
+
}
|
|
567
|
+
executionMode = {
|
|
568
|
+
_tag: "ralph",
|
|
569
|
+
specFile: options.project.ralphSpec,
|
|
570
|
+
}
|
|
571
|
+
} else {
|
|
572
|
+
executionMode = {
|
|
573
|
+
_tag: "standard",
|
|
574
|
+
gitFlow: options.project.gitFlow,
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
const resolveGitFlowLayer = () => {
|
|
579
|
+
if (executionMode._tag === "ralph") {
|
|
580
|
+
return GitFlowRalph
|
|
581
|
+
}
|
|
582
|
+
if (executionMode.gitFlow === "commit") {
|
|
583
|
+
return GitFlowCommit
|
|
584
|
+
}
|
|
585
|
+
return GitFlowPR
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const resolveRunEffect = (startedDeferred: Deferred.Deferred<void>) => {
|
|
589
|
+
if (executionMode._tag === "ralph") {
|
|
590
|
+
return runRalph({
|
|
591
|
+
targetBranch: options.project.targetBranch,
|
|
592
|
+
stallTimeout: options.stallTimeout,
|
|
593
|
+
runTimeout: options.runTimeout,
|
|
594
|
+
review: options.project.reviewAgent,
|
|
595
|
+
research: options.project.researchAgent,
|
|
596
|
+
specFile: executionMode.specFile,
|
|
597
|
+
maxContext: options.maxContext,
|
|
598
|
+
})
|
|
599
|
+
}
|
|
600
|
+
return run({
|
|
601
|
+
startedDeferred,
|
|
602
|
+
targetBranch: options.project.targetBranch,
|
|
603
|
+
specsDirectory: options.specsDirectory,
|
|
604
|
+
stallTimeout: options.stallTimeout,
|
|
605
|
+
runTimeout: options.runTimeout,
|
|
606
|
+
review: options.project.reviewAgent,
|
|
607
|
+
research: options.project.researchAgent,
|
|
608
|
+
})
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
const handleNoMoreWork = (
|
|
612
|
+
currentIteration: number,
|
|
613
|
+
setIterations: (iterations: number) => void,
|
|
614
|
+
) => {
|
|
615
|
+
if (executionMode._tag === "ralph") {
|
|
616
|
+
return Effect.void
|
|
617
|
+
}
|
|
618
|
+
if (isFinite) {
|
|
619
|
+
// If we have a finite number of iterations, we exit when no more
|
|
620
|
+
// work is found
|
|
621
|
+
setIterations(currentIteration)
|
|
622
|
+
return Effect.log(
|
|
623
|
+
`No more work to process, ending after ${currentIteration} iteration(s).`,
|
|
624
|
+
)
|
|
625
|
+
}
|
|
626
|
+
const log =
|
|
627
|
+
Iterable.size(fibers) <= 1
|
|
628
|
+
? Effect.log("No more work to process, waiting 30 seconds...")
|
|
629
|
+
: Effect.void
|
|
630
|
+
return Effect.andThen(log, Effect.sleep(Duration.seconds(30)))
|
|
631
|
+
}
|
|
632
|
+
|
|
534
633
|
yield* resetInProgress.pipe(Effect.withSpan("Main.resetInProgress"))
|
|
535
634
|
|
|
536
635
|
yield* Effect.log(
|
|
@@ -554,65 +653,28 @@ const runProject = Effect.fnUntraced(
|
|
|
554
653
|
const startedDeferred = yield* Deferred.make<void>()
|
|
555
654
|
let ralphDone = false
|
|
556
655
|
|
|
557
|
-
const
|
|
558
|
-
const isRalph = gitFlow === "ralph"
|
|
559
|
-
const gitFlowLayer =
|
|
560
|
-
gitFlow === "commit"
|
|
561
|
-
? GitFlowCommit
|
|
562
|
-
: gitFlow === "ralph"
|
|
563
|
-
? GitFlowRalph
|
|
564
|
-
: GitFlowPR
|
|
656
|
+
const gitFlowLayer = resolveGitFlowLayer()
|
|
565
657
|
const fiber = yield* checkForWork(options.project).pipe(
|
|
566
658
|
Effect.andThen(
|
|
567
|
-
|
|
568
|
-
isRalph
|
|
569
|
-
? runRalph({
|
|
570
|
-
targetBranch: options.project.targetBranch,
|
|
571
|
-
stallTimeout: options.stallTimeout,
|
|
572
|
-
runTimeout: options.runTimeout,
|
|
573
|
-
maxContext: options.maxContext,
|
|
574
|
-
review: options.project.reviewAgent,
|
|
575
|
-
research: options.project.researchAgent,
|
|
576
|
-
specFile: options.project.ralphSpec!,
|
|
577
|
-
})
|
|
578
|
-
: run({
|
|
579
|
-
startedDeferred,
|
|
580
|
-
targetBranch: options.project.targetBranch,
|
|
581
|
-
specsDirectory: options.specsDirectory,
|
|
582
|
-
stallTimeout: options.stallTimeout,
|
|
583
|
-
runTimeout: options.runTimeout,
|
|
584
|
-
review: options.project.reviewAgent,
|
|
585
|
-
research: options.project.researchAgent,
|
|
586
|
-
}),
|
|
587
|
-
).pipe(
|
|
659
|
+
resolveRunEffect(startedDeferred).pipe(
|
|
588
660
|
Effect.provide(gitFlowLayer, { local: true }),
|
|
589
661
|
withWorkerState(options.project.id),
|
|
590
662
|
),
|
|
591
663
|
),
|
|
592
664
|
Effect.catchTags({
|
|
593
665
|
ChosenTaskNotFound(_error) {
|
|
594
|
-
if (
|
|
666
|
+
if (executionMode._tag !== "ralph") {
|
|
595
667
|
ralphDone = true
|
|
596
|
-
return Effect.
|
|
597
|
-
`No more work to process for Ralph, ending after ${currentIteration + 1} iteration(s).`,
|
|
598
|
-
)
|
|
668
|
+
return Effect.void
|
|
599
669
|
}
|
|
600
|
-
return Effect.
|
|
670
|
+
return Effect.log(
|
|
671
|
+
`No more work to process for Ralph, ending after ${currentIteration + 1} iteration(s).`,
|
|
672
|
+
)
|
|
601
673
|
},
|
|
602
674
|
NoMoreWork(_error) {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
iterations = currentIteration
|
|
607
|
-
return Effect.log(
|
|
608
|
-
`No more work to process, ending after ${currentIteration} iteration(s).`,
|
|
609
|
-
)
|
|
610
|
-
}
|
|
611
|
-
const log =
|
|
612
|
-
Iterable.size(fibers) <= 1
|
|
613
|
-
? Effect.log("No more work to process, waiting 30 seconds...")
|
|
614
|
-
: Effect.void
|
|
615
|
-
return Effect.andThen(log, Effect.sleep(Duration.seconds(30)))
|
|
675
|
+
return handleNoMoreWork(currentIteration, (newIterations) => {
|
|
676
|
+
iterations = newIterations
|
|
677
|
+
})
|
|
616
678
|
},
|
|
617
679
|
QuitError(_error) {
|
|
618
680
|
quit = true
|
|
@@ -628,12 +690,14 @@ const runProject = Effect.fnUntraced(
|
|
|
628
690
|
Effect.ensuring(Deferred.completeWith(startedDeferred, Effect.void)),
|
|
629
691
|
FiberSet.run(fibers),
|
|
630
692
|
)
|
|
631
|
-
|
|
693
|
+
|
|
694
|
+
if (executionMode._tag === "ralph") {
|
|
632
695
|
yield* Fiber.await(fiber)
|
|
633
696
|
if (ralphDone) break
|
|
634
697
|
} else {
|
|
635
698
|
yield* Deferred.await(startedDeferred)
|
|
636
699
|
}
|
|
700
|
+
|
|
637
701
|
iteration++
|
|
638
702
|
}
|
|
639
703
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Data } from "effect"
|
|
2
|
+
import type { PrdIssue } from "./PrdIssue.ts"
|
|
3
|
+
|
|
4
|
+
export type CurrentTask = Data.TaggedEnum<{
|
|
5
|
+
task: {
|
|
6
|
+
readonly task: PrdIssue
|
|
7
|
+
}
|
|
8
|
+
ralph: {
|
|
9
|
+
readonly task: string
|
|
10
|
+
readonly specFile: string
|
|
11
|
+
}
|
|
12
|
+
}>
|
|
13
|
+
|
|
14
|
+
export const CurrentTask = Data.taggedEnum<CurrentTask>()
|