openxgen 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1108,288 +1108,322 @@ var init_ontology = __esm({
1108
1108
  }
1109
1109
  });
1110
1110
 
1111
- // src/dashboard/InkDashboard.tsx
1112
- var InkDashboard_exports = {};
1113
- __export(InkDashboard_exports, {
1114
- startInkDashboard: () => startInkDashboard
1111
+ // src/dashboard/raw-tui.ts
1112
+ var raw_tui_exports = {};
1113
+ __export(raw_tui_exports, {
1114
+ startRawTui: () => startRawTui
1115
1115
  });
1116
- import { useState, useEffect } from "react";
1117
- import { render, Box, Text, useInput, useApp, useStdout } from "ink";
1118
- import TextInput from "ink-text-input";
1119
- import { jsx, jsxs } from "react/jsx-runtime";
1120
- function Header({ tab, serverDisplay, model }) {
1121
- const tabStr = TABS.map((t) => {
1122
- const active = tab === t.key;
1123
- return `[${t.shortcut}]${active ? "\u25B8" : " "}${t.label}`;
1124
- }).join(" ");
1125
- return /* @__PURE__ */ jsxs(Box, { paddingX: 1, children: [
1126
- /* @__PURE__ */ jsx(Text, { bold: true, children: "OPEN XGEN" }),
1127
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1128
- " ",
1129
- model,
1130
- " ",
1131
- serverDisplay,
1132
- " \u2502 ",
1133
- tabStr
1134
- ] })
1135
- ] });
1136
- }
1137
- function ListPanel({ items, selected, onSelect }) {
1138
- const { stdout } = useStdout();
1139
- const height = (stdout?.rows ?? 24) - 8;
1140
- const visibleCount = Math.max(1, height);
1141
- const start = Math.max(0, Math.min(selected - Math.floor(visibleCount / 2), items.length - visibleCount));
1142
- const visible = items.slice(start, start + visibleCount);
1143
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "50%", borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
1144
- visible.map((item, i) => {
1145
- const realIndex = start + i;
1146
- const isSelected = realIndex === selected;
1147
- return /* @__PURE__ */ jsxs(Text, { inverse: isSelected, children: [
1148
- isSelected ? "\u25B8 " : " ",
1149
- item.label,
1150
- item.dimLabel ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1151
- " ",
1152
- item.dimLabel
1153
- ] }) : null
1154
- ] }, `item-${realIndex}`);
1155
- }),
1156
- items.length === 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (\uC5C6\uC74C)" })
1157
- ] });
1158
- }
1159
- function DetailPanel({ lines }) {
1160
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", width: "50%", borderStyle: "single", borderColor: "gray", paddingX: 1, children: lines.map((line, i) => /* @__PURE__ */ jsx(Text, { children: line }, `line-${i}`)) });
1161
- }
1162
- function StatusBar({ message }) {
1163
- return /* @__PURE__ */ jsx(Box, { paddingX: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: message }) });
1164
- }
1165
- function InputBar({ value, onChange, onSubmit, placeholder }) {
1166
- return /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
1167
- /* @__PURE__ */ jsx(Text, { children: "\u276F " }),
1168
- /* @__PURE__ */ jsx(
1169
- TextInput,
1170
- {
1171
- value,
1172
- onChange,
1173
- onSubmit,
1174
- placeholder: placeholder ?? "\uC785\uB825..."
1175
- }
1176
- )
1177
- ] });
1178
- }
1179
- function Dashboard() {
1180
- const { exit } = useApp();
1116
+ async function startRawTui() {
1181
1117
  const provider = getDefaultProvider();
1182
1118
  const server = getServer();
1183
1119
  const auth = getAuth();
1184
1120
  const serverDisplay = auth && server ? `${auth.username}@${server.replace("https://", "").replace("http://", "")}` : "\uBBF8\uC5F0\uACB0";
1185
- const [tab, setTab] = useState("workflows");
1186
- const [selected, setSelected] = useState(0);
1187
- const [workflows, setWorkflows] = useState([]);
1188
- const [collections, setCollections] = useState([]);
1189
- const [nodes, setNodes] = useState([]);
1190
- const [prompts, setPrompts] = useState([]);
1191
- const [tools2, setTools] = useState([]);
1192
- const [detail, setDetail] = useState(["\u2190 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD558\uC138\uC694"]);
1193
- const [inputValue, setInputValue] = useState("");
1194
- const [inputMode, setInputMode] = useState(false);
1195
- const [runTarget, setRunTarget] = useState(null);
1196
- const [loading, setLoading] = useState(true);
1197
- const [statusMsg, setStatusMsg] = useState("\uB85C\uB529...");
1198
- useEffect(() => {
1199
- loadAll();
1200
- }, []);
1201
- async function loadAll() {
1202
- setLoading(true);
1203
- setStatusMsg("\uB85C\uB529...");
1121
+ let tab = "workflows";
1122
+ let selected = 0;
1123
+ let inputMode = false;
1124
+ let inputBuffer = "";
1125
+ let runTarget = null;
1126
+ let workflows = [];
1127
+ let collections = [];
1128
+ let nodes = [];
1129
+ let prompts = [];
1130
+ let tools2 = [];
1131
+ let detail = ["\u2190 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD558\uC138\uC694"];
1132
+ let statusMsg = "\uB85C\uB529...";
1133
+ async function loadData() {
1134
+ statusMsg = "\uB85C\uB529...";
1135
+ render();
1136
+ if (!server || !auth) {
1137
+ statusMsg = "\uC11C\uBC84 \uBBF8\uC5F0\uACB0";
1138
+ render();
1139
+ return;
1140
+ }
1204
1141
  try {
1205
- if (server && auth) {
1206
- const [wfMod, docMod, extraMod] = await Promise.all([
1207
- Promise.resolve().then(() => (init_workflow(), workflow_exports)),
1208
- Promise.resolve().then(() => (init_document(), document_exports)),
1209
- Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports))
1210
- ]);
1211
- const [wfs, cols, nodeList, promptList, toolList] = await Promise.allSettled([
1212
- wfMod.getWorkflowListDetail(),
1213
- docMod.listCollections(),
1214
- extraMod.listNodes(),
1215
- extraMod.listPrompts(),
1216
- extraMod.listToolStore()
1217
- ]);
1218
- if (wfs.status === "fulfilled") {
1219
- setWorkflows(wfs.value.map((w) => ({
1220
- name: w.workflow_name,
1221
- id: w.workflow_id ?? w.id ?? "",
1222
- deployed: !!w.is_deployed
1223
- })));
1224
- }
1225
- if (cols.status === "fulfilled") {
1226
- setCollections(cols.value.map((c) => ({
1227
- name: c.collection_make_name,
1228
- docs: c.total_documents,
1229
- chunks: c.total_chunks
1230
- })));
1231
- }
1232
- if (nodeList.status === "fulfilled") setNodes(nodeList.value);
1233
- if (promptList.status === "fulfilled") setPrompts(promptList.value);
1234
- if (toolList.status === "fulfilled") setTools(toolList.value);
1235
- }
1142
+ const [wfMod, docMod, extraMod] = await Promise.all([
1143
+ Promise.resolve().then(() => (init_workflow(), workflow_exports)),
1144
+ Promise.resolve().then(() => (init_document(), document_exports)),
1145
+ Promise.resolve().then(() => (init_xgen_extra(), xgen_extra_exports))
1146
+ ]);
1147
+ const [wfR, colR, nodeR, promptR, toolR] = await Promise.allSettled([
1148
+ wfMod.getWorkflowListDetail(),
1149
+ docMod.listCollections(),
1150
+ extraMod.listNodes(),
1151
+ extraMod.listPrompts(),
1152
+ extraMod.listToolStore()
1153
+ ]);
1154
+ if (wfR.status === "fulfilled") workflows = wfR.value.map((w) => ({ name: w.workflow_name, id: w.workflow_id ?? w.id ?? "", deployed: !!w.is_deployed }));
1155
+ if (colR.status === "fulfilled") collections = colR.value.map((c) => ({ name: c.collection_make_name, docs: c.total_documents, chunks: c.total_chunks }));
1156
+ if (nodeR.status === "fulfilled") nodes = nodeR.value.map((n) => ({ name: n.nodeName ?? n.name ?? "?", desc: (n.description ?? "").slice(0, 40) }));
1157
+ if (promptR.status === "fulfilled") prompts = promptR.value.map((p) => ({ name: p.name ?? p.title ?? "?", type: p.prompt_type ?? "" }));
1158
+ if (toolR.status === "fulfilled") tools2 = toolR.value.map((t) => ({ name: t.name ?? t.tool_name ?? "?", desc: (t.description ?? "").slice(0, 40) }));
1236
1159
  } catch {
1237
1160
  }
1238
- setLoading(false);
1239
- setStatusMsg("\u2191\u2193:\uC774\uB3D9 Enter:\uC120\uD0DD 1-5:\uD0ED i:\uC785\uB825 r:\uC0C8\uB85C\uACE0\uCE68 q:\uC885\uB8CC");
1161
+ statusMsg = "\u2191\u2193:\uC774\uB3D9 Enter:\uC120\uD0DD/\uC2E4\uD589 1-5:\uD0ED i:\uC785\uB825 r:\uC0C8\uB85C\uACE0\uCE68 q:\uC885\uB8CC";
1162
+ render();
1240
1163
  }
1241
- function getListItems() {
1164
+ function getItems() {
1242
1165
  switch (tab) {
1243
1166
  case "workflows":
1244
- return workflows.map((w) => ({ label: `${w.deployed ? "\u25CF" : "\u25CB"} ${w.name}`, dimLabel: "" }));
1167
+ return workflows.map((w) => ({ label: `${w.deployed ? "\u25CF" : "\u25CB"} ${w.name}`, sub: w.id.slice(0, 20) }));
1245
1168
  case "collections":
1246
- return collections.map((c) => ({ label: c.name, dimLabel: `${c.docs}\uBB38\uC11C ${c.chunks}\uCCAD\uD06C` }));
1169
+ return collections.map((c) => ({ label: c.name, sub: `${c.docs}\uBB38\uC11C ${c.chunks}\uCCAD\uD06C` }));
1247
1170
  case "nodes":
1248
- return nodes.map((n) => ({ label: n.nodeName ?? n.name ?? "?", dimLabel: (n.description ?? "").slice(0, 30) }));
1171
+ return nodes.map((n) => ({ label: n.name, sub: n.desc }));
1249
1172
  case "prompts":
1250
- return prompts.map((p) => ({ label: p.name ?? p.title ?? "?", dimLabel: `[${p.prompt_type ?? ""}]` }));
1173
+ return prompts.map((p) => ({ label: p.name, sub: `[${p.type}]` }));
1251
1174
  case "tools":
1252
- return tools2.map((t) => ({ label: t.name ?? t.tool_name ?? "?", dimLabel: (t.description ?? "").slice(0, 30) }));
1253
- default:
1254
- return [];
1175
+ return tools2.map((t) => ({ label: t.name, sub: t.desc }));
1255
1176
  }
1256
1177
  }
1257
- function showDetail() {
1258
- const items = getListItems();
1178
+ function updateDetail() {
1179
+ const items = getItems();
1259
1180
  if (selected < 0 || selected >= items.length) return;
1260
- if (tab === "workflows") {
1181
+ if (tab === "workflows" && workflows[selected]) {
1261
1182
  const w = workflows[selected];
1262
- if (w) setDetail([w.name, "", `ID ${w.id}`, `\uBC30\uD3EC ${w.deployed ? "Yes" : "No"}`, "", "Enter \u2192 \uC2E4\uD589"]);
1263
- } else if (tab === "collections") {
1183
+ detail = [bold(w.name), "", `ID ${w.id}`, `\uBC30\uD3EC ${w.deployed ? "Yes" : "No"}`, "", "Enter \u2192 \uC2E4\uD589"];
1184
+ } else if (tab === "collections" && collections[selected]) {
1264
1185
  const c = collections[selected];
1265
- if (c) setDetail([c.name, "", `\uBB38\uC11C ${c.docs}\uAC1C`, `\uCCAD\uD06C ${c.chunks}\uAC1C`]);
1266
- } else if (tab === "nodes") {
1186
+ detail = [bold(c.name), "", `\uBB38\uC11C ${c.docs}\uAC1C`, `\uCCAD\uD06C ${c.chunks}\uAC1C`];
1187
+ } else if (tab === "nodes" && nodes[selected]) {
1267
1188
  const n = nodes[selected];
1268
- if (n) setDetail([n.nodeName ?? n.name ?? "?", "", n.description ?? "", "", `ID: ${n.node_id ?? n.id ?? "?"}`]);
1269
- } else if (tab === "prompts") {
1189
+ detail = [bold(n.name), "", n.desc];
1190
+ } else if (tab === "prompts" && prompts[selected]) {
1270
1191
  const p = prompts[selected];
1271
- if (p) setDetail([p.name ?? "?", `[${p.prompt_type ?? ""}]`, "", (p.content ?? "").slice(0, 200)]);
1272
- } else if (tab === "tools") {
1192
+ detail = [bold(p.name), `[${p.type}]`];
1193
+ } else if (tab === "tools" && tools2[selected]) {
1273
1194
  const t = tools2[selected];
1274
- if (t) setDetail([t.name ?? t.tool_name ?? "?", "", t.description ?? ""]);
1275
- }
1276
- }
1277
- useEffect(() => {
1278
- showDetail();
1279
- }, [selected, tab]);
1280
- function switchTab(t) {
1281
- setTab(t);
1282
- setSelected(0);
1283
- setInputMode(false);
1284
- setRunTarget(null);
1285
- }
1286
- async function handleSubmit(value) {
1287
- if (!value.trim()) {
1288
- setInputMode(false);
1289
- setRunTarget(null);
1290
- return;
1291
- }
1292
- if (runTarget) {
1293
- setDetail([`\uC2E4\uD589 \uC911: ${runTarget.name}`, `\uC785\uB825: ${value}`, "", "..."]);
1294
- setInputValue("");
1295
- setInputMode(false);
1296
- try {
1297
- const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
1298
- const { randomUUID: randomUUID4 } = await import("crypto");
1299
- const result = await executeWorkflow2({
1300
- workflow_id: runTarget.id,
1301
- workflow_name: runTarget.name,
1302
- input_data: value,
1303
- interaction_id: `tui_${randomUUID4().slice(0, 8)}`,
1304
- user_id: auth?.userId ? parseInt(auth.userId) : 1
1305
- });
1306
- const content = result.content ?? result.message ?? JSON.stringify(result).slice(0, 500);
1307
- setDetail([`${runTarget.name}`, "", `\uC785\uB825: ${value}`, "", `\uACB0\uACFC:`, String(content)]);
1308
- } catch (err) {
1309
- setDetail([`\uC2E4\uD589 \uC2E4\uD328: ${err.message}`]);
1195
+ detail = [bold(t.name), "", t.desc];
1196
+ }
1197
+ }
1198
+ function render() {
1199
+ const cols = process.stdout.columns || 120;
1200
+ const rows = process.stdout.rows || 30;
1201
+ const leftW = Math.floor(cols / 2);
1202
+ const rightW = cols - leftW;
1203
+ const listH = rows - 5;
1204
+ clear();
1205
+ moveTo(1, 1);
1206
+ const tabStr = TABS.map((t) => {
1207
+ const active = tab === t.key;
1208
+ return `[${t.num}]${active ? bold("\u25B8" + t.label) : dim(t.label)}`;
1209
+ }).join(" ");
1210
+ process.stdout.write(` ${bold("OPEN XGEN")} ${dim(provider?.model ?? "")} ${serverDisplay} \u2502 ${tabStr}`);
1211
+ moveTo(2, 1);
1212
+ process.stdout.write(dim("\u2500".repeat(cols)));
1213
+ const items = getItems();
1214
+ const visibleCount = listH;
1215
+ const scrollStart = Math.max(0, Math.min(selected - Math.floor(visibleCount / 2), items.length - visibleCount));
1216
+ for (let i = 0; i < visibleCount; i++) {
1217
+ moveTo(3 + i, 1);
1218
+ const idx = scrollStart + i;
1219
+ if (idx < items.length) {
1220
+ const item = items[idx];
1221
+ const prefix = idx === selected ? "\u25B8 " : " ";
1222
+ const line = `${prefix}${String(idx + 1).padStart(2)}. ${item.label}`;
1223
+ const trimmed = line.slice(0, leftW - 2);
1224
+ process.stdout.write(idx === selected ? inverse(trimmed.padEnd(leftW - 1)) : trimmed);
1225
+ } else {
1226
+ process.stdout.write(" ".repeat(leftW - 1));
1310
1227
  }
1311
- setRunTarget(null);
1228
+ process.stdout.write(dim("\u2502"));
1229
+ if (i < detail.length) {
1230
+ const dline = detail[i].slice(0, rightW - 2);
1231
+ process.stdout.write(` ${dline}`);
1232
+ }
1233
+ }
1234
+ moveTo(rows - 2, 1);
1235
+ process.stdout.write(dim("\u2500".repeat(cols)));
1236
+ moveTo(rows - 1, 1);
1237
+ if (inputMode) {
1238
+ const prompt2 = runTarget ? `${runTarget.name} \u276F ` : "\u276F ";
1239
+ process.stdout.write(` ${prompt2}${inputBuffer}`);
1240
+ showCursor();
1312
1241
  } else {
1313
- setInputValue("");
1314
- setInputMode(false);
1242
+ process.stdout.write(dim(" \u276F i\uB97C \uB20C\uB7EC \uC785\uB825 \xB7 Enter\uB85C \uC2E4\uD589"));
1243
+ hideCursor();
1244
+ }
1245
+ moveTo(rows, 1);
1246
+ process.stdout.write(dim(` ${statusMsg}`.slice(0, cols)));
1247
+ }
1248
+ async function executeWorkflowAction(wf, input) {
1249
+ detail = [`\uC2E4\uD589 \uC911: ${wf.name}`, `\uC785\uB825: ${input}`, "", "..."];
1250
+ render();
1251
+ try {
1252
+ const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
1253
+ const { randomUUID: randomUUID4 } = await import("crypto");
1254
+ const r = await executeWorkflow2({
1255
+ workflow_id: wf.id,
1256
+ workflow_name: wf.name,
1257
+ input_data: input,
1258
+ interaction_id: `tui_${randomUUID4().slice(0, 8)}`,
1259
+ user_id: auth?.userId ? parseInt(auth.userId) : 1
1260
+ });
1261
+ const content = r.content ?? r.message ?? JSON.stringify(r).slice(0, 500);
1262
+ detail = [bold(wf.name), "", `\uC785\uB825: ${input}`, "", "\uACB0\uACFC:", ...String(content).split("\n").slice(0, 15)];
1263
+ } catch (err) {
1264
+ detail = [`\uC2E4\uD589 \uC2E4\uD328: ${err.message}`];
1315
1265
  }
1266
+ render();
1316
1267
  }
1317
- useInput((input, key) => {
1268
+ function handleKey(data) {
1269
+ const s = data.toString();
1318
1270
  if (inputMode) {
1319
- if (key.escape) {
1320
- setInputMode(false);
1321
- setRunTarget(null);
1271
+ if (s === "\x1B" || s === "\x1B\x1B") {
1272
+ inputMode = false;
1273
+ inputBuffer = "";
1274
+ runTarget = null;
1275
+ render();
1276
+ return;
1322
1277
  }
1278
+ if (s === "\r" || s === "\n") {
1279
+ const val = inputBuffer.trim();
1280
+ inputMode = false;
1281
+ inputBuffer = "";
1282
+ if (val && runTarget) {
1283
+ executeWorkflowAction(runTarget, val);
1284
+ runTarget = null;
1285
+ }
1286
+ render();
1287
+ return;
1288
+ }
1289
+ if (s === "\x7F" || s === "\b") {
1290
+ inputBuffer = inputBuffer.slice(0, -1);
1291
+ render();
1292
+ return;
1293
+ }
1294
+ if (s.length > 0 && s.charCodeAt(0) >= 32) {
1295
+ inputBuffer += s;
1296
+ render();
1297
+ return;
1298
+ }
1299
+ return;
1300
+ }
1301
+ if (s === "q" || s === "") {
1302
+ cleanup();
1303
+ process.exit(0);
1304
+ }
1305
+ if (s === "r") {
1306
+ loadData();
1307
+ return;
1308
+ }
1309
+ if (s === "i") {
1310
+ inputMode = true;
1311
+ render();
1323
1312
  return;
1324
1313
  }
1325
- if (input === "q" || key.ctrl && input === "c") {
1326
- exit();
1314
+ const tabNum = parseInt(s);
1315
+ if (tabNum >= 1 && tabNum <= 5) {
1316
+ tab = TABS[tabNum - 1].key;
1317
+ selected = 0;
1318
+ updateDetail();
1319
+ render();
1327
1320
  return;
1328
1321
  }
1329
- if (input === "r") {
1330
- loadAll();
1322
+ if (s === " ") {
1323
+ const idx = TABS.findIndex((t) => t.key === tab);
1324
+ tab = TABS[(idx + 1) % TABS.length].key;
1325
+ selected = 0;
1326
+ updateDetail();
1327
+ render();
1331
1328
  return;
1332
1329
  }
1333
- if (input === "i") {
1334
- setInputMode(true);
1330
+ if (s === "\x1B[A") {
1331
+ const items = getItems();
1332
+ selected = Math.max(0, selected - 1);
1333
+ updateDetail();
1334
+ render();
1335
1335
  return;
1336
1336
  }
1337
- if (input === "1") switchTab("workflows");
1338
- else if (input === "2") switchTab("collections");
1339
- else if (input === "3") switchTab("nodes");
1340
- else if (input === "4") switchTab("prompts");
1341
- else if (input === "5") switchTab("tools");
1342
- const items = getListItems();
1343
- if (key.upArrow) setSelected(Math.max(0, selected - 1));
1344
- else if (key.downArrow) setSelected(Math.min(items.length - 1, selected + 1));
1345
- else if (key.tab) switchTab(TABS[(TABS.findIndex((t) => t.key === tab) + 1) % TABS.length].key);
1346
- if (key.return && items.length > 0) {
1337
+ if (s === "\x1B[B") {
1338
+ const items = getItems();
1339
+ selected = Math.min(items.length - 1, selected + 1);
1340
+ updateDetail();
1341
+ render();
1342
+ return;
1343
+ }
1344
+ if (s === "\r" || s === "\n") {
1347
1345
  if (tab === "workflows" && workflows[selected]) {
1348
- setRunTarget(workflows[selected]);
1349
- setInputMode(true);
1350
- setStatusMsg(`${workflows[selected].name} \u2014 \uC785\uB825 \uD6C4 Enter\uB85C \uC2E4\uD589, Esc \uCDE8\uC18C`);
1346
+ runTarget = workflows[selected];
1347
+ inputMode = true;
1348
+ statusMsg = `${runTarget.name} \u2014 \uC785\uB825 \uD6C4 Enter \uC2E4\uD589, Esc \uCDE8\uC18C`;
1349
+ render();
1350
+ } else if (tab === "collections" && collections[selected]) {
1351
+ const c = collections[selected];
1352
+ detail = [`${c.name} \uBB38\uC11C \uB85C\uB529...`];
1353
+ render();
1354
+ Promise.resolve().then(() => (init_document(), document_exports)).then(async (m) => {
1355
+ try {
1356
+ const docs = await m.listDocuments(String(collections[selected].id ?? ""));
1357
+ if (!docs.length) {
1358
+ detail = [bold(c.name), "", "\uBB38\uC11C \uC5C6\uC74C"];
1359
+ } else {
1360
+ detail = [bold(c.name) + ` \u2014 ${docs.length}\uAC1C \uBB38\uC11C`, "", ...docs.map(
1361
+ (d, i) => ` ${i + 1}. ${d.name || d.file_name || "\uC774\uB984\uC5C6\uC74C"}`
1362
+ ).slice(0, 15)];
1363
+ }
1364
+ } catch (err) {
1365
+ detail = [`\uBB38\uC11C \uB85C\uB4DC \uC2E4\uD328: ${err.message}`];
1366
+ }
1367
+ render();
1368
+ });
1351
1369
  }
1370
+ return;
1352
1371
  }
1353
- });
1354
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
1355
- /* @__PURE__ */ jsx(Header, { tab, serverDisplay, model: provider?.model ?? "" }),
1356
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexGrow: 1, children: [
1357
- /* @__PURE__ */ jsx(ListPanel, { items: getListItems(), selected }),
1358
- /* @__PURE__ */ jsx(DetailPanel, { lines: detail })
1359
- ] }),
1360
- inputMode ? /* @__PURE__ */ jsx(
1361
- InputBar,
1362
- {
1363
- value: inputValue,
1364
- onChange: setInputValue,
1365
- onSubmit: handleSubmit,
1366
- placeholder: runTarget ? `${runTarget.name}\uC5D0 \uC785\uB825...` : "\uC785\uB825..."
1367
- }
1368
- ) : /* @__PURE__ */ jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u276F i\uB97C \uB20C\uB7EC \uC785\uB825 \xB7 Enter\uB85C \uC2E4\uD589" }) }),
1369
- /* @__PURE__ */ jsx(StatusBar, { message: loading ? "\uB85C\uB529..." : statusMsg })
1370
- ] });
1371
- }
1372
- async function startInkDashboard() {
1373
- if (process.stdin.isPaused?.()) {
1374
- process.stdin.resume();
1375
1372
  }
1376
- const { waitUntilExit } = render(/* @__PURE__ */ jsx(Dashboard, {}), {
1377
- exitOnCtrlC: true
1373
+ function cleanup() {
1374
+ showCursor();
1375
+ clear();
1376
+ if (process.stdin.isTTY && process.stdin.isRaw) {
1377
+ process.stdin.setRawMode(false);
1378
+ }
1379
+ process.stdin.removeAllListeners("data");
1380
+ process.stdin.pause();
1381
+ }
1382
+ if (!process.stdin.isTTY) {
1383
+ console.error("\uB300\uC2DC\uBCF4\uB4DC\uB294 \uD130\uBBF8\uB110(TTY)\uC5D0\uC11C\uB9CC \uC2E4\uD589 \uAC00\uB2A5\uD569\uB2C8\uB2E4.");
1384
+ return;
1385
+ }
1386
+ process.stdin.setRawMode(true);
1387
+ process.stdin.resume();
1388
+ process.stdin.setEncoding("utf8");
1389
+ hideCursor();
1390
+ process.stdin.on("data", (data) => {
1391
+ try {
1392
+ handleKey(data);
1393
+ } catch {
1394
+ }
1395
+ });
1396
+ process.on("SIGINT", () => {
1397
+ cleanup();
1398
+ process.exit(0);
1399
+ });
1400
+ process.on("exit", () => {
1401
+ showCursor();
1402
+ });
1403
+ await loadData();
1404
+ await new Promise(() => {
1378
1405
  });
1379
- await waitUntilExit();
1380
1406
  }
1381
- var TABS;
1382
- var init_InkDashboard = __esm({
1383
- "src/dashboard/InkDashboard.tsx"() {
1407
+ var TABS, CSI, clear, moveTo, dim, bold, inverse, hideCursor, showCursor;
1408
+ var init_raw_tui = __esm({
1409
+ "src/dashboard/raw-tui.ts"() {
1384
1410
  "use strict";
1385
1411
  init_store();
1386
1412
  TABS = [
1387
- { key: "workflows", label: "\uC6CC\uD06C\uD50C\uB85C\uC6B0", shortcut: "1" },
1388
- { key: "collections", label: "\uCEEC\uB809\uC158", shortcut: "2" },
1389
- { key: "nodes", label: "\uB178\uB4DC", shortcut: "3" },
1390
- { key: "prompts", label: "\uD504\uB86C\uD504\uD2B8", shortcut: "4" },
1391
- { key: "tools", label: "\uB3C4\uAD6C", shortcut: "5" }
1413
+ { key: "workflows", label: "\uC6CC\uD06C\uD50C\uB85C\uC6B0", num: "1" },
1414
+ { key: "collections", label: "\uCEEC\uB809\uC158", num: "2" },
1415
+ { key: "nodes", label: "\uB178\uB4DC", num: "3" },
1416
+ { key: "prompts", label: "\uD504\uB86C\uD504\uD2B8", num: "4" },
1417
+ { key: "tools", label: "\uB3C4\uAD6C", num: "5" }
1392
1418
  ];
1419
+ CSI = "\x1B[";
1420
+ clear = () => process.stdout.write(`${CSI}2J${CSI}H`);
1421
+ moveTo = (r, c) => process.stdout.write(`${CSI}${r};${c}H`);
1422
+ dim = (s) => `${CSI}2m${s}${CSI}0m`;
1423
+ bold = (s) => `${CSI}1m${s}${CSI}0m`;
1424
+ inverse = (s) => `${CSI}7m${s}${CSI}0m`;
1425
+ hideCursor = () => process.stdout.write(`${CSI}?25l`);
1426
+ showCursor = () => process.stdout.write(`${CSI}?25h`);
1393
1427
  }
1394
1428
  });
1395
1429
 
@@ -3597,7 +3631,7 @@ ${result.answer}
3597
3631
  }
3598
3632
 
3599
3633
  // src/index.ts
3600
- var VERSION = "2.2.0";
3634
+ var VERSION = "2.3.0";
3601
3635
  var LOGO = chalk15.cyan(`
3602
3636
  \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588
3603
3637
  \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588
@@ -3645,8 +3679,8 @@ registerAgentCommand(program);
3645
3679
  registerDocCommand(program);
3646
3680
  registerOntologyCommand(program);
3647
3681
  program.command("dash").alias("dashboard").description("XGEN TUI \uB300\uC2DC\uBCF4\uB4DC").action(async () => {
3648
- const { startInkDashboard: startInkDashboard2 } = await Promise.resolve().then(() => (init_InkDashboard(), InkDashboard_exports));
3649
- await startInkDashboard2();
3682
+ const { startRawTui: startRawTui2 } = await Promise.resolve().then(() => (init_raw_tui(), raw_tui_exports));
3683
+ await startRawTui2();
3650
3684
  });
3651
3685
  if (process.argv.length <= 2) {
3652
3686
  agentRepl().catch((err) => {