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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ineedcodes",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "Your terminal, now autonomous. Just say what you want, ineed does the rest.",
5
5
  "license": "MIT",
6
6
  "type": "module",
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
- const TUI = process.stdout.isTTY && !process.env.NO_COLOR;
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
- if (TUI) { process.stdout.write(chunk); lastStreamedForHooks += chunk; }
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
- function tuiUserLine(input) {
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.0';
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);