openxgen 1.6.1 → 1.8.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
@@ -1063,104 +1063,71 @@ __export(tui_exports, {
1063
1063
  });
1064
1064
  import blessed from "blessed";
1065
1065
  async function startTui() {
1066
- const screen = blessed.screen({
1067
- smartCSR: true,
1068
- title: "OPEN XGEN",
1069
- fullUnicode: true
1070
- });
1066
+ const screen = blessed.screen({ smartCSR: true, title: "OPEN XGEN", fullUnicode: true });
1071
1067
  const provider = getDefaultProvider();
1072
1068
  const server = getServer();
1073
1069
  const auth = getAuth();
1074
- const env = getActiveEnvironment();
1070
+ const serverDisplay = auth && server ? `${auth.username}@${server.replace("https://", "").replace("http://", "")}` : "\uBBF8\uC5F0\uACB0";
1071
+ let activeTab = "workflows";
1075
1072
  const header = blessed.box({
1076
1073
  top: 0,
1077
1074
  left: 0,
1078
1075
  width: "100%",
1079
1076
  height: 3,
1080
- content: `{center}{bold}OPEN XGEN{/bold} ${provider?.model ?? "AI \uBBF8\uC124\uC815"} \xB7 ${auth?.username ?? "\uBBF8\uC5F0\uACB0"}@${env?.name ?? server?.replace("https://", "") ?? ""}{/center}`,
1081
1077
  tags: true,
1082
- style: { fg: "white", bg: "blue" }
1078
+ style: { fg: "white", bg: "black" }
1083
1079
  });
1084
- const wfPanel = blessed.list({
1080
+ function renderHeader() {
1081
+ const wf = activeTab === "workflows" ? "{bold}{underline}\uC6CC\uD06C\uD50C\uB85C\uC6B0{/underline}{/bold}" : "{gray-fg}\uC6CC\uD06C\uD50C\uB85C\uC6B0{/gray-fg}";
1082
+ const col = activeTab === "collections" ? "{bold}{underline}\uCEEC\uB809\uC158{/underline}{/bold}" : "{gray-fg}\uCEEC\uB809\uC158{/gray-fg}";
1083
+ header.setContent(` OPEN XGEN {gray-fg}${provider?.model ?? ""}{/gray-fg} ${serverDisplay} \u2502 [1]${wf} [2]${col}`);
1084
+ screen.render();
1085
+ }
1086
+ const listPanel = blessed.list({
1085
1087
  top: 3,
1086
1088
  left: 0,
1087
1089
  width: "50%",
1088
- height: "50%-2",
1089
- label: " \uC6CC\uD06C\uD50C\uB85C\uC6B0 ",
1090
+ height: "100%-9",
1090
1091
  border: { type: "line" },
1091
1092
  style: {
1092
- border: { fg: "cyan" },
1093
- selected: { fg: "black", bg: "cyan" },
1093
+ border: { fg: "gray" },
1094
+ selected: { fg: "black", bg: "white" },
1094
1095
  item: { fg: "white" },
1095
- label: { fg: "cyan", bold: true }
1096
+ label: { fg: "white", bold: true }
1096
1097
  },
1097
1098
  keys: true,
1098
1099
  vi: true,
1099
1100
  mouse: true,
1100
- scrollbar: { ch: "\u2502", style: { fg: "cyan" } },
1101
+ scrollbar: { ch: "\u2502", style: { fg: "gray" } },
1101
1102
  tags: true
1102
1103
  });
1103
- const detailPanel = blessed.box({
1104
- top: 3,
1105
- left: "50%",
1106
- width: "50%",
1107
- height: "50%-2",
1108
- label: " \uC0C1\uC138 ",
1109
- border: { type: "line" },
1110
- scrollable: true,
1111
- alwaysScroll: true,
1112
- mouse: true,
1113
- tags: true,
1114
- style: {
1115
- border: { fg: "green" },
1116
- label: { fg: "green", bold: true }
1117
- }
1118
- });
1119
- const colPanel = blessed.list({
1120
- top: "50%+1",
1104
+ const chatInput = blessed.textbox({
1105
+ bottom: 3,
1121
1106
  left: 0,
1122
1107
  width: "50%",
1123
- height: "50%-4",
1124
- label: " \uCEEC\uB809\uC158 (\uBB38\uC11C) ",
1108
+ height: 3,
1109
+ label: " \u276F ",
1125
1110
  border: { type: "line" },
1111
+ inputOnFocus: true,
1126
1112
  style: {
1127
- border: { fg: "yellow" },
1128
- selected: { fg: "black", bg: "yellow" },
1129
- item: { fg: "white" },
1130
- label: { fg: "yellow", bold: true }
1131
- },
1132
- keys: true,
1133
- vi: true,
1134
- mouse: true,
1135
- tags: true
1113
+ border: { fg: "gray" },
1114
+ label: { fg: "white", bold: true }
1115
+ }
1136
1116
  });
1137
- const chatLog = blessed.log({
1138
- top: "50%+1",
1117
+ const detailPanel = blessed.log({
1118
+ top: 3,
1139
1119
  left: "50%",
1140
1120
  width: "50%",
1141
- height: "50%-7",
1142
- label: " AI \uCC44\uD305 ",
1121
+ height: "100%-6",
1122
+ label: " \uC0C1\uC138 ",
1143
1123
  border: { type: "line" },
1144
1124
  scrollable: true,
1145
1125
  alwaysScroll: true,
1146
1126
  mouse: true,
1147
1127
  tags: true,
1148
1128
  style: {
1149
- border: { fg: "magenta" },
1150
- label: { fg: "magenta", bold: true }
1151
- }
1152
- });
1153
- const chatInput = blessed.textbox({
1154
- bottom: 3,
1155
- left: "50%",
1156
- width: "50%",
1157
- height: 3,
1158
- label: " \uC785\uB825 ",
1159
- border: { type: "line" },
1160
- inputOnFocus: true,
1161
- style: {
1162
- border: { fg: "magenta" },
1163
- label: { fg: "magenta" }
1129
+ border: { fg: "gray" },
1130
+ label: { fg: "white", bold: true }
1164
1131
  }
1165
1132
  });
1166
1133
  const statusBar = blessed.box({
@@ -1168,176 +1135,236 @@ async function startTui() {
1168
1135
  left: 0,
1169
1136
  width: "100%",
1170
1137
  height: 3,
1171
- content: " {bold}Tab{/bold}:\uD328\uB110\uC804\uD658 {bold}Enter{/bold}:\uC120\uD0DD {bold}r{/bold}:\uC0C8\uB85C\uACE0\uCE68 {bold}c{/bold}:\uCC44\uD305 {bold}q{/bold}:\uC885\uB8CC {bold}\u2191\u2193{/bold}:\uC774\uB3D9",
1172
1138
  tags: true,
1173
- style: { fg: "white", bg: "gray" }
1139
+ style: { fg: "gray", bg: "black" }
1174
1140
  });
1141
+ function renderStatusBar(msg) {
1142
+ statusBar.setContent(msg ?? " {white-fg}{bold}1/2{/bold}{/white-fg}:\uD0ED {white-fg}{bold}Enter{/bold}{/white-fg}:\uC2E4\uD589 {white-fg}{bold}i{/bold}{/white-fg}:\uC785\uB825 {white-fg}{bold}r{/bold}{/white-fg}:\uC0C8\uB85C\uACE0\uCE68 {white-fg}{bold}Esc{/bold}{/white-fg}:\uBAA9\uB85D {white-fg}{bold}q{/bold}{/white-fg}:\uC885\uB8CC");
1143
+ screen.render();
1144
+ }
1175
1145
  screen.append(header);
1176
- screen.append(wfPanel);
1177
- screen.append(detailPanel);
1178
- screen.append(colPanel);
1179
- screen.append(chatLog);
1146
+ screen.append(listPanel);
1180
1147
  screen.append(chatInput);
1148
+ screen.append(detailPanel);
1181
1149
  screen.append(statusBar);
1182
1150
  let workflows = [];
1183
1151
  let collections = [];
1184
- async function loadData() {
1185
- if (!server || !auth) {
1186
- wfPanel.setItems(["\uC11C\uBC84 \uBBF8\uC5F0\uACB0 \u2014 q \uC885\uB8CC \uD6C4 xgen agent \u2192 /connect"]);
1187
- colPanel.setItems(["\uC11C\uBC84 \uBBF8\uC5F0\uACB0"]);
1188
- screen.render();
1189
- return;
1190
- }
1191
- statusBar.setContent(" \uB85C\uB529 \uC911...");
1192
- screen.render();
1152
+ async function loadWorkflows() {
1153
+ if (!server || !auth) return;
1193
1154
  try {
1194
1155
  const { getWorkflowListDetail: getWorkflowListDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
1195
1156
  const wfs = await getWorkflowListDetail2();
1196
1157
  workflows = wfs.map((w) => ({
1197
1158
  name: w.workflow_name,
1198
1159
  id: (w.workflow_id ?? w.id ?? "").toString(),
1199
- deployed: !!w.is_deployed,
1200
- deployKey: w.deploy_key,
1201
- nodeCount: w.node_count
1202
- }));
1203
- wfPanel.setItems(workflows.map((w) => {
1204
- const tag = w.deployed ? "{green-fg}[\uBC30\uD3EC]{/green-fg}" : "";
1205
- return ` ${w.name} ${tag}`;
1160
+ deployed: !!w.is_deployed
1206
1161
  }));
1207
- } catch (err) {
1208
- wfPanel.setItems([`\uC624\uB958: ${err.message}`]);
1162
+ } catch {
1163
+ workflows = [];
1209
1164
  }
1165
+ }
1166
+ async function loadCollections() {
1167
+ if (!server || !auth) return;
1210
1168
  try {
1211
1169
  const { listCollections: listCollections2 } = await Promise.resolve().then(() => (init_document(), document_exports));
1212
1170
  const cols = await listCollections2();
1213
1171
  collections = cols.map((c) => ({
1214
1172
  name: c.collection_make_name,
1173
+ id: c.id,
1215
1174
  docs: c.total_documents,
1216
1175
  chunks: c.total_chunks,
1217
1176
  shared: c.is_shared,
1218
- group: c.share_group ?? void 0
1219
- }));
1220
- colPanel.setItems(collections.map((c) => {
1221
- const shared = c.shared ? `{yellow-fg}[${c.group}]{/yellow-fg}` : "";
1222
- return ` ${c.name} ${shared} \u2014 ${c.docs}\uBB38\uC11C ${c.chunks}\uCCAD\uD06C`;
1177
+ group: c.share_group ?? void 0,
1178
+ model: c.init_embedding_model ?? void 0
1223
1179
  }));
1224
1180
  } catch {
1225
- colPanel.setItems(["\uCEEC\uB809\uC158 \uB85C\uB4DC \uC2E4\uD328"]);
1181
+ collections = [];
1182
+ }
1183
+ }
1184
+ function renderList() {
1185
+ if (activeTab === "workflows") {
1186
+ listPanel.label = ` \uC6CC\uD06C\uD50C\uB85C\uC6B0 (${workflows.length}) `;
1187
+ listPanel.setItems(workflows.map((w, i) => {
1188
+ const dot = w.deployed ? "\u25CF" : "\u25CB";
1189
+ return ` ${dot} ${String(i + 1).padStart(2)}. ${w.name}`;
1190
+ }));
1191
+ } else {
1192
+ listPanel.label = ` \uCEEC\uB809\uC158 (${collections.length}) `;
1193
+ listPanel.setItems(collections.map(
1194
+ (c, i) => ` ${String(i + 1).padStart(2)}. ${c.name} {gray-fg}${c.docs}\uBB38\uC11C{/gray-fg}`
1195
+ ));
1226
1196
  }
1227
- statusBar.setContent(" {bold}Tab{/bold}:\uD328\uB110\uC804\uD658 {bold}Enter{/bold}:\uC120\uD0DD {bold}r{/bold}:\uC0C8\uB85C\uACE0\uCE68 {bold}c{/bold}:\uCC44\uD305 {bold}q{/bold}:\uC885\uB8CC {bold}\u2191\u2193{/bold}:\uC774\uB3D9");
1228
1197
  screen.render();
1229
1198
  }
1230
- wfPanel.on("select item", (_item, index) => {
1231
- const w = workflows[index];
1232
- if (!w) return;
1233
- detailPanel.setContent([
1234
- `{bold}${w.name}{/bold}`,
1235
- "",
1236
- `ID: ${w.id}`,
1237
- `\uBC30\uD3EC: ${w.deployed ? "{green-fg}Yes{/green-fg}" : "No"}`,
1238
- w.deployKey ? `Deploy Key: ${w.deployKey}` : "",
1239
- w.nodeCount ? `\uB178\uB4DC: ${w.nodeCount}\uAC1C` : "",
1240
- "",
1241
- w.deployed ? "{green-fg}Enter\uB85C \uC2E4\uD589{/green-fg}" : "{gray-fg}\uBBF8\uBC30\uD3EC \u2014 \uC2E4\uD589 \uBD88\uAC00{/gray-fg}"
1242
- ].filter(Boolean).join("\n"));
1199
+ async function loadAll() {
1200
+ renderStatusBar(" \uB85C\uB529...");
1201
+ await Promise.all([loadWorkflows(), loadCollections()]);
1202
+ renderList();
1203
+ renderHeader();
1204
+ renderStatusBar();
1205
+ }
1206
+ listPanel.on("select item", (_item, index) => {
1207
+ if (activeTab === "workflows") {
1208
+ const w = workflows[index];
1209
+ if (!w) return;
1210
+ detailPanel.setContent([
1211
+ `{bold}${w.name}{/bold}`,
1212
+ ``,
1213
+ `ID ${w.id}`,
1214
+ `\uBC30\uD3EC ${w.deployed ? "Yes" : "No"}`,
1215
+ ``,
1216
+ `Enter \u2192 \uC2E4\uD589 \uC785\uB825`
1217
+ ].join("\n"));
1218
+ } else {
1219
+ const c = collections[index];
1220
+ if (!c) return;
1221
+ detailPanel.setContent([
1222
+ `{bold}${c.name}{/bold}`,
1223
+ ``,
1224
+ `\uBB38\uC11C ${c.docs}\uAC1C`,
1225
+ `\uCCAD\uD06C ${c.chunks}\uAC1C`,
1226
+ `\uACF5\uC720 ${c.shared ? `Yes (${c.group})` : "No"}`,
1227
+ `\uBAA8\uB378 ${c.model ?? "-"}`,
1228
+ ``,
1229
+ `Enter \u2192 \uBB38\uC11C \uBAA9\uB85D`
1230
+ ].join("\n"));
1231
+ }
1243
1232
  screen.render();
1244
1233
  });
1245
- wfPanel.on("select", async (_item, index) => {
1246
- const w = workflows[index];
1247
- if (!w || !w.deployed || !w.deployKey) {
1248
- detailPanel.setContent("{red-fg}\uBC30\uD3EC\uB41C \uC6CC\uD06C\uD50C\uB85C\uC6B0\uB9CC \uC2E4\uD589 \uAC00\uB2A5\uD569\uB2C8\uB2E4.{/red-fg}");
1234
+ listPanel.on("select", async (_item, index) => {
1235
+ if (activeTab === "workflows") {
1236
+ const w = workflows[index];
1237
+ if (!w) return;
1238
+ chatInput.label = ` ${w.name} \u276F `;
1239
+ chatInput.focus();
1249
1240
  screen.render();
1250
- return;
1251
- }
1252
- detailPanel.setContent(`{yellow-fg}${w.name} \uC2E4\uD589 \uC911...{/yellow-fg}`);
1253
- screen.render();
1254
- try {
1255
- const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
1256
- const { randomUUID: randomUUID4 } = await import("crypto");
1257
- const result = await executeWorkflow2({
1258
- workflow_id: w.id,
1259
- workflow_name: w.name,
1260
- input_data: "\uD14C\uC2A4\uD2B8 \uC2E4\uD589",
1261
- interaction_id: `cli_${randomUUID4().slice(0, 8)}`,
1262
- deploy_key: w.deployKey
1241
+ chatInput.once("submit", async (value) => {
1242
+ if (!value.trim()) {
1243
+ chatInput.label = " \u276F ";
1244
+ chatInput.clearValue();
1245
+ listPanel.focus();
1246
+ screen.render();
1247
+ return;
1248
+ }
1249
+ detailPanel.log(`{gray-fg}\u2500\u2500 ${w.name} \u2500\u2500{/gray-fg}`);
1250
+ detailPanel.log(`\uC785\uB825: ${value}`);
1251
+ screen.render();
1252
+ try {
1253
+ const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
1254
+ const { randomUUID: randomUUID4 } = await import("crypto");
1255
+ const result = await executeWorkflow2({
1256
+ workflow_id: w.id,
1257
+ workflow_name: w.name,
1258
+ input_data: value,
1259
+ interaction_id: `tui_${randomUUID4().slice(0, 8)}`,
1260
+ user_id: auth?.userId ? parseInt(auth.userId) : 1
1261
+ });
1262
+ if (result.content) {
1263
+ detailPanel.log(`${String(result.content)}
1264
+ `);
1265
+ } else if (result.error || result.message) {
1266
+ detailPanel.log(`\uC624\uB958: ${result.error ?? result.message}
1267
+ `);
1268
+ } else {
1269
+ detailPanel.log(JSON.stringify(result, null, 2).slice(0, 800) + "\n");
1270
+ }
1271
+ } catch (err) {
1272
+ detailPanel.log(`\uC2E4\uD328: ${err.message}
1273
+ `);
1274
+ }
1275
+ chatInput.label = " \u276F ";
1276
+ chatInput.clearValue();
1277
+ listPanel.focus();
1278
+ screen.render();
1263
1279
  });
1264
- if (result.content) {
1265
- detailPanel.setContent(`{green-fg}\uACB0\uACFC:{/green-fg}
1280
+ } else {
1281
+ const c = collections[index];
1282
+ if (!c) return;
1283
+ detailPanel.setContent(`${c.name} \uBB38\uC11C \uB85C\uB529...`);
1284
+ screen.render();
1285
+ try {
1286
+ const { listDocuments: listDocuments2 } = await Promise.resolve().then(() => (init_document(), document_exports));
1287
+ const docs = await listDocuments2(c.id?.toString());
1288
+ if (!docs.length) {
1289
+ detailPanel.setContent(`{bold}${c.name}{/bold}
1266
1290
 
1267
- ${String(result.content).slice(0, 500)}`);
1268
- } else if (result.error) {
1269
- detailPanel.setContent(`{red-fg}\uC624\uB958:{/red-fg} ${result.error}`);
1270
- } else {
1271
- detailPanel.setContent(JSON.stringify(result, null, 2).slice(0, 500));
1291
+ \uBB38\uC11C \uC5C6\uC74C`);
1292
+ } else {
1293
+ const docList = docs.map((d, i) => {
1294
+ const name = d.name || d.file_name || "\uC774\uB984 \uC5C6\uC74C";
1295
+ return ` ${i + 1}. ${name}`;
1296
+ }).join("\n");
1297
+ detailPanel.setContent(`{bold}${c.name}{/bold} \u2014 ${docs.length}\uAC1C \uBB38\uC11C
1298
+
1299
+ ${docList}`);
1300
+ }
1301
+ } catch (err) {
1302
+ detailPanel.setContent(`\uBB38\uC11C \uB85C\uB4DC \uC2E4\uD328: ${err.message}`);
1272
1303
  }
1273
- } catch (err) {
1274
- detailPanel.setContent(`{red-fg}\uC2E4\uD589 \uC2E4\uD328:{/red-fg} ${err.message}`);
1304
+ screen.render();
1275
1305
  }
1276
- screen.render();
1277
- });
1278
- colPanel.on("select item", (_item, index) => {
1279
- const c = collections[index];
1280
- if (!c) return;
1281
- detailPanel.setContent([
1282
- `{bold}${c.name}{/bold}`,
1283
- "",
1284
- `\uBB38\uC11C: ${c.docs}\uAC1C`,
1285
- `\uCCAD\uD06C: ${c.chunks}\uAC1C`,
1286
- `\uACF5\uC720: ${c.shared ? `Yes (${c.group})` : "No"}`
1287
- ].join("\n"));
1288
- screen.render();
1289
1306
  });
1290
1307
  chatInput.on("submit", async (value) => {
1291
1308
  if (!value.trim()) {
1292
1309
  chatInput.clearValue();
1293
- chatInput.focus();
1310
+ listPanel.focus();
1294
1311
  screen.render();
1295
1312
  return;
1296
1313
  }
1297
- chatLog.log(`{blue-fg}You:{/blue-fg} ${value}`);
1314
+ detailPanel.log(`{white-fg}\u276F ${value}{/white-fg}`);
1298
1315
  chatInput.clearValue();
1299
1316
  screen.render();
1300
1317
  try {
1301
- const provider2 = getDefaultProvider();
1302
- if (!provider2) {
1303
- chatLog.log("{red-fg}\uD504\uB85C\uBC14\uC774\uB354 \uBBF8\uC124\uC815{/red-fg}");
1318
+ const p = getDefaultProvider();
1319
+ if (!p) {
1320
+ detailPanel.log("\uD504\uB85C\uBC14\uC774\uB354 \uBBF8\uC124\uC815");
1304
1321
  chatInput.focus();
1305
1322
  screen.render();
1306
1323
  return;
1307
1324
  }
1308
1325
  const { createLLMClient: createLLMClient2, streamChat: streamChat2 } = await Promise.resolve().then(() => (init_llm(), llm_exports));
1309
- const client2 = createLLMClient2(provider2);
1310
- const result = await streamChat2(client2, provider2.model, [
1311
- { role: "system", content: "You are OPEN XGEN. Be concise. Respond in Korean. Max 3 sentences." },
1326
+ const client2 = createLLMClient2(p);
1327
+ const result = await streamChat2(client2, p.model, [
1328
+ { role: "system", content: "You are OPEN XGEN. Concise. Korean." },
1312
1329
  { role: "user", content: value }
1313
1330
  ]);
1314
- chatLog.log(`{green-fg}AI:{/green-fg} ${result.content || "(no response)"}`);
1331
+ detailPanel.log(`${result.content || "(\uC751\uB2F5 \uC5C6\uC74C)"}
1332
+ `);
1315
1333
  } catch (err) {
1316
- chatLog.log(`{red-fg}\uC624\uB958:{/red-fg} ${err.message}`);
1334
+ detailPanel.log(`\uC624\uB958: ${err.message}
1335
+ `);
1317
1336
  }
1318
1337
  chatInput.focus();
1319
1338
  screen.render();
1320
1339
  });
1321
- const panels = [wfPanel, colPanel, chatInput];
1322
- let activePanel = 0;
1323
- function focusPanel(idx) {
1324
- activePanel = idx;
1325
- panels[idx].focus();
1326
- screen.render();
1327
- }
1340
+ screen.key(["1"], () => {
1341
+ activeTab = "workflows";
1342
+ renderList();
1343
+ renderHeader();
1344
+ listPanel.focus();
1345
+ });
1346
+ screen.key(["2"], () => {
1347
+ activeTab = "collections";
1348
+ renderList();
1349
+ renderHeader();
1350
+ listPanel.focus();
1351
+ });
1328
1352
  screen.key(["tab"], () => {
1329
- activePanel = (activePanel + 1) % panels.length;
1330
- focusPanel(activePanel);
1353
+ if (screen.focused === listPanel) chatInput.focus();
1354
+ else listPanel.focus();
1355
+ screen.render();
1331
1356
  });
1332
- screen.key(["S-tab"], () => {
1333
- activePanel = (activePanel - 1 + panels.length) % panels.length;
1334
- focusPanel(activePanel);
1357
+ screen.key(["i"], () => {
1358
+ chatInput.focus();
1359
+ screen.render();
1335
1360
  });
1336
1361
  screen.key(["r"], async () => {
1337
- await loadData();
1362
+ await loadAll();
1338
1363
  });
1339
- screen.key(["c"], () => {
1340
- focusPanel(2);
1364
+ screen.key(["escape"], () => {
1365
+ chatInput.label = " \u276F ";
1366
+ listPanel.focus();
1367
+ screen.render();
1341
1368
  });
1342
1369
  screen.key(["q", "C-c"], () => {
1343
1370
  screen.destroy();
@@ -1345,12 +1372,12 @@ ${String(result.content).slice(0, 500)}`);
1345
1372
  });
1346
1373
  setInterval(async () => {
1347
1374
  try {
1348
- await loadData();
1375
+ await loadAll();
1349
1376
  } catch {
1350
1377
  }
1351
- }, 3e4);
1352
- await loadData();
1353
- focusPanel(0);
1378
+ }, 6e4);
1379
+ await loadAll();
1380
+ listPanel.focus();
1354
1381
  screen.render();
1355
1382
  }
1356
1383
  var init_tui = __esm({
@@ -2653,14 +2680,14 @@ async function workflowList2() {
2653
2680
  const { getWorkflowListDetail: getWorkflowListDetail2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
2654
2681
  const wfs = await getWorkflowListDetail2();
2655
2682
  if (!wfs.length) return "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC5C6\uC74C.";
2656
- return wfs.map((w, i) => {
2683
+ const header = `\uCD1D ${wfs.length}\uAC1C \uC6CC\uD06C\uD50C\uB85C\uC6B0:
2684
+ `;
2685
+ const list = wfs.map((w, i) => {
2657
2686
  const deployed = w.is_deployed;
2658
- const dk = w.deploy_key;
2659
- const tag = deployed ? " [\uBC30\uD3EC\uB428]" : "";
2660
- return `${i + 1}. ${w.workflow_name}${tag}
2661
- ID: ${w.workflow_id ?? w.id}
2662
- deploy_key: ${dk || "\uC5C6\uC74C"}`;
2687
+ const tag = deployed ? " \u25CF" : "";
2688
+ return `${i + 1}. ${w.workflow_name}${tag} | ${w.workflow_id ?? w.id}`;
2663
2689
  }).join("\n");
2690
+ return header + list;
2664
2691
  }
2665
2692
  async function workflowRun2(args) {
2666
2693
  const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
@@ -3093,13 +3120,33 @@ async function agentRepl() {
3093
3120
  const env = getActiveEnvironment();
3094
3121
  console.log(chalk12.gray(` model ${provider.model}`));
3095
3122
  if (server && auth) {
3096
- console.log(chalk12.gray(` xgen ${chalk12.green("\u25CF")} ${auth.username}@${(env?.name ?? server).replace("https://", "")}`));
3123
+ console.log(chalk12.gray(` xgen ${chalk12.green("\u25CF")} ${auth.username}@${server.replace("https://", "").replace("http://", "")}`));
3097
3124
  } else {
3098
3125
  console.log(chalk12.gray(` xgen ${chalk12.red("\u25CB")} \uBBF8\uC5F0\uACB0`));
3099
3126
  }
3100
3127
  console.log(chalk12.gray(` cwd ${process.cwd()}`));
3101
3128
  console.log();
3102
- console.log(chalk12.gray(` \uBB34\uC5C7\uC774\uB4E0 \uBB3C\uC5B4\uBCF4\uC138\uC694. /help`));
3129
+ if (server && auth) {
3130
+ try {
3131
+ const [wfRes, colRes] = await Promise.allSettled([
3132
+ Promise.resolve().then(() => (init_workflow(), workflow_exports)).then((m) => m.getWorkflowListDetail()),
3133
+ Promise.resolve().then(() => (init_document(), document_exports)).then((m) => m.listCollections())
3134
+ ]);
3135
+ const wfCount = wfRes.status === "fulfilled" ? wfRes.value.length : 0;
3136
+ const colCount = colRes.status === "fulfilled" ? colRes.value.length : 0;
3137
+ const deployed = wfRes.status === "fulfilled" ? wfRes.value.filter((w) => w.is_deployed).length : 0;
3138
+ console.log(chalk12.gray(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
3139
+ console.log(chalk12.gray(` \uC6CC\uD06C\uD50C\uB85C\uC6B0 ${chalk12.white(String(wfCount))}\uAC1C (\uBC30\uD3EC ${deployed}) \xB7 \uCEEC\uB809\uC158 ${chalk12.white(String(colCount))}\uAC1C`));
3140
+ console.log(chalk12.gray(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
3141
+ console.log();
3142
+ console.log(chalk12.gray(` "\uC6CC\uD06C\uD50C\uB85C\uC6B0 \uBAA9\uB85D", "\uCEEC\uB809\uC158", "6\uBC88 \uC2E4\uD589" \uB4F1 \uC790\uC720\uB86D\uAC8C \uC785\uB825`));
3143
+ console.log(chalk12.gray(` /dashboard \uB85C TUI \uB300\uC2DC\uBCF4\uB4DC \xB7 /help \uC804\uCCB4 \uB3C4\uC6C0\uB9D0`));
3144
+ } catch {
3145
+ console.log(chalk12.gray(` \uBB34\uC5C7\uC774\uB4E0 \uBB3C\uC5B4\uBCF4\uC138\uC694. /help`));
3146
+ }
3147
+ } else {
3148
+ console.log(chalk12.gray(` \uBB34\uC5C7\uC774\uB4E0 \uBB3C\uC5B4\uBCF4\uC138\uC694. /help`));
3149
+ }
3103
3150
  console.log();
3104
3151
  const rl = createInterface5({ input: process.stdin, output: process.stdout });
3105
3152
  let rlClosed = false;
@@ -3338,7 +3385,7 @@ async function runLoop(client2, model, messages, tools2) {
3338
3385
  } else {
3339
3386
  toolResult2 = await executeTool(tc.name, args);
3340
3387
  }
3341
- const truncated = toolResult2.length > 4e3 ? toolResult2.slice(0, 4e3) + "\n\u2026(truncated)" : toolResult2;
3388
+ const truncated = toolResult2.length > 8e3 ? toolResult2.slice(0, 8e3) + "\n\u2026(truncated)" : toolResult2;
3342
3389
  const preview = toolResult2.split("\n")[0].slice(0, 60);
3343
3390
  console.log(chalk12.dim(` \u2514 ${preview}${toolResult2.length > 60 ? "\u2026" : ""}`));
3344
3391
  messages.push({ role: "tool", tool_call_id: tc.id, content: truncated });