@yr-kits/dev-copilot 0.1.0 → 0.1.2

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.
Files changed (33) hide show
  1. package/dist/app/index.d.mts +2 -0
  2. package/dist/app/index.mjs +4 -0
  3. package/dist/bin/bridge.mjs +4 -881
  4. package/dist/bin/bridge.mjs.map +1 -1
  5. package/dist/bin/dev-copilot.mjs +13 -3
  6. package/dist/bin/dev-copilot.mjs.map +1 -1
  7. package/dist/bridge/app/index.d.mts +24 -0
  8. package/dist/bridge/app/index.d.mts.map +1 -0
  9. package/dist/bridge/app/index.mjs +3 -0
  10. package/dist/{types/index.d.mts → copilot-D8--qKgC.d.mts} +3 -3
  11. package/dist/copilot-D8--qKgC.d.mts.map +1 -0
  12. package/dist/copilot-overlay-ClRoIHew.mjs +1129 -0
  13. package/dist/copilot-overlay-ClRoIHew.mjs.map +1 -0
  14. package/dist/copilot-overlay-NlUgrMjy.d.mts +7 -0
  15. package/dist/copilot-overlay-NlUgrMjy.d.mts.map +1 -0
  16. package/dist/dev-copilot-context-CA9bqV_U.mjs +35 -0
  17. package/dist/dev-copilot-context-CA9bqV_U.mjs.map +1 -0
  18. package/dist/dev-copilot-provider-CP_gJvWG.d.mts +22 -0
  19. package/dist/dev-copilot-provider-CP_gJvWG.d.mts.map +1 -0
  20. package/dist/dev-copilot-provider-D0_wEEem.mjs +14 -0
  21. package/dist/dev-copilot-provider-D0_wEEem.mjs.map +1 -0
  22. package/dist/index.d.mts +5 -33
  23. package/dist/index.mjs +6 -849
  24. package/dist/run-bridge-cli-DVLGcVgq.mjs +1510 -0
  25. package/dist/run-bridge-cli-DVLGcVgq.mjs.map +1 -0
  26. package/dist/types.d.mts +2 -0
  27. package/dist/widgets/copilot-overlay/index.d.mts +2 -0
  28. package/dist/widgets/copilot-overlay/index.mjs +4 -0
  29. package/package.json +29 -9
  30. package/dist/index.d.mts.map +0 -1
  31. package/dist/index.mjs.map +0 -1
  32. package/dist/types/index.d.mts.map +0 -1
  33. /package/dist/{types/index.mjs → types.mjs} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-bridge-cli-DVLGcVgq.mjs","names":["execFileAsync","fs","getPathExecutableNames","CODEX_MODEL","fs","fs","isCopilotAgent"],"sources":["../src/bridge/shared/config/bridge-config.ts","../src/bridge/shared/lib/temp-path.ts","../src/bridge/lib/patch.ts","../src/bridge/lib/guards.ts","../src/bridge/lib/store.ts","../src/bridge/features/patch-flow/patch-flow-service.ts","../src/bridge/shared/http/read-json-body.ts","../src/bridge/shared/http/respond.ts","../src/bridge/features/apply/apply-route.ts","../src/bridge/internal/agents/edit-response-schema.ts","../src/bridge/internal/agents/constants.ts","../src/bridge/internal/agents/agent-response.ts","../src/bridge/internal/agents/cli-error.ts","../src/bridge/internal/agents/run-cli.ts","../src/bridge/internal/agents/claude-command.ts","../src/bridge/internal/prompts.ts","../src/bridge/entities/agent/status.ts","../src/bridge/internal/agents/claude-adapter.ts","../src/bridge/internal/agents/codex-command.ts","../src/bridge/internal/agents/codex-home.ts","../src/bridge/internal/agents/codex-health.ts","../src/bridge/internal/agents/codex-adapter.ts","../src/bridge/features/agent-runner/resolve-agent-adapter.ts","../src/bridge/features/project-context/search-strategies.ts","../src/bridge/features/project-context/build-project-context.ts","../src/bridge/features/chat/chat-route.ts","../src/bridge/features/status/status-route.ts","../src/bridge/shared/http/error-mapper.ts","../src/bridge/app/create-bridge-server.ts","../src/bridge/app/run-bridge-cli.ts"],"sourcesContent":["import type { CopilotAgent } from \"../../../shared/contracts/copilot\";\n\nexport interface DevCopilotBridgeConfig {\n rootDir: string;\n host: string;\n port: number;\n corsOrigin: string;\n agent: CopilotAgent;\n allowedPaths: string[];\n}\n\nconst DEFAULT_ALLOWED_PATHS = [\n \"app\",\n \"src\",\n \"widgets\",\n \"features\",\n \"entities\",\n \"shared\",\n \"components\",\n];\n\nexport const createDevCopilotBridgeConfig = (\n config: Partial<DevCopilotBridgeConfig> & { rootDir: string },\n): DevCopilotBridgeConfig => {\n return {\n rootDir: config.rootDir,\n host: config.host ?? \"127.0.0.1\",\n port: config.port ?? 3339,\n corsOrigin: config.corsOrigin ?? \"*\",\n agent: config.agent ?? \"codex\",\n allowedPaths: config.allowedPaths ?? DEFAULT_ALLOWED_PATHS,\n };\n};\n","import os from \"node:os\";\nimport path from \"node:path\";\n\nexport const createTempPath = (prefix: string, extension = \"\") => {\n const suffix = `${Date.now()}-${Math.random().toString(16).slice(2)}`;\n return path.join(os.tmpdir(), `${prefix}-${suffix}${extension}`);\n};\n","import { execFile } from \"node:child_process\";\nimport { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nimport { createTempPath } from \"../shared/lib/temp-path\";\n\nconst execFileAsync = promisify(execFile);\n\nconst getChangedFiles = (patchPreview: string) => {\n const regex = /^\\+\\+\\+ b\\/(.+)$/gm;\n const changedFiles = new Set<string>();\n\n let match = regex.exec(patchPreview);\n while (match) {\n changedFiles.add(match[1]);\n match = regex.exec(patchPreview);\n }\n\n return [...changedFiles];\n};\n\nconst getGitApplyDirectoryArgs = async (cwd: string) => {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--show-prefix\"], {\n cwd,\n });\n const prefix = stdout.trim().replace(/\\/$/, \"\");\n\n return prefix ? [\"--directory\", prefix] : [];\n } catch {\n return [];\n }\n};\n\ninterface TextReplacement {\n path: string;\n oldText: string;\n newText: string;\n}\n\nconst withOriginalLineIndent = (content: string, oldText: string, newText: string) => {\n if (!newText.includes(\"\\n\")) {\n return newText;\n }\n\n const matchIndex = content.indexOf(oldText);\n\n if (matchIndex < 0) {\n return newText;\n }\n\n const lineStartIndex = content.lastIndexOf(\"\\n\", matchIndex) + 1;\n const linePrefix = content.slice(lineStartIndex, matchIndex);\n const indent = linePrefix.match(/^[ \\t]*/)?.[0] ?? \"\";\n\n return indent ? newText.replaceAll(\"\\n\", `\\n${indent}`) : newText;\n};\n\nconst escapeRegExp = (value: string) => value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nconst createWhitespaceTolerantPattern = (value: string) => {\n const tokens = value.trim().split(/\\s+/).filter(Boolean);\n\n if (!tokens.length) {\n return null;\n }\n\n return new RegExp(tokens.map(escapeRegExp).join(\"\\\\s+\"));\n};\n\nconst replaceText = (\n content: string,\n oldText: string,\n newText: string,\n) => {\n if (content.includes(oldText)) {\n return {\n replaced: true,\n content: content.replace(\n oldText,\n withOriginalLineIndent(content, oldText, newText),\n ),\n };\n }\n\n const whitespaceTolerantPattern = createWhitespaceTolerantPattern(oldText);\n const match = whitespaceTolerantPattern?.exec(content);\n\n if (!match) {\n return {\n replaced: false,\n content,\n };\n }\n\n const matchedText = match[0];\n\n return {\n replaced: true,\n content: content.replace(\n matchedText,\n withOriginalLineIndent(content, matchedText, newText),\n ),\n };\n};\n\nexport const normalizeUnifiedPatch = (patchPreview: string) => {\n const withoutFence = patchPreview\n .replace(/^```(?:diff|patch)?\\s*/i, \"\")\n .replace(/\\s*```$/i, \"\")\n .trim();\n const diffStartIndex = withoutFence.indexOf(\"diff --git \");\n\n return diffStartIndex >= 0\n ? withoutFence.slice(diffStartIndex).trim()\n : withoutFence;\n};\n\nexport const validatePatchPaths = (\n patchPreview: string,\n validatePath: (filePath: string) => string,\n) => {\n const changedFiles = getChangedFiles(patchPreview);\n\n if (!changedFiles.length) {\n throw new Error(\"패치에서 변경 파일을 찾을 수 없습니다.\");\n }\n\n changedFiles.forEach(validatePath);\n\n return changedFiles;\n};\n\nexport const checkUnifiedPatch = async (patchPreview: string, cwd: string) => {\n const tempFilePath = createTempPath(\"dev-copilot-check\", \".patch\");\n\n await fs.writeFile(tempFilePath, patchPreview, \"utf-8\");\n\n try {\n const directoryArgs = await getGitApplyDirectoryArgs(cwd);\n await execFileAsync(\"git\", [\"apply\", \"--check\", ...directoryArgs, tempFilePath], { cwd });\n } catch (error) {\n const detail =\n error instanceof Error && \"stderr\" in error\n ? String((error as Error & { stderr?: unknown }).stderr)\n : error instanceof Error\n ? error.message\n : \"알 수 없는 patch 검증 오류\";\n\n throw new Error(`적용 가능한 diff를 생성하지 못했습니다: ${detail.trim()}`);\n } finally {\n await fs.rm(tempFilePath, { force: true });\n }\n};\n\nconst createGitPatch = async (\n filePath: string,\n oldContent: string,\n newContent: string,\n) => {\n const tempDir = createTempPath(\"dev-copilot-diff\");\n const oldFilePath = path.join(tempDir, \"old\", filePath);\n const newFilePath = path.join(tempDir, \"new\", filePath);\n\n await fs.mkdir(path.dirname(oldFilePath), { recursive: true });\n await fs.mkdir(path.dirname(newFilePath), { recursive: true });\n await fs.writeFile(oldFilePath, oldContent, \"utf-8\");\n await fs.writeFile(newFilePath, newContent, \"utf-8\");\n\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\n \"diff\",\n \"--no-index\",\n \"--no-ext-diff\",\n \"--src-prefix=a/\",\n \"--dst-prefix=b/\",\n \"--\",\n path.join(\"old\", filePath),\n path.join(\"new\", filePath),\n ],\n { cwd: tempDir },\n ).catch((error: unknown) => {\n const typedError = error as { stdout?: string; code?: number };\n\n if (typedError.code === 1 && typedError.stdout) {\n return { stdout: typedError.stdout };\n }\n\n throw error;\n });\n\n return stdout\n .replaceAll(`a/old/${filePath}`, `a/${filePath}`)\n .replaceAll(`b/new/${filePath}`, `b/${filePath}`);\n } finally {\n await fs.rm(tempDir, { force: true, recursive: true });\n }\n};\n\nexport const createPatchFromTextReplacements = async (\n replacements: TextReplacement[],\n cwd: string,\n validatePath: (filePath: string) => string,\n) => {\n const byPath = new Map<string, TextReplacement[]>();\n\n for (const replacement of replacements) {\n const normalizedPath = validatePath(replacement.path);\n const current = byPath.get(normalizedPath) ?? [];\n current.push(replacement);\n byPath.set(normalizedPath, current);\n }\n\n const patches: string[] = [];\n\n for (const [filePath, fileReplacements] of byPath.entries()) {\n const absolutePath = path.join(cwd, filePath);\n const oldContent = await fs.readFile(absolutePath, \"utf-8\");\n let newContent = oldContent;\n\n for (const replacement of fileReplacements) {\n const result = replaceText(newContent, replacement.oldText, replacement.newText);\n\n if (!result.replaced) {\n throw new Error(`원문을 파일에서 찾을 수 없습니다: ${filePath}`);\n }\n\n newContent = result.content;\n }\n\n if (newContent === oldContent) {\n continue;\n }\n\n patches.push(await createGitPatch(filePath, oldContent, newContent));\n }\n\n const patchPreview = patches.join(\"\\n\");\n\n if (!patchPreview.trim()) {\n throw new Error(\"변경할 내용이 없습니다.\");\n }\n\n return patchPreview;\n};\n\nexport const applyUnifiedPatch = async (\n patchPreview: string,\n cwd: string,\n actor: string,\n) => {\n const tempFilePath = createTempPath(\"dev-copilot\", \".patch\");\n\n await fs.writeFile(tempFilePath, patchPreview, \"utf-8\");\n\n try {\n const directoryArgs = await getGitApplyDirectoryArgs(cwd);\n const { stdout: statOutput } = await execFileAsync(\n \"git\",\n [\"apply\", \"--numstat\", ...directoryArgs, tempFilePath],\n { cwd },\n );\n\n if (!statOutput.trim()) {\n throw new Error(\"patch가 실제 파일 변경을 만들지 않았습니다.\");\n }\n\n await execFileAsync(\"git\", [\"apply\", \"--check\", ...directoryArgs, tempFilePath], { cwd });\n await execFileAsync(\"git\", [\"apply\", ...directoryArgs, tempFilePath], { cwd });\n\n const changedFiles = getChangedFiles(patchPreview);\n\n return {\n actor,\n changedFiles,\n };\n } catch (error) {\n const detail =\n error instanceof Error && \"stderr\" in error\n ? String((error as Error & { stderr?: unknown }).stderr)\n : error instanceof Error\n ? error.message\n : \"알 수 없는 patch 적용 오류\";\n\n throw new Error(`patch 적용에 실패했습니다: ${detail.trim()}`);\n } finally {\n await fs.rm(tempFilePath, { force: true });\n }\n};\n","import path from \"node:path\";\n\nexport const resolveAndValidatePath = (\n filePath: string,\n allowedPaths: string[],\n rootDir?: string,\n) => {\n if (!filePath) {\n throw new Error(\"허용되지 않은 파일 경로입니다.\");\n }\n\n let normalizedInput = filePath.replaceAll(\"\\\\\", \"/\");\n\n if (rootDir) {\n const normalizedRootDir = rootDir.replaceAll(\"\\\\\", \"/\").replace(/\\/+$/, \"\");\n\n if (normalizedInput.startsWith(`${normalizedRootDir}/`)) {\n normalizedInput = normalizedInput.slice(normalizedRootDir.length + 1);\n }\n }\n\n if (path.isAbsolute(normalizedInput) || normalizedInput.includes(\"..\")) {\n throw new Error(\"허용되지 않은 파일 경로입니다.\");\n }\n\n const normalized = normalizedInput;\n const firstSegment = normalized.split(\"/\")[0];\n const allowAll = allowedPaths.includes(\".\") || allowedPaths.includes(\"*\");\n\n if (!allowAll && !allowedPaths.includes(firstSegment)) {\n throw new Error(`허용 경로 외 파일은 수정할 수 없습니다: ${firstSegment}`);\n }\n\n return normalized;\n};\n","import { randomUUID } from \"node:crypto\";\n\ninterface ProposedPatch {\n patchId: string;\n approvalToken: string;\n patchPreview: string;\n allowedPaths: string[];\n createdAt: number;\n}\n\nconst patchStore = new Map<string, ProposedPatch>();\nconst TTL_MS = 1000 * 60 * 15;\n\nconst pruneExpired = () => {\n const now = Date.now();\n\n for (const [key, value] of patchStore.entries()) {\n if (now - value.createdAt > TTL_MS) {\n patchStore.delete(key);\n }\n }\n};\n\nexport const createProposedPatch = (patchPreview: string, allowedPaths: string[]) => {\n pruneExpired();\n\n const patchId = randomUUID();\n const approvalToken = `approve:${patchId}`;\n\n patchStore.set(patchId, {\n patchId,\n approvalToken,\n patchPreview,\n allowedPaths,\n createdAt: Date.now(),\n });\n\n return {\n patchId,\n approvalToken,\n };\n};\n\nexport const getProposedPatch = (patchId: string, approvalToken: string) => {\n pruneExpired();\n\n const item = patchStore.get(patchId);\n\n if (!item || item.approvalToken !== approvalToken) {\n return null;\n }\n\n return item;\n};\n\nexport const deleteProposedPatch = (patchId: string) => {\n patchStore.delete(patchId);\n};\n","import {\n applyUnifiedPatch,\n checkUnifiedPatch,\n createPatchFromTextReplacements,\n validatePatchPaths,\n} from \"../../lib/patch\";\nimport { resolveAndValidatePath } from \"../../lib/guards\";\nimport {\n createProposedPatch,\n deleteProposedPatch,\n getProposedPatch,\n} from \"../../lib/store\";\n\nimport type { DevCopilotBridgeConfig } from \"../../shared/config/bridge-config\";\n\nconst sanitizeAllowedPaths = (fileHints?: string[]) => {\n if (!fileHints?.length) {\n return null;\n }\n\n const sanitized = fileHints\n .map((value) => value.trim())\n .filter(Boolean)\n .filter((value) => value === \".\" || value === \"*\" || /^[A-Za-z0-9._-]+$/.test(value));\n\n return sanitized.length ? Array.from(new Set(sanitized)) : null;\n};\n\nexport const resolveAllowedPathsWithSrcFallback = (\n config: DevCopilotBridgeConfig,\n fileHints?: string[],\n) => {\n const resolved = sanitizeAllowedPaths(fileHints) ?? config.allowedPaths;\n\n // 대부분의 웹 프로젝트에서 src가 실질 수정 대상이므로 누락 시 보정한다.\n if (!resolved.includes(\".\") && !resolved.includes(\"*\") && !resolved.includes(\"src\")) {\n return [...resolved, \"src\"];\n }\n\n return resolved;\n};\n\nexport const buildPatchPreview = async (\n changes: Array<{ path: string; oldText: string; newText: string }> | undefined,\n config: DevCopilotBridgeConfig,\n allowedPaths: string[],\n) => {\n if (!changes?.length) {\n return \"\";\n }\n\n return createPatchFromTextReplacements(changes, config.rootDir, (filePath) =>\n resolveAndValidatePath(filePath, allowedPaths, config.rootDir),\n );\n};\n\nexport const validatePatchPreview = async (\n patchPreview: string,\n config: DevCopilotBridgeConfig,\n allowedPaths: string[],\n) => {\n validatePatchPaths(patchPreview, (filePath) =>\n resolveAndValidatePath(filePath, allowedPaths, config.rootDir),\n );\n await checkUnifiedPatch(patchPreview, config.rootDir);\n};\n\nexport const saveProposedPatch = (patchPreview: string, allowedPaths: string[]) => {\n return createProposedPatch(patchPreview, allowedPaths);\n};\n\nexport const applySavedPatch = async (\n config: DevCopilotBridgeConfig,\n patchId: string,\n approvalToken: string,\n) => {\n const proposedPatch = getProposedPatch(patchId, approvalToken);\n\n if (!proposedPatch) {\n throw new Error(\"유효하지 않거나 만료된 patchId입니다.\");\n }\n\n validatePatchPaths(proposedPatch.patchPreview, (filePath) =>\n resolveAndValidatePath(\n filePath,\n proposedPatch.allowedPaths?.length ? proposedPatch.allowedPaths : config.allowedPaths,\n config.rootDir,\n ),\n );\n\n const result = await applyUnifiedPatch(\n proposedPatch.patchPreview,\n config.rootDir,\n \"local-codex-bridge\",\n );\n deleteProposedPatch(patchId);\n\n return result;\n};\n","import type { IncomingMessage } from \"node:http\";\n\nexport const readJsonBody = async <T>(request: IncomingMessage) => {\n const chunks: Buffer[] = [];\n\n for await (const chunk of request) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n const raw = Buffer.concat(chunks).toString(\"utf-8\");\n return JSON.parse(raw) as T;\n};\n","import type { ServerResponse } from \"node:http\";\n\nimport type { DevCopilotBridgeConfig } from \"../config/bridge-config\";\n\nexport const createCorsHeaders = (config: DevCopilotBridgeConfig) => ({\n \"Access-Control-Allow-Origin\": config.corsOrigin,\n \"Access-Control-Allow-Methods\": \"GET,POST,OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type\",\n \"Content-Type\": \"application/json; charset=utf-8\",\n});\n\nexport const sendJson = (\n response: ServerResponse,\n config: DevCopilotBridgeConfig,\n statusCode: number,\n payload: unknown,\n) => {\n response.writeHead(statusCode, createCorsHeaders(config));\n response.end(JSON.stringify(payload));\n};\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { CopilotApplyRequest, CopilotApplyResponse } from \"../../../shared/contracts/copilot\";\nimport { applySavedPatch } from \"../patch-flow/patch-flow-service\";\nimport type { DevCopilotBridgeConfig } from \"../../shared/config/bridge-config\";\nimport { readJsonBody } from \"../../shared/http/read-json-body\";\nimport { sendJson } from \"../../shared/http/respond\";\n\nconst toPatchSummary = (changedFiles: string[]) => {\n return changedFiles.length === 1\n ? \"1개 파일에 수정이 반영되었습니다.\"\n : `${changedFiles.length}개 파일에 수정이 반영되었습니다.`;\n};\n\nexport const handleApplyRoute = async (\n request: IncomingMessage,\n response: ServerResponse,\n config: DevCopilotBridgeConfig,\n) => {\n const payload = await readJsonBody<CopilotApplyRequest>(request);\n\n if (!payload.patchId || !payload.approvalToken) {\n sendJson(response, config, 400, {\n error: \"patchId와 approvalToken이 필요합니다.\",\n });\n return;\n }\n\n const result = await applySavedPatch(config, payload.patchId, payload.approvalToken);\n\n const applyResponse: CopilotApplyResponse = {\n applied: true,\n changedFiles: result.changedFiles,\n summary: toPatchSummary(result.changedFiles),\n };\n\n sendJson(response, config, 200, applyResponse);\n};\n","export const agentEditResponseSchema = {\n type: \"object\",\n properties: {\n message: { type: \"string\" },\n warnings: {\n type: \"array\",\n items: { type: \"string\" },\n },\n changes: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n properties: {\n path: { type: \"string\" },\n oldText: { type: \"string\" },\n newText: { type: \"string\" },\n },\n required: [\"path\", \"oldText\", \"newText\"],\n additionalProperties: false,\n },\n },\n },\n required: [\"message\", \"warnings\", \"changes\"],\n additionalProperties: false,\n} as const;\n\nexport const agentEditResponseSchemaJson = JSON.stringify(agentEditResponseSchema);\n","export const DEFAULT_AGENT_TIMEOUT_MS = 120_000;\nexport const DEFAULT_AGENT_MAX_BUFFER_BYTES = 1024 * 1024 * 5;\nexport const STATUS_CHECK_TIMEOUT_MS = 10_000;\nexport const QUICK_STATUS_CHECK_TIMEOUT_MS = 5_000;\nexport const MODEL_STATUS_CHECK_TIMEOUT_MS = 30_000;\n","import type { AgentBridgeResponse } from \"../../entities/agent/types\";\n\ntype ClaudePrintJsonResponse = {\n result?: unknown;\n structured_output?: unknown;\n message?: unknown;\n output?: unknown;\n content?: unknown;\n};\n\nexport const findFirstString = (value: unknown): string | null => {\n if (typeof value === \"string\") {\n const text = value.trim();\n return text ? text : null;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n const found = findFirstString(item);\n if (found) {\n return found;\n }\n }\n return null;\n }\n\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const preferredKeys = [\"result\", \"message\", \"output\", \"text\", \"content\"];\n\n for (const key of preferredKeys) {\n if (key in record) {\n const found = findFirstString(record[key]);\n if (found) {\n return found;\n }\n }\n }\n\n for (const nestedValue of Object.values(record)) {\n const found = findFirstString(nestedValue);\n if (found) {\n return found;\n }\n }\n }\n\n return null;\n};\n\nexport const normalizeAgentBridgeResponse = (\n value: Partial<AgentBridgeResponse>,\n): AgentBridgeResponse => {\n return {\n message: typeof value.message === \"string\" ? value.message : \"\",\n patchPreview: value.patchPreview,\n changes: value.changes,\n warnings: Array.isArray(value.warnings) ? value.warnings : [],\n };\n};\n\nexport const parseJsonLikeText = (text: string) => {\n const trimmed = text.trim();\n const fenced = trimmed.match(/```(?:json)?\\s*([\\s\\S]*?)\\s*```/i);\n const jsonText = fenced?.[1]?.trim() ?? trimmed;\n return JSON.parse(jsonText) as Partial<AgentBridgeResponse>;\n};\n\nexport const parseClaudeJsonOutput = (raw: string) => {\n const parsed = JSON.parse(raw) as ClaudePrintJsonResponse;\n const text = findFirstString(parsed) ?? \"\";\n\n return {\n parsed,\n text,\n };\n};\n\nexport const parseClaudeEditResponse = (raw: string): AgentBridgeResponse => {\n const { parsed, text } = parseClaudeJsonOutput(raw);\n const response =\n parsed.structured_output && typeof parsed.structured_output === \"object\"\n ? (parsed.structured_output as Partial<AgentBridgeResponse>)\n : parseJsonLikeText(text);\n\n return normalizeAgentBridgeResponse(response);\n};\n\nexport const parseCodexEditResponse = (raw: string): AgentBridgeResponse => {\n return normalizeAgentBridgeResponse(parseJsonLikeText(raw));\n};\n\nexport const parseAnswerResponse = (rawOutput: string): AgentBridgeResponse => {\n return {\n message: rawOutput.trim(),\n warnings: [],\n };\n};\n","export interface CliErrorDetails {\n message: string;\n stderr: string;\n stdout: string;\n signal: string;\n killed: boolean;\n merged: string;\n}\n\nexport const extractCliErrorDetails = (error: unknown): CliErrorDetails => {\n const record = error && typeof error === \"object\" ? (error as Record<string, unknown>) : null;\n const message = error instanceof Error ? error.message : String(error);\n const stderr = typeof record?.stderr === \"string\" ? record.stderr : \"\";\n const stdout = typeof record?.stdout === \"string\" ? record.stdout : \"\";\n const signal = typeof record?.signal === \"string\" ? record.signal : \"\";\n const killed = record?.killed === true;\n const merged = [message, stderr, stdout, signal, killed ? \"killed\" : \"\"]\n .map((part) => part.trim())\n .filter(Boolean)\n .join(\"\\n\");\n\n return {\n message,\n stderr,\n stdout,\n signal,\n killed,\n merged,\n };\n};\n\nexport const isCliTimeout = (details: CliErrorDetails) => {\n return /SIGTERM|timed out|timeout/i.test(details.merged);\n};\n\nexport const isCliCommandMissing = (details: CliErrorDetails) => {\n return /ENOENT/.test(details.merged);\n};\n","import { spawn } from \"node:child_process\";\n\nimport { DEFAULT_AGENT_MAX_BUFFER_BYTES } from \"./constants\";\n\ninterface RunCliOptions {\n cwd: string;\n timeoutMs: number;\n maxBuffer?: number;\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface RunCliResult {\n stdout: string;\n stderr: string;\n}\n\nexport const runCli = (command: string, args: string[], options: RunCliOptions) => {\n return new Promise<RunCliResult>((resolve, reject) => {\n const maxBuffer = options.maxBuffer ?? DEFAULT_AGENT_MAX_BUFFER_BYTES;\n const child = spawn(command, args, {\n cwd: options.cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: {\n ...process.env,\n NO_COLOR: \"1\",\n ...options.env,\n },\n });\n const stdoutChunks: Buffer[] = [];\n const stderrChunks: Buffer[] = [];\n let stdoutLength = 0;\n let stderrLength = 0;\n let settled = false;\n\n const timeout = setTimeout(() => {\n if (settled) return;\n settled = true;\n child.kill(\"SIGTERM\");\n const error = new Error(`${command} 실행 시간이 초과되었습니다.`);\n Object.assign(error, {\n signal: \"SIGTERM\",\n killed: true,\n });\n reject(error);\n }, options.timeoutMs);\n\n const fail = (error: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeout);\n child.kill(\"SIGTERM\");\n reject(error);\n };\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n stdoutLength += chunk.length;\n if (stdoutLength > maxBuffer) {\n fail(new Error(`${command} stdout이 허용된 크기를 초과했습니다.`));\n return;\n }\n stdoutChunks.push(chunk);\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderrLength += chunk.length;\n if (stderrLength > maxBuffer) {\n fail(new Error(`${command} stderr가 허용된 크기를 초과했습니다.`));\n return;\n }\n stderrChunks.push(chunk);\n });\n\n child.on(\"error\", (error) => {\n fail(error);\n });\n\n child.on(\"close\", (code, signal) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeout);\n\n const stdout = Buffer.concat(stdoutChunks).toString(\"utf-8\");\n const stderr = Buffer.concat(stderrChunks).toString(\"utf-8\");\n\n if (code === 0) {\n resolve({ stdout, stderr });\n return;\n }\n\n const error = new Error(stderr || `${command} 실행에 실패했습니다. code=${code ?? \"unknown\"}`);\n Object.assign(error, {\n stdout,\n stderr,\n signal,\n killed: signal === \"SIGTERM\",\n code,\n });\n reject(error);\n });\n });\n};\n","import { delimiter, join } from \"node:path\";\n\nimport { runCli } from \"./run-cli\";\nimport { QUICK_STATUS_CHECK_TIMEOUT_MS } from \"./constants\";\n\ninterface ClaudeCommandCandidate {\n command: string;\n source: \"env\" | \"path\";\n}\n\nlet claudeCommandPromise: Promise<string> | null = null;\n\nconst CLAUDE_SMOKE_MODEL = process.env.DEV_COPILOT_CLAUDE_MODEL ?? \"haiku\";\n\nconst getPathExecutableNames = () => {\n if (process.platform !== \"win32\") {\n return [\"claude\"];\n }\n\n const pathExts = process.env.PATHEXT?.split(\";\").filter(Boolean) ?? [\".EXE\", \".CMD\", \".BAT\"];\n return [\"claude\", ...pathExts.map((ext) => `claude${ext.toLowerCase()}`)];\n};\n\nconst collectClaudeCandidates = () => {\n const candidates: ClaudeCommandCandidate[] = [];\n const envCommand = process.env.DEV_COPILOT_CLAUDE_BIN?.trim();\n\n if (envCommand) {\n candidates.push({ command: envCommand, source: \"env\" });\n }\n\n const executableNames = getPathExecutableNames();\n const pathCandidates = (process.env.PATH ?? \"\")\n .split(delimiter)\n .filter(Boolean)\n .flatMap((pathDir) => executableNames.map((name) => join(pathDir, name)));\n\n for (const command of pathCandidates) {\n candidates.push({ command, source: \"path\" });\n }\n\n return Array.from(\n new Map(candidates.map((candidate) => [candidate.command, candidate])).values(),\n );\n};\n\nconst canRunClaude = async (command: string) => {\n try {\n await runCli(\n command,\n [\n \"-p\",\n \"--output-format\",\n \"json\",\n \"--model\",\n CLAUDE_SMOKE_MODEL,\n \"--tools\",\n \"\",\n \"--strict-mcp-config\",\n \"--mcp-config\",\n '{\"mcpServers\":{}}',\n \"--\",\n \"OK만 출력해줘.\",\n ],\n {\n cwd: process.cwd(),\n timeoutMs: QUICK_STATUS_CHECK_TIMEOUT_MS,\n maxBuffer: 1024 * 128,\n },\n );\n return true;\n } catch {\n return false;\n }\n};\n\nexport const resolveClaudeCommand = async () => {\n if (claudeCommandPromise) {\n return claudeCommandPromise;\n }\n\n claudeCommandPromise = (async () => {\n const candidates = collectClaudeCandidates();\n const envCandidate = candidates.find((candidate) => candidate.source === \"env\");\n\n if (envCandidate) {\n return envCandidate.command;\n }\n\n for (const candidate of candidates) {\n if (await canRunClaude(candidate.command)) {\n return candidate.command;\n }\n }\n\n return process.env.DEV_COPILOT_CLAUDE_BIN?.trim() || \"claude\";\n })();\n\n return claudeCommandPromise;\n};\n","import type { CopilotMode } from \"../../shared/contracts/copilot\";\n\nexport interface AgentPromptRequest {\n selectedText: string;\n prompt: string;\n mode: CopilotMode;\n route?: string;\n fileHints?: string[];\n projectContext?: string;\n previousResponse?: string;\n}\n\nexport const buildAgentPrompt = (request: AgentPromptRequest) => {\n if (request.mode === \"answer\") {\n return [\n \"Answer the user's web overlay request.\",\n \"Do not modify files.\",\n \"Use the provided project context when it is relevant.\",\n \"Respond in Korean.\",\n \"Keep the answer concise and actionable.\",\n \"\",\n `Current route: ${request.route ?? \"unknown\"}`,\n `Selected text:\\n${request.selectedText || \"(none)\"}`,\n `User prompt:\\n${request.prompt}`,\n `Previous AI response:\\n${request.previousResponse ?? \"(none)\"}`,\n `Project context:\\n${request.projectContext ?? \"(none)\"}`,\n ].join(\"\\n\");\n }\n\n return [\n \"You are a local code-edit proposal generator called from a web overlay.\",\n \"Do not modify files directly.\",\n \"Return JSON only.\",\n \"Do not generate unified diff directly.\",\n \"Put repository-relative file path(path), exact old text(oldText), and replacement text(newText) into the changes array.\",\n \"Never use absolute paths. The path must be relative to the repository root, for example src/features/article/model/data.ts.\",\n \"oldText must exactly match the file content and must not use ellipsis.\",\n \"If the selected text spans multiple rendered lines, use the actual file text from project context for oldText.\",\n \"newText must be meaningfully different from oldText.\",\n \"Ground the proposal in the selected text, user prompt, and provided project context.\",\n \"Write the message field in Korean.\",\n \"\",\n `Current route: ${request.route ?? \"unknown\"}`,\n `Allowed path hints: ${(request.fileHints ?? []).join(\", \") || \"(none)\"}`,\n `Selected text:\\n${request.selectedText || \"(none)\"}`,\n `User prompt:\\n${request.prompt}`,\n `Previous AI response:\\n${request.previousResponse ?? \"(none)\"}`,\n `Project context:\\n${request.projectContext ?? \"(none)\"}`,\n ].join(\"\\n\");\n};\n","import type { CopilotAgent } from \"../../../shared/contracts/copilot\";\nimport type { AgentStatus } from \"./types\";\n\nexport const createAuthenticatedStatus = (params: {\n agent: CopilotAgent;\n message: string;\n model?: string;\n}): AgentStatus => ({\n available: true,\n authenticated: true,\n agent: params.agent,\n message: params.message,\n model: params.model,\n});\n\nexport const createLoginRequiredStatus = (params: {\n agent: CopilotAgent;\n message: string;\n loginCommand: string;\n available?: boolean;\n}): AgentStatus => ({\n available: params.available ?? true,\n authenticated: false,\n agent: params.agent,\n message: params.message,\n loginCommand: params.loginCommand,\n});\n\nexport const createUnavailableStatus = (params: {\n agent: CopilotAgent;\n message: string;\n}): AgentStatus => ({\n available: false,\n authenticated: false,\n agent: params.agent,\n message: params.message,\n});\n\nexport const createUnauthenticatedStatus = (params: {\n agent: CopilotAgent;\n message: string;\n loginCommand?: string;\n available?: boolean;\n}): AgentStatus => ({\n available: params.available ?? true,\n authenticated: false,\n agent: params.agent,\n message: params.message,\n loginCommand: params.loginCommand,\n});\n","import { agentEditResponseSchemaJson } from \"./edit-response-schema\";\nimport { DEFAULT_AGENT_TIMEOUT_MS, QUICK_STATUS_CHECK_TIMEOUT_MS } from \"./constants\";\nimport {\n parseAnswerResponse,\n parseClaudeEditResponse,\n parseClaudeJsonOutput,\n} from \"./agent-response\";\nimport {\n extractCliErrorDetails,\n isCliCommandMissing,\n isCliTimeout,\n} from \"./cli-error\";\nimport { resolveClaudeCommand } from \"./claude-command\";\nimport { runCli } from \"./run-cli\";\nimport { buildAgentPrompt } from \"../prompts\";\nimport {\n createAuthenticatedStatus,\n createLoginRequiredStatus,\n createUnauthenticatedStatus,\n createUnavailableStatus,\n} from \"../../entities/agent/status\";\nimport type {\n AgentAdapter,\n AgentBridgeRequest,\n AgentBridgeResponse,\n AgentStatus,\n} from \"../../entities/agent/types\";\n\nconst CLAUDE_MODEL = process.env.DEV_COPILOT_CLAUDE_MODEL ?? \"haiku\";\nconst CLAUDE_TIMEOUT_MS = Number(process.env.DEV_COPILOT_CLAUDE_TIMEOUT_MS ?? DEFAULT_AGENT_TIMEOUT_MS);\nconst AUTH_ERROR_PATTERN =\n /401|authentication|invalid authentication credentials|please run \\/login|claude\\s*\\/login|로그인/i;\n\nconst toClaudeErrorMessage = (error: unknown) => {\n const details = extractCliErrorDetails(error);\n\n if (isCliTimeout(details)) {\n return \"Claude Code 응답 시간이 초과되었습니다. 잠시 후 다시 시도해 주세요.\";\n }\n\n if (AUTH_ERROR_PATTERN.test(details.merged)) {\n return \"Claude Code 로그인이 필요합니다. 터미널에서 `claude /login`을 실행해 주세요.\";\n }\n\n if (isCliCommandMissing(details)) {\n return \"Claude CLI를 찾을 수 없습니다. Claude Code CLI 설치 상태를 확인해 주세요.\";\n }\n\n return details.message;\n};\n\nexport const claudeAdapter: AgentAdapter = {\n agent: \"claude\",\n async run(request: AgentBridgeRequest): Promise<AgentBridgeResponse> {\n const claudeCommand = await resolveClaudeCommand();\n const prompt = buildAgentPrompt(request);\n const args = [\n \"-p\",\n \"--output-format\",\n \"json\",\n \"--model\",\n CLAUDE_MODEL,\n \"--tools\",\n \"\",\n \"--strict-mcp-config\",\n \"--mcp-config\",\n '{\"mcpServers\":{}}',\n ...(request.mode === \"edit\" ? [\"--json-schema\", agentEditResponseSchemaJson] : []),\n \"--\",\n prompt,\n ];\n\n try {\n const { stdout } = await runCli(claudeCommand, args, {\n cwd: request.cwd,\n timeoutMs: Number(process.env.DEV_COPILOT_AGENT_TIMEOUT_MS ?? CLAUDE_TIMEOUT_MS),\n });\n\n if (request.mode === \"answer\") {\n const { text } = parseClaudeJsonOutput(stdout);\n return parseAnswerResponse(text);\n }\n\n return parseClaudeEditResponse(stdout);\n } catch (error) {\n throw new Error(toClaudeErrorMessage(error));\n }\n },\n async getStatus(cwd: string): Promise<AgentStatus> {\n try {\n const claudeCommand = await resolveClaudeCommand();\n await runCli(claudeCommand, [\"--version\"], {\n cwd,\n timeoutMs: QUICK_STATUS_CHECK_TIMEOUT_MS,\n maxBuffer: 1024 * 32,\n });\n\n return createAuthenticatedStatus({\n agent: \"claude\",\n message: \"Claude Code CLI에 로그인되어 있습니다.\",\n model: CLAUDE_MODEL,\n });\n } catch (error) {\n const details = extractCliErrorDetails(error);\n\n if (isCliCommandMissing(details)) {\n return createUnavailableStatus({\n agent: \"claude\",\n message: \"Claude CLI를 찾을 수 없습니다.\",\n });\n }\n\n if (AUTH_ERROR_PATTERN.test(details.merged)) {\n return createLoginRequiredStatus({\n agent: \"claude\",\n message: \"Claude Code 로그인이 필요합니다.\",\n loginCommand: \"claude /login\",\n });\n }\n\n return createUnauthenticatedStatus({\n agent: \"claude\",\n message: isCliTimeout(details)\n ? \"Claude Code 상태 확인 시간이 초과되었습니다. 잠시 후 다시 시도해 주세요.\"\n : `Claude Code 상태 확인에 실패했습니다: ${details.message}`,\n loginCommand: isCliTimeout(details) ? undefined : \"claude /login\",\n });\n }\n },\n};\n\nexport const __internal = {\n toClaudeErrorMessage,\n};\n","import { access } from \"node:fs/promises\";\nimport { delimiter, join } from \"node:path\";\n\nimport { STATUS_CHECK_TIMEOUT_MS } from \"./constants\";\nimport { runCli } from \"./run-cli\";\n\ninterface CodexCommandCandidate {\n command: string;\n}\n\ninterface ResolvedCodexCommand extends CodexCommandCandidate {\n version: string;\n}\n\nlet codexCommandPromise: Promise<string> | null = null;\n\nconst canAccess = async (path: string) => {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n};\n\nconst getPathExecutableNames = () => {\n if (process.platform !== \"win32\") {\n return [\"codex\"];\n }\n\n const pathExts = process.env.PATHEXT?.split(\";\").filter(Boolean) ?? [\".EXE\", \".CMD\", \".BAT\"];\n return [\"codex\", ...pathExts.map((ext) => `codex${ext.toLowerCase()}`)];\n};\n\nconst collectCodexCandidates = async () => {\n const executableNames = getPathExecutableNames();\n const candidates: CodexCommandCandidate[] = [];\n const pathCandidates = (process.env.PATH ?? \"\")\n .split(delimiter)\n .filter(Boolean)\n .flatMap((pathDir) => executableNames.map((name) => join(pathDir, name)));\n\n for (const command of pathCandidates) {\n if (await canAccess(command)) {\n candidates.push({ command });\n }\n }\n\n return Array.from(\n new Map(candidates.map((candidate) => [candidate.command, candidate])).values(),\n );\n};\n\nconst parseCodexVersion = (output: string) => {\n const version = output.match(/\\d+\\.\\d+\\.\\d+(?:[-+][^\\s]+)?/)?.[0];\n\n if (!version) {\n return null;\n }\n\n return {\n version,\n };\n};\n\nconst resolveCandidate = async (candidate: CodexCommandCandidate) => {\n const { stdout, stderr } = await runCli(candidate.command, [\"--version\"], {\n cwd: process.cwd(),\n timeoutMs: STATUS_CHECK_TIMEOUT_MS,\n maxBuffer: 1024 * 128,\n });\n const parsedVersion = parseCodexVersion(`${stdout}\\n${stderr}`);\n\n if (!parsedVersion) {\n return null;\n }\n\n return {\n ...candidate,\n ...parsedVersion,\n } satisfies ResolvedCodexCommand;\n};\n\nexport const resolveCodexCommand = async () => {\n if (codexCommandPromise) {\n return codexCommandPromise;\n }\n\n codexCommandPromise = (async () => {\n const candidates = await collectCodexCandidates();\n const resolved = await Promise.all(\n candidates.map(async (candidate) => {\n try {\n return await resolveCandidate(candidate);\n } catch {\n return null;\n }\n }),\n );\n const available = resolved.filter((candidate): candidate is ResolvedCodexCommand => Boolean(candidate));\n\n if (!available.length) {\n throw new Error(\"Codex CLI를 찾을 수 없습니다.\");\n }\n\n return available[0].command;\n })();\n\n return codexCommandPromise;\n};\n\nexport const __internal = {\n resetCodexCommandCacheForTests: () => {\n codexCommandPromise = null;\n },\n};\n","import { access, copyFile, mkdtemp, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nlet codexExecutionEnvPromise: Promise<NodeJS.ProcessEnv> | null = null;\n\nconst copyIfExists = async (sourcePath: string, targetPath: string) => {\n try {\n await access(sourcePath);\n await copyFile(sourcePath, targetPath);\n } catch {\n return;\n }\n};\n\nconst writeIsolatedConfig = async (targetPath: string) => {\n try {\n const existingConfig = await readFile(targetPath, \"utf-8\");\n\n if (existingConfig === \"\") {\n return;\n }\n } catch {\n // no-op\n }\n\n await writeFile(targetPath, \"\", \"utf-8\");\n};\n\nconst resolveSourceCodexHome = (env: NodeJS.ProcessEnv = process.env) => {\n return env.CODEX_HOME?.trim() || join(homedir(), \".codex\");\n};\n\nconst createIsolatedCodexHome = async (sourceCodexHome: string) => {\n const isolatedCodexHome = await mkdtemp(join(tmpdir(), \"dev-copilot-codex-home-\"));\n await copyIfExists(join(sourceCodexHome, \"auth.json\"), join(isolatedCodexHome, \"auth.json\"));\n await copyIfExists(\n join(sourceCodexHome, \".credentials.json\"),\n join(isolatedCodexHome, \".credentials.json\"),\n );\n await writeIsolatedConfig(join(isolatedCodexHome, \"config.toml\"));\n\n return isolatedCodexHome;\n};\n\nexport const getCodexExecutionEnv = async (options?: { sourceCodexHome?: string }) => {\n if (codexExecutionEnvPromise) {\n return codexExecutionEnvPromise;\n }\n\n codexExecutionEnvPromise = (async () => {\n const sourceCodexHome = options?.sourceCodexHome ?? resolveSourceCodexHome();\n const isolatedCodexHome = await createIsolatedCodexHome(sourceCodexHome);\n\n return {\n CODEX_HOME: isolatedCodexHome,\n } satisfies NodeJS.ProcessEnv;\n })();\n\n return codexExecutionEnvPromise;\n};\n\nexport const __internal = {\n resetCodexExecutionEnvCacheForTests: () => {\n codexExecutionEnvPromise = null;\n },\n resolveSourceCodexHome,\n};\n","import { readFile, rm, writeFile } from \"node:fs/promises\";\n\nimport { extractCliErrorDetails, isCliCommandMissing, isCliTimeout } from \"./cli-error\";\nimport {\n MODEL_STATUS_CHECK_TIMEOUT_MS,\n STATUS_CHECK_TIMEOUT_MS,\n} from \"./constants\";\nimport { resolveCodexCommand } from \"./codex-command\";\nimport { getCodexExecutionEnv } from \"./codex-home\";\nimport { agentEditResponseSchema } from \"./edit-response-schema\";\nimport { runCli } from \"./run-cli\";\nimport { createTempPath } from \"../../shared/lib/temp-path\";\n\nconst CODEX_MODEL = process.env.DEV_COPILOT_CODEX_MODEL ?? \"gpt-5.3-codex\";\ntype CodexEditStrategy = \"output-schema\" | \"prompt-json\";\n\nexport type CodexHealthStatus =\n | \"ready\"\n | \"unavailable\"\n | \"login_required\"\n | \"exec_failed\"\n | \"schema_failed\"\n | \"timeout\";\n\nexport interface CodexHealthCheck {\n status: CodexHealthStatus;\n message: string;\n command?: string;\n model?: string;\n loginCommand?: string;\n editStrategy?: CodexEditStrategy;\n}\n\nlet codexHealthPromise: Promise<CodexHealthCheck> | null = null;\n\nconst isAuthenticatedFromStatus = (statusOutput: string) => {\n const normalized = statusOutput.toLowerCase();\n\n if (/not logged in|login required|로그인 필요/.test(normalized)) {\n return false;\n }\n\n return /logged in|로그인됨|로그인되어/.test(normalized);\n};\n\nconst createSchemaSmokePayload = () =>\n JSON.stringify({\n message: \"ok\",\n warnings: [],\n changes: [\n {\n path: \"src/App.tsx\",\n oldText: \"before\",\n newText: \"after\",\n },\n ],\n });\n\nconst createPromptJsonSmokePayload = () =>\n JSON.stringify({\n message: \"ok\",\n warnings: [],\n changes: [\n {\n path: \"src/App.tsx\",\n oldText: \"before\",\n newText: \"after\",\n },\n ],\n });\n\nconst runExecSmokeTest = async (command: string, cwd: string, env: NodeJS.ProcessEnv) => {\n const outputPath = createTempPath(\"dev-copilot-codex-answer-smoke\", \".txt\");\n\n try {\n await runCli(\n command,\n [\n \"exec\",\n \"--ephemeral\",\n \"--model\",\n CODEX_MODEL,\n \"--cd\",\n cwd,\n \"--sandbox\",\n \"read-only\",\n \"--skip-git-repo-check\",\n \"--output-last-message\",\n outputPath,\n \"OK만 출력해줘.\",\n ],\n {\n cwd,\n timeoutMs: MODEL_STATUS_CHECK_TIMEOUT_MS,\n maxBuffer: 1024 * 512,\n env,\n },\n );\n\n const output = await readFile(outputPath, \"utf-8\");\n if (!output.trim()) {\n throw new Error(\"Codex CLI smoke test output이 비어 있습니다.\");\n }\n } finally {\n await rm(outputPath, { force: true });\n }\n};\n\nconst runEditSchemaSmokeTest = async (command: string, cwd: string, env: NodeJS.ProcessEnv) => {\n const outputPath = createTempPath(\"dev-copilot-codex-edit-smoke\", \".json\");\n const schemaPath = createTempPath(\"dev-copilot-codex-edit-schema\", \".json\");\n\n try {\n await writeFile(schemaPath, JSON.stringify(agentEditResponseSchema), \"utf-8\");\n\n await runCli(\n command,\n [\n \"exec\",\n \"--ephemeral\",\n \"--model\",\n CODEX_MODEL,\n \"--cd\",\n cwd,\n \"--sandbox\",\n \"read-only\",\n \"--skip-git-repo-check\",\n \"--output-last-message\",\n outputPath,\n \"--output-schema\",\n schemaPath,\n \"message에 ok, warnings에 빈 배열, changes에 한 개의 수정 항목만 담아 JSON으로 응답해줘.\",\n ],\n {\n cwd,\n timeoutMs: MODEL_STATUS_CHECK_TIMEOUT_MS,\n maxBuffer: 1024 * 512,\n env,\n },\n );\n\n const output = await readFile(outputPath, \"utf-8\");\n if (output.trim() !== createSchemaSmokePayload()) {\n JSON.parse(output);\n }\n } finally {\n await rm(outputPath, { force: true });\n await rm(schemaPath, { force: true });\n }\n};\n\nconst runEditPromptJsonSmokeTest = async (command: string, cwd: string, env: NodeJS.ProcessEnv) => {\n const outputPath = createTempPath(\"dev-copilot-codex-edit-prompt-json-smoke\", \".json\");\n\n try {\n await runCli(\n command,\n [\n \"exec\",\n \"--ephemeral\",\n \"--model\",\n CODEX_MODEL,\n \"--cd\",\n cwd,\n \"--sandbox\",\n \"read-only\",\n \"--skip-git-repo-check\",\n \"--output-last-message\",\n outputPath,\n [\n \"Return JSON only.\",\n \"Respond with an object that has message, warnings, and changes.\",\n \"warnings must be an empty array.\",\n \"changes must contain exactly one object with path, oldText, and newText.\",\n \"Use this exact payload:\",\n createPromptJsonSmokePayload(),\n ].join(\"\\n\"),\n ],\n {\n cwd,\n timeoutMs: MODEL_STATUS_CHECK_TIMEOUT_MS,\n maxBuffer: 1024 * 512,\n env,\n },\n );\n\n const output = await readFile(outputPath, \"utf-8\");\n const normalized = output.trim().replace(/^```json\\s*|\\s*```$/g, \"\");\n const parsed = JSON.parse(normalized);\n\n if (JSON.stringify(parsed) !== createPromptJsonSmokePayload()) {\n throw new Error(\"Codex CLI prompt-json smoke test payload mismatch\");\n }\n } finally {\n await rm(outputPath, { force: true });\n }\n};\n\nexport const getCodexHealthCheck = async (cwd: string): Promise<CodexHealthCheck> => {\n if (codexHealthPromise) {\n return codexHealthPromise;\n }\n\n codexHealthPromise = (async () => {\n let command: string;\n try {\n command = await resolveCodexCommand();\n } catch (error) {\n return {\n status: \"unavailable\",\n message:\n error instanceof Error\n ? error.message\n : \"Codex CLI를 찾을 수 없습니다.\",\n } satisfies CodexHealthCheck;\n }\n\n const env = await getCodexExecutionEnv();\n\n try {\n const { stdout, stderr } = await runCli(command, [\"login\", \"status\"], {\n cwd,\n timeoutMs: STATUS_CHECK_TIMEOUT_MS,\n maxBuffer: 1024 * 128,\n env,\n });\n const statusText = stdout.trim() || stderr.trim();\n\n if (statusText && !isAuthenticatedFromStatus(statusText)) {\n return {\n status: \"login_required\",\n message: statusText || \"Codex CLI 로그인이 필요합니다.\",\n loginCommand: \"codex login\",\n command,\n } satisfies CodexHealthCheck;\n }\n } catch (error) {\n const details = extractCliErrorDetails(error);\n\n if (isCliTimeout(details)) {\n return {\n status: \"timeout\",\n message: \"Codex CLI 상태 확인 중 시간이 초과되었습니다.\",\n command,\n } satisfies CodexHealthCheck;\n }\n\n if (isCliCommandMissing(details)) {\n return {\n status: \"unavailable\",\n message: \"Codex CLI를 실행할 수 없습니다.\",\n } satisfies CodexHealthCheck;\n }\n\n if (isCliCommandMissing(details)) {\n return {\n status: \"unavailable\",\n message: \"Codex CLI를 실행할 수 없습니다.\",\n } satisfies CodexHealthCheck;\n }\n }\n\n try {\n await runExecSmokeTest(command, cwd, env);\n } catch (error) {\n const details = extractCliErrorDetails(error);\n return {\n status: isCliTimeout(details) ? \"timeout\" : \"exec_failed\",\n message: isCliTimeout(details)\n ? \"Codex CLI 답변 smoke test 중 시간이 초과되었습니다.\"\n : \"Codex CLI 답변 smoke test에 실패했습니다.\",\n command,\n } satisfies CodexHealthCheck;\n }\n\n try {\n await runEditSchemaSmokeTest(command, cwd, env);\n } catch (error) {\n const details = extractCliErrorDetails(error);\n\n if (isCliTimeout(details)) {\n return {\n status: \"timeout\",\n message: \"Codex CLI edit schema smoke test 중 시간이 초과되었습니다.\",\n command,\n } satisfies CodexHealthCheck;\n }\n\n try {\n await runEditPromptJsonSmokeTest(command, cwd, env);\n return {\n status: \"ready\",\n message: \"Codex CLI가 prompt-json fallback으로 응답 준비를 마쳤습니다.\",\n command,\n model: CODEX_MODEL,\n editStrategy: \"prompt-json\",\n } satisfies CodexHealthCheck;\n } catch {\n return {\n status: \"schema_failed\",\n message: \"Codex CLI edit 응답 스키마 smoke test에 실패했습니다.\",\n command,\n } satisfies CodexHealthCheck;\n }\n }\n\n return {\n status: \"ready\",\n message: \"Codex CLI가 응답 준비를 마쳤습니다.\",\n command,\n model: CODEX_MODEL,\n editStrategy: \"output-schema\",\n } satisfies CodexHealthCheck;\n })();\n\n return codexHealthPromise;\n};\n\nexport const __internal = {\n resetCodexHealthCheckCacheForTests: () => {\n codexHealthPromise = null;\n },\n};\n","import { promises as fs } from \"node:fs\";\n\nimport { buildAgentPrompt } from \"../prompts\";\nimport {\n parseCodexEditResponse,\n parseAnswerResponse,\n} from \"./agent-response\";\nimport {\n extractCliErrorDetails,\n isCliCommandMissing,\n} from \"./cli-error\";\nimport { agentEditResponseSchema } from \"./edit-response-schema\";\nimport { getCodexHealthCheck } from \"./codex-health\";\nimport { runCli } from \"./run-cli\";\nimport { getCodexExecutionEnv } from \"./codex-home\";\nimport {\n DEFAULT_AGENT_MAX_BUFFER_BYTES,\n DEFAULT_AGENT_TIMEOUT_MS,\n} from \"./constants\";\nimport {\n createAuthenticatedStatus,\n createLoginRequiredStatus,\n createUnauthenticatedStatus,\n createUnavailableStatus,\n} from \"../../entities/agent/status\";\nimport type {\n AgentAdapter,\n AgentBridgeRequest,\n AgentBridgeResponse,\n AgentStatus,\n} from \"../../entities/agent/types\";\nimport { createTempPath } from \"../../shared/lib/temp-path\";\n\nconst CODEX_MODEL = process.env.DEV_COPILOT_CODEX_MODEL ?? \"gpt-5.3-codex\";\nconst CODEX_TIMEOUT_MS = Number(process.env.DEV_COPILOT_CODEX_TIMEOUT_MS ?? DEFAULT_AGENT_TIMEOUT_MS);\n\nconst isCodexLoginRequiredError = (error: unknown) => {\n const details = extractCliErrorDetails(error);\n\n return /not logged in|login required|authentication|unauthorized/i.test(details.merged);\n};\n\nconst toCodexErrorMessage = (error: unknown) => {\n const details = extractCliErrorDetails(error);\n\n if (/requires a newer version of Codex/i.test(details.merged)) {\n return [\n \"현재 설치된 Codex CLI 버전과 모델 조합이 호환되지 않습니다.\",\n \"Codex CLI를 업데이트하거나 DEV_COPILOT_CODEX_MODEL 값을 호환 가능한 모델로 지정해 주세요.\",\n ].join(\" \");\n }\n\n if (/migration .* is missing in the resolved migrations/i.test(details.merged)) {\n return [\n \"Codex 로컬 상태 DB 마이그레이션 오류가 발생했습니다.\",\n \"Codex CLI를 최신 버전으로 업데이트한 뒤 다시 시도해 주세요.\",\n ].join(\" \");\n }\n\n if (/Error loading config\\.toml: invalid transport/i.test(details.merged)) {\n return [\n \"현재 Codex CLI가 Codex 설정 파일의 MCP 형식을 해석하지 못했습니다.\",\n \"Dev Copilot이 호환되는 Codex 실행 파일을 자동으로 찾지 못했습니다.\",\n \"Codex CLI를 업데이트한 뒤 다시 시도해 주세요.\",\n ].join(\" \");\n }\n\n if (isCodexLoginRequiredError(error)) {\n return \"Codex CLI 로그인이 필요합니다. 터미널에서 `codex login`을 실행해 주세요.\";\n }\n\n if (isCliCommandMissing(details)) {\n return \"Codex CLI를 찾을 수 없습니다. Codex CLI 설치 상태를 확인해 주세요.\";\n }\n\n return details.message;\n};\n\nexport const codexAdapter: AgentAdapter = {\n agent: \"codex\",\n async warmup(cwd: string) {\n await getCodexHealthCheck(cwd);\n },\n async run(request: AgentBridgeRequest): Promise<AgentBridgeResponse> {\n const health = await getCodexHealthCheck(request.cwd);\n if (health.status !== \"ready\" || !health.command) {\n throw new Error(health.message);\n }\n\n const codexCommand = health.command;\n const outputPath = createTempPath(\"dev-copilot-codex\", \".json\");\n const schemaPath = createTempPath(\"dev-copilot-codex-schema\", \".json\");\n const useOutputSchema = health.editStrategy !== \"prompt-json\";\n\n if (request.mode === \"edit\" && useOutputSchema) {\n await fs.writeFile(\n schemaPath,\n JSON.stringify(agentEditResponseSchema),\n \"utf-8\",\n );\n }\n\n const prompt = request.mode === \"edit\" && !useOutputSchema\n ? [\n buildAgentPrompt(request),\n \"\",\n \"Return a JSON object only.\",\n \"Do not include markdown fences unless strictly necessary.\",\n \"The object must contain message, warnings, and changes.\",\n \"warnings must be an array of strings.\",\n \"changes must be an array of { path, oldText, newText } objects.\",\n ].join(\"\\n\")\n : buildAgentPrompt(request);\n const env = await getCodexExecutionEnv();\n const args = [\n \"exec\",\n \"--ephemeral\",\n \"--model\",\n CODEX_MODEL,\n \"--cd\",\n request.cwd,\n \"--sandbox\",\n \"read-only\",\n \"--skip-git-repo-check\",\n \"--output-last-message\",\n outputPath,\n ...(request.mode === \"edit\" && useOutputSchema ? [\"--output-schema\", schemaPath] : []),\n prompt,\n ];\n\n try {\n await runCli(codexCommand, args, {\n cwd: request.cwd,\n maxBuffer: DEFAULT_AGENT_MAX_BUFFER_BYTES,\n timeoutMs: Number(process.env.DEV_COPILOT_AGENT_TIMEOUT_MS ?? CODEX_TIMEOUT_MS),\n env,\n });\n\n if (request.mode === \"answer\") {\n const output = await fs.readFile(outputPath, \"utf-8\");\n return parseAnswerResponse(output);\n }\n\n return parseCodexEditResponse(await fs.readFile(outputPath, \"utf-8\"));\n } catch (error) {\n throw new Error(toCodexErrorMessage(error));\n } finally {\n await fs.rm(outputPath, { force: true });\n await fs.rm(schemaPath, { force: true });\n }\n },\n async getStatus(cwd: string): Promise<AgentStatus> {\n const health = await getCodexHealthCheck(cwd);\n\n if (health.status === \"ready\") {\n return createAuthenticatedStatus({\n agent: \"codex\",\n message: \"Codex CLI에 로그인되어 있습니다.\",\n model: health.model ?? CODEX_MODEL,\n });\n }\n\n if (health.status === \"login_required\") {\n return createLoginRequiredStatus({\n agent: \"codex\",\n message: health.message,\n loginCommand: health.loginCommand ?? \"codex login\",\n });\n }\n\n if (health.status === \"unavailable\") {\n return createUnavailableStatus({\n agent: \"codex\",\n message: health.message,\n });\n }\n\n return createUnauthenticatedStatus({\n agent: \"codex\",\n message: health.message,\n });\n },\n};\n\nexport const __internal = {\n isCodexLoginRequiredError,\n toCodexErrorMessage,\n};\n","import type { CopilotAgent } from \"../../../shared/contracts/copilot\";\nimport type { AgentAdapter } from \"../../entities/agent/types\";\nimport { claudeAdapter } from \"../../internal/agents/claude-adapter\";\nimport { codexAdapter } from \"../../internal/agents/codex-adapter\";\n\nconst adapters: Record<CopilotAgent, AgentAdapter> = {\n codex: codexAdapter,\n claude: claudeAdapter,\n};\n\nconst testAdapters: Partial<Record<CopilotAgent, AgentAdapter>> = {};\n\nexport const resolveAgentAdapter = (agent: CopilotAgent): AgentAdapter => {\n return testAdapters[agent] ?? adapters[agent];\n};\n\nexport const __internal = {\n setAgentAdapterForTests: (agent: CopilotAgent, adapter: AgentAdapter) => {\n testAdapters[agent] = adapter;\n },\n resetAgentAdaptersForTests: () => {\n for (const agent of Object.keys(testAdapters) as CopilotAgent[]) {\n delete testAdapters[agent];\n }\n },\n};\n","import { execFile } from \"node:child_process\";\nimport { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\ninterface SearchConfig {\n rootDir: string;\n allowedDirs: string[];\n}\n\nexport interface SearchResult {\n path: string;\n line: number;\n text: string;\n}\n\nconst normalize = (value: string) => value.replaceAll(\"\\\\\", \"/\").replace(/^\\.\\//, \"\");\n\nconst walk = async (rootDir: string, relativeDir: string, files: string[], limit: number) => {\n if (files.length >= limit) {\n return;\n }\n\n const absoluteDir = path.join(rootDir, relativeDir);\n const entries = await fs.readdir(absoluteDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (files.length >= limit) {\n return;\n }\n\n const relativePath = normalize(path.join(relativeDir, entry.name));\n\n if ([\"node_modules\", \".next\", \".git\", \"dist\", \"build\", \"coverage\"].some((name) => relativePath.includes(`/${name}/`) || relativePath.startsWith(`${name}/`))) {\n continue;\n }\n\n if (entry.isDirectory()) {\n await walk(rootDir, relativePath, files, limit);\n continue;\n }\n\n if (entry.isFile()) {\n files.push(relativePath);\n }\n }\n};\n\nconst searchWithRg = async (config: SearchConfig, query: string, limit: number) => {\n const { stdout } = await execFileAsync(\n \"rg\",\n [\n \"--line-number\",\n \"--fixed-strings\",\n \"--color\",\n \"never\",\n \"--glob\",\n \"!node_modules/**\",\n \"--glob\",\n \"!.next/**\",\n \"--glob\",\n \"!.git/**\",\n query,\n ...config.allowedDirs,\n ],\n {\n cwd: config.rootDir,\n maxBuffer: 1024 * 1024,\n },\n );\n\n return stdout\n .split(\"\\n\")\n .filter(Boolean)\n .slice(0, limit)\n .map((line) => {\n const [filePath, lineNumber, ...rest] = line.split(\":\");\n return {\n path: filePath,\n line: Number(lineNumber),\n text: rest.join(\":\").trim(),\n };\n });\n};\n\nconst searchWithNode = async (config: SearchConfig, query: string, limit: number): Promise<SearchResult[]> => {\n const files: string[] = [];\n\n for (const dir of config.allowedDirs) {\n try {\n await walk(config.rootDir, dir, files, 500);\n } catch {\n continue;\n }\n }\n\n const results: SearchResult[] = [];\n\n for (const filePath of files) {\n if (results.length >= limit) {\n break;\n }\n\n try {\n const content = await fs.readFile(path.join(config.rootDir, filePath), \"utf-8\");\n const lines = content.slice(0, 100_000).split(\"\\n\");\n\n lines.forEach((line, index) => {\n if (results.length < limit && line.includes(query)) {\n results.push({\n path: filePath,\n line: index + 1,\n text: line.trim(),\n });\n }\n });\n } catch {\n continue;\n }\n }\n\n return results;\n};\n\nexport const searchProjectText = async (\n config: SearchConfig,\n query: string,\n limit: number,\n): Promise<SearchResult[]> => {\n if (!query.trim()) {\n return [];\n }\n\n try {\n return await searchWithRg(config, query, limit);\n } catch {\n return searchWithNode(config, query, limit);\n }\n};\n\nconst compact = (value: string) => value.replace(/\\s+/g, \"\");\n\nexport const searchProjectTextIgnoringWhitespace = async (\n config: SearchConfig,\n query: string,\n limit: number,\n): Promise<SearchResult[]> => {\n const compactQuery = compact(query);\n\n if (!compactQuery) {\n return [];\n }\n\n const files: string[] = [];\n\n for (const dir of config.allowedDirs) {\n try {\n await walk(config.rootDir, dir, files, 500);\n } catch {\n continue;\n }\n }\n\n const results: SearchResult[] = [];\n\n for (const filePath of files) {\n if (results.length >= limit) {\n break;\n }\n\n try {\n const content = await fs.readFile(path.join(config.rootDir, filePath), \"utf-8\");\n const lines = content.slice(0, 100_000).split(\"\\n\");\n\n lines.forEach((line, index) => {\n if (results.length < limit && compact(line).includes(compactQuery)) {\n results.push({\n path: filePath,\n line: index + 1,\n text: line.trim(),\n });\n }\n });\n } catch {\n continue;\n }\n }\n\n return results;\n};\n","import {\n searchProjectText,\n searchProjectTextIgnoringWhitespace,\n} from \"./search-strategies\";\n\ninterface CopilotContextParams {\n selectedText?: string;\n route?: string;\n fileHints?: string[];\n}\n\nconst findBySelectedText = async (\n rootDir: string,\n allowedDirs: string[],\n text: string,\n) => {\n const normalized = text.replace(/\\s+/g, \" \").trim();\n const candidates = [\n normalized,\n normalized.slice(0, 120),\n ...normalized.split(/[.!?]\\s+/).filter((item) => item.length > 12),\n ];\n\n for (const candidate of candidates) {\n const results = await searchProjectText({ rootDir, allowedDirs }, candidate, 8);\n if (results.length) {\n return { query: candidate, results };\n }\n }\n\n for (const candidate of candidates) {\n const results = await searchProjectTextIgnoringWhitespace(\n { rootDir, allowedDirs },\n candidate,\n 8,\n );\n if (results.length) {\n return { query: `${candidate} (ignore-whitespace)`, results };\n }\n }\n\n return { query: normalized, results: [] };\n};\n\nexport const buildCopilotProjectContext = async (\n rootDir: string,\n allowedDirs: string[],\n params: CopilotContextParams,\n) => {\n const routeQuery = params.route?.startsWith(\"/\")\n ? `app${params.route === \"/\" ? \"\" : params.route}/page.tsx`\n : params.route;\n\n const selectedText = params.selectedText?.trim();\n const textMatches = selectedText\n ? await findBySelectedText(rootDir, allowedDirs, selectedText)\n : { query: \"\", results: [] };\n\n const routeMatches = routeQuery\n ? await searchProjectText({ rootDir, allowedDirs }, routeQuery, 5)\n : [];\n\n return JSON.stringify(\n {\n project: {\n allowedDirs,\n },\n requestContext: {\n route: params.route,\n fileHints: params.fileHints,\n },\n selectedTextLookup: textMatches,\n routeLookup: routeMatches,\n guidance:\n \"selectedTextLookup.results의 path와 text를 우선 사용해 path/oldText/newText 수정안을 작성하세요.\",\n },\n null,\n 2,\n );\n};\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type {\n CopilotAgent,\n CopilotChatRequest,\n CopilotChatResponse,\n} from \"../../../shared/contracts/copilot\";\nimport { resolveAgentAdapter } from \"../agent-runner/resolve-agent-adapter\";\nimport { buildCopilotProjectContext } from \"../project-context/build-project-context\";\nimport {\n buildPatchPreview,\n resolveAllowedPathsWithSrcFallback,\n saveProposedPatch,\n validatePatchPreview,\n} from \"../patch-flow/patch-flow-service\";\nimport type { DevCopilotBridgeConfig } from \"../../shared/config/bridge-config\";\nimport { readJsonBody } from \"../../shared/http/read-json-body\";\nimport { sendJson } from \"../../shared/http/respond\";\n\nconst isCopilotAgent = (value: unknown): value is CopilotAgent => {\n return value === \"codex\" || value === \"claude\";\n};\n\nexport const handleChatRoute = async (\n request: IncomingMessage,\n response: ServerResponse,\n config: DevCopilotBridgeConfig,\n) => {\n const payload = await readJsonBody<CopilotChatRequest>(request);\n const effectiveAllowedPaths = resolveAllowedPathsWithSrcFallback(config, payload.context?.fileHints);\n const agent = isCopilotAgent(payload.context?.agent) ? payload.context.agent : config.agent;\n const adapter = resolveAgentAdapter(agent);\n\n if (!payload.prompt?.trim()) {\n sendJson(response, config, 400, { error: \"프롬프트를 입력해 주세요.\" });\n return;\n }\n\n const projectContext = await buildCopilotProjectContext(config.rootDir, effectiveAllowedPaths, {\n selectedText: payload.selectedText,\n route: payload.context?.route,\n fileHints: payload.context?.fileHints,\n });\n\n const agentResponse = await adapter.run({\n selectedText: payload.selectedText ?? \"\",\n prompt: payload.prompt,\n mode: payload.mode,\n route: payload.context?.route,\n fileHints: payload.context?.fileHints,\n previousResponse: payload.context?.previousResponse,\n projectContext,\n cwd: config.rootDir,\n });\n\n if (payload.mode === \"answer\") {\n const answerResponse: CopilotChatResponse = {\n message: agentResponse.message,\n warnings: agentResponse.warnings,\n };\n\n sendJson(response, config, 200, answerResponse);\n return;\n }\n\n let patchPreview = \"\";\n\n try {\n patchPreview = await buildPatchPreview(agentResponse.changes, config, effectiveAllowedPaths);\n } catch (error) {\n sendJson(response, config, 200, {\n message:\n agentResponse.message ??\n \"에이전트가 수정안을 만들었지만 실제 파일 내용과 매칭하지 못했습니다.\",\n warnings: [\n ...(agentResponse.warnings ?? []),\n error instanceof Error ? error.message : \"수정안 생성에 실패했습니다.\",\n ],\n } satisfies CopilotChatResponse);\n return;\n }\n\n if (!patchPreview) {\n sendJson(response, config, 200, {\n message: agentResponse.message ?? \"패치 제안을 생성하지 못했습니다.\",\n warnings: [\n ...(agentResponse.warnings ?? []),\n \"적용 가능한 변경 목록이 없어 패치 미리보기와 적용 버튼을 만들 수 없습니다.\",\n ],\n } satisfies CopilotChatResponse);\n return;\n }\n\n try {\n await validatePatchPreview(patchPreview, config, effectiveAllowedPaths);\n } catch (error) {\n sendJson(response, config, 200, {\n message:\n agentResponse.message ??\n \"에이전트가 수정안을 만들었지만 적용 가능한 diff 형식이 아닙니다.\",\n patchPreview,\n warnings: [\n ...(agentResponse.warnings ?? []),\n error instanceof Error ? error.message : \"patch 검증에 실패했습니다.\",\n ],\n } satisfies CopilotChatResponse);\n return;\n }\n\n const patch = saveProposedPatch(patchPreview, effectiveAllowedPaths);\n sendJson(response, config, 200, {\n message: agentResponse.message ?? \"에이전트가 패치 미리보기를 생성했습니다.\",\n patchPreview,\n patchId: patch.patchId,\n warnings: agentResponse.warnings ?? [],\n } satisfies CopilotChatResponse);\n};\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { CopilotAgent } from \"../../../shared/contracts/copilot\";\nimport { resolveAgentAdapter } from \"../agent-runner/resolve-agent-adapter\";\nimport type { DevCopilotBridgeConfig } from \"../../shared/config/bridge-config\";\nimport { sendJson } from \"../../shared/http/respond\";\n\nconst isCopilotAgent = (value: string | null): value is CopilotAgent => {\n return value === \"codex\" || value === \"claude\";\n};\n\nexport const handleStatusRoute = async (\n _request: IncomingMessage,\n response: ServerResponse,\n config: DevCopilotBridgeConfig,\n url: URL,\n) => {\n const queryAgent = url.searchParams.get(\"agent\");\n const agent = isCopilotAgent(queryAgent) ? queryAgent : config.agent;\n const adapter = resolveAgentAdapter(agent);\n\n sendJson(response, config, 200, await adapter.getStatus(config.rootDir));\n};\n","export const toBridgeErrorMessage = (error: unknown) => {\n if (error instanceof Error) {\n return error.message;\n }\n\n return \"브리지 서버 처리 중 오류가 발생했습니다.\";\n};\n","import { createServer } from \"node:http\";\n\nimport type { DevCopilotBridgeConfig } from \"../shared/config/bridge-config\";\nimport { handleApplyRoute } from \"../features/apply/apply-route\";\nimport { handleChatRoute } from \"../features/chat/chat-route\";\nimport { handleStatusRoute } from \"../features/status/status-route\";\nimport { toBridgeErrorMessage } from \"../shared/http/error-mapper\";\nimport { createCorsHeaders, sendJson } from \"../shared/http/respond\";\n\nexport const createDevCopilotBridgeServer = (config: DevCopilotBridgeConfig) => {\n return createServer(async (request, response) => {\n const method = request.method ?? \"GET\";\n const url = new URL(request.url ?? \"/\", `http://${config.host}:${config.port}`);\n\n if (method === \"OPTIONS\") {\n response.writeHead(204, createCorsHeaders(config));\n response.end();\n return;\n }\n\n try {\n if (method === \"GET\" && url.pathname === \"/status\") {\n await handleStatusRoute(request, response, config, url);\n return;\n }\n\n if (method === \"POST\" && url.pathname === \"/chat\") {\n await handleChatRoute(request, response, config);\n return;\n }\n\n if (method === \"POST\" && url.pathname === \"/apply\") {\n await handleApplyRoute(request, response, config);\n return;\n }\n\n sendJson(response, config, 404, { error: \"지원하지 않는 경로입니다.\" });\n } catch (error) {\n sendJson(response, config, 500, { error: toBridgeErrorMessage(error) });\n }\n });\n};\n","import type { CopilotAgent } from \"../../shared/contracts/copilot\";\nimport { resolveAgentAdapter } from \"../features/agent-runner/resolve-agent-adapter\";\nimport { createDevCopilotBridgeConfig } from \"../shared/config/bridge-config\";\nimport { createDevCopilotBridgeServer } from \"./create-bridge-server\";\n\nconst resolveAgent = (value: string | undefined): CopilotAgent => {\n if (value === \"claude\") {\n return \"claude\";\n }\n\n return \"codex\";\n};\n\nexport const runDevCopilotBridgeCli = async (argv: string[]) => {\n const portFlagIndex = argv.findIndex((value) => value === \"-p\");\n const portFlagValue = portFlagIndex >= 0 ? argv[portFlagIndex + 1] : undefined;\n const positionalPort = argv.find((value) => /^\\d+$/.test(value));\n const resolvedPort = portFlagValue\n ? Number(portFlagValue)\n : positionalPort\n ? Number(positionalPort)\n : Number(process.env.DEV_COPILOT_BRIDGE_PORT ?? 3339);\n const positionalAgent = argv.find((value) => value === \"codex\" || value === \"claude\");\n\n const config = createDevCopilotBridgeConfig({\n rootDir: process.cwd(),\n host: process.env.DEV_COPILOT_BRIDGE_HOST,\n port: Number.isFinite(resolvedPort) ? resolvedPort : 3339,\n corsOrigin: process.env.DEV_COPILOT_BRIDGE_CORS_ORIGIN ?? \"*\",\n agent: resolveAgent(positionalAgent),\n allowedPaths: (process.env.DEV_COPILOT_ALLOWED_PATHS ??\n \"app,src,widgets,features,entities,shared,components\")\n .split(\",\")\n .map((value) => value.trim())\n .filter(Boolean),\n });\n\n const server = createDevCopilotBridgeServer(config);\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", (error) => {\n reject(error);\n });\n\n server.listen(config.port, config.host, () => {\n process.stdout.write(\n `[dev-copilot-bridge] listening on http://${config.host}:${config.port}\\n`,\n );\n resolve();\n });\n });\n\n void resolveAgentAdapter(config.agent)\n .warmup?.(config.rootDir)\n .catch((error) => {\n process.stderr.write(\n `[dev-copilot-bridge] startup health check failed: ${\n error instanceof Error ? error.message : String(error)\n }\\n`,\n );\n });\n};\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { a as CopilotChatRequest, c as CopilotMode, i as CopilotApplyResponse, n as CopilotAgentStatusResponse, o as CopilotChatResponse, r as CopilotApplyRequest, s as CopilotErrorResponse, t as CopilotAgent } from "./copilot-D8--qKgC.mjs";
2
+ export { CopilotAgent, CopilotAgentStatusResponse, CopilotApplyRequest, CopilotApplyResponse, CopilotChatRequest, CopilotChatResponse, CopilotErrorResponse, CopilotMode };
@@ -0,0 +1,2 @@
1
+ import { t as CopilotOverlayWidget } from "../../copilot-overlay-NlUgrMjy.mjs";
2
+ export { CopilotOverlayWidget as DevCopilotOverlay };
@@ -0,0 +1,4 @@
1
+ import "../../dev-copilot-context-CA9bqV_U.mjs";
2
+ import { t as CopilotOverlayWidget } from "../../copilot-overlay-ClRoIHew.mjs";
3
+
4
+ export { CopilotOverlayWidget as DevCopilotOverlay };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yr-kits/dev-copilot",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "선택 텍스트 기반 Dev Copilot 오버레이와 로컬 브리지 실행 CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -9,11 +9,28 @@
9
9
  "exports": {
10
10
  ".": {
11
11
  "types": "./dist/index.d.mts",
12
- "import": "./dist/index.mjs"
12
+ "import": "./dist/index.mjs",
13
+ "default": "./dist/index.mjs"
14
+ },
15
+ "./app": {
16
+ "types": "./dist/app/index.d.mts",
17
+ "import": "./dist/app/index.mjs",
18
+ "default": "./dist/app/index.mjs"
19
+ },
20
+ "./widgets/copilot-overlay": {
21
+ "types": "./dist/widgets/copilot-overlay/index.d.mts",
22
+ "import": "./dist/widgets/copilot-overlay/index.mjs",
23
+ "default": "./dist/widgets/copilot-overlay/index.mjs"
24
+ },
25
+ "./bridge/app": {
26
+ "types": "./dist/bridge/app/index.d.mts",
27
+ "import": "./dist/bridge/app/index.mjs",
28
+ "default": "./dist/bridge/app/index.mjs"
13
29
  },
14
30
  "./types": {
15
- "types": "./dist/types/index.d.mts",
16
- "import": "./dist/types/index.mjs"
31
+ "types": "./dist/types.d.mts",
32
+ "import": "./dist/types.mjs",
33
+ "default": "./dist/types.mjs"
17
34
  }
18
35
  },
19
36
  "bin": {
@@ -45,7 +62,9 @@
45
62
  "react": "^18.2.0 || ^19.0.0",
46
63
  "react-dom": "^18.2.0 || ^19.0.0"
47
64
  },
48
- "dependencies": {},
65
+ "dependencies": {
66
+ "@yr-kits/cli": "^0.1.7"
67
+ },
49
68
  "devDependencies": {
50
69
  "@types/node": "^22.10.0",
51
70
  "@types/react": "^19.2.2",
@@ -56,9 +75,10 @@
56
75
  "scripts": {
57
76
  "build": "tsdown",
58
77
  "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"
78
+ "test": "tsdown src/**/*.test.ts --format esm --out-dir /tmp/dev-copilot-tests --clean && node --test $(find /tmp/dev-copilot-tests -name '*.test.mjs' -print)",
79
+ "release:patch": "npm version patch --no-git-tag-version && pnpm publish --access public --no-git-checks",
80
+ "release:minor": "npm version minor --no-git-tag-version && pnpm publish --access public --no-git-checks",
81
+ "release:major": "npm version major --no-git-tag-version && pnpm publish --access public --no-git-checks",
82
+ "lint:architecture": "node ./scripts/check-boundaries.mjs"
63
83
  }
64
84
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/config.ts","../src/components/dev-copilot-provider.tsx","../src/components/dev-copilot-overlay.tsx","../src/hooks/use-selection-capture.ts"],"mappings":";;;;;;UAAiB,gBAAA;EACf,OAAA;EACA,YAAA;AAAA;;;UCSQ,uBAAA;EACR,MAAA,GAAS,OAAA,CAAQ,gBAAA;EACjB,QAAA,EAAU,SAAA;AAAA;AAAA,iBAGI,kBAAA,CAAA;EACd,MAAA;EACA;AAAA,GACC,uBAAA,GAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCqCV,iBAAA,CAAA,GAAiB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;cC3BpB,mBAAA;;mBAoCZ,KAAA,CAAA,QAAA,CAAA,KAAA,CAAA,cAAA"}
@@ -1 +0,0 @@
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":"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"}
@@ -1 +0,0 @@
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"}
File without changes