@fencyai/react 0.1.32 → 0.1.34

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,22 @@
1
+ import { FencyInstance } from '@fencyai/js';
2
+ export declare const ChatCompletionContextValue: import("react").Context<ChatCompletionContext | undefined>;
3
+ /**
4
+ * Provider component that provides Fency instance to child components
5
+ * Expects a promise that resolves to a Fency instance
6
+ */
7
+ export declare function ChatCompletionProvider({ fency, children, }: ChatCompletionProviderProps): import("react/jsx-runtime").JSX.Element | null;
8
+ export interface ChatCompletionContext {
9
+ fency: FencyInstance;
10
+ loading: boolean;
11
+ error: Error | null;
12
+ }
13
+ /**
14
+ * Props for ChatCompletionProvider
15
+ */
16
+ export interface ChatCompletionProviderProps {
17
+ fency: Promise<FencyInstance>;
18
+ children: React.ReactNode;
19
+ options?: {
20
+ fetchClientSecret: () => Promise<string>;
21
+ };
22
+ }
@@ -1,12 +1,12 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useEffect, useState } from 'react';
3
3
  // Create the context
4
- export const FencyContextValue = createContext(undefined);
4
+ export const ChatCompletionContextValue = createContext(undefined);
5
5
  /**
6
6
  * Provider component that provides Fency instance to child components
7
7
  * Expects a promise that resolves to a Fency instance
8
8
  */
9
- export function FencyProvider({ fency, children }) {
9
+ export function ChatCompletionProvider({ fency, children, }) {
10
10
  const [fencyInstance, setFencyInstance] = useState(null);
11
11
  const [loading, setLoading] = useState(true);
12
12
  const [error, setError] = useState(null);
@@ -33,5 +33,5 @@ export function FencyProvider({ fency, children }) {
33
33
  loading,
34
34
  error,
35
35
  };
36
- return (_jsx(FencyContextValue.Provider, { value: value, children: children }));
36
+ return (_jsx(ChatCompletionContextValue.Provider, { value: value, children: children }));
37
37
  }
@@ -0,0 +1,5 @@
1
+ import type { ChatCompletionContext } from './ChatCompletionProvider';
2
+ /**
3
+ * Hook to access Fency instance and loading state
4
+ */
5
+ export declare function useChatCompletionContext(): ChatCompletionContext;
@@ -0,0 +1,12 @@
1
+ import { useContext } from 'react';
2
+ import { ChatCompletionContextValue } from './ChatCompletionProvider';
3
+ /**
4
+ * Hook to access Fency instance and loading state
5
+ */
6
+ export function useChatCompletionContext() {
7
+ const context = useContext(ChatCompletionContextValue);
8
+ if (context === undefined) {
9
+ throw new Error('useChatCompletionContext must be used within a ChatCompletionProvider');
10
+ }
11
+ return context;
12
+ }
@@ -10,21 +10,26 @@ interface Completions {
10
10
  }
11
11
  interface HookResponse {
12
12
  chatCompletions: Completions[];
13
- createStreamingChatCompletion: (params: {
13
+ createChatCompletion: (params: {
14
14
  openai?: CreateOpenAiChatCompletionParams;
15
15
  gemini?: CreateGeminiChatCompletionParams;
16
16
  anthropic?: CreateAnthropicChatCompletionParams;
17
- }) => Promise<{
18
- chatCompletionStreamId: string;
19
- chatCompletionId: string;
20
- }>;
21
- createSynchronousChatCompletion: <T extends ZodTypeAny>(params: {
17
+ }) => Promise<ChatCompletion>;
18
+ createStructuredChatCompletion: <T extends ZodTypeAny>(params: {
22
19
  openai?: CreateOpenAiChatCompletionParams;
23
20
  gemini?: CreateGeminiChatCompletionParams;
24
21
  anthropic?: CreateAnthropicChatCompletionParams;
25
- responseFormat?: T;
22
+ responseFormat: T;
26
23
  }) => Promise<ChatCompletion & {
27
- structuredResponse?: z.infer<T>;
24
+ structuredResponse: z.infer<T>;
25
+ }>;
26
+ createStreamingChatCompletion: (params: {
27
+ openai?: CreateOpenAiChatCompletionParams;
28
+ gemini?: CreateGeminiChatCompletionParams;
29
+ anthropic?: CreateAnthropicChatCompletionParams;
30
+ }) => Promise<{
31
+ chatCompletionStreamId: string;
32
+ chatCompletionId: string;
28
33
  }>;
29
34
  latestCompletion: Completions | null;
30
35
  }
@@ -2,25 +2,24 @@
2
2
  import { createChatCompletion, createChatCompletionStream, } from '@fencyai/js';
3
3
  import { useCallback, useEffect, useMemo, useState } from 'react';
4
4
  import z from 'zod';
5
+ import { useChatCompletionContext } from './useChatCompletionContext';
5
6
  import { useEventSource } from './useEventSource';
6
- import { useFency } from './useFency';
7
7
  export function useChatCompletions() {
8
- const fency = useFency();
8
+ const context = useChatCompletionContext();
9
9
  const { chunks, setUrl } = useEventSource();
10
10
  const [chatCompletions, setChatCompletions] = useState([]);
11
11
  const [stream, setStream] = useState(null);
12
- console.log('v2');
13
12
  const createStreamingChatCompletion = useCallback(async (params) => {
14
13
  // Step 1: Create stream if not exists
15
14
  const s = await createChatCompletionStream({
16
- pk: fency.fency.publishableKey,
17
- baseUrl: fency.fency.baseUrl,
15
+ pk: context.fency.publishableKey,
16
+ baseUrl: context.fency.baseUrl,
18
17
  });
19
18
  setStream(s);
20
19
  // Step 2: Send chat completion
21
20
  const chatCompletion = await createChatCompletion({
22
- pk: fency.fency.publishableKey,
23
- baseUrl: fency.fency.baseUrl,
21
+ pk: context.fency.publishableKey,
22
+ baseUrl: context.fency.baseUrl,
24
23
  request: {
25
24
  streamId: s.id,
26
25
  openai: params.openai
@@ -48,17 +47,41 @@ export function useChatCompletions() {
48
47
  chatCompletionStreamId: s.id,
49
48
  chatCompletionId: chatCompletion.id,
50
49
  };
51
- }, [fency]);
50
+ }, [context]);
52
51
  const createSynchronousChatCompletion = useCallback(async (params) => {
53
- const jsonSchema = params.responseFormat
54
- ? z.toJSONSchema(params.responseFormat)
55
- : undefined;
56
- const parsedJsonSchema = jsonSchema
57
- ? JSON.stringify(jsonSchema)
58
- : undefined;
59
52
  const chatCompletion = await createChatCompletion({
60
- pk: fency.fency.publishableKey,
61
- baseUrl: fency.fency.baseUrl,
53
+ pk: context.fency.publishableKey,
54
+ baseUrl: context.fency.baseUrl,
55
+ request: {
56
+ openai: params.openai
57
+ ? {
58
+ model: params.openai.model,
59
+ messages: params.openai.messages,
60
+ }
61
+ : undefined,
62
+ gemini: params.gemini
63
+ ? {
64
+ model: params.gemini.model,
65
+ content: params.gemini.content,
66
+ }
67
+ : undefined,
68
+ anthropic: params.anthropic
69
+ ? {
70
+ model: params.anthropic.model,
71
+ messages: params.anthropic.messages,
72
+ }
73
+ : undefined,
74
+ },
75
+ });
76
+ setChatCompletions((prev) => [...prev, chatCompletion]);
77
+ return chatCompletion;
78
+ }, [context]);
79
+ const createStructuredChatCompletion = useCallback(async (params) => {
80
+ const jsonSchema = z.toJSONSchema(params.responseFormat);
81
+ const parsedJsonSchema = JSON.stringify(jsonSchema);
82
+ const chatCompletion = await createChatCompletion({
83
+ pk: context.fency.publishableKey,
84
+ baseUrl: context.fency.baseUrl,
62
85
  request: {
63
86
  openai: params.openai
64
87
  ? {
@@ -83,16 +106,14 @@ export function useChatCompletions() {
83
106
  },
84
107
  });
85
108
  setChatCompletions((prev) => [...prev, chatCompletion]);
86
- if (chatCompletion.responseIsStructured &&
87
- params.responseFormat &&
88
- chatCompletion.response) {
109
+ if (chatCompletion.response) {
89
110
  return {
90
111
  ...chatCompletion,
91
112
  structuredResponse: params.responseFormat.parse(JSON.parse(chatCompletion.response)),
92
113
  };
93
114
  }
94
- return chatCompletion;
95
- }, [fency]);
115
+ throw new Error('No response from chat completion');
116
+ }, [context]);
96
117
  const completions = useMemo(() => {
97
118
  const completions = [];
98
119
  for (const chatCompletion of chatCompletions) {
@@ -115,12 +136,13 @@ export function useChatCompletions() {
115
136
  }, [completions]);
116
137
  useEffect(() => {
117
138
  if (stream) {
118
- setUrl(`${fency.fency.baseUrl}/v1/pub/chat-completion-streams/${stream.id}?pk=${fency.fency.publishableKey}`);
139
+ setUrl(`${context.fency.baseUrl}/v1/pub/chat-completion-streams/${stream.id}?pk=${context.fency.publishableKey}`);
119
140
  }
120
- }, [stream, fency.fency.publishableKey, setUrl]);
141
+ }, [stream, context.fency.publishableKey, setUrl]);
121
142
  return {
143
+ createChatCompletion: createSynchronousChatCompletion,
144
+ createStructuredChatCompletion: createStructuredChatCompletion,
122
145
  createStreamingChatCompletion: createStreamingChatCompletion,
123
- createSynchronousChatCompletion: createSynchronousChatCompletion,
124
146
  chatCompletions: completions,
125
147
  latestCompletion,
126
148
  };
@@ -6,17 +6,24 @@ export function useEventSource() {
6
6
  if (!url)
7
7
  return;
8
8
  const eventSource = new EventSource(url);
9
- eventSource.onmessage = (event) => {
10
- const chunk = getChatCompletionChunk(event);
9
+ eventSource.onmessage = (message) => {
10
+ if (message.data === '__END_OF_STREAM__') {
11
+ eventSource.close();
12
+ setUrl(null); // Clear URL to prevent reconnection
13
+ return;
14
+ }
15
+ const chunk = getChatCompletionChunk(message);
11
16
  if (chunk) {
12
17
  setChunks((prev) => [...prev, chunk]);
13
18
  }
14
19
  else {
15
- console.warn('Unknown message:', event);
20
+ console.warn('Unknown message:', message);
16
21
  }
17
22
  };
18
23
  eventSource.onerror = (error) => {
19
24
  console.error('EventSource error:', error);
25
+ eventSource.close();
26
+ setUrl(null); // Clear URL on error
20
27
  };
21
28
  return () => {
22
29
  eventSource.close();
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { FencyProvider } from './FencyProvider';
2
- export { useChatCompletions } from './hooks/useChatCompletions';
3
- export { useFency } from './hooks/useFency';
4
- export type { FencyContext, FencyProviderProps } from './FencyProvider';
1
+ export { ChatCompletionProvider } from './chat-completions/ChatCompletionProvider';
2
+ export { useChatCompletionContext } from './chat-completions/useChatCompletionContext';
3
+ export { useChatCompletions } from './chat-completions/useChatCompletions';
4
+ export type { ChatCompletionContext, ChatCompletionProviderProps, } from './chat-completions/ChatCompletionProvider';
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // Re-export components and hooks
2
- export { FencyProvider } from './FencyProvider';
3
- export { useChatCompletions } from './hooks/useChatCompletions';
4
- export { useFency } from './hooks/useFency';
2
+ export { ChatCompletionProvider } from './chat-completions/ChatCompletionProvider';
3
+ export { useChatCompletionContext } from './chat-completions/useChatCompletionContext';
4
+ export { useChatCompletions } from './chat-completions/useChatCompletions';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fencyai/react",
3
- "version": "0.1.32",
3
+ "version": "0.1.34",
4
4
  "description": "> TODO: description",
5
5
  "author": "staklau <steinaageklaussen@gmail.com>",
6
6
  "homepage": "",
@@ -36,7 +36,7 @@
36
36
  "zod": "^4.0.5"
37
37
  },
38
38
  "devDependencies": {
39
- "@fencyai/js": "^0.1.32",
39
+ "@fencyai/js": "^0.1.34",
40
40
  "@types/jest": "^29.5.11",
41
41
  "@types/node": "^20.10.5",
42
42
  "@types/react": "^18.2.45",
@@ -45,8 +45,8 @@
45
45
  "typescript": "^5.3.3"
46
46
  },
47
47
  "peerDependencies": {
48
- "@fencyai/js": "^0.1.32",
48
+ "@fencyai/js": "^0.1.34",
49
49
  "react": ">=16.8.0"
50
50
  },
51
- "gitHead": "a487d68673a259c2490b83a9a6fba991ea02d034"
51
+ "gitHead": "a4dcf1572fcf4587355ffe38e6971b18025e4568"
52
52
  }
@@ -1,19 +0,0 @@
1
- import { FencyInstance } from '@fencyai/js';
2
- export declare const FencyContextValue: import("react").Context<FencyContext | undefined>;
3
- /**
4
- * Provider component that provides Fency instance to child components
5
- * Expects a promise that resolves to a Fency instance
6
- */
7
- export declare function FencyProvider({ fency, children }: FencyProviderProps): import("react/jsx-runtime").JSX.Element | null;
8
- export interface FencyContext {
9
- fency: FencyInstance;
10
- loading: boolean;
11
- error: Error | null;
12
- }
13
- /**
14
- * Props for FencyProvider
15
- */
16
- export interface FencyProviderProps {
17
- fency: Promise<FencyInstance>;
18
- children: React.ReactNode;
19
- }
@@ -1,5 +0,0 @@
1
- import type { FencyContext } from '../FencyProvider';
2
- /**
3
- * Hook to access Fency instance and loading state
4
- */
5
- export declare function useFency(): FencyContext;
@@ -1,12 +0,0 @@
1
- import { useContext } from 'react';
2
- import { FencyContextValue } from '../FencyProvider';
3
- /**
4
- * Hook to access Fency instance and loading state
5
- */
6
- export function useFency() {
7
- const context = useContext(FencyContextValue);
8
- if (context === undefined) {
9
- throw new Error('useFency must be used within a FencyProvider');
10
- }
11
- return context;
12
- }