@conduit-d365/ai-chat 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/AIChatProvider.d.ts +15 -0
- package/dist/AIChatProvider.d.ts.map +1 -0
- package/dist/AIChatProvider.js +183 -0
- package/dist/AIChatProvider.js.map +1 -0
- package/dist/ChatSidebar.d.ts +10 -0
- package/dist/ChatSidebar.d.ts.map +1 -0
- package/dist/ChatSidebar.js +187 -0
- package/dist/ChatSidebar.js.map +1 -0
- package/dist/ChatToggle.d.ts +8 -0
- package/dist/ChatToggle.d.ts.map +1 -0
- package/dist/ChatToggle.js +49 -0
- package/dist/ChatToggle.js.map +1 -0
- package/dist/components/ContextBadge.d.ts +6 -0
- package/dist/components/ContextBadge.d.ts.map +1 -0
- package/dist/components/ContextBadge.js +25 -0
- package/dist/components/ContextBadge.js.map +1 -0
- package/dist/components/MarkdownRenderer.d.ts +5 -0
- package/dist/components/MarkdownRenderer.d.ts.map +1 -0
- package/dist/components/MarkdownRenderer.js +108 -0
- package/dist/components/MarkdownRenderer.js.map +1 -0
- package/dist/components/MessageBubble.d.ts +7 -0
- package/dist/components/MessageBubble.d.ts.map +1 -0
- package/dist/components/MessageBubble.js +51 -0
- package/dist/components/MessageBubble.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +59 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { AIChatConfig, UseAIChatReturn, UsePageContextReturn } from './types';
|
|
3
|
+
export interface AIChatProviderProps extends AIChatConfig {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
/**
|
|
6
|
+
* Optional async function that returns a Bearer token.
|
|
7
|
+
* Typically pass getAccessToken from @conduit-d365/auth's useAuth().
|
|
8
|
+
* If omitted, requests are sent without an Authorization header.
|
|
9
|
+
*/
|
|
10
|
+
getAccessToken?: () => Promise<string>;
|
|
11
|
+
}
|
|
12
|
+
export declare function AIChatProvider({ children, appName, endpoint, placeholder: _placeholder, maxHistory, getAccessToken, }: AIChatProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare function useAIChat(): UseAIChatReturn;
|
|
14
|
+
export declare function usePageContext(): UsePageContextReturn;
|
|
15
|
+
//# sourceMappingURL=AIChatProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AIChatProvider.d.ts","sourceRoot":"","sources":["../src/AIChatProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EACV,YAAY,EAIZ,eAAe,EACf,oBAAoB,EACrB,MAAM,SAAS,CAAA;AAUhB,MAAM,WAAW,mBAAoB,SAAQ,YAAY;IACvD,QAAQ,EAAE,SAAS,CAAA;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACvC;AAOD,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,OAAO,EACP,QAAyB,EACzB,WAAW,EAAE,YAAY,EACzB,UAAe,EACf,cAAc,GACf,EAAE,mBAAmB,2CAgMrB;AAID,wBAAgB,SAAS,IAAI,eAAe,CAM3C;AAED,wBAAgB,cAAc,IAAI,oBAAoB,CAMrD"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useRef, useState, } from 'react';
|
|
3
|
+
// ── Contexts ──────────────────────────────────────────────────────────
|
|
4
|
+
const AIChatContext = createContext(null);
|
|
5
|
+
const PageContextContext = createContext(null);
|
|
6
|
+
const GetTokenContext = createContext(null);
|
|
7
|
+
let nextId = 0;
|
|
8
|
+
function generateId() {
|
|
9
|
+
return `msg_${Date.now()}_${nextId++}`;
|
|
10
|
+
}
|
|
11
|
+
export function AIChatProvider({ children, appName, endpoint = '/api/ai/chat', placeholder: _placeholder, maxHistory = 50, getAccessToken, }) {
|
|
12
|
+
const [messages, setMessages] = useState([]);
|
|
13
|
+
const [isStreaming, setIsStreaming] = useState(false);
|
|
14
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
15
|
+
const [error, setError] = useState(null);
|
|
16
|
+
const [pageContext, setPageContext] = useState(null);
|
|
17
|
+
// Ref to abort in-flight requests
|
|
18
|
+
const abortRef = useRef(null);
|
|
19
|
+
const sendMessage = useCallback(async (content) => {
|
|
20
|
+
if (!content.trim() || isStreaming)
|
|
21
|
+
return;
|
|
22
|
+
const userMessage = {
|
|
23
|
+
id: generateId(),
|
|
24
|
+
role: 'user',
|
|
25
|
+
content: content.trim(),
|
|
26
|
+
timestamp: Date.now(),
|
|
27
|
+
};
|
|
28
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
29
|
+
setError(null);
|
|
30
|
+
setIsStreaming(true);
|
|
31
|
+
// Build the assistant placeholder
|
|
32
|
+
const assistantId = generateId();
|
|
33
|
+
const assistantMessage = {
|
|
34
|
+
id: assistantId,
|
|
35
|
+
role: 'assistant',
|
|
36
|
+
content: '',
|
|
37
|
+
timestamp: Date.now(),
|
|
38
|
+
};
|
|
39
|
+
setMessages((prev) => [...prev, assistantMessage]);
|
|
40
|
+
try {
|
|
41
|
+
abortRef.current = new AbortController();
|
|
42
|
+
// Build history (trim to maxHistory)
|
|
43
|
+
const history = [...messages, userMessage].slice(-maxHistory);
|
|
44
|
+
const body = {
|
|
45
|
+
message: content.trim(),
|
|
46
|
+
history,
|
|
47
|
+
pageContext,
|
|
48
|
+
appName,
|
|
49
|
+
};
|
|
50
|
+
const headers = {
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
};
|
|
53
|
+
if (getAccessToken) {
|
|
54
|
+
try {
|
|
55
|
+
const token = await getAccessToken();
|
|
56
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// If token acquisition fails, proceed without auth
|
|
60
|
+
// (backend will reject with 401 if auth is required)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const response = await fetch(endpoint, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers,
|
|
66
|
+
body: JSON.stringify(body),
|
|
67
|
+
signal: abortRef.current.signal,
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
71
|
+
throw new Error(response.status === 401
|
|
72
|
+
? 'Authentication required. Please sign in.'
|
|
73
|
+
: response.status === 429
|
|
74
|
+
? 'Rate limit exceeded. Please wait a moment.'
|
|
75
|
+
: `Chat request failed: ${errorText}`);
|
|
76
|
+
}
|
|
77
|
+
// Stream SSE response
|
|
78
|
+
const reader = response.body?.getReader();
|
|
79
|
+
if (!reader)
|
|
80
|
+
throw new Error('No response body');
|
|
81
|
+
const decoder = new TextDecoder();
|
|
82
|
+
let buffer = '';
|
|
83
|
+
while (true) {
|
|
84
|
+
const { done, value } = await reader.read();
|
|
85
|
+
if (done)
|
|
86
|
+
break;
|
|
87
|
+
buffer += decoder.decode(value, { stream: true });
|
|
88
|
+
// Process SSE lines
|
|
89
|
+
const lines = buffer.split('\n');
|
|
90
|
+
buffer = lines.pop() ?? '';
|
|
91
|
+
for (const line of lines) {
|
|
92
|
+
if (line.startsWith('data: ')) {
|
|
93
|
+
const data = line.slice(6);
|
|
94
|
+
if (data === '[DONE]')
|
|
95
|
+
break;
|
|
96
|
+
try {
|
|
97
|
+
const parsed = JSON.parse(data);
|
|
98
|
+
if (parsed.error) {
|
|
99
|
+
throw new Error(parsed.error);
|
|
100
|
+
}
|
|
101
|
+
if (parsed.content) {
|
|
102
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId
|
|
103
|
+
? { ...m, content: m.content + parsed.content }
|
|
104
|
+
: m));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
if (e instanceof SyntaxError) {
|
|
109
|
+
// Not JSON — treat raw data as content chunk
|
|
110
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId
|
|
111
|
+
? { ...m, content: m.content + data }
|
|
112
|
+
: m));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
throw e;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
if (err.name === 'AbortError')
|
|
124
|
+
return;
|
|
125
|
+
const errorMessage = err instanceof Error ? err.message : 'An error occurred';
|
|
126
|
+
setError(errorMessage);
|
|
127
|
+
// Remove the empty assistant message on error
|
|
128
|
+
setMessages((prev) => {
|
|
129
|
+
const last = prev[prev.length - 1];
|
|
130
|
+
if (last?.id === assistantId && !last.content) {
|
|
131
|
+
return prev.slice(0, -1);
|
|
132
|
+
}
|
|
133
|
+
return prev;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
setIsStreaming(false);
|
|
138
|
+
abortRef.current = null;
|
|
139
|
+
}
|
|
140
|
+
}, [isStreaming, messages, pageContext, appName, endpoint, maxHistory, getAccessToken]);
|
|
141
|
+
const clearHistory = useCallback(() => {
|
|
142
|
+
if (abortRef.current)
|
|
143
|
+
abortRef.current.abort();
|
|
144
|
+
setMessages([]);
|
|
145
|
+
setError(null);
|
|
146
|
+
setIsStreaming(false);
|
|
147
|
+
}, []);
|
|
148
|
+
const toggle = useCallback(() => setIsOpen((v) => !v), []);
|
|
149
|
+
const open = useCallback(() => setIsOpen(true), []);
|
|
150
|
+
const close = useCallback(() => setIsOpen(false), []);
|
|
151
|
+
const chatValue = {
|
|
152
|
+
messages,
|
|
153
|
+
isStreaming,
|
|
154
|
+
isOpen,
|
|
155
|
+
error,
|
|
156
|
+
sendMessage,
|
|
157
|
+
clearHistory,
|
|
158
|
+
toggle,
|
|
159
|
+
open,
|
|
160
|
+
close,
|
|
161
|
+
};
|
|
162
|
+
const pageContextValue = {
|
|
163
|
+
pageContext,
|
|
164
|
+
setPageContext,
|
|
165
|
+
};
|
|
166
|
+
return (_jsx(GetTokenContext.Provider, { value: getAccessToken ?? null, children: _jsx(PageContextContext.Provider, { value: pageContextValue, children: _jsx(AIChatContext.Provider, { value: chatValue, children: children }) }) }));
|
|
167
|
+
}
|
|
168
|
+
// ── Hooks ─────────────────────────────────────────────────────────────
|
|
169
|
+
export function useAIChat() {
|
|
170
|
+
const context = useContext(AIChatContext);
|
|
171
|
+
if (!context) {
|
|
172
|
+
throw new Error('useAIChat must be used within an AIChatProvider');
|
|
173
|
+
}
|
|
174
|
+
return context;
|
|
175
|
+
}
|
|
176
|
+
export function usePageContext() {
|
|
177
|
+
const context = useContext(PageContextContext);
|
|
178
|
+
if (!context) {
|
|
179
|
+
throw new Error('usePageContext must be used within an AIChatProvider');
|
|
180
|
+
}
|
|
181
|
+
return context;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=AIChatProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AIChatProvider.js","sourceRoot":"","sources":["../src/AIChatProvider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ChatSidebarProps {
|
|
2
|
+
/** Width of the sidebar in pixels. Defaults to 400. */
|
|
3
|
+
width?: number;
|
|
4
|
+
/** Which side to render on. Defaults to "right". */
|
|
5
|
+
position?: 'left' | 'right';
|
|
6
|
+
/** Title displayed in the sidebar header. Defaults to "Conduit AI". */
|
|
7
|
+
title?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function ChatSidebar({ width, position, title, }: ChatSidebarProps): import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
//# sourceMappingURL=ChatSidebar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatSidebar.d.ts","sourceRoot":"","sources":["../src/ChatSidebar.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAmDD,wBAAgB,WAAW,CAAC,EAC1B,KAAW,EACX,QAAkB,EAClB,KAAoB,GACrB,EAAE,gBAAgB,kDAmSlB"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { useAIChat, usePageContext } from './AIChatProvider';
|
|
4
|
+
import { MessageBubble } from './components/MessageBubble';
|
|
5
|
+
import { ContextBadge } from './components/ContextBadge';
|
|
6
|
+
/**
|
|
7
|
+
* CSS keyframes injected once into the document head.
|
|
8
|
+
* Uses a data-attribute guard to avoid duplicate injection.
|
|
9
|
+
*/
|
|
10
|
+
const STYLE_ID = 'conduit-ai-chat-styles';
|
|
11
|
+
function ensureStyles() {
|
|
12
|
+
if (typeof document === 'undefined')
|
|
13
|
+
return;
|
|
14
|
+
if (document.getElementById(STYLE_ID))
|
|
15
|
+
return;
|
|
16
|
+
const style = document.createElement('style');
|
|
17
|
+
style.id = STYLE_ID;
|
|
18
|
+
style.textContent = `
|
|
19
|
+
@keyframes conduit-ai-dot {
|
|
20
|
+
0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); }
|
|
21
|
+
40% { opacity: 1; transform: scale(1); }
|
|
22
|
+
}
|
|
23
|
+
@keyframes conduit-ai-blink {
|
|
24
|
+
0%, 100% { opacity: 1; }
|
|
25
|
+
50% { opacity: 0; }
|
|
26
|
+
}
|
|
27
|
+
@keyframes conduit-ai-slide-in-right {
|
|
28
|
+
from { transform: translateX(100%); }
|
|
29
|
+
to { transform: translateX(0); }
|
|
30
|
+
}
|
|
31
|
+
@keyframes conduit-ai-slide-in-left {
|
|
32
|
+
from { transform: translateX(-100%); }
|
|
33
|
+
to { transform: translateX(0); }
|
|
34
|
+
}
|
|
35
|
+
.conduit-ai-sidebar-enter-right {
|
|
36
|
+
animation: conduit-ai-slide-in-right 0.2s ease-out;
|
|
37
|
+
}
|
|
38
|
+
.conduit-ai-sidebar-enter-left {
|
|
39
|
+
animation: conduit-ai-slide-in-left 0.2s ease-out;
|
|
40
|
+
}
|
|
41
|
+
.conduit-ai-input:focus {
|
|
42
|
+
outline: 2px solid #FF831D;
|
|
43
|
+
outline-offset: -2px;
|
|
44
|
+
}
|
|
45
|
+
.conduit-ai-send-btn:hover:not(:disabled) {
|
|
46
|
+
background-color: #e6720f !important;
|
|
47
|
+
}
|
|
48
|
+
.conduit-ai-clear-btn:hover {
|
|
49
|
+
background-color: var(--conduit-bg-muted, #f1f5f9) !important;
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
document.head.appendChild(style);
|
|
53
|
+
}
|
|
54
|
+
export function ChatSidebar({ width = 400, position = 'right', title = 'Conduit AI', }) {
|
|
55
|
+
const { messages, isStreaming, isOpen, error, sendMessage, clearHistory, close } = useAIChat();
|
|
56
|
+
const { pageContext } = usePageContext();
|
|
57
|
+
const [input, setInput] = useState('');
|
|
58
|
+
const messagesEndRef = useRef(null);
|
|
59
|
+
const inputRef = useRef(null);
|
|
60
|
+
useEffect(() => ensureStyles(), []);
|
|
61
|
+
// Auto-scroll to bottom on new messages
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
64
|
+
}, [messages]);
|
|
65
|
+
// Focus input when sidebar opens
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (isOpen) {
|
|
68
|
+
setTimeout(() => inputRef.current?.focus(), 200);
|
|
69
|
+
}
|
|
70
|
+
}, [isOpen]);
|
|
71
|
+
const handleSubmit = useCallback(() => {
|
|
72
|
+
if (!input.trim() || isStreaming)
|
|
73
|
+
return;
|
|
74
|
+
sendMessage(input);
|
|
75
|
+
setInput('');
|
|
76
|
+
}, [input, isStreaming, sendMessage]);
|
|
77
|
+
const handleKeyDown = useCallback((e) => {
|
|
78
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
handleSubmit();
|
|
81
|
+
}
|
|
82
|
+
}, [handleSubmit]);
|
|
83
|
+
if (!isOpen)
|
|
84
|
+
return null;
|
|
85
|
+
const isLeft = position === 'left';
|
|
86
|
+
return (_jsxs("div", { className: isLeft ? 'conduit-ai-sidebar-enter-left' : 'conduit-ai-sidebar-enter-right', style: {
|
|
87
|
+
position: 'fixed',
|
|
88
|
+
top: 0,
|
|
89
|
+
[position]: 0,
|
|
90
|
+
width: `${width}px`,
|
|
91
|
+
maxWidth: '100vw',
|
|
92
|
+
height: '100vh',
|
|
93
|
+
display: 'flex',
|
|
94
|
+
flexDirection: 'column',
|
|
95
|
+
backgroundColor: 'var(--conduit-ai-sidebar-bg, #ffffff)',
|
|
96
|
+
borderLeft: isLeft ? 'none' : '1px solid var(--conduit-border, #e2e8f0)',
|
|
97
|
+
borderRight: isLeft ? '1px solid var(--conduit-border, #e2e8f0)' : 'none',
|
|
98
|
+
zIndex: 1000,
|
|
99
|
+
fontFamily: "'Inter', system-ui, -apple-system, sans-serif",
|
|
100
|
+
color: 'var(--conduit-fg, #334155)',
|
|
101
|
+
}, children: [_jsxs("div", { style: {
|
|
102
|
+
display: 'flex',
|
|
103
|
+
alignItems: 'center',
|
|
104
|
+
justifyContent: 'space-between',
|
|
105
|
+
padding: '12px 16px',
|
|
106
|
+
borderBottom: '1px solid var(--conduit-border, #e2e8f0)',
|
|
107
|
+
flexShrink: 0,
|
|
108
|
+
}, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' }, children: [_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: [_jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z", fill: "#02018C" }), _jsx("path", { d: "M8 10.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM16 10.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z", fill: "#FFFFFF" }), _jsx("path", { d: "M12 17c-2.21 0-4-1.34-4-3h8c0 1.66-1.79 3-4 3z", fill: "#FF831D" })] }), _jsx("span", { style: { fontWeight: 600, fontSize: '15px' }, children: title })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [messages.length > 0 && (_jsx("button", { onClick: clearHistory, className: "conduit-ai-clear-btn", title: "Clear chat", style: {
|
|
109
|
+
background: 'none',
|
|
110
|
+
border: 'none',
|
|
111
|
+
cursor: 'pointer',
|
|
112
|
+
padding: '4px 8px',
|
|
113
|
+
borderRadius: '6px',
|
|
114
|
+
fontSize: '12px',
|
|
115
|
+
color: 'var(--conduit-fg, #64748b)',
|
|
116
|
+
}, children: "Clear" })), _jsx("button", { onClick: close, title: "Close", style: {
|
|
117
|
+
background: 'none',
|
|
118
|
+
border: 'none',
|
|
119
|
+
cursor: 'pointer',
|
|
120
|
+
padding: '4px',
|
|
121
|
+
borderRadius: '6px',
|
|
122
|
+
color: 'var(--conduit-fg, #64748b)',
|
|
123
|
+
fontSize: '18px',
|
|
124
|
+
lineHeight: 1,
|
|
125
|
+
}, children: "\u00D7" })] })] }), _jsx(ContextBadge, { context: pageContext }), _jsxs("div", { style: {
|
|
126
|
+
flex: 1,
|
|
127
|
+
overflowY: 'auto',
|
|
128
|
+
padding: '16px',
|
|
129
|
+
}, children: [messages.length === 0 && (_jsxs("div", { style: {
|
|
130
|
+
textAlign: 'center',
|
|
131
|
+
padding: '48px 24px',
|
|
132
|
+
color: 'var(--conduit-fg, #94a3b8)',
|
|
133
|
+
fontSize: '14px',
|
|
134
|
+
}, children: [_jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", style: { margin: '0 auto 12px', opacity: 0.5 }, children: _jsx("path", { d: "M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z", fill: "currentColor" }) }), _jsx("p", { style: { margin: '0 0 4px', fontWeight: 500 }, children: "Ask me anything" }), _jsx("p", { style: { margin: 0, fontSize: '13px' }, children: "I can help with D365 entity mapping, metadata queries, and transformation scripts." })] })), messages.map((message, index) => (_jsx(MessageBubble, { message: message, isStreaming: isStreaming && index === messages.length - 1 && message.role === 'assistant' }, message.id))), error && (_jsx("div", { style: {
|
|
135
|
+
margin: '8px 0',
|
|
136
|
+
padding: '8px 12px',
|
|
137
|
+
borderRadius: '8px',
|
|
138
|
+
fontSize: '13px',
|
|
139
|
+
backgroundColor: '#fef2f2',
|
|
140
|
+
color: '#b91c1c',
|
|
141
|
+
border: '1px solid #fecaca',
|
|
142
|
+
}, children: error })), _jsx("div", { ref: messagesEndRef })] }), _jsxs("div", { style: {
|
|
143
|
+
padding: '12px 16px',
|
|
144
|
+
borderTop: '1px solid var(--conduit-border, #e2e8f0)',
|
|
145
|
+
flexShrink: 0,
|
|
146
|
+
}, children: [_jsxs("div", { style: {
|
|
147
|
+
display: 'flex',
|
|
148
|
+
gap: '8px',
|
|
149
|
+
alignItems: 'flex-end',
|
|
150
|
+
}, children: [_jsx("textarea", { ref: inputRef, className: "conduit-ai-input", value: input, onChange: (e) => setInput(e.target.value), onKeyDown: handleKeyDown, placeholder: "Ask about D365 entities, mappings...", disabled: isStreaming, rows: 1, style: {
|
|
151
|
+
flex: 1,
|
|
152
|
+
resize: 'none',
|
|
153
|
+
border: '1px solid var(--conduit-border, #e2e8f0)',
|
|
154
|
+
borderRadius: '8px',
|
|
155
|
+
padding: '8px 12px',
|
|
156
|
+
fontSize: '14px',
|
|
157
|
+
lineHeight: '1.4',
|
|
158
|
+
fontFamily: 'inherit',
|
|
159
|
+
backgroundColor: 'var(--conduit-ai-input-bg, #ffffff)',
|
|
160
|
+
color: 'var(--conduit-fg, #334155)',
|
|
161
|
+
maxHeight: '120px',
|
|
162
|
+
overflowY: 'auto',
|
|
163
|
+
}, onInput: (e) => {
|
|
164
|
+
const el = e.currentTarget;
|
|
165
|
+
el.style.height = 'auto';
|
|
166
|
+
el.style.height = Math.min(el.scrollHeight, 120) + 'px';
|
|
167
|
+
} }), _jsx("button", { className: "conduit-ai-send-btn", onClick: handleSubmit, disabled: !input.trim() || isStreaming, title: "Send message", style: {
|
|
168
|
+
flexShrink: 0,
|
|
169
|
+
width: '36px',
|
|
170
|
+
height: '36px',
|
|
171
|
+
borderRadius: '8px',
|
|
172
|
+
border: 'none',
|
|
173
|
+
cursor: input.trim() && !isStreaming ? 'pointer' : 'default',
|
|
174
|
+
backgroundColor: input.trim() && !isStreaming ? '#FF831D' : '#cbd5e1',
|
|
175
|
+
color: '#ffffff',
|
|
176
|
+
display: 'flex',
|
|
177
|
+
alignItems: 'center',
|
|
178
|
+
justifyContent: 'center',
|
|
179
|
+
transition: 'background-color 0.15s',
|
|
180
|
+
}, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M2.5 8H13.5M13.5 8L9 3.5M13.5 8L9 12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] }), _jsx("div", { style: {
|
|
181
|
+
marginTop: '6px',
|
|
182
|
+
fontSize: '11px',
|
|
183
|
+
color: 'var(--conduit-fg, #94a3b8)',
|
|
184
|
+
opacity: 0.6,
|
|
185
|
+
}, children: "Shift+Enter for new line" })] })] }));
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=ChatSidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatSidebar.js","sourceRoot":"","sources":["../src/ChatSidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ChatToggleProps {
|
|
2
|
+
/** Which corner to place the toggle button. Defaults to "bottom-right". */
|
|
3
|
+
position?: 'bottom-right' | 'bottom-left';
|
|
4
|
+
/** Distance from the edge in pixels. Defaults to 24. */
|
|
5
|
+
offset?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function ChatToggle({ position, offset, }: ChatToggleProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
|
+
//# sourceMappingURL=ChatToggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatToggle.d.ts","sourceRoot":"","sources":["../src/ChatToggle.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,CAAA;IACzC,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAsBD,wBAAgB,UAAU,CAAC,EACzB,QAAyB,EACzB,MAAW,GACZ,EAAE,eAAe,kDA8CjB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { useAIChat } from './AIChatProvider';
|
|
4
|
+
const TOGGLE_STYLE_ID = 'conduit-ai-toggle-styles';
|
|
5
|
+
function ensureToggleStyles() {
|
|
6
|
+
if (typeof document === 'undefined')
|
|
7
|
+
return;
|
|
8
|
+
if (document.getElementById(TOGGLE_STYLE_ID))
|
|
9
|
+
return;
|
|
10
|
+
const style = document.createElement('style');
|
|
11
|
+
style.id = TOGGLE_STYLE_ID;
|
|
12
|
+
style.textContent = `
|
|
13
|
+
.conduit-ai-toggle:hover {
|
|
14
|
+
transform: scale(1.08);
|
|
15
|
+
box-shadow: 0 6px 20px rgba(255, 131, 29, 0.4) !important;
|
|
16
|
+
}
|
|
17
|
+
.conduit-ai-toggle:active {
|
|
18
|
+
transform: scale(0.95);
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
document.head.appendChild(style);
|
|
22
|
+
}
|
|
23
|
+
export function ChatToggle({ position = 'bottom-right', offset = 24, }) {
|
|
24
|
+
const { toggle, isOpen } = useAIChat();
|
|
25
|
+
useEffect(() => ensureToggleStyles(), []);
|
|
26
|
+
// Hide the toggle when the sidebar is open
|
|
27
|
+
if (isOpen)
|
|
28
|
+
return null;
|
|
29
|
+
const isRight = position === 'bottom-right';
|
|
30
|
+
return (_jsx("button", { className: "conduit-ai-toggle", onClick: toggle, title: "Open AI chat", style: {
|
|
31
|
+
position: 'fixed',
|
|
32
|
+
bottom: `${offset}px`,
|
|
33
|
+
[isRight ? 'right' : 'left']: `${offset}px`,
|
|
34
|
+
width: '52px',
|
|
35
|
+
height: '52px',
|
|
36
|
+
borderRadius: '50%',
|
|
37
|
+
border: 'none',
|
|
38
|
+
cursor: 'pointer',
|
|
39
|
+
backgroundColor: '#FF831D',
|
|
40
|
+
color: '#ffffff',
|
|
41
|
+
boxShadow: '0 4px 12px rgba(255, 131, 29, 0.3)',
|
|
42
|
+
display: 'flex',
|
|
43
|
+
alignItems: 'center',
|
|
44
|
+
justifyContent: 'center',
|
|
45
|
+
zIndex: 999,
|
|
46
|
+
transition: 'transform 0.15s, box-shadow 0.15s',
|
|
47
|
+
}, children: _jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: [_jsx("path", { d: "M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2z", fill: "currentColor" }), _jsx("circle", { cx: "8", cy: "10", r: "1", fill: "#02018C" }), _jsx("circle", { cx: "12", cy: "10", r: "1", fill: "#02018C" }), _jsx("circle", { cx: "16", cy: "10", r: "1", fill: "#02018C" })] }) }));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=ChatToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatToggle.js","sourceRoot":"","sources":["../src/ChatToggle.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAS5C,MAAM,eAAe,GAAG,0BAA0B,CAAA;AAElD,SAAS,kBAAkB;IACzB,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAM;IAC3C,IAAI,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC;QAAE,OAAM;IAEpD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;IAC7C,KAAK,CAAC,EAAE,GAAG,eAAe,CAAA;IAC1B,KAAK,CAAC,WAAW,GAAG;;;;;;;;GAQnB,CAAA;IACD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;AAClC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,GAAG,cAAc,EACzB,MAAM,GAAG,EAAE,GACK;IAChB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAA;IAEtC,SAAS,CAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAA;IAEzC,2CAA2C;IAC3C,IAAI,MAAM;QAAE,OAAO,IAAI,CAAA;IAEvB,MAAM,OAAO,GAAG,QAAQ,KAAK,cAAc,CAAA;IAE3C,OAAO,CACL,iBACE,SAAS,EAAC,mBAAmB,EAC7B,OAAO,EAAE,MAAM,EACf,KAAK,EAAC,cAAc,EACpB,KAAK,EAAE;YACL,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,GAAG,MAAM,IAAI;YACrB,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,IAAI;YAC3C,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,MAAM;YACd,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,SAAS;YACjB,eAAe,EAAE,SAAS;YAC1B,KAAK,EAAE,SAAS;YAChB,SAAS,EAAE,oCAAoC;YAC/C,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,mCAAmC;SAChD,YAGD,eAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,aACzD,eACE,CAAC,EAAC,mEAAmE,EACrE,IAAI,EAAC,cAAc,GACnB,EACF,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,GAAG,EAAC,IAAI,EAAC,SAAS,GAAG,EAC9C,iBAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,GAAG,EAAC,IAAI,EAAC,SAAS,GAAG,EAC/C,iBAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,GAAG,EAAC,IAAI,EAAC,SAAS,GAAG,IAC3C,GACC,CACV,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PageContext } from '../types';
|
|
2
|
+
export interface ContextBadgeProps {
|
|
3
|
+
context: PageContext | null;
|
|
4
|
+
}
|
|
5
|
+
export declare function ContextBadge({ context }: ContextBadgeProps): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
//# sourceMappingURL=ContextBadge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContextBadge.d.ts","sourceRoot":"","sources":["../../src/components/ContextBadge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;CAC5B;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,iBAAiB,kDAmD1D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function ContextBadge({ context }) {
|
|
3
|
+
if (!context)
|
|
4
|
+
return null;
|
|
5
|
+
const label = context.entity
|
|
6
|
+
? `Viewing: ${context.entity}`
|
|
7
|
+
: context.summary
|
|
8
|
+
? context.summary
|
|
9
|
+
: `Page: ${context.view}`;
|
|
10
|
+
return (_jsxs("div", { style: {
|
|
11
|
+
display: 'flex',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
gap: '6px',
|
|
14
|
+
padding: '6px 12px',
|
|
15
|
+
fontSize: '12px',
|
|
16
|
+
color: 'var(--conduit-fg, #64748b)',
|
|
17
|
+
backgroundColor: 'var(--conduit-bg-muted, #f1f5f9)',
|
|
18
|
+
borderBottom: '1px solid var(--conduit-border, #e2e8f0)',
|
|
19
|
+
}, children: [_jsxs("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", style: { flexShrink: 0, opacity: 0.7 }, children: [_jsx("circle", { cx: "8", cy: "8", r: "6", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }), _jsx("circle", { cx: "8", cy: "8", r: "2", fill: "#FF831D" })] }), _jsx("span", { style: {
|
|
20
|
+
overflow: 'hidden',
|
|
21
|
+
textOverflow: 'ellipsis',
|
|
22
|
+
whiteSpace: 'nowrap',
|
|
23
|
+
}, children: label })] }));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=ContextBadge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContextBadge.js","sourceRoot":"","sources":["../../src/components/ContextBadge.tsx"],"names":[],"mappings":";AAMA,MAAM,UAAU,YAAY,CAAC,EAAE,OAAO,EAAqB;IACzD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAEzB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM;QAC1B,CAAC,CAAC,YAAY,OAAO,CAAC,MAAM,EAAE;QAC9B,CAAC,CAAC,OAAO,CAAC,OAAO;YACf,CAAC,CAAC,OAAO,CAAC,OAAO;YACjB,CAAC,CAAC,SAAS,OAAO,CAAC,IAAI,EAAE,CAAA;IAE7B,OAAO,CACL,eACE,KAAK,EAAE;YACL,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;YACpB,GAAG,EAAE,KAAK;YACV,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,4BAA4B;YACnC,eAAe,EAAE,kCAAkC;YACnD,YAAY,EAAE,0CAA0C;SACzD,aAGD,eACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,aAEtC,iBACE,EAAE,EAAC,GAAG,EACN,EAAE,EAAC,GAAG,EACN,CAAC,EAAC,GAAG,EACL,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,IAAI,EAAC,MAAM,GACX,EACF,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,CAAC,EAAC,GAAG,EAAC,IAAI,EAAC,SAAS,GAAG,IACzC,EACN,eACE,KAAK,EAAE;oBACL,QAAQ,EAAE,QAAQ;oBAClB,YAAY,EAAE,UAAU;oBACxB,UAAU,EAAE,QAAQ;iBACrB,YAEA,KAAK,GACD,IACH,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownRenderer.d.ts","sourceRoot":"","sources":["../../src/components/MarkdownRenderer.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAA;CAChB;AA4JD,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE,qBAAqB,2CAQlE"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback } from 'react';
|
|
3
|
+
import ReactMarkdown from 'react-markdown';
|
|
4
|
+
import remarkGfm from 'remark-gfm';
|
|
5
|
+
function CodeBlock({ children, className }) {
|
|
6
|
+
const [copied, setCopied] = useState(false);
|
|
7
|
+
const language = className?.replace('language-', '') ?? '';
|
|
8
|
+
const handleCopy = useCallback(() => {
|
|
9
|
+
navigator.clipboard.writeText(children).then(() => {
|
|
10
|
+
setCopied(true);
|
|
11
|
+
setTimeout(() => setCopied(false), 2000);
|
|
12
|
+
});
|
|
13
|
+
}, [children]);
|
|
14
|
+
return (_jsxs("div", { style: {
|
|
15
|
+
position: 'relative',
|
|
16
|
+
margin: '8px 0',
|
|
17
|
+
borderRadius: '8px',
|
|
18
|
+
overflow: 'hidden',
|
|
19
|
+
border: '1px solid var(--conduit-border, #e2e8f0)',
|
|
20
|
+
}, children: [language && (_jsxs("div", { style: {
|
|
21
|
+
display: 'flex',
|
|
22
|
+
justifyContent: 'space-between',
|
|
23
|
+
alignItems: 'center',
|
|
24
|
+
padding: '4px 12px',
|
|
25
|
+
fontSize: '11px',
|
|
26
|
+
fontWeight: 500,
|
|
27
|
+
color: 'var(--conduit-fg, #64748b)',
|
|
28
|
+
backgroundColor: 'var(--conduit-bg-muted, #f1f5f9)',
|
|
29
|
+
borderBottom: '1px solid var(--conduit-border, #e2e8f0)',
|
|
30
|
+
}, children: [_jsx("span", { children: language }), _jsx("button", { onClick: handleCopy, style: {
|
|
31
|
+
background: 'none',
|
|
32
|
+
border: 'none',
|
|
33
|
+
cursor: 'pointer',
|
|
34
|
+
fontSize: '11px',
|
|
35
|
+
color: 'var(--conduit-fg, #64748b)',
|
|
36
|
+
padding: '2px 6px',
|
|
37
|
+
borderRadius: '4px',
|
|
38
|
+
}, children: copied ? 'Copied!' : 'Copy' })] })), _jsx("pre", { style: {
|
|
39
|
+
margin: 0,
|
|
40
|
+
padding: '12px',
|
|
41
|
+
overflow: 'auto',
|
|
42
|
+
fontSize: '13px',
|
|
43
|
+
lineHeight: '1.5',
|
|
44
|
+
backgroundColor: 'var(--conduit-bg-muted, #f1f5f9)',
|
|
45
|
+
color: 'var(--conduit-fg, #334155)',
|
|
46
|
+
}, children: _jsx("code", { children: children }) })] }));
|
|
47
|
+
}
|
|
48
|
+
const components = {
|
|
49
|
+
code({ children, className, ...props }) {
|
|
50
|
+
// Block code (inside <pre>) vs inline code
|
|
51
|
+
const isInline = !className;
|
|
52
|
+
if (isInline) {
|
|
53
|
+
return (_jsx("code", { style: {
|
|
54
|
+
padding: '2px 5px',
|
|
55
|
+
borderRadius: '4px',
|
|
56
|
+
fontSize: '13px',
|
|
57
|
+
backgroundColor: 'var(--conduit-bg-muted, #f1f5f9)',
|
|
58
|
+
border: '1px solid var(--conduit-border, #e2e8f0)',
|
|
59
|
+
}, ...props, children: children }));
|
|
60
|
+
}
|
|
61
|
+
return _jsx(CodeBlock, { className: className, children: String(children).replace(/\n$/, '') });
|
|
62
|
+
},
|
|
63
|
+
pre({ children }) {
|
|
64
|
+
// react-markdown wraps code blocks in <pre><code>. We handle
|
|
65
|
+
// rendering in the code component above, so just pass through.
|
|
66
|
+
return _jsx(_Fragment, { children: children });
|
|
67
|
+
},
|
|
68
|
+
table({ children }) {
|
|
69
|
+
return (_jsx("div", { style: { overflowX: 'auto', margin: '8px 0' }, children: _jsx("table", { style: {
|
|
70
|
+
borderCollapse: 'collapse',
|
|
71
|
+
width: '100%',
|
|
72
|
+
fontSize: '13px',
|
|
73
|
+
}, children: children }) }));
|
|
74
|
+
},
|
|
75
|
+
th({ children }) {
|
|
76
|
+
return (_jsx("th", { style: {
|
|
77
|
+
padding: '6px 10px',
|
|
78
|
+
textAlign: 'left',
|
|
79
|
+
borderBottom: '2px solid var(--conduit-border, #e2e8f0)',
|
|
80
|
+
fontWeight: 600,
|
|
81
|
+
}, children: children }));
|
|
82
|
+
},
|
|
83
|
+
td({ children }) {
|
|
84
|
+
return (_jsx("td", { style: {
|
|
85
|
+
padding: '6px 10px',
|
|
86
|
+
borderBottom: '1px solid var(--conduit-border, #e2e8f0)',
|
|
87
|
+
}, children: children }));
|
|
88
|
+
},
|
|
89
|
+
p({ children }) {
|
|
90
|
+
return _jsx("p", { style: { margin: '6px 0' }, children: children });
|
|
91
|
+
},
|
|
92
|
+
ul({ children }) {
|
|
93
|
+
return _jsx("ul", { style: { margin: '6px 0', paddingLeft: '20px' }, children: children });
|
|
94
|
+
},
|
|
95
|
+
ol({ children }) {
|
|
96
|
+
return _jsx("ol", { style: { margin: '6px 0', paddingLeft: '20px' }, children: children });
|
|
97
|
+
},
|
|
98
|
+
li({ children }) {
|
|
99
|
+
return _jsx("li", { style: { margin: '2px 0' }, children: children });
|
|
100
|
+
},
|
|
101
|
+
strong({ children }) {
|
|
102
|
+
return _jsx("strong", { style: { fontWeight: 600 }, children: children });
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
export function MarkdownRenderer({ content }) {
|
|
106
|
+
return (_jsx("div", { style: { overflowWrap: 'break-word', wordBreak: 'break-word' }, children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: components, children: content }) }));
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=MarkdownRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownRenderer.js","sourceRoot":"","sources":["../../src/components/MarkdownRenderer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ChatMessage } from '../types';
|
|
2
|
+
export interface MessageBubbleProps {
|
|
3
|
+
message: ChatMessage;
|
|
4
|
+
isStreaming?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function MessageBubble({ message, isStreaming }: MessageBubbleProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=MessageBubble.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageBubble.d.ts","sourceRoot":"","sources":["../../src/components/MessageBubble.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAG3C,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,WAAW,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,kBAAkB,2CAiDzE"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { MarkdownRenderer } from './MarkdownRenderer';
|
|
3
|
+
export function MessageBubble({ message, isStreaming }) {
|
|
4
|
+
const isUser = message.role === 'user';
|
|
5
|
+
return (_jsx("div", { style: {
|
|
6
|
+
display: 'flex',
|
|
7
|
+
justifyContent: isUser ? 'flex-end' : 'flex-start',
|
|
8
|
+
marginBottom: '12px',
|
|
9
|
+
paddingLeft: isUser ? '32px' : '0',
|
|
10
|
+
paddingRight: isUser ? '0' : '32px',
|
|
11
|
+
}, children: _jsx("div", { style: {
|
|
12
|
+
maxWidth: '100%',
|
|
13
|
+
padding: '10px 14px',
|
|
14
|
+
borderRadius: '12px',
|
|
15
|
+
fontSize: '14px',
|
|
16
|
+
lineHeight: '1.5',
|
|
17
|
+
...(isUser
|
|
18
|
+
? {
|
|
19
|
+
backgroundColor: 'var(--conduit-ai-user-bg, #eff6ff)',
|
|
20
|
+
color: 'var(--conduit-ai-user-fg, #1e40af)',
|
|
21
|
+
borderBottomRightRadius: '4px',
|
|
22
|
+
}
|
|
23
|
+
: {
|
|
24
|
+
backgroundColor: 'var(--conduit-ai-assistant-bg, #f8fafc)',
|
|
25
|
+
color: 'var(--conduit-fg, #334155)',
|
|
26
|
+
borderBottomLeftRadius: '4px',
|
|
27
|
+
border: '1px solid var(--conduit-border, #e2e8f0)',
|
|
28
|
+
}),
|
|
29
|
+
}, children: isUser ? (_jsx("span", { style: { whiteSpace: 'pre-wrap' }, children: message.content })) : (_jsxs(_Fragment, { children: [message.content ? (_jsx(MarkdownRenderer, { content: message.content })) : isStreaming ? (_jsx(StreamingDots, {})) : null, isStreaming && message.content && _jsx(StreamingCursor, {})] })) }) }));
|
|
30
|
+
}
|
|
31
|
+
function StreamingDots() {
|
|
32
|
+
return (_jsx("div", { style: { display: 'flex', gap: '4px', padding: '4px 0' }, children: [0, 1, 2].map((i) => (_jsx("div", { style: {
|
|
33
|
+
width: '6px',
|
|
34
|
+
height: '6px',
|
|
35
|
+
borderRadius: '50%',
|
|
36
|
+
backgroundColor: '#FF831D',
|
|
37
|
+
animation: `conduit-ai-dot 1.2s ${i * 0.2}s ease-in-out infinite`,
|
|
38
|
+
} }, i))) }));
|
|
39
|
+
}
|
|
40
|
+
function StreamingCursor() {
|
|
41
|
+
return (_jsx("span", { style: {
|
|
42
|
+
display: 'inline-block',
|
|
43
|
+
width: '2px',
|
|
44
|
+
height: '14px',
|
|
45
|
+
backgroundColor: '#FF831D',
|
|
46
|
+
marginLeft: '2px',
|
|
47
|
+
verticalAlign: 'text-bottom',
|
|
48
|
+
animation: 'conduit-ai-blink 0.8s step-end infinite',
|
|
49
|
+
} }));
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=MessageBubble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageBubble.js","sourceRoot":"","sources":["../../src/components/MessageBubble.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAOrD,MAAM,UAAU,aAAa,CAAC,EAAE,OAAO,EAAE,WAAW,EAAsB;IACxE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM,CAAA;IAEtC,OAAO,CACL,cACE,KAAK,EAAE;YACL,OAAO,EAAE,MAAM;YACf,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;YAClD,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG;YAClC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM;SACpC,YAED,cACE,KAAK,EAAE;gBACL,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,WAAW;gBACpB,YAAY,EAAE,MAAM;gBACpB,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,KAAK;gBACjB,GAAG,CAAC,MAAM;oBACR,CAAC,CAAC;wBACE,eAAe,EAAE,oCAAoC;wBACrD,KAAK,EAAE,oCAAoC;wBAC3C,uBAAuB,EAAE,KAAK;qBAC/B;oBACH,CAAC,CAAC;wBACE,eAAe,EAAE,yCAAyC;wBAC1D,KAAK,EAAE,4BAA4B;wBACnC,sBAAsB,EAAE,KAAK;wBAC7B,MAAM,EAAE,0CAA0C;qBACnD,CAAC;aACP,YAEA,MAAM,CAAC,CAAC,CAAC,CACR,eAAM,KAAK,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,YAAG,OAAO,CAAC,OAAO,GAAQ,CAClE,CAAC,CAAC,CAAC,CACF,8BACG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CACjB,KAAC,gBAAgB,IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,GAAI,CAC/C,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAChB,KAAC,aAAa,KAAG,CAClB,CAAC,CAAC,CAAC,IAAI,EACP,WAAW,IAAI,OAAO,CAAC,OAAO,IAAI,KAAC,eAAe,KAAG,IACrD,CACJ,GACG,GACF,CACP,CAAA;AACH,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,CACL,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAC1D,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACpB,cAEE,KAAK,EAAE;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,KAAK;gBACb,YAAY,EAAE,KAAK;gBACnB,eAAe,EAAE,SAAS;gBAC1B,SAAS,EAAE,uBAAuB,CAAC,GAAG,GAAG,wBAAwB;aAClE,IAPI,CAAC,CAQN,CACH,CAAC,GACE,CACP,CAAA;AACH,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,CACL,eACE,KAAK,EAAE;YACL,OAAO,EAAE,cAAc;YACvB,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,MAAM;YACd,eAAe,EAAE,SAAS;YAC1B,UAAU,EAAE,KAAK;YACjB,aAAa,EAAE,aAAa;YAC5B,SAAS,EAAE,yCAAyC;SACrD,GACD,CACH,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { AIChatProvider, useAIChat, usePageContext } from './AIChatProvider';
|
|
2
|
+
export type { AIChatProviderProps } from './AIChatProvider';
|
|
3
|
+
export { ChatSidebar } from './ChatSidebar';
|
|
4
|
+
export type { ChatSidebarProps } from './ChatSidebar';
|
|
5
|
+
export { ChatToggle } from './ChatToggle';
|
|
6
|
+
export type { ChatToggleProps } from './ChatToggle';
|
|
7
|
+
export { MessageBubble } from './components/MessageBubble';
|
|
8
|
+
export type { MessageBubbleProps } from './components/MessageBubble';
|
|
9
|
+
export { MarkdownRenderer } from './components/MarkdownRenderer';
|
|
10
|
+
export type { MarkdownRendererProps } from './components/MarkdownRenderer';
|
|
11
|
+
export { ContextBadge } from './components/ContextBadge';
|
|
12
|
+
export type { ContextBadgeProps } from './components/ContextBadge';
|
|
13
|
+
export type { ChatMessage, MessageRole, PageContext, AIChatConfig, UseAIChatReturn, UsePageContextReturn, ChatRequest, } from './types';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC5E,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAG3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGnD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAEpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,YAAY,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAE1E,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAGlE,YAAY,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,WAAW,GACZ,MAAM,SAAS,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Provider & hooks
|
|
2
|
+
export { AIChatProvider, useAIChat, usePageContext } from './AIChatProvider';
|
|
3
|
+
// Components
|
|
4
|
+
export { ChatSidebar } from './ChatSidebar';
|
|
5
|
+
export { ChatToggle } from './ChatToggle';
|
|
6
|
+
// Sub-components (for custom layouts)
|
|
7
|
+
export { MessageBubble } from './components/MessageBubble';
|
|
8
|
+
export { MarkdownRenderer } from './components/MarkdownRenderer';
|
|
9
|
+
export { ContextBadge } from './components/ContextBadge';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAG5E,aAAa;AACb,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAG3C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAGzC,sCAAsC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAG1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAGhE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** Role of a chat message sender. */
|
|
2
|
+
export type MessageRole = 'user' | 'assistant';
|
|
3
|
+
/** A single message in the chat history. */
|
|
4
|
+
export interface ChatMessage {
|
|
5
|
+
id: string;
|
|
6
|
+
role: MessageRole;
|
|
7
|
+
content: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Page context registered by consumer apps via usePageContext().
|
|
12
|
+
* Sent with every chat message so the AI knows what the user is viewing.
|
|
13
|
+
*/
|
|
14
|
+
export interface PageContext {
|
|
15
|
+
/** Current view/page identifier (e.g. "field-mapping", "entity-detail") */
|
|
16
|
+
view: string;
|
|
17
|
+
/** Primary entity or object the user is viewing */
|
|
18
|
+
entity?: string;
|
|
19
|
+
/** Human-readable summary of what's on screen */
|
|
20
|
+
summary?: string;
|
|
21
|
+
/** Arbitrary structured data relevant to the current view */
|
|
22
|
+
data?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/** Configuration for the AIChatProvider. */
|
|
25
|
+
export interface AIChatConfig {
|
|
26
|
+
/** Name of the consuming app (e.g. "MigrationMapper", "Scripter") */
|
|
27
|
+
appName: string;
|
|
28
|
+
/** API endpoint for chat requests. Defaults to "/api/ai/chat" */
|
|
29
|
+
endpoint?: string;
|
|
30
|
+
/** Placeholder text for the input field */
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
/** Maximum number of messages to retain in history (sent to backend). Defaults to 50. */
|
|
33
|
+
maxHistory?: number;
|
|
34
|
+
}
|
|
35
|
+
/** Shape of the value returned by useAIChat(). */
|
|
36
|
+
export interface UseAIChatReturn {
|
|
37
|
+
messages: ChatMessage[];
|
|
38
|
+
isStreaming: boolean;
|
|
39
|
+
isOpen: boolean;
|
|
40
|
+
error: string | null;
|
|
41
|
+
sendMessage: (content: string) => void;
|
|
42
|
+
clearHistory: () => void;
|
|
43
|
+
toggle: () => void;
|
|
44
|
+
open: () => void;
|
|
45
|
+
close: () => void;
|
|
46
|
+
}
|
|
47
|
+
/** Shape of the value returned by usePageContext(). */
|
|
48
|
+
export interface UsePageContextReturn {
|
|
49
|
+
pageContext: PageContext | null;
|
|
50
|
+
setPageContext: (context: PageContext | null) => void;
|
|
51
|
+
}
|
|
52
|
+
/** Request body sent to the AI backend. */
|
|
53
|
+
export interface ChatRequest {
|
|
54
|
+
message: string;
|
|
55
|
+
history: ChatMessage[];
|
|
56
|
+
pageContext: PageContext | null;
|
|
57
|
+
appName: string;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,CAAA;AAE9C,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,WAAW,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED,4CAA4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAA;IACf,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,kDAAkD;AAClD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,WAAW,EAAE,OAAO,CAAA;IACpB,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,cAAc,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;CACtD;AAED,2CAA2C;AAC3C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,OAAO,EAAE,MAAM,CAAA;CAChB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@conduit-d365/ai-chat",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared AI chat sidebar for the Conduit suite",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"assets"
|
|
11
|
+
],
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react": "^18.0 || ^19.0",
|
|
21
|
+
"react-dom": "^18.0 || ^19.0"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"react-markdown": "^9.0",
|
|
25
|
+
"remark-gfm": "^4.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/react": "^19.0",
|
|
29
|
+
"react": "^19.0",
|
|
30
|
+
"react-dom": "^19.0",
|
|
31
|
+
"typescript": "^5.5"
|
|
32
|
+
}
|
|
33
|
+
}
|