@clawjedi/paperclip-plugin-chat 1.0.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.
@@ -0,0 +1,38 @@
1
+ import { z } from "@paperclipai/plugin-sdk";
2
+ var manifest_default = {
3
+ id: "paperclip.chat",
4
+ displayName: "Chat",
5
+ description: "Real-time agent chat for Paperclip",
6
+ version: "1.0.0",
7
+ category: "ui",
8
+ entrypoints: {
9
+ worker: "dist/worker.js",
10
+ ui: "dist/ui"
11
+ },
12
+ instanceConfigSchema: z.object({}),
13
+ requiredCapabilities: [
14
+ "agents.read",
15
+ "agent.sessions.create",
16
+ "agent.sessions.send",
17
+ "agent.sessions.close",
18
+ "agent.sessions.list",
19
+ "plugin.state.read",
20
+ "plugin.state.write",
21
+ "plugin.streams",
22
+ "events.subscribe"
23
+ ],
24
+ ui: {
25
+ slots: [
26
+ {
27
+ type: "page",
28
+ path: "/chat",
29
+ component: "ChatPage",
30
+ displayName: "Chat"
31
+ }
32
+ ]
33
+ }
34
+ };
35
+ export {
36
+ manifest_default as default
37
+ };
38
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/manifest.ts"],
4
+ "sourcesContent": ["import { z } from \"@paperclipai/plugin-sdk\";\n\nexport default {\n id: \"paperclip.chat\",\n displayName: \"Chat\",\n description: \"Real-time agent chat for Paperclip\",\n version: \"1.0.0\",\n category: \"ui\" as const,\n\n entrypoints: {\n worker: \"dist/worker.js\",\n ui: \"dist/ui\",\n },\n\n instanceConfigSchema: z.object({}),\n\n requiredCapabilities: [\n \"agents.read\",\n \"agent.sessions.create\",\n \"agent.sessions.send\",\n \"agent.sessions.close\",\n \"agent.sessions.list\",\n \"plugin.state.read\",\n \"plugin.state.write\",\n \"plugin.streams\",\n \"events.subscribe\",\n ],\n\n ui: {\n slots: [\n {\n type: \"page\" as const,\n path: \"/chat\",\n component: \"ChatPage\",\n displayName: \"Chat\",\n },\n ],\n },\n};\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAElB,IAAO,mBAAQ;AAAA,EACb,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,aAAa;AAAA,EACb,SAAS;AAAA,EACT,UAAU;AAAA,EAEV,aAAa;AAAA,IACX,QAAQ;AAAA,IACR,IAAI;AAAA,EACN;AAAA,EAEA,sBAAsB,EAAE,OAAO,CAAC,CAAC;AAAA,EAEjC,sBAAsB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,IAAI;AAAA,IACF,OAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,WAAW;AAAA,QACX,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,489 @@
1
+ // src/ui/ChatPage.tsx
2
+ import { useState, useRef, useEffect, useCallback } from "react";
3
+ import {
4
+ usePluginData,
5
+ usePluginAction,
6
+ usePluginStream,
7
+ useHostContext,
8
+ usePluginToast
9
+ } from "@paperclipai/plugin-sdk/ui";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ function ChatPage() {
12
+ const ctx = useHostContext();
13
+ const companyId = ctx.companyId;
14
+ const toast = usePluginToast();
15
+ const [selectedAgentId, setSelectedAgentId] = useState("");
16
+ const [activeSession, setActiveSession] = useState(null);
17
+ const [messages, setMessages] = useState([]);
18
+ const [streamingContent, setStreamingContent] = useState("");
19
+ const [streamingMsgId, setStreamingMsgId] = useState(null);
20
+ const [input, setInput] = useState("");
21
+ const [sending, setSending] = useState(false);
22
+ const messagesEndRef = useRef(null);
23
+ const inputRef = useRef(null);
24
+ const { data: agentsData, loading: agentsLoading } = usePluginData("list-agents", { companyId });
25
+ const { data: sessionsData } = usePluginData("list-sessions", { companyId });
26
+ const createSession = usePluginAction("create-session");
27
+ const sendMessage = usePluginAction("send-message");
28
+ const closeSession = usePluginAction("close-session");
29
+ const { events: streamEvents } = usePluginStream(
30
+ activeSession ? `chat-${activeSession.sessionId}` : "__inactive__",
31
+ { companyId: companyId ?? void 0 }
32
+ );
33
+ useEffect(() => {
34
+ if (!streamEvents || streamEvents.length === 0) return;
35
+ const latest = streamEvents[streamEvents.length - 1];
36
+ if (latest.type === "assistant-chunk" && latest.fullContent) {
37
+ setStreamingContent(latest.fullContent);
38
+ setStreamingMsgId(latest.messageId ?? null);
39
+ } else if (latest.type === "assistant-done" && latest.message) {
40
+ setMessages((prev) => [...prev, latest.message]);
41
+ setStreamingContent("");
42
+ setStreamingMsgId(null);
43
+ setSending(false);
44
+ } else if (latest.type === "assistant-error") {
45
+ toast({
46
+ title: "Error",
47
+ body: latest.error ?? "Unknown error",
48
+ tone: "error"
49
+ });
50
+ setStreamingContent("");
51
+ setStreamingMsgId(null);
52
+ setSending(false);
53
+ } else if (latest.type === "user-message" && latest.message) {
54
+ setMessages((prev) => {
55
+ if (prev.some((m) => m.id === latest.message.id)) return prev;
56
+ return [...prev, latest.message];
57
+ });
58
+ }
59
+ }, [streamEvents, toast]);
60
+ useEffect(() => {
61
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
62
+ }, [messages, streamingContent]);
63
+ const { data: historyData } = usePluginData(
64
+ "chat-history",
65
+ {
66
+ companyId,
67
+ sessionId: activeSession?.sessionId ?? ""
68
+ }
69
+ );
70
+ useEffect(() => {
71
+ if (historyData?.messages) {
72
+ setMessages(historyData.messages);
73
+ }
74
+ }, [historyData]);
75
+ const handleNewChat = useCallback(async () => {
76
+ if (!selectedAgentId || !companyId) return;
77
+ try {
78
+ const session = await createSession({
79
+ agentId: selectedAgentId,
80
+ companyId
81
+ });
82
+ setActiveSession(session);
83
+ setMessages([]);
84
+ setStreamingContent("");
85
+ inputRef.current?.focus();
86
+ } catch (err) {
87
+ toast({
88
+ title: "Failed to create session",
89
+ body: String(err),
90
+ tone: "error"
91
+ });
92
+ }
93
+ }, [selectedAgentId, companyId, createSession, toast]);
94
+ const handleSend = useCallback(async () => {
95
+ if (!input.trim() || !activeSession || !companyId || sending) return;
96
+ const content = input.trim();
97
+ setInput("");
98
+ setSending(true);
99
+ try {
100
+ await sendMessage({
101
+ sessionId: activeSession.sessionId,
102
+ companyId,
103
+ content
104
+ });
105
+ } catch (err) {
106
+ toast({
107
+ title: "Failed to send message",
108
+ body: String(err),
109
+ tone: "error"
110
+ });
111
+ setSending(false);
112
+ }
113
+ }, [input, activeSession, companyId, sending, sendMessage, toast]);
114
+ const handleCloseSession = useCallback(async () => {
115
+ if (!activeSession || !companyId) return;
116
+ try {
117
+ await closeSession({
118
+ sessionId: activeSession.sessionId,
119
+ companyId
120
+ });
121
+ setActiveSession(null);
122
+ setMessages([]);
123
+ toast({ title: "Session closed", tone: "info" });
124
+ } catch (err) {
125
+ toast({
126
+ title: "Failed to close session",
127
+ body: String(err),
128
+ tone: "error"
129
+ });
130
+ }
131
+ }, [activeSession, companyId, closeSession, toast]);
132
+ const handleResumeSession = useCallback(
133
+ (session) => {
134
+ setActiveSession(session);
135
+ setSelectedAgentId(session.agentId);
136
+ },
137
+ []
138
+ );
139
+ const handleKeyDown = useCallback(
140
+ (e) => {
141
+ if (e.key === "Enter" && !e.shiftKey) {
142
+ e.preventDefault();
143
+ handleSend();
144
+ }
145
+ },
146
+ [handleSend]
147
+ );
148
+ const agents = agentsData?.agents ?? [];
149
+ const activeSessions = sessionsData?.sessions ?? [];
150
+ return /* @__PURE__ */ jsxs("div", { style: styles.container, children: [
151
+ /* @__PURE__ */ jsxs("div", { style: styles.sidebar, children: [
152
+ /* @__PURE__ */ jsx("div", { style: styles.sidebarHeader, children: /* @__PURE__ */ jsx("h2", { style: styles.sidebarTitle, children: "Chat" }) }),
153
+ /* @__PURE__ */ jsxs("div", { style: styles.newChatSection, children: [
154
+ /* @__PURE__ */ jsxs(
155
+ "select",
156
+ {
157
+ value: selectedAgentId,
158
+ onChange: (e) => setSelectedAgentId(e.target.value),
159
+ style: styles.select,
160
+ disabled: agentsLoading,
161
+ children: [
162
+ /* @__PURE__ */ jsx("option", { value: "", children: "Select an agent..." }),
163
+ agents.filter((a) => a.status !== "paused").map((agent) => /* @__PURE__ */ jsxs("option", { value: agent.id, children: [
164
+ agent.name,
165
+ agent.title ? ` \u2014 ${agent.title}` : ""
166
+ ] }, agent.id))
167
+ ]
168
+ }
169
+ ),
170
+ /* @__PURE__ */ jsx(
171
+ "button",
172
+ {
173
+ onClick: handleNewChat,
174
+ disabled: !selectedAgentId || !companyId,
175
+ style: {
176
+ ...styles.button,
177
+ ...!selectedAgentId ? styles.buttonDisabled : {}
178
+ },
179
+ children: "New Chat"
180
+ }
181
+ )
182
+ ] }),
183
+ activeSessions.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles.sessionsList, children: [
184
+ /* @__PURE__ */ jsx("h3", { style: styles.sessionsTitle, children: "Active Sessions" }),
185
+ activeSessions.map((session) => /* @__PURE__ */ jsxs(
186
+ "button",
187
+ {
188
+ onClick: () => handleResumeSession(session),
189
+ style: {
190
+ ...styles.sessionItem,
191
+ ...activeSession?.sessionId === session.sessionId ? styles.sessionItemActive : {}
192
+ },
193
+ children: [
194
+ /* @__PURE__ */ jsx("span", { style: styles.sessionAgent, children: session.agentName }),
195
+ /* @__PURE__ */ jsx("span", { style: styles.sessionTime, children: new Date(session.createdAt).toLocaleTimeString() })
196
+ ]
197
+ },
198
+ session.sessionId
199
+ ))
200
+ ] })
201
+ ] }),
202
+ /* @__PURE__ */ jsx("div", { style: styles.main, children: !activeSession ? /* @__PURE__ */ jsxs("div", { style: styles.emptyState, children: [
203
+ /* @__PURE__ */ jsx("h2", { style: styles.emptyTitle, children: "Start a conversation" }),
204
+ /* @__PURE__ */ jsx("p", { style: styles.emptyText, children: 'Select an agent from the sidebar and click "New Chat" to begin.' })
205
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
206
+ /* @__PURE__ */ jsxs("div", { style: styles.chatHeader, children: [
207
+ /* @__PURE__ */ jsxs("div", { children: [
208
+ /* @__PURE__ */ jsx("strong", { children: activeSession.agentName }),
209
+ /* @__PURE__ */ jsxs("span", { style: styles.sessionId, children: [
210
+ " ",
211
+ "\xB7 ",
212
+ activeSession.sessionId.slice(0, 8)
213
+ ] })
214
+ ] }),
215
+ /* @__PURE__ */ jsx("button", { onClick: handleCloseSession, style: styles.closeButton, children: "Close Session" })
216
+ ] }),
217
+ /* @__PURE__ */ jsxs("div", { style: styles.messages, children: [
218
+ messages.map((msg) => /* @__PURE__ */ jsxs(
219
+ "div",
220
+ {
221
+ style: {
222
+ ...styles.message,
223
+ ...msg.role === "user" ? styles.userMessage : styles.assistantMessage
224
+ },
225
+ children: [
226
+ /* @__PURE__ */ jsxs("div", { style: styles.messageHeader, children: [
227
+ /* @__PURE__ */ jsx("span", { style: styles.messageRole, children: msg.role === "user" ? "You" : msg.agentName ?? "Agent" }),
228
+ /* @__PURE__ */ jsx("span", { style: styles.messageTime, children: new Date(msg.timestamp).toLocaleTimeString() })
229
+ ] }),
230
+ /* @__PURE__ */ jsx("div", { style: styles.messageContent, children: /* @__PURE__ */ jsx("span", { style: { whiteSpace: "pre-wrap" }, children: msg.content }) })
231
+ ]
232
+ },
233
+ msg.id
234
+ )),
235
+ streamingContent && /* @__PURE__ */ jsxs("div", { style: { ...styles.message, ...styles.assistantMessage }, children: [
236
+ /* @__PURE__ */ jsxs("div", { style: styles.messageHeader, children: [
237
+ /* @__PURE__ */ jsx("span", { style: styles.messageRole, children: activeSession.agentName }),
238
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: "#71717a" }, children: "typing\u2026" })
239
+ ] }),
240
+ /* @__PURE__ */ jsx("div", { style: styles.messageContent, children: /* @__PURE__ */ jsx("span", { style: { whiteSpace: "pre-wrap" }, children: streamingContent }) })
241
+ ] }),
242
+ /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
243
+ ] }),
244
+ /* @__PURE__ */ jsxs("div", { style: styles.inputArea, children: [
245
+ /* @__PURE__ */ jsx(
246
+ "textarea",
247
+ {
248
+ ref: inputRef,
249
+ value: input,
250
+ onChange: (e) => setInput(e.target.value),
251
+ onKeyDown: handleKeyDown,
252
+ placeholder: sending ? "Waiting for response..." : "Type a message...",
253
+ disabled: sending,
254
+ style: styles.textarea,
255
+ rows: 2
256
+ }
257
+ ),
258
+ /* @__PURE__ */ jsx(
259
+ "button",
260
+ {
261
+ onClick: handleSend,
262
+ disabled: !input.trim() || sending,
263
+ style: {
264
+ ...styles.sendButton,
265
+ ...!input.trim() || sending ? styles.buttonDisabled : {}
266
+ },
267
+ children: sending ? "\u2026" : "Send"
268
+ }
269
+ )
270
+ ] })
271
+ ] }) })
272
+ ] });
273
+ }
274
+ var styles = {
275
+ container: {
276
+ display: "flex",
277
+ height: "100%",
278
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
279
+ color: "#e4e4e7",
280
+ backgroundColor: "#09090b"
281
+ },
282
+ sidebar: {
283
+ width: 280,
284
+ borderRight: "1px solid #27272a",
285
+ display: "flex",
286
+ flexDirection: "column",
287
+ backgroundColor: "#0c0c0f"
288
+ },
289
+ sidebarHeader: {
290
+ padding: "16px 16px 8px",
291
+ borderBottom: "1px solid #27272a"
292
+ },
293
+ sidebarTitle: {
294
+ margin: 0,
295
+ fontSize: 18,
296
+ fontWeight: 600
297
+ },
298
+ newChatSection: {
299
+ padding: 16,
300
+ display: "flex",
301
+ flexDirection: "column",
302
+ gap: 8
303
+ },
304
+ select: {
305
+ padding: "8px 12px",
306
+ borderRadius: 6,
307
+ border: "1px solid #27272a",
308
+ backgroundColor: "#18181b",
309
+ color: "#e4e4e7",
310
+ fontSize: 14,
311
+ outline: "none"
312
+ },
313
+ button: {
314
+ padding: "8px 16px",
315
+ borderRadius: 6,
316
+ border: "none",
317
+ backgroundColor: "#3b82f6",
318
+ color: "#fff",
319
+ fontSize: 14,
320
+ fontWeight: 500,
321
+ cursor: "pointer"
322
+ },
323
+ buttonDisabled: {
324
+ opacity: 0.5,
325
+ cursor: "not-allowed"
326
+ },
327
+ sessionsList: {
328
+ flex: 1,
329
+ overflowY: "auto",
330
+ padding: "0 8px"
331
+ },
332
+ sessionsTitle: {
333
+ fontSize: 12,
334
+ fontWeight: 600,
335
+ textTransform: "uppercase",
336
+ color: "#71717a",
337
+ padding: "8px 8px 4px",
338
+ margin: 0
339
+ },
340
+ sessionItem: {
341
+ display: "flex",
342
+ justifyContent: "space-between",
343
+ alignItems: "center",
344
+ width: "100%",
345
+ padding: "8px 12px",
346
+ borderRadius: 6,
347
+ border: "none",
348
+ backgroundColor: "transparent",
349
+ color: "#a1a1aa",
350
+ fontSize: 13,
351
+ cursor: "pointer",
352
+ textAlign: "left"
353
+ },
354
+ sessionItemActive: {
355
+ backgroundColor: "#1e293b",
356
+ color: "#e4e4e7"
357
+ },
358
+ sessionAgent: {
359
+ fontWeight: 500
360
+ },
361
+ sessionTime: {
362
+ fontSize: 11,
363
+ color: "#52525b"
364
+ },
365
+ main: {
366
+ flex: 1,
367
+ display: "flex",
368
+ flexDirection: "column",
369
+ minWidth: 0
370
+ },
371
+ emptyState: {
372
+ flex: 1,
373
+ display: "flex",
374
+ flexDirection: "column",
375
+ alignItems: "center",
376
+ justifyContent: "center",
377
+ color: "#52525b"
378
+ },
379
+ emptyTitle: {
380
+ fontSize: 20,
381
+ fontWeight: 600,
382
+ marginBottom: 8,
383
+ color: "#71717a"
384
+ },
385
+ emptyText: {
386
+ fontSize: 14
387
+ },
388
+ chatHeader: {
389
+ display: "flex",
390
+ justifyContent: "space-between",
391
+ alignItems: "center",
392
+ padding: "12px 20px",
393
+ borderBottom: "1px solid #27272a",
394
+ fontSize: 14
395
+ },
396
+ sessionId: {
397
+ color: "#52525b",
398
+ fontSize: 12
399
+ },
400
+ closeButton: {
401
+ padding: "4px 12px",
402
+ borderRadius: 4,
403
+ border: "1px solid #3f3f46",
404
+ backgroundColor: "transparent",
405
+ color: "#a1a1aa",
406
+ fontSize: 12,
407
+ cursor: "pointer"
408
+ },
409
+ messages: {
410
+ flex: 1,
411
+ overflowY: "auto",
412
+ padding: 20,
413
+ display: "flex",
414
+ flexDirection: "column",
415
+ gap: 16
416
+ },
417
+ message: {
418
+ maxWidth: "80%",
419
+ padding: "10px 14px",
420
+ borderRadius: 10
421
+ },
422
+ userMessage: {
423
+ alignSelf: "flex-end",
424
+ backgroundColor: "#1e40af",
425
+ borderBottomRightRadius: 2
426
+ },
427
+ assistantMessage: {
428
+ alignSelf: "flex-start",
429
+ backgroundColor: "#18181b",
430
+ border: "1px solid #27272a",
431
+ borderBottomLeftRadius: 2
432
+ },
433
+ messageHeader: {
434
+ display: "flex",
435
+ justifyContent: "space-between",
436
+ alignItems: "center",
437
+ marginBottom: 4,
438
+ gap: 8
439
+ },
440
+ messageRole: {
441
+ fontSize: 12,
442
+ fontWeight: 600,
443
+ color: "#a1a1aa"
444
+ },
445
+ messageTime: {
446
+ fontSize: 11,
447
+ color: "#52525b"
448
+ },
449
+ messageContent: {
450
+ fontSize: 14,
451
+ lineHeight: 1.5,
452
+ wordBreak: "break-word"
453
+ },
454
+ inputArea: {
455
+ display: "flex",
456
+ gap: 8,
457
+ padding: "12px 20px",
458
+ borderTop: "1px solid #27272a",
459
+ backgroundColor: "#0c0c0f"
460
+ },
461
+ textarea: {
462
+ flex: 1,
463
+ padding: "10px 14px",
464
+ borderRadius: 8,
465
+ border: "1px solid #27272a",
466
+ backgroundColor: "#18181b",
467
+ color: "#e4e4e7",
468
+ fontSize: 14,
469
+ fontFamily: "inherit",
470
+ resize: "none",
471
+ outline: "none",
472
+ lineHeight: 1.5
473
+ },
474
+ sendButton: {
475
+ padding: "10px 20px",
476
+ borderRadius: 8,
477
+ border: "none",
478
+ backgroundColor: "#3b82f6",
479
+ color: "#fff",
480
+ fontSize: 14,
481
+ fontWeight: 500,
482
+ cursor: "pointer",
483
+ alignSelf: "flex-end"
484
+ }
485
+ };
486
+ export {
487
+ ChatPage
488
+ };
489
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/ChatPage.tsx"],
4
+ "sourcesContent": ["import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport {\n usePluginData,\n usePluginAction,\n usePluginStream,\n useHostContext,\n usePluginToast,\n} from \"@paperclipai/plugin-sdk/ui\";\n\ninterface Agent {\n id: string;\n name: string;\n title: string | null;\n icon: string | null;\n status: string;\n}\n\ninterface ChatMessage {\n id: string;\n sessionId: string;\n role: \"user\" | \"assistant\";\n content: string;\n agentId: string;\n agentName?: string;\n timestamp: string;\n}\n\ninterface SessionMeta {\n sessionId: string;\n agentId: string;\n agentName: string;\n companyId: string;\n createdAt: string;\n status: string;\n}\n\ninterface StreamEvent {\n type: string;\n messageId?: string;\n message?: ChatMessage;\n chunk?: string;\n fullContent?: string;\n status?: string;\n error?: string;\n agentName?: string;\n}\n\nexport function ChatPage() {\n const ctx = useHostContext();\n const companyId = ctx.companyId;\n const toast = usePluginToast();\n\n const [selectedAgentId, setSelectedAgentId] = useState<string>(\"\");\n const [activeSession, setActiveSession] = useState<SessionMeta | null>(null);\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [streamingContent, setStreamingContent] = useState<string>(\"\");\n const [streamingMsgId, setStreamingMsgId] = useState<string | null>(null);\n const [input, setInput] = useState(\"\");\n const [sending, setSending] = useState(false);\n\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n\n // Data fetchers\n const { data: agentsData, loading: agentsLoading } = usePluginData<{\n agents: Agent[];\n }>(\"list-agents\", { companyId });\n\n const { data: sessionsData } = usePluginData<{\n sessions: SessionMeta[];\n }>(\"list-sessions\", { companyId });\n\n // Actions\n const createSession = usePluginAction(\"create-session\");\n const sendMessage = usePluginAction(\"send-message\");\n const closeSession = usePluginAction(\"close-session\");\n\n // Stream subscription (only when we have an active session)\n const { events: streamEvents } = usePluginStream<StreamEvent>(\n activeSession ? `chat-${activeSession.sessionId}` : \"__inactive__\",\n { companyId: companyId ?? undefined }\n );\n\n // Process stream events\n useEffect(() => {\n if (!streamEvents || streamEvents.length === 0) return;\n const latest = streamEvents[streamEvents.length - 1];\n\n if (latest.type === \"assistant-chunk\" && latest.fullContent) {\n setStreamingContent(latest.fullContent);\n setStreamingMsgId(latest.messageId ?? null);\n } else if (latest.type === \"assistant-done\" && latest.message) {\n setMessages((prev) => [...prev, latest.message!]);\n setStreamingContent(\"\");\n setStreamingMsgId(null);\n setSending(false);\n } else if (latest.type === \"assistant-error\") {\n toast({\n title: \"Error\",\n body: latest.error ?? \"Unknown error\",\n tone: \"error\",\n });\n setStreamingContent(\"\");\n setStreamingMsgId(null);\n setSending(false);\n } else if (latest.type === \"user-message\" && latest.message) {\n setMessages((prev) => {\n if (prev.some((m) => m.id === latest.message!.id)) return prev;\n return [...prev, latest.message!];\n });\n }\n }, [streamEvents, toast]);\n\n // Auto-scroll to bottom\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages, streamingContent]);\n\n // Load chat history when session changes\n const { data: historyData } = usePluginData<{ messages: ChatMessage[] }>(\n \"chat-history\",\n {\n companyId,\n sessionId: activeSession?.sessionId ?? \"\",\n }\n );\n\n useEffect(() => {\n if (historyData?.messages) {\n setMessages(historyData.messages);\n }\n }, [historyData]);\n\n const handleNewChat = useCallback(async () => {\n if (!selectedAgentId || !companyId) return;\n try {\n const session = (await createSession({\n agentId: selectedAgentId,\n companyId,\n })) as SessionMeta;\n setActiveSession(session);\n setMessages([]);\n setStreamingContent(\"\");\n inputRef.current?.focus();\n } catch (err) {\n toast({\n title: \"Failed to create session\",\n body: String(err),\n tone: \"error\",\n });\n }\n }, [selectedAgentId, companyId, createSession, toast]);\n\n const handleSend = useCallback(async () => {\n if (!input.trim() || !activeSession || !companyId || sending) return;\n\n const content = input.trim();\n setInput(\"\");\n setSending(true);\n\n try {\n await sendMessage({\n sessionId: activeSession.sessionId,\n companyId,\n content,\n });\n } catch (err) {\n toast({\n title: \"Failed to send message\",\n body: String(err),\n tone: \"error\",\n });\n setSending(false);\n }\n }, [input, activeSession, companyId, sending, sendMessage, toast]);\n\n const handleCloseSession = useCallback(async () => {\n if (!activeSession || !companyId) return;\n try {\n await closeSession({\n sessionId: activeSession.sessionId,\n companyId,\n });\n setActiveSession(null);\n setMessages([]);\n toast({ title: \"Session closed\", tone: \"info\" });\n } catch (err) {\n toast({\n title: \"Failed to close session\",\n body: String(err),\n tone: \"error\",\n });\n }\n }, [activeSession, companyId, closeSession, toast]);\n\n const handleResumeSession = useCallback(\n (session: SessionMeta) => {\n setActiveSession(session);\n setSelectedAgentId(session.agentId);\n },\n []\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n const agents = agentsData?.agents ?? [];\n const activeSessions = sessionsData?.sessions ?? [];\n\n return (\n <div style={styles.container}>\n {/* Sidebar */}\n <div style={styles.sidebar}>\n <div style={styles.sidebarHeader}>\n <h2 style={styles.sidebarTitle}>Chat</h2>\n </div>\n\n {/* Agent selector */}\n <div style={styles.newChatSection}>\n <select\n value={selectedAgentId}\n onChange={(e) => setSelectedAgentId(e.target.value)}\n style={styles.select}\n disabled={agentsLoading}\n >\n <option value=\"\">Select an agent...</option>\n {agents\n .filter((a) => a.status !== \"paused\")\n .map((agent) => (\n <option key={agent.id} value={agent.id}>\n {agent.name}\n {agent.title ? ` \u2014 ${agent.title}` : \"\"}\n </option>\n ))}\n </select>\n <button\n onClick={handleNewChat}\n disabled={!selectedAgentId || !companyId}\n style={{\n ...styles.button,\n ...(!selectedAgentId ? styles.buttonDisabled : {}),\n }}\n >\n New Chat\n </button>\n </div>\n\n {/* Active sessions list */}\n {activeSessions.length > 0 && (\n <div style={styles.sessionsList}>\n <h3 style={styles.sessionsTitle}>Active Sessions</h3>\n {activeSessions.map((session) => (\n <button\n key={session.sessionId}\n onClick={() => handleResumeSession(session)}\n style={{\n ...styles.sessionItem,\n ...(activeSession?.sessionId === session.sessionId\n ? styles.sessionItemActive\n : {}),\n }}\n >\n <span style={styles.sessionAgent}>{session.agentName}</span>\n <span style={styles.sessionTime}>\n {new Date(session.createdAt).toLocaleTimeString()}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Main chat area */}\n <div style={styles.main}>\n {!activeSession ? (\n <div style={styles.emptyState}>\n <h2 style={styles.emptyTitle}>Start a conversation</h2>\n <p style={styles.emptyText}>\n Select an agent from the sidebar and click \"New Chat\" to begin.\n </p>\n </div>\n ) : (\n <>\n {/* Chat header */}\n <div style={styles.chatHeader}>\n <div>\n <strong>{activeSession.agentName}</strong>\n <span style={styles.sessionId}>\n {\" \"}\n \u00B7 {activeSession.sessionId.slice(0, 8)}\n </span>\n </div>\n <button onClick={handleCloseSession} style={styles.closeButton}>\n Close Session\n </button>\n </div>\n\n {/* Messages */}\n <div style={styles.messages}>\n {messages.map((msg) => (\n <div\n key={msg.id}\n style={{\n ...styles.message,\n ...(msg.role === \"user\"\n ? styles.userMessage\n : styles.assistantMessage),\n }}\n >\n <div style={styles.messageHeader}>\n <span style={styles.messageRole}>\n {msg.role === \"user\" ? \"You\" : msg.agentName ?? \"Agent\"}\n </span>\n <span style={styles.messageTime}>\n {new Date(msg.timestamp).toLocaleTimeString()}\n </span>\n </div>\n <div style={styles.messageContent}>\n <span style={{ whiteSpace: \"pre-wrap\" }}>\n {msg.content}\n </span>\n </div>\n </div>\n ))}\n\n {/* Streaming message */}\n {streamingContent && (\n <div style={{ ...styles.message, ...styles.assistantMessage }}>\n <div style={styles.messageHeader}>\n <span style={styles.messageRole}>\n {activeSession.agentName}\n </span>\n <span style={{ fontSize: 11, color: \"#71717a\" }}>typing\u2026</span>\n </div>\n <div style={styles.messageContent}>\n <span style={{ whiteSpace: \"pre-wrap\" }}>\n {streamingContent}\n </span>\n </div>\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input area */}\n <div style={styles.inputArea}>\n <textarea\n ref={inputRef}\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={\n sending ? \"Waiting for response...\" : \"Type a message...\"\n }\n disabled={sending}\n style={styles.textarea}\n rows={2}\n />\n <button\n onClick={handleSend}\n disabled={!input.trim() || sending}\n style={{\n ...styles.sendButton,\n ...(!input.trim() || sending ? styles.buttonDisabled : {}),\n }}\n >\n {sending ? \"\u2026\" : \"Send\"}\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: \"flex\",\n height: \"100%\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n color: \"#e4e4e7\",\n backgroundColor: \"#09090b\",\n },\n sidebar: {\n width: 280,\n borderRight: \"1px solid #27272a\",\n display: \"flex\",\n flexDirection: \"column\",\n backgroundColor: \"#0c0c0f\",\n },\n sidebarHeader: {\n padding: \"16px 16px 8px\",\n borderBottom: \"1px solid #27272a\",\n },\n sidebarTitle: {\n margin: 0,\n fontSize: 18,\n fontWeight: 600,\n },\n newChatSection: {\n padding: 16,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 8,\n },\n select: {\n padding: \"8px 12px\",\n borderRadius: 6,\n border: \"1px solid #27272a\",\n backgroundColor: \"#18181b\",\n color: \"#e4e4e7\",\n fontSize: 14,\n outline: \"none\",\n },\n button: {\n padding: \"8px 16px\",\n borderRadius: 6,\n border: \"none\",\n backgroundColor: \"#3b82f6\",\n color: \"#fff\",\n fontSize: 14,\n fontWeight: 500,\n cursor: \"pointer\",\n },\n buttonDisabled: {\n opacity: 0.5,\n cursor: \"not-allowed\",\n },\n sessionsList: {\n flex: 1,\n overflowY: \"auto\" as const,\n padding: \"0 8px\",\n },\n sessionsTitle: {\n fontSize: 12,\n fontWeight: 600,\n textTransform: \"uppercase\" as const,\n color: \"#71717a\",\n padding: \"8px 8px 4px\",\n margin: 0,\n },\n sessionItem: {\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n width: \"100%\",\n padding: \"8px 12px\",\n borderRadius: 6,\n border: \"none\",\n backgroundColor: \"transparent\",\n color: \"#a1a1aa\",\n fontSize: 13,\n cursor: \"pointer\",\n textAlign: \"left\" as const,\n },\n sessionItemActive: {\n backgroundColor: \"#1e293b\",\n color: \"#e4e4e7\",\n },\n sessionAgent: {\n fontWeight: 500,\n },\n sessionTime: {\n fontSize: 11,\n color: \"#52525b\",\n },\n main: {\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n minWidth: 0,\n },\n emptyState: {\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#52525b\",\n },\n emptyTitle: {\n fontSize: 20,\n fontWeight: 600,\n marginBottom: 8,\n color: \"#71717a\",\n },\n emptyText: {\n fontSize: 14,\n },\n chatHeader: {\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n padding: \"12px 20px\",\n borderBottom: \"1px solid #27272a\",\n fontSize: 14,\n },\n sessionId: {\n color: \"#52525b\",\n fontSize: 12,\n },\n closeButton: {\n padding: \"4px 12px\",\n borderRadius: 4,\n border: \"1px solid #3f3f46\",\n backgroundColor: \"transparent\",\n color: \"#a1a1aa\",\n fontSize: 12,\n cursor: \"pointer\",\n },\n messages: {\n flex: 1,\n overflowY: \"auto\" as const,\n padding: 20,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 16,\n },\n message: {\n maxWidth: \"80%\",\n padding: \"10px 14px\",\n borderRadius: 10,\n },\n userMessage: {\n alignSelf: \"flex-end\",\n backgroundColor: \"#1e40af\",\n borderBottomRightRadius: 2,\n },\n assistantMessage: {\n alignSelf: \"flex-start\",\n backgroundColor: \"#18181b\",\n border: \"1px solid #27272a\",\n borderBottomLeftRadius: 2,\n },\n messageHeader: {\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 4,\n gap: 8,\n },\n messageRole: {\n fontSize: 12,\n fontWeight: 600,\n color: \"#a1a1aa\",\n },\n messageTime: {\n fontSize: 11,\n color: \"#52525b\",\n },\n messageContent: {\n fontSize: 14,\n lineHeight: 1.5,\n wordBreak: \"break-word\" as const,\n },\n inputArea: {\n display: \"flex\",\n gap: 8,\n padding: \"12px 20px\",\n borderTop: \"1px solid #27272a\",\n backgroundColor: \"#0c0c0f\",\n },\n textarea: {\n flex: 1,\n padding: \"10px 14px\",\n borderRadius: 8,\n border: \"1px solid #27272a\",\n backgroundColor: \"#18181b\",\n color: \"#e4e4e7\",\n fontSize: 14,\n fontFamily: \"inherit\",\n resize: \"none\" as const,\n outline: \"none\",\n lineHeight: 1.5,\n },\n sendButton: {\n padding: \"10px 20px\",\n borderRadius: 8,\n border: \"none\",\n backgroundColor: \"#3b82f6\",\n color: \"#fff\",\n fontSize: 14,\n fontWeight: 500,\n cursor: \"pointer\",\n alignSelf: \"flex-end\",\n },\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }