@dreb/coding-agent 2.22.1 → 2.24.0
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 +8 -0
- package/README.md +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +12 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +14 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +4 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +1 -0
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +35 -2
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/copy-selector.d.ts +32 -0
- package/dist/modes/interactive/components/copy-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/copy-selector.js +155 -0
- package/dist/modes/interactive/components/copy-selector.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +89 -9
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/clipboard.d.ts +4 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +12 -2
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/message-text.d.ts +21 -0
- package/dist/utils/message-text.d.ts.map +1 -0
- package/dist/utils/message-text.js +118 -0
- package/dist/utils/message-text.js.map +1 -0
- package/docs/extensions.md +13 -0
- package/docs/keybindings.md +1 -0
- package/package.json +1 -1
|
@@ -28,6 +28,7 @@ import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/cha
|
|
|
28
28
|
import { copyToClipboard } from "../../utils/clipboard.js";
|
|
29
29
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
30
30
|
import { parseGitUrl } from "../../utils/git.js";
|
|
31
|
+
import { extractCopyableText, getMessagePreview, getMessageRoleLabel } from "../../utils/message-text.js";
|
|
31
32
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
32
33
|
import { ArminComponent } from "./components/armin.js";
|
|
33
34
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
@@ -36,6 +37,7 @@ import { BorderedLoader } from "./components/bordered-loader.js";
|
|
|
36
37
|
import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
|
|
37
38
|
import { BuddyComponent } from "./components/buddy-component.js";
|
|
38
39
|
import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
|
|
40
|
+
import { CopySelectorComponent } from "./components/copy-selector.js";
|
|
39
41
|
import { CustomEditor } from "./components/custom-editor.js";
|
|
40
42
|
import { CustomMessageComponent } from "./components/custom-message.js";
|
|
41
43
|
import { DaxnutsComponent } from "./components/daxnuts.js";
|
|
@@ -1711,6 +1713,7 @@ export class InteractiveMode {
|
|
|
1711
1713
|
this.defaultEditor.onAction("app.session.tree", () => this.showTreeSelector());
|
|
1712
1714
|
this.defaultEditor.onAction("app.session.fork", () => this.showUserMessageSelector());
|
|
1713
1715
|
this.defaultEditor.onAction("app.session.resume", () => this.showSessionSelector());
|
|
1716
|
+
this.defaultEditor.onAction("app.clipboard.copyMessages", () => this.showCopySelector());
|
|
1714
1717
|
this.defaultEditor.onChange = (text) => {
|
|
1715
1718
|
const wasBashMode = this.isBashMode;
|
|
1716
1719
|
this.isBashMode = text.trimStart().startsWith("!");
|
|
@@ -2226,6 +2229,33 @@ export class InteractiveMode {
|
|
|
2226
2229
|
this.ui.requestRender();
|
|
2227
2230
|
break;
|
|
2228
2231
|
}
|
|
2232
|
+
case "length_retry": {
|
|
2233
|
+
// Remove the ghost streaming component left from the truncated stream
|
|
2234
|
+
if (this.streamingComponent) {
|
|
2235
|
+
this.chatContainer.removeChild(this.streamingComponent);
|
|
2236
|
+
this.streamingComponent = undefined;
|
|
2237
|
+
this.streamingMessage = undefined;
|
|
2238
|
+
}
|
|
2239
|
+
// Clear any pending tool components from the truncated partial
|
|
2240
|
+
for (const [, component] of this.pendingTools.entries()) {
|
|
2241
|
+
this.chatContainer.removeChild(component);
|
|
2242
|
+
}
|
|
2243
|
+
this.pendingTools.clear();
|
|
2244
|
+
// Show retry status
|
|
2245
|
+
this.statusContainer.clear();
|
|
2246
|
+
if (this.loadingAnimation) {
|
|
2247
|
+
this.loadingAnimation.stop();
|
|
2248
|
+
this.loadingAnimation = undefined;
|
|
2249
|
+
}
|
|
2250
|
+
if (this.retryLoader) {
|
|
2251
|
+
this.retryLoader.stop();
|
|
2252
|
+
this.retryLoader = undefined;
|
|
2253
|
+
}
|
|
2254
|
+
this.retryLoader = new Loader(this.ui, (spinner) => theme.fg("warning", spinner), (text) => theme.fg("muted", text), `Response truncated, retrying with larger token budget (${event.attempt}/${event.maxAttempts})... (${keyText("app.interrupt")} to cancel)`);
|
|
2255
|
+
this.statusContainer.addChild(this.retryLoader);
|
|
2256
|
+
this.ui.requestRender();
|
|
2257
|
+
break;
|
|
2258
|
+
}
|
|
2229
2259
|
case "background_agent_start":
|
|
2230
2260
|
case "background_agent_end": {
|
|
2231
2261
|
this.updateBackgroundAgentStatus();
|
|
@@ -3655,18 +3685,68 @@ export class InteractiveMode {
|
|
|
3655
3685
|
}
|
|
3656
3686
|
}
|
|
3657
3687
|
async handleCopyCommand() {
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3688
|
+
this.showCopySelector();
|
|
3689
|
+
}
|
|
3690
|
+
showCopySelector() {
|
|
3691
|
+
const messages = this.session.messages;
|
|
3692
|
+
if (messages.length === 0) {
|
|
3693
|
+
this.showStatus("No messages to copy");
|
|
3661
3694
|
return;
|
|
3662
3695
|
}
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3696
|
+
// Build items from session messages
|
|
3697
|
+
const items = messages.map((msg, index) => ({
|
|
3698
|
+
index,
|
|
3699
|
+
roleLabel: getMessageRoleLabel(msg),
|
|
3700
|
+
preview: getMessagePreview(msg),
|
|
3701
|
+
}));
|
|
3702
|
+
// Hide buddy while selector is open to free vertical space
|
|
3703
|
+
const hadBuddy = this.buddyComponent !== null;
|
|
3704
|
+
if (hadBuddy) {
|
|
3705
|
+
this.widgetContainerBelow.clear();
|
|
3706
|
+
this.ui.requestRender();
|
|
3669
3707
|
}
|
|
3708
|
+
// Calculate max visible items based on terminal height
|
|
3709
|
+
// Reserve lines for: header(4) + borders(2) + spacers(2) + scroll indicator(1) + footer(1) + padding(2) = ~12 lines overhead
|
|
3710
|
+
const terminalRows = this.ui.terminal.rows;
|
|
3711
|
+
const overhead = 12;
|
|
3712
|
+
const maxVisible = Math.max(3, Math.min(15, terminalRows - overhead));
|
|
3713
|
+
this.showSelector((done) => {
|
|
3714
|
+
const selector = new CopySelectorComponent(items, async (selectedIndices) => {
|
|
3715
|
+
done();
|
|
3716
|
+
// Restore buddy
|
|
3717
|
+
if (hadBuddy)
|
|
3718
|
+
this.renderWidgets();
|
|
3719
|
+
this.ui.requestRender();
|
|
3720
|
+
if (selectedIndices.length === 0) {
|
|
3721
|
+
this.showWarning("No messages selected");
|
|
3722
|
+
return;
|
|
3723
|
+
}
|
|
3724
|
+
// Extract text from selected messages in chronological order
|
|
3725
|
+
const selectedTexts = selectedIndices
|
|
3726
|
+
.map((i) => extractCopyableText(messages[i]))
|
|
3727
|
+
.filter((text) => text.length > 0);
|
|
3728
|
+
if (selectedTexts.length === 0) {
|
|
3729
|
+
this.showWarning("Selected messages have no copyable text");
|
|
3730
|
+
return;
|
|
3731
|
+
}
|
|
3732
|
+
const combined = selectedTexts.join("\n\n---\n\n");
|
|
3733
|
+
const result = await copyToClipboard(combined);
|
|
3734
|
+
const count = selectedTexts.length;
|
|
3735
|
+
if (result.method === "osc52") {
|
|
3736
|
+
this.showStatus(`Sent ${count} message${count === 1 ? "" : "s"} to terminal clipboard (OSC 52)`);
|
|
3737
|
+
}
|
|
3738
|
+
else {
|
|
3739
|
+
this.showStatus(`Copied ${count} message${count === 1 ? "" : "s"} to clipboard`);
|
|
3740
|
+
}
|
|
3741
|
+
}, () => {
|
|
3742
|
+
done();
|
|
3743
|
+
// Restore buddy
|
|
3744
|
+
if (hadBuddy)
|
|
3745
|
+
this.renderWidgets();
|
|
3746
|
+
this.ui.requestRender();
|
|
3747
|
+
}, maxVisible);
|
|
3748
|
+
return { component: selector, focus: selector.getMessageList() };
|
|
3749
|
+
});
|
|
3670
3750
|
}
|
|
3671
3751
|
handleNameCommand(text) {
|
|
3672
3752
|
const name = text.replace(/^\/name\s*/, "").trim();
|