ineedcodes 1.5.0 → 1.5.1
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/package.json +1 -1
- package/src/config.js +1 -0
- package/src/session.js +32 -4
- package/src/ui.js +1 -1
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -26,6 +26,7 @@ export function normalize(c) {
|
|
|
26
26
|
mode: c.mode === 'plan' ? 'plan' : 'build',
|
|
27
27
|
memory: c.memory !== false,
|
|
28
28
|
mcp: c.mcp !== false,
|
|
29
|
+
tui: c.tui === true ? true : c.tui === false ? false : null,
|
|
29
30
|
humanize: c.humanize !== false,
|
|
30
31
|
stream: c.stream === true,
|
|
31
32
|
searchUrl: c.searchUrl ? String(c.searchUrl) : '',
|
package/src/session.js
CHANGED
|
@@ -77,7 +77,11 @@ export async function startSession(cfg, { fresh = false, resume = null } = {}) {
|
|
|
77
77
|
const pendingLines = [];
|
|
78
78
|
const steerQueue = []; // notes typed while a task runs, injected mid-task
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
// Full-screen TUI: great in ANSI terminals (Linux/macOS/Windows Terminal), but
|
|
81
|
+
// legacy Windows consoles garble alt-screen sequences. Auto: on everywhere except
|
|
82
|
+
// win32; force with config "tui": true, disable with "tui": false.
|
|
83
|
+
const TUI = process.stdout.isTTY && !process.env.NO_COLOR
|
|
84
|
+
&& (state.tui === true || (state.tui === null && process.platform !== 'win32'));
|
|
81
85
|
let sessionId = null;
|
|
82
86
|
let lastBoost = null;
|
|
83
87
|
let usage = { input: 0, output: 0 };
|
|
@@ -86,6 +90,14 @@ export async function startSession(cfg, { fresh = false, resume = null } = {}) {
|
|
|
86
90
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
87
91
|
let handleRef = null;
|
|
88
92
|
const ask = makeInput(rl, l => handleRef?.(l));
|
|
93
|
+
// EOF (Ctrl+D or closed pipe): exit cleanly, unless a task is still running
|
|
94
|
+
rl.on('close', () => {
|
|
95
|
+
if (!busy) doExit();
|
|
96
|
+
else {
|
|
97
|
+
const wait = setInterval(() => { if (!busy) { clearInterval(wait); doExit(); } }, 200);
|
|
98
|
+
setTimeout(() => { clearInterval(wait); doExit(); }, 30_000);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
89
101
|
|
|
90
102
|
const say = TUI ? lines => tuiPrint(lines) : (lines => console.log(lines));
|
|
91
103
|
|
|
@@ -116,6 +128,17 @@ export async function startSession(cfg, { fresh = false, resume = null } = {}) {
|
|
|
116
128
|
}
|
|
117
129
|
|
|
118
130
|
let lastStreamedForHooks = '';
|
|
131
|
+
let streamFlushTimer = null;
|
|
132
|
+
let streamFlushedCount = 0;
|
|
133
|
+
let streamBaseLines = null;
|
|
134
|
+
|
|
135
|
+
function flushStreamed() {
|
|
136
|
+
if (!TUI || !lastStreamedForHooks) return;
|
|
137
|
+
if (streamBaseLines === null) streamBaseLines = chatLines.length;
|
|
138
|
+
chatLines.length = streamBaseLines; // re-render the growing answer in place
|
|
139
|
+
for (const l of wrapLines(lastStreamedForHooks, Math.max(10, (process.stdout.columns || 80) - 4))) chatLines.push(l);
|
|
140
|
+
redrawChat();
|
|
141
|
+
}
|
|
119
142
|
|
|
120
143
|
function hooksForRun(stopSpinner) {
|
|
121
144
|
let spinner = null;
|
|
@@ -132,7 +155,11 @@ export async function startSession(cfg, { fresh = false, resume = null } = {}) {
|
|
|
132
155
|
onResult: out => { say(gray(' ' + trunc(out, 110))); },
|
|
133
156
|
onText: t => { stop(); },
|
|
134
157
|
onDelta: chunk => {
|
|
135
|
-
|
|
158
|
+
// stream into the chat buffer; the full text lands on flushStreamed()
|
|
159
|
+
lastStreamedForHooks += chunk;
|
|
160
|
+
if (TUI && !streamFlushTimer) {
|
|
161
|
+
streamFlushTimer = setTimeout(() => { streamFlushTimer = null; flushStreamed(); }, 120);
|
|
162
|
+
}
|
|
136
163
|
},
|
|
137
164
|
onTodos: list => {
|
|
138
165
|
stop();
|
|
@@ -174,6 +201,7 @@ export async function startSession(cfg, { fresh = false, resume = null } = {}) {
|
|
|
174
201
|
async function runTask(input) {
|
|
175
202
|
busy = true;
|
|
176
203
|
lastStreamedForHooks = '';
|
|
204
|
+
streamFlushedCount = 0;
|
|
177
205
|
if (TUI) tuiUserLine(input);
|
|
178
206
|
const hooks = hooksForRun();
|
|
179
207
|
const stopSpinner = hooks.spinnerStop;
|
|
@@ -609,10 +637,10 @@ export async function startSession(cfg, { fresh = false, resume = null } = {}) {
|
|
|
609
637
|
redrawChat();
|
|
610
638
|
}
|
|
611
639
|
|
|
612
|
-
|
|
640
|
+
const tuiUserLine = input => {
|
|
613
641
|
for (const l of wrapLines(userBubble(input), Math.max(10, (process.stdout.columns || 80) - 4))) chatLines.push(l);
|
|
614
642
|
redrawChat();
|
|
615
|
-
}
|
|
643
|
+
};
|
|
616
644
|
|
|
617
645
|
const layout = () => {
|
|
618
646
|
const rows = process.stdout.rows || 24;
|
package/src/ui.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// ui.js: terminal helpers. No dependencies, respects NO_COLOR and non-TTY.
|
|
2
2
|
|
|
3
|
-
export const VERSION = '1.5.
|
|
3
|
+
export const VERSION = '1.5.1';
|
|
4
4
|
|
|
5
5
|
const USE_COLOR = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
6
6
|
const wrap = (code, t) => USE_COLOR ? `\x1b[${code}m${t}\x1b[0m` : String(t);
|