nou-cli 0.5.13 → 0.5.14
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 +1 -1
- package/dist/src/ui/App.js +22 -8
- package/dist/src/ui/commands.js +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@ Every change is reviewed like a code review:
|
|
|
113
113
|
| <kbd>m</kbd> | mouse on/off, so you can select and copy text in the terminal (in the chat, just drag over the text: it's copied when you let go; double-click copies a word, path or link, triple-click a paragraph) |
|
|
114
114
|
| <kbd>s</kbd> | settings: model, preferences, plugins |
|
|
115
115
|
| <kbd>y</kbd> / <kbd>n</kbd> | accept / reject a proposed edit or command, from any pane; the rest of Nou keeps working while it waits (<kbd>o</kbd> shows the edit) |
|
|
116
|
-
| <kbd>Enter</kbd> while Nou works | queue the message: it goes when Nou finishes, together with anything else you queued, as one message; commands that only change the screen, like `/terminal`, `/games` or `/open`, run right away. To send now instead of waiting: <kbd>Alt</kbd>+<kbd>Enter</kbd> (stops Nou and sends it), click the queued message, or `/now
|
|
116
|
+
| <kbd>Enter</kbd> while Nou works | queue the message: it goes when Nou finishes, together with anything else you queued, as one message; commands that only change the screen, like `/terminal`, `/games` or `/open`, run right away. To send now instead of waiting: <kbd>Alt</kbd>+<kbd>Enter</kbd> (stops Nou and sends it), click the queued message, or `/now`. Nou answers it first, then finishes what it was working on, unless your message says to drop it; or turn on **Send while Nou works** in settings so <kbd>Enter</kbd> sends right away (<kbd>Alt</kbd>+<kbd>Enter</kbd> then queues) |
|
|
117
117
|
| <kbd>Esc</kbd> | stop Nou (anything queued goes back in the input) · close a diff · back to chat |
|
|
118
118
|
| <kbd>Ctrl</kbd>+<kbd>C</kbd> | stop Nou while it works · press twice to quit |
|
|
119
119
|
|
package/dist/src/ui/App.js
CHANGED
|
@@ -35,7 +35,7 @@ import { FIND_KEY, isFind } from "./keys.js";
|
|
|
35
35
|
import { FileTree } from "./FileTree.js";
|
|
36
36
|
import { CodeView } from "./CodeView.js";
|
|
37
37
|
import { Editor } from "./Editor.js";
|
|
38
|
-
import { SLASH_COMMANDS, closestCommand, onlyChangesScreen, runsWhileBusy } from "./commands.js";
|
|
38
|
+
import { SLASH_COMMANDS, closestCommand, finishAfter, onlyChangesScreen, runsWhileBusy } from "./commands.js";
|
|
39
39
|
import { WHEEL_STEP, sendWheel } from "./scroll.js";
|
|
40
40
|
import { Chat, chatTabZones } from "./Chat.js";
|
|
41
41
|
import { copyToClipboard, openInBrowser } from "./clipboard.js";
|
|
@@ -2017,6 +2017,17 @@ ${snippet}
|
|
|
2017
2017
|
agentRef.current?.cancel();
|
|
2018
2018
|
stopped.current = true;
|
|
2019
2019
|
};
|
|
2020
|
+
/** What Nou was working on when a message cut in (see interruptToSend), so it finishes that too. */
|
|
2021
|
+
const unfinished = useRef(null);
|
|
2022
|
+
const lastAsked = useRef(null);
|
|
2023
|
+
/** Stops Nou so what's queued goes now; the request it was on isn't dropped, it's handed back with it. */
|
|
2024
|
+
const interruptToSend = () => {
|
|
2025
|
+
// What the agent was last asked, unfinished work handed back included: cutting in twice keeps both.
|
|
2026
|
+
if (lastAsked.current)
|
|
2027
|
+
unfinished.current = lastAsked.current;
|
|
2028
|
+
stop();
|
|
2029
|
+
stopped.current = false; // what's queued is meant to go
|
|
2030
|
+
};
|
|
2020
2031
|
useEffect(() => {
|
|
2021
2032
|
if (busy || approval || !queued.length)
|
|
2022
2033
|
return;
|
|
@@ -2031,7 +2042,10 @@ ${snippet}
|
|
|
2031
2042
|
const isCommand = (text) => text.startsWith("/");
|
|
2032
2043
|
const take = isCommand(queued[0]) ? 1 : Math.max(1, queued.findIndex(isCommand) === -1 ? queued.length : queued.findIndex(isCommand));
|
|
2033
2044
|
setQueued(queued.slice(take));
|
|
2034
|
-
|
|
2045
|
+
const text = queued.slice(0, take).join("\n\n");
|
|
2046
|
+
const previous = unfinished.current;
|
|
2047
|
+
unfinished.current = null;
|
|
2048
|
+
send(text, previous && !isCommand(text) ? finishAfter(text, previous) : undefined);
|
|
2035
2049
|
}, [busy, approval, queued]);
|
|
2036
2050
|
// When a reply points at places in the code (Nou's engine with show_places, the others with a ```nou-show
|
|
2037
2051
|
// block, which is taken out of the reply), the first one opens highlighted and the rest are listed.
|
|
@@ -2186,8 +2200,7 @@ ${snippet}
|
|
|
2186
2200
|
const sendNow = () => {
|
|
2187
2201
|
if (!queued.length)
|
|
2188
2202
|
return;
|
|
2189
|
-
|
|
2190
|
-
stopped.current = false; // what's queued is meant to go
|
|
2203
|
+
interruptToSend();
|
|
2191
2204
|
};
|
|
2192
2205
|
/**
|
|
2193
2206
|
* From the chat: while Nou works, a message waits its turn, or (`now`: Alt+Enter) stops Nou and goes right
|
|
@@ -2198,14 +2211,14 @@ ${snippet}
|
|
|
2198
2211
|
return send(text);
|
|
2199
2212
|
const now = settings.sendNowWhileBusy ? !alt : alt;
|
|
2200
2213
|
if (now) {
|
|
2201
|
-
|
|
2202
|
-
stopped.current = false; // this one is meant to go
|
|
2214
|
+
interruptToSend();
|
|
2203
2215
|
setQueued((q) => [text, ...q]);
|
|
2204
2216
|
}
|
|
2205
2217
|
else
|
|
2206
2218
|
setQueued((q) => [...q, text]);
|
|
2207
2219
|
};
|
|
2208
|
-
|
|
2220
|
+
/** `forAgent`: what the agent gets instead of `text` (the chat still shows `text`). */
|
|
2221
|
+
const send = (text, forAgent) => {
|
|
2209
2222
|
// Right after /resume lists them, a number picks a conversation instead of being sent to the agent.
|
|
2210
2223
|
const picking = pickingResume.current;
|
|
2211
2224
|
pickingResume.current = false;
|
|
@@ -2222,7 +2235,8 @@ ${snippet}
|
|
|
2222
2235
|
return;
|
|
2223
2236
|
}
|
|
2224
2237
|
setEntries((prev) => [...prev, { kind: "user", text }]);
|
|
2225
|
-
|
|
2238
|
+
lastAsked.current = forAgent ?? text;
|
|
2239
|
+
void agentRef.current.send(forAgent ?? text, editorContext() ?? undefined);
|
|
2226
2240
|
};
|
|
2227
2241
|
function saveFromEditor(text, file = openFile) {
|
|
2228
2242
|
if (!file)
|
package/dist/src/ui/commands.js
CHANGED
|
@@ -96,3 +96,11 @@ export function matchCommands(typed, extra = []) {
|
|
|
96
96
|
const contains = query ? all.filter((c) => !c.name.startsWith(query) && (c.name.includes(query) || c.description.includes(query))) : [];
|
|
97
97
|
return [...starts.sort((a, b) => Number(b.name === query) - Number(a.name === query)), ...contains];
|
|
98
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* A message sent while Nou was working stops it so it's answered now, but what Nou was on isn't dropped:
|
|
101
|
+
* the agent is told what that was and to finish it after, unless the new message says otherwise.
|
|
102
|
+
*/
|
|
103
|
+
export function finishAfter(text, previous) {
|
|
104
|
+
const was = previous.length > 6000 ? `${previous.slice(0, 6000)}…` : previous;
|
|
105
|
+
return `${text}\n\n[Sent while you were still working on my previous message, so you were interrupted. Handle this first, then carry on with and finish the previous request, picking up where you left off (don't redo finished steps), unless this message cancels or replaces it. The previous request was:\n${was}]`;
|
|
106
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nou-cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.14",
|
|
4
4
|
"description": "Nou: an IDE-style AI coding assistant for your terminal. Local (Ollama, LM Studio) and cloud (Claude, OpenAI, Gemini...) models, live diffs, git-aware, built-in editor.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|