@monaco-ai-editor/react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,904 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ AiChatPanel: () => AiChatPanel,
34
+ EditorCoordinator: () => EditorCoordinator,
35
+ EditorPanel: () => EditorPanel,
36
+ LANGUAGES: () => import_core6.LANGUAGES,
37
+ LOCALES: () => import_core6.LOCALES,
38
+ MonacoAiEditor: () => MonacoAiEditor,
39
+ SQL_DATA_TYPES: () => import_core6.SQL_DATA_TYPES,
40
+ SQL_FUNCTIONS: () => import_core6.SQL_FUNCTIONS,
41
+ SQL_KEYWORDS: () => import_core6.SQL_KEYWORDS,
42
+ StatusBar: () => StatusBar,
43
+ THEMES: () => import_core6.THEMES,
44
+ Toolbar: () => Toolbar,
45
+ configureMonaco: () => configureMonaco,
46
+ useEditorCoordinator: () => useEditorCoordinator
47
+ });
48
+ module.exports = __toCommonJS(index_exports);
49
+
50
+ // <define:import.meta.env>
51
+ var define_import_meta_env_default = {};
52
+
53
+ // src/components/EditorPanel.tsx
54
+ var import_react3 = require("react");
55
+ var import_react4 = __toESM(require("@monaco-editor/react"), 1);
56
+ var import_core = require("@monaco-ai-editor/core");
57
+
58
+ // src/hooks/useOptionalCoordinator.ts
59
+ var import_react2 = require("react");
60
+
61
+ // src/context/internal.ts
62
+ var import_react = require("react");
63
+ var EditorCoordinatorContext = (0, import_react.createContext)(null);
64
+
65
+ // src/hooks/useOptionalCoordinator.ts
66
+ function useOptionalCoordinator() {
67
+ return (0, import_react2.useContext)(EditorCoordinatorContext);
68
+ }
69
+
70
+ // src/components/EditorPanel.tsx
71
+ var import_jsx_runtime = require("react/jsx-runtime");
72
+ var EditorPanel = ({
73
+ value,
74
+ onChange,
75
+ language,
76
+ theme,
77
+ vsPath,
78
+ sqlSchema,
79
+ builtinSqlExcludeLabels,
80
+ apiConfig: apiConfigProp,
81
+ completionProviders,
82
+ onMount,
83
+ minimap,
84
+ editorOptions,
85
+ onAiError,
86
+ className,
87
+ loading
88
+ }) => {
89
+ const coordinator = useOptionalCoordinator();
90
+ const effectiveLanguage = language ?? coordinator?.editorState.language ?? "typescript";
91
+ const effectiveTheme = theme ?? coordinator?.editorState.theme ?? "vs-dark";
92
+ const effectiveApiConfig = apiConfigProp ?? coordinator?.apiConfig ?? null;
93
+ const effectiveSqlSchema = sqlSchema ?? coordinator?.sqlSchema ?? {};
94
+ const effectiveProviders = completionProviders ?? coordinator?.completionProviders ?? [];
95
+ const controllerRef = (0, import_react3.useRef)(null);
96
+ const apiConfigRef = (0, import_react3.useRef)(effectiveApiConfig);
97
+ const pendingRef = (0, import_react3.useRef)(null);
98
+ const [aiLoading, setAiLoading] = (0, import_react3.useState)(false);
99
+ const [aiError, setAiError] = (0, import_react3.useState)(null);
100
+ const errorTimerRef = (0, import_react3.useRef)(null);
101
+ (0, import_react3.useEffect)(() => {
102
+ if (vsPath) {
103
+ import_react4.loader.config({ paths: { vs: vsPath } });
104
+ }
105
+ }, [vsPath]);
106
+ (0, import_react3.useEffect)(() => {
107
+ apiConfigRef.current = effectiveApiConfig;
108
+ }, [effectiveApiConfig]);
109
+ const showAiError = (msg) => {
110
+ if (errorTimerRef.current) clearTimeout(errorTimerRef.current);
111
+ setAiError(msg);
112
+ onAiError?.(msg);
113
+ errorTimerRef.current = setTimeout(() => setAiError(null), 4e3);
114
+ };
115
+ const schemaRef = (0, import_react3.useRef)(effectiveSqlSchema);
116
+ (0, import_react3.useEffect)(() => {
117
+ schemaRef.current = effectiveSqlSchema;
118
+ }, [effectiveSqlSchema]);
119
+ const excludeLabelsRef = (0, import_react3.useRef)(
120
+ new Set((builtinSqlExcludeLabels ?? []).map((l) => l.toUpperCase()))
121
+ );
122
+ (0, import_react3.useEffect)(() => {
123
+ excludeLabelsRef.current = new Set((builtinSqlExcludeLabels ?? []).map((l) => l.toUpperCase()));
124
+ }, [builtinSqlExcludeLabels]);
125
+ const handleBeforeMount = (monaco) => {
126
+ window.__monaco_ai_monaco = monaco;
127
+ };
128
+ const handleMount = (editor, monaco) => {
129
+ (0, import_core.registerSqlCompletion)(monaco, schemaRef, excludeLabelsRef);
130
+ (0, import_core.registerAiInlineCompletion)(monaco, pendingRef);
131
+ for (const provider of effectiveProviders) {
132
+ const langs = provider.languages ?? ["*"];
133
+ for (const lang of langs) {
134
+ monaco.languages.registerCompletionItemProvider(lang, {
135
+ triggerCharacters: provider.triggerCharacters,
136
+ provideCompletionItems: async (model, position, context) => {
137
+ const ctx = {
138
+ monaco,
139
+ model,
140
+ position,
141
+ lineText: model.getLineContent(position.lineNumber),
142
+ currentWord: model.getWordUntilPosition(position).word,
143
+ fullText: model.getValue(),
144
+ triggerCharacter: context.triggerCharacter
145
+ };
146
+ if (provider.shouldTrigger && !provider.shouldTrigger(ctx)) {
147
+ return { suggestions: [] };
148
+ }
149
+ return { suggestions: await provider.provide(ctx) };
150
+ }
151
+ });
152
+ }
153
+ }
154
+ (0, import_core.registerAiCompletionCommand)(
155
+ editor,
156
+ () => apiConfigRef.current,
157
+ pendingRef,
158
+ setAiLoading,
159
+ showAiError
160
+ );
161
+ const controller = createControllerFromEditor(editor, monaco);
162
+ controllerRef.current = controller;
163
+ if (coordinator) {
164
+ coordinator.setEditor(controller);
165
+ coordinator.bus.registerEditor(controller);
166
+ editor.onDidChangeCursorPosition((e) => {
167
+ coordinator.patchEditorState({
168
+ cursorLine: e.position.lineNumber,
169
+ cursorColumn: e.position.column
170
+ });
171
+ });
172
+ editor.onDidChangeModelContent(() => {
173
+ coordinator.patchEditorState({ value: editor.getValue() });
174
+ });
175
+ }
176
+ onMount?.(controller);
177
+ };
178
+ (0, import_react3.useEffect)(() => {
179
+ return () => {
180
+ if (errorTimerRef.current) clearTimeout(errorTimerRef.current);
181
+ if (coordinator && controllerRef.current) {
182
+ coordinator.setEditor(null);
183
+ }
184
+ };
185
+ }, []);
186
+ const mergedOptions = (0, import_react3.useMemo)(
187
+ () => {
188
+ const defaultMinimap = {
189
+ enabled: true,
190
+ side: "right",
191
+ showSlider: "mouseover",
192
+ renderCharacters: true,
193
+ maxColumn: 120
194
+ };
195
+ const minimapFromProp = typeof minimap === "boolean" ? { enabled: minimap } : minimap;
196
+ const mergedMinimap = {
197
+ ...defaultMinimap,
198
+ ...minimapFromProp,
199
+ ...editorOptions?.minimap
200
+ };
201
+ return {
202
+ fontSize: 14,
203
+ scrollBeyondLastLine: false,
204
+ automaticLayout: true,
205
+ // 让 suggest/hover/find 等溢出浮层以 fixed 定位渲染到 body 层级,
206
+ // 避免被祖先的 overflow:hidden 裁剪(如 tooltip 贴边被遮挡)
207
+ fixedOverflowWidgets: true,
208
+ lineNumbers: "on",
209
+ renderLineHighlight: "all",
210
+ smoothScrolling: true,
211
+ cursorBlinking: "smooth",
212
+ bracketPairColorization: { enabled: true },
213
+ tabSize: 2,
214
+ wordWrap: "on",
215
+ folding: true,
216
+ formatOnPaste: true,
217
+ formatOnType: false,
218
+ suggestOnTriggerCharacters: true,
219
+ quickSuggestions: { other: true, comments: false, strings: false },
220
+ acceptSuggestionOnCommitCharacter: true,
221
+ acceptSuggestionOnEnter: "on",
222
+ inlineSuggest: { enabled: true },
223
+ tabCompletion: "on",
224
+ ...editorOptions,
225
+ minimap: mergedMinimap
226
+ };
227
+ },
228
+ [minimap, editorOptions]
229
+ );
230
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, style: { position: "relative", flex: 1, height: "100%" }, children: [
231
+ aiLoading && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mae-ai-loading", style: loadingStyle, children: [
232
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mae-spinner", style: spinnerStyle }),
233
+ " AI \u8865\u5168\u4E2D\u2026"
234
+ ] }),
235
+ aiError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { onClick: () => setAiError(null), style: errorStyle, title: "\u70B9\u51FB\u5173\u95ED", children: aiError }),
236
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
237
+ import_react4.default,
238
+ {
239
+ height: "100%",
240
+ language: effectiveLanguage,
241
+ theme: effectiveTheme,
242
+ value,
243
+ loading,
244
+ onChange: (val) => onChange?.(val ?? ""),
245
+ beforeMount: handleBeforeMount,
246
+ onMount: handleMount,
247
+ options: mergedOptions
248
+ }
249
+ )
250
+ ] });
251
+ };
252
+ function createControllerFromEditor(editor, monaco) {
253
+ const fake = Object.create(import_core.EditorController.prototype);
254
+ fake.editor = editor;
255
+ fake.monaco = monaco;
256
+ fake.disposables = [];
257
+ fake.pendingCompletionRef = { current: null };
258
+ fake.customProviders = [];
259
+ fake.listeners = {};
260
+ return fake;
261
+ }
262
+ var loadingStyle = {
263
+ position: "absolute",
264
+ bottom: 32,
265
+ right: 16,
266
+ zIndex: 10,
267
+ display: "flex",
268
+ alignItems: "center",
269
+ gap: 6,
270
+ borderRadius: 9999,
271
+ border: "1px solid rgba(59,130,246,0.3)",
272
+ background: "rgba(17,24,39,0.9)",
273
+ padding: "4px 12px",
274
+ fontSize: 12,
275
+ color: "#60a5fa"
276
+ };
277
+ var spinnerStyle = {
278
+ display: "inline-block",
279
+ width: 12,
280
+ height: 12,
281
+ border: "2px solid rgba(96,165,250,0.3)",
282
+ borderTopColor: "#60a5fa",
283
+ borderRadius: "50%",
284
+ animation: "mae-spin 0.8s linear infinite"
285
+ };
286
+ var errorStyle = {
287
+ position: "absolute",
288
+ bottom: 32,
289
+ right: 16,
290
+ zIndex: 10,
291
+ maxWidth: 320,
292
+ cursor: "pointer",
293
+ borderRadius: 8,
294
+ border: "1px solid rgba(239,68,68,0.4)",
295
+ background: "rgba(17,24,39,0.95)",
296
+ padding: "8px 12px",
297
+ fontSize: 12,
298
+ color: "#f87171",
299
+ lineHeight: 1.5
300
+ };
301
+
302
+ // src/components/AiChatPanel.tsx
303
+ var import_react5 = require("react");
304
+ var import_react6 = require("@monaco-editor/react");
305
+ var import_core2 = require("@monaco-ai-editor/core");
306
+ var import_jsx_runtime2 = require("react/jsx-runtime");
307
+ function parseContent(raw, isStreaming) {
308
+ const parts = [];
309
+ const blockRe = /```(\w*)\n?([\s\S]*?)```/g;
310
+ let last = 0;
311
+ let m;
312
+ while ((m = blockRe.exec(raw)) !== null) {
313
+ if (m.index > last) parts.push({ type: "text", content: raw.slice(last, m.index) });
314
+ parts.push({ type: "code", lang: m[1] || "code", content: m[2].trimEnd() });
315
+ last = m.index + m[0].length;
316
+ }
317
+ const remaining = raw.slice(last);
318
+ if (remaining) {
319
+ const idx = remaining.indexOf("```");
320
+ if (idx !== -1) {
321
+ if (idx > 0) parts.push({ type: "text", content: remaining.slice(0, idx) });
322
+ const block = remaining.slice(idx + 3);
323
+ const lm = block.match(/^(\w*)\n?/);
324
+ parts.push({ type: "code", lang: lm?.[1] ?? "", content: block.slice(lm?.[0]?.length ?? 0) + (isStreaming ? "\u258B" : "") });
325
+ } else {
326
+ parts.push({ type: "text", content: remaining + (isStreaming ? "\u258B" : "") });
327
+ }
328
+ } else if (isStreaming && raw.length > 0 && !raw.endsWith("```")) {
329
+ parts.push({ type: "text", content: "\u258B" });
330
+ }
331
+ return parts;
332
+ }
333
+ var MessageContent = ({ content, isStreaming, onInsertCode, onShowDiff }) => {
334
+ const parts = parseContent(content, isStreaming);
335
+ if (isStreaming && content === "") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { animation: "pulse 1s infinite", color: "#9ca3af" }, children: "\u258B" });
336
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: parts.map(
337
+ (p, i) => p.type === "code" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { margin: "8px 0", borderRadius: 8, overflow: "hidden", border: "1px solid rgb(75,85,99)" }, children: [
338
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "4px 12px", background: "rgb(55,65,71)" }, children: [
339
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 11, color: "rgb(156,163,175)" }, children: p.lang }),
340
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
341
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => navigator.clipboard.writeText(p.content), style: codeBtnStyle, children: "\u590D\u5236" }),
342
+ onShowDiff && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => onShowDiff(p.content, p.lang), style: { ...codeBtnStyle, color: "#fbbf24" }, children: "\u5DEE\u5F02" }),
343
+ onInsertCode && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => onInsertCode(p.content), style: { ...codeBtnStyle, color: "#60a5fa" }, children: "\u63D2\u5165" })
344
+ ] })
345
+ ] }),
346
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { style: { margin: 0, padding: 12, overflowX: "auto", background: "rgb(3,7,18)", fontSize: 12, lineHeight: 1.6, color: "rgb(229,231,235)" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { children: p.content }) })
347
+ ] }, i) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { whiteSpace: "pre-wrap", lineHeight: 1.6 }, children: p.content }, i)
348
+ ) });
349
+ };
350
+ var codeBtnStyle = {
351
+ fontSize: 11,
352
+ color: "rgb(156,163,175)",
353
+ background: "transparent",
354
+ border: "none",
355
+ cursor: "pointer",
356
+ padding: 0
357
+ };
358
+ var MIN_WIDTH = 260;
359
+ var MAX_WIDTH = 720;
360
+ var AiChatPanel = (props) => {
361
+ const coordinator = useOptionalCoordinator();
362
+ const [width, setWidth] = (0, import_react5.useState)(props.defaultWidth ?? 320);
363
+ const [messages, setMessages] = (0, import_react5.useState)([]);
364
+ const [input, setInput] = (0, import_react5.useState)("");
365
+ const [loading, setLoading] = (0, import_react5.useState)(false);
366
+ const [showSettings, setShowSettings] = (0, import_react5.useState)(false);
367
+ const [configDraft, setConfigDraft] = (0, import_react5.useState)(props.apiConfig ?? coordinator?.apiConfig ?? { baseUrl: "", apiKey: "", model: "" });
368
+ const [diffState, setDiffState] = (0, import_react5.useState)(null);
369
+ const messagesEndRef = (0, import_react5.useRef)(null);
370
+ const abortRef = (0, import_react5.useRef)(null);
371
+ const ctrlRef = (0, import_react5.useRef)(null);
372
+ const isDragging = (0, import_react5.useRef)(false);
373
+ const dragStartX = (0, import_react5.useRef)(0);
374
+ const dragStartW = (0, import_react5.useRef)(0);
375
+ const editorContent = props.editorContent ?? coordinator?.editor?.getValue() ?? "";
376
+ const language = props.language ?? coordinator?.editorState.language;
377
+ const effectiveApiConfig = props.apiConfig ?? coordinator?.apiConfig ?? configDraft;
378
+ (0, import_react5.useEffect)(() => {
379
+ const ctrl = new import_core2.AiChatController(effectiveApiConfig);
380
+ ctrlRef.current = ctrl;
381
+ const offAdd = ctrl.on("messageAdded", (msg) => setMessages((prev) => [...prev, msg]));
382
+ const offUpd = ctrl.on("messageUpdated", (msg) => setMessages((prev) => prev.map((m) => m.id === msg.id ? msg : m)));
383
+ const offClear = ctrl.on("cleared", () => setMessages([]));
384
+ const offLoad = ctrl.on("loadingChange", ({ loading: l }) => setLoading(l));
385
+ if (coordinator) coordinator.setChat(ctrl);
386
+ return () => {
387
+ offAdd();
388
+ offUpd();
389
+ offClear();
390
+ offLoad();
391
+ ctrl.dispose();
392
+ };
393
+ }, []);
394
+ (0, import_react5.useEffect)(() => {
395
+ if (ctrlRef.current) ctrlRef.current.setApiConfig(effectiveApiConfig);
396
+ setConfigDraft(effectiveApiConfig);
397
+ }, [effectiveApiConfig]);
398
+ (0, import_react5.useEffect)(() => {
399
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
400
+ }, [messages]);
401
+ const handleSend = (0, import_react5.useCallback)(() => {
402
+ ctrlRef.current?.send(input, { editorContent, language });
403
+ setInput("");
404
+ }, [input, editorContent, language]);
405
+ const handleKeyDown = (e) => {
406
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
407
+ e.preventDefault();
408
+ handleSend();
409
+ }
410
+ };
411
+ const handleStop = () => ctrlRef.current?.stop();
412
+ const handleClear = () => ctrlRef.current?.clear();
413
+ const handleSaveConfig = () => {
414
+ if (coordinator?.onApiConfigChange) {
415
+ coordinator.onApiConfigChange(configDraft);
416
+ }
417
+ if (props.onApiConfigChange) {
418
+ props.onApiConfigChange(configDraft);
419
+ }
420
+ setShowSettings(false);
421
+ };
422
+ const handleAddEditorContext = () => {
423
+ if (!editorContent) return;
424
+ const snippet = `\u4EE5\u4E0B\u662F\u5F53\u524D\u7F16\u8F91\u5668\u4E2D\u7684${language ? ` ${language} ` : ""}\u4EE3\u7801\uFF1A
425
+ \`\`\`${language}
426
+ ${editorContent}
427
+ \`\`\``;
428
+ setInput((prev) => prev.trim() ? `${prev}
429
+
430
+ ${snippet}` : snippet);
431
+ };
432
+ const handleInsert = props.onInsertCode ? props.onInsertCode : (code) => coordinator?.bus?.insertToEditor(code);
433
+ const handleReplace = props.onReplaceCode ? props.onReplaceCode : (code) => coordinator?.bus?.replaceEditor(code);
434
+ const handleShowDiff = (0, import_react5.useCallback)((aiCode, codeLang) => {
435
+ setDiffState({ original: editorContent ?? "", modified: aiCode, language: codeLang || language || "plaintext" });
436
+ }, [editorContent, language]);
437
+ const handleApplyDiff = () => {
438
+ if (!diffState) return;
439
+ if (handleReplace) handleReplace(diffState.modified);
440
+ else if (handleInsert) handleInsert(diffState.modified);
441
+ setDiffState(null);
442
+ };
443
+ const handleResizeMouseDown = (e) => {
444
+ e.preventDefault();
445
+ isDragging.current = true;
446
+ dragStartX.current = e.clientX;
447
+ dragStartW.current = width;
448
+ const onMove = (ev) => {
449
+ const next = Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, dragStartW.current + (dragStartX.current - ev.clientX)));
450
+ setWidth(next);
451
+ };
452
+ const onUp = () => {
453
+ isDragging.current = false;
454
+ document.removeEventListener("mousemove", onMove);
455
+ document.removeEventListener("mouseup", onUp);
456
+ document.body.style.cursor = "";
457
+ };
458
+ document.body.style.cursor = "col-resize";
459
+ document.addEventListener("mousemove", onMove);
460
+ document.addEventListener("mouseup", onUp);
461
+ };
462
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "flex", flexDirection: "column", borderLeft: "1px solid rgb(55,65,81)", background: "rgb(17,24,39)", width, height: "100%" }, children: [
463
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { onMouseDown: handleResizeMouseDown, style: { position: "absolute", left: 0, top: 0, width: 4, height: "100%", cursor: "col-resize", zIndex: 10 } }),
464
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "8px 12px", borderBottom: "1px solid rgb(55,65,81)" }, children: [
465
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { style: { width: 16, height: 16, color: "#60a5fa", marginRight: 8 }, viewBox: "0 0 20 20", fill: "currentColor", children: [
466
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2 5a2 2 0 012-2h7a2 2 0 012 2v4a2 2 0 01-2 2H9l-3 3v-3H4a2 2 0 01-2-2V5z" }),
467
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M15 7v2a4 4 0 01-4 4H9.828l-1.766 1.767c.28.149.599.233.938.233h2l3 3v-3h2a2 2 0 002-2V9a2 2 0 00-2-2h-1z" })
468
+ ] }),
469
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1, fontSize: 13, fontWeight: 500, color: "#fff" }, children: "AI \u5BF9\u8BDD" }),
470
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => {
471
+ setConfigDraft(effectiveApiConfig);
472
+ setShowSettings((v) => !v);
473
+ }, style: { ...iconBtnStyle, color: showSettings ? "#60a5fa" : "#9ca3af" }, title: "\u8BBE\u7F6E", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { style: { width: 16, height: 16 }, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
474
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" }),
475
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "3" })
476
+ ] }) }),
477
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: handleClear, style: iconBtnStyle, title: "\u6E05\u7A7A", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { style: { width: 16, height: 16 }, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }) }),
478
+ props.onClose && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: props.onClose, style: iconBtnStyle, title: "\u5173\u95ED", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { style: { width: 16, height: 16 }, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
479
+ ] }),
480
+ showSettings && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: 12, borderBottom: "1px solid rgb(55,65,81)", background: "rgb(31,41,55)" }, children: [
481
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 11, fontWeight: 600, color: "#d1d5db", marginBottom: 12 }, children: "API \u914D\u7F6E" }),
482
+ ["baseUrl", "apiKey", "model"].map((field) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
483
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: { display: "block", fontSize: 11, color: "#9ca3af", marginBottom: 4 }, children: field === "baseUrl" ? "Base URL" : field === "apiKey" ? "API Key" : "\u6A21\u578B" }),
484
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
485
+ "input",
486
+ {
487
+ type: field === "apiKey" ? "password" : "text",
488
+ value: configDraft[field],
489
+ onChange: (e) => setConfigDraft((p) => ({ ...p, [field]: e.target.value })),
490
+ placeholder: field === "baseUrl" ? "https://api.openai.com/v1" : field === "model" ? "gpt-4o-mini" : "",
491
+ style: inputStyle
492
+ }
493
+ )
494
+ ] }, field)),
495
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8, marginTop: 12 }, children: [
496
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: handleSaveConfig, style: { flex: 1, padding: "6px 0", fontSize: 12, background: "rgb(37,99,235)", color: "#fff", border: "none", borderRadius: 4, cursor: "pointer" }, children: "\u4FDD\u5B58" }),
497
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => setShowSettings(false), style: { flex: 1, padding: "6px 0", fontSize: 12, background: "rgb(75,85,99)", color: "#fff", border: "none", borderRadius: 4, cursor: "pointer" }, children: "\u53D6\u6D88" })
498
+ ] })
499
+ ] }),
500
+ diffState && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", background: "rgb(17,24,39)" }, children: [
501
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: "4px 8px", borderBottom: "1px solid rgb(55,65,81)", background: "rgb(31,41,55)", display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
502
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 12, color: "#fff" }, children: "Diff \u5BF9\u6BD4" }),
503
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
504
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: handleApplyDiff, style: { fontSize: 11, color: "#60a5fa", background: "transparent", border: "none", cursor: "pointer" }, children: "\u5E94\u7528\u66F4\u6539" }),
505
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => setDiffState(null), style: { fontSize: 11, color: "#9ca3af", background: "transparent", border: "none", cursor: "pointer" }, children: "\u5173\u95ED" })
506
+ ] })
507
+ ] }),
508
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
509
+ import_react6.DiffEditor,
510
+ {
511
+ height: "100%",
512
+ language: diffState.language,
513
+ original: diffState.original,
514
+ modified: diffState.modified,
515
+ theme: "vs-dark"
516
+ }
517
+ )
518
+ ] }),
519
+ !diffState && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { flex: 1, overflowY: "auto", padding: 12 }, children: [
520
+ messages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", height: "100%", flexDirection: "column", alignItems: "center", justifyContent: "center", textAlign: "center" }, children: [
521
+ !effectiveApiConfig.apiKey.trim() && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { width: "100%", marginBottom: 16, padding: "8px 12px", borderRadius: 8, border: "1px solid rgba(250,204,21,0.4)", background: "rgba(250,204,21,0.1)", textAlign: "left" }, children: [
522
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { marginBottom: 4, fontSize: 11, fontWeight: 600, color: "#fbbf24" }, children: "\u26A0\uFE0F \u672A\u914D\u7F6E API Key" }),
523
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: 11, color: "rgba(251,191,36,0.8)", lineHeight: 1.5 }, children: "\u8BF7\u70B9\u51FB\u53F3\u4E0A\u89D2 \u2699\uFE0F \u6309\u94AE\u586B\u5199\u914D\u7F6E\u540E\u5F00\u59CB\u5BF9\u8BDD" })
524
+ ] }),
525
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { style: { width: 40, height: 40, color: "rgb(75,85,99)", marginBottom: 12 }, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" }) }),
526
+ !loading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: 12, color: "#6b7280" }, children: "\u5F00\u59CB\u4F60\u7684 AI \u7F16\u7A0B\u5BF9\u8BDD\u5427" })
527
+ ] }),
528
+ messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { marginBottom: 12, display: "flex", flexDirection: "column", alignItems: msg.role === "user" ? "flex-end" : "flex-start" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { maxWidth: "90%", padding: "8px 12px", borderRadius: 8, fontSize: 12, color: "#e5e7eb", background: msg.role === "user" ? "rgb(55,65,81)" : "rgb(31,41,55)", lineHeight: 1.5 }, children: msg.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MessageContent, { content: msg.content, isStreaming: msg.isStreaming, onInsertCode: handleInsert, onShowDiff: handleShowDiff }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { whiteSpace: "pre-wrap" }, children: msg.content }) }) }, msg.id)),
529
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: messagesEndRef })
530
+ ] }),
531
+ !diffState && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: "8px 12px", borderTop: "1px solid rgb(55,65,81)" }, children: [
532
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: 4, marginBottom: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: handleAddEditorContext, style: { fontSize: 11, color: "#9ca3af", background: "transparent", border: "none", cursor: "pointer" }, title: "\u5F15\u7528\u7F16\u8F91\u5668\u4EE3\u7801", children: "+ \u5F15\u7528\u4EE3\u7801" }) }),
533
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
534
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
535
+ "textarea",
536
+ {
537
+ value: input,
538
+ onChange: (e) => setInput(e.target.value),
539
+ onKeyDown: handleKeyDown,
540
+ placeholder: "\u8F93\u5165\u6D88\u606F\uFF0CCtrl+Enter \u53D1\u9001...",
541
+ style: { flex: 1, padding: "6px 8px", fontSize: 12, background: "rgb(31,41,55)", color: "#e5e7eb", border: "1px solid rgb(75,85,99)", borderRadius: 4, outline: "none", resize: "none", minHeight: 32 },
542
+ rows: 2
543
+ }
544
+ ),
545
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: handleStop, style: { padding: "6px 12px", fontSize: 12, background: "rgb(220,38,38)", color: "#fff", border: "none", borderRadius: 4, cursor: "pointer", whiteSpace: "nowrap" }, children: "\u505C\u6B62" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: handleSend, style: { padding: "6px 12px", fontSize: 12, background: "rgb(37,99,235)", color: "#fff", border: "none", borderRadius: 4, cursor: "pointer", whiteSpace: "nowrap" }, children: "\u53D1\u9001" })
546
+ ] })
547
+ ] })
548
+ ] });
549
+ };
550
+ var iconBtnStyle = {
551
+ padding: 4,
552
+ color: "#9ca3af",
553
+ background: "transparent",
554
+ border: "none",
555
+ cursor: "pointer",
556
+ display: "flex",
557
+ borderRadius: 4
558
+ };
559
+ var inputStyle = {
560
+ width: "100%",
561
+ padding: "4px 8px",
562
+ fontSize: 12,
563
+ background: "rgb(55,65,81)",
564
+ color: "rgb(229,231,235)",
565
+ border: "1px solid rgb(75,85,99)",
566
+ borderRadius: 4,
567
+ outline: "none",
568
+ marginBottom: 8,
569
+ boxSizing: "border-box"
570
+ };
571
+
572
+ // src/components/Toolbar.tsx
573
+ var import_core3 = require("@monaco-ai-editor/core");
574
+ var import_jsx_runtime3 = require("react/jsx-runtime");
575
+ var Toolbar = ({
576
+ language,
577
+ theme,
578
+ onLanguageChange,
579
+ onThemeChange,
580
+ onFormat,
581
+ onToggleAiChat,
582
+ aiChatVisible,
583
+ className
584
+ }) => {
585
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
586
+ "div",
587
+ {
588
+ className,
589
+ style: toolbarStyle,
590
+ children: [
591
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: labelStyle, children: "\u8BED\u8A00" }),
592
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
593
+ "select",
594
+ {
595
+ value: language ?? "typescript",
596
+ onChange: (e) => onLanguageChange?.(e.target.value),
597
+ style: selectStyle,
598
+ children: import_core3.LANGUAGES.map((lang) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: lang, children: lang }, lang))
599
+ }
600
+ ),
601
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...labelStyle, marginLeft: 16 }, children: "\u4E3B\u9898" }),
602
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
603
+ "select",
604
+ {
605
+ value: theme ?? "vs-dark",
606
+ onChange: (e) => onThemeChange?.(e.target.value),
607
+ style: selectStyle,
608
+ children: import_core3.THEMES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: t.value, children: t.label }, t.value))
609
+ }
610
+ ),
611
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 } }),
612
+ onToggleAiChat && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
613
+ "button",
614
+ {
615
+ onClick: onToggleAiChat,
616
+ style: {
617
+ ...buttonStyle,
618
+ background: aiChatVisible ? "rgb(37,99,235)" : "rgb(55,65,81)"
619
+ },
620
+ children: [
621
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
622
+ "svg",
623
+ {
624
+ style: { width: 16, height: 16, marginRight: 4 },
625
+ viewBox: "0 0 20 20",
626
+ fill: "currentColor",
627
+ children: [
628
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M2 5a2 2 0 012-2h7a2 2 0 012 2v4a2 2 0 01-2 2H9l-3 3v-3H4a2 2 0 01-2-2V5z" }),
629
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M15 7v2a4 4 0 01-4 4H9.828l-1.766 1.767c.28.149.599.233.938.233h2l3 3v-3h2a2 2 0 002-2V9a2 2 0 00-2-2h-1z" })
630
+ ]
631
+ }
632
+ ),
633
+ "AI"
634
+ ]
635
+ }
636
+ ),
637
+ onFormat && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { onClick: onFormat, style: { ...buttonStyle, marginLeft: 8 }, children: "\u683C\u5F0F\u5316" })
638
+ ]
639
+ }
640
+ );
641
+ };
642
+ var toolbarStyle = {
643
+ display: "flex",
644
+ alignItems: "center",
645
+ padding: "8px 16px",
646
+ background: "rgb(31,41,55)",
647
+ borderBottom: "1px solid rgb(55,65,81)"
648
+ };
649
+ var labelStyle = {
650
+ fontSize: 13,
651
+ color: "rgb(156,163,175)"
652
+ };
653
+ var selectStyle = {
654
+ marginLeft: 8,
655
+ padding: "4px 8px",
656
+ fontSize: 13,
657
+ background: "rgb(55,65,81)",
658
+ color: "rgb(229,231,235)",
659
+ border: "1px solid rgb(75,85,99)",
660
+ borderRadius: 4,
661
+ outline: "none"
662
+ };
663
+ var buttonStyle = {
664
+ padding: "4px 12px",
665
+ fontSize: 13,
666
+ color: "#fff",
667
+ background: "rgb(55,65,81)",
668
+ border: "none",
669
+ borderRadius: 4,
670
+ cursor: "pointer",
671
+ display: "flex",
672
+ alignItems: "center"
673
+ };
674
+
675
+ // src/components/StatusBar.tsx
676
+ var import_jsx_runtime4 = require("react/jsx-runtime");
677
+ var StatusBar = ({
678
+ language,
679
+ lineCount = 0,
680
+ charCount = 0,
681
+ cursorLine = 1,
682
+ cursorColumn = 1,
683
+ className
684
+ }) => {
685
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className, style: statusBarStyle, children: [
686
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: itemStyle, children: [
687
+ "Ln ",
688
+ cursorLine,
689
+ ", Col ",
690
+ cursorColumn
691
+ ] }),
692
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: dividerStyle, children: "|" }),
693
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: itemStyle, children: [
694
+ lineCount,
695
+ " \u884C"
696
+ ] }),
697
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: dividerStyle, children: "|" }),
698
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: itemStyle, children: [
699
+ charCount,
700
+ " \u5B57\u7B26"
701
+ ] }),
702
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { flex: 1 } }),
703
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: itemStyle, children: language?.toUpperCase() ?? "" }),
704
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: dividerStyle, children: "|" }),
705
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: itemStyle, children: "UTF-8" })
706
+ ] });
707
+ };
708
+ var statusBarStyle = {
709
+ display: "flex",
710
+ alignItems: "center",
711
+ gap: 12,
712
+ padding: "0 16px",
713
+ height: 22,
714
+ fontSize: 11,
715
+ color: "#fff",
716
+ background: "rgb(29,78,216)"
717
+ };
718
+ var itemStyle = {
719
+ display: "flex",
720
+ alignItems: "center"
721
+ };
722
+ var dividerStyle = {
723
+ color: "rgba(255,255,255,0.5)"
724
+ };
725
+
726
+ // src/components/MonacoAiEditor.tsx
727
+ var import_react8 = require("react");
728
+
729
+ // src/context/EditorCoordinator.tsx
730
+ var import_react7 = require("react");
731
+ var import_core4 = require("@monaco-ai-editor/core");
732
+ var import_jsx_runtime5 = require("react/jsx-runtime");
733
+ function EditorCoordinator({
734
+ children,
735
+ language: initialLang,
736
+ theme: initialTheme,
737
+ apiConfig: initialApiConfig,
738
+ sqlSchema,
739
+ completionProviders = [],
740
+ onApiConfigChange
741
+ }) {
742
+ const busRef = (0, import_react7.useRef)(new import_core4.EditorBus());
743
+ const [editor, setEditor] = (0, import_react7.useState)(null);
744
+ const [chat, setChat] = (0, import_react7.useState)(null);
745
+ const [editorState, setEditorState] = (0, import_react7.useState)({
746
+ value: "",
747
+ language: initialLang ?? "typescript",
748
+ theme: initialTheme ?? "vs-dark",
749
+ cursorLine: 1,
750
+ cursorColumn: 1
751
+ });
752
+ const patchEditorState = (0, import_react7.useCallback)((patch) => {
753
+ setEditorState((prev) => ({ ...prev, ...patch }));
754
+ }, []);
755
+ const value = (0, import_react7.useMemo)(
756
+ () => ({
757
+ editor,
758
+ chat,
759
+ editorState,
760
+ patchEditorState,
761
+ setEditor,
762
+ setChat,
763
+ bus: busRef.current,
764
+ apiConfig: initialApiConfig ?? null,
765
+ sqlSchema: sqlSchema ?? {},
766
+ completionProviders,
767
+ onApiConfigChange
768
+ }),
769
+ [editor, chat, editorState, patchEditorState, initialApiConfig, sqlSchema, completionProviders, onApiConfigChange]
770
+ );
771
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EditorCoordinatorContext.Provider, { value, children });
772
+ }
773
+ function useEditorCoordinator() {
774
+ const ctx = (0, import_react7.useContext)(EditorCoordinatorContext);
775
+ if (!ctx) throw new Error("useEditorCoordinator must be used within <EditorCoordinator>");
776
+ return ctx;
777
+ }
778
+
779
+ // src/components/MonacoAiEditor.tsx
780
+ var import_jsx_runtime6 = require("react/jsx-runtime");
781
+ var MonacoAiEditor = ({
782
+ language = "typescript",
783
+ theme = "vs-dark",
784
+ apiConfig,
785
+ onApiConfigChange,
786
+ sqlSchema,
787
+ completionProviders,
788
+ showAiChat: showAiChatProp = true,
789
+ ...rest
790
+ }) => {
791
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
792
+ EditorCoordinator,
793
+ {
794
+ language,
795
+ theme,
796
+ apiConfig,
797
+ sqlSchema,
798
+ completionProviders,
799
+ onApiConfigChange,
800
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MonacoAiEditorInner, { ...rest, showAiChat: showAiChatProp })
801
+ }
802
+ );
803
+ };
804
+ var MonacoAiEditorInner = ({ value, onChange, vsPath, showToolbar = true, showStatusBar = true, showAiChat = true, className }) => {
805
+ const coordinator = useEditorCoordinator();
806
+ const [aiVisible, setAiVisible] = (0, import_react8.useState)(showAiChat);
807
+ const onLangChange = (0, import_react8.useCallback)((lang) => {
808
+ coordinator.editor?.setLanguage(lang);
809
+ coordinator.patchEditorState({ language: lang });
810
+ }, [coordinator]);
811
+ const onThemeChange = (0, import_react8.useCallback)((theme) => {
812
+ coordinator.editor?.setTheme(theme);
813
+ coordinator.patchEditorState({ theme });
814
+ }, [coordinator]);
815
+ const onFormat = (0, import_react8.useCallback)(() => coordinator.editor?.format(), [coordinator]);
816
+ const onEditorMount = (0, import_react8.useCallback)((controller) => {
817
+ coordinator.setEditor(controller);
818
+ }, [coordinator]);
819
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
820
+ "div",
821
+ {
822
+ className,
823
+ style: { display: "flex", flexDirection: "column", height: "100%", background: "rgb(17,24,39)" },
824
+ children: [
825
+ showToolbar && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
826
+ Toolbar,
827
+ {
828
+ language: coordinator.editorState.language,
829
+ theme: coordinator.editorState.theme,
830
+ onLanguageChange: onLangChange,
831
+ onThemeChange,
832
+ onFormat,
833
+ onToggleAiChat: () => setAiVisible((v) => !v),
834
+ aiChatVisible: aiVisible
835
+ }
836
+ ),
837
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
838
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
839
+ EditorPanel,
840
+ {
841
+ value,
842
+ onChange: (v) => {
843
+ onChange?.(v);
844
+ coordinator.patchEditorState({ value: v });
845
+ },
846
+ language: coordinator.editorState.language,
847
+ theme: coordinator.editorState.theme,
848
+ vsPath,
849
+ onMount: onEditorMount
850
+ }
851
+ ),
852
+ aiVisible && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AiChatPanel, { onClose: () => setAiVisible(false) })
853
+ ] }),
854
+ showStatusBar && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
855
+ StatusBar,
856
+ {
857
+ language: coordinator.editorState.language,
858
+ lineCount: coordinator.editorState.value.split("\n").length,
859
+ charCount: coordinator.editorState.value.length,
860
+ cursorLine: coordinator.editorState.cursorLine,
861
+ cursorColumn: coordinator.editorState.cursorColumn
862
+ }
863
+ )
864
+ ]
865
+ }
866
+ );
867
+ };
868
+
869
+ // src/utils/configureMonaco.ts
870
+ var import_react9 = require("@monaco-editor/react");
871
+ var import_core5 = require("@monaco-ai-editor/core");
872
+ function configureMonaco(options = {}) {
873
+ const { locale = import_core5.LOCALES.ZH_CN, vsPath } = options;
874
+ const baseUrl = (define_import_meta_env_default?.BASE_URL ?? "/").replace(/\/$/, "");
875
+ const effectiveVsPath = vsPath ?? `${baseUrl}/vs`;
876
+ const config = {
877
+ paths: { vs: effectiveVsPath },
878
+ "vs/nls": {
879
+ availableLanguages: { "*": locale }
880
+ }
881
+ };
882
+ import_react9.loader.config(config);
883
+ }
884
+
885
+ // src/index.ts
886
+ var import_core6 = require("@monaco-ai-editor/core");
887
+ // Annotate the CommonJS export names for ESM import in node:
888
+ 0 && (module.exports = {
889
+ AiChatPanel,
890
+ EditorCoordinator,
891
+ EditorPanel,
892
+ LANGUAGES,
893
+ LOCALES,
894
+ MonacoAiEditor,
895
+ SQL_DATA_TYPES,
896
+ SQL_FUNCTIONS,
897
+ SQL_KEYWORDS,
898
+ StatusBar,
899
+ THEMES,
900
+ Toolbar,
901
+ configureMonaco,
902
+ useEditorCoordinator
903
+ });
904
+ //# sourceMappingURL=index.cjs.map