lalph 0.3.47 → 0.3.49
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 +239 -86
- package/package.json +3 -3
- package/src/Agents/worker.ts +2 -8
- package/src/Clanka.ts +20 -13
- package/src/PromptGen.ts +5 -6
- package/src/TaskTools.ts +34 -33
- package/src/commands/plan/tasks.ts +2 -0
- package/src/commands/plan.ts +2 -0
- package/src/commands/root.ts +10 -1
package/dist/cli.mjs
CHANGED
|
@@ -24452,6 +24452,50 @@ const publish = /* @__PURE__ */ dual(2, (self, value) => suspend$3(() => {
|
|
|
24452
24452
|
return self.strategy.handleSurplus(self.pubsub, self.subscribers, [value], self.shutdownFlag);
|
|
24453
24453
|
}));
|
|
24454
24454
|
/**
|
|
24455
|
+
* Publishes all of the specified messages to the `PubSub`, returning whether they
|
|
24456
|
+
* were published to the `PubSub`.
|
|
24457
|
+
*
|
|
24458
|
+
* @example
|
|
24459
|
+
* ```ts
|
|
24460
|
+
* import { Effect } from "effect"
|
|
24461
|
+
* import * as PubSub from "effect/PubSub"
|
|
24462
|
+
*
|
|
24463
|
+
* const program = Effect.gen(function*() {
|
|
24464
|
+
* const pubsub = yield* PubSub.bounded<string>(10)
|
|
24465
|
+
*
|
|
24466
|
+
* // Publish multiple messages at once
|
|
24467
|
+
* const messages = ["Hello", "World", "from", "Effect"]
|
|
24468
|
+
* const allPublished = yield* PubSub.publishAll(pubsub, messages)
|
|
24469
|
+
* console.log("All messages published:", allPublished) // true
|
|
24470
|
+
*
|
|
24471
|
+
* // With a smaller capacity
|
|
24472
|
+
* const smallPubsub = yield* PubSub.bounded<string>(2)
|
|
24473
|
+
* const manyMessages = ["msg1", "msg2", "msg3", "msg4"]
|
|
24474
|
+
*
|
|
24475
|
+
* // Will suspend until space becomes available for all messages
|
|
24476
|
+
* const publishAllEffect = PubSub.publishAll(smallPubsub, manyMessages)
|
|
24477
|
+
*
|
|
24478
|
+
* // Subscribe to consume messages and free space
|
|
24479
|
+
* yield* Effect.scoped(Effect.gen(function*() {
|
|
24480
|
+
* const subscription = yield* PubSub.subscribe(smallPubsub)
|
|
24481
|
+
* yield* PubSub.takeAll(subscription) // consume all messages
|
|
24482
|
+
* const result = yield* publishAllEffect
|
|
24483
|
+
* console.log("All messages eventually published:", result)
|
|
24484
|
+
* }))
|
|
24485
|
+
* })
|
|
24486
|
+
* ```
|
|
24487
|
+
*
|
|
24488
|
+
* @since 2.0.0
|
|
24489
|
+
* @category publishing
|
|
24490
|
+
*/
|
|
24491
|
+
const publishAll = /* @__PURE__ */ dual(2, (self, elements) => suspend$3(() => {
|
|
24492
|
+
if (self.shutdownFlag.current) return interrupt$1;
|
|
24493
|
+
const surplus = self.pubsub.publishAll(elements);
|
|
24494
|
+
self.strategy.completeSubscribersUnsafe(self.pubsub, self.subscribers);
|
|
24495
|
+
if (surplus.length === 0) return succeed$3(true);
|
|
24496
|
+
return self.strategy.handleSurplus(self.pubsub, self.subscribers, surplus, self.shutdownFlag);
|
|
24497
|
+
}));
|
|
24498
|
+
/**
|
|
24455
24499
|
* Subscribes to receive messages from the `PubSub`. The resulting subscription can
|
|
24456
24500
|
* be evaluated multiple times within the scope to take a message from the `PubSub`
|
|
24457
24501
|
* each time.
|
|
@@ -28443,6 +28487,11 @@ const toPull$1 = /* @__PURE__ */ fnUntraced(function* (self) {
|
|
|
28443
28487
|
const toPullScoped = (self, scope) => toTransform(self)(done(), scope);
|
|
28444
28488
|
const makePubSub = (options) => acquireRelease(options.capacity === "unbounded" ? unbounded$1(options) : options.strategy === "dropping" ? dropping(options) : options.strategy === "sliding" ? sliding(options) : bounded$1(options), shutdown$1);
|
|
28445
28489
|
/**
|
|
28490
|
+
* @since 4.0.0
|
|
28491
|
+
* @category Destructors
|
|
28492
|
+
*/
|
|
28493
|
+
const runIntoPubSubArray = /* @__PURE__ */ dual((args) => isChannel(args[0]), (self, pubsub, options) => runForEach$1(self, (value) => publishAll(pubsub, value)).pipe(options?.shutdownOnEnd === true ? ensuring$2(shutdown$1(pubsub)) : identity));
|
|
28494
|
+
/**
|
|
28446
28495
|
* Converts a channel to a PubSub for concurrent consumption.
|
|
28447
28496
|
*
|
|
28448
28497
|
* @since 4.0.0
|
|
@@ -28913,9 +28962,9 @@ const getState = (self) => uninterruptibleMask((restore) => {
|
|
|
28913
28962
|
const get$11 = /* @__PURE__ */ fnUntraced(function* (self_) {
|
|
28914
28963
|
const self = self_;
|
|
28915
28964
|
const state = yield* getState(self);
|
|
28916
|
-
const scope$
|
|
28965
|
+
const scope$8 = yield* scope;
|
|
28917
28966
|
const isFinite = self.idleTimeToLive !== void 0 && isFinite$2(self.idleTimeToLive);
|
|
28918
|
-
yield* addFinalizerExit(scope$
|
|
28967
|
+
yield* addFinalizerExit(scope$8, () => {
|
|
28919
28968
|
state.refCount--;
|
|
28920
28969
|
if (state.refCount > 0) return void_$1;
|
|
28921
28970
|
if (self.idleTimeToLive === void 0) {
|
|
@@ -30930,6 +30979,38 @@ const toReadableStreamWith = /* @__PURE__ */ dual((args) => isStream(args[0]), (
|
|
|
30930
30979
|
*/
|
|
30931
30980
|
const toReadableStreamEffect = /* @__PURE__ */ dual((args) => isStream(args[0]), (self, options) => map$8(services(), (context) => toReadableStreamWith(self, context, options)));
|
|
30932
30981
|
/**
|
|
30982
|
+
* Runs the stream, publishing elements into the provided PubSub.
|
|
30983
|
+
*
|
|
30984
|
+
* `shutdownOnEnd` controls whether the PubSub is shut down when the stream ends.
|
|
30985
|
+
* It only shuts down when set to `true`.
|
|
30986
|
+
*
|
|
30987
|
+
* @example
|
|
30988
|
+
* ```ts
|
|
30989
|
+
* import { Console, Effect, PubSub, Stream } from "effect"
|
|
30990
|
+
*
|
|
30991
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
30992
|
+
* const pubsub = yield* PubSub.unbounded<number>()
|
|
30993
|
+
* const subscription = yield* PubSub.subscribe(pubsub)
|
|
30994
|
+
*
|
|
30995
|
+
* yield* Stream.runIntoPubSub(Stream.fromIterable([1, 2]), pubsub)
|
|
30996
|
+
*
|
|
30997
|
+
* const first = yield* PubSub.take(subscription)
|
|
30998
|
+
* const second = yield* PubSub.take(subscription)
|
|
30999
|
+
*
|
|
31000
|
+
* yield* Console.log(first)
|
|
31001
|
+
* yield* Console.log(second)
|
|
31002
|
+
* }))
|
|
31003
|
+
*
|
|
31004
|
+
* Effect.runPromise(program)
|
|
31005
|
+
* //=> 1
|
|
31006
|
+
* //=> 2
|
|
31007
|
+
* ```
|
|
31008
|
+
*
|
|
31009
|
+
* @since 2.0.0
|
|
31010
|
+
* @category Destructors
|
|
31011
|
+
*/
|
|
31012
|
+
const runIntoPubSub = /* @__PURE__ */ dual((args) => isStream(args[0]), (self, pubsub, options) => runIntoPubSubArray(self.channel, pubsub, options));
|
|
31013
|
+
/**
|
|
30933
31014
|
* Converts a stream to a PubSub for concurrent consumption.
|
|
30934
31015
|
*
|
|
30935
31016
|
* `Take` values include the stream's end and failure signals.
|
|
@@ -52972,6 +53053,32 @@ const randomWith = (f) => withFiber((fiber) => succeed$3(f(fiber.getRef(Random))
|
|
|
52972
53053
|
* @category Random Number Generators
|
|
52973
53054
|
*/
|
|
52974
53055
|
const next = /* @__PURE__ */ randomWith((r) => r.nextDoubleUnsafe());
|
|
53056
|
+
/**
|
|
53057
|
+
* Uses the pseudo-random number generator to shuffle the specified iterable.
|
|
53058
|
+
*
|
|
53059
|
+
* @example
|
|
53060
|
+
* ```ts
|
|
53061
|
+
* import { Effect, Random } from "effect"
|
|
53062
|
+
*
|
|
53063
|
+
* const program = Effect.gen(function*() {
|
|
53064
|
+
* const values = yield* Random.shuffle([1, 2, 3, 4, 5])
|
|
53065
|
+
* console.log(values)
|
|
53066
|
+
* })
|
|
53067
|
+
* ```
|
|
53068
|
+
*
|
|
53069
|
+
* @since 4.0.0
|
|
53070
|
+
* @category Random Number Generators
|
|
53071
|
+
*/
|
|
53072
|
+
const shuffle = (elements) => randomWith((r) => {
|
|
53073
|
+
const buffer = Array.from(elements);
|
|
53074
|
+
for (let i = buffer.length - 1; i >= 1; i = i - 1) {
|
|
53075
|
+
const index = Math.min(i, Math.floor(r.nextDoubleUnsafe() * (i + 1)));
|
|
53076
|
+
const value = buffer[i];
|
|
53077
|
+
buffer[i] = buffer[index];
|
|
53078
|
+
buffer[index] = value;
|
|
53079
|
+
}
|
|
53080
|
+
return buffer;
|
|
53081
|
+
});
|
|
52975
53082
|
//#endregion
|
|
52976
53083
|
//#region node_modules/.pnpm/effect@4.0.0-beta.30/node_modules/effect/dist/Ref.js
|
|
52977
53084
|
const RefProto = {
|
|
@@ -53380,7 +53487,7 @@ var BackingPersistence = class extends Service$1()("effect/persistence/BackingPe
|
|
|
53380
53487
|
*/
|
|
53381
53488
|
const layer$21 = /* @__PURE__ */ effect$1(Persistence)(/* @__PURE__ */ gen(function* () {
|
|
53382
53489
|
const backing = yield* BackingPersistence;
|
|
53383
|
-
const scope$
|
|
53490
|
+
const scope$6 = yield* scope;
|
|
53384
53491
|
return Persistence.of({ make: fnUntraced(function* (options) {
|
|
53385
53492
|
const storage = yield* backing.make(options.storeId);
|
|
53386
53493
|
const timeToLive = options.timeToLive ?? (() => infinity);
|
|
@@ -53415,7 +53522,7 @@ const layer$21 = /* @__PURE__ */ effect$1(Persistence)(/* @__PURE__ */ gen(funct
|
|
|
53415
53522
|
}
|
|
53416
53523
|
out[i] = exit$3.value;
|
|
53417
53524
|
}
|
|
53418
|
-
if (toRemove) for (let i = 0; i < toRemove.length; i++) yield* forkIn(storage.remove(toRemove[i]), scope$
|
|
53525
|
+
if (toRemove) for (let i = 0; i < toRemove.length; i++) yield* forkIn(storage.remove(toRemove[i]), scope$6);
|
|
53419
53526
|
return out;
|
|
53420
53527
|
}),
|
|
53421
53528
|
set(key, value) {
|
|
@@ -85497,9 +85604,9 @@ const layer$6 = /* @__PURE__ */ provideMerge(layer$20, /* @__PURE__ */ mergeAll$
|
|
|
85497
85604
|
* @category constructors
|
|
85498
85605
|
*/
|
|
85499
85606
|
const make$15 = /* @__PURE__ */ fnUntraced(function* (evaluate, options) {
|
|
85500
|
-
const scope$
|
|
85607
|
+
const scope$4 = yield* scope;
|
|
85501
85608
|
const server = evaluate();
|
|
85502
|
-
yield* addFinalizer$1(scope$
|
|
85609
|
+
yield* addFinalizer$1(scope$4, callback$1((resume) => {
|
|
85503
85610
|
if (!server.listening) return resume(void_$1);
|
|
85504
85611
|
server.close((error) => {
|
|
85505
85612
|
if (error) resume(die$2(error));
|
|
@@ -85519,7 +85626,7 @@ const make$15 = /* @__PURE__ */ fnUntraced(function* (evaluate, options) {
|
|
|
85519
85626
|
const address = server.address();
|
|
85520
85627
|
const wss = yield* acquireRelease(sync(() => new import_websocket_server.default({ noServer: true })), (wss) => callback$1((resume) => {
|
|
85521
85628
|
wss.close(() => resume(void_$1));
|
|
85522
|
-
})).pipe(provide$4(scope$
|
|
85629
|
+
})).pipe(provide$4(scope$4), cached);
|
|
85523
85630
|
return make$21({
|
|
85524
85631
|
address: typeof address === "string" ? {
|
|
85525
85632
|
_tag: "UnixAddress",
|
|
@@ -85530,14 +85637,14 @@ const make$15 = /* @__PURE__ */ fnUntraced(function* (evaluate, options) {
|
|
|
85530
85637
|
port: address.port
|
|
85531
85638
|
},
|
|
85532
85639
|
serve: fnUntraced(function* (httpApp, middleware) {
|
|
85533
|
-
const scope$
|
|
85640
|
+
const scope$5 = yield* scope;
|
|
85534
85641
|
const handler = yield* makeHandler(httpApp, {
|
|
85535
85642
|
middleware,
|
|
85536
|
-
scope: scope$
|
|
85643
|
+
scope: scope$5
|
|
85537
85644
|
});
|
|
85538
85645
|
const upgradeHandler = yield* makeUpgradeHandler(wss, httpApp, {
|
|
85539
85646
|
middleware,
|
|
85540
|
-
scope: scope$
|
|
85647
|
+
scope: scope$5
|
|
85541
85648
|
});
|
|
85542
85649
|
yield* addFinalizer(() => sync(() => {
|
|
85543
85650
|
server.off("request", handler);
|
|
@@ -86389,12 +86496,12 @@ const AtomRegistry = /* @__PURE__ */ Service$1(TypeId$6);
|
|
|
86389
86496
|
* @category Layers
|
|
86390
86497
|
*/
|
|
86391
86498
|
const layerOptions = (options) => effect$1(AtomRegistry, gen(function* () {
|
|
86392
|
-
const scope$
|
|
86499
|
+
const scope$3 = yield* scope;
|
|
86393
86500
|
const registry = make$13({
|
|
86394
86501
|
...options,
|
|
86395
86502
|
scheduleTask: options?.scheduleTask
|
|
86396
86503
|
});
|
|
86397
|
-
yield* addFinalizer$1(scope$
|
|
86504
|
+
yield* addFinalizer$1(scope$3, sync(() => registry.dispose()));
|
|
86398
86505
|
return registry;
|
|
86399
86506
|
}));
|
|
86400
86507
|
/**
|
|
@@ -180286,12 +180393,11 @@ The following instructions should be done without interaction or asking for perm
|
|
|
180286
180393
|
Set \`githubPrNumber\` to the PR number if one exists, otherwise use \`null\`.
|
|
180287
180394
|
` : "\n\nLeave `githubPrNumber` as null."}
|
|
180288
180395
|
`;
|
|
180289
|
-
const promptChooseClanka = (options) =>
|
|
180290
|
-
**
|
|
180291
|
-
|
|
180292
|
-
|
|
180293
|
-
|
|
180294
|
-
- Decide which single task to work on next from "listEligibleTasks". This should
|
|
180396
|
+
const promptChooseClanka = (options) => `- Use the "listEligibleTasks" function to view the list of tasks that you can start working on.
|
|
180397
|
+
- **NO NOT PARSE THE yaml OUTPUT IN ANY WAY**
|
|
180398
|
+
- **DO NOT** implement the task yet.
|
|
180399
|
+
- **DO NOT** use the "delegate" function for any step in this workflow
|
|
180400
|
+
- After reading through the list of tasks, choose the task to work on. This should
|
|
180295
180401
|
be the task YOU decide as the most important to work on next, not just the
|
|
180296
180402
|
first task in the list.${options.gitFlow.requiresGithubPr ? `
|
|
180297
180403
|
- Check if there is an open Github PR for the chosen task. If there is, note the PR number for inclusion when calling "chooseTask".
|
|
@@ -188245,7 +188351,7 @@ var ji = Bt, Ii = Object.assign(Qe, { sync: Bt }), zi = Ut, Bi = Object.assign(e
|
|
|
188245
188351
|
});
|
|
188246
188352
|
Ze.glob = Ze;
|
|
188247
188353
|
//#endregion
|
|
188248
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
188354
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/ApplyPatch.js
|
|
188249
188355
|
/**
|
|
188250
188356
|
* @since 1.0.0
|
|
188251
188357
|
*/
|
|
@@ -188574,7 +188680,7 @@ const patchChunks = (file, input, chunks) => {
|
|
|
188574
188680
|
return eol === "\r\n" ? text.replace(/\n/g, "\r\n") : text;
|
|
188575
188681
|
};
|
|
188576
188682
|
//#endregion
|
|
188577
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
188683
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/AgentTools.js
|
|
188578
188684
|
/**
|
|
188579
188685
|
* @since 1.0.0
|
|
188580
188686
|
*/
|
|
@@ -188614,7 +188720,7 @@ const AgentTools = make$9(make$7("readFile", {
|
|
|
188614
188720
|
}),
|
|
188615
188721
|
dependencies: [CurrentDirectory]
|
|
188616
188722
|
}), make$7("applyPatch", {
|
|
188617
|
-
description: "Apply a git diff / unified diff patch across one or more files.",
|
|
188723
|
+
description: "Apply a git diff / unified diff patch, or a wrapped apply_patch patch, across one or more files.",
|
|
188618
188724
|
parameters: String$1.annotate({ identifier: "patch" }),
|
|
188619
188725
|
success: String$1,
|
|
188620
188726
|
dependencies: [CurrentDirectory]
|
|
@@ -188643,6 +188749,7 @@ const AgentTools = make$9(make$7("readFile", {
|
|
|
188643
188749
|
parameters: Struct({
|
|
188644
188750
|
pattern: String$1,
|
|
188645
188751
|
glob: optional$2(String$1).annotate({ documentation: "--glob" }),
|
|
188752
|
+
noIgnore: optional$2(Boolean$2).annotate({ documentation: "--no-ignore" }),
|
|
188646
188753
|
maxLines: optional$2(Finite).annotate({ documentation: "The total maximum number of lines to return across all files (default: 500)" })
|
|
188647
188754
|
}),
|
|
188648
188755
|
success: String$1,
|
|
@@ -188704,7 +188811,6 @@ const AgentToolHandlers = AgentTools.toLayer(gen(function* () {
|
|
|
188704
188811
|
yield* logInfo(`Calling "writeFile"`).pipe(annotateLogs({ path: options.path }));
|
|
188705
188812
|
const cwd = yield* CurrentDirectory;
|
|
188706
188813
|
const path = pathService.resolve(cwd, options.path);
|
|
188707
|
-
if (yield* fs.exists(path)) return yield* die$2("File already exists");
|
|
188708
188814
|
yield* fs.makeDirectory(pathService.dirname(path), { recursive: true });
|
|
188709
188815
|
yield* fs.writeFileString(path, options.content);
|
|
188710
188816
|
}, orDie$2),
|
|
@@ -188740,6 +188846,7 @@ const AgentToolHandlers = AgentTools.toLayer(gen(function* () {
|
|
|
188740
188846
|
"--line-number"
|
|
188741
188847
|
];
|
|
188742
188848
|
if (options.glob) args.push("--glob", options.glob);
|
|
188849
|
+
if (options.noIgnore) args.push("--no-ignore");
|
|
188743
188850
|
args.push(options.pattern);
|
|
188744
188851
|
let stream = pipe(spawner.streamLines(make$36("rg", args, {
|
|
188745
188852
|
cwd,
|
|
@@ -188870,7 +188977,7 @@ const AgentToolHandlers = AgentTools.toLayer(gen(function* () {
|
|
|
188870
188977
|
}));
|
|
188871
188978
|
var ApplyPatchError = class extends TaggedClass$1("ApplyPatchError") {};
|
|
188872
188979
|
//#endregion
|
|
188873
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
188980
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/Executor.js
|
|
188874
188981
|
/**
|
|
188875
188982
|
* @since 1.0.0
|
|
188876
188983
|
*/
|
|
@@ -188950,7 +189057,7 @@ var QueueWriteStream = class extends Writable {
|
|
|
188950
189057
|
}
|
|
188951
189058
|
};
|
|
188952
189059
|
//#endregion
|
|
188953
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
189060
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/TypeBuilder.js
|
|
188954
189061
|
const resolveDocumentation = resolveAt("documentation");
|
|
188955
189062
|
const identifierPattern = /^[$A-Z_a-z][$0-9A-Z_a-z]*$/u;
|
|
188956
189063
|
const Precedence = {
|
|
@@ -189223,7 +189330,7 @@ const render = (schema, options) => {
|
|
|
189223
189330
|
return printNode({ text: documentation === void 0 ? rendered.text : `${renderJsDoc(documentation, 0, printerOptions)}${printerOptions.newLine}${rendered.text}` }, printerOptions);
|
|
189224
189331
|
};
|
|
189225
189332
|
//#endregion
|
|
189226
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
189333
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/ToolkitRenderer.js
|
|
189227
189334
|
/**
|
|
189228
189335
|
* @since 1.0.0
|
|
189229
189336
|
*/
|
|
@@ -189245,7 +189352,7 @@ declare function ${name}(${params}): Promise<${render(tool.successSchema)}>`);
|
|
|
189245
189352
|
}) });
|
|
189246
189353
|
};
|
|
189247
189354
|
//#endregion
|
|
189248
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
189355
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/Agent.js
|
|
189249
189356
|
/**
|
|
189250
189357
|
* @since 1.0.0
|
|
189251
189358
|
*/
|
|
@@ -189300,7 +189407,8 @@ ${content}
|
|
|
189300
189407
|
for (const [id, state] of outputBuffer) {
|
|
189301
189408
|
outputBuffer.delete(id);
|
|
189302
189409
|
offerAllUnsafe(output, state);
|
|
189303
|
-
|
|
189410
|
+
const lastPart = state[state.length - 1];
|
|
189411
|
+
if (lastPart._tag === "ScriptDelta" || lastPart._tag === "ReasoningDelta") {
|
|
189304
189412
|
currentOutputAgent = id;
|
|
189305
189413
|
break;
|
|
189306
189414
|
}
|
|
@@ -189322,17 +189430,23 @@ ${content}
|
|
|
189322
189430
|
${prompt}`));
|
|
189323
189431
|
return gen(function* () {
|
|
189324
189432
|
const provider = yield* ProviderName;
|
|
189325
|
-
|
|
189326
|
-
|
|
189327
|
-
|
|
189328
|
-
|
|
189329
|
-
|
|
189330
|
-
|
|
189433
|
+
maybeSend({
|
|
189434
|
+
agentId,
|
|
189435
|
+
part: new SubagentStart({
|
|
189436
|
+
id,
|
|
189437
|
+
prompt,
|
|
189438
|
+
model: yield* ModelName,
|
|
189439
|
+
provider
|
|
189440
|
+
}),
|
|
189441
|
+
release: true
|
|
189442
|
+
});
|
|
189331
189443
|
return yield* stream.pipe(runForEachArray((parts) => {
|
|
189332
189444
|
for (const part of parts) switch (part._tag) {
|
|
189333
189445
|
case "SubagentStart":
|
|
189334
189446
|
case "SubagentComplete":
|
|
189335
|
-
case "SubagentPart":
|
|
189447
|
+
case "SubagentPart":
|
|
189448
|
+
offerUnsafe(output, part);
|
|
189449
|
+
break;
|
|
189336
189450
|
default:
|
|
189337
189451
|
offerUnsafe(output, new SubagentPart({
|
|
189338
189452
|
id,
|
|
@@ -189555,7 +189669,7 @@ Javascript output:
|
|
|
189555
189669
|
\`\`\``;
|
|
189556
189670
|
};
|
|
189557
189671
|
const generateSystemMulti = (toolsDts) => {
|
|
189558
|
-
return `
|
|
189672
|
+
return `You complete your tasks by **only writing javascript code** to interact with your environment.
|
|
189559
189673
|
|
|
189560
189674
|
- Use \`console.log\` to print any output you need.
|
|
189561
189675
|
- Top level await is supported.
|
|
@@ -200013,7 +200127,7 @@ const transformToolCallParams = /* @__PURE__ */ fnUntraced(function* (tools, too
|
|
|
200013
200127
|
})));
|
|
200014
200128
|
});
|
|
200015
200129
|
//#endregion
|
|
200016
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
200130
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/CodexAuth.js
|
|
200017
200131
|
/**
|
|
200018
200132
|
* @since 1.0.0
|
|
200019
200133
|
*/
|
|
@@ -200233,7 +200347,7 @@ var CodexAuth = class CodexAuth extends Service$1()("clanka/CodexAuth") {
|
|
|
200233
200347
|
static layerClient = this.layerClientNoDeps.pipe(provide$3(CodexAuth.layer));
|
|
200234
200348
|
};
|
|
200235
200349
|
//#endregion
|
|
200236
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
200350
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/Codex.js
|
|
200237
200351
|
/**
|
|
200238
200352
|
* @since 1.0.0
|
|
200239
200353
|
*/
|
|
@@ -201548,7 +201662,7 @@ const getUsageDetailNumber = (details, field) => {
|
|
|
201548
201662
|
return typeof value === "number" ? value : void 0;
|
|
201549
201663
|
};
|
|
201550
201664
|
//#endregion
|
|
201551
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
201665
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/CopilotAuth.js
|
|
201552
201666
|
/**
|
|
201553
201667
|
* @since 1.0.0
|
|
201554
201668
|
*/
|
|
@@ -201739,7 +201853,7 @@ var GithubCopilotAuth = class GithubCopilotAuth extends Service$1()("clanka/Gith
|
|
|
201739
201853
|
static layerClient = this.layerClientNoDeps.pipe(provide$3(GithubCopilotAuth.layer));
|
|
201740
201854
|
};
|
|
201741
201855
|
//#endregion
|
|
201742
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
201856
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/Copilot.js
|
|
201743
201857
|
/**
|
|
201744
201858
|
* @since 1.0.0
|
|
201745
201859
|
*/
|
|
@@ -202162,7 +202276,7 @@ Object.defineProperties(createChalk.prototype, styles);
|
|
|
202162
202276
|
const chalk = createChalk();
|
|
202163
202277
|
createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
202164
202278
|
//#endregion
|
|
202165
|
-
//#region node_modules/.pnpm/clanka@0.0.
|
|
202279
|
+
//#region node_modules/.pnpm/clanka@0.0.23_@effect+ai-openai-compat@4.0.0-beta.30_effect@4.0.0-beta.30__@effect+ai-o_733f8e6611470b8c9676b30a3d55b413/node_modules/clanka/dist/OutputFormatter.js
|
|
202166
202280
|
/**
|
|
202167
202281
|
* @since 1.0.0
|
|
202168
202282
|
*/
|
|
@@ -202203,6 +202317,47 @@ const scriptIcon = "";
|
|
|
202203
202317
|
const subagentIcon = " ";
|
|
202204
202318
|
const thinkingIcon = "";
|
|
202205
202319
|
const doneIcon = "";
|
|
202320
|
+
/**
|
|
202321
|
+
* @since 1.0.0
|
|
202322
|
+
* @category Muxer
|
|
202323
|
+
*/
|
|
202324
|
+
var Muxer = class extends Service$1()("clanka/OutputFormatter/Muxer") {};
|
|
202325
|
+
/**
|
|
202326
|
+
* @since 1.0.0
|
|
202327
|
+
* @category Muxer
|
|
202328
|
+
*/
|
|
202329
|
+
const layerMuxer = (formatter) => effect$1(Muxer, gen(function* () {
|
|
202330
|
+
const scope$2 = yield* scope;
|
|
202331
|
+
const output = yield* unbounded$1();
|
|
202332
|
+
let agentCount = 0;
|
|
202333
|
+
let currentAgentId = null;
|
|
202334
|
+
const semaphore = makeUnsafe$8(1);
|
|
202335
|
+
return Muxer.of({
|
|
202336
|
+
add(stream) {
|
|
202337
|
+
const id = ++agentCount;
|
|
202338
|
+
return stream.pipe(tap(fnUntraced(function* (part_) {
|
|
202339
|
+
if (currentAgentId === null || id !== currentAgentId) yield* semaphore.take(1);
|
|
202340
|
+
switch ((part_._tag === "SubagentPart" ? part_.part : part_)._tag) {
|
|
202341
|
+
case "ReasoningStart":
|
|
202342
|
+
case "ScriptStart":
|
|
202343
|
+
currentAgentId = id;
|
|
202344
|
+
break;
|
|
202345
|
+
case "ScriptDelta":
|
|
202346
|
+
case "ReasoningDelta": break;
|
|
202347
|
+
default:
|
|
202348
|
+
currentAgentId = null;
|
|
202349
|
+
break;
|
|
202350
|
+
}
|
|
202351
|
+
if (id !== currentAgentId) yield* semaphore.release(1);
|
|
202352
|
+
})), formatter, runIntoPubSub(output), onExit$1(() => {
|
|
202353
|
+
if (currentAgentId !== id) return void_$1;
|
|
202354
|
+
currentAgentId = null;
|
|
202355
|
+
return semaphore.release(1);
|
|
202356
|
+
}), forkIn(scope$2), asVoid);
|
|
202357
|
+
},
|
|
202358
|
+
output: fromPubSub(output)
|
|
202359
|
+
});
|
|
202360
|
+
}));
|
|
202206
202361
|
//#endregion
|
|
202207
202362
|
//#region src/TaskTools.ts
|
|
202208
202363
|
var ChosenTaskDeferred = class extends Reference("lalph/TaskTools/ChosenTaskDeferred", { defaultValue: makeUnsafe$13 }) {};
|
|
@@ -202221,6 +202376,14 @@ const TaskList = Array$1(Struct({
|
|
|
202221
202376
|
"blockedBy"
|
|
202222
202377
|
])
|
|
202223
202378
|
}));
|
|
202379
|
+
const toTaskListItem = (issue) => ({
|
|
202380
|
+
id: issue.id ?? "",
|
|
202381
|
+
title: issue.title,
|
|
202382
|
+
description: issue.description,
|
|
202383
|
+
state: issue.state,
|
|
202384
|
+
priority: issue.priority,
|
|
202385
|
+
blockedBy: issue.blockedBy
|
|
202386
|
+
});
|
|
202224
202387
|
var TaskTools = class extends make$9(make$7("listTasks", {
|
|
202225
202388
|
description: "Returns the current list of tasks.",
|
|
202226
202389
|
success: TaskList,
|
|
@@ -202251,43 +202414,31 @@ var TaskTools = class extends make$9(make$7("listTasks", {
|
|
|
202251
202414
|
parameters: String$1.annotate({ identifier: "taskId" }),
|
|
202252
202415
|
dependencies: [CurrentProjectId]
|
|
202253
202416
|
})) {};
|
|
202254
|
-
var
|
|
202417
|
+
var TaskChooseTools = class extends make$9(make$7("chooseTask", {
|
|
202255
202418
|
description: "Choose the task to work on",
|
|
202256
202419
|
parameters: Struct({
|
|
202257
202420
|
taskId: String$1,
|
|
202258
202421
|
githubPrNumber: optional$2(Number$1)
|
|
202259
202422
|
})
|
|
202260
202423
|
}), make$7("listEligibleTasks", {
|
|
202261
|
-
description: "List tasks eligible for being chosen with chooseTask.",
|
|
202262
|
-
success:
|
|
202424
|
+
description: "List tasks eligible for being chosen with chooseTask in yaml format.",
|
|
202425
|
+
success: String$1,
|
|
202263
202426
|
dependencies: [CurrentProjectId]
|
|
202264
|
-
}))
|
|
202427
|
+
})) {};
|
|
202428
|
+
var TaskToolsWithChoose = class extends merge(TaskTools, TaskChooseTools) {};
|
|
202265
202429
|
const TaskToolsHandlers = TaskToolsWithChoose.toLayer(gen(function* () {
|
|
202266
202430
|
const source = yield* IssueSource;
|
|
202267
202431
|
return TaskToolsWithChoose.of({
|
|
202268
202432
|
listTasks: fn("TaskTools.listTasks")(function* () {
|
|
202269
202433
|
yield* log$1(`Calling "listTasks"`);
|
|
202270
202434
|
const projectId = yield* CurrentProjectId;
|
|
202271
|
-
return (yield* source.issues(projectId)).map(
|
|
202272
|
-
id: issue.id ?? "",
|
|
202273
|
-
title: issue.title,
|
|
202274
|
-
description: issue.description,
|
|
202275
|
-
state: issue.state,
|
|
202276
|
-
priority: issue.priority,
|
|
202277
|
-
blockedBy: issue.blockedBy
|
|
202278
|
-
}));
|
|
202435
|
+
return (yield* source.issues(projectId)).map(toTaskListItem);
|
|
202279
202436
|
}, orDie$2),
|
|
202280
202437
|
listEligibleTasks: fn("TaskTools.listEligibleTasks")(function* () {
|
|
202281
202438
|
yield* log$1(`Calling "listEligibleTasks"`);
|
|
202282
202439
|
const projectId = yield* CurrentProjectId;
|
|
202283
|
-
|
|
202284
|
-
|
|
202285
|
-
title: issue.title,
|
|
202286
|
-
description: issue.description,
|
|
202287
|
-
state: issue.state,
|
|
202288
|
-
priority: issue.priority,
|
|
202289
|
-
blockedBy: issue.blockedBy
|
|
202290
|
-
}));
|
|
202440
|
+
const shuffled = yield* shuffle((yield* source.issues(projectId)).filter((t) => t.state === "todo" && t.blockedBy.length === 0).map(toTaskListItem));
|
|
202441
|
+
return import_dist.stringify(shuffled, null, 2);
|
|
202291
202442
|
}, orDie$2),
|
|
202292
202443
|
chooseTask: fn("TaskTools.chooseTask")(function* (options) {
|
|
202293
202444
|
yield* log$1(`Calling "chooseTask"`).pipe(annotateLogs(options));
|
|
@@ -202359,28 +202510,27 @@ const reasoningToCopilotConfig = (model, reasoning) => {
|
|
|
202359
202510
|
};
|
|
202360
202511
|
//#endregion
|
|
202361
202512
|
//#region src/Clanka.ts
|
|
202362
|
-
const
|
|
202363
|
-
|
|
202364
|
-
|
|
202365
|
-
|
|
202366
|
-
|
|
202367
|
-
|
|
202368
|
-
|
|
202369
|
-
|
|
202370
|
-
|
|
202371
|
-
|
|
202372
|
-
|
|
202373
|
-
|
|
202374
|
-
|
|
202375
|
-
|
|
202376
|
-
|
|
202377
|
-
|
|
202378
|
-
|
|
202379
|
-
|
|
202380
|
-
},
|
|
202381
|
-
|
|
202382
|
-
|
|
202383
|
-
);
|
|
202513
|
+
const ClankaMuxerLayer = effectDiscard(gen(function* () {
|
|
202514
|
+
const muxer = yield* Muxer;
|
|
202515
|
+
const stdio = yield* Stdio;
|
|
202516
|
+
yield* muxer.output.pipe(run$7(stdio.stdout()), forkScoped);
|
|
202517
|
+
})).pipe(provideMerge(layerMuxer(pretty)));
|
|
202518
|
+
const runClanka = fnUntraced(function* (options) {
|
|
202519
|
+
const models = yield* ClankaModels;
|
|
202520
|
+
const muxer = yield* Muxer;
|
|
202521
|
+
const agent = yield* make$5({
|
|
202522
|
+
...options,
|
|
202523
|
+
tools: options.withChoose ? TaskChooseTools : TaskTools,
|
|
202524
|
+
subagentModel: clankaSubagent(models, options.model)
|
|
202525
|
+
}).pipe(provide$1(models.get(options.model)));
|
|
202526
|
+
yield* muxer.add(agent.output);
|
|
202527
|
+
let stream = options.stallTimeout ? withStallTimeout(options.stallTimeout)(agent.output) : agent.output;
|
|
202528
|
+
if (options.steer) yield* options.steer.pipe(switchMap(fnUntraced(function* (message) {
|
|
202529
|
+
yield* log$1(`Received steer message: ${message}`);
|
|
202530
|
+
yield* agent.steer(message);
|
|
202531
|
+
}, fromEffectDrain)), runDrain, forkScoped);
|
|
202532
|
+
yield* stream.pipe(runDrain, catchTag$1("AgentFinished", () => void_$1));
|
|
202533
|
+
}, scoped$1, provide$1([layerServices, TaskToolsHandlers]));
|
|
202384
202534
|
//#endregion
|
|
202385
202535
|
//#region src/Agents/worker.ts
|
|
202386
202536
|
const agentWorker = fnUntraced(function* (options) {
|
|
@@ -202394,7 +202544,7 @@ const agentWorker = fnUntraced(function* (options) {
|
|
|
202394
202544
|
prompt: options.prompt,
|
|
202395
202545
|
stallTimeout: options.stallTimeout,
|
|
202396
202546
|
steer: options.steer
|
|
202397
|
-
})
|
|
202547
|
+
});
|
|
202398
202548
|
return ExitCode(0);
|
|
202399
202549
|
}
|
|
202400
202550
|
return yield* pipe(options.preset.cliAgent.command({
|
|
@@ -202719,7 +202869,7 @@ const run = fnUntraced(function* (options) {
|
|
|
202719
202869
|
preset: taskPreset,
|
|
202720
202870
|
prompt: instructions,
|
|
202721
202871
|
steer
|
|
202722
|
-
}).pipe(catchStallInReview, withSpan("Main.agentWorker"))}`);
|
|
202872
|
+
}).pipe(provideService$2(CurrentTaskRef, issueRef), catchStallInReview, withSpan("Main.agentWorker"))}`);
|
|
202723
202873
|
if (options.review) {
|
|
202724
202874
|
registry.update(currentWorker.state, (s) => s.transitionTo(WorkerStatus.Reviewing({ issueId: taskId })));
|
|
202725
202875
|
yield* agentReviewer({
|
|
@@ -202821,6 +202971,7 @@ const commandRoot = make$46("lalph", {
|
|
|
202821
202971
|
});
|
|
202822
202972
|
}, scoped$1, provide$1([
|
|
202823
202973
|
ClankaModels.layer,
|
|
202974
|
+
ClankaMuxerLayer,
|
|
202824
202975
|
PromptGen.layer,
|
|
202825
202976
|
GithubCli.layer,
|
|
202826
202977
|
Settings.layer,
|
|
@@ -202925,6 +203076,7 @@ const generateTasks = fnUntraced(function* ({ specsDirectory, specificationPath,
|
|
|
202925
203076
|
});
|
|
202926
203077
|
}, provide$1([
|
|
202927
203078
|
ClankaModels.layer,
|
|
203079
|
+
ClankaMuxerLayer,
|
|
202928
203080
|
Settings.layer,
|
|
202929
203081
|
PromptGen.layer,
|
|
202930
203082
|
Prd.layerProvided.pipe(provideMerge(layerProjectIdPrompt))
|
|
@@ -202997,7 +203149,8 @@ const commandPlan = make$46("plan", {
|
|
|
202997
203149
|
}).pipe(provide$1([
|
|
202998
203150
|
Settings.layer,
|
|
202999
203151
|
CurrentIssueSource.layer,
|
|
203000
|
-
ClankaModels.layer
|
|
203152
|
+
ClankaModels.layer,
|
|
203153
|
+
ClankaMuxerLayer
|
|
203001
203154
|
]));
|
|
203002
203155
|
}, scoped$1, provide$1(Editor.layer))), withSubcommands([commandPlanTasks]));
|
|
203003
203156
|
const plan = fnUntraced(function* (options) {
|
|
@@ -203129,7 +203282,7 @@ const commandEdit = make$46("edit").pipe(withDescription("Open the selected proj
|
|
|
203129
203282
|
const commandSource = make$46("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));
|
|
203130
203283
|
//#endregion
|
|
203131
203284
|
//#region package.json
|
|
203132
|
-
var version = "0.3.
|
|
203285
|
+
var version = "0.3.49";
|
|
203133
203286
|
//#endregion
|
|
203134
203287
|
//#region src/commands/projects/ls.ts
|
|
203135
203288
|
const commandProjectsLs = make$46("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.49",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
|
31
31
|
"@octokit/types": "^16.0.0",
|
|
32
32
|
"@typescript/native-preview": "7.0.0-dev.20260310.1",
|
|
33
|
-
"clanka": "^0.0.
|
|
33
|
+
"clanka": "^0.0.23",
|
|
34
34
|
"concurrently": "^9.2.1",
|
|
35
35
|
"effect": "4.0.0-beta.30",
|
|
36
36
|
"husky": "^9.1.7",
|
|
37
37
|
"lint-staged": "^16.3.3",
|
|
38
38
|
"octokit": "^5.0.5",
|
|
39
|
-
"oxlint": "^1.
|
|
39
|
+
"oxlint": "^1.53.0",
|
|
40
40
|
"prettier": "^3.8.1",
|
|
41
41
|
"tsdown": "^0.21.1",
|
|
42
42
|
"typescript": "^5.9.3",
|
package/src/Agents/worker.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { Duration, Effect,
|
|
1
|
+
import { Duration, Effect, Path, pipe, Stream } from "effect"
|
|
2
2
|
import { ChildProcess } from "effect/unstable/process"
|
|
3
3
|
import { Worktree } from "../Worktree.ts"
|
|
4
4
|
import type { CliAgentPreset } from "../domain/CliAgentPreset.ts"
|
|
5
5
|
import { runClanka } from "../Clanka.ts"
|
|
6
6
|
import { ExitCode } from "effect/unstable/process/ChildProcessSpawner"
|
|
7
|
-
import { CurrentTaskRef } from "../TaskTools.ts"
|
|
8
7
|
|
|
9
8
|
export const agentWorker = Effect.fnUntraced(function* (options: {
|
|
10
9
|
readonly stallTimeout: Duration.Duration
|
|
@@ -12,7 +11,6 @@ export const agentWorker = Effect.fnUntraced(function* (options: {
|
|
|
12
11
|
readonly system?: string
|
|
13
12
|
readonly prompt: string
|
|
14
13
|
readonly steer?: Stream.Stream<string>
|
|
15
|
-
readonly taskRef?: CurrentTaskRef["Service"]
|
|
16
14
|
}) {
|
|
17
15
|
const pathService = yield* Path.Path
|
|
18
16
|
const worktree = yield* Worktree
|
|
@@ -26,11 +24,7 @@ export const agentWorker = Effect.fnUntraced(function* (options: {
|
|
|
26
24
|
prompt: options.prompt,
|
|
27
25
|
stallTimeout: options.stallTimeout,
|
|
28
26
|
steer: options.steer,
|
|
29
|
-
})
|
|
30
|
-
options.taskRef
|
|
31
|
-
? Effect.provideService(CurrentTaskRef, options.taskRef)
|
|
32
|
-
: identity,
|
|
33
|
-
)
|
|
27
|
+
})
|
|
34
28
|
return ExitCode(0)
|
|
35
29
|
}
|
|
36
30
|
|
package/src/Clanka.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Agent, OutputFormatter } from "clanka"
|
|
2
|
-
import { Duration, Effect, Stream } from "effect"
|
|
2
|
+
import { Duration, Effect, Layer, Stdio, Stream } from "effect"
|
|
3
3
|
import {
|
|
4
|
+
TaskChooseTools,
|
|
4
5
|
TaskTools,
|
|
5
6
|
TaskToolsHandlers,
|
|
6
7
|
TaskToolsWithChoose,
|
|
@@ -8,8 +9,15 @@ import {
|
|
|
8
9
|
import { ClankaModels, clankaSubagent } from "./ClankaModels.ts"
|
|
9
10
|
import { withStallTimeout } from "./shared/stream.ts"
|
|
10
11
|
|
|
12
|
+
export const ClankaMuxerLayer = Layer.effectDiscard(
|
|
13
|
+
Effect.gen(function* () {
|
|
14
|
+
const muxer = yield* OutputFormatter.Muxer
|
|
15
|
+
const stdio = yield* Stdio.Stdio
|
|
16
|
+
yield* muxer.output.pipe(Stream.run(stdio.stdout()), Effect.forkScoped)
|
|
17
|
+
}),
|
|
18
|
+
).pipe(Layer.provideMerge(OutputFormatter.layerMuxer(OutputFormatter.pretty)))
|
|
19
|
+
|
|
11
20
|
export const runClanka = Effect.fnUntraced(
|
|
12
|
-
/** The working directory to run the agent in */
|
|
13
21
|
function* (options: {
|
|
14
22
|
readonly directory: string
|
|
15
23
|
readonly model: string
|
|
@@ -20,14 +28,18 @@ export const runClanka = Effect.fnUntraced(
|
|
|
20
28
|
readonly withChoose?: boolean | undefined
|
|
21
29
|
}) {
|
|
22
30
|
const models = yield* ClankaModels
|
|
31
|
+
const muxer = yield* OutputFormatter.Muxer
|
|
32
|
+
|
|
23
33
|
const agent = yield* Agent.make({
|
|
24
34
|
...options,
|
|
25
|
-
tools: options.withChoose
|
|
26
|
-
?
|
|
27
|
-
:
|
|
35
|
+
tools: (options.withChoose
|
|
36
|
+
? TaskChooseTools
|
|
37
|
+
: TaskTools) as unknown as typeof TaskToolsWithChoose,
|
|
28
38
|
subagentModel: clankaSubagent(models, options.model),
|
|
29
39
|
}).pipe(Effect.provide(models.get(options.model)))
|
|
30
40
|
|
|
41
|
+
yield* muxer.add(agent.output)
|
|
42
|
+
|
|
31
43
|
let stream = options.stallTimeout
|
|
32
44
|
? withStallTimeout(options.stallTimeout)(agent.output)
|
|
33
45
|
: agent.output
|
|
@@ -45,14 +57,9 @@ export const runClanka = Effect.fnUntraced(
|
|
|
45
57
|
)
|
|
46
58
|
}
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
for (const item of out) {
|
|
52
|
-
process.stdout.write(item)
|
|
53
|
-
}
|
|
54
|
-
return Effect.void
|
|
55
|
-
}),
|
|
60
|
+
yield* stream.pipe(
|
|
61
|
+
Stream.runDrain,
|
|
62
|
+
Effect.catchTag("AgentFinished", () => Effect.void),
|
|
56
63
|
)
|
|
57
64
|
},
|
|
58
65
|
Effect.scoped,
|
package/src/PromptGen.ts
CHANGED
|
@@ -90,12 +90,11 @@ Set \`githubPrNumber\` to the PR number if one exists, otherwise use \`null\`.
|
|
|
90
90
|
|
|
91
91
|
const promptChooseClanka = (options: {
|
|
92
92
|
readonly gitFlow: GitFlow["Service"]
|
|
93
|
-
}) =>
|
|
94
|
-
**
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- Decide which single task to work on next from "listEligibleTasks". This should
|
|
93
|
+
}) => `- Use the "listEligibleTasks" function to view the list of tasks that you can start working on.
|
|
94
|
+
- **NO NOT PARSE THE yaml OUTPUT IN ANY WAY**
|
|
95
|
+
- **DO NOT** implement the task yet.
|
|
96
|
+
- **DO NOT** use the "delegate" function for any step in this workflow
|
|
97
|
+
- After reading through the list of tasks, choose the task to work on. This should
|
|
99
98
|
be the task YOU decide as the most important to work on next, not just the
|
|
100
99
|
first task in the list.${
|
|
101
100
|
options.gitFlow.requiresGithubPr
|
package/src/TaskTools.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Effect,
|
|
4
4
|
MutableRef,
|
|
5
5
|
Option,
|
|
6
|
+
Random,
|
|
6
7
|
Schema,
|
|
7
8
|
ServiceMap,
|
|
8
9
|
Struct,
|
|
@@ -11,6 +12,7 @@ import { Tool, Toolkit } from "effect/unstable/ai"
|
|
|
11
12
|
import { PrdIssue } from "./domain/PrdIssue.ts"
|
|
12
13
|
import { IssueSource } from "./IssueSource.ts"
|
|
13
14
|
import { CurrentProjectId } from "./Settings.ts"
|
|
15
|
+
import * as Yaml from "yaml"
|
|
14
16
|
|
|
15
17
|
export class ChosenTaskDeferred extends ServiceMap.Reference(
|
|
16
18
|
"lalph/TaskTools/ChosenTaskDeferred",
|
|
@@ -48,6 +50,15 @@ const TaskList = Schema.Array(
|
|
|
48
50
|
}),
|
|
49
51
|
)
|
|
50
52
|
|
|
53
|
+
const toTaskListItem = (issue: PrdIssue) => ({
|
|
54
|
+
id: issue.id ?? "",
|
|
55
|
+
title: issue.title,
|
|
56
|
+
description: issue.description,
|
|
57
|
+
state: issue.state,
|
|
58
|
+
priority: issue.priority,
|
|
59
|
+
blockedBy: issue.blockedBy,
|
|
60
|
+
})
|
|
61
|
+
|
|
51
62
|
export class TaskTools extends Toolkit.make(
|
|
52
63
|
Tool.make("listTasks", {
|
|
53
64
|
description: "Returns the current list of tasks.",
|
|
@@ -86,22 +97,25 @@ export class TaskTools extends Toolkit.make(
|
|
|
86
97
|
}),
|
|
87
98
|
) {}
|
|
88
99
|
|
|
100
|
+
export class TaskChooseTools extends Toolkit.make(
|
|
101
|
+
Tool.make("chooseTask", {
|
|
102
|
+
description: "Choose the task to work on",
|
|
103
|
+
parameters: Schema.Struct({
|
|
104
|
+
taskId: Schema.String,
|
|
105
|
+
githubPrNumber: Schema.optional(Schema.Number),
|
|
106
|
+
}),
|
|
107
|
+
}),
|
|
108
|
+
Tool.make("listEligibleTasks", {
|
|
109
|
+
description:
|
|
110
|
+
"List tasks eligible for being chosen with chooseTask in yaml format.",
|
|
111
|
+
success: Schema.String,
|
|
112
|
+
dependencies: [CurrentProjectId],
|
|
113
|
+
}),
|
|
114
|
+
) {}
|
|
115
|
+
|
|
89
116
|
export class TaskToolsWithChoose extends Toolkit.merge(
|
|
90
117
|
TaskTools,
|
|
91
|
-
|
|
92
|
-
Tool.make("chooseTask", {
|
|
93
|
-
description: "Choose the task to work on",
|
|
94
|
-
parameters: Schema.Struct({
|
|
95
|
-
taskId: Schema.String,
|
|
96
|
-
githubPrNumber: Schema.optional(Schema.Number),
|
|
97
|
-
}),
|
|
98
|
-
}),
|
|
99
|
-
Tool.make("listEligibleTasks", {
|
|
100
|
-
description: "List tasks eligible for being chosen with chooseTask.",
|
|
101
|
-
success: TaskList,
|
|
102
|
-
dependencies: [CurrentProjectId],
|
|
103
|
-
}),
|
|
104
|
-
),
|
|
118
|
+
TaskChooseTools,
|
|
105
119
|
) {}
|
|
106
120
|
|
|
107
121
|
export const TaskToolsHandlers = TaskToolsWithChoose.toLayer(
|
|
@@ -113,29 +127,16 @@ export const TaskToolsHandlers = TaskToolsWithChoose.toLayer(
|
|
|
113
127
|
yield* Effect.log(`Calling "listTasks"`)
|
|
114
128
|
const projectId = yield* CurrentProjectId
|
|
115
129
|
const tasks = yield* source.issues(projectId)
|
|
116
|
-
return tasks.map(
|
|
117
|
-
id: issue.id ?? "",
|
|
118
|
-
title: issue.title,
|
|
119
|
-
description: issue.description,
|
|
120
|
-
state: issue.state,
|
|
121
|
-
priority: issue.priority,
|
|
122
|
-
blockedBy: issue.blockedBy,
|
|
123
|
-
}))
|
|
130
|
+
return tasks.map(toTaskListItem)
|
|
124
131
|
}, Effect.orDie),
|
|
125
132
|
listEligibleTasks: Effect.fn("TaskTools.listEligibleTasks")(function* () {
|
|
126
133
|
yield* Effect.log(`Calling "listEligibleTasks"`)
|
|
127
134
|
const projectId = yield* CurrentProjectId
|
|
128
|
-
const tasks = yield* source.issues(projectId)
|
|
129
|
-
|
|
130
|
-
.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
title: issue.title,
|
|
134
|
-
description: issue.description,
|
|
135
|
-
state: issue.state,
|
|
136
|
-
priority: issue.priority,
|
|
137
|
-
blockedBy: issue.blockedBy,
|
|
138
|
-
}))
|
|
135
|
+
const tasks = (yield* source.issues(projectId))
|
|
136
|
+
.filter((t) => t.state === "todo" && t.blockedBy.length === 0)
|
|
137
|
+
.map(toTaskListItem)
|
|
138
|
+
const shuffled = yield* Random.shuffle(tasks)
|
|
139
|
+
return Yaml.stringify(shuffled, null, 2)
|
|
139
140
|
}, Effect.orDie),
|
|
140
141
|
chooseTask: Effect.fn("TaskTools.chooseTask")(function* (options) {
|
|
141
142
|
yield* Effect.log(`Calling "chooseTask"`).pipe(
|
|
@@ -11,6 +11,7 @@ import { selectCliAgentPreset } from "../../Presets.ts"
|
|
|
11
11
|
import { CurrentIssueSource } from "../../CurrentIssueSource.ts"
|
|
12
12
|
import type { CliAgentPreset } from "../../domain/CliAgentPreset.ts"
|
|
13
13
|
import { ClankaModels } from "../../ClankaModels.ts"
|
|
14
|
+
import { ClankaMuxerLayer } from "../../Clanka.ts"
|
|
14
15
|
|
|
15
16
|
const specificationPath = Argument.path("spec", {
|
|
16
17
|
pathType: "file",
|
|
@@ -72,6 +73,7 @@ const generateTasks = Effect.fnUntraced(
|
|
|
72
73
|
},
|
|
73
74
|
Effect.provide([
|
|
74
75
|
ClankaModels.layer,
|
|
76
|
+
ClankaMuxerLayer,
|
|
75
77
|
Settings.layer,
|
|
76
78
|
PromptGen.layer,
|
|
77
79
|
Prd.layerProvided.pipe(Layer.provideMerge(layerProjectIdPrompt)),
|
package/src/commands/plan.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
|
|
|
25
25
|
import { parseBranch } from "../shared/git.ts"
|
|
26
26
|
import type { CliAgentPreset } from "../domain/CliAgentPreset.ts"
|
|
27
27
|
import { ClankaModels } from "../ClankaModels.ts"
|
|
28
|
+
import { ClankaMuxerLayer } from "../Clanka.ts"
|
|
28
29
|
|
|
29
30
|
const dangerous = Flag.boolean("dangerous").pipe(
|
|
30
31
|
Flag.withAlias("d"),
|
|
@@ -99,6 +100,7 @@ export const commandPlan = Command.make("plan", {
|
|
|
99
100
|
Settings.layer,
|
|
100
101
|
CurrentIssueSource.layer,
|
|
101
102
|
ClankaModels.layer,
|
|
103
|
+
ClankaMuxerLayer,
|
|
102
104
|
]),
|
|
103
105
|
)
|
|
104
106
|
},
|
package/src/commands/root.ts
CHANGED
|
@@ -52,6 +52,9 @@ import type { ChildProcessSpawner } from "effect/unstable/process"
|
|
|
52
52
|
import { ClankaModels } from "../ClankaModels.ts"
|
|
53
53
|
import type { AiError } from "effect/unstable/ai/AiError"
|
|
54
54
|
import type { PrdIssue } from "../domain/PrdIssue.ts"
|
|
55
|
+
import { CurrentTaskRef } from "../TaskTools.ts"
|
|
56
|
+
import type { OutputFormatter } from "clanka"
|
|
57
|
+
import { ClankaMuxerLayer } from "../Clanka.ts"
|
|
55
58
|
|
|
56
59
|
// Main iteration run logic
|
|
57
60
|
|
|
@@ -88,6 +91,7 @@ const run = Effect.fnUntraced(
|
|
|
88
91
|
| Prd
|
|
89
92
|
| Worktree
|
|
90
93
|
| ClankaModels
|
|
94
|
+
| OutputFormatter.Muxer
|
|
91
95
|
| Scope.Scope
|
|
92
96
|
> {
|
|
93
97
|
const projectId = yield* CurrentProjectId
|
|
@@ -236,7 +240,11 @@ const run = Effect.fnUntraced(
|
|
|
236
240
|
preset: taskPreset,
|
|
237
241
|
prompt: instructions,
|
|
238
242
|
steer,
|
|
239
|
-
}).pipe(
|
|
243
|
+
}).pipe(
|
|
244
|
+
Effect.provideService(CurrentTaskRef, issueRef),
|
|
245
|
+
catchStallInReview,
|
|
246
|
+
Effect.withSpan("Main.agentWorker"),
|
|
247
|
+
)
|
|
240
248
|
yield* Effect.log(`Agent exited with code: ${exitCode}`)
|
|
241
249
|
|
|
242
250
|
// 3. Review task
|
|
@@ -484,6 +492,7 @@ export const commandRoot = Command.make("lalph", {
|
|
|
484
492
|
Effect.scoped,
|
|
485
493
|
Effect.provide([
|
|
486
494
|
ClankaModels.layer,
|
|
495
|
+
ClankaMuxerLayer,
|
|
487
496
|
PromptGen.layer,
|
|
488
497
|
GithubCli.layer,
|
|
489
498
|
Settings.layer,
|