@hydra-acp/cli 0.1.54 → 0.1.55

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.js CHANGED
@@ -407,6 +407,17 @@ var init_config = __esm({
407
407
  // installs can grow past this — it's enforced at load time and per
408
408
  // append in memory.
409
409
  promptHistoryMaxEntries: z.number().int().positive().default(2e3),
410
+ // Cap on tool rows shown inside the collapsed tools block. When more
411
+ // tools have fired than the cap, only the most recent N are visible
412
+ // and the header advertises "^O expand" so the user can see the rest.
413
+ // 0 disables the cap entirely — every tool row stays visible.
414
+ maxToolItems: z.number().int().nonnegative().default(5),
415
+ // Cap on plan entries rendered before the formatter switches to a
416
+ // sliding window around the active (in_progress / first pending)
417
+ // entry. Counters in the header summarize what's done and what's
418
+ // left when truncation kicks in. 0 disables the cap — every plan
419
+ // entry is rendered.
420
+ maxPlanItems: z.number().int().nonnegative().default(5),
410
421
  // How edit-style tool calls (Edit, Write, str_replace) render in
411
422
  // scrollback, *in addition to* the normal tool row inside the tools
412
423
  // block.
@@ -495,6 +506,8 @@ var init_config = __esm({
495
506
  defaultEnterAction: "amend",
496
507
  showThoughts: true,
497
508
  promptHistoryMaxEntries: 2e3,
509
+ maxToolItems: 5,
510
+ maxPlanItems: 5,
498
511
  showFileUpdates: "edit"
499
512
  })
500
513
  });
@@ -6575,7 +6588,7 @@ var init_session_row = __esm({
6575
6588
  import chalk2 from "chalk";
6576
6589
  import { highlight, supportsLanguage } from "cli-highlight";
6577
6590
  import stringWidth from "string-width";
6578
- function formatEvent(event) {
6591
+ function formatEvent(event, options = {}) {
6579
6592
  switch (event.kind) {
6580
6593
  case "user-text": {
6581
6594
  const lines = formatBlock(
@@ -6610,7 +6623,7 @@ function formatEvent(event) {
6610
6623
  case "exit-plan-mode":
6611
6624
  return [];
6612
6625
  case "plan":
6613
- return formatPlan(event);
6626
+ return formatPlan(event, options.maxPlanItems ?? PLAN_VISIBLE_LIMIT);
6614
6627
  case "mode-changed":
6615
6628
  return [
6616
6629
  {
@@ -7335,7 +7348,27 @@ function exitPlanFooter(status) {
7335
7348
  return null;
7336
7349
  }
7337
7350
  }
7338
- function formatPlan(event) {
7351
+ function pickPlanWindow(entries, limit) {
7352
+ const total = entries.length;
7353
+ if (limit <= 0 || total <= limit) {
7354
+ return { start: 0, end: total };
7355
+ }
7356
+ const inProgressIdx = entries.findIndex(
7357
+ (e) => (e.status ?? "pending") === "in_progress"
7358
+ );
7359
+ const firstPendingIdx = entries.findIndex(
7360
+ (e) => (e.status ?? "pending") === "pending"
7361
+ );
7362
+ const anchor = inProgressIdx >= 0 ? inProgressIdx : firstPendingIdx >= 0 ? firstPendingIdx : total - 1;
7363
+ const aboveSlots = Math.floor((limit - 1) / 2);
7364
+ let start = Math.max(0, anchor - aboveSlots);
7365
+ let end = Math.min(total, start + limit);
7366
+ if (end - start < limit) {
7367
+ start = Math.max(0, end - limit);
7368
+ }
7369
+ return { start, end };
7370
+ }
7371
+ function formatPlan(event, limit) {
7339
7372
  const stopped = event.stopped === true;
7340
7373
  const amended = event.amended === true;
7341
7374
  const stoppedStyle = amended ? "tool-status-cancelled" : "tool-status-fail";
@@ -7343,21 +7376,43 @@ function formatPlan(event) {
7343
7376
  (e) => (e.status ?? "pending") === "completed"
7344
7377
  );
7345
7378
  const headerStyle = allComplete ? "plan-done" : stopped ? stoppedStyle : "plan";
7379
+ const total = event.entries.length;
7380
+ const { start: winStart, end: winEnd } = pickPlanWindow(
7381
+ event.entries,
7382
+ limit
7383
+ );
7384
+ const truncated = winEnd - winStart < total;
7385
+ let headerBody = "Plan";
7386
+ if (truncated) {
7387
+ let doneCount = 0;
7388
+ for (const e of event.entries) {
7389
+ if ((e.status ?? "pending") === "completed") {
7390
+ doneCount += 1;
7391
+ }
7392
+ }
7393
+ const leftCount = total - doneCount;
7394
+ headerBody = leftCount === 0 ? `Plan \xB7 ${doneCount} done` : `Plan \xB7 ${doneCount} done \xB7 ${leftCount} left`;
7395
+ }
7346
7396
  const lines = [
7347
7397
  {
7348
7398
  prefix: "\u25A3 ",
7349
7399
  prefixStyle: headerStyle,
7350
- body: "Plan",
7400
+ body: headerBody,
7351
7401
  bodyStyle: headerStyle
7352
7402
  }
7353
7403
  ];
7354
- for (const entry of event.entries) {
7404
+ for (let i = winStart; i < winEnd; i++) {
7405
+ const entry = event.entries[i];
7406
+ if (!entry) {
7407
+ continue;
7408
+ }
7355
7409
  const status = entry.status ?? "pending";
7356
7410
  const marker = status === "completed" ? "[x]" : status === "in_progress" ? "[~]" : "[ ]";
7357
7411
  const style = status === "completed" ? "plan-done" : status === "in_progress" ? stopped ? "plan-pending" : "plan" : "plan-pending";
7412
+ const content = entry.content.replace(/^\d+\/\d+\s+/, "").replace(/\s*\(?\d+\/\d+\)?\s*$/, "");
7358
7413
  lines.push({
7359
7414
  prefix: " ",
7360
- body: `${marker} ${entry.content}`,
7415
+ body: `${marker} ${content}`,
7361
7416
  bodyStyle: style
7362
7417
  });
7363
7418
  }
@@ -7383,7 +7438,7 @@ function toolStatusStyle(status) {
7383
7438
  return "tool-status-pending";
7384
7439
  }
7385
7440
  }
7386
- var TABLE_MIN_COL, TABLE_PREFIX_WIDTH, TABLE_SEP_WIDTH, highlightChalk, HIGHLIGHT_THEME, EDIT_DIFF_MAX_LINES;
7441
+ var TABLE_MIN_COL, TABLE_PREFIX_WIDTH, TABLE_SEP_WIDTH, highlightChalk, HIGHLIGHT_THEME, EDIT_DIFF_MAX_LINES, PLAN_VISIBLE_LIMIT;
7387
7442
  var init_format = __esm({
7388
7443
  "src/tui/format.ts"() {
7389
7444
  "use strict";
@@ -7418,6 +7473,7 @@ var init_format = __esm({
7418
7473
  name: highlightChalk.cyanBright
7419
7474
  };
7420
7475
  EDIT_DIFF_MAX_LINES = 40;
7476
+ PLAN_VISIBLE_LIMIT = 5;
7421
7477
  }
7422
7478
  });
7423
7479
 
@@ -9579,6 +9635,13 @@ var init_screen = __esm({
9579
9635
  // current line count so subsequent upserts splice in-place — adjusting
9580
9636
  // the starts of any later keyed blocks if the size changes.
9581
9637
  keyedBlocks = /* @__PURE__ */ new Map();
9638
+ // When set, the named block is kept at the bottom of scrollback: any
9639
+ // subsequent append/upsert that lands new content after it triggers a
9640
+ // float that slides the sticky block back to the end. Used so the
9641
+ // agent's plan stays anchored at the bottom of the current turn even
9642
+ // as tool calls / agent text accumulate below it. Surviving past
9643
+ // `clearKey(stickyBottomKey)` is a no-op since the block is gone.
9644
+ stickyBottomKey = null;
9582
9645
  streamingActive = false;
9583
9646
  // When true, lines with bodyStyle="thought" are skipped at draw time
9584
9647
  // (they remain in `this.lines` so toggling back on reveals them again).
@@ -10103,6 +10166,7 @@ uncaught: ${err.stack ?? err.message}
10103
10166
  this.lines.push(...lines);
10104
10167
  this.trackLines(lines);
10105
10168
  this.adjustScrollForRowChange(this.wrappedRowsOfMany(lines));
10169
+ this.moveStickyToEnd();
10106
10170
  this.trimScrollback();
10107
10171
  this.scheduleRepaint();
10108
10172
  }
@@ -10111,6 +10175,7 @@ uncaught: ${err.stack ?? err.message}
10111
10175
  this.lines.push(line);
10112
10176
  this.trackLine(line);
10113
10177
  this.adjustScrollForRowChange(this.wrappedRowsOf(line));
10178
+ this.moveStickyToEnd();
10114
10179
  this.trimScrollback();
10115
10180
  this.scheduleRepaint();
10116
10181
  }
@@ -10233,6 +10298,9 @@ uncaught: ${err.stack ?? err.message}
10233
10298
  this.streamingActive = false;
10234
10299
  }
10235
10300
  this.adjustScrollForRowChange(rowDelta);
10301
+ if (key !== this.stickyBottomKey) {
10302
+ this.moveStickyToEnd();
10303
+ }
10236
10304
  this.trimScrollback();
10237
10305
  this.scheduleRepaint();
10238
10306
  }
@@ -10291,6 +10359,7 @@ uncaught: ${err.stack ?? err.message}
10291
10359
  }
10292
10360
  this.streamingActive = true;
10293
10361
  this.adjustScrollForRowChange(rowDelta);
10362
+ this.moveStickyToEnd();
10294
10363
  this.trimScrollback();
10295
10364
  this.scheduleRepaint();
10296
10365
  }
@@ -10490,6 +10559,48 @@ uncaught: ${err.stack ?? err.message}
10490
10559
  clearKey(key) {
10491
10560
  this.keyedBlocks.delete(key);
10492
10561
  }
10562
+ // Mark `key` as the sticky-bottom block. While set, whenever new content
10563
+ // lands after the block's lines (appendLines / appendStreaming / a new
10564
+ // upserted block) the screen floats this block back to the end so it
10565
+ // remains the last thing in scrollback. Pass null to disable. The key
10566
+ // doesn't need to refer to an existing block — the float is a no-op
10567
+ // until a block with that key is upserted.
10568
+ setStickyBottomKey(key) {
10569
+ this.stickyBottomKey = key;
10570
+ this.moveStickyToEnd();
10571
+ this.scheduleRepaint();
10572
+ }
10573
+ // If a sticky-bottom block is configured and isn't already at the tail,
10574
+ // splice it out and re-push it at the end. Indices of the other keyed
10575
+ // blocks that sat after the sticky block shift up by sticky.count to
10576
+ // stay aligned with the lines array. Resets streamingActive because the
10577
+ // last line is now part of the sticky block — extending the buried
10578
+ // streaming line in place would corrupt the sticky content.
10579
+ moveStickyToEnd() {
10580
+ if (this.stickyBottomKey === null) {
10581
+ return;
10582
+ }
10583
+ const sticky = this.keyedBlocks.get(this.stickyBottomKey);
10584
+ if (!sticky) {
10585
+ return;
10586
+ }
10587
+ const stickyEnd = sticky.start + sticky.count;
10588
+ if (stickyEnd >= this.lines.length) {
10589
+ return;
10590
+ }
10591
+ const stickyLines = this.lines.splice(sticky.start, sticky.count);
10592
+ for (const [k, range] of this.keyedBlocks) {
10593
+ if (k === this.stickyBottomKey) {
10594
+ continue;
10595
+ }
10596
+ if (range.start >= stickyEnd) {
10597
+ range.start -= sticky.count;
10598
+ }
10599
+ }
10600
+ sticky.start = this.lines.length;
10601
+ this.lines.push(...stickyLines);
10602
+ this.streamingActive = false;
10603
+ }
10493
10604
  // Splice a keyed block's lines out of scrollback entirely and drop the
10494
10605
  // key. Used when a placeholder block (e.g. "thinking…" with no tool
10495
10606
  // calls ever fired) shouldn't be kept as a historical artifact after
@@ -10598,18 +10709,36 @@ uncaught: ${err.stack ?? err.message}
10598
10709
  this.repaint();
10599
10710
  }
10600
10711
  // Adds a blank spacer line to the scrollback, but only if scrollback is
10601
- // non-empty and the last line isn't already a spacer. Idempotent so callers
10602
- // can request it freely at turn boundaries.
10712
+ // non-empty and the last "real" line isn't already a spacer. Idempotent
10713
+ // so callers can request it freely at turn boundaries. When a sticky
10714
+ // block sits at the tail, the separator is inserted directly above it
10715
+ // and the "is there already a separator" check looks at the line above
10716
+ // the sticky block instead of the array tail. The sticky block's own
10717
+ // first line (if blank) doesn't count: that blank floats with the
10718
+ // plan to its eventual tail position, and the separator we're adding
10719
+ // here is for whatever content is *about* to be appended (which will
10720
+ // land at sticky.start and push the plan back via moveStickyToEnd).
10603
10721
  ensureSeparator() {
10604
10722
  if (this.lines.length === 0) {
10605
10723
  return;
10606
10724
  }
10607
- const last = this.lines[this.lines.length - 1];
10608
- if (last && last.body === "" && (last.prefix === void 0 || last.prefix === "")) {
10725
+ const sticky = this.stickyBottomKey !== null ? this.keyedBlocks.get(this.stickyBottomKey) : void 0;
10726
+ const stickyAtEnd = sticky !== void 0 && sticky.start + sticky.count === this.lines.length;
10727
+ const probeIdx = stickyAtEnd ? sticky.start - 1 : this.lines.length - 1;
10728
+ if (probeIdx < 0) {
10729
+ return;
10730
+ }
10731
+ const probe = this.lines[probeIdx];
10732
+ if (probe && probe.body === "" && (probe.prefix === void 0 || probe.prefix === "")) {
10609
10733
  return;
10610
10734
  }
10611
10735
  const sep2 = { body: "" };
10612
- this.lines.push(sep2);
10736
+ if (stickyAtEnd) {
10737
+ this.lines.splice(sticky.start, 0, sep2);
10738
+ sticky.start += 1;
10739
+ } else {
10740
+ this.lines.push(sep2);
10741
+ }
10613
10742
  this.trackLine(sep2);
10614
10743
  this.streamingActive = false;
10615
10744
  this.adjustScrollForRowChange(this.wrappedRowsOf(sep2));
@@ -12217,6 +12346,11 @@ async function pickSession(term, opts) {
12217
12346
  let renameBuffer = "";
12218
12347
  let transientStatus = null;
12219
12348
  const composer = new InputDispatcher({ history: [] });
12349
+ const composerHistoryCap = opts.config.tui.promptHistoryMaxEntries;
12350
+ loadHistory(paths.globalTuiHistoryFile()).then((entries) => {
12351
+ const capped = entries.length > composerHistoryCap ? entries.slice(entries.length - composerHistoryCap) : entries;
12352
+ composer.setHistory(capped);
12353
+ }).catch(() => void 0);
12220
12354
  let termHeight = readTermHeight2(term);
12221
12355
  let termWidth = readTermWidth2(term);
12222
12356
  let viewportSize = 0;
@@ -13461,8 +13595,10 @@ ${cells}`;
13461
13595
  return;
13462
13596
  }
13463
13597
  if (name === "DOWN") {
13598
+ const cs = composer.state();
13599
+ const inWalk = cs.historyIndex !== -1 || cs.queueIndex !== -1;
13464
13600
  const atBottom = composerVisualRows.length === 0 || composerCursorRow === composerVisualRows.length - 1;
13465
- if (atBottom && visible.length > 0) {
13601
+ if (!inWalk && atBottom && visible.length > 0) {
13466
13602
  move(1);
13467
13603
  return;
13468
13604
  }
@@ -13865,6 +14001,7 @@ var init_picker = __esm({
13865
14001
  init_session();
13866
14002
  init_hydra_version();
13867
14003
  init_discovery();
14004
+ init_history();
13868
14005
  init_input();
13869
14006
  init_screen();
13870
14007
  init_import_action_prompt();
@@ -15231,6 +15368,7 @@ async function runSession(term, config, target, opts, exitHint, viewPrefs, picke
15231
15368
  }
15232
15369
  });
15233
15370
  screenRef = screen;
15371
+ screen.setStickyBottomKey("plan");
15234
15372
  const builtinCommands = [
15235
15373
  { name: "/help", description: "Show TUI built-in commands" },
15236
15374
  { name: "/quit", description: "Exit the TUI" },
@@ -16269,7 +16407,9 @@ async function runSession(term, config, target, opts, exitHint, viewPrefs, picke
16269
16407
  let toolsBlockEndedAt = null;
16270
16408
  let toolsBlockStopReason = null;
16271
16409
  let lastPlanEvent = null;
16272
- const TOOLS_COLLAPSED_LIMIT = 5;
16410
+ const TOOLS_COLLAPSED_LIMIT = config.tui.maxToolItems;
16411
+ const PLAN_VISIBLE_LIMIT2 = config.tui.maxPlanItems;
16412
+ const formatOptions = { maxPlanItems: PLAN_VISIBLE_LIMIT2 };
16273
16413
  let agentBuffer = "";
16274
16414
  let agentKey = null;
16275
16415
  let agentSeq = 0;
@@ -16336,7 +16476,8 @@ async function runSession(term, config, target, opts, exitHint, viewPrefs, picke
16336
16476
  return;
16337
16477
  }
16338
16478
  const total = toolCallOrder.length;
16339
- const visibleIds = toolsExpanded ? toolCallOrder : toolCallOrder.slice(Math.max(0, total - TOOLS_COLLAPSED_LIMIT));
16479
+ const capped = TOOLS_COLLAPSED_LIMIT > 0;
16480
+ const visibleIds = !capped || toolsExpanded ? toolCallOrder : toolCallOrder.slice(Math.max(0, total - TOOLS_COLLAPSED_LIMIT));
16340
16481
  const hidden = total - visibleIds.length;
16341
16482
  const inProgress = toolsBlockEndedAt === null;
16342
16483
  const end = toolsBlockEndedAt ?? Date.now();
@@ -16355,7 +16496,7 @@ async function runSession(term, config, target, opts, exitHint, viewPrefs, picke
16355
16496
  const noun = total === 1 ? "tool" : "tools";
16356
16497
  const timing = stoppedReason !== null ? stoppedLabel : inProgress ? formatElapsed(elapsed) : `took ${formatElapsed(elapsed)}`;
16357
16498
  const parts = [`${total} ${noun}`, timing];
16358
- if (inProgress) {
16499
+ if (inProgress && capped) {
16359
16500
  if (hidden > 0) {
16360
16501
  parts.push(`${hidden} hidden \u2014 ^O expand`);
16361
16502
  } else if (toolsExpanded && total > TOOLS_COLLAPSED_LIMIT) {
@@ -16581,10 +16722,14 @@ async function runSession(term, config, target, opts, exitHint, viewPrefs, picke
16581
16722
  closeAgentText();
16582
16723
  closeThought();
16583
16724
  lastPlanEvent = event;
16584
- const lines = formatEvent(event);
16725
+ const lines = formatEvent(event, formatOptions);
16585
16726
  if (lines.length > 0) {
16586
- screen.upsertLines("plan", lines);
16727
+ screen.upsertLines("plan", [{ body: "" }, ...lines]);
16587
16728
  }
16729
+ const allComplete = event.entries.length > 0 && event.entries.every(
16730
+ (e) => (e.status ?? "pending") === "completed"
16731
+ );
16732
+ screen.setStickyBottomKey(allComplete ? null : "plan");
16588
16733
  return;
16589
16734
  }
16590
16735
  if (event.kind === "tool-call-update") {
@@ -16620,17 +16765,21 @@ async function runSession(term, config, target, opts, exitHint, viewPrefs, picke
16620
16765
  effectiveStopReason = "error";
16621
16766
  }
16622
16767
  if (lastPlanEvent !== null && effectiveStopReason !== void 0 && effectiveStopReason !== "end_turn") {
16623
- const lines = formatEvent({
16624
- ...lastPlanEvent,
16625
- stopped: true,
16626
- amended: event.amended === true
16627
- });
16768
+ const lines = formatEvent(
16769
+ {
16770
+ ...lastPlanEvent,
16771
+ stopped: true,
16772
+ amended: event.amended === true
16773
+ },
16774
+ formatOptions
16775
+ );
16628
16776
  if (lines.length > 0) {
16629
- screen.upsertLines("plan", lines);
16777
+ screen.upsertLines("plan", [{ body: "" }, ...lines]);
16630
16778
  }
16631
16779
  }
16632
16780
  lastPlanEvent = null;
16633
16781
  screen.clearKey("plan");
16782
+ screen.setStickyBottomKey("plan");
16634
16783
  if (toolsBlockStartedAt !== null) {
16635
16784
  toolsBlockEndedAt = Date.now();
16636
16785
  toolsBlockStopReason = effectiveStopReason ?? null;
package/dist/index.d.ts CHANGED
@@ -153,6 +153,8 @@ declare const HydraConfig: z.ZodObject<{
153
153
  defaultEnterAction: z.ZodDefault<z.ZodEnum<["enqueue", "amend"]>>;
154
154
  showThoughts: z.ZodDefault<z.ZodBoolean>;
155
155
  promptHistoryMaxEntries: z.ZodDefault<z.ZodNumber>;
156
+ maxToolItems: z.ZodDefault<z.ZodNumber>;
157
+ maxPlanItems: z.ZodDefault<z.ZodNumber>;
156
158
  showFileUpdates: z.ZodDefault<z.ZodEnum<["none", "edit", "diff"]>>;
157
159
  }, "strip", z.ZodTypeAny, {
158
160
  repaintThrottleMs: number;
@@ -164,6 +166,8 @@ declare const HydraConfig: z.ZodObject<{
164
166
  defaultEnterAction: "enqueue" | "amend";
165
167
  showThoughts: boolean;
166
168
  promptHistoryMaxEntries: number;
169
+ maxToolItems: number;
170
+ maxPlanItems: number;
167
171
  showFileUpdates: "diff" | "none" | "edit";
168
172
  }, {
169
173
  repaintThrottleMs?: number | undefined;
@@ -175,6 +179,8 @@ declare const HydraConfig: z.ZodObject<{
175
179
  defaultEnterAction?: "enqueue" | "amend" | undefined;
176
180
  showThoughts?: boolean | undefined;
177
181
  promptHistoryMaxEntries?: number | undefined;
182
+ maxToolItems?: number | undefined;
183
+ maxPlanItems?: number | undefined;
178
184
  showFileUpdates?: "diff" | "none" | "edit" | undefined;
179
185
  }>>;
180
186
  }, "strip", z.ZodTypeAny, {
@@ -188,6 +194,8 @@ declare const HydraConfig: z.ZodObject<{
188
194
  defaultEnterAction: "enqueue" | "amend";
189
195
  showThoughts: boolean;
190
196
  promptHistoryMaxEntries: number;
197
+ maxToolItems: number;
198
+ maxPlanItems: number;
191
199
  showFileUpdates: "diff" | "none" | "edit";
192
200
  };
193
201
  daemon: {
@@ -240,6 +248,8 @@ declare const HydraConfig: z.ZodObject<{
240
248
  defaultEnterAction?: "enqueue" | "amend" | undefined;
241
249
  showThoughts?: boolean | undefined;
242
250
  promptHistoryMaxEntries?: number | undefined;
251
+ maxToolItems?: number | undefined;
252
+ maxPlanItems?: number | undefined;
243
253
  showFileUpdates?: "diff" | "none" | "edit" | undefined;
244
254
  } | undefined;
245
255
  daemon?: {
package/dist/index.js CHANGED
@@ -315,6 +315,17 @@ var TuiConfig = z.object({
315
315
  // installs can grow past this — it's enforced at load time and per
316
316
  // append in memory.
317
317
  promptHistoryMaxEntries: z.number().int().positive().default(2e3),
318
+ // Cap on tool rows shown inside the collapsed tools block. When more
319
+ // tools have fired than the cap, only the most recent N are visible
320
+ // and the header advertises "^O expand" so the user can see the rest.
321
+ // 0 disables the cap entirely — every tool row stays visible.
322
+ maxToolItems: z.number().int().nonnegative().default(5),
323
+ // Cap on plan entries rendered before the formatter switches to a
324
+ // sliding window around the active (in_progress / first pending)
325
+ // entry. Counters in the header summarize what's done and what's
326
+ // left when truncation kicks in. 0 disables the cap — every plan
327
+ // entry is rendered.
328
+ maxPlanItems: z.number().int().nonnegative().default(5),
318
329
  // How edit-style tool calls (Edit, Write, str_replace) render in
319
330
  // scrollback, *in addition to* the normal tool row inside the tools
320
331
  // block.
@@ -403,6 +414,8 @@ var HydraConfig = z.object({
403
414
  defaultEnterAction: "amend",
404
415
  showThoughts: true,
405
416
  promptHistoryMaxEntries: 2e3,
417
+ maxToolItems: 5,
418
+ maxPlanItems: 5,
406
419
  showFileUpdates: "edit"
407
420
  })
408
421
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/cli",
3
- "version": "0.1.54",
3
+ "version": "0.1.55",
4
4
  "description": "Multi-client ACP session daemon: spawn agents, attach over WSS, multiplex sessions across editors.",
5
5
  "license": "MIT",
6
6
  "type": "module",