openxgen 2.0.0 → 2.1.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 +316 -378
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
package/dist/index.js
CHANGED
|
@@ -891,75 +891,6 @@ var init_provider = __esm({
|
|
|
891
891
|
}
|
|
892
892
|
});
|
|
893
893
|
|
|
894
|
-
// src/agent/llm.ts
|
|
895
|
-
var llm_exports = {};
|
|
896
|
-
__export(llm_exports, {
|
|
897
|
-
createLLMClient: () => createLLMClient,
|
|
898
|
-
streamChat: () => streamChat
|
|
899
|
-
});
|
|
900
|
-
import OpenAI2 from "openai";
|
|
901
|
-
function createLLMClient(provider) {
|
|
902
|
-
const opts = {
|
|
903
|
-
apiKey: provider.apiKey || "ollama"
|
|
904
|
-
};
|
|
905
|
-
if (provider.baseUrl) {
|
|
906
|
-
opts.baseURL = provider.baseUrl;
|
|
907
|
-
}
|
|
908
|
-
return new OpenAI2(opts);
|
|
909
|
-
}
|
|
910
|
-
async function streamChat(client2, model, messages, tools2, onDelta) {
|
|
911
|
-
const params = {
|
|
912
|
-
model,
|
|
913
|
-
messages,
|
|
914
|
-
stream: true,
|
|
915
|
-
stream_options: { include_usage: true }
|
|
916
|
-
};
|
|
917
|
-
if (tools2 && tools2.length > 0) {
|
|
918
|
-
params.tools = tools2;
|
|
919
|
-
}
|
|
920
|
-
const stream = await client2.chat.completions.create(params);
|
|
921
|
-
let content = "";
|
|
922
|
-
let usage = null;
|
|
923
|
-
const toolCallMap = /* @__PURE__ */ new Map();
|
|
924
|
-
for await (const chunk of stream) {
|
|
925
|
-
if (chunk.usage) {
|
|
926
|
-
usage = {
|
|
927
|
-
promptTokens: chunk.usage.prompt_tokens ?? 0,
|
|
928
|
-
completionTokens: chunk.usage.completion_tokens ?? 0,
|
|
929
|
-
totalTokens: chunk.usage.total_tokens ?? 0
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
const delta = chunk.choices[0]?.delta;
|
|
933
|
-
if (!delta) continue;
|
|
934
|
-
if (delta.content) {
|
|
935
|
-
content += delta.content;
|
|
936
|
-
onDelta?.(delta.content);
|
|
937
|
-
}
|
|
938
|
-
if (delta.tool_calls) {
|
|
939
|
-
for (const tc of delta.tool_calls) {
|
|
940
|
-
const idx = tc.index;
|
|
941
|
-
if (!toolCallMap.has(idx)) {
|
|
942
|
-
toolCallMap.set(idx, { id: tc.id ?? "", name: tc.function?.name ?? "", arguments: "" });
|
|
943
|
-
}
|
|
944
|
-
const entry = toolCallMap.get(idx);
|
|
945
|
-
if (tc.id) entry.id = tc.id;
|
|
946
|
-
if (tc.function?.name) entry.name = tc.function.name;
|
|
947
|
-
if (tc.function?.arguments) entry.arguments += tc.function.arguments;
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
return {
|
|
952
|
-
content,
|
|
953
|
-
toolCalls: [...toolCallMap.values()],
|
|
954
|
-
usage
|
|
955
|
-
};
|
|
956
|
-
}
|
|
957
|
-
var init_llm = __esm({
|
|
958
|
-
"src/agent/llm.ts"() {
|
|
959
|
-
"use strict";
|
|
960
|
-
}
|
|
961
|
-
});
|
|
962
|
-
|
|
963
894
|
// src/api/xgen-extra.ts
|
|
964
895
|
var xgen_extra_exports = {};
|
|
965
896
|
__export(xgen_extra_exports, {
|
|
@@ -1177,334 +1108,283 @@ var init_ontology = __esm({
|
|
|
1177
1108
|
}
|
|
1178
1109
|
});
|
|
1179
1110
|
|
|
1180
|
-
// src/dashboard/
|
|
1181
|
-
var
|
|
1182
|
-
__export(
|
|
1183
|
-
|
|
1111
|
+
// src/dashboard/InkDashboard.tsx
|
|
1112
|
+
var InkDashboard_exports = {};
|
|
1113
|
+
__export(InkDashboard_exports, {
|
|
1114
|
+
startInkDashboard: () => startInkDashboard
|
|
1184
1115
|
});
|
|
1185
|
-
import
|
|
1186
|
-
|
|
1187
|
-
|
|
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();
|
|
1188
1181
|
const provider = getDefaultProvider();
|
|
1189
1182
|
const server = getServer();
|
|
1190
1183
|
const auth = getAuth();
|
|
1191
1184
|
const serverDisplay = auth && server ? `${auth.username}@${server.replace("https://", "").replace("http://", "")}` : "\uBBF8\uC5F0\uACB0";
|
|
1192
|
-
|
|
1193
|
-
const
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
height: "100%-9",
|
|
1212
|
-
border: { type: "line" },
|
|
1213
|
-
style: {
|
|
1214
|
-
border: { fg: "gray" },
|
|
1215
|
-
selected: { fg: "black", bg: "white" },
|
|
1216
|
-
item: { fg: "white" },
|
|
1217
|
-
label: { fg: "white", bold: true }
|
|
1218
|
-
},
|
|
1219
|
-
keys: true,
|
|
1220
|
-
vi: true,
|
|
1221
|
-
mouse: true,
|
|
1222
|
-
scrollbar: { ch: "\u2502", style: { fg: "gray" } },
|
|
1223
|
-
tags: true
|
|
1224
|
-
});
|
|
1225
|
-
const chatInput = blessed.textbox({
|
|
1226
|
-
bottom: 3,
|
|
1227
|
-
left: 0,
|
|
1228
|
-
width: "50%",
|
|
1229
|
-
height: 3,
|
|
1230
|
-
label: " \u276F ",
|
|
1231
|
-
border: { type: "line" },
|
|
1232
|
-
inputOnFocus: true,
|
|
1233
|
-
style: {
|
|
1234
|
-
border: { fg: "gray" },
|
|
1235
|
-
label: { fg: "white", bold: true }
|
|
1236
|
-
}
|
|
1237
|
-
});
|
|
1238
|
-
const detailPanel = blessed.log({
|
|
1239
|
-
top: 3,
|
|
1240
|
-
left: "50%",
|
|
1241
|
-
width: "50%",
|
|
1242
|
-
height: "100%-6",
|
|
1243
|
-
label: " \uC0C1\uC138 ",
|
|
1244
|
-
border: { type: "line" },
|
|
1245
|
-
scrollable: true,
|
|
1246
|
-
alwaysScroll: true,
|
|
1247
|
-
mouse: true,
|
|
1248
|
-
tags: true,
|
|
1249
|
-
style: {
|
|
1250
|
-
border: { fg: "gray" },
|
|
1251
|
-
label: { fg: "white", bold: true }
|
|
1252
|
-
}
|
|
1253
|
-
});
|
|
1254
|
-
const statusBar = blessed.box({
|
|
1255
|
-
bottom: 0,
|
|
1256
|
-
left: 0,
|
|
1257
|
-
width: "100%",
|
|
1258
|
-
height: 3,
|
|
1259
|
-
tags: true,
|
|
1260
|
-
style: { fg: "gray", bg: "black" }
|
|
1261
|
-
});
|
|
1262
|
-
function renderStatusBar(msg) {
|
|
1263
|
-
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");
|
|
1264
|
-
screen.render();
|
|
1265
|
-
}
|
|
1266
|
-
screen.append(header);
|
|
1267
|
-
screen.append(listPanel);
|
|
1268
|
-
screen.append(chatInput);
|
|
1269
|
-
screen.append(detailPanel);
|
|
1270
|
-
screen.append(statusBar);
|
|
1271
|
-
let workflows = [];
|
|
1272
|
-
let collections = [];
|
|
1273
|
-
async function loadWorkflows() {
|
|
1274
|
-
if (!server || !auth) return;
|
|
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...");
|
|
1275
1204
|
try {
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
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
|
+
}
|
|
1283
1236
|
} catch {
|
|
1284
|
-
workflows = [];
|
|
1285
1237
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
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");
|
|
1240
|
+
}
|
|
1241
|
+
function getListItems() {
|
|
1242
|
+
switch (tab) {
|
|
1243
|
+
case "workflows":
|
|
1244
|
+
return workflows.map((w) => ({ label: `${w.deployed ? "\u25CF" : "\u25CB"} ${w.name}`, dimLabel: "" }));
|
|
1245
|
+
case "collections":
|
|
1246
|
+
return collections.map((c) => ({ label: c.name, dimLabel: `${c.docs}\uBB38\uC11C ${c.chunks}\uCCAD\uD06C` }));
|
|
1247
|
+
case "nodes":
|
|
1248
|
+
return nodes.map((n) => ({ label: n.nodeName ?? n.name ?? "?", dimLabel: (n.description ?? "").slice(0, 30) }));
|
|
1249
|
+
case "prompts":
|
|
1250
|
+
return prompts.map((p) => ({ label: p.name ?? p.title ?? "?", dimLabel: `[${p.prompt_type ?? ""}]` }));
|
|
1251
|
+
case "tools":
|
|
1252
|
+
return tools2.map((t) => ({ label: t.name ?? t.tool_name ?? "?", dimLabel: (t.description ?? "").slice(0, 30) }));
|
|
1253
|
+
default:
|
|
1254
|
+
return [];
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
function showDetail() {
|
|
1258
|
+
const items = getListItems();
|
|
1259
|
+
if (selected < 0 || selected >= items.length) return;
|
|
1260
|
+
if (tab === "workflows") {
|
|
1261
|
+
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") {
|
|
1264
|
+
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") {
|
|
1267
|
+
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") {
|
|
1270
|
+
const p = prompts[selected];
|
|
1271
|
+
if (p) setDetail([p.name ?? "?", `[${p.prompt_type ?? ""}]`, "", (p.content ?? "").slice(0, 200)]);
|
|
1272
|
+
} else if (tab === "tools") {
|
|
1273
|
+
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;
|
|
1303
1291
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
const
|
|
1310
|
-
|
|
1311
|
-
|
|
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}`]);
|
|
1310
|
+
}
|
|
1311
|
+
setRunTarget(null);
|
|
1312
1312
|
} else {
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
(c, i) => ` ${String(i + 1).padStart(2)}. ${c.name} {gray-fg}${c.docs}\uBB38\uC11C{/gray-fg}`
|
|
1316
|
-
));
|
|
1313
|
+
setInputValue("");
|
|
1314
|
+
setInputMode(false);
|
|
1317
1315
|
}
|
|
1318
|
-
screen.render();
|
|
1319
1316
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
renderStatusBar();
|
|
1326
|
-
}
|
|
1327
|
-
listPanel.on("select item", (_item, index) => {
|
|
1328
|
-
if (activeTab === "workflows") {
|
|
1329
|
-
const w = workflows[index];
|
|
1330
|
-
if (!w) return;
|
|
1331
|
-
detailPanel.setContent([
|
|
1332
|
-
`{bold}${w.name}{/bold}`,
|
|
1333
|
-
``,
|
|
1334
|
-
`ID ${w.id}`,
|
|
1335
|
-
`\uBC30\uD3EC ${w.deployed ? "Yes" : "No"}`,
|
|
1336
|
-
``,
|
|
1337
|
-
`Enter \u2192 \uC2E4\uD589 \uC785\uB825`
|
|
1338
|
-
].join("\n"));
|
|
1339
|
-
} else {
|
|
1340
|
-
const c = collections[index];
|
|
1341
|
-
if (!c) return;
|
|
1342
|
-
detailPanel.setContent([
|
|
1343
|
-
`{bold}${c.name}{/bold}`,
|
|
1344
|
-
``,
|
|
1345
|
-
`\uBB38\uC11C ${c.docs}\uAC1C`,
|
|
1346
|
-
`\uCCAD\uD06C ${c.chunks}\uAC1C`,
|
|
1347
|
-
`\uACF5\uC720 ${c.shared ? `Yes (${c.group})` : "No"}`,
|
|
1348
|
-
`\uBAA8\uB378 ${c.model ?? "-"}`,
|
|
1349
|
-
``,
|
|
1350
|
-
`Enter \u2192 \uBB38\uC11C \uBAA9\uB85D`
|
|
1351
|
-
].join("\n"));
|
|
1352
|
-
}
|
|
1353
|
-
screen.render();
|
|
1354
|
-
});
|
|
1355
|
-
listPanel.on("select", async (_item, index) => {
|
|
1356
|
-
if (activeTab === "workflows") {
|
|
1357
|
-
const w = workflows[index];
|
|
1358
|
-
if (!w) return;
|
|
1359
|
-
chatInput.label = ` ${w.name} \u276F `;
|
|
1360
|
-
chatInput.focus();
|
|
1361
|
-
screen.render();
|
|
1362
|
-
chatInput.once("submit", async (value) => {
|
|
1363
|
-
if (!value.trim()) {
|
|
1364
|
-
chatInput.label = " \u276F ";
|
|
1365
|
-
chatInput.clearValue();
|
|
1366
|
-
listPanel.focus();
|
|
1367
|
-
screen.render();
|
|
1368
|
-
return;
|
|
1369
|
-
}
|
|
1370
|
-
detailPanel.log(`{gray-fg}\u2500\u2500 ${w.name} \u2500\u2500{/gray-fg}`);
|
|
1371
|
-
detailPanel.log(`\uC785\uB825: ${value}`);
|
|
1372
|
-
screen.render();
|
|
1373
|
-
try {
|
|
1374
|
-
const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1375
|
-
const { randomUUID: randomUUID4 } = await import("crypto");
|
|
1376
|
-
const result = await executeWorkflow2({
|
|
1377
|
-
workflow_id: w.id,
|
|
1378
|
-
workflow_name: w.name,
|
|
1379
|
-
input_data: value,
|
|
1380
|
-
interaction_id: `tui_${randomUUID4().slice(0, 8)}`,
|
|
1381
|
-
user_id: auth?.userId ? parseInt(auth.userId) : 1
|
|
1382
|
-
});
|
|
1383
|
-
if (result.content) {
|
|
1384
|
-
detailPanel.log(`${String(result.content)}
|
|
1385
|
-
`);
|
|
1386
|
-
} else if (result.error || result.message) {
|
|
1387
|
-
detailPanel.log(`\uC624\uB958: ${result.error ?? result.message}
|
|
1388
|
-
`);
|
|
1389
|
-
} else {
|
|
1390
|
-
detailPanel.log(JSON.stringify(result, null, 2).slice(0, 800) + "\n");
|
|
1391
|
-
}
|
|
1392
|
-
} catch (err) {
|
|
1393
|
-
detailPanel.log(`\uC2E4\uD328: ${err.message}
|
|
1394
|
-
`);
|
|
1395
|
-
}
|
|
1396
|
-
chatInput.label = " \u276F ";
|
|
1397
|
-
chatInput.clearValue();
|
|
1398
|
-
listPanel.focus();
|
|
1399
|
-
screen.render();
|
|
1400
|
-
});
|
|
1401
|
-
} else {
|
|
1402
|
-
const c = collections[index];
|
|
1403
|
-
if (!c) return;
|
|
1404
|
-
detailPanel.setContent(`${c.name} \uBB38\uC11C \uB85C\uB529...`);
|
|
1405
|
-
screen.render();
|
|
1406
|
-
try {
|
|
1407
|
-
const { listDocuments: listDocuments2 } = await Promise.resolve().then(() => (init_document(), document_exports));
|
|
1408
|
-
const docs = await listDocuments2(c.id?.toString());
|
|
1409
|
-
if (!docs.length) {
|
|
1410
|
-
detailPanel.setContent(`{bold}${c.name}{/bold}
|
|
1411
|
-
|
|
1412
|
-
\uBB38\uC11C \uC5C6\uC74C`);
|
|
1413
|
-
} else {
|
|
1414
|
-
const docList = docs.map((d, i) => {
|
|
1415
|
-
const name = d.name || d.file_name || "\uC774\uB984 \uC5C6\uC74C";
|
|
1416
|
-
return ` ${i + 1}. ${name}`;
|
|
1417
|
-
}).join("\n");
|
|
1418
|
-
detailPanel.setContent(`{bold}${c.name}{/bold} \u2014 ${docs.length}\uAC1C \uBB38\uC11C
|
|
1419
|
-
|
|
1420
|
-
${docList}`);
|
|
1421
|
-
}
|
|
1422
|
-
} catch (err) {
|
|
1423
|
-
detailPanel.setContent(`\uBB38\uC11C \uB85C\uB4DC \uC2E4\uD328: ${err.message}`);
|
|
1317
|
+
useInput((input, key) => {
|
|
1318
|
+
if (inputMode) {
|
|
1319
|
+
if (key.escape) {
|
|
1320
|
+
setInputMode(false);
|
|
1321
|
+
setRunTarget(null);
|
|
1424
1322
|
}
|
|
1425
|
-
|
|
1323
|
+
return;
|
|
1426
1324
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
if (!value.trim()) {
|
|
1430
|
-
chatInput.clearValue();
|
|
1431
|
-
listPanel.focus();
|
|
1432
|
-
screen.render();
|
|
1325
|
+
if (input === "q" || key.ctrl && input === "c") {
|
|
1326
|
+
exit();
|
|
1433
1327
|
return;
|
|
1434
1328
|
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1329
|
+
if (input === "r") {
|
|
1330
|
+
loadAll();
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
if (input === "i") {
|
|
1334
|
+
setInputMode(true);
|
|
1335
|
+
return;
|
|
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) {
|
|
1347
|
+
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`);
|
|
1445
1351
|
}
|
|
1446
|
-
const { createLLMClient: createLLMClient2, streamChat: streamChat2 } = await Promise.resolve().then(() => (init_llm(), llm_exports));
|
|
1447
|
-
const client2 = createLLMClient2(p);
|
|
1448
|
-
const result = await streamChat2(client2, p.model, [
|
|
1449
|
-
{ role: "system", content: "You are OPEN XGEN. Concise. Korean." },
|
|
1450
|
-
{ role: "user", content: value }
|
|
1451
|
-
]);
|
|
1452
|
-
detailPanel.log(`${result.content || "(\uC751\uB2F5 \uC5C6\uC74C)"}
|
|
1453
|
-
`);
|
|
1454
|
-
} catch (err) {
|
|
1455
|
-
detailPanel.log(`\uC624\uB958: ${err.message}
|
|
1456
|
-
`);
|
|
1457
1352
|
}
|
|
1458
|
-
chatInput.focus();
|
|
1459
|
-
screen.render();
|
|
1460
1353
|
});
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
});
|
|
1478
|
-
screen.key(["i"], () => {
|
|
1479
|
-
chatInput.focus();
|
|
1480
|
-
screen.render();
|
|
1481
|
-
});
|
|
1482
|
-
screen.key(["r"], async () => {
|
|
1483
|
-
await loadAll();
|
|
1484
|
-
});
|
|
1485
|
-
screen.key(["escape"], () => {
|
|
1486
|
-
chatInput.label = " \u276F ";
|
|
1487
|
-
listPanel.focus();
|
|
1488
|
-
screen.render();
|
|
1489
|
-
});
|
|
1490
|
-
screen.key(["q", "C-c"], () => {
|
|
1491
|
-
screen.destroy();
|
|
1492
|
-
process.exit(0);
|
|
1493
|
-
});
|
|
1494
|
-
setInterval(async () => {
|
|
1495
|
-
try {
|
|
1496
|
-
await loadAll();
|
|
1497
|
-
} catch {
|
|
1498
|
-
}
|
|
1499
|
-
}, 6e4);
|
|
1500
|
-
await loadAll();
|
|
1501
|
-
listPanel.focus();
|
|
1502
|
-
screen.render();
|
|
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
|
+
] });
|
|
1503
1371
|
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1372
|
+
async function startInkDashboard() {
|
|
1373
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx(Dashboard, {}));
|
|
1374
|
+
await waitUntilExit();
|
|
1375
|
+
}
|
|
1376
|
+
var TABS;
|
|
1377
|
+
var init_InkDashboard = __esm({
|
|
1378
|
+
"src/dashboard/InkDashboard.tsx"() {
|
|
1506
1379
|
"use strict";
|
|
1507
1380
|
init_store();
|
|
1381
|
+
TABS = [
|
|
1382
|
+
{ key: "workflows", label: "\uC6CC\uD06C\uD50C\uB85C\uC6B0", shortcut: "1" },
|
|
1383
|
+
{ key: "collections", label: "\uCEEC\uB809\uC158", shortcut: "2" },
|
|
1384
|
+
{ key: "nodes", label: "\uB178\uB4DC", shortcut: "3" },
|
|
1385
|
+
{ key: "prompts", label: "\uD504\uB86C\uD504\uD2B8", shortcut: "4" },
|
|
1386
|
+
{ key: "tools", label: "\uB3C4\uAD6C", shortcut: "5" }
|
|
1387
|
+
];
|
|
1508
1388
|
}
|
|
1509
1389
|
});
|
|
1510
1390
|
|
|
@@ -2265,13 +2145,71 @@ init_provider();
|
|
|
2265
2145
|
|
|
2266
2146
|
// src/commands/agent.ts
|
|
2267
2147
|
init_store();
|
|
2268
|
-
init_llm();
|
|
2269
2148
|
import chalk12 from "chalk";
|
|
2270
2149
|
import { createInterface as createInterface5 } from "readline";
|
|
2271
2150
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync5, readdirSync } from "fs";
|
|
2272
2151
|
import { join as join4 } from "path";
|
|
2273
2152
|
import { homedir as homedir2 } from "os";
|
|
2274
2153
|
|
|
2154
|
+
// src/agent/llm.ts
|
|
2155
|
+
import OpenAI2 from "openai";
|
|
2156
|
+
function createLLMClient(provider) {
|
|
2157
|
+
const opts = {
|
|
2158
|
+
apiKey: provider.apiKey || "ollama"
|
|
2159
|
+
};
|
|
2160
|
+
if (provider.baseUrl) {
|
|
2161
|
+
opts.baseURL = provider.baseUrl;
|
|
2162
|
+
}
|
|
2163
|
+
return new OpenAI2(opts);
|
|
2164
|
+
}
|
|
2165
|
+
async function streamChat(client2, model, messages, tools2, onDelta) {
|
|
2166
|
+
const params = {
|
|
2167
|
+
model,
|
|
2168
|
+
messages,
|
|
2169
|
+
stream: true,
|
|
2170
|
+
stream_options: { include_usage: true }
|
|
2171
|
+
};
|
|
2172
|
+
if (tools2 && tools2.length > 0) {
|
|
2173
|
+
params.tools = tools2;
|
|
2174
|
+
}
|
|
2175
|
+
const stream = await client2.chat.completions.create(params);
|
|
2176
|
+
let content = "";
|
|
2177
|
+
let usage = null;
|
|
2178
|
+
const toolCallMap = /* @__PURE__ */ new Map();
|
|
2179
|
+
for await (const chunk of stream) {
|
|
2180
|
+
if (chunk.usage) {
|
|
2181
|
+
usage = {
|
|
2182
|
+
promptTokens: chunk.usage.prompt_tokens ?? 0,
|
|
2183
|
+
completionTokens: chunk.usage.completion_tokens ?? 0,
|
|
2184
|
+
totalTokens: chunk.usage.total_tokens ?? 0
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2187
|
+
const delta = chunk.choices[0]?.delta;
|
|
2188
|
+
if (!delta) continue;
|
|
2189
|
+
if (delta.content) {
|
|
2190
|
+
content += delta.content;
|
|
2191
|
+
onDelta?.(delta.content);
|
|
2192
|
+
}
|
|
2193
|
+
if (delta.tool_calls) {
|
|
2194
|
+
for (const tc of delta.tool_calls) {
|
|
2195
|
+
const idx = tc.index;
|
|
2196
|
+
if (!toolCallMap.has(idx)) {
|
|
2197
|
+
toolCallMap.set(idx, { id: tc.id ?? "", name: tc.function?.name ?? "", arguments: "" });
|
|
2198
|
+
}
|
|
2199
|
+
const entry = toolCallMap.get(idx);
|
|
2200
|
+
if (tc.id) entry.id = tc.id;
|
|
2201
|
+
if (tc.function?.name) entry.name = tc.function.name;
|
|
2202
|
+
if (tc.function?.arguments) entry.arguments += tc.function.arguments;
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
return {
|
|
2207
|
+
content,
|
|
2208
|
+
toolCalls: [...toolCallMap.values()],
|
|
2209
|
+
usage
|
|
2210
|
+
};
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2275
2213
|
// src/agent/tools/file-read.ts
|
|
2276
2214
|
var file_read_exports = {};
|
|
2277
2215
|
__export(file_read_exports, {
|
|
@@ -3374,8 +3312,8 @@ async function agentRepl() {
|
|
|
3374
3312
|
mcpManager?.stopAll();
|
|
3375
3313
|
rl.close();
|
|
3376
3314
|
if (process.stdin.isTTY) process.stdin.setRawMode?.(false);
|
|
3377
|
-
const {
|
|
3378
|
-
await
|
|
3315
|
+
const { startInkDashboard: startInkDashboard2 } = await Promise.resolve().then(() => (init_InkDashboard(), InkDashboard_exports));
|
|
3316
|
+
await startInkDashboard2();
|
|
3379
3317
|
return;
|
|
3380
3318
|
}
|
|
3381
3319
|
messages.push({ role: "user", content: input });
|