@bahulam/code 2.6.14 → 2.6.16
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 +5 -5
- package/src/auth/tarang-auth.mjs +6 -0
- package/src/config/cli-args.mjs +7 -1
- package/src/config/model-catalog.mjs +57 -0
- package/src/core/approval-log.mjs +23 -0
- package/src/core/approval.mjs +93 -17
- package/src/core/bundled-runtime.mjs +12 -0
- package/src/core/error-guidance.mjs +8 -4
- package/src/core/file-diff.mjs +1 -1
- package/src/core/local-agent.mjs +3 -3
- package/src/core/risk-tier.mjs +53 -2
- package/src/core/safety.mjs +61 -4
- package/src/core/tool-executor.mjs +25 -13
- package/src/core/trust.mjs +5 -3
- package/src/index.mjs +7 -3
- package/src/permissions/command-classifier.mjs +50 -2
- package/src/telemetry/index.mjs +97 -71
- package/src/terminal/main.mjs +40 -0
- package/src/terminal/repl-format.mjs +64 -4
- package/src/terminal/repl-model-form.mjs +132 -0
- package/src/terminal/repl-render.mjs +256 -33
- package/src/terminal/repl-resume.mjs +27 -12
- package/src/terminal/repl-state.mjs +16 -0
- package/src/terminal/repl.mjs +644 -85
- package/src/terminal/tool-display.mjs +20 -1
- package/src/ui/approval.mjs +33 -5
- package/src/ui/input-dock.mjs +192 -16
- package/src/ui/render-queue.mjs +500 -0
- package/src/ui/slash-commands.mjs +2 -0
- package/src/ui/sub-agent.mjs +17 -2
- package/src/ui/tool-card.mjs +156 -13
- package/src/ui/tool-details.mjs +96 -3
|
@@ -30,6 +30,8 @@ import {
|
|
|
30
30
|
resumeModeLabel,
|
|
31
31
|
resumeTailTurnCount,
|
|
32
32
|
startResumeProgress,
|
|
33
|
+
writeOverlayFrame,
|
|
34
|
+
eraseOverlayFrame,
|
|
33
35
|
} from './repl-format.mjs';
|
|
34
36
|
import { TarangStreamClient } from '../core/stream-client.mjs';
|
|
35
37
|
import { getRecentSessions, getSessionDetail, buildResumeHistory, combineResumeSummaries } from '../core/local-store.mjs';
|
|
@@ -86,9 +88,6 @@ export async function pickResumableSession(resumable, ctx) {
|
|
|
86
88
|
let renderedLines = 0;
|
|
87
89
|
|
|
88
90
|
const renderMenu = () => {
|
|
89
|
-
if (renderedLines > 0) {
|
|
90
|
-
process.stderr.write(`\x1b[${renderedLines}F\r\x1b[J`);
|
|
91
|
-
}
|
|
92
91
|
if (selected < offset) offset = selected;
|
|
93
92
|
if (selected >= offset + pageSize) offset = selected - pageSize + 1;
|
|
94
93
|
|
|
@@ -119,13 +118,19 @@ export async function pickResumableSession(resumable, ctx) {
|
|
|
119
118
|
` ${c.dim(`↑↓ move · Enter resume · P preview · Esc cancel · ${selected + 1}/${resumable.length}`)}`,
|
|
120
119
|
cols - 1
|
|
121
120
|
));
|
|
122
|
-
|
|
121
|
+
writeOverlayFrame(renderedLines, lines);
|
|
123
122
|
renderedLines = lines.length;
|
|
124
123
|
};
|
|
125
124
|
|
|
126
125
|
const cleanup = (value) => {
|
|
127
126
|
process.stdin.removeListener('data', onData);
|
|
128
127
|
process.stdin.setRawMode(wasRaw || false);
|
|
128
|
+
// Collapse the list to one line: picked → which session; preview →
|
|
129
|
+
// erase only (preview overlay paints next); cancel → caller reports.
|
|
130
|
+
const picked = value?.action === 'resume' ? value.session : null;
|
|
131
|
+
eraseOverlayFrame(renderedLines, picked
|
|
132
|
+
? ` ${c.green('↺')} ${c.brand(picked.project || '(unknown)')} ${c.dim(`· ${picked.messageCount} msgs · resuming…`)}`
|
|
133
|
+
: '');
|
|
129
134
|
if (rl) rl.resume();
|
|
130
135
|
resolve(value);
|
|
131
136
|
};
|
|
@@ -183,7 +188,6 @@ export async function chooseThresholdMode(ctx, decision) {
|
|
|
183
188
|
let renderedLines = 0;
|
|
184
189
|
|
|
185
190
|
const render = () => {
|
|
186
|
-
if (renderedLines > 0) process.stderr.write(`\x1b[${renderedLines}F\r\x1b[J`);
|
|
187
191
|
const cols = Math.max(60, process.stderr.columns || 120);
|
|
188
192
|
const pct = Math.round(decision.usageRatio * 100);
|
|
189
193
|
const projected = formatCtxTokens(decision.projected);
|
|
@@ -221,13 +225,16 @@ export async function chooseThresholdMode(ctx, decision) {
|
|
|
221
225
|
}
|
|
222
226
|
lines.push('');
|
|
223
227
|
lines.push(fitAnsiLine(` ${c.dim('↑↓ move · Enter pick · f/s/1/2 shortcut · Esc cancel')}`, cols - 1));
|
|
224
|
-
|
|
228
|
+
writeOverlayFrame(renderedLines, lines);
|
|
225
229
|
renderedLines = lines.length;
|
|
226
230
|
};
|
|
227
231
|
|
|
228
232
|
const cleanup = (value) => {
|
|
229
233
|
process.stdin.removeListener('data', onData);
|
|
230
234
|
process.stdin.setRawMode(wasRaw || false);
|
|
235
|
+
eraseOverlayFrame(renderedLines, value
|
|
236
|
+
? ` ${c.dim('mode:')} ${c.brand(resumeModeLabel(value))}`
|
|
237
|
+
: '');
|
|
231
238
|
if (rl) rl.resume();
|
|
232
239
|
resolve(value);
|
|
233
240
|
};
|
|
@@ -281,7 +288,6 @@ export async function previewResumeSession(session, ctx) {
|
|
|
281
288
|
let scrollOffset = 0;
|
|
282
289
|
|
|
283
290
|
const render = () => {
|
|
284
|
-
if (renderedLines > 0) process.stderr.write(`\x1b[${renderedLines}F\r\x1b[J`);
|
|
285
291
|
const cols = Math.max(60, process.stderr.columns || 120);
|
|
286
292
|
const rows = Math.max(10, Math.min((process.stderr.rows || 30) - 6, 20));
|
|
287
293
|
const contentLines = (history.summary || '').split('\n');
|
|
@@ -305,13 +311,14 @@ export async function previewResumeSession(session, ctx) {
|
|
|
305
311
|
}
|
|
306
312
|
lines.push('');
|
|
307
313
|
lines.push(fitAnsiLine(` ${c.dim(`↑↓/PgUp/PgDn scroll · f/s/1/2 switch mode · Enter resume this · q back · ${scrollOffset + 1}-${Math.min(scrollOffset + rows, totalLines)}/${totalLines}`)}`, cols - 1));
|
|
308
|
-
|
|
314
|
+
writeOverlayFrame(renderedLines, lines);
|
|
309
315
|
renderedLines = lines.length;
|
|
310
316
|
};
|
|
311
317
|
|
|
312
318
|
const cleanup = (value) => {
|
|
313
319
|
process.stdin.removeListener('data', onData);
|
|
314
320
|
process.stdin.setRawMode(wasRaw || false);
|
|
321
|
+
eraseOverlayFrame(renderedLines);
|
|
315
322
|
if (rl) rl.resume();
|
|
316
323
|
resolve(value);
|
|
317
324
|
};
|
|
@@ -343,9 +350,12 @@ export async function previewResumeSession(session, ctx) {
|
|
|
343
350
|
*/
|
|
344
351
|
export async function confirmCwdSwitch(ctx, savedPath, currentPath) {
|
|
345
352
|
if (!process.stdin.isTTY) return 'switch';
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
353
|
+
const frame = [
|
|
354
|
+
` ${c.dim('This session lives in another repo:')}`,
|
|
355
|
+
` ${c.dim('→')} ${c.brand(savedPath)} ${c.dim(`(current cwd: ${currentPath})`)}`,
|
|
356
|
+
` ${c.dim('[Enter]')} switch cwd and resume · ${c.dim('[s]')} stay here and resume anyway · ${c.dim('[n]')} cancel`,
|
|
357
|
+
];
|
|
358
|
+
writeOverlayFrame(0, frame);
|
|
349
359
|
const rl = ctx._rl || null;
|
|
350
360
|
if (rl) rl.pause();
|
|
351
361
|
return await new Promise((resolve) => {
|
|
@@ -353,8 +363,13 @@ export async function confirmCwdSwitch(ctx, savedPath, currentPath) {
|
|
|
353
363
|
const cleanup = (value) => {
|
|
354
364
|
process.stdin.removeListener('data', onData);
|
|
355
365
|
process.stdin.setRawMode(wasRaw || false);
|
|
366
|
+
const summary = value === 'switch'
|
|
367
|
+
? ` ${c.dim('cwd →')} ${c.brand(savedPath)}`
|
|
368
|
+
: value === 'stay'
|
|
369
|
+
? ` ${c.dim(`staying in ${currentPath}`)}`
|
|
370
|
+
: '';
|
|
371
|
+
eraseOverlayFrame(frame.length, summary);
|
|
356
372
|
if (rl) rl.resume();
|
|
357
|
-
process.stderr.write('\n');
|
|
358
373
|
resolve(value);
|
|
359
374
|
};
|
|
360
375
|
const onData = (data) => {
|
|
@@ -39,6 +39,7 @@ export const runtime = {
|
|
|
39
39
|
pendingHead: null, // { callId, head, indent } buffered until result arrives
|
|
40
40
|
lastRenderedBlock: null, // 'tool' | 'content' | 'thinking' | 'status' | 'plan' | null
|
|
41
41
|
renderedToolResults: new Set(),
|
|
42
|
+
renderedFileDiffPreviews: new Set(),
|
|
42
43
|
|
|
43
44
|
// Explore-run collapse (read/list/search/index bursts as concise progress).
|
|
44
45
|
exploreRun: { counts: {}, recent: [], lineActive: false, lastPrintedSummary: '', lastPrintedTotal: 0, lastPrintedAt: 0 },
|
|
@@ -48,6 +49,19 @@ export const runtime = {
|
|
|
48
49
|
spinInterval: null,
|
|
49
50
|
spinText: '',
|
|
50
51
|
spinFrame: 0,
|
|
52
|
+
// Activity phase tracking — elapsed time + progress counters on the
|
|
53
|
+
// status line. spinPhase changes reset spinStartedAt; text updates
|
|
54
|
+
// within the same phase keep the clock running so "thinking · 14s"
|
|
55
|
+
// and "explore agent · 32s · 12 calls" count up live.
|
|
56
|
+
spinPhase: null, // 'thinking' | 'status' | `tool:<id>` | `sub:<type>` | null
|
|
57
|
+
spinStartedAt: 0, // Date.now() when the current phase began
|
|
58
|
+
spinToolCalls: 0, // per-phase tool-call counter (sub-agents)
|
|
59
|
+
|
|
60
|
+
// Sub-agent live tool window: while a sub-agent runs (queue active),
|
|
61
|
+
// its inner tool calls stream into a fixed-height status block (last
|
|
62
|
+
// N lines under the spinner) instead of appending to the transcript.
|
|
63
|
+
// Full detail stays on the recorded cards (/expand, /last, `d`).
|
|
64
|
+
subAgentWindow: { active: false, lines: [] },
|
|
51
65
|
};
|
|
52
66
|
|
|
53
67
|
// Full session state for the current CLI process. Set by the REPL loop
|
|
@@ -89,6 +103,8 @@ export const session = {
|
|
|
89
103
|
totalCost: 0, // accumulated session cost (USD)
|
|
90
104
|
costAccurate: false, // true if backend provides per-model breakdown
|
|
91
105
|
modelOverrides: {}, // session-local role -> model overrides sent to backend
|
|
106
|
+
modelMode: null, // named mode (fast|thinking|extra|max) sent as model_mode
|
|
107
|
+
routePreference: null, // --route platform|byok; controls catalog validation only
|
|
92
108
|
isByok: false, // set from session_info; hides cost + credits when true
|
|
93
109
|
// ── Subscription / credit state (server-authoritative; set from
|
|
94
110
|
// session_info + complete events) ──
|