@microboxlabs/miot-chat 0.1.0 → 0.1.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/dist/cli.js +512 -272
- package/dist/index.js +511 -269
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { createRequire } from "module";
|
|
5
4
|
import { Command } from "commander";
|
|
6
5
|
|
|
7
6
|
// src/commands/ask.ts
|
|
@@ -861,10 +860,18 @@ import { render } from "ink";
|
|
|
861
860
|
import { createElement } from "react";
|
|
862
861
|
|
|
863
862
|
// src/tui/App.tsx
|
|
864
|
-
import { Box as
|
|
865
|
-
import { useCallback as useCallback2, useMemo as useMemo2, useState as
|
|
863
|
+
import { Box as Box16, Text as Text17, useInput as useInput7 } from "ink";
|
|
864
|
+
import { useCallback as useCallback2, useMemo as useMemo2, useState as useState8 } from "react";
|
|
866
865
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
867
866
|
|
|
867
|
+
// src/version.ts
|
|
868
|
+
import { createRequire } from "module";
|
|
869
|
+
function packageVersion() {
|
|
870
|
+
const require2 = createRequire(import.meta.url);
|
|
871
|
+
const pkg = require2("../package.json");
|
|
872
|
+
return pkg.version;
|
|
873
|
+
}
|
|
874
|
+
|
|
868
875
|
// src/tui/input/Editor.tsx
|
|
869
876
|
import { Box, Text, useInput } from "ink";
|
|
870
877
|
import { useReducer, useState } from "react";
|
|
@@ -1218,15 +1225,9 @@ function renderLine(line, cursorCol) {
|
|
|
1218
1225
|
] });
|
|
1219
1226
|
}
|
|
1220
1227
|
|
|
1221
|
-
// src/tui/
|
|
1228
|
+
// src/tui/chrome/TopLine.tsx
|
|
1222
1229
|
import { Box as Box2, Text as Text3 } from "ink";
|
|
1223
1230
|
|
|
1224
|
-
// src/tui/session/agentic.ts
|
|
1225
|
-
var AGENTIC_TENANT_LOCK2 = "mintral";
|
|
1226
|
-
function isAgenticTenantMismatch(mode, tenant) {
|
|
1227
|
-
return mode === "agentic" && tenant !== AGENTIC_TENANT_LOCK2;
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
1231
|
// src/tui/transcript/Spinner.tsx
|
|
1231
1232
|
import { Text as Text2 } from "ink";
|
|
1232
1233
|
import { useEffect, useState as useState2 } from "react";
|
|
@@ -1247,129 +1248,421 @@ function Spinner(props) {
|
|
|
1247
1248
|
return /* @__PURE__ */ jsx2(Text2, { color: props.color, children: FRAMES[frame] });
|
|
1248
1249
|
}
|
|
1249
1250
|
|
|
1250
|
-
// src/tui/
|
|
1251
|
-
import {
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1251
|
+
// src/tui/theme/ThemeProvider.tsx
|
|
1252
|
+
import { createContext, useContext, useMemo, useState as useState3 } from "react";
|
|
1253
|
+
|
|
1254
|
+
// src/tui/theme/themes.ts
|
|
1255
|
+
var DARK_THEME = {
|
|
1256
|
+
accent: "cyan",
|
|
1257
|
+
assistant: "white",
|
|
1258
|
+
user: "cyan",
|
|
1259
|
+
dim: "gray",
|
|
1260
|
+
warn: "yellow",
|
|
1261
|
+
err: "red",
|
|
1262
|
+
ok: "green",
|
|
1263
|
+
border: "gray",
|
|
1264
|
+
prompt: "cyan",
|
|
1265
|
+
spinner: "cyan"
|
|
1266
|
+
};
|
|
1267
|
+
var LIGHT_THEME = {
|
|
1268
|
+
accent: "blue",
|
|
1269
|
+
assistant: "black",
|
|
1270
|
+
user: "blue",
|
|
1271
|
+
dim: "gray",
|
|
1272
|
+
warn: "yellow",
|
|
1273
|
+
err: "red",
|
|
1274
|
+
ok: "green",
|
|
1275
|
+
border: "gray",
|
|
1276
|
+
prompt: "blue",
|
|
1277
|
+
spinner: "blue"
|
|
1278
|
+
};
|
|
1279
|
+
var HIGH_CONTRAST_THEME = {
|
|
1280
|
+
accent: "white",
|
|
1281
|
+
assistant: "white",
|
|
1282
|
+
user: "white",
|
|
1283
|
+
dim: "white",
|
|
1284
|
+
warn: "yellow",
|
|
1285
|
+
err: "red",
|
|
1286
|
+
ok: "green",
|
|
1287
|
+
border: "white",
|
|
1288
|
+
prompt: "white",
|
|
1289
|
+
spinner: "white"
|
|
1290
|
+
};
|
|
1291
|
+
var BUILTIN_THEMES = {
|
|
1292
|
+
dark: DARK_THEME,
|
|
1293
|
+
light: LIGHT_THEME,
|
|
1294
|
+
"high-contrast": HIGH_CONTRAST_THEME
|
|
1295
|
+
};
|
|
1296
|
+
var DEFAULT_THEME_NAME = "dark";
|
|
1297
|
+
function builtinThemeNames() {
|
|
1298
|
+
return Object.keys(BUILTIN_THEMES).sort();
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// src/tui/theme/ThemeProvider.tsx
|
|
1302
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1303
|
+
var ThemeContext = createContext({
|
|
1304
|
+
theme: DARK_THEME,
|
|
1305
|
+
setTheme: () => void 0
|
|
1306
|
+
});
|
|
1307
|
+
function ThemeProvider(props) {
|
|
1308
|
+
const [theme, setTheme] = useState3(
|
|
1309
|
+
props.initialTheme ?? DARK_THEME
|
|
1276
1310
|
);
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
"
|
|
1295
|
-
props.
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
+
const value = useMemo(
|
|
1312
|
+
() => ({ theme, setTheme }),
|
|
1313
|
+
[theme]
|
|
1314
|
+
);
|
|
1315
|
+
return /* @__PURE__ */ jsx3(ThemeContext.Provider, { value, children: props.children });
|
|
1316
|
+
}
|
|
1317
|
+
function useTheme() {
|
|
1318
|
+
return useContext(ThemeContext);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// src/tui/chrome/TopLine.tsx
|
|
1322
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1323
|
+
function TopLine(props) {
|
|
1324
|
+
const { theme } = useTheme();
|
|
1325
|
+
const shortConv = props.meta.conversationId.slice(0, 8);
|
|
1326
|
+
return /* @__PURE__ */ jsxs2(Box2, { paddingX: 1, children: [
|
|
1327
|
+
/* @__PURE__ */ jsxs2(Text3, { color: theme.dim, children: [
|
|
1328
|
+
"\u2387 ",
|
|
1329
|
+
props.meta.tenantId,
|
|
1330
|
+
" \xB7 ",
|
|
1331
|
+
props.meta.userId,
|
|
1332
|
+
" \xB7 conv ",
|
|
1333
|
+
shortConv
|
|
1334
|
+
] }),
|
|
1335
|
+
props.streaming ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1336
|
+
/* @__PURE__ */ jsx4(Text3, { color: theme.dim, children: " " }),
|
|
1337
|
+
/* @__PURE__ */ jsx4(Spinner, { color: theme.spinner })
|
|
1338
|
+
] }) : null
|
|
1339
|
+
] });
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
// src/tui/chrome/TipLine.tsx
|
|
1343
|
+
import { Box as Box3, Text as Text4 } from "ink";
|
|
1344
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1345
|
+
var TIPS = [
|
|
1346
|
+
"Tip: type / to see available commands.",
|
|
1347
|
+
"Tip: ctrl+r resumes a saved session.",
|
|
1348
|
+
"Tip: ctrl+t switches the color theme.",
|
|
1349
|
+
"Tip: /save stores this conversation for later.",
|
|
1350
|
+
"Tip: /export writes the conversation as markdown."
|
|
1351
|
+
];
|
|
1352
|
+
function TipLine(props) {
|
|
1353
|
+
const { theme } = useTheme();
|
|
1354
|
+
const tip = TIPS[props.tipIndex % TIPS.length];
|
|
1355
|
+
return /* @__PURE__ */ jsx5(Box3, { paddingX: 1, children: /* @__PURE__ */ jsx5(Text4, { color: theme.dim, children: tip }) });
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
// src/tui/chrome/FooterLine.tsx
|
|
1359
|
+
import { Box as Box4, Text as Text5 } from "ink";
|
|
1360
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1361
|
+
function FooterLine(props) {
|
|
1362
|
+
const { theme } = useTheme();
|
|
1363
|
+
const segments = [];
|
|
1364
|
+
segments.push(`turns ${props.turns}`);
|
|
1365
|
+
segments.push(`ctx\u2248${props.approxTokens}tok (${props.contextPercent}%)`);
|
|
1366
|
+
const u = props.usageTotals;
|
|
1367
|
+
if (u && (u.inputTokens > 0 || u.outputTokens > 0)) {
|
|
1311
1368
|
const cost = u.costUsd > 0 ? ` $${u.costUsd.toFixed(4)}` : "";
|
|
1312
|
-
|
|
1313
|
-
/* @__PURE__ */ jsxs2(Text3, { dimColor: true, children: [
|
|
1314
|
-
"usage=",
|
|
1315
|
-
u.inputTokens,
|
|
1316
|
-
"\u2192",
|
|
1317
|
-
u.outputTokens,
|
|
1318
|
-
cost
|
|
1319
|
-
] }, "usage")
|
|
1320
|
-
);
|
|
1369
|
+
segments.push(`${u.inputTokens}\u2192${u.outputTokens}${cost}`);
|
|
1321
1370
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1371
|
+
segments.push(props.baseUrl);
|
|
1372
|
+
if (props.profileName) {
|
|
1373
|
+
segments.push(`profile ${props.profileName}`);
|
|
1324
1374
|
}
|
|
1325
|
-
return /* @__PURE__ */
|
|
1375
|
+
return /* @__PURE__ */ jsxs3(Box4, { paddingX: 1, justifyContent: "flex-end", children: [
|
|
1376
|
+
props.pendingApprovals > 0 ? /* @__PURE__ */ jsxs3(Text5, { color: theme.warn, children: [
|
|
1377
|
+
"approvals ",
|
|
1378
|
+
props.pendingApprovals,
|
|
1379
|
+
" \xB7 "
|
|
1380
|
+
] }) : null,
|
|
1381
|
+
/* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: segments.join(" \xB7 ") })
|
|
1382
|
+
] });
|
|
1326
1383
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1384
|
+
|
|
1385
|
+
// src/tui/chrome/InputFrame.tsx
|
|
1386
|
+
import { Box as Box5, Text as Text6 } from "ink";
|
|
1387
|
+
|
|
1388
|
+
// src/tui/hooks/useTerminalWidth.ts
|
|
1389
|
+
import { useStdout } from "ink";
|
|
1390
|
+
import { useEffect as useEffect2, useState as useState4 } from "react";
|
|
1391
|
+
var FALLBACK_COLUMNS = 80;
|
|
1392
|
+
var MIN_COLUMNS = 20;
|
|
1393
|
+
function useTerminalWidth() {
|
|
1394
|
+
const { stdout } = useStdout();
|
|
1395
|
+
const [columns, setColumns] = useState4(
|
|
1396
|
+
stdout?.columns ?? FALLBACK_COLUMNS
|
|
1397
|
+
);
|
|
1398
|
+
useEffect2(() => {
|
|
1399
|
+
if (!stdout) return;
|
|
1400
|
+
const onResize = () => {
|
|
1401
|
+
setColumns(stdout.columns ?? FALLBACK_COLUMNS);
|
|
1402
|
+
};
|
|
1403
|
+
stdout.on("resize", onResize);
|
|
1404
|
+
return () => {
|
|
1405
|
+
stdout.off("resize", onResize);
|
|
1406
|
+
};
|
|
1407
|
+
}, [stdout]);
|
|
1408
|
+
return Math.max(MIN_COLUMNS, columns);
|
|
1409
|
+
}
|
|
1410
|
+
var FALLBACK_ROWS = 24;
|
|
1411
|
+
var MIN_ROWS = 10;
|
|
1412
|
+
function useTerminalRows() {
|
|
1413
|
+
const { stdout } = useStdout();
|
|
1414
|
+
const [rows, setRows] = useState4(stdout?.rows ?? FALLBACK_ROWS);
|
|
1415
|
+
useEffect2(() => {
|
|
1416
|
+
if (!stdout) return;
|
|
1417
|
+
const onResize = () => {
|
|
1418
|
+
setRows(stdout.rows ?? FALLBACK_ROWS);
|
|
1419
|
+
};
|
|
1420
|
+
stdout.on("resize", onResize);
|
|
1421
|
+
return () => {
|
|
1422
|
+
stdout.off("resize", onResize);
|
|
1423
|
+
};
|
|
1424
|
+
}, [stdout]);
|
|
1425
|
+
return Math.max(MIN_ROWS, rows);
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
// src/tui/chrome/InputFrame.tsx
|
|
1429
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1430
|
+
function InputFrame(props) {
|
|
1431
|
+
const cols = useTerminalWidth();
|
|
1432
|
+
const { theme } = useTheme();
|
|
1433
|
+
return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", width: cols, children: [
|
|
1434
|
+
/* @__PURE__ */ jsx7(
|
|
1435
|
+
Box5,
|
|
1436
|
+
{
|
|
1437
|
+
borderStyle: "round",
|
|
1438
|
+
borderColor: theme.border,
|
|
1439
|
+
borderBottom: false,
|
|
1440
|
+
paddingX: 1,
|
|
1441
|
+
children: props.children
|
|
1442
|
+
}
|
|
1443
|
+
),
|
|
1444
|
+
/* @__PURE__ */ jsx7(
|
|
1445
|
+
BottomBorder,
|
|
1446
|
+
{
|
|
1447
|
+
cols,
|
|
1448
|
+
label: props.label,
|
|
1449
|
+
warn: props.labelWarn ?? false
|
|
1450
|
+
}
|
|
1451
|
+
)
|
|
1452
|
+
] });
|
|
1453
|
+
}
|
|
1454
|
+
function BottomBorder(props) {
|
|
1455
|
+
const { theme } = useTheme();
|
|
1456
|
+
const visibleLabel = props.warn ? `\u26A0 ${props.label}` : props.label;
|
|
1457
|
+
const labelText = ` ${visibleLabel} `;
|
|
1458
|
+
const fill = props.cols - 2 - labelText.length - 2;
|
|
1459
|
+
if (fill < 1) {
|
|
1460
|
+
return /* @__PURE__ */ jsxs4(Text6, { color: theme.border, children: [
|
|
1461
|
+
"\u2570",
|
|
1462
|
+
"\u2500".repeat(Math.max(0, props.cols - 2)),
|
|
1463
|
+
"\u256F"
|
|
1464
|
+
] });
|
|
1465
|
+
}
|
|
1466
|
+
return /* @__PURE__ */ jsxs4(Text6, { children: [
|
|
1467
|
+
/* @__PURE__ */ jsxs4(Text6, { color: theme.border, children: [
|
|
1468
|
+
"\u2570",
|
|
1469
|
+
"\u2500".repeat(fill)
|
|
1470
|
+
] }),
|
|
1471
|
+
/* @__PURE__ */ jsx7(Text6, { color: props.warn ? theme.warn : theme.dim, children: labelText }),
|
|
1472
|
+
/* @__PURE__ */ jsx7(Text6, { color: theme.border, children: "\u2500\u2500\u256F" })
|
|
1473
|
+
] });
|
|
1334
1474
|
}
|
|
1335
1475
|
|
|
1336
|
-
// src/tui/
|
|
1476
|
+
// src/tui/chrome/WelcomeCard.tsx
|
|
1337
1477
|
import { Box as Box6, Text as Text7 } from "ink";
|
|
1478
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1479
|
+
var LOGO = [
|
|
1480
|
+
[
|
|
1481
|
+
{ text: "\u2880", tone: "accent" },
|
|
1482
|
+
{ text: "\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800", tone: "accent" },
|
|
1483
|
+
{ text: "\u28C0", tone: "accent" },
|
|
1484
|
+
{ text: "\u28E4\u28E4\u28C0", tone: "warn" },
|
|
1485
|
+
{ text: "\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800", tone: "accent" },
|
|
1486
|
+
{ text: "\u2840", tone: "accent" }
|
|
1487
|
+
],
|
|
1488
|
+
[
|
|
1489
|
+
{ text: "\u2800", tone: "accent" },
|
|
1490
|
+
{ text: "\u28BF\u28F6\u28F6\u28E4\u28E4\u28F0", tone: "accent" },
|
|
1491
|
+
{ text: "\u28B6\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28F7", tone: "warn" },
|
|
1492
|
+
{ text: "\u28C6\u28E4\u28E4\u28F6\u28F6\u287F", tone: "accent" },
|
|
1493
|
+
{ text: "\u2800", tone: "accent" }
|
|
1494
|
+
],
|
|
1495
|
+
[
|
|
1496
|
+
{ text: "\u2800", tone: "accent" },
|
|
1497
|
+
{ text: "\u2808\u281B\u28DB\u289B\u28DB\u28DB\u285B\u283A", tone: "accent" },
|
|
1498
|
+
{ text: "\u28BF\u28FF\u28FF\u287F", tone: "warn" },
|
|
1499
|
+
{ text: "\u281F\u281B\u28DB\u28DB\u28DB\u28DB\u281B\u2801", tone: "accent" },
|
|
1500
|
+
{ text: "\u2800", tone: "accent" }
|
|
1501
|
+
],
|
|
1502
|
+
[
|
|
1503
|
+
{ text: "\u2800", tone: "accent" },
|
|
1504
|
+
{ text: "\u2880\u28FF\u28FF", tone: "accent" },
|
|
1505
|
+
{ text: "\u28FF\u289F\u28DB\u28DB\u28BF\u28E6", tone: "face" },
|
|
1506
|
+
{ text: "\u28CC\u28E1", tone: "accent" },
|
|
1507
|
+
{ text: "\u28F4\u287E\u28DB\u28DB\u287F\u28FF", tone: "face" },
|
|
1508
|
+
{ text: "\u28FF\u28F7", tone: "accent" },
|
|
1509
|
+
{ text: "\u2800\u2800", tone: "accent" }
|
|
1510
|
+
],
|
|
1511
|
+
[
|
|
1512
|
+
{ text: "\u2800", tone: "accent" },
|
|
1513
|
+
{ text: "\u28F8\u28FF", tone: "accent" },
|
|
1514
|
+
{ text: "\u28FF", tone: "face" },
|
|
1515
|
+
{ text: "\u28B3", tone: "accent" },
|
|
1516
|
+
{ text: "\u287F", tone: "warn" },
|
|
1517
|
+
{ text: "\u286F", tone: "accent" },
|
|
1518
|
+
{ text: "\u2819\u28F7", tone: "warn" },
|
|
1519
|
+
{ text: "\u28BB\u28FF\u28FF\u285F", tone: "face" },
|
|
1520
|
+
{ text: "\u28FE\u280B", tone: "warn" },
|
|
1521
|
+
{ text: "\u28BD", tone: "accent" },
|
|
1522
|
+
{ text: "\u28BB", tone: "warn" },
|
|
1523
|
+
{ text: "\u28FD", tone: "accent" },
|
|
1524
|
+
{ text: "\u28FF", tone: "face" },
|
|
1525
|
+
{ text: "\u28FF\u2847", tone: "accent" },
|
|
1526
|
+
{ text: "\u2800", tone: "accent" }
|
|
1527
|
+
],
|
|
1528
|
+
[
|
|
1529
|
+
{ text: "\u2800", tone: "accent" },
|
|
1530
|
+
{ text: "\u28BB\u28FF", tone: "accent" },
|
|
1531
|
+
{ text: "\u28FF", tone: "face" },
|
|
1532
|
+
{ text: "\u285C\u28E7\u28C0\u28E0\u287F", tone: "warn" },
|
|
1533
|
+
{ text: "\u28FC\u287F\u28FF\u28E7", tone: "face" },
|
|
1534
|
+
{ text: "\u28BF\u28C4\u28E0\u287E", tone: "warn" },
|
|
1535
|
+
{ text: "\u28FB", tone: "accent" },
|
|
1536
|
+
{ text: "\u28FF", tone: "face" },
|
|
1537
|
+
{ text: "\u28FF\u2847", tone: "accent" },
|
|
1538
|
+
{ text: "\u2800", tone: "accent" }
|
|
1539
|
+
],
|
|
1540
|
+
[
|
|
1541
|
+
{ text: "\u2800", tone: "accent" },
|
|
1542
|
+
{ text: "\u2818\u28FF\u28FF", tone: "accent" },
|
|
1543
|
+
{ text: "\u28FF\u28F6\u28EF\u28F7\u28FE\u285F", tone: "face" },
|
|
1544
|
+
{ text: "\u2801\u28EC", tone: "accent" },
|
|
1545
|
+
{ text: "\u28FB\u28F7\u28FE\u28FF\u28FE\u28FF", tone: "face" },
|
|
1546
|
+
{ text: "\u28FF\u287F", tone: "accent" },
|
|
1547
|
+
{ text: "\u2800\u2800", tone: "accent" }
|
|
1548
|
+
],
|
|
1549
|
+
[
|
|
1550
|
+
{ text: "\u2800\u2800", tone: "accent" },
|
|
1551
|
+
{ text: "\u2818\u28BF\u28FF\u28FF", tone: "accent" },
|
|
1552
|
+
{ text: "\u28FF\u28FF\u28FF\u28FF", tone: "face" },
|
|
1553
|
+
{ text: "\u2844\u28A1", tone: "accent" },
|
|
1554
|
+
{ text: "\u28FF\u28FF\u28FF\u28FF", tone: "face" },
|
|
1555
|
+
{ text: "\u28FF\u28FF\u281F\u2801", tone: "accent" },
|
|
1556
|
+
{ text: "\u2800\u2800", tone: "accent" }
|
|
1557
|
+
],
|
|
1558
|
+
[
|
|
1559
|
+
{ text: "\u2800\u2800\u2800\u2800", tone: "accent" },
|
|
1560
|
+
{ text: "\u2819\u283B\u28BF\u28FF\u28FF", tone: "accent" },
|
|
1561
|
+
{ text: "\u28FF\u28FF\u28FF\u28FF", tone: "face" },
|
|
1562
|
+
{ text: "\u28FF\u28FF\u287F\u281F\u2801", tone: "accent" },
|
|
1563
|
+
{ text: "\u2800\u2800\u2800\u2800", tone: "accent" }
|
|
1564
|
+
],
|
|
1565
|
+
[
|
|
1566
|
+
{ text: "\u2800\u2800\u2800\u2800\u2800\u2800\u2800", tone: "accent" },
|
|
1567
|
+
{ text: "\u2808\u2819\u281B\u281B\u281B\u281B\u2809\u2801", tone: "accent" },
|
|
1568
|
+
{ text: "\u2800\u2800\u2800\u2800\u2800\u2800\u2800", tone: "accent" }
|
|
1569
|
+
]
|
|
1570
|
+
];
|
|
1571
|
+
var MENU = [
|
|
1572
|
+
{ label: "Resume session", shortcut: "ctrl+r" },
|
|
1573
|
+
{ label: "Switch theme", shortcut: "ctrl+t" },
|
|
1574
|
+
{ label: "Help", shortcut: "ctrl+g (/help)" },
|
|
1575
|
+
{ label: "Quit", shortcut: "ctrl+q" }
|
|
1576
|
+
];
|
|
1577
|
+
var CHROME_ROWS = 6;
|
|
1578
|
+
var CARD_ROWS = 14;
|
|
1579
|
+
function WelcomeCard(props) {
|
|
1580
|
+
const cols = useTerminalWidth();
|
|
1581
|
+
const rows = useTerminalRows();
|
|
1582
|
+
const { theme } = useTheme();
|
|
1583
|
+
return /* @__PURE__ */ jsx8(
|
|
1584
|
+
Box6,
|
|
1585
|
+
{
|
|
1586
|
+
flexDirection: "column",
|
|
1587
|
+
justifyContent: "center",
|
|
1588
|
+
height: Math.max(CARD_ROWS + 1, rows - CHROME_ROWS),
|
|
1589
|
+
children: /* @__PURE__ */ jsxs5(
|
|
1590
|
+
Box6,
|
|
1591
|
+
{
|
|
1592
|
+
borderStyle: "round",
|
|
1593
|
+
borderColor: theme.border,
|
|
1594
|
+
width: Math.min(cols, 64),
|
|
1595
|
+
alignSelf: "center",
|
|
1596
|
+
paddingX: 2,
|
|
1597
|
+
paddingY: 1,
|
|
1598
|
+
flexDirection: "row",
|
|
1599
|
+
children: [
|
|
1600
|
+
/* @__PURE__ */ jsx8(Box6, { flexDirection: "column", marginRight: 3, children: LOGO.map((row, i) => /* @__PURE__ */ jsx8(Text7, { children: row.map((seg, j) => /* @__PURE__ */ jsx8(
|
|
1601
|
+
Text7,
|
|
1602
|
+
{
|
|
1603
|
+
color: seg.tone === "warn" ? theme.warn : seg.tone === "face" ? theme.assistant : theme.accent,
|
|
1604
|
+
children: seg.text
|
|
1605
|
+
},
|
|
1606
|
+
j
|
|
1607
|
+
)) }, i)) }),
|
|
1608
|
+
/* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", flexGrow: 1, children: [
|
|
1609
|
+
/* @__PURE__ */ jsxs5(Box6, { children: [
|
|
1610
|
+
/* @__PURE__ */ jsx8(Text7, { color: theme.accent, bold: true, children: "miot chat" }),
|
|
1611
|
+
/* @__PURE__ */ jsxs5(Text7, { color: theme.dim, children: [
|
|
1612
|
+
" v",
|
|
1613
|
+
props.version
|
|
1614
|
+
] })
|
|
1615
|
+
] }),
|
|
1616
|
+
/* @__PURE__ */ jsx8(Box6, { height: 1 }),
|
|
1617
|
+
MENU.map((item) => /* @__PURE__ */ jsxs5(Box6, { justifyContent: "space-between", children: [
|
|
1618
|
+
/* @__PURE__ */ jsx8(Text7, { children: item.label }),
|
|
1619
|
+
/* @__PURE__ */ jsx8(Text7, { color: theme.dim, children: item.shortcut })
|
|
1620
|
+
] }, item.label))
|
|
1621
|
+
] })
|
|
1622
|
+
]
|
|
1623
|
+
}
|
|
1624
|
+
)
|
|
1625
|
+
}
|
|
1626
|
+
);
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
// src/tui/transcript/Transcript.tsx
|
|
1630
|
+
import { Box as Box10, Text as Text11 } from "ink";
|
|
1338
1631
|
|
|
1339
1632
|
// src/tui/transcript/AssistantTurn.tsx
|
|
1340
|
-
import { Box as
|
|
1341
|
-
import { Fragment as
|
|
1633
|
+
import { Box as Box7, Text as Text8 } from "ink";
|
|
1634
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1342
1635
|
function AssistantTurn(props) {
|
|
1343
1636
|
const { text, status } = props.item;
|
|
1344
1637
|
const color = status === "failed" ? "red" : status === "complete" ? "green" : "white";
|
|
1345
|
-
return /* @__PURE__ */
|
|
1346
|
-
status === "streaming" ? /* @__PURE__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
/* @__PURE__ */
|
|
1638
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "row", marginTop: 1, children: [
|
|
1639
|
+
status === "streaming" ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1640
|
+
/* @__PURE__ */ jsx9(Spinner, { color: "cyan" }),
|
|
1641
|
+
/* @__PURE__ */ jsxs6(Text8, { color, bold: true, children: [
|
|
1349
1642
|
" ",
|
|
1350
1643
|
"miot",
|
|
1351
1644
|
" "
|
|
1352
1645
|
] })
|
|
1353
|
-
] }) : /* @__PURE__ */
|
|
1646
|
+
] }) : /* @__PURE__ */ jsxs6(Text8, { color, bold: true, children: [
|
|
1354
1647
|
status === "failed" ? "\u2717 " : "\u2713 ",
|
|
1355
1648
|
"miot",
|
|
1356
1649
|
" "
|
|
1357
1650
|
] }),
|
|
1358
|
-
/* @__PURE__ */
|
|
1651
|
+
/* @__PURE__ */ jsx9(Text8, { color, children: text })
|
|
1359
1652
|
] });
|
|
1360
1653
|
}
|
|
1361
1654
|
|
|
1362
1655
|
// src/tui/transcript/ToolCall.tsx
|
|
1363
|
-
import { Box as
|
|
1364
|
-
import { jsx as
|
|
1656
|
+
import { Box as Box8, Text as Text9 } from "ink";
|
|
1657
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1365
1658
|
function ToolCall(props) {
|
|
1366
1659
|
const { name, status, message } = props.item;
|
|
1367
1660
|
const color = status === "failed" ? "red" : status === "ok" ? "green" : "yellow";
|
|
1368
1661
|
const glyph = status === "running" ? null : status === "ok" ? "\u2713" : "\u2717";
|
|
1369
|
-
return /* @__PURE__ */
|
|
1370
|
-
/* @__PURE__ */
|
|
1371
|
-
status === "running" ? /* @__PURE__ */
|
|
1372
|
-
/* @__PURE__ */
|
|
1662
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", children: [
|
|
1663
|
+
/* @__PURE__ */ jsx10(Text9, { color, children: glyph !== null ? `${glyph} ` : "" }),
|
|
1664
|
+
status === "running" ? /* @__PURE__ */ jsx10(Spinner, { color }) : null,
|
|
1665
|
+
/* @__PURE__ */ jsxs7(Text9, { color, children: [
|
|
1373
1666
|
" ",
|
|
1374
1667
|
"tool: ",
|
|
1375
1668
|
name,
|
|
@@ -1379,24 +1672,24 @@ function ToolCall(props) {
|
|
|
1379
1672
|
}
|
|
1380
1673
|
|
|
1381
1674
|
// src/tui/transcript/UserTurn.tsx
|
|
1382
|
-
import { Box as
|
|
1383
|
-
import { jsx as
|
|
1675
|
+
import { Box as Box9, Text as Text10 } from "ink";
|
|
1676
|
+
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1384
1677
|
function UserTurn(props) {
|
|
1385
1678
|
const { text } = props.item;
|
|
1386
|
-
return /* @__PURE__ */
|
|
1387
|
-
/* @__PURE__ */
|
|
1679
|
+
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", marginTop: 1, children: [
|
|
1680
|
+
/* @__PURE__ */ jsxs8(Text10, { color: "cyan", bold: true, children: [
|
|
1388
1681
|
"you",
|
|
1389
1682
|
" "
|
|
1390
1683
|
] }),
|
|
1391
|
-
/* @__PURE__ */
|
|
1684
|
+
/* @__PURE__ */ jsx11(Text10, { children: text })
|
|
1392
1685
|
] });
|
|
1393
1686
|
}
|
|
1394
1687
|
|
|
1395
1688
|
// src/tui/transcript/Transcript.tsx
|
|
1396
|
-
import { jsx as
|
|
1689
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1397
1690
|
function Transcript(props) {
|
|
1398
1691
|
const activeChainIdx = props.isStreaming ? findActiveChainIndex(props.items) : -1;
|
|
1399
|
-
return /* @__PURE__ */
|
|
1692
|
+
return /* @__PURE__ */ jsx12(Box10, { flexDirection: "column", children: props.items.map((item, i) => /* @__PURE__ */ jsx12(
|
|
1400
1693
|
TranscriptItemView,
|
|
1401
1694
|
{
|
|
1402
1695
|
item,
|
|
@@ -1421,38 +1714,38 @@ function TranscriptItemView(props) {
|
|
|
1421
1714
|
const { item, isActive } = props;
|
|
1422
1715
|
switch (item.kind) {
|
|
1423
1716
|
case "user":
|
|
1424
|
-
return /* @__PURE__ */
|
|
1717
|
+
return /* @__PURE__ */ jsx12(UserTurn, { item });
|
|
1425
1718
|
case "assistant":
|
|
1426
|
-
return /* @__PURE__ */
|
|
1719
|
+
return /* @__PURE__ */ jsx12(AssistantTurn, { item });
|
|
1427
1720
|
case "tool":
|
|
1428
|
-
return /* @__PURE__ */
|
|
1721
|
+
return /* @__PURE__ */ jsx12(ToolCall, { item });
|
|
1429
1722
|
case "route":
|
|
1430
|
-
return /* @__PURE__ */
|
|
1723
|
+
return /* @__PURE__ */ jsx12(ChainRow, { prefix: "route:", isActive, children: item.route });
|
|
1431
1724
|
case "agent":
|
|
1432
|
-
return /* @__PURE__ */
|
|
1725
|
+
return /* @__PURE__ */ jsx12(ChainRow, { prefix: "agent:", isActive, children: item.agent });
|
|
1433
1726
|
case "thinking":
|
|
1434
|
-
return /* @__PURE__ */
|
|
1435
|
-
/* @__PURE__ */
|
|
1436
|
-
/* @__PURE__ */
|
|
1727
|
+
return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", children: [
|
|
1728
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " \u22EE " }),
|
|
1729
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: item.text })
|
|
1437
1730
|
] });
|
|
1438
1731
|
case "plan":
|
|
1439
|
-
return /* @__PURE__ */
|
|
1732
|
+
return /* @__PURE__ */ jsx12(ChainRow, { prefix: "plan:", isActive, children: item.message });
|
|
1440
1733
|
case "freshness":
|
|
1441
|
-
return /* @__PURE__ */
|
|
1734
|
+
return /* @__PURE__ */ jsxs9(Text11, { color: "yellow", children: [
|
|
1442
1735
|
"\u26A0 ",
|
|
1443
1736
|
item.message
|
|
1444
1737
|
] });
|
|
1445
1738
|
case "artifact":
|
|
1446
|
-
return /* @__PURE__ */
|
|
1739
|
+
return /* @__PURE__ */ jsx12(ChainRow, { prefix: "artifact:", isActive, children: item.artifactKind });
|
|
1447
1740
|
case "system":
|
|
1448
|
-
return /* @__PURE__ */
|
|
1741
|
+
return /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: item.text });
|
|
1449
1742
|
}
|
|
1450
1743
|
}
|
|
1451
1744
|
function ChainRow(props) {
|
|
1452
1745
|
if (props.isActive) {
|
|
1453
|
-
return /* @__PURE__ */
|
|
1454
|
-
/* @__PURE__ */
|
|
1455
|
-
/* @__PURE__ */
|
|
1746
|
+
return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", children: [
|
|
1747
|
+
/* @__PURE__ */ jsx12(Spinner, { color: "cyan" }),
|
|
1748
|
+
/* @__PURE__ */ jsxs9(Text11, { color: "cyan", bold: true, children: [
|
|
1456
1749
|
" ",
|
|
1457
1750
|
props.prefix,
|
|
1458
1751
|
" ",
|
|
@@ -1460,7 +1753,7 @@ function ChainRow(props) {
|
|
|
1460
1753
|
] })
|
|
1461
1754
|
] });
|
|
1462
1755
|
}
|
|
1463
|
-
return /* @__PURE__ */
|
|
1756
|
+
return /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
1464
1757
|
"\xB7 ",
|
|
1465
1758
|
props.prefix,
|
|
1466
1759
|
" ",
|
|
@@ -1469,7 +1762,7 @@ function ChainRow(props) {
|
|
|
1469
1762
|
}
|
|
1470
1763
|
|
|
1471
1764
|
// src/tui/modals/ContextModal.tsx
|
|
1472
|
-
import { Box as
|
|
1765
|
+
import { Box as Box11, Text as Text12, useInput as useInput2 } from "ink";
|
|
1473
1766
|
|
|
1474
1767
|
// src/tui/session/selectors.ts
|
|
1475
1768
|
function isStreaming(state) {
|
|
@@ -1521,7 +1814,7 @@ function contextPercent(state) {
|
|
|
1521
1814
|
}
|
|
1522
1815
|
|
|
1523
1816
|
// src/tui/modals/ContextModal.tsx
|
|
1524
|
-
import { jsx as
|
|
1817
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1525
1818
|
function ContextModal(props) {
|
|
1526
1819
|
const { session, lastRunId } = props;
|
|
1527
1820
|
useInput2(
|
|
@@ -1546,24 +1839,24 @@ function ContextModal(props) {
|
|
|
1546
1839
|
"pending approvals",
|
|
1547
1840
|
String(session.pendingApprovals.length)
|
|
1548
1841
|
]);
|
|
1549
|
-
return /* @__PURE__ */
|
|
1550
|
-
/* @__PURE__ */
|
|
1551
|
-
fields.map(([key, value]) => /* @__PURE__ */
|
|
1842
|
+
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1843
|
+
/* @__PURE__ */ jsx13(Text12, { bold: true, children: "session context" }),
|
|
1844
|
+
fields.map(([key, value]) => /* @__PURE__ */ jsxs10(Text12, { children: [
|
|
1552
1845
|
key.padEnd(18),
|
|
1553
1846
|
" ",
|
|
1554
1847
|
value
|
|
1555
1848
|
] }, key)),
|
|
1556
|
-
/* @__PURE__ */
|
|
1849
|
+
/* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "esc/enter to close" })
|
|
1557
1850
|
] });
|
|
1558
1851
|
}
|
|
1559
1852
|
|
|
1560
1853
|
// src/tui/modals/ResumePicker.tsx
|
|
1561
|
-
import { Box as
|
|
1562
|
-
import { useState as
|
|
1563
|
-
import { jsx as
|
|
1854
|
+
import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
|
|
1855
|
+
import { useState as useState5 } from "react";
|
|
1856
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1564
1857
|
function ResumePicker(props) {
|
|
1565
1858
|
const maxRows = props.maxRows ?? 10;
|
|
1566
|
-
const [index, setIndex] =
|
|
1859
|
+
const [index, setIndex] = useState5(0);
|
|
1567
1860
|
const summaries = props.summaries;
|
|
1568
1861
|
const cap = Math.max(0, summaries.length - 1);
|
|
1569
1862
|
useInput3(
|
|
@@ -1588,23 +1881,23 @@ function ResumePicker(props) {
|
|
|
1588
1881
|
{ isActive: props.isFocused ?? true }
|
|
1589
1882
|
);
|
|
1590
1883
|
if (summaries.length === 0) {
|
|
1591
|
-
return /* @__PURE__ */
|
|
1592
|
-
/* @__PURE__ */
|
|
1593
|
-
/* @__PURE__ */
|
|
1594
|
-
/* @__PURE__ */
|
|
1884
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1885
|
+
/* @__PURE__ */ jsx14(Text13, { bold: true, children: "resume session" }),
|
|
1886
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "(no saved sessions)" }),
|
|
1887
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "esc to close" })
|
|
1595
1888
|
] });
|
|
1596
1889
|
}
|
|
1597
1890
|
const visible = summaries.slice(0, maxRows);
|
|
1598
1891
|
const truncated = summaries.length - visible.length;
|
|
1599
|
-
return /* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
visible.map((s, i) => /* @__PURE__ */
|
|
1602
|
-
truncated > 0 ? /* @__PURE__ */
|
|
1892
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1893
|
+
/* @__PURE__ */ jsx14(Text13, { bold: true, children: "resume session" }),
|
|
1894
|
+
visible.map((s, i) => /* @__PURE__ */ jsx14(Text13, { inverse: i === index, children: summarize(s) }, s.id)),
|
|
1895
|
+
truncated > 0 ? /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
|
|
1603
1896
|
"\u2026 ",
|
|
1604
1897
|
truncated,
|
|
1605
1898
|
" more"
|
|
1606
1899
|
] }) : null,
|
|
1607
|
-
/* @__PURE__ */
|
|
1900
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "\u2191\u2193 navigate \xB7 enter select \xB7 esc cancel" })
|
|
1608
1901
|
] });
|
|
1609
1902
|
}
|
|
1610
1903
|
function summarize(s) {
|
|
@@ -1620,62 +1913,13 @@ function truncate(text, max) {
|
|
|
1620
1913
|
}
|
|
1621
1914
|
|
|
1622
1915
|
// src/tui/modals/ThemePicker.tsx
|
|
1623
|
-
import { Box as
|
|
1624
|
-
import { useState as
|
|
1625
|
-
|
|
1626
|
-
// src/tui/theme/themes.ts
|
|
1627
|
-
var DARK_THEME = {
|
|
1628
|
-
accent: "cyan",
|
|
1629
|
-
assistant: "white",
|
|
1630
|
-
user: "cyan",
|
|
1631
|
-
dim: "gray",
|
|
1632
|
-
warn: "yellow",
|
|
1633
|
-
err: "red",
|
|
1634
|
-
ok: "green",
|
|
1635
|
-
border: "gray",
|
|
1636
|
-
prompt: "cyan",
|
|
1637
|
-
spinner: "cyan"
|
|
1638
|
-
};
|
|
1639
|
-
var LIGHT_THEME = {
|
|
1640
|
-
accent: "blue",
|
|
1641
|
-
assistant: "black",
|
|
1642
|
-
user: "blue",
|
|
1643
|
-
dim: "gray",
|
|
1644
|
-
warn: "yellow",
|
|
1645
|
-
err: "red",
|
|
1646
|
-
ok: "green",
|
|
1647
|
-
border: "gray",
|
|
1648
|
-
prompt: "blue",
|
|
1649
|
-
spinner: "blue"
|
|
1650
|
-
};
|
|
1651
|
-
var HIGH_CONTRAST_THEME = {
|
|
1652
|
-
accent: "white",
|
|
1653
|
-
assistant: "white",
|
|
1654
|
-
user: "white",
|
|
1655
|
-
dim: "white",
|
|
1656
|
-
warn: "yellow",
|
|
1657
|
-
err: "red",
|
|
1658
|
-
ok: "green",
|
|
1659
|
-
border: "white",
|
|
1660
|
-
prompt: "white",
|
|
1661
|
-
spinner: "white"
|
|
1662
|
-
};
|
|
1663
|
-
var BUILTIN_THEMES = {
|
|
1664
|
-
dark: DARK_THEME,
|
|
1665
|
-
light: LIGHT_THEME,
|
|
1666
|
-
"high-contrast": HIGH_CONTRAST_THEME
|
|
1667
|
-
};
|
|
1668
|
-
var DEFAULT_THEME_NAME = "dark";
|
|
1669
|
-
function builtinThemeNames() {
|
|
1670
|
-
return Object.keys(BUILTIN_THEMES).sort();
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
// src/tui/modals/ThemePicker.tsx
|
|
1674
|
-
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1916
|
+
import { Box as Box13, Text as Text14, useInput as useInput4 } from "ink";
|
|
1917
|
+
import { useState as useState6 } from "react";
|
|
1918
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1675
1919
|
function ThemePicker(props) {
|
|
1676
1920
|
const names = builtinThemeNames();
|
|
1677
1921
|
const initial = props.initialName ? Math.max(0, names.indexOf(props.initialName)) : 0;
|
|
1678
|
-
const [index, setIndex] =
|
|
1922
|
+
const [index, setIndex] = useState6(initial);
|
|
1679
1923
|
const cap = names.length - 1;
|
|
1680
1924
|
useInput4(
|
|
1681
1925
|
(_input, key) => {
|
|
@@ -1698,23 +1942,23 @@ function ThemePicker(props) {
|
|
|
1698
1942
|
},
|
|
1699
1943
|
{ isActive: props.isFocused ?? true }
|
|
1700
1944
|
);
|
|
1701
|
-
return /* @__PURE__ */
|
|
1702
|
-
/* @__PURE__ */
|
|
1945
|
+
return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1946
|
+
/* @__PURE__ */ jsx15(Text14, { bold: true, children: "theme" }),
|
|
1703
1947
|
names.map((name, i) => {
|
|
1704
1948
|
const t = BUILTIN_THEMES[name];
|
|
1705
1949
|
const sample = t ? `accent=${t.accent} user=${t.user}` : "";
|
|
1706
|
-
return /* @__PURE__ */
|
|
1950
|
+
return /* @__PURE__ */ jsxs12(Text14, { inverse: i === index, children: [
|
|
1707
1951
|
name.padEnd(15),
|
|
1708
1952
|
" ",
|
|
1709
1953
|
sample
|
|
1710
1954
|
] }, name);
|
|
1711
1955
|
}),
|
|
1712
|
-
/* @__PURE__ */
|
|
1956
|
+
/* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "\u2191\u2193 navigate \xB7 enter apply \xB7 esc cancel" })
|
|
1713
1957
|
] });
|
|
1714
1958
|
}
|
|
1715
1959
|
|
|
1716
1960
|
// src/tui/modals/ApprovalModal.tsx
|
|
1717
|
-
import { Box as
|
|
1961
|
+
import { Box as Box14, Text as Text15, useInput as useInput5 } from "ink";
|
|
1718
1962
|
|
|
1719
1963
|
// src/tui/session/approvals.ts
|
|
1720
1964
|
var APPROVALS_UI_ENV = "MIOT_CHAT_APPROVALS_UI";
|
|
@@ -1726,7 +1970,7 @@ function isApprovalsUiEnabled(env = process.env) {
|
|
|
1726
1970
|
var APPROVAL_REPLY_PLACEHOLDER = "approval reply not yet supported by harness";
|
|
1727
1971
|
|
|
1728
1972
|
// src/tui/modals/ApprovalModal.tsx
|
|
1729
|
-
import { jsx as
|
|
1973
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1730
1974
|
function ApprovalModal(props) {
|
|
1731
1975
|
const { approval, onResolve } = props;
|
|
1732
1976
|
useInput5(
|
|
@@ -1739,22 +1983,22 @@ function ApprovalModal(props) {
|
|
|
1739
1983
|
{ isActive: props.isFocused ?? true }
|
|
1740
1984
|
);
|
|
1741
1985
|
const data = JSON.stringify(approval.data, null, 2);
|
|
1742
|
-
return /* @__PURE__ */
|
|
1743
|
-
/* @__PURE__ */
|
|
1744
|
-
/* @__PURE__ */
|
|
1745
|
-
/* @__PURE__ */
|
|
1746
|
-
/* @__PURE__ */
|
|
1747
|
-
/* @__PURE__ */
|
|
1986
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1987
|
+
/* @__PURE__ */ jsx16(Text15, { bold: true, color: "yellow", children: "approval requested" }),
|
|
1988
|
+
/* @__PURE__ */ jsx16(Text15, { children: approval.message || "(no message)" }),
|
|
1989
|
+
/* @__PURE__ */ jsx16(Text15, { dimColor: true, children: data }),
|
|
1990
|
+
/* @__PURE__ */ jsx16(Text15, { children: "[Y] approve [N] deny [Esc] later" }),
|
|
1991
|
+
/* @__PURE__ */ jsx16(Text15, { dimColor: true, children: APPROVAL_REPLY_PLACEHOLDER })
|
|
1748
1992
|
] });
|
|
1749
1993
|
}
|
|
1750
1994
|
|
|
1751
1995
|
// src/tui/modals/RunsPicker.tsx
|
|
1752
|
-
import { Box as
|
|
1753
|
-
import { useState as
|
|
1754
|
-
import { jsx as
|
|
1996
|
+
import { Box as Box15, Text as Text16, useInput as useInput6 } from "ink";
|
|
1997
|
+
import { useState as useState7 } from "react";
|
|
1998
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1755
1999
|
function RunsPicker(props) {
|
|
1756
2000
|
const maxRows = props.maxRows ?? 10;
|
|
1757
|
-
const [index, setIndex] =
|
|
2001
|
+
const [index, setIndex] = useState7(0);
|
|
1758
2002
|
const cap = Math.max(0, props.runs.length - 1);
|
|
1759
2003
|
useInput6(
|
|
1760
2004
|
(_input, key) => {
|
|
@@ -1778,23 +2022,23 @@ function RunsPicker(props) {
|
|
|
1778
2022
|
{ isActive: props.isFocused ?? true }
|
|
1779
2023
|
);
|
|
1780
2024
|
if (props.runs.length === 0) {
|
|
1781
|
-
return /* @__PURE__ */
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
/* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
2025
|
+
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
2026
|
+
/* @__PURE__ */ jsx17(Text16, { bold: true, children: "recent runs" }),
|
|
2027
|
+
/* @__PURE__ */ jsx17(Text16, { dimColor: true, children: "(no runs in this session)" }),
|
|
2028
|
+
/* @__PURE__ */ jsx17(Text16, { dimColor: true, children: "esc to close" })
|
|
1785
2029
|
] });
|
|
1786
2030
|
}
|
|
1787
2031
|
const visible = props.runs.slice(0, maxRows);
|
|
1788
2032
|
const truncated = props.runs.length - visible.length;
|
|
1789
|
-
return /* @__PURE__ */
|
|
1790
|
-
/* @__PURE__ */
|
|
1791
|
-
visible.map((r, i) => /* @__PURE__ */
|
|
1792
|
-
truncated > 0 ? /* @__PURE__ */
|
|
2033
|
+
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
2034
|
+
/* @__PURE__ */ jsx17(Text16, { bold: true, children: "recent runs" }),
|
|
2035
|
+
visible.map((r, i) => /* @__PURE__ */ jsx17(Text16, { inverse: i === index, children: formatRow(r) }, r.runId)),
|
|
2036
|
+
truncated > 0 ? /* @__PURE__ */ jsxs14(Text16, { dimColor: true, children: [
|
|
1793
2037
|
"\u2026 ",
|
|
1794
2038
|
truncated,
|
|
1795
2039
|
" more"
|
|
1796
2040
|
] }) : null,
|
|
1797
|
-
/* @__PURE__ */
|
|
2041
|
+
/* @__PURE__ */ jsx17(Text16, { dimColor: true, children: "\u2191\u2193 navigate \xB7 enter replay \xB7 esc cancel" })
|
|
1798
2042
|
] });
|
|
1799
2043
|
}
|
|
1800
2044
|
function formatRow(r) {
|
|
@@ -1833,27 +2077,6 @@ function findPrecedingPrompt(items, startAt) {
|
|
|
1833
2077
|
return null;
|
|
1834
2078
|
}
|
|
1835
2079
|
|
|
1836
|
-
// src/tui/theme/ThemeProvider.tsx
|
|
1837
|
-
import { createContext, useContext, useMemo, useState as useState6 } from "react";
|
|
1838
|
-
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1839
|
-
var ThemeContext = createContext({
|
|
1840
|
-
theme: DARK_THEME,
|
|
1841
|
-
setTheme: () => void 0
|
|
1842
|
-
});
|
|
1843
|
-
function ThemeProvider(props) {
|
|
1844
|
-
const [theme, setTheme] = useState6(
|
|
1845
|
-
props.initialTheme ?? DARK_THEME
|
|
1846
|
-
);
|
|
1847
|
-
const value = useMemo(
|
|
1848
|
-
() => ({ theme, setTheme }),
|
|
1849
|
-
[theme]
|
|
1850
|
-
);
|
|
1851
|
-
return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value, children: props.children });
|
|
1852
|
-
}
|
|
1853
|
-
function useTheme() {
|
|
1854
|
-
return useContext(ThemeContext);
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
2080
|
// src/tui/theme/loadUserTheme.ts
|
|
1858
2081
|
function loadUserTheme(config) {
|
|
1859
2082
|
if (config === void 0 || config === null) {
|
|
@@ -1885,8 +2108,14 @@ function resolveByName(name) {
|
|
|
1885
2108
|
};
|
|
1886
2109
|
}
|
|
1887
2110
|
|
|
2111
|
+
// src/tui/session/agentic.ts
|
|
2112
|
+
var AGENTIC_TENANT_LOCK2 = "mintral";
|
|
2113
|
+
function isAgenticTenantMismatch(mode, tenant) {
|
|
2114
|
+
return mode === "agentic" && tenant !== AGENTIC_TENANT_LOCK2;
|
|
2115
|
+
}
|
|
2116
|
+
|
|
1888
2117
|
// src/tui/useSession.ts
|
|
1889
|
-
import { useCallback, useEffect as
|
|
2118
|
+
import { useCallback, useEffect as useEffect3, useReducer as useReducer2, useRef } from "react";
|
|
1890
2119
|
import { appendFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
1891
2120
|
import { dirname as dirname3 } from "path";
|
|
1892
2121
|
|
|
@@ -2368,7 +2597,7 @@ function useSession(opts) {
|
|
|
2368
2597
|
() => initialSession(opts.initial, opts.ctx)
|
|
2369
2598
|
);
|
|
2370
2599
|
const stateRef = useRef(state);
|
|
2371
|
-
|
|
2600
|
+
useEffect3(() => {
|
|
2372
2601
|
stateRef.current = state;
|
|
2373
2602
|
}, [state]);
|
|
2374
2603
|
const abortRef = useRef(null);
|
|
@@ -2961,14 +3190,13 @@ function lastUserPrompt(state) {
|
|
|
2961
3190
|
}
|
|
2962
3191
|
|
|
2963
3192
|
// src/tui/App.tsx
|
|
2964
|
-
import {
|
|
2965
|
-
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3193
|
+
import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2966
3194
|
function App(props) {
|
|
2967
3195
|
const themeResult = useMemo2(
|
|
2968
3196
|
() => loadUserTheme(props.config.theme),
|
|
2969
3197
|
[props.config.theme]
|
|
2970
3198
|
);
|
|
2971
|
-
return /* @__PURE__ */
|
|
3199
|
+
return /* @__PURE__ */ jsx18(ThemeProvider, { initialTheme: themeResult.theme, children: /* @__PURE__ */ jsx18(AppInner, { ...props, themeWarning: themeResult.warning }) });
|
|
2972
3200
|
}
|
|
2973
3201
|
function AppInner(props) {
|
|
2974
3202
|
const home = props.home ?? defaultMiotChatHome();
|
|
@@ -2988,8 +3216,8 @@ function AppInner(props) {
|
|
|
2988
3216
|
client: props.client
|
|
2989
3217
|
});
|
|
2990
3218
|
const { setTheme } = useTheme();
|
|
2991
|
-
const [extraItems, setExtraItems] =
|
|
2992
|
-
const [modal, setModalState] =
|
|
3219
|
+
const [extraItems, setExtraItems] = useState8([]);
|
|
3220
|
+
const [modal, setModalState] = useState8({ spec: null });
|
|
2993
3221
|
const registry = useMemo2(() => {
|
|
2994
3222
|
const reg = new SlashRegistry();
|
|
2995
3223
|
reg.register(helpCommand).register(clearCommand).register(resetCommand).register(exitCommand).register(modeCommand).register(tenantCommand).register(userCommand).register(saveCommand).register(contextCommand).register(whoamiCommand).register(themeCommand).register(resumeCommand).register(exportCommand).register(runsCommand).register(approveCommand);
|
|
@@ -3047,6 +3275,13 @@ function AppInner(props) {
|
|
|
3047
3275
|
appendSystem
|
|
3048
3276
|
]
|
|
3049
3277
|
);
|
|
3278
|
+
useInput7((input, key) => {
|
|
3279
|
+
if (!key.ctrl || modal.spec !== null) return;
|
|
3280
|
+
if (input === "r") void dispatchSlash("/resume");
|
|
3281
|
+
else if (input === "t") void dispatchSlash("/theme");
|
|
3282
|
+
else if (input === "g") void dispatchSlash("/help");
|
|
3283
|
+
else if (input === "q") void dispatchSlash("/exit");
|
|
3284
|
+
});
|
|
3050
3285
|
const handleSubmit = useCallback2(
|
|
3051
3286
|
(text) => {
|
|
3052
3287
|
if (text.trim().startsWith("/")) {
|
|
@@ -3067,16 +3302,21 @@ function AppInner(props) {
|
|
|
3067
3302
|
);
|
|
3068
3303
|
const modalSpec = modal.spec;
|
|
3069
3304
|
const editorActive = modalSpec === null;
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3305
|
+
const version2 = useMemo2(() => packageVersion(), []);
|
|
3306
|
+
const showWelcome = allItems.length === 0 && modalSpec === null;
|
|
3307
|
+
const meta = session.state.meta;
|
|
3308
|
+
const agenticWarn = isAgenticTenantMismatch(meta.mode, meta.tenantId);
|
|
3309
|
+
return /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", children: [
|
|
3310
|
+
props.themeWarning ? /* @__PURE__ */ jsx18(Box16, { paddingX: 1, children: /* @__PURE__ */ jsx18(SystemNote, { text: `theme: ${props.themeWarning}` }) }) : null,
|
|
3311
|
+
/* @__PURE__ */ jsx18(TopLine, { meta, streaming: isStreaming(session.state) }),
|
|
3312
|
+
showWelcome ? /* @__PURE__ */ jsx18(WelcomeCard, { version: version2 }) : /* @__PURE__ */ jsx18(
|
|
3073
3313
|
Transcript,
|
|
3074
3314
|
{
|
|
3075
3315
|
items: allItems,
|
|
3076
3316
|
isStreaming: isStreaming(session.state)
|
|
3077
3317
|
}
|
|
3078
3318
|
),
|
|
3079
|
-
modalSpec?.kind === "context" ? /* @__PURE__ */
|
|
3319
|
+
modalSpec?.kind === "context" ? /* @__PURE__ */ jsx18(
|
|
3080
3320
|
ContextModal,
|
|
3081
3321
|
{
|
|
3082
3322
|
session: session.state,
|
|
@@ -3084,7 +3324,7 @@ function AppInner(props) {
|
|
|
3084
3324
|
onClose: closeModal
|
|
3085
3325
|
}
|
|
3086
3326
|
) : null,
|
|
3087
|
-
modalSpec?.kind === "resume" ? /* @__PURE__ */
|
|
3327
|
+
modalSpec?.kind === "resume" ? /* @__PURE__ */ jsx18(
|
|
3088
3328
|
ResumePicker,
|
|
3089
3329
|
{
|
|
3090
3330
|
summaries: listSessions(home),
|
|
@@ -3097,7 +3337,7 @@ function AppInner(props) {
|
|
|
3097
3337
|
onCancel: closeModal
|
|
3098
3338
|
}
|
|
3099
3339
|
) : null,
|
|
3100
|
-
modalSpec?.kind === "theme" ? /* @__PURE__ */
|
|
3340
|
+
modalSpec?.kind === "theme" ? /* @__PURE__ */ jsx18(
|
|
3101
3341
|
ThemePicker,
|
|
3102
3342
|
{
|
|
3103
3343
|
initialName: typeof modalSpec.payload?.name === "string" ? modalSpec.payload.name : void 0,
|
|
@@ -3112,7 +3352,7 @@ function AppInner(props) {
|
|
|
3112
3352
|
onCancel: closeModal
|
|
3113
3353
|
}
|
|
3114
3354
|
) : null,
|
|
3115
|
-
modalSpec?.kind === "approval" && isApprovalsUiEnabled() && session.state.pendingApprovals.length > 0 ? /* @__PURE__ */
|
|
3355
|
+
modalSpec?.kind === "approval" && isApprovalsUiEnabled() && session.state.pendingApprovals.length > 0 ? /* @__PURE__ */ jsx18(
|
|
3116
3356
|
ApprovalModal,
|
|
3117
3357
|
{
|
|
3118
3358
|
approval: session.state.pendingApprovals[0],
|
|
@@ -3122,7 +3362,7 @@ function AppInner(props) {
|
|
|
3122
3362
|
}
|
|
3123
3363
|
}
|
|
3124
3364
|
) : null,
|
|
3125
|
-
modalSpec?.kind === "runs" ? /* @__PURE__ */
|
|
3365
|
+
modalSpec?.kind === "runs" ? /* @__PURE__ */ jsx18(
|
|
3126
3366
|
RunsPickerWrapped,
|
|
3127
3367
|
{
|
|
3128
3368
|
state: session.state,
|
|
@@ -3133,27 +3373,28 @@ function AppInner(props) {
|
|
|
3133
3373
|
onCancel: closeModal
|
|
3134
3374
|
}
|
|
3135
3375
|
) : null,
|
|
3136
|
-
/* @__PURE__ */
|
|
3137
|
-
|
|
3376
|
+
/* @__PURE__ */ jsx18(TipLine, { tipIndex: turnCount(session.state) }),
|
|
3377
|
+
/* @__PURE__ */ jsx18(InputFrame, { label: `miot \xB7 ${meta.mode}`, labelWarn: agenticWarn, children: /* @__PURE__ */ jsx18(Editor, { onSubmit: handleSubmit, isFocused: editorActive }) }),
|
|
3378
|
+
/* @__PURE__ */ jsx18(
|
|
3379
|
+
FooterLine,
|
|
3138
3380
|
{
|
|
3139
|
-
meta: session.state.meta,
|
|
3140
|
-
streaming: isStreaming(session.state),
|
|
3141
|
-
pendingApprovals: pendingApprovalCount(session.state),
|
|
3142
3381
|
turns: turnCount(session.state),
|
|
3143
3382
|
approxTokens: approxTokenCount(session.state),
|
|
3144
3383
|
contextPercent: contextPercent(session.state),
|
|
3145
|
-
usageTotals: session.state.usageTotals
|
|
3384
|
+
usageTotals: session.state.usageTotals,
|
|
3385
|
+
baseUrl: meta.baseUrl,
|
|
3386
|
+
profileName: meta.profileName,
|
|
3387
|
+
pendingApprovals: pendingApprovalCount(session.state)
|
|
3146
3388
|
}
|
|
3147
|
-
)
|
|
3148
|
-
/* @__PURE__ */ jsx14(Editor, { onSubmit: handleSubmit, isFocused: editorActive })
|
|
3389
|
+
)
|
|
3149
3390
|
] });
|
|
3150
3391
|
}
|
|
3151
3392
|
function RunsPickerWrapped(props) {
|
|
3152
3393
|
const runs = summarizeRuns(props.state);
|
|
3153
|
-
return /* @__PURE__ */
|
|
3394
|
+
return /* @__PURE__ */ jsx18(RunsPicker, { runs, onSelect: props.onSelect, onCancel: props.onCancel });
|
|
3154
3395
|
}
|
|
3155
3396
|
function SystemNote(props) {
|
|
3156
|
-
return /* @__PURE__ */
|
|
3397
|
+
return /* @__PURE__ */ jsx18(Box16, { children: /* @__PURE__ */ jsx18(Text17, { dimColor: true, children: props.text }) });
|
|
3157
3398
|
}
|
|
3158
3399
|
|
|
3159
3400
|
// src/tui/runTui.ts
|
|
@@ -3278,8 +3519,7 @@ async function runMiotChat(opts) {
|
|
|
3278
3519
|
}
|
|
3279
3520
|
|
|
3280
3521
|
// src/cli.ts
|
|
3281
|
-
var
|
|
3282
|
-
var { version } = require2("../package.json");
|
|
3522
|
+
var version = packageVersion();
|
|
3283
3523
|
var program = new Command();
|
|
3284
3524
|
program.name("miot-chat").description(
|
|
3285
3525
|
"Copilot-style agentic chat CLI for miot-harness (SSE streaming)."
|