@yr-kits/dev-copilot 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/bin/bridge.d.mts +1 -0
- package/dist/bin/bridge.mjs +892 -0
- package/dist/bin/bridge.mjs.map +1 -0
- package/dist/bin/dev-copilot.d.mts +1 -0
- package/dist/bin/dev-copilot.mjs +122 -0
- package/dist/bin/dev-copilot.mjs.map +1 -0
- package/dist/index.d.mts +33 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +850 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types/index.d.mts +43 -0
- package/dist/types/index.d.mts.map +1 -0
- package/dist/types/index.mjs +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/config.ts","../src/components/dev-copilot-provider.tsx","../src/lib/api-client.ts","../src/hooks/use-selection-capture.ts","../src/components/icons.tsx","../src/components/dev-copilot-overlay.tsx"],"sourcesContent":["export interface DevCopilotConfig {\n enabled: boolean;\n allowedPaths: string[];\n}\n\nconst defaultConfig: DevCopilotConfig = {\n enabled: process.env.NODE_ENV === \"development\",\n allowedPaths: [\".\"],\n};\n\nexport const resolveDevCopilotConfig = (\n config?: Partial<DevCopilotConfig>,\n): DevCopilotConfig => {\n const nextConfig = config ?? {};\n\n return {\n ...defaultConfig,\n ...nextConfig,\n };\n};\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nimport {\n resolveDevCopilotConfig,\n type DevCopilotConfig,\n} from \"../lib/config\";\n\nconst DevCopilotContext = createContext<DevCopilotConfig | null>(null);\n\ninterface DevCopilotProviderProps {\n config?: Partial<DevCopilotConfig>;\n children: ReactNode;\n}\n\nexport function DevCopilotProvider({\n config,\n children,\n}: DevCopilotProviderProps) {\n const resolvedConfig = resolveDevCopilotConfig(config);\n\n return (\n <DevCopilotContext.Provider value={resolvedConfig}>\n {children}\n </DevCopilotContext.Provider>\n );\n}\n\nexport const useDevCopilotConfig = () => {\n const context = useContext(DevCopilotContext);\n\n if (!context) {\n throw new Error(\"DevCopilotProvider 내부에서만 사용할 수 있습니다.\");\n }\n\n return context;\n};\n","import type {\n CopilotAgent,\n CopilotApplyRequest,\n CopilotApplyResponse,\n CopilotAgentStatusResponse,\n CopilotChatRequest,\n CopilotChatResponse,\n CopilotErrorResponse,\n} from \"../types\";\n\nconst API_BASE_URL = \"http://127.0.0.1:3339\";\n\nconst parseResponse = async <T>(response: Response): Promise<T> => {\n const payload = (await response.json()) as T | CopilotErrorResponse;\n\n if (!response.ok) {\n const errorMessage =\n typeof payload === \"object\" && payload && \"error\" in payload\n ? payload.error\n : \"요청 처리 중 오류가 발생했습니다.\";\n throw new Error(errorMessage);\n }\n\n return payload as T;\n};\n\nexport const createCopilotApiClient = () => {\n const post = async <T, U>(path: string, body: T): Promise<U> => {\n const response = await fetch(`${API_BASE_URL}${path}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n return parseResponse<U>(response);\n };\n\n return {\n status: async (agent?: CopilotAgent) => {\n const query = agent ? `?agent=${agent}` : \"\";\n const response = await fetch(`${API_BASE_URL}/status${query}`);\n return parseResponse<CopilotAgentStatusResponse>(response);\n },\n chat: (payload: CopilotChatRequest) =>\n post<CopilotChatRequest, CopilotChatResponse>(\"/chat\", payload),\n apply: (payload: CopilotApplyRequest) =>\n post<CopilotApplyRequest, CopilotApplyResponse>(\"/apply\", payload),\n };\n};\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\n\nconst OVERLAY_ATTRIBUTE = \"data-dev-copilot-overlay\";\n\nconst toSelectionText = () => {\n const selection = window.getSelection();\n const value = selection?.toString().trim() ?? \"\";\n return value;\n};\n\nconst isNodeInsideOverlay = (node: Node | null) => {\n if (!node) {\n return false;\n }\n\n const element = node instanceof Element ? node : node.parentElement;\n\n return Boolean(element?.closest(`[${OVERLAY_ATTRIBUTE}]`));\n};\n\nconst isInsideOverlay = (target: EventTarget | null) => {\n return (\n target instanceof Element &&\n Boolean(target.closest(`[${OVERLAY_ATTRIBUTE}]`))\n );\n};\n\nexport const useSelectionCapture = () => {\n const [selectedText, setSelectedText] = useState(\"\");\n\n const syncSelection = useCallback((event: MouseEvent | KeyboardEvent) => {\n const selection = window.getSelection();\n const startedInsideOverlay = isNodeInsideOverlay(selection?.anchorNode ?? null);\n const endedInsideOverlay = isNodeInsideOverlay(selection?.focusNode ?? null);\n\n if (isInsideOverlay(event.target) || startedInsideOverlay || endedInsideOverlay) {\n return;\n }\n\n const nextSelectedText = selection?.toString().trim() ?? toSelectionText();\n\n if (!nextSelectedText) {\n return;\n }\n\n setSelectedText(nextSelectedText);\n }, []);\n\n useEffect(() => {\n document.addEventListener(\"mouseup\", syncSelection);\n document.addEventListener(\"keyup\", syncSelection);\n\n return () => {\n document.removeEventListener(\"mouseup\", syncSelection);\n document.removeEventListener(\"keyup\", syncSelection);\n };\n }, [syncSelection]);\n\n return {\n selectedText,\n setSelectedText,\n clearSelection: () => setSelectedText(\"\"),\n };\n};\n\nexport { OVERLAY_ATTRIBUTE };\n","import type { ComponentPropsWithoutRef } from \"react\";\n\ntype SvgIconProps = ComponentPropsWithoutRef<\"svg\">;\n\nexport const SparklesIcon = (props: SvgIconProps) => {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M12 3.75 13.68 8.32 18.25 10 13.68 11.68 12 16.25 10.32 11.68 5.75 10 10.32 8.32 12 3.75Z\" />\n <path d=\"M18.5 3.75 19.08 5.42 20.75 6 19.08 6.58 18.5 8.25 17.92 6.58 16.25 6 17.92 5.42 18.5 3.75Z\" />\n <path d=\"M6 15.5 7 18.25 9.75 19.25 7 20.25 6 23 5 20.25 2.25 19.25 5 18.25 6 15.5Z\" />\n </svg>\n );\n};\n\nexport const PanelRightOpenIcon = (props: SvgIconProps) => {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <rect x=\"3.75\" y=\"4.75\" width=\"16.5\" height=\"14.5\" rx=\"2.25\" />\n <path d=\"M8.75 4.75v14.5\" />\n <path d=\"m13 9.25 3 2.75-3 2.75\" />\n </svg>\n );\n};\n\nexport const PanelRightCloseIcon = (props: SvgIconProps) => {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <rect x=\"3.75\" y=\"4.75\" width=\"16.5\" height=\"14.5\" rx=\"2.25\" />\n <path d=\"M15.25 4.75v14.5\" />\n <path d=\"m11 9.25-3 2.75 3 2.75\" />\n </svg>\n );\n};\n","\"use client\";\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\";\n\nimport { createCopilotApiClient } from \"../lib/api-client\";\nimport type {\n CopilotAgent,\n CopilotAgentStatusResponse,\n CopilotChatResponse,\n CopilotMode,\n} from \"../types\";\nimport {\n OVERLAY_ATTRIBUTE,\n useSelectionCapture,\n} from \"../hooks/use-selection-capture\";\nimport {\n PanelRightCloseIcon,\n PanelRightOpenIcon,\n SparklesIcon,\n} from \"./icons\";\nimport { useDevCopilotConfig } from \"./dev-copilot-provider\";\n\nconst FLOATING_BUTTON_SIZE = 48;\nconst DRAG_CLICK_THRESHOLD = 4;\nconst PANEL_WIDTH = \"min(1028px, calc(100vw - 48px))\";\nconst INPUT_PANEL_WIDTH = 420;\nconst RAIL_WIDTH = 36;\nconst AGENT_LABELS: Record<CopilotAgent, string> = {\n codex: \"Codex CLI\",\n claude: \"Claude Code CLI\",\n};\nconst UI_LABELS = {\n title: \"Dev Copilot\",\n subtitle: \"텍스트를 선택한 뒤 프롬프트를 입력하세요.\",\n promptPlaceholder: \"무엇을 도와드릴까요?\",\n askButton: \"질문\",\n editButton: \"코드 수정 제안\",\n applyButton: \"미리보기 적용\",\n} as const;\n\nconst styleText = `\n.yrdc-trigger{transition:transform 150ms ease-out, box-shadow 150ms ease-out}\n.yrdc-trigger:hover{transform:scale(1.05)}\n.yrdc-pressable{transition:transform 150ms ease-out, background-color 150ms ease-out, opacity 150ms ease-out}\n.yrdc-pressable:hover{transform:translateY(-1px)}\n.yrdc-spinner{animation:yrdc-spin 1s linear infinite}\n.yrdc-field:focus{outline:none;box-shadow:0 0 0 3px rgba(59,130,246,.14);border-color:#93c5fd}\n@keyframes yrdc-spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}\n`;\n\nexport function DevCopilotOverlay() {\n const config = useDevCopilotConfig();\n const apiClient = useMemo(() => createCopilotApiClient(), []);\n const { selectedText, setSelectedText } = useSelectionCapture();\n\n const [open, setOpen] = useState(false);\n const [prompt, setPrompt] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [chatResult, setChatResult] = useState<CopilotChatResponse | null>(null);\n const [toastMessage, setToastMessage] = useState<string | null>(null);\n const [agentStatus, setAgentStatus] =\n useState<CopilotAgentStatusResponse | null>(null);\n const [selectedAgent, setSelectedAgent] = useState<CopilotAgent>(\"codex\");\n const [position, setPosition] = useState<{ x: number; y: number } | null>(null);\n const [showResponsePanel, setShowResponsePanel] = useState(false);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const suppressMainToggleClickRef = useRef(false);\n const dragStateRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n originX: number;\n originY: number;\n moved: boolean;\n } | null>(null);\n\n useEffect(() => {\n const onResize = () => {\n setPosition((prev) => {\n if (!prev) {\n return prev;\n }\n\n return {\n x: Math.min(\n Math.max(prev.x, 0),\n Math.max(0, window.innerWidth - FLOATING_BUTTON_SIZE),\n ),\n y: Math.min(\n Math.max(prev.y, 0),\n Math.max(0, window.innerHeight - FLOATING_BUTTON_SIZE),\n ),\n };\n });\n };\n\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n let ignore = false;\n\n apiClient\n .status(selectedAgent)\n .then((status) => {\n if (!ignore) {\n setAgentStatus(status);\n }\n })\n .catch((caughtError) => {\n if (!ignore) {\n setAgentStatus({\n available: false,\n authenticated: false,\n agent: selectedAgent,\n message:\n caughtError instanceof Error\n ? caughtError.message\n : \"로컬 에이전트 상태 확인에 실패했습니다.\",\n });\n }\n });\n\n return () => {\n ignore = true;\n };\n }, [apiClient, open, selectedAgent]);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const onPointerDownOutside = (event: PointerEvent) => {\n const target = event.target;\n\n if (!(target instanceof Node)) {\n return;\n }\n\n if (containerRef.current?.contains(target)) {\n return;\n }\n\n setOpen(false);\n setShowResponsePanel(false);\n dragStateRef.current = null;\n suppressMainToggleClickRef.current = false;\n };\n\n document.addEventListener(\"pointerdown\", onPointerDownOutside);\n\n return () => {\n document.removeEventListener(\"pointerdown\", onPointerDownOutside);\n };\n }, [open]);\n\n if (!config.enabled) {\n return null;\n }\n\n const onPointerDown = (event: React.PointerEvent<HTMLButtonElement>) => {\n if (event.button !== 0) {\n return;\n }\n\n const wrapperRect = containerRef.current?.getBoundingClientRect();\n const originX = position?.x ?? wrapperRect?.left ?? 0;\n const originY = position?.y ?? wrapperRect?.top ?? 0;\n\n event.currentTarget.setPointerCapture(event.pointerId);\n dragStateRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n originX,\n originY,\n moved: false,\n };\n };\n\n const onPointerMove = (event: React.PointerEvent<HTMLButtonElement>) => {\n const dragState = dragStateRef.current;\n if (!dragState || dragState.pointerId !== event.pointerId) {\n return;\n }\n\n const deltaX = event.clientX - dragState.startX;\n const deltaY = event.clientY - dragState.startY;\n const moved =\n Math.abs(deltaX) > DRAG_CLICK_THRESHOLD ||\n Math.abs(deltaY) > DRAG_CLICK_THRESHOLD;\n\n if (!moved && !dragState.moved) {\n return;\n }\n\n dragState.moved = true;\n\n setPosition({\n x: Math.min(\n Math.max(dragState.originX + deltaX, 0),\n Math.max(0, window.innerWidth - FLOATING_BUTTON_SIZE),\n ),\n y: Math.min(\n Math.max(dragState.originY + deltaY, 0),\n Math.max(0, window.innerHeight - FLOATING_BUTTON_SIZE),\n ),\n });\n };\n\n const onPointerEnd = (event: React.PointerEvent<HTMLButtonElement>) => {\n if (dragStateRef.current?.pointerId !== event.pointerId) {\n return;\n }\n\n suppressMainToggleClickRef.current = dragStateRef.current.moved;\n dragStateRef.current = null;\n event.currentTarget.releasePointerCapture(event.pointerId);\n };\n\n const onMainToggleClick = () => {\n if (suppressMainToggleClickRef.current) {\n suppressMainToggleClickRef.current = false;\n return;\n }\n\n setOpen((prev) => {\n const next = !prev;\n if (!next) {\n setPosition(null);\n dragStateRef.current = null;\n suppressMainToggleClickRef.current = false;\n }\n return next;\n });\n };\n\n const previousResponse = chatResult\n ? [\n `message:\\n${chatResult.message}`,\n chatResult.patchPreview\n ? `patchPreview:\\n${chatResult.patchPreview}`\n : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\\n\")\n : undefined;\n\n const onSubmit = async (mode: CopilotMode) => {\n if (agentStatus && (!agentStatus.available || !agentStatus.authenticated)) {\n setError(agentStatus.message);\n return;\n }\n\n if (!prompt.trim()) {\n setError(\"프롬프트를 입력해 주세요.\");\n return;\n }\n\n setBusy(true);\n setError(null);\n setShowResponsePanel(true);\n\n try {\n const currentRoute =\n typeof window !== \"undefined\" ? window.location.pathname : undefined;\n const result = await apiClient.chat({\n selectedText,\n prompt,\n mode,\n context: {\n route: currentRoute,\n fileHints: config.allowedPaths,\n previousResponse,\n agent: selectedAgent,\n },\n });\n\n setChatResult(result);\n } catch (caughtError) {\n setError(\n caughtError instanceof Error\n ? caughtError.message\n : \"요청 처리 중 오류가 발생했습니다.\",\n );\n } finally {\n setBusy(false);\n }\n };\n\n const onApply = async () => {\n if (!chatResult?.patchId) {\n setError(\"적용 가능한 패치가 없습니다.\");\n return;\n }\n\n setBusy(true);\n setError(null);\n setShowResponsePanel(true);\n\n try {\n const result = await apiClient.apply({\n patchId: chatResult.patchId,\n approvalToken: `approve:${chatResult.patchId}`,\n });\n\n if (result.applied) {\n setToastMessage(result.summary);\n window.setTimeout(() => {\n setToastMessage(null);\n }, 3000);\n }\n } catch (caughtError) {\n setError(\n caughtError instanceof Error\n ? caughtError.message\n : \"패치 적용 중 오류가 발생했습니다.\",\n );\n } finally {\n setBusy(false);\n }\n };\n\n const floatingWrapperStyle: CSSProperties = position\n ? {\n position: \"fixed\",\n zIndex: 2147483000,\n left: `${position.x}px`,\n top: `${position.y}px`,\n }\n : {\n position: \"fixed\",\n right: 24,\n bottom: 24,\n zIndex: 2147483000,\n };\n\n const panelStyle: CSSProperties = {\n position: \"relative\",\n marginTop: 12,\n display: \"grid\",\n gridTemplateColumns: showResponsePanel\n ? `${INPUT_PANEL_WIDTH}px ${RAIL_WIDTH}px minmax(0, 1fr)`\n : `${INPUT_PANEL_WIDTH}px ${RAIL_WIDTH}px`,\n width: showResponsePanel ? PANEL_WIDTH : INPUT_PANEL_WIDTH + RAIL_WIDTH,\n maxHeight: \"calc(100vh - 96px)\",\n overflow: \"hidden\",\n border: \"1px solid #e5e7eb\",\n borderRadius: 24,\n background: \"#f8fafc\",\n boxShadow: \"0 18px 60px rgba(15, 23, 42, 0.16)\",\n color: \"#0f172a\",\n fontFamily:\n \"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n };\n\n return (\n <>\n <style>{styleText}</style>\n\n {toastMessage ? (\n <div style={toastStyle}>\n <p aria-live=\"polite\" style={{ margin: 0 }}>\n {toastMessage}\n </p>\n </div>\n ) : null}\n\n <div ref={containerRef} style={floatingWrapperStyle} {...{ [OVERLAY_ATTRIBUTE]: \"\" }}>\n <div>\n <button\n type=\"button\"\n className=\"yrdc-trigger\"\n style={triggerButtonStyle}\n onClick={onMainToggleClick}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerEnd}\n onPointerCancel={onPointerEnd}\n aria-label=\"Dev Copilot 열기\"\n title=\"Dev Copilot 열기/닫기 / 드래그해서 이동\"\n >\n <SparklesIcon aria-hidden style={{ width: 16, height: 16 }} />\n </button>\n </div>\n\n {open ? (\n <section style={panelStyle}>\n <div style={railStyle}>\n <button\n type=\"button\"\n className=\"yrdc-pressable\"\n style={railToggleStyle}\n onClick={() => setShowResponsePanel((prev) => !prev)}\n aria-label={showResponsePanel ? \"응답 패널 닫기\" : \"응답 패널 열기\"}\n title={showResponsePanel ? \"응답 패널 닫기\" : \"응답 패널 열기\"}\n >\n {showResponsePanel ? (\n <PanelRightCloseIcon aria-hidden style={{ width: 14, height: 14 }} />\n ) : (\n <PanelRightOpenIcon aria-hidden style={{ width: 14, height: 14 }} />\n )}\n </button>\n </div>\n\n <div style={inputPanelStyle}>\n <header>\n <p style={titleStyle}>{UI_LABELS.title}</p>\n <p style={subtitleStyle}>{UI_LABELS.subtitle}</p>\n </header>\n\n <div style={statusBoxStyle}>\n <p style={statusLineStyle}>로컬 에이전트: {AGENT_LABELS[selectedAgent]}</p>\n {agentStatus?.model ? (\n <p style={statusLineStyle}>모델: {agentStatus.model}</p>\n ) : null}\n {agentStatus ? (\n <p\n style={{\n ...statusLineStyle,\n color: agentStatus.authenticated ? \"#15803d\" : \"#dc2626\",\n }}\n >\n {agentStatus.message}\n {agentStatus.loginCommand\n ? ` 터미널에서 ${agentStatus.loginCommand} 실행`\n : \"\"}\n </p>\n ) : null}\n </div>\n\n <label style={labelStyle}>에이전트</label>\n <div style={agentToggleRowStyle}>\n {([\"codex\", \"claude\"] as CopilotAgent[]).map((agent) => {\n const active = selectedAgent === agent;\n return (\n <button\n key={agent}\n type=\"button\"\n className=\"yrdc-pressable\"\n onClick={() => setSelectedAgent(agent)}\n disabled={busy}\n style={{\n ...agentToggleButtonStyle,\n background: active ? \"#111827\" : \"#e2e8f0\",\n color: active ? \"#ffffff\" : \"#1e293b\",\n opacity: busy ? 0.6 : 1,\n }}\n >\n {AGENT_LABELS[agent]}\n </button>\n );\n })}\n </div>\n\n <label style={labelStyle}>선택 텍스트</label>\n <textarea\n value={selectedText}\n onChange={(event) => setSelectedText(event.target.value)}\n rows={5}\n className=\"yrdc-field\"\n style={textareaStyle}\n />\n\n <label style={labelStyle}>프롬프트</label>\n <textarea\n value={prompt}\n onChange={(event) => setPrompt(event.target.value)}\n rows={4}\n placeholder={UI_LABELS.promptPlaceholder}\n className=\"yrdc-field\"\n style={textareaStyle}\n />\n\n <div style={buttonRowStyle}>\n <button\n type=\"button\"\n className=\"yrdc-pressable\"\n onClick={() => onSubmit(\"answer\")}\n disabled={busy || Boolean(agentStatus && !agentStatus.authenticated)}\n style={{\n ...buttonStyle,\n background: \"#111827\",\n color: \"#ffffff\",\n opacity: busy || Boolean(agentStatus && !agentStatus.authenticated) ? 0.55 : 1,\n }}\n >\n {UI_LABELS.askButton}\n </button>\n <button\n type=\"button\"\n className=\"yrdc-pressable\"\n onClick={() => onSubmit(\"edit\")}\n disabled={busy || Boolean(agentStatus && !agentStatus.authenticated)}\n style={{\n ...buttonStyle,\n background: \"#2563eb\",\n color: \"#ffffff\",\n opacity: busy || Boolean(agentStatus && !agentStatus.authenticated) ? 0.55 : 1,\n }}\n >\n {UI_LABELS.editButton}\n </button>\n </div>\n </div>\n\n {showResponsePanel ? (\n <aside style={responsePanelStyle}>\n <div style={{ display: \"flex\", flexDirection: \"column\", minHeight: 320, height: \"100%\" }}>\n <div>\n <p style={titleStyle}>응답</p>\n </div>\n\n <div style={responseCardStyle}>\n {busy ? (\n <div style={busyContainerStyle}>\n <span className=\"yrdc-spinner\" style={spinnerStyle} />\n <span>{AGENT_LABELS[selectedAgent]} 응답을 기다리는 중입니다.</span>\n </div>\n ) : chatResult ? (\n <article style={articleStyle}>\n {error ? (\n <p style={errorBoxStyle}>{error}</p>\n ) : null}\n {chatResult.warnings.length ? (\n <div style={warningBoxStyle}>\n {chatResult.warnings.map((warning) => (\n <p key={warning} style={{ margin: 0 }}>\n {warning}\n </p>\n ))}\n </div>\n ) : null}\n <p style={messageStyle}>{chatResult.message}</p>\n\n {chatResult.patchPreview ? (\n <>\n <pre style={patchPreviewStyle}>{chatResult.patchPreview}</pre>\n {chatResult.patchId ? (\n <button\n type=\"button\"\n className=\"yrdc-pressable\"\n onClick={onApply}\n disabled={busy}\n style={{\n ...buttonStyle,\n alignSelf: \"flex-start\",\n background: \"#15803d\",\n color: \"#ffffff\",\n opacity: busy ? 0.55 : 1,\n }}\n >\n {UI_LABELS.applyButton}\n </button>\n ) : null}\n </>\n ) : null}\n </article>\n ) : error ? (\n <p style={errorBoxStyle}>{error}</p>\n ) : (\n <p style={placeholderStyle}>\n 질문 또는 코드 수정 제안을 실행하면 이 영역에 결과가 표시됩니다.\n </p>\n )}\n </div>\n </div>\n </aside>\n ) : null}\n </section>\n ) : null}\n </div>\n </>\n );\n}\n\nconst triggerButtonStyle: CSSProperties = {\n display: \"flex\",\n width: FLOATING_BUTTON_SIZE,\n height: FLOATING_BUTTON_SIZE,\n borderRadius: 9999,\n border: \"1px solid #f2d675\",\n background: \"#fff4b8\",\n color: \"#ffb03d\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxShadow: \"0 12px 28px rgba(15, 23, 42, 0.18)\",\n cursor: \"grab\",\n};\n\nconst railStyle: CSSProperties = {\n display: \"flex\",\n minHeight: 320,\n alignItems: \"center\",\n justifyContent: \"center\",\n borderLeft: \"1px solid #e5e7eb\",\n background: \"#f8fafc\",\n};\n\nconst railToggleStyle: CSSProperties = {\n display: \"flex\",\n width: 24,\n height: 24,\n border: \"0\",\n background: \"transparent\",\n color: \"#64748b\",\n cursor: \"pointer\",\n alignItems: \"center\",\n justifyContent: \"center\",\n};\n\nconst inputPanelStyle: CSSProperties = {\n padding: 16,\n minHeight: 0,\n overflowY: \"auto\",\n background: \"#ffffff\",\n};\n\nconst responsePanelStyle: CSSProperties = {\n minHeight: 0,\n overflow: \"hidden\",\n padding: 16,\n borderLeft: \"1px solid #e5e7eb\",\n background: \"#f8fafc\",\n};\n\nconst titleStyle: CSSProperties = {\n margin: 0,\n fontSize: 18,\n fontWeight: 700,\n lineHeight: 1.4,\n color: \"#111827\",\n};\n\nconst subtitleStyle: CSSProperties = {\n margin: \"4px 0 0\",\n fontSize: 14,\n lineHeight: 1.5,\n color: \"#6b7280\",\n};\n\nconst statusBoxStyle: CSSProperties = {\n marginTop: 12,\n border: \"1px solid #e5e7eb\",\n borderRadius: 16,\n background: \"#ffffff\",\n padding: \"12px 14px\",\n fontSize: 14,\n lineHeight: 1.6,\n color: \"#6b7280\",\n};\n\nconst statusLineStyle: CSSProperties = {\n margin: 0,\n};\n\nconst labelStyle: CSSProperties = {\n display: \"block\",\n marginTop: 16,\n fontSize: 14,\n lineHeight: 1.5,\n color: \"#6b7280\",\n};\n\nconst textareaStyle: CSSProperties = {\n width: \"100%\",\n resize: \"vertical\",\n borderRadius: 16,\n border: \"1px solid #e5e7eb\",\n background: \"#ffffff\",\n padding: \"12px 14px\",\n marginTop: 6,\n fontSize: 15,\n lineHeight: 1.7,\n color: \"#111827\",\n boxSizing: \"border-box\",\n minHeight: 132,\n};\n\nconst agentToggleRowStyle: CSSProperties = {\n display: \"flex\",\n gap: 8,\n marginTop: 6,\n};\n\nconst agentToggleButtonStyle: CSSProperties = {\n border: 0,\n borderRadius: 10,\n padding: \"8px 12px\",\n fontSize: 13,\n fontWeight: 600,\n lineHeight: 1.2,\n cursor: \"pointer\",\n};\n\nconst buttonRowStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n marginTop: 16,\n};\n\nconst buttonStyle: CSSProperties = {\n border: 0,\n borderRadius: 12,\n padding: \"10px 14px\",\n fontSize: 14,\n fontWeight: 600,\n lineHeight: 1,\n cursor: \"pointer\",\n};\n\nconst responseCardStyle: CSSProperties = {\n marginTop: 12,\n minHeight: 0,\n flex: 1,\n overflowY: \"auto\",\n borderRadius: 18,\n border: \"1px solid #e5e7eb\",\n background: \"#ffffff\",\n padding: 16,\n};\n\nconst busyContainerStyle: CSSProperties = {\n display: \"flex\",\n height: \"100%\",\n minHeight: 192,\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 12,\n color: \"#6b7280\",\n fontSize: 14,\n};\n\nconst spinnerStyle: CSSProperties = {\n display: \"inline-block\",\n width: 18,\n height: 18,\n borderRadius: 9999,\n border: \"2px solid #d1d5db\",\n borderTopColor: \"#2563eb\",\n};\n\nconst articleStyle: CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n gap: 12,\n};\n\nconst errorBoxStyle: CSSProperties = {\n margin: 0,\n border: \"1px solid #fca5a5\",\n borderRadius: 12,\n background: \"#fef2f2\",\n padding: \"10px 12px\",\n fontSize: 14,\n lineHeight: 1.6,\n color: \"#dc2626\",\n whiteSpace: \"pre-wrap\",\n};\n\nconst warningBoxStyle: CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n gap: 6,\n border: \"1px solid #fca5a5\",\n borderRadius: 12,\n background: \"#fef2f2\",\n padding: \"10px 12px\",\n fontSize: 14,\n lineHeight: 1.6,\n color: \"#dc2626\",\n};\n\nconst messageStyle: CSSProperties = {\n margin: 0,\n whiteSpace: \"pre-wrap\",\n fontSize: 15,\n lineHeight: 1.7,\n color: \"#111827\",\n};\n\nconst patchPreviewStyle: CSSProperties = {\n margin: 0,\n maxHeight: 288,\n overflow: \"auto\",\n borderRadius: 12,\n border: \"1px solid #e5e7eb\",\n background: \"#f8fafc\",\n padding: 12,\n fontSize: 13,\n lineHeight: 1.6,\n color: \"#111827\",\n fontFamily:\n \"ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Consolas, monospace\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n};\n\nconst placeholderStyle: CSSProperties = {\n margin: 0,\n fontSize: 14,\n lineHeight: 1.6,\n color: \"#6b7280\",\n};\n\nconst toastStyle: CSSProperties = {\n position: \"fixed\",\n top: 16,\n right: 16,\n zIndex: 2147483600,\n maxWidth: 360,\n borderRadius: 16,\n border: \"1px solid #bbf7d0\",\n background: \"#f0fdf4\",\n color: \"#15803d\",\n padding: \"12px 14px\",\n boxShadow: \"0 12px 28px rgba(15, 23, 42, 0.12)\",\n fontFamily:\n \"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: 14,\n lineHeight: 1.6,\n};\n"],"mappings":";;;;AAKA,MAAM,gBAAkC;CACtC,SAAS,QAAQ,IAAI,aAAa;CAClC,cAAc,CAAC,IAAI;CACpB;AAED,MAAa,2BACX,WACqB;CACrB,MAAM,aAAa,UAAU,EAAE;AAE/B,QAAO;EACL,GAAG;EACH,GAAG;EACJ;;;;;ACTH,MAAM,oBAAoB,cAAuC,KAAK;AAOtE,SAAgB,mBAAmB,EACjC,QACA,YAC0B;CAC1B,MAAM,iBAAiB,wBAAwB,OAAO;AAEtD,QACE,oBAAC,kBAAkB;EAAS,OAAO;EAChC;GAC0B;;AAIjC,MAAa,4BAA4B;CACvC,MAAM,UAAU,WAAW,kBAAkB;AAE7C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,uCAAuC;AAGzD,QAAO;;;;;AC1BT,MAAM,eAAe;AAErB,MAAM,gBAAgB,OAAU,aAAmC;CACjE,MAAM,UAAW,MAAM,SAAS,MAAM;AAEtC,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,eACJ,OAAO,YAAY,YAAY,WAAW,WAAW,UACjD,QAAQ,QACR;AACN,QAAM,IAAI,MAAM,aAAa;;AAG/B,QAAO;;AAGT,MAAa,+BAA+B;CAC1C,MAAM,OAAO,OAAa,MAAc,SAAwB;AAS9D,SAAO,cARU,MAAM,MAAM,GAAG,eAAe,QAAQ;GACrD,QAAQ;GACR,SAAS,EACP,gBAAgB,oBACjB;GACD,MAAM,KAAK,UAAU,KAAK;GAC3B,CAAC,CAE+B;;AAGnC,QAAO;EACL,QAAQ,OAAO,UAAyB;GACtC,MAAM,QAAQ,QAAQ,UAAU,UAAU;AAE1C,UAAO,cADU,MAAM,MAAM,GAAG,aAAa,SAAS,QAAQ,CACJ;;EAE5D,OAAO,YACL,KAA8C,SAAS,QAAQ;EACjE,QAAQ,YACN,KAAgD,UAAU,QAAQ;EACrE;;;;;AC7CH,MAAM,oBAAoB;AAE1B,MAAM,wBAAwB;AAG5B,QAFkB,OAAO,cAAc,EACd,UAAU,CAAC,MAAM,IAAI;;AAIhD,MAAM,uBAAuB,SAAsB;AACjD,KAAI,CAAC,KACH,QAAO;CAGT,MAAM,UAAU,gBAAgB,UAAU,OAAO,KAAK;AAEtD,QAAO,QAAQ,SAAS,QAAQ,IAAI,kBAAkB,GAAG,CAAC;;AAG5D,MAAM,mBAAmB,WAA+B;AACtD,QACE,kBAAkB,WAClB,QAAQ,OAAO,QAAQ,IAAI,kBAAkB,GAAG,CAAC;;AAIrD,MAAa,4BAA4B;CACvC,MAAM,CAAC,cAAc,mBAAmB,SAAS,GAAG;CAEpD,MAAM,gBAAgB,aAAa,UAAsC;EACvE,MAAM,YAAY,OAAO,cAAc;EACvC,MAAM,uBAAuB,oBAAoB,WAAW,cAAc,KAAK;EAC/E,MAAM,qBAAqB,oBAAoB,WAAW,aAAa,KAAK;AAE5E,MAAI,gBAAgB,MAAM,OAAO,IAAI,wBAAwB,mBAC3D;EAGF,MAAM,mBAAmB,WAAW,UAAU,CAAC,MAAM,IAAI,iBAAiB;AAE1E,MAAI,CAAC,iBACH;AAGF,kBAAgB,iBAAiB;IAChC,EAAE,CAAC;AAEN,iBAAgB;AACd,WAAS,iBAAiB,WAAW,cAAc;AACnD,WAAS,iBAAiB,SAAS,cAAc;AAEjD,eAAa;AACX,YAAS,oBAAoB,WAAW,cAAc;AACtD,YAAS,oBAAoB,SAAS,cAAc;;IAErD,CAAC,cAAc,CAAC;AAEnB,QAAO;EACL;EACA;EACA,sBAAsB,gBAAgB,GAAG;EAC1C;;;;;AC5DH,MAAa,gBAAgB,UAAwB;AACnD,QACE,qBAAC;EACC,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAY;EACZ,eAAc;EACd,gBAAe;EACf,GAAI;;GAEJ,oBAAC,UAAK,GAAE,8FAA8F;GACtG,oBAAC,UAAK,GAAE,gGAAgG;GACxG,oBAAC,UAAK,GAAE,+EAA+E;;GACnF;;AAIV,MAAa,sBAAsB,UAAwB;AACzD,QACE,qBAAC;EACC,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAY;EACZ,eAAc;EACd,gBAAe;EACf,GAAI;;GAEJ,oBAAC;IAAK,GAAE;IAAO,GAAE;IAAO,OAAM;IAAO,QAAO;IAAO,IAAG;KAAS;GAC/D,oBAAC,UAAK,GAAE,oBAAoB;GAC5B,oBAAC,UAAK,GAAE,2BAA2B;;GAC/B;;AAIV,MAAa,uBAAuB,UAAwB;AAC1D,QACE,qBAAC;EACC,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAY;EACZ,eAAc;EACd,gBAAe;EACf,GAAI;;GAEJ,oBAAC;IAAK,GAAE;IAAO,GAAE;IAAO,OAAM;IAAO,QAAO;IAAO,IAAG;KAAS;GAC/D,oBAAC,UAAK,GAAE,qBAAqB;GAC7B,oBAAC,UAAK,GAAE,2BAA2B;;GAC/B;;;;;AC1BV,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,cAAc;AACpB,MAAM,oBAAoB;AAC1B,MAAM,aAAa;AACnB,MAAM,eAA6C;CACjD,OAAO;CACP,QAAQ;CACT;AACD,MAAM,YAAY;CAChB,OAAO;CACP,UAAU;CACV,mBAAmB;CACnB,WAAW;CACX,YAAY;CACZ,aAAa;CACd;AAED,MAAM,YAAY;;;;;;;;;AAUlB,SAAgB,oBAAoB;CAClC,MAAM,SAAS,qBAAqB;CACpC,MAAM,YAAY,cAAc,wBAAwB,EAAE,EAAE,CAAC;CAC7D,MAAM,EAAE,cAAc,oBAAoB,qBAAqB;CAE/D,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;CACvC,MAAM,CAAC,QAAQ,aAAa,SAAS,GAAG;CACxC,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;CACvC,MAAM,CAAC,OAAO,YAAY,SAAwB,KAAK;CACvD,MAAM,CAAC,YAAY,iBAAiB,SAAqC,KAAK;CAC9E,MAAM,CAAC,cAAc,mBAAmB,SAAwB,KAAK;CACrE,MAAM,CAAC,aAAa,kBAClB,SAA4C,KAAK;CACnD,MAAM,CAAC,eAAe,oBAAoB,SAAuB,QAAQ;CACzE,MAAM,CAAC,UAAU,eAAe,SAA0C,KAAK;CAC/E,MAAM,CAAC,mBAAmB,wBAAwB,SAAS,MAAM;CAEjE,MAAM,eAAe,OAAuB,KAAK;CACjD,MAAM,6BAA6B,OAAO,MAAM;CAChD,MAAM,eAAe,OAOX,KAAK;AAEf,iBAAgB;EACd,MAAM,iBAAiB;AACrB,gBAAa,SAAS;AACpB,QAAI,CAAC,KACH,QAAO;AAGT,WAAO;KACL,GAAG,KAAK,IACN,KAAK,IAAI,KAAK,GAAG,EAAE,EACnB,KAAK,IAAI,GAAG,OAAO,aAAa,qBAAqB,CACtD;KACD,GAAG,KAAK,IACN,KAAK,IAAI,KAAK,GAAG,EAAE,EACnB,KAAK,IAAI,GAAG,OAAO,cAAc,qBAAqB,CACvD;KACF;KACD;;AAGJ,SAAO,iBAAiB,UAAU,SAAS;AAC3C,eAAa,OAAO,oBAAoB,UAAU,SAAS;IAC1D,EAAE,CAAC;AAEN,iBAAgB;AACd,MAAI,CAAC,KACH;EAGF,IAAI,SAAS;AAEb,YACG,OAAO,cAAc,CACrB,MAAM,WAAW;AAChB,OAAI,CAAC,OACH,gBAAe,OAAO;IAExB,CACD,OAAO,gBAAgB;AACtB,OAAI,CAAC,OACH,gBAAe;IACb,WAAW;IACX,eAAe;IACf,OAAO;IACP,SACE,uBAAuB,QACnB,YAAY,UACZ;IACP,CAAC;IAEJ;AAEJ,eAAa;AACX,YAAS;;IAEV;EAAC;EAAW;EAAM;EAAc,CAAC;AAEpC,iBAAgB;AACd,MAAI,CAAC,KACH;EAGF,MAAM,wBAAwB,UAAwB;GACpD,MAAM,SAAS,MAAM;AAErB,OAAI,EAAE,kBAAkB,MACtB;AAGF,OAAI,aAAa,SAAS,SAAS,OAAO,CACxC;AAGF,WAAQ,MAAM;AACd,wBAAqB,MAAM;AAC3B,gBAAa,UAAU;AACvB,8BAA2B,UAAU;;AAGvC,WAAS,iBAAiB,eAAe,qBAAqB;AAE9D,eAAa;AACX,YAAS,oBAAoB,eAAe,qBAAqB;;IAElE,CAAC,KAAK,CAAC;AAEV,KAAI,CAAC,OAAO,QACV,QAAO;CAGT,MAAM,iBAAiB,UAAiD;AACtE,MAAI,MAAM,WAAW,EACnB;EAGF,MAAM,cAAc,aAAa,SAAS,uBAAuB;EACjE,MAAM,UAAU,UAAU,KAAK,aAAa,QAAQ;EACpD,MAAM,UAAU,UAAU,KAAK,aAAa,OAAO;AAEnD,QAAM,cAAc,kBAAkB,MAAM,UAAU;AACtD,eAAa,UAAU;GACrB,WAAW,MAAM;GACjB,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd;GACA;GACA,OAAO;GACR;;CAGH,MAAM,iBAAiB,UAAiD;EACtE,MAAM,YAAY,aAAa;AAC/B,MAAI,CAAC,aAAa,UAAU,cAAc,MAAM,UAC9C;EAGF,MAAM,SAAS,MAAM,UAAU,UAAU;EACzC,MAAM,SAAS,MAAM,UAAU,UAAU;AAKzC,MAAI,EAHF,KAAK,IAAI,OAAO,GAAG,wBACnB,KAAK,IAAI,OAAO,GAAG,yBAEP,CAAC,UAAU,MACvB;AAGF,YAAU,QAAQ;AAElB,cAAY;GACV,GAAG,KAAK,IACN,KAAK,IAAI,UAAU,UAAU,QAAQ,EAAE,EACvC,KAAK,IAAI,GAAG,OAAO,aAAa,qBAAqB,CACtD;GACD,GAAG,KAAK,IACN,KAAK,IAAI,UAAU,UAAU,QAAQ,EAAE,EACvC,KAAK,IAAI,GAAG,OAAO,cAAc,qBAAqB,CACvD;GACF,CAAC;;CAGJ,MAAM,gBAAgB,UAAiD;AACrE,MAAI,aAAa,SAAS,cAAc,MAAM,UAC5C;AAGF,6BAA2B,UAAU,aAAa,QAAQ;AAC1D,eAAa,UAAU;AACvB,QAAM,cAAc,sBAAsB,MAAM,UAAU;;CAG5D,MAAM,0BAA0B;AAC9B,MAAI,2BAA2B,SAAS;AACtC,8BAA2B,UAAU;AACrC;;AAGF,WAAS,SAAS;GAChB,MAAM,OAAO,CAAC;AACd,OAAI,CAAC,MAAM;AACT,gBAAY,KAAK;AACjB,iBAAa,UAAU;AACvB,+BAA2B,UAAU;;AAEvC,UAAO;IACP;;CAGJ,MAAM,mBAAmB,aACrB,CACE,aAAa,WAAW,WACxB,WAAW,eACP,kBAAkB,WAAW,iBAC7B,GACL,CACE,OAAO,QAAQ,CACf,KAAK,OAAO,GACf;CAEJ,MAAM,WAAW,OAAO,SAAsB;AAC5C,MAAI,gBAAgB,CAAC,YAAY,aAAa,CAAC,YAAY,gBAAgB;AACzE,YAAS,YAAY,QAAQ;AAC7B;;AAGF,MAAI,CAAC,OAAO,MAAM,EAAE;AAClB,YAAS,iBAAiB;AAC1B;;AAGF,UAAQ,KAAK;AACb,WAAS,KAAK;AACd,uBAAqB,KAAK;AAE1B,MAAI;GACF,MAAM,eACJ,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAa7D,iBAZe,MAAM,UAAU,KAAK;IAClC;IACA;IACA;IACA,SAAS;KACP,OAAO;KACP,WAAW,OAAO;KAClB;KACA,OAAO;KACR;IACF,CAAC,CAEmB;WACd,aAAa;AACpB,YACE,uBAAuB,QACnB,YAAY,UACZ,sBACL;YACO;AACR,WAAQ,MAAM;;;CAIlB,MAAM,UAAU,YAAY;AAC1B,MAAI,CAAC,YAAY,SAAS;AACxB,YAAS,mBAAmB;AAC5B;;AAGF,UAAQ,KAAK;AACb,WAAS,KAAK;AACd,uBAAqB,KAAK;AAE1B,MAAI;GACF,MAAM,SAAS,MAAM,UAAU,MAAM;IACnC,SAAS,WAAW;IACpB,eAAe,WAAW,WAAW;IACtC,CAAC;AAEF,OAAI,OAAO,SAAS;AAClB,oBAAgB,OAAO,QAAQ;AAC/B,WAAO,iBAAiB;AACtB,qBAAgB,KAAK;OACpB,IAAK;;WAEH,aAAa;AACpB,YACE,uBAAuB,QACnB,YAAY,UACZ,sBACL;YACO;AACR,WAAQ,MAAM;;;CAIlB,MAAM,uBAAsC,WACxC;EACE,UAAU;EACV,QAAQ;EACR,MAAM,GAAG,SAAS,EAAE;EACpB,KAAK,GAAG,SAAS,EAAE;EACpB,GACD;EACE,UAAU;EACV,OAAO;EACP,QAAQ;EACR,QAAQ;EACT;CAEL,MAAM,aAA4B;EAChC,UAAU;EACV,WAAW;EACX,SAAS;EACT,qBAAqB,oBACjB,GAAG,kBAAkB,KAAK,WAAW,qBACrC,GAAG,kBAAkB,KAAK,WAAW;EACzC,OAAO,oBAAoB,cAAc,oBAAoB;EAC7D,WAAW;EACX,UAAU;EACV,QAAQ;EACR,cAAc;EACd,YAAY;EACZ,WAAW;EACX,OAAO;EACP,YACE;EACH;AAED,QACE;EACE,oBAAC,qBAAO,YAAkB;EAEzB,eACC,oBAAC;GAAI,OAAO;aACV,oBAAC;IAAE,aAAU;IAAS,OAAO,EAAE,QAAQ,GAAG;cACvC;KACC;IACA,GACJ;EAEJ,qBAAC;GAAI,KAAK;GAAc,OAAO;IAA6B,oBAAoB;cAC9E,oBAAC,mBACC,oBAAC;IACC,MAAK;IACL,WAAU;IACV,OAAO;IACP,SAAS;IACM;IACA;IACf,aAAa;IACb,iBAAiB;IACjB,cAAW;IACX,OAAM;cAEN,oBAAC;KAAa;KAAY,OAAO;MAAE,OAAO;MAAI,QAAQ;MAAI;MAAI;KACvD,GACL,EAEL,OACC,qBAAC;IAAQ,OAAO;;KACd,oBAAC;MAAI,OAAO;gBACV,oBAAC;OACC,MAAK;OACL,WAAU;OACV,OAAO;OACP,eAAe,sBAAsB,SAAS,CAAC,KAAK;OACpD,cAAY,oBAAoB,aAAa;OAC7C,OAAO,oBAAoB,aAAa;iBAEvC,oBACC,oBAAC;QAAoB;QAAY,OAAO;SAAE,OAAO;SAAI,QAAQ;SAAI;SAAI,GAErE,oBAAC;QAAmB;QAAY,OAAO;SAAE,OAAO;SAAI,QAAQ;SAAI;SAAI;QAE/D;OACL;KAEN,qBAAC;MAAI,OAAO;;OACV,qBAAC,uBACC,oBAAC;QAAE,OAAO;kBAAa,UAAU;SAAU,EAC3C,oBAAC;QAAE,OAAO;kBAAgB,UAAU;SAAa,IAC1C;OAET,qBAAC;QAAI,OAAO;;SACV,qBAAC;UAAE,OAAO;qBAAiB,aAAU,aAAa;WAAmB;SACpE,aAAa,QACZ,qBAAC;UAAE,OAAO;qBAAiB,QAAK,YAAY;WAAU,GACpD;SACH,cACC,qBAAC;UACC,OAAO;WACL,GAAG;WACH,OAAO,YAAY,gBAAgB,YAAY;WAChD;qBAEA,YAAY,SACZ,YAAY,eACT,UAAU,YAAY,aAAa,OACnC;WACF,GACF;;SACA;OAEN,oBAAC;QAAM,OAAO;kBAAY;SAAY;OACtC,oBAAC;QAAI,OAAO;kBACR,CAAC,SAAS,SAAS,CAAoB,KAAK,UAAU;SACtD,MAAM,SAAS,kBAAkB;AACjC,gBACE,oBAAC;UAEC,MAAK;UACL,WAAU;UACV,eAAe,iBAAiB,MAAM;UACtC,UAAU;UACV,OAAO;WACL,GAAG;WACH,YAAY,SAAS,YAAY;WACjC,OAAO,SAAS,YAAY;WAC5B,SAAS,OAAO,KAAM;WACvB;oBAEA,aAAa;YAZT,MAaE;UAEX;SACE;OAEN,oBAAC;QAAM,OAAO;kBAAY;SAAc;OACxC,oBAAC;QACC,OAAO;QACP,WAAW,UAAU,gBAAgB,MAAM,OAAO,MAAM;QACxD,MAAM;QACN,WAAU;QACV,OAAO;SACP;OAEF,oBAAC;QAAM,OAAO;kBAAY;SAAY;OACtC,oBAAC;QACC,OAAO;QACP,WAAW,UAAU,UAAU,MAAM,OAAO,MAAM;QAClD,MAAM;QACN,aAAa,UAAU;QACvB,WAAU;QACV,OAAO;SACP;OAEF,qBAAC;QAAI,OAAO;mBACV,oBAAC;SACC,MAAK;SACL,WAAU;SACV,eAAe,SAAS,SAAS;SACjC,UAAU,QAAQ,QAAQ,eAAe,CAAC,YAAY,cAAc;SACpE,OAAO;UACL,GAAG;UACH,YAAY;UACZ,OAAO;UACP,SAAS,QAAQ,QAAQ,eAAe,CAAC,YAAY,cAAc,GAAG,MAAO;UAC9E;mBAEA,UAAU;UACJ,EACT,oBAAC;SACC,MAAK;SACL,WAAU;SACV,eAAe,SAAS,OAAO;SAC/B,UAAU,QAAQ,QAAQ,eAAe,CAAC,YAAY,cAAc;SACpE,OAAO;UACL,GAAG;UACH,YAAY;UACZ,OAAO;UACP,SAAS,QAAQ,QAAQ,eAAe,CAAC,YAAY,cAAc,GAAG,MAAO;UAC9E;mBAEA,UAAU;UACJ;SACL;;OACF;KAEL,oBACC,oBAAC;MAAM,OAAO;gBACZ,qBAAC;OAAI,OAAO;QAAE,SAAS;QAAQ,eAAe;QAAU,WAAW;QAAK,QAAQ;QAAQ;kBACtF,oBAAC,mBACC,oBAAC;QAAE,OAAO;kBAAY;SAAM,GACxB,EAEN,oBAAC;QAAI,OAAO;kBACT,OACC,qBAAC;SAAI,OAAO;oBACV,oBAAC;UAAK,WAAU;UAAe,OAAO;WAAgB,EACtD,qBAAC,qBAAM,aAAa,gBAAe,qBAAsB;UACrD,GACJ,aACF,qBAAC;SAAQ,OAAO;;UACb,QACC,oBAAC;WAAE,OAAO;qBAAgB;YAAU,GAClC;UACH,WAAW,SAAS,SACnB,oBAAC;WAAI,OAAO;qBACT,WAAW,SAAS,KAAK,YACxB,oBAAC;YAAgB,OAAO,EAAE,QAAQ,GAAG;sBAClC;cADK,QAEJ,CACJ;YACE,GACJ;UACJ,oBAAC;WAAE,OAAO;qBAAe,WAAW;YAAY;UAE/C,WAAW,eACV,4CACE,oBAAC;WAAI,OAAO;qBAAoB,WAAW;YAAmB,EAC7D,WAAW,UACV,oBAAC;WACC,MAAK;WACL,WAAU;WACV,SAAS;WACT,UAAU;WACV,OAAO;YACL,GAAG;YACH,WAAW;YACX,YAAY;YACZ,OAAO;YACP,SAAS,OAAO,MAAO;YACxB;qBAEA,UAAU;YACJ,GACP,QACH,GACD;;UACI,GACR,QACF,oBAAC;SAAE,OAAO;mBAAgB;UAAU,GAEpC,oBAAC;SAAE,OAAO;mBAAkB;UAExB;SAEF;QACF;OACA,GACN;;KACI,GACR;IACA;KACL;;AAIP,MAAM,qBAAoC;CACxC,SAAS;CACT,OAAO;CACP,QAAQ;CACR,cAAc;CACd,QAAQ;CACR,YAAY;CACZ,OAAO;CACP,YAAY;CACZ,gBAAgB;CAChB,WAAW;CACX,QAAQ;CACT;AAED,MAAM,YAA2B;CAC/B,SAAS;CACT,WAAW;CACX,YAAY;CACZ,gBAAgB;CAChB,YAAY;CACZ,YAAY;CACb;AAED,MAAM,kBAAiC;CACrC,SAAS;CACT,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,YAAY;CACZ,OAAO;CACP,QAAQ;CACR,YAAY;CACZ,gBAAgB;CACjB;AAED,MAAM,kBAAiC;CACrC,SAAS;CACT,WAAW;CACX,WAAW;CACX,YAAY;CACb;AAED,MAAM,qBAAoC;CACxC,WAAW;CACX,UAAU;CACV,SAAS;CACT,YAAY;CACZ,YAAY;CACb;AAED,MAAM,aAA4B;CAChC,QAAQ;CACR,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,OAAO;CACR;AAED,MAAM,gBAA+B;CACnC,QAAQ;CACR,UAAU;CACV,YAAY;CACZ,OAAO;CACR;AAED,MAAM,iBAAgC;CACpC,WAAW;CACX,QAAQ;CACR,cAAc;CACd,YAAY;CACZ,SAAS;CACT,UAAU;CACV,YAAY;CACZ,OAAO;CACR;AAED,MAAM,kBAAiC,EACrC,QAAQ,GACT;AAED,MAAM,aAA4B;CAChC,SAAS;CACT,WAAW;CACX,UAAU;CACV,YAAY;CACZ,OAAO;CACR;AAED,MAAM,gBAA+B;CACnC,OAAO;CACP,QAAQ;CACR,cAAc;CACd,QAAQ;CACR,YAAY;CACZ,SAAS;CACT,WAAW;CACX,UAAU;CACV,YAAY;CACZ,OAAO;CACP,WAAW;CACX,WAAW;CACZ;AAED,MAAM,sBAAqC;CACzC,SAAS;CACT,KAAK;CACL,WAAW;CACZ;AAED,MAAM,yBAAwC;CAC5C,QAAQ;CACR,cAAc;CACd,SAAS;CACT,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,QAAQ;CACT;AAED,MAAM,iBAAgC;CACpC,SAAS;CACT,YAAY;CACZ,KAAK;CACL,WAAW;CACZ;AAED,MAAM,cAA6B;CACjC,QAAQ;CACR,cAAc;CACd,SAAS;CACT,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,QAAQ;CACT;AAED,MAAM,oBAAmC;CACvC,WAAW;CACX,WAAW;CACX,MAAM;CACN,WAAW;CACX,cAAc;CACd,QAAQ;CACR,YAAY;CACZ,SAAS;CACV;AAED,MAAM,qBAAoC;CACxC,SAAS;CACT,QAAQ;CACR,WAAW;CACX,YAAY;CACZ,gBAAgB;CAChB,KAAK;CACL,OAAO;CACP,UAAU;CACX;AAED,MAAM,eAA8B;CAClC,SAAS;CACT,OAAO;CACP,QAAQ;CACR,cAAc;CACd,QAAQ;CACR,gBAAgB;CACjB;AAED,MAAM,eAA8B;CAClC,SAAS;CACT,eAAe;CACf,KAAK;CACN;AAED,MAAM,gBAA+B;CACnC,QAAQ;CACR,QAAQ;CACR,cAAc;CACd,YAAY;CACZ,SAAS;CACT,UAAU;CACV,YAAY;CACZ,OAAO;CACP,YAAY;CACb;AAED,MAAM,kBAAiC;CACrC,SAAS;CACT,eAAe;CACf,KAAK;CACL,QAAQ;CACR,cAAc;CACd,YAAY;CACZ,SAAS;CACT,UAAU;CACV,YAAY;CACZ,OAAO;CACR;AAED,MAAM,eAA8B;CAClC,QAAQ;CACR,YAAY;CACZ,UAAU;CACV,YAAY;CACZ,OAAO;CACR;AAED,MAAM,oBAAmC;CACvC,QAAQ;CACR,WAAW;CACX,UAAU;CACV,cAAc;CACd,QAAQ;CACR,YAAY;CACZ,SAAS;CACT,UAAU;CACV,YAAY;CACZ,OAAO;CACP,YACE;CACF,YAAY;CACZ,WAAW;CACZ;AAED,MAAM,mBAAkC;CACtC,QAAQ;CACR,UAAU;CACV,YAAY;CACZ,OAAO;CACR;AAED,MAAM,aAA4B;CAChC,UAAU;CACV,KAAK;CACL,OAAO;CACP,QAAQ;CACR,UAAU;CACV,cAAc;CACd,QAAQ;CACR,YAAY;CACZ,OAAO;CACP,SAAS;CACT,WAAW;CACX,YACE;CACF,UAAU;CACV,YAAY;CACb"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/types/index.d.ts
|
|
2
|
+
type CopilotMode = "answer" | "edit";
|
|
3
|
+
type CopilotAgent = "codex" | "claude";
|
|
4
|
+
interface CopilotChatRequest {
|
|
5
|
+
selectedText: string;
|
|
6
|
+
prompt: string;
|
|
7
|
+
mode: CopilotMode;
|
|
8
|
+
context?: {
|
|
9
|
+
route?: string;
|
|
10
|
+
fileHints?: string[];
|
|
11
|
+
previousResponse?: string;
|
|
12
|
+
agent?: CopilotAgent;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
interface CopilotApplyRequest {
|
|
16
|
+
patchId: string;
|
|
17
|
+
approvalToken: string;
|
|
18
|
+
}
|
|
19
|
+
interface CopilotChatResponse {
|
|
20
|
+
message: string;
|
|
21
|
+
patchPreview?: string;
|
|
22
|
+
patchId?: string;
|
|
23
|
+
warnings: string[];
|
|
24
|
+
}
|
|
25
|
+
interface CopilotApplyResponse {
|
|
26
|
+
applied: boolean;
|
|
27
|
+
changedFiles: string[];
|
|
28
|
+
summary: string;
|
|
29
|
+
}
|
|
30
|
+
interface CopilotAgentStatusResponse {
|
|
31
|
+
available: boolean;
|
|
32
|
+
authenticated: boolean;
|
|
33
|
+
agent: CopilotAgent;
|
|
34
|
+
message: string;
|
|
35
|
+
model?: string;
|
|
36
|
+
loginCommand?: string;
|
|
37
|
+
}
|
|
38
|
+
interface CopilotErrorResponse {
|
|
39
|
+
error: string;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { CopilotAgent, CopilotAgentStatusResponse, CopilotApplyRequest, CopilotApplyResponse, CopilotChatRequest, CopilotChatResponse, CopilotErrorResponse, CopilotMode };
|
|
43
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/types/index.ts"],"mappings":";KAAY,WAAA;AAAA,KACA,YAAA;AAAA,UAEK,kBAAA;EACf,YAAA;EACA,MAAA;EACA,IAAA,EAAM,WAAA;EACN,OAAA;IACE,KAAA;IACA,SAAA;IACA,gBAAA;IACA,KAAA,GAAQ,YAAA;EAAA;AAAA;AAAA,UAIK,mBAAA;EACf,OAAA;EACA,aAAA;AAAA;AAAA,UAGe,mBAAA;EACf,OAAA;EACA,YAAA;EACA,OAAA;EACA,QAAA;AAAA;AAAA,UAGe,oBAAA;EACf,OAAA;EACA,YAAA;EACA,OAAA;AAAA;AAAA,UAGe,0BAAA;EACf,SAAA;EACA,aAAA;EACA,KAAA,EAAO,YAAA;EACP,OAAA;EACA,KAAA;EACA,YAAA;AAAA;AAAA,UAGe,oBAAA;EACf,KAAA;AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yr-kits/dev-copilot",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "선택 텍스트 기반 Dev Copilot 오버레이와 로컬 브리지 실행 CLI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.mjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.mts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"import": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"./types": {
|
|
15
|
+
"types": "./dist/types/index.d.mts",
|
|
16
|
+
"import": "./dist/types/index.mjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"dev-copilot": "./dist/bin/dev-copilot.mjs",
|
|
21
|
+
"dev-copilot-bridge": "./dist/bin/bridge.mjs"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"codex",
|
|
28
|
+
"copilot",
|
|
29
|
+
"react",
|
|
30
|
+
"overlay"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/1eeyerin/yr-kits.git"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://yr-kits.vercel.app/docs/dev-copilot/overview",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/1eeyerin/yr-kits/issues"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": "^18.2.0 || ^19.0.0",
|
|
46
|
+
"react-dom": "^18.2.0 || ^19.0.0"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^22.10.0",
|
|
51
|
+
"@types/react": "^19.2.2",
|
|
52
|
+
"@types/react-dom": "^19.2.3",
|
|
53
|
+
"tsdown": "^0.20.3",
|
|
54
|
+
"typescript": "^5.7.2"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsdown",
|
|
58
|
+
"dev": "tsdown --watch",
|
|
59
|
+
"test": "echo \"No tests yet\"",
|
|
60
|
+
"release:patch": "pnpm version patch --no-git-tag-version && pnpm publish --access public --no-git-checks",
|
|
61
|
+
"release:minor": "pnpm version minor --no-git-tag-version && pnpm publish --access public --no-git-checks",
|
|
62
|
+
"release:major": "pnpm version major --no-git-tag-version && pnpm publish --access public --no-git-checks"
|
|
63
|
+
}
|
|
64
|
+
}
|