xgen-dex-cli 1.2.2 → 1.4.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/chunks/{chunk-GS2Q7ZZA.js → chunk-ULMEXJOR.js} +14 -3
- package/dist/chunks/chunk-ULMEXJOR.js.map +7 -0
- package/dist/chunks/{tui-PNFWGJTJ.js → tui-MLHYSLBS.js} +358 -150
- package/dist/chunks/tui-MLHYSLBS.js.map +7 -0
- package/dist/chunks/update-NA7YA6YF.js +100 -0
- package/dist/chunks/update-NA7YA6YF.js.map +7 -0
- package/dist/cli.js +66 -3
- package/dist/cli.js.map +3 -3
- package/package.json +2 -2
- package/dist/chunks/chunk-GS2Q7ZZA.js.map +0 -7
- package/dist/chunks/tui-PNFWGJTJ.js.map +0 -7
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DexError,
|
|
3
3
|
publicError
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ULMEXJOR.js";
|
|
5
5
|
|
|
6
6
|
// src/tui/index.tsx
|
|
7
7
|
import { render } from "ink";
|
|
8
|
+
import { stdout } from "node:process";
|
|
8
9
|
|
|
9
10
|
// src/tui/app.tsx
|
|
10
|
-
import { useCallback, useEffect as
|
|
11
|
-
import { Box as
|
|
11
|
+
import { useCallback, useEffect as useEffect7, useState as useState10 } from "react";
|
|
12
|
+
import { Box as Box9, Text as Text10, useApp as useApp2, useInput as useInput9 } from "ink";
|
|
12
13
|
|
|
13
14
|
// src/tui/dashboard.tsx
|
|
14
|
-
import { useEffect as
|
|
15
|
-
import { Box as
|
|
15
|
+
import { useEffect as useEffect5, useReducer, useRef as useRef2, useState as useState6 } from "react";
|
|
16
|
+
import { Box as Box5, Text as Text6, useApp, useInput as useInput5 } from "ink";
|
|
16
17
|
|
|
17
18
|
// src/tui/chat-state.ts
|
|
18
19
|
var initialChatState = { messages: [], running: false };
|
|
@@ -182,7 +183,7 @@ function TerminalCursor({ origin, offset }) {
|
|
|
182
183
|
return null;
|
|
183
184
|
}
|
|
184
185
|
function ImeTextInput(props) {
|
|
185
|
-
const { stdout } = useStdout();
|
|
186
|
+
const { stdout: stdout2 } = useStdout();
|
|
186
187
|
const initialSegments = graphemes(props.value);
|
|
187
188
|
const [cursor, setCursor] = useState(initialSegments.length);
|
|
188
189
|
const valueRef = useRef(props.value);
|
|
@@ -248,7 +249,7 @@ function ImeTextInput(props) {
|
|
|
248
249
|
const rawSegments = graphemes(props.value);
|
|
249
250
|
const safeCursor = clamp(cursor, 0, rawSegments.length);
|
|
250
251
|
const displayedSegments = props.mask ? rawSegments.map(() => props.mask ?? "") : rawSegments;
|
|
251
|
-
const maximumWidth = Math.max(1, (
|
|
252
|
+
const maximumWidth = Math.max(1, (stdout2.columns || 100) - props.cursorOrigin.x - 3);
|
|
252
253
|
const visible = visibleInput(displayedSegments, safeCursor, maximumWidth);
|
|
253
254
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
254
255
|
rawSegments.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: props.placeholder ?? "" }) : /* @__PURE__ */ jsx(Text, { children: visible.text }),
|
|
@@ -383,40 +384,126 @@ function HistoryScreen(props) {
|
|
|
383
384
|
] });
|
|
384
385
|
}
|
|
385
386
|
|
|
386
|
-
// src/tui/
|
|
387
|
+
// src/tui/start-panel.tsx
|
|
387
388
|
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
389
|
+
import { Box as Box4, Text as Text5, useInput as useInput4 } from "ink";
|
|
390
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
391
|
+
function StartPanel(props) {
|
|
392
|
+
const rows = [
|
|
393
|
+
{ kind: "new" },
|
|
394
|
+
...props.conversations.map((conversation) => ({ kind: "conversation", conversation }))
|
|
395
|
+
];
|
|
396
|
+
const [cursor, setCursor] = useState4(0);
|
|
397
|
+
const [opening, setOpening] = useState4(false);
|
|
398
|
+
const [error, setError] = useState4();
|
|
399
|
+
useEffect3(() => {
|
|
400
|
+
setCursor((current) => Math.min(current, Math.max(0, rows.length - 1)));
|
|
401
|
+
}, [rows.length]);
|
|
402
|
+
useInput4(
|
|
403
|
+
(_input, key) => {
|
|
404
|
+
if (key.escape) {
|
|
405
|
+
props.onCancel();
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
if (key.upArrow) setCursor((current) => Math.max(0, current - 1));
|
|
409
|
+
if (key.downArrow) setCursor((current) => Math.min(rows.length - 1, current + 1));
|
|
410
|
+
if (!key.return) return;
|
|
411
|
+
const row = rows[cursor];
|
|
412
|
+
if (!row) return;
|
|
413
|
+
if (row.kind === "new" || !row.conversation) {
|
|
414
|
+
props.onNew();
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
const conversation = row.conversation;
|
|
418
|
+
setOpening(true);
|
|
419
|
+
setError(void 0);
|
|
420
|
+
props.engine.historyTurns(
|
|
421
|
+
conversation.workflowId,
|
|
422
|
+
conversation.interactionId,
|
|
423
|
+
conversation.workflowName,
|
|
424
|
+
props.profile
|
|
425
|
+
).then((turns) => props.onOpen(conversation, turns)).catch((reason) => {
|
|
426
|
+
setError(publicError(reason).message);
|
|
427
|
+
setOpening(false);
|
|
428
|
+
});
|
|
429
|
+
},
|
|
430
|
+
{ isActive: !opening }
|
|
431
|
+
);
|
|
432
|
+
return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: "cyan", padding: 1, children: [
|
|
433
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, children: props.agentName }),
|
|
434
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "\uC5B4\uB5BB\uAC8C \uC2DC\uC791\uD560\uAE4C\uC694?" }),
|
|
435
|
+
/* @__PURE__ */ jsx5(Box4, { flexDirection: "column", marginTop: 1, children: rows.map((row, index) => {
|
|
436
|
+
const active = index === cursor;
|
|
437
|
+
const mark = active ? "\u203A" : " ";
|
|
438
|
+
if (row.kind === "new") {
|
|
439
|
+
return /* @__PURE__ */ jsxs5(Text5, { color: active ? "cyan" : void 0, children: [
|
|
440
|
+
mark,
|
|
441
|
+
" \uC0C8 \uB300\uD654"
|
|
442
|
+
] }, "new");
|
|
443
|
+
}
|
|
444
|
+
const conversation = row.conversation;
|
|
445
|
+
if (!conversation) return null;
|
|
446
|
+
return /* @__PURE__ */ jsxs5(Text5, { color: active ? "cyan" : void 0, children: [
|
|
447
|
+
mark,
|
|
448
|
+
" ",
|
|
449
|
+
when(conversation),
|
|
450
|
+
" ",
|
|
451
|
+
/* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
452
|
+
"\xB7 ",
|
|
453
|
+
conversation.interactionCount,
|
|
454
|
+
"\uD134"
|
|
455
|
+
] })
|
|
456
|
+
] }, conversation.interactionId);
|
|
457
|
+
}) }),
|
|
458
|
+
opening ? /* @__PURE__ */ jsx5(Loading, { label: "\uB300\uD654\uB97C \uBD88\uB7EC\uC624\uB294 \uC911..." }) : null,
|
|
459
|
+
error ? /* @__PURE__ */ jsx5(Notice, { error: true, children: error }) : null,
|
|
460
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "\u2191\u2193 \uC774\uB3D9 \xB7 Enter \uC120\uD0DD \xB7 Esc \uBAA9\uB85D\uC73C\uB85C" }) })
|
|
461
|
+
] });
|
|
462
|
+
}
|
|
463
|
+
function when(conversation) {
|
|
464
|
+
const raw = conversation.updatedAt || conversation.createdAt;
|
|
465
|
+
const date = new Date(raw);
|
|
466
|
+
if (Number.isNaN(date.getTime())) return raw || "(\uC2DC\uAC01 \uC5C6\uC74C)";
|
|
467
|
+
const now = /* @__PURE__ */ new Date();
|
|
468
|
+
const sameDay = date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate();
|
|
469
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
470
|
+
return sameDay ? `\uC624\uB298 ${pad(date.getHours())}:${pad(date.getMinutes())}` : `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// src/tui/use-terminal-size.ts
|
|
474
|
+
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
388
475
|
import { useStdout as useStdout2 } from "ink";
|
|
389
476
|
function useTerminalSize() {
|
|
390
|
-
const { stdout } = useStdout2();
|
|
477
|
+
const { stdout: stdout2 } = useStdout2();
|
|
391
478
|
const read = () => {
|
|
392
|
-
const columns =
|
|
393
|
-
const rows =
|
|
479
|
+
const columns = stdout2.columns || 100;
|
|
480
|
+
const rows = stdout2.rows || 30;
|
|
394
481
|
return { columns, rows, wide: columns >= 88 };
|
|
395
482
|
};
|
|
396
|
-
const [size, setSize] =
|
|
397
|
-
|
|
483
|
+
const [size, setSize] = useState5(read);
|
|
484
|
+
useEffect4(() => {
|
|
398
485
|
const resize = () => setSize(read());
|
|
399
|
-
|
|
486
|
+
stdout2.on("resize", resize);
|
|
400
487
|
return () => {
|
|
401
|
-
|
|
488
|
+
stdout2.off("resize", resize);
|
|
402
489
|
};
|
|
403
|
-
}, [
|
|
490
|
+
}, [stdout2]);
|
|
404
491
|
return size;
|
|
405
492
|
}
|
|
406
493
|
|
|
407
494
|
// src/tui/dashboard.tsx
|
|
408
|
-
import { jsx as
|
|
495
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
409
496
|
function AgentSidebar(props) {
|
|
410
497
|
const radius = Math.max(3, Math.floor((props.height - 4) / 2));
|
|
411
498
|
const start = Math.max(0, props.cursor - radius);
|
|
412
499
|
const visible = props.agents.slice(start, start + radius * 2 + 1);
|
|
413
|
-
return /* @__PURE__ */
|
|
414
|
-
/* @__PURE__ */
|
|
500
|
+
return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", width: 30, borderStyle: "round", borderColor: props.focused ? "cyan" : "gray", paddingX: 1, children: [
|
|
501
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: "Agents" }),
|
|
415
502
|
visible.map((agent) => {
|
|
416
503
|
const index = props.agents.indexOf(agent);
|
|
417
504
|
const cursor = index === props.cursor;
|
|
418
505
|
const selected = agent.workflowId === props.selected;
|
|
419
|
-
return /* @__PURE__ */
|
|
506
|
+
return /* @__PURE__ */ jsxs6(Text6, { color: cursor && props.focused ? "cyan" : void 0, wrap: "truncate-end", children: [
|
|
420
507
|
cursor ? "\u203A" : " ",
|
|
421
508
|
" ",
|
|
422
509
|
selected ? "\u25CF" : "\u25CB",
|
|
@@ -424,7 +511,7 @@ function AgentSidebar(props) {
|
|
|
424
511
|
agent.workflowName
|
|
425
512
|
] }, agent.workflowId);
|
|
426
513
|
}),
|
|
427
|
-
props.agents.length === 0 ? /* @__PURE__ */
|
|
514
|
+
props.agents.length === 0 ? /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "\uC0AC\uC6A9 \uAC00\uB2A5\uD55C Agent\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }) : null
|
|
428
515
|
] });
|
|
429
516
|
}
|
|
430
517
|
function messageColor(role) {
|
|
@@ -443,25 +530,25 @@ function labelOf(role, agentName) {
|
|
|
443
530
|
function ChatPane(props) {
|
|
444
531
|
const visibleCount = Math.max(4, Math.floor((props.height - 5) / 2));
|
|
445
532
|
const visible = props.messages.slice(-visibleCount);
|
|
446
|
-
return /* @__PURE__ */
|
|
447
|
-
/* @__PURE__ */
|
|
448
|
-
/* @__PURE__ */
|
|
449
|
-
visible.length === 0 ? /* @__PURE__ */
|
|
450
|
-
visible.map((message) => /* @__PURE__ */
|
|
451
|
-
/* @__PURE__ */
|
|
452
|
-
/* @__PURE__ */
|
|
533
|
+
return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: "blue", paddingX: 1, children: [
|
|
534
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: props.agent?.workflowName ?? "Agent\uB97C \uC120\uD0DD\uD558\uC138\uC694" }),
|
|
535
|
+
/* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", flexGrow: 1, children: [
|
|
536
|
+
visible.length === 0 ? /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: props.agent ? "\uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD574 \uB300\uD654\uB97C \uC2DC\uC791\uD558\uC138\uC694." : "\uC67C\uCABD\uC5D0\uC11C Agent\uB97C \uC120\uD0DD\uD558\uC138\uC694." }) : null,
|
|
537
|
+
visible.map((message) => /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginTop: message.role === "activity" ? 0 : 1, children: [
|
|
538
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, color: messageColor(message.role), children: labelOf(message.role, props.agent?.workflowName ?? "Agent") }),
|
|
539
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: message.role === "activity", children: message.text || (message.role === "assistant" ? "\u2026" : "") })
|
|
453
540
|
] }, message.id))
|
|
454
541
|
] }),
|
|
455
|
-
props.status ? /* @__PURE__ */
|
|
542
|
+
props.status ? /* @__PURE__ */ jsxs6(Text6, { color: "yellow", children: [
|
|
456
543
|
"\u25C6 ",
|
|
457
544
|
props.status
|
|
458
545
|
] }) : null
|
|
459
546
|
] });
|
|
460
547
|
}
|
|
461
548
|
function Composer(props) {
|
|
462
|
-
return /* @__PURE__ */
|
|
463
|
-
/* @__PURE__ */
|
|
464
|
-
props.disabled ? /* @__PURE__ */
|
|
549
|
+
return /* @__PURE__ */ jsxs6(Box5, { borderStyle: "round", borderColor: props.focused ? "cyan" : "gray", paddingX: 1, children: [
|
|
550
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u203A " }),
|
|
551
|
+
props.disabled ? /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "\uC751\uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uC911..." }) : /* @__PURE__ */ jsx6(
|
|
465
552
|
ImeTextInput,
|
|
466
553
|
{
|
|
467
554
|
value: props.value,
|
|
@@ -478,23 +565,46 @@ function Dashboard(props) {
|
|
|
478
565
|
const { exit } = useApp();
|
|
479
566
|
const size = useTerminalSize();
|
|
480
567
|
const bodyHeight = Math.max(12, size.rows - 5);
|
|
481
|
-
const [focus, setFocus] =
|
|
482
|
-
const [cursor, setCursor] =
|
|
483
|
-
const [selected, setSelected] =
|
|
568
|
+
const [focus, setFocus] = useState6("agents");
|
|
569
|
+
const [cursor, setCursor] = useState6(0);
|
|
570
|
+
const [selected, setSelected] = useState6(() => {
|
|
484
571
|
const first = props.session.agents[0];
|
|
485
572
|
return first ? { workflowId: first.workflowId, workflowName: first.workflowName } : void 0;
|
|
486
573
|
});
|
|
487
|
-
const [input, setInput] =
|
|
574
|
+
const [input, setInput] = useState6("");
|
|
488
575
|
const [chat, dispatch] = useReducer(chatReducer, initialChatState);
|
|
489
|
-
const [palette, setPalette] =
|
|
490
|
-
const [history, setHistory] =
|
|
576
|
+
const [palette, setPalette] = useState6(false);
|
|
577
|
+
const [history, setHistory] = useState6(false);
|
|
578
|
+
const [start, setStart] = useState6();
|
|
579
|
+
const [starting, setStarting] = useState6(false);
|
|
491
580
|
const controller = useRef2(null);
|
|
492
|
-
|
|
493
|
-
const selectAgent = () => {
|
|
581
|
+
useEffect5(() => () => controller.current?.abort(), []);
|
|
582
|
+
const selectAgent = async () => {
|
|
494
583
|
const agent = props.session.agents[cursor];
|
|
495
|
-
if (!agent || chat.running) return;
|
|
496
|
-
|
|
584
|
+
if (!agent || chat.running || starting) return;
|
|
585
|
+
const ref = { workflowId: agent.workflowId, workflowName: agent.workflowName };
|
|
586
|
+
setStarting(true);
|
|
587
|
+
let conversations = [];
|
|
588
|
+
try {
|
|
589
|
+
const all = await props.engine.listConversations(props.session.profile);
|
|
590
|
+
conversations = all.filter((item) => item.workflowId === ref.workflowId);
|
|
591
|
+
} catch {
|
|
592
|
+
conversations = [];
|
|
593
|
+
} finally {
|
|
594
|
+
setStarting(false);
|
|
595
|
+
}
|
|
596
|
+
if (conversations.length === 0) {
|
|
597
|
+
openNewChat(ref);
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
setSelected(ref);
|
|
601
|
+
setStart({ agent: ref, conversations });
|
|
602
|
+
};
|
|
603
|
+
const openNewChat = (ref) => {
|
|
604
|
+
setSelected(ref);
|
|
497
605
|
dispatch({ type: "reset" });
|
|
606
|
+
setInput("");
|
|
607
|
+
setStart(void 0);
|
|
498
608
|
setFocus("composer");
|
|
499
609
|
};
|
|
500
610
|
const openHistory = (conversation, turns) => {
|
|
@@ -503,6 +613,7 @@ function Dashboard(props) {
|
|
|
503
613
|
const index = props.session.agents.findIndex((agent) => agent.workflowId === conversation.workflowId);
|
|
504
614
|
if (index >= 0) setCursor(index);
|
|
505
615
|
setHistory(false);
|
|
616
|
+
setStart(void 0);
|
|
506
617
|
setFocus("composer");
|
|
507
618
|
};
|
|
508
619
|
const cancelTurn = () => {
|
|
@@ -543,7 +654,7 @@ function Dashboard(props) {
|
|
|
543
654
|
controller.current = null;
|
|
544
655
|
}
|
|
545
656
|
};
|
|
546
|
-
|
|
657
|
+
useInput5(
|
|
547
658
|
(keyInput, key) => {
|
|
548
659
|
if (key.ctrl && keyInput === "k") setPalette(true);
|
|
549
660
|
else if (key.ctrl && keyInput === "p") {
|
|
@@ -559,9 +670,11 @@ function Dashboard(props) {
|
|
|
559
670
|
else if (focus === "agents" && key.upArrow) setCursor((current) => Math.max(0, current - 1));
|
|
560
671
|
else if (focus === "agents" && key.downArrow && props.session.agents.length > 0) {
|
|
561
672
|
setCursor((current) => Math.min(props.session.agents.length - 1, current + 1));
|
|
562
|
-
} else if (focus === "agents" && key.return) selectAgent();
|
|
673
|
+
} else if (focus === "agents" && key.return) void selectAgent();
|
|
563
674
|
},
|
|
564
|
-
|
|
675
|
+
// 갈림길·팔레트·이력 화면이 떠 있으면 그 화면이 키를 갖는다 — 여기서도 받으면
|
|
676
|
+
// 방향키 하나가 두 곳에서 움직인다.
|
|
677
|
+
{ isActive: !palette && !history && !start }
|
|
565
678
|
);
|
|
566
679
|
const paletteActions = [
|
|
567
680
|
{ id: "new", label: "\uC0C8 \uB300\uD654", run: newConversation },
|
|
@@ -595,9 +708,9 @@ function Dashboard(props) {
|
|
|
595
708
|
];
|
|
596
709
|
let body;
|
|
597
710
|
if (palette) {
|
|
598
|
-
body = /* @__PURE__ */
|
|
711
|
+
body = /* @__PURE__ */ jsx6(CommandPalette, { actions: paletteActions, onCancel: () => setPalette(false) });
|
|
599
712
|
} else if (history) {
|
|
600
|
-
body = /* @__PURE__ */
|
|
713
|
+
body = /* @__PURE__ */ jsx6(
|
|
601
714
|
HistoryScreen,
|
|
602
715
|
{
|
|
603
716
|
engine: props.engine,
|
|
@@ -607,7 +720,7 @@ function Dashboard(props) {
|
|
|
607
720
|
}
|
|
608
721
|
);
|
|
609
722
|
} else {
|
|
610
|
-
const sidebar = /* @__PURE__ */
|
|
723
|
+
const sidebar = /* @__PURE__ */ jsx6(
|
|
611
724
|
AgentSidebar,
|
|
612
725
|
{
|
|
613
726
|
agents: props.session.agents,
|
|
@@ -617,9 +730,23 @@ function Dashboard(props) {
|
|
|
617
730
|
height: bodyHeight
|
|
618
731
|
}
|
|
619
732
|
);
|
|
620
|
-
const conversation = /* @__PURE__ */
|
|
621
|
-
|
|
622
|
-
|
|
733
|
+
const conversation = start ? /* @__PURE__ */ jsx6(
|
|
734
|
+
StartPanel,
|
|
735
|
+
{
|
|
736
|
+
engine: props.engine,
|
|
737
|
+
profile: props.session.profile,
|
|
738
|
+
agentName: start.agent.workflowName,
|
|
739
|
+
conversations: start.conversations,
|
|
740
|
+
onNew: () => openNewChat(start.agent),
|
|
741
|
+
onOpen: openHistory,
|
|
742
|
+
onCancel: () => {
|
|
743
|
+
setStart(void 0);
|
|
744
|
+
setFocus("agents");
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
) : /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", flexGrow: 1, children: [
|
|
748
|
+
/* @__PURE__ */ jsx6(ChatPane, { agent: selected, messages: chat.messages, status: chat.status, height: bodyHeight - 3 }),
|
|
749
|
+
/* @__PURE__ */ jsx6(
|
|
623
750
|
Composer,
|
|
624
751
|
{
|
|
625
752
|
value: input,
|
|
@@ -631,13 +758,13 @@ function Dashboard(props) {
|
|
|
631
758
|
}
|
|
632
759
|
)
|
|
633
760
|
] });
|
|
634
|
-
body = size.wide ? /* @__PURE__ */
|
|
761
|
+
body = size.wide ? /* @__PURE__ */ jsxs6(Box5, { height: bodyHeight, children: [
|
|
635
762
|
sidebar,
|
|
636
763
|
conversation
|
|
637
|
-
] }) : focus === "agents" ? /* @__PURE__ */
|
|
764
|
+
] }) : focus === "agents" ? /* @__PURE__ */ jsx6(Box5, { height: bodyHeight, children: sidebar }) : /* @__PURE__ */ jsx6(Box5, { height: bodyHeight, children: conversation });
|
|
638
765
|
}
|
|
639
|
-
return /* @__PURE__ */
|
|
640
|
-
/* @__PURE__ */
|
|
766
|
+
return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", children: [
|
|
767
|
+
/* @__PURE__ */ jsx6(
|
|
641
768
|
Header,
|
|
642
769
|
{
|
|
643
770
|
profile: props.session.profile,
|
|
@@ -646,22 +773,23 @@ function Dashboard(props) {
|
|
|
646
773
|
}
|
|
647
774
|
),
|
|
648
775
|
body,
|
|
649
|
-
/* @__PURE__ */
|
|
776
|
+
/* @__PURE__ */ jsx6(Footer, { text: "Tab \uD328\uB110 \xB7 Ctrl+K \uBA85\uB839 \xB7 Ctrl+H \uAE30\uB85D \xB7 Ctrl+P \uD504\uB85C\uD544 \xB7 Esc \uCDE8\uC18C \xB7 Ctrl+Q \uC885\uB8CC" })
|
|
650
777
|
] });
|
|
651
778
|
}
|
|
652
779
|
|
|
653
780
|
// src/tui/login-screen.tsx
|
|
654
|
-
import { useState as
|
|
655
|
-
import { Box as
|
|
656
|
-
import { jsx as
|
|
781
|
+
import { useState as useState7 } from "react";
|
|
782
|
+
import { Box as Box6, Text as Text7, useInput as useInput6 } from "ink";
|
|
783
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
657
784
|
function LoginScreen(props) {
|
|
658
|
-
const [email, setEmail] =
|
|
659
|
-
const [password, setPassword] =
|
|
660
|
-
const [focus, setFocus] =
|
|
661
|
-
|
|
785
|
+
const [email, setEmail] = useState7("");
|
|
786
|
+
const [password, setPassword] = useState7("");
|
|
787
|
+
const [focus, setFocus] = useState7("email");
|
|
788
|
+
useInput6(
|
|
662
789
|
(input, key) => {
|
|
663
790
|
if (key.tab) setFocus((current) => current === "email" ? "password" : "email");
|
|
664
791
|
if (key.ctrl && input === "p") props.onProfiles();
|
|
792
|
+
if (key.ctrl && input === "e") props.onEditServer();
|
|
665
793
|
},
|
|
666
794
|
{ isActive: !props.busy }
|
|
667
795
|
);
|
|
@@ -676,13 +804,17 @@ function LoginScreen(props) {
|
|
|
676
804
|
props.onSubmit(email.trim(), secret);
|
|
677
805
|
}
|
|
678
806
|
};
|
|
679
|
-
return /* @__PURE__ */
|
|
680
|
-
/* @__PURE__ */
|
|
681
|
-
/* @__PURE__ */
|
|
682
|
-
/* @__PURE__ */
|
|
683
|
-
/* @__PURE__ */
|
|
684
|
-
|
|
685
|
-
|
|
807
|
+
return /* @__PURE__ */ jsxs7(Box6, { flexDirection: "column", children: [
|
|
808
|
+
/* @__PURE__ */ jsx7(Header, { profile: props.profile, connected: false }),
|
|
809
|
+
/* @__PURE__ */ jsxs7(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "blue", padding: 1, children: [
|
|
810
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: "\uB85C\uADF8\uC778" }),
|
|
811
|
+
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
812
|
+
props.serverUrl,
|
|
813
|
+
" ",
|
|
814
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: "(Ctrl+E \uBC14\uAFB8\uAE30)" })
|
|
815
|
+
] }),
|
|
816
|
+
/* @__PURE__ */ jsxs7(Box6, { flexDirection: "column", marginTop: 1, children: [
|
|
817
|
+
/* @__PURE__ */ jsx7(
|
|
686
818
|
FormField,
|
|
687
819
|
{
|
|
688
820
|
label: "Email",
|
|
@@ -694,7 +826,7 @@ function LoginScreen(props) {
|
|
|
694
826
|
placeholder: "me@corp.com"
|
|
695
827
|
}
|
|
696
828
|
),
|
|
697
|
-
/* @__PURE__ */
|
|
829
|
+
/* @__PURE__ */ jsx7(
|
|
698
830
|
FormField,
|
|
699
831
|
{
|
|
700
832
|
label: "Password",
|
|
@@ -707,25 +839,25 @@ function LoginScreen(props) {
|
|
|
707
839
|
}
|
|
708
840
|
)
|
|
709
841
|
] }),
|
|
710
|
-
props.busy ? /* @__PURE__ */
|
|
711
|
-
props.error ? /* @__PURE__ */
|
|
842
|
+
props.busy ? /* @__PURE__ */ jsx7(Loading, { label: "\uB85C\uADF8\uC778\uD558\uB294 \uC911..." }) : null,
|
|
843
|
+
props.error ? /* @__PURE__ */ jsx7(Notice, { error: true, children: props.error }) : null
|
|
712
844
|
] }),
|
|
713
|
-
/* @__PURE__ */
|
|
845
|
+
/* @__PURE__ */ jsx7(Footer, { text: "Tab \uC774\uB3D9 \xB7 Enter \uB85C\uADF8\uC778 \xB7 Ctrl+E \uC11C\uBC84 \xB7 Ctrl+P \uD504\uB85C\uD544 \xB7 Ctrl+Q \uC885\uB8CC" })
|
|
714
846
|
] });
|
|
715
847
|
}
|
|
716
848
|
|
|
717
849
|
// src/tui/profile-screen.tsx
|
|
718
|
-
import { useEffect as
|
|
719
|
-
import { Box as
|
|
720
|
-
import { jsx as
|
|
850
|
+
import { useEffect as useEffect6, useState as useState8 } from "react";
|
|
851
|
+
import { Box as Box7, Text as Text8, useInput as useInput7 } from "ink";
|
|
852
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
721
853
|
function ProfileScreen(props) {
|
|
722
|
-
const [cursor, setCursor] =
|
|
723
|
-
const [creating, setCreating] =
|
|
724
|
-
const [focus, setFocus] =
|
|
725
|
-
const [name, setName] =
|
|
726
|
-
const [serverUrl, setServerUrl] =
|
|
727
|
-
|
|
728
|
-
|
|
854
|
+
const [cursor, setCursor] = useState8(Math.max(0, props.profiles.findIndex((profile) => profile.current)));
|
|
855
|
+
const [creating, setCreating] = useState8(false);
|
|
856
|
+
const [focus, setFocus] = useState8("name");
|
|
857
|
+
const [name, setName] = useState8("");
|
|
858
|
+
const [serverUrl, setServerUrl] = useState8("");
|
|
859
|
+
useEffect6(() => setCursor((current) => Math.min(current, Math.max(0, props.profiles.length - 1))), [props.profiles]);
|
|
860
|
+
useInput7(
|
|
729
861
|
(input, key) => {
|
|
730
862
|
if (key.escape) {
|
|
731
863
|
if (creating) setCreating(false);
|
|
@@ -755,12 +887,12 @@ function ProfileScreen(props) {
|
|
|
755
887
|
}
|
|
756
888
|
if (name.trim() && serverUrl.trim()) props.onCreate(name.trim(), serverUrl.trim());
|
|
757
889
|
};
|
|
758
|
-
return /* @__PURE__ */
|
|
759
|
-
/* @__PURE__ */
|
|
760
|
-
/* @__PURE__ */
|
|
761
|
-
/* @__PURE__ */
|
|
762
|
-
creating ? /* @__PURE__ */
|
|
763
|
-
/* @__PURE__ */
|
|
890
|
+
return /* @__PURE__ */ jsxs8(Box7, { flexDirection: "column", children: [
|
|
891
|
+
/* @__PURE__ */ jsx8(Header, {}),
|
|
892
|
+
/* @__PURE__ */ jsxs8(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [
|
|
893
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, children: creating ? "\uC0C8 \uD504\uB85C\uD544" : "\uD504\uB85C\uD544 \uC804\uD658" }),
|
|
894
|
+
creating ? /* @__PURE__ */ jsxs8(Box7, { flexDirection: "column", marginTop: 1, children: [
|
|
895
|
+
/* @__PURE__ */ jsx8(
|
|
764
896
|
FormField,
|
|
765
897
|
{
|
|
766
898
|
label: "Name",
|
|
@@ -772,7 +904,7 @@ function ProfileScreen(props) {
|
|
|
772
904
|
placeholder: "corp"
|
|
773
905
|
}
|
|
774
906
|
),
|
|
775
|
-
/* @__PURE__ */
|
|
907
|
+
/* @__PURE__ */ jsx8(
|
|
776
908
|
FormField,
|
|
777
909
|
{
|
|
778
910
|
label: "Server URL",
|
|
@@ -784,8 +916,8 @@ function ProfileScreen(props) {
|
|
|
784
916
|
placeholder: "https://xgen.example.com"
|
|
785
917
|
}
|
|
786
918
|
)
|
|
787
|
-
] }) : /* @__PURE__ */
|
|
788
|
-
props.profiles.map((profile, index) => /* @__PURE__ */
|
|
919
|
+
] }) : /* @__PURE__ */ jsxs8(Box7, { flexDirection: "column", marginTop: 1, children: [
|
|
920
|
+
props.profiles.map((profile, index) => /* @__PURE__ */ jsxs8(Text8, { color: index === cursor ? "cyan" : void 0, children: [
|
|
789
921
|
index === cursor ? "\u203A" : " ",
|
|
790
922
|
" ",
|
|
791
923
|
profile.current ? "\u25CF" : "\u25CB",
|
|
@@ -793,14 +925,14 @@ function ProfileScreen(props) {
|
|
|
793
925
|
profile.name,
|
|
794
926
|
" \xB7",
|
|
795
927
|
" ",
|
|
796
|
-
/* @__PURE__ */
|
|
928
|
+
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: profile.serverUrl })
|
|
797
929
|
] }, profile.name)),
|
|
798
|
-
props.profiles.length === 0 ? /* @__PURE__ */
|
|
930
|
+
props.profiles.length === 0 ? /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "\uC800\uC7A5\uB41C \uD504\uB85C\uD544\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." }) : null
|
|
799
931
|
] }),
|
|
800
|
-
props.busy ? /* @__PURE__ */
|
|
801
|
-
props.error ? /* @__PURE__ */
|
|
932
|
+
props.busy ? /* @__PURE__ */ jsx8(Loading, { label: "\uD504\uB85C\uD544\uC744 \uC804\uD658\uD558\uB294 \uC911..." }) : null,
|
|
933
|
+
props.error ? /* @__PURE__ */ jsx8(Notice, { error: true, children: props.error }) : null
|
|
802
934
|
] }),
|
|
803
|
-
/* @__PURE__ */
|
|
935
|
+
/* @__PURE__ */ jsx8(
|
|
804
936
|
Footer,
|
|
805
937
|
{
|
|
806
938
|
text: creating ? "Tab \uC774\uB3D9 \xB7 Enter \uC800\uC7A5 \xB7 Esc \uB4A4\uB85C" : "\u2191\u2193 \uC774\uB3D9 \xB7 Enter \uC120\uD0DD \xB7 N \uC0C8 \uD504\uB85C\uD544 \xB7 Esc \uB2EB\uAE30"
|
|
@@ -809,18 +941,25 @@ function ProfileScreen(props) {
|
|
|
809
941
|
] });
|
|
810
942
|
}
|
|
811
943
|
|
|
812
|
-
// src/tui/
|
|
813
|
-
import { useState as
|
|
814
|
-
import { Box as
|
|
815
|
-
import { jsx as
|
|
816
|
-
function
|
|
817
|
-
const [serverUrl, setServerUrl] =
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
944
|
+
// src/tui/server-screen.tsx
|
|
945
|
+
import { useState as useState9 } from "react";
|
|
946
|
+
import { Box as Box8, Text as Text9, useInput as useInput8 } from "ink";
|
|
947
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
948
|
+
function ServerScreen(props) {
|
|
949
|
+
const [serverUrl, setServerUrl] = useState9(props.initialValue ?? "");
|
|
950
|
+
const editing = props.initialValue !== void 0;
|
|
951
|
+
useInput8(
|
|
952
|
+
(_input, key) => {
|
|
953
|
+
if (key.escape) props.onCancel?.();
|
|
954
|
+
},
|
|
955
|
+
{ isActive: !props.busy && !!props.onCancel }
|
|
956
|
+
);
|
|
957
|
+
return /* @__PURE__ */ jsxs9(Box8, { flexDirection: "column", children: [
|
|
958
|
+
/* @__PURE__ */ jsx9(Header, { profile: props.profile, connected: false }),
|
|
959
|
+
/* @__PURE__ */ jsxs9(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "blue", padding: 1, children: [
|
|
960
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, children: editing ? "\uC11C\uBC84 \uC8FC\uC18C \uBC14\uAFB8\uAE30" : "\uCC98\uC74C \uC624\uC168\uAD70\uC694" }),
|
|
961
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "\uC5F0\uACB0\uD560 XGEN Gateway \uC8FC\uC18C\uB97C \uC785\uB825\uD558\uC138\uC694." }),
|
|
962
|
+
/* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(
|
|
824
963
|
FormField,
|
|
825
964
|
{
|
|
826
965
|
label: "Server URL",
|
|
@@ -829,27 +968,34 @@ function SetupScreen(props) {
|
|
|
829
968
|
onSubmit: (value) => value.trim() && props.onSubmit(value.trim()),
|
|
830
969
|
focus: !props.busy,
|
|
831
970
|
cursorOrigin: { x: 16, y: 6 },
|
|
832
|
-
placeholder: "
|
|
971
|
+
placeholder: "xgen.example.com"
|
|
833
972
|
}
|
|
834
973
|
) }),
|
|
835
|
-
|
|
836
|
-
props.
|
|
974
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "https:// \uB294 \uC0DD\uB7B5\uD574\uB3C4 \uB429\uB2C8\uB2E4." }),
|
|
975
|
+
props.busy ? /* @__PURE__ */ jsx9(Loading, { label: "\uC11C\uBC84 \uD504\uB85C\uD544\uC744 \uC800\uC7A5\uD558\uB294 \uC911..." }) : null,
|
|
976
|
+
props.error ? /* @__PURE__ */ jsx9(Notice, { error: true, children: props.error }) : null
|
|
837
977
|
] }),
|
|
838
|
-
/* @__PURE__ */
|
|
978
|
+
/* @__PURE__ */ jsx9(
|
|
979
|
+
Footer,
|
|
980
|
+
{
|
|
981
|
+
text: props.onCancel ? "Enter \uC800\uC7A5 \xB7 Esc \uCDE8\uC18C \xB7 Ctrl+Q \uC885\uB8CC" : "Enter \uACC4\uC18D \xB7 Ctrl+Q \uC885\uB8CC"
|
|
982
|
+
}
|
|
983
|
+
)
|
|
839
984
|
] });
|
|
840
985
|
}
|
|
841
986
|
|
|
842
987
|
// src/tui/app.tsx
|
|
843
|
-
import { jsx as
|
|
988
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
844
989
|
function App({ engine }) {
|
|
845
990
|
const { exit } = useApp2();
|
|
846
|
-
const [route, setRoute] =
|
|
847
|
-
const [session, setSession] =
|
|
848
|
-
const [profiles, setProfiles] =
|
|
849
|
-
const [loginTarget, setLoginTarget] =
|
|
850
|
-
const [
|
|
851
|
-
const [
|
|
852
|
-
|
|
991
|
+
const [route, setRoute] = useState10("boot");
|
|
992
|
+
const [session, setSession] = useState10();
|
|
993
|
+
const [profiles, setProfiles] = useState10([]);
|
|
994
|
+
const [loginTarget, setLoginTarget] = useState10();
|
|
995
|
+
const [editingServer, setEditingServer] = useState10();
|
|
996
|
+
const [busy, setBusy] = useState10(false);
|
|
997
|
+
const [error, setError] = useState10();
|
|
998
|
+
useInput9((input, key) => {
|
|
853
999
|
if (key.ctrl && input === "q") exit();
|
|
854
1000
|
});
|
|
855
1001
|
const bootstrap = useCallback(
|
|
@@ -862,7 +1008,7 @@ function App({ engine }) {
|
|
|
862
1008
|
setProfiles(available);
|
|
863
1009
|
if (available.length === 0) {
|
|
864
1010
|
setSession(void 0);
|
|
865
|
-
setRoute("
|
|
1011
|
+
setRoute("server");
|
|
866
1012
|
return;
|
|
867
1013
|
}
|
|
868
1014
|
if (preferredProfile) {
|
|
@@ -899,17 +1045,19 @@ function App({ engine }) {
|
|
|
899
1045
|
},
|
|
900
1046
|
[engine]
|
|
901
1047
|
);
|
|
902
|
-
|
|
1048
|
+
useEffect7(() => {
|
|
903
1049
|
void bootstrap();
|
|
904
1050
|
}, [bootstrap]);
|
|
905
1051
|
const configure = async (serverUrl) => {
|
|
906
1052
|
setBusy(true);
|
|
907
1053
|
setError(void 0);
|
|
1054
|
+
const target = editingServer?.profile ?? loginTarget?.profile ?? "default";
|
|
908
1055
|
try {
|
|
909
|
-
const profile = await engine.setProfile(
|
|
1056
|
+
const profile = await engine.setProfile(target, serverUrl);
|
|
910
1057
|
await engine.useProfile(profile.name);
|
|
911
1058
|
setLoginTarget({ profile: profile.name, serverUrl: profile.serverUrl });
|
|
912
1059
|
setProfiles(await engine.listProfiles());
|
|
1060
|
+
setEditingServer(void 0);
|
|
913
1061
|
setRoute("login");
|
|
914
1062
|
} catch (reason) {
|
|
915
1063
|
setError(publicError(reason).message);
|
|
@@ -972,17 +1120,31 @@ function App({ engine }) {
|
|
|
972
1120
|
}
|
|
973
1121
|
};
|
|
974
1122
|
if (route === "boot") {
|
|
975
|
-
return /* @__PURE__ */
|
|
976
|
-
/* @__PURE__ */
|
|
977
|
-
/* @__PURE__ */
|
|
978
|
-
/* @__PURE__ */
|
|
1123
|
+
return /* @__PURE__ */ jsxs10(Box9, { flexDirection: "column", children: [
|
|
1124
|
+
/* @__PURE__ */ jsx10(Header, {}),
|
|
1125
|
+
/* @__PURE__ */ jsx10(Loading, { label: "Dex\uB97C \uC900\uBE44\uD558\uB294 \uC911..." }),
|
|
1126
|
+
/* @__PURE__ */ jsx10(Footer, { text: "Ctrl+Q \uC885\uB8CC" })
|
|
979
1127
|
] });
|
|
980
1128
|
}
|
|
981
|
-
if (route === "
|
|
982
|
-
return /* @__PURE__ */
|
|
1129
|
+
if (route === "server") {
|
|
1130
|
+
return /* @__PURE__ */ jsx10(
|
|
1131
|
+
ServerScreen,
|
|
1132
|
+
{
|
|
1133
|
+
initialValue: editingServer?.serverUrl,
|
|
1134
|
+
profile: editingServer?.profile,
|
|
1135
|
+
busy,
|
|
1136
|
+
error,
|
|
1137
|
+
onSubmit: (url) => void configure(url),
|
|
1138
|
+
onCancel: editingServer ? () => {
|
|
1139
|
+
setEditingServer(void 0);
|
|
1140
|
+
setError(void 0);
|
|
1141
|
+
setRoute("login");
|
|
1142
|
+
} : void 0
|
|
1143
|
+
}
|
|
1144
|
+
);
|
|
983
1145
|
}
|
|
984
1146
|
if (route === "login" && loginTarget) {
|
|
985
|
-
return /* @__PURE__ */
|
|
1147
|
+
return /* @__PURE__ */ jsx10(
|
|
986
1148
|
LoginScreen,
|
|
987
1149
|
{
|
|
988
1150
|
profile: loginTarget.profile,
|
|
@@ -990,12 +1152,17 @@ function App({ engine }) {
|
|
|
990
1152
|
busy,
|
|
991
1153
|
error,
|
|
992
1154
|
onSubmit: (email, password) => void login(email, password),
|
|
993
|
-
onProfiles: () => void openProfiles()
|
|
1155
|
+
onProfiles: () => void openProfiles(),
|
|
1156
|
+
onEditServer: () => {
|
|
1157
|
+
setEditingServer(loginTarget);
|
|
1158
|
+
setError(void 0);
|
|
1159
|
+
setRoute("server");
|
|
1160
|
+
}
|
|
994
1161
|
}
|
|
995
1162
|
);
|
|
996
1163
|
}
|
|
997
1164
|
if (route === "profiles") {
|
|
998
|
-
return /* @__PURE__ */
|
|
1165
|
+
return /* @__PURE__ */ jsx10(
|
|
999
1166
|
ProfileScreen,
|
|
1000
1167
|
{
|
|
1001
1168
|
profiles,
|
|
@@ -1003,12 +1170,12 @@ function App({ engine }) {
|
|
|
1003
1170
|
error,
|
|
1004
1171
|
onSelect: (name) => void bootstrap(name),
|
|
1005
1172
|
onCreate: (name, url) => void createProfile(name, url),
|
|
1006
|
-
onCancel: () => setRoute(session ? "dashboard" : loginTarget ? "login" : "
|
|
1173
|
+
onCancel: () => setRoute(session ? "dashboard" : loginTarget ? "login" : "server")
|
|
1007
1174
|
}
|
|
1008
1175
|
);
|
|
1009
1176
|
}
|
|
1010
1177
|
if (route === "dashboard" && session) {
|
|
1011
|
-
return /* @__PURE__ */
|
|
1178
|
+
return /* @__PURE__ */ jsx10(
|
|
1012
1179
|
Dashboard,
|
|
1013
1180
|
{
|
|
1014
1181
|
engine,
|
|
@@ -1018,31 +1185,72 @@ function App({ engine }) {
|
|
|
1018
1185
|
}
|
|
1019
1186
|
);
|
|
1020
1187
|
}
|
|
1021
|
-
return /* @__PURE__ */
|
|
1022
|
-
/* @__PURE__ */
|
|
1023
|
-
/* @__PURE__ */
|
|
1024
|
-
/* @__PURE__ */
|
|
1025
|
-
/* @__PURE__ */
|
|
1026
|
-
/* @__PURE__ */
|
|
1188
|
+
return /* @__PURE__ */ jsxs10(Box9, { flexDirection: "column", children: [
|
|
1189
|
+
/* @__PURE__ */ jsx10(Header, {}),
|
|
1190
|
+
/* @__PURE__ */ jsx10(Notice, { error: true, children: error ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4." }),
|
|
1191
|
+
/* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\uC11C\uBC84\uC640 \uD0A4\uCCB4\uC778 \uC0C1\uD0DC\uB97C \uD655\uC778\uD55C \uB4A4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694." }),
|
|
1192
|
+
/* @__PURE__ */ jsx10(Footer, { text: "R \uB2E4\uC2DC \uC2DC\uB3C4 \xB7 Ctrl+Q \uC885\uB8CC" }),
|
|
1193
|
+
/* @__PURE__ */ jsx10(RetryInput, { onRetry: () => void bootstrap() })
|
|
1027
1194
|
] });
|
|
1028
1195
|
}
|
|
1029
1196
|
function RetryInput({ onRetry }) {
|
|
1030
|
-
|
|
1197
|
+
useInput9((input) => {
|
|
1031
1198
|
if (input.toLowerCase() === "r") onRetry();
|
|
1032
1199
|
});
|
|
1033
1200
|
return null;
|
|
1034
1201
|
}
|
|
1035
1202
|
|
|
1203
|
+
// src/tui/screen.ts
|
|
1204
|
+
var ESC = "\x1B";
|
|
1205
|
+
var ENTER_ALT_SCREEN = `${ESC}[?1049h`;
|
|
1206
|
+
var LEAVE_ALT_SCREEN = `${ESC}[?1049l`;
|
|
1207
|
+
var SHOW_CURSOR = `${ESC}[?25h`;
|
|
1208
|
+
function createScreenGuard(stream) {
|
|
1209
|
+
const alt = Boolean(stream.isTTY);
|
|
1210
|
+
let entered = false;
|
|
1211
|
+
let restored = false;
|
|
1212
|
+
return {
|
|
1213
|
+
enter() {
|
|
1214
|
+
if (entered || !alt) return;
|
|
1215
|
+
entered = true;
|
|
1216
|
+
stream.write(ENTER_ALT_SCREEN);
|
|
1217
|
+
},
|
|
1218
|
+
restore() {
|
|
1219
|
+
if (restored) return;
|
|
1220
|
+
restored = true;
|
|
1221
|
+
if (entered) stream.write(LEAVE_ALT_SCREEN);
|
|
1222
|
+
stream.write(SHOW_CURSOR);
|
|
1223
|
+
}
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1036
1227
|
// src/tui/index.tsx
|
|
1037
|
-
import { jsx as
|
|
1228
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1038
1229
|
async function runTui(engine) {
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1230
|
+
const screen = createScreenGuard(stdout);
|
|
1231
|
+
const restore = () => screen.restore();
|
|
1232
|
+
const onSignal = () => {
|
|
1233
|
+
restore();
|
|
1234
|
+
process.exit(0);
|
|
1235
|
+
};
|
|
1236
|
+
process.once("exit", restore);
|
|
1237
|
+
process.once("SIGINT", onSignal);
|
|
1238
|
+
process.once("SIGTERM", onSignal);
|
|
1239
|
+
screen.enter();
|
|
1240
|
+
try {
|
|
1241
|
+
const instance = render(/* @__PURE__ */ jsx11(App, { engine }), {
|
|
1242
|
+
exitOnCtrlC: true,
|
|
1243
|
+
patchConsole: true
|
|
1244
|
+
});
|
|
1245
|
+
await instance.waitUntilExit();
|
|
1246
|
+
} finally {
|
|
1247
|
+
restore();
|
|
1248
|
+
process.off("exit", restore);
|
|
1249
|
+
process.off("SIGINT", onSignal);
|
|
1250
|
+
process.off("SIGTERM", onSignal);
|
|
1251
|
+
}
|
|
1044
1252
|
}
|
|
1045
1253
|
export {
|
|
1046
1254
|
runTui
|
|
1047
1255
|
};
|
|
1048
|
-
//# sourceMappingURL=tui-
|
|
1256
|
+
//# sourceMappingURL=tui-MLHYSLBS.js.map
|