lalph 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +27 -4
- package/package.json +1 -1
- package/src/commands/root.ts +47 -2
- package/src/domain/Errors.ts +8 -0
- package/src/domain/LinearIssues.ts +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -144005,7 +144005,11 @@ var IssuesNode = class extends Class("IssuesNode")({
|
|
|
144005
144005
|
}) {
|
|
144006
144006
|
blockedBy = this.inverseRelations.nodes.filter((relation) => relation.type === "blocks" && incompleteStates.has(relation.issue.state.type));
|
|
144007
144007
|
};
|
|
144008
|
-
const incompleteStates = new Set([
|
|
144008
|
+
const incompleteStates = new Set([
|
|
144009
|
+
"backlog",
|
|
144010
|
+
"unstarted",
|
|
144011
|
+
"started"
|
|
144012
|
+
]);
|
|
144009
144013
|
const LinearIssueData = Struct({ issue: IssuesNode });
|
|
144010
144014
|
var Issues = class extends Class("Issues")({ nodes: Array$1(IssuesNode) }) {};
|
|
144011
144015
|
var LinearIssuesData = class extends Class("LinearIssuesData")({ issues: Issues }) {};
|
|
@@ -151442,6 +151446,9 @@ ${prdNotes(options)}`;
|
|
|
151442
151446
|
var RunnerStalled = class extends TaggedError("RunnerStalled") {
|
|
151443
151447
|
message = "The runner has stalled due to inactivity.";
|
|
151444
151448
|
};
|
|
151449
|
+
var TaskStateChanged = class extends TaggedError("TaskStateChanged") {
|
|
151450
|
+
message = `Task "${this.issueId}" moved to "${this.state}", cancelling run.`;
|
|
151451
|
+
};
|
|
151445
151452
|
|
|
151446
151453
|
//#endregion
|
|
151447
151454
|
//#region src/domain/WorkerState.ts
|
|
@@ -152196,7 +152203,7 @@ const run = fnUntraced(function* (options) {
|
|
|
152196
152203
|
yield* fs.writeFileString(pathService.join(worktree.directory, ".lalph", "feedback.md"), feedback);
|
|
152197
152204
|
}
|
|
152198
152205
|
const taskPreset = getOrElse$1(yield* source.issueCliAgentPreset(chosenTask.prd), () => preset);
|
|
152199
|
-
yield* gen(function* () {
|
|
152206
|
+
if (yield* gen(function* () {
|
|
152200
152207
|
registry.update(currentWorker.state, (s) => s.transitionTo(WorkerStatus.Working({ issueId: taskId })));
|
|
152201
152208
|
const instructions = (yield* PromptGen).prompt({
|
|
152202
152209
|
specsDirectory: options.specsDirectory,
|
|
@@ -152225,7 +152232,7 @@ const run = fnUntraced(function* (options) {
|
|
|
152225
152232
|
stallTimeout: options.stallTimeout,
|
|
152226
152233
|
preset: taskPreset,
|
|
152227
152234
|
task: chosenTask.prd
|
|
152228
|
-
})));
|
|
152235
|
+
})), raceFirst(watchTaskState({ issueId: taskId })), as(false), catchTag("TaskStateChanged", (error) => log$1(`Task ${error.issueId} moved to ${error.state}; cancelling run.`).pipe(as(true))))) return;
|
|
152229
152236
|
yield* gitFlow.postWork({
|
|
152230
152237
|
worktree,
|
|
152231
152238
|
targetBranch: getOrUndefined(options.targetBranch),
|
|
@@ -152318,6 +152325,22 @@ const commandRoot = make$35("lalph", {
|
|
|
152318
152325
|
layer,
|
|
152319
152326
|
layer$17
|
|
152320
152327
|
]))));
|
|
152328
|
+
const watchTaskState = fnUntraced(function* (options) {
|
|
152329
|
+
const registry = yield* AtomRegistry;
|
|
152330
|
+
const projectId = yield* CurrentProjectId;
|
|
152331
|
+
return yield* toStreamResult(registry, currentIssuesAtom(projectId)).pipe(runForEach((issues) => {
|
|
152332
|
+
const issue = issues.find((entry) => entry.id === options.issueId);
|
|
152333
|
+
if (!issue) return fail$4(new TaskStateChanged({
|
|
152334
|
+
issueId: options.issueId,
|
|
152335
|
+
state: "missing"
|
|
152336
|
+
}));
|
|
152337
|
+
if (issue.state === "in-progress" || issue.state === "in-review") return void_$1;
|
|
152338
|
+
return fail$4(new TaskStateChanged({
|
|
152339
|
+
issueId: options.issueId,
|
|
152340
|
+
state: issue.state
|
|
152341
|
+
}));
|
|
152342
|
+
}), withSpan("Main.watchTaskState"));
|
|
152343
|
+
});
|
|
152321
152344
|
|
|
152322
152345
|
//#endregion
|
|
152323
152346
|
//#region src/Agents/planner.ts
|
|
@@ -152534,7 +152557,7 @@ const commandSource = make$35("source").pipe(withDescription("Select the issue s
|
|
|
152534
152557
|
|
|
152535
152558
|
//#endregion
|
|
152536
152559
|
//#region package.json
|
|
152537
|
-
var version = "0.3.
|
|
152560
|
+
var version = "0.3.6";
|
|
152538
152561
|
|
|
152539
152562
|
//#endregion
|
|
152540
152563
|
//#region src/commands/projects/ls.ts
|
package/package.json
CHANGED
package/src/commands/root.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
Iterable,
|
|
9
9
|
Option,
|
|
10
10
|
Path,
|
|
11
|
+
Stream,
|
|
11
12
|
} from "effect"
|
|
12
13
|
import { PromptGen } from "../PromptGen.ts"
|
|
13
14
|
import { Prd } from "../Prd.ts"
|
|
@@ -17,12 +18,13 @@ import { IssueSource } from "../IssueSource.ts"
|
|
|
17
18
|
import {
|
|
18
19
|
checkForWork,
|
|
19
20
|
CurrentIssueSource,
|
|
21
|
+
currentIssuesAtom,
|
|
20
22
|
resetInProgress,
|
|
21
23
|
} from "../CurrentIssueSource.ts"
|
|
22
24
|
import { GithubCli } from "../Github/Cli.ts"
|
|
23
25
|
import { agentWorker } from "../Agents/worker.ts"
|
|
24
26
|
import { agentChooser } from "../Agents/chooser.ts"
|
|
25
|
-
import { RunnerStalled } from "../domain/Errors.ts"
|
|
27
|
+
import { RunnerStalled, TaskStateChanged } from "../domain/Errors.ts"
|
|
26
28
|
import { agentReviewer } from "../Agents/reviewer.ts"
|
|
27
29
|
import { agentTimeout } from "../Agents/timeout.ts"
|
|
28
30
|
import { CurrentProjectId, Settings } from "../Settings.ts"
|
|
@@ -135,7 +137,7 @@ const run = Effect.fnUntraced(
|
|
|
135
137
|
() => preset,
|
|
136
138
|
)
|
|
137
139
|
|
|
138
|
-
yield* Effect.gen(function* () {
|
|
140
|
+
const cancelled = yield* Effect.gen(function* () {
|
|
139
141
|
//
|
|
140
142
|
// 2. Work on task
|
|
141
143
|
// -----------------------
|
|
@@ -185,8 +187,17 @@ const run = Effect.fnUntraced(
|
|
|
185
187
|
task: chosenTask.prd,
|
|
186
188
|
}),
|
|
187
189
|
),
|
|
190
|
+
Effect.raceFirst(watchTaskState({ issueId: taskId })),
|
|
191
|
+
Effect.as(false),
|
|
192
|
+
Effect.catchTag("TaskStateChanged", (error) =>
|
|
193
|
+
Effect.log(
|
|
194
|
+
`Task ${error.issueId} moved to ${error.state}; cancelling run.`,
|
|
195
|
+
).pipe(Effect.as(true)),
|
|
196
|
+
),
|
|
188
197
|
)
|
|
189
198
|
|
|
199
|
+
if (cancelled) return
|
|
200
|
+
|
|
190
201
|
yield* gitFlow.postWork({
|
|
191
202
|
worktree,
|
|
192
203
|
targetBranch: Option.getOrUndefined(options.targetBranch),
|
|
@@ -396,3 +407,37 @@ export const commandRoot = Command.make("lalph", {
|
|
|
396
407
|
),
|
|
397
408
|
),
|
|
398
409
|
)
|
|
410
|
+
|
|
411
|
+
const watchTaskState = Effect.fnUntraced(function* (options: {
|
|
412
|
+
readonly issueId: string
|
|
413
|
+
}) {
|
|
414
|
+
const registry = yield* AtomRegistry.AtomRegistry
|
|
415
|
+
const projectId = yield* CurrentProjectId
|
|
416
|
+
|
|
417
|
+
return yield* AtomRegistry.toStreamResult(
|
|
418
|
+
registry,
|
|
419
|
+
currentIssuesAtom(projectId),
|
|
420
|
+
).pipe(
|
|
421
|
+
Stream.runForEach((issues) => {
|
|
422
|
+
const issue = issues.find((entry) => entry.id === options.issueId)
|
|
423
|
+
if (!issue) {
|
|
424
|
+
return Effect.fail(
|
|
425
|
+
new TaskStateChanged({
|
|
426
|
+
issueId: options.issueId,
|
|
427
|
+
state: "missing",
|
|
428
|
+
}),
|
|
429
|
+
)
|
|
430
|
+
}
|
|
431
|
+
if (issue.state === "in-progress" || issue.state === "in-review") {
|
|
432
|
+
return Effect.void
|
|
433
|
+
}
|
|
434
|
+
return Effect.fail(
|
|
435
|
+
new TaskStateChanged({
|
|
436
|
+
issueId: options.issueId,
|
|
437
|
+
state: issue.state,
|
|
438
|
+
}),
|
|
439
|
+
)
|
|
440
|
+
}),
|
|
441
|
+
Effect.withSpan("Main.watchTaskState"),
|
|
442
|
+
)
|
|
443
|
+
})
|
package/src/domain/Errors.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { Data } from "effect"
|
|
2
|
+
import type { PrdIssue } from "./PrdIssue.ts"
|
|
2
3
|
|
|
3
4
|
export class RunnerStalled extends Data.TaggedError("RunnerStalled") {
|
|
4
5
|
readonly message = "The runner has stalled due to inactivity."
|
|
5
6
|
}
|
|
7
|
+
|
|
8
|
+
export class TaskStateChanged extends Data.TaggedError("TaskStateChanged")<{
|
|
9
|
+
readonly issueId: string
|
|
10
|
+
readonly state: PrdIssue["state"] | "missing"
|
|
11
|
+
}> {
|
|
12
|
+
readonly message = `Task "${this.issueId}" moved to "${this.state}", cancelling run.`
|
|
13
|
+
}
|
|
@@ -54,7 +54,7 @@ export class IssuesNode extends S.Class<IssuesNode>("IssuesNode")({
|
|
|
54
54
|
incompleteStates.has(relation.issue.state.type),
|
|
55
55
|
)
|
|
56
56
|
}
|
|
57
|
-
const incompleteStates = new Set<Type>(["unstarted", "started"])
|
|
57
|
+
const incompleteStates = new Set<Type>(["backlog", "unstarted", "started"])
|
|
58
58
|
|
|
59
59
|
export const LinearIssueData = S.Struct({
|
|
60
60
|
issue: IssuesNode,
|