@journeyrewards/hive-vercel 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.
package/dist/index.js ADDED
@@ -0,0 +1,451 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AgentStatus: () => AgentStatus,
24
+ ConversationView: () => ConversationView,
25
+ JourneyHiveProvider: () => JourneyHiveProvider,
26
+ MessageBubble: () => MessageBubble,
27
+ ResponseStream: () => ResponseStream,
28
+ useAgent: () => useAgent,
29
+ useAgents: () => useAgents,
30
+ useConversation: () => useConversation,
31
+ useJourneyHive: () => useJourneyHive,
32
+ useResponse: () => useResponse
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/hooks.ts
37
+ var import_react = require("react");
38
+ function createClient(config) {
39
+ const baseUrl = config.baseUrl || "https://journey-hive.replit.app";
40
+ const headers = {
41
+ "Content-Type": "application/json",
42
+ Authorization: `Bearer ${config.apiKey}`
43
+ };
44
+ async function request(method, path, body) {
45
+ const res = await fetch(`${baseUrl}${path}`, {
46
+ method,
47
+ headers,
48
+ body: body ? JSON.stringify(body) : void 0
49
+ });
50
+ if (!res.ok) {
51
+ const err = await res.json().catch(() => ({}));
52
+ throw new Error(err?.error?.message || `Request failed with status ${res.status}`);
53
+ }
54
+ return res.json();
55
+ }
56
+ async function* streamRequest(path, body) {
57
+ const res = await fetch(`${baseUrl}${path}`, {
58
+ method: "POST",
59
+ headers,
60
+ body: JSON.stringify(body)
61
+ });
62
+ if (!res.ok) {
63
+ const err = await res.json().catch(() => ({}));
64
+ throw new Error(err?.error?.message || `Request failed with status ${res.status}`);
65
+ }
66
+ const reader = res.body?.getReader();
67
+ if (!reader) throw new Error("No response body");
68
+ const decoder = new TextDecoder();
69
+ let buffer = "";
70
+ while (true) {
71
+ const { done, value } = await reader.read();
72
+ if (done) break;
73
+ buffer += decoder.decode(value, { stream: true });
74
+ const lines = buffer.split("\n");
75
+ buffer = lines.pop() || "";
76
+ let currentEvent = "";
77
+ for (const line of lines) {
78
+ if (line.startsWith("event: ")) {
79
+ currentEvent = line.slice(7).trim();
80
+ } else if (line.startsWith("data: ")) {
81
+ const dataStr = line.slice(6);
82
+ try {
83
+ const data = JSON.parse(dataStr);
84
+ yield { event: currentEvent, data };
85
+ } catch {
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ return {
92
+ config,
93
+ responses: {
94
+ async create(params) {
95
+ if (params.stream) {
96
+ return streamRequest("/v1/responses", params);
97
+ }
98
+ return request("POST", "/v1/responses", params);
99
+ }
100
+ },
101
+ conversations: {
102
+ get: (id) => request("GET", `/v1/conversations/${id}`),
103
+ messages: (id) => request("GET", `/v1/conversations/${id}/messages`)
104
+ },
105
+ agents: {
106
+ get: (id) => request("GET", `/v1/agents/${id}`),
107
+ list: () => request("GET", "/v1/agents"),
108
+ update: (id, params) => request("PATCH", `/v1/agents/${id}`, params)
109
+ }
110
+ };
111
+ }
112
+ var JourneyHiveContext = (0, import_react.createContext)(null);
113
+ function JourneyHiveProvider({ apiKey, baseUrl, children }) {
114
+ const clientRef = (0, import_react.useRef)(null);
115
+ if (!clientRef.current || clientRef.current.config.apiKey !== apiKey || clientRef.current.config.baseUrl !== baseUrl) {
116
+ clientRef.current = createClient({ apiKey, baseUrl });
117
+ }
118
+ return (0, import_react.createElement)(JourneyHiveContext.Provider, { value: clientRef.current }, children);
119
+ }
120
+ function useJourneyHive() {
121
+ const client = (0, import_react.useContext)(JourneyHiveContext);
122
+ if (!client) {
123
+ throw new Error("useJourneyHive must be used within a JourneyHiveProvider");
124
+ }
125
+ return client;
126
+ }
127
+ function useResponse(params) {
128
+ const client = useJourneyHive();
129
+ const [data, setData] = (0, import_react.useState)(null);
130
+ const [isLoading, setIsLoading] = (0, import_react.useState)(false);
131
+ const [isStreaming, setIsStreaming] = (0, import_react.useState)(false);
132
+ const [streamedText, setStreamedText] = (0, import_react.useState)("");
133
+ const [error, setError] = (0, import_react.useState)(null);
134
+ const send = (0, import_react.useCallback)(
135
+ async (input) => {
136
+ setIsLoading(true);
137
+ setIsStreaming(false);
138
+ setStreamedText("");
139
+ setError(null);
140
+ setData(null);
141
+ try {
142
+ const createParams = {
143
+ agent_id: params?.agent_id || "",
144
+ input,
145
+ stream: true,
146
+ ...params
147
+ };
148
+ const result = await client.responses.create(createParams);
149
+ if (Symbol.asyncIterator in result) {
150
+ setIsStreaming(true);
151
+ let accumulated = "";
152
+ for await (const { event, data: eventData } of result) {
153
+ if (event === "response.output_text.delta") {
154
+ accumulated += eventData.delta;
155
+ setStreamedText(accumulated);
156
+ } else if (event === "response.completed") {
157
+ setData(eventData);
158
+ } else if (event === "response.failed") {
159
+ throw new Error(eventData.error?.message || "Response failed");
160
+ }
161
+ }
162
+ setIsStreaming(false);
163
+ } else {
164
+ setData(result);
165
+ }
166
+ } catch (err) {
167
+ setError(err instanceof Error ? err : new Error(String(err)));
168
+ } finally {
169
+ setIsLoading(false);
170
+ setIsStreaming(false);
171
+ }
172
+ },
173
+ [client, params]
174
+ );
175
+ return { data, isLoading, isStreaming, streamedText, error, send };
176
+ }
177
+ function useConversation(conversationId) {
178
+ const client = useJourneyHive();
179
+ const [conversation, setConversation] = (0, import_react.useState)(null);
180
+ const [messages, setMessages] = (0, import_react.useState)([]);
181
+ const [isLoading, setIsLoading] = (0, import_react.useState)(true);
182
+ const [error, setError] = (0, import_react.useState)(null);
183
+ (0, import_react.useEffect)(() => {
184
+ if (!conversationId) return;
185
+ setIsLoading(true);
186
+ Promise.all([
187
+ client.conversations.get(conversationId),
188
+ client.conversations.messages(conversationId)
189
+ ]).then(([conv, msgResult]) => {
190
+ setConversation(conv);
191
+ setMessages(msgResult.data);
192
+ }).catch((err) => setError(err instanceof Error ? err : new Error(String(err)))).finally(() => setIsLoading(false));
193
+ }, [conversationId, client]);
194
+ const sendMessage = (0, import_react.useCallback)(
195
+ async (input) => {
196
+ if (!conversation) return;
197
+ const optimisticMsg = {
198
+ id: `temp_${Date.now()}`,
199
+ object: "message",
200
+ role: "user",
201
+ content: [{ type: "output_text", text: input }],
202
+ created_at: Math.floor(Date.now() / 1e3)
203
+ };
204
+ setMessages((prev) => [...prev, optimisticMsg]);
205
+ try {
206
+ const result = await client.responses.create({
207
+ agent_id: conversation.agent_id,
208
+ input,
209
+ conversation_id: conversationId
210
+ });
211
+ const response = result;
212
+ if (response.output) {
213
+ const assistantMsg = {
214
+ id: response.output[0]?.id || `msg_${Date.now()}`,
215
+ object: "message",
216
+ role: "assistant",
217
+ content: response.output[0]?.content || [],
218
+ created_at: response.created_at
219
+ };
220
+ setMessages((prev) => [...prev, assistantMsg]);
221
+ }
222
+ } catch (err) {
223
+ setError(err instanceof Error ? err : new Error(String(err)));
224
+ setMessages((prev) => prev.filter((m) => m.id !== optimisticMsg.id));
225
+ }
226
+ },
227
+ [client, conversation, conversationId]
228
+ );
229
+ return { conversation, messages, isLoading, error, sendMessage };
230
+ }
231
+ function useAgent(agentId) {
232
+ const client = useJourneyHive();
233
+ const [agent, setAgent] = (0, import_react.useState)(null);
234
+ const [isLoading, setIsLoading] = (0, import_react.useState)(true);
235
+ const [error, setError] = (0, import_react.useState)(null);
236
+ (0, import_react.useEffect)(() => {
237
+ if (!agentId) return;
238
+ setIsLoading(true);
239
+ client.agents.get(agentId).then(setAgent).catch((err) => setError(err instanceof Error ? err : new Error(String(err)))).finally(() => setIsLoading(false));
240
+ }, [agentId, client]);
241
+ const update = (0, import_react.useCallback)(
242
+ async (params) => {
243
+ try {
244
+ const updated = await client.agents.update(agentId, params);
245
+ setAgent(updated);
246
+ } catch (err) {
247
+ setError(err instanceof Error ? err : new Error(String(err)));
248
+ }
249
+ },
250
+ [client, agentId]
251
+ );
252
+ return { agent, isLoading, error, update };
253
+ }
254
+ function useAgents() {
255
+ const client = useJourneyHive();
256
+ const [agents, setAgents] = (0, import_react.useState)([]);
257
+ const [isLoading, setIsLoading] = (0, import_react.useState)(true);
258
+ const [error, setError] = (0, import_react.useState)(null);
259
+ (0, import_react.useEffect)(() => {
260
+ setIsLoading(true);
261
+ client.agents.list().then((result) => setAgents(result.data)).catch((err) => setError(err instanceof Error ? err : new Error(String(err)))).finally(() => setIsLoading(false));
262
+ }, [client]);
263
+ return { agents, isLoading, error };
264
+ }
265
+
266
+ // src/components.tsx
267
+ var import_react2 = require("react");
268
+ function ResponseStream({ agentId, input, onComplete, className }) {
269
+ const { streamedText, isStreaming, isLoading, error, send } = useResponse({ agent_id: agentId });
270
+ const sentRef = (0, import_react2.useRef)(false);
271
+ (0, import_react2.useEffect)(() => {
272
+ if (input && !sentRef.current) {
273
+ sentRef.current = true;
274
+ send(input);
275
+ }
276
+ }, [input, send]);
277
+ (0, import_react2.useEffect)(() => {
278
+ if (!isStreaming && !isLoading && streamedText && onComplete) {
279
+ onComplete(streamedText);
280
+ }
281
+ }, [isStreaming, isLoading, streamedText, onComplete]);
282
+ if (error) {
283
+ return (0, import_react2.createElement)("div", { className: `jh-error ${className || ""}`.trim() }, error.message);
284
+ }
285
+ return (0, import_react2.createElement)(
286
+ "div",
287
+ { className: `jh-response-stream ${className || ""}`.trim() },
288
+ (0, import_react2.createElement)("div", { className: "jh-stream-content" }, streamedText || ""),
289
+ isStreaming ? (0, import_react2.createElement)(
290
+ "span",
291
+ { className: "jh-typing-indicator" },
292
+ (0, import_react2.createElement)("span", { className: "jh-dot" }),
293
+ (0, import_react2.createElement)("span", { className: "jh-dot" }),
294
+ (0, import_react2.createElement)("span", { className: "jh-dot" })
295
+ ) : null
296
+ );
297
+ }
298
+ function MessageBubble({ role, content, timestamp }) {
299
+ const isUser = role === "user";
300
+ const time = timestamp ? new Date(timestamp * 1e3).toLocaleTimeString() : null;
301
+ return (0, import_react2.createElement)(
302
+ "div",
303
+ {
304
+ className: `jh-message-bubble jh-message-${isUser ? "user" : "assistant"}`,
305
+ style: {
306
+ display: "flex",
307
+ flexDirection: "column",
308
+ alignItems: isUser ? "flex-end" : "flex-start",
309
+ marginBottom: "8px"
310
+ }
311
+ },
312
+ (0, import_react2.createElement)(
313
+ "div",
314
+ {
315
+ className: "jh-message-content",
316
+ style: {
317
+ padding: "8px 12px",
318
+ borderRadius: "8px",
319
+ maxWidth: "80%"
320
+ }
321
+ },
322
+ content
323
+ ),
324
+ time ? (0, import_react2.createElement)(
325
+ "span",
326
+ {
327
+ className: "jh-message-time",
328
+ style: { fontSize: "0.75em", opacity: 0.6, marginTop: "2px" }
329
+ },
330
+ time
331
+ ) : null
332
+ );
333
+ }
334
+ function ConversationView({ conversationId, agentId, className }) {
335
+ const { messages, isLoading, error, sendMessage } = useConversation(conversationId);
336
+ const [inputValue, setInputValue] = (0, import_react2.useState)("");
337
+ const messagesEndRef = (0, import_react2.useRef)(null);
338
+ (0, import_react2.useEffect)(() => {
339
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
340
+ }, [messages]);
341
+ const handleSubmit = (0, import_react2.useCallback)(
342
+ (e) => {
343
+ e.preventDefault();
344
+ if (!inputValue.trim()) return;
345
+ sendMessage(inputValue.trim());
346
+ setInputValue("");
347
+ },
348
+ [inputValue, sendMessage]
349
+ );
350
+ if (error) {
351
+ return (0, import_react2.createElement)("div", { className: `jh-error ${className || ""}`.trim() }, error.message);
352
+ }
353
+ return (0, import_react2.createElement)(
354
+ "div",
355
+ {
356
+ className: `jh-conversation-view ${className || ""}`.trim(),
357
+ style: { display: "flex", flexDirection: "column", height: "100%" }
358
+ },
359
+ (0, import_react2.createElement)(
360
+ "div",
361
+ {
362
+ className: "jh-messages",
363
+ style: { flex: 1, overflowY: "auto", padding: "16px" }
364
+ },
365
+ isLoading ? (0, import_react2.createElement)("div", { className: "jh-loading" }, "Loading messages...") : messages.map((msg) => {
366
+ const text = msg.content?.map((c) => c.type === "output_text" ? c.text : "").join("") || "";
367
+ return (0, import_react2.createElement)(MessageBubble, {
368
+ key: msg.id,
369
+ role: msg.role,
370
+ content: text,
371
+ timestamp: msg.created_at
372
+ });
373
+ }),
374
+ (0, import_react2.createElement)("div", { ref: messagesEndRef })
375
+ ),
376
+ (0, import_react2.createElement)(
377
+ "form",
378
+ {
379
+ onSubmit: handleSubmit,
380
+ className: "jh-input-form",
381
+ style: { display: "flex", padding: "8px", gap: "8px" }
382
+ },
383
+ (0, import_react2.createElement)("input", {
384
+ type: "text",
385
+ value: inputValue,
386
+ onChange: (e) => setInputValue(e.target.value),
387
+ placeholder: "Type a message...",
388
+ className: "jh-input",
389
+ style: { flex: 1, padding: "8px", borderRadius: "4px", border: "1px solid #ccc" }
390
+ }),
391
+ (0, import_react2.createElement)(
392
+ "button",
393
+ {
394
+ type: "submit",
395
+ className: "jh-send-button",
396
+ style: { padding: "8px 16px", borderRadius: "4px" }
397
+ },
398
+ "Send"
399
+ )
400
+ )
401
+ );
402
+ }
403
+ function AgentStatus({ agent }) {
404
+ const statusColors = {
405
+ active: "#22c55e",
406
+ sleeping: "#eab308",
407
+ provisioning: "#3b82f6",
408
+ error: "#ef4444",
409
+ stopped: "#6b7280"
410
+ };
411
+ const color = statusColors[agent.status] || "#6b7280";
412
+ return (0, import_react2.createElement)(
413
+ "span",
414
+ {
415
+ className: "jh-agent-status",
416
+ style: {
417
+ display: "inline-flex",
418
+ alignItems: "center",
419
+ gap: "6px",
420
+ padding: "2px 8px",
421
+ borderRadius: "9999px",
422
+ fontSize: "0.75em",
423
+ fontWeight: 500,
424
+ border: `1px solid ${color}`,
425
+ color
426
+ }
427
+ },
428
+ (0, import_react2.createElement)("span", {
429
+ style: {
430
+ width: "6px",
431
+ height: "6px",
432
+ borderRadius: "50%",
433
+ backgroundColor: color
434
+ }
435
+ }),
436
+ agent.status
437
+ );
438
+ }
439
+ // Annotate the CommonJS export names for ESM import in node:
440
+ 0 && (module.exports = {
441
+ AgentStatus,
442
+ ConversationView,
443
+ JourneyHiveProvider,
444
+ MessageBubble,
445
+ ResponseStream,
446
+ useAgent,
447
+ useAgents,
448
+ useConversation,
449
+ useJourneyHive,
450
+ useResponse
451
+ });