@kolisachint/hoocode-agent 0.5.55 → 0.5.57
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/CHANGELOG.md +44 -0
- package/dist/core/keybindings.d.ts +12 -12
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +17 -16
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/session-identity.d.ts +11 -0
- package/dist/core/session-identity.d.ts.map +1 -1
- package/dist/core/session-identity.js +16 -0
- package/dist/core/session-identity.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +1 -1
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +1 -1
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/tool-output-view.d.ts +28 -10
- package/dist/core/tool-output-view.d.ts.map +1 -1
- package/dist/core/tool-output-view.js +24 -9
- package/dist/core/tool-output-view.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -2
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/plugins.d.ts.map +1 -1
- package/dist/core/tools/plugins.js +2 -1
- package/dist/core/tools/plugins.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/search.d.ts.map +1 -1
- package/dist/core/tools/search.js +2 -1
- package/dist/core/tools/search.js.map +1 -1
- package/dist/core/tools/webfetch.d.ts.map +1 -1
- package/dist/core/tools/webfetch.js +2 -1
- package/dist/core/tools/webfetch.js.map +1 -1
- package/dist/core/tools/websearch.d.ts.map +1 -1
- package/dist/core/tools/websearch.js +2 -1
- package/dist/core/tools/websearch.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/modes/interactive/command-executor.d.ts.map +1 -1
- package/dist/modes/interactive/command-executor.js +5 -5
- package/dist/modes/interactive/command-executor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +3 -2
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +1 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-chain-summary.d.ts +2 -1
- package/dist/modes/interactive/components/tool-chain-summary.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-chain-summary.js +2 -1
- package/dist/modes/interactive/components/tool-chain-summary.js.map +1 -1
- package/dist/modes/interactive/components/tool-chain.d.ts +2 -9
- package/dist/modes/interactive/components/tool-chain.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-chain.js +3 -20
- package/dist/modes/interactive/components/tool-chain.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +16 -20
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +38 -37
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-signal.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-signal.js +1 -1
- package/dist/modes/interactive/components/tool-signal.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +39 -20
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +77 -69
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/keybindings.md +5 -1
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -4
|
@@ -26,11 +26,12 @@ import { formatTokens } from "../../core/format-tokens.js";
|
|
|
26
26
|
import { KeybindingsManager } from "../../core/keybindings.js";
|
|
27
27
|
import { measurePromptSurface, measureToolSchemaTokens } from "../../core/light.js";
|
|
28
28
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
29
|
+
import { cycleSessionColorSlot, sessionColorName } from "../../core/session-identity.js";
|
|
29
30
|
import { SessionManager } from "../../core/session-manager.js";
|
|
30
31
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
31
32
|
import { startupProgress } from "../../core/startup-progress.js";
|
|
32
33
|
import { taskStore } from "../../core/task-store.js";
|
|
33
|
-
import { cycleToolOutputView } from "../../core/tool-output-view.js";
|
|
34
|
+
import { cycleToolOutputView, DEFAULT_TOOL_OUTPUT_VIEW, MAX_TOOL_OUTPUT_VIEW, } from "../../core/tool-output-view.js";
|
|
34
35
|
import { settleDanglingMainTasks } from "../../core/tools/todo.js";
|
|
35
36
|
import { buildCompactWordmark } from "../../core/wordmark.js";
|
|
36
37
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
@@ -201,10 +202,21 @@ export class InteractiveMode {
|
|
|
201
202
|
});
|
|
202
203
|
// Tool execution tracking: toolCallId -> component
|
|
203
204
|
pendingTools = new Map();
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
//
|
|
207
|
-
|
|
205
|
+
// Persisted view dial (radar / peek / full). See core/tool-output-view.ts.
|
|
206
|
+
toolOutputView = DEFAULT_TOOL_OUTPUT_VIEW;
|
|
207
|
+
// Where `app.tools.expand` came from, so the same key goes back there. Kept
|
|
208
|
+
// in memory only: the jump is the momentary look, the dial is the decision.
|
|
209
|
+
viewBeforeJump;
|
|
210
|
+
/**
|
|
211
|
+
* Whether everything foldable is currently open.
|
|
212
|
+
*
|
|
213
|
+
* Not a state of its own any more — it is the top of the view dial. The
|
|
214
|
+
* header, compaction and branch summaries and skill blocks follow the dial
|
|
215
|
+
* for the same reason tool bodies do: `full` means nothing is held back.
|
|
216
|
+
*/
|
|
217
|
+
get toolOutputExpanded() {
|
|
218
|
+
return this.toolOutputView === MAX_TOOL_OUTPUT_VIEW;
|
|
219
|
+
}
|
|
208
220
|
// The chain currently collecting tool calls, if the agent is mid-run.
|
|
209
221
|
openChain;
|
|
210
222
|
/** The newest tool block in the transcript; radar marks it. */
|
|
@@ -707,9 +719,8 @@ export class InteractiveMode {
|
|
|
707
719
|
hint("app.thinking.cycle", "to cycle thinking level"),
|
|
708
720
|
rawKeyHint(`${keyText("app.model.cycleForward")}/${keyText("app.model.cycleBackward")}`, "to cycle models"),
|
|
709
721
|
hint("app.model.select", "to select model"),
|
|
710
|
-
hint("app.tools.expand", "to
|
|
711
|
-
hint("app.
|
|
712
|
-
hint("app.view.cycleForward", "to cycle tool output (radar/glance/full)"),
|
|
722
|
+
hint("app.tools.expand", "to jump to full output and back"),
|
|
723
|
+
hint("app.view.cycleForward", "to cycle tool output (radar/peek/full)"),
|
|
713
724
|
hint("app.thinking.toggle", "to expand thinking"),
|
|
714
725
|
hint("app.tasks.cycleView", "to cycle task panel view"),
|
|
715
726
|
...(this.teamFocus.connected ? [hint("app.team.focus", "to focus team roster")] : []),
|
|
@@ -1505,11 +1516,9 @@ export class InteractiveMode {
|
|
|
1505
1516
|
// Global debug handler on TUI (works regardless of focus)
|
|
1506
1517
|
this.ui.onDebug = () => this.commandExecutor.handleDebug();
|
|
1507
1518
|
this.defaultEditor.onAction("app.model.select", () => this.modelController.showModelSelector());
|
|
1508
|
-
this.defaultEditor.onAction("app.tools.expand", () => this.
|
|
1519
|
+
this.defaultEditor.onAction("app.tools.expand", () => this.jumpToFullView());
|
|
1509
1520
|
this.defaultEditor.onAction("app.view.cycleForward", () => this.cycleToolOutputView("forward"));
|
|
1510
1521
|
this.defaultEditor.onAction("app.view.cycleBackward", () => this.cycleToolOutputView("backward"));
|
|
1511
|
-
this.defaultEditor.onAction("app.tools.unfoldOne", () => this.stepToolOutput("unfold"));
|
|
1512
|
-
this.defaultEditor.onAction("app.tools.foldOne", () => this.stepToolOutput("fold"));
|
|
1513
1522
|
this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
|
|
1514
1523
|
this.defaultEditor.onAction("app.tasks.cycleView", () => {
|
|
1515
1524
|
this.taskPanel.cycleView();
|
|
@@ -1529,6 +1538,8 @@ export class InteractiveMode {
|
|
|
1529
1538
|
this.editor.setText("/cd ");
|
|
1530
1539
|
this.ui.requestRender();
|
|
1531
1540
|
});
|
|
1541
|
+
this.defaultEditor.onAction("app.session.color.cycleForward", () => this.cycleSessionColor("forward"));
|
|
1542
|
+
this.defaultEditor.onAction("app.session.color.cycleBackward", () => this.cycleSessionColor("backward"));
|
|
1532
1543
|
this.defaultEditor.onAction("app.settings.open", () => this.showSettingsSelector());
|
|
1533
1544
|
this.defaultEditor.onAction("app.hotkeys.open", () => this.commandExecutor.handleHotkeys());
|
|
1534
1545
|
this.defaultEditor.onAction("app.mode.cycle", () => void this.cycleAgentMode());
|
|
@@ -2019,7 +2030,6 @@ export class InteractiveMode {
|
|
|
2019
2030
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
2020
2031
|
view: this.toolOutputView,
|
|
2021
2032
|
}, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
|
|
2022
|
-
component.setExpanded(this.toolOutputExpanded);
|
|
2023
2033
|
this.attachToolBlock(component);
|
|
2024
2034
|
this.pendingTools.set(content.id, component);
|
|
2025
2035
|
}
|
|
@@ -2086,7 +2096,6 @@ export class InteractiveMode {
|
|
|
2086
2096
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
2087
2097
|
view: this.toolOutputView,
|
|
2088
2098
|
}, this.getRegisteredToolDefinition(event.toolName), this.ui, this.sessionManager.getCwd());
|
|
2089
|
-
component.setExpanded(this.toolOutputExpanded);
|
|
2090
2099
|
this.attachToolBlock(component);
|
|
2091
2100
|
this.pendingTools.set(event.toolCallId, component);
|
|
2092
2101
|
}
|
|
@@ -2385,7 +2394,6 @@ export class InteractiveMode {
|
|
|
2385
2394
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
2386
2395
|
view: this.toolOutputView,
|
|
2387
2396
|
}, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
|
|
2388
|
-
component.setExpanded(this.toolOutputExpanded);
|
|
2389
2397
|
this.attachToolBlock(component);
|
|
2390
2398
|
if (message.stopReason === "aborted" || message.stopReason === "error") {
|
|
2391
2399
|
let errorMessage;
|
|
@@ -2711,66 +2719,35 @@ export class InteractiveMode {
|
|
|
2711
2719
|
}
|
|
2712
2720
|
return blocks;
|
|
2713
2721
|
}
|
|
2714
|
-
/** Every chain in the transcript, in order. */
|
|
2715
|
-
transcriptChains() {
|
|
2716
|
-
return this.chatContainer.children.filter((child) => child instanceof ToolChainComponent);
|
|
2717
|
-
}
|
|
2718
|
-
toggleToolOutputExpansion() {
|
|
2719
|
-
this.setToolsExpanded(!this.toolOutputExpanded);
|
|
2720
|
-
}
|
|
2721
2722
|
/**
|
|
2722
|
-
*
|
|
2723
|
+
* Jump to the full view, or back to where the jump started.
|
|
2723
2724
|
*
|
|
2724
|
-
*
|
|
2725
|
-
*
|
|
2726
|
-
*
|
|
2727
|
-
*
|
|
2725
|
+
* The dial's top stop is the whole result with nothing trimmed, which is what
|
|
2726
|
+
* "expand" always meant — so expand is not a second state layered over the
|
|
2727
|
+
* dial any more, it is a jump along it. From any stop the first press lands
|
|
2728
|
+
* on `full`; the next press returns to the stop you came from (`peek` if the
|
|
2729
|
+
* jump started there, so the key is never a no-op).
|
|
2728
2730
|
*
|
|
2729
|
-
*
|
|
2730
|
-
*
|
|
2731
|
-
* scrolling — anything far enough up is in the terminal's own scrollback,
|
|
2732
|
-
* where this process cannot put a cursor or scroll to a selection. So the
|
|
2733
|
-
* key peels backwards through what is actually on screen, and each block it
|
|
2734
|
-
* opens is its own marker for where you have got to.
|
|
2731
|
+
* Only `app.view.cycleForward` writes the setting. This key deliberately does
|
|
2732
|
+
* not: the dial is the decision you keep, the jump is the look you take.
|
|
2735
2733
|
*/
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
if (this.toolOutputView === "radar") {
|
|
2742
|
-
const chains = this.transcriptChains();
|
|
2743
|
-
for (let i = chains.length - 1; i >= 0; i--) {
|
|
2744
|
-
if (chains[i].isEmpty || chains[i].isOpened === wantOpen)
|
|
2745
|
-
continue;
|
|
2746
|
-
// A chain of one is never summarised, so there is nothing for unfold to
|
|
2747
|
-
// reveal; skipping it keeps the press moving to a chain that will change.
|
|
2748
|
-
if (wantOpen && !chains[i].isSummarised)
|
|
2749
|
-
continue;
|
|
2750
|
-
chains[i].setOpened(wantOpen);
|
|
2751
|
-
this.ui.requestRender();
|
|
2752
|
-
return;
|
|
2753
|
-
}
|
|
2754
|
-
this.showStatus(wantOpen ? "No collapsed chains below this point" : "No open chains below this point");
|
|
2734
|
+
jumpToFullView() {
|
|
2735
|
+
if (this.toolOutputView === MAX_TOOL_OUTPUT_VIEW) {
|
|
2736
|
+
const back = this.viewBeforeJump ?? DEFAULT_TOOL_OUTPUT_VIEW;
|
|
2737
|
+
this.viewBeforeJump = undefined;
|
|
2738
|
+
this.applyToolOutputView(back, { persist: false });
|
|
2755
2739
|
return;
|
|
2756
2740
|
}
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
const block = blocks[i];
|
|
2760
|
-
if (block.isRevealed() === wantOpen)
|
|
2761
|
-
continue;
|
|
2762
|
-
block.setExpanded(wantOpen);
|
|
2763
|
-
this.ui.requestRender();
|
|
2764
|
-
return;
|
|
2765
|
-
}
|
|
2766
|
-
this.showStatus(wantOpen ? "No folded tool output below this point" : "No unfolded tool output below this point");
|
|
2741
|
+
this.viewBeforeJump = this.toolOutputView;
|
|
2742
|
+
this.applyToolOutputView(MAX_TOOL_OUTPUT_VIEW, { persist: false });
|
|
2767
2743
|
}
|
|
2768
2744
|
/**
|
|
2769
|
-
* Move the view dial one stop
|
|
2745
|
+
* Move the view dial one stop; the footer shows where it landed.
|
|
2770
2746
|
*
|
|
2771
|
-
*
|
|
2772
|
-
*
|
|
2773
|
-
*
|
|
2747
|
+
* This is the persistent decision ("how much do I ever want to see"), which
|
|
2748
|
+
* is why it saves. `app.tools.expand` jumps along the same dial without
|
|
2749
|
+
* saving, which is what keeps "the look I am taking now" from overwriting
|
|
2750
|
+
* "the view I live in".
|
|
2774
2751
|
*/
|
|
2775
2752
|
cycleToolOutputView(direction) {
|
|
2776
2753
|
const next = cycleToolOutputView(this.toolOutputView, direction);
|
|
@@ -2799,10 +2776,17 @@ export class InteractiveMode {
|
|
|
2799
2776
|
return "omit";
|
|
2800
2777
|
return this.hideThinkingBlock ? "label" : "full";
|
|
2801
2778
|
}
|
|
2802
|
-
applyToolOutputView(view) {
|
|
2779
|
+
applyToolOutputView(view, options = {}) {
|
|
2803
2780
|
const previousThinking = this.thinkingDisplayForView();
|
|
2781
|
+
const wasExpanded = this.toolOutputExpanded;
|
|
2804
2782
|
this.toolOutputView = view;
|
|
2805
|
-
|
|
2783
|
+
if (options.persist !== false) {
|
|
2784
|
+
this.settingsManager.setToolOutputView(view);
|
|
2785
|
+
// Anything that moves the dial deliberately — the cycle key, the
|
|
2786
|
+
// settings pane — is a new home stop, so the jump has nowhere stale to
|
|
2787
|
+
// return to.
|
|
2788
|
+
this.viewBeforeJump = undefined;
|
|
2789
|
+
}
|
|
2806
2790
|
this.footer.setToolOutputView(view);
|
|
2807
2791
|
const thinking = this.thinkingDisplayForView();
|
|
2808
2792
|
for (const child of this.chatContainer.children) {
|
|
@@ -2817,10 +2801,18 @@ export class InteractiveMode {
|
|
|
2817
2801
|
if (this.streamingComponent && thinking !== previousThinking) {
|
|
2818
2802
|
this.streamingComponent.setThinkingDisplay(thinking);
|
|
2819
2803
|
}
|
|
2804
|
+
// The header and the summary blocks are not tool output, but "full" means
|
|
2805
|
+
// nothing is held back, so they open and close with the dial's top stop.
|
|
2806
|
+
if (this.toolOutputExpanded !== wasExpanded)
|
|
2807
|
+
this.setToolsExpanded(this.toolOutputExpanded);
|
|
2820
2808
|
this.ui.requestRender();
|
|
2821
2809
|
}
|
|
2810
|
+
/**
|
|
2811
|
+
* Open or close everything that folds but is not a tool call — the header,
|
|
2812
|
+
* compaction and branch summaries, skill blocks. Tool blocks and chains are
|
|
2813
|
+
* not in this sweep: they take the view dial directly.
|
|
2814
|
+
*/
|
|
2822
2815
|
setToolsExpanded(expanded) {
|
|
2823
|
-
this.toolOutputExpanded = expanded;
|
|
2824
2816
|
const activeHeader = this.chrome.customHeader ?? this.builtInHeader;
|
|
2825
2817
|
if (isExpandable(activeHeader)) {
|
|
2826
2818
|
activeHeader.setExpanded(expanded);
|
|
@@ -2859,6 +2851,22 @@ export class InteractiveMode {
|
|
|
2859
2851
|
const next = modes[(index + 1) % modes.length];
|
|
2860
2852
|
await this.session.prompt(`/mode ${next}`);
|
|
2861
2853
|
}
|
|
2854
|
+
/**
|
|
2855
|
+
* Step the session chip to the next colour slot, no picker involved.
|
|
2856
|
+
*
|
|
2857
|
+
* The picker exists for choosing a colour; this exists for telling two
|
|
2858
|
+
* terminals apart, which is a different job — you press the key until the two
|
|
2859
|
+
* chips stop looking alike, and the chip repaints on each press because
|
|
2860
|
+
* setSessionColor writes the slot and the session_info event refreshes the
|
|
2861
|
+
* identity. The status line names the slot as well, since the point of the
|
|
2862
|
+
* names is that `/color <name>` takes them.
|
|
2863
|
+
*/
|
|
2864
|
+
cycleSessionColor(direction) {
|
|
2865
|
+
const slot = cycleSessionColorSlot(this.sessionManager.getSessionColorSlot(), direction);
|
|
2866
|
+
this.session.setSessionColor(slot);
|
|
2867
|
+
const name = sessionColorName(slot);
|
|
2868
|
+
this.showStatus(`Session color: ${name ?? slot}`);
|
|
2869
|
+
}
|
|
2862
2870
|
toggleThinkingBlockVisibility() {
|
|
2863
2871
|
this.hideThinkingBlock = !this.hideThinkingBlock;
|
|
2864
2872
|
this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
|
|
@@ -3522,7 +3530,7 @@ export class InteractiveMode {
|
|
|
3522
3530
|
const selector = new SessionColorSelectorComponent(this.sessionManager.getDisplayName(), originalSlot, (slot) => {
|
|
3523
3531
|
done();
|
|
3524
3532
|
this.session.setSessionColor(slot);
|
|
3525
|
-
this.showStatus(`Session color
|
|
3533
|
+
this.showStatus(`Session color: ${sessionColorName(slot) ?? slot}`);
|
|
3526
3534
|
}, () => {
|
|
3527
3535
|
done();
|
|
3528
3536
|
// Cancelling must put back the colour the session actually has,
|