From f38252d21e8a3ef642ef4399d8c9dfcb9e68f9e1 Mon Sep 17 00:00:00 2001 From: chyoo Date: Wed, 15 Jul 2026 14:08:30 +0900 Subject: [PATCH] feat: add global AI guide to LMS launcher --- package-lock.json | 21 +- package.json | 1 + src/main/index.ts | 295 +++++++++++------- src/preload/index.ts | 6 + .../public/autoware-viewer/slam_temp.png | Bin 23147 -> 0 bytes src/renderer/src/App.tsx | 81 ++++- src/renderer/src/components/Sidebar.tsx | 5 +- src/renderer/src/env.d.ts | 4 + src/renderer/src/features/AiGuideView.tsx | 97 ++++++ .../src/features/workspace/ModuleListRow.tsx | 50 ++- .../src/features/workspace/ModuleListView.tsx | 3 + .../workspace/WorkspaceTerminalPanel.tsx | 2 +- .../src/features/workspace/sourceSettings.ts | 12 +- .../src/features/workspace/useQaChat.ts | 133 ++++++-- .../workspace/useWorkspaceModuleControl.ts | 18 +- .../workspace/useWorkspaceTerminal.ts | 44 ++- tsconfig.node.tsbuildinfo | 2 +- 17 files changed, 605 insertions(+), 169 deletions(-) delete mode 100644 src/renderer/public/autoware-viewer/slam_temp.png create mode 100644 src/renderer/src/features/AiGuideView.tsx diff --git a/package-lock.json b/package-lock.json index 84921e5..8eb339d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lms", - "version": "1.0.4", + "version": "1.0.19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lms", - "version": "1.0.4", + "version": "1.0.19", "dependencies": { "@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/utils": "^4.0.0", @@ -16,6 +16,7 @@ "driver.js": "^1.4.0", "lucide-react": "^1.14.0", "monaco-editor": "^0.55.1", + "node-pty": "^1.1.0", "react-markdown": "^10.1.0", "remark-gfm": "^4.0.1", "socket.io-client": "^4.8.3" @@ -7410,6 +7411,22 @@ "node": ">=10" } }, + "node_modules/node-pty": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/node-pty/-/node-pty-1.1.0.tgz", + "integrity": "sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^7.1.0" + } + }, + "node_modules/node-pty/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, "node_modules/node-releases": { "version": "2.0.44", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", diff --git a/package.json b/package.json index 17c1d71..28f7ea4 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "driver.js": "^1.4.0", "lucide-react": "^1.14.0", "monaco-editor": "^0.55.1", + "node-pty": "^1.1.0", "react-markdown": "^10.1.0", "remark-gfm": "^4.0.1", "socket.io-client": "^4.8.3" diff --git a/src/main/index.ts b/src/main/index.ts index cf0dbb6..4b62638 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,6 +1,8 @@ import { app, BrowserWindow, Menu, globalShortcut, ipcMain, screen } from 'electron' import type { WebContents } from 'electron' import { spawn, type ChildProcessWithoutNullStreams } from 'child_process' +import * as pty from 'node-pty' +import type { IPty } from 'node-pty' import { createWriteStream, existsSync } from 'fs' import { cp, mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'fs/promises' import { homedir } from 'os' @@ -15,7 +17,7 @@ let splashWindow: BrowserWindow | null = null const MIN_SPLASH_VISIBLE_MS = 2000 let splashVisibleStartedAt = 0 let splashCloseTimer: NodeJS.Timeout | null = null -const terminalProcesses = new Map() +const terminalProcesses = new Map() const terminalStopTimers = new Map() const intentionalTerminalStops = new Set() const moduleCacheRoot = resolve(homedir(), '.caches') @@ -45,7 +47,8 @@ const workspaceGitIgnoreLines = [ '*.py[cod]', '.pytest_cache/', '.mypy_cache/', - '.cache/' + '.cache/', + '.autonomy-studio-git.json' ] const workspaceGitPathspec = [ '--', @@ -489,7 +492,7 @@ function formatDockerRuntime(status: string): string { if (!runtime) return '실행 중' const normalized = runtime.toLowerCase() - if (normalized === 'less than a second') return '<1 sec' + if (normalized === 'less than a second') return '1 sec' return runtime .replace(/\babout\s+/gi, '') @@ -872,14 +875,16 @@ function parseGitStatus(stdout: string): GitChangedFile[] { const rawPath = line.slice(3).trim() const filePath = rawPath.includes(' -> ') ? rawPath.split(' -> ').at(-1)?.trim() ?? rawPath : rawPath if (isGeneratedWorkspacePath(filePath)) return null - const statusCode = x === '?' && y === '?' ? '?' : x.trim() || y.trim() || 'M' + const xStatus = x.trim() + const yStatus = y.trim() + const statusCode = xStatus === '?' && yStatus === '?' ? '?' : xStatus || yStatus || 'M' - return { - path: filePath, - status: mapGitStatusCode(statusCode), - staged: x !== ' ' && x !== '?', - unstaged: y !== ' ' || (x === '?' && y === '?') - } + return { + path: filePath, + status: mapGitStatusCode(statusCode), + staged: xStatus !== '' && xStatus !== '?', + unstaged: yStatus !== '' + } }) .filter((file): file is GitChangedFile => Boolean(file)) } @@ -2354,6 +2359,43 @@ async function startWorkspaceModule( return { ok: true, message: '실행 요청을 보냈습니다.' } } +async function buildWorkspaceModule( + moduleName: string, + workspaceRoot?: string | null, + folderName?: string | null, + _gpuEnabled?: boolean | null, + rosDomainId?: string | null, + runtimeImages?: RuntimeImageArtifact[] | null, +): Promise<{ ok: boolean; message: string }> { + const resolvedWorkspaceRoot = expandUserPath(workspaceRoot) + if (!resolvedWorkspaceRoot) throw new Error('워크스페이스 경로가 설정되어 있지 않습니다.') + const targetFolderName = folderName?.trim() + if (!targetFolderName) throw new Error('모듈 폴더명이 없습니다.') + + const moduleRoot = await findWorkspaceModuleRoot(moduleName, resolvedWorkspaceRoot, targetFolderName) + if (!moduleRoot) throw new Error('설치된 모듈을 찾을 수 없습니다.') + const dockerInfo = parseModuleDockerInfo(targetFolderName) + if (!dockerInfo || !isAllowedContainerName(dockerInfo.containerKey)) throw new Error('모듈 폴더명 형식이 올바르지 않습니다.') + + await prepareRuntimeImages(runtimeImages) + await runCommand( + 'docker', + [ + 'run', '--rm', '--name', `${dockerInfo.containerKey}-build`, + '--volume', `${moduleRoot}:/autoware:rw`, + '-u', 'root', '--net=host', + '-e', `ROS_DOMAIN_ID=${String(rosDomainId ?? process.env.ROS_DOMAIN_ID ?? '0').trim() || '0'}`, + '-v', '/etc/localtime:/etc/localtime:ro', + '--entrypoint', '/bin/bash', autowareDockerImage, + '-lc', 'cd /autoware && source /opt/ros/humble/setup.bash && colcon build --symlink-install' + ], + undefined, + undefined, + 900000 + ) + return { ok: true, message: '빌드가 완료되었습니다.' } +} + async function startRemoteWorkspaceModule( targetInput: RemoteWorkspaceTarget, moduleName: string, @@ -2364,7 +2406,7 @@ async function startRemoteWorkspaceModule( runtimeImages?: RuntimeImageArtifact[] | null, ): Promise<{ ok: boolean; message: string }> { const target = normalizeRemoteTarget(targetInput) - const targetFolderName = folderName?.trim() + const targetFolderName = folderName?.trim() || moduleName if (!targetFolderName) throw new Error('모듈 폴더명이 없습니다.') const dockerInfo = parseModuleDockerInfo(targetFolderName) @@ -2459,21 +2501,9 @@ async function startRemoteWorkspaceModule( ...expandRemotePathVar('ROOT'), `FOLDER=${quoteShellSingle(targetFolderName)}`, 'MODULE_PATH="$ROOT/$FOLDER"', - `BUILD_CONTAINER=${quoteShellSingle(`${dockerInfo.containerKey}-build`)}`, - `DOCKER_IMAGE_NAME=${quoteShellSingle(autowareDockerImage)}`, - `ROS_DOMAIN_ID_VALUE=${quoteShellSingle(String(rosDomainId ?? process.env.ROS_DOMAIN_ID ?? '0').trim() || '0')}`, - 'docker rm -f "$BUILD_CONTAINER" >/dev/null 2>&1 || true', - 'docker run --rm \\', - ' --name "$BUILD_CONTAINER" \\', - ' --volume="$MODULE_PATH:/autoware:rw" \\', - ' -u root \\', - ' --net=host \\', - ' -e ROS_DOMAIN_ID="$ROS_DOMAIN_ID_VALUE" \\', - ' -v /etc/localtime:/etc/localtime:ro \\', - ' --entrypoint /bin/bash \\', - ' "$DOCKER_IMAGE_NAME" -lc "cd /autoware && rm -rf build install log && source /opt/ros/humble/setup.bash && colcon build --symlink-install"' + 'true' ].join('\n'), - 900000 + 30000 ) await runSsh( @@ -2494,6 +2524,42 @@ async function startRemoteWorkspaceModule( return { ok: true, message: '실행 요청을 보냈습니다.' } } +async function buildRemoteWorkspaceModule( + targetInput: RemoteWorkspaceTarget, + moduleName: string, + folderName?: string | null, + _gpuEnabled?: boolean | null, + rosDomainId?: string | null, + _runtimeImages?: RuntimeImageArtifact[] | null, +): Promise<{ ok: boolean; message: string }> { + const target = normalizeRemoteTarget(targetInput) + const targetFolderName = folderName?.trim() || moduleName + const dockerInfo = parseModuleDockerInfo(targetFolderName) + if (!dockerInfo || !isAllowedContainerName(dockerInfo.containerKey)) throw new Error('모듈 폴더명 형식이 올바르지 않습니다.') + + await runSsh(target, [ + 'set -e', + `ROOT=${quoteShellSingle(target.workspaceRoot)}`, + ...expandRemotePathVar('ROOT'), + `FOLDER=${quoteShellSingle(targetFolderName)}`, + 'MODULE_PATH="$ROOT/$FOLDER"', + '[ -d "$MODULE_PATH" ] || { echo "설치된 모듈을 찾을 수 없습니다." >&2; exit 1; }', + `BUILD_CONTAINER=${quoteShellSingle(`${dockerInfo.containerKey}-build`)}`, + `ROS_DOMAIN_ID_VALUE=${quoteShellSingle(String(rosDomainId ?? process.env.ROS_DOMAIN_ID ?? '0').trim() || '0')}`, + 'docker rm -f "$BUILD_CONTAINER" >/dev/null 2>&1 || true', + 'docker run --rm \\', + ' --name "$BUILD_CONTAINER" \\', + ' --volume="$MODULE_PATH:/autoware:rw" \\', + ' -u root \\', + ' --net=host \\', + ' -e ROS_DOMAIN_ID="$ROS_DOMAIN_ID_VALUE" \\', + ' -v /etc/localtime:/etc/localtime:ro \\', + ' --entrypoint /bin/bash \\', + ` ${quoteShellSingle(autowareDockerImage)} -lc "cd /autoware && source /opt/ros/humble/setup.bash && colcon build --symlink-install"` + ].join('\n'), 900000) + return { ok: true, message: '빌드가 완료되었습니다.' } +} + async function stopWorkspaceModule( moduleName: string, workspaceRoot?: string | null, @@ -2510,7 +2576,12 @@ async function stopWorkspaceModule( const statuses = await readDockerStatuses().catch(() => new Map()) const current = statuses.get(dockerInfo.containerKey) - if (!current?.exists) return { ok: true, message: '중지할 컨테이너가 없습니다.' } + const buildContainer = `${dockerInfo.containerKey}-build` + const currentBuild = statuses.get(buildContainer) + if (currentBuild?.exists) { + await runCommand('docker', ['rm', '-f', buildContainer], undefined, undefined, 30000).catch(() => undefined) + } + if (!current?.exists) return { ok: true, message: currentBuild?.exists ? '빌드를 중지했습니다.' : '중지할 컨테이너가 없습니다.' } await runCommand('docker', ['stop', dockerInfo.containerKey], undefined, undefined, 30000).catch(async (error) => { if (current.running) throw error @@ -2520,14 +2591,20 @@ async function stopWorkspaceModule( async function stopRemoteWorkspaceModule( targetInput: RemoteWorkspaceTarget, + moduleName: string, folderName?: string | null, ): Promise<{ ok: boolean; message: string }> { const target = normalizeRemoteTarget(targetInput) - const containerKey = remoteContainerKey(folderName) + const targetFolderName = folderName?.trim() || moduleName?.trim() + const containerKey = remoteContainerKey(targetFolderName) if (!containerKey || !isAllowedContainerName(containerKey)) throw new Error('모듈 폴더명 형식이 올바르지 않습니다.') - const currentStatus = await runSshOutput(target, `timeout 12s docker ps -a --filter ${quoteShellSingle(`name=^/${containerKey}$`)} --format "{{.Status}}" 2>/dev/null || true`, 20000) - if (!currentStatus.trim()) return { ok: true, message: '중지할 컨테이너가 없습니다.' } + const [currentStatus, buildStatus] = await Promise.all([ + runSshOutput(target, `timeout 12s docker ps -a --filter ${quoteShellSingle(`name=^/${containerKey}$`)} --format "{{.Status}}" 2>/dev/null || true`, 20000), + runSshOutput(target, `timeout 12s docker ps -a --filter ${quoteShellSingle(`name=^/${containerKey}-build$`)} --format "{{.Status}}" 2>/dev/null || true`, 20000), + ]) + if (buildStatus.trim()) await runSsh(target, `docker rm -f ${quoteShellSingle(`${containerKey}-build`)} >/dev/null 2>&1 || true`, 30000) + if (!currentStatus.trim()) return { ok: true, message: buildStatus.trim() ? '빌드를 중지했습니다.' : '중지할 컨테이너가 없습니다.' } if (/^Up\b/i.test(currentStatus.trim())) { await runSsh(target, `docker stop ${quoteShellSingle(containerKey)}`, 30000) } @@ -2632,7 +2709,7 @@ async function restartRemoteWorkspaceModule( rosDomainId?: string | null, runtimeImages?: RuntimeImageArtifact[] | null, ): Promise<{ ok: boolean; message: string }> { - await stopRemoteWorkspaceModule(target, folderName) + await stopRemoteWorkspaceModule(target, moduleName, folderName) return startRemoteWorkspaceModule(target, moduleName, folderName, rosParamsOverride, gpuEnabled, rosDomainId, runtimeImages) } @@ -2665,10 +2742,12 @@ async function readWorkspaceModuleLogs( async function readRemoteWorkspaceModuleLogs( targetInput: RemoteWorkspaceTarget, + moduleName: string, folderName?: string | null, ): Promise<{ ok: boolean; logs: string; message?: string }> { const target = normalizeRemoteTarget(targetInput) - const containerKey = remoteContainerKey(folderName) + const targetFolderName = folderName?.trim() || moduleName?.trim() + const containerKey = remoteContainerKey(targetFolderName) if (!containerKey || !isAllowedContainerName(containerKey)) throw new Error('모듈 폴더명 형식이 올바르지 않습니다.') const existsOutput = await runSshOutput(target, `timeout 12s docker ps -a --filter ${quoteShellSingle(`name=^/${containerKey}$`)} --format "{{.Names}}" 2>/dev/null || true`, 20000) @@ -2861,7 +2940,7 @@ function stopTerminal(terminalKey: string): void { if (!proc) return intentionalTerminalStops.add(terminalKey) terminalProcesses.delete(terminalKey) - if (!proc.killed) proc.kill() + proc.kill() } function stopTerminalsForWebContents(webContentsId: number): void { @@ -2885,10 +2964,19 @@ function cancelStopTerminal(terminalKey: string): void { terminalStopTimers.delete(terminalKey) } -function writeHiddenTerminalCommand(sender: WebContents, sessionId: string, proc: ChildProcessWithoutNullStreams, command: string): void { +function writeHiddenTerminalCommand(sender: WebContents, sessionId: string, proc: IPty, command: string): void { sender.send('terminal-suppress-data', sessionId, `${command}\r\n`) sender.send('terminal-suppress-data', sessionId, `${command}\n`) - proc.stdin.write(`${command}\n`) + proc.write(`${command}\n`) +} + +function resizeTerminal(sender: WebContents, sessionId: string, cols?: number, rows?: number): boolean { + const proc = terminalProcesses.get(getTerminalKey(sender.id, sessionId)) + if (!proc) return false + const safeCols = Math.max(20, Math.min(300, Math.floor(cols ?? 80))) + const safeRows = Math.max(5, Math.min(120, Math.floor(rows ?? 24))) + proc.resize(safeCols, safeRows) + return true } async function resolveModuleTerminalRoot(moduleName?: string, workspaceRoot?: string | null, folderName?: string | null): Promise { @@ -2898,6 +2986,30 @@ async function resolveModuleTerminalRoot(moduleName?: string, workspaceRoot?: st return moduleRoot } +function terminalEnvironment(cols: number, rows: number): Record { + return Object.fromEntries( + Object.entries({ + ...process.env, + TERM: 'xterm-256color', + COLORTERM: 'truecolor', + COLUMNS: String(cols), + LINES: String(rows) + }).filter((entry): entry is [string, string] => typeof entry[1] === 'string') + ) +} + +function attachTerminalProcess(sender: WebContents, sessionId: string, terminalKey: string, proc: IPty): void { + terminalProcesses.set(terminalKey, proc) + proc.onData((data) => { + if (!sender.isDestroyed()) sender.send('terminal-data', sessionId, data) + }) + proc.onExit(({ exitCode }) => { + terminalProcesses.delete(terminalKey) + if (intentionalTerminalStops.delete(terminalKey)) return + if (!sender.isDestroyed()) sender.send('terminal-data', sessionId, `\r\n[terminal exited: ${exitCode}]\r\n`) + }) +} + function registerTerminalHandlers(): void { ipcMain.handle('terminal-start', async (event, moduleName?: string, cols?: number, rows?: number, sessionId = 'default', workspaceRoot?: string | null, folderName?: string | null) => { const webContentsId = event.sender.id @@ -2911,34 +3023,21 @@ function registerTerminalHandlers(): void { await mkdir(terminalCwd, { recursive: true }) const existingProc = terminalProcesses.get(terminalKey) - if (existingProc && !existingProc.killed) { + if (existingProc) { return true } const safeCols = Math.max(20, Math.min(300, Math.floor(cols ?? 80))) const safeRows = Math.max(5, Math.min(120, Math.floor(rows ?? 24))) - const proc = spawn('script', ['-q', '/dev/null', '-c', buildWorkspaceShellCommand(moduleName, terminalCwd, safeCols, safeRows)], { + const proc = pty.spawn('/bin/bash', ['--noprofile', '--norc', '-c', buildWorkspaceShellCommand(moduleName, terminalCwd, safeCols, safeRows)], { cwd: terminalCwd, - env: { - ...process.env, - TERM: 'xterm-256color', - COLORTERM: 'truecolor', - COLUMNS: String(safeCols), - LINES: String(safeRows) - } + name: 'xterm-256color', + cols: safeCols, + rows: safeRows, + env: terminalEnvironment(safeCols, safeRows) }) - terminalProcesses.set(terminalKey, proc) - const send = (data: Buffer): void => { - if (!event.sender.isDestroyed()) event.sender.send('terminal-data', sessionId, data.toString()) - } - proc.stdout.on('data', send) - proc.stderr.on('data', send) - proc.on('close', (code) => { - terminalProcesses.delete(terminalKey) - if (intentionalTerminalStops.delete(terminalKey)) return - if (!event.sender.isDestroyed()) event.sender.send('terminal-data', sessionId, `\r\n[terminal exited: ${code ?? 'unknown'}]\r\n`) - }) + attachTerminalProcess(event.sender, sessionId, terminalKey, proc) event.sender.once('destroyed', () => stopTerminalsForWebContents(webContentsId)) return true }) @@ -2954,34 +3053,21 @@ function registerTerminalHandlers(): void { await mkdir(terminalCwd, { recursive: true }) const existingProc = terminalProcesses.get(terminalKey) - if (existingProc && !existingProc.killed) { + if (existingProc) { return true } const safeCols = Math.max(20, Math.min(300, Math.floor(cols ?? 80))) const safeRows = Math.max(5, Math.min(120, Math.floor(rows ?? 24))) - const proc = spawn('script', ['-q', '/dev/null', '-c', buildWorkspaceShellCommand(moduleName, terminalCwd, safeCols, safeRows)], { + const proc = pty.spawn('/bin/bash', ['--noprofile', '--norc', '-c', buildWorkspaceShellCommand(moduleName, terminalCwd, safeCols, safeRows)], { cwd: terminalCwd, - env: { - ...process.env, - TERM: 'xterm-256color', - COLORTERM: 'truecolor', - COLUMNS: String(safeCols), - LINES: String(safeRows) - } + name: 'xterm-256color', + cols: safeCols, + rows: safeRows, + env: terminalEnvironment(safeCols, safeRows) }) - terminalProcesses.set(terminalKey, proc) - const send = (data: Buffer): void => { - if (!event.sender.isDestroyed()) event.sender.send('terminal-data', sessionId, data.toString()) - } - proc.stdout.on('data', send) - proc.stderr.on('data', send) - proc.on('close', (code) => { - terminalProcesses.delete(terminalKey) - if (intentionalTerminalStops.delete(terminalKey)) return - if (!event.sender.isDestroyed()) event.sender.send('terminal-data', sessionId, `\r\n[terminal exited: ${code ?? 'unknown'}]\r\n`) - }) + attachTerminalProcess(event.sender, sessionId, terminalKey, proc) event.sender.once('destroyed', () => stopTerminalsForWebContents(webContentsId)) return true }) @@ -2999,12 +3085,12 @@ function registerTerminalHandlers(): void { if (!resolved) return false const existingProc = terminalProcesses.get(terminalKey) - if (existingProc && !existingProc.killed) return true + if (existingProc) return true const safeCols = Math.max(20, Math.min(300, Math.floor(cols ?? 80))) const safeRows = Math.max(5, Math.min(120, Math.floor(rows ?? 24))) const target = normalizeRemoteTarget(resolved.target) - const proc = spawn('ssh', [ + const proc = pty.spawn('ssh', [ '-tt', '-p', String(target.port), @@ -3019,45 +3105,35 @@ function registerTerminalHandlers(): void { `${target.user}@${target.host}`, buildWorkspaceShellCommand(moduleName, resolved.moduleRoot, safeCols, safeRows) ], { - env: { - ...process.env, - TERM: 'xterm-256color', - COLORTERM: 'truecolor', - COLUMNS: String(safeCols), - LINES: String(safeRows) - } + name: 'xterm-256color', + cols: safeCols, + rows: safeRows, + env: terminalEnvironment(safeCols, safeRows) }) - terminalProcesses.set(terminalKey, proc) - const send = (data: Buffer): void => { - if (!event.sender.isDestroyed()) event.sender.send('terminal-data', sessionId, data.toString()) - } - proc.stdout.on('data', send) - proc.stderr.on('data', send) - proc.on('close', (code) => { - terminalProcesses.delete(terminalKey) - if (intentionalTerminalStops.delete(terminalKey)) return - if (!event.sender.isDestroyed()) event.sender.send('terminal-data', sessionId, `\r\n[terminal exited: ${code ?? 'unknown'}]\r\n`) - }) + attachTerminalProcess(event.sender, sessionId, terminalKey, proc) event.sender.once('destroyed', () => stopTerminalsForWebContents(webContentsId)) return true }) + ipcMain.handle('terminal-resize', (event, cols?: number, rows?: number, sessionId = 'default') => resizeTerminal(event.sender, sessionId, cols, rows)) + ipcMain.handle('local-workspace:terminal:resize', (event, cols?: number, rows?: number, sessionId = 'default') => resizeTerminal(event.sender, sessionId, cols, rows)) + ipcMain.handle('remote-workspace:terminal:resize', (event, _target: RemoteWorkspaceTarget, cols?: number, rows?: number, sessionId = 'default') => resizeTerminal(event.sender, sessionId, cols, rows)) ipcMain.on('terminal-write', (event, data: string, sessionId = 'default') => { - terminalProcesses.get(getTerminalKey(event.sender.id, sessionId))?.stdin.write(data) + terminalProcesses.get(getTerminalKey(event.sender.id, sessionId))?.write(data) }) ipcMain.on('local-workspace:terminal:write', (event, data: string, sessionId = 'default') => { - terminalProcesses.get(getTerminalKey(event.sender.id, sessionId))?.stdin.write(data) + terminalProcesses.get(getTerminalKey(event.sender.id, sessionId))?.write(data) }) ipcMain.on('remote-workspace:terminal:write', (event, data: string, sessionId = 'default') => { - terminalProcesses.get(getTerminalKey(event.sender.id, sessionId))?.stdin.write(data) + terminalProcesses.get(getTerminalKey(event.sender.id, sessionId))?.write(data) }) ipcMain.handle('terminal-change-directory', async (event, moduleName: string, sessionId = 'default', workspaceRoot?: string | null, folderName?: string | null) => { const terminalKey = getTerminalKey(event.sender.id, sessionId) cancelStopTerminal(terminalKey) const proc = terminalProcesses.get(terminalKey) - if (!proc || proc.killed) return false + if (!proc) return false const terminalCwd = await resolveModuleTerminalRoot(moduleName, workspaceRoot, folderName).catch((error) => { event.sender.send('terminal-data', sessionId, `\r\n[terminal error: ${error instanceof Error ? error.message : 'workspace not found'}]\r\n`) return null @@ -3071,7 +3147,7 @@ function registerTerminalHandlers(): void { const terminalKey = getTerminalKey(event.sender.id, sessionId) cancelStopTerminal(terminalKey) const proc = terminalProcesses.get(terminalKey) - if (!proc || proc.killed) return false + if (!proc) return false const terminalCwd = await resolveModuleTerminalRoot(moduleName, workspaceRoot, folderName).catch((error) => { event.sender.send('terminal-data', sessionId, `\r\n[terminal error: ${error instanceof Error ? error.message : 'workspace not found'}]\r\n`) return null @@ -3085,7 +3161,7 @@ function registerTerminalHandlers(): void { const terminalKey = getTerminalKey(event.sender.id, sessionId) cancelStopTerminal(terminalKey) const proc = terminalProcesses.get(terminalKey) - if (!proc || proc.killed) return false + if (!proc) return false const resolved = await resolveRemoteGitModuleRoot(targetInput, moduleName, folderName).catch((error) => { event.sender.send('terminal-data', sessionId, `\r\n[terminal error: ${error instanceof Error ? error.message : 'workspace not found'}]\r\n`) return null @@ -3096,13 +3172,13 @@ function registerTerminalHandlers(): void { }) ipcMain.on('terminal-stop', (event, sessionId = 'default') => { - scheduleStopTerminal(getTerminalKey(event.sender.id, sessionId)) + stopTerminal(getTerminalKey(event.sender.id, sessionId)) }) ipcMain.on('local-workspace:terminal:stop', (event, sessionId = 'default') => { - scheduleStopTerminal(getTerminalKey(event.sender.id, sessionId)) + stopTerminal(getTerminalKey(event.sender.id, sessionId)) }) ipcMain.on('remote-workspace:terminal:stop', (event, sessionId = 'default') => { - scheduleStopTerminal(getTerminalKey(event.sender.id, sessionId)) + stopTerminal(getTerminalKey(event.sender.id, sessionId)) }) } @@ -3275,6 +3351,7 @@ function registerLocalWorkspaceHandlers(): void { ipcMain.handle('local-workspace:modules:install', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => installModuleFromCache(moduleName, workspaceRoot, folderName, templateRepositoryUrl, studentRepositoryUrl, options)) ipcMain.handle('local-workspace:modules:delete', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null) => deleteWorkspaceModule(moduleName, workspaceRoot, folderName)) ipcMain.handle('local-workspace:modules:start', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null, rosParams?: string | null, gpuEnabled?: boolean | null, rosDomainId?: string | null, runtimeImages?: RuntimeImageArtifact[] | null) => startWorkspaceModule(moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages)) + ipcMain.handle('local-workspace:modules:build', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null, gpuEnabled?: boolean | null, rosDomainId?: string | null, runtimeImages?: RuntimeImageArtifact[] | null) => buildWorkspaceModule(moduleName, workspaceRoot, folderName, gpuEnabled, rosDomainId, runtimeImages)) ipcMain.handle('local-workspace:modules:stop', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null) => stopWorkspaceModule(moduleName, workspaceRoot, folderName)) ipcMain.handle('local-workspace:modules:stop-many', (_event, modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string | null) => stopWorkspaceModules(modules, workspaceRoot)) ipcMain.handle('local-workspace:modules:stop-running', () => stopRunningWorkspaceContainers()) @@ -3284,11 +3361,12 @@ function registerLocalWorkspaceHandlers(): void { ipcMain.handle('remote-workspace:modules:list', (_event, target: RemoteWorkspaceTarget, modules?: CourseModuleInput[] | null) => collectRemoteAvailableModules(target, modules)) ipcMain.handle('remote-workspace:modules:install', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => installRemoteWorkspaceModule(target, moduleName, folderName, templateRepositoryUrl, studentRepositoryUrl, options)) ipcMain.handle('remote-workspace:modules:start', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null, rosParams?: string | null, gpuEnabled?: boolean | null, rosDomainId?: string | null, runtimeImages?: RuntimeImageArtifact[] | null) => startRemoteWorkspaceModule(target, moduleName, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages)) - ipcMain.handle('remote-workspace:modules:stop', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null) => stopRemoteWorkspaceModule(target, folderName)) + ipcMain.handle('remote-workspace:modules:build', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null, gpuEnabled?: boolean | null, rosDomainId?: string | null, runtimeImages?: RuntimeImageArtifact[] | null) => buildRemoteWorkspaceModule(target, moduleName, folderName, gpuEnabled, rosDomainId, runtimeImages)) + ipcMain.handle('remote-workspace:modules:stop', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null) => stopRemoteWorkspaceModule(target, moduleName, folderName)) ipcMain.handle('remote-workspace:modules:stop-many', (_event, target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null }>) => stopRemoteWorkspaceModules(target, modules)) ipcMain.handle('remote-workspace:modules:reset-session', (_event, target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null }>) => resetRemoteWorkspaceSession(target, modules)) ipcMain.handle('remote-workspace:modules:restart', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null, rosParams?: string | null, gpuEnabled?: boolean | null, rosDomainId?: string | null, runtimeImages?: RuntimeImageArtifact[] | null) => restartRemoteWorkspaceModule(target, moduleName, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages)) - ipcMain.handle('remote-workspace:modules:logs', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null) => readRemoteWorkspaceModuleLogs(target, folderName)) + ipcMain.handle('remote-workspace:modules:logs', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null) => readRemoteWorkspaceModuleLogs(target, moduleName, folderName)) ipcMain.handle('remote-workspace:git:status', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null, selectedFilePath?: string | null) => readRemoteWorkspaceGitStatus(target, moduleName, folderName, selectedFilePath)) ipcMain.handle('remote-workspace:git:submit', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null, message?: string | null, authorName?: string | null, authorEmail?: string | null, submissionId?: string | null) => submitRemoteWorkspaceGitChanges(target, moduleName, folderName, message, authorName, authorEmail, submissionId)) ipcMain.handle('remote-workspace:git:restore-file', (_event, target: RemoteWorkspaceTarget, moduleName: string, folderName?: string | null, filePath?: string | null, status?: GitChangedFile['status'] | null) => restoreRemoteWorkspaceGitFile(target, moduleName, folderName, filePath, status)) @@ -3400,7 +3478,7 @@ function openLearningVideoWindow(owner: BrowserWindow | null, input: LearningVid const url = input.url?.trim() ?? '' const videoId = getYoutubeVideoIdFromEmbedUrl(url) if (!videoId) return { ok: false, message: '지원하지 않는 동영상 URL입니다.' } - const watchUrl = `https://www.youtube.com/watch?v=${videoId}` + const embedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1&rel=0` const videoWindow = new BrowserWindow({ width: 1080, @@ -3422,7 +3500,9 @@ function openLearningVideoWindow(owner: BrowserWindow | null, input: LearningVid }) videoWindow.webContents.setWindowOpenHandler(() => ({ action: 'deny' })) - videoWindow.loadURL(watchUrl).catch((error) => { + videoWindow.loadURL(embedUrl, { + httpReferrer: 'https://workspace.autonomystudio.net/' + }).catch((error) => { console.error('[learning-video] load failed', error) }) @@ -3446,6 +3526,7 @@ app.whenReady().then(() => { ipcMain.handle('modules:install', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => installModuleFromCache(moduleName, workspaceRoot, folderName, templateRepositoryUrl, studentRepositoryUrl, options)) ipcMain.handle('modules:delete', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null) => deleteWorkspaceModule(moduleName, workspaceRoot, folderName)) ipcMain.handle('modules:start', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null, rosParams?: string | null, gpuEnabled?: boolean | null, rosDomainId?: string | null, runtimeImages?: RuntimeImageArtifact[] | null) => startWorkspaceModule(moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages)) + ipcMain.handle('modules:build', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null, gpuEnabled?: boolean | null, rosDomainId?: string | null, runtimeImages?: RuntimeImageArtifact[] | null) => buildWorkspaceModule(moduleName, workspaceRoot, folderName, gpuEnabled, rosDomainId, runtimeImages)) ipcMain.handle('modules:stop', (_event, moduleName: string, workspaceRoot?: string | null, folderName?: string | null) => stopWorkspaceModule(moduleName, workspaceRoot, folderName)) ipcMain.handle('modules:stop-many', (_event, modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string | null) => stopWorkspaceModules(modules, workspaceRoot)) ipcMain.handle('modules:stop-running', () => stopRunningWorkspaceContainers()) diff --git a/src/preload/index.ts b/src/preload/index.ts index aae4c6f..7cc474e 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -109,6 +109,7 @@ contextBridge.exposeInMainWorld('modules', { install: (moduleName: string, workspaceRoot?: string, folderName?: string, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => ipcRenderer.invoke('modules:install', moduleName, workspaceRoot, folderName, templateRepositoryUrl, studentRepositoryUrl, options), delete: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('modules:delete', moduleName, workspaceRoot, folderName), start: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('modules:start', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages), + build: (moduleName: string, workspaceRoot?: string, folderName?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('modules:build', moduleName, workspaceRoot, folderName, gpuEnabled, rosDomainId, runtimeImages), stop: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('modules:stop', moduleName, workspaceRoot, folderName), stopMany: (modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string) => ipcRenderer.invoke('modules:stop-many', modules, workspaceRoot), stopRunning: () => ipcRenderer.invoke('modules:stop-running'), @@ -127,6 +128,7 @@ contextBridge.exposeInMainWorld('exampleCode', { }) contextBridge.exposeInMainWorld('terminal', { start: (moduleName?: string, cols?: number, rows?: number, sessionId?: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('terminal-start', moduleName, cols, rows, sessionId, workspaceRoot, folderName), + resize: (cols?: number, rows?: number, sessionId?: string) => ipcRenderer.invoke('terminal-resize', cols, rows, sessionId), changeDirectory: (moduleName: string, sessionId?: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('terminal-change-directory', moduleName, sessionId, workspaceRoot, folderName), write: (data: string, sessionId?: string) => ipcRenderer.send('terminal-write', data, sessionId), stop: (sessionId?: string) => ipcRenderer.send('terminal-stop', sessionId), @@ -164,6 +166,7 @@ contextBridge.exposeInMainWorld('localWorkspace', { install: (moduleName: string, workspaceRoot?: string, folderName?: string, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => ipcRenderer.invoke('local-workspace:modules:install', moduleName, workspaceRoot, folderName, templateRepositoryUrl, studentRepositoryUrl, options), delete: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:modules:delete', moduleName, workspaceRoot, folderName), start: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('local-workspace:modules:start', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages), + build: (moduleName: string, workspaceRoot?: string, folderName?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('local-workspace:modules:build', moduleName, workspaceRoot, folderName, gpuEnabled, rosDomainId, runtimeImages), stop: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:modules:stop', moduleName, workspaceRoot, folderName), stopMany: (modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string) => ipcRenderer.invoke('local-workspace:modules:stop-many', modules, workspaceRoot), stopRunning: () => ipcRenderer.invoke('local-workspace:modules:stop-running'), @@ -185,6 +188,7 @@ contextBridge.exposeInMainWorld('localWorkspace', { }, terminal: { start: (moduleName?: string, cols?: number, rows?: number, sessionId?: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:terminal:start', moduleName, cols, rows, sessionId, workspaceRoot, folderName), + resize: (cols?: number, rows?: number, sessionId?: string) => ipcRenderer.invoke('local-workspace:terminal:resize', cols, rows, sessionId), changeDirectory: (moduleName: string, sessionId?: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:terminal:change-directory', moduleName, sessionId, workspaceRoot, folderName), write: (data: string, sessionId?: string) => ipcRenderer.send('local-workspace:terminal:write', data, sessionId), stop: (sessionId?: string) => ipcRenderer.send('local-workspace:terminal:stop', sessionId), @@ -217,6 +221,7 @@ contextBridge.exposeInMainWorld('remoteWorkspace', { list: (target: RemoteWorkspaceTarget, modules?: Array<{ sortOrder?: number | null; category: string; name: string; folderName: string; templateRepositoryUrl?: string | null }>) => ipcRenderer.invoke('remote-workspace:modules:list', target, modules), install: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => ipcRenderer.invoke('remote-workspace:modules:install', target, moduleName, folderName, templateRepositoryUrl, studentRepositoryUrl, options), start: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('remote-workspace:modules:start', target, moduleName, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages), + build: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('remote-workspace:modules:build', target, moduleName, folderName, gpuEnabled, rosDomainId, runtimeImages), stop: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:modules:stop', target, moduleName, folderName), stopMany: (target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null }>) => ipcRenderer.invoke('remote-workspace:modules:stop-many', target, modules), resetSession: (target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null }>) => ipcRenderer.invoke('remote-workspace:modules:reset-session', target, modules), @@ -232,6 +237,7 @@ contextBridge.exposeInMainWorld('remoteWorkspace', { }, terminal: { start: (target: RemoteWorkspaceTarget, moduleName?: string, cols?: number, rows?: number, sessionId?: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:terminal:start', target, moduleName, cols, rows, sessionId, folderName), + resize: (target: RemoteWorkspaceTarget, cols?: number, rows?: number, sessionId?: string) => ipcRenderer.invoke('remote-workspace:terminal:resize', target, cols, rows, sessionId), changeDirectory: (target: RemoteWorkspaceTarget, moduleName: string, sessionId?: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:terminal:change-directory', target, moduleName, sessionId, folderName), write: (data: string, sessionId?: string) => ipcRenderer.send('remote-workspace:terminal:write', data, sessionId), stop: (sessionId?: string) => ipcRenderer.send('remote-workspace:terminal:stop', sessionId), diff --git a/src/renderer/public/autoware-viewer/slam_temp.png b/src/renderer/public/autoware-viewer/slam_temp.png deleted file mode 100644 index 0c5ea8bd2d8615419f32a6531a4837b10ca83667..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23147 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 diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 4237430..41a3cb1 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -19,6 +19,7 @@ import MaterialsModal from './features/curriculum/MaterialsModal' import { fetchCurriculum, fetchStudentCourses, getDownloadResourceSizeLabel, getDownloadResourceWeek, resolveDownloadUrl } from './features/curriculum/curriculumApi' import type { CurriculumWeek, DownloadResource, LearningStat, StudentCourseOption } from './features/curriculum/types' import { getContextHelpSteps } from './features/help/contextHelp' +import AiGuideView from './features/AiGuideView' import type { PlatformFilter } from './features/platforms/PlatformFilterTabs' import PlatformSelectModal from './features/platforms/PlatformSelectModal' import PlatformSelectionPanel from './features/platforms/PlatformSelectionPanel' @@ -653,7 +654,7 @@ function LocalPcWorkspaceMockup({ const textMid = dark ? 'text-white/70' : 'text-[#4f596b]' const textDim = dark ? 'text-white/45' : 'text-[#727b8c]' const studentSlug = makeStudentSlug(studentEmail) - const clonePathPreview = makePlatformWorkspaceRoot(configuredWorkspaceRoot, studentSlug, weekNumber, platformKey) + const clonePathPreview = makePlatformWorkspaceRoot(configuredWorkspaceRoot, studentSlug, courseKey, weekNumber, platformKey) const remoteRuntimeRoot = `/tmp/autonomy-studio/sessions/${`${platformId}-${studentSlug}-week-${weekNumber}`.replace(/[^a-zA-Z0-9_.-]+/g, '-')}` const { visualizationStacks, @@ -730,7 +731,7 @@ function LocalPcWorkspaceMockup({ curriculumModuleKey, remoteWorkspace, remoteWorkspaceTargetKey, - pollingActive: activeIdeActivity === 'modules', + pollingActive: true, applyModuleParameterOverrides }) const readGitStatus = useCallback((module: ModuleRow, selectedPath: string | null) => ( @@ -2621,6 +2622,7 @@ function LocalPcWorkspaceMockup({ onDeleteModule={(module, options) => void deleteModule(module, options)} onUpdateModuleParameters={(module, rosParams) => void updateModuleParameters(module, rosParams)} onStartModule={(module) => void runModuleControl(module, 'start')} + onBuildModule={(module) => void runModuleControl(module, 'build')} onStopModule={(module) => void runModuleControl(module, 'stop')} onRestartModule={(module) => void runModuleControl(module, 'restart')} onInstallAll={() => void installAllModules()} @@ -2709,6 +2711,7 @@ export default function App(): React.JSX.Element { const [studentCoursesLoaded, setStudentCoursesLoaded] = useState(false) const [selectedCourseId, setSelectedCourseId] = useState(() => window.localStorage.getItem(SELECTED_COURSE_STORAGE_KEY) ?? '') const [courseSelectionVisible, setCourseSelectionVisible] = useState(false) + const [outerView, setOuterView] = useState<'curriculum' | 'guide'>('curriculum') const [selectedWeekState, setSelectedWeekState] = useState(null) const [activeLearningStep, setActiveLearningStep] = useState(null) const [curriculumRefreshSignal, setCurriculumRefreshSignal] = useState(0) @@ -2914,6 +2917,32 @@ export default function App(): React.JSX.Element { return makeRequest(nextSession.accessToken) }, [applyAuthSession, clearAuthSession, getFreshAccessToken]) + const { + aiPending: guideAiPending, + aiTypingMessageId: guideAiTypingMessageId, + qaMessagesLoading: guideMessagesLoading, + displayedAiMessages: guideAiMessages, + aiConversationHistory: guideAiConversationHistory, + activeAiConversation: guideActiveAiConversation, + selectedAiConversationId: guideSelectedAiConversationId, + viewingAiHistory: guideViewingAiHistory, + chatAvailable: guideChatAvailable, + stopAiResponse: stopGuideAiResponse, + sendQaMessage: sendGuideQaMessage, + selectAiConversation: selectGuideAiConversation, + startNewAiConversation: startGuideAiConversation, + deleteAiConversation: deleteGuideAiConversation + } = useQaChat({ + accessToken: authSession?.accessToken ?? '', + weekNumber: 0, + globalScope: true, + apiBaseUrl: LMS_API_BASE_URL, + socketBaseUrl: LMS_SOCKET_ORIGIN, + socketPath: LMS_SOCKET_PATH, + getFreshAccessToken, + onTitlebarNotice: showTitlebarNotice + }) + useEffect(() => { let cancelled = false @@ -3689,13 +3718,21 @@ export default function App(): React.JSX.Element { await loadCurriculum() setPlatformModalOpen(true) } - const navigateSidebar = (item: 'curriculum' | 'studio' | 'guide' | 'settings'): void => { + const navigateSidebar = (item: 'curriculum' | 'studio' | 'guide'): void => { if (item === 'curriculum') { + setOuterView('curriculum') setLocalPcLayoutOpen(false) setRecentSessionModalOpen(false) if (!userSidebarCollapsed) setSidebarCollapsed(false) return } + if (item === 'guide') { + setOuterView('guide') + setLocalPcLayoutOpen(false) + setRecentSessionModalOpen(false) + setSidebarCollapsed(true) + return + } if (item === 'studio' && instructorAccount) { showInstructorStudioGuide() return @@ -4006,13 +4043,14 @@ export default function App(): React.JSX.Element { onOpenCourseSelection={() => { setCourseSelectionVisible(true) setLocalPcLayoutOpen(false) + setOuterView('curriculum') }} />
)} -
- {courseSelectionVisible ? ( +
+ {outerView === 'guide' ? ( + void sendGuideQaMessage(content)} + onQuickSubmit={(content) => void sendGuideQaMessage(content, { contextWeek: selectedWeekState?.week })} + onStop={stopGuideAiResponse} + onClear={() => void startGuideAiConversation()} + onSelectHistory={selectGuideAiConversation} + onDeleteHistory={(threadId) => void deleteGuideAiConversation(threadId)} + onClose={() => { + setOuterView('curriculum') + if (!userSidebarCollapsed) setSidebarCollapsed(false) + }} + /> + ) : courseSelectionVisible ? ( delete: (moduleName: string, workspaceRoot?: string, folderName?: string) => Promise<{ ok: boolean }> start: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => Promise<{ ok: boolean; message: string }> + build: (moduleName: string, workspaceRoot?: string, folderName?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => Promise<{ ok: boolean; message: string }> stop: (moduleName: string, workspaceRoot?: string, folderName?: string) => Promise<{ ok: boolean; message: string }> stopMany: (modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string) => Promise<{ ok: boolean; message: string }> stopRunning: () => Promise<{ ok: boolean; message: string }> @@ -177,6 +178,7 @@ interface Window { } terminal: { start: (moduleName?: string, cols?: number, rows?: number, sessionId?: string, workspaceRoot?: string, folderName?: string) => Promise + resize: (cols?: number, rows?: number, sessionId?: string) => Promise changeDirectory: (moduleName: string, sessionId?: string, workspaceRoot?: string, folderName?: string) => Promise write: (data: string, sessionId?: string) => void stop: (sessionId?: string) => void @@ -239,6 +241,7 @@ interface Window { } }> start: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => Promise<{ ok: boolean; message: string }> + build: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => Promise<{ ok: boolean; message: string }> stop: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string) => Promise<{ ok: boolean; message: string }> stopMany: (target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null }>) => Promise<{ ok: boolean; message: string }> resetSession: (target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null }>) => Promise<{ ok: boolean; message: string }> @@ -254,6 +257,7 @@ interface Window { } terminal: { start: (target: RemoteWorkspaceTarget, moduleName?: string, cols?: number, rows?: number, sessionId?: string, folderName?: string) => Promise + resize: (target: RemoteWorkspaceTarget, cols?: number, rows?: number, sessionId?: string) => Promise changeDirectory: (target: RemoteWorkspaceTarget, moduleName: string, sessionId?: string, folderName?: string) => Promise write: (data: string, sessionId?: string) => void stop: (sessionId?: string) => void diff --git a/src/renderer/src/features/AiGuideView.tsx b/src/renderer/src/features/AiGuideView.tsx new file mode 100644 index 0000000..145d94a --- /dev/null +++ b/src/renderer/src/features/AiGuideView.tsx @@ -0,0 +1,97 @@ +import { BookOpen, ChevronRight, Code2, LoaderCircle, MessageSquareText, Plus, Sparkles, Trash2, X } from 'lucide-react' +import type React from 'react' +import { useRef, useState } from 'react' +import { ExpandableMarkdownMessage, QaInputBox } from '../components/ChatWidgets' +import type { QaChatMessage, QaChatThread } from './workspace/useQaChat' + +type Props = { + courseTitle: string | null; weekNumber: number | null; weekTitle: string | null + messages: QaChatMessage[]; activeConversation: QaChatThread | null; typingMessageId: string | null + history: QaChatThread[]; selectedHistoryId: string | null; viewingHistory: boolean + loading: boolean; busy: boolean; disabled: boolean + onSubmit: (content: string) => void; onQuickSubmit: (content: string) => void; onStop: () => void; onClear: () => void + onSelectHistory: (threadId: string | null) => void; onDeleteHistory: (threadId: string) => void; onClose: () => void +} + +const quickQuestions = [ + { Icon: BookOpen, label: '이번 주차 요약', prompt: '현재 주차의 학습 목표와 진행 순서를 간단히 정리해줘.' }, + { Icon: Code2, label: '실습 시작 방법', prompt: '현재 주차 실습을 시작하기 전에 확인할 내용을 알려줘.' } +] + +const formatDate = (value?: string): string => { + if (!value) return '' + const date = new Date(value) + return Number.isNaN(date.getTime()) ? '' : new Intl.DateTimeFormat('ko-KR', { month: 'numeric', day: 'numeric' }).format(date) +} + +const formatTime = (value?: string): string => { + if (!value) return '' + const date = new Date(value) + return Number.isNaN(date.getTime()) ? '' : new Intl.DateTimeFormat('ko-KR', { hour: '2-digit', minute: '2-digit' }).format(date) +} + +export default function AiGuideView(props: Props): React.JSX.Element { + const { + courseTitle, weekNumber, weekTitle, messages, activeConversation, typingMessageId, history, selectedHistoryId, viewingHistory, + loading, busy, disabled, onSubmit, onQuickSubmit, onStop, onClear, onSelectHistory, onDeleteHistory, onClose + } = props + const [selectedQuestionId, setSelectedQuestionId] = useState(null) + const [switchingConversation, setSwitchingConversation] = useState(false) + const [deleteConfirmThread, setDeleteConfirmThread] = useState(null) + const questionRefs = useRef>({}) + const conversationScrollRef = useRef(null) + const contextLabel = weekNumber && weekTitle ? `${weekNumber}주차 · ${weekTitle}` : '선택된 학습 주차 없음' + const latestAssistantMessageId = [...messages].reverse().find((message) => message.role === 'assistant')?.id + const questionMessages = messages.filter((message) => message.role === 'user') + + const selectConversation = (threadId: string | null): void => { + setSwitchingConversation(true) + setSelectedQuestionId(null) + onSelectHistory(threadId) + window.requestAnimationFrame(() => window.requestAnimationFrame(() => { + conversationScrollRef.current?.scrollTo({ top: conversationScrollRef.current.scrollHeight, behavior: 'auto' }) + window.setTimeout(() => setSwitchingConversation(false), 1000) + })) + } + + return ( +
+
+ AI 가이드 + +
+
+ +
+
+ {loading ?
이전 대화를 불러오는 중
: disabled ?
AI 가이드를 준비하고 있습니다
:
+ {messages.length === 0 &&

무엇이 궁금한가요?

개념, 실습 순서, 오류 원인처럼 학습에 필요한 내용을 질문하세요.

} + {messages.map((message) =>
{ questionRefs.current[message.id] = node } : undefined} className={message.role === 'user' ? 'flex w-full justify-end' : 'w-full'}>
{message.role === 'user' ?

{message.content}

: <><>{(message.isTyping || message.id === typingMessageId) && 생각 중}}
{message.status === 'CANCELED' &&

응답이 중단됨

}
)} + {busy &&
생각 중
} +
} +
+
+ {switchingConversation &&
대화 불러오는 중
} +
+ +
+ {deleteConfirmThread &&
대화 삭제

이 대화 내역을 삭제할까요?

{deleteConfirmThread.title || '이전 대화'}

삭제한 대화와 답변은 복구할 수 없습니다.

} +
+ ) +} diff --git a/src/renderer/src/features/workspace/ModuleListRow.tsx b/src/renderer/src/features/workspace/ModuleListRow.tsx index 13570fd..03ae505 100644 --- a/src/renderer/src/features/workspace/ModuleListRow.tsx +++ b/src/renderer/src/features/workspace/ModuleListRow.tsx @@ -1,4 +1,4 @@ -import { Download, FolderOpen, Play, RefreshCw, Square, Trash2 } from 'lucide-react' +import { Download, FolderOpen, Hammer, Play, RefreshCw, Square, Trash2 } from 'lucide-react' import type { LucideIcon } from 'lucide-react' import type React from 'react' @@ -25,6 +25,7 @@ type ModuleListRowProps = { onInstallModule: (module: Module) => void onDeleteModule: (module: Module) => void onStartModule: (module: Module) => void + onBuildModule: (module: Module) => void onStopModule: (module: Module) => void onRestartModule: (module: Module) => void } @@ -85,6 +86,7 @@ export default function ModuleListRow({ onInstallModule, onDeleteModule, onStartModule, + onBuildModule, onStopModule, onRestartModule }: ModuleListRowProps): React.JSX.Element { @@ -105,8 +107,16 @@ export default function ModuleListRow({ { label: '재시작', Icon: RefreshCw, tone: 'neutral', action: onRestartModule }, { label: '중지', Icon: Square, tone: 'warning', action: onStopModule } ] - : module.state === 'stopped' - ? [{ label: '실행', Icon: Play, tone: 'start', action: onStartModule }] + : module.state === 'stopped' && controlling + ? [ + { label: '빌드', Icon: Hammer, tone: 'neutral', action: onBuildModule }, + { label: '중지', Icon: Square, tone: 'warning', action: onStopModule } + ] + : module.state === 'stopped' + ? [ + { label: '빌드', Icon: Hammer, tone: 'neutral', action: onBuildModule }, + { label: '실행', Icon: Play, tone: 'start', action: onStartModule } + ] : [] const installAction = module.state === 'uninstalled' ? { label: '설치', Icon: Download, tone: 'install' as ModuleActionTone } @@ -203,20 +213,26 @@ export default function ModuleListRow({ )} {controlActions.map(({ label, Icon, tone, action }) => ( - + (() => { + const canCancelBuild = module.state === 'stopped' && controlling && label === '중지' + const disabled = busy && !canCancelBuild + return ( + + ) + })() ))} diff --git a/src/renderer/src/features/workspace/ModuleListView.tsx b/src/renderer/src/features/workspace/ModuleListView.tsx index 6b6d975..93329ab 100644 --- a/src/renderer/src/features/workspace/ModuleListView.tsx +++ b/src/renderer/src/features/workspace/ModuleListView.tsx @@ -23,6 +23,7 @@ type ModuleListViewProps = { onDeleteModule: (module: ModuleRow, options: { deleteRepository: boolean }) => void onUpdateModuleParameters: (module: ModuleRow, parameters: ModuleParameterPair[]) => void onStartModule: (module: ModuleRow) => void + onBuildModule: (module: ModuleRow) => void onStopModule: (module: ModuleRow) => void onRestartModule: (module: ModuleRow) => void onInstallAll: () => void @@ -44,6 +45,7 @@ export default function ModuleListView({ onDeleteModule, onUpdateModuleParameters, onStartModule, + onBuildModule, onStopModule, onRestartModule, onInstallAll, @@ -134,6 +136,7 @@ export default function ModuleListView({ onInstallModule={onInstallModule} onDeleteModule={setDeleteConfirmModule} onStartModule={onStartModule} + onBuildModule={onBuildModule} onStopModule={onStopModule} onRestartModule={onRestartModule} /> diff --git a/src/renderer/src/features/workspace/WorkspaceTerminalPanel.tsx b/src/renderer/src/features/workspace/WorkspaceTerminalPanel.tsx index 68f2815..6e620d4 100644 --- a/src/renderer/src/features/workspace/WorkspaceTerminalPanel.tsx +++ b/src/renderer/src/features/workspace/WorkspaceTerminalPanel.tsx @@ -35,7 +35,7 @@ function WorkspaceTerminalPanel({
diff --git a/src/renderer/src/features/workspace/sourceSettings.ts b/src/renderer/src/features/workspace/sourceSettings.ts index 0c39693..ad58784 100644 --- a/src/renderer/src/features/workspace/sourceSettings.ts +++ b/src/renderer/src/features/workspace/sourceSettings.ts @@ -9,18 +9,22 @@ export const defaultStudioSourceSettings: StudioSourceSettings = { rosDomainId: '77' } -export function makeWeekWorkspaceRoot(workspaceRoot: string, studentSlug: string, weekNumber: number): string { +function normalizeCoursePathSegment(courseKey: string): string { + return courseKey.trim().replace(/[^a-zA-Z0-9_-]+/g, '-') || 'default-course' +} + +export function makeWeekWorkspaceRoot(workspaceRoot: string, studentSlug: string, courseKey: string, weekNumber: number): string { const normalizedRoot = (workspaceRoot || defaultStudioSourceSettings.workspaceRoot).replace(/\/+$/, '') - const suffix = `${studentSlug}/week-${weekNumber}` + const suffix = `${studentSlug}/${normalizeCoursePathSegment(courseKey)}/week-${weekNumber}` if (normalizedRoot === suffix || normalizedRoot.endsWith(`/${suffix}`)) { return normalizedRoot } return `${normalizedRoot}/${suffix}` } -export function makePlatformWorkspaceRoot(workspaceRoot: string, studentSlug: string, weekNumber: number, platformKey: string): string { +export function makePlatformWorkspaceRoot(workspaceRoot: string, studentSlug: string, courseKey: string, weekNumber: number, platformKey: string): string { const normalizedRoot = (workspaceRoot || defaultStudioSourceSettings.workspaceRoot).replace(/\/+$/, '') - if (platformKey === 'futuredrive-local-pc') return makeWeekWorkspaceRoot(normalizedRoot, studentSlug, weekNumber) + if (platformKey === 'futuredrive-local-pc') return makeWeekWorkspaceRoot(normalizedRoot, studentSlug, courseKey, weekNumber) const safePlatformKey = platformKey .replace(/^futuredrive[-_]/i, '') .replace(/[^a-zA-Z0-9_-]+/g, '-') diff --git a/src/renderer/src/features/workspace/useQaChat.ts b/src/renderer/src/features/workspace/useQaChat.ts index 4df91af..be7751c 100644 --- a/src/renderer/src/features/workspace/useQaChat.ts +++ b/src/renderer/src/features/workspace/useQaChat.ts @@ -15,10 +15,20 @@ export type QaChatMessage = { status?: 'ACTIVE' | 'CANCELED' } +export type QaChatThread = { + id: string + title: string + status: 'OPEN' | 'WAITING_INSTRUCTOR' | 'RESOLVED' | 'ARCHIVED' + lastMessageAt?: string + messages: QaChatMessage[] +} + type ChatThreadResponse = { id: string type: 'AI' | 'INSTRUCTOR' | 'MIXED' - status: 'OPEN' | 'WAITING_INSTRUCTOR' | 'RESOLVED' | 'ARCHIVED' + status: QaChatThread['status'] + title: string + lastMessageAt?: string messages: Array<{ id: string senderType: 'STUDENT' | 'AI' | 'INSTRUCTOR' | 'SYSTEM' @@ -43,6 +53,7 @@ type ChatNotificationPayload = { type UseQaChatOptions = { accessToken: string weekNumber: number + globalScope?: boolean apiBaseUrl: string socketBaseUrl: string socketPath: string @@ -63,6 +74,7 @@ const qaVisibleMessageLimit = 20 export function useQaChat({ accessToken, weekNumber, + globalScope = false, apiBaseUrl, socketBaseUrl, socketPath, @@ -71,12 +83,15 @@ export function useQaChat({ }: UseQaChatOptions) { const [qaMode, setQaMode] = useState('ai') const [aiMessages, setAiMessages] = useState(initialAiChatMessages) + const [aiConversations, setAiConversations] = useState([]) + const [activeAiConversationId, setActiveAiConversationId] = useState(null) + const [selectedAiConversationId, setSelectedAiConversationId] = useState(null) const [teacherMessages, setTeacherMessages] = useState([]) const [teacherThreadStatus, setTeacherThreadStatus] = useState(null) const [chatRefreshSignal, setChatRefreshSignal] = useState(0) const [teacherChatFlash, setTeacherChatFlash] = useState(false) - const [aiMessagesLoading, setAiMessagesLoading] = useState(Boolean(accessToken && weekNumber >= 1)) - const [teacherMessagesLoading, setTeacherMessagesLoading] = useState(Boolean(accessToken && weekNumber >= 1)) + const [aiMessagesLoading, setAiMessagesLoading] = useState(Boolean(accessToken && (globalScope || weekNumber >= 1))) + const [teacherMessagesLoading, setTeacherMessagesLoading] = useState(Boolean(accessToken && (globalScope || weekNumber >= 1))) const [aiPending, setAiPending] = useState(false) const [aiTypingMessageId, setAiTypingMessageId] = useState(null) const [qaCollapseSignal, setQaCollapseSignal] = useState(0) @@ -85,7 +100,9 @@ export function useQaChat({ const aiRevealCancelRef = useRef(false) const expandedAiMessageIdsRef = useRef>(new Set()) - const validChatWeek = Number.isInteger(weekNumber) && weekNumber >= 1 ? weekNumber : null + const validChatWeek = globalScope ? null : Number.isInteger(weekNumber) && weekNumber >= 1 ? weekNumber : null + const chatAvailable = globalScope || validChatWeek !== null + const chatWeekQuery = validChatWeek ? `&week=${validChatWeek}` : '' const requestChatApi = async (path: string, options?: RequestInit): Promise => { const requestAccessToken = accessToken ? await getFreshAccessToken() : null @@ -141,7 +158,7 @@ export function useQaChat({ }, [accessToken, onTitlebarNotice, socketBaseUrl, socketPath]) useEffect(() => { - if (!accessToken || !validChatWeek) { + if (!accessToken || !chatAvailable) { setAiMessagesLoading(false) setTeacherMessagesLoading(false) return @@ -149,11 +166,22 @@ export function useQaChat({ let cancelled = false setAiMessagesLoading(true) - requestChatApi<{ threads: ChatThreadResponse[] }>(`/chat/threads?mode=ai&week=${validChatWeek}`) + requestChatApi<{ threads: ChatThreadResponse[] }>(`/chat/threads?mode=ai${chatWeekQuery}&includeArchived=true`) .then((payload) => { if (cancelled) return - const messages = payload.threads[0]?.messages ?? [] - setAiMessages(messages.length ? toQaMessages(messages) : initialAiChatMessages) + const conversations = payload.threads.map((thread) => ({ + id: thread.id, + title: thread.title, + status: thread.status, + lastMessageAt: thread.lastMessageAt, + messages: toQaMessages(thread.messages) + })) + const activeConversation = conversations.find((thread) => thread.status !== 'ARCHIVED') + setAiConversations(conversations) + setActiveAiConversationId(activeConversation?.id ?? null) + setSelectedAiConversationId(null) + const messages = activeConversation?.messages ?? [] + setAiMessages(messages.length ? messages : initialAiChatMessages) }) .catch(() => { if (!cancelled) setAiMessages(initialAiChatMessages) @@ -163,7 +191,7 @@ export function useQaChat({ }) setTeacherMessagesLoading(true) - requestChatApi<{ threads: ChatThreadResponse[] }>(`/chat/threads?mode=teacher&week=${validChatWeek}`) + requestChatApi<{ threads: ChatThreadResponse[] }>(`/chat/threads?mode=teacher${chatWeekQuery}`) .then((payload) => { if (cancelled) return const thread = payload.threads[0] @@ -183,7 +211,7 @@ export function useQaChat({ return () => { cancelled = true } - }, [accessToken, chatRefreshSignal, validChatWeek]) + }, [accessToken, chatAvailable, chatRefreshSignal, chatWeekQuery]) useEffect(() => { const target = workspaceChatScrollRef.current @@ -236,7 +264,7 @@ export function useQaChat({ setAiPending(false) void requestChatApi<{ message: ChatThreadResponse['messages'][number] | null }>('/chat/ai/cancel-active', { method: 'POST', - body: JSON.stringify({ week: validChatWeek }) + body: JSON.stringify(validChatWeek ? { week: validChatWeek } : {}) }).catch(() => {}) setAiMessages((messages) => [ ...messages, @@ -250,9 +278,9 @@ export function useQaChat({ } } - const sendQaMessage = async (rawContent: string): Promise => { + const sendQaMessage = async (rawContent: string, options?: { contextWeek?: number }): Promise => { const content = rawContent.trim() - if (!content || aiPending || aiTypingMessageId || !validChatWeek) return + if (!content || aiPending || aiTypingMessageId || !chatAvailable) return setQaCollapseSignal((value) => value + 1) if (qaMode !== 'ai') { @@ -266,7 +294,7 @@ export function useQaChat({ try { const response = await requestChatApi<{ message: { id: string; content: string; createdAt: string } }>('/chat/messages', { method: 'POST', - body: JSON.stringify({ mode: 'teacher', content, week: validChatWeek }) + body: JSON.stringify({ mode: 'teacher', content, ...(validChatWeek ? { week: validChatWeek } : {}) }) }) setTeacherMessages((messages) => messages.map((message) => ( message.id === userMessage.id @@ -290,7 +318,8 @@ export function useQaChat({ const userMessage: QaChatMessage = { id: `user-${Date.now()}`, role: 'user', - content + content, + createdAt: new Date().toISOString() } const nextMessages = [...aiMessages, userMessage] @@ -301,14 +330,36 @@ export function useQaChat({ aiAbortControllerRef.current = abortController try { - const response = await requestChatApi<{ message: { id: string; content: string; createdAt: string }; content: string; canceled?: boolean }>('/chat/ai/respond', { + const response = await requestChatApi<{ threadId: string; threadTitle?: string | null; message: { id: string; content: string; createdAt: string }; content: string; canceled?: boolean }>('/chat/ai/respond', { method: 'POST', - body: JSON.stringify({ content, week: validChatWeek }), + body: JSON.stringify({ + content, + ...(validChatWeek ? { week: validChatWeek } : {}), + ...(options?.contextWeek ? { contextWeek: options.contextWeek } : {}) + }), signal: abortController.signal }) aiAbortControllerRef.current = null if (aiRevealCancelRef.current || response.canceled) return const fullContent = response.content ?? '' + setActiveAiConversationId(response.threadId) + setAiConversations((threads) => { + const assistantMessage: QaChatMessage = { + id: response.message.id, + role: 'assistant', + content: fullContent, + createdAt: response.message.createdAt, + keepExpanded: true + } + const nextThread: QaChatThread = { + id: response.threadId, + title: response.threadTitle ?? threads.find((thread) => thread.id === response.threadId)?.title ?? content.slice(0, 42), + status: 'OPEN', + lastMessageAt: response.message.createdAt, + messages: [...nextMessages, assistantMessage] + } + return [nextThread, ...threads.filter((thread) => thread.id !== response.threadId)] + }) expandedAiMessageIdsRef.current.add(response.message.id) setAiPending(false) setAiTypingMessageId(response.message.id) @@ -369,7 +420,7 @@ export function useQaChat({ } const clearQaConversation = async (): Promise => { - if (!validChatWeek) return + if (!chatAvailable) return if (qaMode === 'ai') { aiRevealCancelRef.current = true aiAbortControllerRef.current?.abort() @@ -378,11 +429,20 @@ export function useQaChat({ setAiTypingMessageId(null) } - await requestChatApi<{ deletedCount: number }>(`/chat/threads?mode=${qaMode}&week=${validChatWeek}`, { + await requestChatApi<{ deletedCount: number }>(`/chat/threads?mode=${qaMode}${chatWeekQuery}`, { method: 'DELETE' }) if (qaMode === 'ai') { + if (activeAiConversationId) { + setAiConversations((threads) => threads.map((thread) => ( + thread.id === activeAiConversationId + ? { ...thread, status: 'ARCHIVED', messages: aiMessages } + : thread + ))) + } + setActiveAiConversationId(null) + setSelectedAiConversationId(null) setAiMessages(initialAiChatMessages) return } @@ -396,6 +456,28 @@ export function useQaChat({ if (mode === 'teacher') setTeacherChatFlash(false) } + const selectedAiConversation = selectedAiConversationId + ? aiConversations.find((thread) => thread.id === selectedAiConversationId) ?? null + : null + + const selectAiConversation = (threadId: string | null): void => { + setSelectedAiConversationId(threadId) + } + + const startNewAiConversation = async (): Promise => { + if (activeAiConversationId) { + await clearQaConversation() + return + } + setSelectedAiConversationId(null) + } + + const deleteAiConversation = async (threadId: string): Promise => { + await requestChatApi<{ id: string }>(`/chat/threads/${threadId}`, { method: 'DELETE' }) + setAiConversations((threads) => threads.filter((thread) => thread.id !== threadId)) + if (selectedAiConversationId === threadId) setSelectedAiConversationId(null) + } + return { qaMode, setQaMode: setMode, @@ -407,8 +489,21 @@ export function useQaChat({ qaCollapseSignal, qaMessagesLoading: qaMode === 'ai' ? aiMessagesLoading : teacherMessagesLoading, visibleAiMessages: aiMessages.filter((message) => message.id !== 'welcome').slice(-qaVisibleMessageLimit), + displayedAiMessages: selectedAiConversation + ? selectedAiConversation.messages + : aiMessages.filter((message) => message.id !== 'welcome').slice(-qaVisibleMessageLimit), + aiConversationHistory: aiConversations.filter((thread) => thread.status === 'ARCHIVED'), + activeAiConversation: activeAiConversationId + ? aiConversations.find((thread) => thread.id === activeAiConversationId) ?? null + : null, + selectedAiConversationId, + viewingAiHistory: Boolean(selectedAiConversation), + selectAiConversation, + startNewAiConversation, + deleteAiConversation, visibleTeacherMessages: teacherMessages.slice(-qaVisibleMessageLimit), validChatWeek, + chatAvailable, workspaceChatScrollRef, stopAiResponse, sendQaMessage, diff --git a/src/renderer/src/features/workspace/useWorkspaceModuleControl.ts b/src/renderer/src/features/workspace/useWorkspaceModuleControl.ts index e66ccb1..200ee62 100644 --- a/src/renderer/src/features/workspace/useWorkspaceModuleControl.ts +++ b/src/renderer/src/features/workspace/useWorkspaceModuleControl.ts @@ -38,7 +38,7 @@ type UseWorkspaceModuleControlResult = { installAllModules: () => Promise startAllModules: () => Promise stopAllModules: () => Promise - runModuleControl: (module: ModuleRow, action: 'start' | 'stop' | 'restart') => Promise + runModuleControl: (module: ModuleRow, action: 'start' | 'stop' | 'restart' | 'build') => Promise updateModuleParameters: (module: ModuleRow, parameters: ModuleParameterPair[]) => Promise } @@ -229,7 +229,7 @@ export function useWorkspaceModuleControl({ } }, [availableModules, clonePathPreview, installingModuleName, loadAvailableModules, onTitlebarNotice, remoteModuleStop, remoteWorkspace]) - const runModuleControl = useCallback(async (module: ModuleRow, action: 'start' | 'stop' | 'restart'): Promise => { + const runModuleControl = useCallback(async (module: ModuleRow, action: 'start' | 'stop' | 'restart' | 'build'): Promise => { if (installingModuleName || controllingModuleNames.includes(module.name)) return setControllingModuleNames((names) => (names.includes(module.name) ? names : [...names, module.name])) @@ -239,7 +239,11 @@ export function useWorkspaceModuleControl({ ? remoteWorkspace ? await remoteModuleStop(module) : await window.localWorkspace.modules.stop(module.name, clonePathPreview, module.folderName) - : action === 'restart' + : action === 'build' + ? remoteWorkspace + ? await window.remoteWorkspace.modules.build(getRemoteWorkspaceTarget(), module.name, module.folderName, sourceSettings.gpuEnabled, sourceSettings.rosDomainId, activeRuntimeImages) + : await window.localWorkspace.modules.build(module.name, clonePathPreview, module.folderName, sourceSettings.gpuEnabled, sourceSettings.rosDomainId, activeRuntimeImages) + : action === 'restart' ? remoteWorkspace ? await remoteModuleRestart(module) : await window.localWorkspace.modules.restart(module.name, clonePathPreview, module.folderName, getModuleRosParams(module), sourceSettings.gpuEnabled, sourceSettings.rosDomainId, activeRuntimeImages) @@ -250,7 +254,9 @@ export function useWorkspaceModuleControl({ await loadAvailableModules({ silent: true }) const actionLabel = action === 'stop' ? '종료되었습니다' - : action === 'restart' + : action === 'build' + ? '빌드되었습니다' + : action === 'restart' ? '재시작되었습니다' : '실행되었습니다' onTitlebarNotice(`[${module.name}] ${actionLabel}`, 'info') @@ -259,7 +265,9 @@ export function useWorkspaceModuleControl({ setModuleInstallError(error instanceof Error ? error.message : '모듈 제어 실패') const actionLabel = action === 'stop' ? '종료 실패' - : action === 'restart' + : action === 'build' + ? '빌드 실패' + : action === 'restart' ? '재시작 실패' : '실행 실패' onTitlebarNotice(`[${module.name}] ${actionLabel}`, 'error') diff --git a/src/renderer/src/features/workspace/useWorkspaceTerminal.ts b/src/renderer/src/features/workspace/useWorkspaceTerminal.ts index 0ad6ca7..451cfc9 100644 --- a/src/renderer/src/features/workspace/useWorkspaceTerminal.ts +++ b/src/renderer/src/features/workspace/useWorkspaceTerminal.ts @@ -74,7 +74,10 @@ export function useWorkspaceTerminal({ if (text) window.localWorkspace.terminal.write(text, terminalSessionId) }) .catch((error) => console.error('[terminal] paste failed', error)) - .finally(() => setTerminalContextMenu(null)) + .finally(() => { + setTerminalContextMenu(null) + window.requestAnimationFrame(() => terminalRef.current?.focus()) + }) } const startTerminalResize = (event: React.MouseEvent): void => { @@ -123,7 +126,15 @@ export function useWorkspaceTerminal({ term.loadAddon(fitAddon) term.open(terminalHostRef.current) fitAddon.fit() + term.focus() + term.attachCustomKeyEventHandler((event) => { + if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown'].includes(event.key)) { + event.stopPropagation() + } + return true + }) const terminalElement = terminalHostRef.current + const focusTerminal = (): void => term.focus() const handleTerminalContextMenu = (event: MouseEvent): void => { const selection = term.getSelection().trim() event.preventDefault() @@ -134,6 +145,7 @@ export function useWorkspaceTerminal({ }) } terminalElement.addEventListener('contextmenu', handleTerminalContextMenu) + terminalElement.addEventListener('mousedown', focusTerminal) let terminalReceivedVisibleData = Boolean(terminalOutputBufferRef.current[terminalSessionId]) if (terminalOutputBufferRef.current[terminalSessionId]) { term.write(terminalOutputBufferRef.current[terminalSessionId]) @@ -162,10 +174,29 @@ export function useWorkspaceTerminal({ const inputDisposable = term.onData((data) => terminalApi.write(data, terminalSessionId)) let fallbackPromptTimer: number | null = null - const startTerminal = window.localWorkspace.terminal.start(moduleName, term.cols, term.rows, terminalSessionId, clonePathPreview, moduleFolderName ?? undefined) + let sizeSyncTimer: number | null = null + let startFrame: number | null = null + let startNestedFrame: number | null = null + let disposed = false + const startTerminal = new Promise((resolvePromise) => { + startFrame = window.requestAnimationFrame(() => { + startNestedFrame = window.requestAnimationFrame(() => { + fitAddon.fit() + if (disposed) return resolvePromise(false) + void window.localWorkspace.terminal + .start(moduleName, term.cols, term.rows, terminalSessionId, clonePathPreview, moduleFolderName ?? undefined) + .then(resolvePromise) + .catch(() => resolvePromise(false)) + }) + }) + }) void startTerminal.then((started) => { fitAddon.fit() if (!started) return + sizeSyncTimer = window.setTimeout(() => { + fitAddon.fit() + void terminalApi.resize(term.cols, term.rows, terminalSessionId) + }, 150) fallbackPromptTimer = window.setTimeout(() => { if (terminalFallbackPromptShownRef.current.has(terminalSessionId) && terminalOutputBufferRef.current[terminalSessionId]) return if (terminalReceivedVisibleData || terminalOutputBufferRef.current[terminalSessionId]) return @@ -183,12 +214,21 @@ export function useWorkspaceTerminal({ window.addEventListener('resize', onResize) return () => { + disposed = true + if (startFrame !== null) window.cancelAnimationFrame(startFrame) + if (startNestedFrame !== null) window.cancelAnimationFrame(startNestedFrame) window.removeEventListener('resize', onResize) terminalElement.removeEventListener('contextmenu', handleTerminalContextMenu) + terminalElement.removeEventListener('mousedown', focusTerminal) removeDataListener() removeSuppressListener() inputDisposable.dispose() if (fallbackPromptTimer !== null) window.clearTimeout(fallbackPromptTimer) + if (sizeSyncTimer !== null) window.clearTimeout(sizeSyncTimer) + // Full-screen programs such as vi cannot be restored from a partial raw output buffer. + delete terminalOutputBufferRef.current[terminalSessionId] + terminalFallbackPromptShownRef.current.delete(terminalSessionId) + terminalApi.stop(terminalSessionId) term.dispose() terminalRef.current = null terminalFitRef.current = null diff --git a/tsconfig.node.tsbuildinfo b/tsconfig.node.tsbuildinfo index 350f6a3..b4223b1 100644 --- a/tsconfig.node.tsbuildinfo +++ b/tsconfig.node.tsbuildinfo @@ -1 +1 @@ -{"fileNames":["./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.es2021.d.ts","./node_modules/typescript/lib/lib.es2022.d.ts","./node_modules/typescript/lib/lib.es2023.d.ts","./node_modules/typescript/lib/lib.es2024.d.ts","./node_modules/typescript/lib/lib.esnext.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/typescript/lib/lib.dom.asynciterable.d.ts","./node_modules/typescript/lib/lib.webworker.importscripts.d.ts","./node_modules/typescript/lib/lib.scripthost.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.es2021.promise.d.ts","./node_modules/typescript/lib/lib.es2021.string.d.ts","./node_modules/typescript/lib/lib.es2021.weakref.d.ts","./node_modules/typescript/lib/lib.es2021.intl.d.ts","./node_modules/typescript/lib/lib.es2022.array.d.ts","./node_modules/typescript/lib/lib.es2022.error.d.ts","./node_modules/typescript/lib/lib.es2022.intl.d.ts","./node_modules/typescript/lib/lib.es2022.object.d.ts","./node_modules/typescript/lib/lib.es2022.string.d.ts","./node_modules/typescript/lib/lib.es2022.regexp.d.ts","./node_modules/typescript/lib/lib.es2023.array.d.ts","./node_modules/typescript/lib/lib.es2023.collection.d.ts","./node_modules/typescript/lib/lib.es2023.intl.d.ts","./node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2024.collection.d.ts","./node_modules/typescript/lib/lib.es2024.object.d.ts","./node_modules/typescript/lib/lib.es2024.promise.d.ts","./node_modules/typescript/lib/lib.es2024.regexp.d.ts","./node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2024.string.d.ts","./node_modules/typescript/lib/lib.esnext.array.d.ts","./node_modules/typescript/lib/lib.esnext.collection.d.ts","./node_modules/typescript/lib/lib.esnext.intl.d.ts","./node_modules/typescript/lib/lib.esnext.disposable.d.ts","./node_modules/typescript/lib/lib.esnext.promise.d.ts","./node_modules/typescript/lib/lib.esnext.decorators.d.ts","./node_modules/typescript/lib/lib.esnext.iterator.d.ts","./node_modules/typescript/lib/lib.esnext.float16.d.ts","./node_modules/typescript/lib/lib.esnext.error.d.ts","./node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts","./node_modules/typescript/lib/lib.decorators.d.ts","./node_modules/typescript/lib/lib.decorators.legacy.d.ts","./node_modules/typescript/lib/lib.esnext.full.d.ts","./node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/@types/node/globals.typedarray.d.ts","./node_modules/@types/node/buffer.buffer.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/web-globals/abortcontroller.d.ts","./node_modules/@types/node/web-globals/blob.d.ts","./node_modules/@types/node/web-globals/console.d.ts","./node_modules/@types/node/web-globals/crypto.d.ts","./node_modules/@types/node/web-globals/domexception.d.ts","./node_modules/@types/node/web-globals/encoding.d.ts","./node_modules/@types/node/web-globals/events.d.ts","./node_modules/undici-types/utility.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client-stats.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/round-robin-pool.d.ts","./node_modules/undici-types/h2c-client.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-call-history.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/snapshot-agent.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/socks5-proxy-agent.d.ts","./node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/undici-types/retry-handler.d.ts","./node_modules/undici-types/retry-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/cache-interceptor.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/util.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/eventsource.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/web-globals/fetch.d.ts","./node_modules/@types/node/web-globals/importmeta.d.ts","./node_modules/@types/node/web-globals/messaging.d.ts","./node_modules/@types/node/web-globals/navigator.d.ts","./node_modules/@types/node/web-globals/performance.d.ts","./node_modules/@types/node/web-globals/storage.d.ts","./node_modules/@types/node/web-globals/streams.d.ts","./node_modules/@types/node/web-globals/timers.d.ts","./node_modules/@types/node/web-globals/url.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/inspector.generated.d.ts","./node_modules/@types/node/inspector/promises.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/buffer/index.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/path/posix.d.ts","./node_modules/@types/node/path/win32.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/quic.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/sea.d.ts","./node_modules/@types/node/sqlite.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/iter.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/test/reporters.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/util/types.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/zlib/iter.d.ts","./node_modules/@types/node/index.d.ts","./node_modules/@types/estree/index.d.ts","./node_modules/rollup/dist/rollup.d.ts","./node_modules/rollup/dist/parseAst.d.ts","./node_modules/vite/types/hmrPayload.d.ts","./node_modules/vite/types/customEvent.d.ts","./node_modules/vite/types/hot.d.ts","./node_modules/vite/dist/node/moduleRunnerTransport.d-DJ_mE5sf.d.ts","./node_modules/vite/dist/node/module-runner.d.ts","./node_modules/esbuild/lib/main.d.ts","./node_modules/source-map-js/source-map.d.ts","./node_modules/postcss/lib/previous-map.d.ts","./node_modules/postcss/lib/input.d.ts","./node_modules/postcss/lib/css-syntax-error.d.ts","./node_modules/postcss/lib/declaration.d.ts","./node_modules/postcss/lib/root.d.ts","./node_modules/postcss/lib/warning.d.ts","./node_modules/postcss/lib/lazy-result.d.ts","./node_modules/postcss/lib/no-work-result.d.ts","./node_modules/postcss/lib/processor.d.ts","./node_modules/postcss/lib/result.d.ts","./node_modules/postcss/lib/document.d.ts","./node_modules/postcss/lib/rule.d.ts","./node_modules/postcss/lib/node.d.ts","./node_modules/postcss/lib/comment.d.ts","./node_modules/postcss/lib/container.d.ts","./node_modules/postcss/lib/at-rule.d.ts","./node_modules/postcss/lib/list.d.ts","./node_modules/postcss/lib/postcss.d.ts","./node_modules/postcss/lib/postcss.d.mts","./node_modules/lightningcss/node/ast.d.ts","./node_modules/lightningcss/node/targets.d.ts","./node_modules/lightningcss/node/index.d.ts","./node_modules/vite/types/internal/lightningcssOptions.d.ts","./node_modules/vite/types/internal/cssPreprocessorOptions.d.ts","./node_modules/vite/types/importGlob.d.ts","./node_modules/vite/types/metadata.d.ts","./node_modules/vite/dist/node/index.d.ts","./node_modules/electron-vite/dist/index.d.ts","./node_modules/@babel/types/lib/index.d.ts","./node_modules/@types/babel__generator/index.d.ts","./node_modules/@babel/parser/typings/babel-parser.d.ts","./node_modules/@types/babel__template/index.d.ts","./node_modules/@types/babel__traverse/index.d.ts","./node_modules/@types/babel__core/index.d.ts","./node_modules/@vitejs/plugin-react/dist/index.d.ts","./node_modules/@tailwindcss/vite/dist/index.d.mts","./electron.vite.config.ts","./node_modules/electron/electron.d.ts","./node_modules/@electron-toolkit/utils/dist/index.d.ts","./src/main/index.ts","./node_modules/@electron-toolkit/preload/dist/index.d.ts","./src/preload/index.ts","./node_modules/electron-vite/node.d.ts"],"fileIdsList":[[89,153,161,165,168,170,171,172,177,185,250,257,258],[89,153,161,165,168,170,171,172,185,251],[89,153,161,165,168,170,171,172,185],[89,153,161,165,168,170,171,172,185,260],[89,153,161,165,168,170,171,172,185,249],[89,153,161,165,168,170,171,172,185,251,252,253,254,255],[89,153,161,165,168,170,171,172,185,251,253],[89,150,151,153,161,165,168,170,171,172,185],[89,152,153,161,165,168,170,171,172,185],[153,161,165,168,170,171,172,185],[89,153,161,165,168,170,171,172,185,194],[89,153,154,159,161,164,165,168,170,171,172,174,185,190,203],[89,153,154,155,161,164,165,168,170,171,172,185],[89,153,156,161,165,168,170,171,172,185,204],[89,153,157,158,161,165,168,170,171,172,176,185],[89,153,158,161,165,168,170,171,172,185,190,200],[89,153,159,161,164,165,168,170,171,172,174,185],[89,152,153,160,161,165,168,170,171,172,185],[89,153,161,162,165,168,170,171,172,185],[89,153,161,163,164,165,168,170,171,172,185],[89,152,153,161,164,165,168,170,171,172,185],[89,153,161,164,165,166,168,170,171,172,185,190,203],[89,153,161,164,165,166,168,170,171,172,185,190,192,194],[89,140,153,161,164,165,167,168,170,171,172,174,185,190,203],[89,153,161,164,165,167,168,170,171,172,174,185,190,200,203],[89,153,161,165,167,168,169,170,171,172,185,190,200,203],[87,88,89,90,91,92,93,94,95,96,97,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211],[89,153,161,164,165,168,170,171,172,185],[89,153,161,165,168,170,172,185],[89,153,161,165,168,170,171,172,173,185,203],[89,153,161,164,165,168,170,171,172,174,185,190],[89,153,161,165,168,170,171,172,176,185],[89,153,161,165,168,170,171,172,177,185],[89,153,161,164,165,168,170,171,172,180,185],[89,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210],[89,153,161,165,168,170,171,172,182,185],[89,153,161,165,168,170,171,172,183,185],[89,153,158,161,165,168,170,171,172,174,185,194],[89,153,161,164,165,168,170,171,172,185,186],[89,153,161,165,168,170,171,172,185,187,204,207],[89,153,161,164,165,168,170,171,172,185,190,193,194],[89,153,161,165,168,170,171,172,185,191,194],[89,153,161,165,168,170,171,172,185,192],[89,153,161,165,168,170,171,172,185,194,204],[89,153,161,165,168,170,171,172,185,195],[89,150,153,161,165,168,170,171,172,185,190,197,203],[89,153,161,165,168,170,171,172,185,190,196],[89,153,161,164,165,168,170,171,172,185,198,199],[89,153,161,165,168,170,171,172,185,198,199],[89,153,158,161,165,168,170,171,172,174,185,190,200],[89,153,161,165,168,170,171,172,185,201],[89,153,161,165,168,170,171,172,174,185,202],[89,153,161,165,167,168,170,171,172,183,185,203],[89,153,161,165,168,170,171,172,185,204,205],[89,153,158,161,165,168,170,171,172,185,205],[89,153,161,165,168,170,171,172,185,190,206],[89,153,161,165,168,170,171,172,173,185,207],[89,153,161,165,168,170,171,172,185,208],[89,153,156,161,165,168,170,171,172,185],[89,153,158,161,165,168,170,171,172,185],[89,153,161,165,168,170,171,172,185,204],[89,140,153,161,165,168,170,171,172,185],[89,153,161,165,168,170,171,172,185,203],[89,153,161,165,168,170,171,172,185,209],[89,153,161,165,168,170,171,172,180,185],[89,153,161,165,168,170,171,172,185,199],[89,140,153,161,164,165,166,168,170,171,172,180,185,190,194,203,206,207,209],[89,153,161,165,168,170,171,172,185,190,210],[89,153,161,165,168,170,171,172,185,192,211],[89,153,161,165,168,170,171,172,185,249,256],[89,153,161,164,165,168,170,171,172,185,212],[89,153,161,165,168,170,171,172,185,242,243],[89,153,161,165,168,170,171,172,185,237],[89,153,161,165,168,170,171,172,185,235,237],[89,153,161,165,168,170,171,172,185,226,234,235,236,238,240],[89,153,161,165,168,170,171,172,185,224],[89,153,161,165,168,170,171,172,185,227,232,237,240],[89,153,161,165,168,170,171,172,185,223,240],[89,153,161,165,168,170,171,172,185,227,228,231,232,233,240],[89,153,161,165,168,170,171,172,185,227,228,229,231,232,240],[89,153,161,165,168,170,171,172,185,224,225,226,227,228,232,233,234,236,237,238,240],[89,153,161,165,168,170,171,172,185,240],[89,153,161,165,168,170,171,172,185,222,224,225,226,227,228,229,231,232,233,234,235,236,237,238,239],[89,153,161,165,168,170,171,172,185,222,240],[89,153,161,165,168,170,171,172,185,227,229,230,232,233,240],[89,153,161,165,168,170,171,172,185,231,240],[89,153,161,165,168,170,171,172,185,232,233,237,240],[89,153,161,165,168,170,171,172,185,225,235],[89,153,161,165,168,170,171,172,185,214,248,249],[89,153,161,165,168,170,171,172,185,213,214],[89,104,107,110,111,153,161,165,168,170,171,172,185,203],[89,107,153,161,165,168,170,171,172,185,190,203],[89,107,111,153,161,165,168,170,171,172,185,203],[89,153,161,165,168,170,171,172,185,190],[89,101,153,161,165,168,170,171,172,185],[89,105,153,161,165,168,170,171,172,185],[89,103,104,107,153,161,165,168,170,171,172,185,203],[89,153,161,165,168,170,171,172,174,185,200],[89,153,161,165,168,170,171,172,185,212],[89,101,153,161,165,168,170,171,172,185,212],[89,103,107,153,161,165,168,170,171,172,174,185,203],[89,98,99,100,102,106,153,161,164,165,168,170,171,172,185,190,203],[89,107,116,124,153,161,165,168,170,171,172,185],[89,99,105,153,161,165,168,170,171,172,185],[89,107,134,135,153,161,165,168,170,171,172,185],[89,99,102,107,153,161,165,168,170,171,172,185,194,203,212],[89,107,153,161,165,168,170,171,172,185],[89,103,107,153,161,165,168,170,171,172,185,203],[89,98,153,161,165,168,170,171,172,185],[89,101,102,103,105,106,107,108,109,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,135,136,137,138,139,153,161,165,168,170,171,172,185],[89,107,127,130,153,161,165,168,170,171,172,185],[89,107,116,117,118,153,161,165,168,170,171,172,185],[89,105,107,117,119,153,161,165,168,170,171,172,185],[89,106,153,161,165,168,170,171,172,185],[89,99,101,107,153,161,165,168,170,171,172,185],[89,107,111,117,119,153,161,165,168,170,171,172,185],[89,111,153,161,165,168,170,171,172,185],[89,105,107,110,153,161,165,168,170,171,172,185,203],[89,99,103,107,116,153,161,165,168,170,171,172,185],[89,107,127,153,161,165,168,170,171,172,185],[89,119,153,161,165,168,170,171,172,185],[89,99,103,107,111,153,161,165,168,170,171,172,185],[89,101,107,134,153,161,165,168,170,171,172,185,194,209,212],[89,153,161,164,165,167,168,169,170,171,172,174,185,190,200,203,210,212,214,215,216,217,219,220,221,241,245,246,247,248,249],[89,153,161,165,168,170,171,172,185,216,217,218,219],[89,153,161,165,168,170,171,172,185,216],[89,153,161,165,168,170,171,172,185,217],[89,153,161,165,168,170,171,172,185,244],[89,153,161,165,168,170,171,172,185,214,249],[89,153,154,161,165,166,168,170,171,172,176,177,185,260,261],[89,153,161,165,168,170,171,172,185,260,263]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"8fd575e12870e9944c7e1d62e1f5a73fcf23dd8d3a321f2a2c74c20d022283fe","impliedFormat":1},{"version":"2ab096661c711e4a81cc464fa1e6feb929a54f5340b46b0a07ac6bbf857471f0","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7a3c8b952931daebdfc7a2897c53c0a1c73624593fa070e46bd537e64dcd20a","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"87dc0f382502f5bbce5129bdc0aea21e19a3abbc19259e0b43ae038a9fc4e326","affectsGlobalScope":true,"impliedFormat":1},{"version":"b1cb28af0c891c8c96b2d6b7be76bd394fddcfdb4709a20ba05a7c1605eea0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2fef54945a13095fdb9b84f705f2b5994597640c46afeb2ce78352fab4cb3279","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac77cb3e8c6d3565793eb90a8373ee8033146315a3dbead3bde8db5eaf5e5ec6","affectsGlobalScope":true,"impliedFormat":1},{"version":"56e4ed5aab5f5920980066a9409bfaf53e6d21d3f8d020c17e4de584d29600ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ece9f17b3866cc077099c73f4983bddbcb1dc7ddb943227f1ec070f529dedd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a6282c8827e4b9a95f4bf4f5c205673ada31b982f50572d27103df8ceb8013c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1c9319a09485199c1f7b0498f2988d6d2249793ef67edda49d1e584746be9032","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3a2a0cee0f03ffdde24d89660eba2685bfbdeae955a6c67e8c4c9fd28928eeb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"60037901da1a425516449b9a20073aa03386cce92f7a1fd902d7602be3a7c2e9","affectsGlobalScope":true,"impliedFormat":1},{"version":"d4b1d2c51d058fc21ec2629fff7a76249dec2e36e12960ea056e3ef89174080f","affectsGlobalScope":true,"impliedFormat":1},{"version":"22adec94ef7047a6c9d1af3cb96be87a335908bf9ef386ae9fd50eeb37f44c47","affectsGlobalScope":true,"impliedFormat":1},{"version":"196cb558a13d4533a5163286f30b0509ce0210e4b316c56c38d4c0fd2fb38405","affectsGlobalScope":true,"impliedFormat":1},{"version":"73f78680d4c08509933daf80947902f6ff41b6230f94dd002ae372620adb0f60","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5239f5c01bcfa9cd32f37c496cf19c61d69d37e48be9de612b541aac915805b","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"bde31fd423cd93b0eff97197a3f66df7c93e8c0c335cbeb113b7ff1ac35c23f4","impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ccdaa19852d25ecd84eec365c3bfa16e7859cadecf6e9ca6d0dbbbee439743f","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc2110f7decca6bfb9392e30421cfa1436479e4a6756e8fec6cbc22625d4f881","affectsGlobalScope":true,"impliedFormat":1},{"version":"096116f8fedc1765d5bd6ef360c257b4a9048e5415054b3bf3c41b07f8951b0b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5e01375c9e124a83b52ee4b3244ed1a4d214a6cfb54ac73e164a823a4a7860a","affectsGlobalScope":true,"impliedFormat":1},{"version":"f90ae2bbce1505e67f2f6502392e318f5714bae82d2d969185c4a6cecc8af2fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b58e207b93a8f1c88bbf2a95ddc686ac83962b13830fe8ad3f404ffc7051fb4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1fefabcb2b06736a66d2904074d56268753654805e829989a46a0161cd8412c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"c18a99f01eb788d849ad032b31cafd49de0b19e083fe775370834c5675d7df8e","affectsGlobalScope":true,"impliedFormat":1},{"version":"5247874c2a23b9a62d178ae84f2db6a1d54e6c9a2e7e057e178cc5eea13757fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"10ec5e82144dfac6f04fa5d1d6c11763b3e4dbbac6d99101427219ab3e2ae887","impliedFormat":1},{"version":"615754924717c0b1e293e083b83503c0a872717ad5aa60ed7f1a699eb1b4ea5c","impliedFormat":1},{"version":"14e9acf826baba0ef4b5665704084896e7bcc06f65a9ab13af7e93d27d6b7069","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"21adf13435b9b748529c8cedf80f884e5130b9684188120a686cd2b26a2059c7","impliedFormat":1},{"version":"eec76bf6b9346f3f95fa402621b889489e96930e72295b0369022f332e9b4a6a","impliedFormat":1},{"version":"0ecd58f413f9bc3b7d4383eae31b0c8fc576985cd7404d6f99f8c643543ade74","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"d33ce35e3f9cfcc1d94eca415bdd3bde94d5b153ffdd33e6c4455c029986c630","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"98498b101803bb3dde9f76a56e65c14b75db1cc8bec5f4db72be541570f74fc5","impliedFormat":1},{"version":"4dc59f6e1dbf3d5f66660fceabe6c174d3261b37b696ae1854f0dbaf255fc753","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"436d7b4543b340b0f3eef4310d524242e41369b9652aa9c70428767c4dcac455","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"114f493b30f364255290472111b5a4791d5902c308645670cd0401429cbc6930","impliedFormat":1},{"version":"c3f5289820990ab66b70c7fb5b63cb674001009ff84b13de40619619a9c8175f","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3275d55fac10b799c9546804126239baf020d220136163f763b55a74e50e750","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa68a0a3b7cb32c00e39ee3cd31f8f15b80cac97dce51b6ee7fc14a1e8deb30b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c36e755bced82df7fb6ce8169265d0a7bb046ab4e2cb6d0da0cb72b22033e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7a93de4ff8a63bafe62ba86b89af1df0ccb5e40bb85b0c67d6bbcfdcf96bf3d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"90e85f9bc549dfe2b5749b45fe734144e96cd5d04b38eae244028794e142a77e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e0a5deeb610b2a50a6350bd23df6490036a1773a8a71d70f2f9549ab009e67ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"d2ae155afe8a01cc0ae612d99117cf8ef16692ba7c4366590156fdec1bcf2d8c","impliedFormat":1},{"version":"3f5e5d9be35913db9fea42a63f3df0b7e3c8703b97670a2125587b4dbbd56d7c","impliedFormat":1},{"version":"c8b8968311ec4e5e97b7b5fb8a65efaba455db9bdcfd7fff7fb15f6e317bfba0","impliedFormat":1},{"version":"57c23df0b5f7a8e26363a3849b0bc7763f6b241207157c8e40089d1df4116f35","affectsGlobalScope":true,"impliedFormat":1},{"version":"3b8bc0c17b54081b0878673989216229e575d67a10874e84566a21025a2461ee","impliedFormat":1},{"version":"5b0db5a58b73498792a29bfebc333438e61906fef75da898b410e24e52229e6f","impliedFormat":1},{"version":"dbe055b2b29a7bab2c1ca8f259436306adb43f469dca7e639a02cd3695d3f621","impliedFormat":1},{"version":"1678b04557dca52feab73cc67610918a7f5e25bfdba3e7fa081acd625d93106d","impliedFormat":1},{"version":"aecbf1d9e6a18dab7d92ef8a89a1444b47e1eb6134cb2bb776a26d55ff58c29a","impliedFormat":1},{"version":"2ea729503db9793f2691162fec3dd1118cab62e96d025f8eeb376d43ec293395","impliedFormat":1},{"version":"9ec87fea42b92894b0f209931a880789d43c3397d09dd99c631ae40a2f7071d1","impliedFormat":1},{"version":"c68e88cdfadfb6c8ba5fc38e58a3a166b0beae77b1f05b7d921150a32a5ffb8d","impliedFormat":1},{"version":"2bc7aa4fba46df0bd495425a7c8201437a7d465f83854fac859df2d67f664df3","impliedFormat":1},{"version":"41d17e1ad9a002feb11c8cdd2777e5bbc0cdb1e3f595d237e4dded0b6949983b","impliedFormat":1},{"version":"1fede9296beac11ce8e6b425396a1791f64341f2be85deebb6286faf6e16306e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce697b6a251d9cad53998c7fd3098072df883b525ec45d83530e434dc6d80dc6","impliedFormat":1},{"version":"719412f054e6ecc35489462c9a21bab0323d173a7d04e55b0ace4b5d86fbeb07","impliedFormat":1},{"version":"0eb5d0cbf09de5d34542b977fd6a933bb2e0817bffe8e1a541b2f1ad1b9af1ff","impliedFormat":1},{"version":"fac3e88881b35d3a757ed891ac912b2674792c25e2a1a74e1f5fbc72d19a9792","impliedFormat":1},{"version":"2c2bdaa1d8ead9f68628d6d9d250e46ee8e81aa4898b4769a36956ae15e060fe","impliedFormat":1},{"version":"c32c840c62d8bd7aeb3147aa6754cd2d922b990a6b6634530cb2ebdce5adc8e9","impliedFormat":1},{"version":"5ff4433a2deae4f85ab1377e90a7554ce6b47ae51c69a84ca30a6e22fae85834","impliedFormat":1},{"version":"82b91e4e42e6c41bc7fc1b6c2dc5eba6a2ba98375eb1f210e6ff6bba2d54177e","impliedFormat":1},{"version":"c1fa52b3d014001e8662fa2669d90ea15373958a288e3b83a3b621733d25292a","affectsGlobalScope":true,"impliedFormat":1},{"version":"cbed824fec91efefc7bbdcb8b43d1a531fdbebd0e2ef19481501ff365a93cb70","impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"d0716593b3f2b0451bcf0c24cfa86dec2235c325c89f201934248b7c742715fc","impliedFormat":1},{"version":"ec501101c2a96133a6c695f934c8f6642149cc728571b29cbb7b770984c1088e","impliedFormat":1},{"version":"b214ebcf76c51b115453f69729ee8aa7b7f8eccdae2a922b568a45c2d7ff52f7","impliedFormat":1},{"version":"429c9cdfa7d126255779efd7e6d9057ced2d69c81859bbab32073bad52e9ba76","impliedFormat":1},{"version":"2991bca2cc0f0628a278df2a2ccdb8d6cbcb700f3761abbed62bba137d5b1790","impliedFormat":1},{"version":"5e66972e83eb4dc7123939bf816e6cbd9ad81af5552db1cab84e6bd9c64d2ecc","affectsGlobalScope":true,"impliedFormat":1},{"version":"230763250f20449fa7b3c9273e1967adb0023dc890d4be1553faca658ee65971","impliedFormat":1},{"version":"c3e9078b60cb329d1221f5878e88cecfa3e74460550e605a58fcfb41a66029ff","impliedFormat":1},{"version":"8413d0641f293aed551c7464615b770d34a02dedede889b9591172287d68e773","impliedFormat":1},{"version":"0ea59f7d3e51440baa64f429253759b106cfcbaf51e474cae606e02265b37cf8","impliedFormat":1},{"version":"bc18a1991ba681f03e13285fa1d7b99b03b67ee671b7bc936254467177543890","impliedFormat":1},{"version":"1b241e24f3227d078c06aeda6e050187ad59a4e591f4467abed44d92b084e08d","impliedFormat":1},{"version":"fa94bbf532b7af8f394b95fa310980d6e20bd2d4c871c6a6cb9f70f03750a44b","impliedFormat":1},{"version":"7fde0e1be5c8be204ffbf428abfcf01da2eb0f130e1bc3f539eb7275f4fd1f58","impliedFormat":1},{"version":"e284328553df5f425a5d33d36a0c3fa66b46af9d097cad6f4d2e8696dfdeb0f1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7fa2214bb0d64701bc6f9ce8cde2fd2ff8c571e0b23065fa04a8a5a6beb91511","impliedFormat":1},{"version":"b58040a9d317060d1a5f6e78bb8bd125894fb660feea534fe0e733cf5fdd7d07","impliedFormat":1},{"version":"f1c93e046fb3d9b7f8249629f4b63dc068dd839b824dd0aa39a5e68476dc9420","impliedFormat":1},{"version":"016b29bf4926b80255a108c53a1451717350059da04fcae64d1075f5e93bbb39","impliedFormat":1},{"version":"841983e39bd4cbb463be385e92fda11057cab368bf27100a801c492f1d86cbaa","impliedFormat":1},{"version":"1c4f139ade4f6ebf45463505f8155173e5d7a5305e50e0aae0a5e712d6ff3b48","impliedFormat":1},{"version":"e16b319e5aca1031168de823c4946ff8e29629c4c8cc0ec0fcfe2a8ab2155043","impliedFormat":1},{"version":"e4156ddb25aa0e3b5303d372f26957b36778f0f6bbd4326359269873295e3058","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc1b433a84cae05ddc5672d4823170af78606ad21ecef60dbc4570190cbf1357","impliedFormat":1},{"version":"9d3821bc75c59577e52643324cec92fc2145642e8d17cf7ee07a3181f21d985d","impliedFormat":1},{"version":"7f78cfb2b343838612c192cb251746e3a7c62ac7675726a47e130d9b213f6580","impliedFormat":1},{"version":"201db9cf1687fab1adf5282fcba861f382b32303dc4f67c89d59655e78a25461","impliedFormat":1},{"version":"2c3c5c0f54055e87640f5d233716fd889f3034fc7911d603b642369b0dbeb2a7","impliedFormat":1},{"version":"0a20eaf2e4b1e3c1e1f87f7bccb0c936375b23b022baeea750519b7c9bc6ce83","impliedFormat":1},{"version":"b484ec11ba00e3a2235562a41898d55372ccabe607986c6fa4f4aba72093749f","impliedFormat":1},{"version":"a16b91b27bd6b706c687c88cbc8a7d4ee98e5ed6043026d6b84bda923c0aed67","impliedFormat":1},{"version":"1c9e5b1a17b1fc9b3711fb36e0690421261ab2880f15b145155b5b2ba2ab6c2d","impliedFormat":1},{"version":"99ab6d0d660ce4d21efb52288a39fd35bb3f556980ec5463b1ae8f304a3bbc85","impliedFormat":1},{"version":"6eeded8c7e352be6e0efb83f4935ec752513c4d22043b52522b90849a49a3a11","impliedFormat":1},{"version":"6c1ad90050ffbb151cacc68e2d06ea1a26a945659391e32651f5d42b86fd7f2c","impliedFormat":1},{"version":"afa1c49f8e559e413d57343339db857d2a8159435cf9cf7d4deb41718fff1b88","impliedFormat":1},{"version":"6953d7597831d0860c7034cf4f0419687d263b6b98a4b32e37ce6d49615c36e2","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"ee70b8037ecdf0de6c04f35277f253663a536d7e38f1539d270e4e916d225a3f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a660aa95476042d3fdcc1343cf6bb8fdf24772d31712b1db321c5a4dcc325434","impliedFormat":1},{"version":"a7ca8df4f2931bef2aa4118078584d84a0b16539598eaadf7dce9104dfaa381c","impliedFormat":1},{"version":"11443a1dcfaaa404c68d53368b5b818712b95dd19f188cab1669c39bee8b84b3","impliedFormat":1},{"version":"36977c14a7f7bfc8c0426ae4343875689949fb699f3f84ecbe5b300ebf9a2c55","impliedFormat":1},{"version":"035d0934d304483f07148427a5bd5b98ac265dae914a6b49749fe23fbd893ec7","impliedFormat":99},{"version":"e2ed5b81cbed3a511b21a18ab2539e79ac1f4bc1d1d28f8d35d8104caa3b429f","impliedFormat":99},{"version":"161c8e0690c46021506e32fda85956d785b70f309ae97011fd27374c065cac9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"402e5c534fb2b85fa771170595db3ac0dd532112c8fa44fc23f233bc6967488b","impliedFormat":1},{"version":"52dcc257df5119fb66d864625112ce5033ac51a4c2afe376a0b299d2f7f76e4a","impliedFormat":1},{"version":"e5bab5f871ef708d52d47b3e5d0aa72a08ee7a152f33931d9a60809711a2a9a3","impliedFormat":1},{"version":"e16dc2a81595736024a206c7d5c8a39bfe2e6039208ef29981d0d95434ba8fcf","impliedFormat":1},{"version":"cc4a4903fb698ca1d961d4c10dce658aa3a479faf40509d526f122b044eaf6a4","impliedFormat":1},{"version":"19ee8416e6473ed6c7adb868fa796b5653cf0fa2a337658e677eaa0d134388c3","impliedFormat":1},{"version":"1328ab4e442614b28cdb3d4b414cf68325c0da0dca07287a338d0654b7a00261","impliedFormat":1},{"version":"a039dc21f045919f3cbee2ec13812cc6cc3eebc99dae4be00973230f468d19a6","impliedFormat":1},{"version":"3fbe57af01460e49dcd29df55d6931e1672bc6f1be0fb073d11410bc16f9037d","impliedFormat":1},{"version":"f760be449e8562ec5c09bb5187e8e1eabf3c113c0c58cddda53ef8c69f3e2131","impliedFormat":1},{"version":"44325ed13294fce6ab825b82947bbeed2611db7dad9d9135260192f375e5a189","impliedFormat":1},{"version":"e392e8fb5b514eafc585601c1d781485aa6dd6a320e75daf1064a4c6918a1b45","impliedFormat":1},{"version":"46e4a36e8ddbdfb4e7330e11c81c970dc8b218611df9183d39c41c5f8c653b55","impliedFormat":1},{"version":"370bde134aa8c2abc926d0e99d3a4d5d5dba65c6ee65459137e4f02670cbf841","impliedFormat":1},{"version":"6332f565867cf4a740a70e30f31cefba37ef7cebcf74f22eab8d744fde6d193e","impliedFormat":1},{"version":"2977b7884aedc895a1d0c9c210c7cf3272c29d6959a08a6fa3ff71e0aff08175","impliedFormat":1},{"version":"17f2922d41ddd032830a91371c948cd9ce903b35c95adca72271a54584f19b0b","impliedFormat":1},{"version":"3eed76ede2a1a14d7c9bb0a642041282dcc264811139d3dd275c9fe14efc9840","impliedFormat":1},{"version":"e3cf0611709328b449ec13f8c436712d62003620ce480139fae46ce001c2ee9f","impliedFormat":1},{"version":"8d369483f0c2b9ee388129cfdb6a43bc8112b377e86a41884bd06e19ce04f4c1","impliedFormat":99},{"version":"3fd8a5aefd8c3feb3936ca66f5aa89dff7bf6e6537b4158dbd0f6e0d65ed3b9e","impliedFormat":1},{"version":"a18642ddf216f162052a16cba0944892c4c4c977d3306a87cb673d46abbb0cbf","impliedFormat":1},{"version":"41c41c6e90133bb2a14f7561f29944771886e5535945b2b372e2f6ed6987746e","impliedFormat":1},{"version":"4ec16d7a4e366c06a4573d299e15fe6207fc080f41beac5da06f4af33ea9761e","impliedFormat":1},{"version":"7870becb94cbc11d2d01b77c4422589adcba4d8e59f726246d40cd0d129784d8","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f698624bbbb060ece7c0e51b7236520ebada74b747d7523c7df376453ed6fea","impliedFormat":1},{"version":"f70b8328a15ca1d10b1436b691e134a49bc30dcf3183a69bfaa7ba77e1b78ecd","impliedFormat":1},{"version":"d9030fc0c412a31e7e13d189b9ad032b5177c20217add0f24fd3fff0cf272882","impliedFormat":99},{"version":"e7ba74900e0edb9cb93edb1547cbb65238d26af0e5f10d24be3a61d862262cfd","impliedFormat":99},{"version":"556ccd493ec36c7d7cb130d51be66e147b91cc1415be383d71da0f1e49f742a9","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"95aba78013d782537cc5e23868e736bec5d377b918990e28ed56110e3ae8b958","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"26e0ffceb2198feb1ef460d5d14111c69ad07d44c5a67fd4bfeb74c969aa9afb","impliedFormat":99},{"version":"7757c6ca7a8ad1992401c6aff33633d6a088515be5a39d7ee188b35bfc8e5f8e","impliedFormat":99},{"version":"c10b076ee841362c05de654cdd30ae9e00e7dde4b699a751017554fa5f7fba6d","signature":"8d916869b630869b2798d91a5cfceab8acc6247d81d4042ce14198d01ddebb60"},{"version":"94a0fcd4f758fe669bc78f1c9146f5fc07879783787364ca89ce486b0cf37920","affectsGlobalScope":true,"impliedFormat":1},{"version":"194779039dc8a41af2eefa2ff740594be9cf44333870346c20602031ad73f168","impliedFormat":1},{"version":"1403f3caeb418381eeacfbe13cd314abda9d30ceabb17e82089ab0d92d100dc4","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"2329508bb462ba8f17cc60c4ed5b346618a42eefcaaddcbb0fcbf7f09cfd0a87","impliedFormat":1},{"version":"ab0cb717711176e8c8e7eb1e38d69f742b033f8d055e4827f81a7b2a3c520912","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"2efbc5086f10635b6507392c3d9d073e94d9308a5cf08af5ae4389c250d1791c","affectsGlobalScope":true,"impliedFormat":99}],"root":[259,262,264],"options":{"composite":true,"esModuleInterop":true,"jsx":1,"module":99,"noImplicitAny":false,"noImplicitReturns":true,"noUnusedLocals":true,"noUnusedParameters":true,"skipLibCheck":true,"sourceMap":false,"strict":true,"target":99},"referencedMap":[[259,1],[253,2],[251,3],[263,4],[261,4],[258,5],[256,6],[252,2],[254,7],[255,2],[213,3],[150,8],[151,8],[152,9],[89,10],[153,11],[154,12],[155,13],[87,3],[156,14],[157,15],[158,16],[159,17],[160,18],[161,19],[162,19],[163,20],[164,21],[165,22],[166,23],[90,3],[88,3],[167,24],[168,25],[169,26],[212,27],[170,28],[171,29],[172,28],[173,30],[174,31],[176,32],[177,33],[178,33],[179,33],[180,34],[181,35],[182,36],[183,37],[184,38],[185,39],[186,39],[187,40],[188,3],[189,3],[190,41],[191,42],[192,43],[193,41],[194,44],[195,45],[196,46],[197,47],[198,48],[199,49],[200,50],[201,51],[202,52],[203,53],[204,54],[205,55],[206,56],[207,57],[208,58],[91,28],[92,3],[93,59],[94,60],[95,3],[96,61],[97,3],[141,62],[142,63],[143,64],[144,64],[145,65],[146,3],[147,11],[148,66],[149,63],[209,67],[210,68],[211,69],[257,70],[175,3],[250,5],[265,64],[260,71],[221,3],[242,3],[244,72],[243,3],[238,73],[236,74],[237,75],[225,76],[226,74],[233,77],[224,78],[229,79],[239,3],[230,80],[235,81],[241,82],[240,83],[223,84],[231,85],[232,86],[227,87],[234,73],[228,88],[215,89],[214,90],[222,3],[84,3],[85,3],[15,3],[13,3],[14,3],[19,3],[18,3],[2,3],[20,3],[21,3],[22,3],[23,3],[24,3],[25,3],[26,3],[27,3],[3,3],[28,3],[29,3],[4,3],[30,3],[34,3],[31,3],[32,3],[33,3],[35,3],[36,3],[37,3],[5,3],[38,3],[39,3],[40,3],[41,3],[6,3],[45,3],[42,3],[43,3],[44,3],[46,3],[7,3],[47,3],[52,3],[53,3],[48,3],[49,3],[50,3],[51,3],[8,3],[57,3],[54,3],[55,3],[56,3],[58,3],[9,3],[59,3],[60,3],[61,3],[63,3],[62,3],[64,3],[65,3],[10,3],[66,3],[67,3],[68,3],[11,3],[69,3],[70,3],[71,3],[72,3],[73,3],[1,3],[74,3],[75,3],[12,3],[79,3],[77,3],[82,3],[81,3],[86,3],[76,3],[80,3],[78,3],[83,3],[17,3],[16,3],[116,91],[129,92],[113,93],[130,94],[139,95],[104,96],[105,97],[103,98],[138,99],[133,100],[137,101],[107,102],[126,103],[106,104],[136,105],[101,106],[102,100],[108,107],[109,3],[115,108],[112,107],[99,109],[140,110],[131,111],[119,112],[118,107],[120,113],[123,114],[117,115],[121,116],[134,99],[110,117],[111,118],[124,119],[100,94],[128,120],[127,107],[114,118],[122,121],[125,122],[132,3],[98,3],[135,123],[249,124],[220,125],[219,126],[217,126],[216,3],[218,127],[247,3],[246,3],[245,128],[248,129],[262,130],[264,131]],"affectedFilesPendingEmit":[[262,17],[264,17]],"latestChangedDtsFile":"./src/preload/index.d.ts","version":"5.9.3"} \ No newline at end of file +{"fileNames":["./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.es2021.d.ts","./node_modules/typescript/lib/lib.es2022.d.ts","./node_modules/typescript/lib/lib.es2023.d.ts","./node_modules/typescript/lib/lib.es2024.d.ts","./node_modules/typescript/lib/lib.esnext.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/typescript/lib/lib.dom.asynciterable.d.ts","./node_modules/typescript/lib/lib.webworker.importscripts.d.ts","./node_modules/typescript/lib/lib.scripthost.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.es2021.promise.d.ts","./node_modules/typescript/lib/lib.es2021.string.d.ts","./node_modules/typescript/lib/lib.es2021.weakref.d.ts","./node_modules/typescript/lib/lib.es2021.intl.d.ts","./node_modules/typescript/lib/lib.es2022.array.d.ts","./node_modules/typescript/lib/lib.es2022.error.d.ts","./node_modules/typescript/lib/lib.es2022.intl.d.ts","./node_modules/typescript/lib/lib.es2022.object.d.ts","./node_modules/typescript/lib/lib.es2022.string.d.ts","./node_modules/typescript/lib/lib.es2022.regexp.d.ts","./node_modules/typescript/lib/lib.es2023.array.d.ts","./node_modules/typescript/lib/lib.es2023.collection.d.ts","./node_modules/typescript/lib/lib.es2023.intl.d.ts","./node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2024.collection.d.ts","./node_modules/typescript/lib/lib.es2024.object.d.ts","./node_modules/typescript/lib/lib.es2024.promise.d.ts","./node_modules/typescript/lib/lib.es2024.regexp.d.ts","./node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2024.string.d.ts","./node_modules/typescript/lib/lib.esnext.array.d.ts","./node_modules/typescript/lib/lib.esnext.collection.d.ts","./node_modules/typescript/lib/lib.esnext.intl.d.ts","./node_modules/typescript/lib/lib.esnext.disposable.d.ts","./node_modules/typescript/lib/lib.esnext.promise.d.ts","./node_modules/typescript/lib/lib.esnext.decorators.d.ts","./node_modules/typescript/lib/lib.esnext.iterator.d.ts","./node_modules/typescript/lib/lib.esnext.float16.d.ts","./node_modules/typescript/lib/lib.esnext.error.d.ts","./node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts","./node_modules/typescript/lib/lib.decorators.d.ts","./node_modules/typescript/lib/lib.decorators.legacy.d.ts","./node_modules/typescript/lib/lib.esnext.full.d.ts","./node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/@types/node/globals.typedarray.d.ts","./node_modules/@types/node/buffer.buffer.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/web-globals/abortcontroller.d.ts","./node_modules/@types/node/web-globals/blob.d.ts","./node_modules/@types/node/web-globals/console.d.ts","./node_modules/@types/node/web-globals/crypto.d.ts","./node_modules/@types/node/web-globals/domexception.d.ts","./node_modules/@types/node/web-globals/encoding.d.ts","./node_modules/@types/node/web-globals/events.d.ts","./node_modules/undici-types/utility.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client-stats.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/round-robin-pool.d.ts","./node_modules/undici-types/h2c-client.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-call-history.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/snapshot-agent.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/socks5-proxy-agent.d.ts","./node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/undici-types/retry-handler.d.ts","./node_modules/undici-types/retry-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/cache-interceptor.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/util.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/eventsource.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/web-globals/fetch.d.ts","./node_modules/@types/node/web-globals/importmeta.d.ts","./node_modules/@types/node/web-globals/messaging.d.ts","./node_modules/@types/node/web-globals/navigator.d.ts","./node_modules/@types/node/web-globals/performance.d.ts","./node_modules/@types/node/web-globals/storage.d.ts","./node_modules/@types/node/web-globals/streams.d.ts","./node_modules/@types/node/web-globals/timers.d.ts","./node_modules/@types/node/web-globals/url.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/inspector.generated.d.ts","./node_modules/@types/node/inspector/promises.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/buffer/index.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/path/posix.d.ts","./node_modules/@types/node/path/win32.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/quic.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/sea.d.ts","./node_modules/@types/node/sqlite.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/iter.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/test/reporters.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/util/types.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/zlib/iter.d.ts","./node_modules/@types/node/index.d.ts","./node_modules/@types/estree/index.d.ts","./node_modules/rollup/dist/rollup.d.ts","./node_modules/rollup/dist/parseAst.d.ts","./node_modules/vite/types/hmrPayload.d.ts","./node_modules/vite/types/customEvent.d.ts","./node_modules/vite/types/hot.d.ts","./node_modules/vite/dist/node/moduleRunnerTransport.d-DJ_mE5sf.d.ts","./node_modules/vite/dist/node/module-runner.d.ts","./node_modules/esbuild/lib/main.d.ts","./node_modules/source-map-js/source-map.d.ts","./node_modules/postcss/lib/previous-map.d.ts","./node_modules/postcss/lib/input.d.ts","./node_modules/postcss/lib/css-syntax-error.d.ts","./node_modules/postcss/lib/declaration.d.ts","./node_modules/postcss/lib/root.d.ts","./node_modules/postcss/lib/warning.d.ts","./node_modules/postcss/lib/lazy-result.d.ts","./node_modules/postcss/lib/no-work-result.d.ts","./node_modules/postcss/lib/processor.d.ts","./node_modules/postcss/lib/result.d.ts","./node_modules/postcss/lib/document.d.ts","./node_modules/postcss/lib/rule.d.ts","./node_modules/postcss/lib/node.d.ts","./node_modules/postcss/lib/comment.d.ts","./node_modules/postcss/lib/container.d.ts","./node_modules/postcss/lib/at-rule.d.ts","./node_modules/postcss/lib/list.d.ts","./node_modules/postcss/lib/postcss.d.ts","./node_modules/postcss/lib/postcss.d.mts","./node_modules/lightningcss/node/ast.d.ts","./node_modules/lightningcss/node/targets.d.ts","./node_modules/lightningcss/node/index.d.ts","./node_modules/vite/types/internal/lightningcssOptions.d.ts","./node_modules/vite/types/internal/cssPreprocessorOptions.d.ts","./node_modules/vite/types/importGlob.d.ts","./node_modules/vite/types/metadata.d.ts","./node_modules/vite/dist/node/index.d.ts","./node_modules/electron-vite/dist/index.d.ts","./node_modules/@babel/types/lib/index.d.ts","./node_modules/@types/babel__generator/index.d.ts","./node_modules/@babel/parser/typings/babel-parser.d.ts","./node_modules/@types/babel__template/index.d.ts","./node_modules/@types/babel__traverse/index.d.ts","./node_modules/@types/babel__core/index.d.ts","./node_modules/@vitejs/plugin-react/dist/index.d.ts","./node_modules/@tailwindcss/vite/dist/index.d.mts","./electron.vite.config.ts","./node_modules/electron/electron.d.ts","./node_modules/@electron-toolkit/utils/dist/index.d.ts","./src/main/index.ts","./node_modules/@electron-toolkit/preload/dist/index.d.ts","./src/preload/index.ts","./node_modules/electron-vite/node.d.ts"],"fileIdsList":[[89,153,161,165,168,170,171,172,177,185,250,257,258],[89,153,161,165,168,170,171,172,185,251],[89,153,161,165,168,170,171,172,185],[89,153,161,165,168,170,171,172,185,260],[89,153,161,165,168,170,171,172,185,249],[89,153,161,165,168,170,171,172,185,251,252,253,254,255],[89,153,161,165,168,170,171,172,185,251,253],[89,150,151,153,161,165,168,170,171,172,185],[89,152,153,161,165,168,170,171,172,185],[153,161,165,168,170,171,172,185],[89,153,161,165,168,170,171,172,185,194],[89,153,154,159,161,164,165,168,170,171,172,174,185,190,203],[89,153,154,155,161,164,165,168,170,171,172,185],[89,153,156,161,165,168,170,171,172,185,204],[89,153,157,158,161,165,168,170,171,172,176,185],[89,153,158,161,165,168,170,171,172,185,190,200],[89,153,159,161,164,165,168,170,171,172,174,185],[89,152,153,160,161,165,168,170,171,172,185],[89,153,161,162,165,168,170,171,172,185],[89,153,161,163,164,165,168,170,171,172,185],[89,152,153,161,164,165,168,170,171,172,185],[89,153,161,164,165,166,168,170,171,172,185,190,203],[89,153,161,164,165,166,168,170,171,172,185,190,192,194],[89,140,153,161,164,165,167,168,170,171,172,174,185,190,203],[89,153,161,164,165,167,168,170,171,172,174,185,190,200,203],[89,153,161,165,167,168,169,170,171,172,185,190,200,203],[87,88,89,90,91,92,93,94,95,96,97,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211],[89,153,161,164,165,168,170,171,172,185],[89,153,161,165,168,170,172,185],[89,153,161,165,168,170,171,172,173,185,203],[89,153,161,164,165,168,170,171,172,174,185,190],[89,153,161,165,168,170,171,172,176,185],[89,153,161,165,168,170,171,172,177,185],[89,153,161,164,165,168,170,171,172,180,185],[89,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210],[89,153,161,165,168,170,171,172,182,185],[89,153,161,165,168,170,171,172,183,185],[89,153,158,161,165,168,170,171,172,174,185,194],[89,153,161,164,165,168,170,171,172,185,186],[89,153,161,165,168,170,171,172,185,187,204,207],[89,153,161,164,165,168,170,171,172,185,190,193,194],[89,153,161,165,168,170,171,172,185,191,194],[89,153,161,165,168,170,171,172,185,192],[89,153,161,165,168,170,171,172,185,194,204],[89,153,161,165,168,170,171,172,185,195],[89,150,153,161,165,168,170,171,172,185,190,197,203],[89,153,161,165,168,170,171,172,185,190,196],[89,153,161,164,165,168,170,171,172,185,198,199],[89,153,161,165,168,170,171,172,185,198,199],[89,153,158,161,165,168,170,171,172,174,185,190,200],[89,153,161,165,168,170,171,172,185,201],[89,153,161,165,168,170,171,172,174,185,202],[89,153,161,165,167,168,170,171,172,183,185,203],[89,153,161,165,168,170,171,172,185,204,205],[89,153,158,161,165,168,170,171,172,185,205],[89,153,161,165,168,170,171,172,185,190,206],[89,153,161,165,168,170,171,172,173,185,207],[89,153,161,165,168,170,171,172,185,208],[89,153,156,161,165,168,170,171,172,185],[89,153,158,161,165,168,170,171,172,185],[89,153,161,165,168,170,171,172,185,204],[89,140,153,161,165,168,170,171,172,185],[89,153,161,165,168,170,171,172,185,203],[89,153,161,165,168,170,171,172,185,209],[89,153,161,165,168,170,171,172,180,185],[89,153,161,165,168,170,171,172,185,199],[89,140,153,161,164,165,166,168,170,171,172,180,185,190,194,203,206,207,209],[89,153,161,165,168,170,171,172,185,190,210],[89,153,161,165,168,170,171,172,185,192,211],[89,153,161,165,168,170,171,172,185,249,256],[89,153,161,164,165,168,170,171,172,185,212],[89,153,161,165,168,170,171,172,185,242,243],[89,153,161,165,168,170,171,172,185,237],[89,153,161,165,168,170,171,172,185,235,237],[89,153,161,165,168,170,171,172,185,226,234,235,236,238,240],[89,153,161,165,168,170,171,172,185,224],[89,153,161,165,168,170,171,172,185,227,232,237,240],[89,153,161,165,168,170,171,172,185,223,240],[89,153,161,165,168,170,171,172,185,227,228,231,232,233,240],[89,153,161,165,168,170,171,172,185,227,228,229,231,232,240],[89,153,161,165,168,170,171,172,185,224,225,226,227,228,232,233,234,236,237,238,240],[89,153,161,165,168,170,171,172,185,240],[89,153,161,165,168,170,171,172,185,222,224,225,226,227,228,229,231,232,233,234,235,236,237,238,239],[89,153,161,165,168,170,171,172,185,222,240],[89,153,161,165,168,170,171,172,185,227,229,230,232,233,240],[89,153,161,165,168,170,171,172,185,231,240],[89,153,161,165,168,170,171,172,185,232,233,237,240],[89,153,161,165,168,170,171,172,185,225,235],[89,153,161,165,168,170,171,172,185,214,248,249],[89,153,161,165,168,170,171,172,185,213,214],[89,104,107,110,111,153,161,165,168,170,171,172,185,203],[89,107,153,161,165,168,170,171,172,185,190,203],[89,107,111,153,161,165,168,170,171,172,185,203],[89,153,161,165,168,170,171,172,185,190],[89,101,153,161,165,168,170,171,172,185],[89,105,153,161,165,168,170,171,172,185],[89,103,104,107,153,161,165,168,170,171,172,185,203],[89,153,161,165,168,170,171,172,174,185,200],[89,153,161,165,168,170,171,172,185,212],[89,101,153,161,165,168,170,171,172,185,212],[89,103,107,153,161,165,168,170,171,172,174,185,203],[89,98,99,100,102,106,153,161,164,165,168,170,171,172,185,190,203],[89,107,116,124,153,161,165,168,170,171,172,185],[89,99,105,153,161,165,168,170,171,172,185],[89,107,134,135,153,161,165,168,170,171,172,185],[89,99,102,107,153,161,165,168,170,171,172,185,194,203,212],[89,107,153,161,165,168,170,171,172,185],[89,103,107,153,161,165,168,170,171,172,185,203],[89,98,153,161,165,168,170,171,172,185],[89,101,102,103,105,106,107,108,109,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,135,136,137,138,139,153,161,165,168,170,171,172,185],[89,107,127,130,153,161,165,168,170,171,172,185],[89,107,116,117,118,153,161,165,168,170,171,172,185],[89,105,107,117,119,153,161,165,168,170,171,172,185],[89,106,153,161,165,168,170,171,172,185],[89,99,101,107,153,161,165,168,170,171,172,185],[89,107,111,117,119,153,161,165,168,170,171,172,185],[89,111,153,161,165,168,170,171,172,185],[89,105,107,110,153,161,165,168,170,171,172,185,203],[89,99,103,107,116,153,161,165,168,170,171,172,185],[89,107,127,153,161,165,168,170,171,172,185],[89,119,153,161,165,168,170,171,172,185],[89,99,103,107,111,153,161,165,168,170,171,172,185],[89,101,107,134,153,161,165,168,170,171,172,185,194,209,212],[89,153,161,164,165,167,168,169,170,171,172,174,185,190,200,203,210,212,214,215,216,217,219,220,221,241,245,246,247,248,249],[89,153,161,165,168,170,171,172,185,216,217,218,219],[89,153,161,165,168,170,171,172,185,216],[89,153,161,165,168,170,171,172,185,217],[89,153,161,165,168,170,171,172,185,244],[89,153,161,165,168,170,171,172,185,214,249],[89,153,154,158,161,165,166,167,168,169,170,171,172,176,177,185,260,261],[89,153,161,165,168,170,171,172,185,260,263]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"8fd575e12870e9944c7e1d62e1f5a73fcf23dd8d3a321f2a2c74c20d022283fe","impliedFormat":1},{"version":"2ab096661c711e4a81cc464fa1e6feb929a54f5340b46b0a07ac6bbf857471f0","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7a3c8b952931daebdfc7a2897c53c0a1c73624593fa070e46bd537e64dcd20a","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"87dc0f382502f5bbce5129bdc0aea21e19a3abbc19259e0b43ae038a9fc4e326","affectsGlobalScope":true,"impliedFormat":1},{"version":"b1cb28af0c891c8c96b2d6b7be76bd394fddcfdb4709a20ba05a7c1605eea0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2fef54945a13095fdb9b84f705f2b5994597640c46afeb2ce78352fab4cb3279","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac77cb3e8c6d3565793eb90a8373ee8033146315a3dbead3bde8db5eaf5e5ec6","affectsGlobalScope":true,"impliedFormat":1},{"version":"56e4ed5aab5f5920980066a9409bfaf53e6d21d3f8d020c17e4de584d29600ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ece9f17b3866cc077099c73f4983bddbcb1dc7ddb943227f1ec070f529dedd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a6282c8827e4b9a95f4bf4f5c205673ada31b982f50572d27103df8ceb8013c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1c9319a09485199c1f7b0498f2988d6d2249793ef67edda49d1e584746be9032","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3a2a0cee0f03ffdde24d89660eba2685bfbdeae955a6c67e8c4c9fd28928eeb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"60037901da1a425516449b9a20073aa03386cce92f7a1fd902d7602be3a7c2e9","affectsGlobalScope":true,"impliedFormat":1},{"version":"d4b1d2c51d058fc21ec2629fff7a76249dec2e36e12960ea056e3ef89174080f","affectsGlobalScope":true,"impliedFormat":1},{"version":"22adec94ef7047a6c9d1af3cb96be87a335908bf9ef386ae9fd50eeb37f44c47","affectsGlobalScope":true,"impliedFormat":1},{"version":"196cb558a13d4533a5163286f30b0509ce0210e4b316c56c38d4c0fd2fb38405","affectsGlobalScope":true,"impliedFormat":1},{"version":"73f78680d4c08509933daf80947902f6ff41b6230f94dd002ae372620adb0f60","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5239f5c01bcfa9cd32f37c496cf19c61d69d37e48be9de612b541aac915805b","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"bde31fd423cd93b0eff97197a3f66df7c93e8c0c335cbeb113b7ff1ac35c23f4","impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ccdaa19852d25ecd84eec365c3bfa16e7859cadecf6e9ca6d0dbbbee439743f","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc2110f7decca6bfb9392e30421cfa1436479e4a6756e8fec6cbc22625d4f881","affectsGlobalScope":true,"impliedFormat":1},{"version":"096116f8fedc1765d5bd6ef360c257b4a9048e5415054b3bf3c41b07f8951b0b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5e01375c9e124a83b52ee4b3244ed1a4d214a6cfb54ac73e164a823a4a7860a","affectsGlobalScope":true,"impliedFormat":1},{"version":"f90ae2bbce1505e67f2f6502392e318f5714bae82d2d969185c4a6cecc8af2fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b58e207b93a8f1c88bbf2a95ddc686ac83962b13830fe8ad3f404ffc7051fb4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1fefabcb2b06736a66d2904074d56268753654805e829989a46a0161cd8412c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"c18a99f01eb788d849ad032b31cafd49de0b19e083fe775370834c5675d7df8e","affectsGlobalScope":true,"impliedFormat":1},{"version":"5247874c2a23b9a62d178ae84f2db6a1d54e6c9a2e7e057e178cc5eea13757fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"10ec5e82144dfac6f04fa5d1d6c11763b3e4dbbac6d99101427219ab3e2ae887","impliedFormat":1},{"version":"615754924717c0b1e293e083b83503c0a872717ad5aa60ed7f1a699eb1b4ea5c","impliedFormat":1},{"version":"14e9acf826baba0ef4b5665704084896e7bcc06f65a9ab13af7e93d27d6b7069","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"21adf13435b9b748529c8cedf80f884e5130b9684188120a686cd2b26a2059c7","impliedFormat":1},{"version":"eec76bf6b9346f3f95fa402621b889489e96930e72295b0369022f332e9b4a6a","impliedFormat":1},{"version":"0ecd58f413f9bc3b7d4383eae31b0c8fc576985cd7404d6f99f8c643543ade74","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"d33ce35e3f9cfcc1d94eca415bdd3bde94d5b153ffdd33e6c4455c029986c630","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"98498b101803bb3dde9f76a56e65c14b75db1cc8bec5f4db72be541570f74fc5","impliedFormat":1},{"version":"4dc59f6e1dbf3d5f66660fceabe6c174d3261b37b696ae1854f0dbaf255fc753","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"436d7b4543b340b0f3eef4310d524242e41369b9652aa9c70428767c4dcac455","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"114f493b30f364255290472111b5a4791d5902c308645670cd0401429cbc6930","impliedFormat":1},{"version":"c3f5289820990ab66b70c7fb5b63cb674001009ff84b13de40619619a9c8175f","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3275d55fac10b799c9546804126239baf020d220136163f763b55a74e50e750","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa68a0a3b7cb32c00e39ee3cd31f8f15b80cac97dce51b6ee7fc14a1e8deb30b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c36e755bced82df7fb6ce8169265d0a7bb046ab4e2cb6d0da0cb72b22033e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7a93de4ff8a63bafe62ba86b89af1df0ccb5e40bb85b0c67d6bbcfdcf96bf3d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"90e85f9bc549dfe2b5749b45fe734144e96cd5d04b38eae244028794e142a77e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e0a5deeb610b2a50a6350bd23df6490036a1773a8a71d70f2f9549ab009e67ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"d2ae155afe8a01cc0ae612d99117cf8ef16692ba7c4366590156fdec1bcf2d8c","impliedFormat":1},{"version":"3f5e5d9be35913db9fea42a63f3df0b7e3c8703b97670a2125587b4dbbd56d7c","impliedFormat":1},{"version":"c8b8968311ec4e5e97b7b5fb8a65efaba455db9bdcfd7fff7fb15f6e317bfba0","impliedFormat":1},{"version":"57c23df0b5f7a8e26363a3849b0bc7763f6b241207157c8e40089d1df4116f35","affectsGlobalScope":true,"impliedFormat":1},{"version":"3b8bc0c17b54081b0878673989216229e575d67a10874e84566a21025a2461ee","impliedFormat":1},{"version":"5b0db5a58b73498792a29bfebc333438e61906fef75da898b410e24e52229e6f","impliedFormat":1},{"version":"dbe055b2b29a7bab2c1ca8f259436306adb43f469dca7e639a02cd3695d3f621","impliedFormat":1},{"version":"1678b04557dca52feab73cc67610918a7f5e25bfdba3e7fa081acd625d93106d","impliedFormat":1},{"version":"aecbf1d9e6a18dab7d92ef8a89a1444b47e1eb6134cb2bb776a26d55ff58c29a","impliedFormat":1},{"version":"2ea729503db9793f2691162fec3dd1118cab62e96d025f8eeb376d43ec293395","impliedFormat":1},{"version":"9ec87fea42b92894b0f209931a880789d43c3397d09dd99c631ae40a2f7071d1","impliedFormat":1},{"version":"c68e88cdfadfb6c8ba5fc38e58a3a166b0beae77b1f05b7d921150a32a5ffb8d","impliedFormat":1},{"version":"2bc7aa4fba46df0bd495425a7c8201437a7d465f83854fac859df2d67f664df3","impliedFormat":1},{"version":"41d17e1ad9a002feb11c8cdd2777e5bbc0cdb1e3f595d237e4dded0b6949983b","impliedFormat":1},{"version":"1fede9296beac11ce8e6b425396a1791f64341f2be85deebb6286faf6e16306e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce697b6a251d9cad53998c7fd3098072df883b525ec45d83530e434dc6d80dc6","impliedFormat":1},{"version":"719412f054e6ecc35489462c9a21bab0323d173a7d04e55b0ace4b5d86fbeb07","impliedFormat":1},{"version":"0eb5d0cbf09de5d34542b977fd6a933bb2e0817bffe8e1a541b2f1ad1b9af1ff","impliedFormat":1},{"version":"fac3e88881b35d3a757ed891ac912b2674792c25e2a1a74e1f5fbc72d19a9792","impliedFormat":1},{"version":"2c2bdaa1d8ead9f68628d6d9d250e46ee8e81aa4898b4769a36956ae15e060fe","impliedFormat":1},{"version":"c32c840c62d8bd7aeb3147aa6754cd2d922b990a6b6634530cb2ebdce5adc8e9","impliedFormat":1},{"version":"5ff4433a2deae4f85ab1377e90a7554ce6b47ae51c69a84ca30a6e22fae85834","impliedFormat":1},{"version":"82b91e4e42e6c41bc7fc1b6c2dc5eba6a2ba98375eb1f210e6ff6bba2d54177e","impliedFormat":1},{"version":"c1fa52b3d014001e8662fa2669d90ea15373958a288e3b83a3b621733d25292a","affectsGlobalScope":true,"impliedFormat":1},{"version":"cbed824fec91efefc7bbdcb8b43d1a531fdbebd0e2ef19481501ff365a93cb70","impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"d0716593b3f2b0451bcf0c24cfa86dec2235c325c89f201934248b7c742715fc","impliedFormat":1},{"version":"ec501101c2a96133a6c695f934c8f6642149cc728571b29cbb7b770984c1088e","impliedFormat":1},{"version":"b214ebcf76c51b115453f69729ee8aa7b7f8eccdae2a922b568a45c2d7ff52f7","impliedFormat":1},{"version":"429c9cdfa7d126255779efd7e6d9057ced2d69c81859bbab32073bad52e9ba76","impliedFormat":1},{"version":"2991bca2cc0f0628a278df2a2ccdb8d6cbcb700f3761abbed62bba137d5b1790","impliedFormat":1},{"version":"5e66972e83eb4dc7123939bf816e6cbd9ad81af5552db1cab84e6bd9c64d2ecc","affectsGlobalScope":true,"impliedFormat":1},{"version":"230763250f20449fa7b3c9273e1967adb0023dc890d4be1553faca658ee65971","impliedFormat":1},{"version":"c3e9078b60cb329d1221f5878e88cecfa3e74460550e605a58fcfb41a66029ff","impliedFormat":1},{"version":"8413d0641f293aed551c7464615b770d34a02dedede889b9591172287d68e773","impliedFormat":1},{"version":"0ea59f7d3e51440baa64f429253759b106cfcbaf51e474cae606e02265b37cf8","impliedFormat":1},{"version":"bc18a1991ba681f03e13285fa1d7b99b03b67ee671b7bc936254467177543890","impliedFormat":1},{"version":"1b241e24f3227d078c06aeda6e050187ad59a4e591f4467abed44d92b084e08d","impliedFormat":1},{"version":"fa94bbf532b7af8f394b95fa310980d6e20bd2d4c871c6a6cb9f70f03750a44b","impliedFormat":1},{"version":"7fde0e1be5c8be204ffbf428abfcf01da2eb0f130e1bc3f539eb7275f4fd1f58","impliedFormat":1},{"version":"e284328553df5f425a5d33d36a0c3fa66b46af9d097cad6f4d2e8696dfdeb0f1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7fa2214bb0d64701bc6f9ce8cde2fd2ff8c571e0b23065fa04a8a5a6beb91511","impliedFormat":1},{"version":"b58040a9d317060d1a5f6e78bb8bd125894fb660feea534fe0e733cf5fdd7d07","impliedFormat":1},{"version":"f1c93e046fb3d9b7f8249629f4b63dc068dd839b824dd0aa39a5e68476dc9420","impliedFormat":1},{"version":"016b29bf4926b80255a108c53a1451717350059da04fcae64d1075f5e93bbb39","impliedFormat":1},{"version":"841983e39bd4cbb463be385e92fda11057cab368bf27100a801c492f1d86cbaa","impliedFormat":1},{"version":"1c4f139ade4f6ebf45463505f8155173e5d7a5305e50e0aae0a5e712d6ff3b48","impliedFormat":1},{"version":"e16b319e5aca1031168de823c4946ff8e29629c4c8cc0ec0fcfe2a8ab2155043","impliedFormat":1},{"version":"e4156ddb25aa0e3b5303d372f26957b36778f0f6bbd4326359269873295e3058","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc1b433a84cae05ddc5672d4823170af78606ad21ecef60dbc4570190cbf1357","impliedFormat":1},{"version":"9d3821bc75c59577e52643324cec92fc2145642e8d17cf7ee07a3181f21d985d","impliedFormat":1},{"version":"7f78cfb2b343838612c192cb251746e3a7c62ac7675726a47e130d9b213f6580","impliedFormat":1},{"version":"201db9cf1687fab1adf5282fcba861f382b32303dc4f67c89d59655e78a25461","impliedFormat":1},{"version":"2c3c5c0f54055e87640f5d233716fd889f3034fc7911d603b642369b0dbeb2a7","impliedFormat":1},{"version":"0a20eaf2e4b1e3c1e1f87f7bccb0c936375b23b022baeea750519b7c9bc6ce83","impliedFormat":1},{"version":"b484ec11ba00e3a2235562a41898d55372ccabe607986c6fa4f4aba72093749f","impliedFormat":1},{"version":"a16b91b27bd6b706c687c88cbc8a7d4ee98e5ed6043026d6b84bda923c0aed67","impliedFormat":1},{"version":"1c9e5b1a17b1fc9b3711fb36e0690421261ab2880f15b145155b5b2ba2ab6c2d","impliedFormat":1},{"version":"99ab6d0d660ce4d21efb52288a39fd35bb3f556980ec5463b1ae8f304a3bbc85","impliedFormat":1},{"version":"6eeded8c7e352be6e0efb83f4935ec752513c4d22043b52522b90849a49a3a11","impliedFormat":1},{"version":"6c1ad90050ffbb151cacc68e2d06ea1a26a945659391e32651f5d42b86fd7f2c","impliedFormat":1},{"version":"afa1c49f8e559e413d57343339db857d2a8159435cf9cf7d4deb41718fff1b88","impliedFormat":1},{"version":"6953d7597831d0860c7034cf4f0419687d263b6b98a4b32e37ce6d49615c36e2","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"ee70b8037ecdf0de6c04f35277f253663a536d7e38f1539d270e4e916d225a3f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a660aa95476042d3fdcc1343cf6bb8fdf24772d31712b1db321c5a4dcc325434","impliedFormat":1},{"version":"a7ca8df4f2931bef2aa4118078584d84a0b16539598eaadf7dce9104dfaa381c","impliedFormat":1},{"version":"11443a1dcfaaa404c68d53368b5b818712b95dd19f188cab1669c39bee8b84b3","impliedFormat":1},{"version":"36977c14a7f7bfc8c0426ae4343875689949fb699f3f84ecbe5b300ebf9a2c55","impliedFormat":1},{"version":"035d0934d304483f07148427a5bd5b98ac265dae914a6b49749fe23fbd893ec7","impliedFormat":99},{"version":"e2ed5b81cbed3a511b21a18ab2539e79ac1f4bc1d1d28f8d35d8104caa3b429f","impliedFormat":99},{"version":"161c8e0690c46021506e32fda85956d785b70f309ae97011fd27374c065cac9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"402e5c534fb2b85fa771170595db3ac0dd532112c8fa44fc23f233bc6967488b","impliedFormat":1},{"version":"52dcc257df5119fb66d864625112ce5033ac51a4c2afe376a0b299d2f7f76e4a","impliedFormat":1},{"version":"e5bab5f871ef708d52d47b3e5d0aa72a08ee7a152f33931d9a60809711a2a9a3","impliedFormat":1},{"version":"e16dc2a81595736024a206c7d5c8a39bfe2e6039208ef29981d0d95434ba8fcf","impliedFormat":1},{"version":"cc4a4903fb698ca1d961d4c10dce658aa3a479faf40509d526f122b044eaf6a4","impliedFormat":1},{"version":"19ee8416e6473ed6c7adb868fa796b5653cf0fa2a337658e677eaa0d134388c3","impliedFormat":1},{"version":"1328ab4e442614b28cdb3d4b414cf68325c0da0dca07287a338d0654b7a00261","impliedFormat":1},{"version":"a039dc21f045919f3cbee2ec13812cc6cc3eebc99dae4be00973230f468d19a6","impliedFormat":1},{"version":"3fbe57af01460e49dcd29df55d6931e1672bc6f1be0fb073d11410bc16f9037d","impliedFormat":1},{"version":"f760be449e8562ec5c09bb5187e8e1eabf3c113c0c58cddda53ef8c69f3e2131","impliedFormat":1},{"version":"44325ed13294fce6ab825b82947bbeed2611db7dad9d9135260192f375e5a189","impliedFormat":1},{"version":"e392e8fb5b514eafc585601c1d781485aa6dd6a320e75daf1064a4c6918a1b45","impliedFormat":1},{"version":"46e4a36e8ddbdfb4e7330e11c81c970dc8b218611df9183d39c41c5f8c653b55","impliedFormat":1},{"version":"370bde134aa8c2abc926d0e99d3a4d5d5dba65c6ee65459137e4f02670cbf841","impliedFormat":1},{"version":"6332f565867cf4a740a70e30f31cefba37ef7cebcf74f22eab8d744fde6d193e","impliedFormat":1},{"version":"2977b7884aedc895a1d0c9c210c7cf3272c29d6959a08a6fa3ff71e0aff08175","impliedFormat":1},{"version":"17f2922d41ddd032830a91371c948cd9ce903b35c95adca72271a54584f19b0b","impliedFormat":1},{"version":"3eed76ede2a1a14d7c9bb0a642041282dcc264811139d3dd275c9fe14efc9840","impliedFormat":1},{"version":"e3cf0611709328b449ec13f8c436712d62003620ce480139fae46ce001c2ee9f","impliedFormat":1},{"version":"8d369483f0c2b9ee388129cfdb6a43bc8112b377e86a41884bd06e19ce04f4c1","impliedFormat":99},{"version":"3fd8a5aefd8c3feb3936ca66f5aa89dff7bf6e6537b4158dbd0f6e0d65ed3b9e","impliedFormat":1},{"version":"a18642ddf216f162052a16cba0944892c4c4c977d3306a87cb673d46abbb0cbf","impliedFormat":1},{"version":"41c41c6e90133bb2a14f7561f29944771886e5535945b2b372e2f6ed6987746e","impliedFormat":1},{"version":"4ec16d7a4e366c06a4573d299e15fe6207fc080f41beac5da06f4af33ea9761e","impliedFormat":1},{"version":"7870becb94cbc11d2d01b77c4422589adcba4d8e59f726246d40cd0d129784d8","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f698624bbbb060ece7c0e51b7236520ebada74b747d7523c7df376453ed6fea","impliedFormat":1},{"version":"f70b8328a15ca1d10b1436b691e134a49bc30dcf3183a69bfaa7ba77e1b78ecd","impliedFormat":1},{"version":"d9030fc0c412a31e7e13d189b9ad032b5177c20217add0f24fd3fff0cf272882","impliedFormat":99},{"version":"e7ba74900e0edb9cb93edb1547cbb65238d26af0e5f10d24be3a61d862262cfd","impliedFormat":99},{"version":"556ccd493ec36c7d7cb130d51be66e147b91cc1415be383d71da0f1e49f742a9","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"95aba78013d782537cc5e23868e736bec5d377b918990e28ed56110e3ae8b958","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"26e0ffceb2198feb1ef460d5d14111c69ad07d44c5a67fd4bfeb74c969aa9afb","impliedFormat":99},{"version":"7757c6ca7a8ad1992401c6aff33633d6a088515be5a39d7ee188b35bfc8e5f8e","impliedFormat":99},{"version":"2d2dc284419f923a138671df4faa72f22e27e50edfb36be0965828d1e29261a2","signature":"8d916869b630869b2798d91a5cfceab8acc6247d81d4042ce14198d01ddebb60"},{"version":"94a0fcd4f758fe669bc78f1c9146f5fc07879783787364ca89ce486b0cf37920","affectsGlobalScope":true,"impliedFormat":1},{"version":"194779039dc8a41af2eefa2ff740594be9cf44333870346c20602031ad73f168","impliedFormat":1},{"version":"3aaef82d6d7e64660d934e633012b8d3474ae8c5c100c245a6e35f9b8ff56fde","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"2329508bb462ba8f17cc60c4ed5b346618a42eefcaaddcbb0fcbf7f09cfd0a87","impliedFormat":1},{"version":"991a3dc027a78cffb335f3a502fab683cc955fc0e4fab478817ba0fda311b83b","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"2efbc5086f10635b6507392c3d9d073e94d9308a5cf08af5ae4389c250d1791c","affectsGlobalScope":true,"impliedFormat":99}],"root":[259,262,264],"options":{"composite":true,"esModuleInterop":true,"jsx":1,"module":99,"noImplicitAny":false,"noImplicitReturns":true,"noUnusedLocals":true,"noUnusedParameters":true,"skipLibCheck":true,"sourceMap":false,"strict":true,"target":99},"referencedMap":[[259,1],[253,2],[251,3],[263,4],[261,4],[258,5],[256,6],[252,2],[254,7],[255,2],[213,3],[150,8],[151,8],[152,9],[89,10],[153,11],[154,12],[155,13],[87,3],[156,14],[157,15],[158,16],[159,17],[160,18],[161,19],[162,19],[163,20],[164,21],[165,22],[166,23],[90,3],[88,3],[167,24],[168,25],[169,26],[212,27],[170,28],[171,29],[172,28],[173,30],[174,31],[176,32],[177,33],[178,33],[179,33],[180,34],[181,35],[182,36],[183,37],[184,38],[185,39],[186,39],[187,40],[188,3],[189,3],[190,41],[191,42],[192,43],[193,41],[194,44],[195,45],[196,46],[197,47],[198,48],[199,49],[200,50],[201,51],[202,52],[203,53],[204,54],[205,55],[206,56],[207,57],[208,58],[91,28],[92,3],[93,59],[94,60],[95,3],[96,61],[97,3],[141,62],[142,63],[143,64],[144,64],[145,65],[146,3],[147,11],[148,66],[149,63],[209,67],[210,68],[211,69],[257,70],[175,3],[250,5],[265,64],[260,71],[221,3],[242,3],[244,72],[243,3],[238,73],[236,74],[237,75],[225,76],[226,74],[233,77],[224,78],[229,79],[239,3],[230,80],[235,81],[241,82],[240,83],[223,84],[231,85],[232,86],[227,87],[234,73],[228,88],[215,89],[214,90],[222,3],[84,3],[85,3],[15,3],[13,3],[14,3],[19,3],[18,3],[2,3],[20,3],[21,3],[22,3],[23,3],[24,3],[25,3],[26,3],[27,3],[3,3],[28,3],[29,3],[4,3],[30,3],[34,3],[31,3],[32,3],[33,3],[35,3],[36,3],[37,3],[5,3],[38,3],[39,3],[40,3],[41,3],[6,3],[45,3],[42,3],[43,3],[44,3],[46,3],[7,3],[47,3],[52,3],[53,3],[48,3],[49,3],[50,3],[51,3],[8,3],[57,3],[54,3],[55,3],[56,3],[58,3],[9,3],[59,3],[60,3],[61,3],[63,3],[62,3],[64,3],[65,3],[10,3],[66,3],[67,3],[68,3],[11,3],[69,3],[70,3],[71,3],[72,3],[73,3],[1,3],[74,3],[75,3],[12,3],[79,3],[77,3],[82,3],[81,3],[86,3],[76,3],[80,3],[78,3],[83,3],[17,3],[16,3],[116,91],[129,92],[113,93],[130,94],[139,95],[104,96],[105,97],[103,98],[138,99],[133,100],[137,101],[107,102],[126,103],[106,104],[136,105],[101,106],[102,100],[108,107],[109,3],[115,108],[112,107],[99,109],[140,110],[131,111],[119,112],[118,107],[120,113],[123,114],[117,115],[121,116],[134,99],[110,117],[111,118],[124,119],[100,94],[128,120],[127,107],[114,118],[122,121],[125,122],[132,3],[98,3],[135,123],[249,124],[220,125],[219,126],[217,126],[216,3],[218,127],[247,3],[246,3],[245,128],[248,129],[262,130],[264,131]],"affectedFilesPendingEmit":[[259,17],[262,17],[264,17]],"latestChangedDtsFile":"./src/preload/index.d.ts","version":"5.9.3"} \ No newline at end of file