@mvriu5/payload-ai 0.5.6 → 0.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -5
- package/dist/ai/providerOptions.d.ts +1 -14
- package/dist/ai/providerOptions.js +0 -23
- package/dist/ai/providerRuntime.d.ts +3 -2
- package/dist/ai/providerRuntime.js +6 -15
- package/dist/components/AIActionProposalList.d.ts +2 -1
- package/dist/components/AIActionProposalList.js +74 -6
- package/dist/components/AIActionProposalList.module.css +49 -5
- package/dist/components/AIApiKeyField.js +0 -8
- package/dist/components/AIInput.d.ts +1 -1
- package/dist/components/AIInput.js +156 -23
- package/dist/components/AIInput.module.css +185 -147
- package/dist/components/CollectionMentionPopover.d.ts +1 -1
- package/dist/components/DiffDialog.d.ts +12 -0
- package/dist/components/DiffDialog.js +310 -0
- package/dist/components/DiffDialog.module.css +249 -0
- package/dist/components/Icons.d.ts +9 -0
- package/dist/components/Icons.js +266 -0
- package/dist/components/RecentChangesList.d.ts +18 -0
- package/dist/components/RecentChangesList.js +66 -0
- package/dist/components/RecentChangesList.module.css +135 -0
- package/dist/components/hooks/useAISettings.d.ts +1 -1
- package/dist/endpoints/aiApplyActionEndpointHandler.d.ts +3 -1
- package/dist/endpoints/aiApplyActionEndpointHandler.js +209 -8
- package/dist/endpoints/aiChatEndpointHandler.d.ts +5 -1
- package/dist/endpoints/aiChatEndpointHandler.js +106 -21
- package/dist/endpoints/aiMentionSuggestionsEndpointHandler.d.ts +2 -1
- package/dist/endpoints/aiMentionSuggestionsEndpointHandler.js +7 -7
- package/dist/endpoints/aiProposalDiffEndpointHandler.d.ts +7 -0
- package/dist/endpoints/aiProposalDiffEndpointHandler.js +138 -0
- package/dist/endpoints/aiRecentChangesEndpointHandler.d.ts +6 -0
- package/dist/endpoints/aiRecentChangesEndpointHandler.js +35 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +140 -18
- package/dist/payload/collectionPermissions.d.ts +22 -0
- package/dist/payload/collectionPermissions.js +68 -0
- package/dist/payload/schemaContext.d.ts +46 -2
- package/dist/payload/schemaContext.js +105 -14
- package/package.json +113 -121
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useConfig } from "@payloadcms/ui";
|
|
3
3
|
import { formatAdminURL } from "payload/shared";
|
|
4
|
-
import { useMemo, useRef, useState } from "react";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { getResolvedAIModelConfig } from "../ai/providerOptions.js";
|
|
6
6
|
import { getSerializableLabel, isInternalCollection } from "../payload/shared.js";
|
|
7
7
|
import { AIActionProposalList } from "./AIActionProposalList.js";
|
|
8
8
|
import styles from "./AIInput.module.css";
|
|
9
9
|
import { CollectionMentionPopover } from "./CollectionMentionPopover.js";
|
|
10
|
+
import { ClaudeIcon, GoogleGeminiIcon, MistralAiIcon, OpenaiIcon, Send } from "./Icons.js";
|
|
11
|
+
import { RecentChangesList } from "./RecentChangesList.js";
|
|
10
12
|
import { useAISettings } from "./hooks/useAISettings.js";
|
|
11
13
|
import { useDocumentMentionSuggestions } from "./hooks/useDocumentMentionSuggestions.js";
|
|
12
14
|
const collectBlockOptions = ({ fields, parent })=>{
|
|
@@ -35,6 +37,52 @@ const collectBlockOptions = ({ fields, parent })=>{
|
|
|
35
37
|
}
|
|
36
38
|
return options;
|
|
37
39
|
};
|
|
40
|
+
const getProviderIcon = (provider)=>{
|
|
41
|
+
const iconProps = {
|
|
42
|
+
"aria-hidden": true,
|
|
43
|
+
className: styles.selectProviderIcon
|
|
44
|
+
};
|
|
45
|
+
switch(provider){
|
|
46
|
+
case "claude":
|
|
47
|
+
return /*#__PURE__*/ React.createElement(ClaudeIcon, iconProps);
|
|
48
|
+
case "google":
|
|
49
|
+
return /*#__PURE__*/ React.createElement(GoogleGeminiIcon, iconProps);
|
|
50
|
+
case "mistral":
|
|
51
|
+
return /*#__PURE__*/ React.createElement(MistralAiIcon, iconProps);
|
|
52
|
+
case "openai":
|
|
53
|
+
return /*#__PURE__*/ React.createElement(OpenaiIcon, iconProps);
|
|
54
|
+
default:
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const parseSSEEvent = (chunk)=>{
|
|
59
|
+
const lines = chunk.split("\n");
|
|
60
|
+
let eventName = "";
|
|
61
|
+
const dataLines = [];
|
|
62
|
+
for (const line of lines){
|
|
63
|
+
if (line.startsWith("event:")) {
|
|
64
|
+
eventName = line.slice(6).trim();
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (line.startsWith("data:")) {
|
|
68
|
+
dataLines.push(line.slice(5).trim());
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!eventName) return null;
|
|
72
|
+
try {
|
|
73
|
+
const data = JSON.parse(dataLines.join("\n"));
|
|
74
|
+
if (eventName !== "text" && eventName !== "proposals" && eventName !== "error" && eventName !== "done") {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
data,
|
|
79
|
+
event: eventName
|
|
80
|
+
};
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const sanitizeResponseText = (value)=>value.replace(/\*\*/g, "");
|
|
38
86
|
export const AIInput = ()=>{
|
|
39
87
|
const { config } = useConfig();
|
|
40
88
|
const editorRef = useRef(null);
|
|
@@ -56,9 +104,48 @@ export const AIInput = ()=>{
|
|
|
56
104
|
const [response, setResponse] = useState("");
|
|
57
105
|
const [error, setError] = useState("");
|
|
58
106
|
const [proposals, setProposals] = useState([]);
|
|
107
|
+
const [appliedChanges, setAppliedChanges] = useState([]);
|
|
59
108
|
const [isLoading, setIsLoading] = useState(false);
|
|
60
109
|
const [isApplying, setIsApplying] = useState(false);
|
|
61
|
-
const
|
|
110
|
+
const enabledCollectionSlugs = config.admin?.custom?.payloadAiPlugin?.collectionSlugs;
|
|
111
|
+
const enabledCollectionSlugSet = useMemo(()=>enabledCollectionSlugs ? new Set(enabledCollectionSlugs) : null, [
|
|
112
|
+
enabledCollectionSlugs
|
|
113
|
+
]);
|
|
114
|
+
const isCollectionMentionEnabled = (slug)=>!enabledCollectionSlugSet || enabledCollectionSlugSet.has(slug);
|
|
115
|
+
const recentChangesEndpoint = useMemo(()=>formatAdminURL({
|
|
116
|
+
apiRoute: config.routes.api,
|
|
117
|
+
path: "/ai-recent-changes"
|
|
118
|
+
}), [
|
|
119
|
+
config.routes.api
|
|
120
|
+
]);
|
|
121
|
+
const loadRecentChanges = useCallback(async ()=>{
|
|
122
|
+
const res = await fetch(recentChangesEndpoint);
|
|
123
|
+
const result = await res.json().catch(()=>null);
|
|
124
|
+
if (res.ok && result?.changes) {
|
|
125
|
+
setAppliedChanges(result.changes);
|
|
126
|
+
}
|
|
127
|
+
}, [
|
|
128
|
+
recentChangesEndpoint
|
|
129
|
+
]);
|
|
130
|
+
useEffect(()=>{
|
|
131
|
+
void loadRecentChanges().catch(()=>undefined);
|
|
132
|
+
}, [
|
|
133
|
+
loadRecentChanges
|
|
134
|
+
]);
|
|
135
|
+
useEffect(()=>{
|
|
136
|
+
if (isLoading || error || proposals.length > 0 || !response) return;
|
|
137
|
+
const timeout = window.setTimeout(()=>{
|
|
138
|
+
setResponse("");
|
|
139
|
+
clearInput();
|
|
140
|
+
}, 5000);
|
|
141
|
+
return ()=>window.clearTimeout(timeout);
|
|
142
|
+
}, [
|
|
143
|
+
error,
|
|
144
|
+
isLoading,
|
|
145
|
+
proposals.length,
|
|
146
|
+
response
|
|
147
|
+
]);
|
|
148
|
+
const collections = config.collections.filter((collection)=>!isInternalCollection(collection.slug)).filter((collection)=>isCollectionMentionEnabled(collection.slug)).map((collection)=>({
|
|
62
149
|
label: getSerializableLabel(collection.labels?.singular, collection.slug),
|
|
63
150
|
slug: collection.slug,
|
|
64
151
|
type: "collection"
|
|
@@ -69,7 +156,7 @@ export const AIInput = ()=>{
|
|
|
69
156
|
type: "global"
|
|
70
157
|
})) || [];
|
|
71
158
|
const blocks = [
|
|
72
|
-
...config.collections.flatMap((collection)=>collectBlockOptions({
|
|
159
|
+
...config.collections.filter((collection)=>isCollectionMentionEnabled(collection.slug)).flatMap((collection)=>collectBlockOptions({
|
|
73
160
|
fields: collection.fields,
|
|
74
161
|
parent: collection.slug
|
|
75
162
|
})),
|
|
@@ -106,14 +193,6 @@ export const AIInput = ()=>{
|
|
|
106
193
|
clonedRange.setEnd(range.endContainer, range.endOffset);
|
|
107
194
|
return clonedRange.toString().length;
|
|
108
195
|
};
|
|
109
|
-
const moveCaretToEnd = (element)=>{
|
|
110
|
-
const selection = window.getSelection();
|
|
111
|
-
const range = document.createRange();
|
|
112
|
-
range.selectNodeContents(element);
|
|
113
|
-
range.collapse(false);
|
|
114
|
-
selection?.removeAllRanges();
|
|
115
|
-
selection?.addRange(range);
|
|
116
|
-
};
|
|
117
196
|
const getTextNodeAtOffset = (element, offset)=>{
|
|
118
197
|
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
|
|
119
198
|
let currentOffset = 0;
|
|
@@ -231,6 +310,9 @@ export const AIInput = ()=>{
|
|
|
231
310
|
if (!trimmedPrompt) return;
|
|
232
311
|
setIsLoading(true);
|
|
233
312
|
setAppliedProposalIndexes([]);
|
|
313
|
+
setError("");
|
|
314
|
+
setProposals([]);
|
|
315
|
+
setResponse("");
|
|
234
316
|
try {
|
|
235
317
|
const res = await fetch(formatAdminURL({
|
|
236
318
|
apiRoute: config.routes.api,
|
|
@@ -246,15 +328,49 @@ export const AIInput = ()=>{
|
|
|
246
328
|
},
|
|
247
329
|
method: "POST"
|
|
248
330
|
});
|
|
249
|
-
const result = await res.json();
|
|
250
331
|
if (!res.ok) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
332
|
+
const result = await res.json().catch(()=>null);
|
|
333
|
+
throw new Error(result?.error || "AI request failed");
|
|
334
|
+
}
|
|
335
|
+
if (!res.body) {
|
|
336
|
+
throw new Error("AI response stream is unavailable");
|
|
337
|
+
}
|
|
338
|
+
const reader = res.body.getReader();
|
|
339
|
+
const decoder = new TextDecoder();
|
|
340
|
+
let buffer = "";
|
|
341
|
+
while(true){
|
|
342
|
+
const { done, value } = await reader.read();
|
|
343
|
+
if (done) break;
|
|
344
|
+
buffer += decoder.decode(value, {
|
|
345
|
+
stream: true
|
|
346
|
+
});
|
|
347
|
+
const chunks = buffer.split("\n\n");
|
|
348
|
+
buffer = chunks.pop() || "";
|
|
349
|
+
for (const chunk of chunks){
|
|
350
|
+
const event = parseSSEEvent(chunk);
|
|
351
|
+
if (!event) continue;
|
|
352
|
+
if (event.event === "text") {
|
|
353
|
+
if (event.data.delta) {
|
|
354
|
+
setResponse((current)=>current + sanitizeResponseText(event.data.delta || ""));
|
|
355
|
+
}
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (event.event === "proposals") {
|
|
359
|
+
setProposals(event.data.proposals || []);
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (event.event === "error") {
|
|
363
|
+
throw new Error(event.data.error || "AI request failed");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const finalEvent = buffer.trim() ? parseSSEEvent(buffer.trim()) : null;
|
|
368
|
+
if (finalEvent?.event === "proposals") {
|
|
369
|
+
setProposals(finalEvent.data.proposals || []);
|
|
370
|
+
}
|
|
371
|
+
if (finalEvent?.event === "error") {
|
|
372
|
+
throw new Error(finalEvent.data.error || "AI request failed");
|
|
254
373
|
}
|
|
255
|
-
setError("");
|
|
256
|
-
setResponse(result.text || "");
|
|
257
|
-
setProposals(result.proposals || []);
|
|
258
374
|
} catch (err) {
|
|
259
375
|
setProposals([]);
|
|
260
376
|
setResponse("");
|
|
@@ -289,6 +405,13 @@ export const AIInput = ()=>{
|
|
|
289
405
|
setError("");
|
|
290
406
|
setProposals([]);
|
|
291
407
|
setResponse("");
|
|
408
|
+
if (result.change) {
|
|
409
|
+
setAppliedChanges((current)=>[
|
|
410
|
+
result.change,
|
|
411
|
+
...current
|
|
412
|
+
].slice(0, 12));
|
|
413
|
+
}
|
|
414
|
+
void loadRecentChanges().catch(()=>undefined);
|
|
292
415
|
clearInput();
|
|
293
416
|
} catch (err) {
|
|
294
417
|
setError(err instanceof Error ? err.message : "Could not apply proposal");
|
|
@@ -297,6 +420,8 @@ export const AIInput = ()=>{
|
|
|
297
420
|
}
|
|
298
421
|
};
|
|
299
422
|
return /*#__PURE__*/ React.createElement("div", {
|
|
423
|
+
className: styles.chatLayout
|
|
424
|
+
}, /*#__PURE__*/ React.createElement("div", {
|
|
300
425
|
className: styles.chat
|
|
301
426
|
}, /*#__PURE__*/ React.createElement("div", {
|
|
302
427
|
className: styles.chatHeader
|
|
@@ -349,22 +474,28 @@ export const AIInput = ()=>{
|
|
|
349
474
|
className: styles.setting
|
|
350
475
|
}, /*#__PURE__*/ React.createElement("span", {
|
|
351
476
|
className: styles.settingLabel
|
|
352
|
-
}, "Model"), /*#__PURE__*/ React.createElement("
|
|
477
|
+
}, "Model"), /*#__PURE__*/ React.createElement("div", {
|
|
478
|
+
className: styles.selectWrapper
|
|
479
|
+
}, getProviderIcon(settingsProvider), /*#__PURE__*/ React.createElement("select", {
|
|
353
480
|
className: styles.select,
|
|
354
481
|
disabled: !settingsProvider,
|
|
355
482
|
onChange: (event)=>setSelectedModel(event.target.value),
|
|
356
483
|
value: selectedModel
|
|
357
|
-
}, !settingsProvider
|
|
484
|
+
}, !settingsProvider && /*#__PURE__*/ React.createElement("option", {
|
|
358
485
|
value: ""
|
|
359
|
-
}, "Select provider in account settings")
|
|
486
|
+
}, "Select provider in account settings"), settingsProvider && aiModelConfig.providers[settingsProvider].map((model)=>/*#__PURE__*/ React.createElement("option", {
|
|
360
487
|
key: model.value,
|
|
361
488
|
value: model.value
|
|
362
|
-
}, model.label))
|
|
489
|
+
}, model.label)))))), /*#__PURE__*/ React.createElement("button", {
|
|
363
490
|
className: styles.chatButton,
|
|
364
491
|
disabled: !prompt.trim() || !settingsProvider || !selectedModel || isLoading,
|
|
365
492
|
onClick: ()=>void handleSubmit(),
|
|
366
493
|
type: "button"
|
|
367
|
-
},
|
|
494
|
+
}, /*#__PURE__*/ React.createElement(Send, {
|
|
495
|
+
width: 14,
|
|
496
|
+
height: 14
|
|
497
|
+
}), isLoading ? "Sending..." : "Send")), /*#__PURE__*/ React.createElement(AIActionProposalList, {
|
|
498
|
+
apiRoute: config.routes.api,
|
|
368
499
|
appliedProposalIndexes: appliedProposalIndexes,
|
|
369
500
|
description: response,
|
|
370
501
|
error: error,
|
|
@@ -382,5 +513,7 @@ export const AIInput = ()=>{
|
|
|
382
513
|
},
|
|
383
514
|
onApply: (proposal, _index)=>void handleApplyProposal(proposal),
|
|
384
515
|
proposals: proposals
|
|
516
|
+
})), /*#__PURE__*/ React.createElement(RecentChangesList, {
|
|
517
|
+
changes: appliedChanges
|
|
385
518
|
}));
|
|
386
519
|
};
|
|
@@ -1,237 +1,275 @@
|
|
|
1
|
+
.chatLayout {
|
|
2
|
+
align-items: stretch;
|
|
3
|
+
display: grid;
|
|
4
|
+
gap: 16px;
|
|
5
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
6
|
+
margin-bottom: 24px;
|
|
7
|
+
max-width: 1280px;
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
.chat {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
max-width: 920px;
|
|
6
|
-
padding: 20px;
|
|
11
|
+
border: 1px solid var(--theme-elevation-150);
|
|
12
|
+
border-radius: 8px;
|
|
13
|
+
padding: 20px;
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
.chatHeader {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
align-items: flex-start;
|
|
18
|
+
display: flex;
|
|
19
|
+
justify-content: space-between;
|
|
20
|
+
margin-bottom: 16px;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
.chatTitle {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
font-size: 18px;
|
|
25
|
+
line-height: 1.3;
|
|
26
|
+
margin: 0;
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
.chatDescription {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
color: var(--theme-elevation-600);
|
|
31
|
+
font-size: 13px;
|
|
32
|
+
line-height: 1.4;
|
|
33
|
+
margin: 4px 0 0;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
.settings {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
align-items: flex-end;
|
|
38
|
+
display: flex;
|
|
39
|
+
gap: 10px;
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
.setting {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
gap: 4px;
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
.settingLabel {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
color: var(--theme-elevation-600);
|
|
50
|
+
font-size: 11px;
|
|
51
|
+
line-height: 1.2;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.selectWrapper {
|
|
55
|
+
align-items: center;
|
|
56
|
+
display: flex;
|
|
57
|
+
position: relative;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.selectProviderIcon {
|
|
61
|
+
color: var(--theme-text);
|
|
62
|
+
height: 12px;
|
|
63
|
+
left: 10px;
|
|
64
|
+
pointer-events: none;
|
|
65
|
+
position: absolute;
|
|
66
|
+
top: 50%;
|
|
67
|
+
transform: translateY(-50%);
|
|
68
|
+
width: 16px;
|
|
45
69
|
}
|
|
46
70
|
|
|
47
71
|
.select {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
background: var(--theme-input-bg);
|
|
73
|
+
border: 1px solid var(--theme-elevation-150);
|
|
74
|
+
border-radius: 4px;
|
|
75
|
+
color: var(--theme-text);
|
|
76
|
+
font: inherit;
|
|
77
|
+
min-height: 24px;
|
|
78
|
+
min-width: 160px;
|
|
79
|
+
padding: 0 28px 0 34px;
|
|
56
80
|
}
|
|
57
81
|
|
|
58
82
|
.select:focus {
|
|
59
|
-
|
|
60
|
-
|
|
83
|
+
border-color: var(--theme-success-500);
|
|
84
|
+
outline: none;
|
|
61
85
|
}
|
|
62
86
|
|
|
63
87
|
.chatInputRow {
|
|
64
|
-
|
|
65
|
-
|
|
88
|
+
position: relative;
|
|
89
|
+
width: 100%;
|
|
66
90
|
}
|
|
67
91
|
|
|
68
92
|
.chatActionsRow {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
93
|
+
align-items: flex-end;
|
|
94
|
+
display: flex;
|
|
95
|
+
gap: 12px;
|
|
96
|
+
justify-content: space-between;
|
|
97
|
+
margin-top: 12px;
|
|
74
98
|
}
|
|
75
99
|
|
|
76
100
|
.chatInput {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
101
|
+
background: transparent;
|
|
102
|
+
border: 0;
|
|
103
|
+
color: var(--theme-text);
|
|
104
|
+
font: inherit;
|
|
105
|
+
min-height: 84px;
|
|
106
|
+
padding: 0;
|
|
107
|
+
white-space: pre-wrap;
|
|
108
|
+
width: 100%;
|
|
85
109
|
}
|
|
86
110
|
|
|
87
111
|
.chatInput:focus {
|
|
88
|
-
|
|
112
|
+
outline: none;
|
|
89
113
|
}
|
|
90
114
|
|
|
91
115
|
.chatInput:empty::before {
|
|
92
|
-
|
|
93
|
-
|
|
116
|
+
color: var(--theme-elevation-400);
|
|
117
|
+
content: attr(data-placeholder);
|
|
94
118
|
}
|
|
95
119
|
|
|
96
120
|
.chatInputSurface {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
121
|
+
background: var(--theme-input-bg);
|
|
122
|
+
border: 1px solid var(--theme-elevation-150);
|
|
123
|
+
border-radius: 4px;
|
|
124
|
+
padding: 12px;
|
|
125
|
+
width: 100%;
|
|
102
126
|
}
|
|
103
127
|
|
|
104
128
|
.chatInputSurface:focus-within {
|
|
105
|
-
|
|
129
|
+
border-color: var(--theme-success-500);
|
|
106
130
|
}
|
|
107
131
|
|
|
108
132
|
.inlineBadge {
|
|
109
|
-
|
|
110
|
-
|
|
133
|
+
margin: 0 2px;
|
|
134
|
+
vertical-align: middle;
|
|
111
135
|
}
|
|
112
136
|
|
|
113
137
|
.badge {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
align-items: center;
|
|
139
|
+
background: var(--theme-elevation-100);
|
|
140
|
+
border: 1px solid var(--theme-elevation-150);
|
|
141
|
+
border-radius: 999px;
|
|
142
|
+
color: var(--theme-text);
|
|
143
|
+
display: inline-flex;
|
|
144
|
+
font-size: 11px;
|
|
145
|
+
gap: 3px;
|
|
146
|
+
line-height: 1;
|
|
147
|
+
min-height: 20px;
|
|
148
|
+
padding: 0 8px;
|
|
149
|
+
position: relative;
|
|
150
|
+
top: -2px;
|
|
151
|
+
white-space: nowrap;
|
|
128
152
|
}
|
|
129
153
|
|
|
130
154
|
.prefix {
|
|
131
|
-
|
|
155
|
+
color: var(--theme-elevation-500);
|
|
132
156
|
}
|
|
133
157
|
|
|
134
158
|
.name {
|
|
135
|
-
|
|
159
|
+
color: var(--theme-text);
|
|
136
160
|
}
|
|
137
161
|
|
|
138
162
|
.collection {
|
|
139
|
-
|
|
140
|
-
|
|
163
|
+
background: color-mix(in srgb, #2f7d68 12%, var(--theme-bg));
|
|
164
|
+
border-color: color-mix(in srgb, #2f7d68 28%, var(--theme-elevation-150));
|
|
141
165
|
}
|
|
142
166
|
|
|
143
167
|
.global {
|
|
144
|
-
|
|
145
|
-
|
|
168
|
+
background: color-mix(in srgb, #8b6f24 12%, var(--theme-bg));
|
|
169
|
+
border-color: color-mix(in srgb, #8b6f24 28%, var(--theme-elevation-150));
|
|
146
170
|
}
|
|
147
171
|
|
|
148
172
|
.block {
|
|
149
|
-
|
|
150
|
-
|
|
173
|
+
background: color-mix(in srgb, #5a6fa8 12%, var(--theme-bg));
|
|
174
|
+
border-color: color-mix(in srgb, #5a6fa8 28%, var(--theme-elevation-150));
|
|
151
175
|
}
|
|
152
176
|
|
|
153
177
|
.doc {
|
|
154
|
-
|
|
155
|
-
|
|
178
|
+
background: color-mix(in srgb, #7a5c9e 12%, var(--theme-bg));
|
|
179
|
+
border-color: color-mix(in srgb, #7a5c9e 28%, var(--theme-elevation-150));
|
|
156
180
|
}
|
|
157
181
|
|
|
158
182
|
.chatButton {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
183
|
+
align-items: center;
|
|
184
|
+
background: var(--theme-text);
|
|
185
|
+
border: 0;
|
|
186
|
+
border-radius: 4px;
|
|
187
|
+
color: var(--theme-bg);
|
|
188
|
+
cursor: pointer;
|
|
189
|
+
display: inline-flex;
|
|
190
|
+
font: inherit;
|
|
191
|
+
gap: 6px;
|
|
192
|
+
justify-content: center;
|
|
193
|
+
line-height: 24px;
|
|
194
|
+
min-height: 24px;
|
|
195
|
+
padding: 0 14px;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.chatButton svg {
|
|
199
|
+
flex: 0 0 auto;
|
|
167
200
|
}
|
|
168
201
|
|
|
169
202
|
.chatButton:disabled {
|
|
170
|
-
|
|
171
|
-
|
|
203
|
+
cursor: not-allowed;
|
|
204
|
+
opacity: 0.45;
|
|
172
205
|
}
|
|
173
206
|
|
|
174
207
|
.chatError {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
208
|
+
color: var(--theme-error-500);
|
|
209
|
+
font-size: 13px;
|
|
210
|
+
line-height: 1.4;
|
|
211
|
+
margin-top: 12px;
|
|
179
212
|
}
|
|
180
213
|
|
|
181
214
|
.debugInfo {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
215
|
+
background: var(--theme-elevation-50);
|
|
216
|
+
border: 1px solid var(--theme-elevation-150);
|
|
217
|
+
border-radius: 4px;
|
|
218
|
+
color: var(--theme-elevation-800);
|
|
219
|
+
font-size: 12px;
|
|
220
|
+
line-height: 1.5;
|
|
221
|
+
margin: 12px 0 0;
|
|
222
|
+
max-height: 260px;
|
|
223
|
+
overflow: auto;
|
|
224
|
+
padding: 12px;
|
|
225
|
+
white-space: pre-wrap;
|
|
193
226
|
}
|
|
194
227
|
|
|
195
228
|
.chatResponse {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
229
|
+
background: var(--theme-elevation-50);
|
|
230
|
+
border: 1px solid var(--theme-elevation-100);
|
|
231
|
+
border-radius: 4px;
|
|
232
|
+
line-height: 1.5;
|
|
233
|
+
margin-top: 16px;
|
|
234
|
+
padding: 12px;
|
|
235
|
+
white-space: pre-wrap;
|
|
203
236
|
}
|
|
204
237
|
|
|
205
238
|
@media (max-width: 768px) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
239
|
+
.chatLayout {
|
|
240
|
+
grid-template-columns: minmax(0, 1fr);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.chatHeader {
|
|
244
|
+
flex-direction: column;
|
|
245
|
+
gap: 12px;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.chatInputRow {
|
|
249
|
+
width: 100%;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.chatActionsRow {
|
|
253
|
+
align-items: stretch;
|
|
254
|
+
flex-direction: column;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.settings {
|
|
258
|
+
align-items: stretch;
|
|
259
|
+
width: 100%;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.setting {
|
|
263
|
+
flex: 1;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.select {
|
|
267
|
+
min-width: 0;
|
|
268
|
+
width: 100%;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.chatButton {
|
|
272
|
+
align-self: stretch;
|
|
273
|
+
}
|
|
233
274
|
|
|
234
|
-
.chatButton {
|
|
235
|
-
align-self: stretch;
|
|
236
|
-
}
|
|
237
275
|
}
|