@journeyrewards/hive-vercel 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +59 -2
- package/dist/index.d.ts +59 -2
- package/dist/index.js +153 -28
- package/dist/index.mjs +148 -28
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { JourneyHiveConfig, CreateResponseParams, Response, Conversation, Message, Agent } from '@journeyrewards/hive-sdk';
|
|
3
|
+
import { JourneyHiveConfig, CreateResponseParams, Response, Conversation, Message, ListResponse, UpdateConversationParams, Agent, ContentPart } from '@journeyrewards/hive-sdk';
|
|
4
4
|
|
|
5
5
|
interface JourneyHiveClient {
|
|
6
6
|
config: JourneyHiveConfig;
|
|
@@ -15,6 +15,13 @@ interface JourneyHiveClient {
|
|
|
15
15
|
messages(id: string): Promise<{
|
|
16
16
|
data: Message[];
|
|
17
17
|
}>;
|
|
18
|
+
list(params?: {
|
|
19
|
+
agent_id?: string;
|
|
20
|
+
status?: string;
|
|
21
|
+
limit?: number;
|
|
22
|
+
cursor?: string;
|
|
23
|
+
}): Promise<ListResponse<Conversation>>;
|
|
24
|
+
update(id: string, params: UpdateConversationParams): Promise<Conversation>;
|
|
18
25
|
};
|
|
19
26
|
agents: {
|
|
20
27
|
get(id: string): Promise<Agent>;
|
|
@@ -61,6 +68,22 @@ interface UseAgentsReturn {
|
|
|
61
68
|
error: Error | null;
|
|
62
69
|
}
|
|
63
70
|
declare function useAgents(): UseAgentsReturn;
|
|
71
|
+
interface UseConversationsReturn {
|
|
72
|
+
conversations: Conversation[];
|
|
73
|
+
isLoading: boolean;
|
|
74
|
+
error: Error | null;
|
|
75
|
+
refetch: () => void;
|
|
76
|
+
}
|
|
77
|
+
declare function useConversations(agentId: string): UseConversationsReturn;
|
|
78
|
+
interface UseConversationActionsReturn {
|
|
79
|
+
star: (id: string, starred: boolean) => Promise<Conversation>;
|
|
80
|
+
rename: (id: string, title: string) => Promise<Conversation>;
|
|
81
|
+
update: (id: string, params: UpdateConversationParams) => Promise<Conversation>;
|
|
82
|
+
isUpdating: boolean;
|
|
83
|
+
error: Error | null;
|
|
84
|
+
}
|
|
85
|
+
declare function useConversationActions(): UseConversationActionsReturn;
|
|
86
|
+
declare function useChartUrl(chartId: string): string;
|
|
64
87
|
|
|
65
88
|
interface ResponseStreamProps {
|
|
66
89
|
agentId: string;
|
|
@@ -85,6 +108,40 @@ declare function MessageBubble({ role, content, timestamp }: MessageBubbleProps)
|
|
|
85
108
|
marginBottom: string;
|
|
86
109
|
};
|
|
87
110
|
}, HTMLElement>;
|
|
111
|
+
interface ChartEmbedProps {
|
|
112
|
+
embedUrl?: string;
|
|
113
|
+
imageUrl?: string;
|
|
114
|
+
title?: string;
|
|
115
|
+
chartId?: string;
|
|
116
|
+
width?: string;
|
|
117
|
+
height?: string;
|
|
118
|
+
className?: string;
|
|
119
|
+
}
|
|
120
|
+
declare function ChartEmbed({ embedUrl, imageUrl, title, chartId, width, height, className }: ChartEmbedProps): react.DetailedReactHTMLElement<{
|
|
121
|
+
className: string;
|
|
122
|
+
style: {
|
|
123
|
+
margin: string;
|
|
124
|
+
borderRadius: string;
|
|
125
|
+
overflow: string;
|
|
126
|
+
border: string;
|
|
127
|
+
maxWidth: string;
|
|
128
|
+
};
|
|
129
|
+
}, HTMLElement> | null;
|
|
130
|
+
interface RichMessageProps {
|
|
131
|
+
role: string;
|
|
132
|
+
content: ContentPart[];
|
|
133
|
+
timestamp?: number;
|
|
134
|
+
className?: string;
|
|
135
|
+
}
|
|
136
|
+
declare function RichMessage({ role, content, timestamp, className }: RichMessageProps): react.DetailedReactHTMLElement<{
|
|
137
|
+
className: string;
|
|
138
|
+
style: {
|
|
139
|
+
display: "flex";
|
|
140
|
+
flexDirection: "column";
|
|
141
|
+
alignItems: "flex-end" | "flex-start";
|
|
142
|
+
marginBottom: string;
|
|
143
|
+
};
|
|
144
|
+
}, HTMLElement>;
|
|
88
145
|
interface ConversationViewProps {
|
|
89
146
|
conversationId: string;
|
|
90
147
|
agentId?: string;
|
|
@@ -111,4 +168,4 @@ declare function AgentStatus({ agent }: AgentStatusProps): react.DetailedReactHT
|
|
|
111
168
|
};
|
|
112
169
|
}, HTMLElement>;
|
|
113
170
|
|
|
114
|
-
export { AgentStatus, ConversationView, JourneyHiveProvider, MessageBubble, ResponseStream, useAgent, useAgents, useConversation, useJourneyHive, useResponse };
|
|
171
|
+
export { AgentStatus, ChartEmbed, ConversationView, JourneyHiveProvider, MessageBubble, ResponseStream, RichMessage, useAgent, useAgents, useChartUrl, useConversation, useConversationActions, useConversations, useJourneyHive, useResponse };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { JourneyHiveConfig, CreateResponseParams, Response, Conversation, Message, Agent } from '@journeyrewards/hive-sdk';
|
|
3
|
+
import { JourneyHiveConfig, CreateResponseParams, Response, Conversation, Message, ListResponse, UpdateConversationParams, Agent, ContentPart } from '@journeyrewards/hive-sdk';
|
|
4
4
|
|
|
5
5
|
interface JourneyHiveClient {
|
|
6
6
|
config: JourneyHiveConfig;
|
|
@@ -15,6 +15,13 @@ interface JourneyHiveClient {
|
|
|
15
15
|
messages(id: string): Promise<{
|
|
16
16
|
data: Message[];
|
|
17
17
|
}>;
|
|
18
|
+
list(params?: {
|
|
19
|
+
agent_id?: string;
|
|
20
|
+
status?: string;
|
|
21
|
+
limit?: number;
|
|
22
|
+
cursor?: string;
|
|
23
|
+
}): Promise<ListResponse<Conversation>>;
|
|
24
|
+
update(id: string, params: UpdateConversationParams): Promise<Conversation>;
|
|
18
25
|
};
|
|
19
26
|
agents: {
|
|
20
27
|
get(id: string): Promise<Agent>;
|
|
@@ -61,6 +68,22 @@ interface UseAgentsReturn {
|
|
|
61
68
|
error: Error | null;
|
|
62
69
|
}
|
|
63
70
|
declare function useAgents(): UseAgentsReturn;
|
|
71
|
+
interface UseConversationsReturn {
|
|
72
|
+
conversations: Conversation[];
|
|
73
|
+
isLoading: boolean;
|
|
74
|
+
error: Error | null;
|
|
75
|
+
refetch: () => void;
|
|
76
|
+
}
|
|
77
|
+
declare function useConversations(agentId: string): UseConversationsReturn;
|
|
78
|
+
interface UseConversationActionsReturn {
|
|
79
|
+
star: (id: string, starred: boolean) => Promise<Conversation>;
|
|
80
|
+
rename: (id: string, title: string) => Promise<Conversation>;
|
|
81
|
+
update: (id: string, params: UpdateConversationParams) => Promise<Conversation>;
|
|
82
|
+
isUpdating: boolean;
|
|
83
|
+
error: Error | null;
|
|
84
|
+
}
|
|
85
|
+
declare function useConversationActions(): UseConversationActionsReturn;
|
|
86
|
+
declare function useChartUrl(chartId: string): string;
|
|
64
87
|
|
|
65
88
|
interface ResponseStreamProps {
|
|
66
89
|
agentId: string;
|
|
@@ -85,6 +108,40 @@ declare function MessageBubble({ role, content, timestamp }: MessageBubbleProps)
|
|
|
85
108
|
marginBottom: string;
|
|
86
109
|
};
|
|
87
110
|
}, HTMLElement>;
|
|
111
|
+
interface ChartEmbedProps {
|
|
112
|
+
embedUrl?: string;
|
|
113
|
+
imageUrl?: string;
|
|
114
|
+
title?: string;
|
|
115
|
+
chartId?: string;
|
|
116
|
+
width?: string;
|
|
117
|
+
height?: string;
|
|
118
|
+
className?: string;
|
|
119
|
+
}
|
|
120
|
+
declare function ChartEmbed({ embedUrl, imageUrl, title, chartId, width, height, className }: ChartEmbedProps): react.DetailedReactHTMLElement<{
|
|
121
|
+
className: string;
|
|
122
|
+
style: {
|
|
123
|
+
margin: string;
|
|
124
|
+
borderRadius: string;
|
|
125
|
+
overflow: string;
|
|
126
|
+
border: string;
|
|
127
|
+
maxWidth: string;
|
|
128
|
+
};
|
|
129
|
+
}, HTMLElement> | null;
|
|
130
|
+
interface RichMessageProps {
|
|
131
|
+
role: string;
|
|
132
|
+
content: ContentPart[];
|
|
133
|
+
timestamp?: number;
|
|
134
|
+
className?: string;
|
|
135
|
+
}
|
|
136
|
+
declare function RichMessage({ role, content, timestamp, className }: RichMessageProps): react.DetailedReactHTMLElement<{
|
|
137
|
+
className: string;
|
|
138
|
+
style: {
|
|
139
|
+
display: "flex";
|
|
140
|
+
flexDirection: "column";
|
|
141
|
+
alignItems: "flex-end" | "flex-start";
|
|
142
|
+
marginBottom: string;
|
|
143
|
+
};
|
|
144
|
+
}, HTMLElement>;
|
|
88
145
|
interface ConversationViewProps {
|
|
89
146
|
conversationId: string;
|
|
90
147
|
agentId?: string;
|
|
@@ -111,4 +168,4 @@ declare function AgentStatus({ agent }: AgentStatusProps): react.DetailedReactHT
|
|
|
111
168
|
};
|
|
112
169
|
}, HTMLElement>;
|
|
113
170
|
|
|
114
|
-
export { AgentStatus, ConversationView, JourneyHiveProvider, MessageBubble, ResponseStream, useAgent, useAgents, useConversation, useJourneyHive, useResponse };
|
|
171
|
+
export { AgentStatus, ChartEmbed, ConversationView, JourneyHiveProvider, MessageBubble, ResponseStream, RichMessage, useAgent, useAgents, useChartUrl, useConversation, useConversationActions, useConversations, useJourneyHive, useResponse };
|
package/dist/index.js
CHANGED
|
@@ -21,13 +21,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AgentStatus: () => AgentStatus,
|
|
24
|
+
ChartEmbed: () => ChartEmbed,
|
|
24
25
|
ConversationView: () => ConversationView,
|
|
25
26
|
JourneyHiveProvider: () => JourneyHiveProvider,
|
|
26
27
|
MessageBubble: () => MessageBubble,
|
|
27
28
|
ResponseStream: () => ResponseStream,
|
|
29
|
+
RichMessage: () => RichMessage,
|
|
28
30
|
useAgent: () => useAgent,
|
|
29
31
|
useAgents: () => useAgents,
|
|
32
|
+
useChartUrl: () => useChartUrl,
|
|
30
33
|
useConversation: () => useConversation,
|
|
34
|
+
useConversationActions: () => useConversationActions,
|
|
35
|
+
useConversations: () => useConversations,
|
|
31
36
|
useJourneyHive: () => useJourneyHive,
|
|
32
37
|
useResponse: () => useResponse
|
|
33
38
|
});
|
|
@@ -100,7 +105,17 @@ function createClient(config) {
|
|
|
100
105
|
},
|
|
101
106
|
conversations: {
|
|
102
107
|
get: (id) => request("GET", `/v1/conversations/${id}`),
|
|
103
|
-
messages: (id) => request("GET", `/v1/conversations/${id}/messages`)
|
|
108
|
+
messages: (id) => request("GET", `/v1/conversations/${id}/messages`),
|
|
109
|
+
list: (params) => {
|
|
110
|
+
const searchParams = new URLSearchParams();
|
|
111
|
+
if (params?.agent_id) searchParams.set("agent_id", params.agent_id);
|
|
112
|
+
if (params?.status) searchParams.set("status", params.status);
|
|
113
|
+
if (params?.limit) searchParams.set("limit", String(params.limit));
|
|
114
|
+
if (params?.cursor) searchParams.set("cursor", params.cursor);
|
|
115
|
+
const query = searchParams.toString();
|
|
116
|
+
return request("GET", `/v1/conversations${query ? `?${query}` : ""}`);
|
|
117
|
+
},
|
|
118
|
+
update: (id, params) => request("PATCH", `/v1/conversations/${id}`, params)
|
|
104
119
|
},
|
|
105
120
|
agents: {
|
|
106
121
|
get: (id) => request("GET", `/v1/agents/${id}`),
|
|
@@ -262,6 +277,57 @@ function useAgents() {
|
|
|
262
277
|
}, [client]);
|
|
263
278
|
return { agents, isLoading, error };
|
|
264
279
|
}
|
|
280
|
+
function useConversations(agentId) {
|
|
281
|
+
const client = useJourneyHive();
|
|
282
|
+
const [conversations, setConversations] = (0, import_react.useState)([]);
|
|
283
|
+
const [isLoading, setIsLoading] = (0, import_react.useState)(true);
|
|
284
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
285
|
+
const fetchConversations = (0, import_react.useCallback)(() => {
|
|
286
|
+
if (!agentId) return;
|
|
287
|
+
setIsLoading(true);
|
|
288
|
+
client.conversations.list({ agent_id: agentId }).then((result) => setConversations(result.data)).catch((err) => setError(err instanceof Error ? err : new Error(String(err)))).finally(() => setIsLoading(false));
|
|
289
|
+
}, [agentId, client]);
|
|
290
|
+
(0, import_react.useEffect)(() => {
|
|
291
|
+
fetchConversations();
|
|
292
|
+
}, [fetchConversations]);
|
|
293
|
+
return { conversations, isLoading, error, refetch: fetchConversations };
|
|
294
|
+
}
|
|
295
|
+
function useConversationActions() {
|
|
296
|
+
const client = useJourneyHive();
|
|
297
|
+
const [isUpdating, setIsUpdating] = (0, import_react.useState)(false);
|
|
298
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
299
|
+
const update = (0, import_react.useCallback)(
|
|
300
|
+
async (id, params) => {
|
|
301
|
+
setIsUpdating(true);
|
|
302
|
+
setError(null);
|
|
303
|
+
try {
|
|
304
|
+
const result = await client.conversations.update(id, params);
|
|
305
|
+
return result;
|
|
306
|
+
} catch (err) {
|
|
307
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
308
|
+
setError(error2);
|
|
309
|
+
throw error2;
|
|
310
|
+
} finally {
|
|
311
|
+
setIsUpdating(false);
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
[client]
|
|
315
|
+
);
|
|
316
|
+
const star = (0, import_react.useCallback)(
|
|
317
|
+
(id, starred) => update(id, { starred }),
|
|
318
|
+
[update]
|
|
319
|
+
);
|
|
320
|
+
const rename = (0, import_react.useCallback)(
|
|
321
|
+
(id, title) => update(id, { title }),
|
|
322
|
+
[update]
|
|
323
|
+
);
|
|
324
|
+
return { star, rename, update, isUpdating, error };
|
|
325
|
+
}
|
|
326
|
+
function useChartUrl(chartId) {
|
|
327
|
+
const client = useJourneyHive();
|
|
328
|
+
const baseUrl = client.config.baseUrl || "https://journey-hive.replit.app";
|
|
329
|
+
return `${baseUrl}/charts/${chartId}.png`;
|
|
330
|
+
}
|
|
265
331
|
|
|
266
332
|
// src/components.tsx
|
|
267
333
|
var import_react2 = require("react");
|
|
@@ -331,6 +397,79 @@ function MessageBubble({ role, content, timestamp }) {
|
|
|
331
397
|
) : null
|
|
332
398
|
);
|
|
333
399
|
}
|
|
400
|
+
function isSafeUrl(url) {
|
|
401
|
+
try {
|
|
402
|
+
const parsed = new URL(url);
|
|
403
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
404
|
+
} catch {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
function ChartEmbed({ embedUrl, imageUrl, title, chartId, width, height, className }) {
|
|
409
|
+
const containerStyle = {
|
|
410
|
+
margin: "8px 0 16px",
|
|
411
|
+
borderRadius: "12px",
|
|
412
|
+
overflow: "hidden",
|
|
413
|
+
border: "1px solid #e2e2ea",
|
|
414
|
+
maxWidth: width || "640px"
|
|
415
|
+
};
|
|
416
|
+
if (embedUrl && isSafeUrl(embedUrl)) {
|
|
417
|
+
return (0, import_react2.createElement)(
|
|
418
|
+
"div",
|
|
419
|
+
{ className: `jh-chart-embed ${className || ""}`.trim(), style: containerStyle },
|
|
420
|
+
(0, import_react2.createElement)("iframe", {
|
|
421
|
+
src: embedUrl,
|
|
422
|
+
title: title || "Chart",
|
|
423
|
+
style: { width: "100%", height: height || "400px", border: "none" },
|
|
424
|
+
loading: "lazy",
|
|
425
|
+
sandbox: "allow-scripts allow-same-origin",
|
|
426
|
+
referrerPolicy: "no-referrer"
|
|
427
|
+
})
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
if (imageUrl && isSafeUrl(imageUrl)) {
|
|
431
|
+
return (0, import_react2.createElement)(
|
|
432
|
+
"div",
|
|
433
|
+
{ className: `jh-chart-embed ${className || ""}`.trim(), style: containerStyle },
|
|
434
|
+
(0, import_react2.createElement)("img", {
|
|
435
|
+
src: imageUrl,
|
|
436
|
+
alt: title || "Chart",
|
|
437
|
+
style: { width: "100%", height: "auto", display: "block" },
|
|
438
|
+
loading: "lazy",
|
|
439
|
+
referrerPolicy: "no-referrer"
|
|
440
|
+
})
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
function RichMessage({ role, content, timestamp, className }) {
|
|
446
|
+
const isUser = role === "user";
|
|
447
|
+
const textParts = content.filter((c) => c.type === "output_text");
|
|
448
|
+
const chartParts = content.filter((c) => c.type === "output_chart");
|
|
449
|
+
const text = textParts.map((c) => c.text).join("");
|
|
450
|
+
return (0, import_react2.createElement)(
|
|
451
|
+
"div",
|
|
452
|
+
{
|
|
453
|
+
className: `jh-rich-message ${className || ""}`.trim(),
|
|
454
|
+
style: {
|
|
455
|
+
display: "flex",
|
|
456
|
+
flexDirection: "column",
|
|
457
|
+
alignItems: isUser ? "flex-end" : "flex-start",
|
|
458
|
+
marginBottom: "8px"
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
text ? (0, import_react2.createElement)(MessageBubble, { role, content: text, timestamp }) : null,
|
|
462
|
+
...chartParts.map(
|
|
463
|
+
(chart) => (0, import_react2.createElement)(ChartEmbed, {
|
|
464
|
+
key: chart.chart_id,
|
|
465
|
+
embedUrl: chart.embed_url,
|
|
466
|
+
imageUrl: chart.image_url,
|
|
467
|
+
title: chart.title,
|
|
468
|
+
chartId: chart.chart_id
|
|
469
|
+
})
|
|
470
|
+
)
|
|
471
|
+
);
|
|
472
|
+
}
|
|
334
473
|
function ConversationView({ conversationId, agentId, className }) {
|
|
335
474
|
const { messages, isLoading, error, sendMessage } = useConversation(conversationId);
|
|
336
475
|
const [inputValue, setInputValue] = (0, import_react2.useState)("");
|
|
@@ -362,33 +501,14 @@ function ConversationView({ conversationId, agentId, className }) {
|
|
|
362
501
|
className: "jh-messages",
|
|
363
502
|
style: { flex: 1, overflowY: "auto", padding: "16px" }
|
|
364
503
|
},
|
|
365
|
-
isLoading ? (0, import_react2.createElement)("div", { className: "jh-loading" }, "Loading messages...") : messages.map(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
key: `text-${msg.id}`,
|
|
374
|
-
role: msg.role,
|
|
375
|
-
content: text,
|
|
376
|
-
timestamp: msg.created_at
|
|
377
|
-
}),
|
|
378
|
-
...chartParts.map(
|
|
379
|
-
(chart) => (0, import_react2.createElement)("div", {
|
|
380
|
-
key: `chart-${chart.chart_id}`,
|
|
381
|
-
className: "jh-chart-embed",
|
|
382
|
-
style: { margin: "8px 0 16px", borderRadius: "12px", overflow: "hidden", border: "1px solid #e2e2ea", maxWidth: "640px" }
|
|
383
|
-
}, (0, import_react2.createElement)("iframe", {
|
|
384
|
-
src: chart.embed_url,
|
|
385
|
-
title: chart.title,
|
|
386
|
-
style: { width: "100%", height: "400px", border: "none" },
|
|
387
|
-
loading: "lazy"
|
|
388
|
-
}))
|
|
389
|
-
)
|
|
390
|
-
);
|
|
391
|
-
}),
|
|
504
|
+
isLoading ? (0, import_react2.createElement)("div", { className: "jh-loading" }, "Loading messages...") : messages.map(
|
|
505
|
+
(msg) => (0, import_react2.createElement)(RichMessage, {
|
|
506
|
+
key: msg.id,
|
|
507
|
+
role: msg.role,
|
|
508
|
+
content: msg.content || [],
|
|
509
|
+
timestamp: msg.created_at
|
|
510
|
+
})
|
|
511
|
+
),
|
|
392
512
|
(0, import_react2.createElement)("div", { ref: messagesEndRef })
|
|
393
513
|
),
|
|
394
514
|
(0, import_react2.createElement)(
|
|
@@ -457,13 +577,18 @@ function AgentStatus({ agent }) {
|
|
|
457
577
|
// Annotate the CommonJS export names for ESM import in node:
|
|
458
578
|
0 && (module.exports = {
|
|
459
579
|
AgentStatus,
|
|
580
|
+
ChartEmbed,
|
|
460
581
|
ConversationView,
|
|
461
582
|
JourneyHiveProvider,
|
|
462
583
|
MessageBubble,
|
|
463
584
|
ResponseStream,
|
|
585
|
+
RichMessage,
|
|
464
586
|
useAgent,
|
|
465
587
|
useAgents,
|
|
588
|
+
useChartUrl,
|
|
466
589
|
useConversation,
|
|
590
|
+
useConversationActions,
|
|
591
|
+
useConversations,
|
|
467
592
|
useJourneyHive,
|
|
468
593
|
useResponse
|
|
469
594
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -73,7 +73,17 @@ function createClient(config) {
|
|
|
73
73
|
},
|
|
74
74
|
conversations: {
|
|
75
75
|
get: (id) => request("GET", `/v1/conversations/${id}`),
|
|
76
|
-
messages: (id) => request("GET", `/v1/conversations/${id}/messages`)
|
|
76
|
+
messages: (id) => request("GET", `/v1/conversations/${id}/messages`),
|
|
77
|
+
list: (params) => {
|
|
78
|
+
const searchParams = new URLSearchParams();
|
|
79
|
+
if (params?.agent_id) searchParams.set("agent_id", params.agent_id);
|
|
80
|
+
if (params?.status) searchParams.set("status", params.status);
|
|
81
|
+
if (params?.limit) searchParams.set("limit", String(params.limit));
|
|
82
|
+
if (params?.cursor) searchParams.set("cursor", params.cursor);
|
|
83
|
+
const query = searchParams.toString();
|
|
84
|
+
return request("GET", `/v1/conversations${query ? `?${query}` : ""}`);
|
|
85
|
+
},
|
|
86
|
+
update: (id, params) => request("PATCH", `/v1/conversations/${id}`, params)
|
|
77
87
|
},
|
|
78
88
|
agents: {
|
|
79
89
|
get: (id) => request("GET", `/v1/agents/${id}`),
|
|
@@ -235,6 +245,57 @@ function useAgents() {
|
|
|
235
245
|
}, [client]);
|
|
236
246
|
return { agents, isLoading, error };
|
|
237
247
|
}
|
|
248
|
+
function useConversations(agentId) {
|
|
249
|
+
const client = useJourneyHive();
|
|
250
|
+
const [conversations, setConversations] = useState([]);
|
|
251
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
252
|
+
const [error, setError] = useState(null);
|
|
253
|
+
const fetchConversations = useCallback(() => {
|
|
254
|
+
if (!agentId) return;
|
|
255
|
+
setIsLoading(true);
|
|
256
|
+
client.conversations.list({ agent_id: agentId }).then((result) => setConversations(result.data)).catch((err) => setError(err instanceof Error ? err : new Error(String(err)))).finally(() => setIsLoading(false));
|
|
257
|
+
}, [agentId, client]);
|
|
258
|
+
useEffect(() => {
|
|
259
|
+
fetchConversations();
|
|
260
|
+
}, [fetchConversations]);
|
|
261
|
+
return { conversations, isLoading, error, refetch: fetchConversations };
|
|
262
|
+
}
|
|
263
|
+
function useConversationActions() {
|
|
264
|
+
const client = useJourneyHive();
|
|
265
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
|
266
|
+
const [error, setError] = useState(null);
|
|
267
|
+
const update = useCallback(
|
|
268
|
+
async (id, params) => {
|
|
269
|
+
setIsUpdating(true);
|
|
270
|
+
setError(null);
|
|
271
|
+
try {
|
|
272
|
+
const result = await client.conversations.update(id, params);
|
|
273
|
+
return result;
|
|
274
|
+
} catch (err) {
|
|
275
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
276
|
+
setError(error2);
|
|
277
|
+
throw error2;
|
|
278
|
+
} finally {
|
|
279
|
+
setIsUpdating(false);
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
[client]
|
|
283
|
+
);
|
|
284
|
+
const star = useCallback(
|
|
285
|
+
(id, starred) => update(id, { starred }),
|
|
286
|
+
[update]
|
|
287
|
+
);
|
|
288
|
+
const rename = useCallback(
|
|
289
|
+
(id, title) => update(id, { title }),
|
|
290
|
+
[update]
|
|
291
|
+
);
|
|
292
|
+
return { star, rename, update, isUpdating, error };
|
|
293
|
+
}
|
|
294
|
+
function useChartUrl(chartId) {
|
|
295
|
+
const client = useJourneyHive();
|
|
296
|
+
const baseUrl = client.config.baseUrl || "https://journey-hive.replit.app";
|
|
297
|
+
return `${baseUrl}/charts/${chartId}.png`;
|
|
298
|
+
}
|
|
238
299
|
|
|
239
300
|
// src/components.tsx
|
|
240
301
|
import {
|
|
@@ -310,6 +371,79 @@ function MessageBubble({ role, content, timestamp }) {
|
|
|
310
371
|
) : null
|
|
311
372
|
);
|
|
312
373
|
}
|
|
374
|
+
function isSafeUrl(url) {
|
|
375
|
+
try {
|
|
376
|
+
const parsed = new URL(url);
|
|
377
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
378
|
+
} catch {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
function ChartEmbed({ embedUrl, imageUrl, title, chartId, width, height, className }) {
|
|
383
|
+
const containerStyle = {
|
|
384
|
+
margin: "8px 0 16px",
|
|
385
|
+
borderRadius: "12px",
|
|
386
|
+
overflow: "hidden",
|
|
387
|
+
border: "1px solid #e2e2ea",
|
|
388
|
+
maxWidth: width || "640px"
|
|
389
|
+
};
|
|
390
|
+
if (embedUrl && isSafeUrl(embedUrl)) {
|
|
391
|
+
return createElement2(
|
|
392
|
+
"div",
|
|
393
|
+
{ className: `jh-chart-embed ${className || ""}`.trim(), style: containerStyle },
|
|
394
|
+
createElement2("iframe", {
|
|
395
|
+
src: embedUrl,
|
|
396
|
+
title: title || "Chart",
|
|
397
|
+
style: { width: "100%", height: height || "400px", border: "none" },
|
|
398
|
+
loading: "lazy",
|
|
399
|
+
sandbox: "allow-scripts allow-same-origin",
|
|
400
|
+
referrerPolicy: "no-referrer"
|
|
401
|
+
})
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
if (imageUrl && isSafeUrl(imageUrl)) {
|
|
405
|
+
return createElement2(
|
|
406
|
+
"div",
|
|
407
|
+
{ className: `jh-chart-embed ${className || ""}`.trim(), style: containerStyle },
|
|
408
|
+
createElement2("img", {
|
|
409
|
+
src: imageUrl,
|
|
410
|
+
alt: title || "Chart",
|
|
411
|
+
style: { width: "100%", height: "auto", display: "block" },
|
|
412
|
+
loading: "lazy",
|
|
413
|
+
referrerPolicy: "no-referrer"
|
|
414
|
+
})
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
function RichMessage({ role, content, timestamp, className }) {
|
|
420
|
+
const isUser = role === "user";
|
|
421
|
+
const textParts = content.filter((c) => c.type === "output_text");
|
|
422
|
+
const chartParts = content.filter((c) => c.type === "output_chart");
|
|
423
|
+
const text = textParts.map((c) => c.text).join("");
|
|
424
|
+
return createElement2(
|
|
425
|
+
"div",
|
|
426
|
+
{
|
|
427
|
+
className: `jh-rich-message ${className || ""}`.trim(),
|
|
428
|
+
style: {
|
|
429
|
+
display: "flex",
|
|
430
|
+
flexDirection: "column",
|
|
431
|
+
alignItems: isUser ? "flex-end" : "flex-start",
|
|
432
|
+
marginBottom: "8px"
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
text ? createElement2(MessageBubble, { role, content: text, timestamp }) : null,
|
|
436
|
+
...chartParts.map(
|
|
437
|
+
(chart) => createElement2(ChartEmbed, {
|
|
438
|
+
key: chart.chart_id,
|
|
439
|
+
embedUrl: chart.embed_url,
|
|
440
|
+
imageUrl: chart.image_url,
|
|
441
|
+
title: chart.title,
|
|
442
|
+
chartId: chart.chart_id
|
|
443
|
+
})
|
|
444
|
+
)
|
|
445
|
+
);
|
|
446
|
+
}
|
|
313
447
|
function ConversationView({ conversationId, agentId, className }) {
|
|
314
448
|
const { messages, isLoading, error, sendMessage } = useConversation(conversationId);
|
|
315
449
|
const [inputValue, setInputValue] = useState2("");
|
|
@@ -341,33 +475,14 @@ function ConversationView({ conversationId, agentId, className }) {
|
|
|
341
475
|
className: "jh-messages",
|
|
342
476
|
style: { flex: 1, overflowY: "auto", padding: "16px" }
|
|
343
477
|
},
|
|
344
|
-
isLoading ? createElement2("div", { className: "jh-loading" }, "Loading messages...") : messages.map(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
key: `text-${msg.id}`,
|
|
353
|
-
role: msg.role,
|
|
354
|
-
content: text,
|
|
355
|
-
timestamp: msg.created_at
|
|
356
|
-
}),
|
|
357
|
-
...chartParts.map(
|
|
358
|
-
(chart) => createElement2("div", {
|
|
359
|
-
key: `chart-${chart.chart_id}`,
|
|
360
|
-
className: "jh-chart-embed",
|
|
361
|
-
style: { margin: "8px 0 16px", borderRadius: "12px", overflow: "hidden", border: "1px solid #e2e2ea", maxWidth: "640px" }
|
|
362
|
-
}, createElement2("iframe", {
|
|
363
|
-
src: chart.embed_url,
|
|
364
|
-
title: chart.title,
|
|
365
|
-
style: { width: "100%", height: "400px", border: "none" },
|
|
366
|
-
loading: "lazy"
|
|
367
|
-
}))
|
|
368
|
-
)
|
|
369
|
-
);
|
|
370
|
-
}),
|
|
478
|
+
isLoading ? createElement2("div", { className: "jh-loading" }, "Loading messages...") : messages.map(
|
|
479
|
+
(msg) => createElement2(RichMessage, {
|
|
480
|
+
key: msg.id,
|
|
481
|
+
role: msg.role,
|
|
482
|
+
content: msg.content || [],
|
|
483
|
+
timestamp: msg.created_at
|
|
484
|
+
})
|
|
485
|
+
),
|
|
371
486
|
createElement2("div", { ref: messagesEndRef })
|
|
372
487
|
),
|
|
373
488
|
createElement2(
|
|
@@ -435,13 +550,18 @@ function AgentStatus({ agent }) {
|
|
|
435
550
|
}
|
|
436
551
|
export {
|
|
437
552
|
AgentStatus,
|
|
553
|
+
ChartEmbed,
|
|
438
554
|
ConversationView,
|
|
439
555
|
JourneyHiveProvider,
|
|
440
556
|
MessageBubble,
|
|
441
557
|
ResponseStream,
|
|
558
|
+
RichMessage,
|
|
442
559
|
useAgent,
|
|
443
560
|
useAgents,
|
|
561
|
+
useChartUrl,
|
|
444
562
|
useConversation,
|
|
563
|
+
useConversationActions,
|
|
564
|
+
useConversations,
|
|
445
565
|
useJourneyHive,
|
|
446
566
|
useResponse
|
|
447
567
|
};
|