@ragion/react-hooks 0.1.0-alpha.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/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # @ragion/react-hooks
2
+
3
+ React hooks para o Ragion SDK.
4
+
5
+ ## Instalação
6
+
7
+ ```bash
8
+ npm install @ragion/react-hooks @ragion/sdk react
9
+ ```
10
+
11
+ ## Uso Básico
12
+
13
+ ```typescript
14
+ import { RagionProvider, useRagionChat } from '@ragion/react-hooks'
15
+
16
+ function App() {
17
+ return (
18
+ <RagionProvider config={{ apiKey: 'sk_...' }}>
19
+ <ChatComponent />
20
+ </RagionProvider>
21
+ )
22
+ }
23
+
24
+ function ChatComponent() {
25
+ const { messages, sendMessage } = useRagionChat()
26
+ // ...
27
+ }
28
+ ```
29
+
30
+ ## Hooks Disponíveis
31
+
32
+ - `useRagionChat` - Chat com streaming
33
+
34
+ Veja a [documentação completa](../../README.md) para detalhes.
35
+
36
+ ## Build
37
+
38
+ ```bash
39
+ npm run build
40
+ ```
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRagionChat = void 0;
4
+ const react_1 = require("react");
5
+ const RagionProvider_1 = require("../providers/RagionProvider");
6
+ const generateMessageId = () => {
7
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
8
+ };
9
+ /**
10
+ * React hook for managing chat conversations with the Ragion API
11
+ * Handles message state, streaming responses, and conversation flow
12
+ * @param options - Configuration options for the chat
13
+ * @param options.sessionId - Session ID for conversation continuity (optional)
14
+ * @param options.onSessionIdChange - Callback when session ID changes (optional)
15
+ * @returns Object containing chat state and control methods
16
+ * @example
17
+ * ```tsx
18
+ * const {
19
+ * messages,
20
+ * sendMessage,
21
+ * isStreaming,
22
+ * error,
23
+ * clearMessages,
24
+ * abort
25
+ * } = useRagionChat();
26
+ *
27
+ * // Send a message
28
+ * sendMessage('Hello!');
29
+ *
30
+ * // Clear conversation
31
+ * clearMessages();
32
+ *
33
+ * // Cancel ongoing request
34
+ * abort();
35
+ * ```
36
+ */
37
+ const useRagionChat = (options = {}) => {
38
+ const { sdk } = (0, RagionProvider_1.useRagionContext)();
39
+ const { sessionId: initialSessionId, onSessionIdChange } = options;
40
+ const [messages, setMessages] = (0, react_1.useState)([]);
41
+ const [isStreaming, setIsStreaming] = (0, react_1.useState)(false);
42
+ const [error, setError] = (0, react_1.useState)(null);
43
+ const [sessionId, setSessionId] = (0, react_1.useState)(initialSessionId);
44
+ const currentControllerRef = (0, react_1.useRef)(null);
45
+ const currentMessageRef = (0, react_1.useRef)("");
46
+ const isStreamingRef = (0, react_1.useRef)(false);
47
+ (0, react_1.useEffect)(() => {
48
+ if (initialSessionId !== undefined) {
49
+ setSessionId(initialSessionId);
50
+ }
51
+ }, [initialSessionId]);
52
+ (0, react_1.useEffect)(() => {
53
+ if (sessionId && onSessionIdChange) {
54
+ onSessionIdChange(sessionId);
55
+ }
56
+ }, [sessionId, onSessionIdChange]);
57
+ const updateAssistantMessage = (0, react_1.useCallback)((assistantMessageId, content) => {
58
+ setMessages(prev => {
59
+ const lastMessage = prev[prev.length - 1];
60
+ if (lastMessage && lastMessage.role === "assistant" && lastMessage.id === assistantMessageId) {
61
+ return [
62
+ ...prev.slice(0, -1),
63
+ Object.assign(Object.assign({}, lastMessage), { content }),
64
+ ];
65
+ }
66
+ return prev;
67
+ });
68
+ }, []);
69
+ const removeAssistantMessage = (0, react_1.useCallback)((assistantMessageId) => {
70
+ setMessages(prev => {
71
+ const lastMessage = prev[prev.length - 1];
72
+ if (lastMessage && lastMessage.id === assistantMessageId) {
73
+ return prev.slice(0, -1);
74
+ }
75
+ return prev;
76
+ });
77
+ }, []);
78
+ const finalizeAssistantMessage = (0, react_1.useCallback)((assistantMessageId) => {
79
+ setMessages(prev => {
80
+ const lastMessage = prev[prev.length - 1];
81
+ if (lastMessage && lastMessage.id === assistantMessageId) {
82
+ return [
83
+ ...prev.slice(0, -1),
84
+ Object.assign(Object.assign({}, lastMessage), { id: generateMessageId() }),
85
+ ];
86
+ }
87
+ return prev;
88
+ });
89
+ }, []);
90
+ const resetStreamingState = (0, react_1.useCallback)(() => {
91
+ currentMessageRef.current = "";
92
+ isStreamingRef.current = false;
93
+ setIsStreaming(false);
94
+ currentControllerRef.current = null;
95
+ }, []);
96
+ const sendMessage = (0, react_1.useCallback)((message) => {
97
+ if (!message.trim() || isStreamingRef.current)
98
+ return;
99
+ const userMessage = {
100
+ id: generateMessageId(),
101
+ role: "user",
102
+ content: message.trim(),
103
+ timestamp: new Date(),
104
+ };
105
+ setMessages(prev => [...prev, userMessage]);
106
+ setError(null);
107
+ currentMessageRef.current = "";
108
+ isStreamingRef.current = true;
109
+ setIsStreaming(true);
110
+ const assistantMessageId = `streaming-${Date.now()}`;
111
+ setMessages(prev => [
112
+ ...prev,
113
+ {
114
+ id: assistantMessageId,
115
+ role: "assistant",
116
+ content: "",
117
+ timestamp: new Date(),
118
+ },
119
+ ]);
120
+ const controller = sdk.chat.ask({
121
+ message: message.trim(),
122
+ sessionId,
123
+ onChunk: (chunk) => {
124
+ currentMessageRef.current += chunk;
125
+ isStreamingRef.current = true;
126
+ updateAssistantMessage(assistantMessageId, currentMessageRef.current);
127
+ },
128
+ onComplete: () => {
129
+ finalizeAssistantMessage(assistantMessageId);
130
+ resetStreamingState();
131
+ },
132
+ onError: (err) => {
133
+ setError(err);
134
+ removeAssistantMessage(assistantMessageId);
135
+ resetStreamingState();
136
+ },
137
+ });
138
+ currentControllerRef.current = controller;
139
+ }, [sdk, sessionId, updateAssistantMessage, finalizeAssistantMessage, removeAssistantMessage, resetStreamingState]);
140
+ const clearMessages = (0, react_1.useCallback)(() => {
141
+ if (currentControllerRef.current) {
142
+ currentControllerRef.current.abort();
143
+ currentControllerRef.current = null;
144
+ }
145
+ setMessages([]);
146
+ setError(null);
147
+ resetStreamingState();
148
+ }, [resetStreamingState]);
149
+ const abort = (0, react_1.useCallback)(() => {
150
+ if (currentControllerRef.current) {
151
+ currentControllerRef.current.abort();
152
+ currentControllerRef.current = null;
153
+ resetStreamingState();
154
+ }
155
+ }, [resetStreamingState]);
156
+ return {
157
+ messages,
158
+ sendMessage,
159
+ isStreaming,
160
+ error,
161
+ sessionId,
162
+ clearMessages,
163
+ abort,
164
+ };
165
+ };
166
+ exports.useRagionChat = useRagionChat;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRagionChat = exports.useRagionContext = exports.RagionProvider = void 0;
4
+ var RagionProvider_1 = require("./providers/RagionProvider");
5
+ Object.defineProperty(exports, "RagionProvider", { enumerable: true, get: function () { return RagionProvider_1.RagionProvider; } });
6
+ Object.defineProperty(exports, "useRagionContext", { enumerable: true, get: function () { return RagionProvider_1.useRagionContext; } });
7
+ var useChat_1 = require("./hooks/useChat");
8
+ Object.defineProperty(exports, "useRagionChat", { enumerable: true, get: function () { return useChat_1.useRagionChat; } });
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRagionContext = exports.RagionProvider = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const sdk_1 = require("@ragion/sdk");
6
+ const react_1 = require("react");
7
+ const RagionContext = (0, react_1.createContext)(null);
8
+ /**
9
+ * Provider component that initializes and provides the Ragion SDK instance to child components
10
+ * @param props - Component props
11
+ * @param props.config - Ragion SDK configuration
12
+ * @param props.children - Child components that will have access to the SDK
13
+ * @example
14
+ * ```tsx
15
+ * <RagionProvider config={{ apiKey: 'your-api-key' }}>
16
+ * <App />
17
+ * </RagionProvider>
18
+ * ```
19
+ */
20
+ const RagionProvider = ({ config, children }) => {
21
+ const sdk = (0, react_1.useMemo)(() => new sdk_1.RagionSDK(config), [config.apiKey]);
22
+ const value = (0, react_1.useMemo)(() => ({ sdk }), [sdk]);
23
+ return (0, jsx_runtime_1.jsx)(RagionContext.Provider, { value: value, children: children });
24
+ };
25
+ exports.RagionProvider = RagionProvider;
26
+ /**
27
+ * Hook to access the Ragion SDK instance from context
28
+ * @returns Object containing the SDK instance
29
+ * @throws {Error} If used outside of RagionProvider
30
+ * @example
31
+ * ```tsx
32
+ * const { sdk } = useRagionContext();
33
+ * ```
34
+ */
35
+ const useRagionContext = () => {
36
+ const context = (0, react_1.useContext)(RagionContext);
37
+ if (!context) {
38
+ throw new Error("useRagionContext must be used within a RagionProvider");
39
+ }
40
+ return context;
41
+ };
42
+ exports.useRagionContext = useRagionContext;
@@ -0,0 +1,162 @@
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { useRagionContext } from "../providers/RagionProvider";
3
+ const generateMessageId = () => {
4
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
5
+ };
6
+ /**
7
+ * React hook for managing chat conversations with the Ragion API
8
+ * Handles message state, streaming responses, and conversation flow
9
+ * @param options - Configuration options for the chat
10
+ * @param options.sessionId - Session ID for conversation continuity (optional)
11
+ * @param options.onSessionIdChange - Callback when session ID changes (optional)
12
+ * @returns Object containing chat state and control methods
13
+ * @example
14
+ * ```tsx
15
+ * const {
16
+ * messages,
17
+ * sendMessage,
18
+ * isStreaming,
19
+ * error,
20
+ * clearMessages,
21
+ * abort
22
+ * } = useRagionChat();
23
+ *
24
+ * // Send a message
25
+ * sendMessage('Hello!');
26
+ *
27
+ * // Clear conversation
28
+ * clearMessages();
29
+ *
30
+ * // Cancel ongoing request
31
+ * abort();
32
+ * ```
33
+ */
34
+ export const useRagionChat = (options = {}) => {
35
+ const { sdk } = useRagionContext();
36
+ const { sessionId: initialSessionId, onSessionIdChange } = options;
37
+ const [messages, setMessages] = useState([]);
38
+ const [isStreaming, setIsStreaming] = useState(false);
39
+ const [error, setError] = useState(null);
40
+ const [sessionId, setSessionId] = useState(initialSessionId);
41
+ const currentControllerRef = useRef(null);
42
+ const currentMessageRef = useRef("");
43
+ const isStreamingRef = useRef(false);
44
+ useEffect(() => {
45
+ if (initialSessionId !== undefined) {
46
+ setSessionId(initialSessionId);
47
+ }
48
+ }, [initialSessionId]);
49
+ useEffect(() => {
50
+ if (sessionId && onSessionIdChange) {
51
+ onSessionIdChange(sessionId);
52
+ }
53
+ }, [sessionId, onSessionIdChange]);
54
+ const updateAssistantMessage = useCallback((assistantMessageId, content) => {
55
+ setMessages(prev => {
56
+ const lastMessage = prev[prev.length - 1];
57
+ if (lastMessage && lastMessage.role === "assistant" && lastMessage.id === assistantMessageId) {
58
+ return [
59
+ ...prev.slice(0, -1),
60
+ Object.assign(Object.assign({}, lastMessage), { content }),
61
+ ];
62
+ }
63
+ return prev;
64
+ });
65
+ }, []);
66
+ const removeAssistantMessage = useCallback((assistantMessageId) => {
67
+ setMessages(prev => {
68
+ const lastMessage = prev[prev.length - 1];
69
+ if (lastMessage && lastMessage.id === assistantMessageId) {
70
+ return prev.slice(0, -1);
71
+ }
72
+ return prev;
73
+ });
74
+ }, []);
75
+ const finalizeAssistantMessage = useCallback((assistantMessageId) => {
76
+ setMessages(prev => {
77
+ const lastMessage = prev[prev.length - 1];
78
+ if (lastMessage && lastMessage.id === assistantMessageId) {
79
+ return [
80
+ ...prev.slice(0, -1),
81
+ Object.assign(Object.assign({}, lastMessage), { id: generateMessageId() }),
82
+ ];
83
+ }
84
+ return prev;
85
+ });
86
+ }, []);
87
+ const resetStreamingState = useCallback(() => {
88
+ currentMessageRef.current = "";
89
+ isStreamingRef.current = false;
90
+ setIsStreaming(false);
91
+ currentControllerRef.current = null;
92
+ }, []);
93
+ const sendMessage = useCallback((message) => {
94
+ if (!message.trim() || isStreamingRef.current)
95
+ return;
96
+ const userMessage = {
97
+ id: generateMessageId(),
98
+ role: "user",
99
+ content: message.trim(),
100
+ timestamp: new Date(),
101
+ };
102
+ setMessages(prev => [...prev, userMessage]);
103
+ setError(null);
104
+ currentMessageRef.current = "";
105
+ isStreamingRef.current = true;
106
+ setIsStreaming(true);
107
+ const assistantMessageId = `streaming-${Date.now()}`;
108
+ setMessages(prev => [
109
+ ...prev,
110
+ {
111
+ id: assistantMessageId,
112
+ role: "assistant",
113
+ content: "",
114
+ timestamp: new Date(),
115
+ },
116
+ ]);
117
+ const controller = sdk.chat.ask({
118
+ message: message.trim(),
119
+ sessionId,
120
+ onChunk: (chunk) => {
121
+ currentMessageRef.current += chunk;
122
+ isStreamingRef.current = true;
123
+ updateAssistantMessage(assistantMessageId, currentMessageRef.current);
124
+ },
125
+ onComplete: () => {
126
+ finalizeAssistantMessage(assistantMessageId);
127
+ resetStreamingState();
128
+ },
129
+ onError: (err) => {
130
+ setError(err);
131
+ removeAssistantMessage(assistantMessageId);
132
+ resetStreamingState();
133
+ },
134
+ });
135
+ currentControllerRef.current = controller;
136
+ }, [sdk, sessionId, updateAssistantMessage, finalizeAssistantMessage, removeAssistantMessage, resetStreamingState]);
137
+ const clearMessages = useCallback(() => {
138
+ if (currentControllerRef.current) {
139
+ currentControllerRef.current.abort();
140
+ currentControllerRef.current = null;
141
+ }
142
+ setMessages([]);
143
+ setError(null);
144
+ resetStreamingState();
145
+ }, [resetStreamingState]);
146
+ const abort = useCallback(() => {
147
+ if (currentControllerRef.current) {
148
+ currentControllerRef.current.abort();
149
+ currentControllerRef.current = null;
150
+ resetStreamingState();
151
+ }
152
+ }, [resetStreamingState]);
153
+ return {
154
+ messages,
155
+ sendMessage,
156
+ isStreaming,
157
+ error,
158
+ sessionId,
159
+ clearMessages,
160
+ abort,
161
+ };
162
+ };
@@ -0,0 +1,2 @@
1
+ export { RagionProvider, useRagionContext } from "./providers/RagionProvider";
2
+ export { useRagionChat } from "./hooks/useChat";
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { RagionSDK } from "@ragion/sdk";
3
+ import { createContext, useContext, useMemo } from "react";
4
+ const RagionContext = createContext(null);
5
+ /**
6
+ * Provider component that initializes and provides the Ragion SDK instance to child components
7
+ * @param props - Component props
8
+ * @param props.config - Ragion SDK configuration
9
+ * @param props.children - Child components that will have access to the SDK
10
+ * @example
11
+ * ```tsx
12
+ * <RagionProvider config={{ apiKey: 'your-api-key' }}>
13
+ * <App />
14
+ * </RagionProvider>
15
+ * ```
16
+ */
17
+ export const RagionProvider = ({ config, children }) => {
18
+ const sdk = useMemo(() => new RagionSDK(config), [config.apiKey]);
19
+ const value = useMemo(() => ({ sdk }), [sdk]);
20
+ return _jsx(RagionContext.Provider, { value: value, children: children });
21
+ };
22
+ /**
23
+ * Hook to access the Ragion SDK instance from context
24
+ * @returns Object containing the SDK instance
25
+ * @throws {Error} If used outside of RagionProvider
26
+ * @example
27
+ * ```tsx
28
+ * const { sdk } = useRagionContext();
29
+ * ```
30
+ */
31
+ export const useRagionContext = () => {
32
+ const context = useContext(RagionContext);
33
+ if (!context) {
34
+ throw new Error("useRagionContext must be used within a RagionProvider");
35
+ }
36
+ return context;
37
+ };
@@ -0,0 +1,43 @@
1
+ import type { ChatMessage } from "@ragion/sdk";
2
+ export interface UseRagionChatOptions {
3
+ sessionId?: string;
4
+ onSessionIdChange?: (sessionId: string) => void;
5
+ }
6
+ export interface UseRagionChatReturn {
7
+ messages: ChatMessage[];
8
+ sendMessage: (message: string) => void;
9
+ isStreaming: boolean;
10
+ error: Error | null;
11
+ sessionId: string | undefined;
12
+ clearMessages: () => void;
13
+ abort: () => void;
14
+ }
15
+ /**
16
+ * React hook for managing chat conversations with the Ragion API
17
+ * Handles message state, streaming responses, and conversation flow
18
+ * @param options - Configuration options for the chat
19
+ * @param options.sessionId - Session ID for conversation continuity (optional)
20
+ * @param options.onSessionIdChange - Callback when session ID changes (optional)
21
+ * @returns Object containing chat state and control methods
22
+ * @example
23
+ * ```tsx
24
+ * const {
25
+ * messages,
26
+ * sendMessage,
27
+ * isStreaming,
28
+ * error,
29
+ * clearMessages,
30
+ * abort
31
+ * } = useRagionChat();
32
+ *
33
+ * // Send a message
34
+ * sendMessage('Hello!');
35
+ *
36
+ * // Clear conversation
37
+ * clearMessages();
38
+ *
39
+ * // Cancel ongoing request
40
+ * abort();
41
+ * ```
42
+ */
43
+ export declare const useRagionChat: (options?: UseRagionChatOptions) => UseRagionChatReturn;
@@ -0,0 +1,4 @@
1
+ export { RagionProvider, useRagionContext } from "./providers/RagionProvider";
2
+ export type { RagionProviderProps } from "./providers/RagionProvider";
3
+ export { useRagionChat } from "./hooks/useChat";
4
+ export type { UseRagionChatOptions, UseRagionChatReturn } from "./hooks/useChat";
@@ -0,0 +1,33 @@
1
+ import { RagionSDK, type RagionConfig } from "@ragion/sdk";
2
+ import { type ReactNode } from "react";
3
+ interface RagionContextType {
4
+ sdk: RagionSDK;
5
+ }
6
+ export interface RagionProviderProps {
7
+ config: RagionConfig;
8
+ children: ReactNode;
9
+ }
10
+ /**
11
+ * Provider component that initializes and provides the Ragion SDK instance to child components
12
+ * @param props - Component props
13
+ * @param props.config - Ragion SDK configuration
14
+ * @param props.children - Child components that will have access to the SDK
15
+ * @example
16
+ * ```tsx
17
+ * <RagionProvider config={{ apiKey: 'your-api-key' }}>
18
+ * <App />
19
+ * </RagionProvider>
20
+ * ```
21
+ */
22
+ export declare const RagionProvider: ({ config, children }: RagionProviderProps) => import("react/jsx-runtime").JSX.Element;
23
+ /**
24
+ * Hook to access the Ragion SDK instance from context
25
+ * @returns Object containing the SDK instance
26
+ * @throws {Error} If used outside of RagionProvider
27
+ * @example
28
+ * ```tsx
29
+ * const { sdk } = useRagionContext();
30
+ * ```
31
+ */
32
+ export declare const useRagionContext: () => RagionContextType;
33
+ export {};
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@ragion/react-hooks",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "React hooks for Ragion SDK - External integrations with x-Api-Key",
5
+ "main": "./dist/cjs/index.js",
6
+ "module": "./dist/esm/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/esm/index.js",
11
+ "require": "./dist/cjs/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "rimraf dist && tsc && tsc --project tsconfig.esm.json",
20
+ "dev": "tsc --watch",
21
+ "clean": "rimraf dist"
22
+ },
23
+ "peerDependencies": {
24
+ "@ragion/sdk": "^0.1.0-alpha.0",
25
+ "react": ">=18.0.0"
26
+ },
27
+ "keywords": [
28
+ "ragion",
29
+ "rag",
30
+ "ai",
31
+ "chat",
32
+ "react",
33
+ "hooks"
34
+ ],
35
+ "author": "Ragion",
36
+ "license": "MIT",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/ragion/ragion-app"
40
+ },
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^25.0.0",
46
+ "@types/react": "^19.2.13",
47
+ "eslint": "^9.18.0",
48
+ "eslint-config-prettier": "^10.0.1",
49
+ "eslint-plugin-prettier": "^5.2.2",
50
+ "prettier": "^3.4.2",
51
+ "rimraf": "^5.0.0",
52
+ "ts-node": "^10.9.2",
53
+ "typescript": "^5.6.3",
54
+ "typescript-eslint": "^8.20.0"
55
+ }
56
+ }