@corenel/term 0.2.9 → 0.3.0
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/dist/{chunk-L4KCEKIT.js → chunk-2MGDL3I4.js} +7 -2
- package/dist/chunk-5RPHYXND.js +138 -0
- package/dist/{chunk-QZJTOVZL.js → chunk-HUVRQX53.js} +513 -34
- package/dist/commands.d.ts +39 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +11 -3
- package/dist/contextText.d.ts +37 -0
- package/dist/contextText.d.ts.map +1 -0
- package/dist/ink/App.d.ts +14 -0
- package/dist/ink/App.d.ts.map +1 -1
- package/dist/ink/ContextOverlay.d.ts +18 -0
- package/dist/ink/ContextOverlay.d.ts.map +1 -0
- package/dist/ink/HelpOverlay.d.ts +12 -0
- package/dist/ink/HelpOverlay.d.ts.map +1 -0
- package/dist/ink/McpOverlay.d.ts +12 -0
- package/dist/ink/McpOverlay.d.ts.map +1 -0
- package/dist/ink/Modal.d.ts +7 -2
- package/dist/ink/Modal.d.ts.map +1 -1
- package/dist/ink/index.d.ts.map +1 -1
- package/dist/ink/index.js +253 -77
- package/dist/ink/scroll.d.ts.map +1 -1
- package/dist/mcpText.d.ts +20 -0
- package/dist/mcpText.d.ts.map +1 -0
- package/dist/session.d.ts +172 -6
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +3 -3
- package/dist/state.d.ts +83 -2
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-VTJEWHM3.js +0 -65
package/dist/ink/index.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TermSession,
|
|
3
|
+
ageWord,
|
|
4
|
+
formatContext,
|
|
5
|
+
mcpStatusWord,
|
|
3
6
|
parseMarkdown
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-HUVRQX53.js";
|
|
8
|
+
import "../chunk-2MGDL3I4.js";
|
|
6
9
|
import {
|
|
10
|
+
TERM_COMMANDS,
|
|
7
11
|
filterCommands,
|
|
8
12
|
parseCommand
|
|
9
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-5RPHYXND.js";
|
|
10
14
|
import "../chunk-M44CET5L.js";
|
|
11
15
|
import {
|
|
12
16
|
formatEndingChange
|
|
@@ -28,7 +32,7 @@ import { STANDARD_POLICY } from "@corenel/harness/guardrail/builtins";
|
|
|
28
32
|
// src/ink/App.tsx
|
|
29
33
|
import { useEffect, useState } from "react";
|
|
30
34
|
import { homedir } from "node:os";
|
|
31
|
-
import { Box as
|
|
35
|
+
import { Box as Box8, Static, Text as Text8, useStdout } from "ink";
|
|
32
36
|
import TextInput from "ink-text-input";
|
|
33
37
|
|
|
34
38
|
// src/ink/items.tsx
|
|
@@ -169,27 +173,132 @@ function LiveToolRow({ tool }) {
|
|
|
169
173
|
] });
|
|
170
174
|
}
|
|
171
175
|
|
|
172
|
-
// src/ink/
|
|
176
|
+
// src/ink/McpOverlay.tsx
|
|
173
177
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
174
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
178
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
179
|
+
function statusColor(word) {
|
|
180
|
+
if (word === "connected") return palette.good;
|
|
181
|
+
if (word === "unreachable") return palette.bad;
|
|
182
|
+
return palette.warn;
|
|
183
|
+
}
|
|
184
|
+
function McpOverlay({ modal }) {
|
|
185
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: palette.tool, paddingX: 1, children: [
|
|
186
|
+
/* @__PURE__ */ jsx2(Text2, { color: palette.tool, bold: true, children: "MCP servers" }),
|
|
187
|
+
modal.servers.length === 0 ? /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: palette.dim, children: "none configured -- press a to add one" }) }) : /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginTop: 1, children: modal.servers.map((s, i) => {
|
|
188
|
+
const word = mcpStatusWord(s);
|
|
189
|
+
const isSelected = i === modal.selected;
|
|
190
|
+
return /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
191
|
+
/* @__PURE__ */ jsx2(Text2, { color: palette.ember, children: isSelected ? `${glyph.active} ` : " " }),
|
|
192
|
+
/* @__PURE__ */ jsx2(Text2, { bold: isSelected, children: s.name }),
|
|
193
|
+
/* @__PURE__ */ jsx2(Text2, { color: palette.dim, children: " " }),
|
|
194
|
+
/* @__PURE__ */ jsx2(Text2, { color: statusColor(word), children: word }),
|
|
195
|
+
/* @__PURE__ */ jsxs2(Text2, { color: palette.dim, children: [
|
|
196
|
+
" ",
|
|
197
|
+
s.toolCount,
|
|
198
|
+
" tool",
|
|
199
|
+
s.toolCount === 1 ? "" : "s",
|
|
200
|
+
", ",
|
|
201
|
+
ageWord(s.fetchedAt, Date.now())
|
|
202
|
+
] })
|
|
203
|
+
] }, s.name);
|
|
204
|
+
}) }),
|
|
205
|
+
modal.login ? /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginTop: 1, children: modal.login.url ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
206
|
+
/* @__PURE__ */ jsxs2(Text2, { color: palette.amber, children: [
|
|
207
|
+
"signing in to ",
|
|
208
|
+
modal.login.server,
|
|
209
|
+
" -- open this URL:"
|
|
210
|
+
] }),
|
|
211
|
+
/* @__PURE__ */ jsx2(Text2, { children: modal.login.url }),
|
|
212
|
+
/* @__PURE__ */ jsx2(Text2, { color: palette.dim, children: "esc cancels" })
|
|
213
|
+
] }) : /* @__PURE__ */ jsxs2(Text2, { color: palette.amber, children: [
|
|
214
|
+
"signing in to ",
|
|
215
|
+
modal.login.server,
|
|
216
|
+
" -- waiting for a login URL..."
|
|
217
|
+
] }) }) : null,
|
|
218
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsxs2(Text2, { color: palette.dim, children: [
|
|
219
|
+
glyph.active,
|
|
220
|
+
" select ",
|
|
221
|
+
glyph.sep,
|
|
222
|
+
" a add ",
|
|
223
|
+
glyph.sep,
|
|
224
|
+
" x remove ",
|
|
225
|
+
glyph.sep,
|
|
226
|
+
" l login ",
|
|
227
|
+
glyph.sep,
|
|
228
|
+
" r refresh ",
|
|
229
|
+
glyph.sep,
|
|
230
|
+
" esc close"
|
|
231
|
+
] }) })
|
|
232
|
+
] });
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/ink/HelpOverlay.tsx
|
|
236
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
237
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
238
|
+
function HelpOverlay() {
|
|
239
|
+
const width = Math.max(...TERM_COMMANDS.map((c) => `${c.name} ${c.args ?? ""}`.trim().length));
|
|
240
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", borderStyle: "round", borderColor: palette.tool, paddingX: 1, children: [
|
|
241
|
+
/* @__PURE__ */ jsx3(Text3, { color: palette.tool, bold: true, children: "Commands" }),
|
|
242
|
+
/* @__PURE__ */ jsx3(Box3, { flexDirection: "column", marginTop: 1, children: TERM_COMMANDS.map((c) => {
|
|
243
|
+
const usage = `${c.name} ${c.args ?? ""}`.trim();
|
|
244
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
245
|
+
/* @__PURE__ */ jsxs3(Text3, { color: palette.ember, children: [
|
|
246
|
+
"/",
|
|
247
|
+
usage.padEnd(width)
|
|
248
|
+
] }),
|
|
249
|
+
/* @__PURE__ */ jsxs3(Text3, { color: palette.dim, children: [
|
|
250
|
+
" ",
|
|
251
|
+
c.summary
|
|
252
|
+
] })
|
|
253
|
+
] }, c.name);
|
|
254
|
+
}) }),
|
|
255
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { color: palette.dim, children: "esc close" }) })
|
|
256
|
+
] });
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// src/ink/ContextOverlay.tsx
|
|
260
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
261
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
262
|
+
function ContextOverlay({ snapshot }) {
|
|
263
|
+
const text = formatContext(snapshot);
|
|
264
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: palette.tool, paddingX: 1, children: [
|
|
265
|
+
/* @__PURE__ */ jsx4(Text4, { color: palette.tool, bold: true, children: "Context window" }),
|
|
266
|
+
/* @__PURE__ */ jsx4(Box4, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { children: text }) }),
|
|
267
|
+
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { color: palette.dim, children: "esc close" }) })
|
|
268
|
+
] });
|
|
269
|
+
}
|
|
270
|
+
function contextSnapshotFromState(state, contextWindow, toolCount) {
|
|
271
|
+
return {
|
|
272
|
+
sentTokens: state.sentTokens,
|
|
273
|
+
contextWindow,
|
|
274
|
+
offloaded: state.offloaded,
|
|
275
|
+
checkpoints: state.checkpoints,
|
|
276
|
+
toolCount,
|
|
277
|
+
loadedToolNames: state.toolNames
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/ink/Modal.tsx
|
|
282
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
283
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
175
284
|
function DiffPreview({ diff }) {
|
|
176
285
|
const contentUnchanged = diff.added === 0 && diff.removed === 0;
|
|
177
|
-
const endingRow = diff.endingChange && /* @__PURE__ */
|
|
178
|
-
const unexplainedRow = diff.unexplainedChange && /* @__PURE__ */
|
|
286
|
+
const endingRow = diff.endingChange && /* @__PURE__ */ jsx5(Text5, { color: palette.amber, bold: true, children: formatEndingChange(diff.endingChange, contentUnchanged) });
|
|
287
|
+
const unexplainedRow = diff.unexplainedChange && /* @__PURE__ */ jsx5(Text5, { color: palette.amber, bold: true, children: "the file changes in a way not shown above (e.g. trailing whitespace or encoding)" });
|
|
179
288
|
if (diff.noop) {
|
|
180
|
-
return /* @__PURE__ */
|
|
289
|
+
return /* @__PURE__ */ jsx5(Text5, { color: palette.dim, children: "(no change -- new content is identical to what's on disk)" });
|
|
181
290
|
}
|
|
182
|
-
return /* @__PURE__ */
|
|
291
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
183
292
|
endingRow,
|
|
184
293
|
unexplainedRow,
|
|
185
|
-
diff.isNewFile && /* @__PURE__ */
|
|
294
|
+
diff.isNewFile && /* @__PURE__ */ jsx5(Text5, { color: palette.dim, children: "(new file)" }),
|
|
186
295
|
diff.rows.map((r, i) => {
|
|
187
296
|
if (r.kind === "skip") {
|
|
188
297
|
const label = r.reason === "changes" ? `\u2026 ${r.count} more changed line${r.count === 1 ? "" : "s"}` : `\u2026 ${r.count} unchanged line${r.count === 1 ? "" : "s"}`;
|
|
189
|
-
return /* @__PURE__ */
|
|
298
|
+
return /* @__PURE__ */ jsx5(Text5, { color: palette.dim, children: label }, i);
|
|
190
299
|
}
|
|
191
|
-
return /* @__PURE__ */
|
|
192
|
-
|
|
300
|
+
return /* @__PURE__ */ jsxs5(
|
|
301
|
+
Text5,
|
|
193
302
|
{
|
|
194
303
|
color: r.kind === "add" ? palette.good : r.kind === "del" ? palette.bad : palette.dim,
|
|
195
304
|
children: [
|
|
@@ -200,7 +309,7 @@ function DiffPreview({ diff }) {
|
|
|
200
309
|
i
|
|
201
310
|
);
|
|
202
311
|
}),
|
|
203
|
-
/* @__PURE__ */
|
|
312
|
+
/* @__PURE__ */ jsxs5(Text5, { color: palette.dim, children: [
|
|
204
313
|
"+",
|
|
205
314
|
diff.added,
|
|
206
315
|
" \u2212",
|
|
@@ -210,37 +319,37 @@ function DiffPreview({ diff }) {
|
|
|
210
319
|
}
|
|
211
320
|
function ModalView({ modal }) {
|
|
212
321
|
if (modal.kind === "permission") {
|
|
213
|
-
return /* @__PURE__ */
|
|
214
|
-
/* @__PURE__ */
|
|
322
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: palette.warn, paddingX: 1, children: [
|
|
323
|
+
/* @__PURE__ */ jsxs5(Text5, { color: palette.warn, children: [
|
|
215
324
|
modal.tool,
|
|
216
325
|
" wants to run"
|
|
217
326
|
] }),
|
|
218
|
-
/* @__PURE__ */
|
|
219
|
-
modal.diff && /* @__PURE__ */
|
|
220
|
-
/* @__PURE__ */
|
|
221
|
-
/* @__PURE__ */
|
|
222
|
-
/* @__PURE__ */
|
|
223
|
-
/* @__PURE__ */
|
|
224
|
-
/* @__PURE__ */
|
|
327
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { bold: true, children: modal.detail }) }),
|
|
328
|
+
modal.diff && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(DiffPreview, { diff: modal.diff }) }),
|
|
329
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
330
|
+
/* @__PURE__ */ jsx5(Text5, { color: palette.good, children: "[y]" }),
|
|
331
|
+
/* @__PURE__ */ jsx5(Text5, { color: palette.dim, children: " run it " }),
|
|
332
|
+
/* @__PURE__ */ jsx5(Text5, { color: palette.bad, children: "[n]" }),
|
|
333
|
+
/* @__PURE__ */ jsx5(Text5, { color: palette.dim, children: " deny esc denies" })
|
|
225
334
|
] })
|
|
226
335
|
] });
|
|
227
336
|
}
|
|
228
337
|
const q = modal.questions[0];
|
|
229
|
-
return /* @__PURE__ */
|
|
230
|
-
/* @__PURE__ */
|
|
231
|
-
/* @__PURE__ */
|
|
232
|
-
/* @__PURE__ */
|
|
233
|
-
/* @__PURE__ */
|
|
338
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: palette.ember, paddingX: 1, children: [
|
|
339
|
+
/* @__PURE__ */ jsx5(Text5, { color: palette.dim, children: q?.header }),
|
|
340
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, children: q?.question }),
|
|
341
|
+
/* @__PURE__ */ jsx5(Box5, { flexDirection: "column", marginTop: 1, children: (q?.options ?? []).map((o, i) => /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
342
|
+
/* @__PURE__ */ jsxs5(Text5, { color: palette.amber, children: [
|
|
234
343
|
i + 1,
|
|
235
344
|
" "
|
|
236
345
|
] }),
|
|
237
|
-
/* @__PURE__ */
|
|
238
|
-
o.description ? /* @__PURE__ */
|
|
346
|
+
/* @__PURE__ */ jsx5(Text5, { children: o.label }),
|
|
347
|
+
o.description ? /* @__PURE__ */ jsxs5(Text5, { color: palette.dim, children: [
|
|
239
348
|
" ",
|
|
240
349
|
o.description
|
|
241
350
|
] }) : null
|
|
242
351
|
] }, o.label)) }),
|
|
243
|
-
/* @__PURE__ */
|
|
352
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsxs5(Text5, { color: palette.dim, children: [
|
|
244
353
|
"1-",
|
|
245
354
|
(q?.options ?? []).length,
|
|
246
355
|
" choose \xB7 \u21B5 confirm \xB7 or type your own answer \xB7 esc dismisses"
|
|
@@ -249,28 +358,28 @@ function ModalView({ modal }) {
|
|
|
249
358
|
}
|
|
250
359
|
|
|
251
360
|
// src/ink/Palette.tsx
|
|
252
|
-
import { Box as
|
|
253
|
-
import { jsx as
|
|
361
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
362
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
254
363
|
function PaletteView({ items, selected }) {
|
|
255
|
-
return /* @__PURE__ */
|
|
256
|
-
items.map((c, i) => /* @__PURE__ */
|
|
257
|
-
/* @__PURE__ */
|
|
364
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
365
|
+
items.map((c, i) => /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
366
|
+
/* @__PURE__ */ jsxs6(Text6, { color: i === selected ? palette.ember : palette.dim, children: [
|
|
258
367
|
i === selected ? "\u203A " : " ",
|
|
259
368
|
"/",
|
|
260
369
|
c.name,
|
|
261
370
|
c.args ? ` ${c.args}` : ""
|
|
262
371
|
] }),
|
|
263
|
-
/* @__PURE__ */
|
|
372
|
+
/* @__PURE__ */ jsxs6(Text6, { color: palette.dim, children: [
|
|
264
373
|
" ",
|
|
265
374
|
c.summary
|
|
266
375
|
] })
|
|
267
376
|
] }, c.name)),
|
|
268
|
-
/* @__PURE__ */
|
|
377
|
+
/* @__PURE__ */ jsx6(Text6, { color: palette.dim, children: " \u2191\u2193 choose \xB7 tab completes \xB7 esc closes" })
|
|
269
378
|
] });
|
|
270
379
|
}
|
|
271
380
|
|
|
272
381
|
// src/ink/TodoBlock.tsx
|
|
273
|
-
import { Box as
|
|
382
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
274
383
|
|
|
275
384
|
// src/ink/todos.ts
|
|
276
385
|
var DEFAULT_TODO_ROW_CAP = 4;
|
|
@@ -300,7 +409,7 @@ function toRows(items) {
|
|
|
300
409
|
}
|
|
301
410
|
|
|
302
411
|
// src/ink/TodoBlock.tsx
|
|
303
|
-
import { jsx as
|
|
412
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
304
413
|
function marker(status) {
|
|
305
414
|
switch (status) {
|
|
306
415
|
case "in_progress":
|
|
@@ -316,21 +425,21 @@ function marker(status) {
|
|
|
316
425
|
}
|
|
317
426
|
function TodoRowView({ row }) {
|
|
318
427
|
const { char, color } = marker(row.status);
|
|
319
|
-
return /* @__PURE__ */
|
|
320
|
-
/* @__PURE__ */
|
|
428
|
+
return /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
429
|
+
/* @__PURE__ */ jsxs7(Text7, { color, children: [
|
|
321
430
|
char,
|
|
322
431
|
" "
|
|
323
432
|
] }),
|
|
324
|
-
/* @__PURE__ */
|
|
433
|
+
/* @__PURE__ */ jsx7(Text7, { color: row.status === "in_progress" ? palette.ink : palette.soft, children: row.title })
|
|
325
434
|
] });
|
|
326
435
|
}
|
|
327
436
|
function TodoBlock({ todos }) {
|
|
328
437
|
const view = visibleTodos(todos);
|
|
329
438
|
if (!view) return null;
|
|
330
|
-
return /* @__PURE__ */
|
|
331
|
-
/* @__PURE__ */
|
|
332
|
-
view.rows.map((row) => /* @__PURE__ */
|
|
333
|
-
view.overflow ? /* @__PURE__ */
|
|
439
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, children: [
|
|
440
|
+
/* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: view.header }),
|
|
441
|
+
view.rows.map((row) => /* @__PURE__ */ jsx7(TodoRowView, { row }, row.id)),
|
|
442
|
+
view.overflow ? /* @__PURE__ */ jsxs7(Text7, { color: palette.dim, children: [
|
|
334
443
|
" ",
|
|
335
444
|
view.overflow
|
|
336
445
|
] }) : null
|
|
@@ -380,7 +489,7 @@ function fitStatus(left, identity, columns) {
|
|
|
380
489
|
}
|
|
381
490
|
|
|
382
491
|
// src/ink/App.tsx
|
|
383
|
-
import { jsx as
|
|
492
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
384
493
|
function useColumns() {
|
|
385
494
|
const { stdout } = useStdout();
|
|
386
495
|
const [columns, setColumns] = useState(stdout?.columns ?? DEFAULT_COLUMNS);
|
|
@@ -412,31 +521,31 @@ function App(props) {
|
|
|
412
521
|
const costSeg = state.costUsd > 0 ? ` ${glyph.sep} ${usd(state.costUsd)}` : "";
|
|
413
522
|
const escSeg = busy ? ` ${glyph.sep} esc stops` : "";
|
|
414
523
|
const queuedSeg = state.queued.length ? ` ${glyph.sep} ${state.queued.length} queued` : "";
|
|
415
|
-
const shellSeg =
|
|
524
|
+
const shellSeg = ` ${glyph.sep} shell ${props.approveAll ? "auto-approved" : "asks first"}`;
|
|
416
525
|
const statusLeft = ` ${statusWord}${roundSeg}${tokenSeg}${costSeg}${escSeg}${queuedSeg}${shellSeg}`;
|
|
417
|
-
const { right: statusRight } = fitStatus(statusLeft, { model:
|
|
418
|
-
return /* @__PURE__ */
|
|
419
|
-
/* @__PURE__ */
|
|
420
|
-
state.live?.tools.map((t) => /* @__PURE__ */
|
|
421
|
-
state.live?.streaming ? /* @__PURE__ */
|
|
422
|
-
/* @__PURE__ */
|
|
423
|
-
state.modal ? /* @__PURE__ */
|
|
424
|
-
paletteItems.length && !state.modal ? /* @__PURE__ */
|
|
425
|
-
state.pendingSkill ? /* @__PURE__ */
|
|
426
|
-
/* @__PURE__ */
|
|
526
|
+
const { right: statusRight } = fitStatus(statusLeft, { model: state.model, cwd: props.cwd, home: homedir() }, columns);
|
|
527
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
528
|
+
/* @__PURE__ */ jsx8(Static, { items: state.committed, children: (item) => /* @__PURE__ */ jsx8(CommittedRow, { item }, item.id) }, `transcript-${state.transcriptGen}`),
|
|
529
|
+
state.live?.tools.map((t) => /* @__PURE__ */ jsx8(LiveToolRow, { tool: t }, t.callId)),
|
|
530
|
+
state.live?.streaming ? /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.soft, children: state.live.streaming }) }) : null,
|
|
531
|
+
/* @__PURE__ */ jsx8(TodoBlock, { todos: state.todos }),
|
|
532
|
+
state.modal ? /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: state.modal.kind === "mcp" ? /* @__PURE__ */ jsx8(McpOverlay, { modal: state.modal }) : state.modal.kind === "help" ? /* @__PURE__ */ jsx8(HelpOverlay, {}) : state.modal.kind === "context" ? /* @__PURE__ */ jsx8(ContextOverlay, { snapshot: contextSnapshotFromState(state, props.contextWindow ?? null, props.toolCount) }) : state.modal.kind === "permission" || state.modal.kind === "user" ? /* @__PURE__ */ jsx8(ModalView, { modal: state.modal }) : null }) : null,
|
|
533
|
+
paletteItems.length && !state.modal ? /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(PaletteView, { items: paletteItems, selected: paletteSelected }) }) : null,
|
|
534
|
+
state.pendingSkill ? /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
|
|
535
|
+
/* @__PURE__ */ jsxs8(Text8, { color: palette.ember, children: [
|
|
427
536
|
glyph.sep,
|
|
428
537
|
" skill armed: ",
|
|
429
538
|
state.pendingSkill,
|
|
430
539
|
" "
|
|
431
540
|
] }),
|
|
432
|
-
/* @__PURE__ */
|
|
541
|
+
/* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "-- applies to your next message, then clears" })
|
|
433
542
|
] }) : null,
|
|
434
|
-
/* @__PURE__ */
|
|
435
|
-
/* @__PURE__ */
|
|
543
|
+
/* @__PURE__ */ jsxs8(Box8, { borderStyle: "round", borderColor: palette.dim, paddingX: 1, marginTop: 1, children: [
|
|
544
|
+
/* @__PURE__ */ jsxs8(Text8, { color: palette.ember, children: [
|
|
436
545
|
glyph.prompt,
|
|
437
546
|
" "
|
|
438
547
|
] }),
|
|
439
|
-
/* @__PURE__ */
|
|
548
|
+
/* @__PURE__ */ jsx8(
|
|
440
549
|
TextInput,
|
|
441
550
|
{
|
|
442
551
|
value: props.value,
|
|
@@ -448,9 +557,9 @@ function App(props) {
|
|
|
448
557
|
props.inputKey
|
|
449
558
|
)
|
|
450
559
|
] }),
|
|
451
|
-
state.committed.length === 0 ? /* @__PURE__ */
|
|
560
|
+
state.committed.length === 0 ? /* @__PURE__ */ jsx8(Box8, { marginBottom: 1, children: /* @__PURE__ */ jsxs8(Text8, { color: palette.soft, children: [
|
|
452
561
|
"Type a request. ",
|
|
453
|
-
/* @__PURE__ */
|
|
562
|
+
/* @__PURE__ */ jsxs8(Text8, { color: palette.dim, children: [
|
|
454
563
|
"/help for commands ",
|
|
455
564
|
glyph.sep,
|
|
456
565
|
" Ctrl-C stops a turn ",
|
|
@@ -458,22 +567,22 @@ function App(props) {
|
|
|
458
567
|
" Ctrl-D leaves"
|
|
459
568
|
] })
|
|
460
569
|
] }) }) : null,
|
|
461
|
-
/* @__PURE__ */
|
|
462
|
-
/* @__PURE__ */
|
|
463
|
-
/* @__PURE__ */
|
|
570
|
+
/* @__PURE__ */ jsxs8(Box8, { justifyContent: "space-between", children: [
|
|
571
|
+
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
572
|
+
/* @__PURE__ */ jsxs8(Text8, { color: busy ? palette.amber : palette.dim, children: [
|
|
464
573
|
" ",
|
|
465
574
|
statusWord
|
|
466
575
|
] }),
|
|
467
|
-
/* @__PURE__ */
|
|
576
|
+
/* @__PURE__ */ jsxs8(Text8, { color: palette.dim, children: [
|
|
468
577
|
roundSeg,
|
|
469
578
|
tokenSeg,
|
|
470
579
|
costSeg,
|
|
471
580
|
escSeg,
|
|
472
581
|
queuedSeg
|
|
473
582
|
] }),
|
|
474
|
-
|
|
583
|
+
/* @__PURE__ */ jsx8(Text8, { color: props.approveAll ? palette.ember : palette.warn, children: shellSeg })
|
|
475
584
|
] }),
|
|
476
|
-
statusRight ? /* @__PURE__ */
|
|
585
|
+
statusRight ? /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: statusRight }) : null
|
|
477
586
|
] })
|
|
478
587
|
] });
|
|
479
588
|
}
|
|
@@ -561,7 +670,7 @@ function writeBanner(out, opts) {
|
|
|
561
670
|
}
|
|
562
671
|
|
|
563
672
|
// src/ink/index.tsx
|
|
564
|
-
import { jsx as
|
|
673
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
565
674
|
function Root({ session, deps }) {
|
|
566
675
|
const state = useSyncExternalStore(
|
|
567
676
|
useCallback((fn) => session.subscribe(fn), [session]),
|
|
@@ -592,6 +701,53 @@ function Root({ session, deps }) {
|
|
|
592
701
|
};
|
|
593
702
|
useInput((input, key) => {
|
|
594
703
|
if (state.modal) {
|
|
704
|
+
if (state.modal.kind === "mcp") {
|
|
705
|
+
if (key.escape) {
|
|
706
|
+
session.closeMcpManager();
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
if (key.upArrow) {
|
|
710
|
+
session.moveMcpSelection(-1);
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
if (key.downArrow) {
|
|
714
|
+
session.moveMcpSelection(1);
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
const lower = input.toLowerCase();
|
|
718
|
+
if (lower === "x") {
|
|
719
|
+
void session.removeMcpSelection();
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
if (lower === "l") {
|
|
723
|
+
void session.loginMcpSelection();
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
if (lower === "r") {
|
|
727
|
+
void session.refreshMcpSelection();
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (lower === "a") {
|
|
731
|
+
session.closeMcpManager();
|
|
732
|
+
completeTo("/mcp add ");
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
if (state.modal.kind === "help") {
|
|
738
|
+
if (key.escape) {
|
|
739
|
+
session.closeHelp();
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
if (state.modal.kind === "context") {
|
|
745
|
+
if (key.escape) {
|
|
746
|
+
session.closeContext();
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
595
751
|
if (key.escape) {
|
|
596
752
|
session.answer(state.modal.kind === "permission" ? "deny" : null);
|
|
597
753
|
return;
|
|
@@ -649,7 +805,7 @@ function Root({ session, deps }) {
|
|
|
649
805
|
}
|
|
650
806
|
if (sawSigint) setSawSigint(false);
|
|
651
807
|
});
|
|
652
|
-
return /* @__PURE__ */
|
|
808
|
+
return /* @__PURE__ */ jsx9(
|
|
653
809
|
App,
|
|
654
810
|
{
|
|
655
811
|
state,
|
|
@@ -657,10 +813,26 @@ function Root({ session, deps }) {
|
|
|
657
813
|
cwd: deps.cwd,
|
|
658
814
|
version: deps.version,
|
|
659
815
|
toolCount: deps.tools.length,
|
|
816
|
+
contextWindow: deps.contextWindow?.() ?? null,
|
|
660
817
|
approveAll: deps.approveAll === true,
|
|
661
818
|
value,
|
|
662
819
|
onChange: handleChange,
|
|
663
820
|
onSubmit: (v) => {
|
|
821
|
+
if (v.trim() === "/help") {
|
|
822
|
+
setValue("");
|
|
823
|
+
session.openHelp();
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
if (v.trim() === "/mcp") {
|
|
827
|
+
setValue("");
|
|
828
|
+
void session.openMcpManager();
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
if (v.trim() === "/context") {
|
|
832
|
+
setValue("");
|
|
833
|
+
session.openContext();
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
664
836
|
const items = v.startsWith("/") ? filterCommands(v) : [];
|
|
665
837
|
if (items.length > 0 && !parseCommand(v)) {
|
|
666
838
|
const chosen = items[Math.min(paletteIndex, items.length - 1)];
|
|
@@ -677,6 +849,10 @@ function Root({ session, deps }) {
|
|
|
677
849
|
return;
|
|
678
850
|
}
|
|
679
851
|
}
|
|
852
|
+
if (session.willReject(v)) {
|
|
853
|
+
void session.submit(v);
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
680
856
|
setValue("");
|
|
681
857
|
void session.submit(v).then(() => {
|
|
682
858
|
if (session.wantsExit) exit();
|
|
@@ -687,9 +863,9 @@ function Root({ session, deps }) {
|
|
|
687
863
|
const modal = session.getSnapshot().modal;
|
|
688
864
|
if (!modal) return;
|
|
689
865
|
if (modal.kind === "permission") session.answer(/^y(es)?$/i.test(v.trim()) ? "allow" : "deny");
|
|
690
|
-
else session.answer(v.trim() ? { [modal.questions[0].header]: [v.trim()] } : null);
|
|
866
|
+
else if (modal.kind === "user") session.answer(v.trim() ? { [modal.questions[0].header]: [v.trim()] } : null);
|
|
691
867
|
},
|
|
692
|
-
focus: state.modal
|
|
868
|
+
focus: state.modal == null || state.modal.kind === "user",
|
|
693
869
|
paletteSelected: paletteIndex,
|
|
694
870
|
inputKey: fieldGen
|
|
695
871
|
}
|
|
@@ -714,7 +890,7 @@ async function runTui(deps) {
|
|
|
714
890
|
reserve: bannerHeight(process.stdout, bannerOpts)
|
|
715
891
|
});
|
|
716
892
|
writeBanner(process.stdout, bannerOpts);
|
|
717
|
-
const app = render(/* @__PURE__ */
|
|
893
|
+
const app = render(/* @__PURE__ */ jsx9(Root, { session, deps }), {
|
|
718
894
|
/* LOAD-BEARING — do not "clean up" or default this away. Ink's own App
|
|
719
895
|
* component (build/components/App.js, handleInput) intercepts the raw
|
|
720
896
|
* \x03 byte and calls handleExit() BEFORE it ever emits the 'input'
|
package/dist/ink/scroll.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../src/ink/scroll.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../src/ink/scroll.ts"],"names":[],"mappings":"AAqCA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;wBASoB;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;uCAEmC;IACnC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;6CAI6C;AAC7C,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAehF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { McpServerView } from './state';
|
|
2
|
+
/** Status word, in priority order: a server can be simultaneously signed out
|
|
3
|
+
* AND unreachable, but `error` is the more actionable fact -- there is
|
|
4
|
+
* nothing to sign into until the connection itself works. `cached` is what is
|
|
5
|
+
* left once neither applies: a primed-from-disk tool list nothing has
|
|
6
|
+
* refreshed yet this run. */
|
|
7
|
+
/** Exported for the Ink manager overlay (McpOverlay.tsx), which presents the
|
|
8
|
+
* SAME status computed here rather than a second copy of it -- see this
|
|
9
|
+
* module's own comment. */
|
|
10
|
+
export declare function mcpStatusWord(v: McpServerView): string;
|
|
11
|
+
/** The age phrase ALREADY READS AS A COMPLETE CLAUSE -- the caller does not
|
|
12
|
+
* prefix it with "fetched". Returning "never fetched" while the caller also
|
|
13
|
+
* wrote "fetched " produced "fetched never fetched" on every server nobody had
|
|
14
|
+
* refreshed yet, which is every server on a cold machine.
|
|
15
|
+
*
|
|
16
|
+
* Exported so the Ink manager overlay (McpOverlay.tsx) can reuse this same
|
|
17
|
+
* logic instead of writing a second age formatter -- two would drift. */
|
|
18
|
+
export declare function ageWord(fetchedAt: number | null, now: number): string;
|
|
19
|
+
export declare function formatMcpServers(views: McpServerView[], now: number): string;
|
|
20
|
+
//# sourceMappingURL=mcpText.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpText.d.ts","sourceRoot":"","sources":["../src/mcpText.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;6BAI6B;AAC7B;;2BAE2B;AAC3B,wBAAgB,aAAa,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAKtD;AAED;;;;;;0EAM0E;AAC1E,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAUrE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAgB5E"}
|