xgen-dex-cli 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -527,9 +527,18 @@ function parseKeyEvents(chunk) {
527
527
  }
528
528
  return events;
529
529
  }
530
- async function supportsKittyKeyboard(streams, timeoutMs = 200) {
531
- if (process.env.DEX_NO_KITTY === "1") return false;
530
+ function knownKittyTerminal(env = process.env) {
531
+ if (env.KITTY_WINDOW_ID) return true;
532
+ if (env.GHOSTTY_RESOURCES_DIR) return true;
533
+ const term = (env.TERM ?? "").toLowerCase();
534
+ if (term === "xterm-kitty" || term === "xterm-ghostty" || term.includes("foot")) return true;
535
+ const program = (env.TERM_PROGRAM ?? "").toLowerCase();
536
+ return program === "wezterm" || program === "ghostty" || program === "kitty";
537
+ }
538
+ async function supportsKittyKeyboard(streams, timeoutMs = 200, env = process.env) {
539
+ if (env.DEX_NO_KITTY === "1") return false;
532
540
  if (!streams.stdout.isTTY || !streams.isTTY) return false;
541
+ if (knownKittyTerminal(env)) return true;
533
542
  const wasRaw = streams.stdin.isRaw === true;
534
543
  const wasPaused = !wasRaw;
535
544
  streams.stdin.setRawMode?.(true);
@@ -589,6 +598,12 @@ function visibleInput(segments, cursor, maximumWidth) {
589
598
  cursorWidth: widthBeforeCursor
590
599
  };
591
600
  }
601
+ function isHangulToggle(input, key) {
602
+ if (key.ctrl && (input === "`" || input === " " || input === "l")) return true;
603
+ if (key.meta && input === " ") return true;
604
+ if (key.shift && input === " ") return true;
605
+ return false;
606
+ }
592
607
  function TerminalCursor({ x, y }) {
593
608
  const { setCursorPosition } = useCursor();
594
609
  setCursorPosition({ x, y });
@@ -674,7 +689,7 @@ function ImeTextInput(props) {
674
689
  }
675
690
  return;
676
691
  }
677
- if (key.ctrl && (input === "`" || input === "l") || key.meta && input === " ") {
692
+ if (isHangulToggle(input, key)) {
678
693
  settle();
679
694
  props.onHangulModeChange?.(!props.hangulMode);
680
695
  return;
@@ -1857,11 +1872,18 @@ async function runTui(engine) {
1857
1872
  {
1858
1873
  exitOnCtrlC: true,
1859
1874
  patchConsole: true,
1860
- // 모든 키를 이스케이프로 받아야 수식자체가 사건으로 온다.
1875
+ // 모든 키를 이스케이프로 받아야 한/영(오른쪽 Alt)와 Caps Lock 이 사건으로
1876
+ // 온다. 그런데 그렇게만 켜면 터미널이 **글쇠 코드만** 보내서 Shift+r 이
1877
+ // 소문자 `r` 로 도착한다 — 된소리도 영문 대문자도 사라진다. 그래서 글자까지
1878
+ // 함께 보내 달라고(reportAssociatedText) 요청한다.
1861
1879
  ...kitty ? {
1862
1880
  kittyKeyboard: {
1863
1881
  mode: "enabled",
1864
- flags: ["disambiguateEscapeCodes", "reportAllKeysAsEscapeCodes"]
1882
+ flags: [
1883
+ "disambiguateEscapeCodes",
1884
+ "reportAllKeysAsEscapeCodes",
1885
+ "reportAssociatedText"
1886
+ ]
1865
1887
  }
1866
1888
  } : {}
1867
1889
  }
@@ -1877,4 +1899,4 @@ async function runTui(engine) {
1877
1899
  export {
1878
1900
  runTui
1879
1901
  };
1880
- //# sourceMappingURL=tui-QF5OJEFW.js.map
1902
+ //# sourceMappingURL=tui-H3VM2MGV.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/tui/index.tsx", "../../src/tui/app.tsx", "../../src/tui/dashboard.tsx", "../../src/tui/chat-state.ts", "../../src/tui/measure.ts", "../../src/tui/transcript.ts", "../../src/tui/command-palette.tsx", "../../src/tui/components.tsx", "../../src/tui/ime-text-input.tsx", "../../src/tui/terminal-input.ts", "../../src/tui/hangul.ts", "../../src/tui/kitty.ts", "../../src/tui/history-screen.tsx", "../../src/tui/start-panel.tsx", "../../src/tui/use-terminal-size.ts", "../../src/tui/login-screen.tsx", "../../src/tui/profile-screen.tsx", "../../src/tui/server-screen.tsx", "../../src/tui/screen.ts", "../../src/tui/preferences.ts"],
4
+ "sourcesContent": ["import { render } from 'ink';\nimport { stdin, stdout } from 'node:process';\nimport type { DexEngine } from '@dex/engine';\nimport { App } from './app';\nimport { createScreenGuard } from './screen';\nimport { readPreferences, writePreferences } from './preferences';\nimport { supportsKittyKeyboard } from './kitty';\n\n/**\n * TUI \uB97C \uB300\uCCB4 \uD654\uBA74\uC5D0\uC11C \uB744\uC6B4\uB2E4. \uADDC\uCE59\uC740 `./screen` \uC5D0 \uC788\uB2E4 \u2014 \uC5EC\uAE30\uC11C\uB294 \uD504\uB85C\uC138\uC2A4\uAC00\n * **\uC5B4\uB5BB\uAC8C \uB05D\uB098\uB4E0** \uB418\uB3CC\uC544\uAC00\uAC8C \uBC30\uC120\uB9CC \uD55C\uB2E4.\n */\nexport async function runTui(engine: DexEngine): Promise<void> {\n let screen = createScreenGuard(stdout);\n const restore = (): void => screen.restore();\n\n // SIGINT/SIGTERM \uC740 Ink \uC758 \uC815\uB9AC\uB97C \uAC70\uCE58\uC9C0 \uC54A\uACE0 \uACE7\uC7A5 \uC8FD\uC744 \uC218 \uC788\uB2E4. 'exit' \uC740\n // process.exit() \uC640 \uC608\uC678\uB85C \uC8FD\uB294 \uACBD\uC6B0\uAE4C\uC9C0 \uBC1B\uB294\uB2E4.\n const onSignal = (): void => {\n restore();\n process.exit(0);\n };\n process.once('exit', restore);\n process.once('SIGINT', onSignal);\n process.once('SIGTERM', onSignal);\n\n // \uCDE8\uD5A5\uC740 \uADF8\uB9AC\uAE30 \uC804\uC5D0 \uC77D\uB294\uB2E4. \uB098\uC911\uC5D0 \uC77D\uC73C\uBA74 \uCCAB \uD504\uB808\uC784\uC774 EN \uC73C\uB85C \uB5B4\uB2E4\uAC00 \uBC14\uB00C\uC5B4,\n // \uD55C\uAE00\uB85C \uC4F0\uB358 \uC0AC\uB78C\uC5D0\uAC8C\uB294 \uBAA8\uB4DC\uAC00 \uAEBC\uC9C4 \uAC83\uCC98\uB7FC \uBCF4\uC778\uB2E4.\n const preferences = await readPreferences();\n\n // \uD55C/\uC601 \uD0A4(\uC624\uB978\uCABD Alt \uC790\uB9AC)\uC640 Caps Lock \uC740 \uAE00\uC790\uB97C \uB9CC\uB4E4\uC9C0 \uC54A\uC544 \uBCF4\uD1B5 \uC571\uC5D0 \uC624\uC9C0\n // \uC54A\uB294\uB2E4. \uADF8 \uD0A4\uB4E4\uAE4C\uC9C0 \uBCF4\uACE0\uD558\uB294 \uD130\uBBF8\uB110\uC778\uC9C0 \uBA3C\uC800 \uBB3C\uC5B4\uBCF8\uB2E4 \u2014 ink \uC740 kitty\u00B7ghostty\u00B7\n // WezTerm \uB9CC \uC774\uB984\uC73C\uB85C \uC9D0\uC791\uD558\uC9C0\uB9CC, \uC694\uC998\uC740 \uB354 \uB9CE\uC740 \uD130\uBBF8\uB110\uC774 \uC774 \uD504\uB85C\uD1A0\uCF5C\uC744 \uC548\uB2E4.\n const kitty = await supportsKittyKeyboard({ stdin, stdout, isTTY: stdin.isTTY });\n screen = createScreenGuard(stdout, { kittyKeyboard: kitty });\n\n screen.enter();\n\n try {\n const instance = render(\n <App\n engine={engine}\n preferences={{\n hangulMode: preferences.hangulMode,\n onHangulModeChange: (enabled) => void writePreferences({ hangulMode: enabled }),\n }}\n />,\n {\n exitOnCtrlC: true,\n patchConsole: true,\n // \uBAA8\uB4E0 \uD0A4\uB97C \uC774\uC2A4\uCF00\uC774\uD504\uB85C \uBC1B\uC544\uC57C \uD55C/\uC601 \uD0A4(\uC624\uB978\uCABD Alt)\uC640 Caps Lock \uC774 \uC0AC\uAC74\uC73C\uB85C\n // \uC628\uB2E4. \uADF8\uB7F0\uB370 \uADF8\uB807\uAC8C\uB9CC \uCF1C\uBA74 \uD130\uBBF8\uB110\uC774 **\uAE00\uC1E0 \uCF54\uB4DC\uB9CC** \uBCF4\uB0B4\uC11C Shift+r \uC774\n // \uC18C\uBB38\uC790 `r` \uB85C \uB3C4\uCC29\uD55C\uB2E4 \u2014 \uB41C\uC18C\uB9AC\uB3C4 \uC601\uBB38 \uB300\uBB38\uC790\uB3C4 \uC0AC\uB77C\uC9C4\uB2E4. \uADF8\uB798\uC11C \uAE00\uC790\uAE4C\uC9C0\n // \uD568\uAED8 \uBCF4\uB0B4 \uB2EC\uB77C\uACE0(reportAssociatedText) \uC694\uCCAD\uD55C\uB2E4.\n ...(kitty\n ? {\n kittyKeyboard: {\n mode: 'enabled' as const,\n flags: [\n 'disambiguateEscapeCodes' as const,\n 'reportAllKeysAsEscapeCodes' as const,\n 'reportAssociatedText' as const,\n ],\n },\n }\n : {}),\n },\n );\n await instance.waitUntilExit();\n } finally {\n restore();\n process.off('exit', restore);\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n }\n}\n", "import { useCallback, useEffect, useState } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport { DexError, publicError } from '@dex/engine';\nimport type { ProfileSummary } from '@dex/engine';\nimport { Dashboard } from './dashboard';\nimport { Footer, Header, Loading, Notice } from './components';\nimport { LoginScreen } from './login-screen';\nimport type { TuiEngine, TuiSession } from './model';\nimport { ProfileScreen } from './profile-screen';\nimport { ServerScreen } from './server-screen';\n\ntype Route = 'boot' | 'server' | 'login' | 'dashboard' | 'profiles' | 'fatal';\n\nexport function App({\n engine,\n preferences,\n}: {\n engine: TuiEngine;\n /** \uAE30\uC5B5\uD574 \uB454 \uD130\uBBF8\uB110 \uCDE8\uD5A5. \uC9C0\uAE08\uC740 \uD55C/\uC601 \uD558\uB098\uBFD0\uC774\uB2E4. */\n preferences?: { hangulMode: boolean; onHangulModeChange?: (enabled: boolean) => void };\n}): React.ReactNode {\n const { exit } = useApp();\n const [route, setRoute] = useState<Route>('boot');\n const [session, setSession] = useState<TuiSession>();\n const [profiles, setProfiles] = useState<ProfileSummary[]>([]);\n const [loginTarget, setLoginTarget] = useState<{ profile: string; serverUrl: string }>();\n /** \uC11C\uBC84 \uC8FC\uC18C\uB97C \uACE0\uCE58\uB294 \uC911 \u2014 \uC9C0\uAE08 \uAC12\uC774 \uD654\uBA74\uC5D0 \uCC44\uC6CC\uC9C4\uB2E4. */\n const [editingServer, setEditingServer] = useState<{ profile: string; serverUrl: string }>();\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string>();\n\n useInput((input, key) => {\n if (key.ctrl && input === 'q') exit();\n });\n\n const bootstrap = useCallback(\n async (preferredProfile?: string): Promise<void> => {\n setRoute('boot');\n setBusy(true);\n setError(undefined);\n try {\n let available = await engine.listProfiles();\n setProfiles(available);\n if (available.length === 0) {\n setSession(undefined);\n setRoute('server');\n return;\n }\n if (preferredProfile) {\n await engine.useProfile(preferredProfile);\n available = await engine.listProfiles();\n setProfiles(available);\n }\n const current =\n available.find((profile) => profile.current) ??\n available.find((profile) => profile.name === preferredProfile) ??\n available[0];\n if (!current) throw new DexError('config_invalid', '\uC0AC\uC6A9\uD560 \uD504\uB85C\uD544\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.');\n const status = await engine.authStatus(current.name);\n if (!status.authenticated) {\n if (status.reason === 'network') {\n throw new DexError('network_error', `XGEN \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${current.serverUrl}`);\n }\n setSession(undefined);\n setLoginTarget({ profile: current.name, serverUrl: current.serverUrl });\n setRoute('login');\n return;\n }\n const agents = await engine.listAgents({ pageSize: 100, includeHarness: true }, current.name);\n setSession({\n profile: current.name,\n serverUrl: current.serverUrl,\n username: status.user?.username ?? 'unknown',\n agents: agents.items,\n });\n setRoute('dashboard');\n } catch (reason) {\n setError(publicError(reason).message);\n setRoute('fatal');\n } finally {\n setBusy(false);\n }\n },\n [engine],\n );\n\n useEffect(() => {\n void bootstrap();\n }, [bootstrap]);\n\n /**\n * \uC11C\uBC84 \uC8FC\uC18C\uB97C \uC815\uD55C\uB2E4 \u2014 \uCC98\uC74C\uC774\uB4E0 \uACE0\uCE58\uB294 \uAC83\uC774\uB4E0 \uAC19\uC740 \uAE38.\n *\n * \uACE0\uCE60 \uB54C\uB294 **\uC9C0\uAE08 \uD504\uB85C\uD544\uC744 \uADF8\uB300\uB85C \uB36E\uC5B4\uC4F4\uB2E4.** \uC608\uC804\uC5D0\uB294 \uB418\uB3CC\uC544\uC62C \uAE38\uC774 \uC5C6\uC5B4\uC11C\n * \uC624\uD0C0 \uD558\uB098\uC5D0 \uD504\uB85C\uD544\uC774 \uD558\uB098\uC529 \uB298\uC5C8\uB2E4.\n */\n const configure = async (serverUrl: string): Promise<void> => {\n setBusy(true);\n setError(undefined);\n const target = editingServer?.profile ?? loginTarget?.profile ?? 'default';\n try {\n const profile = await engine.setProfile(target, serverUrl);\n await engine.useProfile(profile.name);\n setLoginTarget({ profile: profile.name, serverUrl: profile.serverUrl });\n setProfiles(await engine.listProfiles());\n setEditingServer(undefined);\n setRoute('login');\n } catch (reason) {\n setError(publicError(reason).message);\n } finally {\n setBusy(false);\n }\n };\n\n const login = async (email: string, password: string): Promise<void> => {\n if (!loginTarget) return;\n setBusy(true);\n setError(undefined);\n try {\n await engine.login(email, password, loginTarget.profile);\n await bootstrap(loginTarget.profile);\n } catch (reason) {\n setError(publicError(reason).message);\n setRoute('login');\n } finally {\n setBusy(false);\n }\n };\n\n const openProfiles = async (): Promise<void> => {\n setBusy(true);\n setError(undefined);\n try {\n setProfiles(await engine.listProfiles());\n setRoute('profiles');\n } catch (reason) {\n setError(publicError(reason).message);\n } finally {\n setBusy(false);\n }\n };\n\n const createProfile = async (name: string, serverUrl: string): Promise<void> => {\n setBusy(true);\n setError(undefined);\n try {\n await engine.setProfile(name, serverUrl);\n await bootstrap(name);\n } catch (reason) {\n setError(publicError(reason).message);\n setRoute('profiles');\n } finally {\n setBusy(false);\n }\n };\n\n const logout = async (): Promise<void> => {\n if (!session) return;\n setBusy(true);\n try {\n await engine.logout(session.profile);\n setLoginTarget({ profile: session.profile, serverUrl: session.serverUrl });\n setSession(undefined);\n setRoute('login');\n } catch (reason) {\n setError(publicError(reason).message);\n setRoute('fatal');\n } finally {\n setBusy(false);\n }\n };\n\n if (route === 'boot') {\n return (\n <Box flexDirection=\"column\">\n <Header />\n <Loading label=\"Dex\uB97C \uC900\uBE44\uD558\uB294 \uC911...\" />\n <Footer text=\"Ctrl+Q \uC885\uB8CC\" />\n </Box>\n );\n }\n if (route === 'server') {\n return (\n <ServerScreen\n initialValue={editingServer?.serverUrl}\n profile={editingServer?.profile}\n busy={busy}\n error={error}\n onSubmit={(url) => void configure(url)}\n // \uCC98\uC74C \uC124\uC815\uC5D0\uB294 \uCDE8\uC18C\uAC00 \uC5C6\uB2E4 \u2014 \uB3CC\uC544\uAC08 \uACF3\uC774 \uC5C6\uB2E4.\n onCancel={\n editingServer\n ? () => {\n setEditingServer(undefined);\n setError(undefined);\n setRoute('login');\n }\n : undefined\n }\n />\n );\n }\n if (route === 'login' && loginTarget) {\n return (\n <LoginScreen\n profile={loginTarget.profile}\n serverUrl={loginTarget.serverUrl}\n busy={busy}\n error={error}\n onSubmit={(email, password) => void login(email, password)}\n onProfiles={() => void openProfiles()}\n onEditServer={() => {\n setEditingServer(loginTarget);\n setError(undefined);\n setRoute('server');\n }}\n />\n );\n }\n if (route === 'profiles') {\n return (\n <ProfileScreen\n profiles={profiles}\n busy={busy}\n error={error}\n onSelect={(name) => void bootstrap(name)}\n onCreate={(name, url) => void createProfile(name, url)}\n onCancel={() => setRoute(session ? 'dashboard' : loginTarget ? 'login' : 'server')}\n />\n );\n }\n if (route === 'dashboard' && session) {\n return (\n <Dashboard\n preferences={preferences}\n engine={engine}\n session={session}\n onProfiles={() => void openProfiles()}\n onLogout={() => void logout()}\n />\n );\n }\n return (\n <Box flexDirection=\"column\">\n <Header />\n <Notice error>{error ?? '\uC54C \uC218 \uC5C6\uB294 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.'}</Notice>\n <Text dimColor>\uC11C\uBC84\uC640 \uD0A4\uCCB4\uC778 \uC0C1\uD0DC\uB97C \uD655\uC778\uD55C \uB4A4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.</Text>\n <Footer text=\"R \uB2E4\uC2DC \uC2DC\uB3C4 \u00B7 Ctrl+Q \uC885\uB8CC\" />\n <RetryInput onRetry={() => void bootstrap()} />\n </Box>\n );\n}\n\nfunction RetryInput({ onRetry }: { onRetry: () => void }): null {\n useInput((input) => {\n if (input.toLowerCase() === 'r') onRetry();\n });\n return null;\n}\n", "import { useEffect, useReducer, useRef, useState } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport { publicError } from '@dex/engine';\nimport type { Agent, Conversation, HistoryTurn } from '@dex/engine';\nimport { chatReducer, initialChatState, type ChatMessage } from './chat-state';\nimport { useMeasured } from './measure';\nimport { maximumScroll, renderTranscript, viewportOf } from './transcript';\nimport { CommandPalette, type PaletteAction } from './command-palette';\nimport { Footer, Header } from './components';\nimport { HistoryScreen } from './history-screen';\nimport { StartPanel } from './start-panel';\nimport { ImeTextInput } from './ime-text-input';\nimport type { TuiEngine, TuiSession } from './model';\nimport { useTerminalSize } from './use-terminal-size';\n\ninterface AgentRef {\n workflowId: string;\n workflowName: string;\n}\n\nfunction AgentSidebar(props: {\n agents: Agent[];\n cursor: number;\n selected?: string;\n focused: boolean;\n height: number;\n}): React.ReactNode {\n const radius = Math.max(3, Math.floor((props.height - 4) / 2));\n const start = Math.max(0, props.cursor - radius);\n const visible = props.agents.slice(start, start + radius * 2 + 1);\n return (\n <Box flexDirection=\"column\" width={30} borderStyle=\"round\" borderColor={props.focused ? 'cyan' : 'gray'} paddingX={1}>\n <Text bold>Agents</Text>\n {visible.map((agent) => {\n const index = props.agents.indexOf(agent);\n const cursor = index === props.cursor;\n const selected = agent.workflowId === props.selected;\n return (\n <Text key={agent.workflowId} color={cursor && props.focused ? 'cyan' : undefined} wrap=\"truncate-end\">\n {cursor ? '\u203A' : ' '} {selected ? '\u25CF' : '\u25CB'} {agent.workflowName}\n </Text>\n );\n })}\n {props.agents.length === 0 ? <Text dimColor>\uC0AC\uC6A9 \uAC00\uB2A5\uD55C Agent\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.</Text> : null}\n </Box>\n );\n}\n\nfunction ChatPane(props: {\n agent?: AgentRef;\n messages: ChatMessage[];\n status?: string;\n scrollUp: number;\n onViewport: (lineCount: number, height: number) => void;\n}): React.ReactNode {\n const [ref, box] = useMeasured();\n // \uCCAB \uD504\uB808\uC784\uC5D0\uB294 \uC544\uC9C1 \uC7B0 \uAC12\uC774 \uC5C6\uB2E4. \uB109\uB109\uD788 \uC7A1\uC73C\uBA74 \uADF8 \uD55C \uD504\uB808\uC784\uC774 \uB118\uCCD0 \uD654\uBA74\uC744\n // \uBC1F\uC73C\uBBC0\uB85C, \uD655\uC2E4\uD788 \uC548 \uB118\uCE60 \uB9CC\uD07C\uB9CC \uC7A1\uACE0 \uB2E4\uC74C \uD504\uB808\uC784\uC5D0\uC11C \uB9DE\uCD98\uB2E4.\n const width = box?.width ?? 20;\n const height = box?.height ?? 1;\n const lines = renderTranscript(props.messages, props.agent?.workflowName ?? 'Agent', width);\n const view = viewportOf(lines, height, props.scrollUp);\n\n useEffect(() => {\n props.onViewport(lines.length, height);\n }, [lines.length, height]);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"round\" borderColor=\"blue\" paddingX={1}>\n <Box>\n <Text bold wrap=\"truncate-end\">\n {props.agent?.workflowName ?? 'Agent\uB97C \uC120\uD0DD\uD558\uC138\uC694'}\n </Text>\n {view.below > 0 ? <Text dimColor> \u00B7 \u2193{view.below}\uC904</Text> : null}\n </Box>\n {/* \uC7B0 \uB192\uC774 \uC548\uC5D0\uC11C\uB9CC \uADF8\uB9B0\uB2E4. \uB118\uCE58\uBA74 ink \uC774 \uC9C0\uC6B0\uB294 \uC790\uB9AC\uC640 \uADF8\uB9AC\uB294 \uC790\uB9AC\uAC00\n \uC5B4\uAE0B\uB098 \uC785\uB825\uCC3D\uACFC \uC548\uB0B4\uC904\uAE4C\uC9C0 \uBC1F\uD78C\uB2E4. */}\n <Box ref={ref} flexDirection=\"column\" flexGrow={1} overflow=\"hidden\">\n {view.lines.length === 0 ? (\n <Text dimColor wrap=\"truncate-end\">\n {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.'}\n </Text>\n ) : null}\n {view.lines.map((line) => (\n <Text\n key={line.key}\n wrap=\"truncate-end\"\n bold={line.role === 'label'}\n dimColor={line.role === 'activity'}\n color={line.color}\n >\n {line.text || ' '}\n </Text>\n ))}\n </Box>\n {props.status ? (\n <Text color=\"yellow\" wrap=\"truncate-end\">\n \u25C6 {props.status}\n </Text>\n ) : null}\n </Box>\n );\n}\n\nfunction Composer(props: {\n value: string;\n onChange: (value: string) => void;\n onSubmit: (value: string) => void;\n focused: boolean;\n disabled: boolean;\n hangulMode: boolean;\n onHangulModeChange: (enabled: boolean) => void;\n}): React.ReactNode {\n return (\n <Box borderStyle=\"round\" borderColor={props.focused ? 'cyan' : 'gray'} paddingX={1}>\n {/* \uC9C0\uAE08 \uBB34\uC5C7\uC774 \uCCD0\uC9C0\uB294\uC9C0 \uB298 \uBCF4\uC774\uAC8C \uB454\uB2E4 \u2014 \uBAA8\uB974\uACE0 \uCE58\uBA74 `dkssud` \uC774 \uB098\uC628\uB2E4. */}\n <Text color={props.hangulMode ? 'yellow' : undefined} dimColor={!props.hangulMode}>\n {props.hangulMode ? '\uD55C' : 'EN'}\n </Text>\n <Text color=\"cyan\"> \u203A </Text>\n {props.disabled ? (\n <Text dimColor>\uC751\uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uC911...</Text>\n ) : (\n <ImeTextInput\n value={props.value}\n onChange={props.onChange}\n onSubmit={props.onSubmit}\n focus={props.focused}\n placeholder=\"\uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694\"\n hangulMode={props.hangulMode}\n onHangulModeChange={props.onHangulModeChange}\n />\n )}\n </Box>\n );\n}\n\nexport function Dashboard(props: {\n engine: TuiEngine;\n session: TuiSession;\n onProfiles: () => void;\n onLogout: () => void;\n preferences?: { hangulMode: boolean; onHangulModeChange?: (enabled: boolean) => void };\n}): React.ReactNode {\n const { exit } = useApp();\n const size = useTerminalSize();\n const bodyHeight = Math.max(12, size.rows - 5);\n const [focus, setFocus] = useState<'agents' | 'composer'>('agents');\n const [cursor, setCursor] = useState(0);\n const [selected, setSelected] = useState<AgentRef | undefined>(() => {\n const first = props.session.agents[0];\n return first ? { workflowId: first.workflowId, workflowName: first.workflowName } : undefined;\n });\n const [input, setInput] = useState('');\n const [chat, dispatch] = useReducer(chatReducer, initialChatState);\n const [palette, setPalette] = useState(false);\n const [history, setHistory] = useState(false);\n /** \uC5D0\uC774\uC804\uD2B8\uB97C \uACE0\uB978 \uC9C1\uD6C4\uC758 \uAC08\uB9BC\uAE38. \uC774\uB825\uC774 \uC788\uC744 \uB54C\uB9CC \uCC44\uC6CC\uC9C4\uB2E4. */\n const [start, setStart] = useState<{ agent: AgentRef; conversations: Conversation[] }>();\n /**\n * \uB300\uD654\uCC3D\uC744 \uB9E8 \uC544\uB798\uC5D0\uC11C \uBA87 \uC904 \uC62C\uB824 \uB480\uB294\uC9C0.\n *\n * 0 \uC774\uBA74 \uB298 \uCD5C\uC2E0\uC5D0 \uBD99\uC5B4 \uC788\uB2E4 \u2014 \uC751\uB2F5\uC774 \uD758\uB7EC\uB3C4 \uB530\uB77C\uAC04\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uC62C\uB824 \uB454 \uB3D9\uC548\uC5D0\uB294\n * \uC0C8 \uC904\uC774 \uC640\uB3C4 \uADF8 \uC790\uB9AC\uB97C \uC9C0\uD0A8\uB2E4. \uC77D\uB358 \uACF3\uC774 \uD280\uC5B4 \uB0B4\uB824\uAC00\uBA74 \uC77D\uC744 \uC218\uAC00 \uC5C6\uB2E4.\n */\n const [scrollUp, setScrollUp] = useState(0);\n /**\n * \uD55C\uAE00 \uC870\uD569 \uCF2C/\uB054.\n *\n * \uD130\uBBF8\uB110 IME \uC5D0 \uB9E1\uAE30\uB358 \uAC83\uC744 CLI \uC548\uC73C\uB85C \uB4E4\uC5EC\uC654\uB2E4 \u2014 \uD130\uBBF8\uB110\uB9C8\uB2E4 \uB2E4\uB974\uACE0 SSH\u00B7tmux \uB97C\n * \uAC70\uCE58\uBA74 \uC544\uC608 \uC548 \uC624\uB358 \uC790\uB9AC\uB77C, \uC6B0\uB9AC\uAC00 \uC870\uD569\uD574\uC57C \uC5B4\uB514\uC11C\uB4E0 \uAC19\uAC8C \uB3D9\uC791\uD55C\uB2E4.\n */\n const [hangulMode, setHangulMode] = useState(props.preferences?.hangulMode ?? false);\n const changeHangulMode = (enabled: boolean): void => {\n setHangulMode(enabled);\n props.preferences?.onHangulModeChange?.(enabled);\n };\n const viewport = useRef({ lineCount: 0, height: 0 });\n const [starting, setStarting] = useState(false);\n const controller = useRef<AbortController | null>(null);\n\n useEffect(() => () => controller.current?.abort(), []);\n\n /**\n * \uC5D0\uC774\uC804\uD2B8\uB97C \uACE0\uB978\uB2E4.\n *\n * \uC774 \uC5D0\uC774\uC804\uD2B8\uC5D0 **\uC774\uC804 \uB300\uD654\uAC00 \uC788\uC73C\uBA74** \uAC08\uB9BC\uAE38\uC744 \uBCF4\uC5EC \uC900\uB2E4(\uC0C8\uB85C \uC2DC\uC791 / \uC774\uC5B4\uAC00\uAE30).\n * \uC5C6\uC73C\uBA74 \uBC14\uB85C \uC0C8 \uB300\uD654\uB97C \uC5F0\uB2E4 \u2014 \uC120\uD0DD\uC9C0\uAC00 \uD558\uB098\uBFD0\uC778 \uC9C8\uBB38\uC740 \uD55C \uBC88 \uB354 \uB204\uB974\uAC8C \uD558\uB294\n * \uC77C\uC77C \uBFD0\uC774\uB2E4.\n *\n * \uBAA9\uB85D \uC870\uD68C\uAC00 \uC2E4\uD328\uD574\uB3C4 \uB9C9\uC9C0 \uC54A\uB294\uB2E4. \uC774\uB825\uC744 \uBABB \uC77D\uB294 \uAC83\uACFC \uB300\uD654\uB97C \uBABB \uD558\uB294 \uAC83\uC740\n * \uB2E4\uB978 \uC77C\uC774\uACE0, \uD6C4\uC790\uB97C \uC804\uC790 \uB54C\uBB38\uC5D0 \uB9C9\uC73C\uBA74 \uC548 \uB41C\uB2E4 \u2014 \uADF8\uB0E5 \uC0C8 \uB300\uD654\uB85C \uC5F0\uB2E4.\n */\n const selectAgent = async (): Promise<void> => {\n const agent = props.session.agents[cursor];\n if (!agent || chat.running || starting) return;\n const ref: AgentRef = { workflowId: agent.workflowId, workflowName: agent.workflowName };\n\n setStarting(true);\n let conversations: Conversation[] = [];\n try {\n const all = await props.engine.listConversations(props.session.profile);\n conversations = all.filter((item) => item.workflowId === ref.workflowId);\n } catch {\n conversations = [];\n } finally {\n setStarting(false);\n }\n\n if (conversations.length === 0) {\n openNewChat(ref);\n return;\n }\n setSelected(ref);\n setStart({ agent: ref, conversations });\n };\n\n /** \uBE48 \uB300\uD654\uB97C \uC5F0\uB2E4 \u2014 \uAC08\uB9BC\uAE38\uC5D0\uC11C [\uC0C8 \uB300\uD654] \uB97C \uACE0\uB978 \uAC83\uACFC \uAC19\uC740 \uC790\uB9AC. */\n const openNewChat = (ref: AgentRef): void => {\n setSelected(ref);\n dispatch({ type: 'reset' });\n setInput('');\n setScrollUp(0);\n setStart(undefined);\n setFocus('composer');\n };\n\n const openHistory = (conversation: Conversation, turns: HistoryTurn[]): void => {\n setSelected({ workflowId: conversation.workflowId, workflowName: conversation.workflowName });\n dispatch({ type: 'history_loaded', interactionId: conversation.interactionId, turns });\n // \uBD88\uB7EC\uC628 \uB300\uD654\uB294 \uB9E8 \uC544\uB798(\uAC00\uC7A5 \uCD5C\uADFC)\uBD80\uD130 \uBCF4\uC5EC \uC900\uB2E4.\n setScrollUp(0);\n const index = props.session.agents.findIndex((agent) => agent.workflowId === conversation.workflowId);\n if (index >= 0) setCursor(index);\n setHistory(false);\n setStart(undefined);\n setFocus('composer');\n };\n\n const cancelTurn = (): void => {\n controller.current?.abort();\n dispatch({ type: 'turn_cancelled' });\n };\n\n const newConversation = (): void => {\n if (chat.running) return;\n dispatch({ type: 'reset' });\n setInput('');\n setScrollUp(0);\n setPalette(false);\n setFocus('composer');\n };\n\n const send = async (value: string): Promise<void> => {\n const text = value.trim();\n if (!text || !selected || chat.running) return;\n try {\n const resolved = await props.engine.resolveChatInput({\n profile: props.session.profile,\n workflowId: selected.workflowId,\n workflowName: selected.workflowName,\n interactionId: chat.interactionId,\n input: text,\n });\n setInput('');\n setScrollUp(0);\n dispatch({ type: 'turn_started', interactionId: resolved.interactionId, input: text });\n const active = new AbortController();\n controller.current = active;\n for await (const event of props.engine.chat(resolved, active.signal)) {\n dispatch({ type: 'event_received', event });\n }\n if (active.signal.aborted) dispatch({ type: 'turn_cancelled' });\n else dispatch({ type: 'turn_completed' });\n } catch (error) {\n if (controller.current?.signal.aborted) dispatch({ type: 'turn_cancelled' });\n else dispatch({ type: 'turn_failed', message: publicError(error).message });\n } finally {\n controller.current = null;\n }\n };\n\n /**\n * \uB300\uD654\uCC3D\uC744 \uD55C \uD654\uBA74\uC758 \uC808\uBC18\uC529 \uC6C0\uC9C1\uC778\uB2E4. `direction` \uC774 -1 \uC774\uBA74 \uACFC\uAC70\uB85C.\n *\n * \uD55C \uD654\uBA74\uC744 \uD1B5\uC9F8\uB85C \uB118\uAE30\uBA74 \uC55E\uB4A4\uAC00 \uC774\uC5B4\uC9C0\uC9C0 \uC54A\uC544 \uC77D\uB358 \uC790\uB9AC\uB97C \uB193\uCE5C\uB2E4.\n */\n const scrollBy = (direction: -1 | 1): void => {\n const { lineCount, height } = viewport.current;\n const step = Math.max(1, Math.floor(height / 2));\n const limit = maximumScroll(lineCount, height);\n setScrollUp((current) => Math.min(limit, Math.max(0, current - direction * step)));\n };\n\n useInput(\n (keyInput, key) => {\n if (key.ctrl && keyInput === 'k') setPalette(true);\n else if (key.ctrl && keyInput === 'p') {\n controller.current?.abort();\n props.onProfiles();\n } else if (key.ctrl && keyInput === 'h') {\n if (chat.running) cancelTurn();\n setHistory(true);\n }\n else if (key.ctrl && keyInput === 'n') newConversation();\n else if (key.pageUp) scrollBy(-1);\n else if (key.pageDown) scrollBy(1);\n else if (key.escape && chat.running) cancelTurn();\n else if (key.escape) setFocus('agents');\n else if (key.tab) setFocus((current) => (current === 'agents' ? 'composer' : 'agents'));\n else if (focus === 'agents' && key.upArrow) setCursor((current) => Math.max(0, current - 1));\n else if (focus === 'agents' && key.downArrow && props.session.agents.length > 0) {\n setCursor((current) => Math.min(props.session.agents.length - 1, current + 1));\n } else if (focus === 'agents' && key.return) void selectAgent();\n },\n // \uAC08\uB9BC\uAE38\u00B7\uD314\uB808\uD2B8\u00B7\uC774\uB825 \uD654\uBA74\uC774 \uB5A0 \uC788\uC73C\uBA74 \uADF8 \uD654\uBA74\uC774 \uD0A4\uB97C \uAC16\uB294\uB2E4 \u2014 \uC5EC\uAE30\uC11C\uB3C4 \uBC1B\uC73C\uBA74\n // \uBC29\uD5A5\uD0A4 \uD558\uB098\uAC00 \uB450 \uACF3\uC5D0\uC11C \uC6C0\uC9C1\uC778\uB2E4.\n { isActive: !palette && !history && !start },\n );\n\n const paletteActions: PaletteAction[] = [\n { id: 'new', label: '\uC0C8 \uB300\uD654', run: newConversation },\n {\n id: 'history',\n label: '\uB300\uD654 \uAE30\uB85D',\n run: () => {\n if (chat.running) cancelTurn();\n setPalette(false);\n setHistory(true);\n },\n },\n {\n id: 'profile',\n label: '\uD504\uB85C\uD544 \uC804\uD658',\n run: () => {\n controller.current?.abort();\n setPalette(false);\n props.onProfiles();\n },\n },\n {\n id: 'logout',\n label: '\uB85C\uADF8\uC544\uC6C3',\n run: () => {\n controller.current?.abort();\n props.onLogout();\n },\n },\n { id: 'quit', label: '\uC885\uB8CC', run: exit },\n ];\n\n let body: React.ReactNode;\n if (palette) {\n body = <CommandPalette actions={paletteActions} onCancel={() => setPalette(false)} />;\n } else if (history) {\n body = (\n <HistoryScreen\n engine={props.engine}\n profile={props.session.profile}\n onOpen={openHistory}\n onCancel={() => setHistory(false)}\n />\n );\n } else {\n const sidebar = (\n <AgentSidebar\n agents={props.session.agents}\n cursor={cursor}\n selected={selected?.workflowId}\n focused={focus === 'agents'}\n height={bodyHeight}\n />\n );\n // \uAC08\uB9BC\uAE38\uC774 \uC5F4\uB824 \uC788\uC73C\uBA74 \uB300\uD654\uCC3D \uC790\uB9AC\uB97C \uADF8\uAC83\uC774 \uC4F4\uB2E4 \u2014 \uBAA9\uB85D\uC740 \uADF8\uB300\uB85C \uC606\uC5D0 \uB0A8\uC544\n // \uC5B4\uB290 \uC5D0\uC774\uC804\uD2B8\uB97C \uACE0\uB978 \uAC83\uC778\uC9C0 \uBCF4\uC778\uB2E4.\n const conversation = start ? (\n <StartPanel\n engine={props.engine}\n profile={props.session.profile}\n agentName={start.agent.workflowName}\n conversations={start.conversations}\n onNew={() => openNewChat(start.agent)}\n onOpen={openHistory}\n onCancel={() => {\n setStart(undefined);\n setFocus('agents');\n }}\n />\n ) : (\n <Box flexDirection=\"column\" flexGrow={1}>\n <ChatPane\n agent={selected}\n messages={chat.messages}\n status={chat.status}\n scrollUp={scrollUp}\n onViewport={(lineCount, height) => {\n viewport.current = { lineCount, height };\n }}\n />\n <Composer\n value={input}\n onChange={setInput}\n onSubmit={(value) => void send(value)}\n focused={focus === 'composer'}\n disabled={chat.running || !selected}\n hangulMode={hangulMode}\n onHangulModeChange={changeHangulMode}\n />\n </Box>\n );\n body = size.wide ? (\n <Box height={bodyHeight}>{sidebar}{conversation}</Box>\n ) : focus === 'agents' ? (\n <Box height={bodyHeight}>{sidebar}</Box>\n ) : (\n <Box height={bodyHeight}>{conversation}</Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Header\n profile={props.session.profile}\n username={props.session.username}\n connected\n />\n {body}\n <Footer\n mode={hangulMode ? '\uD55C' : 'EN'}\n text=\"Ctrl+Space \uD55C/\uC601 \u00B7 Tab \uD328\uB110 \u00B7 PgUp/PgDn \uC2A4\uD06C\uB864 \u00B7 Ctrl+K \uBA85\uB839 \u00B7 Ctrl+H \uAE30\uB85D \u00B7 Ctrl+P \uD504\uB85C\uD544 \u00B7 Esc \uCDE8\uC18C \u00B7 Ctrl+Q \uC885\uB8CC\"\n />\n </Box>\n );\n}\n", "import type { ChatEvent, HistoryTurn } from '@dex/engine';\n\nexport type ChatMessageRole = 'user' | 'assistant' | 'activity' | 'system';\n\nexport interface ChatMessage {\n id: string;\n role: ChatMessageRole;\n text: string;\n activityKey?: string;\n}\n\nexport interface ChatState {\n interactionId?: string;\n messages: ChatMessage[];\n running: boolean;\n status?: string;\n}\n\nexport type ChatAction =\n | { type: 'reset' }\n | { type: 'history_loaded'; interactionId: string; turns: HistoryTurn[] }\n | { type: 'turn_started'; interactionId: string; input: string }\n | { type: 'event_received'; event: ChatEvent }\n | { type: 'turn_completed' }\n | { type: 'turn_cancelled' }\n | { type: 'turn_failed'; message: string };\n\nexport const initialChatState: ChatState = { messages: [], running: false };\n\nfunction lastMessageIndex(\n messages: ChatMessage[],\n predicate: (message: ChatMessage) => boolean,\n): number {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (predicate(messages[index])) return index;\n }\n return -1;\n}\n\nfunction appendAssistant(messages: ChatMessage[], content: string): ChatMessage[] {\n const index = lastMessageIndex(messages, (message) => message.role === 'assistant');\n if (index < 0) {\n return [...messages, { id: `assistant-${messages.length}`, role: 'assistant', text: content }];\n }\n const next = [...messages];\n next[index] = { ...next[index], text: next[index].text + content };\n return next;\n}\n\nfunction upsertActivity(messages: ChatMessage[], key: string, text: string): ChatMessage[] {\n const index = lastMessageIndex(\n messages,\n (message) => message.role === 'activity' && message.activityKey === key,\n );\n const startsNewRun =\n index >= 0 && text.endsWith('\uC2E4\uD589 \uC911') && !messages[index].text.endsWith('\uC2E4\uD589 \uC911');\n if (index < 0 || startsNewRun) {\n return [\n ...messages,\n { id: `activity-${messages.length}`, role: 'activity', activityKey: key, text },\n ];\n }\n const next = [...messages];\n next[index] = { ...next[index], text };\n return next;\n}\n\nfunction eventState(state: ChatState, event: ChatEvent): ChatState {\n if (event.kind === 'text') return { ...state, messages: appendAssistant(state.messages, event.content) };\n if (event.kind === 'summary') {\n const assistantIndex = lastMessageIndex(state.messages, (message) => message.role === 'assistant');\n const assistant = assistantIndex >= 0 ? state.messages[assistantIndex] : undefined;\n return assistant?.text ? state : { ...state, messages: appendAssistant(state.messages, event.text) };\n }\n if (event.kind === 'tool') {\n const tool = event.event.toolName ?? 'tool';\n const key = event.event.runId ?? tool;\n const suffix = event.event.error\n ? `\uC2E4\uD328: ${event.event.error}`\n : event.event.eventType.includes('result')\n ? '\uC644\uB8CC'\n : '\uC2E4\uD589 \uC911';\n return { ...state, messages: upsertActivity(state.messages, key, `${tool} \u00B7 ${suffix}`) };\n }\n if (event.kind === 'node_status') {\n return { ...state, status: `${event.event.nodeId} \u00B7 ${event.event.status}` };\n }\n if (event.kind === 'status') {\n return { ...state, status: event.detail ?? event.surface };\n }\n if (event.kind === 'quota') {\n return {\n ...state,\n messages: [\n ...state.messages,\n { id: `quota-${state.messages.length}`, role: 'system', text: `Quota ${event.level}` },\n ],\n };\n }\n if (event.kind === 'error') {\n return {\n ...state,\n running: false,\n status: undefined,\n messages: [\n ...state.messages,\n { id: `error-${state.messages.length}`, role: 'system', text: event.detail },\n ],\n };\n }\n if (event.kind === 'end') return { ...state, running: false, status: undefined };\n return state;\n}\n\nexport function chatReducer(state: ChatState, action: ChatAction): ChatState {\n switch (action.type) {\n case 'reset':\n return initialChatState;\n case 'history_loaded':\n return {\n interactionId: action.interactionId,\n running: false,\n messages: action.turns.flatMap((turn, index) => [\n { id: `history-user-${index}`, role: 'user' as const, text: turn.input },\n { id: `history-assistant-${index}`, role: 'assistant' as const, text: turn.output },\n ]),\n };\n case 'turn_started':\n return {\n ...state,\n interactionId: action.interactionId,\n running: true,\n status: '\uC751\uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uC911',\n messages: [\n ...state.messages,\n { id: `user-${state.messages.length}`, role: 'user', text: action.input },\n { id: `assistant-${state.messages.length + 1}`, role: 'assistant', text: '' },\n ],\n };\n case 'event_received':\n return eventState(state, action.event);\n case 'turn_completed':\n return { ...state, running: false, status: undefined };\n case 'turn_cancelled':\n return { ...state, running: false, status: undefined };\n case 'turn_failed':\n return {\n ...state,\n running: false,\n status: undefined,\n messages: [\n ...state.messages,\n { id: `failure-${state.messages.length}`, role: 'system', text: action.message },\n ],\n };\n }\n}\n", "import { useEffect, useRef, useState } from 'react';\nimport type { DOMElement } from 'ink';\n\n/**\n * \uC5B4\uB5A4 \uCE78\uC774 \uD654\uBA74\uC758 **\uC5B4\uB514\uC5D0, \uC5BC\uB9C8\uB9CC\uD07C** \uADF8\uB824\uC9C0\uB294\uC9C0 \uB808\uC774\uC544\uC6C3\uC5D0\uC11C \uC77D\uC5B4 \uC628\uB2E4.\n *\n * \uC608\uC804\uC5D0\uB294 \uD654\uBA74\uB9C8\uB2E4 `{ x: 16, y: 6 }`, `height - 5` \uCC98\uB7FC \uC190\uC73C\uB85C \uC138\uC5B4 \uB123\uC5C8\uB2E4. \uADF8\n * \uC22B\uC790\uB294 \uADF8\uB54C\uC758 \uB808\uC774\uC544\uC6C3\uC5D0\uC11C\uB9CC \uB9DE\uB2E4 \u2014 \uB77C\uBCA8 \uD55C \uAE00\uC790, \uD14C\uB450\uB9AC \uD558\uB098, \uC0AC\uC774\uB4DC\uBC14 \uD3ED\uC774\n * \uBC14\uB00C\uBA74 \uC870\uC6A9\uD788 \uC5B4\uAE0B\uB09C\uB2E4. yoga \uAC00 \uC774\uBBF8 \uC815\uD655\uD788 \uC544\uB294 \uAC12\uC774\uB77C \uC140 \uC774\uC720\uAC00 \uC5C6\uB2E4.\n */\nexport interface Placement {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport function placementOf(node: DOMElement | null): Placement | undefined {\n const yogaSelf = node?.yogaNode;\n if (!node || !yogaSelf) return undefined;\n let x = 0;\n let y = 0;\n for (let current: DOMElement | undefined = node; current; current = current.parentNode) {\n const yoga = current.yogaNode;\n if (!yoga) continue;\n x += yoga.getComputedLeft();\n y += yoga.getComputedTop();\n }\n return { x, y, width: yogaSelf.getComputedWidth(), height: yogaSelf.getComputedHeight() };\n}\n\n/**\n * \uBD99\uC778 \uCE78\uC758 \uC790\uB9AC\uB97C \uC7AC\uC11C \uB3CC\uB824\uC900\uB2E4. \uCCAB \uD504\uB808\uC784\uC5D0\uB294 `undefined` \uB2E4.\n *\n * ink \uC740 \uCEE4\uBC0B\uC774 **\uB05D\uB09C \uB4A4\uC5D0** \uB808\uC774\uC544\uC6C3\uC744 \uACC4\uC0B0\uD558\uBBC0\uB85C \uC5EC\uAE30\uC11C \uC77D\uC73C\uBA74 \uD55C \uD504\uB808\uC784 \uB2A6\uB2E4.\n * \uB2EC\uB77C\uC84C\uC744 \uB54C\uB9CC \uC0C1\uD0DC\uB97C \uBC14\uAFD4 \uB2E4\uC74C \uD504\uB808\uC784\uC5D0\uC11C \uB9DE\uCD98\uB2E4 \u2014 \uB9E4\uBC88 \uBC14\uAFB8\uBA74 \uB80C\uB354\uAC00 \uB05D\uC5C6\uC774 \uB3C8\uB2E4.\n */\nexport function useMeasured(): [React.MutableRefObject<DOMElement | null>, Placement | undefined] {\n const ref = useRef<DOMElement | null>(null);\n const [placement, setPlacement] = useState<Placement | undefined>(undefined);\n useEffect(() => {\n const measured = placementOf(ref.current);\n if (!measured) return;\n if (\n placement?.x !== measured.x ||\n placement?.y !== measured.y ||\n placement?.width !== measured.width ||\n placement?.height !== measured.height\n ) {\n setPlacement(measured);\n }\n });\n return [ref, placement];\n}\n", "import stringWidth from 'string-width';\nimport type { ChatMessage } from './chat-state';\n\n/**\n * \uB300\uD654\uB97C **\uC904 \uB2E8\uC704\uB85C** \uD3BC\uCE5C\uB2E4.\n *\n * \uC608\uC804\uC5D0\uB294 \uB9C8\uC9C0\uB9C9 \uBA87 **\uAC1C\uC758 \uBA54\uC2DC\uC9C0**\uB97C \uC798\uB77C \uBCF4\uC5EC \uC92C\uB2E4. \uD55C \uBA54\uC2DC\uC9C0\uAC00 \uD55C\uB450 \uC904\uC774\uB77C\uACE0\n * \uCE5C \uC148\uC778\uB370, \uC2E4\uC81C\uB85C\uB294 \uC218\uC2ED \uC904\uC9DC\uB9AC\uAC00 \uC628\uB2E4. \uADF8\uB7EC\uBA74 \uB300\uD654\uCC3D\uC774 \uC81C \uB192\uC774\uB97C \uB118\uC5B4 \uC790\uB77C\uACE0,\n * ink \uC740 \uC904 \uC218\uB97C \uC138\uC5B4 \uD654\uBA74\uC744 \uC9C0\uC6B0\uBBC0\uB85C \uADF8 \uC21C\uAC04\uBD80\uD130 \uC9C0\uC6B0\uB294 \uC790\uB9AC\uC640 \uADF8\uB9AC\uB294 \uC790\uB9AC\uAC00\n * \uC5B4\uAE0B\uB09C\uB2E4 \u2014 \uAE00\uC790\uAC00 \uD14C\uB450\uB9AC \uBC16\uC73C\uB85C \uC0C8\uACE0, \uC785\uB825\uCC3D\uACFC \uC544\uB798 \uC548\uB0B4\uC904\uAE4C\uC9C0 \uBC1F\uD78C\uB2E4. \uB300\uD654\uAC00\n * \uAE38\uC5B4\uC9C8\uC218\uB85D \uD655\uC2E4\uD788 \uAE68\uC84C\uB2E4.\n *\n * \uADF8\uB798\uC11C \uC5EC\uAE30\uC11C **\uBA3C\uC800 \uD3ED\uC5D0 \uB9DE\uCDB0 \uC904\uB85C \uB9CC\uB4E0 \uB4A4** \uB192\uC774\uB9CC\uD07C\uB9CC \uC790\uB978\uB2E4. \uB300\uD654\uCC3D\uC774 \uC790\uAE30\n * \uB192\uC774\uB97C \uB118\uB294 \uC77C\uC774 \uAD6C\uC870\uC801\uC73C\uB85C \uBD88\uAC00\uB2A5\uD574\uC9C0\uACE0, \uADF8 \uB355\uC5D0 \uC2A4\uD06C\uB864\uB3C4 \uC904 \uB2E8\uC704\uB85C \uC815\uD655\uD574\uC9C4\uB2E4.\n */\n\nexport type LineRole = 'label' | 'text' | 'activity' | 'system';\n\nexport interface TranscriptLine {\n key: string;\n text: string;\n role: LineRole;\n color?: string;\n}\n\n/** \uC774 \uC904 \uC55E\uC5D0 \uBD99\uB294 \uB4E4\uC5EC\uC4F0\uAE30. \uB9D0\uD55C \uC0AC\uB78C \uC544\uB798\uB85C \uB0B4\uC6A9\uC774 \uC815\uB82C\uB41C\uB2E4. */\nconst INDENT = ' ';\n\nfunction colorOf(role: ChatMessage['role']): string | undefined {\n if (role === 'user') return 'cyan';\n if (role === 'assistant') return 'green';\n if (role === 'activity') return 'yellow';\n if (role === 'system') return 'red';\n return undefined;\n}\n\nfunction labelOf(role: ChatMessage['role'], agentName: string): string {\n if (role === 'user') return 'You';\n if (role === 'assistant') return agentName;\n if (role === 'activity') return 'Tool';\n return 'System';\n}\n\n/**\n * \uD55C \uBB38\uB2E8\uC744 \uD3ED\uC5D0 \uB9DE\uCDB0 \uC790\uB978\uB2E4.\n *\n * \uACF5\uBC31\uC5D0\uC11C \uB04A\uB294 \uAC83\uC744 \uC6B0\uC120\uD558\uB418, \uD55C \uB0B1\uB9D0\uC774 \uD3ED\uBCF4\uB2E4 \uAE38\uAC70\uB098 \uD55C\uAD6D\uC5B4\uCC98\uB7FC \uACF5\uBC31\uC774 \uC5C6\uC73C\uBA74\n * \uAE00\uC790 \uD3ED\uC744 \uC138\uC5B4 \uB04A\uB294\uB2E4. `String.length` \uB85C\uB294 \uC548 \uB41C\uB2E4 \u2014 \uD55C\uAE00\u00B7\uC774\uBAA8\uC9C0\uB294 \uD55C \uAE00\uC790\uAC00\n * \uB450 \uCE78\uC774\uB77C, \uAE38\uC774\uB85C \uC790\uB974\uBA74 \uC904\uC774 \uD3ED\uC744 \uB118\uC5B4 \uACB0\uAD6D \uB300\uD654\uCC3D\uC774 \uC790\uB780\uB2E4.\n */\nexport function wrapToWidth(text: string, width: number): string[] {\n if (width <= 0) return [text];\n const lines: string[] = [];\n for (const paragraph of text.split('\\n')) {\n if (paragraph === '') {\n lines.push('');\n continue;\n }\n let line = '';\n let lineWidth = 0;\n const flush = (): void => {\n lines.push(line);\n line = '';\n lineWidth = 0;\n };\n // \uACF5\uBC31\uC744 \uB0B1\uB9D0\uC5D0 \uBD99\uC5EC \uB450\uBA74 \uC904 \uB05D\uC5D0\uC11C \uD568\uAED8 \uB118\uC5B4\uAC00 \uC55E\uC904\uC774 \uD3ED\uC744 \uB118\uC9C0 \uC54A\uB294\uB2E4.\n for (const word of paragraph.match(/\\s+|\\S+/g) ?? []) {\n const wordWidth = stringWidth(word);\n if (lineWidth > 0 && lineWidth + wordWidth > width) {\n flush();\n if (/^\\s+$/.test(word)) continue; // \uC904\uBC14\uAFC8 \uC790\uB9AC\uC758 \uACF5\uBC31\uC740 \uBC84\uB9B0\uB2E4\n }\n if (wordWidth <= width) {\n line += word;\n lineWidth += wordWidth;\n continue;\n }\n // \uB0B1\uB9D0 \uD558\uB098\uAC00 \uD3ED\uBCF4\uB2E4 \uAE38\uB2E4 \u2014 \uAE00\uC790 \uD3ED\uC744 \uC138\uC5B4 \uB04A\uB294\uB2E4.\n for (const char of word) {\n const charWidth = stringWidth(char);\n if (lineWidth + charWidth > width) flush();\n line += char;\n lineWidth += charWidth;\n }\n }\n flush();\n }\n return lines;\n}\n\n/**\n * \uB9D0\uD55C \uC0AC\uB78C\uC744 \uAC00\uB85C\uC904\uB85C \uBABB\uBC15\uB294\uB2E4: `\u2500\u2500 You \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`.\n *\n * \uC774\uB984\uB9CC \uAD75\uAC8C \uC4F0\uB358 \uB54C\uB294 \uB300\uD654\uB97C \uBD88\uB7EC\uC624\uBA74 \uC5B4\uB514\uC11C \uB204\uAC00 \uBC14\uB00C\uB294\uC9C0 \uB208\uC5D0 \uB4E4\uC5B4\uC624\uC9C0 \uC54A\uC558\uB2E4.\n * \uAC00\uB85C\uC904\uC740 \uC2A4\uD06C\uB864 \uB3C4\uC911 \uC544\uBB34 \uB370\uC11C\uB098 \uBA48\uCDB0\uB3C4 \uACBD\uACC4\uAC00 \uBC14\uB85C \uBCF4\uC778\uB2E4.\n */\nfunction ruleFor(label: string, width: number): string {\n // \uC774\uB984\uC774 \uAE38\uBA74 \uC904\uC778\uB2E4. \uB118\uCE58\uB294 \uCC44\uB85C \uB450\uBA74 \uB300\uD654\uCC3D\uC774 \uC790\uB77C\uACE0, \uADF8 \uC21C\uAC04 ink \uC774 \uC9C0\uC6B0\uB294\n // \uC790\uB9AC\uC640 \uADF8\uB9AC\uB294 \uC790\uB9AC\uAC00 \uC5B4\uAE0B\uB09C\uB2E4 \u2014 \uC5D0\uC774\uC804\uD2B8 \uC774\uB984\uC740 \uC0AC\uC6A9\uC790\uAC00 \uC9D3\uB294 \uAC12\uC774\uB77C \uC5BC\uB9C8\uB4E0\uC9C0\n // \uAE38 \uC218 \uC788\uB2E4.\n const room = Math.max(0, width - stringWidth('\u2500\u2500 '));\n let trimmed = '';\n let used = 0;\n for (const char of label) {\n const charWidth = stringWidth(char);\n if (used + charWidth > room) {\n trimmed = trimmed.slice(0, -1) + '\u2026';\n break;\n }\n trimmed += char;\n used += charWidth;\n }\n const head = `\u2500\u2500 ${trimmed} `;\n return head + '\u2500'.repeat(Math.max(0, width - stringWidth(head)));\n}\n\nexport function renderTranscript(\n messages: ChatMessage[],\n agentName: string,\n width: number,\n): TranscriptLine[] {\n const lines: TranscriptLine[] = [];\n const bodyWidth = Math.max(1, width - INDENT.length);\n\n for (const message of messages) {\n const color = colorOf(message.role);\n\n // \uB3C4\uAD6C \uD65C\uB3D9\uC740 \uB300\uD654\uAC00 \uC544\uB2C8\uB77C \uACC1\uB2E4\uB9AC\uB2E4. \uAC00\uB85C\uC904\uAE4C\uC9C0 \uB450\uBA74 \uC9C4\uC9DC \uB300\uD654\uAC00 \uBB3B\uD78C\uB2E4.\n if (message.role === 'activity') {\n for (const [index, text] of wrapToWidth(message.text, bodyWidth).entries()) {\n lines.push({\n key: `${message.id}:${index}`,\n text: `${index === 0 ? '\u00B7 ' : INDENT}${text}`,\n role: 'activity',\n color,\n });\n }\n continue;\n }\n\n if (lines.length > 0) lines.push({ key: `${message.id}:gap`, text: '', role: 'text' });\n lines.push({\n key: `${message.id}:label`,\n text: ruleFor(labelOf(message.role, agentName), width),\n role: 'label',\n color,\n });\n\n // \uC544\uC9C1 \uD55C \uAE00\uC790\uB3C4 \uC624\uC9C0 \uC54A\uC740 \uC751\uB2F5\uC740 \uBE48\uCE78\uC774 \uC544\uB2C8\uB77C \uAE30\uB2E4\uB9AC\uB294 \uC911\uC774\uB77C\uACE0 \uB9D0\uD574 \uC900\uB2E4.\n const body = message.text || (message.role === 'assistant' ? '\u2026' : '');\n for (const [index, text] of wrapToWidth(body, bodyWidth).entries()) {\n lines.push({\n key: `${message.id}:${index}`,\n text: INDENT + text,\n role: message.role === 'system' ? 'system' : 'text',\n color: message.role === 'system' ? color : undefined,\n });\n }\n }\n return lines;\n}\n\nexport interface Viewport {\n lines: TranscriptLine[];\n /** \uC704\uB85C \uAC00\uB824\uC9C4 \uC904 \uC218. 0 \uBCF4\uB2E4 \uD06C\uBA74 \uB354 \uBCFC \uAC83\uC774 \uC788\uB2E4\uB294 \uB73B\uC774\uB2E4. */\n above: number;\n /** \uC544\uB798\uB85C \uAC00\uB824\uC9C4 \uC904 \uC218. 0 \uC774\uBA74 \uB9E8 \uC544\uB798\uC5D0 \uBD99\uC5B4 \uC788\uB2E4. */\n below: number;\n}\n\n/**\n * \uB192\uC774\uB9CC\uD07C\uB9CC \uC798\uB77C \uB0B8\uB2E4.\n *\n * `scrollUp` \uC740 **\uB9E8 \uC544\uB798\uC5D0\uC11C \uBA87 \uC904 \uC62C\uB77C\uAC14\uB294\uC9C0**\uB2E4. 0 \uC774\uBA74 \uB298 \uCD5C\uC2E0\uC774 \uBCF4\uC778\uB2E4 \u2014 \uC0C8\n * \uC751\uB2F5\uC774 \uD758\uB7EC\uB3C4 \uB530\uB77C\uAC04\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uC62C\uB824 \uB454 \uB3D9\uC548\uC5D0\uB294 \uADF8 \uC790\uB9AC\uB97C \uC9C0\uD0A8\uB2E4.\n */\nexport function viewportOf(\n lines: TranscriptLine[],\n height: number,\n scrollUp: number,\n): Viewport {\n if (height <= 0) return { lines: [], above: lines.length, below: 0 };\n const maximumScroll = Math.max(0, lines.length - height);\n const up = Math.min(Math.max(0, scrollUp), maximumScroll);\n const end = lines.length - up;\n const start = Math.max(0, end - height);\n return { lines: lines.slice(start, end), above: start, below: lines.length - end };\n}\n\n/** \uC62C\uB77C\uAC08 \uC218 \uC788\uB294 \uCD5C\uB300\uCE58. \uC774 \uB108\uBA38\uB85C\uB294 \uC62C\uB824 \uBD10\uC57C \uAC19\uC740 \uD654\uBA74\uC774\uB2E4. */\nexport function maximumScroll(lineCount: number, height: number): number {\n return Math.max(0, lineCount - Math.max(0, height));\n}\n", "import { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { Footer } from './components';\n\nexport interface PaletteAction {\n id: string;\n label: string;\n run: () => void;\n}\n\nexport function CommandPalette(props: {\n actions: PaletteAction[];\n onCancel: () => void;\n}): React.ReactNode {\n const [cursor, setCursor] = useState(0);\n useInput((_input, key) => {\n if (key.escape) props.onCancel();\n if (key.upArrow) setCursor((current) => Math.max(0, current - 1));\n if (key.downArrow) setCursor((current) => Math.min(props.actions.length - 1, current + 1));\n if (key.return && props.actions[cursor]) props.actions[cursor].run();\n });\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"double\" borderColor=\"magenta\" padding={1}>\n <Text bold>\uBA85\uB839</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {props.actions.map((action, index) => (\n <Text key={action.id} color={index === cursor ? 'magentaBright' : undefined}>\n {index === cursor ? '\u203A' : ' '} {action.label}\n </Text>\n ))}\n </Box>\n <Footer text=\"\u2191\u2193 \uC774\uB3D9 \u00B7 Enter \uC2E4\uD589 \u00B7 Esc \uB2EB\uAE30\" />\n </Box>\n );\n}\n", "import type { ReactNode } from 'react';\nimport { Box, Text } from 'ink';\nimport { ImeTextInput } from './ime-text-input';\n\nexport function Header(props: {\n profile?: string;\n username?: string;\n connected?: boolean;\n}): ReactNode {\n return (\n <Box paddingX={1} justifyContent=\"space-between\">\n <Text bold color=\"blueBright\">\n XGEN Dex\n </Text>\n {props.profile ? (\n <Text>\n {props.profile} \u00B7 {props.username ?? '\uB85C\uADF8\uC778 \uD544\uC694'} \u00B7{' '}\n <Text color={props.connected ? 'green' : 'yellow'}>\n {props.connected ? 'Connected' : 'Offline'}\n </Text>\n </Text>\n ) : (\n <Text dimColor>\uC124\uC815 \uD544\uC694</Text>\n )}\n </Box>\n );\n}\n\nexport function Footer({ text, mode }: { text: string; mode?: string }): ReactNode {\n return (\n <Box paddingX={1}>\n {/* \uC9C0\uAE08 \uD55C\uAE00\uC778\uC9C0 \uC601\uBB38\uC778\uC9C0\uB294 \uC0C1\uD0DC\uBC14\uC5D0\uC11C\uB3C4 \uBCF4\uC5EC\uC57C \uD55C\uB2E4 \u2014 \uC785\uB825\uCC3D\uC5D0\uC11C \uB208\uC744 \uB5BC\uACE0\n \uC788\uB2E4\uAC00 \uBAA8\uB974\uACE0 \uCE58\uBA74 `dkssud` \uC774 \uB098\uC628\uB2E4. */}\n {mode ? (\n <Text bold color={mode === '\uD55C' ? 'yellow' : 'gray'}>\n [{mode}]{' '}\n </Text>\n ) : null}\n <Text dimColor wrap=\"truncate-end\">\n {text}\n </Text>\n </Box>\n );\n}\n\nexport function Loading({ label = '\uBD88\uB7EC\uC624\uB294 \uC911...' }: { label?: string }): ReactNode {\n return (\n <Box padding={1}>\n <Text color=\"cyan\">\u25C6 {label}</Text>\n </Box>\n );\n}\n\nexport function Notice({ children, error = false }: { children: ReactNode; error?: boolean }): ReactNode {\n return (\n <Box borderStyle=\"round\" borderColor={error ? 'red' : 'cyan'} paddingX={1}>\n <Text color={error ? 'red' : undefined}>{children}</Text>\n </Box>\n );\n}\n\nexport function FormField(props: {\n label: string;\n value: string;\n onChange: (value: string) => void;\n onSubmit?: (value: string) => void;\n focus: boolean;\n placeholder?: string;\n secret?: boolean;\n}): ReactNode {\n return (\n // \uAC00\uB85C\uB85C \uB298\uB824 \uB46C\uC57C \uC785\uB825 \uCE78\uC774 \uB0A8\uB294 \uD3ED\uC744 \uC54C \uC218 \uC788\uB2E4. \uB0B4\uC6A9\uB9CC\uD07C\uB9CC \uB113\uC73C\uBA74 \uCE78\uC758 \uD3ED\uC774\n // \uACE7 \uAE00\uC790 \uD3ED\uC774 \uB418\uC5B4, \uAE34 \uC8FC\uC18C\uAC00 \uC2A4\uC2A4\uB85C\uB97C \uC798\uB77C \uB0B4\uB294 \uAF34\uC774 \uB41C\uB2E4.\n <Box flexGrow={1}>\n <Box width={14} flexShrink={0}>\n <Text color={props.focus ? 'cyan' : undefined}>{props.focus ? '\u203A' : ' '} {props.label}</Text>\n </Box>\n <ImeTextInput\n value={props.value}\n onChange={props.onChange}\n onSubmit={props.onSubmit}\n focus={props.focus}\n placeholder={props.placeholder}\n mask={props.secret ? '\u2022' : undefined}\n />\n </Box>\n );\n}\n", "import { useEffect, useRef, useState } from 'react';\nimport { Box, Text, useCursor, useInput, useStdin } from 'ink';\nimport stringWidth from 'string-width';\nimport { useMeasured } from './measure';\nimport { classifyInput } from './terminal-input';\nimport * as hangul from './hangul';\nimport { parseKeyEvents } from './kitty';\n\ninterface ImeTextInputProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit?: (value: string) => void;\n focus: boolean;\n placeholder?: string;\n mask?: string;\n /** \uD55C\uAE00 \uC870\uD569 \uC911\uC778\uAC00. \uBAA8\uB4DC \uD45C\uC2DC\uB97C \uC606\uC5D0 \uBD99\uC774\uB294 \uCABD\uC5D0\uC11C \uC4F4\uB2E4. */\n hangulMode?: boolean;\n onHangulModeChange?: (enabled: boolean) => void;\n}\n\nconst segmenter = new Intl.Segmenter('ko', { granularity: 'grapheme' });\n\nfunction graphemes(value: string): string[] {\n return [...segmenter.segment(value)].map(({ segment }) => segment);\n}\n\nfunction clamp(value: number, minimum: number, maximum: number): number {\n return Math.min(Math.max(value, minimum), maximum);\n}\n\nfunction visibleInput(\n segments: string[],\n cursor: number,\n maximumWidth: number,\n): { text: string; cursorWidth: number } {\n let start = cursor;\n let widthBeforeCursor = 0;\n const followingWidth = cursor < segments.length ? stringWidth(segments[cursor] ?? '') : 0;\n const beforeLimit = Math.max(0, maximumWidth - Math.min(followingWidth, maximumWidth));\n\n while (start > 0) {\n const width = stringWidth(segments[start - 1] ?? '');\n if (widthBeforeCursor + width > beforeLimit) break;\n widthBeforeCursor += width;\n start -= 1;\n }\n\n let end = cursor;\n let totalWidth = widthBeforeCursor;\n while (end < segments.length) {\n const width = stringWidth(segments[end] ?? '');\n if (totalWidth + width > maximumWidth) break;\n totalWidth += width;\n end += 1;\n }\n\n return {\n text: segments.slice(start, end).join(''),\n cursorWidth: widthBeforeCursor,\n };\n}\n\n/**\n * \uC774 \uC785\uB825\uC774 \uD55C/\uC601 \uC804\uD658\uC778\uAC00.\n *\n * \uD130\uBBF8\uB110\uB9C8\uB2E4 \uAC19\uC740 \uD0A4\uAC00 \uB2E4\uB978 \uBAA8\uC2B5\uC73C\uB85C \uC628\uB2E4. \uD558\uB098\uB97C \uB193\uCE58\uBA74 \uADF8 \uD130\uBBF8\uB110\uC5D0\uC11C\uB294 \uD55C\uAE00\uC744\n * \uCF1C\uC9C0\uB3C4 \uB044\uC9C0\uB3C4 \uBABB\uD55C\uB2E4.\n */\nexport function isHangulToggle(\n input: string,\n key: { ctrl: boolean; meta: boolean; shift: boolean },\n): boolean {\n if (key.ctrl && (input === '`' || input === ' ' || input === 'l')) return true; // Ctrl+Space \u00B7 Ctrl+L\n if (key.meta && input === ' ') return true; // Alt+Space \u2014 \uD55C/\uC601 \uD0A4\uAC00 \uB193\uC778 \uC790\uB9AC\n if (key.shift && input === ' ') return true; // Shift+Space\n return false;\n}\n\nfunction TerminalCursor({ x, y }: { x: number; y: number }): null {\n const { setCursorPosition } = useCursor();\n setCursorPosition({ x, y });\n return null;\n}\n\n/**\n * \uC9C4\uC9DC \uD130\uBBF8\uB110 \uCEE4\uC11C\uB97C \uAE00\uC790 \uC790\uB9AC\uC5D0 \uB450\uB294 \uD55C \uC904 \uC785\uB825 \uCE78.\n *\n * \uD130\uBBF8\uB110 IME \uB294 \uC870\uD569 \uC911\uC778 \uD55C\uAE00\uC744 \uCEE4\uC11C \uC790\uB9AC\uC5D0 \uADF8\uB9B0\uB2E4. \uADF8\uB798\uC11C \uCEE4\uC11C\uAC00 \uC5B4\uB514\uC5D0 \uC11C\uB294\uC9C0\uAC00\n * \uACE7 \uD55C\uAE00\uC774 \uC5B4\uB514\uC5D0 \uBCF4\uC774\uB294\uC9C0\uB2E4.\n */\nexport function ImeTextInput(props: ImeTextInputProps): React.ReactNode {\n const [ref, placement] = useMeasured();\n const initialSegments = graphemes(props.value);\n const [cursor, setCursor] = useState(initialSegments.length);\n const valueRef = useRef(props.value);\n const cursorRef = useRef(initialSegments.length);\n const pastingRef = useRef(false);\n /** \uC544\uC9C1 \uC644\uC131\uB418\uC9C0 \uC54A\uC740 \uD55C\uAE00 \uD55C \uAE00\uC790. \uAC12\uC5D0\uB294 \uC774\uBBF8 \uBCF4\uC774\uC9C0\uB9CC \uB2E4\uC74C \uD0A4\uB85C \uBC14\uB014 \uC218 \uC788\uB2E4. */\n const typingRef = useRef<hangul.Typing>(hangul.IDLE);\n\n const moveCursor = (next: number, length: number): void => {\n const resolved = clamp(next, 0, length);\n cursorRef.current = resolved;\n setCursor(resolved);\n };\n\n const updateValue = (segments: string[], nextCursor: number): void => {\n const nextValue = segments.join('');\n valueRef.current = nextValue;\n moveCursor(nextCursor, segments.length);\n props.onChange(nextValue);\n };\n\n // \uD55C/\uC601 \uD0A4(\uC624\uB978\uCABD Alt \uC790\uB9AC)\uC640 Caps Lock \uC740 \uAE00\uC790\uB97C \uB9CC\uB4E4\uC9C0 \uC54A\uC544 \uBCF4\uD1B5\uC740 \uC571\uC5D0 \uC624\uC9C0\n // \uC54A\uB294\uB2E4. Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC744 \uC544\uB294 \uD130\uBBF8\uB110\uB9CC \uC774 \uC0AC\uAC74\uC744 \uBCF4\uB0B4 \uC8FC\uBBC0\uB85C, \uC6D0\uC2DC\n // \uC785\uB825\uC744 \uACC1\uC5D0\uC11C \uC9C0\uCF1C\uBCF8\uB2E4 \u2014 ink \uC740 \uC774 \uC0AC\uAC74\uB4E4\uC744 \uBE48 \uC785\uB825\uC73C\uB85C \uD758\uB824\uBCF4\uB0B8\uB2E4.\n const { stdin, isRawModeSupported } = useStdin();\n const onModeKeyRef = useRef<(() => void) | undefined>(undefined);\n onModeKeyRef.current = () => props.onHangulModeChange?.(!props.hangulMode);\n useEffect(() => {\n if (!props.focus || !isRawModeSupported) return undefined;\n const onData = (data: Buffer | string): void => {\n const chunk = typeof data === 'string' ? data : data.toString('utf8');\n for (const event of parseKeyEvents(chunk)) {\n // \uD130\uBBF8\uB110\uC774 \uC54C\uB824 \uC8FC\uBA74 \uCD94\uC815 \uB300\uC2E0 \uADF8 \uAC12\uC744 \uBBFF\uB294\uB2E4.\n typingRef.current = { ...typingRef.current, capsLock: event.capsLock };\n // \uB5C4 \uB54C\uAC00 \uC544\uB2C8\uB77C \uB204\uB97C \uB54C \uD55C \uBC88\uB9CC \uBC14\uAFBC\uB2E4.\n if (event.eventType !== 1) continue;\n if (event.name === 'rightalt' || event.name === 'capslock') onModeKeyRef.current?.();\n }\n };\n stdin?.on('data', onData);\n return () => void stdin?.off('data', onData);\n }, [props.focus, isRawModeSupported, stdin]);\n\n // \uD3EC\uCEE4\uC2A4\uB97C \uC783\uAC70\uB098 \uD55C\uAE00 \uBAA8\uB4DC\uB97C \uB044\uBA74 \uC870\uD569\uC744 \uB05D\uB0B8\uB2E4. \uB0A8\uACA8 \uB450\uBA74 \uB2E4\uC74C\uC5D0 \uB3CC\uC544\uC654\uC744 \uB54C\n // \uC5C9\uB6B1\uD55C \uAE00\uC790\uC5D0 \uC774\uC5B4 \uBD99\uB294\uB2E4.\n useEffect(() => {\n // Caps Lock \uD310\uB2E8\uC740 \uB0A8\uACA8 \uB454\uB2E4 \u2014 \uBAA8\uB4DC\uB97C \uAED0\uB2E4 \uCF20\uB2E4\uACE0 \uC790\uD310\uC774 \uBC14\uB00C\uC9C0\uB294 \uC54A\uB294\uB2E4.\n if (!props.focus || !props.hangulMode) {\n typingRef.current = { ...hangul.IDLE, capsLock: typingRef.current.capsLock };\n }\n }, [props.focus, props.hangulMode]);\n\n useEffect(() => {\n if (props.value === valueRef.current) return;\n const previousLength = graphemes(valueRef.current).length;\n const nextLength = graphemes(props.value).length;\n const wasAtEnd = cursorRef.current >= previousLength;\n valueRef.current = props.value;\n moveCursor(wasAtEnd ? nextLength : cursorRef.current, nextLength);\n }, [props.value]);\n\n /**\n * \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB97C \uAC12\uC5D0 **\uADF8\uB300\uB85C \uBC18\uC601**\uD55C\uB2E4.\n *\n * \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB294 \uAC12\uC758 \uCEE4\uC11C \uBC14\uB85C \uC55E \uD55C \uAE00\uC790\uB97C \uCC28\uC9C0\uD55C\uB2E4. \uD0A4\uAC00 \uC62C \uB54C\uB9C8\uB2E4 \uADF8 \uC790\uB9AC\uB97C\n * \uC0C8 \uBAA8\uC2B5\uC73C\uB85C \uAC08\uC544 \uB07C\uC6B0\uBBC0\uB85C, \uC0AC\uC6A9\uC790\uB294 `\u3131 \u2192 \uAC00 \u2192 \uAC04` \uC774 \uC790\uB77C\uB098\uB294 \uAC83\uC744 \uADF8\uB300\uB85C \uBCF8\uB2E4.\n * \uAC12\uC774 \uACE7 \uD654\uBA74\uC774\uB77C \uB530\uB85C \uADF8\uB9B4 \uAC83\uC774 \uC5C6\uACE0, \uC804\uC1A1\uD558\uBA74 \uBCF4\uC774\uB358 \uADF8\uB300\uB85C \uB098\uAC04\uB2E4.\n */\n const applyComposition = (\n segments: string[],\n cursor: number,\n previous: string,\n commit: string,\n next: string,\n ): void => {\n const removed = previous ? 1 : 0;\n const inserted = graphemes(commit + next);\n segments.splice(cursor - removed, removed, ...inserted);\n updateValue(segments, cursor - removed + inserted.length);\n };\n\n useInput(\n (input, key) => {\n const current = graphemes(valueRef.current);\n const currentCursor = clamp(cursorRef.current, 0, current.length);\n const event = classifyInput(input, pastingRef.current);\n const shown = hangul.display(typingRef.current.state);\n\n /** \uC870\uD569\uC744 \uB05D\uB0B8\uB2E4. \uCEE4\uC11C\uB97C \uC62E\uAE30\uAC70\uB098 \uC804\uC1A1\uD558\uAE30 \uC804\uC5D0 \uBD80\uB978\uB2E4. */\n const settle = (): void => {\n typingRef.current = { ...hangul.IDLE, capsLock: typingRef.current.capsLock };\n };\n\n if (event.kind === 'paste-start') {\n settle();\n pastingRef.current = true;\n return;\n }\n if (event.kind === 'paste-end') {\n pastingRef.current = false;\n return;\n }\n\n // \uBD99\uC5EC\uB123\uB294 \uB3D9\uC548\uC740 \uD0A4\uB85C \uC77D\uC9C0 \uC54A\uB294\uB2E4. \uBD99\uC778 \uB0B4\uC6A9 \uC548\uC758 \uC904\uBC14\uAFC8\uC774 \"\uC804\uC1A1\" \uC73C\uB85C\n // \uC77D\uD788\uBA74 \uBC18\uCABD\uC9DC\uB9AC \uBA54\uC2DC\uC9C0\uAC00 \uB098\uAC00 \uBC84\uB9B0\uB2E4.\n if (pastingRef.current) {\n if (event.kind === 'text') {\n const inserted = graphemes(event.text);\n current.splice(currentCursor, 0, ...inserted);\n updateValue(current, currentCursor + inserted.length);\n }\n return;\n }\n\n // Ctrl+Space \uB85C \uD55C/\uC601\uC744 \uBC14\uAFBC\uB2E4 \u2014 ibus\u00B7fcitx \uB97C \uC4F0\uB358 \uC190\uC774 \uC774\uBBF8 \uC544\uB294 \uC790\uB9AC\uB2E4.\n // (ink \uC740 Ctrl+Space \uB97C ctrl + '`' \uB85C \uC900\uB2E4.) Ctrl+L \uB3C4 \uBC1B\uB294\uB2E4: \uD130\uBBF8\uB110\uC774\uB098\n // tmux \uAC00 Ctrl+Space \uB97C \uBA3C\uC800 \uCC44\uAC00\uB294 \uACBD\uC6B0\uAC00 \uC788\uB2E4.\n // \uD55C/\uC601 \uC804\uD658 \uD0A4\uB4E4.\n //\n // \uAC19\uC740 Ctrl+Space \uB77C\uB3C4 \uD130\uBBF8\uB110\uC5D0 \uB530\uB77C \uB2E4\uB974\uAC8C \uB3C4\uCC29\uD55C\uB2E4. \uC608\uC804 \uBC29\uC2DD\uC5D0\uC11C\uB294 NUL \uC774\n // \uC640\uC11C ink \uC774 ctrl + '`' \uB85C \uC77D\uACE0, Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC5D0\uC11C\uB294 **ctrl \uC774 \uBD99\uC740\n // \uACF5\uBC31**\uC73C\uB85C \uC628\uB2E4. \uC55E\uC758 \uAC83\uB9CC \uBCF4\uACE0 \uC788\uC5B4\uC11C kitty \uC5D0\uC11C\uB294 \uC544\uBB34 \uC77C\uB3C4 \uC77C\uC5B4\uB098\uC9C0\n // \uC54A\uC558\uB2E4 \u2014 \uBAA8\uB4DC\uAC00 \uCF1C\uC838 \uC788\uC5B4\uB3C4 \uB418\uB3CC\uB9B4 \uC218\uAC00 \uC5C6\uC5C8\uB2E4.\n //\n // Shift+Space \uB3C4 \uBC1B\uB294\uB2E4(\uB9AC\uB205\uC2A4 \uC785\uB825\uAE30\uC758 \uC624\uB79C \uD55C/\uC601 \uC790\uB9AC). \uC218\uC2DD \uC5C6\uB294 \uADF8\uB0E5 \uACF5\uBC31\uC740\n // \uAC78\uB9AC\uC9C0 \uC54A\uC73C\uBBC0\uB85C \uAE00 \uC4F0\uB294 \uB370 \uC9C0\uC7A5\uC774 \uC5C6\uB2E4.\n if (isHangulToggle(input, key)) {\n settle();\n props.onHangulModeChange?.(!props.hangulMode);\n return;\n }\n\n if (key.return) {\n settle();\n props.onSubmit?.(valueRef.current);\n return;\n }\n if (key.leftArrow) {\n settle();\n moveCursor(currentCursor - 1, current.length);\n return;\n }\n if (key.rightArrow) {\n settle();\n moveCursor(currentCursor + 1, current.length);\n return;\n }\n if (key.home) {\n settle();\n moveCursor(0, current.length);\n return;\n }\n if (key.end) {\n settle();\n moveCursor(current.length, current.length);\n return;\n }\n if (key.backspace || key.delete) {\n // \uC870\uD569 \uC911\uC774\uBA74 \uAE00\uC790\uB97C \uB418\uC9DA\uB294\uB2E4: `\uD55C` \u2192 `\uD558` \u2192 `\u314E`. \uD1B5\uC9F8\uB85C \uC9C0\uC6B0\uBA74 \uC624\uD0C0\n // \uD558\uB098\uC5D0 \uCC98\uC74C\uBD80\uD130 \uB2E4\uC2DC \uCCD0\uC57C \uD55C\uB2E4.\n const stepped = hangul.backspace(typingRef.current);\n if (stepped.handled) {\n typingRef.current = stepped.session;\n applyComposition(current, currentCursor, shown, '', stepped.composing);\n return;\n }\n if (currentCursor === 0) return;\n current.splice(currentCursor - 1, 1);\n updateValue(current, currentCursor - 1);\n return;\n }\n if (\n key.ctrl ||\n key.meta ||\n key.tab ||\n key.escape ||\n key.upArrow ||\n key.downArrow ||\n key.pageUp ||\n key.pageDown\n ) {\n settle();\n return;\n }\n if (event.kind !== 'text') return;\n\n if (props.hangulMode) {\n // \uD55C \uBC88\uC5D0 \uC5EC\uB7EC \uAE00\uC790\uAC00 \uC624\uB294 \uAC83(\uBE60\uB978 \uC785\uB825)\uB3C4 \uC21C\uC11C\uB300\uB85C \uBA39\uC778\uB2E4.\n let session = typingRef.current;\n let previous = shown;\n let segments = current;\n let cursor = currentCursor;\n for (const character of event.text) {\n const result = hangul.typeKey(session, character);\n session = result.session;\n applyComposition(segments, cursor, previous, result.commit, result.composing);\n segments = graphemes(valueRef.current);\n cursor = cursorRef.current;\n previous = result.composing;\n }\n typingRef.current = session;\n return;\n }\n\n settle();\n const inserted = graphemes(event.text);\n current.splice(currentCursor, 0, ...inserted);\n updateValue(current, currentCursor + inserted.length);\n },\n { isActive: props.focus },\n );\n\n const rawSegments = graphemes(props.value);\n const safeCursor = clamp(cursor, 0, rawSegments.length);\n const displayedSegments = props.mask ? rawSegments.map(() => props.mask ?? '') : rawSegments;\n // \uC870\uD569 \uC911\uC778 \uAE00\uC790\uAC00 \uC124 \uC790\uB9AC \uD55C \uCE78\uC744 \uB0A8\uAE34\uB2E4.\n const maximumWidth = Math.max(1, (placement?.width ?? 40) - 1);\n const visible = visibleInput(displayedSegments, safeCursor, maximumWidth);\n\n return (\n <Box ref={ref} flexGrow={1}>\n {rawSegments.length === 0 ? (\n <Text dimColor>{props.placeholder ?? ''}</Text>\n ) : (\n <Text>{visible.text}</Text>\n )}\n {props.focus && placement ? (\n <TerminalCursor x={placement.x + visible.cursorWidth} y={placement.y} />\n ) : null}\n </Box>\n );\n}\n", "/**\n * \uD130\uBBF8\uB110\uC774 \uBCF4\uB0B4\uC624\uB294 \uBC14\uC774\uD2B8 \uC911 **\uBB34\uC5C7\uC774 \uC0AC\uB78C\uC774 \uCE5C \uAE00\uC790\uC778\uAC00** \uB97C \uAC00\uB978\uB2E4.\n *\n * \uD130\uBBF8\uB110\uC740 \uD0A4 \uC785\uB825\uB9CC \uBCF4\uB0B4\uC9C0 \uC54A\uB294\uB2E4. \uCC3D \uD3EC\uCEE4\uC2A4\uAC00 \uBC14\uB00C\uBA74 `ESC[I`/`ESC[O` \uB97C,\n * \uB9C8\uC6B0\uC2A4\uB97C \uC6C0\uC9C1\uC774\uBA74 `ESC[<0;1;1M` \uC744, \uD06C\uAE30\u00B7\uC7A5\uCE58\uB97C \uBB3C\uC5B4\uBCF8 \uC801\uC774 \uC788\uC73C\uBA74 `ESC[1;2R`\u00B7\n * `ESC[?1;2c` \uB97C, \uBD99\uC5EC\uB123\uAE30\uC5D0\uB294 `ESC[200~` ... `ESC[201~` \uB85C \uAC10\uC2F8\uC11C \uBCF4\uB0B8\uB2E4. \uC774\uAC83\uB4E4\uC740\n * \uC0AC\uC6A9\uC790\uAC00 \uCE5C \uC801 \uC5C6\uB294 \uC785\uB825\uC774\uACE0, \uC55E\uC758 ESC \uD55C \uAE00\uC790\uB294 ink \uC774 \uB5BC\uC5B4 \uB0B8 \uB4A4 \uC6B0\uB9AC\uC5D0\uAC8C\n * \uC628\uB2E4. \uADF8\uB300\uB85C \uBC1B\uC544 \uB123\uC73C\uBA74 \uBA54\uC2DC\uC9C0 \uCE78\uC5D0 `[200~`\u00B7`[I`\u00B7`[<0;1;1M` \uAC19\uC740 \uAC83\uC774 \uD0C0\uC774\uD551\uB41C\uB2E4.\n *\n * \uD55C\uAE00\uC5D0\uC11C \uD2B9\uD788 \uC544\uD504\uB2E4. IME \uD6C4\uBCF4\uCC3D\uC774 \uB728\uACE0 \uB2EB\uD790 \uB54C\uB9C8\uB2E4 \uD130\uBBF8\uB110 \uD3EC\uCEE4\uC2A4\uAC00 \uC624\uAC00\uBA74\uC11C\n * `[I`/`[O` \uAC00 \uAE00\uC790 \uC0AC\uC774\uC5D0 \uBC15\uD788\uACE0, \uCEE4\uBC0B\uB41C \uAE00\uC790\uAC00 \uBD99\uC5EC\uB123\uAE30\uB85C \uC624\uBA74 `[200~` \uC774 \uC55E\uC5D0\n * \uBD99\uB294\uB2E4. \uC0AC\uC6A9\uC790\uC5D0\uAC8C\uB294 \"\uD55C\uAE00\uC774 \uC785\uB825\uB418\uC9C0 \uC54A\uB294\uB2E4\" \uB85C \uBCF4\uC778\uB2E4.\n *\n * \uADF8\uB798\uC11C \uB450 \uACB9\uC73C\uB85C \uB9C9\uB294\uB2E4. \uD130\uBBF8\uB110\uC5D0\uAC8C \uC774\uB7F0 \uBCF4\uACE0\uB97C \uC544\uC608 \uBCF4\uB0B4\uC9C0 \uB9D0\uB77C\uACE0 \uD558\uACE0\n * ([screen.ts] \uCC38\uACE0), \uADF8\uB798\uB3C4 \uC624\uB294 \uAC83\uC740 \uC5EC\uAE30\uC11C \uAC78\uB7EC \uB0B8\uB2E4 \u2014 \uBAA8\uB4DC\uB294 \uC55E\uC11C \uC2E4\uD589\uB41C\n * \uD504\uB85C\uADF8\uB7A8\uC774 \uCF1C \uB450\uACE0 \uB044\uC9C0 \uC54A\uC740 \uCC44 \uB0A8\uC544 \uC788\uC744 \uC218 \uC788\uB2E4.\n */\n\nexport type InputEvent =\n /** \uC0AC\uB78C\uC774 \uCE5C \uAE00\uC790. \uADF8\uB300\uB85C \uB123\uB294\uB2E4. */\n | { kind: 'text'; text: string }\n /** \uBD99\uC5EC\uB123\uAE30 \uC2DC\uC791 \u2014 \uC5EC\uAE30\uC11C\uBD80\uD130 \uC624\uB294 \uAC83\uC740 \uD0A4\uAC00 \uC544\uB2C8\uB77C \uB0B4\uC6A9\uC774\uB2E4. */\n | { kind: 'paste-start' }\n | { kind: 'paste-end' }\n /** \uD130\uBBF8\uB110\uC774 \uBCF4\uB0B8 \uBCF4\uACE0. \uC0AC\uC6A9\uC790\uAC00 \uCE5C \uAC83\uC774 \uC544\uB2C8\uB2E4. */\n | { kind: 'ignore' };\n\nconst PASTE_START = '[200~';\nconst PASTE_END = '[201~';\n\n/**\n * ESC \uAC00 \uB5A8\uC5B4\uC838 \uB098\uAC04 \uC81C\uC5B4 \uC2DC\uD000\uC2A4\uC758 \uAF2C\uB9AC.\n *\n * CSI \uB294 `[` + \uB9E4\uAC1C\uBCC0\uC218 + \uB9C8\uC9C0\uB9C9 \uBC14\uC774\uD2B8, SS3 \uB294 `O` + \uB9C8\uC9C0\uB9C9 \uBC14\uC774\uD2B8\uB2E4. \uC0AC\uB78C\uC774 \uCE5C\n * `[` \uB098 `O` \uB294 **\uD55C \uAE00\uC790\uC9DC\uB9AC \uC774\uBCA4\uD2B8 \uD558\uB098**\uB85C \uC624\uBBC0\uB85C \uC774 \uADDC\uCE59\uC5D0 \uAC78\uB9AC\uC9C0 \uC54A\uB294\uB2E4 \u2014\n * \uB450 \uAE00\uC790 \uC774\uC0C1\uC774 \uD55C \uBC88\uC5D0 \uC624\uBA74\uC11C \uC774 \uBAA8\uC591\uC774\uBA74 \uD130\uBBF8\uB110\uC774 \uBCF4\uB0B8 \uAC83\uC774\uB2E4.\n */\nconst CONTROL_TAIL = /^(?:\\[[\\d;:<>?!\"'$ ]*[@-~]|O[@-~])$/;\n\n/** \uD654\uBA74\uC5D0 \uADF8\uB824\uC9C0\uC9C0 \uC54A\uB294 C0 \uC81C\uC5B4\uBB38\uC790\uC640 DEL. \uAC12\uC5D0 \uB4E4\uC5B4\uAC00\uBA74 \uBCF4\uC774\uC9C0 \uC54A\uB294 \uC4F0\uB808\uAE30\uAC00 \uB41C\uB2E4. */\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHARS = /[\\u0000-\\u001F\\u007F]/g;\n\n/**\n * \uD55C \uBC88\uC758 \uC785\uB825 \uC774\uBCA4\uD2B8\uB97C \uAC08\uB798\uB0B8\uB2E4.\n *\n * `pasting` \uC774 \uCC38\uC774\uBA74 \uB0B4\uC6A9\uC744 \uAE00\uC790\uB85C\uB9CC \uBCF8\uB2E4 \u2014 \uBD99\uC5EC\uB123\uAE30 \uC548\uC758 `\\r` \uC740 \"\uC804\uC1A1\" \uC774 \uC544\uB2C8\uACE0,\n * `[` \uB85C \uC2DC\uC791\uD558\uB294 \uC904\uB3C4 \uC81C\uC5B4 \uC2DC\uD000\uC2A4\uAC00 \uC544\uB2C8\uB2E4.\n */\nexport function classifyInput(input: string, pasting = false): InputEvent {\n if (input === PASTE_START) return { kind: 'paste-start' };\n if (input === PASTE_END) return { kind: 'paste-end' };\n if (!pasting && input.length > 1 && CONTROL_TAIL.test(input)) return { kind: 'ignore' };\n\n // \uC5EC\uB7EC \uC904 \uBD99\uC5EC\uB123\uAE30\uB294 \uD55C \uC904 \uC785\uB825 \uCE78\uC5D0 \uB9DE\uAC8C \uACF5\uBC31\uC73C\uB85C \uB215\uD78C\uB2E4. \uC904\uBC14\uAFC8\uC744 \uB0A8\uAE30\uBA74\n // \uB80C\uB354\uAC00 \uAE68\uC9C0\uACE0, \uBC84\uB9AC\uBA74 \uB2E8\uC5B4\uAC00 \uBD99\uC5B4 \uBC84\uB9B0\uB2E4.\n const flattened = input.replace(/\\r\\n|[\\r\\n]/g, ' ');\n const text = flattened.replace(CONTROL_CHARS, '');\n return text ? { kind: 'text', text } : { kind: 'ignore' };\n}\n", "/**\n * \uB450\uBC8C\uC2DD \uD55C\uAE00 \uC870\uD569\uAE30.\n *\n * \uC608\uC804\uC5D0\uB294 \uD130\uBBF8\uB110\uC758 IME \uC5D0 \uB9E1\uACBC\uB2E4 \u2014 \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB294 \uD130\uBBF8\uB110\uC774 \uCEE4\uC11C \uC790\uB9AC\uC5D0 \uADF8\uB9AC\uACE0,\n * \uC644\uC131\uB41C \uAE00\uC790\uB9CC \uC6B0\uB9AC\uC5D0\uAC8C \uC654\uB2E4. \uC798 \uB418\uB294 \uC870\uD569\uB3C4 \uC788\uC9C0\uB9CC **\uD130\uBBF8\uB110\uB9C8\uB2E4 \uB2E4\uB974\uACE0**, SSH \uB098\n * tmux \uB97C \uAC70\uCE58\uBA74 \uC544\uC608 \uC548 \uC624\uB294 \uACBD\uC6B0\uAC00 \uD754\uD558\uB2E4. \uC6B0\uB9AC \uCABD\uC5D0\uC11C\uB294 \uACE0\uCE60 \uC218\uAC00 \uC5C6\uB294 \uC790\uB9AC\uB2E4.\n *\n * \uADF8\uB798\uC11C \uC870\uD569\uC744 \uC5EC\uAE30\uC11C \uD55C\uB2E4. `r k s` \uB77C\uB294 \uC138 \uBC88\uC758 \uD0A4 \uC785\uB825\uC744 `\u3131 \u2192 \uAC00 \u2192 \uAC04` \uC73C\uB85C\n * \uB9CC\uB4DC\uB294 \uC77C\uC774\uB2E4. \uD130\uBBF8\uB110\uC774 \uBB34\uC5C7\uC744 \uD558\uB4E0, SSH \uB108\uBA38\uB4E0, \uD55C\uAE00\uC774 \uAC19\uC740 \uBC29\uC2DD\uC73C\uB85C \uB4E4\uC5B4\uAC04\uB2E4.\n *\n * \uC790\uD310\uC740 \uD45C\uC900 \uB450\uBC8C\uC2DD\uC774\uB2E4. \uACB9\uBC1B\uCE68\uC774 \uAC08\uB77C\uC9C0\uB294 \uC790\uB9AC(`\uAC04` + `\u314F` \u2192 `\uAC00` + `\uB098`)\uC640\n * \uBC31\uC2A4\uD398\uC774\uC2A4\uAC00 \uAE00\uC790\uB97C \uB418\uC9DA\uB294 \uC790\uB9AC(`\uD55C` \u2192 `\uD558` \u2192 `\u314E`)\uAC00 \uC774 \uD30C\uC77C\uC758 \uD575\uC2EC\uC774\uB2E4.\n */\n\n/** \uCD08\uC131 19\uC790. \uC778\uB371\uC2A4\uAC00 \uC720\uB2C8\uCF54\uB4DC \uACC4\uC0B0\uC5D0 \uADF8\uB300\uB85C \uC4F0\uC778\uB2E4. */\nconst CHO = '\u3131\u3132\u3134\u3137\u3138\u3139\u3141\u3142\u3143\u3145\u3146\u3147\u3148\u3149\u314A\u314B\u314C\u314D\u314E';\n/** \uC911\uC131 21\uC790. */\nconst JUNG = '\u314F\u3150\u3151\u3152\u3153\u3154\u3155\u3156\u3157\u3158\u3159\u315A\u315B\u315C\u315D\u315E\u315F\u3160\u3161\u3162\u3163';\n/** \uC885\uC131 28\uC790. 0\uBC88\uC740 \uBC1B\uCE68 \uC5C6\uC74C\uC774\uB77C \uC790\uB9AC\uB97C \uBE44\uC6CC \uB454\uB2E4. */\nconst JONG = ' \u3131\u3132\u3133\u3134\u3135\u3136\u3137\u3139\u313A\u313B\u313C\u313D\u313E\u313F\u3140\u3141\u3142\u3144\u3145\u3146\u3147\u3148\u314A\u314B\u314C\u314D\u314E';\n\nconst SYLLABLE_BASE = 0xac00;\n\n/**\n * \uB450\uBC8C\uC2DD \uC790\uD310. \uD45C\uC900\uB300\uB85C **\uC790\uC74C 19 + \uBAA8\uC74C 21** \uC774 \uC544\uB2C8\uB77C, \uD0A4\uB97C \uB20C\uB7EC \uB098\uC624\uB294 \uB0B1\uC790\uB9CC\n * \uC801\uB294\uB2E4 \u2014 \u3132\u3138\u3143\u3146\u3149\u3152\u3156 \uB294 \uC2DC\uD504\uD2B8\uB85C, \uB098\uBA38\uC9C0 \uB300\uBB38\uC790\uB294 \uC18C\uBB38\uC790\uC640 \uAC19\uC740 \uB0B1\uC790\uB2E4.\n */\nconst KEYS: Record<string, string> = {\n r: '\u3131', R: '\u3132', s: '\u3134', e: '\u3137', E: '\u3138', f: '\u3139', a: '\u3141', q: '\u3142', Q: '\u3143',\n t: '\u3145', T: '\u3146', d: '\u3147', w: '\u3148', W: '\u3149', c: '\u314A', z: '\u314B', x: '\u314C', v: '\u314D', g: '\u314E',\n k: '\u314F', o: '\u3150', i: '\u3151', O: '\u3152', j: '\u3153', p: '\u3154', u: '\u3155', P: '\u3156',\n h: '\u3157', y: '\u315B', n: '\u315C', b: '\u3160', m: '\u3161', l: '\u3163',\n};\n\n/** \uBAA8\uC74C \uB450 \uAC1C\uAC00 \uD558\uB098\uB85C \uD569\uCCD0\uC9C0\uB294 \uC790\uB9AC. */\nconst VOWEL_PAIRS: Record<string, string> = {\n '\u3157\u314F': '\u3158', '\u3157\u3150': '\u3159', '\u3157\u3163': '\u315A',\n '\u315C\u3153': '\u315D', '\u315C\u3154': '\u315E', '\u315C\u3163': '\u315F',\n '\u3161\u3163': '\u3162',\n};\n\n/** \uACB9\uBC1B\uCE68. */\nconst FINAL_PAIRS: Record<string, string> = {\n '\u3131\u3145': '\u3133',\n '\u3134\u3148': '\u3135', '\u3134\u314E': '\u3136',\n '\u3139\u3131': '\u313A', '\u3139\u3141': '\u313B', '\u3139\u3142': '\u313C', '\u3139\u3145': '\u313D', '\u3139\u314C': '\u313E', '\u3139\u314D': '\u313F', '\u3139\u314E': '\u3140',\n '\u3142\u3145': '\u3144',\n};\n\n/** \uD569\uCCD0\uC9C4 \uB0B1\uC790\uB97C \uB3C4\uB85C \uB458\uB85C \uAC00\uB978\uB2E4. \uAC08\uB77C\uC9C0\uB294 \uC790\uB9AC\uC5D0\uC11C \uC4F4\uB2E4. */\nconst SPLIT: Record<string, [string, string]> = Object.fromEntries(\n [...Object.entries(VOWEL_PAIRS), ...Object.entries(FINAL_PAIRS)].map(([pair, joined]) => [\n joined,\n [pair[0]!, pair[1]!] as [string, string],\n ]),\n);\n\n/**\n * \uC870\uD569 \uC911\uC778 \uAE00\uC790 \uD558\uB098.\n *\n * \uC544\uC9C1 \uC644\uC131\uB418\uC9C0 \uC54A\uC558\uC73C\uBBC0\uB85C \uAC12\uC5D0 \uB123\uC9C0 \uC54A\uACE0 \uB530\uB85C \uB4E4\uACE0 \uC788\uB294\uB2E4 \u2014 \uB2E4\uC74C \uD0A4\uAC00 \uBB34\uC5C7\uC774\uB0D0\uC5D0\n * \uB530\uB77C `\uAC00` \uAC00 `\uAC01` \uC774 \uB420 \uC218\uB3C4, `\uAC00` \uB85C \uB05D\uB098\uACE0 \uC0C8 \uAE00\uC790\uAC00 \uC2DC\uC791\uB420 \uC218\uB3C4 \uC788\uB2E4.\n */\nexport interface Composition {\n cho?: string;\n jung?: string;\n jong?: string;\n}\n\nexport const EMPTY: Composition = {};\n\n/**\n * \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uC57C \uB73B\uC774 \uB2EC\uB77C\uC9C0\uB294 \uD0A4\uB4E4 \u2014 \uB41C\uC18C\uB9AC\uC640 \u3152\u3156.\n *\n * \uB098\uBA38\uC9C0 \uAE00\uC1E0\uB294 \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uB3C4 \uAC19\uC740 \uB0B1\uC790\uB2E4. \uADF8\uB798\uC11C \uADF8\uB7F0 \uAE00\uC1E0\uC5D0 \uC2DC\uD504\uD2B8\uAC00 \uAC78\uB824\n * \uC788\uB2E4\uB294 \uAC83\uC740 **Caps Lock \uC774 \uCF1C\uC838 \uC788\uB2E4\uB294 \uB73B**\uC774\uB2E4 (\uC544\uBB34 \uC774\uB4DD\uB3C4 \uC5C6\uB294 \uC2DC\uD504\uD2B8\uB97C \uC77C\uBD80\uB7EC\n * \uB204\uB97C \uC774\uC720\uAC00 \uC5C6\uB2E4). \uC774 \uC131\uC9C8\uC744 Caps Lock \uD310\uB2E8\uC5D0 \uC4F4\uB2E4.\n */\nconst SHIFTED_KEYS = new Set(['r', 'e', 'q', 't', 'w', 'o', 'p']);\n\n/**\n * \uC774 \uD0A4\uAC00 \uD55C\uAE00 \uB0B1\uC790\uC778\uAC00. \uC544\uB2C8\uBA74 \uC870\uD569\uAE30\uB97C \uAC70\uCE58\uC9C0 \uC54A\uACE0 \uADF8\uB300\uB85C \uB4E4\uC5B4\uAC04\uB2E4.\n *\n * `capsLock` \uC774 \uCC38\uC774\uBA74 \uB300\uC18C\uBB38\uC790\uB97C \uB4A4\uC9D1\uC5B4 \uBCF8\uB2E4. Caps Lock \uC774 \uCF1C\uC838 \uC788\uC73C\uBA74 \uADF8\uB0E5 \uB204\uB978\n * \uAE00\uC1E0\uAC00 \uB300\uBB38\uC790\uB85C \uC624\uACE0, \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uC57C \uC18C\uBB38\uC790\uAC00 \uC628\uB2E4 \u2014 \uB4A4\uC9D1\uC9C0 \uC54A\uC73C\uBA74 `\uC548\uB155` \uC744\n * \uCE58\uB824\uB2E4 `\u3143\u3151\u3138\u3138` \uAC19\uC740 \uAC83\uC774 \uB098\uC628\uB2E4.\n */\nexport function jamoOf(key: string, capsLock = false): string | undefined {\n const effective = capsLock ? swapCase(key) : key;\n if (KEYS[effective]) return KEYS[effective];\n // \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uB3C4 \uAC19\uC740 \uB0B1\uC790\uC778 \uB300\uBB38\uC790\uB4E4 \u2014 \uC2E4\uC81C IME \uC640 \uAC19\uAC8C \uC18C\uBB38\uC790\uB85C \uBCF8\uB2E4.\n const lower = effective.toLowerCase();\n return lower === effective ? undefined : KEYS[lower];\n}\n\nfunction swapCase(key: string): string {\n const lower = key.toLowerCase();\n return key === lower ? key.toUpperCase() : lower;\n}\n\n/**\n * \uAE00\uC790 \uD558\uB098\uB97C \uBCF4\uACE0 Caps Lock \uC774 \uCF1C\uC838 \uC788\uB294\uC9C0 \uACE0\uCCD0 \uC7A1\uB294\uB2E4.\n *\n * \uD130\uBBF8\uB110\uC740 Caps Lock \uC0C1\uD0DC\uB97C \uC54C\uB824 \uC8FC\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC6B0\uB9AC\uC5D0\uAC8C \uC624\uB294 \uAC83\uC740 \uACB0\uACFC \uAE00\uC790\uBFD0\uC774\uB77C\n * `R` \uC774 Shift+r \uC778\uC9C0 Caps+r \uC778\uC9C0 \uAD6C\uBCC4\uD560 \uC218 \uC5C6\uB2E4. \uB300\uC2E0 **\uB73B \uC5C6\uB294 \uC2DC\uD504\uD2B8**\uB97C \uC2E0\uD638\uB85C\n * \uC4F4\uB2E4: `\u3141` \uC790\uB9AC(a)\uC5D0 \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uB3C4 `\u3141` \uC774\uBBC0\uB85C, \uB300\uBB38\uC790 `A` \uAC00 \uC654\uB2E4\uBA74 \uC0AC\uB78C\uC774\n * \uC77C\uBD80\uB7EC \uB204\uB978 \uAC83\uC774 \uC544\uB2C8\uB77C Caps Lock \uC774 \uCF1C\uC838 \uC788\uB294 \uAC83\uC774\uB2E4. \uBC18\uB300\uCABD\uB3C4 \uAC19\uB2E4 \u2014 Caps \uAC00\n * \uCF1C\uC9C4 \uC0C1\uD0DC\uC5D0\uC11C \uC18C\uBB38\uC790 `a` \uAC00 \uC654\uB2E4\uBA74 \uADF8\uB54C\uB9CC \uC2DC\uD504\uD2B8\uB97C \uB5C0 \uC148\uC774\uB2C8 Caps \uAC00 \uAEBC\uC9C4 \uAC83\uC774\uB2E4.\n *\n * \uB41C\uC18C\uB9AC \uAE00\uC1E0(r\u318De\u318Dq\u318Dt\u318Dw\u318Do\u318Dp)\uB294 \uC2DC\uD504\uD2B8\uC5D0 \uB73B\uC774 \uC788\uC73C\uBBC0\uB85C \uD310\uB2E8\uC5D0 \uC4F0\uC9C0 \uC54A\uB294\uB2E4.\n */\nexport function detectCapsLock(current: boolean, key: string): boolean {\n const lower = key.toLowerCase();\n const upper = key.toUpperCase();\n if (lower === upper) return current; // \uAE00\uC790\uAC00 \uC544\uB2C8\uBA74 \uC544\uBB34\uAC83\uB3C4 \uB9D0\uD574 \uC8FC\uC9C0 \uC54A\uB294\uB2E4\n if (!KEYS[lower]) return current; // \uD55C\uAE00 \uC790\uD310 \uBC16\uC758 \uAE00\uC1E0\n if (SHIFTED_KEYS.has(lower)) return current; // \uC2DC\uD504\uD2B8\uC5D0 \uB73B\uC774 \uC788\uB294 \uAE00\uC1E0\n return key === upper;\n}\n\nfunction isVowel(jamo: string): boolean {\n return JUNG.includes(jamo) || jamo === '\u3157' || jamo === '\u315C' || jamo === '\u3161';\n}\n\n/** \uBC1B\uCE68\uC73C\uB85C \uC124 \uC218 \uC788\uB294 \uC790\uC74C\uC778\uAC00. \u3138\u3143\u3149 \uC740 \uBABB \uC120\uB2E4. */\nfunction canBeFinal(jamo: string): boolean {\n return JONG.indexOf(jamo) > 0;\n}\n\n/** \uC870\uD569 \uC911\uC778 \uC0C1\uD0DC\uB97C \uB208\uC5D0 \uBCF4\uC774\uB294 \uAE00\uC790\uB85C. \uC544\uC9C1 \uC544\uBB34\uAC83\uB3C4 \uC5C6\uC73C\uBA74 \uBE48 \uBB38\uC790\uC5F4. */\nexport function display(state: Composition): string {\n const { cho, jung, jong } = state;\n if (cho && jung) {\n const l = CHO.indexOf(cho);\n const v = JUNG.indexOf(jung);\n const t = jong ? JONG.indexOf(jong) : 0;\n if (l >= 0 && v >= 0 && t >= 0) {\n return String.fromCharCode(SYLLABLE_BASE + (l * 21 + v) * 28 + t);\n }\n }\n // \uC544\uC9C1 \uD55C \uB0B1\uC790\uBFD0\uC774\uBA74 \uADF8 \uB0B1\uC790\uB97C \uADF8\uB300\uB85C \uBCF4\uC5EC \uC900\uB2E4 \u2014 `\u3131` \uC744 \uB204\uB978 \uC21C\uAC04\uBD80\uD130 \uBCF4\uC5EC\uC57C\n // \uBB34\uC5C7\uC774 \uB4E4\uC5B4\uAC00\uACE0 \uC788\uB294\uC9C0 \uC54C \uC218 \uC788\uB2E4.\n return cho ?? jung ?? '';\n}\n\nexport interface FeedResult {\n /** \uD655\uC815\uB418\uC5B4 \uAC12\uC5D0 \uB4E4\uC5B4\uAC08 \uAE00\uC790. \uC5C6\uC744 \uC218\uB3C4, \uD55C \uAE00\uC790\uC77C \uC218\uB3C4 \uC788\uB2E4. */\n commit: string;\n /** \uC544\uC9C1 \uC870\uD569 \uC911\uC778 \uC0C1\uD0DC. */\n state: Composition;\n}\n\n/**\n * \uB0B1\uC790 \uD558\uB098\uB97C \uB123\uB294\uB2E4.\n *\n * \uB3CC\uB824\uC8FC\uB294 `commit` \uC740 **\uC774\uBC88\uC5D0 \uD655\uC815\uB41C** \uAE00\uC790\uB2E4. \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB294 `state` \uC5D0 \uB0A8\uC544\n * \uB2E4\uC74C \uD0A4\uB97C \uAE30\uB2E4\uB9B0\uB2E4.\n */\nexport function feed(state: Composition, jamo: string): FeedResult {\n const { cho, jung, jong } = state;\n\n if (isVowel(jamo)) {\n // \uBC1B\uCE68\uC774 \uC788\uB294\uB370 \uBAA8\uC74C\uC774 \uC624\uBA74 \uADF8 \uBC1B\uCE68\uC740 \uC774 \uAE00\uC790\uC758 \uAC83\uC774 \uC544\uB2C8\uC5C8\uB2E4. \uC55E \uAE00\uC790\uC5D0\uC11C\n // \uB5BC\uC5B4 \uB0B4 \uC0C8 \uAE00\uC790\uC758 \uCCAB\uC18C\uB9AC\uB85C \uB118\uAE34\uB2E4: `\uAC04` + `\u314F` \u2192 `\uAC00` + `\uB098`.\n if (cho && jung && jong) {\n const parts = SPLIT[jong];\n const moved = parts ? parts[1] : jong;\n const kept = parts ? parts[0] : undefined;\n return {\n commit: display({ cho, jung, jong: kept }),\n state: { cho: moved, jung: jamo },\n };\n }\n if (cho && jung) {\n const merged = VOWEL_PAIRS[jung + jamo];\n if (merged) return { commit: '', state: { cho, jung: merged } };\n return { commit: display(state), state: { jung: jamo } };\n }\n if (cho) return { commit: '', state: { cho, jung: jamo } };\n if (jung) {\n const merged = VOWEL_PAIRS[jung + jamo];\n if (merged) return { commit: '', state: { jung: merged } };\n return { commit: jung, state: { jung: jamo } };\n }\n return { commit: '', state: { jung: jamo } };\n }\n\n // \uC790\uC74C\n if (cho && jung) {\n if (!jong) {\n if (canBeFinal(jamo)) return { commit: '', state: { cho, jung, jong: jamo } };\n return { commit: display(state), state: { cho: jamo } };\n }\n const merged = FINAL_PAIRS[jong + jamo];\n if (merged) return { commit: '', state: { cho, jung, jong: merged } };\n return { commit: display(state), state: { cho: jamo } };\n }\n if (cho) {\n // \uC790\uC74C\uC774 \uC787\uB2EC\uC544 \uC624\uBA74 \uC55E \uC790\uC74C\uC740 \uD640\uB85C \uB0A8\uB294\uB2E4 \u2014 `\u3131\u3134` \uCC98\uB7FC \uB0B1\uC790\uB85C \uCE5C \uACBD\uC6B0\uB2E4.\n return { commit: cho, state: { cho: jamo } };\n }\n if (jung) return { commit: jung, state: { cho: jamo } };\n return { commit: '', state: { cho: jamo } };\n}\n\nexport interface BackResult {\n state: Composition;\n /** \uC870\uD569\uAE30\uAC00 \uCC98\uB9AC\uD588\uB294\uAC00. \uC544\uB2C8\uBA74 \uBD80\uB974\uB294 \uCABD\uC774 \uAC12\uC5D0\uC11C \uD55C \uAE00\uC790\uB97C \uC9C0\uC6CC\uC57C \uD55C\uB2E4. */\n handled: boolean;\n}\n\n/**\n * \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB97C \uD55C \uB2E8\uACC4 \uB418\uC9DA\uB294\uB2E4: `\uD55C` \u2192 `\uD558` \u2192 `\u314E` \u2192 (\uC5C6\uC74C).\n *\n * \uC644\uC131\uB41C \uAE00\uC790\uB97C \uD1B5\uC9F8\uB85C \uC9C0\uC6B0\uB294 IME \uB3C4 \uC788\uC9C0\uB9CC, \uB418\uC9DA\uB294 \uCABD\uC774 \uC624\uD0C0\uB97C \uACE0\uCE58\uAE30 \uC27D\uB2E4.\n */\nexport function back(state: Composition): BackResult {\n const { cho, jung, jong } = state;\n if (jong) {\n const parts = SPLIT[jong];\n return { state: { cho, jung, jong: parts ? parts[0] : undefined }, handled: true };\n }\n if (jung) {\n const parts = SPLIT[jung];\n return { state: { cho, jung: parts ? parts[0] : undefined }, handled: true };\n }\n if (cho) return { state: EMPTY, handled: true };\n return { state: EMPTY, handled: false };\n}\n\n/** \uC870\uD569\uC744 \uB05D\uB0B4\uACE0 \uB0A8\uC740 \uAE00\uC790\uB97C \uD655\uC815\uD55C\uB2E4. \uB2E4\uB978 \uD0A4\uB85C \uB118\uC5B4\uAC00\uAC70\uB098 \uC804\uC1A1\uD560 \uB54C \uBD80\uB978\uB2E4. */\nexport function flush(state: Composition): { commit: string; state: Composition } {\n return { commit: display(state), state: EMPTY };\n}\n\n/**\n * \uD0C0\uC790 \uD55C \uD310. \uC870\uD569 \uC911\uC778 \uAE00\uC790\uC640, \uADF8\uAC83\uC744 \uB9CC\uB4E0 \uAE00\uC1E0\uC640, Caps Lock \uD310\uB2E8\uC744 \uD568\uAED8 \uB4E0\uB2E4.\n *\n * \uAE00\uC1E0\uB97C \uD568\uAED8 \uB4DC\uB294 \uC774\uC720\uB294 Caps Lock \uD310\uB2E8\uC774 **\uB2A6\uAC8C \uC11C\uAE30 \uB54C\uBB38**\uC774\uB2E4. \uB41C\uC18C\uB9AC \uAE00\uC1E0\uB294\n * \uC2DC\uD504\uD2B8\uC5D0 \uB73B\uC774 \uC788\uC5B4 \uD310\uB2E8 \uADFC\uAC70\uAC00 \uBABB \uB418\uBBC0\uB85C, `\uAE4C` \uB97C \uCE58\uB824\uACE0 \uC2DC\uD504\uD2B8\uB97C \uBA3C\uC800 \uB204\uB974\uBA74\n * \uADF8 \uAE00\uC1E0\uB294 \uC99D\uAC70 \uC5C6\uC774 \uC77D\uD78C\uB2E4. \uB2E4\uC74C \uAE00\uC1E0\uC5D0\uC11C \uD310\uB2E8\uC774 \uB4A4\uC9D1\uD788\uBA74 \uC9C0\uAE08 \uAE00\uC790\uB97C \uCC98\uC74C\uBD80\uD130\n * \uB2E4\uC2DC \uC9DA\uC5B4\uC57C \uD55C\uB2E4 \u2014 \uADF8\uB7EC\uC9C0 \uC54A\uC73C\uBA74 \uCCAB \uAE00\uC790\uB9CC \uC5C9\uB6B1\uD558\uAC8C \uB0A8\uB294\uB2E4.\n */\nexport interface Typing {\n state: Composition;\n keys: string[];\n capsLock: boolean;\n}\n\nexport const IDLE: Typing = { state: EMPTY, keys: [], capsLock: false };\n\nexport interface TypeResult {\n session: Typing;\n /** \uD655\uC815\uB418\uC5B4 \uAC12\uC5D0 \uB4E4\uC5B4\uAC08 \uAE00\uC790. \uB418\uC9DA\uB290\uB77C \uB298\uC5B4\uB0A0 \uC218\uB3C4 \uC788\uB2E4. */\n commit: string;\n /** \uC544\uC9C1 \uC870\uD569 \uC911\uC778 \uAE00\uC790. \uAC12\uC758 \uCEE4\uC11C \uC55E \uD55C \uAE00\uC790\uB97C \uCC28\uC9C0\uD55C\uB2E4. */\n composing: string;\n}\n\n/** \uAE00\uC1E0 \uD558\uB098\uB97C \uCE5C\uB2E4. \uD55C\uAE00 \uB0B1\uC790\uAC00 \uC544\uB2C8\uBA74 \uC870\uD569\uC744 \uB05D\uB0B4\uACE0 \uADF8 \uAE00\uC790\uB97C \uADF8\uB300\uB85C \uC2E3\uB294\uB2E4. */\nexport function typeKey(session: Typing, key: string): TypeResult {\n const caps = detectCapsLock(session.capsLock, key);\n let { state, keys } = session;\n let commit = '';\n\n // \uD310\uB2E8\uC774 \uB4A4\uC9D1\uD614\uC73C\uBA74 \uC9C0\uAE08 \uAE00\uC790\uB97C \uCC98\uC74C\uBD80\uD130 \uB2E4\uC2DC \uC9DA\uB294\uB2E4.\n if (caps !== session.capsLock && keys.length > 0) {\n let rebuilt: Composition = EMPTY;\n for (const previous of keys) {\n const jamo = jamoOf(previous, caps);\n if (!jamo) continue;\n const step = feed(rebuilt, jamo);\n commit += step.commit;\n rebuilt = step.state;\n }\n state = rebuilt;\n }\n\n const jamo = jamoOf(key, caps);\n if (!jamo) {\n commit += display(state) + key;\n return { session: { state: EMPTY, keys: [], capsLock: caps }, commit, composing: '' };\n }\n\n const result = feed(state, jamo);\n commit += result.commit;\n // \uAE00\uC790\uAC00 \uD655\uC815\uB418\uBA74 \uC55E \uAE00\uC790\uC758 \uAE00\uC1E0\uB294 \uC78A\uB294\uB2E4 \u2014 \uB418\uC9DA\uC744 \uB300\uC0C1\uC740 \uC9C0\uAE08 \uAE00\uC790\uBFD0\uC774\uB2E4.\n keys = result.commit ? [key] : [...keys, key];\n return {\n session: { state: result.state, keys, capsLock: caps },\n commit,\n composing: display(result.state),\n };\n}\n\n/** \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB97C \uD55C \uB2E8\uACC4 \uB418\uC9DA\uB294\uB2E4. \uAE00\uC1E0 \uAE30\uB85D\uB3C4 \uD568\uAED8 \uC904\uC778\uB2E4. */\nexport function backspace(session: Typing): { session: Typing; composing: string; handled: boolean } {\n const stepped = back(session.state);\n if (!stepped.handled) return { session, composing: '', handled: false };\n return {\n session: { ...session, state: stepped.state, keys: session.keys.slice(0, -1) },\n composing: display(stepped.state),\n handled: true,\n };\n}\n\n/**\n * \uBB38\uC790\uC5F4 \uD558\uB098\uB97C \uD1B5\uC9F8\uB85C \uC870\uD569\uD55C\uB2E4. \uC2DC\uD5D8\uACFC \uBD99\uC5EC\uB123\uAE30\uC5D0 \uC4F4\uB2E4.\n *\n * `'rkstk'` \u2192 `'\uAC04\uC0AC'` \uCC98\uB7FC, \uD0A4\uB97C \uC21C\uC11C\uB300\uB85C \uB20C\uB800\uC744 \uB54C \uB098\uC624\uB294 \uACB0\uACFC.\n */\nexport function compose(keys: string, capsLock = false): string {\n let session: Typing = { ...IDLE, capsLock };\n let text = '';\n for (const key of keys) {\n const result = typeKey(session, key);\n text += result.commit;\n session = result.session;\n }\n return text + display(session.state);\n}\n", "/**\n * \uD130\uBBF8\uB110\uC774 **\uD0A4 \uC790\uCCB4**\uB97C \uC54C\uB824 \uC8FC\uAC8C \uD55C\uB2E4.\n *\n * \uBCF4\uD1B5 \uD130\uBBF8\uB110\uC740 \uAE00\uC790\uB9CC \uBCF4\uB0B8\uB2E4. \uADF8\uB798\uC11C \uD55C/\uC601 \uD0A4(\uC624\uB978\uCABD Alt \uC790\uB9AC)\uB098 Caps Lock \uCC98\uB7FC\n * \uAE00\uC790\uB97C \uB9CC\uB4E4\uC9C0 \uC54A\uB294 \uD0A4\uB294 \uC571\uC5D0 \uC544\uC608 \uB3C4\uCC29\uD558\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC5B4\uB5A4 \uD130\uBBF8\uB110 \uD504\uB85C\uADF8\uB7A8\uB3C4 \uADF8\n * \uD0A4\uAC00 \uB20C\uB838\uB294\uC9C0 \uC54C \uC218 \uC5C6\uB2E4.\n *\n * Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC740 \uADF8 \uD0A4\uB4E4\uAE4C\uC9C0 `ESC[<\uCF54\uB4DC>;<\uC218\uC2DD>u` \uB85C \uBCF4\uACE0\uD55C\uB2E4. \uC9C0\uC6D0\uD558\uB294\n * \uD130\uBBF8\uB110(kitty\u00B7ghostty\u00B7WezTerm\u00B7foot\u00B7Alacritty\u00B7\uCD5C\uC2E0 Konsole \uB4F1)\uC5D0\uC11C\uB9CC \uCF1C\uC9C0\uACE0, \uB098\uBA38\uC9C0\uB294\n * \uBB3C\uC5B4\uBD10\uB3C4 \uB300\uB2F5\uD558\uC9C0 \uC54A\uC73C\uBBC0\uB85C \uADF8\uB0E5 \uC608\uC804\uCC98\uB7FC \uB3D9\uC791\uD55C\uB2E4 \u2014 \uCF1C\uB3C4 \uC783\uB294 \uAC83\uC774 \uC5C6\uB2E4.\n *\n * @see https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n */\n\nconst ESC = '\\u001B';\n/** \uC774 \uD504\uB85C\uD1A0\uCF5C\uC744 \uC4F8 \uC218 \uC788\uB294\uC9C0 \uBB3B\uB294\uB2E4. \uC9C0\uC6D0\uD558\uBA74 `ESC[?<flags>u` \uB85C \uB2F5\uD55C\uB2E4. */\nexport const QUERY = `${ESC}[?u`;\n\n/**\n * \uC6B0\uB9AC\uAC00 \uC54C\uC544\uBCF4\uACE0 \uC2F6\uC740 \uD0A4\uB4E4. \uC22B\uC790\uB294 \uD504\uB85C\uD1A0\uCF5C\uC774 \uC815\uD55C \uCF54\uB4DC\uB2E4.\n *\n * \uD55C/\uC601 \uD0A4 \uC790\uCCB4(keysym Hangul)\uB294 \uC774 \uD504\uB85C\uD1A0\uCF5C\uC5D0\uB3C4 \uC790\uB9AC\uAC00 \uC5C6\uB2E4. \uB300\uC2E0 \uD55C\uAD6D\uC5B4 \uC790\uD310\uC5D0\uC11C\n * **\uADF8 \uD0A4\uAC00 \uB193\uC778 \uC790\uB9AC**\uAC00 \uC624\uB978\uCABD Alt \uB77C, \uD55C\uAD6D\uC5B4 \uC785\uB825\uAE30\uAC00 \uC5C6\uB294 \uD658\uACBD\uC5D0\uC11C\uB294 \uC624\uB978\uCABD\n * Alt \uB85C \uB3C4\uCC29\uD55C\uB2E4. \uADF8\uAC83\uC744 \uD55C/\uC601\uC73C\uB85C \uBC1B\uB294\uB2E4.\n */\nexport const KEY_CODES: Record<number, string> = {\n 57358: 'capslock',\n 57449: 'rightalt',\n};\n\n/** Caps Lock \uC774 \uB20C\uB824 \uC788\uC74C\uC744 \uB73B\uD558\uB294 \uC218\uC2DD \uBE44\uD2B8. \uD504\uB85C\uD1A0\uCF5C \uAC12\uC740 \uC5EC\uAE30\uC5D0 1 \uC744 \uB354\uD55C \uAC83\uC774\uB2E4. */\nconst CAPS_LOCK_BIT = 64;\n\nexport interface KeyEvent {\n /** `KEY_CODES` \uC5D0 \uC788\uB294 \uC774\uB984. \uADF8 \uBC16\uC758 \uD0A4\uB294 \uC774\uB984 \uC5C6\uC774 \uC218\uC2DD\uB9CC \uC2E4\uC5B4 \uB098\uB978\uB2E4. */\n name?: string;\n capsLock: boolean;\n /** \uB20C\uB9BC(1)\u00B7\uBC18\uBCF5(2)\u00B7\uB5CC(3). \uC5C6\uC73C\uBA74 \uB20C\uB9BC\uC774\uB2E4. */\n eventType: number;\n}\n\n/**\n * \uB4E4\uC5B4\uC628 \uBC14\uC774\uD2B8\uC5D0\uC11C \uD0A4 \uC0AC\uAC74\uC744 \uACE8\uB77C\uB0B8\uB2E4.\n *\n * `ESC[<\uCF54\uB4DC>[:\uB300\uCCB4];<\uC218\uC2DD>[:\uC885\uB958][;<\uAE00\uC790>]u` \uAF34\uC774\uB2E4. \uC6B0\uB9AC\uB294 \uCF54\uB4DC\u00B7\uC218\uC2DD\u00B7\uC885\uB958\uB9CC \uBCF8\uB2E4.\n */\nexport function parseKeyEvents(chunk: string): KeyEvent[] {\n const events: KeyEvent[] = [];\n const pattern = /\\u001B\\[(\\d+)(?::\\d+)*(?:;(\\d+)(?::(\\d+))?)?(?:;[\\d:]*)?u/g;\n for (const match of chunk.matchAll(pattern)) {\n const code = Number(match[1]);\n // \uD504\uB85C\uD1A0\uCF5C\uC740 \uC218\uC2DD\uC744 \"\uC2E4\uC81C \uAC12 + 1\" \uB85C \uC2E3\uB294\uB2E4. \uC5C6\uC73C\uBA74 \uC544\uBB34 \uC218\uC2DD\uB3C4 \uC5C6\uB2E4\uB294 \uB73B\uC774\uB2E4.\n const modifiers = match[2] ? Number(match[2]) - 1 : 0;\n events.push({\n name: KEY_CODES[code],\n // eslint-disable-next-line no-bitwise\n capsLock: (modifiers & CAPS_LOCK_BIT) !== 0,\n eventType: match[3] ? Number(match[3]) : 1,\n });\n }\n return events;\n}\n\nexport interface QueryStreams {\n /** \uB2F5\uC744 \uAE30\uB2E4\uB9B4 \uACF3. \uC9C4\uC9DC stdin \uB3C4, \uC2DC\uD5D8\uC758 \uAC00\uC9DC \uC2A4\uD2B8\uB9BC\uB3C4 \uC774\uB9CC\uD07C\uC774\uBA74 \uB41C\uB2E4. */\n stdin: {\n on(event: 'data', listener: (chunk: Buffer | string) => void): unknown;\n removeListener(event: 'data', listener: (chunk: Buffer | string) => void): unknown;\n /**\n * \uB2F5\uC740 \uC904\uBC14\uAFC8 \uC5C6\uC774 \uC624\uBBC0\uB85C **\uD589 \uB2E8\uC704 \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uCEE4\uB110\uC774 \uBD99\uB4E4\uACE0 \uC788\uB2E4**.\n * \uBB3C\uC5B4\uBCF4\uB294 \uB3D9\uC548\uB9CC \uC6D0\uC2DC \uBAA8\uB4DC\uB85C \uBC14\uAFBC\uB2E4 \u2014 \uADF8\uB7EC\uC9C0 \uC54A\uC73C\uBA74 \uC9C0\uC6D0\uD558\uB294 \uD130\uBBF8\uB110\uB3C4\n * \uB300\uB2F5\uD558\uC9C0 \uC54A\uB294 \uAC83\uCC98\uB7FC \uBCF4\uC778\uB2E4.\n */\n isRaw?: boolean;\n setRawMode?(mode: boolean): unknown;\n resume?(): unknown;\n pause?(): unknown;\n };\n stdout: { isTTY?: boolean; write(chunk: string): unknown };\n isTTY?: boolean;\n}\n\n/**\n * \uC774 \uD130\uBBF8\uB110\uC774 \uD504\uB85C\uD1A0\uCF5C\uC744 \uC544\uB294\uC9C0 \uBB3C\uC5B4\uBCF8\uB2E4.\n *\n * \uB300\uB2F5\uC774 \uC5C6\uC73C\uBA74 \uBAA8\uB974\uB294 \uAC83\uC774\uB2E4 \u2014 \uAE30\uB2E4\uB9AC\uB2E4 \uADF8\uB0E5 \uB118\uC5B4\uAC04\uB2E4. \uB2F5\uC744 \uBABB \uBC1B\uC558\uB2E4\uACE0 \uCF1C \uBC84\uB9AC\uBA74\n * \uBAA8\uB974\uB294 \uD130\uBBF8\uB110\uC774 \uC6B0\uB9AC \uC9C8\uBB38\uC744 \uAE00\uC790\uB85C \uBC49\uC5B4 \uD654\uBA74\uC5D0 `[?u` \uAC00 \uCC0D\uD78C\uB2E4.\n */\n/**\n * \uC774\uB984\uB9CC\uC73C\uB85C \uC544\uB294 \uD130\uBBF8\uB110\uC778\uAC00.\n *\n * \uBB3C\uC5B4\uBCF4\uACE0 \uAE30\uB2E4\uB9AC\uB294 200ms \uB294 \uC9E7\uC9C0\uB9CC, \uC774\uBBF8 \uC544\uB294 \uD130\uBBF8\uB110\uC5D0\uAE4C\uC9C0 \uBB3C\uC744 \uC774\uC720\uB294 \uC5C6\uB2E4.\n * SSH \uCC98\uB7FC \uC655\uBCF5\uC774 \uB290\uB9B0 \uACF3\uC5D0\uC11C\uB294 \uB2F5\uC774 \uB2A6\uC5B4 \uC9C0\uC6D0\uD558\uB294 \uD130\uBBF8\uB110\uC744 \uB193\uCE58\uAE30\uB3C4 \uD55C\uB2E4.\n */\nexport function knownKittyTerminal(env: NodeJS.ProcessEnv = process.env): boolean {\n if (env.KITTY_WINDOW_ID) return true;\n if (env.GHOSTTY_RESOURCES_DIR) return true;\n const term = (env.TERM ?? '').toLowerCase();\n if (term === 'xterm-kitty' || term === 'xterm-ghostty' || term.includes('foot')) return true;\n const program = (env.TERM_PROGRAM ?? '').toLowerCase();\n return program === 'wezterm' || program === 'ghostty' || program === 'kitty';\n}\n\nexport async function supportsKittyKeyboard(\n streams: QueryStreams,\n timeoutMs = 200,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<boolean> {\n if (env.DEX_NO_KITTY === '1') return false;\n if (!streams.stdout.isTTY || !streams.isTTY) return false;\n if (knownKittyTerminal(env)) return true;\n\n const wasRaw = streams.stdin.isRaw === true;\n const wasPaused = !wasRaw;\n streams.stdin.setRawMode?.(true);\n streams.stdin.resume?.();\n\n return new Promise<boolean>((resolve) => {\n let settled = false;\n let seen = '';\n const finish = (supported: boolean): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n streams.stdin.removeListener('data', onData);\n // \uBB3C\uC5B4\uBCF4\uAE30 \uC804 \uC0C1\uD0DC\uB85C \uB3CC\uB824 \uB193\uB294\uB2E4. ink \uC774 \uACE7 \uC790\uAE30 \uBC29\uC2DD\uB300\uB85C \uB2E4\uC2DC \uC7A1\uB294\uB2E4.\n if (!wasRaw) streams.stdin.setRawMode?.(false);\n if (wasPaused) streams.stdin.pause?.();\n resolve(supported);\n };\n const onData = (data: Buffer | string): void => {\n seen += typeof data === 'string' ? data : data.toString('utf8');\n if (/\\u001B\\[\\?\\d*u/.test(seen)) finish(true);\n };\n // \uC774 \uD0C0\uC774\uBA38\uB294 unref \uD558\uC9C0 \uC54A\uB294\uB2E4. \uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uAC83 \uB9D0\uACE0 \uD560 \uC77C\uC774 \uC5C6\uC744 \uB54C \uD504\uB85C\uADF8\uB7A8\uC774\n // \uBA3C\uC800 \uB05D\uB098 \uBC84\uB9AC\uBA74, \uB300\uB2F5\uC744 \uC601\uC601 \uBABB \uBC1B\uACE0 \uB118\uC5B4\uAC04\uB2E4.\n const timer = setTimeout(() => finish(false), timeoutMs);\n streams.stdin.on('data', onData);\n streams.stdout.write(QUERY);\n });\n}\n", "import { useEffect, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { publicError } from '@dex/engine';\nimport type { Conversation, HistoryTurn } from '@dex/engine';\nimport type { TuiEngine } from './model';\nimport { Footer, Loading, Notice } from './components';\n\nexport function HistoryScreen(props: {\n engine: TuiEngine;\n profile: string;\n onOpen: (conversation: Conversation, turns: HistoryTurn[]) => void;\n onCancel: () => void;\n}): React.ReactNode {\n const [items, setItems] = useState<Conversation[]>([]);\n const [cursor, setCursor] = useState(0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string>();\n\n useEffect(() => {\n let alive = true;\n props.engine\n .listConversations(props.profile)\n .then((result) => alive && setItems(result))\n .catch((reason: unknown) => alive && setError(publicError(reason).message))\n .finally(() => alive && setLoading(false));\n return () => {\n alive = false;\n };\n }, [props.engine, props.profile]);\n\n useInput(\n (_input, key) => {\n if (key.escape) props.onCancel();\n if (key.upArrow) setCursor((current) => Math.max(0, current - 1));\n if (key.downArrow && items.length > 0) {\n setCursor((current) => Math.min(items.length - 1, current + 1));\n }\n if (key.return && items[cursor]) {\n const conversation = items[cursor];\n setLoading(true);\n setError(undefined);\n props.engine\n .historyTurns(\n conversation.workflowId,\n conversation.interactionId,\n conversation.workflowName,\n props.profile,\n )\n .then((turns) => props.onOpen(conversation, turns))\n .catch((reason: unknown) => setError(publicError(reason).message))\n .finally(() => setLoading(false));\n }\n },\n { isActive: !loading },\n );\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"round\" borderColor=\"cyan\" padding={1}>\n <Text bold>\uB300\uD654 \uAE30\uB85D</Text>\n {loading ? <Loading /> : null}\n {!loading && items.length === 0 ? <Text dimColor>\uB300\uD654 \uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.</Text> : null}\n {!loading\n ? items.slice(Math.max(0, cursor - 8), cursor + 9).map((item) => {\n const index = items.indexOf(item);\n return (\n <Text key={item.interactionId} color={index === cursor ? 'cyan' : undefined}>\n {index === cursor ? '\u203A' : ' '} {item.workflowName} \u00B7{' '}\n <Text dimColor>{item.updatedAt || item.createdAt}</Text>\n </Text>\n );\n })\n : null}\n {error ? <Notice error>{error}</Notice> : null}\n <Footer text=\"\u2191\u2193 \uC774\uB3D9 \u00B7 Enter \uC5F4\uAE30 \u00B7 Esc \uB3CC\uC544\uAC00\uAE30\" />\n </Box>\n );\n}\n", "import { useEffect, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { publicError } from '@dex/engine';\nimport type { Conversation, HistoryTurn } from '@dex/engine';\nimport type { TuiEngine } from './model';\nimport { Loading, Notice } from './components';\n\n/**\n * \uC5D0\uC774\uC804\uD2B8\uB97C \uACE0\uB978 \uC9C1\uD6C4\uC758 \uAC08\uB9BC\uAE38 \u2014 **\uC0C8\uB85C \uC2DC\uC791\uD560\uAE4C, \uD558\uB358 \uAC78 \uC774\uC5B4\uAC08\uAE4C.**\n *\n * \uC608\uC804\uC5D0\uB294 Enter \uB97C \uB204\uB974\uBA74 \uBC14\uB85C \uBE48 \uB300\uD654\uAC00 \uC5F4\uB838\uB2E4. \uC774\uC5B4\uC11C \uD558\uB824\uBA74 \uADF8\uAC78 \uC548 \uD558\uACE0\n * Ctrl+H \uB97C \uB20C\uB7EC **\uBAA8\uB4E0 \uC5D0\uC774\uC804\uD2B8\uC758** \uB300\uD654 \uBAA9\uB85D\uC5D0\uC11C \uCC3E\uC544\uC57C \uD588\uB2E4. \uBC29\uAE08 \uACE0\uB978 \uC5D0\uC774\uC804\uD2B8\uAC00\n * \uC774\uBBF8 \uD654\uBA74\uC5D0 \uC788\uB294\uB370\uB3C4.\n *\n * \uADF8\uB798\uC11C \uACE0\uB978 \uC5D0\uC774\uC804\uD2B8\uC758 \uB300\uD654\uB9CC \uC5EC\uAE30 \uBCF4\uC5EC \uC900\uB2E4.\n *\n * **\uC774\uB825\uC774 \uC5C6\uC73C\uBA74 \uC774 \uD654\uBA74\uC740 \uB728\uC9C0 \uC54A\uB294\uB2E4.** \uC120\uD0DD\uC9C0\uAC00 \uD558\uB098\uBFD0\uC778 \uC9C8\uBB38\uC744 \uB358\uC9C0\uB294 \uAC83\uC740\n * \uB3C4\uC6C0\uC774 \uC544\uB2C8\uB77C \uD55C \uBC88 \uB354 \uB204\uB974\uAC8C \uD558\uB294 \uC77C\uC774\uB2E4 \u2014 \uBD80\uBAA8\uAC00 \uADF8\uB54C\uB294 \uBC14\uB85C \uB300\uD654\uB97C \uC5F0\uB2E4.\n */\n\ninterface Row {\n kind: 'new' | 'conversation';\n conversation?: Conversation;\n}\n\nexport function StartPanel(props: {\n engine: TuiEngine;\n profile: string;\n agentName: string;\n conversations: Conversation[];\n onNew: () => void;\n onOpen: (conversation: Conversation, turns: HistoryTurn[]) => void;\n onCancel: () => void;\n}): React.ReactNode {\n const rows: Row[] = [\n { kind: 'new' },\n ...props.conversations.map((conversation) => ({ kind: 'conversation' as const, conversation })),\n ];\n const [cursor, setCursor] = useState(0);\n const [opening, setOpening] = useState(false);\n const [error, setError] = useState<string>();\n\n // \uBAA9\uB85D\uC774 \uBC14\uB00C\uBA74 \uCEE4\uC11C\uAC00 \uBC94\uC704\uB97C \uBC97\uC5B4\uB0A0 \uC218 \uC788\uB2E4.\n useEffect(() => {\n setCursor((current) => Math.min(current, Math.max(0, rows.length - 1)));\n }, [rows.length]);\n\n useInput(\n (_input, key) => {\n if (key.escape) {\n props.onCancel();\n return;\n }\n if (key.upArrow) setCursor((current) => Math.max(0, current - 1));\n if (key.downArrow) setCursor((current) => Math.min(rows.length - 1, current + 1));\n if (!key.return) return;\n\n const row = rows[cursor];\n if (!row) return;\n if (row.kind === 'new' || !row.conversation) {\n props.onNew();\n return;\n }\n const conversation = row.conversation;\n setOpening(true);\n setError(undefined);\n props.engine\n .historyTurns(\n conversation.workflowId,\n conversation.interactionId,\n conversation.workflowName,\n props.profile,\n )\n .then((turns) => props.onOpen(conversation, turns))\n .catch((reason: unknown) => {\n setError(publicError(reason).message);\n setOpening(false);\n });\n },\n { isActive: !opening },\n );\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"round\" borderColor=\"cyan\" padding={1}>\n <Text bold>{props.agentName}</Text>\n <Text dimColor>\uC5B4\uB5BB\uAC8C \uC2DC\uC791\uD560\uAE4C\uC694?</Text>\n\n <Box flexDirection=\"column\" marginTop={1}>\n {rows.map((row, index) => {\n const active = index === cursor;\n const mark = active ? '\u203A' : ' ';\n if (row.kind === 'new') {\n return (\n <Text key=\"new\" color={active ? 'cyan' : undefined}>\n {mark} \uC0C8 \uB300\uD654\n </Text>\n );\n }\n const conversation = row.conversation;\n if (!conversation) return null;\n return (\n <Text key={conversation.interactionId} color={active ? 'cyan' : undefined}>\n {mark} {when(conversation)} <Text dimColor>\u00B7 {conversation.interactionCount}\uD134</Text>\n </Text>\n );\n })}\n </Box>\n\n {opening ? <Loading label=\"\uB300\uD654\uB97C \uBD88\uB7EC\uC624\uB294 \uC911...\" /> : null}\n {error ? <Notice error>{error}</Notice> : null}\n\n <Box marginTop={1}>\n <Text dimColor>\u2191\u2193 \uC774\uB3D9 \u00B7 Enter \uC120\uD0DD \u00B7 Esc \uBAA9\uB85D\uC73C\uB85C</Text>\n </Box>\n </Box>\n );\n}\n\n/**\n * \uB300\uD654\uB97C \uC5B8\uC81C \uD588\uB294\uC9C0.\n *\n * \uC11C\uBC84\uAC00 \uC8FC\uB294 \uBB38\uC790\uC5F4\uC744 \uADF8\uB300\uB85C \uC4F0\uC9C0 \uC54A\uB294\uB2E4 \u2014 `2026-08-31T02:11:09.482Z` \uB294 \uBAA9\uB85D\uC5D0\uC11C\n * \uC77D\uC73C\uB77C\uACE0 \uC788\uB294 \uAC12\uC774 \uC544\uB2C8\uB2E4. \uC624\uB298 \uAC83\uC740 \uC2DC\uAC01\uB9CC, \uADF8 \uBC16\uC740 \uB0A0\uC9DC\uB9CC \uBCF4\uC5EC \uC900\uB2E4.\n */\nfunction when(conversation: Conversation): string {\n const raw = conversation.updatedAt || conversation.createdAt;\n const date = new Date(raw);\n if (Number.isNaN(date.getTime())) return raw || '(\uC2DC\uAC01 \uC5C6\uC74C)';\n const now = new Date();\n const sameDay =\n date.getFullYear() === now.getFullYear() &&\n date.getMonth() === now.getMonth() &&\n date.getDate() === now.getDate();\n const pad = (n: number): string => String(n).padStart(2, '0');\n return sameDay\n ? `\uC624\uB298 ${pad(date.getHours())}:${pad(date.getMinutes())}`\n : `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;\n}\n", "import { useEffect, useState } from 'react';\nimport { useStdout } from 'ink';\n\nexport interface TerminalSize {\n columns: number;\n rows: number;\n wide: boolean;\n}\n\nexport function useTerminalSize(): TerminalSize {\n const { stdout } = useStdout();\n const read = (): TerminalSize => {\n const columns = stdout.columns || 100;\n const rows = stdout.rows || 30;\n return { columns, rows, wide: columns >= 88 };\n };\n const [size, setSize] = useState(read);\n useEffect(() => {\n const resize = (): void => setSize(read());\n stdout.on('resize', resize);\n return () => {\n stdout.off('resize', resize);\n };\n }, [stdout]);\n return size;\n}\n", "import { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { Footer, FormField, Header, Loading, Notice } from './components';\n\nexport function LoginScreen(props: {\n profile: string;\n serverUrl: string;\n busy: boolean;\n error?: string;\n onSubmit: (email: string, password: string) => void;\n onProfiles: () => void;\n /** \uC8FC\uC18C\uB97C \uC798\uBABB \uCE5C \uAC83\uC744 \uC5EC\uAE30\uC11C \uBC14\uB85C \uACE0\uCE5C\uB2E4 \u2014 \uD504\uB85C\uD544\uC744 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uC54A\uACE0. */\n onEditServer: () => void;\n}): React.ReactNode {\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [focus, setFocus] = useState<'email' | 'password'>('email');\n\n useInput(\n (input, key) => {\n if (key.tab) setFocus((current) => (current === 'email' ? 'password' : 'email'));\n if (key.ctrl && input === 'p') props.onProfiles();\n if (key.ctrl && input === 'e') props.onEditServer();\n },\n { isActive: !props.busy },\n );\n\n const submit = (): void => {\n if (focus === 'email') {\n setFocus('password');\n return;\n }\n if (email.trim() && password) {\n const secret = password;\n setPassword('');\n props.onSubmit(email.trim(), secret);\n }\n };\n\n return (\n <Box flexDirection=\"column\">\n <Header profile={props.profile} connected={false} />\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"blue\" padding={1}>\n <Text bold>\uB85C\uADF8\uC778</Text>\n {/* \uC8FC\uC18C\uB97C \uD06C\uAC8C \uBCF4\uC5EC \uC900\uB2E4 \u2014 \uB85C\uADF8\uC778\uC774 \uC548 \uB420 \uB54C \uAC00\uC7A5 \uBA3C\uC800 \uC758\uC2EC\uD560 \uAC12\uC774\uB2E4. */}\n <Text dimColor>\n {props.serverUrl} <Text color=\"cyan\">(Ctrl+E \uBC14\uAFB8\uAE30)</Text>\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <FormField\n label=\"Email\"\n value={email}\n onChange={setEmail}\n onSubmit={() => setFocus('password')}\n focus={!props.busy && focus === 'email'}\n placeholder=\"me@corp.com\"\n />\n <FormField\n label=\"Password\"\n value={password}\n onChange={setPassword}\n onSubmit={submit}\n focus={!props.busy && focus === 'password'}\n secret\n />\n </Box>\n {props.busy ? <Loading label=\"\uB85C\uADF8\uC778\uD558\uB294 \uC911...\" /> : null}\n {props.error ? <Notice error>{props.error}</Notice> : null}\n </Box>\n <Footer text=\"Tab \uC774\uB3D9 \u00B7 Enter \uB85C\uADF8\uC778 \u00B7 Ctrl+E \uC11C\uBC84 \u00B7 Ctrl+P \uD504\uB85C\uD544 \u00B7 Ctrl+Q \uC885\uB8CC\" />\n </Box>\n );\n}\n", "import { useEffect, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { ProfileSummary } from '@dex/engine';\nimport { Footer, FormField, Header, Loading, Notice } from './components';\n\nexport function ProfileScreen(props: {\n profiles: ProfileSummary[];\n busy: boolean;\n error?: string;\n onSelect: (name: string) => void;\n onCreate: (name: string, serverUrl: string) => void;\n onCancel: () => void;\n}): React.ReactNode {\n const [cursor, setCursor] = useState(Math.max(0, props.profiles.findIndex((profile) => profile.current)));\n const [creating, setCreating] = useState(false);\n const [focus, setFocus] = useState<'name' | 'url'>('name');\n const [name, setName] = useState('');\n const [serverUrl, setServerUrl] = useState('');\n\n useEffect(() => setCursor((current) => Math.min(current, Math.max(0, props.profiles.length - 1))), [props.profiles]);\n\n useInput(\n (input, key) => {\n if (key.escape) {\n if (creating) setCreating(false);\n else props.onCancel();\n return;\n }\n if (creating) {\n if (key.tab) setFocus((current) => (current === 'name' ? 'url' : 'name'));\n return;\n }\n if (key.upArrow) setCursor((current) => Math.max(0, current - 1));\n if (key.downArrow && props.profiles.length > 0) {\n setCursor((current) => Math.min(props.profiles.length - 1, current + 1));\n }\n if (key.return && props.profiles[cursor]) props.onSelect(props.profiles[cursor].name);\n if (input === 'n') {\n setCreating(true);\n setFocus('name');\n }\n },\n { isActive: !props.busy },\n );\n\n const create = (): void => {\n if (focus === 'name') {\n setFocus('url');\n return;\n }\n if (name.trim() && serverUrl.trim()) props.onCreate(name.trim(), serverUrl.trim());\n };\n\n return (\n <Box flexDirection=\"column\">\n <Header />\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" padding={1}>\n <Text bold>{creating ? '\uC0C8 \uD504\uB85C\uD544' : '\uD504\uB85C\uD544 \uC804\uD658'}</Text>\n {creating ? (\n <Box flexDirection=\"column\" marginTop={1}>\n <FormField\n label=\"Name\"\n value={name}\n onChange={setName}\n onSubmit={() => setFocus('url')}\n focus={!props.busy && focus === 'name'}\n placeholder=\"corp\"\n />\n <FormField\n label=\"Server URL\"\n value={serverUrl}\n onChange={setServerUrl}\n onSubmit={create}\n focus={!props.busy && focus === 'url'}\n placeholder=\"https://xgen.example.com\"\n />\n </Box>\n ) : (\n <Box flexDirection=\"column\" marginTop={1}>\n {props.profiles.map((profile, index) => (\n <Text key={profile.name} color={index === cursor ? 'cyan' : undefined}>\n {index === cursor ? '\u203A' : ' '} {profile.current ? '\u25CF' : '\u25CB'} {profile.name} \u00B7{' '}\n <Text dimColor>{profile.serverUrl}</Text>\n </Text>\n ))}\n {props.profiles.length === 0 ? <Text dimColor>\uC800\uC7A5\uB41C \uD504\uB85C\uD544\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.</Text> : null}\n </Box>\n )}\n {props.busy ? <Loading label=\"\uD504\uB85C\uD544\uC744 \uC804\uD658\uD558\uB294 \uC911...\" /> : null}\n {props.error ? <Notice error>{props.error}</Notice> : null}\n </Box>\n <Footer\n text={creating ? 'Tab \uC774\uB3D9 \u00B7 Enter \uC800\uC7A5 \u00B7 Esc \uB4A4\uB85C' : '\u2191\u2193 \uC774\uB3D9 \u00B7 Enter \uC120\uD0DD \u00B7 N \uC0C8 \uD504\uB85C\uD544 \u00B7 Esc \uB2EB\uAE30'}\n />\n </Box>\n );\n}\n", "import { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { Footer, FormField, Header, Loading, Notice } from './components';\n\n/**\n * \uC11C\uBC84 \uC8FC\uC18C\uB97C \uC815\uD558\uB294 \uD654\uBA74. **\uCC98\uC74C \uC124\uC815\uACFC \uB098\uC911 \uC218\uC815\uC774 \uAC19\uC740 \uD654\uBA74**\uC774\uB2E4.\n *\n * \uC608\uC804\uC5D0\uB294 \uCC98\uC74C \uC124\uC815 \uC804\uC6A9\uC774\uC5C8\uB2E4. \uADF8\uB798\uC11C \uC8FC\uC18C\uB97C \uC798\uBABB \uCE58\uACE0 \uB118\uC5B4\uAC00\uBA74 \uB418\uB3CC\uC544\uC62C \uAE38\uC774\n * \uC5C6\uC5C8\uB2E4 \u2014 \uB85C\uADF8\uC778 \uD654\uBA74\uC5D0\uC11C \uD560 \uC218 \uC788\uB294 \uAC83\uC740 Ctrl+P \uB85C \uD504\uB85C\uD544 \uBAA9\uB85D\uC5D0 \uAC00\uC11C \uC0C8 \uD504\uB85C\uD544\uC744\n * \uB9CC\uB4DC\uB294 \uAC83\uBFD0\uC774\uC5C8\uACE0, \uC624\uD0C0 \uD558\uB098 \uACE0\uCE58\uC790\uACE0 \uD504\uB85C\uD544\uC774 \uD558\uB098 \uB354 \uC0DD\uACBC\uB2E4.\n *\n * \uACE0\uCE60 \uB54C\uB294 \uC9C0\uAE08 \uAC12\uC774 \uCC44\uC6CC\uC9C4 \uCC44\uB85C \uC5F4\uB9B0\uB2E4 \u2014 \uB2E4\uC2DC \uCE58\uB294 \uAC8C \uC544\uB2C8\uB77C \uACE0\uCE58\uB294 \uAC83\uC774\uB2E4.\n */\nexport function ServerScreen(props: {\n /** \uACE0\uCE60 \uB54C\uC758 \uD604\uC7AC \uAC12. \uCC98\uC74C \uC124\uC815\uC774\uBA74 \uBE44\uC5B4 \uC788\uB2E4. */\n initialValue?: string;\n profile?: string;\n busy: boolean;\n error?: string;\n onSubmit: (serverUrl: string) => void;\n /** \uCC98\uC74C \uC124\uC815\uC5D0\uB294 \uC5C6\uB2E4 \u2014 \uB3CC\uC544\uAC08 \uACF3\uC774 \uC5C6\uAE30 \uB54C\uBB38\uC774\uB2E4. */\n onCancel?: () => void;\n}): React.ReactNode {\n const [serverUrl, setServerUrl] = useState(props.initialValue ?? '');\n const editing = props.initialValue !== undefined;\n\n useInput(\n (_input, key) => {\n if (key.escape) props.onCancel?.();\n },\n { isActive: !props.busy && !!props.onCancel },\n );\n\n return (\n <Box flexDirection=\"column\">\n <Header profile={props.profile} connected={false} />\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"blue\" padding={1}>\n <Text bold>{editing ? '\uC11C\uBC84 \uC8FC\uC18C \uBC14\uAFB8\uAE30' : '\uCC98\uC74C \uC624\uC168\uAD70\uC694'}</Text>\n <Text dimColor>\uC5F0\uACB0\uD560 XGEN Gateway \uC8FC\uC18C\uB97C \uC785\uB825\uD558\uC138\uC694.</Text>\n <Box marginTop={1}>\n <FormField\n label=\"Server URL\"\n value={serverUrl}\n onChange={setServerUrl}\n onSubmit={(value) => value.trim() && props.onSubmit(value.trim())}\n focus={!props.busy}\n placeholder=\"xgen.example.com\"\n />\n </Box>\n {/* http:// \uB97C \uC548 \uC368\uB3C4 \uB41C\uB2E4\uB294 \uAC83\uC744 \uC5EC\uAE30\uC11C \uB9D0\uD574 \uC900\uB2E4 \u2014 \uC608\uC804\uC5D0\uB294 \uADF8\uAC78 \uBAA8\uB974\uACE0\n \uCE58\uB2E4\uAC00 \"http:// \uB610\uB294 https://\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4\" \uB97C \uBCF4\uACE0\uC11C\uC57C \uC54C\uC558\uB2E4. */}\n <Text dimColor>https:// \uB294 \uC0DD\uB7B5\uD574\uB3C4 \uB429\uB2C8\uB2E4.</Text>\n {props.busy ? <Loading label=\"\uC11C\uBC84 \uD504\uB85C\uD544\uC744 \uC800\uC7A5\uD558\uB294 \uC911...\" /> : null}\n {props.error ? <Notice error>{props.error}</Notice> : null}\n </Box>\n <Footer\n text={\n props.onCancel\n ? 'Enter \uC800\uC7A5 \u00B7 Esc \uCDE8\uC18C \u00B7 Ctrl+Q \uC885\uB8CC'\n : 'Enter \uACC4\uC18D \u00B7 Ctrl+Q \uC885\uB8CC'\n }\n />\n </Box>\n );\n}\n", "/**\n * \uB300\uCCB4 \uD654\uBA74(alternate screen) \uAD00\uB9AC.\n *\n * \uC608\uC804\uC5D0\uB294 TUI \uB97C \uC9C0\uAE08 \uC4F0\uB358 \uD130\uBBF8\uB110\uC5D0 \uADF8\uB300\uB85C \uADF8\uB838\uB2E4. \uADF8\uB798\uC11C Ctrl+Q \uB85C \uB098\uAC00\uBA74 \uB9C8\uC9C0\uB9C9\n * \uD504\uB808\uC784 \u2014 \uC5D0\uC774\uC804\uD2B8 \uBAA9\uB85D, \uB300\uD654\uCC3D, \uD14C\uB450\uB9AC \u2014 \uC774 \uC2A4\uD06C\uB864\uBC31\uC5D0 \uADF8\uB300\uB85C \uB0A8\uC558\uB2E4. \uADF8 \uC704\uB85C\n * \uB2E4\uC74C \uD504\uB86C\uD504\uD2B8\uAC00 \uCC0D\uD788\uB2C8 \uD654\uBA74\uC774 \uC5C9\uD0A8 \uAC83\uCC98\uB7FC \uBCF4\uC774\uACE0, \uC704\uB85C \uC2A4\uD06C\uB864\uD558\uBA74 \uC4F0\uC9C0\uB3C4 \uC54A\uC744\n * UI \uC794\uD574\uAC00 \uC608\uC804 \uBA85\uB839\uB4E4 \uC0AC\uC774\uC5D0 \uB07C\uC5B4 \uC788\uB2E4.\n *\n * `vim`\u00B7`less`\u00B7`htop` \uC774 \uC4F0\uB294 \uAC83\uACFC \uAC19\uC740 \uBC29\uBC95\uC774\uB2E4: \uB4E4\uC5B4\uAC08 \uB54C \uD654\uBA74\uC744 \uD55C \uC7A5 \uC0C8\uB85C \uAE54\uACE0,\n * \uB098\uC62C \uB54C \uC6D0\uB798 \uD654\uBA74\uC744 \uB418\uB3CC\uB9B0\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uBCF4\uAE30\uC5D0\uB294 **\uB744\uC6B0\uAE30 \uC804 \uC0C1\uD0DC\uB85C \uADF8\uB300\uB85C \uB3CC\uC544\uC628\uB2E4.**\n *\n * \uBCC4\uB3C4 \uD30C\uC77C\uC778 \uC774\uC720\uB294 \uC774 \uADDC\uCE59\uB4E4\uC774 \uB208\uC73C\uB85C\uB294 \uD655\uC778\uB418\uC9C0 \uC54A\uAE30 \uB54C\uBB38\uC774\uB2E4 \u2014 \uD2C0\uB9AC\uBA74 \uC0AC\uC6A9\uC790\n * \uD130\uBBF8\uB110\uC774 \uB9DD\uAC00\uC9C4 \uB4A4\uC5D0\uC57C \uC548\uB2E4. \uADF8\uB798\uC11C \uAC00\uC9DC \uC2A4\uD2B8\uB9BC\uC5D0 \uB300\uACE0 \uC2DC\uD5D8\uD560 \uC218 \uC788\uAC8C \uB5BC\uC5B4 \uB480\uB2E4.\n */\n\n/** \uC4F0\uAE30\uB9CC \uD544\uC694\uD558\uB2E4. \uC9C4\uC9DC stdout \uB3C4, \uD14C\uC2A4\uD2B8\uC758 \uAC00\uC9DC \uC2A4\uD2B8\uB9BC\uB3C4 \uC774\uAC78 \uB9CC\uC871\uD55C\uB2E4. */\nexport interface ScreenStream {\n isTTY?: boolean;\n write(chunk: string): unknown;\n}\n\nconst ESC = '\\u001B';\n/** \uB300\uCCB4 \uD654\uBA74\uC73C\uB85C \uB4E4\uC5B4\uAC04\uB2E4 (DECSET 1049). \uCEE4\uC11C \uC704\uCE58\uAE4C\uC9C0 \uD568\uAED8 \uBCF4\uAD00\uB41C\uB2E4. */\nexport const ENTER_ALT_SCREEN = `${ESC}[?1049h`;\n/** \uC6D0\uB798 \uD654\uBA74\uC73C\uB85C \uB3CC\uC544\uC628\uB2E4. \uB4E4\uC5B4\uAC00\uAE30 \uC804 \uB0B4\uC6A9\uC774 \uADF8\uB300\uB85C \uBCF5\uC6D0\uB41C\uB2E4. */\nexport const LEAVE_ALT_SCREEN = `${ESC}[?1049l`;\n/** Ink \uB294 \uADF8\uB9AC\uB294 \uB3D9\uC548 \uCEE4\uC11C\uB97C \uC228\uAE34\uB2E4. \uB418\uB3CC\uB9AC\uC9C0 \uC54A\uC73C\uBA74 \uB098\uAC04 \uB4A4 \uCEE4\uC11C\uAC00 \uBCF4\uC774\uC9C0 \uC54A\uB294\uB2E4. */\nexport const SHOW_CURSOR = `${ESC}[?25h`;\n\n/**\n * \uD130\uBBF8\uB110\uC5D0\uAC8C **\uD0A4\uAC00 \uC544\uB2CC \uAC83\uC744 \uBCF4\uB0B4\uC9C0 \uB9D0\uB77C** \uACE0 \uB9D0\uD55C\uB2E4.\n *\n * \uD130\uBBF8\uB110\uC740 \uCC3D \uD3EC\uCEE4\uC2A4\uAC00 \uBC14\uB00C\uBA74 `ESC[I`/`ESC[O`, \uB9C8\uC6B0\uC2A4\uB97C \uAC74\uB4DC\uB9AC\uBA74 `ESC[<0;1;1M` \uC744\n * \uC785\uB825\uC778 \uAC83\uCC98\uB7FC \uBCF4\uB0B8\uB2E4. \uC774 \uBAA8\uB4DC\uB4E4\uC740 \uC55E\uC11C \uC2E4\uD589\uB41C \uD504\uB85C\uADF8\uB7A8\uC774 \uCF1C \uB450\uACE0 \uB044\uC9C0 \uC54A\uC740 \uCC44\n * \uB0A8\uC544 \uC788\uC744 \uC218 \uC788\uC5B4\uC11C, \uC6B0\uB9AC\uAC00 \uCF20 \uC801 \uC5C6\uC5B4\uB3C4 \uB3C4\uCC29\uD55C\uB2E4. \uADF8\uB300\uB85C \uB450\uBA74 \uBA54\uC2DC\uC9C0 \uCE78\uC5D0\n * `[I`\u00B7`[<0;1;1M` \uC774 \uD0C0\uC774\uD551\uB41C\uB2E4 \u2014 \uD55C\uAE00 IME \uD6C4\uBCF4\uCC3D\uC774 \uB728\uACE0 \uB2EB\uD790 \uB54C\uB9C8\uB2E4 \uD3EC\uCEE4\uC2A4\uAC00\n * \uC624\uAC00\uBBC0\uB85C \uD2B9\uD788 \uC790\uC8FC \uD130\uC9C4\uB2E4.\n */\nconst DISABLE_REPORTS = [\n `${ESC}[?1004l`, // \uD3EC\uCEE4\uC2A4 \uB4E4\uC5B4\uC634/\uB098\uAC10\n `${ESC}[?1000l`, // \uB9C8\uC6B0\uC2A4 \uD074\uB9AD\n `${ESC}[?1002l`, // \uB9C8\uC6B0\uC2A4 \uB4DC\uB798\uADF8\n `${ESC}[?1003l`, // \uB9C8\uC6B0\uC2A4 \uC774\uB3D9 \uC804\uBD80\n `${ESC}[?1006l`, // SGR \uD655\uC7A5 \uC88C\uD45C\n].join('');\n\n/**\n * \uBD99\uC5EC\uB123\uAE30\uB97C `ESC[200~` ... `ESC[201~` \uB85C \uAC10\uC2F8 \uB2EC\uB77C\uACE0 \uD55C\uB2E4.\n *\n * \uAC10\uC2F8 \uC8FC\uBA74 \uBD99\uC778 \uB0B4\uC6A9\uC744 **\uD0A4\uAC00 \uC544\uB2C8\uB77C \uAE00\uC790**\uB85C \uB2E4\uB8F0 \uC218 \uC788\uB2E4. \uC548 \uAC10\uC2F8\uBA74 \uBD99\uC5EC\uB123\uC740\n * \uC904\uBC14\uAFC8\uC774 \"\uC804\uC1A1\" \uC73C\uB85C \uC77D\uD600 \uBC18\uCABD\uC9DC\uB9AC \uBA54\uC2DC\uC9C0\uAC00 \uB098\uAC00\uACE0, \uB0B4\uC6A9 \uC548\uC758 ESC \uB294 \uC81C\uC5B4\n * \uC2DC\uD000\uC2A4\uB85C \uC798\uBABB \uD574\uC11D\uB41C\uB2E4.\n */\nconst ENABLE_BRACKETED_PASTE = `${ESC}[?2004h`;\nconst DISABLE_BRACKETED_PASTE = `${ESC}[?2004l`;\n\n/**\n * Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC744 \uC6D0\uB798\uB300\uB85C \uB418\uB3CC\uB9B0\uB2E4.\n *\n * \uCF20 \uCC44\uB85C \uB098\uAC00\uBA74 \uB2E4\uC74C\uC5D0 \uC774 \uD130\uBBF8\uB110\uC744 \uC4F0\uB294 \uD504\uB85C\uADF8\uB7A8\uC774 \uB0AF\uC120 \uC774\uC2A4\uCF00\uC774\uD504\uB97C \uBC1B\uB294\uB2E4 \u2014\n * \uC178\uC5D0\uC11C \uBC29\uD5A5\uD0A4\uAC00 \uAE00\uC790\uB85C \uCC0D\uD788\uB294 \uC2DD\uC73C\uB85C \uB9DD\uAC00\uC9C4\uB2E4. ink \uB3C4 \uC815\uB9AC\uD558\uC9C0\uB9CC Ctrl+Q \uB098\n * \uC2E0\uD638\uB85C \uC8FD\uC744 \uB54C\uB294 \uAC70\uCE58\uC9C0 \uBABB\uD560 \uC218 \uC788\uC5B4, \uD654\uBA74\uC744 \uB418\uB3CC\uB9AC\uB294 \uC790\uB9AC\uC5D0\uC11C \uD568\uAED8 \uB418\uB3CC\uB9B0\uB2E4.\n * \uCF20 \uC801\uC774 \uC5C6\uC5B4\uB3C4 \uC548\uC804\uD558\uB2E4 \u2014 \uBE48 \uAC83\uC744 \uAEBC\uB0B4\uB294 \uAC83\uC740 \uC544\uBB34 \uC77C\uB3C4 \uD558\uC9C0 \uC54A\uB294\uB2E4.\n */\nconst POP_KITTY_KEYBOARD = `${ESC}[<u`;\n\nexport interface ScreenGuardOptions {\n /** Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC744 \uCF1C\uC11C \uB4E4\uC5B4\uC654\uB294\uAC00. \uB098\uAC08 \uB54C \uB418\uB3CC\uB824\uC57C \uD55C\uB2E4. */\n kittyKeyboard?: boolean;\n}\n\nexport interface ScreenGuard {\n /** \uB300\uCCB4 \uD654\uBA74\uC73C\uB85C \uB4E4\uC5B4\uAC04\uB2E4. TTY \uAC00 \uC544\uB2C8\uBA74 \uC544\uBB34 \uAC83\uB3C4 \uD558\uC9C0 \uC54A\uB294\uB2E4. */\n enter(): void;\n /** \uC6D0\uB798 \uD654\uBA74\uACFC \uCEE4\uC11C\uB97C \uB418\uB3CC\uB9B0\uB2E4. \uC5EC\uB7EC \uBC88 \uBD88\uB7EC\uB3C4 \uD55C \uBC88\uB9CC \uB3D9\uC791\uD55C\uB2E4. */\n restore(): void;\n}\n\nexport function createScreenGuard(\n stream: ScreenStream,\n options: ScreenGuardOptions = {},\n): ScreenGuard {\n // TTY \uAC00 \uC544\uB2C8\uBA74 \uC190\uB300\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uD30C\uC774\uD504\uB098 CI \uB85C\uADF8\uC5D0 \uC81C\uC5B4 \uBB38\uC790\uB97C \uBFCC\uB9B4 \uC774\uC720\uAC00 \uC5C6\uB2E4.\n const alt = Boolean(stream.isTTY);\n let entered = false;\n let restored = false;\n\n return {\n enter(): void {\n if (entered || !alt) return;\n entered = true;\n stream.write(ENTER_ALT_SCREEN + DISABLE_REPORTS + ENABLE_BRACKETED_PASTE);\n },\n restore(): void {\n // \uB418\uB3CC\uB9AC\uAE30\uB294 **\uD55C \uBC88\uB9CC** \uD55C\uB2E4. \uC815\uC0C1 \uC885\uB8CC\u00B7Ctrl+C\u00B7\uC608\uC678\uAC00 \uACB9\uCCD0 \uB450 \uBC88 \uB098\uAC00\uBA74\n // \uB300\uCCB4 \uD654\uBA74\uC744 \uD558\uB098 \uB354 \uBC97\uACA8\uB0B4 \uC0AC\uC6A9\uC790\uC758 \uC6D0\uB798 \uD654\uBA74\uAE4C\uC9C0 \uC9C0\uC6B4\uB2E4.\n if (restored) return;\n restored = true;\n // \uCF20 \uAC83\uB9CC \uB418\uB3CC\uB9B0\uB2E4. \uBCF4\uACE0 \uBAA8\uB4DC\uB294 \uC6D0\uB798 \uAEBC\uC838 \uC788\uC5B4\uC57C \uC815\uC0C1\uC774\uBBC0\uB85C \uB2E4\uC2DC \uCF1C\uC9C0 \uC54A\uB294\uB2E4.\n if (entered) {\n stream.write(\n (options.kittyKeyboard ? POP_KITTY_KEYBOARD : '') +\n DISABLE_BRACKETED_PASTE +\n LEAVE_ALT_SCREEN,\n );\n }\n stream.write(SHOW_CURSOR);\n },\n };\n}\n", "import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { dataDirectory } from '@dex/engine';\n\n/**\n * \uD130\uBBF8\uB110 UI \uC758 \uCDE8\uD5A5\uC744 \uAE30\uC5B5\uD55C\uB2E4.\n *\n * \uC9C0\uAE08\uC740 \uD55C/\uC601 \uD558\uB098\uBFD0\uC774\uB2E4. \uC11C\uBC84 \uC124\uC815(config.json)\uACFC \uC11E\uC9C0 \uC54A\uC740 \uC774\uC720\uB294 \uADF8\uCABD\uC774 \uC571\u00B7\uD655\uC7A5\uACFC\n * \uD568\uAED8 \uC4F0\uB294 \uACC4\uC57D\uC774\uAE30 \uB54C\uBB38\uC774\uB2E4 \u2014 \uD130\uBBF8\uB110\uC5D0\uC11C\uB9CC \uB73B\uC774 \uC788\uB294 \uAC12\uC744 \uAC70\uAE30 \uB123\uC73C\uBA74, \uADF8 \uACC4\uC57D\uC744\n * \uC77D\uB294 \uBAA8\uB4E0 \uACF3\uC774 \uC774 \uAC12\uC744 \uC54C\uC544\uC57C \uD558\uB294 \uAC83\uCC98\uB7FC \uBCF4\uC778\uB2E4.\n *\n * \uC77D\uAE30\uB3C4 \uC4F0\uAE30\uB3C4 \uC2E4\uD328\uD574\uB3C4 \uC870\uC6A9\uD788 \uB118\uC5B4\uAC04\uB2E4. \uCDE8\uD5A5\uC744 \uAE30\uC5B5\uD558\uC9C0 \uBABB\uD558\uB294 \uAC83\uACFC \uB300\uD654\uB97C \uBABB \uD558\uB294\n * \uAC83\uC740 \uB2E4\uB978 \uC77C\uC774\uACE0, \uD6C4\uC790\uB97C \uC804\uC790 \uB54C\uBB38\uC5D0 \uB9C9\uC73C\uBA74 \uC548 \uB41C\uB2E4.\n */\nexport interface TuiPreferences {\n hangulMode: boolean;\n}\n\nexport function preferencesPath(env: NodeJS.ProcessEnv = process.env): string {\n return join(dataDirectory(env), 'tui.json');\n}\n\n/**\n * \uC544\uC9C1 \uACE0\uB978 \uC801\uC774 \uC5C6\uC744 \uB54C\uC758 \uAE30\uBCF8\uAC12.\n *\n * \uB85C\uCF00\uC77C\uC774 \uD55C\uAD6D\uC5B4\uBA74 \uD55C\uAE00\uB85C \uC2DC\uC791\uD55C\uB2E4. \uD55C\uAD6D\uC5B4 \uD658\uACBD\uC5D0\uC11C \uC4F0\uB294 \uC0AC\uB78C\uC774 \uB9E4\uBC88 Ctrl+Space\n * \uB97C \uB20C\uB7EC\uC57C \uD55C\uB2E4\uBA74, \uADF8 \uC790\uCCB4\uAC00 \uC6B0\uB9AC\uAC00 \uC5C6\uC560\uB824\uB358 \uBD88\uD3B8\uC774\uB2E4.\n */\nexport function localeDefaultHangul(env: NodeJS.ProcessEnv = process.env): boolean {\n const locale = env.LC_ALL || env.LC_CTYPE || env.LANG || '';\n return /^ko(_|-|\\.|$)/i.test(locale.trim());\n}\n\nexport async function readPreferences(env: NodeJS.ProcessEnv = process.env): Promise<TuiPreferences> {\n const fallback: TuiPreferences = { hangulMode: localeDefaultHangul(env) };\n try {\n const raw = JSON.parse(await readFile(preferencesPath(env), 'utf8')) as Record<string, unknown>;\n return typeof raw.hangulMode === 'boolean' ? { hangulMode: raw.hangulMode } : fallback;\n } catch {\n return fallback;\n }\n}\n\nexport async function writePreferences(\n preferences: TuiPreferences,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n try {\n const path = preferencesPath(env);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(preferences, null, 2)}\\n`, 'utf8');\n } catch {\n // \uCDE8\uD5A5\uC744 \uBABB \uC801\uB294\uB2E4\uACE0 \uB300\uD654\uB97C \uB9C9\uC9C0 \uC54A\uB294\uB2E4.\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["useEffect", "useState", "Box", "Text", "useApp", "useInput", "useEffect", "useRef", "useState", "Box", "Text", "useInput", "maximumScroll", "useState", "Box", "Text", "useInput", "Box", "Text", "useEffect", "useRef", "useState", "stringWidth", "jamo", "stringWidth", "useState", "useRef", "stdin", "useEffect", "cursor", "inserted", "jsx", "jsxs", "Box", "Text", "jsx", "jsxs", "useState", "useInput", "Box", "Text", "useEffect", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useEffect", "useInput", "Box", "Text", "useEffect", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useEffect", "useInput", "Box", "Text", "useEffect", "useState", "stdout", "jsx", "jsxs", "Box", "Text", "useEffect", "useState", "useRef", "useInput", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useInput", "Box", "Text", "useEffect", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useEffect", "useInput", "Box", "Text", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useInput", "Box", "Text", "jsx", "jsxs", "useApp", "useState", "useInput", "useEffect", "Box", "Text", "ESC", "jsx"]
7
+ }
package/dist/cli.js CHANGED
@@ -625,7 +625,7 @@ function bindCliHost(configStore) {
625
625
  var credentials = new SystemCredentialStore();
626
626
 
627
627
  // src/cli.ts
628
- var VERSION = true ? "1.7.0" : "dev";
628
+ var VERSION = true ? "1.7.1" : "dev";
629
629
  var HELP = `XGEN Dex CLI ${VERSION}
630
630
 
631
631
  Usage:
@@ -894,7 +894,7 @@ async function run2() {
894
894
  ci: process.env.CI
895
895
  };
896
896
  if (shouldLaunchTui(args.positionals, terminal)) {
897
- const { runTui } = await import("./chunks/tui-QF5OJEFW.js");
897
+ const { runTui } = await import("./chunks/tui-H3VM2MGV.js");
898
898
  try {
899
899
  await runTui(engine);
900
900
  } finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xgen-dex-cli",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "XGEN Dex CLI — 터미널에서 XGEN 에이전트와 대화하고, 이 컴퓨터의 셸·파일·MCP 를 에이전트에게 빌려 줍니다.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/tui/index.tsx", "../../src/tui/app.tsx", "../../src/tui/dashboard.tsx", "../../src/tui/chat-state.ts", "../../src/tui/measure.ts", "../../src/tui/transcript.ts", "../../src/tui/command-palette.tsx", "../../src/tui/components.tsx", "../../src/tui/ime-text-input.tsx", "../../src/tui/terminal-input.ts", "../../src/tui/hangul.ts", "../../src/tui/kitty.ts", "../../src/tui/history-screen.tsx", "../../src/tui/start-panel.tsx", "../../src/tui/use-terminal-size.ts", "../../src/tui/login-screen.tsx", "../../src/tui/profile-screen.tsx", "../../src/tui/server-screen.tsx", "../../src/tui/screen.ts", "../../src/tui/preferences.ts"],
4
- "sourcesContent": ["import { render } from 'ink';\nimport { stdin, stdout } from 'node:process';\nimport type { DexEngine } from '@dex/engine';\nimport { App } from './app';\nimport { createScreenGuard } from './screen';\nimport { readPreferences, writePreferences } from './preferences';\nimport { supportsKittyKeyboard } from './kitty';\n\n/**\n * TUI \uB97C \uB300\uCCB4 \uD654\uBA74\uC5D0\uC11C \uB744\uC6B4\uB2E4. \uADDC\uCE59\uC740 `./screen` \uC5D0 \uC788\uB2E4 \u2014 \uC5EC\uAE30\uC11C\uB294 \uD504\uB85C\uC138\uC2A4\uAC00\n * **\uC5B4\uB5BB\uAC8C \uB05D\uB098\uB4E0** \uB418\uB3CC\uC544\uAC00\uAC8C \uBC30\uC120\uB9CC \uD55C\uB2E4.\n */\nexport async function runTui(engine: DexEngine): Promise<void> {\n let screen = createScreenGuard(stdout);\n const restore = (): void => screen.restore();\n\n // SIGINT/SIGTERM \uC740 Ink \uC758 \uC815\uB9AC\uB97C \uAC70\uCE58\uC9C0 \uC54A\uACE0 \uACE7\uC7A5 \uC8FD\uC744 \uC218 \uC788\uB2E4. 'exit' \uC740\n // process.exit() \uC640 \uC608\uC678\uB85C \uC8FD\uB294 \uACBD\uC6B0\uAE4C\uC9C0 \uBC1B\uB294\uB2E4.\n const onSignal = (): void => {\n restore();\n process.exit(0);\n };\n process.once('exit', restore);\n process.once('SIGINT', onSignal);\n process.once('SIGTERM', onSignal);\n\n // \uCDE8\uD5A5\uC740 \uADF8\uB9AC\uAE30 \uC804\uC5D0 \uC77D\uB294\uB2E4. \uB098\uC911\uC5D0 \uC77D\uC73C\uBA74 \uCCAB \uD504\uB808\uC784\uC774 EN \uC73C\uB85C \uB5B4\uB2E4\uAC00 \uBC14\uB00C\uC5B4,\n // \uD55C\uAE00\uB85C \uC4F0\uB358 \uC0AC\uB78C\uC5D0\uAC8C\uB294 \uBAA8\uB4DC\uAC00 \uAEBC\uC9C4 \uAC83\uCC98\uB7FC \uBCF4\uC778\uB2E4.\n const preferences = await readPreferences();\n\n // \uD55C/\uC601 \uD0A4(\uC624\uB978\uCABD Alt \uC790\uB9AC)\uC640 Caps Lock \uC740 \uAE00\uC790\uB97C \uB9CC\uB4E4\uC9C0 \uC54A\uC544 \uBCF4\uD1B5 \uC571\uC5D0 \uC624\uC9C0\n // \uC54A\uB294\uB2E4. \uADF8 \uD0A4\uB4E4\uAE4C\uC9C0 \uBCF4\uACE0\uD558\uB294 \uD130\uBBF8\uB110\uC778\uC9C0 \uBA3C\uC800 \uBB3C\uC5B4\uBCF8\uB2E4 \u2014 ink \uC740 kitty\u00B7ghostty\u00B7\n // WezTerm \uB9CC \uC774\uB984\uC73C\uB85C \uC9D0\uC791\uD558\uC9C0\uB9CC, \uC694\uC998\uC740 \uB354 \uB9CE\uC740 \uD130\uBBF8\uB110\uC774 \uC774 \uD504\uB85C\uD1A0\uCF5C\uC744 \uC548\uB2E4.\n const kitty = await supportsKittyKeyboard({ stdin, stdout, isTTY: stdin.isTTY });\n screen = createScreenGuard(stdout, { kittyKeyboard: kitty });\n\n screen.enter();\n\n try {\n const instance = render(\n <App\n engine={engine}\n preferences={{\n hangulMode: preferences.hangulMode,\n onHangulModeChange: (enabled) => void writePreferences({ hangulMode: enabled }),\n }}\n />,\n {\n exitOnCtrlC: true,\n patchConsole: true,\n // \uBAA8\uB4E0 \uD0A4\uB97C \uC774\uC2A4\uCF00\uC774\uD504\uB85C \uBC1B\uC544\uC57C \uC218\uC2DD \uD0A4 \uC790\uCCB4\uAC00 \uC0AC\uAC74\uC73C\uB85C \uC628\uB2E4.\n ...(kitty\n ? {\n kittyKeyboard: {\n mode: 'enabled' as const,\n flags: ['disambiguateEscapeCodes' as const, 'reportAllKeysAsEscapeCodes' as const],\n },\n }\n : {}),\n },\n );\n await instance.waitUntilExit();\n } finally {\n restore();\n process.off('exit', restore);\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n }\n}\n", "import { useCallback, useEffect, useState } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport { DexError, publicError } from '@dex/engine';\nimport type { ProfileSummary } from '@dex/engine';\nimport { Dashboard } from './dashboard';\nimport { Footer, Header, Loading, Notice } from './components';\nimport { LoginScreen } from './login-screen';\nimport type { TuiEngine, TuiSession } from './model';\nimport { ProfileScreen } from './profile-screen';\nimport { ServerScreen } from './server-screen';\n\ntype Route = 'boot' | 'server' | 'login' | 'dashboard' | 'profiles' | 'fatal';\n\nexport function App({\n engine,\n preferences,\n}: {\n engine: TuiEngine;\n /** \uAE30\uC5B5\uD574 \uB454 \uD130\uBBF8\uB110 \uCDE8\uD5A5. \uC9C0\uAE08\uC740 \uD55C/\uC601 \uD558\uB098\uBFD0\uC774\uB2E4. */\n preferences?: { hangulMode: boolean; onHangulModeChange?: (enabled: boolean) => void };\n}): React.ReactNode {\n const { exit } = useApp();\n const [route, setRoute] = useState<Route>('boot');\n const [session, setSession] = useState<TuiSession>();\n const [profiles, setProfiles] = useState<ProfileSummary[]>([]);\n const [loginTarget, setLoginTarget] = useState<{ profile: string; serverUrl: string }>();\n /** \uC11C\uBC84 \uC8FC\uC18C\uB97C \uACE0\uCE58\uB294 \uC911 \u2014 \uC9C0\uAE08 \uAC12\uC774 \uD654\uBA74\uC5D0 \uCC44\uC6CC\uC9C4\uB2E4. */\n const [editingServer, setEditingServer] = useState<{ profile: string; serverUrl: string }>();\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string>();\n\n useInput((input, key) => {\n if (key.ctrl && input === 'q') exit();\n });\n\n const bootstrap = useCallback(\n async (preferredProfile?: string): Promise<void> => {\n setRoute('boot');\n setBusy(true);\n setError(undefined);\n try {\n let available = await engine.listProfiles();\n setProfiles(available);\n if (available.length === 0) {\n setSession(undefined);\n setRoute('server');\n return;\n }\n if (preferredProfile) {\n await engine.useProfile(preferredProfile);\n available = await engine.listProfiles();\n setProfiles(available);\n }\n const current =\n available.find((profile) => profile.current) ??\n available.find((profile) => profile.name === preferredProfile) ??\n available[0];\n if (!current) throw new DexError('config_invalid', '\uC0AC\uC6A9\uD560 \uD504\uB85C\uD544\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.');\n const status = await engine.authStatus(current.name);\n if (!status.authenticated) {\n if (status.reason === 'network') {\n throw new DexError('network_error', `XGEN \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${current.serverUrl}`);\n }\n setSession(undefined);\n setLoginTarget({ profile: current.name, serverUrl: current.serverUrl });\n setRoute('login');\n return;\n }\n const agents = await engine.listAgents({ pageSize: 100, includeHarness: true }, current.name);\n setSession({\n profile: current.name,\n serverUrl: current.serverUrl,\n username: status.user?.username ?? 'unknown',\n agents: agents.items,\n });\n setRoute('dashboard');\n } catch (reason) {\n setError(publicError(reason).message);\n setRoute('fatal');\n } finally {\n setBusy(false);\n }\n },\n [engine],\n );\n\n useEffect(() => {\n void bootstrap();\n }, [bootstrap]);\n\n /**\n * \uC11C\uBC84 \uC8FC\uC18C\uB97C \uC815\uD55C\uB2E4 \u2014 \uCC98\uC74C\uC774\uB4E0 \uACE0\uCE58\uB294 \uAC83\uC774\uB4E0 \uAC19\uC740 \uAE38.\n *\n * \uACE0\uCE60 \uB54C\uB294 **\uC9C0\uAE08 \uD504\uB85C\uD544\uC744 \uADF8\uB300\uB85C \uB36E\uC5B4\uC4F4\uB2E4.** \uC608\uC804\uC5D0\uB294 \uB418\uB3CC\uC544\uC62C \uAE38\uC774 \uC5C6\uC5B4\uC11C\n * \uC624\uD0C0 \uD558\uB098\uC5D0 \uD504\uB85C\uD544\uC774 \uD558\uB098\uC529 \uB298\uC5C8\uB2E4.\n */\n const configure = async (serverUrl: string): Promise<void> => {\n setBusy(true);\n setError(undefined);\n const target = editingServer?.profile ?? loginTarget?.profile ?? 'default';\n try {\n const profile = await engine.setProfile(target, serverUrl);\n await engine.useProfile(profile.name);\n setLoginTarget({ profile: profile.name, serverUrl: profile.serverUrl });\n setProfiles(await engine.listProfiles());\n setEditingServer(undefined);\n setRoute('login');\n } catch (reason) {\n setError(publicError(reason).message);\n } finally {\n setBusy(false);\n }\n };\n\n const login = async (email: string, password: string): Promise<void> => {\n if (!loginTarget) return;\n setBusy(true);\n setError(undefined);\n try {\n await engine.login(email, password, loginTarget.profile);\n await bootstrap(loginTarget.profile);\n } catch (reason) {\n setError(publicError(reason).message);\n setRoute('login');\n } finally {\n setBusy(false);\n }\n };\n\n const openProfiles = async (): Promise<void> => {\n setBusy(true);\n setError(undefined);\n try {\n setProfiles(await engine.listProfiles());\n setRoute('profiles');\n } catch (reason) {\n setError(publicError(reason).message);\n } finally {\n setBusy(false);\n }\n };\n\n const createProfile = async (name: string, serverUrl: string): Promise<void> => {\n setBusy(true);\n setError(undefined);\n try {\n await engine.setProfile(name, serverUrl);\n await bootstrap(name);\n } catch (reason) {\n setError(publicError(reason).message);\n setRoute('profiles');\n } finally {\n setBusy(false);\n }\n };\n\n const logout = async (): Promise<void> => {\n if (!session) return;\n setBusy(true);\n try {\n await engine.logout(session.profile);\n setLoginTarget({ profile: session.profile, serverUrl: session.serverUrl });\n setSession(undefined);\n setRoute('login');\n } catch (reason) {\n setError(publicError(reason).message);\n setRoute('fatal');\n } finally {\n setBusy(false);\n }\n };\n\n if (route === 'boot') {\n return (\n <Box flexDirection=\"column\">\n <Header />\n <Loading label=\"Dex\uB97C \uC900\uBE44\uD558\uB294 \uC911...\" />\n <Footer text=\"Ctrl+Q \uC885\uB8CC\" />\n </Box>\n );\n }\n if (route === 'server') {\n return (\n <ServerScreen\n initialValue={editingServer?.serverUrl}\n profile={editingServer?.profile}\n busy={busy}\n error={error}\n onSubmit={(url) => void configure(url)}\n // \uCC98\uC74C \uC124\uC815\uC5D0\uB294 \uCDE8\uC18C\uAC00 \uC5C6\uB2E4 \u2014 \uB3CC\uC544\uAC08 \uACF3\uC774 \uC5C6\uB2E4.\n onCancel={\n editingServer\n ? () => {\n setEditingServer(undefined);\n setError(undefined);\n setRoute('login');\n }\n : undefined\n }\n />\n );\n }\n if (route === 'login' && loginTarget) {\n return (\n <LoginScreen\n profile={loginTarget.profile}\n serverUrl={loginTarget.serverUrl}\n busy={busy}\n error={error}\n onSubmit={(email, password) => void login(email, password)}\n onProfiles={() => void openProfiles()}\n onEditServer={() => {\n setEditingServer(loginTarget);\n setError(undefined);\n setRoute('server');\n }}\n />\n );\n }\n if (route === 'profiles') {\n return (\n <ProfileScreen\n profiles={profiles}\n busy={busy}\n error={error}\n onSelect={(name) => void bootstrap(name)}\n onCreate={(name, url) => void createProfile(name, url)}\n onCancel={() => setRoute(session ? 'dashboard' : loginTarget ? 'login' : 'server')}\n />\n );\n }\n if (route === 'dashboard' && session) {\n return (\n <Dashboard\n preferences={preferences}\n engine={engine}\n session={session}\n onProfiles={() => void openProfiles()}\n onLogout={() => void logout()}\n />\n );\n }\n return (\n <Box flexDirection=\"column\">\n <Header />\n <Notice error>{error ?? '\uC54C \uC218 \uC5C6\uB294 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.'}</Notice>\n <Text dimColor>\uC11C\uBC84\uC640 \uD0A4\uCCB4\uC778 \uC0C1\uD0DC\uB97C \uD655\uC778\uD55C \uB4A4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.</Text>\n <Footer text=\"R \uB2E4\uC2DC \uC2DC\uB3C4 \u00B7 Ctrl+Q \uC885\uB8CC\" />\n <RetryInput onRetry={() => void bootstrap()} />\n </Box>\n );\n}\n\nfunction RetryInput({ onRetry }: { onRetry: () => void }): null {\n useInput((input) => {\n if (input.toLowerCase() === 'r') onRetry();\n });\n return null;\n}\n", "import { useEffect, useReducer, useRef, useState } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport { publicError } from '@dex/engine';\nimport type { Agent, Conversation, HistoryTurn } from '@dex/engine';\nimport { chatReducer, initialChatState, type ChatMessage } from './chat-state';\nimport { useMeasured } from './measure';\nimport { maximumScroll, renderTranscript, viewportOf } from './transcript';\nimport { CommandPalette, type PaletteAction } from './command-palette';\nimport { Footer, Header } from './components';\nimport { HistoryScreen } from './history-screen';\nimport { StartPanel } from './start-panel';\nimport { ImeTextInput } from './ime-text-input';\nimport type { TuiEngine, TuiSession } from './model';\nimport { useTerminalSize } from './use-terminal-size';\n\ninterface AgentRef {\n workflowId: string;\n workflowName: string;\n}\n\nfunction AgentSidebar(props: {\n agents: Agent[];\n cursor: number;\n selected?: string;\n focused: boolean;\n height: number;\n}): React.ReactNode {\n const radius = Math.max(3, Math.floor((props.height - 4) / 2));\n const start = Math.max(0, props.cursor - radius);\n const visible = props.agents.slice(start, start + radius * 2 + 1);\n return (\n <Box flexDirection=\"column\" width={30} borderStyle=\"round\" borderColor={props.focused ? 'cyan' : 'gray'} paddingX={1}>\n <Text bold>Agents</Text>\n {visible.map((agent) => {\n const index = props.agents.indexOf(agent);\n const cursor = index === props.cursor;\n const selected = agent.workflowId === props.selected;\n return (\n <Text key={agent.workflowId} color={cursor && props.focused ? 'cyan' : undefined} wrap=\"truncate-end\">\n {cursor ? '\u203A' : ' '} {selected ? '\u25CF' : '\u25CB'} {agent.workflowName}\n </Text>\n );\n })}\n {props.agents.length === 0 ? <Text dimColor>\uC0AC\uC6A9 \uAC00\uB2A5\uD55C Agent\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.</Text> : null}\n </Box>\n );\n}\n\nfunction ChatPane(props: {\n agent?: AgentRef;\n messages: ChatMessage[];\n status?: string;\n scrollUp: number;\n onViewport: (lineCount: number, height: number) => void;\n}): React.ReactNode {\n const [ref, box] = useMeasured();\n // \uCCAB \uD504\uB808\uC784\uC5D0\uB294 \uC544\uC9C1 \uC7B0 \uAC12\uC774 \uC5C6\uB2E4. \uB109\uB109\uD788 \uC7A1\uC73C\uBA74 \uADF8 \uD55C \uD504\uB808\uC784\uC774 \uB118\uCCD0 \uD654\uBA74\uC744\n // \uBC1F\uC73C\uBBC0\uB85C, \uD655\uC2E4\uD788 \uC548 \uB118\uCE60 \uB9CC\uD07C\uB9CC \uC7A1\uACE0 \uB2E4\uC74C \uD504\uB808\uC784\uC5D0\uC11C \uB9DE\uCD98\uB2E4.\n const width = box?.width ?? 20;\n const height = box?.height ?? 1;\n const lines = renderTranscript(props.messages, props.agent?.workflowName ?? 'Agent', width);\n const view = viewportOf(lines, height, props.scrollUp);\n\n useEffect(() => {\n props.onViewport(lines.length, height);\n }, [lines.length, height]);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"round\" borderColor=\"blue\" paddingX={1}>\n <Box>\n <Text bold wrap=\"truncate-end\">\n {props.agent?.workflowName ?? 'Agent\uB97C \uC120\uD0DD\uD558\uC138\uC694'}\n </Text>\n {view.below > 0 ? <Text dimColor> \u00B7 \u2193{view.below}\uC904</Text> : null}\n </Box>\n {/* \uC7B0 \uB192\uC774 \uC548\uC5D0\uC11C\uB9CC \uADF8\uB9B0\uB2E4. \uB118\uCE58\uBA74 ink \uC774 \uC9C0\uC6B0\uB294 \uC790\uB9AC\uC640 \uADF8\uB9AC\uB294 \uC790\uB9AC\uAC00\n \uC5B4\uAE0B\uB098 \uC785\uB825\uCC3D\uACFC \uC548\uB0B4\uC904\uAE4C\uC9C0 \uBC1F\uD78C\uB2E4. */}\n <Box ref={ref} flexDirection=\"column\" flexGrow={1} overflow=\"hidden\">\n {view.lines.length === 0 ? (\n <Text dimColor wrap=\"truncate-end\">\n {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.'}\n </Text>\n ) : null}\n {view.lines.map((line) => (\n <Text\n key={line.key}\n wrap=\"truncate-end\"\n bold={line.role === 'label'}\n dimColor={line.role === 'activity'}\n color={line.color}\n >\n {line.text || ' '}\n </Text>\n ))}\n </Box>\n {props.status ? (\n <Text color=\"yellow\" wrap=\"truncate-end\">\n \u25C6 {props.status}\n </Text>\n ) : null}\n </Box>\n );\n}\n\nfunction Composer(props: {\n value: string;\n onChange: (value: string) => void;\n onSubmit: (value: string) => void;\n focused: boolean;\n disabled: boolean;\n hangulMode: boolean;\n onHangulModeChange: (enabled: boolean) => void;\n}): React.ReactNode {\n return (\n <Box borderStyle=\"round\" borderColor={props.focused ? 'cyan' : 'gray'} paddingX={1}>\n {/* \uC9C0\uAE08 \uBB34\uC5C7\uC774 \uCCD0\uC9C0\uB294\uC9C0 \uB298 \uBCF4\uC774\uAC8C \uB454\uB2E4 \u2014 \uBAA8\uB974\uACE0 \uCE58\uBA74 `dkssud` \uC774 \uB098\uC628\uB2E4. */}\n <Text color={props.hangulMode ? 'yellow' : undefined} dimColor={!props.hangulMode}>\n {props.hangulMode ? '\uD55C' : 'EN'}\n </Text>\n <Text color=\"cyan\"> \u203A </Text>\n {props.disabled ? (\n <Text dimColor>\uC751\uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uC911...</Text>\n ) : (\n <ImeTextInput\n value={props.value}\n onChange={props.onChange}\n onSubmit={props.onSubmit}\n focus={props.focused}\n placeholder=\"\uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694\"\n hangulMode={props.hangulMode}\n onHangulModeChange={props.onHangulModeChange}\n />\n )}\n </Box>\n );\n}\n\nexport function Dashboard(props: {\n engine: TuiEngine;\n session: TuiSession;\n onProfiles: () => void;\n onLogout: () => void;\n preferences?: { hangulMode: boolean; onHangulModeChange?: (enabled: boolean) => void };\n}): React.ReactNode {\n const { exit } = useApp();\n const size = useTerminalSize();\n const bodyHeight = Math.max(12, size.rows - 5);\n const [focus, setFocus] = useState<'agents' | 'composer'>('agents');\n const [cursor, setCursor] = useState(0);\n const [selected, setSelected] = useState<AgentRef | undefined>(() => {\n const first = props.session.agents[0];\n return first ? { workflowId: first.workflowId, workflowName: first.workflowName } : undefined;\n });\n const [input, setInput] = useState('');\n const [chat, dispatch] = useReducer(chatReducer, initialChatState);\n const [palette, setPalette] = useState(false);\n const [history, setHistory] = useState(false);\n /** \uC5D0\uC774\uC804\uD2B8\uB97C \uACE0\uB978 \uC9C1\uD6C4\uC758 \uAC08\uB9BC\uAE38. \uC774\uB825\uC774 \uC788\uC744 \uB54C\uB9CC \uCC44\uC6CC\uC9C4\uB2E4. */\n const [start, setStart] = useState<{ agent: AgentRef; conversations: Conversation[] }>();\n /**\n * \uB300\uD654\uCC3D\uC744 \uB9E8 \uC544\uB798\uC5D0\uC11C \uBA87 \uC904 \uC62C\uB824 \uB480\uB294\uC9C0.\n *\n * 0 \uC774\uBA74 \uB298 \uCD5C\uC2E0\uC5D0 \uBD99\uC5B4 \uC788\uB2E4 \u2014 \uC751\uB2F5\uC774 \uD758\uB7EC\uB3C4 \uB530\uB77C\uAC04\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uC62C\uB824 \uB454 \uB3D9\uC548\uC5D0\uB294\n * \uC0C8 \uC904\uC774 \uC640\uB3C4 \uADF8 \uC790\uB9AC\uB97C \uC9C0\uD0A8\uB2E4. \uC77D\uB358 \uACF3\uC774 \uD280\uC5B4 \uB0B4\uB824\uAC00\uBA74 \uC77D\uC744 \uC218\uAC00 \uC5C6\uB2E4.\n */\n const [scrollUp, setScrollUp] = useState(0);\n /**\n * \uD55C\uAE00 \uC870\uD569 \uCF2C/\uB054.\n *\n * \uD130\uBBF8\uB110 IME \uC5D0 \uB9E1\uAE30\uB358 \uAC83\uC744 CLI \uC548\uC73C\uB85C \uB4E4\uC5EC\uC654\uB2E4 \u2014 \uD130\uBBF8\uB110\uB9C8\uB2E4 \uB2E4\uB974\uACE0 SSH\u00B7tmux \uB97C\n * \uAC70\uCE58\uBA74 \uC544\uC608 \uC548 \uC624\uB358 \uC790\uB9AC\uB77C, \uC6B0\uB9AC\uAC00 \uC870\uD569\uD574\uC57C \uC5B4\uB514\uC11C\uB4E0 \uAC19\uAC8C \uB3D9\uC791\uD55C\uB2E4.\n */\n const [hangulMode, setHangulMode] = useState(props.preferences?.hangulMode ?? false);\n const changeHangulMode = (enabled: boolean): void => {\n setHangulMode(enabled);\n props.preferences?.onHangulModeChange?.(enabled);\n };\n const viewport = useRef({ lineCount: 0, height: 0 });\n const [starting, setStarting] = useState(false);\n const controller = useRef<AbortController | null>(null);\n\n useEffect(() => () => controller.current?.abort(), []);\n\n /**\n * \uC5D0\uC774\uC804\uD2B8\uB97C \uACE0\uB978\uB2E4.\n *\n * \uC774 \uC5D0\uC774\uC804\uD2B8\uC5D0 **\uC774\uC804 \uB300\uD654\uAC00 \uC788\uC73C\uBA74** \uAC08\uB9BC\uAE38\uC744 \uBCF4\uC5EC \uC900\uB2E4(\uC0C8\uB85C \uC2DC\uC791 / \uC774\uC5B4\uAC00\uAE30).\n * \uC5C6\uC73C\uBA74 \uBC14\uB85C \uC0C8 \uB300\uD654\uB97C \uC5F0\uB2E4 \u2014 \uC120\uD0DD\uC9C0\uAC00 \uD558\uB098\uBFD0\uC778 \uC9C8\uBB38\uC740 \uD55C \uBC88 \uB354 \uB204\uB974\uAC8C \uD558\uB294\n * \uC77C\uC77C \uBFD0\uC774\uB2E4.\n *\n * \uBAA9\uB85D \uC870\uD68C\uAC00 \uC2E4\uD328\uD574\uB3C4 \uB9C9\uC9C0 \uC54A\uB294\uB2E4. \uC774\uB825\uC744 \uBABB \uC77D\uB294 \uAC83\uACFC \uB300\uD654\uB97C \uBABB \uD558\uB294 \uAC83\uC740\n * \uB2E4\uB978 \uC77C\uC774\uACE0, \uD6C4\uC790\uB97C \uC804\uC790 \uB54C\uBB38\uC5D0 \uB9C9\uC73C\uBA74 \uC548 \uB41C\uB2E4 \u2014 \uADF8\uB0E5 \uC0C8 \uB300\uD654\uB85C \uC5F0\uB2E4.\n */\n const selectAgent = async (): Promise<void> => {\n const agent = props.session.agents[cursor];\n if (!agent || chat.running || starting) return;\n const ref: AgentRef = { workflowId: agent.workflowId, workflowName: agent.workflowName };\n\n setStarting(true);\n let conversations: Conversation[] = [];\n try {\n const all = await props.engine.listConversations(props.session.profile);\n conversations = all.filter((item) => item.workflowId === ref.workflowId);\n } catch {\n conversations = [];\n } finally {\n setStarting(false);\n }\n\n if (conversations.length === 0) {\n openNewChat(ref);\n return;\n }\n setSelected(ref);\n setStart({ agent: ref, conversations });\n };\n\n /** \uBE48 \uB300\uD654\uB97C \uC5F0\uB2E4 \u2014 \uAC08\uB9BC\uAE38\uC5D0\uC11C [\uC0C8 \uB300\uD654] \uB97C \uACE0\uB978 \uAC83\uACFC \uAC19\uC740 \uC790\uB9AC. */\n const openNewChat = (ref: AgentRef): void => {\n setSelected(ref);\n dispatch({ type: 'reset' });\n setInput('');\n setScrollUp(0);\n setStart(undefined);\n setFocus('composer');\n };\n\n const openHistory = (conversation: Conversation, turns: HistoryTurn[]): void => {\n setSelected({ workflowId: conversation.workflowId, workflowName: conversation.workflowName });\n dispatch({ type: 'history_loaded', interactionId: conversation.interactionId, turns });\n // \uBD88\uB7EC\uC628 \uB300\uD654\uB294 \uB9E8 \uC544\uB798(\uAC00\uC7A5 \uCD5C\uADFC)\uBD80\uD130 \uBCF4\uC5EC \uC900\uB2E4.\n setScrollUp(0);\n const index = props.session.agents.findIndex((agent) => agent.workflowId === conversation.workflowId);\n if (index >= 0) setCursor(index);\n setHistory(false);\n setStart(undefined);\n setFocus('composer');\n };\n\n const cancelTurn = (): void => {\n controller.current?.abort();\n dispatch({ type: 'turn_cancelled' });\n };\n\n const newConversation = (): void => {\n if (chat.running) return;\n dispatch({ type: 'reset' });\n setInput('');\n setScrollUp(0);\n setPalette(false);\n setFocus('composer');\n };\n\n const send = async (value: string): Promise<void> => {\n const text = value.trim();\n if (!text || !selected || chat.running) return;\n try {\n const resolved = await props.engine.resolveChatInput({\n profile: props.session.profile,\n workflowId: selected.workflowId,\n workflowName: selected.workflowName,\n interactionId: chat.interactionId,\n input: text,\n });\n setInput('');\n setScrollUp(0);\n dispatch({ type: 'turn_started', interactionId: resolved.interactionId, input: text });\n const active = new AbortController();\n controller.current = active;\n for await (const event of props.engine.chat(resolved, active.signal)) {\n dispatch({ type: 'event_received', event });\n }\n if (active.signal.aborted) dispatch({ type: 'turn_cancelled' });\n else dispatch({ type: 'turn_completed' });\n } catch (error) {\n if (controller.current?.signal.aborted) dispatch({ type: 'turn_cancelled' });\n else dispatch({ type: 'turn_failed', message: publicError(error).message });\n } finally {\n controller.current = null;\n }\n };\n\n /**\n * \uB300\uD654\uCC3D\uC744 \uD55C \uD654\uBA74\uC758 \uC808\uBC18\uC529 \uC6C0\uC9C1\uC778\uB2E4. `direction` \uC774 -1 \uC774\uBA74 \uACFC\uAC70\uB85C.\n *\n * \uD55C \uD654\uBA74\uC744 \uD1B5\uC9F8\uB85C \uB118\uAE30\uBA74 \uC55E\uB4A4\uAC00 \uC774\uC5B4\uC9C0\uC9C0 \uC54A\uC544 \uC77D\uB358 \uC790\uB9AC\uB97C \uB193\uCE5C\uB2E4.\n */\n const scrollBy = (direction: -1 | 1): void => {\n const { lineCount, height } = viewport.current;\n const step = Math.max(1, Math.floor(height / 2));\n const limit = maximumScroll(lineCount, height);\n setScrollUp((current) => Math.min(limit, Math.max(0, current - direction * step)));\n };\n\n useInput(\n (keyInput, key) => {\n if (key.ctrl && keyInput === 'k') setPalette(true);\n else if (key.ctrl && keyInput === 'p') {\n controller.current?.abort();\n props.onProfiles();\n } else if (key.ctrl && keyInput === 'h') {\n if (chat.running) cancelTurn();\n setHistory(true);\n }\n else if (key.ctrl && keyInput === 'n') newConversation();\n else if (key.pageUp) scrollBy(-1);\n else if (key.pageDown) scrollBy(1);\n else if (key.escape && chat.running) cancelTurn();\n else if (key.escape) setFocus('agents');\n else if (key.tab) setFocus((current) => (current === 'agents' ? 'composer' : 'agents'));\n else if (focus === 'agents' && key.upArrow) setCursor((current) => Math.max(0, current - 1));\n else if (focus === 'agents' && key.downArrow && props.session.agents.length > 0) {\n setCursor((current) => Math.min(props.session.agents.length - 1, current + 1));\n } else if (focus === 'agents' && key.return) void selectAgent();\n },\n // \uAC08\uB9BC\uAE38\u00B7\uD314\uB808\uD2B8\u00B7\uC774\uB825 \uD654\uBA74\uC774 \uB5A0 \uC788\uC73C\uBA74 \uADF8 \uD654\uBA74\uC774 \uD0A4\uB97C \uAC16\uB294\uB2E4 \u2014 \uC5EC\uAE30\uC11C\uB3C4 \uBC1B\uC73C\uBA74\n // \uBC29\uD5A5\uD0A4 \uD558\uB098\uAC00 \uB450 \uACF3\uC5D0\uC11C \uC6C0\uC9C1\uC778\uB2E4.\n { isActive: !palette && !history && !start },\n );\n\n const paletteActions: PaletteAction[] = [\n { id: 'new', label: '\uC0C8 \uB300\uD654', run: newConversation },\n {\n id: 'history',\n label: '\uB300\uD654 \uAE30\uB85D',\n run: () => {\n if (chat.running) cancelTurn();\n setPalette(false);\n setHistory(true);\n },\n },\n {\n id: 'profile',\n label: '\uD504\uB85C\uD544 \uC804\uD658',\n run: () => {\n controller.current?.abort();\n setPalette(false);\n props.onProfiles();\n },\n },\n {\n id: 'logout',\n label: '\uB85C\uADF8\uC544\uC6C3',\n run: () => {\n controller.current?.abort();\n props.onLogout();\n },\n },\n { id: 'quit', label: '\uC885\uB8CC', run: exit },\n ];\n\n let body: React.ReactNode;\n if (palette) {\n body = <CommandPalette actions={paletteActions} onCancel={() => setPalette(false)} />;\n } else if (history) {\n body = (\n <HistoryScreen\n engine={props.engine}\n profile={props.session.profile}\n onOpen={openHistory}\n onCancel={() => setHistory(false)}\n />\n );\n } else {\n const sidebar = (\n <AgentSidebar\n agents={props.session.agents}\n cursor={cursor}\n selected={selected?.workflowId}\n focused={focus === 'agents'}\n height={bodyHeight}\n />\n );\n // \uAC08\uB9BC\uAE38\uC774 \uC5F4\uB824 \uC788\uC73C\uBA74 \uB300\uD654\uCC3D \uC790\uB9AC\uB97C \uADF8\uAC83\uC774 \uC4F4\uB2E4 \u2014 \uBAA9\uB85D\uC740 \uADF8\uB300\uB85C \uC606\uC5D0 \uB0A8\uC544\n // \uC5B4\uB290 \uC5D0\uC774\uC804\uD2B8\uB97C \uACE0\uB978 \uAC83\uC778\uC9C0 \uBCF4\uC778\uB2E4.\n const conversation = start ? (\n <StartPanel\n engine={props.engine}\n profile={props.session.profile}\n agentName={start.agent.workflowName}\n conversations={start.conversations}\n onNew={() => openNewChat(start.agent)}\n onOpen={openHistory}\n onCancel={() => {\n setStart(undefined);\n setFocus('agents');\n }}\n />\n ) : (\n <Box flexDirection=\"column\" flexGrow={1}>\n <ChatPane\n agent={selected}\n messages={chat.messages}\n status={chat.status}\n scrollUp={scrollUp}\n onViewport={(lineCount, height) => {\n viewport.current = { lineCount, height };\n }}\n />\n <Composer\n value={input}\n onChange={setInput}\n onSubmit={(value) => void send(value)}\n focused={focus === 'composer'}\n disabled={chat.running || !selected}\n hangulMode={hangulMode}\n onHangulModeChange={changeHangulMode}\n />\n </Box>\n );\n body = size.wide ? (\n <Box height={bodyHeight}>{sidebar}{conversation}</Box>\n ) : focus === 'agents' ? (\n <Box height={bodyHeight}>{sidebar}</Box>\n ) : (\n <Box height={bodyHeight}>{conversation}</Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Header\n profile={props.session.profile}\n username={props.session.username}\n connected\n />\n {body}\n <Footer\n mode={hangulMode ? '\uD55C' : 'EN'}\n text=\"Ctrl+Space \uD55C/\uC601 \u00B7 Tab \uD328\uB110 \u00B7 PgUp/PgDn \uC2A4\uD06C\uB864 \u00B7 Ctrl+K \uBA85\uB839 \u00B7 Ctrl+H \uAE30\uB85D \u00B7 Ctrl+P \uD504\uB85C\uD544 \u00B7 Esc \uCDE8\uC18C \u00B7 Ctrl+Q \uC885\uB8CC\"\n />\n </Box>\n );\n}\n", "import type { ChatEvent, HistoryTurn } from '@dex/engine';\n\nexport type ChatMessageRole = 'user' | 'assistant' | 'activity' | 'system';\n\nexport interface ChatMessage {\n id: string;\n role: ChatMessageRole;\n text: string;\n activityKey?: string;\n}\n\nexport interface ChatState {\n interactionId?: string;\n messages: ChatMessage[];\n running: boolean;\n status?: string;\n}\n\nexport type ChatAction =\n | { type: 'reset' }\n | { type: 'history_loaded'; interactionId: string; turns: HistoryTurn[] }\n | { type: 'turn_started'; interactionId: string; input: string }\n | { type: 'event_received'; event: ChatEvent }\n | { type: 'turn_completed' }\n | { type: 'turn_cancelled' }\n | { type: 'turn_failed'; message: string };\n\nexport const initialChatState: ChatState = { messages: [], running: false };\n\nfunction lastMessageIndex(\n messages: ChatMessage[],\n predicate: (message: ChatMessage) => boolean,\n): number {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (predicate(messages[index])) return index;\n }\n return -1;\n}\n\nfunction appendAssistant(messages: ChatMessage[], content: string): ChatMessage[] {\n const index = lastMessageIndex(messages, (message) => message.role === 'assistant');\n if (index < 0) {\n return [...messages, { id: `assistant-${messages.length}`, role: 'assistant', text: content }];\n }\n const next = [...messages];\n next[index] = { ...next[index], text: next[index].text + content };\n return next;\n}\n\nfunction upsertActivity(messages: ChatMessage[], key: string, text: string): ChatMessage[] {\n const index = lastMessageIndex(\n messages,\n (message) => message.role === 'activity' && message.activityKey === key,\n );\n const startsNewRun =\n index >= 0 && text.endsWith('\uC2E4\uD589 \uC911') && !messages[index].text.endsWith('\uC2E4\uD589 \uC911');\n if (index < 0 || startsNewRun) {\n return [\n ...messages,\n { id: `activity-${messages.length}`, role: 'activity', activityKey: key, text },\n ];\n }\n const next = [...messages];\n next[index] = { ...next[index], text };\n return next;\n}\n\nfunction eventState(state: ChatState, event: ChatEvent): ChatState {\n if (event.kind === 'text') return { ...state, messages: appendAssistant(state.messages, event.content) };\n if (event.kind === 'summary') {\n const assistantIndex = lastMessageIndex(state.messages, (message) => message.role === 'assistant');\n const assistant = assistantIndex >= 0 ? state.messages[assistantIndex] : undefined;\n return assistant?.text ? state : { ...state, messages: appendAssistant(state.messages, event.text) };\n }\n if (event.kind === 'tool') {\n const tool = event.event.toolName ?? 'tool';\n const key = event.event.runId ?? tool;\n const suffix = event.event.error\n ? `\uC2E4\uD328: ${event.event.error}`\n : event.event.eventType.includes('result')\n ? '\uC644\uB8CC'\n : '\uC2E4\uD589 \uC911';\n return { ...state, messages: upsertActivity(state.messages, key, `${tool} \u00B7 ${suffix}`) };\n }\n if (event.kind === 'node_status') {\n return { ...state, status: `${event.event.nodeId} \u00B7 ${event.event.status}` };\n }\n if (event.kind === 'status') {\n return { ...state, status: event.detail ?? event.surface };\n }\n if (event.kind === 'quota') {\n return {\n ...state,\n messages: [\n ...state.messages,\n { id: `quota-${state.messages.length}`, role: 'system', text: `Quota ${event.level}` },\n ],\n };\n }\n if (event.kind === 'error') {\n return {\n ...state,\n running: false,\n status: undefined,\n messages: [\n ...state.messages,\n { id: `error-${state.messages.length}`, role: 'system', text: event.detail },\n ],\n };\n }\n if (event.kind === 'end') return { ...state, running: false, status: undefined };\n return state;\n}\n\nexport function chatReducer(state: ChatState, action: ChatAction): ChatState {\n switch (action.type) {\n case 'reset':\n return initialChatState;\n case 'history_loaded':\n return {\n interactionId: action.interactionId,\n running: false,\n messages: action.turns.flatMap((turn, index) => [\n { id: `history-user-${index}`, role: 'user' as const, text: turn.input },\n { id: `history-assistant-${index}`, role: 'assistant' as const, text: turn.output },\n ]),\n };\n case 'turn_started':\n return {\n ...state,\n interactionId: action.interactionId,\n running: true,\n status: '\uC751\uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uC911',\n messages: [\n ...state.messages,\n { id: `user-${state.messages.length}`, role: 'user', text: action.input },\n { id: `assistant-${state.messages.length + 1}`, role: 'assistant', text: '' },\n ],\n };\n case 'event_received':\n return eventState(state, action.event);\n case 'turn_completed':\n return { ...state, running: false, status: undefined };\n case 'turn_cancelled':\n return { ...state, running: false, status: undefined };\n case 'turn_failed':\n return {\n ...state,\n running: false,\n status: undefined,\n messages: [\n ...state.messages,\n { id: `failure-${state.messages.length}`, role: 'system', text: action.message },\n ],\n };\n }\n}\n", "import { useEffect, useRef, useState } from 'react';\nimport type { DOMElement } from 'ink';\n\n/**\n * \uC5B4\uB5A4 \uCE78\uC774 \uD654\uBA74\uC758 **\uC5B4\uB514\uC5D0, \uC5BC\uB9C8\uB9CC\uD07C** \uADF8\uB824\uC9C0\uB294\uC9C0 \uB808\uC774\uC544\uC6C3\uC5D0\uC11C \uC77D\uC5B4 \uC628\uB2E4.\n *\n * \uC608\uC804\uC5D0\uB294 \uD654\uBA74\uB9C8\uB2E4 `{ x: 16, y: 6 }`, `height - 5` \uCC98\uB7FC \uC190\uC73C\uB85C \uC138\uC5B4 \uB123\uC5C8\uB2E4. \uADF8\n * \uC22B\uC790\uB294 \uADF8\uB54C\uC758 \uB808\uC774\uC544\uC6C3\uC5D0\uC11C\uB9CC \uB9DE\uB2E4 \u2014 \uB77C\uBCA8 \uD55C \uAE00\uC790, \uD14C\uB450\uB9AC \uD558\uB098, \uC0AC\uC774\uB4DC\uBC14 \uD3ED\uC774\n * \uBC14\uB00C\uBA74 \uC870\uC6A9\uD788 \uC5B4\uAE0B\uB09C\uB2E4. yoga \uAC00 \uC774\uBBF8 \uC815\uD655\uD788 \uC544\uB294 \uAC12\uC774\uB77C \uC140 \uC774\uC720\uAC00 \uC5C6\uB2E4.\n */\nexport interface Placement {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport function placementOf(node: DOMElement | null): Placement | undefined {\n const yogaSelf = node?.yogaNode;\n if (!node || !yogaSelf) return undefined;\n let x = 0;\n let y = 0;\n for (let current: DOMElement | undefined = node; current; current = current.parentNode) {\n const yoga = current.yogaNode;\n if (!yoga) continue;\n x += yoga.getComputedLeft();\n y += yoga.getComputedTop();\n }\n return { x, y, width: yogaSelf.getComputedWidth(), height: yogaSelf.getComputedHeight() };\n}\n\n/**\n * \uBD99\uC778 \uCE78\uC758 \uC790\uB9AC\uB97C \uC7AC\uC11C \uB3CC\uB824\uC900\uB2E4. \uCCAB \uD504\uB808\uC784\uC5D0\uB294 `undefined` \uB2E4.\n *\n * ink \uC740 \uCEE4\uBC0B\uC774 **\uB05D\uB09C \uB4A4\uC5D0** \uB808\uC774\uC544\uC6C3\uC744 \uACC4\uC0B0\uD558\uBBC0\uB85C \uC5EC\uAE30\uC11C \uC77D\uC73C\uBA74 \uD55C \uD504\uB808\uC784 \uB2A6\uB2E4.\n * \uB2EC\uB77C\uC84C\uC744 \uB54C\uB9CC \uC0C1\uD0DC\uB97C \uBC14\uAFD4 \uB2E4\uC74C \uD504\uB808\uC784\uC5D0\uC11C \uB9DE\uCD98\uB2E4 \u2014 \uB9E4\uBC88 \uBC14\uAFB8\uBA74 \uB80C\uB354\uAC00 \uB05D\uC5C6\uC774 \uB3C8\uB2E4.\n */\nexport function useMeasured(): [React.MutableRefObject<DOMElement | null>, Placement | undefined] {\n const ref = useRef<DOMElement | null>(null);\n const [placement, setPlacement] = useState<Placement | undefined>(undefined);\n useEffect(() => {\n const measured = placementOf(ref.current);\n if (!measured) return;\n if (\n placement?.x !== measured.x ||\n placement?.y !== measured.y ||\n placement?.width !== measured.width ||\n placement?.height !== measured.height\n ) {\n setPlacement(measured);\n }\n });\n return [ref, placement];\n}\n", "import stringWidth from 'string-width';\nimport type { ChatMessage } from './chat-state';\n\n/**\n * \uB300\uD654\uB97C **\uC904 \uB2E8\uC704\uB85C** \uD3BC\uCE5C\uB2E4.\n *\n * \uC608\uC804\uC5D0\uB294 \uB9C8\uC9C0\uB9C9 \uBA87 **\uAC1C\uC758 \uBA54\uC2DC\uC9C0**\uB97C \uC798\uB77C \uBCF4\uC5EC \uC92C\uB2E4. \uD55C \uBA54\uC2DC\uC9C0\uAC00 \uD55C\uB450 \uC904\uC774\uB77C\uACE0\n * \uCE5C \uC148\uC778\uB370, \uC2E4\uC81C\uB85C\uB294 \uC218\uC2ED \uC904\uC9DC\uB9AC\uAC00 \uC628\uB2E4. \uADF8\uB7EC\uBA74 \uB300\uD654\uCC3D\uC774 \uC81C \uB192\uC774\uB97C \uB118\uC5B4 \uC790\uB77C\uACE0,\n * ink \uC740 \uC904 \uC218\uB97C \uC138\uC5B4 \uD654\uBA74\uC744 \uC9C0\uC6B0\uBBC0\uB85C \uADF8 \uC21C\uAC04\uBD80\uD130 \uC9C0\uC6B0\uB294 \uC790\uB9AC\uC640 \uADF8\uB9AC\uB294 \uC790\uB9AC\uAC00\n * \uC5B4\uAE0B\uB09C\uB2E4 \u2014 \uAE00\uC790\uAC00 \uD14C\uB450\uB9AC \uBC16\uC73C\uB85C \uC0C8\uACE0, \uC785\uB825\uCC3D\uACFC \uC544\uB798 \uC548\uB0B4\uC904\uAE4C\uC9C0 \uBC1F\uD78C\uB2E4. \uB300\uD654\uAC00\n * \uAE38\uC5B4\uC9C8\uC218\uB85D \uD655\uC2E4\uD788 \uAE68\uC84C\uB2E4.\n *\n * \uADF8\uB798\uC11C \uC5EC\uAE30\uC11C **\uBA3C\uC800 \uD3ED\uC5D0 \uB9DE\uCDB0 \uC904\uB85C \uB9CC\uB4E0 \uB4A4** \uB192\uC774\uB9CC\uD07C\uB9CC \uC790\uB978\uB2E4. \uB300\uD654\uCC3D\uC774 \uC790\uAE30\n * \uB192\uC774\uB97C \uB118\uB294 \uC77C\uC774 \uAD6C\uC870\uC801\uC73C\uB85C \uBD88\uAC00\uB2A5\uD574\uC9C0\uACE0, \uADF8 \uB355\uC5D0 \uC2A4\uD06C\uB864\uB3C4 \uC904 \uB2E8\uC704\uB85C \uC815\uD655\uD574\uC9C4\uB2E4.\n */\n\nexport type LineRole = 'label' | 'text' | 'activity' | 'system';\n\nexport interface TranscriptLine {\n key: string;\n text: string;\n role: LineRole;\n color?: string;\n}\n\n/** \uC774 \uC904 \uC55E\uC5D0 \uBD99\uB294 \uB4E4\uC5EC\uC4F0\uAE30. \uB9D0\uD55C \uC0AC\uB78C \uC544\uB798\uB85C \uB0B4\uC6A9\uC774 \uC815\uB82C\uB41C\uB2E4. */\nconst INDENT = ' ';\n\nfunction colorOf(role: ChatMessage['role']): string | undefined {\n if (role === 'user') return 'cyan';\n if (role === 'assistant') return 'green';\n if (role === 'activity') return 'yellow';\n if (role === 'system') return 'red';\n return undefined;\n}\n\nfunction labelOf(role: ChatMessage['role'], agentName: string): string {\n if (role === 'user') return 'You';\n if (role === 'assistant') return agentName;\n if (role === 'activity') return 'Tool';\n return 'System';\n}\n\n/**\n * \uD55C \uBB38\uB2E8\uC744 \uD3ED\uC5D0 \uB9DE\uCDB0 \uC790\uB978\uB2E4.\n *\n * \uACF5\uBC31\uC5D0\uC11C \uB04A\uB294 \uAC83\uC744 \uC6B0\uC120\uD558\uB418, \uD55C \uB0B1\uB9D0\uC774 \uD3ED\uBCF4\uB2E4 \uAE38\uAC70\uB098 \uD55C\uAD6D\uC5B4\uCC98\uB7FC \uACF5\uBC31\uC774 \uC5C6\uC73C\uBA74\n * \uAE00\uC790 \uD3ED\uC744 \uC138\uC5B4 \uB04A\uB294\uB2E4. `String.length` \uB85C\uB294 \uC548 \uB41C\uB2E4 \u2014 \uD55C\uAE00\u00B7\uC774\uBAA8\uC9C0\uB294 \uD55C \uAE00\uC790\uAC00\n * \uB450 \uCE78\uC774\uB77C, \uAE38\uC774\uB85C \uC790\uB974\uBA74 \uC904\uC774 \uD3ED\uC744 \uB118\uC5B4 \uACB0\uAD6D \uB300\uD654\uCC3D\uC774 \uC790\uB780\uB2E4.\n */\nexport function wrapToWidth(text: string, width: number): string[] {\n if (width <= 0) return [text];\n const lines: string[] = [];\n for (const paragraph of text.split('\\n')) {\n if (paragraph === '') {\n lines.push('');\n continue;\n }\n let line = '';\n let lineWidth = 0;\n const flush = (): void => {\n lines.push(line);\n line = '';\n lineWidth = 0;\n };\n // \uACF5\uBC31\uC744 \uB0B1\uB9D0\uC5D0 \uBD99\uC5EC \uB450\uBA74 \uC904 \uB05D\uC5D0\uC11C \uD568\uAED8 \uB118\uC5B4\uAC00 \uC55E\uC904\uC774 \uD3ED\uC744 \uB118\uC9C0 \uC54A\uB294\uB2E4.\n for (const word of paragraph.match(/\\s+|\\S+/g) ?? []) {\n const wordWidth = stringWidth(word);\n if (lineWidth > 0 && lineWidth + wordWidth > width) {\n flush();\n if (/^\\s+$/.test(word)) continue; // \uC904\uBC14\uAFC8 \uC790\uB9AC\uC758 \uACF5\uBC31\uC740 \uBC84\uB9B0\uB2E4\n }\n if (wordWidth <= width) {\n line += word;\n lineWidth += wordWidth;\n continue;\n }\n // \uB0B1\uB9D0 \uD558\uB098\uAC00 \uD3ED\uBCF4\uB2E4 \uAE38\uB2E4 \u2014 \uAE00\uC790 \uD3ED\uC744 \uC138\uC5B4 \uB04A\uB294\uB2E4.\n for (const char of word) {\n const charWidth = stringWidth(char);\n if (lineWidth + charWidth > width) flush();\n line += char;\n lineWidth += charWidth;\n }\n }\n flush();\n }\n return lines;\n}\n\n/**\n * \uB9D0\uD55C \uC0AC\uB78C\uC744 \uAC00\uB85C\uC904\uB85C \uBABB\uBC15\uB294\uB2E4: `\u2500\u2500 You \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`.\n *\n * \uC774\uB984\uB9CC \uAD75\uAC8C \uC4F0\uB358 \uB54C\uB294 \uB300\uD654\uB97C \uBD88\uB7EC\uC624\uBA74 \uC5B4\uB514\uC11C \uB204\uAC00 \uBC14\uB00C\uB294\uC9C0 \uB208\uC5D0 \uB4E4\uC5B4\uC624\uC9C0 \uC54A\uC558\uB2E4.\n * \uAC00\uB85C\uC904\uC740 \uC2A4\uD06C\uB864 \uB3C4\uC911 \uC544\uBB34 \uB370\uC11C\uB098 \uBA48\uCDB0\uB3C4 \uACBD\uACC4\uAC00 \uBC14\uB85C \uBCF4\uC778\uB2E4.\n */\nfunction ruleFor(label: string, width: number): string {\n // \uC774\uB984\uC774 \uAE38\uBA74 \uC904\uC778\uB2E4. \uB118\uCE58\uB294 \uCC44\uB85C \uB450\uBA74 \uB300\uD654\uCC3D\uC774 \uC790\uB77C\uACE0, \uADF8 \uC21C\uAC04 ink \uC774 \uC9C0\uC6B0\uB294\n // \uC790\uB9AC\uC640 \uADF8\uB9AC\uB294 \uC790\uB9AC\uAC00 \uC5B4\uAE0B\uB09C\uB2E4 \u2014 \uC5D0\uC774\uC804\uD2B8 \uC774\uB984\uC740 \uC0AC\uC6A9\uC790\uAC00 \uC9D3\uB294 \uAC12\uC774\uB77C \uC5BC\uB9C8\uB4E0\uC9C0\n // \uAE38 \uC218 \uC788\uB2E4.\n const room = Math.max(0, width - stringWidth('\u2500\u2500 '));\n let trimmed = '';\n let used = 0;\n for (const char of label) {\n const charWidth = stringWidth(char);\n if (used + charWidth > room) {\n trimmed = trimmed.slice(0, -1) + '\u2026';\n break;\n }\n trimmed += char;\n used += charWidth;\n }\n const head = `\u2500\u2500 ${trimmed} `;\n return head + '\u2500'.repeat(Math.max(0, width - stringWidth(head)));\n}\n\nexport function renderTranscript(\n messages: ChatMessage[],\n agentName: string,\n width: number,\n): TranscriptLine[] {\n const lines: TranscriptLine[] = [];\n const bodyWidth = Math.max(1, width - INDENT.length);\n\n for (const message of messages) {\n const color = colorOf(message.role);\n\n // \uB3C4\uAD6C \uD65C\uB3D9\uC740 \uB300\uD654\uAC00 \uC544\uB2C8\uB77C \uACC1\uB2E4\uB9AC\uB2E4. \uAC00\uB85C\uC904\uAE4C\uC9C0 \uB450\uBA74 \uC9C4\uC9DC \uB300\uD654\uAC00 \uBB3B\uD78C\uB2E4.\n if (message.role === 'activity') {\n for (const [index, text] of wrapToWidth(message.text, bodyWidth).entries()) {\n lines.push({\n key: `${message.id}:${index}`,\n text: `${index === 0 ? '\u00B7 ' : INDENT}${text}`,\n role: 'activity',\n color,\n });\n }\n continue;\n }\n\n if (lines.length > 0) lines.push({ key: `${message.id}:gap`, text: '', role: 'text' });\n lines.push({\n key: `${message.id}:label`,\n text: ruleFor(labelOf(message.role, agentName), width),\n role: 'label',\n color,\n });\n\n // \uC544\uC9C1 \uD55C \uAE00\uC790\uB3C4 \uC624\uC9C0 \uC54A\uC740 \uC751\uB2F5\uC740 \uBE48\uCE78\uC774 \uC544\uB2C8\uB77C \uAE30\uB2E4\uB9AC\uB294 \uC911\uC774\uB77C\uACE0 \uB9D0\uD574 \uC900\uB2E4.\n const body = message.text || (message.role === 'assistant' ? '\u2026' : '');\n for (const [index, text] of wrapToWidth(body, bodyWidth).entries()) {\n lines.push({\n key: `${message.id}:${index}`,\n text: INDENT + text,\n role: message.role === 'system' ? 'system' : 'text',\n color: message.role === 'system' ? color : undefined,\n });\n }\n }\n return lines;\n}\n\nexport interface Viewport {\n lines: TranscriptLine[];\n /** \uC704\uB85C \uAC00\uB824\uC9C4 \uC904 \uC218. 0 \uBCF4\uB2E4 \uD06C\uBA74 \uB354 \uBCFC \uAC83\uC774 \uC788\uB2E4\uB294 \uB73B\uC774\uB2E4. */\n above: number;\n /** \uC544\uB798\uB85C \uAC00\uB824\uC9C4 \uC904 \uC218. 0 \uC774\uBA74 \uB9E8 \uC544\uB798\uC5D0 \uBD99\uC5B4 \uC788\uB2E4. */\n below: number;\n}\n\n/**\n * \uB192\uC774\uB9CC\uD07C\uB9CC \uC798\uB77C \uB0B8\uB2E4.\n *\n * `scrollUp` \uC740 **\uB9E8 \uC544\uB798\uC5D0\uC11C \uBA87 \uC904 \uC62C\uB77C\uAC14\uB294\uC9C0**\uB2E4. 0 \uC774\uBA74 \uB298 \uCD5C\uC2E0\uC774 \uBCF4\uC778\uB2E4 \u2014 \uC0C8\n * \uC751\uB2F5\uC774 \uD758\uB7EC\uB3C4 \uB530\uB77C\uAC04\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uC62C\uB824 \uB454 \uB3D9\uC548\uC5D0\uB294 \uADF8 \uC790\uB9AC\uB97C \uC9C0\uD0A8\uB2E4.\n */\nexport function viewportOf(\n lines: TranscriptLine[],\n height: number,\n scrollUp: number,\n): Viewport {\n if (height <= 0) return { lines: [], above: lines.length, below: 0 };\n const maximumScroll = Math.max(0, lines.length - height);\n const up = Math.min(Math.max(0, scrollUp), maximumScroll);\n const end = lines.length - up;\n const start = Math.max(0, end - height);\n return { lines: lines.slice(start, end), above: start, below: lines.length - end };\n}\n\n/** \uC62C\uB77C\uAC08 \uC218 \uC788\uB294 \uCD5C\uB300\uCE58. \uC774 \uB108\uBA38\uB85C\uB294 \uC62C\uB824 \uBD10\uC57C \uAC19\uC740 \uD654\uBA74\uC774\uB2E4. */\nexport function maximumScroll(lineCount: number, height: number): number {\n return Math.max(0, lineCount - Math.max(0, height));\n}\n", "import { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { Footer } from './components';\n\nexport interface PaletteAction {\n id: string;\n label: string;\n run: () => void;\n}\n\nexport function CommandPalette(props: {\n actions: PaletteAction[];\n onCancel: () => void;\n}): React.ReactNode {\n const [cursor, setCursor] = useState(0);\n useInput((_input, key) => {\n if (key.escape) props.onCancel();\n if (key.upArrow) setCursor((current) => Math.max(0, current - 1));\n if (key.downArrow) setCursor((current) => Math.min(props.actions.length - 1, current + 1));\n if (key.return && props.actions[cursor]) props.actions[cursor].run();\n });\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"double\" borderColor=\"magenta\" padding={1}>\n <Text bold>\uBA85\uB839</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {props.actions.map((action, index) => (\n <Text key={action.id} color={index === cursor ? 'magentaBright' : undefined}>\n {index === cursor ? '\u203A' : ' '} {action.label}\n </Text>\n ))}\n </Box>\n <Footer text=\"\u2191\u2193 \uC774\uB3D9 \u00B7 Enter \uC2E4\uD589 \u00B7 Esc \uB2EB\uAE30\" />\n </Box>\n );\n}\n", "import type { ReactNode } from 'react';\nimport { Box, Text } from 'ink';\nimport { ImeTextInput } from './ime-text-input';\n\nexport function Header(props: {\n profile?: string;\n username?: string;\n connected?: boolean;\n}): ReactNode {\n return (\n <Box paddingX={1} justifyContent=\"space-between\">\n <Text bold color=\"blueBright\">\n XGEN Dex\n </Text>\n {props.profile ? (\n <Text>\n {props.profile} \u00B7 {props.username ?? '\uB85C\uADF8\uC778 \uD544\uC694'} \u00B7{' '}\n <Text color={props.connected ? 'green' : 'yellow'}>\n {props.connected ? 'Connected' : 'Offline'}\n </Text>\n </Text>\n ) : (\n <Text dimColor>\uC124\uC815 \uD544\uC694</Text>\n )}\n </Box>\n );\n}\n\nexport function Footer({ text, mode }: { text: string; mode?: string }): ReactNode {\n return (\n <Box paddingX={1}>\n {/* \uC9C0\uAE08 \uD55C\uAE00\uC778\uC9C0 \uC601\uBB38\uC778\uC9C0\uB294 \uC0C1\uD0DC\uBC14\uC5D0\uC11C\uB3C4 \uBCF4\uC5EC\uC57C \uD55C\uB2E4 \u2014 \uC785\uB825\uCC3D\uC5D0\uC11C \uB208\uC744 \uB5BC\uACE0\n \uC788\uB2E4\uAC00 \uBAA8\uB974\uACE0 \uCE58\uBA74 `dkssud` \uC774 \uB098\uC628\uB2E4. */}\n {mode ? (\n <Text bold color={mode === '\uD55C' ? 'yellow' : 'gray'}>\n [{mode}]{' '}\n </Text>\n ) : null}\n <Text dimColor wrap=\"truncate-end\">\n {text}\n </Text>\n </Box>\n );\n}\n\nexport function Loading({ label = '\uBD88\uB7EC\uC624\uB294 \uC911...' }: { label?: string }): ReactNode {\n return (\n <Box padding={1}>\n <Text color=\"cyan\">\u25C6 {label}</Text>\n </Box>\n );\n}\n\nexport function Notice({ children, error = false }: { children: ReactNode; error?: boolean }): ReactNode {\n return (\n <Box borderStyle=\"round\" borderColor={error ? 'red' : 'cyan'} paddingX={1}>\n <Text color={error ? 'red' : undefined}>{children}</Text>\n </Box>\n );\n}\n\nexport function FormField(props: {\n label: string;\n value: string;\n onChange: (value: string) => void;\n onSubmit?: (value: string) => void;\n focus: boolean;\n placeholder?: string;\n secret?: boolean;\n}): ReactNode {\n return (\n // \uAC00\uB85C\uB85C \uB298\uB824 \uB46C\uC57C \uC785\uB825 \uCE78\uC774 \uB0A8\uB294 \uD3ED\uC744 \uC54C \uC218 \uC788\uB2E4. \uB0B4\uC6A9\uB9CC\uD07C\uB9CC \uB113\uC73C\uBA74 \uCE78\uC758 \uD3ED\uC774\n // \uACE7 \uAE00\uC790 \uD3ED\uC774 \uB418\uC5B4, \uAE34 \uC8FC\uC18C\uAC00 \uC2A4\uC2A4\uB85C\uB97C \uC798\uB77C \uB0B4\uB294 \uAF34\uC774 \uB41C\uB2E4.\n <Box flexGrow={1}>\n <Box width={14} flexShrink={0}>\n <Text color={props.focus ? 'cyan' : undefined}>{props.focus ? '\u203A' : ' '} {props.label}</Text>\n </Box>\n <ImeTextInput\n value={props.value}\n onChange={props.onChange}\n onSubmit={props.onSubmit}\n focus={props.focus}\n placeholder={props.placeholder}\n mask={props.secret ? '\u2022' : undefined}\n />\n </Box>\n );\n}\n", "import { useEffect, useRef, useState } from 'react';\nimport { Box, Text, useCursor, useInput, useStdin } from 'ink';\nimport stringWidth from 'string-width';\nimport { useMeasured } from './measure';\nimport { classifyInput } from './terminal-input';\nimport * as hangul from './hangul';\nimport { parseKeyEvents } from './kitty';\n\ninterface ImeTextInputProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit?: (value: string) => void;\n focus: boolean;\n placeholder?: string;\n mask?: string;\n /** \uD55C\uAE00 \uC870\uD569 \uC911\uC778\uAC00. \uBAA8\uB4DC \uD45C\uC2DC\uB97C \uC606\uC5D0 \uBD99\uC774\uB294 \uCABD\uC5D0\uC11C \uC4F4\uB2E4. */\n hangulMode?: boolean;\n onHangulModeChange?: (enabled: boolean) => void;\n}\n\nconst segmenter = new Intl.Segmenter('ko', { granularity: 'grapheme' });\n\nfunction graphemes(value: string): string[] {\n return [...segmenter.segment(value)].map(({ segment }) => segment);\n}\n\nfunction clamp(value: number, minimum: number, maximum: number): number {\n return Math.min(Math.max(value, minimum), maximum);\n}\n\nfunction visibleInput(\n segments: string[],\n cursor: number,\n maximumWidth: number,\n): { text: string; cursorWidth: number } {\n let start = cursor;\n let widthBeforeCursor = 0;\n const followingWidth = cursor < segments.length ? stringWidth(segments[cursor] ?? '') : 0;\n const beforeLimit = Math.max(0, maximumWidth - Math.min(followingWidth, maximumWidth));\n\n while (start > 0) {\n const width = stringWidth(segments[start - 1] ?? '');\n if (widthBeforeCursor + width > beforeLimit) break;\n widthBeforeCursor += width;\n start -= 1;\n }\n\n let end = cursor;\n let totalWidth = widthBeforeCursor;\n while (end < segments.length) {\n const width = stringWidth(segments[end] ?? '');\n if (totalWidth + width > maximumWidth) break;\n totalWidth += width;\n end += 1;\n }\n\n return {\n text: segments.slice(start, end).join(''),\n cursorWidth: widthBeforeCursor,\n };\n}\n\nfunction TerminalCursor({ x, y }: { x: number; y: number }): null {\n const { setCursorPosition } = useCursor();\n setCursorPosition({ x, y });\n return null;\n}\n\n/**\n * \uC9C4\uC9DC \uD130\uBBF8\uB110 \uCEE4\uC11C\uB97C \uAE00\uC790 \uC790\uB9AC\uC5D0 \uB450\uB294 \uD55C \uC904 \uC785\uB825 \uCE78.\n *\n * \uD130\uBBF8\uB110 IME \uB294 \uC870\uD569 \uC911\uC778 \uD55C\uAE00\uC744 \uCEE4\uC11C \uC790\uB9AC\uC5D0 \uADF8\uB9B0\uB2E4. \uADF8\uB798\uC11C \uCEE4\uC11C\uAC00 \uC5B4\uB514\uC5D0 \uC11C\uB294\uC9C0\uAC00\n * \uACE7 \uD55C\uAE00\uC774 \uC5B4\uB514\uC5D0 \uBCF4\uC774\uB294\uC9C0\uB2E4.\n */\nexport function ImeTextInput(props: ImeTextInputProps): React.ReactNode {\n const [ref, placement] = useMeasured();\n const initialSegments = graphemes(props.value);\n const [cursor, setCursor] = useState(initialSegments.length);\n const valueRef = useRef(props.value);\n const cursorRef = useRef(initialSegments.length);\n const pastingRef = useRef(false);\n /** \uC544\uC9C1 \uC644\uC131\uB418\uC9C0 \uC54A\uC740 \uD55C\uAE00 \uD55C \uAE00\uC790. \uAC12\uC5D0\uB294 \uC774\uBBF8 \uBCF4\uC774\uC9C0\uB9CC \uB2E4\uC74C \uD0A4\uB85C \uBC14\uB014 \uC218 \uC788\uB2E4. */\n const typingRef = useRef<hangul.Typing>(hangul.IDLE);\n\n const moveCursor = (next: number, length: number): void => {\n const resolved = clamp(next, 0, length);\n cursorRef.current = resolved;\n setCursor(resolved);\n };\n\n const updateValue = (segments: string[], nextCursor: number): void => {\n const nextValue = segments.join('');\n valueRef.current = nextValue;\n moveCursor(nextCursor, segments.length);\n props.onChange(nextValue);\n };\n\n // \uD55C/\uC601 \uD0A4(\uC624\uB978\uCABD Alt \uC790\uB9AC)\uC640 Caps Lock \uC740 \uAE00\uC790\uB97C \uB9CC\uB4E4\uC9C0 \uC54A\uC544 \uBCF4\uD1B5\uC740 \uC571\uC5D0 \uC624\uC9C0\n // \uC54A\uB294\uB2E4. Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC744 \uC544\uB294 \uD130\uBBF8\uB110\uB9CC \uC774 \uC0AC\uAC74\uC744 \uBCF4\uB0B4 \uC8FC\uBBC0\uB85C, \uC6D0\uC2DC\n // \uC785\uB825\uC744 \uACC1\uC5D0\uC11C \uC9C0\uCF1C\uBCF8\uB2E4 \u2014 ink \uC740 \uC774 \uC0AC\uAC74\uB4E4\uC744 \uBE48 \uC785\uB825\uC73C\uB85C \uD758\uB824\uBCF4\uB0B8\uB2E4.\n const { stdin, isRawModeSupported } = useStdin();\n const onModeKeyRef = useRef<(() => void) | undefined>(undefined);\n onModeKeyRef.current = () => props.onHangulModeChange?.(!props.hangulMode);\n useEffect(() => {\n if (!props.focus || !isRawModeSupported) return undefined;\n const onData = (data: Buffer | string): void => {\n const chunk = typeof data === 'string' ? data : data.toString('utf8');\n for (const event of parseKeyEvents(chunk)) {\n // \uD130\uBBF8\uB110\uC774 \uC54C\uB824 \uC8FC\uBA74 \uCD94\uC815 \uB300\uC2E0 \uADF8 \uAC12\uC744 \uBBFF\uB294\uB2E4.\n typingRef.current = { ...typingRef.current, capsLock: event.capsLock };\n // \uB5C4 \uB54C\uAC00 \uC544\uB2C8\uB77C \uB204\uB97C \uB54C \uD55C \uBC88\uB9CC \uBC14\uAFBC\uB2E4.\n if (event.eventType !== 1) continue;\n if (event.name === 'rightalt' || event.name === 'capslock') onModeKeyRef.current?.();\n }\n };\n stdin?.on('data', onData);\n return () => void stdin?.off('data', onData);\n }, [props.focus, isRawModeSupported, stdin]);\n\n // \uD3EC\uCEE4\uC2A4\uB97C \uC783\uAC70\uB098 \uD55C\uAE00 \uBAA8\uB4DC\uB97C \uB044\uBA74 \uC870\uD569\uC744 \uB05D\uB0B8\uB2E4. \uB0A8\uACA8 \uB450\uBA74 \uB2E4\uC74C\uC5D0 \uB3CC\uC544\uC654\uC744 \uB54C\n // \uC5C9\uB6B1\uD55C \uAE00\uC790\uC5D0 \uC774\uC5B4 \uBD99\uB294\uB2E4.\n useEffect(() => {\n // Caps Lock \uD310\uB2E8\uC740 \uB0A8\uACA8 \uB454\uB2E4 \u2014 \uBAA8\uB4DC\uB97C \uAED0\uB2E4 \uCF20\uB2E4\uACE0 \uC790\uD310\uC774 \uBC14\uB00C\uC9C0\uB294 \uC54A\uB294\uB2E4.\n if (!props.focus || !props.hangulMode) {\n typingRef.current = { ...hangul.IDLE, capsLock: typingRef.current.capsLock };\n }\n }, [props.focus, props.hangulMode]);\n\n useEffect(() => {\n if (props.value === valueRef.current) return;\n const previousLength = graphemes(valueRef.current).length;\n const nextLength = graphemes(props.value).length;\n const wasAtEnd = cursorRef.current >= previousLength;\n valueRef.current = props.value;\n moveCursor(wasAtEnd ? nextLength : cursorRef.current, nextLength);\n }, [props.value]);\n\n /**\n * \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB97C \uAC12\uC5D0 **\uADF8\uB300\uB85C \uBC18\uC601**\uD55C\uB2E4.\n *\n * \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB294 \uAC12\uC758 \uCEE4\uC11C \uBC14\uB85C \uC55E \uD55C \uAE00\uC790\uB97C \uCC28\uC9C0\uD55C\uB2E4. \uD0A4\uAC00 \uC62C \uB54C\uB9C8\uB2E4 \uADF8 \uC790\uB9AC\uB97C\n * \uC0C8 \uBAA8\uC2B5\uC73C\uB85C \uAC08\uC544 \uB07C\uC6B0\uBBC0\uB85C, \uC0AC\uC6A9\uC790\uB294 `\u3131 \u2192 \uAC00 \u2192 \uAC04` \uC774 \uC790\uB77C\uB098\uB294 \uAC83\uC744 \uADF8\uB300\uB85C \uBCF8\uB2E4.\n * \uAC12\uC774 \uACE7 \uD654\uBA74\uC774\uB77C \uB530\uB85C \uADF8\uB9B4 \uAC83\uC774 \uC5C6\uACE0, \uC804\uC1A1\uD558\uBA74 \uBCF4\uC774\uB358 \uADF8\uB300\uB85C \uB098\uAC04\uB2E4.\n */\n const applyComposition = (\n segments: string[],\n cursor: number,\n previous: string,\n commit: string,\n next: string,\n ): void => {\n const removed = previous ? 1 : 0;\n const inserted = graphemes(commit + next);\n segments.splice(cursor - removed, removed, ...inserted);\n updateValue(segments, cursor - removed + inserted.length);\n };\n\n useInput(\n (input, key) => {\n const current = graphemes(valueRef.current);\n const currentCursor = clamp(cursorRef.current, 0, current.length);\n const event = classifyInput(input, pastingRef.current);\n const shown = hangul.display(typingRef.current.state);\n\n /** \uC870\uD569\uC744 \uB05D\uB0B8\uB2E4. \uCEE4\uC11C\uB97C \uC62E\uAE30\uAC70\uB098 \uC804\uC1A1\uD558\uAE30 \uC804\uC5D0 \uBD80\uB978\uB2E4. */\n const settle = (): void => {\n typingRef.current = { ...hangul.IDLE, capsLock: typingRef.current.capsLock };\n };\n\n if (event.kind === 'paste-start') {\n settle();\n pastingRef.current = true;\n return;\n }\n if (event.kind === 'paste-end') {\n pastingRef.current = false;\n return;\n }\n\n // \uBD99\uC5EC\uB123\uB294 \uB3D9\uC548\uC740 \uD0A4\uB85C \uC77D\uC9C0 \uC54A\uB294\uB2E4. \uBD99\uC778 \uB0B4\uC6A9 \uC548\uC758 \uC904\uBC14\uAFC8\uC774 \"\uC804\uC1A1\" \uC73C\uB85C\n // \uC77D\uD788\uBA74 \uBC18\uCABD\uC9DC\uB9AC \uBA54\uC2DC\uC9C0\uAC00 \uB098\uAC00 \uBC84\uB9B0\uB2E4.\n if (pastingRef.current) {\n if (event.kind === 'text') {\n const inserted = graphemes(event.text);\n current.splice(currentCursor, 0, ...inserted);\n updateValue(current, currentCursor + inserted.length);\n }\n return;\n }\n\n // Ctrl+Space \uB85C \uD55C/\uC601\uC744 \uBC14\uAFBC\uB2E4 \u2014 ibus\u00B7fcitx \uB97C \uC4F0\uB358 \uC190\uC774 \uC774\uBBF8 \uC544\uB294 \uC790\uB9AC\uB2E4.\n // (ink \uC740 Ctrl+Space \uB97C ctrl + '`' \uB85C \uC900\uB2E4.) Ctrl+L \uB3C4 \uBC1B\uB294\uB2E4: \uD130\uBBF8\uB110\uC774\uB098\n // tmux \uAC00 Ctrl+Space \uB97C \uBA3C\uC800 \uCC44\uAC00\uB294 \uACBD\uC6B0\uAC00 \uC788\uB2E4.\n // Alt+Space \uB3C4 \uBC1B\uB294\uB2E4. \uD55C\uAD6D\uC5B4 \uC790\uD310\uC758 \uD55C/\uC601 \uD0A4\uB294 \uC624\uB978\uCABD Alt \uC790\uB9AC\uC5D0 \uC788\uC5B4\uC11C,\n // \uADF8 \uD0A4\uAC00 Alt \uB85C \uB3C4\uCC29\uD558\uB294 \uD658\uACBD\uC5D0\uC11C\uB294 \uC624\uB978\uC190 \uC5C4\uC9C0\uB85C \uADF8\uB300\uB85C \uB2FF\uB294\uB2E4.\n if ((key.ctrl && (input === '`' || input === 'l')) || (key.meta && input === ' ')) {\n settle();\n props.onHangulModeChange?.(!props.hangulMode);\n return;\n }\n\n if (key.return) {\n settle();\n props.onSubmit?.(valueRef.current);\n return;\n }\n if (key.leftArrow) {\n settle();\n moveCursor(currentCursor - 1, current.length);\n return;\n }\n if (key.rightArrow) {\n settle();\n moveCursor(currentCursor + 1, current.length);\n return;\n }\n if (key.home) {\n settle();\n moveCursor(0, current.length);\n return;\n }\n if (key.end) {\n settle();\n moveCursor(current.length, current.length);\n return;\n }\n if (key.backspace || key.delete) {\n // \uC870\uD569 \uC911\uC774\uBA74 \uAE00\uC790\uB97C \uB418\uC9DA\uB294\uB2E4: `\uD55C` \u2192 `\uD558` \u2192 `\u314E`. \uD1B5\uC9F8\uB85C \uC9C0\uC6B0\uBA74 \uC624\uD0C0\n // \uD558\uB098\uC5D0 \uCC98\uC74C\uBD80\uD130 \uB2E4\uC2DC \uCCD0\uC57C \uD55C\uB2E4.\n const stepped = hangul.backspace(typingRef.current);\n if (stepped.handled) {\n typingRef.current = stepped.session;\n applyComposition(current, currentCursor, shown, '', stepped.composing);\n return;\n }\n if (currentCursor === 0) return;\n current.splice(currentCursor - 1, 1);\n updateValue(current, currentCursor - 1);\n return;\n }\n if (\n key.ctrl ||\n key.meta ||\n key.tab ||\n key.escape ||\n key.upArrow ||\n key.downArrow ||\n key.pageUp ||\n key.pageDown\n ) {\n settle();\n return;\n }\n if (event.kind !== 'text') return;\n\n if (props.hangulMode) {\n // \uD55C \uBC88\uC5D0 \uC5EC\uB7EC \uAE00\uC790\uAC00 \uC624\uB294 \uAC83(\uBE60\uB978 \uC785\uB825)\uB3C4 \uC21C\uC11C\uB300\uB85C \uBA39\uC778\uB2E4.\n let session = typingRef.current;\n let previous = shown;\n let segments = current;\n let cursor = currentCursor;\n for (const character of event.text) {\n const result = hangul.typeKey(session, character);\n session = result.session;\n applyComposition(segments, cursor, previous, result.commit, result.composing);\n segments = graphemes(valueRef.current);\n cursor = cursorRef.current;\n previous = result.composing;\n }\n typingRef.current = session;\n return;\n }\n\n settle();\n const inserted = graphemes(event.text);\n current.splice(currentCursor, 0, ...inserted);\n updateValue(current, currentCursor + inserted.length);\n },\n { isActive: props.focus },\n );\n\n const rawSegments = graphemes(props.value);\n const safeCursor = clamp(cursor, 0, rawSegments.length);\n const displayedSegments = props.mask ? rawSegments.map(() => props.mask ?? '') : rawSegments;\n // \uC870\uD569 \uC911\uC778 \uAE00\uC790\uAC00 \uC124 \uC790\uB9AC \uD55C \uCE78\uC744 \uB0A8\uAE34\uB2E4.\n const maximumWidth = Math.max(1, (placement?.width ?? 40) - 1);\n const visible = visibleInput(displayedSegments, safeCursor, maximumWidth);\n\n return (\n <Box ref={ref} flexGrow={1}>\n {rawSegments.length === 0 ? (\n <Text dimColor>{props.placeholder ?? ''}</Text>\n ) : (\n <Text>{visible.text}</Text>\n )}\n {props.focus && placement ? (\n <TerminalCursor x={placement.x + visible.cursorWidth} y={placement.y} />\n ) : null}\n </Box>\n );\n}\n", "/**\n * \uD130\uBBF8\uB110\uC774 \uBCF4\uB0B4\uC624\uB294 \uBC14\uC774\uD2B8 \uC911 **\uBB34\uC5C7\uC774 \uC0AC\uB78C\uC774 \uCE5C \uAE00\uC790\uC778\uAC00** \uB97C \uAC00\uB978\uB2E4.\n *\n * \uD130\uBBF8\uB110\uC740 \uD0A4 \uC785\uB825\uB9CC \uBCF4\uB0B4\uC9C0 \uC54A\uB294\uB2E4. \uCC3D \uD3EC\uCEE4\uC2A4\uAC00 \uBC14\uB00C\uBA74 `ESC[I`/`ESC[O` \uB97C,\n * \uB9C8\uC6B0\uC2A4\uB97C \uC6C0\uC9C1\uC774\uBA74 `ESC[<0;1;1M` \uC744, \uD06C\uAE30\u00B7\uC7A5\uCE58\uB97C \uBB3C\uC5B4\uBCF8 \uC801\uC774 \uC788\uC73C\uBA74 `ESC[1;2R`\u00B7\n * `ESC[?1;2c` \uB97C, \uBD99\uC5EC\uB123\uAE30\uC5D0\uB294 `ESC[200~` ... `ESC[201~` \uB85C \uAC10\uC2F8\uC11C \uBCF4\uB0B8\uB2E4. \uC774\uAC83\uB4E4\uC740\n * \uC0AC\uC6A9\uC790\uAC00 \uCE5C \uC801 \uC5C6\uB294 \uC785\uB825\uC774\uACE0, \uC55E\uC758 ESC \uD55C \uAE00\uC790\uB294 ink \uC774 \uB5BC\uC5B4 \uB0B8 \uB4A4 \uC6B0\uB9AC\uC5D0\uAC8C\n * \uC628\uB2E4. \uADF8\uB300\uB85C \uBC1B\uC544 \uB123\uC73C\uBA74 \uBA54\uC2DC\uC9C0 \uCE78\uC5D0 `[200~`\u00B7`[I`\u00B7`[<0;1;1M` \uAC19\uC740 \uAC83\uC774 \uD0C0\uC774\uD551\uB41C\uB2E4.\n *\n * \uD55C\uAE00\uC5D0\uC11C \uD2B9\uD788 \uC544\uD504\uB2E4. IME \uD6C4\uBCF4\uCC3D\uC774 \uB728\uACE0 \uB2EB\uD790 \uB54C\uB9C8\uB2E4 \uD130\uBBF8\uB110 \uD3EC\uCEE4\uC2A4\uAC00 \uC624\uAC00\uBA74\uC11C\n * `[I`/`[O` \uAC00 \uAE00\uC790 \uC0AC\uC774\uC5D0 \uBC15\uD788\uACE0, \uCEE4\uBC0B\uB41C \uAE00\uC790\uAC00 \uBD99\uC5EC\uB123\uAE30\uB85C \uC624\uBA74 `[200~` \uC774 \uC55E\uC5D0\n * \uBD99\uB294\uB2E4. \uC0AC\uC6A9\uC790\uC5D0\uAC8C\uB294 \"\uD55C\uAE00\uC774 \uC785\uB825\uB418\uC9C0 \uC54A\uB294\uB2E4\" \uB85C \uBCF4\uC778\uB2E4.\n *\n * \uADF8\uB798\uC11C \uB450 \uACB9\uC73C\uB85C \uB9C9\uB294\uB2E4. \uD130\uBBF8\uB110\uC5D0\uAC8C \uC774\uB7F0 \uBCF4\uACE0\uB97C \uC544\uC608 \uBCF4\uB0B4\uC9C0 \uB9D0\uB77C\uACE0 \uD558\uACE0\n * ([screen.ts] \uCC38\uACE0), \uADF8\uB798\uB3C4 \uC624\uB294 \uAC83\uC740 \uC5EC\uAE30\uC11C \uAC78\uB7EC \uB0B8\uB2E4 \u2014 \uBAA8\uB4DC\uB294 \uC55E\uC11C \uC2E4\uD589\uB41C\n * \uD504\uB85C\uADF8\uB7A8\uC774 \uCF1C \uB450\uACE0 \uB044\uC9C0 \uC54A\uC740 \uCC44 \uB0A8\uC544 \uC788\uC744 \uC218 \uC788\uB2E4.\n */\n\nexport type InputEvent =\n /** \uC0AC\uB78C\uC774 \uCE5C \uAE00\uC790. \uADF8\uB300\uB85C \uB123\uB294\uB2E4. */\n | { kind: 'text'; text: string }\n /** \uBD99\uC5EC\uB123\uAE30 \uC2DC\uC791 \u2014 \uC5EC\uAE30\uC11C\uBD80\uD130 \uC624\uB294 \uAC83\uC740 \uD0A4\uAC00 \uC544\uB2C8\uB77C \uB0B4\uC6A9\uC774\uB2E4. */\n | { kind: 'paste-start' }\n | { kind: 'paste-end' }\n /** \uD130\uBBF8\uB110\uC774 \uBCF4\uB0B8 \uBCF4\uACE0. \uC0AC\uC6A9\uC790\uAC00 \uCE5C \uAC83\uC774 \uC544\uB2C8\uB2E4. */\n | { kind: 'ignore' };\n\nconst PASTE_START = '[200~';\nconst PASTE_END = '[201~';\n\n/**\n * ESC \uAC00 \uB5A8\uC5B4\uC838 \uB098\uAC04 \uC81C\uC5B4 \uC2DC\uD000\uC2A4\uC758 \uAF2C\uB9AC.\n *\n * CSI \uB294 `[` + \uB9E4\uAC1C\uBCC0\uC218 + \uB9C8\uC9C0\uB9C9 \uBC14\uC774\uD2B8, SS3 \uB294 `O` + \uB9C8\uC9C0\uB9C9 \uBC14\uC774\uD2B8\uB2E4. \uC0AC\uB78C\uC774 \uCE5C\n * `[` \uB098 `O` \uB294 **\uD55C \uAE00\uC790\uC9DC\uB9AC \uC774\uBCA4\uD2B8 \uD558\uB098**\uB85C \uC624\uBBC0\uB85C \uC774 \uADDC\uCE59\uC5D0 \uAC78\uB9AC\uC9C0 \uC54A\uB294\uB2E4 \u2014\n * \uB450 \uAE00\uC790 \uC774\uC0C1\uC774 \uD55C \uBC88\uC5D0 \uC624\uBA74\uC11C \uC774 \uBAA8\uC591\uC774\uBA74 \uD130\uBBF8\uB110\uC774 \uBCF4\uB0B8 \uAC83\uC774\uB2E4.\n */\nconst CONTROL_TAIL = /^(?:\\[[\\d;:<>?!\"'$ ]*[@-~]|O[@-~])$/;\n\n/** \uD654\uBA74\uC5D0 \uADF8\uB824\uC9C0\uC9C0 \uC54A\uB294 C0 \uC81C\uC5B4\uBB38\uC790\uC640 DEL. \uAC12\uC5D0 \uB4E4\uC5B4\uAC00\uBA74 \uBCF4\uC774\uC9C0 \uC54A\uB294 \uC4F0\uB808\uAE30\uAC00 \uB41C\uB2E4. */\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHARS = /[\\u0000-\\u001F\\u007F]/g;\n\n/**\n * \uD55C \uBC88\uC758 \uC785\uB825 \uC774\uBCA4\uD2B8\uB97C \uAC08\uB798\uB0B8\uB2E4.\n *\n * `pasting` \uC774 \uCC38\uC774\uBA74 \uB0B4\uC6A9\uC744 \uAE00\uC790\uB85C\uB9CC \uBCF8\uB2E4 \u2014 \uBD99\uC5EC\uB123\uAE30 \uC548\uC758 `\\r` \uC740 \"\uC804\uC1A1\" \uC774 \uC544\uB2C8\uACE0,\n * `[` \uB85C \uC2DC\uC791\uD558\uB294 \uC904\uB3C4 \uC81C\uC5B4 \uC2DC\uD000\uC2A4\uAC00 \uC544\uB2C8\uB2E4.\n */\nexport function classifyInput(input: string, pasting = false): InputEvent {\n if (input === PASTE_START) return { kind: 'paste-start' };\n if (input === PASTE_END) return { kind: 'paste-end' };\n if (!pasting && input.length > 1 && CONTROL_TAIL.test(input)) return { kind: 'ignore' };\n\n // \uC5EC\uB7EC \uC904 \uBD99\uC5EC\uB123\uAE30\uB294 \uD55C \uC904 \uC785\uB825 \uCE78\uC5D0 \uB9DE\uAC8C \uACF5\uBC31\uC73C\uB85C \uB215\uD78C\uB2E4. \uC904\uBC14\uAFC8\uC744 \uB0A8\uAE30\uBA74\n // \uB80C\uB354\uAC00 \uAE68\uC9C0\uACE0, \uBC84\uB9AC\uBA74 \uB2E8\uC5B4\uAC00 \uBD99\uC5B4 \uBC84\uB9B0\uB2E4.\n const flattened = input.replace(/\\r\\n|[\\r\\n]/g, ' ');\n const text = flattened.replace(CONTROL_CHARS, '');\n return text ? { kind: 'text', text } : { kind: 'ignore' };\n}\n", "/**\n * \uB450\uBC8C\uC2DD \uD55C\uAE00 \uC870\uD569\uAE30.\n *\n * \uC608\uC804\uC5D0\uB294 \uD130\uBBF8\uB110\uC758 IME \uC5D0 \uB9E1\uACBC\uB2E4 \u2014 \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB294 \uD130\uBBF8\uB110\uC774 \uCEE4\uC11C \uC790\uB9AC\uC5D0 \uADF8\uB9AC\uACE0,\n * \uC644\uC131\uB41C \uAE00\uC790\uB9CC \uC6B0\uB9AC\uC5D0\uAC8C \uC654\uB2E4. \uC798 \uB418\uB294 \uC870\uD569\uB3C4 \uC788\uC9C0\uB9CC **\uD130\uBBF8\uB110\uB9C8\uB2E4 \uB2E4\uB974\uACE0**, SSH \uB098\n * tmux \uB97C \uAC70\uCE58\uBA74 \uC544\uC608 \uC548 \uC624\uB294 \uACBD\uC6B0\uAC00 \uD754\uD558\uB2E4. \uC6B0\uB9AC \uCABD\uC5D0\uC11C\uB294 \uACE0\uCE60 \uC218\uAC00 \uC5C6\uB294 \uC790\uB9AC\uB2E4.\n *\n * \uADF8\uB798\uC11C \uC870\uD569\uC744 \uC5EC\uAE30\uC11C \uD55C\uB2E4. `r k s` \uB77C\uB294 \uC138 \uBC88\uC758 \uD0A4 \uC785\uB825\uC744 `\u3131 \u2192 \uAC00 \u2192 \uAC04` \uC73C\uB85C\n * \uB9CC\uB4DC\uB294 \uC77C\uC774\uB2E4. \uD130\uBBF8\uB110\uC774 \uBB34\uC5C7\uC744 \uD558\uB4E0, SSH \uB108\uBA38\uB4E0, \uD55C\uAE00\uC774 \uAC19\uC740 \uBC29\uC2DD\uC73C\uB85C \uB4E4\uC5B4\uAC04\uB2E4.\n *\n * \uC790\uD310\uC740 \uD45C\uC900 \uB450\uBC8C\uC2DD\uC774\uB2E4. \uACB9\uBC1B\uCE68\uC774 \uAC08\uB77C\uC9C0\uB294 \uC790\uB9AC(`\uAC04` + `\u314F` \u2192 `\uAC00` + `\uB098`)\uC640\n * \uBC31\uC2A4\uD398\uC774\uC2A4\uAC00 \uAE00\uC790\uB97C \uB418\uC9DA\uB294 \uC790\uB9AC(`\uD55C` \u2192 `\uD558` \u2192 `\u314E`)\uAC00 \uC774 \uD30C\uC77C\uC758 \uD575\uC2EC\uC774\uB2E4.\n */\n\n/** \uCD08\uC131 19\uC790. \uC778\uB371\uC2A4\uAC00 \uC720\uB2C8\uCF54\uB4DC \uACC4\uC0B0\uC5D0 \uADF8\uB300\uB85C \uC4F0\uC778\uB2E4. */\nconst CHO = '\u3131\u3132\u3134\u3137\u3138\u3139\u3141\u3142\u3143\u3145\u3146\u3147\u3148\u3149\u314A\u314B\u314C\u314D\u314E';\n/** \uC911\uC131 21\uC790. */\nconst JUNG = '\u314F\u3150\u3151\u3152\u3153\u3154\u3155\u3156\u3157\u3158\u3159\u315A\u315B\u315C\u315D\u315E\u315F\u3160\u3161\u3162\u3163';\n/** \uC885\uC131 28\uC790. 0\uBC88\uC740 \uBC1B\uCE68 \uC5C6\uC74C\uC774\uB77C \uC790\uB9AC\uB97C \uBE44\uC6CC \uB454\uB2E4. */\nconst JONG = ' \u3131\u3132\u3133\u3134\u3135\u3136\u3137\u3139\u313A\u313B\u313C\u313D\u313E\u313F\u3140\u3141\u3142\u3144\u3145\u3146\u3147\u3148\u314A\u314B\u314C\u314D\u314E';\n\nconst SYLLABLE_BASE = 0xac00;\n\n/**\n * \uB450\uBC8C\uC2DD \uC790\uD310. \uD45C\uC900\uB300\uB85C **\uC790\uC74C 19 + \uBAA8\uC74C 21** \uC774 \uC544\uB2C8\uB77C, \uD0A4\uB97C \uB20C\uB7EC \uB098\uC624\uB294 \uB0B1\uC790\uB9CC\n * \uC801\uB294\uB2E4 \u2014 \u3132\u3138\u3143\u3146\u3149\u3152\u3156 \uB294 \uC2DC\uD504\uD2B8\uB85C, \uB098\uBA38\uC9C0 \uB300\uBB38\uC790\uB294 \uC18C\uBB38\uC790\uC640 \uAC19\uC740 \uB0B1\uC790\uB2E4.\n */\nconst KEYS: Record<string, string> = {\n r: '\u3131', R: '\u3132', s: '\u3134', e: '\u3137', E: '\u3138', f: '\u3139', a: '\u3141', q: '\u3142', Q: '\u3143',\n t: '\u3145', T: '\u3146', d: '\u3147', w: '\u3148', W: '\u3149', c: '\u314A', z: '\u314B', x: '\u314C', v: '\u314D', g: '\u314E',\n k: '\u314F', o: '\u3150', i: '\u3151', O: '\u3152', j: '\u3153', p: '\u3154', u: '\u3155', P: '\u3156',\n h: '\u3157', y: '\u315B', n: '\u315C', b: '\u3160', m: '\u3161', l: '\u3163',\n};\n\n/** \uBAA8\uC74C \uB450 \uAC1C\uAC00 \uD558\uB098\uB85C \uD569\uCCD0\uC9C0\uB294 \uC790\uB9AC. */\nconst VOWEL_PAIRS: Record<string, string> = {\n '\u3157\u314F': '\u3158', '\u3157\u3150': '\u3159', '\u3157\u3163': '\u315A',\n '\u315C\u3153': '\u315D', '\u315C\u3154': '\u315E', '\u315C\u3163': '\u315F',\n '\u3161\u3163': '\u3162',\n};\n\n/** \uACB9\uBC1B\uCE68. */\nconst FINAL_PAIRS: Record<string, string> = {\n '\u3131\u3145': '\u3133',\n '\u3134\u3148': '\u3135', '\u3134\u314E': '\u3136',\n '\u3139\u3131': '\u313A', '\u3139\u3141': '\u313B', '\u3139\u3142': '\u313C', '\u3139\u3145': '\u313D', '\u3139\u314C': '\u313E', '\u3139\u314D': '\u313F', '\u3139\u314E': '\u3140',\n '\u3142\u3145': '\u3144',\n};\n\n/** \uD569\uCCD0\uC9C4 \uB0B1\uC790\uB97C \uB3C4\uB85C \uB458\uB85C \uAC00\uB978\uB2E4. \uAC08\uB77C\uC9C0\uB294 \uC790\uB9AC\uC5D0\uC11C \uC4F4\uB2E4. */\nconst SPLIT: Record<string, [string, string]> = Object.fromEntries(\n [...Object.entries(VOWEL_PAIRS), ...Object.entries(FINAL_PAIRS)].map(([pair, joined]) => [\n joined,\n [pair[0]!, pair[1]!] as [string, string],\n ]),\n);\n\n/**\n * \uC870\uD569 \uC911\uC778 \uAE00\uC790 \uD558\uB098.\n *\n * \uC544\uC9C1 \uC644\uC131\uB418\uC9C0 \uC54A\uC558\uC73C\uBBC0\uB85C \uAC12\uC5D0 \uB123\uC9C0 \uC54A\uACE0 \uB530\uB85C \uB4E4\uACE0 \uC788\uB294\uB2E4 \u2014 \uB2E4\uC74C \uD0A4\uAC00 \uBB34\uC5C7\uC774\uB0D0\uC5D0\n * \uB530\uB77C `\uAC00` \uAC00 `\uAC01` \uC774 \uB420 \uC218\uB3C4, `\uAC00` \uB85C \uB05D\uB098\uACE0 \uC0C8 \uAE00\uC790\uAC00 \uC2DC\uC791\uB420 \uC218\uB3C4 \uC788\uB2E4.\n */\nexport interface Composition {\n cho?: string;\n jung?: string;\n jong?: string;\n}\n\nexport const EMPTY: Composition = {};\n\n/**\n * \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uC57C \uB73B\uC774 \uB2EC\uB77C\uC9C0\uB294 \uD0A4\uB4E4 \u2014 \uB41C\uC18C\uB9AC\uC640 \u3152\u3156.\n *\n * \uB098\uBA38\uC9C0 \uAE00\uC1E0\uB294 \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uB3C4 \uAC19\uC740 \uB0B1\uC790\uB2E4. \uADF8\uB798\uC11C \uADF8\uB7F0 \uAE00\uC1E0\uC5D0 \uC2DC\uD504\uD2B8\uAC00 \uAC78\uB824\n * \uC788\uB2E4\uB294 \uAC83\uC740 **Caps Lock \uC774 \uCF1C\uC838 \uC788\uB2E4\uB294 \uB73B**\uC774\uB2E4 (\uC544\uBB34 \uC774\uB4DD\uB3C4 \uC5C6\uB294 \uC2DC\uD504\uD2B8\uB97C \uC77C\uBD80\uB7EC\n * \uB204\uB97C \uC774\uC720\uAC00 \uC5C6\uB2E4). \uC774 \uC131\uC9C8\uC744 Caps Lock \uD310\uB2E8\uC5D0 \uC4F4\uB2E4.\n */\nconst SHIFTED_KEYS = new Set(['r', 'e', 'q', 't', 'w', 'o', 'p']);\n\n/**\n * \uC774 \uD0A4\uAC00 \uD55C\uAE00 \uB0B1\uC790\uC778\uAC00. \uC544\uB2C8\uBA74 \uC870\uD569\uAE30\uB97C \uAC70\uCE58\uC9C0 \uC54A\uACE0 \uADF8\uB300\uB85C \uB4E4\uC5B4\uAC04\uB2E4.\n *\n * `capsLock` \uC774 \uCC38\uC774\uBA74 \uB300\uC18C\uBB38\uC790\uB97C \uB4A4\uC9D1\uC5B4 \uBCF8\uB2E4. Caps Lock \uC774 \uCF1C\uC838 \uC788\uC73C\uBA74 \uADF8\uB0E5 \uB204\uB978\n * \uAE00\uC1E0\uAC00 \uB300\uBB38\uC790\uB85C \uC624\uACE0, \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uC57C \uC18C\uBB38\uC790\uAC00 \uC628\uB2E4 \u2014 \uB4A4\uC9D1\uC9C0 \uC54A\uC73C\uBA74 `\uC548\uB155` \uC744\n * \uCE58\uB824\uB2E4 `\u3143\u3151\u3138\u3138` \uAC19\uC740 \uAC83\uC774 \uB098\uC628\uB2E4.\n */\nexport function jamoOf(key: string, capsLock = false): string | undefined {\n const effective = capsLock ? swapCase(key) : key;\n if (KEYS[effective]) return KEYS[effective];\n // \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uB3C4 \uAC19\uC740 \uB0B1\uC790\uC778 \uB300\uBB38\uC790\uB4E4 \u2014 \uC2E4\uC81C IME \uC640 \uAC19\uAC8C \uC18C\uBB38\uC790\uB85C \uBCF8\uB2E4.\n const lower = effective.toLowerCase();\n return lower === effective ? undefined : KEYS[lower];\n}\n\nfunction swapCase(key: string): string {\n const lower = key.toLowerCase();\n return key === lower ? key.toUpperCase() : lower;\n}\n\n/**\n * \uAE00\uC790 \uD558\uB098\uB97C \uBCF4\uACE0 Caps Lock \uC774 \uCF1C\uC838 \uC788\uB294\uC9C0 \uACE0\uCCD0 \uC7A1\uB294\uB2E4.\n *\n * \uD130\uBBF8\uB110\uC740 Caps Lock \uC0C1\uD0DC\uB97C \uC54C\uB824 \uC8FC\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC6B0\uB9AC\uC5D0\uAC8C \uC624\uB294 \uAC83\uC740 \uACB0\uACFC \uAE00\uC790\uBFD0\uC774\uB77C\n * `R` \uC774 Shift+r \uC778\uC9C0 Caps+r \uC778\uC9C0 \uAD6C\uBCC4\uD560 \uC218 \uC5C6\uB2E4. \uB300\uC2E0 **\uB73B \uC5C6\uB294 \uC2DC\uD504\uD2B8**\uB97C \uC2E0\uD638\uB85C\n * \uC4F4\uB2E4: `\u3141` \uC790\uB9AC(a)\uC5D0 \uC2DC\uD504\uD2B8\uB97C \uB20C\uB7EC\uB3C4 `\u3141` \uC774\uBBC0\uB85C, \uB300\uBB38\uC790 `A` \uAC00 \uC654\uB2E4\uBA74 \uC0AC\uB78C\uC774\n * \uC77C\uBD80\uB7EC \uB204\uB978 \uAC83\uC774 \uC544\uB2C8\uB77C Caps Lock \uC774 \uCF1C\uC838 \uC788\uB294 \uAC83\uC774\uB2E4. \uBC18\uB300\uCABD\uB3C4 \uAC19\uB2E4 \u2014 Caps \uAC00\n * \uCF1C\uC9C4 \uC0C1\uD0DC\uC5D0\uC11C \uC18C\uBB38\uC790 `a` \uAC00 \uC654\uB2E4\uBA74 \uADF8\uB54C\uB9CC \uC2DC\uD504\uD2B8\uB97C \uB5C0 \uC148\uC774\uB2C8 Caps \uAC00 \uAEBC\uC9C4 \uAC83\uC774\uB2E4.\n *\n * \uB41C\uC18C\uB9AC \uAE00\uC1E0(r\u318De\u318Dq\u318Dt\u318Dw\u318Do\u318Dp)\uB294 \uC2DC\uD504\uD2B8\uC5D0 \uB73B\uC774 \uC788\uC73C\uBBC0\uB85C \uD310\uB2E8\uC5D0 \uC4F0\uC9C0 \uC54A\uB294\uB2E4.\n */\nexport function detectCapsLock(current: boolean, key: string): boolean {\n const lower = key.toLowerCase();\n const upper = key.toUpperCase();\n if (lower === upper) return current; // \uAE00\uC790\uAC00 \uC544\uB2C8\uBA74 \uC544\uBB34\uAC83\uB3C4 \uB9D0\uD574 \uC8FC\uC9C0 \uC54A\uB294\uB2E4\n if (!KEYS[lower]) return current; // \uD55C\uAE00 \uC790\uD310 \uBC16\uC758 \uAE00\uC1E0\n if (SHIFTED_KEYS.has(lower)) return current; // \uC2DC\uD504\uD2B8\uC5D0 \uB73B\uC774 \uC788\uB294 \uAE00\uC1E0\n return key === upper;\n}\n\nfunction isVowel(jamo: string): boolean {\n return JUNG.includes(jamo) || jamo === '\u3157' || jamo === '\u315C' || jamo === '\u3161';\n}\n\n/** \uBC1B\uCE68\uC73C\uB85C \uC124 \uC218 \uC788\uB294 \uC790\uC74C\uC778\uAC00. \u3138\u3143\u3149 \uC740 \uBABB \uC120\uB2E4. */\nfunction canBeFinal(jamo: string): boolean {\n return JONG.indexOf(jamo) > 0;\n}\n\n/** \uC870\uD569 \uC911\uC778 \uC0C1\uD0DC\uB97C \uB208\uC5D0 \uBCF4\uC774\uB294 \uAE00\uC790\uB85C. \uC544\uC9C1 \uC544\uBB34\uAC83\uB3C4 \uC5C6\uC73C\uBA74 \uBE48 \uBB38\uC790\uC5F4. */\nexport function display(state: Composition): string {\n const { cho, jung, jong } = state;\n if (cho && jung) {\n const l = CHO.indexOf(cho);\n const v = JUNG.indexOf(jung);\n const t = jong ? JONG.indexOf(jong) : 0;\n if (l >= 0 && v >= 0 && t >= 0) {\n return String.fromCharCode(SYLLABLE_BASE + (l * 21 + v) * 28 + t);\n }\n }\n // \uC544\uC9C1 \uD55C \uB0B1\uC790\uBFD0\uC774\uBA74 \uADF8 \uB0B1\uC790\uB97C \uADF8\uB300\uB85C \uBCF4\uC5EC \uC900\uB2E4 \u2014 `\u3131` \uC744 \uB204\uB978 \uC21C\uAC04\uBD80\uD130 \uBCF4\uC5EC\uC57C\n // \uBB34\uC5C7\uC774 \uB4E4\uC5B4\uAC00\uACE0 \uC788\uB294\uC9C0 \uC54C \uC218 \uC788\uB2E4.\n return cho ?? jung ?? '';\n}\n\nexport interface FeedResult {\n /** \uD655\uC815\uB418\uC5B4 \uAC12\uC5D0 \uB4E4\uC5B4\uAC08 \uAE00\uC790. \uC5C6\uC744 \uC218\uB3C4, \uD55C \uAE00\uC790\uC77C \uC218\uB3C4 \uC788\uB2E4. */\n commit: string;\n /** \uC544\uC9C1 \uC870\uD569 \uC911\uC778 \uC0C1\uD0DC. */\n state: Composition;\n}\n\n/**\n * \uB0B1\uC790 \uD558\uB098\uB97C \uB123\uB294\uB2E4.\n *\n * \uB3CC\uB824\uC8FC\uB294 `commit` \uC740 **\uC774\uBC88\uC5D0 \uD655\uC815\uB41C** \uAE00\uC790\uB2E4. \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB294 `state` \uC5D0 \uB0A8\uC544\n * \uB2E4\uC74C \uD0A4\uB97C \uAE30\uB2E4\uB9B0\uB2E4.\n */\nexport function feed(state: Composition, jamo: string): FeedResult {\n const { cho, jung, jong } = state;\n\n if (isVowel(jamo)) {\n // \uBC1B\uCE68\uC774 \uC788\uB294\uB370 \uBAA8\uC74C\uC774 \uC624\uBA74 \uADF8 \uBC1B\uCE68\uC740 \uC774 \uAE00\uC790\uC758 \uAC83\uC774 \uC544\uB2C8\uC5C8\uB2E4. \uC55E \uAE00\uC790\uC5D0\uC11C\n // \uB5BC\uC5B4 \uB0B4 \uC0C8 \uAE00\uC790\uC758 \uCCAB\uC18C\uB9AC\uB85C \uB118\uAE34\uB2E4: `\uAC04` + `\u314F` \u2192 `\uAC00` + `\uB098`.\n if (cho && jung && jong) {\n const parts = SPLIT[jong];\n const moved = parts ? parts[1] : jong;\n const kept = parts ? parts[0] : undefined;\n return {\n commit: display({ cho, jung, jong: kept }),\n state: { cho: moved, jung: jamo },\n };\n }\n if (cho && jung) {\n const merged = VOWEL_PAIRS[jung + jamo];\n if (merged) return { commit: '', state: { cho, jung: merged } };\n return { commit: display(state), state: { jung: jamo } };\n }\n if (cho) return { commit: '', state: { cho, jung: jamo } };\n if (jung) {\n const merged = VOWEL_PAIRS[jung + jamo];\n if (merged) return { commit: '', state: { jung: merged } };\n return { commit: jung, state: { jung: jamo } };\n }\n return { commit: '', state: { jung: jamo } };\n }\n\n // \uC790\uC74C\n if (cho && jung) {\n if (!jong) {\n if (canBeFinal(jamo)) return { commit: '', state: { cho, jung, jong: jamo } };\n return { commit: display(state), state: { cho: jamo } };\n }\n const merged = FINAL_PAIRS[jong + jamo];\n if (merged) return { commit: '', state: { cho, jung, jong: merged } };\n return { commit: display(state), state: { cho: jamo } };\n }\n if (cho) {\n // \uC790\uC74C\uC774 \uC787\uB2EC\uC544 \uC624\uBA74 \uC55E \uC790\uC74C\uC740 \uD640\uB85C \uB0A8\uB294\uB2E4 \u2014 `\u3131\u3134` \uCC98\uB7FC \uB0B1\uC790\uB85C \uCE5C \uACBD\uC6B0\uB2E4.\n return { commit: cho, state: { cho: jamo } };\n }\n if (jung) return { commit: jung, state: { cho: jamo } };\n return { commit: '', state: { cho: jamo } };\n}\n\nexport interface BackResult {\n state: Composition;\n /** \uC870\uD569\uAE30\uAC00 \uCC98\uB9AC\uD588\uB294\uAC00. \uC544\uB2C8\uBA74 \uBD80\uB974\uB294 \uCABD\uC774 \uAC12\uC5D0\uC11C \uD55C \uAE00\uC790\uB97C \uC9C0\uC6CC\uC57C \uD55C\uB2E4. */\n handled: boolean;\n}\n\n/**\n * \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB97C \uD55C \uB2E8\uACC4 \uB418\uC9DA\uB294\uB2E4: `\uD55C` \u2192 `\uD558` \u2192 `\u314E` \u2192 (\uC5C6\uC74C).\n *\n * \uC644\uC131\uB41C \uAE00\uC790\uB97C \uD1B5\uC9F8\uB85C \uC9C0\uC6B0\uB294 IME \uB3C4 \uC788\uC9C0\uB9CC, \uB418\uC9DA\uB294 \uCABD\uC774 \uC624\uD0C0\uB97C \uACE0\uCE58\uAE30 \uC27D\uB2E4.\n */\nexport function back(state: Composition): BackResult {\n const { cho, jung, jong } = state;\n if (jong) {\n const parts = SPLIT[jong];\n return { state: { cho, jung, jong: parts ? parts[0] : undefined }, handled: true };\n }\n if (jung) {\n const parts = SPLIT[jung];\n return { state: { cho, jung: parts ? parts[0] : undefined }, handled: true };\n }\n if (cho) return { state: EMPTY, handled: true };\n return { state: EMPTY, handled: false };\n}\n\n/** \uC870\uD569\uC744 \uB05D\uB0B4\uACE0 \uB0A8\uC740 \uAE00\uC790\uB97C \uD655\uC815\uD55C\uB2E4. \uB2E4\uB978 \uD0A4\uB85C \uB118\uC5B4\uAC00\uAC70\uB098 \uC804\uC1A1\uD560 \uB54C \uBD80\uB978\uB2E4. */\nexport function flush(state: Composition): { commit: string; state: Composition } {\n return { commit: display(state), state: EMPTY };\n}\n\n/**\n * \uD0C0\uC790 \uD55C \uD310. \uC870\uD569 \uC911\uC778 \uAE00\uC790\uC640, \uADF8\uAC83\uC744 \uB9CC\uB4E0 \uAE00\uC1E0\uC640, Caps Lock \uD310\uB2E8\uC744 \uD568\uAED8 \uB4E0\uB2E4.\n *\n * \uAE00\uC1E0\uB97C \uD568\uAED8 \uB4DC\uB294 \uC774\uC720\uB294 Caps Lock \uD310\uB2E8\uC774 **\uB2A6\uAC8C \uC11C\uAE30 \uB54C\uBB38**\uC774\uB2E4. \uB41C\uC18C\uB9AC \uAE00\uC1E0\uB294\n * \uC2DC\uD504\uD2B8\uC5D0 \uB73B\uC774 \uC788\uC5B4 \uD310\uB2E8 \uADFC\uAC70\uAC00 \uBABB \uB418\uBBC0\uB85C, `\uAE4C` \uB97C \uCE58\uB824\uACE0 \uC2DC\uD504\uD2B8\uB97C \uBA3C\uC800 \uB204\uB974\uBA74\n * \uADF8 \uAE00\uC1E0\uB294 \uC99D\uAC70 \uC5C6\uC774 \uC77D\uD78C\uB2E4. \uB2E4\uC74C \uAE00\uC1E0\uC5D0\uC11C \uD310\uB2E8\uC774 \uB4A4\uC9D1\uD788\uBA74 \uC9C0\uAE08 \uAE00\uC790\uB97C \uCC98\uC74C\uBD80\uD130\n * \uB2E4\uC2DC \uC9DA\uC5B4\uC57C \uD55C\uB2E4 \u2014 \uADF8\uB7EC\uC9C0 \uC54A\uC73C\uBA74 \uCCAB \uAE00\uC790\uB9CC \uC5C9\uB6B1\uD558\uAC8C \uB0A8\uB294\uB2E4.\n */\nexport interface Typing {\n state: Composition;\n keys: string[];\n capsLock: boolean;\n}\n\nexport const IDLE: Typing = { state: EMPTY, keys: [], capsLock: false };\n\nexport interface TypeResult {\n session: Typing;\n /** \uD655\uC815\uB418\uC5B4 \uAC12\uC5D0 \uB4E4\uC5B4\uAC08 \uAE00\uC790. \uB418\uC9DA\uB290\uB77C \uB298\uC5B4\uB0A0 \uC218\uB3C4 \uC788\uB2E4. */\n commit: string;\n /** \uC544\uC9C1 \uC870\uD569 \uC911\uC778 \uAE00\uC790. \uAC12\uC758 \uCEE4\uC11C \uC55E \uD55C \uAE00\uC790\uB97C \uCC28\uC9C0\uD55C\uB2E4. */\n composing: string;\n}\n\n/** \uAE00\uC1E0 \uD558\uB098\uB97C \uCE5C\uB2E4. \uD55C\uAE00 \uB0B1\uC790\uAC00 \uC544\uB2C8\uBA74 \uC870\uD569\uC744 \uB05D\uB0B4\uACE0 \uADF8 \uAE00\uC790\uB97C \uADF8\uB300\uB85C \uC2E3\uB294\uB2E4. */\nexport function typeKey(session: Typing, key: string): TypeResult {\n const caps = detectCapsLock(session.capsLock, key);\n let { state, keys } = session;\n let commit = '';\n\n // \uD310\uB2E8\uC774 \uB4A4\uC9D1\uD614\uC73C\uBA74 \uC9C0\uAE08 \uAE00\uC790\uB97C \uCC98\uC74C\uBD80\uD130 \uB2E4\uC2DC \uC9DA\uB294\uB2E4.\n if (caps !== session.capsLock && keys.length > 0) {\n let rebuilt: Composition = EMPTY;\n for (const previous of keys) {\n const jamo = jamoOf(previous, caps);\n if (!jamo) continue;\n const step = feed(rebuilt, jamo);\n commit += step.commit;\n rebuilt = step.state;\n }\n state = rebuilt;\n }\n\n const jamo = jamoOf(key, caps);\n if (!jamo) {\n commit += display(state) + key;\n return { session: { state: EMPTY, keys: [], capsLock: caps }, commit, composing: '' };\n }\n\n const result = feed(state, jamo);\n commit += result.commit;\n // \uAE00\uC790\uAC00 \uD655\uC815\uB418\uBA74 \uC55E \uAE00\uC790\uC758 \uAE00\uC1E0\uB294 \uC78A\uB294\uB2E4 \u2014 \uB418\uC9DA\uC744 \uB300\uC0C1\uC740 \uC9C0\uAE08 \uAE00\uC790\uBFD0\uC774\uB2E4.\n keys = result.commit ? [key] : [...keys, key];\n return {\n session: { state: result.state, keys, capsLock: caps },\n commit,\n composing: display(result.state),\n };\n}\n\n/** \uC870\uD569 \uC911\uC778 \uAE00\uC790\uB97C \uD55C \uB2E8\uACC4 \uB418\uC9DA\uB294\uB2E4. \uAE00\uC1E0 \uAE30\uB85D\uB3C4 \uD568\uAED8 \uC904\uC778\uB2E4. */\nexport function backspace(session: Typing): { session: Typing; composing: string; handled: boolean } {\n const stepped = back(session.state);\n if (!stepped.handled) return { session, composing: '', handled: false };\n return {\n session: { ...session, state: stepped.state, keys: session.keys.slice(0, -1) },\n composing: display(stepped.state),\n handled: true,\n };\n}\n\n/**\n * \uBB38\uC790\uC5F4 \uD558\uB098\uB97C \uD1B5\uC9F8\uB85C \uC870\uD569\uD55C\uB2E4. \uC2DC\uD5D8\uACFC \uBD99\uC5EC\uB123\uAE30\uC5D0 \uC4F4\uB2E4.\n *\n * `'rkstk'` \u2192 `'\uAC04\uC0AC'` \uCC98\uB7FC, \uD0A4\uB97C \uC21C\uC11C\uB300\uB85C \uB20C\uB800\uC744 \uB54C \uB098\uC624\uB294 \uACB0\uACFC.\n */\nexport function compose(keys: string, capsLock = false): string {\n let session: Typing = { ...IDLE, capsLock };\n let text = '';\n for (const key of keys) {\n const result = typeKey(session, key);\n text += result.commit;\n session = result.session;\n }\n return text + display(session.state);\n}\n", "/**\n * \uD130\uBBF8\uB110\uC774 **\uD0A4 \uC790\uCCB4**\uB97C \uC54C\uB824 \uC8FC\uAC8C \uD55C\uB2E4.\n *\n * \uBCF4\uD1B5 \uD130\uBBF8\uB110\uC740 \uAE00\uC790\uB9CC \uBCF4\uB0B8\uB2E4. \uADF8\uB798\uC11C \uD55C/\uC601 \uD0A4(\uC624\uB978\uCABD Alt \uC790\uB9AC)\uB098 Caps Lock \uCC98\uB7FC\n * \uAE00\uC790\uB97C \uB9CC\uB4E4\uC9C0 \uC54A\uB294 \uD0A4\uB294 \uC571\uC5D0 \uC544\uC608 \uB3C4\uCC29\uD558\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC5B4\uB5A4 \uD130\uBBF8\uB110 \uD504\uB85C\uADF8\uB7A8\uB3C4 \uADF8\n * \uD0A4\uAC00 \uB20C\uB838\uB294\uC9C0 \uC54C \uC218 \uC5C6\uB2E4.\n *\n * Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC740 \uADF8 \uD0A4\uB4E4\uAE4C\uC9C0 `ESC[<\uCF54\uB4DC>;<\uC218\uC2DD>u` \uB85C \uBCF4\uACE0\uD55C\uB2E4. \uC9C0\uC6D0\uD558\uB294\n * \uD130\uBBF8\uB110(kitty\u00B7ghostty\u00B7WezTerm\u00B7foot\u00B7Alacritty\u00B7\uCD5C\uC2E0 Konsole \uB4F1)\uC5D0\uC11C\uB9CC \uCF1C\uC9C0\uACE0, \uB098\uBA38\uC9C0\uB294\n * \uBB3C\uC5B4\uBD10\uB3C4 \uB300\uB2F5\uD558\uC9C0 \uC54A\uC73C\uBBC0\uB85C \uADF8\uB0E5 \uC608\uC804\uCC98\uB7FC \uB3D9\uC791\uD55C\uB2E4 \u2014 \uCF1C\uB3C4 \uC783\uB294 \uAC83\uC774 \uC5C6\uB2E4.\n *\n * @see https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n */\n\nconst ESC = '\\u001B';\n/** \uC774 \uD504\uB85C\uD1A0\uCF5C\uC744 \uC4F8 \uC218 \uC788\uB294\uC9C0 \uBB3B\uB294\uB2E4. \uC9C0\uC6D0\uD558\uBA74 `ESC[?<flags>u` \uB85C \uB2F5\uD55C\uB2E4. */\nexport const QUERY = `${ESC}[?u`;\n\n/**\n * \uC6B0\uB9AC\uAC00 \uC54C\uC544\uBCF4\uACE0 \uC2F6\uC740 \uD0A4\uB4E4. \uC22B\uC790\uB294 \uD504\uB85C\uD1A0\uCF5C\uC774 \uC815\uD55C \uCF54\uB4DC\uB2E4.\n *\n * \uD55C/\uC601 \uD0A4 \uC790\uCCB4(keysym Hangul)\uB294 \uC774 \uD504\uB85C\uD1A0\uCF5C\uC5D0\uB3C4 \uC790\uB9AC\uAC00 \uC5C6\uB2E4. \uB300\uC2E0 \uD55C\uAD6D\uC5B4 \uC790\uD310\uC5D0\uC11C\n * **\uADF8 \uD0A4\uAC00 \uB193\uC778 \uC790\uB9AC**\uAC00 \uC624\uB978\uCABD Alt \uB77C, \uD55C\uAD6D\uC5B4 \uC785\uB825\uAE30\uAC00 \uC5C6\uB294 \uD658\uACBD\uC5D0\uC11C\uB294 \uC624\uB978\uCABD\n * Alt \uB85C \uB3C4\uCC29\uD55C\uB2E4. \uADF8\uAC83\uC744 \uD55C/\uC601\uC73C\uB85C \uBC1B\uB294\uB2E4.\n */\nexport const KEY_CODES: Record<number, string> = {\n 57358: 'capslock',\n 57449: 'rightalt',\n};\n\n/** Caps Lock \uC774 \uB20C\uB824 \uC788\uC74C\uC744 \uB73B\uD558\uB294 \uC218\uC2DD \uBE44\uD2B8. \uD504\uB85C\uD1A0\uCF5C \uAC12\uC740 \uC5EC\uAE30\uC5D0 1 \uC744 \uB354\uD55C \uAC83\uC774\uB2E4. */\nconst CAPS_LOCK_BIT = 64;\n\nexport interface KeyEvent {\n /** `KEY_CODES` \uC5D0 \uC788\uB294 \uC774\uB984. \uADF8 \uBC16\uC758 \uD0A4\uB294 \uC774\uB984 \uC5C6\uC774 \uC218\uC2DD\uB9CC \uC2E4\uC5B4 \uB098\uB978\uB2E4. */\n name?: string;\n capsLock: boolean;\n /** \uB20C\uB9BC(1)\u00B7\uBC18\uBCF5(2)\u00B7\uB5CC(3). \uC5C6\uC73C\uBA74 \uB20C\uB9BC\uC774\uB2E4. */\n eventType: number;\n}\n\n/**\n * \uB4E4\uC5B4\uC628 \uBC14\uC774\uD2B8\uC5D0\uC11C \uD0A4 \uC0AC\uAC74\uC744 \uACE8\uB77C\uB0B8\uB2E4.\n *\n * `ESC[<\uCF54\uB4DC>[:\uB300\uCCB4];<\uC218\uC2DD>[:\uC885\uB958][;<\uAE00\uC790>]u` \uAF34\uC774\uB2E4. \uC6B0\uB9AC\uB294 \uCF54\uB4DC\u00B7\uC218\uC2DD\u00B7\uC885\uB958\uB9CC \uBCF8\uB2E4.\n */\nexport function parseKeyEvents(chunk: string): KeyEvent[] {\n const events: KeyEvent[] = [];\n const pattern = /\\u001B\\[(\\d+)(?::\\d+)*(?:;(\\d+)(?::(\\d+))?)?(?:;[\\d:]*)?u/g;\n for (const match of chunk.matchAll(pattern)) {\n const code = Number(match[1]);\n // \uD504\uB85C\uD1A0\uCF5C\uC740 \uC218\uC2DD\uC744 \"\uC2E4\uC81C \uAC12 + 1\" \uB85C \uC2E3\uB294\uB2E4. \uC5C6\uC73C\uBA74 \uC544\uBB34 \uC218\uC2DD\uB3C4 \uC5C6\uB2E4\uB294 \uB73B\uC774\uB2E4.\n const modifiers = match[2] ? Number(match[2]) - 1 : 0;\n events.push({\n name: KEY_CODES[code],\n // eslint-disable-next-line no-bitwise\n capsLock: (modifiers & CAPS_LOCK_BIT) !== 0,\n eventType: match[3] ? Number(match[3]) : 1,\n });\n }\n return events;\n}\n\nexport interface QueryStreams {\n /** \uB2F5\uC744 \uAE30\uB2E4\uB9B4 \uACF3. \uC9C4\uC9DC stdin \uB3C4, \uC2DC\uD5D8\uC758 \uAC00\uC9DC \uC2A4\uD2B8\uB9BC\uB3C4 \uC774\uB9CC\uD07C\uC774\uBA74 \uB41C\uB2E4. */\n stdin: {\n on(event: 'data', listener: (chunk: Buffer | string) => void): unknown;\n removeListener(event: 'data', listener: (chunk: Buffer | string) => void): unknown;\n /**\n * \uB2F5\uC740 \uC904\uBC14\uAFC8 \uC5C6\uC774 \uC624\uBBC0\uB85C **\uD589 \uB2E8\uC704 \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uCEE4\uB110\uC774 \uBD99\uB4E4\uACE0 \uC788\uB2E4**.\n * \uBB3C\uC5B4\uBCF4\uB294 \uB3D9\uC548\uB9CC \uC6D0\uC2DC \uBAA8\uB4DC\uB85C \uBC14\uAFBC\uB2E4 \u2014 \uADF8\uB7EC\uC9C0 \uC54A\uC73C\uBA74 \uC9C0\uC6D0\uD558\uB294 \uD130\uBBF8\uB110\uB3C4\n * \uB300\uB2F5\uD558\uC9C0 \uC54A\uB294 \uAC83\uCC98\uB7FC \uBCF4\uC778\uB2E4.\n */\n isRaw?: boolean;\n setRawMode?(mode: boolean): unknown;\n resume?(): unknown;\n pause?(): unknown;\n };\n stdout: { isTTY?: boolean; write(chunk: string): unknown };\n isTTY?: boolean;\n}\n\n/**\n * \uC774 \uD130\uBBF8\uB110\uC774 \uD504\uB85C\uD1A0\uCF5C\uC744 \uC544\uB294\uC9C0 \uBB3C\uC5B4\uBCF8\uB2E4.\n *\n * \uB300\uB2F5\uC774 \uC5C6\uC73C\uBA74 \uBAA8\uB974\uB294 \uAC83\uC774\uB2E4 \u2014 \uAE30\uB2E4\uB9AC\uB2E4 \uADF8\uB0E5 \uB118\uC5B4\uAC04\uB2E4. \uB2F5\uC744 \uBABB \uBC1B\uC558\uB2E4\uACE0 \uCF1C \uBC84\uB9AC\uBA74\n * \uBAA8\uB974\uB294 \uD130\uBBF8\uB110\uC774 \uC6B0\uB9AC \uC9C8\uBB38\uC744 \uAE00\uC790\uB85C \uBC49\uC5B4 \uD654\uBA74\uC5D0 `[?u` \uAC00 \uCC0D\uD78C\uB2E4.\n */\nexport async function supportsKittyKeyboard(\n streams: QueryStreams,\n timeoutMs = 200,\n): Promise<boolean> {\n if (process.env.DEX_NO_KITTY === '1') return false;\n if (!streams.stdout.isTTY || !streams.isTTY) return false;\n\n const wasRaw = streams.stdin.isRaw === true;\n const wasPaused = !wasRaw;\n streams.stdin.setRawMode?.(true);\n streams.stdin.resume?.();\n\n return new Promise<boolean>((resolve) => {\n let settled = false;\n let seen = '';\n const finish = (supported: boolean): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n streams.stdin.removeListener('data', onData);\n // \uBB3C\uC5B4\uBCF4\uAE30 \uC804 \uC0C1\uD0DC\uB85C \uB3CC\uB824 \uB193\uB294\uB2E4. ink \uC774 \uACE7 \uC790\uAE30 \uBC29\uC2DD\uB300\uB85C \uB2E4\uC2DC \uC7A1\uB294\uB2E4.\n if (!wasRaw) streams.stdin.setRawMode?.(false);\n if (wasPaused) streams.stdin.pause?.();\n resolve(supported);\n };\n const onData = (data: Buffer | string): void => {\n seen += typeof data === 'string' ? data : data.toString('utf8');\n if (/\\u001B\\[\\?\\d*u/.test(seen)) finish(true);\n };\n // \uC774 \uD0C0\uC774\uBA38\uB294 unref \uD558\uC9C0 \uC54A\uB294\uB2E4. \uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uAC83 \uB9D0\uACE0 \uD560 \uC77C\uC774 \uC5C6\uC744 \uB54C \uD504\uB85C\uADF8\uB7A8\uC774\n // \uBA3C\uC800 \uB05D\uB098 \uBC84\uB9AC\uBA74, \uB300\uB2F5\uC744 \uC601\uC601 \uBABB \uBC1B\uACE0 \uB118\uC5B4\uAC04\uB2E4.\n const timer = setTimeout(() => finish(false), timeoutMs);\n streams.stdin.on('data', onData);\n streams.stdout.write(QUERY);\n });\n}\n", "import { useEffect, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { publicError } from '@dex/engine';\nimport type { Conversation, HistoryTurn } from '@dex/engine';\nimport type { TuiEngine } from './model';\nimport { Footer, Loading, Notice } from './components';\n\nexport function HistoryScreen(props: {\n engine: TuiEngine;\n profile: string;\n onOpen: (conversation: Conversation, turns: HistoryTurn[]) => void;\n onCancel: () => void;\n}): React.ReactNode {\n const [items, setItems] = useState<Conversation[]>([]);\n const [cursor, setCursor] = useState(0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string>();\n\n useEffect(() => {\n let alive = true;\n props.engine\n .listConversations(props.profile)\n .then((result) => alive && setItems(result))\n .catch((reason: unknown) => alive && setError(publicError(reason).message))\n .finally(() => alive && setLoading(false));\n return () => {\n alive = false;\n };\n }, [props.engine, props.profile]);\n\n useInput(\n (_input, key) => {\n if (key.escape) props.onCancel();\n if (key.upArrow) setCursor((current) => Math.max(0, current - 1));\n if (key.downArrow && items.length > 0) {\n setCursor((current) => Math.min(items.length - 1, current + 1));\n }\n if (key.return && items[cursor]) {\n const conversation = items[cursor];\n setLoading(true);\n setError(undefined);\n props.engine\n .historyTurns(\n conversation.workflowId,\n conversation.interactionId,\n conversation.workflowName,\n props.profile,\n )\n .then((turns) => props.onOpen(conversation, turns))\n .catch((reason: unknown) => setError(publicError(reason).message))\n .finally(() => setLoading(false));\n }\n },\n { isActive: !loading },\n );\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"round\" borderColor=\"cyan\" padding={1}>\n <Text bold>\uB300\uD654 \uAE30\uB85D</Text>\n {loading ? <Loading /> : null}\n {!loading && items.length === 0 ? <Text dimColor>\uB300\uD654 \uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.</Text> : null}\n {!loading\n ? items.slice(Math.max(0, cursor - 8), cursor + 9).map((item) => {\n const index = items.indexOf(item);\n return (\n <Text key={item.interactionId} color={index === cursor ? 'cyan' : undefined}>\n {index === cursor ? '\u203A' : ' '} {item.workflowName} \u00B7{' '}\n <Text dimColor>{item.updatedAt || item.createdAt}</Text>\n </Text>\n );\n })\n : null}\n {error ? <Notice error>{error}</Notice> : null}\n <Footer text=\"\u2191\u2193 \uC774\uB3D9 \u00B7 Enter \uC5F4\uAE30 \u00B7 Esc \uB3CC\uC544\uAC00\uAE30\" />\n </Box>\n );\n}\n", "import { useEffect, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { publicError } from '@dex/engine';\nimport type { Conversation, HistoryTurn } from '@dex/engine';\nimport type { TuiEngine } from './model';\nimport { Loading, Notice } from './components';\n\n/**\n * \uC5D0\uC774\uC804\uD2B8\uB97C \uACE0\uB978 \uC9C1\uD6C4\uC758 \uAC08\uB9BC\uAE38 \u2014 **\uC0C8\uB85C \uC2DC\uC791\uD560\uAE4C, \uD558\uB358 \uAC78 \uC774\uC5B4\uAC08\uAE4C.**\n *\n * \uC608\uC804\uC5D0\uB294 Enter \uB97C \uB204\uB974\uBA74 \uBC14\uB85C \uBE48 \uB300\uD654\uAC00 \uC5F4\uB838\uB2E4. \uC774\uC5B4\uC11C \uD558\uB824\uBA74 \uADF8\uAC78 \uC548 \uD558\uACE0\n * Ctrl+H \uB97C \uB20C\uB7EC **\uBAA8\uB4E0 \uC5D0\uC774\uC804\uD2B8\uC758** \uB300\uD654 \uBAA9\uB85D\uC5D0\uC11C \uCC3E\uC544\uC57C \uD588\uB2E4. \uBC29\uAE08 \uACE0\uB978 \uC5D0\uC774\uC804\uD2B8\uAC00\n * \uC774\uBBF8 \uD654\uBA74\uC5D0 \uC788\uB294\uB370\uB3C4.\n *\n * \uADF8\uB798\uC11C \uACE0\uB978 \uC5D0\uC774\uC804\uD2B8\uC758 \uB300\uD654\uB9CC \uC5EC\uAE30 \uBCF4\uC5EC \uC900\uB2E4.\n *\n * **\uC774\uB825\uC774 \uC5C6\uC73C\uBA74 \uC774 \uD654\uBA74\uC740 \uB728\uC9C0 \uC54A\uB294\uB2E4.** \uC120\uD0DD\uC9C0\uAC00 \uD558\uB098\uBFD0\uC778 \uC9C8\uBB38\uC744 \uB358\uC9C0\uB294 \uAC83\uC740\n * \uB3C4\uC6C0\uC774 \uC544\uB2C8\uB77C \uD55C \uBC88 \uB354 \uB204\uB974\uAC8C \uD558\uB294 \uC77C\uC774\uB2E4 \u2014 \uBD80\uBAA8\uAC00 \uADF8\uB54C\uB294 \uBC14\uB85C \uB300\uD654\uB97C \uC5F0\uB2E4.\n */\n\ninterface Row {\n kind: 'new' | 'conversation';\n conversation?: Conversation;\n}\n\nexport function StartPanel(props: {\n engine: TuiEngine;\n profile: string;\n agentName: string;\n conversations: Conversation[];\n onNew: () => void;\n onOpen: (conversation: Conversation, turns: HistoryTurn[]) => void;\n onCancel: () => void;\n}): React.ReactNode {\n const rows: Row[] = [\n { kind: 'new' },\n ...props.conversations.map((conversation) => ({ kind: 'conversation' as const, conversation })),\n ];\n const [cursor, setCursor] = useState(0);\n const [opening, setOpening] = useState(false);\n const [error, setError] = useState<string>();\n\n // \uBAA9\uB85D\uC774 \uBC14\uB00C\uBA74 \uCEE4\uC11C\uAC00 \uBC94\uC704\uB97C \uBC97\uC5B4\uB0A0 \uC218 \uC788\uB2E4.\n useEffect(() => {\n setCursor((current) => Math.min(current, Math.max(0, rows.length - 1)));\n }, [rows.length]);\n\n useInput(\n (_input, key) => {\n if (key.escape) {\n props.onCancel();\n return;\n }\n if (key.upArrow) setCursor((current) => Math.max(0, current - 1));\n if (key.downArrow) setCursor((current) => Math.min(rows.length - 1, current + 1));\n if (!key.return) return;\n\n const row = rows[cursor];\n if (!row) return;\n if (row.kind === 'new' || !row.conversation) {\n props.onNew();\n return;\n }\n const conversation = row.conversation;\n setOpening(true);\n setError(undefined);\n props.engine\n .historyTurns(\n conversation.workflowId,\n conversation.interactionId,\n conversation.workflowName,\n props.profile,\n )\n .then((turns) => props.onOpen(conversation, turns))\n .catch((reason: unknown) => {\n setError(publicError(reason).message);\n setOpening(false);\n });\n },\n { isActive: !opening },\n );\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"round\" borderColor=\"cyan\" padding={1}>\n <Text bold>{props.agentName}</Text>\n <Text dimColor>\uC5B4\uB5BB\uAC8C \uC2DC\uC791\uD560\uAE4C\uC694?</Text>\n\n <Box flexDirection=\"column\" marginTop={1}>\n {rows.map((row, index) => {\n const active = index === cursor;\n const mark = active ? '\u203A' : ' ';\n if (row.kind === 'new') {\n return (\n <Text key=\"new\" color={active ? 'cyan' : undefined}>\n {mark} \uC0C8 \uB300\uD654\n </Text>\n );\n }\n const conversation = row.conversation;\n if (!conversation) return null;\n return (\n <Text key={conversation.interactionId} color={active ? 'cyan' : undefined}>\n {mark} {when(conversation)} <Text dimColor>\u00B7 {conversation.interactionCount}\uD134</Text>\n </Text>\n );\n })}\n </Box>\n\n {opening ? <Loading label=\"\uB300\uD654\uB97C \uBD88\uB7EC\uC624\uB294 \uC911...\" /> : null}\n {error ? <Notice error>{error}</Notice> : null}\n\n <Box marginTop={1}>\n <Text dimColor>\u2191\u2193 \uC774\uB3D9 \u00B7 Enter \uC120\uD0DD \u00B7 Esc \uBAA9\uB85D\uC73C\uB85C</Text>\n </Box>\n </Box>\n );\n}\n\n/**\n * \uB300\uD654\uB97C \uC5B8\uC81C \uD588\uB294\uC9C0.\n *\n * \uC11C\uBC84\uAC00 \uC8FC\uB294 \uBB38\uC790\uC5F4\uC744 \uADF8\uB300\uB85C \uC4F0\uC9C0 \uC54A\uB294\uB2E4 \u2014 `2026-08-31T02:11:09.482Z` \uB294 \uBAA9\uB85D\uC5D0\uC11C\n * \uC77D\uC73C\uB77C\uACE0 \uC788\uB294 \uAC12\uC774 \uC544\uB2C8\uB2E4. \uC624\uB298 \uAC83\uC740 \uC2DC\uAC01\uB9CC, \uADF8 \uBC16\uC740 \uB0A0\uC9DC\uB9CC \uBCF4\uC5EC \uC900\uB2E4.\n */\nfunction when(conversation: Conversation): string {\n const raw = conversation.updatedAt || conversation.createdAt;\n const date = new Date(raw);\n if (Number.isNaN(date.getTime())) return raw || '(\uC2DC\uAC01 \uC5C6\uC74C)';\n const now = new Date();\n const sameDay =\n date.getFullYear() === now.getFullYear() &&\n date.getMonth() === now.getMonth() &&\n date.getDate() === now.getDate();\n const pad = (n: number): string => String(n).padStart(2, '0');\n return sameDay\n ? `\uC624\uB298 ${pad(date.getHours())}:${pad(date.getMinutes())}`\n : `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;\n}\n", "import { useEffect, useState } from 'react';\nimport { useStdout } from 'ink';\n\nexport interface TerminalSize {\n columns: number;\n rows: number;\n wide: boolean;\n}\n\nexport function useTerminalSize(): TerminalSize {\n const { stdout } = useStdout();\n const read = (): TerminalSize => {\n const columns = stdout.columns || 100;\n const rows = stdout.rows || 30;\n return { columns, rows, wide: columns >= 88 };\n };\n const [size, setSize] = useState(read);\n useEffect(() => {\n const resize = (): void => setSize(read());\n stdout.on('resize', resize);\n return () => {\n stdout.off('resize', resize);\n };\n }, [stdout]);\n return size;\n}\n", "import { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { Footer, FormField, Header, Loading, Notice } from './components';\n\nexport function LoginScreen(props: {\n profile: string;\n serverUrl: string;\n busy: boolean;\n error?: string;\n onSubmit: (email: string, password: string) => void;\n onProfiles: () => void;\n /** \uC8FC\uC18C\uB97C \uC798\uBABB \uCE5C \uAC83\uC744 \uC5EC\uAE30\uC11C \uBC14\uB85C \uACE0\uCE5C\uB2E4 \u2014 \uD504\uB85C\uD544\uC744 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uC54A\uACE0. */\n onEditServer: () => void;\n}): React.ReactNode {\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [focus, setFocus] = useState<'email' | 'password'>('email');\n\n useInput(\n (input, key) => {\n if (key.tab) setFocus((current) => (current === 'email' ? 'password' : 'email'));\n if (key.ctrl && input === 'p') props.onProfiles();\n if (key.ctrl && input === 'e') props.onEditServer();\n },\n { isActive: !props.busy },\n );\n\n const submit = (): void => {\n if (focus === 'email') {\n setFocus('password');\n return;\n }\n if (email.trim() && password) {\n const secret = password;\n setPassword('');\n props.onSubmit(email.trim(), secret);\n }\n };\n\n return (\n <Box flexDirection=\"column\">\n <Header profile={props.profile} connected={false} />\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"blue\" padding={1}>\n <Text bold>\uB85C\uADF8\uC778</Text>\n {/* \uC8FC\uC18C\uB97C \uD06C\uAC8C \uBCF4\uC5EC \uC900\uB2E4 \u2014 \uB85C\uADF8\uC778\uC774 \uC548 \uB420 \uB54C \uAC00\uC7A5 \uBA3C\uC800 \uC758\uC2EC\uD560 \uAC12\uC774\uB2E4. */}\n <Text dimColor>\n {props.serverUrl} <Text color=\"cyan\">(Ctrl+E \uBC14\uAFB8\uAE30)</Text>\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <FormField\n label=\"Email\"\n value={email}\n onChange={setEmail}\n onSubmit={() => setFocus('password')}\n focus={!props.busy && focus === 'email'}\n placeholder=\"me@corp.com\"\n />\n <FormField\n label=\"Password\"\n value={password}\n onChange={setPassword}\n onSubmit={submit}\n focus={!props.busy && focus === 'password'}\n secret\n />\n </Box>\n {props.busy ? <Loading label=\"\uB85C\uADF8\uC778\uD558\uB294 \uC911...\" /> : null}\n {props.error ? <Notice error>{props.error}</Notice> : null}\n </Box>\n <Footer text=\"Tab \uC774\uB3D9 \u00B7 Enter \uB85C\uADF8\uC778 \u00B7 Ctrl+E \uC11C\uBC84 \u00B7 Ctrl+P \uD504\uB85C\uD544 \u00B7 Ctrl+Q \uC885\uB8CC\" />\n </Box>\n );\n}\n", "import { useEffect, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { ProfileSummary } from '@dex/engine';\nimport { Footer, FormField, Header, Loading, Notice } from './components';\n\nexport function ProfileScreen(props: {\n profiles: ProfileSummary[];\n busy: boolean;\n error?: string;\n onSelect: (name: string) => void;\n onCreate: (name: string, serverUrl: string) => void;\n onCancel: () => void;\n}): React.ReactNode {\n const [cursor, setCursor] = useState(Math.max(0, props.profiles.findIndex((profile) => profile.current)));\n const [creating, setCreating] = useState(false);\n const [focus, setFocus] = useState<'name' | 'url'>('name');\n const [name, setName] = useState('');\n const [serverUrl, setServerUrl] = useState('');\n\n useEffect(() => setCursor((current) => Math.min(current, Math.max(0, props.profiles.length - 1))), [props.profiles]);\n\n useInput(\n (input, key) => {\n if (key.escape) {\n if (creating) setCreating(false);\n else props.onCancel();\n return;\n }\n if (creating) {\n if (key.tab) setFocus((current) => (current === 'name' ? 'url' : 'name'));\n return;\n }\n if (key.upArrow) setCursor((current) => Math.max(0, current - 1));\n if (key.downArrow && props.profiles.length > 0) {\n setCursor((current) => Math.min(props.profiles.length - 1, current + 1));\n }\n if (key.return && props.profiles[cursor]) props.onSelect(props.profiles[cursor].name);\n if (input === 'n') {\n setCreating(true);\n setFocus('name');\n }\n },\n { isActive: !props.busy },\n );\n\n const create = (): void => {\n if (focus === 'name') {\n setFocus('url');\n return;\n }\n if (name.trim() && serverUrl.trim()) props.onCreate(name.trim(), serverUrl.trim());\n };\n\n return (\n <Box flexDirection=\"column\">\n <Header />\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" padding={1}>\n <Text bold>{creating ? '\uC0C8 \uD504\uB85C\uD544' : '\uD504\uB85C\uD544 \uC804\uD658'}</Text>\n {creating ? (\n <Box flexDirection=\"column\" marginTop={1}>\n <FormField\n label=\"Name\"\n value={name}\n onChange={setName}\n onSubmit={() => setFocus('url')}\n focus={!props.busy && focus === 'name'}\n placeholder=\"corp\"\n />\n <FormField\n label=\"Server URL\"\n value={serverUrl}\n onChange={setServerUrl}\n onSubmit={create}\n focus={!props.busy && focus === 'url'}\n placeholder=\"https://xgen.example.com\"\n />\n </Box>\n ) : (\n <Box flexDirection=\"column\" marginTop={1}>\n {props.profiles.map((profile, index) => (\n <Text key={profile.name} color={index === cursor ? 'cyan' : undefined}>\n {index === cursor ? '\u203A' : ' '} {profile.current ? '\u25CF' : '\u25CB'} {profile.name} \u00B7{' '}\n <Text dimColor>{profile.serverUrl}</Text>\n </Text>\n ))}\n {props.profiles.length === 0 ? <Text dimColor>\uC800\uC7A5\uB41C \uD504\uB85C\uD544\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.</Text> : null}\n </Box>\n )}\n {props.busy ? <Loading label=\"\uD504\uB85C\uD544\uC744 \uC804\uD658\uD558\uB294 \uC911...\" /> : null}\n {props.error ? <Notice error>{props.error}</Notice> : null}\n </Box>\n <Footer\n text={creating ? 'Tab \uC774\uB3D9 \u00B7 Enter \uC800\uC7A5 \u00B7 Esc \uB4A4\uB85C' : '\u2191\u2193 \uC774\uB3D9 \u00B7 Enter \uC120\uD0DD \u00B7 N \uC0C8 \uD504\uB85C\uD544 \u00B7 Esc \uB2EB\uAE30'}\n />\n </Box>\n );\n}\n", "import { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { Footer, FormField, Header, Loading, Notice } from './components';\n\n/**\n * \uC11C\uBC84 \uC8FC\uC18C\uB97C \uC815\uD558\uB294 \uD654\uBA74. **\uCC98\uC74C \uC124\uC815\uACFC \uB098\uC911 \uC218\uC815\uC774 \uAC19\uC740 \uD654\uBA74**\uC774\uB2E4.\n *\n * \uC608\uC804\uC5D0\uB294 \uCC98\uC74C \uC124\uC815 \uC804\uC6A9\uC774\uC5C8\uB2E4. \uADF8\uB798\uC11C \uC8FC\uC18C\uB97C \uC798\uBABB \uCE58\uACE0 \uB118\uC5B4\uAC00\uBA74 \uB418\uB3CC\uC544\uC62C \uAE38\uC774\n * \uC5C6\uC5C8\uB2E4 \u2014 \uB85C\uADF8\uC778 \uD654\uBA74\uC5D0\uC11C \uD560 \uC218 \uC788\uB294 \uAC83\uC740 Ctrl+P \uB85C \uD504\uB85C\uD544 \uBAA9\uB85D\uC5D0 \uAC00\uC11C \uC0C8 \uD504\uB85C\uD544\uC744\n * \uB9CC\uB4DC\uB294 \uAC83\uBFD0\uC774\uC5C8\uACE0, \uC624\uD0C0 \uD558\uB098 \uACE0\uCE58\uC790\uACE0 \uD504\uB85C\uD544\uC774 \uD558\uB098 \uB354 \uC0DD\uACBC\uB2E4.\n *\n * \uACE0\uCE60 \uB54C\uB294 \uC9C0\uAE08 \uAC12\uC774 \uCC44\uC6CC\uC9C4 \uCC44\uB85C \uC5F4\uB9B0\uB2E4 \u2014 \uB2E4\uC2DC \uCE58\uB294 \uAC8C \uC544\uB2C8\uB77C \uACE0\uCE58\uB294 \uAC83\uC774\uB2E4.\n */\nexport function ServerScreen(props: {\n /** \uACE0\uCE60 \uB54C\uC758 \uD604\uC7AC \uAC12. \uCC98\uC74C \uC124\uC815\uC774\uBA74 \uBE44\uC5B4 \uC788\uB2E4. */\n initialValue?: string;\n profile?: string;\n busy: boolean;\n error?: string;\n onSubmit: (serverUrl: string) => void;\n /** \uCC98\uC74C \uC124\uC815\uC5D0\uB294 \uC5C6\uB2E4 \u2014 \uB3CC\uC544\uAC08 \uACF3\uC774 \uC5C6\uAE30 \uB54C\uBB38\uC774\uB2E4. */\n onCancel?: () => void;\n}): React.ReactNode {\n const [serverUrl, setServerUrl] = useState(props.initialValue ?? '');\n const editing = props.initialValue !== undefined;\n\n useInput(\n (_input, key) => {\n if (key.escape) props.onCancel?.();\n },\n { isActive: !props.busy && !!props.onCancel },\n );\n\n return (\n <Box flexDirection=\"column\">\n <Header profile={props.profile} connected={false} />\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"blue\" padding={1}>\n <Text bold>{editing ? '\uC11C\uBC84 \uC8FC\uC18C \uBC14\uAFB8\uAE30' : '\uCC98\uC74C \uC624\uC168\uAD70\uC694'}</Text>\n <Text dimColor>\uC5F0\uACB0\uD560 XGEN Gateway \uC8FC\uC18C\uB97C \uC785\uB825\uD558\uC138\uC694.</Text>\n <Box marginTop={1}>\n <FormField\n label=\"Server URL\"\n value={serverUrl}\n onChange={setServerUrl}\n onSubmit={(value) => value.trim() && props.onSubmit(value.trim())}\n focus={!props.busy}\n placeholder=\"xgen.example.com\"\n />\n </Box>\n {/* http:// \uB97C \uC548 \uC368\uB3C4 \uB41C\uB2E4\uB294 \uAC83\uC744 \uC5EC\uAE30\uC11C \uB9D0\uD574 \uC900\uB2E4 \u2014 \uC608\uC804\uC5D0\uB294 \uADF8\uAC78 \uBAA8\uB974\uACE0\n \uCE58\uB2E4\uAC00 \"http:// \uB610\uB294 https://\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4\" \uB97C \uBCF4\uACE0\uC11C\uC57C \uC54C\uC558\uB2E4. */}\n <Text dimColor>https:// \uB294 \uC0DD\uB7B5\uD574\uB3C4 \uB429\uB2C8\uB2E4.</Text>\n {props.busy ? <Loading label=\"\uC11C\uBC84 \uD504\uB85C\uD544\uC744 \uC800\uC7A5\uD558\uB294 \uC911...\" /> : null}\n {props.error ? <Notice error>{props.error}</Notice> : null}\n </Box>\n <Footer\n text={\n props.onCancel\n ? 'Enter \uC800\uC7A5 \u00B7 Esc \uCDE8\uC18C \u00B7 Ctrl+Q \uC885\uB8CC'\n : 'Enter \uACC4\uC18D \u00B7 Ctrl+Q \uC885\uB8CC'\n }\n />\n </Box>\n );\n}\n", "/**\n * \uB300\uCCB4 \uD654\uBA74(alternate screen) \uAD00\uB9AC.\n *\n * \uC608\uC804\uC5D0\uB294 TUI \uB97C \uC9C0\uAE08 \uC4F0\uB358 \uD130\uBBF8\uB110\uC5D0 \uADF8\uB300\uB85C \uADF8\uB838\uB2E4. \uADF8\uB798\uC11C Ctrl+Q \uB85C \uB098\uAC00\uBA74 \uB9C8\uC9C0\uB9C9\n * \uD504\uB808\uC784 \u2014 \uC5D0\uC774\uC804\uD2B8 \uBAA9\uB85D, \uB300\uD654\uCC3D, \uD14C\uB450\uB9AC \u2014 \uC774 \uC2A4\uD06C\uB864\uBC31\uC5D0 \uADF8\uB300\uB85C \uB0A8\uC558\uB2E4. \uADF8 \uC704\uB85C\n * \uB2E4\uC74C \uD504\uB86C\uD504\uD2B8\uAC00 \uCC0D\uD788\uB2C8 \uD654\uBA74\uC774 \uC5C9\uD0A8 \uAC83\uCC98\uB7FC \uBCF4\uC774\uACE0, \uC704\uB85C \uC2A4\uD06C\uB864\uD558\uBA74 \uC4F0\uC9C0\uB3C4 \uC54A\uC744\n * UI \uC794\uD574\uAC00 \uC608\uC804 \uBA85\uB839\uB4E4 \uC0AC\uC774\uC5D0 \uB07C\uC5B4 \uC788\uB2E4.\n *\n * `vim`\u00B7`less`\u00B7`htop` \uC774 \uC4F0\uB294 \uAC83\uACFC \uAC19\uC740 \uBC29\uBC95\uC774\uB2E4: \uB4E4\uC5B4\uAC08 \uB54C \uD654\uBA74\uC744 \uD55C \uC7A5 \uC0C8\uB85C \uAE54\uACE0,\n * \uB098\uC62C \uB54C \uC6D0\uB798 \uD654\uBA74\uC744 \uB418\uB3CC\uB9B0\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uBCF4\uAE30\uC5D0\uB294 **\uB744\uC6B0\uAE30 \uC804 \uC0C1\uD0DC\uB85C \uADF8\uB300\uB85C \uB3CC\uC544\uC628\uB2E4.**\n *\n * \uBCC4\uB3C4 \uD30C\uC77C\uC778 \uC774\uC720\uB294 \uC774 \uADDC\uCE59\uB4E4\uC774 \uB208\uC73C\uB85C\uB294 \uD655\uC778\uB418\uC9C0 \uC54A\uAE30 \uB54C\uBB38\uC774\uB2E4 \u2014 \uD2C0\uB9AC\uBA74 \uC0AC\uC6A9\uC790\n * \uD130\uBBF8\uB110\uC774 \uB9DD\uAC00\uC9C4 \uB4A4\uC5D0\uC57C \uC548\uB2E4. \uADF8\uB798\uC11C \uAC00\uC9DC \uC2A4\uD2B8\uB9BC\uC5D0 \uB300\uACE0 \uC2DC\uD5D8\uD560 \uC218 \uC788\uAC8C \uB5BC\uC5B4 \uB480\uB2E4.\n */\n\n/** \uC4F0\uAE30\uB9CC \uD544\uC694\uD558\uB2E4. \uC9C4\uC9DC stdout \uB3C4, \uD14C\uC2A4\uD2B8\uC758 \uAC00\uC9DC \uC2A4\uD2B8\uB9BC\uB3C4 \uC774\uAC78 \uB9CC\uC871\uD55C\uB2E4. */\nexport interface ScreenStream {\n isTTY?: boolean;\n write(chunk: string): unknown;\n}\n\nconst ESC = '\\u001B';\n/** \uB300\uCCB4 \uD654\uBA74\uC73C\uB85C \uB4E4\uC5B4\uAC04\uB2E4 (DECSET 1049). \uCEE4\uC11C \uC704\uCE58\uAE4C\uC9C0 \uD568\uAED8 \uBCF4\uAD00\uB41C\uB2E4. */\nexport const ENTER_ALT_SCREEN = `${ESC}[?1049h`;\n/** \uC6D0\uB798 \uD654\uBA74\uC73C\uB85C \uB3CC\uC544\uC628\uB2E4. \uB4E4\uC5B4\uAC00\uAE30 \uC804 \uB0B4\uC6A9\uC774 \uADF8\uB300\uB85C \uBCF5\uC6D0\uB41C\uB2E4. */\nexport const LEAVE_ALT_SCREEN = `${ESC}[?1049l`;\n/** Ink \uB294 \uADF8\uB9AC\uB294 \uB3D9\uC548 \uCEE4\uC11C\uB97C \uC228\uAE34\uB2E4. \uB418\uB3CC\uB9AC\uC9C0 \uC54A\uC73C\uBA74 \uB098\uAC04 \uB4A4 \uCEE4\uC11C\uAC00 \uBCF4\uC774\uC9C0 \uC54A\uB294\uB2E4. */\nexport const SHOW_CURSOR = `${ESC}[?25h`;\n\n/**\n * \uD130\uBBF8\uB110\uC5D0\uAC8C **\uD0A4\uAC00 \uC544\uB2CC \uAC83\uC744 \uBCF4\uB0B4\uC9C0 \uB9D0\uB77C** \uACE0 \uB9D0\uD55C\uB2E4.\n *\n * \uD130\uBBF8\uB110\uC740 \uCC3D \uD3EC\uCEE4\uC2A4\uAC00 \uBC14\uB00C\uBA74 `ESC[I`/`ESC[O`, \uB9C8\uC6B0\uC2A4\uB97C \uAC74\uB4DC\uB9AC\uBA74 `ESC[<0;1;1M` \uC744\n * \uC785\uB825\uC778 \uAC83\uCC98\uB7FC \uBCF4\uB0B8\uB2E4. \uC774 \uBAA8\uB4DC\uB4E4\uC740 \uC55E\uC11C \uC2E4\uD589\uB41C \uD504\uB85C\uADF8\uB7A8\uC774 \uCF1C \uB450\uACE0 \uB044\uC9C0 \uC54A\uC740 \uCC44\n * \uB0A8\uC544 \uC788\uC744 \uC218 \uC788\uC5B4\uC11C, \uC6B0\uB9AC\uAC00 \uCF20 \uC801 \uC5C6\uC5B4\uB3C4 \uB3C4\uCC29\uD55C\uB2E4. \uADF8\uB300\uB85C \uB450\uBA74 \uBA54\uC2DC\uC9C0 \uCE78\uC5D0\n * `[I`\u00B7`[<0;1;1M` \uC774 \uD0C0\uC774\uD551\uB41C\uB2E4 \u2014 \uD55C\uAE00 IME \uD6C4\uBCF4\uCC3D\uC774 \uB728\uACE0 \uB2EB\uD790 \uB54C\uB9C8\uB2E4 \uD3EC\uCEE4\uC2A4\uAC00\n * \uC624\uAC00\uBBC0\uB85C \uD2B9\uD788 \uC790\uC8FC \uD130\uC9C4\uB2E4.\n */\nconst DISABLE_REPORTS = [\n `${ESC}[?1004l`, // \uD3EC\uCEE4\uC2A4 \uB4E4\uC5B4\uC634/\uB098\uAC10\n `${ESC}[?1000l`, // \uB9C8\uC6B0\uC2A4 \uD074\uB9AD\n `${ESC}[?1002l`, // \uB9C8\uC6B0\uC2A4 \uB4DC\uB798\uADF8\n `${ESC}[?1003l`, // \uB9C8\uC6B0\uC2A4 \uC774\uB3D9 \uC804\uBD80\n `${ESC}[?1006l`, // SGR \uD655\uC7A5 \uC88C\uD45C\n].join('');\n\n/**\n * \uBD99\uC5EC\uB123\uAE30\uB97C `ESC[200~` ... `ESC[201~` \uB85C \uAC10\uC2F8 \uB2EC\uB77C\uACE0 \uD55C\uB2E4.\n *\n * \uAC10\uC2F8 \uC8FC\uBA74 \uBD99\uC778 \uB0B4\uC6A9\uC744 **\uD0A4\uAC00 \uC544\uB2C8\uB77C \uAE00\uC790**\uB85C \uB2E4\uB8F0 \uC218 \uC788\uB2E4. \uC548 \uAC10\uC2F8\uBA74 \uBD99\uC5EC\uB123\uC740\n * \uC904\uBC14\uAFC8\uC774 \"\uC804\uC1A1\" \uC73C\uB85C \uC77D\uD600 \uBC18\uCABD\uC9DC\uB9AC \uBA54\uC2DC\uC9C0\uAC00 \uB098\uAC00\uACE0, \uB0B4\uC6A9 \uC548\uC758 ESC \uB294 \uC81C\uC5B4\n * \uC2DC\uD000\uC2A4\uB85C \uC798\uBABB \uD574\uC11D\uB41C\uB2E4.\n */\nconst ENABLE_BRACKETED_PASTE = `${ESC}[?2004h`;\nconst DISABLE_BRACKETED_PASTE = `${ESC}[?2004l`;\n\n/**\n * Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC744 \uC6D0\uB798\uB300\uB85C \uB418\uB3CC\uB9B0\uB2E4.\n *\n * \uCF20 \uCC44\uB85C \uB098\uAC00\uBA74 \uB2E4\uC74C\uC5D0 \uC774 \uD130\uBBF8\uB110\uC744 \uC4F0\uB294 \uD504\uB85C\uADF8\uB7A8\uC774 \uB0AF\uC120 \uC774\uC2A4\uCF00\uC774\uD504\uB97C \uBC1B\uB294\uB2E4 \u2014\n * \uC178\uC5D0\uC11C \uBC29\uD5A5\uD0A4\uAC00 \uAE00\uC790\uB85C \uCC0D\uD788\uB294 \uC2DD\uC73C\uB85C \uB9DD\uAC00\uC9C4\uB2E4. ink \uB3C4 \uC815\uB9AC\uD558\uC9C0\uB9CC Ctrl+Q \uB098\n * \uC2E0\uD638\uB85C \uC8FD\uC744 \uB54C\uB294 \uAC70\uCE58\uC9C0 \uBABB\uD560 \uC218 \uC788\uC5B4, \uD654\uBA74\uC744 \uB418\uB3CC\uB9AC\uB294 \uC790\uB9AC\uC5D0\uC11C \uD568\uAED8 \uB418\uB3CC\uB9B0\uB2E4.\n * \uCF20 \uC801\uC774 \uC5C6\uC5B4\uB3C4 \uC548\uC804\uD558\uB2E4 \u2014 \uBE48 \uAC83\uC744 \uAEBC\uB0B4\uB294 \uAC83\uC740 \uC544\uBB34 \uC77C\uB3C4 \uD558\uC9C0 \uC54A\uB294\uB2E4.\n */\nconst POP_KITTY_KEYBOARD = `${ESC}[<u`;\n\nexport interface ScreenGuardOptions {\n /** Kitty \uD0A4\uBCF4\uB4DC \uD504\uB85C\uD1A0\uCF5C\uC744 \uCF1C\uC11C \uB4E4\uC5B4\uC654\uB294\uAC00. \uB098\uAC08 \uB54C \uB418\uB3CC\uB824\uC57C \uD55C\uB2E4. */\n kittyKeyboard?: boolean;\n}\n\nexport interface ScreenGuard {\n /** \uB300\uCCB4 \uD654\uBA74\uC73C\uB85C \uB4E4\uC5B4\uAC04\uB2E4. TTY \uAC00 \uC544\uB2C8\uBA74 \uC544\uBB34 \uAC83\uB3C4 \uD558\uC9C0 \uC54A\uB294\uB2E4. */\n enter(): void;\n /** \uC6D0\uB798 \uD654\uBA74\uACFC \uCEE4\uC11C\uB97C \uB418\uB3CC\uB9B0\uB2E4. \uC5EC\uB7EC \uBC88 \uBD88\uB7EC\uB3C4 \uD55C \uBC88\uB9CC \uB3D9\uC791\uD55C\uB2E4. */\n restore(): void;\n}\n\nexport function createScreenGuard(\n stream: ScreenStream,\n options: ScreenGuardOptions = {},\n): ScreenGuard {\n // TTY \uAC00 \uC544\uB2C8\uBA74 \uC190\uB300\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uD30C\uC774\uD504\uB098 CI \uB85C\uADF8\uC5D0 \uC81C\uC5B4 \uBB38\uC790\uB97C \uBFCC\uB9B4 \uC774\uC720\uAC00 \uC5C6\uB2E4.\n const alt = Boolean(stream.isTTY);\n let entered = false;\n let restored = false;\n\n return {\n enter(): void {\n if (entered || !alt) return;\n entered = true;\n stream.write(ENTER_ALT_SCREEN + DISABLE_REPORTS + ENABLE_BRACKETED_PASTE);\n },\n restore(): void {\n // \uB418\uB3CC\uB9AC\uAE30\uB294 **\uD55C \uBC88\uB9CC** \uD55C\uB2E4. \uC815\uC0C1 \uC885\uB8CC\u00B7Ctrl+C\u00B7\uC608\uC678\uAC00 \uACB9\uCCD0 \uB450 \uBC88 \uB098\uAC00\uBA74\n // \uB300\uCCB4 \uD654\uBA74\uC744 \uD558\uB098 \uB354 \uBC97\uACA8\uB0B4 \uC0AC\uC6A9\uC790\uC758 \uC6D0\uB798 \uD654\uBA74\uAE4C\uC9C0 \uC9C0\uC6B4\uB2E4.\n if (restored) return;\n restored = true;\n // \uCF20 \uAC83\uB9CC \uB418\uB3CC\uB9B0\uB2E4. \uBCF4\uACE0 \uBAA8\uB4DC\uB294 \uC6D0\uB798 \uAEBC\uC838 \uC788\uC5B4\uC57C \uC815\uC0C1\uC774\uBBC0\uB85C \uB2E4\uC2DC \uCF1C\uC9C0 \uC54A\uB294\uB2E4.\n if (entered) {\n stream.write(\n (options.kittyKeyboard ? POP_KITTY_KEYBOARD : '') +\n DISABLE_BRACKETED_PASTE +\n LEAVE_ALT_SCREEN,\n );\n }\n stream.write(SHOW_CURSOR);\n },\n };\n}\n", "import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { dataDirectory } from '@dex/engine';\n\n/**\n * \uD130\uBBF8\uB110 UI \uC758 \uCDE8\uD5A5\uC744 \uAE30\uC5B5\uD55C\uB2E4.\n *\n * \uC9C0\uAE08\uC740 \uD55C/\uC601 \uD558\uB098\uBFD0\uC774\uB2E4. \uC11C\uBC84 \uC124\uC815(config.json)\uACFC \uC11E\uC9C0 \uC54A\uC740 \uC774\uC720\uB294 \uADF8\uCABD\uC774 \uC571\u00B7\uD655\uC7A5\uACFC\n * \uD568\uAED8 \uC4F0\uB294 \uACC4\uC57D\uC774\uAE30 \uB54C\uBB38\uC774\uB2E4 \u2014 \uD130\uBBF8\uB110\uC5D0\uC11C\uB9CC \uB73B\uC774 \uC788\uB294 \uAC12\uC744 \uAC70\uAE30 \uB123\uC73C\uBA74, \uADF8 \uACC4\uC57D\uC744\n * \uC77D\uB294 \uBAA8\uB4E0 \uACF3\uC774 \uC774 \uAC12\uC744 \uC54C\uC544\uC57C \uD558\uB294 \uAC83\uCC98\uB7FC \uBCF4\uC778\uB2E4.\n *\n * \uC77D\uAE30\uB3C4 \uC4F0\uAE30\uB3C4 \uC2E4\uD328\uD574\uB3C4 \uC870\uC6A9\uD788 \uB118\uC5B4\uAC04\uB2E4. \uCDE8\uD5A5\uC744 \uAE30\uC5B5\uD558\uC9C0 \uBABB\uD558\uB294 \uAC83\uACFC \uB300\uD654\uB97C \uBABB \uD558\uB294\n * \uAC83\uC740 \uB2E4\uB978 \uC77C\uC774\uACE0, \uD6C4\uC790\uB97C \uC804\uC790 \uB54C\uBB38\uC5D0 \uB9C9\uC73C\uBA74 \uC548 \uB41C\uB2E4.\n */\nexport interface TuiPreferences {\n hangulMode: boolean;\n}\n\nexport function preferencesPath(env: NodeJS.ProcessEnv = process.env): string {\n return join(dataDirectory(env), 'tui.json');\n}\n\n/**\n * \uC544\uC9C1 \uACE0\uB978 \uC801\uC774 \uC5C6\uC744 \uB54C\uC758 \uAE30\uBCF8\uAC12.\n *\n * \uB85C\uCF00\uC77C\uC774 \uD55C\uAD6D\uC5B4\uBA74 \uD55C\uAE00\uB85C \uC2DC\uC791\uD55C\uB2E4. \uD55C\uAD6D\uC5B4 \uD658\uACBD\uC5D0\uC11C \uC4F0\uB294 \uC0AC\uB78C\uC774 \uB9E4\uBC88 Ctrl+Space\n * \uB97C \uB20C\uB7EC\uC57C \uD55C\uB2E4\uBA74, \uADF8 \uC790\uCCB4\uAC00 \uC6B0\uB9AC\uAC00 \uC5C6\uC560\uB824\uB358 \uBD88\uD3B8\uC774\uB2E4.\n */\nexport function localeDefaultHangul(env: NodeJS.ProcessEnv = process.env): boolean {\n const locale = env.LC_ALL || env.LC_CTYPE || env.LANG || '';\n return /^ko(_|-|\\.|$)/i.test(locale.trim());\n}\n\nexport async function readPreferences(env: NodeJS.ProcessEnv = process.env): Promise<TuiPreferences> {\n const fallback: TuiPreferences = { hangulMode: localeDefaultHangul(env) };\n try {\n const raw = JSON.parse(await readFile(preferencesPath(env), 'utf8')) as Record<string, unknown>;\n return typeof raw.hangulMode === 'boolean' ? { hangulMode: raw.hangulMode } : fallback;\n } catch {\n return fallback;\n }\n}\n\nexport async function writePreferences(\n preferences: TuiPreferences,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n try {\n const path = preferencesPath(env);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(preferences, null, 2)}\\n`, 'utf8');\n } catch {\n // \uCDE8\uD5A5\uC744 \uBABB \uC801\uB294\uB2E4\uACE0 \uB300\uD654\uB97C \uB9C9\uC9C0 \uC54A\uB294\uB2E4.\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["useEffect", "useState", "Box", "Text", "useApp", "useInput", "useEffect", "useRef", "useState", "Box", "Text", "useInput", "maximumScroll", "useState", "Box", "Text", "useInput", "Box", "Text", "useEffect", "useRef", "useState", "stringWidth", "jamo", "stringWidth", "useState", "useRef", "stdin", "useEffect", "cursor", "inserted", "jsx", "jsxs", "Box", "Text", "jsx", "jsxs", "useState", "useInput", "Box", "Text", "useEffect", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useEffect", "useInput", "Box", "Text", "useEffect", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useEffect", "useInput", "Box", "Text", "useEffect", "useState", "stdout", "jsx", "jsxs", "Box", "Text", "useEffect", "useState", "useRef", "useInput", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useInput", "Box", "Text", "useEffect", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useEffect", "useInput", "Box", "Text", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useInput", "Box", "Text", "jsx", "jsxs", "useApp", "useState", "useInput", "useEffect", "Box", "Text", "ESC", "jsx"]
7
- }