@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
package/dist/index.mjs CHANGED
@@ -1,850 +1,7 @@
1
- import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
2
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
1
+ import "./dev-copilot-context-CA9bqV_U.mjs";
2
+ import { t as DevCopilotProvider } from "./dev-copilot-provider-D0_wEEem.mjs";
3
+ import "./app/index.mjs";
4
+ import { t as CopilotOverlayWidget } from "./copilot-overlay-ClRoIHew.mjs";
5
+ import "./widgets/copilot-overlay/index.mjs";
3
6
 
4
- //#region src/lib/config.ts
5
- const defaultConfig = {
6
- enabled: process.env.NODE_ENV === "development",
7
- allowedPaths: ["."]
8
- };
9
- const resolveDevCopilotConfig = (config) => {
10
- const nextConfig = config ?? {};
11
- return {
12
- ...defaultConfig,
13
- ...nextConfig
14
- };
15
- };
16
-
17
- //#endregion
18
- //#region src/components/dev-copilot-provider.tsx
19
- const DevCopilotContext = createContext(null);
20
- function DevCopilotProvider({ config, children }) {
21
- const resolvedConfig = resolveDevCopilotConfig(config);
22
- return /* @__PURE__ */ jsx(DevCopilotContext.Provider, {
23
- value: resolvedConfig,
24
- children
25
- });
26
- }
27
- const useDevCopilotConfig = () => {
28
- const context = useContext(DevCopilotContext);
29
- if (!context) throw new Error("DevCopilotProvider 내부에서만 사용할 수 있습니다.");
30
- return context;
31
- };
32
-
33
- //#endregion
34
- //#region src/lib/api-client.ts
35
- const API_BASE_URL = "http://127.0.0.1:3339";
36
- const parseResponse = async (response) => {
37
- const payload = await response.json();
38
- if (!response.ok) {
39
- const errorMessage = typeof payload === "object" && payload && "error" in payload ? payload.error : "요청 처리 중 오류가 발생했습니다.";
40
- throw new Error(errorMessage);
41
- }
42
- return payload;
43
- };
44
- const createCopilotApiClient = () => {
45
- const post = async (path, body) => {
46
- return parseResponse(await fetch(`${API_BASE_URL}${path}`, {
47
- method: "POST",
48
- headers: { "Content-Type": "application/json" },
49
- body: JSON.stringify(body)
50
- }));
51
- };
52
- return {
53
- status: async (agent) => {
54
- const query = agent ? `?agent=${agent}` : "";
55
- return parseResponse(await fetch(`${API_BASE_URL}/status${query}`));
56
- },
57
- chat: (payload) => post("/chat", payload),
58
- apply: (payload) => post("/apply", payload)
59
- };
60
- };
61
-
62
- //#endregion
63
- //#region src/hooks/use-selection-capture.ts
64
- const OVERLAY_ATTRIBUTE = "data-dev-copilot-overlay";
65
- const toSelectionText = () => {
66
- return window.getSelection()?.toString().trim() ?? "";
67
- };
68
- const isNodeInsideOverlay = (node) => {
69
- if (!node) return false;
70
- const element = node instanceof Element ? node : node.parentElement;
71
- return Boolean(element?.closest(`[${OVERLAY_ATTRIBUTE}]`));
72
- };
73
- const isInsideOverlay = (target) => {
74
- return target instanceof Element && Boolean(target.closest(`[${OVERLAY_ATTRIBUTE}]`));
75
- };
76
- const useSelectionCapture = () => {
77
- const [selectedText, setSelectedText] = useState("");
78
- const syncSelection = useCallback((event) => {
79
- const selection = window.getSelection();
80
- const startedInsideOverlay = isNodeInsideOverlay(selection?.anchorNode ?? null);
81
- const endedInsideOverlay = isNodeInsideOverlay(selection?.focusNode ?? null);
82
- if (isInsideOverlay(event.target) || startedInsideOverlay || endedInsideOverlay) return;
83
- const nextSelectedText = selection?.toString().trim() ?? toSelectionText();
84
- if (!nextSelectedText) return;
85
- setSelectedText(nextSelectedText);
86
- }, []);
87
- useEffect(() => {
88
- document.addEventListener("mouseup", syncSelection);
89
- document.addEventListener("keyup", syncSelection);
90
- return () => {
91
- document.removeEventListener("mouseup", syncSelection);
92
- document.removeEventListener("keyup", syncSelection);
93
- };
94
- }, [syncSelection]);
95
- return {
96
- selectedText,
97
- setSelectedText,
98
- clearSelection: () => setSelectedText("")
99
- };
100
- };
101
-
102
- //#endregion
103
- //#region src/components/icons.tsx
104
- const SparklesIcon = (props) => {
105
- return /* @__PURE__ */ jsxs("svg", {
106
- viewBox: "0 0 24 24",
107
- fill: "none",
108
- stroke: "currentColor",
109
- strokeWidth: "1.8",
110
- strokeLinecap: "round",
111
- strokeLinejoin: "round",
112
- ...props,
113
- children: [
114
- /* @__PURE__ */ jsx("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" }),
115
- /* @__PURE__ */ jsx("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" }),
116
- /* @__PURE__ */ jsx("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" })
117
- ]
118
- });
119
- };
120
- const PanelRightOpenIcon = (props) => {
121
- return /* @__PURE__ */ jsxs("svg", {
122
- viewBox: "0 0 24 24",
123
- fill: "none",
124
- stroke: "currentColor",
125
- strokeWidth: "1.8",
126
- strokeLinecap: "round",
127
- strokeLinejoin: "round",
128
- ...props,
129
- children: [
130
- /* @__PURE__ */ jsx("rect", {
131
- x: "3.75",
132
- y: "4.75",
133
- width: "16.5",
134
- height: "14.5",
135
- rx: "2.25"
136
- }),
137
- /* @__PURE__ */ jsx("path", { d: "M8.75 4.75v14.5" }),
138
- /* @__PURE__ */ jsx("path", { d: "m13 9.25 3 2.75-3 2.75" })
139
- ]
140
- });
141
- };
142
- const PanelRightCloseIcon = (props) => {
143
- return /* @__PURE__ */ jsxs("svg", {
144
- viewBox: "0 0 24 24",
145
- fill: "none",
146
- stroke: "currentColor",
147
- strokeWidth: "1.8",
148
- strokeLinecap: "round",
149
- strokeLinejoin: "round",
150
- ...props,
151
- children: [
152
- /* @__PURE__ */ jsx("rect", {
153
- x: "3.75",
154
- y: "4.75",
155
- width: "16.5",
156
- height: "14.5",
157
- rx: "2.25"
158
- }),
159
- /* @__PURE__ */ jsx("path", { d: "M15.25 4.75v14.5" }),
160
- /* @__PURE__ */ jsx("path", { d: "m11 9.25-3 2.75 3 2.75" })
161
- ]
162
- });
163
- };
164
-
165
- //#endregion
166
- //#region src/components/dev-copilot-overlay.tsx
167
- const FLOATING_BUTTON_SIZE = 48;
168
- const DRAG_CLICK_THRESHOLD = 4;
169
- const PANEL_WIDTH = "min(1028px, calc(100vw - 48px))";
170
- const INPUT_PANEL_WIDTH = 420;
171
- const RAIL_WIDTH = 36;
172
- const AGENT_LABELS = {
173
- codex: "Codex CLI",
174
- claude: "Claude Code CLI"
175
- };
176
- const UI_LABELS = {
177
- title: "Dev Copilot",
178
- subtitle: "텍스트를 선택한 뒤 프롬프트를 입력하세요.",
179
- promptPlaceholder: "무엇을 도와드릴까요?",
180
- askButton: "질문",
181
- editButton: "코드 수정 제안",
182
- applyButton: "미리보기 적용"
183
- };
184
- const styleText = `
185
- .yrdc-trigger{transition:transform 150ms ease-out, box-shadow 150ms ease-out}
186
- .yrdc-trigger:hover{transform:scale(1.05)}
187
- .yrdc-pressable{transition:transform 150ms ease-out, background-color 150ms ease-out, opacity 150ms ease-out}
188
- .yrdc-pressable:hover{transform:translateY(-1px)}
189
- .yrdc-spinner{animation:yrdc-spin 1s linear infinite}
190
- .yrdc-field:focus{outline:none;box-shadow:0 0 0 3px rgba(59,130,246,.14);border-color:#93c5fd}
191
- @keyframes yrdc-spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
192
- `;
193
- function DevCopilotOverlay() {
194
- const config = useDevCopilotConfig();
195
- const apiClient = useMemo(() => createCopilotApiClient(), []);
196
- const { selectedText, setSelectedText } = useSelectionCapture();
197
- const [open, setOpen] = useState(false);
198
- const [prompt, setPrompt] = useState("");
199
- const [busy, setBusy] = useState(false);
200
- const [error, setError] = useState(null);
201
- const [chatResult, setChatResult] = useState(null);
202
- const [toastMessage, setToastMessage] = useState(null);
203
- const [agentStatus, setAgentStatus] = useState(null);
204
- const [selectedAgent, setSelectedAgent] = useState("codex");
205
- const [position, setPosition] = useState(null);
206
- const [showResponsePanel, setShowResponsePanel] = useState(false);
207
- const containerRef = useRef(null);
208
- const suppressMainToggleClickRef = useRef(false);
209
- const dragStateRef = useRef(null);
210
- useEffect(() => {
211
- const onResize = () => {
212
- setPosition((prev) => {
213
- if (!prev) return prev;
214
- return {
215
- x: Math.min(Math.max(prev.x, 0), Math.max(0, window.innerWidth - FLOATING_BUTTON_SIZE)),
216
- y: Math.min(Math.max(prev.y, 0), Math.max(0, window.innerHeight - FLOATING_BUTTON_SIZE))
217
- };
218
- });
219
- };
220
- window.addEventListener("resize", onResize);
221
- return () => window.removeEventListener("resize", onResize);
222
- }, []);
223
- useEffect(() => {
224
- if (!open) return;
225
- let ignore = false;
226
- apiClient.status(selectedAgent).then((status) => {
227
- if (!ignore) setAgentStatus(status);
228
- }).catch((caughtError) => {
229
- if (!ignore) setAgentStatus({
230
- available: false,
231
- authenticated: false,
232
- agent: selectedAgent,
233
- message: caughtError instanceof Error ? caughtError.message : "로컬 에이전트 상태 확인에 실패했습니다."
234
- });
235
- });
236
- return () => {
237
- ignore = true;
238
- };
239
- }, [
240
- apiClient,
241
- open,
242
- selectedAgent
243
- ]);
244
- useEffect(() => {
245
- if (!open) return;
246
- const onPointerDownOutside = (event) => {
247
- const target = event.target;
248
- if (!(target instanceof Node)) return;
249
- if (containerRef.current?.contains(target)) return;
250
- setOpen(false);
251
- setShowResponsePanel(false);
252
- dragStateRef.current = null;
253
- suppressMainToggleClickRef.current = false;
254
- };
255
- document.addEventListener("pointerdown", onPointerDownOutside);
256
- return () => {
257
- document.removeEventListener("pointerdown", onPointerDownOutside);
258
- };
259
- }, [open]);
260
- if (!config.enabled) return null;
261
- const onPointerDown = (event) => {
262
- if (event.button !== 0) return;
263
- const wrapperRect = containerRef.current?.getBoundingClientRect();
264
- const originX = position?.x ?? wrapperRect?.left ?? 0;
265
- const originY = position?.y ?? wrapperRect?.top ?? 0;
266
- event.currentTarget.setPointerCapture(event.pointerId);
267
- dragStateRef.current = {
268
- pointerId: event.pointerId,
269
- startX: event.clientX,
270
- startY: event.clientY,
271
- originX,
272
- originY,
273
- moved: false
274
- };
275
- };
276
- const onPointerMove = (event) => {
277
- const dragState = dragStateRef.current;
278
- if (!dragState || dragState.pointerId !== event.pointerId) return;
279
- const deltaX = event.clientX - dragState.startX;
280
- const deltaY = event.clientY - dragState.startY;
281
- if (!(Math.abs(deltaX) > DRAG_CLICK_THRESHOLD || Math.abs(deltaY) > DRAG_CLICK_THRESHOLD) && !dragState.moved) return;
282
- dragState.moved = true;
283
- setPosition({
284
- x: Math.min(Math.max(dragState.originX + deltaX, 0), Math.max(0, window.innerWidth - FLOATING_BUTTON_SIZE)),
285
- y: Math.min(Math.max(dragState.originY + deltaY, 0), Math.max(0, window.innerHeight - FLOATING_BUTTON_SIZE))
286
- });
287
- };
288
- const onPointerEnd = (event) => {
289
- if (dragStateRef.current?.pointerId !== event.pointerId) return;
290
- suppressMainToggleClickRef.current = dragStateRef.current.moved;
291
- dragStateRef.current = null;
292
- event.currentTarget.releasePointerCapture(event.pointerId);
293
- };
294
- const onMainToggleClick = () => {
295
- if (suppressMainToggleClickRef.current) {
296
- suppressMainToggleClickRef.current = false;
297
- return;
298
- }
299
- setOpen((prev) => {
300
- const next = !prev;
301
- if (!next) {
302
- setPosition(null);
303
- dragStateRef.current = null;
304
- suppressMainToggleClickRef.current = false;
305
- }
306
- return next;
307
- });
308
- };
309
- const previousResponse = chatResult ? [`message:\n${chatResult.message}`, chatResult.patchPreview ? `patchPreview:\n${chatResult.patchPreview}` : ""].filter(Boolean).join("\n\n") : void 0;
310
- const onSubmit = async (mode) => {
311
- if (agentStatus && (!agentStatus.available || !agentStatus.authenticated)) {
312
- setError(agentStatus.message);
313
- return;
314
- }
315
- if (!prompt.trim()) {
316
- setError("프롬프트를 입력해 주세요.");
317
- return;
318
- }
319
- setBusy(true);
320
- setError(null);
321
- setShowResponsePanel(true);
322
- try {
323
- const currentRoute = typeof window !== "undefined" ? window.location.pathname : void 0;
324
- setChatResult(await apiClient.chat({
325
- selectedText,
326
- prompt,
327
- mode,
328
- context: {
329
- route: currentRoute,
330
- fileHints: config.allowedPaths,
331
- previousResponse,
332
- agent: selectedAgent
333
- }
334
- }));
335
- } catch (caughtError) {
336
- setError(caughtError instanceof Error ? caughtError.message : "요청 처리 중 오류가 발생했습니다.");
337
- } finally {
338
- setBusy(false);
339
- }
340
- };
341
- const onApply = async () => {
342
- if (!chatResult?.patchId) {
343
- setError("적용 가능한 패치가 없습니다.");
344
- return;
345
- }
346
- setBusy(true);
347
- setError(null);
348
- setShowResponsePanel(true);
349
- try {
350
- const result = await apiClient.apply({
351
- patchId: chatResult.patchId,
352
- approvalToken: `approve:${chatResult.patchId}`
353
- });
354
- if (result.applied) {
355
- setToastMessage(result.summary);
356
- window.setTimeout(() => {
357
- setToastMessage(null);
358
- }, 3e3);
359
- }
360
- } catch (caughtError) {
361
- setError(caughtError instanceof Error ? caughtError.message : "패치 적용 중 오류가 발생했습니다.");
362
- } finally {
363
- setBusy(false);
364
- }
365
- };
366
- const floatingWrapperStyle = position ? {
367
- position: "fixed",
368
- zIndex: 2147483e3,
369
- left: `${position.x}px`,
370
- top: `${position.y}px`
371
- } : {
372
- position: "fixed",
373
- right: 24,
374
- bottom: 24,
375
- zIndex: 2147483e3
376
- };
377
- const panelStyle = {
378
- position: "relative",
379
- marginTop: 12,
380
- display: "grid",
381
- gridTemplateColumns: showResponsePanel ? `${INPUT_PANEL_WIDTH}px ${RAIL_WIDTH}px minmax(0, 1fr)` : `${INPUT_PANEL_WIDTH}px ${RAIL_WIDTH}px`,
382
- width: showResponsePanel ? PANEL_WIDTH : INPUT_PANEL_WIDTH + RAIL_WIDTH,
383
- maxHeight: "calc(100vh - 96px)",
384
- overflow: "hidden",
385
- border: "1px solid #e5e7eb",
386
- borderRadius: 24,
387
- background: "#f8fafc",
388
- boxShadow: "0 18px 60px rgba(15, 23, 42, 0.16)",
389
- color: "#0f172a",
390
- fontFamily: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
391
- };
392
- return /* @__PURE__ */ jsxs(Fragment, { children: [
393
- /* @__PURE__ */ jsx("style", { children: styleText }),
394
- toastMessage ? /* @__PURE__ */ jsx("div", {
395
- style: toastStyle,
396
- children: /* @__PURE__ */ jsx("p", {
397
- "aria-live": "polite",
398
- style: { margin: 0 },
399
- children: toastMessage
400
- })
401
- }) : null,
402
- /* @__PURE__ */ jsxs("div", {
403
- ref: containerRef,
404
- style: floatingWrapperStyle,
405
- [OVERLAY_ATTRIBUTE]: "",
406
- children: [/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("button", {
407
- type: "button",
408
- className: "yrdc-trigger",
409
- style: triggerButtonStyle,
410
- onClick: onMainToggleClick,
411
- onPointerDown,
412
- onPointerMove,
413
- onPointerUp: onPointerEnd,
414
- onPointerCancel: onPointerEnd,
415
- "aria-label": "Dev Copilot 열기",
416
- title: "Dev Copilot 열기/닫기 / 드래그해서 이동",
417
- children: /* @__PURE__ */ jsx(SparklesIcon, {
418
- "aria-hidden": true,
419
- style: {
420
- width: 16,
421
- height: 16
422
- }
423
- })
424
- }) }), open ? /* @__PURE__ */ jsxs("section", {
425
- style: panelStyle,
426
- children: [
427
- /* @__PURE__ */ jsx("div", {
428
- style: railStyle,
429
- children: /* @__PURE__ */ jsx("button", {
430
- type: "button",
431
- className: "yrdc-pressable",
432
- style: railToggleStyle,
433
- onClick: () => setShowResponsePanel((prev) => !prev),
434
- "aria-label": showResponsePanel ? "응답 패널 닫기" : "응답 패널 열기",
435
- title: showResponsePanel ? "응답 패널 닫기" : "응답 패널 열기",
436
- children: showResponsePanel ? /* @__PURE__ */ jsx(PanelRightCloseIcon, {
437
- "aria-hidden": true,
438
- style: {
439
- width: 14,
440
- height: 14
441
- }
442
- }) : /* @__PURE__ */ jsx(PanelRightOpenIcon, {
443
- "aria-hidden": true,
444
- style: {
445
- width: 14,
446
- height: 14
447
- }
448
- })
449
- })
450
- }),
451
- /* @__PURE__ */ jsxs("div", {
452
- style: inputPanelStyle,
453
- children: [
454
- /* @__PURE__ */ jsxs("header", { children: [/* @__PURE__ */ jsx("p", {
455
- style: titleStyle,
456
- children: UI_LABELS.title
457
- }), /* @__PURE__ */ jsx("p", {
458
- style: subtitleStyle,
459
- children: UI_LABELS.subtitle
460
- })] }),
461
- /* @__PURE__ */ jsxs("div", {
462
- style: statusBoxStyle,
463
- children: [
464
- /* @__PURE__ */ jsxs("p", {
465
- style: statusLineStyle,
466
- children: ["로컬 에이전트: ", AGENT_LABELS[selectedAgent]]
467
- }),
468
- agentStatus?.model ? /* @__PURE__ */ jsxs("p", {
469
- style: statusLineStyle,
470
- children: ["모델: ", agentStatus.model]
471
- }) : null,
472
- agentStatus ? /* @__PURE__ */ jsxs("p", {
473
- style: {
474
- ...statusLineStyle,
475
- color: agentStatus.authenticated ? "#15803d" : "#dc2626"
476
- },
477
- children: [agentStatus.message, agentStatus.loginCommand ? ` 터미널에서 ${agentStatus.loginCommand} 실행` : ""]
478
- }) : null
479
- ]
480
- }),
481
- /* @__PURE__ */ jsx("label", {
482
- style: labelStyle,
483
- children: "에이전트"
484
- }),
485
- /* @__PURE__ */ jsx("div", {
486
- style: agentToggleRowStyle,
487
- children: ["codex", "claude"].map((agent) => {
488
- const active = selectedAgent === agent;
489
- return /* @__PURE__ */ jsx("button", {
490
- type: "button",
491
- className: "yrdc-pressable",
492
- onClick: () => setSelectedAgent(agent),
493
- disabled: busy,
494
- style: {
495
- ...agentToggleButtonStyle,
496
- background: active ? "#111827" : "#e2e8f0",
497
- color: active ? "#ffffff" : "#1e293b",
498
- opacity: busy ? .6 : 1
499
- },
500
- children: AGENT_LABELS[agent]
501
- }, agent);
502
- })
503
- }),
504
- /* @__PURE__ */ jsx("label", {
505
- style: labelStyle,
506
- children: "선택 텍스트"
507
- }),
508
- /* @__PURE__ */ jsx("textarea", {
509
- value: selectedText,
510
- onChange: (event) => setSelectedText(event.target.value),
511
- rows: 5,
512
- className: "yrdc-field",
513
- style: textareaStyle
514
- }),
515
- /* @__PURE__ */ jsx("label", {
516
- style: labelStyle,
517
- children: "프롬프트"
518
- }),
519
- /* @__PURE__ */ jsx("textarea", {
520
- value: prompt,
521
- onChange: (event) => setPrompt(event.target.value),
522
- rows: 4,
523
- placeholder: UI_LABELS.promptPlaceholder,
524
- className: "yrdc-field",
525
- style: textareaStyle
526
- }),
527
- /* @__PURE__ */ jsxs("div", {
528
- style: buttonRowStyle,
529
- children: [/* @__PURE__ */ jsx("button", {
530
- type: "button",
531
- className: "yrdc-pressable",
532
- onClick: () => onSubmit("answer"),
533
- disabled: busy || Boolean(agentStatus && !agentStatus.authenticated),
534
- style: {
535
- ...buttonStyle,
536
- background: "#111827",
537
- color: "#ffffff",
538
- opacity: busy || Boolean(agentStatus && !agentStatus.authenticated) ? .55 : 1
539
- },
540
- children: UI_LABELS.askButton
541
- }), /* @__PURE__ */ jsx("button", {
542
- type: "button",
543
- className: "yrdc-pressable",
544
- onClick: () => onSubmit("edit"),
545
- disabled: busy || Boolean(agentStatus && !agentStatus.authenticated),
546
- style: {
547
- ...buttonStyle,
548
- background: "#2563eb",
549
- color: "#ffffff",
550
- opacity: busy || Boolean(agentStatus && !agentStatus.authenticated) ? .55 : 1
551
- },
552
- children: UI_LABELS.editButton
553
- })]
554
- })
555
- ]
556
- }),
557
- showResponsePanel ? /* @__PURE__ */ jsx("aside", {
558
- style: responsePanelStyle,
559
- children: /* @__PURE__ */ jsxs("div", {
560
- style: {
561
- display: "flex",
562
- flexDirection: "column",
563
- minHeight: 320,
564
- height: "100%"
565
- },
566
- children: [/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", {
567
- style: titleStyle,
568
- children: "응답"
569
- }) }), /* @__PURE__ */ jsx("div", {
570
- style: responseCardStyle,
571
- children: busy ? /* @__PURE__ */ jsxs("div", {
572
- style: busyContainerStyle,
573
- children: [/* @__PURE__ */ jsx("span", {
574
- className: "yrdc-spinner",
575
- style: spinnerStyle
576
- }), /* @__PURE__ */ jsxs("span", { children: [AGENT_LABELS[selectedAgent], " 응답을 기다리는 중입니다."] })]
577
- }) : chatResult ? /* @__PURE__ */ jsxs("article", {
578
- style: articleStyle,
579
- children: [
580
- error ? /* @__PURE__ */ jsx("p", {
581
- style: errorBoxStyle,
582
- children: error
583
- }) : null,
584
- chatResult.warnings.length ? /* @__PURE__ */ jsx("div", {
585
- style: warningBoxStyle,
586
- children: chatResult.warnings.map((warning) => /* @__PURE__ */ jsx("p", {
587
- style: { margin: 0 },
588
- children: warning
589
- }, warning))
590
- }) : null,
591
- /* @__PURE__ */ jsx("p", {
592
- style: messageStyle,
593
- children: chatResult.message
594
- }),
595
- chatResult.patchPreview ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("pre", {
596
- style: patchPreviewStyle,
597
- children: chatResult.patchPreview
598
- }), chatResult.patchId ? /* @__PURE__ */ jsx("button", {
599
- type: "button",
600
- className: "yrdc-pressable",
601
- onClick: onApply,
602
- disabled: busy,
603
- style: {
604
- ...buttonStyle,
605
- alignSelf: "flex-start",
606
- background: "#15803d",
607
- color: "#ffffff",
608
- opacity: busy ? .55 : 1
609
- },
610
- children: UI_LABELS.applyButton
611
- }) : null] }) : null
612
- ]
613
- }) : error ? /* @__PURE__ */ jsx("p", {
614
- style: errorBoxStyle,
615
- children: error
616
- }) : /* @__PURE__ */ jsx("p", {
617
- style: placeholderStyle,
618
- children: "질문 또는 코드 수정 제안을 실행하면 이 영역에 결과가 표시됩니다."
619
- })
620
- })]
621
- })
622
- }) : null
623
- ]
624
- }) : null]
625
- })
626
- ] });
627
- }
628
- const triggerButtonStyle = {
629
- display: "flex",
630
- width: FLOATING_BUTTON_SIZE,
631
- height: FLOATING_BUTTON_SIZE,
632
- borderRadius: 9999,
633
- border: "1px solid #f2d675",
634
- background: "#fff4b8",
635
- color: "#ffb03d",
636
- alignItems: "center",
637
- justifyContent: "center",
638
- boxShadow: "0 12px 28px rgba(15, 23, 42, 0.18)",
639
- cursor: "grab"
640
- };
641
- const railStyle = {
642
- display: "flex",
643
- minHeight: 320,
644
- alignItems: "center",
645
- justifyContent: "center",
646
- borderLeft: "1px solid #e5e7eb",
647
- background: "#f8fafc"
648
- };
649
- const railToggleStyle = {
650
- display: "flex",
651
- width: 24,
652
- height: 24,
653
- border: "0",
654
- background: "transparent",
655
- color: "#64748b",
656
- cursor: "pointer",
657
- alignItems: "center",
658
- justifyContent: "center"
659
- };
660
- const inputPanelStyle = {
661
- padding: 16,
662
- minHeight: 0,
663
- overflowY: "auto",
664
- background: "#ffffff"
665
- };
666
- const responsePanelStyle = {
667
- minHeight: 0,
668
- overflow: "hidden",
669
- padding: 16,
670
- borderLeft: "1px solid #e5e7eb",
671
- background: "#f8fafc"
672
- };
673
- const titleStyle = {
674
- margin: 0,
675
- fontSize: 18,
676
- fontWeight: 700,
677
- lineHeight: 1.4,
678
- color: "#111827"
679
- };
680
- const subtitleStyle = {
681
- margin: "4px 0 0",
682
- fontSize: 14,
683
- lineHeight: 1.5,
684
- color: "#6b7280"
685
- };
686
- const statusBoxStyle = {
687
- marginTop: 12,
688
- border: "1px solid #e5e7eb",
689
- borderRadius: 16,
690
- background: "#ffffff",
691
- padding: "12px 14px",
692
- fontSize: 14,
693
- lineHeight: 1.6,
694
- color: "#6b7280"
695
- };
696
- const statusLineStyle = { margin: 0 };
697
- const labelStyle = {
698
- display: "block",
699
- marginTop: 16,
700
- fontSize: 14,
701
- lineHeight: 1.5,
702
- color: "#6b7280"
703
- };
704
- const textareaStyle = {
705
- width: "100%",
706
- resize: "vertical",
707
- borderRadius: 16,
708
- border: "1px solid #e5e7eb",
709
- background: "#ffffff",
710
- padding: "12px 14px",
711
- marginTop: 6,
712
- fontSize: 15,
713
- lineHeight: 1.7,
714
- color: "#111827",
715
- boxSizing: "border-box",
716
- minHeight: 132
717
- };
718
- const agentToggleRowStyle = {
719
- display: "flex",
720
- gap: 8,
721
- marginTop: 6
722
- };
723
- const agentToggleButtonStyle = {
724
- border: 0,
725
- borderRadius: 10,
726
- padding: "8px 12px",
727
- fontSize: 13,
728
- fontWeight: 600,
729
- lineHeight: 1.2,
730
- cursor: "pointer"
731
- };
732
- const buttonRowStyle = {
733
- display: "flex",
734
- alignItems: "center",
735
- gap: 8,
736
- marginTop: 16
737
- };
738
- const buttonStyle = {
739
- border: 0,
740
- borderRadius: 12,
741
- padding: "10px 14px",
742
- fontSize: 14,
743
- fontWeight: 600,
744
- lineHeight: 1,
745
- cursor: "pointer"
746
- };
747
- const responseCardStyle = {
748
- marginTop: 12,
749
- minHeight: 0,
750
- flex: 1,
751
- overflowY: "auto",
752
- borderRadius: 18,
753
- border: "1px solid #e5e7eb",
754
- background: "#ffffff",
755
- padding: 16
756
- };
757
- const busyContainerStyle = {
758
- display: "flex",
759
- height: "100%",
760
- minHeight: 192,
761
- alignItems: "center",
762
- justifyContent: "center",
763
- gap: 12,
764
- color: "#6b7280",
765
- fontSize: 14
766
- };
767
- const spinnerStyle = {
768
- display: "inline-block",
769
- width: 18,
770
- height: 18,
771
- borderRadius: 9999,
772
- border: "2px solid #d1d5db",
773
- borderTopColor: "#2563eb"
774
- };
775
- const articleStyle = {
776
- display: "flex",
777
- flexDirection: "column",
778
- gap: 12
779
- };
780
- const errorBoxStyle = {
781
- margin: 0,
782
- border: "1px solid #fca5a5",
783
- borderRadius: 12,
784
- background: "#fef2f2",
785
- padding: "10px 12px",
786
- fontSize: 14,
787
- lineHeight: 1.6,
788
- color: "#dc2626",
789
- whiteSpace: "pre-wrap"
790
- };
791
- const warningBoxStyle = {
792
- display: "flex",
793
- flexDirection: "column",
794
- gap: 6,
795
- border: "1px solid #fca5a5",
796
- borderRadius: 12,
797
- background: "#fef2f2",
798
- padding: "10px 12px",
799
- fontSize: 14,
800
- lineHeight: 1.6,
801
- color: "#dc2626"
802
- };
803
- const messageStyle = {
804
- margin: 0,
805
- whiteSpace: "pre-wrap",
806
- fontSize: 15,
807
- lineHeight: 1.7,
808
- color: "#111827"
809
- };
810
- const patchPreviewStyle = {
811
- margin: 0,
812
- maxHeight: 288,
813
- overflow: "auto",
814
- borderRadius: 12,
815
- border: "1px solid #e5e7eb",
816
- background: "#f8fafc",
817
- padding: 12,
818
- fontSize: 13,
819
- lineHeight: 1.6,
820
- color: "#111827",
821
- fontFamily: "ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Consolas, monospace",
822
- whiteSpace: "pre-wrap",
823
- wordBreak: "break-word"
824
- };
825
- const placeholderStyle = {
826
- margin: 0,
827
- fontSize: 14,
828
- lineHeight: 1.6,
829
- color: "#6b7280"
830
- };
831
- const toastStyle = {
832
- position: "fixed",
833
- top: 16,
834
- right: 16,
835
- zIndex: 2147483600,
836
- maxWidth: 360,
837
- borderRadius: 16,
838
- border: "1px solid #bbf7d0",
839
- background: "#f0fdf4",
840
- color: "#15803d",
841
- padding: "12px 14px",
842
- boxShadow: "0 12px 28px rgba(15, 23, 42, 0.12)",
843
- fontFamily: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
844
- fontSize: 14,
845
- lineHeight: 1.6
846
- };
847
-
848
- //#endregion
849
- export { DevCopilotOverlay, DevCopilotProvider, useSelectionCapture };
850
- //# sourceMappingURL=index.mjs.map
7
+ export { CopilotOverlayWidget as DevCopilotOverlay, DevCopilotProvider };