@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/index.js
CHANGED
|
@@ -671,10 +671,18 @@ import { render } from "ink";
|
|
|
671
671
|
import { createElement } from "react";
|
|
672
672
|
|
|
673
673
|
// src/tui/App.tsx
|
|
674
|
-
import { Box as
|
|
675
|
-
import { useCallback as useCallback2, useMemo as useMemo2, useState as
|
|
674
|
+
import { Box as Box16, Text as Text17, useInput as useInput7 } from "ink";
|
|
675
|
+
import { useCallback as useCallback2, useMemo as useMemo2, useState as useState8 } from "react";
|
|
676
676
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
677
677
|
|
|
678
|
+
// src/version.ts
|
|
679
|
+
import { createRequire } from "module";
|
|
680
|
+
function packageVersion() {
|
|
681
|
+
const require2 = createRequire(import.meta.url);
|
|
682
|
+
const pkg = require2("../package.json");
|
|
683
|
+
return pkg.version;
|
|
684
|
+
}
|
|
685
|
+
|
|
678
686
|
// src/tui/input/Editor.tsx
|
|
679
687
|
import { Box, Text, useInput } from "ink";
|
|
680
688
|
import { useReducer, useState } from "react";
|
|
@@ -1028,15 +1036,9 @@ function renderLine(line, cursorCol) {
|
|
|
1028
1036
|
] });
|
|
1029
1037
|
}
|
|
1030
1038
|
|
|
1031
|
-
// src/tui/
|
|
1039
|
+
// src/tui/chrome/TopLine.tsx
|
|
1032
1040
|
import { Box as Box2, Text as Text3 } from "ink";
|
|
1033
1041
|
|
|
1034
|
-
// src/tui/session/agentic.ts
|
|
1035
|
-
var AGENTIC_TENANT_LOCK2 = "mintral";
|
|
1036
|
-
function isAgenticTenantMismatch(mode, tenant) {
|
|
1037
|
-
return mode === "agentic" && tenant !== AGENTIC_TENANT_LOCK2;
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
1042
|
// src/tui/transcript/Spinner.tsx
|
|
1041
1043
|
import { Text as Text2 } from "ink";
|
|
1042
1044
|
import { useEffect, useState as useState2 } from "react";
|
|
@@ -1057,129 +1059,421 @@ function Spinner(props) {
|
|
|
1057
1059
|
return /* @__PURE__ */ jsx2(Text2, { color: props.color, children: FRAMES[frame] });
|
|
1058
1060
|
}
|
|
1059
1061
|
|
|
1060
|
-
// src/tui/
|
|
1061
|
-
import {
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1062
|
+
// src/tui/theme/ThemeProvider.tsx
|
|
1063
|
+
import { createContext, useContext, useMemo, useState as useState3 } from "react";
|
|
1064
|
+
|
|
1065
|
+
// src/tui/theme/themes.ts
|
|
1066
|
+
var DARK_THEME = {
|
|
1067
|
+
accent: "cyan",
|
|
1068
|
+
assistant: "white",
|
|
1069
|
+
user: "cyan",
|
|
1070
|
+
dim: "gray",
|
|
1071
|
+
warn: "yellow",
|
|
1072
|
+
err: "red",
|
|
1073
|
+
ok: "green",
|
|
1074
|
+
border: "gray",
|
|
1075
|
+
prompt: "cyan",
|
|
1076
|
+
spinner: "cyan"
|
|
1077
|
+
};
|
|
1078
|
+
var LIGHT_THEME = {
|
|
1079
|
+
accent: "blue",
|
|
1080
|
+
assistant: "black",
|
|
1081
|
+
user: "blue",
|
|
1082
|
+
dim: "gray",
|
|
1083
|
+
warn: "yellow",
|
|
1084
|
+
err: "red",
|
|
1085
|
+
ok: "green",
|
|
1086
|
+
border: "gray",
|
|
1087
|
+
prompt: "blue",
|
|
1088
|
+
spinner: "blue"
|
|
1089
|
+
};
|
|
1090
|
+
var HIGH_CONTRAST_THEME = {
|
|
1091
|
+
accent: "white",
|
|
1092
|
+
assistant: "white",
|
|
1093
|
+
user: "white",
|
|
1094
|
+
dim: "white",
|
|
1095
|
+
warn: "yellow",
|
|
1096
|
+
err: "red",
|
|
1097
|
+
ok: "green",
|
|
1098
|
+
border: "white",
|
|
1099
|
+
prompt: "white",
|
|
1100
|
+
spinner: "white"
|
|
1101
|
+
};
|
|
1102
|
+
var BUILTIN_THEMES = {
|
|
1103
|
+
dark: DARK_THEME,
|
|
1104
|
+
light: LIGHT_THEME,
|
|
1105
|
+
"high-contrast": HIGH_CONTRAST_THEME
|
|
1106
|
+
};
|
|
1107
|
+
var DEFAULT_THEME_NAME = "dark";
|
|
1108
|
+
function builtinThemeNames() {
|
|
1109
|
+
return Object.keys(BUILTIN_THEMES).sort();
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// src/tui/theme/ThemeProvider.tsx
|
|
1113
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1114
|
+
var ThemeContext = createContext({
|
|
1115
|
+
theme: DARK_THEME,
|
|
1116
|
+
setTheme: () => void 0
|
|
1117
|
+
});
|
|
1118
|
+
function ThemeProvider(props) {
|
|
1119
|
+
const [theme, setTheme] = useState3(
|
|
1120
|
+
props.initialTheme ?? DARK_THEME
|
|
1086
1121
|
);
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
"
|
|
1105
|
-
props.
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1122
|
+
const value = useMemo(
|
|
1123
|
+
() => ({ theme, setTheme }),
|
|
1124
|
+
[theme]
|
|
1125
|
+
);
|
|
1126
|
+
return /* @__PURE__ */ jsx3(ThemeContext.Provider, { value, children: props.children });
|
|
1127
|
+
}
|
|
1128
|
+
function useTheme() {
|
|
1129
|
+
return useContext(ThemeContext);
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
// src/tui/chrome/TopLine.tsx
|
|
1133
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1134
|
+
function TopLine(props) {
|
|
1135
|
+
const { theme } = useTheme();
|
|
1136
|
+
const shortConv = props.meta.conversationId.slice(0, 8);
|
|
1137
|
+
return /* @__PURE__ */ jsxs2(Box2, { paddingX: 1, children: [
|
|
1138
|
+
/* @__PURE__ */ jsxs2(Text3, { color: theme.dim, children: [
|
|
1139
|
+
"\u2387 ",
|
|
1140
|
+
props.meta.tenantId,
|
|
1141
|
+
" \xB7 ",
|
|
1142
|
+
props.meta.userId,
|
|
1143
|
+
" \xB7 conv ",
|
|
1144
|
+
shortConv
|
|
1145
|
+
] }),
|
|
1146
|
+
props.streaming ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1147
|
+
/* @__PURE__ */ jsx4(Text3, { color: theme.dim, children: " " }),
|
|
1148
|
+
/* @__PURE__ */ jsx4(Spinner, { color: theme.spinner })
|
|
1149
|
+
] }) : null
|
|
1150
|
+
] });
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// src/tui/chrome/TipLine.tsx
|
|
1154
|
+
import { Box as Box3, Text as Text4 } from "ink";
|
|
1155
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1156
|
+
var TIPS = [
|
|
1157
|
+
"Tip: type / to see available commands.",
|
|
1158
|
+
"Tip: ctrl+r resumes a saved session.",
|
|
1159
|
+
"Tip: ctrl+t switches the color theme.",
|
|
1160
|
+
"Tip: /save stores this conversation for later.",
|
|
1161
|
+
"Tip: /export writes the conversation as markdown."
|
|
1162
|
+
];
|
|
1163
|
+
function TipLine(props) {
|
|
1164
|
+
const { theme } = useTheme();
|
|
1165
|
+
const tip = TIPS[props.tipIndex % TIPS.length];
|
|
1166
|
+
return /* @__PURE__ */ jsx5(Box3, { paddingX: 1, children: /* @__PURE__ */ jsx5(Text4, { color: theme.dim, children: tip }) });
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// src/tui/chrome/FooterLine.tsx
|
|
1170
|
+
import { Box as Box4, Text as Text5 } from "ink";
|
|
1171
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1172
|
+
function FooterLine(props) {
|
|
1173
|
+
const { theme } = useTheme();
|
|
1174
|
+
const segments = [];
|
|
1175
|
+
segments.push(`turns ${props.turns}`);
|
|
1176
|
+
segments.push(`ctx\u2248${props.approxTokens}tok (${props.contextPercent}%)`);
|
|
1177
|
+
const u = props.usageTotals;
|
|
1178
|
+
if (u && (u.inputTokens > 0 || u.outputTokens > 0)) {
|
|
1121
1179
|
const cost = u.costUsd > 0 ? ` $${u.costUsd.toFixed(4)}` : "";
|
|
1122
|
-
|
|
1123
|
-
/* @__PURE__ */ jsxs2(Text3, { dimColor: true, children: [
|
|
1124
|
-
"usage=",
|
|
1125
|
-
u.inputTokens,
|
|
1126
|
-
"\u2192",
|
|
1127
|
-
u.outputTokens,
|
|
1128
|
-
cost
|
|
1129
|
-
] }, "usage")
|
|
1130
|
-
);
|
|
1180
|
+
segments.push(`${u.inputTokens}\u2192${u.outputTokens}${cost}`);
|
|
1131
1181
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1182
|
+
segments.push(props.baseUrl);
|
|
1183
|
+
if (props.profileName) {
|
|
1184
|
+
segments.push(`profile ${props.profileName}`);
|
|
1134
1185
|
}
|
|
1135
|
-
return /* @__PURE__ */
|
|
1186
|
+
return /* @__PURE__ */ jsxs3(Box4, { paddingX: 1, justifyContent: "flex-end", children: [
|
|
1187
|
+
props.pendingApprovals > 0 ? /* @__PURE__ */ jsxs3(Text5, { color: theme.warn, children: [
|
|
1188
|
+
"approvals ",
|
|
1189
|
+
props.pendingApprovals,
|
|
1190
|
+
" \xB7 "
|
|
1191
|
+
] }) : null,
|
|
1192
|
+
/* @__PURE__ */ jsx6(Text5, { color: theme.dim, children: segments.join(" \xB7 ") })
|
|
1193
|
+
] });
|
|
1136
1194
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1195
|
+
|
|
1196
|
+
// src/tui/chrome/InputFrame.tsx
|
|
1197
|
+
import { Box as Box5, Text as Text6 } from "ink";
|
|
1198
|
+
|
|
1199
|
+
// src/tui/hooks/useTerminalWidth.ts
|
|
1200
|
+
import { useStdout } from "ink";
|
|
1201
|
+
import { useEffect as useEffect2, useState as useState4 } from "react";
|
|
1202
|
+
var FALLBACK_COLUMNS = 80;
|
|
1203
|
+
var MIN_COLUMNS = 20;
|
|
1204
|
+
function useTerminalWidth() {
|
|
1205
|
+
const { stdout } = useStdout();
|
|
1206
|
+
const [columns, setColumns] = useState4(
|
|
1207
|
+
stdout?.columns ?? FALLBACK_COLUMNS
|
|
1208
|
+
);
|
|
1209
|
+
useEffect2(() => {
|
|
1210
|
+
if (!stdout) return;
|
|
1211
|
+
const onResize = () => {
|
|
1212
|
+
setColumns(stdout.columns ?? FALLBACK_COLUMNS);
|
|
1213
|
+
};
|
|
1214
|
+
stdout.on("resize", onResize);
|
|
1215
|
+
return () => {
|
|
1216
|
+
stdout.off("resize", onResize);
|
|
1217
|
+
};
|
|
1218
|
+
}, [stdout]);
|
|
1219
|
+
return Math.max(MIN_COLUMNS, columns);
|
|
1220
|
+
}
|
|
1221
|
+
var FALLBACK_ROWS = 24;
|
|
1222
|
+
var MIN_ROWS = 10;
|
|
1223
|
+
function useTerminalRows() {
|
|
1224
|
+
const { stdout } = useStdout();
|
|
1225
|
+
const [rows, setRows] = useState4(stdout?.rows ?? FALLBACK_ROWS);
|
|
1226
|
+
useEffect2(() => {
|
|
1227
|
+
if (!stdout) return;
|
|
1228
|
+
const onResize = () => {
|
|
1229
|
+
setRows(stdout.rows ?? FALLBACK_ROWS);
|
|
1230
|
+
};
|
|
1231
|
+
stdout.on("resize", onResize);
|
|
1232
|
+
return () => {
|
|
1233
|
+
stdout.off("resize", onResize);
|
|
1234
|
+
};
|
|
1235
|
+
}, [stdout]);
|
|
1236
|
+
return Math.max(MIN_ROWS, rows);
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
// src/tui/chrome/InputFrame.tsx
|
|
1240
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1241
|
+
function InputFrame(props) {
|
|
1242
|
+
const cols = useTerminalWidth();
|
|
1243
|
+
const { theme } = useTheme();
|
|
1244
|
+
return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", width: cols, children: [
|
|
1245
|
+
/* @__PURE__ */ jsx7(
|
|
1246
|
+
Box5,
|
|
1247
|
+
{
|
|
1248
|
+
borderStyle: "round",
|
|
1249
|
+
borderColor: theme.border,
|
|
1250
|
+
borderBottom: false,
|
|
1251
|
+
paddingX: 1,
|
|
1252
|
+
children: props.children
|
|
1253
|
+
}
|
|
1254
|
+
),
|
|
1255
|
+
/* @__PURE__ */ jsx7(
|
|
1256
|
+
BottomBorder,
|
|
1257
|
+
{
|
|
1258
|
+
cols,
|
|
1259
|
+
label: props.label,
|
|
1260
|
+
warn: props.labelWarn ?? false
|
|
1261
|
+
}
|
|
1262
|
+
)
|
|
1263
|
+
] });
|
|
1264
|
+
}
|
|
1265
|
+
function BottomBorder(props) {
|
|
1266
|
+
const { theme } = useTheme();
|
|
1267
|
+
const visibleLabel = props.warn ? `\u26A0 ${props.label}` : props.label;
|
|
1268
|
+
const labelText = ` ${visibleLabel} `;
|
|
1269
|
+
const fill = props.cols - 2 - labelText.length - 2;
|
|
1270
|
+
if (fill < 1) {
|
|
1271
|
+
return /* @__PURE__ */ jsxs4(Text6, { color: theme.border, children: [
|
|
1272
|
+
"\u2570",
|
|
1273
|
+
"\u2500".repeat(Math.max(0, props.cols - 2)),
|
|
1274
|
+
"\u256F"
|
|
1275
|
+
] });
|
|
1276
|
+
}
|
|
1277
|
+
return /* @__PURE__ */ jsxs4(Text6, { children: [
|
|
1278
|
+
/* @__PURE__ */ jsxs4(Text6, { color: theme.border, children: [
|
|
1279
|
+
"\u2570",
|
|
1280
|
+
"\u2500".repeat(fill)
|
|
1281
|
+
] }),
|
|
1282
|
+
/* @__PURE__ */ jsx7(Text6, { color: props.warn ? theme.warn : theme.dim, children: labelText }),
|
|
1283
|
+
/* @__PURE__ */ jsx7(Text6, { color: theme.border, children: "\u2500\u2500\u256F" })
|
|
1284
|
+
] });
|
|
1144
1285
|
}
|
|
1145
1286
|
|
|
1146
|
-
// src/tui/
|
|
1287
|
+
// src/tui/chrome/WelcomeCard.tsx
|
|
1147
1288
|
import { Box as Box6, Text as Text7 } from "ink";
|
|
1289
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1290
|
+
var LOGO = [
|
|
1291
|
+
[
|
|
1292
|
+
{ text: "\u2880", tone: "accent" },
|
|
1293
|
+
{ text: "\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800", tone: "accent" },
|
|
1294
|
+
{ text: "\u28C0", tone: "accent" },
|
|
1295
|
+
{ text: "\u28E4\u28E4\u28C0", tone: "warn" },
|
|
1296
|
+
{ text: "\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800", tone: "accent" },
|
|
1297
|
+
{ text: "\u2840", tone: "accent" }
|
|
1298
|
+
],
|
|
1299
|
+
[
|
|
1300
|
+
{ text: "\u2800", tone: "accent" },
|
|
1301
|
+
{ text: "\u28BF\u28F6\u28F6\u28E4\u28E4\u28F0", tone: "accent" },
|
|
1302
|
+
{ text: "\u28B6\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28F7", tone: "warn" },
|
|
1303
|
+
{ text: "\u28C6\u28E4\u28E4\u28F6\u28F6\u287F", tone: "accent" },
|
|
1304
|
+
{ text: "\u2800", tone: "accent" }
|
|
1305
|
+
],
|
|
1306
|
+
[
|
|
1307
|
+
{ text: "\u2800", tone: "accent" },
|
|
1308
|
+
{ text: "\u2808\u281B\u28DB\u289B\u28DB\u28DB\u285B\u283A", tone: "accent" },
|
|
1309
|
+
{ text: "\u28BF\u28FF\u28FF\u287F", tone: "warn" },
|
|
1310
|
+
{ text: "\u281F\u281B\u28DB\u28DB\u28DB\u28DB\u281B\u2801", tone: "accent" },
|
|
1311
|
+
{ text: "\u2800", tone: "accent" }
|
|
1312
|
+
],
|
|
1313
|
+
[
|
|
1314
|
+
{ text: "\u2800", tone: "accent" },
|
|
1315
|
+
{ text: "\u2880\u28FF\u28FF", tone: "accent" },
|
|
1316
|
+
{ text: "\u28FF\u289F\u28DB\u28DB\u28BF\u28E6", tone: "face" },
|
|
1317
|
+
{ text: "\u28CC\u28E1", tone: "accent" },
|
|
1318
|
+
{ text: "\u28F4\u287E\u28DB\u28DB\u287F\u28FF", tone: "face" },
|
|
1319
|
+
{ text: "\u28FF\u28F7", tone: "accent" },
|
|
1320
|
+
{ text: "\u2800\u2800", tone: "accent" }
|
|
1321
|
+
],
|
|
1322
|
+
[
|
|
1323
|
+
{ text: "\u2800", tone: "accent" },
|
|
1324
|
+
{ text: "\u28F8\u28FF", tone: "accent" },
|
|
1325
|
+
{ text: "\u28FF", tone: "face" },
|
|
1326
|
+
{ text: "\u28B3", tone: "accent" },
|
|
1327
|
+
{ text: "\u287F", tone: "warn" },
|
|
1328
|
+
{ text: "\u286F", tone: "accent" },
|
|
1329
|
+
{ text: "\u2819\u28F7", tone: "warn" },
|
|
1330
|
+
{ text: "\u28BB\u28FF\u28FF\u285F", tone: "face" },
|
|
1331
|
+
{ text: "\u28FE\u280B", tone: "warn" },
|
|
1332
|
+
{ text: "\u28BD", tone: "accent" },
|
|
1333
|
+
{ text: "\u28BB", tone: "warn" },
|
|
1334
|
+
{ text: "\u28FD", tone: "accent" },
|
|
1335
|
+
{ text: "\u28FF", tone: "face" },
|
|
1336
|
+
{ text: "\u28FF\u2847", tone: "accent" },
|
|
1337
|
+
{ text: "\u2800", tone: "accent" }
|
|
1338
|
+
],
|
|
1339
|
+
[
|
|
1340
|
+
{ text: "\u2800", tone: "accent" },
|
|
1341
|
+
{ text: "\u28BB\u28FF", tone: "accent" },
|
|
1342
|
+
{ text: "\u28FF", tone: "face" },
|
|
1343
|
+
{ text: "\u285C\u28E7\u28C0\u28E0\u287F", tone: "warn" },
|
|
1344
|
+
{ text: "\u28FC\u287F\u28FF\u28E7", tone: "face" },
|
|
1345
|
+
{ text: "\u28BF\u28C4\u28E0\u287E", tone: "warn" },
|
|
1346
|
+
{ text: "\u28FB", tone: "accent" },
|
|
1347
|
+
{ text: "\u28FF", tone: "face" },
|
|
1348
|
+
{ text: "\u28FF\u2847", tone: "accent" },
|
|
1349
|
+
{ text: "\u2800", tone: "accent" }
|
|
1350
|
+
],
|
|
1351
|
+
[
|
|
1352
|
+
{ text: "\u2800", tone: "accent" },
|
|
1353
|
+
{ text: "\u2818\u28FF\u28FF", tone: "accent" },
|
|
1354
|
+
{ text: "\u28FF\u28F6\u28EF\u28F7\u28FE\u285F", tone: "face" },
|
|
1355
|
+
{ text: "\u2801\u28EC", tone: "accent" },
|
|
1356
|
+
{ text: "\u28FB\u28F7\u28FE\u28FF\u28FE\u28FF", tone: "face" },
|
|
1357
|
+
{ text: "\u28FF\u287F", tone: "accent" },
|
|
1358
|
+
{ text: "\u2800\u2800", tone: "accent" }
|
|
1359
|
+
],
|
|
1360
|
+
[
|
|
1361
|
+
{ text: "\u2800\u2800", tone: "accent" },
|
|
1362
|
+
{ text: "\u2818\u28BF\u28FF\u28FF", tone: "accent" },
|
|
1363
|
+
{ text: "\u28FF\u28FF\u28FF\u28FF", tone: "face" },
|
|
1364
|
+
{ text: "\u2844\u28A1", tone: "accent" },
|
|
1365
|
+
{ text: "\u28FF\u28FF\u28FF\u28FF", tone: "face" },
|
|
1366
|
+
{ text: "\u28FF\u28FF\u281F\u2801", tone: "accent" },
|
|
1367
|
+
{ text: "\u2800\u2800", tone: "accent" }
|
|
1368
|
+
],
|
|
1369
|
+
[
|
|
1370
|
+
{ text: "\u2800\u2800\u2800\u2800", tone: "accent" },
|
|
1371
|
+
{ text: "\u2819\u283B\u28BF\u28FF\u28FF", tone: "accent" },
|
|
1372
|
+
{ text: "\u28FF\u28FF\u28FF\u28FF", tone: "face" },
|
|
1373
|
+
{ text: "\u28FF\u28FF\u287F\u281F\u2801", tone: "accent" },
|
|
1374
|
+
{ text: "\u2800\u2800\u2800\u2800", tone: "accent" }
|
|
1375
|
+
],
|
|
1376
|
+
[
|
|
1377
|
+
{ text: "\u2800\u2800\u2800\u2800\u2800\u2800\u2800", tone: "accent" },
|
|
1378
|
+
{ text: "\u2808\u2819\u281B\u281B\u281B\u281B\u2809\u2801", tone: "accent" },
|
|
1379
|
+
{ text: "\u2800\u2800\u2800\u2800\u2800\u2800\u2800", tone: "accent" }
|
|
1380
|
+
]
|
|
1381
|
+
];
|
|
1382
|
+
var MENU = [
|
|
1383
|
+
{ label: "Resume session", shortcut: "ctrl+r" },
|
|
1384
|
+
{ label: "Switch theme", shortcut: "ctrl+t" },
|
|
1385
|
+
{ label: "Help", shortcut: "ctrl+g (/help)" },
|
|
1386
|
+
{ label: "Quit", shortcut: "ctrl+q" }
|
|
1387
|
+
];
|
|
1388
|
+
var CHROME_ROWS = 6;
|
|
1389
|
+
var CARD_ROWS = 14;
|
|
1390
|
+
function WelcomeCard(props) {
|
|
1391
|
+
const cols = useTerminalWidth();
|
|
1392
|
+
const rows = useTerminalRows();
|
|
1393
|
+
const { theme } = useTheme();
|
|
1394
|
+
return /* @__PURE__ */ jsx8(
|
|
1395
|
+
Box6,
|
|
1396
|
+
{
|
|
1397
|
+
flexDirection: "column",
|
|
1398
|
+
justifyContent: "center",
|
|
1399
|
+
height: Math.max(CARD_ROWS + 1, rows - CHROME_ROWS),
|
|
1400
|
+
children: /* @__PURE__ */ jsxs5(
|
|
1401
|
+
Box6,
|
|
1402
|
+
{
|
|
1403
|
+
borderStyle: "round",
|
|
1404
|
+
borderColor: theme.border,
|
|
1405
|
+
width: Math.min(cols, 64),
|
|
1406
|
+
alignSelf: "center",
|
|
1407
|
+
paddingX: 2,
|
|
1408
|
+
paddingY: 1,
|
|
1409
|
+
flexDirection: "row",
|
|
1410
|
+
children: [
|
|
1411
|
+
/* @__PURE__ */ jsx8(Box6, { flexDirection: "column", marginRight: 3, children: LOGO.map((row, i) => /* @__PURE__ */ jsx8(Text7, { children: row.map((seg, j) => /* @__PURE__ */ jsx8(
|
|
1412
|
+
Text7,
|
|
1413
|
+
{
|
|
1414
|
+
color: seg.tone === "warn" ? theme.warn : seg.tone === "face" ? theme.assistant : theme.accent,
|
|
1415
|
+
children: seg.text
|
|
1416
|
+
},
|
|
1417
|
+
j
|
|
1418
|
+
)) }, i)) }),
|
|
1419
|
+
/* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", flexGrow: 1, children: [
|
|
1420
|
+
/* @__PURE__ */ jsxs5(Box6, { children: [
|
|
1421
|
+
/* @__PURE__ */ jsx8(Text7, { color: theme.accent, bold: true, children: "miot chat" }),
|
|
1422
|
+
/* @__PURE__ */ jsxs5(Text7, { color: theme.dim, children: [
|
|
1423
|
+
" v",
|
|
1424
|
+
props.version
|
|
1425
|
+
] })
|
|
1426
|
+
] }),
|
|
1427
|
+
/* @__PURE__ */ jsx8(Box6, { height: 1 }),
|
|
1428
|
+
MENU.map((item) => /* @__PURE__ */ jsxs5(Box6, { justifyContent: "space-between", children: [
|
|
1429
|
+
/* @__PURE__ */ jsx8(Text7, { children: item.label }),
|
|
1430
|
+
/* @__PURE__ */ jsx8(Text7, { color: theme.dim, children: item.shortcut })
|
|
1431
|
+
] }, item.label))
|
|
1432
|
+
] })
|
|
1433
|
+
]
|
|
1434
|
+
}
|
|
1435
|
+
)
|
|
1436
|
+
}
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
// src/tui/transcript/Transcript.tsx
|
|
1441
|
+
import { Box as Box10, Text as Text11 } from "ink";
|
|
1148
1442
|
|
|
1149
1443
|
// src/tui/transcript/AssistantTurn.tsx
|
|
1150
|
-
import { Box as
|
|
1151
|
-
import { Fragment as
|
|
1444
|
+
import { Box as Box7, Text as Text8 } from "ink";
|
|
1445
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1152
1446
|
function AssistantTurn(props) {
|
|
1153
1447
|
const { text, status } = props.item;
|
|
1154
1448
|
const color = status === "failed" ? "red" : status === "complete" ? "green" : "white";
|
|
1155
|
-
return /* @__PURE__ */
|
|
1156
|
-
status === "streaming" ? /* @__PURE__ */
|
|
1157
|
-
/* @__PURE__ */
|
|
1158
|
-
/* @__PURE__ */
|
|
1449
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "row", marginTop: 1, children: [
|
|
1450
|
+
status === "streaming" ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1451
|
+
/* @__PURE__ */ jsx9(Spinner, { color: "cyan" }),
|
|
1452
|
+
/* @__PURE__ */ jsxs6(Text8, { color, bold: true, children: [
|
|
1159
1453
|
" ",
|
|
1160
1454
|
"miot",
|
|
1161
1455
|
" "
|
|
1162
1456
|
] })
|
|
1163
|
-
] }) : /* @__PURE__ */
|
|
1457
|
+
] }) : /* @__PURE__ */ jsxs6(Text8, { color, bold: true, children: [
|
|
1164
1458
|
status === "failed" ? "\u2717 " : "\u2713 ",
|
|
1165
1459
|
"miot",
|
|
1166
1460
|
" "
|
|
1167
1461
|
] }),
|
|
1168
|
-
/* @__PURE__ */
|
|
1462
|
+
/* @__PURE__ */ jsx9(Text8, { color, children: text })
|
|
1169
1463
|
] });
|
|
1170
1464
|
}
|
|
1171
1465
|
|
|
1172
1466
|
// src/tui/transcript/ToolCall.tsx
|
|
1173
|
-
import { Box as
|
|
1174
|
-
import { jsx as
|
|
1467
|
+
import { Box as Box8, Text as Text9 } from "ink";
|
|
1468
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1175
1469
|
function ToolCall(props) {
|
|
1176
1470
|
const { name, status, message } = props.item;
|
|
1177
1471
|
const color = status === "failed" ? "red" : status === "ok" ? "green" : "yellow";
|
|
1178
1472
|
const glyph = status === "running" ? null : status === "ok" ? "\u2713" : "\u2717";
|
|
1179
|
-
return /* @__PURE__ */
|
|
1180
|
-
/* @__PURE__ */
|
|
1181
|
-
status === "running" ? /* @__PURE__ */
|
|
1182
|
-
/* @__PURE__ */
|
|
1473
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", children: [
|
|
1474
|
+
/* @__PURE__ */ jsx10(Text9, { color, children: glyph !== null ? `${glyph} ` : "" }),
|
|
1475
|
+
status === "running" ? /* @__PURE__ */ jsx10(Spinner, { color }) : null,
|
|
1476
|
+
/* @__PURE__ */ jsxs7(Text9, { color, children: [
|
|
1183
1477
|
" ",
|
|
1184
1478
|
"tool: ",
|
|
1185
1479
|
name,
|
|
@@ -1189,24 +1483,24 @@ function ToolCall(props) {
|
|
|
1189
1483
|
}
|
|
1190
1484
|
|
|
1191
1485
|
// src/tui/transcript/UserTurn.tsx
|
|
1192
|
-
import { Box as
|
|
1193
|
-
import { jsx as
|
|
1486
|
+
import { Box as Box9, Text as Text10 } from "ink";
|
|
1487
|
+
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1194
1488
|
function UserTurn(props) {
|
|
1195
1489
|
const { text } = props.item;
|
|
1196
|
-
return /* @__PURE__ */
|
|
1197
|
-
/* @__PURE__ */
|
|
1490
|
+
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", marginTop: 1, children: [
|
|
1491
|
+
/* @__PURE__ */ jsxs8(Text10, { color: "cyan", bold: true, children: [
|
|
1198
1492
|
"you",
|
|
1199
1493
|
" "
|
|
1200
1494
|
] }),
|
|
1201
|
-
/* @__PURE__ */
|
|
1495
|
+
/* @__PURE__ */ jsx11(Text10, { children: text })
|
|
1202
1496
|
] });
|
|
1203
1497
|
}
|
|
1204
1498
|
|
|
1205
1499
|
// src/tui/transcript/Transcript.tsx
|
|
1206
|
-
import { jsx as
|
|
1500
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1207
1501
|
function Transcript(props) {
|
|
1208
1502
|
const activeChainIdx = props.isStreaming ? findActiveChainIndex(props.items) : -1;
|
|
1209
|
-
return /* @__PURE__ */
|
|
1503
|
+
return /* @__PURE__ */ jsx12(Box10, { flexDirection: "column", children: props.items.map((item, i) => /* @__PURE__ */ jsx12(
|
|
1210
1504
|
TranscriptItemView,
|
|
1211
1505
|
{
|
|
1212
1506
|
item,
|
|
@@ -1231,38 +1525,38 @@ function TranscriptItemView(props) {
|
|
|
1231
1525
|
const { item, isActive } = props;
|
|
1232
1526
|
switch (item.kind) {
|
|
1233
1527
|
case "user":
|
|
1234
|
-
return /* @__PURE__ */
|
|
1528
|
+
return /* @__PURE__ */ jsx12(UserTurn, { item });
|
|
1235
1529
|
case "assistant":
|
|
1236
|
-
return /* @__PURE__ */
|
|
1530
|
+
return /* @__PURE__ */ jsx12(AssistantTurn, { item });
|
|
1237
1531
|
case "tool":
|
|
1238
|
-
return /* @__PURE__ */
|
|
1532
|
+
return /* @__PURE__ */ jsx12(ToolCall, { item });
|
|
1239
1533
|
case "route":
|
|
1240
|
-
return /* @__PURE__ */
|
|
1534
|
+
return /* @__PURE__ */ jsx12(ChainRow, { prefix: "route:", isActive, children: item.route });
|
|
1241
1535
|
case "agent":
|
|
1242
|
-
return /* @__PURE__ */
|
|
1536
|
+
return /* @__PURE__ */ jsx12(ChainRow, { prefix: "agent:", isActive, children: item.agent });
|
|
1243
1537
|
case "thinking":
|
|
1244
|
-
return /* @__PURE__ */
|
|
1245
|
-
/* @__PURE__ */
|
|
1246
|
-
/* @__PURE__ */
|
|
1538
|
+
return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", children: [
|
|
1539
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " \u22EE " }),
|
|
1540
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: true, children: item.text })
|
|
1247
1541
|
] });
|
|
1248
1542
|
case "plan":
|
|
1249
|
-
return /* @__PURE__ */
|
|
1543
|
+
return /* @__PURE__ */ jsx12(ChainRow, { prefix: "plan:", isActive, children: item.message });
|
|
1250
1544
|
case "freshness":
|
|
1251
|
-
return /* @__PURE__ */
|
|
1545
|
+
return /* @__PURE__ */ jsxs9(Text11, { color: "yellow", children: [
|
|
1252
1546
|
"\u26A0 ",
|
|
1253
1547
|
item.message
|
|
1254
1548
|
] });
|
|
1255
1549
|
case "artifact":
|
|
1256
|
-
return /* @__PURE__ */
|
|
1550
|
+
return /* @__PURE__ */ jsx12(ChainRow, { prefix: "artifact:", isActive, children: item.artifactKind });
|
|
1257
1551
|
case "system":
|
|
1258
|
-
return /* @__PURE__ */
|
|
1552
|
+
return /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: item.text });
|
|
1259
1553
|
}
|
|
1260
1554
|
}
|
|
1261
1555
|
function ChainRow(props) {
|
|
1262
1556
|
if (props.isActive) {
|
|
1263
|
-
return /* @__PURE__ */
|
|
1264
|
-
/* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */
|
|
1557
|
+
return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", children: [
|
|
1558
|
+
/* @__PURE__ */ jsx12(Spinner, { color: "cyan" }),
|
|
1559
|
+
/* @__PURE__ */ jsxs9(Text11, { color: "cyan", bold: true, children: [
|
|
1266
1560
|
" ",
|
|
1267
1561
|
props.prefix,
|
|
1268
1562
|
" ",
|
|
@@ -1270,7 +1564,7 @@ function ChainRow(props) {
|
|
|
1270
1564
|
] })
|
|
1271
1565
|
] });
|
|
1272
1566
|
}
|
|
1273
|
-
return /* @__PURE__ */
|
|
1567
|
+
return /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
1274
1568
|
"\xB7 ",
|
|
1275
1569
|
props.prefix,
|
|
1276
1570
|
" ",
|
|
@@ -1279,7 +1573,7 @@ function ChainRow(props) {
|
|
|
1279
1573
|
}
|
|
1280
1574
|
|
|
1281
1575
|
// src/tui/modals/ContextModal.tsx
|
|
1282
|
-
import { Box as
|
|
1576
|
+
import { Box as Box11, Text as Text12, useInput as useInput2 } from "ink";
|
|
1283
1577
|
|
|
1284
1578
|
// src/tui/session/selectors.ts
|
|
1285
1579
|
function isStreaming(state) {
|
|
@@ -1331,7 +1625,7 @@ function contextPercent(state) {
|
|
|
1331
1625
|
}
|
|
1332
1626
|
|
|
1333
1627
|
// src/tui/modals/ContextModal.tsx
|
|
1334
|
-
import { jsx as
|
|
1628
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1335
1629
|
function ContextModal(props) {
|
|
1336
1630
|
const { session, lastRunId } = props;
|
|
1337
1631
|
useInput2(
|
|
@@ -1356,24 +1650,24 @@ function ContextModal(props) {
|
|
|
1356
1650
|
"pending approvals",
|
|
1357
1651
|
String(session.pendingApprovals.length)
|
|
1358
1652
|
]);
|
|
1359
|
-
return /* @__PURE__ */
|
|
1360
|
-
/* @__PURE__ */
|
|
1361
|
-
fields.map(([key, value]) => /* @__PURE__ */
|
|
1653
|
+
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1654
|
+
/* @__PURE__ */ jsx13(Text12, { bold: true, children: "session context" }),
|
|
1655
|
+
fields.map(([key, value]) => /* @__PURE__ */ jsxs10(Text12, { children: [
|
|
1362
1656
|
key.padEnd(18),
|
|
1363
1657
|
" ",
|
|
1364
1658
|
value
|
|
1365
1659
|
] }, key)),
|
|
1366
|
-
/* @__PURE__ */
|
|
1660
|
+
/* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "esc/enter to close" })
|
|
1367
1661
|
] });
|
|
1368
1662
|
}
|
|
1369
1663
|
|
|
1370
1664
|
// src/tui/modals/ResumePicker.tsx
|
|
1371
|
-
import { Box as
|
|
1372
|
-
import { useState as
|
|
1373
|
-
import { jsx as
|
|
1665
|
+
import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
|
|
1666
|
+
import { useState as useState5 } from "react";
|
|
1667
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1374
1668
|
function ResumePicker(props) {
|
|
1375
1669
|
const maxRows = props.maxRows ?? 10;
|
|
1376
|
-
const [index, setIndex] =
|
|
1670
|
+
const [index, setIndex] = useState5(0);
|
|
1377
1671
|
const summaries = props.summaries;
|
|
1378
1672
|
const cap = Math.max(0, summaries.length - 1);
|
|
1379
1673
|
useInput3(
|
|
@@ -1398,23 +1692,23 @@ function ResumePicker(props) {
|
|
|
1398
1692
|
{ isActive: props.isFocused ?? true }
|
|
1399
1693
|
);
|
|
1400
1694
|
if (summaries.length === 0) {
|
|
1401
|
-
return /* @__PURE__ */
|
|
1402
|
-
/* @__PURE__ */
|
|
1403
|
-
/* @__PURE__ */
|
|
1404
|
-
/* @__PURE__ */
|
|
1695
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1696
|
+
/* @__PURE__ */ jsx14(Text13, { bold: true, children: "resume session" }),
|
|
1697
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "(no saved sessions)" }),
|
|
1698
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "esc to close" })
|
|
1405
1699
|
] });
|
|
1406
1700
|
}
|
|
1407
1701
|
const visible = summaries.slice(0, maxRows);
|
|
1408
1702
|
const truncated = summaries.length - visible.length;
|
|
1409
|
-
return /* @__PURE__ */
|
|
1410
|
-
/* @__PURE__ */
|
|
1411
|
-
visible.map((s, i) => /* @__PURE__ */
|
|
1412
|
-
truncated > 0 ? /* @__PURE__ */
|
|
1703
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1704
|
+
/* @__PURE__ */ jsx14(Text13, { bold: true, children: "resume session" }),
|
|
1705
|
+
visible.map((s, i) => /* @__PURE__ */ jsx14(Text13, { inverse: i === index, children: summarize(s) }, s.id)),
|
|
1706
|
+
truncated > 0 ? /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
|
|
1413
1707
|
"\u2026 ",
|
|
1414
1708
|
truncated,
|
|
1415
1709
|
" more"
|
|
1416
1710
|
] }) : null,
|
|
1417
|
-
/* @__PURE__ */
|
|
1711
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "\u2191\u2193 navigate \xB7 enter select \xB7 esc cancel" })
|
|
1418
1712
|
] });
|
|
1419
1713
|
}
|
|
1420
1714
|
function summarize(s) {
|
|
@@ -1430,62 +1724,13 @@ function truncate(text, max) {
|
|
|
1430
1724
|
}
|
|
1431
1725
|
|
|
1432
1726
|
// src/tui/modals/ThemePicker.tsx
|
|
1433
|
-
import { Box as
|
|
1434
|
-
import { useState as
|
|
1435
|
-
|
|
1436
|
-
// src/tui/theme/themes.ts
|
|
1437
|
-
var DARK_THEME = {
|
|
1438
|
-
accent: "cyan",
|
|
1439
|
-
assistant: "white",
|
|
1440
|
-
user: "cyan",
|
|
1441
|
-
dim: "gray",
|
|
1442
|
-
warn: "yellow",
|
|
1443
|
-
err: "red",
|
|
1444
|
-
ok: "green",
|
|
1445
|
-
border: "gray",
|
|
1446
|
-
prompt: "cyan",
|
|
1447
|
-
spinner: "cyan"
|
|
1448
|
-
};
|
|
1449
|
-
var LIGHT_THEME = {
|
|
1450
|
-
accent: "blue",
|
|
1451
|
-
assistant: "black",
|
|
1452
|
-
user: "blue",
|
|
1453
|
-
dim: "gray",
|
|
1454
|
-
warn: "yellow",
|
|
1455
|
-
err: "red",
|
|
1456
|
-
ok: "green",
|
|
1457
|
-
border: "gray",
|
|
1458
|
-
prompt: "blue",
|
|
1459
|
-
spinner: "blue"
|
|
1460
|
-
};
|
|
1461
|
-
var HIGH_CONTRAST_THEME = {
|
|
1462
|
-
accent: "white",
|
|
1463
|
-
assistant: "white",
|
|
1464
|
-
user: "white",
|
|
1465
|
-
dim: "white",
|
|
1466
|
-
warn: "yellow",
|
|
1467
|
-
err: "red",
|
|
1468
|
-
ok: "green",
|
|
1469
|
-
border: "white",
|
|
1470
|
-
prompt: "white",
|
|
1471
|
-
spinner: "white"
|
|
1472
|
-
};
|
|
1473
|
-
var BUILTIN_THEMES = {
|
|
1474
|
-
dark: DARK_THEME,
|
|
1475
|
-
light: LIGHT_THEME,
|
|
1476
|
-
"high-contrast": HIGH_CONTRAST_THEME
|
|
1477
|
-
};
|
|
1478
|
-
var DEFAULT_THEME_NAME = "dark";
|
|
1479
|
-
function builtinThemeNames() {
|
|
1480
|
-
return Object.keys(BUILTIN_THEMES).sort();
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
// src/tui/modals/ThemePicker.tsx
|
|
1484
|
-
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1727
|
+
import { Box as Box13, Text as Text14, useInput as useInput4 } from "ink";
|
|
1728
|
+
import { useState as useState6 } from "react";
|
|
1729
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1485
1730
|
function ThemePicker(props) {
|
|
1486
1731
|
const names = builtinThemeNames();
|
|
1487
1732
|
const initial = props.initialName ? Math.max(0, names.indexOf(props.initialName)) : 0;
|
|
1488
|
-
const [index, setIndex] =
|
|
1733
|
+
const [index, setIndex] = useState6(initial);
|
|
1489
1734
|
const cap = names.length - 1;
|
|
1490
1735
|
useInput4(
|
|
1491
1736
|
(_input, key) => {
|
|
@@ -1508,23 +1753,23 @@ function ThemePicker(props) {
|
|
|
1508
1753
|
},
|
|
1509
1754
|
{ isActive: props.isFocused ?? true }
|
|
1510
1755
|
);
|
|
1511
|
-
return /* @__PURE__ */
|
|
1512
|
-
/* @__PURE__ */
|
|
1756
|
+
return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1757
|
+
/* @__PURE__ */ jsx15(Text14, { bold: true, children: "theme" }),
|
|
1513
1758
|
names.map((name, i) => {
|
|
1514
1759
|
const t = BUILTIN_THEMES[name];
|
|
1515
1760
|
const sample = t ? `accent=${t.accent} user=${t.user}` : "";
|
|
1516
|
-
return /* @__PURE__ */
|
|
1761
|
+
return /* @__PURE__ */ jsxs12(Text14, { inverse: i === index, children: [
|
|
1517
1762
|
name.padEnd(15),
|
|
1518
1763
|
" ",
|
|
1519
1764
|
sample
|
|
1520
1765
|
] }, name);
|
|
1521
1766
|
}),
|
|
1522
|
-
/* @__PURE__ */
|
|
1767
|
+
/* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "\u2191\u2193 navigate \xB7 enter apply \xB7 esc cancel" })
|
|
1523
1768
|
] });
|
|
1524
1769
|
}
|
|
1525
1770
|
|
|
1526
1771
|
// src/tui/modals/ApprovalModal.tsx
|
|
1527
|
-
import { Box as
|
|
1772
|
+
import { Box as Box14, Text as Text15, useInput as useInput5 } from "ink";
|
|
1528
1773
|
|
|
1529
1774
|
// src/tui/session/approvals.ts
|
|
1530
1775
|
var APPROVALS_UI_ENV = "MIOT_CHAT_APPROVALS_UI";
|
|
@@ -1536,7 +1781,7 @@ function isApprovalsUiEnabled(env = process.env) {
|
|
|
1536
1781
|
var APPROVAL_REPLY_PLACEHOLDER = "approval reply not yet supported by harness";
|
|
1537
1782
|
|
|
1538
1783
|
// src/tui/modals/ApprovalModal.tsx
|
|
1539
|
-
import { jsx as
|
|
1784
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1540
1785
|
function ApprovalModal(props) {
|
|
1541
1786
|
const { approval, onResolve } = props;
|
|
1542
1787
|
useInput5(
|
|
@@ -1549,22 +1794,22 @@ function ApprovalModal(props) {
|
|
|
1549
1794
|
{ isActive: props.isFocused ?? true }
|
|
1550
1795
|
);
|
|
1551
1796
|
const data = JSON.stringify(approval.data, null, 2);
|
|
1552
|
-
return /* @__PURE__ */
|
|
1553
|
-
/* @__PURE__ */
|
|
1554
|
-
/* @__PURE__ */
|
|
1555
|
-
/* @__PURE__ */
|
|
1556
|
-
/* @__PURE__ */
|
|
1557
|
-
/* @__PURE__ */
|
|
1797
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1798
|
+
/* @__PURE__ */ jsx16(Text15, { bold: true, color: "yellow", children: "approval requested" }),
|
|
1799
|
+
/* @__PURE__ */ jsx16(Text15, { children: approval.message || "(no message)" }),
|
|
1800
|
+
/* @__PURE__ */ jsx16(Text15, { dimColor: true, children: data }),
|
|
1801
|
+
/* @__PURE__ */ jsx16(Text15, { children: "[Y] approve [N] deny [Esc] later" }),
|
|
1802
|
+
/* @__PURE__ */ jsx16(Text15, { dimColor: true, children: APPROVAL_REPLY_PLACEHOLDER })
|
|
1558
1803
|
] });
|
|
1559
1804
|
}
|
|
1560
1805
|
|
|
1561
1806
|
// src/tui/modals/RunsPicker.tsx
|
|
1562
|
-
import { Box as
|
|
1563
|
-
import { useState as
|
|
1564
|
-
import { jsx as
|
|
1807
|
+
import { Box as Box15, Text as Text16, useInput as useInput6 } from "ink";
|
|
1808
|
+
import { useState as useState7 } from "react";
|
|
1809
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1565
1810
|
function RunsPicker(props) {
|
|
1566
1811
|
const maxRows = props.maxRows ?? 10;
|
|
1567
|
-
const [index, setIndex] =
|
|
1812
|
+
const [index, setIndex] = useState7(0);
|
|
1568
1813
|
const cap = Math.max(0, props.runs.length - 1);
|
|
1569
1814
|
useInput6(
|
|
1570
1815
|
(_input, key) => {
|
|
@@ -1588,23 +1833,23 @@ function RunsPicker(props) {
|
|
|
1588
1833
|
{ isActive: props.isFocused ?? true }
|
|
1589
1834
|
);
|
|
1590
1835
|
if (props.runs.length === 0) {
|
|
1591
|
-
return /* @__PURE__ */
|
|
1592
|
-
/* @__PURE__ */
|
|
1593
|
-
/* @__PURE__ */
|
|
1594
|
-
/* @__PURE__ */
|
|
1836
|
+
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1837
|
+
/* @__PURE__ */ jsx17(Text16, { bold: true, children: "recent runs" }),
|
|
1838
|
+
/* @__PURE__ */ jsx17(Text16, { dimColor: true, children: "(no runs in this session)" }),
|
|
1839
|
+
/* @__PURE__ */ jsx17(Text16, { dimColor: true, children: "esc to close" })
|
|
1595
1840
|
] });
|
|
1596
1841
|
}
|
|
1597
1842
|
const visible = props.runs.slice(0, maxRows);
|
|
1598
1843
|
const truncated = props.runs.length - visible.length;
|
|
1599
|
-
return /* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
visible.map((r, i) => /* @__PURE__ */
|
|
1602
|
-
truncated > 0 ? /* @__PURE__ */
|
|
1844
|
+
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", borderStyle: "round", paddingX: 1, children: [
|
|
1845
|
+
/* @__PURE__ */ jsx17(Text16, { bold: true, children: "recent runs" }),
|
|
1846
|
+
visible.map((r, i) => /* @__PURE__ */ jsx17(Text16, { inverse: i === index, children: formatRow(r) }, r.runId)),
|
|
1847
|
+
truncated > 0 ? /* @__PURE__ */ jsxs14(Text16, { dimColor: true, children: [
|
|
1603
1848
|
"\u2026 ",
|
|
1604
1849
|
truncated,
|
|
1605
1850
|
" more"
|
|
1606
1851
|
] }) : null,
|
|
1607
|
-
/* @__PURE__ */
|
|
1852
|
+
/* @__PURE__ */ jsx17(Text16, { dimColor: true, children: "\u2191\u2193 navigate \xB7 enter replay \xB7 esc cancel" })
|
|
1608
1853
|
] });
|
|
1609
1854
|
}
|
|
1610
1855
|
function formatRow(r) {
|
|
@@ -1643,27 +1888,6 @@ function findPrecedingPrompt(items, startAt) {
|
|
|
1643
1888
|
return null;
|
|
1644
1889
|
}
|
|
1645
1890
|
|
|
1646
|
-
// src/tui/theme/ThemeProvider.tsx
|
|
1647
|
-
import { createContext, useContext, useMemo, useState as useState6 } from "react";
|
|
1648
|
-
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1649
|
-
var ThemeContext = createContext({
|
|
1650
|
-
theme: DARK_THEME,
|
|
1651
|
-
setTheme: () => void 0
|
|
1652
|
-
});
|
|
1653
|
-
function ThemeProvider(props) {
|
|
1654
|
-
const [theme, setTheme] = useState6(
|
|
1655
|
-
props.initialTheme ?? DARK_THEME
|
|
1656
|
-
);
|
|
1657
|
-
const value = useMemo(
|
|
1658
|
-
() => ({ theme, setTheme }),
|
|
1659
|
-
[theme]
|
|
1660
|
-
);
|
|
1661
|
-
return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value, children: props.children });
|
|
1662
|
-
}
|
|
1663
|
-
function useTheme() {
|
|
1664
|
-
return useContext(ThemeContext);
|
|
1665
|
-
}
|
|
1666
|
-
|
|
1667
1891
|
// src/tui/theme/loadUserTheme.ts
|
|
1668
1892
|
function loadUserTheme(config) {
|
|
1669
1893
|
if (config === void 0 || config === null) {
|
|
@@ -1695,8 +1919,14 @@ function resolveByName(name) {
|
|
|
1695
1919
|
};
|
|
1696
1920
|
}
|
|
1697
1921
|
|
|
1922
|
+
// src/tui/session/agentic.ts
|
|
1923
|
+
var AGENTIC_TENANT_LOCK2 = "mintral";
|
|
1924
|
+
function isAgenticTenantMismatch(mode, tenant) {
|
|
1925
|
+
return mode === "agentic" && tenant !== AGENTIC_TENANT_LOCK2;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1698
1928
|
// src/tui/useSession.ts
|
|
1699
|
-
import { useCallback, useEffect as
|
|
1929
|
+
import { useCallback, useEffect as useEffect3, useReducer as useReducer2, useRef } from "react";
|
|
1700
1930
|
import { appendFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
1701
1931
|
import { dirname as dirname3 } from "path";
|
|
1702
1932
|
|
|
@@ -2178,7 +2408,7 @@ function useSession(opts) {
|
|
|
2178
2408
|
() => initialSession(opts.initial, opts.ctx)
|
|
2179
2409
|
);
|
|
2180
2410
|
const stateRef = useRef(state);
|
|
2181
|
-
|
|
2411
|
+
useEffect3(() => {
|
|
2182
2412
|
stateRef.current = state;
|
|
2183
2413
|
}, [state]);
|
|
2184
2414
|
const abortRef = useRef(null);
|
|
@@ -2771,14 +3001,13 @@ function lastUserPrompt(state) {
|
|
|
2771
3001
|
}
|
|
2772
3002
|
|
|
2773
3003
|
// src/tui/App.tsx
|
|
2774
|
-
import {
|
|
2775
|
-
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3004
|
+
import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2776
3005
|
function App(props) {
|
|
2777
3006
|
const themeResult = useMemo2(
|
|
2778
3007
|
() => loadUserTheme(props.config.theme),
|
|
2779
3008
|
[props.config.theme]
|
|
2780
3009
|
);
|
|
2781
|
-
return /* @__PURE__ */
|
|
3010
|
+
return /* @__PURE__ */ jsx18(ThemeProvider, { initialTheme: themeResult.theme, children: /* @__PURE__ */ jsx18(AppInner, { ...props, themeWarning: themeResult.warning }) });
|
|
2782
3011
|
}
|
|
2783
3012
|
function AppInner(props) {
|
|
2784
3013
|
const home = props.home ?? defaultMiotChatHome();
|
|
@@ -2798,8 +3027,8 @@ function AppInner(props) {
|
|
|
2798
3027
|
client: props.client
|
|
2799
3028
|
});
|
|
2800
3029
|
const { setTheme } = useTheme();
|
|
2801
|
-
const [extraItems, setExtraItems] =
|
|
2802
|
-
const [modal, setModalState] =
|
|
3030
|
+
const [extraItems, setExtraItems] = useState8([]);
|
|
3031
|
+
const [modal, setModalState] = useState8({ spec: null });
|
|
2803
3032
|
const registry = useMemo2(() => {
|
|
2804
3033
|
const reg = new SlashRegistry();
|
|
2805
3034
|
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);
|
|
@@ -2857,6 +3086,13 @@ function AppInner(props) {
|
|
|
2857
3086
|
appendSystem
|
|
2858
3087
|
]
|
|
2859
3088
|
);
|
|
3089
|
+
useInput7((input, key) => {
|
|
3090
|
+
if (!key.ctrl || modal.spec !== null) return;
|
|
3091
|
+
if (input === "r") void dispatchSlash("/resume");
|
|
3092
|
+
else if (input === "t") void dispatchSlash("/theme");
|
|
3093
|
+
else if (input === "g") void dispatchSlash("/help");
|
|
3094
|
+
else if (input === "q") void dispatchSlash("/exit");
|
|
3095
|
+
});
|
|
2860
3096
|
const handleSubmit = useCallback2(
|
|
2861
3097
|
(text) => {
|
|
2862
3098
|
if (text.trim().startsWith("/")) {
|
|
@@ -2877,16 +3113,21 @@ function AppInner(props) {
|
|
|
2877
3113
|
);
|
|
2878
3114
|
const modalSpec = modal.spec;
|
|
2879
3115
|
const editorActive = modalSpec === null;
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
3116
|
+
const version = useMemo2(() => packageVersion(), []);
|
|
3117
|
+
const showWelcome = allItems.length === 0 && modalSpec === null;
|
|
3118
|
+
const meta = session.state.meta;
|
|
3119
|
+
const agenticWarn = isAgenticTenantMismatch(meta.mode, meta.tenantId);
|
|
3120
|
+
return /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", children: [
|
|
3121
|
+
props.themeWarning ? /* @__PURE__ */ jsx18(Box16, { paddingX: 1, children: /* @__PURE__ */ jsx18(SystemNote, { text: `theme: ${props.themeWarning}` }) }) : null,
|
|
3122
|
+
/* @__PURE__ */ jsx18(TopLine, { meta, streaming: isStreaming(session.state) }),
|
|
3123
|
+
showWelcome ? /* @__PURE__ */ jsx18(WelcomeCard, { version }) : /* @__PURE__ */ jsx18(
|
|
2883
3124
|
Transcript,
|
|
2884
3125
|
{
|
|
2885
3126
|
items: allItems,
|
|
2886
3127
|
isStreaming: isStreaming(session.state)
|
|
2887
3128
|
}
|
|
2888
3129
|
),
|
|
2889
|
-
modalSpec?.kind === "context" ? /* @__PURE__ */
|
|
3130
|
+
modalSpec?.kind === "context" ? /* @__PURE__ */ jsx18(
|
|
2890
3131
|
ContextModal,
|
|
2891
3132
|
{
|
|
2892
3133
|
session: session.state,
|
|
@@ -2894,7 +3135,7 @@ function AppInner(props) {
|
|
|
2894
3135
|
onClose: closeModal
|
|
2895
3136
|
}
|
|
2896
3137
|
) : null,
|
|
2897
|
-
modalSpec?.kind === "resume" ? /* @__PURE__ */
|
|
3138
|
+
modalSpec?.kind === "resume" ? /* @__PURE__ */ jsx18(
|
|
2898
3139
|
ResumePicker,
|
|
2899
3140
|
{
|
|
2900
3141
|
summaries: listSessions(home),
|
|
@@ -2907,7 +3148,7 @@ function AppInner(props) {
|
|
|
2907
3148
|
onCancel: closeModal
|
|
2908
3149
|
}
|
|
2909
3150
|
) : null,
|
|
2910
|
-
modalSpec?.kind === "theme" ? /* @__PURE__ */
|
|
3151
|
+
modalSpec?.kind === "theme" ? /* @__PURE__ */ jsx18(
|
|
2911
3152
|
ThemePicker,
|
|
2912
3153
|
{
|
|
2913
3154
|
initialName: typeof modalSpec.payload?.name === "string" ? modalSpec.payload.name : void 0,
|
|
@@ -2922,7 +3163,7 @@ function AppInner(props) {
|
|
|
2922
3163
|
onCancel: closeModal
|
|
2923
3164
|
}
|
|
2924
3165
|
) : null,
|
|
2925
|
-
modalSpec?.kind === "approval" && isApprovalsUiEnabled() && session.state.pendingApprovals.length > 0 ? /* @__PURE__ */
|
|
3166
|
+
modalSpec?.kind === "approval" && isApprovalsUiEnabled() && session.state.pendingApprovals.length > 0 ? /* @__PURE__ */ jsx18(
|
|
2926
3167
|
ApprovalModal,
|
|
2927
3168
|
{
|
|
2928
3169
|
approval: session.state.pendingApprovals[0],
|
|
@@ -2932,7 +3173,7 @@ function AppInner(props) {
|
|
|
2932
3173
|
}
|
|
2933
3174
|
}
|
|
2934
3175
|
) : null,
|
|
2935
|
-
modalSpec?.kind === "runs" ? /* @__PURE__ */
|
|
3176
|
+
modalSpec?.kind === "runs" ? /* @__PURE__ */ jsx18(
|
|
2936
3177
|
RunsPickerWrapped,
|
|
2937
3178
|
{
|
|
2938
3179
|
state: session.state,
|
|
@@ -2943,27 +3184,28 @@ function AppInner(props) {
|
|
|
2943
3184
|
onCancel: closeModal
|
|
2944
3185
|
}
|
|
2945
3186
|
) : null,
|
|
2946
|
-
/* @__PURE__ */
|
|
2947
|
-
|
|
3187
|
+
/* @__PURE__ */ jsx18(TipLine, { tipIndex: turnCount(session.state) }),
|
|
3188
|
+
/* @__PURE__ */ jsx18(InputFrame, { label: `miot \xB7 ${meta.mode}`, labelWarn: agenticWarn, children: /* @__PURE__ */ jsx18(Editor, { onSubmit: handleSubmit, isFocused: editorActive }) }),
|
|
3189
|
+
/* @__PURE__ */ jsx18(
|
|
3190
|
+
FooterLine,
|
|
2948
3191
|
{
|
|
2949
|
-
meta: session.state.meta,
|
|
2950
|
-
streaming: isStreaming(session.state),
|
|
2951
|
-
pendingApprovals: pendingApprovalCount(session.state),
|
|
2952
3192
|
turns: turnCount(session.state),
|
|
2953
3193
|
approxTokens: approxTokenCount(session.state),
|
|
2954
3194
|
contextPercent: contextPercent(session.state),
|
|
2955
|
-
usageTotals: session.state.usageTotals
|
|
3195
|
+
usageTotals: session.state.usageTotals,
|
|
3196
|
+
baseUrl: meta.baseUrl,
|
|
3197
|
+
profileName: meta.profileName,
|
|
3198
|
+
pendingApprovals: pendingApprovalCount(session.state)
|
|
2956
3199
|
}
|
|
2957
|
-
)
|
|
2958
|
-
/* @__PURE__ */ jsx14(Editor, { onSubmit: handleSubmit, isFocused: editorActive })
|
|
3200
|
+
)
|
|
2959
3201
|
] });
|
|
2960
3202
|
}
|
|
2961
3203
|
function RunsPickerWrapped(props) {
|
|
2962
3204
|
const runs = summarizeRuns(props.state);
|
|
2963
|
-
return /* @__PURE__ */
|
|
3205
|
+
return /* @__PURE__ */ jsx18(RunsPicker, { runs, onSelect: props.onSelect, onCancel: props.onCancel });
|
|
2964
3206
|
}
|
|
2965
3207
|
function SystemNote(props) {
|
|
2966
|
-
return /* @__PURE__ */
|
|
3208
|
+
return /* @__PURE__ */ jsx18(Box16, { children: /* @__PURE__ */ jsx18(Text17, { dimColor: true, children: props.text }) });
|
|
2967
3209
|
}
|
|
2968
3210
|
|
|
2969
3211
|
// src/tui/runTui.ts
|