aiexecode 1.0.76 → 1.0.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aiexecode might be problematic. Click here for more details.
- package/index.js +57 -12
- package/package.json +1 -1
- package/payload_viewer/out/404/index.html +1 -1
- package/payload_viewer/out/404.html +1 -1
- package/payload_viewer/out/index.html +1 -1
- package/payload_viewer/out/index.txt +1 -1
- package/src/frontend/App.js +76 -17
- package/src/frontend/components/Header.js +11 -4
- package/src/frontend/components/Input.js +37 -5
- package/src/frontend/components/LoadingIndicator.js +31 -0
- package/src/util/version_check.js +116 -0
- /package/payload_viewer/out/_next/static/{Wnr9eYJaRUoC5a3SUgrBr → 0ijq_fdWNnOdKxNRAYEdQ}/_buildManifest.js +0 -0
- /package/payload_viewer/out/_next/static/{Wnr9eYJaRUoC5a3SUgrBr → 0ijq_fdWNnOdKxNRAYEdQ}/_clientMiddlewareManifest.json +0 -0
- /package/payload_viewer/out/_next/static/{Wnr9eYJaRUoC5a3SUgrBr → 0ijq_fdWNnOdKxNRAYEdQ}/_ssgManifest.js +0 -0
package/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import { performExit } from './src/util/exit_handler.js';
|
|
|
20
20
|
import { Command } from 'commander';
|
|
21
21
|
import { registerMcpCliCommands } from './src/cli/mcp_cli.js';
|
|
22
22
|
import { createDebugLogger } from './src/util/debug_log.js';
|
|
23
|
+
import { checkForUpdates } from './src/util/version_check.js';
|
|
23
24
|
|
|
24
25
|
const debugLog = createDebugLogger('index.log', 'index');
|
|
25
26
|
|
|
@@ -306,18 +307,32 @@ if (!process.env.OPENAI_API_KEY) {
|
|
|
306
307
|
process.exit(1);
|
|
307
308
|
}
|
|
308
309
|
|
|
309
|
-
// MCP Integration 초기화 (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
310
|
+
// MCP Integration 초기화 (백그라운드에서 실행)
|
|
311
|
+
let mcpIntegration = null;
|
|
312
|
+
let mcpToolFunctions = {};
|
|
313
|
+
let mcpToolSchemas = [];
|
|
314
|
+
|
|
315
|
+
// MCP 초기화를 백그라운드에서 실행 (이벤트는 UI 시작 후에 발생)
|
|
316
|
+
initializeMCPIntegration(process.cwd()).then(integration => {
|
|
317
|
+
mcpIntegration = integration;
|
|
318
|
+
mcpToolFunctions = integration ? integration.getToolFunctions() : {};
|
|
319
|
+
mcpToolSchemas = integration ? integration.getToolSchemas() : [];
|
|
320
|
+
|
|
321
|
+
if (integration) {
|
|
322
|
+
const servers = integration.getConnectedServers();
|
|
323
|
+
debugLog(`MCP integration complete: ${servers.length} server(s), ${Object.keys(mcpToolFunctions).length} tool(s)`);
|
|
324
|
+
servers.forEach(server => {
|
|
325
|
+
debugLog(` - ${server.name}: ${server.toolCount} tool(s) (${server.status})`);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
313
328
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
});
|
|
320
|
-
}
|
|
329
|
+
// MCP 초기화 완료 이벤트 발생
|
|
330
|
+
uiEvents.emit('mcp:initialized', { integration });
|
|
331
|
+
}).catch(err => {
|
|
332
|
+
debugLog(`MCP initialization failed: ${err.message}`);
|
|
333
|
+
// 실패해도 MCP 초기화 완료 이벤트 발생
|
|
334
|
+
uiEvents.emit('mcp:initialized', { integration: null });
|
|
335
|
+
});
|
|
321
336
|
|
|
322
337
|
// 커맨드 레지스트리 초기화
|
|
323
338
|
const commandRegistry = new CommandRegistry();
|
|
@@ -440,6 +455,24 @@ if (shouldContinue) {
|
|
|
440
455
|
await deleteHistoryFile(process.app_custom.sessionID);
|
|
441
456
|
}
|
|
442
457
|
|
|
458
|
+
// 버전 체크 (비동기, 백그라운드에서 실행, 이벤트는 UI 시작 후에 발생)
|
|
459
|
+
let updateInfo = null;
|
|
460
|
+
|
|
461
|
+
checkForUpdates(VERSION).then(info => {
|
|
462
|
+
updateInfo = info;
|
|
463
|
+
if (info.updateAvailable) {
|
|
464
|
+
debugLog(`Update available: ${VERSION} → ${info.remoteVersion}`);
|
|
465
|
+
} else {
|
|
466
|
+
debugLog(`No update available (current: ${VERSION})`);
|
|
467
|
+
}
|
|
468
|
+
// 업데이트 여부와 관계없이 버전 체크 완료 이벤트 발생
|
|
469
|
+
uiEvents.emit('version:update', { updateInfo: info });
|
|
470
|
+
}).catch(err => {
|
|
471
|
+
debugLog(`Version check failed: ${err.message}`);
|
|
472
|
+
// 실패해도 버전 체크 완료 이벤트 발생 (Header를 Static으로 만들기 위해)
|
|
473
|
+
uiEvents.emit('version:update', { updateInfo: null });
|
|
474
|
+
});
|
|
475
|
+
|
|
443
476
|
// UI 시작
|
|
444
477
|
const currentModel = await getModelForProvider();
|
|
445
478
|
const currentReasoningEffort = settings?.OPENAI_REASONING_EFFORT || process.env.OPENAI_REASONING_EFFORT;
|
|
@@ -451,7 +484,19 @@ uiInstance = startUI({
|
|
|
451
484
|
model: currentModel,
|
|
452
485
|
version: VERSION,
|
|
453
486
|
initialHistory,
|
|
454
|
-
reasoningEffort: currentReasoningEffort
|
|
487
|
+
reasoningEffort: currentReasoningEffort,
|
|
488
|
+
updateInfo: null // 초기에는 null, 나중에 업데이트됨
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// UI가 시작된 후 로딩 태스크 추가
|
|
492
|
+
uiEvents.emit('loading:task_add', {
|
|
493
|
+
id: 'version_check',
|
|
494
|
+
text: 'Checking for updates...'
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
uiEvents.emit('loading:task_add', {
|
|
498
|
+
id: 'mcp_init',
|
|
499
|
+
text: 'Initializing MCP servers...'
|
|
455
500
|
});
|
|
456
501
|
|
|
457
502
|
// 초기 미션이 있으면 자동 실행
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--0ijq_fdWNnOdKxNRAYEdQ--><html lang="ko" class="dark h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/ecd2072ebf41611f.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/e411019f55d87c42.js"/><script src="/_next/static/chunks/103c802c8f4a5ea1.js" async=""></script><script src="/_next/static/chunks/305b077a9873cf54.js" async=""></script><script src="/_next/static/chunks/turbopack-0ac29803ce3c3c7a.js" async=""></script><script src="/_next/static/chunks/060f9a97930f3d04.js" async=""></script><script src="/_next/static/chunks/cdd12d5c1a5a6064.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>Payload Log Viewer</title><meta name="description" content="AI Agent 로그 파일 뷰어 및 편집기"/><link rel="icon" href="/favicon.ico?favicon.0b3bf435.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><div data-rht-toaster="" style="position:fixed;z-index:9999;top:16px;left:16px;right:16px;bottom:16px;pointer-events:none"></div><script src="/_next/static/chunks/e411019f55d87c42.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n3:I[37457,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n4:I[5766,[\"/_next/static/chunks/cdd12d5c1a5a6064.js\"],\"Toaster\"]\n5:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"OutletBoundary\"]\n7:I[11533,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"AsyncMetadataOutlet\"]\n9:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"ViewportBoundary\"]\nb:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"MetadataBoundary\"]\nc:\"$Sreact.suspense\"\ne:I[68027,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n:HL[\"/_next/static/chunks/ecd2072ebf41611f.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"0ijq_fdWNnOdKxNRAYEdQ\",\"p\":\"\",\"c\":[\"\",\"_not-found\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/ecd2072ebf41611f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/cdd12d5c1a5a6064.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"ko\",\"className\":\"dark h-full\",\"children\":[\"$\",\"body\",null,{\"className\":\"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden\",\"children\":[[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L4\",null,{\"position\":\"bottom-right\",\"toastOptions\":{\"duration\":4000,\"style\":{\"background\":\"hsl(var(--background))\",\"color\":\"hsl(var(--foreground))\",\"border\":\"1px solid hsl(var(--border))\"}}}]]}]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:props:children:0:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:1:props:children:1:props:children:props:children:0:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:props:children:0:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:props:children:0:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L5\",null,{\"children\":[\"$L6\",[\"$\",\"$L7\",null,{\"promise\":\"$@8\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$L9\",null,{\"children\":\"$La\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$Lb\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$c\",null,{\"fallback\":null,\"children\":\"$Ld\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$e\",\"$undefined\"],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n6:null\n"])</script><script>self.__next_f.push([1,"f:I[27201,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"IconMark\"]\n8:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Payload Log Viewer\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"AI Agent 로그 파일 뷰어 및 편집기\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0b3bf435.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$Lf\",\"3\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"d:\"$8:metadata\"\n"])</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--0ijq_fdWNnOdKxNRAYEdQ--><html lang="ko" class="dark h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/ecd2072ebf41611f.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/e411019f55d87c42.js"/><script src="/_next/static/chunks/103c802c8f4a5ea1.js" async=""></script><script src="/_next/static/chunks/305b077a9873cf54.js" async=""></script><script src="/_next/static/chunks/turbopack-0ac29803ce3c3c7a.js" async=""></script><script src="/_next/static/chunks/060f9a97930f3d04.js" async=""></script><script src="/_next/static/chunks/cdd12d5c1a5a6064.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>Payload Log Viewer</title><meta name="description" content="AI Agent 로그 파일 뷰어 및 편집기"/><link rel="icon" href="/favicon.ico?favicon.0b3bf435.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><div data-rht-toaster="" style="position:fixed;z-index:9999;top:16px;left:16px;right:16px;bottom:16px;pointer-events:none"></div><script src="/_next/static/chunks/e411019f55d87c42.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n3:I[37457,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n4:I[5766,[\"/_next/static/chunks/cdd12d5c1a5a6064.js\"],\"Toaster\"]\n5:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"OutletBoundary\"]\n7:I[11533,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"AsyncMetadataOutlet\"]\n9:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"ViewportBoundary\"]\nb:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"MetadataBoundary\"]\nc:\"$Sreact.suspense\"\ne:I[68027,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n:HL[\"/_next/static/chunks/ecd2072ebf41611f.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"0ijq_fdWNnOdKxNRAYEdQ\",\"p\":\"\",\"c\":[\"\",\"_not-found\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/ecd2072ebf41611f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/cdd12d5c1a5a6064.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"ko\",\"className\":\"dark h-full\",\"children\":[\"$\",\"body\",null,{\"className\":\"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden\",\"children\":[[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L4\",null,{\"position\":\"bottom-right\",\"toastOptions\":{\"duration\":4000,\"style\":{\"background\":\"hsl(var(--background))\",\"color\":\"hsl(var(--foreground))\",\"border\":\"1px solid hsl(var(--border))\"}}}]]}]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:props:children:0:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:1:props:children:1:props:children:props:children:0:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:props:children:0:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:props:children:0:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L5\",null,{\"children\":[\"$L6\",[\"$\",\"$L7\",null,{\"promise\":\"$@8\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$L9\",null,{\"children\":\"$La\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$Lb\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$c\",null,{\"fallback\":null,\"children\":\"$Ld\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$e\",\"$undefined\"],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n6:null\n"])</script><script>self.__next_f.push([1,"f:I[27201,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"IconMark\"]\n8:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Payload Log Viewer\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"AI Agent 로그 파일 뷰어 및 편집기\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0b3bf435.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$Lf\",\"3\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"d:\"$8:metadata\"\n"])</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--Wnr9eYJaRUoC5a3SUgrBr--><html lang="ko" class="dark h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/chunks/ecd2072ebf41611f.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/e411019f55d87c42.js"/><script src="/_next/static/chunks/103c802c8f4a5ea1.js" async=""></script><script src="/_next/static/chunks/305b077a9873cf54.js" async=""></script><script src="/_next/static/chunks/turbopack-0ac29803ce3c3c7a.js" async=""></script><script src="/_next/static/chunks/060f9a97930f3d04.js" async=""></script><script src="/_next/static/chunks/cdd12d5c1a5a6064.js" async=""></script><script src="/_next/static/chunks/f1ac9047ac4a3fde.js" async=""></script><script src="/_next/static/chunks/37d0cd2587a38f79.js" async=""></script><meta name="next-size-adjust" content=""/><title>Payload Log Viewer</title><meta name="description" content="AI Agent 로그 파일 뷰어 및 편집기"/><link rel="icon" href="/favicon.ico?favicon.0b3bf435.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden"><div hidden=""><!--$--><!--/$--></div><div class="h-screen bg-background flex"><div class="flex-shrink-0 w-80 border-r border-border bg-background flex flex-col"><div class="flex-shrink-0 border-b border-border p-4"><h2 class="text-lg font-semibold flex items-center gap-2"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-text h-5 w-5" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"></path><path d="M14 2v4a2 2 0 0 0 2 2h4"></path><path d="M10 9H8"></path><path d="M16 13H8"></path><path d="M16 17H8"></path></svg>로그 파일</h2><p class="text-sm text-muted-foreground">로딩 중...</p></div><div class="flex-1 min-h-0"><div dir="ltr" class="relative overflow-hidden h-full" style="position:relative;--radix-scroll-area-corner-width:0px;--radix-scroll-area-corner-height:0px"><style>[data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none}</style><div data-radix-scroll-area-viewport="" class="h-full w-full rounded-[inherit]" style="overflow-x:hidden;overflow-y:hidden"><div style="min-width:100%;display:table"><div class="p-4 text-center text-muted-foreground"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-refresh-cw h-6 w-6 animate-spin mx-auto mb-2" aria-hidden="true"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path><path d="M21 3v5h-5"></path><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path><path d="M8 16H3v5"></path></svg>로딩 중...</div></div></div></div></div></div><div class="flex-1 min-w-0"><div class="rounded-lg border bg-card text-card-foreground shadow-sm h-full"><div class="p-6 pt-0 flex items-center justify-center h-full"><div class="text-center text-muted-foreground"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-square-pen h-12 w-12 mx-auto mb-4 opacity-50" aria-hidden="true"><path d="M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z"></path></svg><p class="text-lg">REQ 파일을 선택하세요</p><p class="text-sm">요청 파일을 선택하면 내용을 편집하고 재실행할 수 있습니다</p></div></div></div></div></div><!--$--><!--/$--><div data-rht-toaster="" style="position:fixed;z-index:9999;top:16px;left:16px;right:16px;bottom:16px;pointer-events:none"></div><script src="/_next/static/chunks/e411019f55d87c42.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n3:I[37457,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n4:I[5766,[\"/_next/static/chunks/cdd12d5c1a5a6064.js\"],\"Toaster\"]\n5:I[47257,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"ClientPageRoot\"]\n6:I[31713,[\"/_next/static/chunks/cdd12d5c1a5a6064.js\",\"/_next/static/chunks/f1ac9047ac4a3fde.js\",\"/_next/static/chunks/37d0cd2587a38f79.js\"],\"default\"]\n9:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"OutletBoundary\"]\nb:I[11533,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"AsyncMetadataOutlet\"]\nd:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"ViewportBoundary\"]\nf:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"MetadataBoundary\"]\n10:\"$Sreact.suspense\"\n12:I[68027,[\"/_next/static/chunks/cdd12d5c1a5a6064.js\"],\"default\"]\n:HL[\"/_next/static/chunks/ecd2072ebf41611f.css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"Wnr9eYJaRUoC5a3SUgrBr\",\"p\":\"\",\"c\":[\"\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/ecd2072ebf41611f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/cdd12d5c1a5a6064.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"ko\",\"className\":\"dark h-full\",\"children\":[\"$\",\"body\",null,{\"className\":\"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden\",\"children\":[[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L4\",null,{\"position\":\"bottom-right\",\"toastOptions\":{\"duration\":4000,\"style\":{\"background\":\"hsl(var(--background))\",\"color\":\"hsl(var(--foreground))\",\"border\":\"1px solid hsl(var(--border))\"}}}]]}]}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L5\",null,{\"Component\":\"$6\",\"searchParams\":{},\"params\":{},\"promises\":[\"$@7\",\"$@8\"]}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/f1ac9047ac4a3fde.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/37d0cd2587a38f79.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L9\",null,{\"children\":[\"$La\",[\"$\",\"$Lb\",null,{\"promise\":\"$@c\"}]]}]]}],{},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$Ld\",null,{\"children\":\"$Le\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$Lf\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$10\",null,{\"fallback\":null,\"children\":\"$L11\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$12\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/ecd2072ebf41611f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"7:{}\n8:\"$0:f:0:1:2:children:1:props:children:0:props:params\"\n"])</script><script>self.__next_f.push([1,"e:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\na:null\n"])</script><script>self.__next_f.push([1,"13:I[27201,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"IconMark\"]\nc:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Payload Log Viewer\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"AI Agent 로그 파일 뷰어 및 편집기\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0b3bf435.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L13\",\"3\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"11:\"$c:metadata\"\n"])</script></body></html>
|
|
1
|
+
<!DOCTYPE html><!--0ijq_fdWNnOdKxNRAYEdQ--><html lang="ko" class="dark h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/chunks/ecd2072ebf41611f.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/e411019f55d87c42.js"/><script src="/_next/static/chunks/103c802c8f4a5ea1.js" async=""></script><script src="/_next/static/chunks/305b077a9873cf54.js" async=""></script><script src="/_next/static/chunks/turbopack-0ac29803ce3c3c7a.js" async=""></script><script src="/_next/static/chunks/060f9a97930f3d04.js" async=""></script><script src="/_next/static/chunks/cdd12d5c1a5a6064.js" async=""></script><script src="/_next/static/chunks/f1ac9047ac4a3fde.js" async=""></script><script src="/_next/static/chunks/37d0cd2587a38f79.js" async=""></script><meta name="next-size-adjust" content=""/><title>Payload Log Viewer</title><meta name="description" content="AI Agent 로그 파일 뷰어 및 편집기"/><link rel="icon" href="/favicon.ico?favicon.0b3bf435.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden"><div hidden=""><!--$--><!--/$--></div><div class="h-screen bg-background flex"><div class="flex-shrink-0 w-80 border-r border-border bg-background flex flex-col"><div class="flex-shrink-0 border-b border-border p-4"><h2 class="text-lg font-semibold flex items-center gap-2"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-text h-5 w-5" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"></path><path d="M14 2v4a2 2 0 0 0 2 2h4"></path><path d="M10 9H8"></path><path d="M16 13H8"></path><path d="M16 17H8"></path></svg>로그 파일</h2><p class="text-sm text-muted-foreground">로딩 중...</p></div><div class="flex-1 min-h-0"><div dir="ltr" class="relative overflow-hidden h-full" style="position:relative;--radix-scroll-area-corner-width:0px;--radix-scroll-area-corner-height:0px"><style>[data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none}</style><div data-radix-scroll-area-viewport="" class="h-full w-full rounded-[inherit]" style="overflow-x:hidden;overflow-y:hidden"><div style="min-width:100%;display:table"><div class="p-4 text-center text-muted-foreground"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-refresh-cw h-6 w-6 animate-spin mx-auto mb-2" aria-hidden="true"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path><path d="M21 3v5h-5"></path><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path><path d="M8 16H3v5"></path></svg>로딩 중...</div></div></div></div></div></div><div class="flex-1 min-w-0"><div class="rounded-lg border bg-card text-card-foreground shadow-sm h-full"><div class="p-6 pt-0 flex items-center justify-center h-full"><div class="text-center text-muted-foreground"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-square-pen h-12 w-12 mx-auto mb-4 opacity-50" aria-hidden="true"><path d="M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z"></path></svg><p class="text-lg">REQ 파일을 선택하세요</p><p class="text-sm">요청 파일을 선택하면 내용을 편집하고 재실행할 수 있습니다</p></div></div></div></div></div><!--$--><!--/$--><div data-rht-toaster="" style="position:fixed;z-index:9999;top:16px;left:16px;right:16px;bottom:16px;pointer-events:none"></div><script src="/_next/static/chunks/e411019f55d87c42.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n3:I[37457,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"default\"]\n4:I[5766,[\"/_next/static/chunks/cdd12d5c1a5a6064.js\"],\"Toaster\"]\n5:I[47257,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"ClientPageRoot\"]\n6:I[31713,[\"/_next/static/chunks/cdd12d5c1a5a6064.js\",\"/_next/static/chunks/f1ac9047ac4a3fde.js\",\"/_next/static/chunks/37d0cd2587a38f79.js\"],\"default\"]\n9:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"OutletBoundary\"]\nb:I[11533,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"AsyncMetadataOutlet\"]\nd:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"ViewportBoundary\"]\nf:I[97367,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"MetadataBoundary\"]\n10:\"$Sreact.suspense\"\n12:I[68027,[\"/_next/static/chunks/cdd12d5c1a5a6064.js\"],\"default\"]\n:HL[\"/_next/static/chunks/ecd2072ebf41611f.css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"0ijq_fdWNnOdKxNRAYEdQ\",\"p\":\"\",\"c\":[\"\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/ecd2072ebf41611f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/cdd12d5c1a5a6064.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"ko\",\"className\":\"dark h-full\",\"children\":[\"$\",\"body\",null,{\"className\":\"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden\",\"children\":[[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L4\",null,{\"position\":\"bottom-right\",\"toastOptions\":{\"duration\":4000,\"style\":{\"background\":\"hsl(var(--background))\",\"color\":\"hsl(var(--foreground))\",\"border\":\"1px solid hsl(var(--border))\"}}}]]}]}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L5\",null,{\"Component\":\"$6\",\"searchParams\":{},\"params\":{},\"promises\":[\"$@7\",\"$@8\"]}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/f1ac9047ac4a3fde.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/37d0cd2587a38f79.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L9\",null,{\"children\":[\"$La\",[\"$\",\"$Lb\",null,{\"promise\":\"$@c\"}]]}]]}],{},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$Ld\",null,{\"children\":\"$Le\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$Lf\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$10\",null,{\"fallback\":null,\"children\":\"$L11\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$12\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/ecd2072ebf41611f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"7:{}\n8:\"$0:f:0:1:2:children:1:props:children:0:props:params\"\n"])</script><script>self.__next_f.push([1,"e:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\na:null\n"])</script><script>self.__next_f.push([1,"13:I[27201,[\"/_next/static/chunks/060f9a97930f3d04.js\"],\"IconMark\"]\nc:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Payload Log Viewer\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"AI Agent 로그 파일 뷰어 및 편집기\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0b3bf435.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L13\",\"3\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"11:\"$c:metadata\"\n"])</script></body></html>
|
|
@@ -13,7 +13,7 @@ f:I[97367,["/_next/static/chunks/060f9a97930f3d04.js"],"MetadataBoundary"]
|
|
|
13
13
|
:HL["/_next/static/chunks/ecd2072ebf41611f.css","style"]
|
|
14
14
|
:HL["/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
15
15
|
:HL["/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
16
|
-
0:{"P":null,"b":"
|
|
16
|
+
0:{"P":null,"b":"0ijq_fdWNnOdKxNRAYEdQ","p":"","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/ecd2072ebf41611f.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/cdd12d5c1a5a6064.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"ko","className":"dark h-full","children":["$","body",null,{"className":"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased h-screen overflow-hidden","children":[["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}],["$","$L4",null,{"position":"bottom-right","toastOptions":{"duration":4000,"style":{"background":"hsl(var(--background))","color":"hsl(var(--foreground))","border":"1px solid hsl(var(--border))"}}}]]}]}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","searchParams":{},"params":{},"promises":["$@7","$@8"]}],[["$","script","script-0",{"src":"/_next/static/chunks/f1ac9047ac4a3fde.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/37d0cd2587a38f79.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$La",["$","$Lb",null,{"promise":"$@c"}]]}]]}],{},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$Ld",null,{"children":"$Le"}],["$","meta",null,{"name":"next-size-adjust","content":""}]],["$","$Lf",null,{"children":["$","div",null,{"hidden":true,"children":["$","$10",null,{"fallback":null,"children":"$L11"}]}]}]]}],false]],"m":"$undefined","G":["$12",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/ecd2072ebf41611f.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"s":false,"S":true}
|
|
17
17
|
7:{}
|
|
18
18
|
8:"$0:f:0:1:2:children:1:props:children:0:props:params"
|
|
19
19
|
e:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
package/src/frontend/App.js
CHANGED
|
@@ -12,6 +12,7 @@ import { SessionSpinner } from './components/SessionSpinner.js';
|
|
|
12
12
|
import { ConversationItem } from './components/ConversationItem.js';
|
|
13
13
|
import { BlankLine } from './components/BlankLine.js';
|
|
14
14
|
import { TodoList } from './components/TodoList.js';
|
|
15
|
+
import { LoadingIndicator } from './components/LoadingIndicator.js';
|
|
15
16
|
import { useTextBuffer } from './utils/inputBuffer.js';
|
|
16
17
|
import { uiEvents } from '../system/ui_events.js';
|
|
17
18
|
import { getToolDisplayConfig, extractMessageFromArgs, formatToolCall, formatToolResult, getToolDisplayName } from '../system/tool_registry.js';
|
|
@@ -21,6 +22,12 @@ import { createDebugLogger } from '../util/debug_log.js';
|
|
|
21
22
|
|
|
22
23
|
const debugLog = createDebugLogger('ui_app.log', 'App');
|
|
23
24
|
|
|
25
|
+
// Loading task IDs
|
|
26
|
+
const LOADING_TASK_IDS = {
|
|
27
|
+
VERSION_CHECK: 'version_check',
|
|
28
|
+
MCP_INIT: 'mcp_init'
|
|
29
|
+
};
|
|
30
|
+
|
|
24
31
|
/**
|
|
25
32
|
* 빈 줄 추가 여부를 결정하는 함수
|
|
26
33
|
*
|
|
@@ -265,8 +272,8 @@ function createItemsWithBlankLines(items, terminalWidth, startKey, keyPrefix = '
|
|
|
265
272
|
}
|
|
266
273
|
|
|
267
274
|
// Memoized header component
|
|
268
|
-
const MemoizedHeader = memo(function MemoizedHeader({ version }) {
|
|
269
|
-
return React.createElement(Header, { version });
|
|
275
|
+
const MemoizedHeader = memo(function MemoizedHeader({ version, updateInfo }) {
|
|
276
|
+
return React.createElement(Header, { version, updateInfo });
|
|
270
277
|
});
|
|
271
278
|
|
|
272
279
|
// Memoized footer component
|
|
@@ -314,12 +321,16 @@ function formatEventAsText(event) {
|
|
|
314
321
|
}
|
|
315
322
|
|
|
316
323
|
// Main app component
|
|
317
|
-
export function App({ onSubmit, onClearScreen, onExit, commands = [], model, version, initialHistory = [], reasoningEffort: initialReasoningEffort = null }) {
|
|
324
|
+
export function App({ onSubmit, onClearScreen, onExit, commands = [], model, version, initialHistory = [], reasoningEffort: initialReasoningEffort = null, updateInfo: initialUpdateInfo = null }) {
|
|
318
325
|
const { stdout } = useStdout();
|
|
319
326
|
|
|
320
327
|
// Model state for dynamic updates
|
|
321
328
|
const [currentModel, setCurrentModel] = useState(model);
|
|
322
329
|
const [reasoningEffort, setReasoningEffort] = useState(initialReasoningEffort);
|
|
330
|
+
const [updateInfo, setUpdateInfo] = useState(initialUpdateInfo);
|
|
331
|
+
const [isVersionCheckComplete, setIsVersionCheckComplete] = useState(false);
|
|
332
|
+
const [isMcpInitComplete, setIsMcpInitComplete] = useState(false);
|
|
333
|
+
const [loadingTasks, setLoadingTasks] = useState([]);
|
|
323
334
|
|
|
324
335
|
// Memoize terminal width to prevent re-renders on stdout changes
|
|
325
336
|
const terminalWidth = useMemo(() => stdout.columns || 80, [stdout.columns]);
|
|
@@ -352,9 +363,7 @@ export function App({ onSubmit, onClearScreen, onExit, commands = [], model, ver
|
|
|
352
363
|
const [todos, setTodos] = useState([]);
|
|
353
364
|
|
|
354
365
|
// Static items: 메모이제이션된 React 엘리먼트들 (Static 컴포넌트 제거로 스크롤 문제 해결)
|
|
355
|
-
const [staticItems, setStaticItems] = useState(() => [
|
|
356
|
-
React.createElement(MemoizedHeader, { key: 'header', version })
|
|
357
|
-
]);
|
|
366
|
+
const [staticItems, setStaticItems] = useState(() => []);
|
|
358
367
|
|
|
359
368
|
// initialHistory를 staticItems에 추가 (초기 렌더링 시 한 번만)
|
|
360
369
|
const initialHistoryAddedRef = useRef(false);
|
|
@@ -423,16 +432,14 @@ export function App({ onSubmit, onClearScreen, onExit, commands = [], model, ver
|
|
|
423
432
|
const handleClearScreen = useCallback(() => {
|
|
424
433
|
setHistory([]);
|
|
425
434
|
setPendingHistory([]);
|
|
426
|
-
// Reset static items
|
|
427
|
-
setStaticItems([
|
|
428
|
-
React.createElement(MemoizedHeader, { key: 'header', version })
|
|
429
|
-
]);
|
|
435
|
+
// Reset static items
|
|
436
|
+
setStaticItems([]);
|
|
430
437
|
// Reset key counter
|
|
431
438
|
staticItemKeyCounter.current = 0;
|
|
432
439
|
if (onClearScreen) {
|
|
433
440
|
onClearScreen();
|
|
434
441
|
}
|
|
435
|
-
}, [onClearScreen
|
|
442
|
+
}, [onClearScreen]);
|
|
436
443
|
|
|
437
444
|
// Hide terminal cursor to prevent double cursor issue
|
|
438
445
|
useEffect(() => {
|
|
@@ -851,10 +858,8 @@ export function App({ onSubmit, onClearScreen, onExit, commands = [], model, ver
|
|
|
851
858
|
const handleClearScreen = () => {
|
|
852
859
|
setHistory([]);
|
|
853
860
|
setPendingHistory([]);
|
|
854
|
-
// Reset static items
|
|
855
|
-
setStaticItems([
|
|
856
|
-
React.createElement(MemoizedHeader, { key: 'header', version })
|
|
857
|
-
]);
|
|
861
|
+
// Reset static items
|
|
862
|
+
setStaticItems([]);
|
|
858
863
|
// Reset key counter
|
|
859
864
|
staticItemKeyCounter.current = 0;
|
|
860
865
|
};
|
|
@@ -886,6 +891,47 @@ export function App({ onSubmit, onClearScreen, onExit, commands = [], model, ver
|
|
|
886
891
|
}
|
|
887
892
|
};
|
|
888
893
|
|
|
894
|
+
const handleVersionUpdate = (event) => {
|
|
895
|
+
const info = event.updateInfo;
|
|
896
|
+
if (info && info.updateAvailable) {
|
|
897
|
+
debugLog(`[handleVersionUpdate] Update available: ${info.remoteVersion}`);
|
|
898
|
+
} else {
|
|
899
|
+
debugLog(`[handleVersionUpdate] No update available or check failed`);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// 버전 체크 완료 후 Header를 Static에 추가
|
|
903
|
+
debugLog(`[handleVersionUpdate] Adding header to static items`);
|
|
904
|
+
setStaticItems(prevItems => {
|
|
905
|
+
const headerElement = React.createElement(MemoizedHeader, {
|
|
906
|
+
key: 'header-static',
|
|
907
|
+
version,
|
|
908
|
+
updateInfo: info
|
|
909
|
+
});
|
|
910
|
+
return [headerElement, ...prevItems];
|
|
911
|
+
});
|
|
912
|
+
|
|
913
|
+
// 버전 체크 완료 표시 및 로딩 태스크에서 제거
|
|
914
|
+
setIsVersionCheckComplete(true);
|
|
915
|
+
setLoadingTasks(prev => prev.filter(task => task.id !== LOADING_TASK_IDS.VERSION_CHECK));
|
|
916
|
+
};
|
|
917
|
+
|
|
918
|
+
const handleMcpInitialized = (event) => {
|
|
919
|
+
debugLog(`[handleMcpInitialized] MCP initialization complete`);
|
|
920
|
+
setIsMcpInitComplete(true);
|
|
921
|
+
setLoadingTasks(prev => prev.filter(task => task.id !== LOADING_TASK_IDS.MCP_INIT));
|
|
922
|
+
};
|
|
923
|
+
|
|
924
|
+
const handleLoadingTaskAdd = (event) => {
|
|
925
|
+
debugLog(`[handleLoadingTaskAdd] Adding task: ${event.id} - ${event.text}`);
|
|
926
|
+
setLoadingTasks(prev => {
|
|
927
|
+
// 중복 방지: 같은 ID가 이미 있으면 추가하지 않음
|
|
928
|
+
if (prev.some(task => task.id === event.id)) {
|
|
929
|
+
return prev;
|
|
930
|
+
}
|
|
931
|
+
return [...prev, { id: event.id, text: event.text }];
|
|
932
|
+
});
|
|
933
|
+
};
|
|
934
|
+
|
|
889
935
|
uiEvents.on('history:add', handleHistoryAdd);
|
|
890
936
|
uiEvents.on('session:state', handleSessionState);
|
|
891
937
|
uiEvents.on('screen:clear', handleClearScreen);
|
|
@@ -894,6 +940,9 @@ export function App({ onSubmit, onClearScreen, onExit, commands = [], model, ver
|
|
|
894
940
|
uiEvents.on('reasoning_effort:changed', handleReasoningEffortChanged);
|
|
895
941
|
uiEvents.on('setup:show', handleSetupShow);
|
|
896
942
|
uiEvents.on('todos:update', handleTodosUpdate);
|
|
943
|
+
uiEvents.on('version:update', handleVersionUpdate);
|
|
944
|
+
uiEvents.on('mcp:initialized', handleMcpInitialized);
|
|
945
|
+
uiEvents.on('loading:task_add', handleLoadingTaskAdd);
|
|
897
946
|
|
|
898
947
|
return () => {
|
|
899
948
|
uiEvents.off('history:add', handleHistoryAdd);
|
|
@@ -904,8 +953,11 @@ export function App({ onSubmit, onClearScreen, onExit, commands = [], model, ver
|
|
|
904
953
|
uiEvents.off('reasoning_effort:changed', handleReasoningEffortChanged);
|
|
905
954
|
uiEvents.off('setup:show', handleSetupShow);
|
|
906
955
|
uiEvents.off('todos:update', handleTodosUpdate);
|
|
956
|
+
uiEvents.off('version:update', handleVersionUpdate);
|
|
957
|
+
uiEvents.off('mcp:initialized', handleMcpInitialized);
|
|
958
|
+
uiEvents.off('loading:task_add', handleLoadingTaskAdd);
|
|
907
959
|
};
|
|
908
|
-
}, [addToHistory, handleSessionTransition]);
|
|
960
|
+
}, [addToHistory, handleSessionTransition, version]);
|
|
909
961
|
|
|
910
962
|
// 승인 요청 처리
|
|
911
963
|
const handleApprovalDecision = useCallback((decision) => {
|
|
@@ -968,6 +1020,13 @@ export function App({ onSubmit, onClearScreen, onExit, commands = [], model, ver
|
|
|
968
1020
|
);
|
|
969
1021
|
}
|
|
970
1022
|
|
|
1023
|
+
// 버전 체크 또는 MCP 초기화가 완료되지 않았으면 로딩 인디케이터 표시
|
|
1024
|
+
if (!isVersionCheckComplete || !isMcpInitComplete) {
|
|
1025
|
+
return React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
1026
|
+
React.createElement(LoadingIndicator, { tasks: loadingTasks })
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
971
1030
|
return React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
972
1031
|
// History area (grows to fill available space, shrinks when needed)
|
|
973
1032
|
React.createElement(Box, {
|
|
@@ -976,7 +1035,7 @@ export function App({ onSubmit, onClearScreen, onExit, commands = [], model, ver
|
|
|
976
1035
|
flexShrink: 1,
|
|
977
1036
|
overflow: 'hidden' // Prevent history from pushing out fixed elements
|
|
978
1037
|
},
|
|
979
|
-
// Static items:
|
|
1038
|
+
// Static items: Header와 히스토리 포함
|
|
980
1039
|
React.createElement(Static, { items: staticItems }, (item) => item)
|
|
981
1040
|
),
|
|
982
1041
|
|
|
@@ -18,18 +18,25 @@ import { theme } from '../design/themeColors.js';
|
|
|
18
18
|
// d88P 888 8888888 8888888888 d88P Y88b 8888888888 "Y8888P "Y88P" "Y88888 "Y8888
|
|
19
19
|
// `;
|
|
20
20
|
|
|
21
|
-
export function Header({ version = '1.0.0' }) {
|
|
21
|
+
export function Header({ version = '1.0.0', updateInfo = null }) {
|
|
22
22
|
const ASCII_LOGO = `
|
|
23
|
-
▞▀▖▜▘▛▀▘▌ ▌▛▀▘ ▌
|
|
23
|
+
▞▀▖▜▘▛▀▘▌ ▌▛▀▘ ▌
|
|
24
24
|
▙▄▌▐ ▙▄ ▝▞ ▙▄ ▞▀▖▞▀▖▞▀▌▞▀▖
|
|
25
|
-
▌ ▌▐ ▌ ▞▝▖▌ ▌ ▖▌ ▌▌ ▌▛▀
|
|
25
|
+
▌ ▌▐ ▌ ▞▝▖▌ ▌ ▖▌ ▌▌ ▌▛▀
|
|
26
26
|
▘ ▘▀▘▀▀▘▘ ▘▀▀▘▝▀ ▝▀ ▝▀▘▝▀▘
|
|
27
27
|
by 코드깎는노인
|
|
28
28
|
`.split('\n').map(line => line.trim()).join("\n");
|
|
29
29
|
return React.createElement(Box, { flexDirection: "column", marginBottom: 1, marginLeft: 2 },
|
|
30
30
|
React.createElement(Text, { color: theme.brand.light }, ASCII_LOGO),
|
|
31
31
|
React.createElement(Box, { justifyContent: "flex-left" },
|
|
32
|
-
React.createElement(Text, { color: theme.text.secondary }, `AIEXEcode v${version}`)
|
|
32
|
+
React.createElement(Text, { color: theme.text.secondary }, `AIEXEcode v${version}`),
|
|
33
|
+
updateInfo && updateInfo.updateAvailable && React.createElement(Text, null,
|
|
34
|
+
React.createElement(Text, { color: '#666666' }, ' → '),
|
|
35
|
+
React.createElement(Text, { color: theme.status.warning }, `v${updateInfo.remoteVersion}`),
|
|
36
|
+
React.createElement(Text, null, ' available ('),
|
|
37
|
+
React.createElement(Text, { color: '#FFD700' }, 'npm install aiexecode -g'),
|
|
38
|
+
React.createElement(Text, null, ')')
|
|
39
|
+
)
|
|
33
40
|
)
|
|
34
41
|
);
|
|
35
42
|
}
|
|
@@ -13,9 +13,41 @@ import { uiEvents } from '../../system/ui_events.js';
|
|
|
13
13
|
import chalk from 'chalk';
|
|
14
14
|
import stringWidth from 'string-width';
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// 20개의 placeholder 메시지
|
|
17
|
+
const PLACEHOLDER_MESSAGES = [
|
|
18
|
+
' Fix all bugs in the codebase',
|
|
19
|
+
' Add unit tests for the API',
|
|
20
|
+
' Refactor the authentication module',
|
|
21
|
+
' Optimize database queries',
|
|
22
|
+
' Implement user profile page',
|
|
23
|
+
' Add error handling to services',
|
|
24
|
+
' Write documentation for utils',
|
|
25
|
+
' Create REST API endpoints',
|
|
26
|
+
' Set up CI/CD pipeline',
|
|
27
|
+
' Improve code performance',
|
|
28
|
+
' Add input validation',
|
|
29
|
+
' Implement caching layer',
|
|
30
|
+
' Fix linting errors',
|
|
31
|
+
' Add logging functionality',
|
|
32
|
+
' Create data migration scripts',
|
|
33
|
+
' Implement search feature',
|
|
34
|
+
' Add authentication middleware',
|
|
35
|
+
' Optimize bundle size',
|
|
36
|
+
' Update dependencies',
|
|
37
|
+
' Add responsive design'
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
// 무작위 placeholder 선택 함수
|
|
41
|
+
function getRandomPlaceholder() {
|
|
42
|
+
return PLACEHOLDER_MESSAGES[Math.floor(Math.random() * PLACEHOLDER_MESSAGES.length)];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function InputPromptComponent({ buffer, onSubmit, onClearScreen, onExit, commands = [], placeholder, focus = true, isSessionRunning = false }) {
|
|
17
46
|
const [isExiting, setIsExiting] = useState(false);
|
|
18
47
|
|
|
48
|
+
// placeholder가 제공되지 않으면 무작위로 선택 (컴포넌트 마운트 시 한 번만)
|
|
49
|
+
const defaultPlaceholder = useMemo(() => placeholder || getRandomPlaceholder(), []);
|
|
50
|
+
|
|
19
51
|
const completionRaw = useCompletion(buffer, commands);
|
|
20
52
|
|
|
21
53
|
// Stabilize completion object to prevent handleInput from being recreated
|
|
@@ -249,12 +281,12 @@ function InputPromptComponent({ buffer, onSubmit, onClearScreen, onExit, command
|
|
|
249
281
|
},
|
|
250
282
|
React.createElement(Text, { color: theme.brand.light }, '> '),
|
|
251
283
|
React.createElement(Box, { flexGrow: 1, flexDirection: "column" },
|
|
252
|
-
bufferTextLength === 0 &&
|
|
284
|
+
bufferTextLength === 0 && defaultPlaceholder
|
|
253
285
|
? (focus
|
|
254
286
|
? React.createElement(Text, null,
|
|
255
|
-
chalk.inverse(
|
|
256
|
-
React.createElement(Text, { color: theme.text.secondary },
|
|
257
|
-
: React.createElement(Text, { color: theme.text.secondary },
|
|
287
|
+
chalk.inverse(defaultPlaceholder.slice(0, 1)),
|
|
288
|
+
React.createElement(Text, { color: theme.text.secondary }, defaultPlaceholder.slice(1)))
|
|
289
|
+
: React.createElement(Text, { color: theme.text.secondary }, defaultPlaceholder))
|
|
258
290
|
: linesToRender.map((lineText, visualIdxInRenderedSet) => {
|
|
259
291
|
const isOnCursorLine = focus && visualIdxInRenderedSet === cursorVisualRow;
|
|
260
292
|
let display = lineText;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loading Indicator component
|
|
3
|
+
* Displays a loading spinner during initialization
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { Box, Text } from 'ink';
|
|
8
|
+
import Spinner from 'ink-spinner';
|
|
9
|
+
|
|
10
|
+
export function LoadingIndicator({ tasks = [] }) {
|
|
11
|
+
return React.createElement(Box, {
|
|
12
|
+
flexDirection: "column",
|
|
13
|
+
alignItems: "center",
|
|
14
|
+
justifyContent: "center",
|
|
15
|
+
height: 10
|
|
16
|
+
},
|
|
17
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
18
|
+
React.createElement(Text, { color: "cyan" },
|
|
19
|
+
React.createElement(Spinner, { type: "dots" }),
|
|
20
|
+
" Initializing..."
|
|
21
|
+
)
|
|
22
|
+
),
|
|
23
|
+
tasks.length > 0 && tasks.map((task) =>
|
|
24
|
+
React.createElement(Text, {
|
|
25
|
+
key: task.id,
|
|
26
|
+
color: "gray",
|
|
27
|
+
dimColor: true
|
|
28
|
+
}, task.text)
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version check utility
|
|
3
|
+
* Compares local version with remote version from GitHub
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createDebugLogger } from './debug_log.js';
|
|
7
|
+
import https from 'https';
|
|
8
|
+
|
|
9
|
+
const debugLog = createDebugLogger('version_check.log', 'version_check');
|
|
10
|
+
|
|
11
|
+
const REMOTE_PACKAGE_JSON_URL = 'https://raw.githubusercontent.com/kstost/aiexecode/refs/heads/main/package.json';
|
|
12
|
+
const TIMEOUT_MS = 5000; // 5 seconds timeout
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Fetch remote package.json from GitHub
|
|
16
|
+
* @returns {Promise<Object|null>} Remote package.json object or null on error
|
|
17
|
+
*/
|
|
18
|
+
async function fetchRemotePackageJson() {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
const req = https.get(REMOTE_PACKAGE_JSON_URL, { timeout: TIMEOUT_MS }, (res) => {
|
|
21
|
+
let data = '';
|
|
22
|
+
|
|
23
|
+
res.on('data', (chunk) => {
|
|
24
|
+
data += chunk;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
res.on('end', () => {
|
|
28
|
+
if (res.statusCode === 200) {
|
|
29
|
+
try {
|
|
30
|
+
const packageJson = JSON.parse(data);
|
|
31
|
+
resolve(packageJson);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
debugLog(`Failed to parse remote package.json: ${err.message}`);
|
|
34
|
+
resolve(null);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
debugLog(`HTTP ${res.statusCode} when fetching remote package.json`);
|
|
38
|
+
resolve(null);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
req.on('error', (err) => {
|
|
44
|
+
debugLog(`Network error when fetching remote package.json: ${err.message}`);
|
|
45
|
+
resolve(null);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
req.on('timeout', () => {
|
|
49
|
+
debugLog('Timeout when fetching remote package.json');
|
|
50
|
+
req.destroy();
|
|
51
|
+
resolve(null);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Compare two semantic versions
|
|
58
|
+
* @param {string} version1 - First version (e.g., "1.0.76")
|
|
59
|
+
* @param {string} version2 - Second version (e.g., "1.0.77")
|
|
60
|
+
* @returns {number} -1 if version1 < version2, 0 if equal, 1 if version1 > version2
|
|
61
|
+
*/
|
|
62
|
+
function compareVersions(version1, version2) {
|
|
63
|
+
const v1parts = version1.split('.').map(Number);
|
|
64
|
+
const v2parts = version2.split('.').map(Number);
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < Math.max(v1parts.length, v2parts.length); i++) {
|
|
67
|
+
const v1 = v1parts[i] || 0;
|
|
68
|
+
const v2 = v2parts[i] || 0;
|
|
69
|
+
|
|
70
|
+
if (v1 < v2) return -1;
|
|
71
|
+
if (v1 > v2) return 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check for available updates
|
|
79
|
+
* @param {string} currentVersion - Current local version
|
|
80
|
+
* @returns {Promise<Object>} Object with { hasUpdate: boolean, remoteVersion: string|null, updateAvailable: boolean }
|
|
81
|
+
*/
|
|
82
|
+
export async function checkForUpdates(currentVersion) {
|
|
83
|
+
debugLog(`Checking for updates... Current version: ${currentVersion}`);
|
|
84
|
+
|
|
85
|
+
const remotePackageJson = await fetchRemotePackageJson();
|
|
86
|
+
|
|
87
|
+
if (!remotePackageJson || !remotePackageJson.version) {
|
|
88
|
+
debugLog('Could not fetch remote version');
|
|
89
|
+
return {
|
|
90
|
+
hasUpdate: false,
|
|
91
|
+
remoteVersion: null,
|
|
92
|
+
updateAvailable: false
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const remoteVersion = remotePackageJson.version;
|
|
97
|
+
debugLog(`Remote version: ${remoteVersion}`);
|
|
98
|
+
|
|
99
|
+
const comparison = compareVersions(currentVersion, remoteVersion);
|
|
100
|
+
|
|
101
|
+
if (comparison < 0) {
|
|
102
|
+
debugLog(`Update available: ${currentVersion} → ${remoteVersion}`);
|
|
103
|
+
return {
|
|
104
|
+
hasUpdate: true,
|
|
105
|
+
remoteVersion,
|
|
106
|
+
updateAvailable: true
|
|
107
|
+
};
|
|
108
|
+
} else {
|
|
109
|
+
debugLog('No update available (local version is up to date or newer)');
|
|
110
|
+
return {
|
|
111
|
+
hasUpdate: false,
|
|
112
|
+
remoteVersion,
|
|
113
|
+
updateAvailable: false
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|