lalph 0.3.88 → 0.3.89

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 CHANGED
@@ -12350,6 +12350,22 @@ const done = done$2;
12350
12350
  */
12351
12351
  const isTimeoutError = isTimeoutError$1;
12352
12352
  /**
12353
+ * Constructs a {@link TimeoutError} with an optional message.
12354
+ *
12355
+ * **Example** (creating a TimeoutError)
12356
+ *
12357
+ * ```ts
12358
+ * import { Cause } from "effect"
12359
+ *
12360
+ * const error = new Cause.TimeoutError("Operation timed out")
12361
+ * console.log(error.message) // "Operation timed out"
12362
+ * ```
12363
+ *
12364
+ * @category constructors
12365
+ * @since 4.0.0
12366
+ */
12367
+ const TimeoutError = TimeoutError$1;
12368
+ /**
12353
12369
  * Constructs an {@link IllegalArgumentError} with an optional message.
12354
12370
  *
12355
12371
  * **Example** (creating an IllegalArgumentError)
@@ -240866,7 +240882,11 @@ const runClanka = fnUntraced(function* (options) {
240866
240882
  yield* log$1(`Received steer message: ${message}`);
240867
240883
  yield* agent.steer(message);
240868
240884
  }, fromEffectDrain)), runDrain, forkScoped);
240869
- return yield* stream.pipe(runDrain, as$1(""), catchTag$1("AgentFinished", (e) => succeed$3(e.summary)));
240885
+ return yield* stream.pipe(options.maxContext ? tap((part) => {
240886
+ if (part._tag !== "Usage") return void_$2;
240887
+ if (part.contextTokens <= options.maxContext) return void_$2;
240888
+ return fail$6(new TimeoutError("Max context reached"));
240889
+ }) : identity, runDrain, as$1(""), catchTag$1("AgentFinished", (e) => succeed$3(e.summary)));
240870
240890
  }, scoped$1, (effect, options) => provide$1(effect, layerLocal({
240871
240891
  directory: options.directory,
240872
240892
  tools: options.mode === "ralph" ? void 0 : options.mode === "choose" ? TaskChooseTools : TaskTools
@@ -240895,6 +240915,7 @@ ${research}`
240895
240915
  }])
240896
240916
  }),
240897
240917
  stallTimeout: options.stallTimeout,
240918
+ maxContext: options.maxContext,
240898
240919
  steer: options.steer,
240899
240920
  mode: options.ralph ? "ralph" : "default"
240900
240921
  });
@@ -241387,6 +241408,7 @@ const runRalph = fnUntraced(function* (options) {
241387
241408
  preset,
241388
241409
  prompt: instructions,
241389
241410
  research: researchResult,
241411
+ maxContext: options.maxContext,
241390
241412
  ralph: true
241391
241413
  }).pipe(withSpan$1("Main.worker"))}`);
241392
241414
  if (options.review) {
@@ -241439,6 +241461,7 @@ const runProject = fnUntraced(function* (options) {
241439
241461
  targetBranch: options.project.targetBranch,
241440
241462
  stallTimeout: options.stallTimeout,
241441
241463
  runTimeout: options.runTimeout,
241464
+ maxContext: options.maxContext,
241442
241465
  review: options.project.reviewAgent,
241443
241466
  research: options.project.researchAgent,
241444
241467
  specFile: options.project.ralphSpec
@@ -241480,17 +241503,19 @@ const runProject = fnUntraced(function* (options) {
241480
241503
  }, (effect, options) => annotateLogs(effect, { project: options.project.id }));
241481
241504
  const iterations = integer$1("iterations").pipe(withDescription$1("Limit how many task iterations run per enabled project (default: unlimited). Use -i 1 to run a single iteration and exit."), withAlias$1("i"), withDefault(Number.POSITIVE_INFINITY));
241482
241505
  const maxIterationMinutes = integer$1("max-minutes").pipe(withDescription$1("Timeout an iteration if execution (and review, if enabled) exceeds this many minutes (default: LALPH_MAX_MINUTES or 90)."), withFallbackConfig(int$1("LALPH_MAX_MINUTES")), withDefault(90));
241506
+ const maxContext = integer$1("max-context").pipe(withDescription$1("If the context window reaches this number of tokens, try again (default: LALPH_MAX_CONTEXT or 250,000)."), withFallbackConfig(int$1("LALPH_MAX_TOKENS")), withDefault(25e4));
241483
241507
  const stallMinutes = integer$1("stall-minutes").pipe(withDescription$1("Fail an iteration if the agent stops responding for this many minutes (default: LALPH_STALL_MINUTES or 5)."), withFallbackConfig(int$1("LALPH_STALL_MINUTES")), withDefault(5));
241484
241508
  const specsDirectory = directory("specs").pipe(withDescription$1("Directory where plan specs are written and read (default: LALPH_SPECS or .specs)."), withAlias$1("s"), withFallbackConfig(string$2("LALPH_SPECS")), withDefault(".specs"));
241485
241509
  const verbose = boolean$2("verbose").pipe(withDescription$1("Increase log output for debugging. Use -v when you need detailed logs."), withAlias$1("v"));
241486
241510
  const commandRoot = make$58("lalph", {
241487
241511
  iterations,
241488
241512
  maxIterationMinutes,
241513
+ maxContext,
241489
241514
  stallMinutes
241490
241515
  }).pipe(withSharedFlags({
241491
241516
  specsDirectory,
241492
241517
  verbose
241493
- }), withDescription("Run the task loop across all enabled projects in parallel: pull issues from the current issue source and execute them with your configured agent preset(s). Use --iterations for a bounded run, and configure per-project concurrency via lalph projects edit."), withHandler(fnUntraced(function* ({ iterations, maxIterationMinutes, stallMinutes, specsDirectory }) {
241518
+ }), withDescription("Run the task loop across all enabled projects in parallel: pull issues from the current issue source and execute them with your configured agent preset(s). Use --iterations for a bounded run, and configure per-project concurrency via lalph projects edit."), withHandler(fnUntraced(function* ({ iterations, maxIterationMinutes, maxContext, stallMinutes, specsDirectory }) {
241494
241519
  yield* getDefaultCliAgentPreset;
241495
241520
  let allProjects = yield* getAllProjects;
241496
241521
  if (allProjects.length === 0) {
@@ -241504,7 +241529,8 @@ const commandRoot = make$58("lalph", {
241504
241529
  project,
241505
241530
  specsDirectory,
241506
241531
  stallTimeout: minutes(stallMinutes),
241507
- runTimeout: minutes(maxIterationMinutes)
241532
+ runTimeout: minutes(maxIterationMinutes),
241533
+ maxContext
241508
241534
  }).pipe(provideService$2(CurrentProjectId, project.id)), {
241509
241535
  concurrency: "unbounded",
241510
241536
  discard: true
@@ -241818,7 +241844,7 @@ const commandEdit = make$58("edit").pipe(withDescription("Open the selected proj
241818
241844
  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));
241819
241845
  //#endregion
241820
241846
  //#region package.json
241821
- var version = "0.3.88";
241847
+ var version = "0.3.89";
241822
241848
  //#endregion
241823
241849
  //#region src/commands/projects/ls.ts
241824
241850
  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.88",
4
+ "version": "0.3.89",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -13,6 +13,7 @@ export const agentWorker = Effect.fnUntraced(function* (options: {
13
13
  readonly prompt: string
14
14
  readonly research: Option.Option<string>
15
15
  readonly steer?: Stream.Stream<string>
16
+ readonly maxContext?: number | undefined
16
17
  readonly ralph: boolean
17
18
  }) {
18
19
  const pathService = yield* Path.Path
@@ -42,6 +43,7 @@ ${research}`,
42
43
  ]),
43
44
  }),
44
45
  stallTimeout: options.stallTimeout,
46
+ maxContext: options.maxContext,
45
47
  steer: options.steer,
46
48
  mode: options.ralph ? "ralph" : "default",
47
49
  })
package/src/Clanka.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import { Agent, OutputFormatter, SemanticSearch } from "clanka"
2
2
  import {
3
+ Cause,
3
4
  Config,
4
5
  Duration,
5
6
  Effect,
7
+ identity,
6
8
  Layer,
7
9
  Option,
8
10
  Path,
@@ -70,6 +72,7 @@ export const runClanka = Effect.fnUntraced(
70
72
  readonly prompt: Prompt.RawInput
71
73
  readonly system?: string | undefined
72
74
  readonly stallTimeout?: Duration.Input | undefined
75
+ readonly maxContext?: number | undefined
73
76
  readonly steer?: Stream.Stream<string> | undefined
74
77
  readonly mode?: "ralph" | "choose" | "default" | undefined
75
78
  }) {
@@ -101,6 +104,14 @@ export const runClanka = Effect.fnUntraced(
101
104
  }
102
105
 
103
106
  return yield* stream.pipe(
107
+ options.maxContext
108
+ ? Stream.tap((part) => {
109
+ if (part._tag !== "Usage") return Effect.void
110
+ const contextTokens = part.contextTokens
111
+ if (contextTokens <= options.maxContext!) return Effect.void
112
+ return Effect.fail(new Cause.TimeoutError("Max context reached"))
113
+ })
114
+ : identity,
104
115
  Stream.runDrain,
105
116
  Effect.as(""),
106
117
  Effect.catchTag("AgentFinished", (e) => Effect.succeed(e.summary)),
@@ -356,6 +356,7 @@ const runRalph = Effect.fnUntraced(
356
356
  readonly research: boolean
357
357
  readonly review: boolean
358
358
  readonly specFile: string
359
+ readonly maxContext: number | undefined
359
360
  }): Effect.fn.Return<
360
361
  void,
361
362
  | PlatformError.PlatformError
@@ -468,6 +469,7 @@ const runRalph = Effect.fnUntraced(
468
469
  preset,
469
470
  prompt: instructions,
470
471
  research: researchResult,
472
+ maxContext: options.maxContext,
471
473
  ralph: true,
472
474
  }).pipe(Effect.withSpan("Main.worker"))
473
475
  yield* Effect.log(`Agent exited with code: ${exitCode}`)
@@ -522,6 +524,7 @@ const runProject = Effect.fnUntraced(
522
524
  readonly specsDirectory: string
523
525
  readonly stallTimeout: Duration.Duration
524
526
  readonly runTimeout: Duration.Duration
527
+ readonly maxContext: number | undefined
525
528
  }) {
526
529
  const isFinite = Number.isFinite(options.iterations)
527
530
  const iterationsDisplay = isFinite ? options.iterations : "unlimited"
@@ -567,6 +570,7 @@ const runProject = Effect.fnUntraced(
567
570
  targetBranch: options.project.targetBranch,
568
571
  stallTimeout: options.stallTimeout,
569
572
  runTimeout: options.runTimeout,
573
+ maxContext: options.maxContext,
570
574
  review: options.project.reviewAgent,
571
575
  research: options.project.researchAgent,
572
576
  specFile: options.project.ralphSpec!,
@@ -659,6 +663,14 @@ const maxIterationMinutes = Flag.integer("max-minutes").pipe(
659
663
  Flag.withDefault(90),
660
664
  )
661
665
 
666
+ const maxContext = Flag.integer("max-context").pipe(
667
+ Flag.withDescription(
668
+ "If the context window reaches this number of tokens, try again (default: LALPH_MAX_CONTEXT or 250,000).",
669
+ ),
670
+ Flag.withFallbackConfig(Config.int("LALPH_MAX_TOKENS")),
671
+ Flag.withDefault(250000),
672
+ )
673
+
662
674
  const stallMinutes = Flag.integer("stall-minutes").pipe(
663
675
  Flag.withDescription(
664
676
  "Fail an iteration if the agent stops responding for this many minutes (default: LALPH_STALL_MINUTES or 5).",
@@ -686,6 +698,7 @@ const verbose = Flag.boolean("verbose").pipe(
686
698
  export const commandRoot = Command.make("lalph", {
687
699
  iterations,
688
700
  maxIterationMinutes,
701
+ maxContext,
689
702
  stallMinutes,
690
703
  }).pipe(
691
704
  Command.withSharedFlags({
@@ -700,6 +713,7 @@ export const commandRoot = Command.make("lalph", {
700
713
  function* ({
701
714
  iterations,
702
715
  maxIterationMinutes,
716
+ maxContext,
703
717
  stallMinutes,
704
718
  specsDirectory,
705
719
  }) {
@@ -726,6 +740,7 @@ export const commandRoot = Command.make("lalph", {
726
740
  specsDirectory,
727
741
  stallTimeout: Duration.minutes(stallMinutes),
728
742
  runTimeout: Duration.minutes(maxIterationMinutes),
743
+ maxContext,
729
744
  }).pipe(Effect.provideService(CurrentProjectId, project.id)),
730
745
  { concurrency: "unbounded", discard: true },
731
746
  )