@meistrari/remy-cli 1.25.0-rc.3 → 1.25.0-rc.5
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/README.md +3 -1
- package/dist/remy.js +282 -252
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,12 +56,14 @@ Press `n` in the dashboard. The new-session flow asks what you want done, select
|
|
|
56
56
|
|
|
57
57
|
On the final review, press `c` to choose MCP servers. Arrows move, Space toggles optional servers, `s` searches, `r` refreshes, and Enter returns to review. Escape clears an active search before returning to review. Servers always included for CLI sessions are locked; unavailable optional connections cannot be added. Previously selected servers that disappear remain visible until you remove them. Catalog failures block creation: open the picker and press `r` to retry without losing your prompt.
|
|
58
58
|
|
|
59
|
-
Use `Tab` while writing the request to complete a local file or directory path. Path suggestions use the same highlighted list as command autocomplete, with File/Directory labels and a menu sized to the terminal; arrows move, Enter accepts, Tab cycles, and Esc dismisses. Remy attaches selected paths when you confirm the request. You can also paste an absolute path directly; quote paths containing spaces (for example, `"/Users/me/Desktop/Screen Shot.png"`) or use shell-style backslash escapes. Autocomplete selection is not required. Each file may be at most 20 MiB. A directory may contain at most 20 MiB across its regular files before compression; Remy uploads it as a temporary `<directory>.tar.gz` archive with the selected directory preserved as its root, so the remote agent can extract and use its files.
|
|
59
|
+
Use `Tab` while writing the request to complete a local file or directory path. Path suggestions use the same highlighted list as command autocomplete, with File/Directory labels and a menu sized to the terminal; arrows move, Enter accepts, Tab cycles, and Esc dismisses. Remy attaches selected paths when you confirm the request. You can also paste an absolute path directly; quote paths containing spaces (for example, `"/Users/me/Desktop/Screen Shot.png"`) or use shell-style backslash escapes. Autocomplete selection is not required. Each file may be at most 20 MiB. A directory may contain at most 20 MiB across its regular files before compression; Remy uploads it as a temporary `<directory>.tar.gz` archive with the selected directory preserved as its root, so the remote agent can extract and use its files. Prompt-path attachments are best-effort: missing, unreadable, oversized or unsupported paths and failed uploads are skipped, and the original message is sent with whichever attachments succeeded. This includes paths selected with Tab or inserted from the clipboard. A non-blocking notice names files skipped during preparation or upload, including selected files that disappeared. When creating a session, the notice carries into the conversation; unrecognized, unselected prose remains quiet. Slashes in ordinary prose do not make attachment errors block your message. Directory archives never follow symbolic links or include other non-regular entries. On macOS, `Ctrl+V` saves a clipboard image as a temporary PNG and adds its path to the request; Remy attaches it on confirmation. Remy uploads attachments before creating the session and shows their filenames beneath your message.
|
|
60
60
|
|
|
61
61
|
In a session, `Esc` dismisses open command/path suggestions or help before it can stop an active turn. Long suggestion labels may be shortened on screen; accepting one inserts the complete value. `/changes` opens read-only workspace Changes; `/workspace` opens its repository Files tree. `/files` or `Ctrl+F` remains the published-file and attachment picker. In the workspace browser, arrows or `j`/`k` navigate, Enter opens a loaded entry (deleted Changes rows open their old-side diff), `s` searches loaded entries, and `r` refreshes. In a file or diff, `g` goes to a line, Space anchors a range, `a` stages captured lines for the next message, `o`/`n` chooses the old/new side, `e` expands verified full context, `w` changes diff scope, `v` switches file/diff, and `d` downloads current regular-file bytes to `~/Downloads`; this is a fresh read and may differ from the displayed capture, not a snapshot export. Esc unwinds search, selection, and navigation before returning with the composer draft intact; returning from a viewer restores the originating list row when it remains available. Up to five contexts can be staged; each range is limited to 200 lines and 12,000 characters. Stale or unavailable captures cannot be staged. Valid human-message workspace trailers display compact repository/path/line references by default; `Ctrl+O` expands the original text. `/context` reviews or removes staged references before sending. The full captured text remains in the canonical message, and malformed trailers display as ordinary text.
|
|
62
62
|
|
|
63
63
|
Opening the workspace browser while a message is being submitted does not discard that attempt. When you return, a failed submission remains available with `Ctrl+R`; retry preserves its original text, captured context, attachments, settings, and request identity. This recovery lasts for the current attached session, not across CLI restarts.
|
|
64
64
|
|
|
65
|
+
The new-session request and conversation composers share path completion and attachment selection. `Tab` completes the path prefix immediately before the cursor, preserving the text after it; accepting a suggestion leaves the cursor at the inserted path, including with joined emoji, combining accents, and wide characters. Restored drafts, history, and search queries also place the cursor at the end of the actual text. Suggestions stay above the input on compact terminals. In the new-session wizard, long drafts scroll within the remaining input space so suggestions and both input dividers remain visible. Editing the draft dismisses the old suggestions, and `Esc` also cancels a lookup that is still loading. A lookup discarded after cursor movement does not consume the next `Esc`. Session commands and previous-message history are available in the conversation composer.
|
|
66
|
+
|
|
65
67
|
### Resume or follow up
|
|
66
68
|
|
|
67
69
|
Every terminal follow-up is appended as an explicit **Steer**, so it targets the work currently in progress. Queuing a message for a later turn (**Next**) is Web-only for now. Remy can replay sessions containing queued-message dispatch, withdrawal, and failure events. Messages withdrawn or failed before reaching Remy show an activity notice; an active submission ends as cancelled or failed instead of waiting for a turn that never started.
|
package/dist/remy.js
CHANGED
|
@@ -34592,7 +34592,7 @@ function formatSessionJson({
|
|
|
34592
34592
|
`;
|
|
34593
34593
|
}
|
|
34594
34594
|
// src/version.ts
|
|
34595
|
-
var remyCliVersion = "1.25.0-rc.
|
|
34595
|
+
var remyCliVersion = "1.25.0-rc.5";
|
|
34596
34596
|
|
|
34597
34597
|
// src/self-update.ts
|
|
34598
34598
|
import { spawn } from "child_process";
|
|
@@ -39610,8 +39610,8 @@ function completionMenuRows(terminalHeight) {
|
|
|
39610
39610
|
}
|
|
39611
39611
|
|
|
39612
39612
|
// src/tui/composer-height.ts
|
|
39613
|
-
function resizeComposer(composer) {
|
|
39614
|
-
composer.height = Math.min(Math.max(composer.editorView.getTotalVirtualLineCount(), 1), TUI_LAYOUT.composerMaxRows);
|
|
39613
|
+
function resizeComposer(composer, availableRows = TUI_LAYOUT.composerMaxRows) {
|
|
39614
|
+
composer.height = Math.min(Math.max(composer.editorView.getTotalVirtualLineCount(), 1), TUI_LAYOUT.composerMaxRows, Math.max(1, availableRows));
|
|
39615
39615
|
}
|
|
39616
39616
|
|
|
39617
39617
|
// src/tui/composer.ts
|
|
@@ -39688,6 +39688,10 @@ function createComposer({
|
|
|
39688
39688
|
}
|
|
39689
39689
|
};
|
|
39690
39690
|
}
|
|
39691
|
+
function setComposerText(editor, text) {
|
|
39692
|
+
editor.setText(text);
|
|
39693
|
+
editor.gotoBufferEnd();
|
|
39694
|
+
}
|
|
39691
39695
|
|
|
39692
39696
|
// src/tui/key-hints.ts
|
|
39693
39697
|
import { dim as dim3, fg as fg4, StyledText as StyledText5 } from "@opentui/core";
|
|
@@ -40744,7 +40748,7 @@ async function createDashboardTui({
|
|
|
40744
40748
|
render();
|
|
40745
40749
|
}, openSessionSearch = function() {
|
|
40746
40750
|
sessionSearchOpen = true;
|
|
40747
|
-
sessionSearchComposer.textarea
|
|
40751
|
+
setComposerText(sessionSearchComposer.textarea, sessionSearchQuery);
|
|
40748
40752
|
render();
|
|
40749
40753
|
}, applySessionSearch = function() {
|
|
40750
40754
|
if (!sessionSearchOpen)
|
|
@@ -41463,6 +41467,9 @@ function renderFeedback(feedback) {
|
|
|
41463
41467
|
function attachmentUploadMessage(filenames) {
|
|
41464
41468
|
return filenames.length === 1 ? `Attaching ${filenames[0]}\u2026` : `Attaching ${filenames.length} files\u2026`;
|
|
41465
41469
|
}
|
|
41470
|
+
function attachmentSkippedMessage(filenames) {
|
|
41471
|
+
return `Continuing without attachments: ${filenames.map(terminalSafeText).join(", ")}.`;
|
|
41472
|
+
}
|
|
41466
41473
|
function renderAttachmentFeedback(feedback) {
|
|
41467
41474
|
return renderFeedback(feedback);
|
|
41468
41475
|
}
|
|
@@ -41481,52 +41488,6 @@ function renderAttachmentSummary(attachments) {
|
|
|
41481
41488
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
41482
41489
|
var SPINNER_INTERVAL_MS = 80;
|
|
41483
41490
|
|
|
41484
|
-
// src/tui/completion-menu.ts
|
|
41485
|
-
import { dim as dim5, fg as fg10, StyledText as StyledText9 } from "@opentui/core";
|
|
41486
|
-
function renderCompletionMenu({ items, selectedIndex, hints, width, maxRows }) {
|
|
41487
|
-
if (items.length === 0)
|
|
41488
|
-
return;
|
|
41489
|
-
const hint = renderKeyHints({ hints, width });
|
|
41490
|
-
const hintRows = hint.chunks.map((chunk) => chunk.text).join("").split(`
|
|
41491
|
-
`).length;
|
|
41492
|
-
const optionBudget = Math.max(1, maxRows - hintRows);
|
|
41493
|
-
const showCount = items.length > Math.min(TUI_LAYOUT.completionMaxOptions, optionBudget) && optionBudget > 1;
|
|
41494
|
-
const maximumVisibleCompletions = Math.min(TUI_LAYOUT.completionMaxOptions, optionBudget - (showCount ? 1 : 0));
|
|
41495
|
-
const firstIndex = Math.min(Math.max(0, selectedIndex - Math.floor(maximumVisibleCompletions / 2)), Math.max(0, items.length - maximumVisibleCompletions));
|
|
41496
|
-
const visibleItems = items.slice(firstIndex, firstIndex + maximumVisibleCompletions);
|
|
41497
|
-
const naturalLabelWidth = Math.max(...items.map((item) => Bun.stringWidth(item.label))) + 2;
|
|
41498
|
-
const descriptionBudget = Math.max(0, width - 2 - Math.min(naturalLabelWidth, Math.floor(width * 0.6)));
|
|
41499
|
-
const descriptionWidth = width >= 30 ? Math.min(descriptionBudget, Math.max(...items.map((item) => Bun.stringWidth(item.description)))) : 0;
|
|
41500
|
-
const labelWidth = Math.max(0, Math.min(naturalLabelWidth, width - 2 - descriptionWidth));
|
|
41501
|
-
const rows = visibleItems.map((item, index) => {
|
|
41502
|
-
const selected = firstIndex + index === selectedIndex;
|
|
41503
|
-
const chunks = [
|
|
41504
|
-
fg10(PALETTE.remyAccent)(`${selected ? "\u203A " : " "}${padText(truncateText(item.label, labelWidth - 2), labelWidth)}`),
|
|
41505
|
-
fg10(PALETTE.dimText)(truncateText(item.description, descriptionWidth))
|
|
41506
|
-
];
|
|
41507
|
-
return new StyledText9(highlightSelection({ chunks, cursor: selected }));
|
|
41508
|
-
});
|
|
41509
|
-
if (showCount && items.length > visibleItems.length)
|
|
41510
|
-
rows.push(new StyledText9([dim5(fg10(PALETTE.dimText)(`${firstIndex + 1}-${firstIndex + visibleItems.length} of ${items.length}`))]));
|
|
41511
|
-
rows.push(hint);
|
|
41512
|
-
return joinStyled(rows, `
|
|
41513
|
-
`);
|
|
41514
|
-
}
|
|
41515
|
-
|
|
41516
|
-
// src/tui/path-completion-menu.ts
|
|
41517
|
-
function renderPathCompletionMenu({ completions, selectedIndex, width, maxRows }) {
|
|
41518
|
-
return renderCompletionMenu({
|
|
41519
|
-
items: completions.map((completion) => ({
|
|
41520
|
-
label: completion.display,
|
|
41521
|
-
description: completion.display.endsWith("/") ? "Directory" : "File"
|
|
41522
|
-
})),
|
|
41523
|
-
selectedIndex,
|
|
41524
|
-
hints: [{ key: "\u2191\u2193", action: "select" }, { key: "Enter", action: "accepts" }, { key: "Tab", action: "next" }, { key: "Esc", action: "dismiss" }],
|
|
41525
|
-
width,
|
|
41526
|
-
maxRows
|
|
41527
|
-
});
|
|
41528
|
-
}
|
|
41529
|
-
|
|
41530
41491
|
// src/tui/path-completion.ts
|
|
41531
41492
|
import { readdir } from "fs/promises";
|
|
41532
41493
|
import { homedir } from "os";
|
|
@@ -41615,6 +41576,163 @@ function activePathToken(text) {
|
|
|
41615
41576
|
return match?.[1];
|
|
41616
41577
|
}
|
|
41617
41578
|
|
|
41579
|
+
// src/tui/completion-menu.ts
|
|
41580
|
+
import { dim as dim5, fg as fg10, StyledText as StyledText9 } from "@opentui/core";
|
|
41581
|
+
function renderCompletionMenu({ items, selectedIndex, hints, width, maxRows }) {
|
|
41582
|
+
if (items.length === 0)
|
|
41583
|
+
return;
|
|
41584
|
+
const hint = renderKeyHints({ hints, width });
|
|
41585
|
+
const hintRows = hint.chunks.map((chunk) => chunk.text).join("").split(`
|
|
41586
|
+
`).length;
|
|
41587
|
+
const optionBudget = Math.max(1, maxRows - hintRows);
|
|
41588
|
+
const showCount = items.length > Math.min(TUI_LAYOUT.completionMaxOptions, optionBudget) && optionBudget > 1;
|
|
41589
|
+
const maximumVisibleCompletions = Math.min(TUI_LAYOUT.completionMaxOptions, optionBudget - (showCount ? 1 : 0));
|
|
41590
|
+
const firstIndex = Math.min(Math.max(0, selectedIndex - Math.floor(maximumVisibleCompletions / 2)), Math.max(0, items.length - maximumVisibleCompletions));
|
|
41591
|
+
const visibleItems = items.slice(firstIndex, firstIndex + maximumVisibleCompletions);
|
|
41592
|
+
const naturalLabelWidth = Math.max(...items.map((item) => Bun.stringWidth(item.label))) + 2;
|
|
41593
|
+
const descriptionBudget = Math.max(0, width - 2 - Math.min(naturalLabelWidth, Math.floor(width * 0.6)));
|
|
41594
|
+
const descriptionWidth = width >= 30 ? Math.min(descriptionBudget, Math.max(...items.map((item) => Bun.stringWidth(item.description)))) : 0;
|
|
41595
|
+
const labelWidth = Math.max(0, Math.min(naturalLabelWidth, width - 2 - descriptionWidth));
|
|
41596
|
+
const rows = visibleItems.map((item, index) => {
|
|
41597
|
+
const selected = firstIndex + index === selectedIndex;
|
|
41598
|
+
const chunks = [
|
|
41599
|
+
fg10(PALETTE.remyAccent)(`${selected ? "\u203A " : " "}${padText(truncateText(item.label, labelWidth - 2), labelWidth)}`),
|
|
41600
|
+
fg10(PALETTE.dimText)(truncateText(item.description, descriptionWidth))
|
|
41601
|
+
];
|
|
41602
|
+
return new StyledText9(highlightSelection({ chunks, cursor: selected }));
|
|
41603
|
+
});
|
|
41604
|
+
if (showCount && items.length > visibleItems.length)
|
|
41605
|
+
rows.push(new StyledText9([dim5(fg10(PALETTE.dimText)(`${firstIndex + 1}-${firstIndex + visibleItems.length} of ${items.length}`))]));
|
|
41606
|
+
rows.push(hint);
|
|
41607
|
+
return joinStyled(rows, `
|
|
41608
|
+
`);
|
|
41609
|
+
}
|
|
41610
|
+
|
|
41611
|
+
// src/tui/path-completion-menu.ts
|
|
41612
|
+
function renderPathCompletionMenu({ completions, selectedIndex, width, maxRows }) {
|
|
41613
|
+
return renderCompletionMenu({
|
|
41614
|
+
items: completions.map((completion) => ({
|
|
41615
|
+
label: completion.display,
|
|
41616
|
+
description: completion.display.endsWith("/") ? "Directory" : "File"
|
|
41617
|
+
})),
|
|
41618
|
+
selectedIndex,
|
|
41619
|
+
hints: [{ key: "\u2191\u2193", action: "select" }, { key: "Enter", action: "accepts" }, { key: "Tab", action: "next" }, { key: "Esc", action: "dismiss" }],
|
|
41620
|
+
width,
|
|
41621
|
+
maxRows
|
|
41622
|
+
});
|
|
41623
|
+
}
|
|
41624
|
+
|
|
41625
|
+
// src/tui/composer-paths.ts
|
|
41626
|
+
function createComposerPaths({
|
|
41627
|
+
editor,
|
|
41628
|
+
cwd,
|
|
41629
|
+
isActive,
|
|
41630
|
+
onChange
|
|
41631
|
+
}) {
|
|
41632
|
+
let previousText = editor.plainText;
|
|
41633
|
+
let selections = [];
|
|
41634
|
+
let completions = [];
|
|
41635
|
+
let selectedIndex = 0;
|
|
41636
|
+
let request;
|
|
41637
|
+
function dismiss() {
|
|
41638
|
+
const wasOpen = request !== undefined;
|
|
41639
|
+
request = undefined;
|
|
41640
|
+
completions = [];
|
|
41641
|
+
return wasOpen;
|
|
41642
|
+
}
|
|
41643
|
+
function matchesEditor(snapshot) {
|
|
41644
|
+
return isActive() && editor.plainText === snapshot.text && editor.cursorOffset === snapshot.cursor;
|
|
41645
|
+
}
|
|
41646
|
+
async function open5() {
|
|
41647
|
+
const snapshot = { text: editor.plainText, cursor: editor.cursorOffset };
|
|
41648
|
+
request = snapshot;
|
|
41649
|
+
const candidates = await completePathToken({ text: editor.editBuffer.getTextRange(0, snapshot.cursor), cwd });
|
|
41650
|
+
if (request !== snapshot)
|
|
41651
|
+
return;
|
|
41652
|
+
if (!matchesEditor(snapshot)) {
|
|
41653
|
+
dismiss();
|
|
41654
|
+
return;
|
|
41655
|
+
}
|
|
41656
|
+
completions = candidates;
|
|
41657
|
+
selectedIndex = 0;
|
|
41658
|
+
if (candidates.length === 0)
|
|
41659
|
+
request = undefined;
|
|
41660
|
+
onChange();
|
|
41661
|
+
}
|
|
41662
|
+
function trackPath({ path, token, end }) {
|
|
41663
|
+
selections.push(createSelectedPathCompletion({ attachmentPath: path, token, end }));
|
|
41664
|
+
previousText = editor.plainText;
|
|
41665
|
+
}
|
|
41666
|
+
return {
|
|
41667
|
+
dismiss,
|
|
41668
|
+
update() {
|
|
41669
|
+
selections = reconcileSelectedPathCompletions({ previousText, text: editor.plainText, selections });
|
|
41670
|
+
previousText = editor.plainText;
|
|
41671
|
+
dismiss();
|
|
41672
|
+
},
|
|
41673
|
+
clearSelections() {
|
|
41674
|
+
selections = [];
|
|
41675
|
+
},
|
|
41676
|
+
selectedPaths(text) {
|
|
41677
|
+
return selectedAttachmentPaths({ text, selections });
|
|
41678
|
+
},
|
|
41679
|
+
insertPath(path) {
|
|
41680
|
+
editor.insertText(path);
|
|
41681
|
+
trackPath({ path, token: path, end: editor.editBuffer.getTextRange(0, editor.cursorOffset).length });
|
|
41682
|
+
},
|
|
41683
|
+
renderMenu({ width, maxRows }) {
|
|
41684
|
+
if (!request || !matchesEditor(request) || completions.length === 0)
|
|
41685
|
+
return;
|
|
41686
|
+
return renderPathCompletionMenu({ completions, selectedIndex, width, maxRows });
|
|
41687
|
+
},
|
|
41688
|
+
handleKey(key) {
|
|
41689
|
+
if (!isActive())
|
|
41690
|
+
return false;
|
|
41691
|
+
if (key.name === "escape" && dismiss()) {
|
|
41692
|
+
key.preventDefault();
|
|
41693
|
+
onChange();
|
|
41694
|
+
return true;
|
|
41695
|
+
}
|
|
41696
|
+
if (request && !matchesEditor(request)) {
|
|
41697
|
+
dismiss();
|
|
41698
|
+
onChange();
|
|
41699
|
+
}
|
|
41700
|
+
if (completions.length > 0) {
|
|
41701
|
+
if (key.name === "up" || key.name === "down" || key.name === "tab") {
|
|
41702
|
+
key.preventDefault();
|
|
41703
|
+
selectedIndex = (selectedIndex + (key.name === "up" ? -1 : 1) + completions.length) % completions.length;
|
|
41704
|
+
onChange();
|
|
41705
|
+
return true;
|
|
41706
|
+
}
|
|
41707
|
+
if (key.name === "return" || key.name === "enter") {
|
|
41708
|
+
key.preventDefault();
|
|
41709
|
+
const completion = completions[selectedIndex];
|
|
41710
|
+
const cursor = editor.cursorOffset;
|
|
41711
|
+
const cursorIndex = editor.editBuffer.getTextRange(0, cursor).length;
|
|
41712
|
+
const prefix = replaceActivePathToken({ text: editor.plainText.slice(0, cursorIndex), replacement: completion.replacement });
|
|
41713
|
+
const text = prefix + editor.plainText.slice(cursorIndex);
|
|
41714
|
+
dismiss();
|
|
41715
|
+
editor.gotoBufferEnd();
|
|
41716
|
+
const suffixOffset = editor.cursorOffset - cursor;
|
|
41717
|
+
setComposerText(editor, text);
|
|
41718
|
+
editor.cursorOffset -= suffixOffset;
|
|
41719
|
+
if (completion.attachmentPath)
|
|
41720
|
+
trackPath({ path: completion.attachmentPath, token: completion.replacement, end: prefix.length });
|
|
41721
|
+
onChange();
|
|
41722
|
+
return true;
|
|
41723
|
+
}
|
|
41724
|
+
dismiss();
|
|
41725
|
+
onChange();
|
|
41726
|
+
}
|
|
41727
|
+
if (key.name !== "tab")
|
|
41728
|
+
return false;
|
|
41729
|
+
key.preventDefault();
|
|
41730
|
+
open5();
|
|
41731
|
+
return true;
|
|
41732
|
+
}
|
|
41733
|
+
};
|
|
41734
|
+
}
|
|
41735
|
+
|
|
41618
41736
|
// src/tui/new-session-wizard.ts
|
|
41619
41737
|
async function createNewSessionWizard({
|
|
41620
41738
|
repositories,
|
|
@@ -41692,6 +41810,8 @@ async function createNewSessionWizard({
|
|
|
41692
41810
|
\u283F \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588`))
|
|
41693
41811
|
]);
|
|
41694
41812
|
}, render = function() {
|
|
41813
|
+
if (step !== "prompt")
|
|
41814
|
+
composerPaths.dismiss();
|
|
41695
41815
|
const repositoryListVisible = step === "repositories" || step === "repositorySearch";
|
|
41696
41816
|
const mcpListVisible = step === "mcps" || step === "mcpSearch";
|
|
41697
41817
|
const selectionListVisible = repositoryListVisible || step === "branches" || mcpListVisible;
|
|
@@ -41720,6 +41840,15 @@ async function createNewSessionWizard({
|
|
|
41720
41840
|
repositoryRows.content = "";
|
|
41721
41841
|
repositoryDivider.content = "";
|
|
41722
41842
|
repositoryFooter.content = "";
|
|
41843
|
+
repositoryDivider.height = selectionListVisible ? "auto" : 0;
|
|
41844
|
+
repositoryFooter.height = selectionListVisible ? "auto" : 0;
|
|
41845
|
+
const menu = composerPaths.renderMenu({ width: renderer.width - 2, maxRows: completionMenuRows(renderer.height) });
|
|
41846
|
+
const menuRows = menu ? menu.chunks.map((chunk) => chunk.text).join("").split(`
|
|
41847
|
+
`).length : 0;
|
|
41848
|
+
pathMenu.content = menu ?? "";
|
|
41849
|
+
pathMenu.height = menuRows;
|
|
41850
|
+
if (step === "prompt")
|
|
41851
|
+
resizeComposer(editor, renderer.height - menuRows - 2);
|
|
41723
41852
|
const attachmentText = renderAttachmentSummary(attachments);
|
|
41724
41853
|
const attachmentStatus = attachmentFeedback ? renderAttachmentFeedback(attachmentFeedback) : undefined;
|
|
41725
41854
|
if (step === "prompt") {
|
|
@@ -41729,9 +41858,6 @@ async function createNewSessionWizard({
|
|
|
41729
41858
|
];
|
|
41730
41859
|
if (attachmentText.chunks.length > 0)
|
|
41731
41860
|
parts.push(attachmentText);
|
|
41732
|
-
const completionMenu = pathCompletionMenuOpen ? renderPathCompletionMenu({ completions: pathCompletions, selectedIndex: completionIndex, width: renderer.width - 2, maxRows: completionMenuRows(renderer.height) }) : undefined;
|
|
41733
|
-
if (completionMenu)
|
|
41734
|
-
parts.push(completionMenu);
|
|
41735
41861
|
if (status)
|
|
41736
41862
|
parts.push(stringToStyledText3(status));
|
|
41737
41863
|
if (attachmentStatus)
|
|
@@ -41977,7 +42103,7 @@ async function createNewSessionWizard({
|
|
|
41977
42103
|
rejectDraft(error93);
|
|
41978
42104
|
}, returnToPromptFromRepositoryLoading = function() {
|
|
41979
42105
|
step = "prompt";
|
|
41980
|
-
editor
|
|
42106
|
+
setComposerText(editor, prompt);
|
|
41981
42107
|
render();
|
|
41982
42108
|
}, requestRepositoryLoad = function({ retry }) {
|
|
41983
42109
|
if (Array.isArray(repositories))
|
|
@@ -42013,6 +42139,10 @@ async function createNewSessionWizard({
|
|
|
42013
42139
|
render();
|
|
42014
42140
|
});
|
|
42015
42141
|
}, goBack = function() {
|
|
42142
|
+
if (composerPaths.dismiss()) {
|
|
42143
|
+
render();
|
|
42144
|
+
return;
|
|
42145
|
+
}
|
|
42016
42146
|
if (step === "mcpSearch") {
|
|
42017
42147
|
step = "mcps";
|
|
42018
42148
|
mcpQuery = "";
|
|
@@ -42027,11 +42157,6 @@ async function createNewSessionWizard({
|
|
|
42027
42157
|
render();
|
|
42028
42158
|
return;
|
|
42029
42159
|
}
|
|
42030
|
-
if (pathCompletionMenuOpen) {
|
|
42031
|
-
pathCompletionMenuOpen = false;
|
|
42032
|
-
render();
|
|
42033
|
-
return;
|
|
42034
|
-
}
|
|
42035
42160
|
if (step === "repositorySearch") {
|
|
42036
42161
|
searchSelections = undefined;
|
|
42037
42162
|
repositoryQuery = "";
|
|
@@ -42072,47 +42197,8 @@ async function createNewSessionWizard({
|
|
|
42072
42197
|
}
|
|
42073
42198
|
finish(null);
|
|
42074
42199
|
}, handleKey = function(key) {
|
|
42075
|
-
if (
|
|
42076
|
-
if (key.name === "up" || key.name === "down") {
|
|
42077
|
-
key.preventDefault();
|
|
42078
|
-
completionIndex = (completionIndex + (key.name === "up" ? -1 : 1) + pathCompletions.length) % pathCompletions.length;
|
|
42079
|
-
render();
|
|
42080
|
-
return;
|
|
42081
|
-
}
|
|
42082
|
-
if (key.name === "tab") {
|
|
42083
|
-
key.preventDefault();
|
|
42084
|
-
completionIndex = (completionIndex + 1) % pathCompletions.length;
|
|
42085
|
-
render();
|
|
42086
|
-
return;
|
|
42087
|
-
}
|
|
42088
|
-
if (key.name === "return" || key.name === "enter") {
|
|
42089
|
-
key.preventDefault();
|
|
42090
|
-
const completion = pathCompletions[completionIndex];
|
|
42091
|
-
if (completion) {
|
|
42092
|
-
const completedText = replaceActivePathToken({ text: editor.plainText, replacement: completion.replacement });
|
|
42093
|
-
editor.setText(completedText);
|
|
42094
|
-
editor.cursorOffset = completedText.length;
|
|
42095
|
-
if (completion.attachmentPath) {
|
|
42096
|
-
const selectedCompletion = createSelectedPathCompletion({
|
|
42097
|
-
attachmentPath: completion.attachmentPath,
|
|
42098
|
-
token: completion.replacement,
|
|
42099
|
-
end: completedText.length
|
|
42100
|
-
});
|
|
42101
|
-
selectedPathCompletions = [...selectedPathCompletions, selectedCompletion];
|
|
42102
|
-
}
|
|
42103
|
-
previousPromptEditorText = completedText;
|
|
42104
|
-
}
|
|
42105
|
-
pathCompletions = [];
|
|
42106
|
-
pathCompletionMenuOpen = false;
|
|
42107
|
-
render();
|
|
42108
|
-
return;
|
|
42109
|
-
}
|
|
42110
|
-
}
|
|
42111
|
-
if (step === "prompt" && key.name === "tab") {
|
|
42112
|
-
key.preventDefault();
|
|
42113
|
-
openPathCompletionMenu();
|
|
42200
|
+
if (composerPaths.handleKey(key))
|
|
42114
42201
|
return;
|
|
42115
|
-
}
|
|
42116
42202
|
if (key.ctrl && key.name === "c") {
|
|
42117
42203
|
key.preventDefault();
|
|
42118
42204
|
finish({ kind: "interrupt" });
|
|
@@ -42193,7 +42279,7 @@ async function createNewSessionWizard({
|
|
|
42193
42279
|
key.preventDefault();
|
|
42194
42280
|
invalidatePendingConfirmation();
|
|
42195
42281
|
step = "prompt";
|
|
42196
|
-
editor
|
|
42282
|
+
setComposerText(editor, prompt);
|
|
42197
42283
|
render();
|
|
42198
42284
|
return;
|
|
42199
42285
|
}
|
|
@@ -42340,12 +42426,14 @@ async function createNewSessionWizard({
|
|
|
42340
42426
|
repositoryScrollBox.visible = false;
|
|
42341
42427
|
const repositoryDivider = new TextRenderable4(renderer, { content: "", flexShrink: 0 });
|
|
42342
42428
|
const repositoryFooter = new TextRenderable4(renderer, { content: "", flexShrink: 0 });
|
|
42429
|
+
const pathMenu = new TextRenderable4(renderer, { content: "", flexShrink: 0 });
|
|
42343
42430
|
contentScrollBox.add(content2);
|
|
42344
42431
|
root.add(contentScrollBox);
|
|
42345
42432
|
repositoryScrollBox.add(repositoryRows);
|
|
42346
42433
|
root.add(repositoryScrollBox);
|
|
42347
42434
|
root.add(repositoryDivider);
|
|
42348
42435
|
root.add(repositoryFooter);
|
|
42436
|
+
root.add(pathMenu);
|
|
42349
42437
|
renderer.root.add(root);
|
|
42350
42438
|
let loadedRepositories = Array.isArray(repositories) ? repositories : [];
|
|
42351
42439
|
let repositoryLoadState = Array.isArray(repositories) ? "ready" : "loading";
|
|
@@ -42363,11 +42451,6 @@ async function createNewSessionWizard({
|
|
|
42363
42451
|
let recomputeInstruction = "";
|
|
42364
42452
|
let suggestionSpinnerFrame = 0;
|
|
42365
42453
|
let attachments = [...initialDraft?.attachments ?? []];
|
|
42366
|
-
let previousPromptEditorText = "";
|
|
42367
|
-
let pathCompletions = [];
|
|
42368
|
-
let selectedPathCompletions = [];
|
|
42369
|
-
let completionIndex = 0;
|
|
42370
|
-
let pathCompletionMenuOpen = false;
|
|
42371
42454
|
let repositoryHeaderHeight;
|
|
42372
42455
|
let awaitingVimGoToTop = false;
|
|
42373
42456
|
const manualSelections = new Map;
|
|
@@ -42405,6 +42488,7 @@ async function createNewSessionWizard({
|
|
|
42405
42488
|
rejectDraft = reject;
|
|
42406
42489
|
});
|
|
42407
42490
|
let editor;
|
|
42491
|
+
let composerPaths;
|
|
42408
42492
|
const composer = createComposer({
|
|
42409
42493
|
renderer,
|
|
42410
42494
|
parent: root,
|
|
@@ -42413,28 +42497,28 @@ async function createNewSessionWizard({
|
|
|
42413
42497
|
submitEditor();
|
|
42414
42498
|
},
|
|
42415
42499
|
onContentChange: () => {
|
|
42416
|
-
if (step === "prompt")
|
|
42417
|
-
|
|
42418
|
-
|
|
42419
|
-
|
|
42420
|
-
selections: selectedPathCompletions
|
|
42421
|
-
});
|
|
42422
|
-
previousPromptEditorText = editor.plainText;
|
|
42423
|
-
}
|
|
42424
|
-
pathCompletionMenuOpen = false;
|
|
42500
|
+
if (step === "prompt")
|
|
42501
|
+
composerPaths.update();
|
|
42502
|
+
else
|
|
42503
|
+
composerPaths.dismiss();
|
|
42425
42504
|
if (step === "mcpSearch") {
|
|
42426
42505
|
mcpQuery = editor.plainText;
|
|
42427
42506
|
mcpIndex = 0;
|
|
42428
|
-
render();
|
|
42429
42507
|
}
|
|
42430
42508
|
if (step === "repositorySearch") {
|
|
42431
42509
|
repositoryQuery = editor.plainText;
|
|
42432
42510
|
repositoryIndex = 0;
|
|
42433
|
-
render();
|
|
42434
42511
|
}
|
|
42512
|
+
render();
|
|
42435
42513
|
}
|
|
42436
42514
|
});
|
|
42437
42515
|
editor = composer.textarea;
|
|
42516
|
+
composerPaths = createComposerPaths({
|
|
42517
|
+
editor,
|
|
42518
|
+
cwd: process.cwd(),
|
|
42519
|
+
isActive: () => !destroyed && !settled && step === "prompt",
|
|
42520
|
+
onChange: render
|
|
42521
|
+
});
|
|
42438
42522
|
let composerMounted = false;
|
|
42439
42523
|
for (const repository of initialDraft?.repositories ?? [])
|
|
42440
42524
|
manualSelections.set(repository.id, true);
|
|
@@ -42521,18 +42605,6 @@ async function createNewSessionWizard({
|
|
|
42521
42605
|
}
|
|
42522
42606
|
render();
|
|
42523
42607
|
}
|
|
42524
|
-
async function openPathCompletionMenu() {
|
|
42525
|
-
if (destroyed)
|
|
42526
|
-
return;
|
|
42527
|
-
const text = editor.plainText;
|
|
42528
|
-
const completions = await completePathToken({ text, cwd: process.cwd() });
|
|
42529
|
-
if (destroyed || editor.plainText !== text)
|
|
42530
|
-
return;
|
|
42531
|
-
pathCompletions = completions;
|
|
42532
|
-
completionIndex = 0;
|
|
42533
|
-
pathCompletionMenuOpen = completions.length > 0;
|
|
42534
|
-
render();
|
|
42535
|
-
}
|
|
42536
42608
|
async function startRepositoryReview() {
|
|
42537
42609
|
if (repositoryLoadState !== "ready") {
|
|
42538
42610
|
step = "loadingRepositories";
|
|
@@ -42563,10 +42635,7 @@ async function createNewSessionWizard({
|
|
|
42563
42635
|
const image = await readClipboardImage();
|
|
42564
42636
|
const path = await savePastedImage(image);
|
|
42565
42637
|
if (!destroyed) {
|
|
42566
|
-
|
|
42567
|
-
const selectedCompletion = createSelectedPathCompletion({ attachmentPath: path, token: path, end: editor.cursorOffset });
|
|
42568
|
-
selectedPathCompletions = [...selectedPathCompletions, selectedCompletion];
|
|
42569
|
-
previousPromptEditorText = editor.plainText;
|
|
42638
|
+
composerPaths.insertPath(path);
|
|
42570
42639
|
attachmentFeedback = { kind: "success", message: "Clipboard image ready to attach." };
|
|
42571
42640
|
}
|
|
42572
42641
|
} catch (error93) {
|
|
@@ -42602,11 +42671,12 @@ async function createNewSessionWizard({
|
|
|
42602
42671
|
}
|
|
42603
42672
|
const repositoryBranchOverrides = branchOverridesForSelection();
|
|
42604
42673
|
const confirmation = Symbol("confirmation");
|
|
42674
|
+
const skippedFilenames = [];
|
|
42605
42675
|
const confirmedAttachments = [...attachments];
|
|
42606
42676
|
const confirmedPrompt = prompt;
|
|
42607
42677
|
const confirmedModel = model;
|
|
42608
42678
|
const confirmedReasoningEffort = reasoningEffort;
|
|
42609
|
-
const confirmedSelectedPaths =
|
|
42679
|
+
const confirmedSelectedPaths = composerPaths.selectedPaths(confirmedPrompt);
|
|
42610
42680
|
pendingConfirmation = confirmation;
|
|
42611
42681
|
const ownsConfirmation = () => !destroyed && !settled && step === "confirmation" && pendingConfirmation === confirmation;
|
|
42612
42682
|
if (attachPromptPaths) {
|
|
@@ -42616,6 +42686,10 @@ async function createNewSessionWizard({
|
|
|
42616
42686
|
text: confirmedPrompt,
|
|
42617
42687
|
excludedPaths: confirmedAttachments.flatMap((attachment) => attachment.sourcePath ? [attachment.sourcePath] : []),
|
|
42618
42688
|
selectedPaths: confirmedSelectedPaths,
|
|
42689
|
+
onUploadSkipped: ({ filename }) => {
|
|
42690
|
+
if (ownsConfirmation())
|
|
42691
|
+
skippedFilenames.push(filename);
|
|
42692
|
+
},
|
|
42619
42693
|
onUploadStart: ({ filenames }) => {
|
|
42620
42694
|
if (!ownsConfirmation())
|
|
42621
42695
|
return;
|
|
@@ -42627,7 +42701,7 @@ async function createNewSessionWizard({
|
|
|
42627
42701
|
return;
|
|
42628
42702
|
confirmedAttachments.push(...promptAttachments);
|
|
42629
42703
|
attachments = confirmedAttachments;
|
|
42630
|
-
|
|
42704
|
+
composerPaths.clearSelections();
|
|
42631
42705
|
attachmentFeedback = undefined;
|
|
42632
42706
|
} catch (error93) {
|
|
42633
42707
|
if (!ownsConfirmation())
|
|
@@ -42646,6 +42720,7 @@ async function createNewSessionWizard({
|
|
|
42646
42720
|
repositories: selected,
|
|
42647
42721
|
...repositoryBranchOverrides.length > 0 ? { repositoryBranchOverrides } : {},
|
|
42648
42722
|
attachments: confirmedAttachments,
|
|
42723
|
+
...skippedFilenames.length > 0 ? { attachmentWarning: attachmentSkippedMessage(skippedFilenames) } : {},
|
|
42649
42724
|
...confirmedMcps.length > 0 ? { mcps: confirmedMcps } : {},
|
|
42650
42725
|
model: confirmedModel,
|
|
42651
42726
|
reasoningEffort: confirmedReasoningEffort
|
|
@@ -43101,6 +43176,7 @@ async function createSessionTui({
|
|
|
43101
43176
|
attachPromptPaths,
|
|
43102
43177
|
initialComposer,
|
|
43103
43178
|
initialFeedback,
|
|
43179
|
+
initialAttachmentWarning,
|
|
43104
43180
|
now: now3 = Date.now,
|
|
43105
43181
|
createRenderer = createDefaultRenderer3
|
|
43106
43182
|
}) {
|
|
@@ -43169,7 +43245,7 @@ async function createSessionTui({
|
|
|
43169
43245
|
composerFeedback = undefined;
|
|
43170
43246
|
slashCompletions = [];
|
|
43171
43247
|
helpVisible = false;
|
|
43172
|
-
|
|
43248
|
+
composerPaths.dismiss();
|
|
43173
43249
|
render();
|
|
43174
43250
|
}, moveAgentSettingsPicker = function(step) {
|
|
43175
43251
|
if (!agentSettingsPicker)
|
|
@@ -43205,10 +43281,9 @@ async function createSessionTui({
|
|
|
43205
43281
|
}
|
|
43206
43282
|
promptHistoryIndex = direction === "up" ? Math.max(0, promptHistoryIndex - 1) : Math.min(promptHistory.length, promptHistoryIndex + 1);
|
|
43207
43283
|
const text = promptHistoryIndex === promptHistory.length ? promptHistoryDraft : promptHistory[promptHistoryIndex];
|
|
43208
|
-
|
|
43284
|
+
composerPaths.clearSelections();
|
|
43209
43285
|
historyReplacement = text;
|
|
43210
|
-
composer
|
|
43211
|
-
composer.cursorOffset = text.length;
|
|
43286
|
+
setComposerText(composer, text);
|
|
43212
43287
|
const viewport = composer.editorView.getViewport();
|
|
43213
43288
|
composer.editorView.setViewport(viewport.offsetX, 0, viewport.width, viewport.height);
|
|
43214
43289
|
render();
|
|
@@ -43252,7 +43327,7 @@ async function createSessionTui({
|
|
|
43252
43327
|
if (latestState.aggregateStatus === "open")
|
|
43253
43328
|
composerLayout.render();
|
|
43254
43329
|
const submissionStatus = renderComposerStatus({ admittedSubmissions, width: renderer.width - 2 });
|
|
43255
|
-
const completionMenu =
|
|
43330
|
+
const completionMenu = composerPaths.renderMenu({ width: renderer.width - 2, maxRows: completionMenuRows(renderer.height) });
|
|
43256
43331
|
const commandMenu = renderSlashCommandMenu({ commands: slashCompletions, selectedIndex: slashCompletionIndex, width: renderer.width - 2, maxRows: completionMenuRows(renderer.height) });
|
|
43257
43332
|
const agentSettingsMenu = agentSettingsPicker && latestState.aggregateStatus === "open" ? renderAgentSettingsPicker({ picker: agentSettingsPicker, width: renderer.width - 2, maxRows: completionMenuRows(renderer.height) }) : undefined;
|
|
43258
43333
|
const composerStatus = [
|
|
@@ -43314,7 +43389,7 @@ ${segment.excerpt}`).join(`
|
|
|
43314
43389
|
}, openLocalMenu = function(mode) {
|
|
43315
43390
|
resourceMode = mode;
|
|
43316
43391
|
localMenuIndex = 0;
|
|
43317
|
-
|
|
43392
|
+
composerPaths.dismiss();
|
|
43318
43393
|
slashCompletions = [];
|
|
43319
43394
|
helpVisible = false;
|
|
43320
43395
|
composer.blur();
|
|
@@ -43326,7 +43401,7 @@ ${segment.excerpt}`).join(`
|
|
|
43326
43401
|
resourceMode = "mcps";
|
|
43327
43402
|
mcpQuery = "";
|
|
43328
43403
|
mcpSelectedId = mcps.getState().attachments[0]?.offering.id;
|
|
43329
|
-
|
|
43404
|
+
composerPaths.dismiss();
|
|
43330
43405
|
slashCompletions = [];
|
|
43331
43406
|
helpVisible = false;
|
|
43332
43407
|
agentSettingsPicker = undefined;
|
|
@@ -43347,7 +43422,7 @@ ${segment.excerpt}`).join(`
|
|
|
43347
43422
|
resourceMode = mode;
|
|
43348
43423
|
resourceKey = resourceChoices()[0]?.key;
|
|
43349
43424
|
resourceFeedback = undefined;
|
|
43350
|
-
|
|
43425
|
+
composerPaths.dismiss();
|
|
43351
43426
|
slashCompletions = [];
|
|
43352
43427
|
helpVisible = false;
|
|
43353
43428
|
agentSettingsPicker = undefined;
|
|
@@ -43503,16 +43578,11 @@ ${segment.excerpt}`).join(`
|
|
|
43503
43578
|
let settled = false;
|
|
43504
43579
|
let activityExpanded = false;
|
|
43505
43580
|
let composerDraft = initialComposer ?? { text: "", attachments: [] };
|
|
43506
|
-
let previousComposerText = composerDraft.text;
|
|
43507
|
-
let pathCompletions = [];
|
|
43508
|
-
let selectedPathCompletions = [];
|
|
43509
|
-
let completionIndex = 0;
|
|
43510
|
-
let pathCompletionMenuOpen = false;
|
|
43511
43581
|
let slashCompletions = [];
|
|
43512
43582
|
let slashCompletionIndex = 0;
|
|
43513
43583
|
let agentSettingsPicker;
|
|
43514
43584
|
let composerFeedback = initialFeedback ? { kind: "info", message: initialFeedback } : undefined;
|
|
43515
|
-
let attachmentFeedback;
|
|
43585
|
+
let attachmentFeedback = initialAttachmentWarning ? { kind: "attention", message: initialAttachmentWarning } : undefined;
|
|
43516
43586
|
let promptHistoryIndex;
|
|
43517
43587
|
let promptHistoryDraft = "";
|
|
43518
43588
|
let historyReplacement;
|
|
@@ -43583,6 +43653,7 @@ ${segment.excerpt}`).join(`
|
|
|
43583
43653
|
});
|
|
43584
43654
|
const composerTag = () => latestState.sessionNumber !== undefined ? `Session #${latestState.sessionNumber}` : latestState.sessionId;
|
|
43585
43655
|
let composer;
|
|
43656
|
+
let composerPaths;
|
|
43586
43657
|
const composerLayout = createComposer({
|
|
43587
43658
|
renderer,
|
|
43588
43659
|
parent: root,
|
|
@@ -43592,23 +43663,23 @@ ${segment.excerpt}`).join(`
|
|
|
43592
43663
|
submitComposer();
|
|
43593
43664
|
},
|
|
43594
43665
|
onContentChange: () => {
|
|
43595
|
-
|
|
43596
|
-
previousText: previousComposerText,
|
|
43597
|
-
text: composer.plainText,
|
|
43598
|
-
selections: selectedPathCompletions
|
|
43599
|
-
});
|
|
43600
|
-
previousComposerText = composer.plainText;
|
|
43666
|
+
composerPaths.update();
|
|
43601
43667
|
if (historyReplacement !== composer.plainText)
|
|
43602
43668
|
promptHistoryIndex = undefined;
|
|
43603
43669
|
historyReplacement = undefined;
|
|
43604
43670
|
refreshSlashCompletions();
|
|
43605
|
-
pathCompletionMenuOpen = false;
|
|
43606
43671
|
if (composer.plainText.length > 0)
|
|
43607
43672
|
helpVisible = false;
|
|
43608
43673
|
render();
|
|
43609
43674
|
}
|
|
43610
43675
|
});
|
|
43611
43676
|
composer = composerLayout.textarea;
|
|
43677
|
+
composerPaths = createComposerPaths({
|
|
43678
|
+
editor: composer,
|
|
43679
|
+
cwd: process.cwd(),
|
|
43680
|
+
isActive: () => !destroyed && !settled && latestState.aggregateStatus === "open" && resourceMode === undefined,
|
|
43681
|
+
onChange: render
|
|
43682
|
+
});
|
|
43612
43683
|
const idleComposerPlaceholder = composer.placeholder;
|
|
43613
43684
|
composerLayout.mount();
|
|
43614
43685
|
const terminalSessionBand = new TextRenderable5(renderer, { content: "", flexShrink: 0, visible: false });
|
|
@@ -43700,7 +43771,7 @@ ${segment.excerpt}`).join(`
|
|
|
43700
43771
|
} else if (key.name === "s") {
|
|
43701
43772
|
mcpSearch = true;
|
|
43702
43773
|
mcpSearchComposer.mount();
|
|
43703
|
-
mcpSearchComposer.textarea
|
|
43774
|
+
setComposerText(mcpSearchComposer.textarea, mcpQuery);
|
|
43704
43775
|
mcpSearchComposer.focus();
|
|
43705
43776
|
} else if (key.name === "r") {
|
|
43706
43777
|
mcps.refresh();
|
|
@@ -43773,9 +43844,8 @@ ${segment.excerpt}`).join(`
|
|
|
43773
43844
|
finish({ kind: "sessions" });
|
|
43774
43845
|
return;
|
|
43775
43846
|
}
|
|
43776
|
-
if (
|
|
43847
|
+
if (composerPaths.dismiss()) {
|
|
43777
43848
|
key.preventDefault();
|
|
43778
|
-
pathCompletionMenuOpen = false;
|
|
43779
43849
|
render();
|
|
43780
43850
|
return;
|
|
43781
43851
|
}
|
|
@@ -43822,10 +43892,7 @@ ${segment.excerpt}`).join(`
|
|
|
43822
43892
|
const path = await savePastedImage(image);
|
|
43823
43893
|
if (destroyed)
|
|
43824
43894
|
return;
|
|
43825
|
-
|
|
43826
|
-
const selectedCompletion = createSelectedPathCompletion({ attachmentPath: path, token: path, end: composer.cursorOffset });
|
|
43827
|
-
selectedPathCompletions = [...selectedPathCompletions, selectedCompletion];
|
|
43828
|
-
previousComposerText = composer.plainText;
|
|
43895
|
+
composerPaths.insertPath(path);
|
|
43829
43896
|
attachmentFeedback = { kind: "success", message: "Clipboard image ready to attach." };
|
|
43830
43897
|
} catch (error93) {
|
|
43831
43898
|
if (!destroyed)
|
|
@@ -43858,10 +43925,8 @@ ${segment.excerpt}`).join(`
|
|
|
43858
43925
|
if (slashCompletions.length > 0 && key.name === "tab") {
|
|
43859
43926
|
key.preventDefault();
|
|
43860
43927
|
const completion = slashCompletions[slashCompletionIndex];
|
|
43861
|
-
if (completion)
|
|
43862
|
-
composer
|
|
43863
|
-
composer.cursorOffset = completion.value.length;
|
|
43864
|
-
}
|
|
43928
|
+
if (completion)
|
|
43929
|
+
setComposerText(composer, completion.value);
|
|
43865
43930
|
slashCompletions = [];
|
|
43866
43931
|
render();
|
|
43867
43932
|
return;
|
|
@@ -43869,55 +43934,14 @@ ${segment.excerpt}`).join(`
|
|
|
43869
43934
|
if (slashCompletions.length > 0 && (key.name === "return" || key.name === "enter")) {
|
|
43870
43935
|
key.preventDefault();
|
|
43871
43936
|
const completion = slashCompletions[slashCompletionIndex];
|
|
43872
|
-
if (completion)
|
|
43873
|
-
composer
|
|
43874
|
-
composer.cursorOffset = completion.value.length;
|
|
43875
|
-
}
|
|
43937
|
+
if (completion)
|
|
43938
|
+
setComposerText(composer, completion.value);
|
|
43876
43939
|
slashCompletions = [];
|
|
43877
43940
|
render();
|
|
43878
43941
|
return;
|
|
43879
43942
|
}
|
|
43880
|
-
if (
|
|
43881
|
-
if (key.name === "up" || key.name === "down") {
|
|
43882
|
-
key.preventDefault();
|
|
43883
|
-
completionIndex = (completionIndex + (key.name === "up" ? -1 : 1) + pathCompletions.length) % pathCompletions.length;
|
|
43884
|
-
render();
|
|
43885
|
-
return;
|
|
43886
|
-
}
|
|
43887
|
-
if (key.name === "tab") {
|
|
43888
|
-
key.preventDefault();
|
|
43889
|
-
completionIndex = (completionIndex + 1) % pathCompletions.length;
|
|
43890
|
-
render();
|
|
43891
|
-
return;
|
|
43892
|
-
}
|
|
43893
|
-
if (key.name === "return" || key.name === "enter") {
|
|
43894
|
-
key.preventDefault();
|
|
43895
|
-
const completion = pathCompletions[completionIndex];
|
|
43896
|
-
if (completion) {
|
|
43897
|
-
const completedText = replaceActivePathToken({ text: composer.plainText, replacement: completion.replacement });
|
|
43898
|
-
composer.setText(completedText);
|
|
43899
|
-
composer.cursorOffset = completedText.length;
|
|
43900
|
-
if (completion.attachmentPath) {
|
|
43901
|
-
const selectedCompletion = createSelectedPathCompletion({
|
|
43902
|
-
attachmentPath: completion.attachmentPath,
|
|
43903
|
-
token: completion.replacement,
|
|
43904
|
-
end: completedText.length
|
|
43905
|
-
});
|
|
43906
|
-
selectedPathCompletions = [...selectedPathCompletions, selectedCompletion];
|
|
43907
|
-
}
|
|
43908
|
-
previousComposerText = completedText;
|
|
43909
|
-
}
|
|
43910
|
-
pathCompletions = [];
|
|
43911
|
-
pathCompletionMenuOpen = false;
|
|
43912
|
-
render();
|
|
43913
|
-
return;
|
|
43914
|
-
}
|
|
43915
|
-
}
|
|
43916
|
-
if (key.name === "tab") {
|
|
43917
|
-
key.preventDefault();
|
|
43918
|
-
openPathCompletionMenu();
|
|
43943
|
+
if (composerPaths.handleKey(key))
|
|
43919
43944
|
return;
|
|
43920
|
-
}
|
|
43921
43945
|
if ((key.name === "up" || key.name === "down") && composerAtVisualEdge(key.name)) {
|
|
43922
43946
|
key.preventDefault();
|
|
43923
43947
|
navigatePromptHistory(key.name);
|
|
@@ -43996,18 +44020,6 @@ ${segment.excerpt}`).join(`
|
|
|
43996
44020
|
});
|
|
43997
44021
|
};
|
|
43998
44022
|
}
|
|
43999
|
-
async function openPathCompletionMenu() {
|
|
44000
|
-
if (destroyed)
|
|
44001
|
-
return;
|
|
44002
|
-
const text = composer.plainText;
|
|
44003
|
-
const completions = await completePathToken({ text, cwd: process.cwd() });
|
|
44004
|
-
if (destroyed || composer.plainText !== text)
|
|
44005
|
-
return;
|
|
44006
|
-
pathCompletions = completions;
|
|
44007
|
-
completionIndex = 0;
|
|
44008
|
-
pathCompletionMenuOpen = completions.length > 0;
|
|
44009
|
-
render();
|
|
44010
|
-
}
|
|
44011
44023
|
async function submitComposer() {
|
|
44012
44024
|
if (attachmentPreparationOwner)
|
|
44013
44025
|
return;
|
|
@@ -44042,12 +44054,17 @@ ${segment.excerpt}`).join(`
|
|
|
44042
44054
|
return;
|
|
44043
44055
|
}
|
|
44044
44056
|
if (attachPromptPaths) {
|
|
44057
|
+
const skippedFilenames = [];
|
|
44045
44058
|
let handedOffToAdmission = false;
|
|
44046
44059
|
try {
|
|
44047
44060
|
const attachments = await attachPromptPaths({
|
|
44048
44061
|
text: composerDraft.text,
|
|
44049
44062
|
excludedPaths: composerDraft.attachments.flatMap((attachment) => attachment.sourcePath ? [attachment.sourcePath] : []),
|
|
44050
|
-
selectedPaths:
|
|
44063
|
+
selectedPaths: composerPaths.selectedPaths(composerDraft.text),
|
|
44064
|
+
onUploadSkipped: ({ filename }) => {
|
|
44065
|
+
if (ownsAttachmentPreparation(preparationOwner))
|
|
44066
|
+
skippedFilenames.push(filename);
|
|
44067
|
+
},
|
|
44051
44068
|
onUploadStart: ({ filenames }) => {
|
|
44052
44069
|
if (!ownsAttachmentPreparation(preparationOwner))
|
|
44053
44070
|
return;
|
|
@@ -44058,8 +44075,8 @@ ${segment.excerpt}`).join(`
|
|
|
44058
44075
|
if (!ownsAttachmentPreparation(preparationOwner))
|
|
44059
44076
|
return;
|
|
44060
44077
|
composerDraft = { ...composerDraft, attachments: [...composerDraft.attachments, ...attachments] };
|
|
44061
|
-
|
|
44062
|
-
attachmentFeedback = undefined;
|
|
44078
|
+
composerPaths.clearSelections();
|
|
44079
|
+
attachmentFeedback = skippedFilenames.length > 0 ? { kind: "attention", message: attachmentSkippedMessage(skippedFilenames) } : undefined;
|
|
44063
44080
|
handedOffToAdmission = true;
|
|
44064
44081
|
} catch (error93) {
|
|
44065
44082
|
if (!ownsAttachmentPreparation(preparationOwner))
|
|
@@ -44184,7 +44201,6 @@ ${segment.excerpt}`).join(`
|
|
|
44184
44201
|
helpVisible = true;
|
|
44185
44202
|
slashCompletions = composerSlashCommands;
|
|
44186
44203
|
slashCompletionIndex = 0;
|
|
44187
|
-
pathCompletionMenuOpen = false;
|
|
44188
44204
|
render();
|
|
44189
44205
|
return true;
|
|
44190
44206
|
}
|
|
@@ -44337,7 +44353,7 @@ ${segment.excerpt}`).join(`
|
|
|
44337
44353
|
});
|
|
44338
44354
|
renderer.addInputHandler(inputHandler);
|
|
44339
44355
|
renderer.keyInput.on("keypress", keyHandler);
|
|
44340
|
-
composer
|
|
44356
|
+
setComposerText(composer, composerDraft.text);
|
|
44341
44357
|
renderer.on(CliRenderEvents5.RENDER_ERROR, (event) => finish(undefined, event.error));
|
|
44342
44358
|
resizeHandler = () => {
|
|
44343
44359
|
if (!destroyed)
|
|
@@ -44989,26 +45005,28 @@ async function attachPromptPaths({
|
|
|
44989
45005
|
excludedPaths = [],
|
|
44990
45006
|
selectedPaths = [],
|
|
44991
45007
|
reserveAndUploadFile: reserveAndUploadFile2,
|
|
44992
|
-
onUploadStart
|
|
45008
|
+
onUploadStart,
|
|
45009
|
+
onUploadSkipped
|
|
44993
45010
|
}) {
|
|
45011
|
+
const selected = new Set(selectedPaths.map((filePath) => resolve3(cwd, filePath)));
|
|
44994
45012
|
const excluded = new Set(excludedPaths);
|
|
44995
45013
|
const pathsToUpload = [];
|
|
44996
|
-
for (const
|
|
44997
|
-
const { filePath } = candidate;
|
|
45014
|
+
for (const filePath of promptFilePaths({ text, cwd, selectedPaths })) {
|
|
44998
45015
|
if (excluded.has(filePath))
|
|
44999
45016
|
continue;
|
|
45000
45017
|
let file3;
|
|
45001
45018
|
try {
|
|
45002
45019
|
file3 = await stat(filePath);
|
|
45003
|
-
} catch
|
|
45004
|
-
if (
|
|
45005
|
-
|
|
45006
|
-
|
|
45020
|
+
} catch {
|
|
45021
|
+
if (selected.has(filePath))
|
|
45022
|
+
onUploadSkipped?.({ filename: basename6(filePath) });
|
|
45023
|
+
continue;
|
|
45007
45024
|
}
|
|
45008
|
-
if (!file3.isFile() && !file3.isDirectory()
|
|
45009
|
-
|
|
45010
|
-
|
|
45025
|
+
if (!file3.isFile() && !file3.isDirectory()) {
|
|
45026
|
+
if (selected.has(filePath))
|
|
45027
|
+
onUploadSkipped?.({ filename: basename6(filePath) });
|
|
45011
45028
|
continue;
|
|
45029
|
+
}
|
|
45012
45030
|
pathsToUpload.push(filePath);
|
|
45013
45031
|
}
|
|
45014
45032
|
if (pathsToUpload.length === 0)
|
|
@@ -45016,11 +45034,16 @@ async function attachPromptPaths({
|
|
|
45016
45034
|
onUploadStart?.({ filenames: pathsToUpload.map((filePath) => basename6(filePath)) });
|
|
45017
45035
|
const attachments = [];
|
|
45018
45036
|
for (const filePath of pathsToUpload) {
|
|
45019
|
-
|
|
45020
|
-
|
|
45021
|
-
|
|
45022
|
-
|
|
45023
|
-
|
|
45037
|
+
try {
|
|
45038
|
+
const uploaded = await uploadLocalAttachment({ filePath, reserveAndUploadFile: reserveAndUploadFile2 });
|
|
45039
|
+
attachments.push({
|
|
45040
|
+
id: randomUUID5(),
|
|
45041
|
+
...uploaded
|
|
45042
|
+
});
|
|
45043
|
+
} catch {
|
|
45044
|
+
onUploadSkipped?.({ filename: basename6(filePath) });
|
|
45045
|
+
continue;
|
|
45046
|
+
}
|
|
45024
45047
|
}
|
|
45025
45048
|
return attachments;
|
|
45026
45049
|
}
|
|
@@ -45155,9 +45178,9 @@ function truncateUtf8(value, maxBytes) {
|
|
|
45155
45178
|
return result;
|
|
45156
45179
|
}
|
|
45157
45180
|
function promptFilePaths({ text, cwd, selectedPaths }) {
|
|
45158
|
-
const paths = new
|
|
45181
|
+
const paths = new Set;
|
|
45159
45182
|
for (const selectedPath of selectedPaths)
|
|
45160
|
-
paths.
|
|
45183
|
+
paths.add(isAbsolute3(selectedPath) ? selectedPath : resolve3(cwd, selectedPath));
|
|
45161
45184
|
const tokens = text.match(/[([{]*@?(?:"[^"]*"|'[^']*'|`[^`]*`)|(?:\\.|[^\s\\])+/g) ?? [];
|
|
45162
45185
|
for (const quotedToken of tokens) {
|
|
45163
45186
|
const wrappedToken = quotedToken.replace(/^[([{]+/, "").replace(/[),.;:!?\]}]+$/, "");
|
|
@@ -45172,9 +45195,9 @@ function promptFilePaths({ text, cwd, selectedPaths }) {
|
|
|
45172
45195
|
continue;
|
|
45173
45196
|
const expandedPath = pathText.startsWith("~/") ? join9(homedir2(), pathText.slice(2)) : pathText;
|
|
45174
45197
|
const filePath = isAbsolute3(expandedPath) ? expandedPath : resolve3(cwd, expandedPath);
|
|
45175
|
-
paths.
|
|
45198
|
+
paths.add(filePath);
|
|
45176
45199
|
}
|
|
45177
|
-
return [...paths]
|
|
45200
|
+
return [...paths];
|
|
45178
45201
|
}
|
|
45179
45202
|
function extensionForMediaType(mediaType) {
|
|
45180
45203
|
if (mediaType === "image/png")
|
|
@@ -46177,7 +46200,7 @@ async function dashboard({
|
|
|
46177
46200
|
holdTransitionScreen();
|
|
46178
46201
|
continue;
|
|
46179
46202
|
}
|
|
46180
|
-
return await attachCreatedSession({ dependencies, operations, created: result.created, repositories: result.repositories, noTui: false, json: false });
|
|
46203
|
+
return await attachCreatedSession({ dependencies, operations, created: result.created, repositories: result.repositories, attachmentWarning: result.attachmentWarning, noTui: false, json: false });
|
|
46181
46204
|
}
|
|
46182
46205
|
}
|
|
46183
46206
|
async function prepareDashboardBootstrap({
|
|
@@ -46421,7 +46444,8 @@ async function attachCreatedSession({
|
|
|
46421
46444
|
created,
|
|
46422
46445
|
repositories,
|
|
46423
46446
|
noTui,
|
|
46424
|
-
json: json3
|
|
46447
|
+
json: json3,
|
|
46448
|
+
attachmentWarning
|
|
46425
46449
|
}) {
|
|
46426
46450
|
const initialMessage = created.messages[0];
|
|
46427
46451
|
if (!initialMessage)
|
|
@@ -46449,7 +46473,8 @@ async function attachCreatedSession({
|
|
|
46449
46473
|
},
|
|
46450
46474
|
noTui,
|
|
46451
46475
|
json: json3,
|
|
46452
|
-
emitCreated: true
|
|
46476
|
+
emitCreated: true,
|
|
46477
|
+
attachmentWarning
|
|
46453
46478
|
});
|
|
46454
46479
|
}
|
|
46455
46480
|
async function createFromTuiDraft({
|
|
@@ -46494,7 +46519,7 @@ async function createReviewedSession({ dependencies, operations, repositories })
|
|
|
46494
46519
|
showRemyTransitionScreen({ write: (chunk) => dependencies.output.writeStdout(chunk) });
|
|
46495
46520
|
try {
|
|
46496
46521
|
const created = await createFromTuiDraft({ dependencies, operations, draft });
|
|
46497
|
-
return { created, repositories: draft.repositories };
|
|
46522
|
+
return { created, repositories: draft.repositories, attachmentWarning: draft.attachmentWarning };
|
|
46498
46523
|
} catch (error93) {
|
|
46499
46524
|
throwIfAborted2(dependencies.abortSignal);
|
|
46500
46525
|
initialDraft = draft;
|
|
@@ -46532,13 +46557,15 @@ async function uploadPromptPaths({
|
|
|
46532
46557
|
text,
|
|
46533
46558
|
excludedPaths,
|
|
46534
46559
|
selectedPaths,
|
|
46535
|
-
onUploadStart
|
|
46560
|
+
onUploadStart,
|
|
46561
|
+
onUploadSkipped
|
|
46536
46562
|
}) {
|
|
46537
46563
|
return await attachPromptPaths({
|
|
46538
46564
|
text,
|
|
46539
46565
|
excludedPaths,
|
|
46540
46566
|
selectedPaths,
|
|
46541
46567
|
onUploadStart,
|
|
46568
|
+
onUploadSkipped,
|
|
46542
46569
|
cwd: process.cwd(),
|
|
46543
46570
|
reserveAndUploadFile: async ({ filePath, mediaType }) => await operations.reserveAndUploadFile({
|
|
46544
46571
|
client: operations.client,
|
|
@@ -46634,7 +46661,8 @@ async function runAttachedSession({
|
|
|
46634
46661
|
noTui,
|
|
46635
46662
|
json: json3,
|
|
46636
46663
|
emitCreated,
|
|
46637
|
-
onCacheError
|
|
46664
|
+
onCacheError,
|
|
46665
|
+
attachmentWarning
|
|
46638
46666
|
}) {
|
|
46639
46667
|
if (dependencies.abortSignal?.aborted)
|
|
46640
46668
|
throw dependencies.abortSignal.reason ?? new Error("interrupted");
|
|
@@ -46722,6 +46750,7 @@ async function runAttachedSession({
|
|
|
46722
46750
|
fetchClient: globalThis.fetch
|
|
46723
46751
|
}),
|
|
46724
46752
|
initialComposer: composerSnapshot,
|
|
46753
|
+
initialAttachmentWarning: attachmentWarning,
|
|
46725
46754
|
admissions,
|
|
46726
46755
|
repositoryLabel: repositories.map((repository) => repository.fullName).join(", ") || undefined,
|
|
46727
46756
|
submitMessage: async (submission) => {
|
|
@@ -46871,6 +46900,7 @@ async function runAttachedSession({
|
|
|
46871
46900
|
operations,
|
|
46872
46901
|
created: result.created,
|
|
46873
46902
|
repositories: result.repositories,
|
|
46903
|
+
attachmentWarning: result.attachmentWarning,
|
|
46874
46904
|
noTui: false,
|
|
46875
46905
|
json: false
|
|
46876
46906
|
});
|