@hydra-acp/cli 0.1.54 → 0.1.56
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 +177 -25
- package/dist/index.d.ts +10 -0
- package/dist/index.js +18 -1
- package/package.json +1 -1
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
|
|
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:
|
|
7400
|
+
body: headerBody,
|
|
7351
7401
|
bodyStyle: headerStyle
|
|
7352
7402
|
}
|
|
7353
7403
|
];
|
|
7354
|
-
for (
|
|
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} ${
|
|
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
|
|
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
|
|
10608
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
16625
|
-
|
|
16626
|
-
|
|
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;
|
|
@@ -24489,8 +24638,11 @@ function registerAcpWsEndpoint(app, deps) {
|
|
|
24489
24638
|
connection.onRequest("session/list", async (raw) => {
|
|
24490
24639
|
const params = SessionListParams.parse(raw ?? {});
|
|
24491
24640
|
const entries = await deps.manager.list({ cwd: params.cwd });
|
|
24641
|
+
const visible = entries.filter(
|
|
24642
|
+
(e) => e.originatingClient?.name !== HYDRA_CAT_CLIENT_NAME
|
|
24643
|
+
);
|
|
24492
24644
|
const result = {
|
|
24493
|
-
sessions:
|
|
24645
|
+
sessions: visible.map(sessionListEntryToWire)
|
|
24494
24646
|
};
|
|
24495
24647
|
return result;
|
|
24496
24648
|
});
|
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
|
});
|
|
@@ -6359,6 +6372,7 @@ function resolveVersion() {
|
|
|
6359
6372
|
return "0.0.0";
|
|
6360
6373
|
}
|
|
6361
6374
|
var HYDRA_VERSION = resolveVersion();
|
|
6375
|
+
var HYDRA_CAT_CLIENT_NAME = "hydra-acp-cat";
|
|
6362
6376
|
|
|
6363
6377
|
// src/core/history-transcript.ts
|
|
6364
6378
|
var DEFAULT_MAX_CHARS = 4e5;
|
|
@@ -12519,8 +12533,11 @@ function registerAcpWsEndpoint(app, deps) {
|
|
|
12519
12533
|
connection.onRequest("session/list", async (raw) => {
|
|
12520
12534
|
const params = SessionListParams.parse(raw ?? {});
|
|
12521
12535
|
const entries = await deps.manager.list({ cwd: params.cwd });
|
|
12536
|
+
const visible = entries.filter(
|
|
12537
|
+
(e) => e.originatingClient?.name !== HYDRA_CAT_CLIENT_NAME
|
|
12538
|
+
);
|
|
12522
12539
|
const result = {
|
|
12523
|
-
sessions:
|
|
12540
|
+
sessions: visible.map(sessionListEntryToWire)
|
|
12524
12541
|
};
|
|
12525
12542
|
return result;
|
|
12526
12543
|
});
|