@fencyai/react 0.1.31 → 0.1.33

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,37 @@
1
+ import { ChatCompletion, CreateAnthropicChatCompletionParams, CreateGeminiChatCompletionParams, CreateOpenAiChatCompletionParams } from '@fencyai/js';
2
+ import z, { ZodTypeAny } from 'zod';
3
+ import { ChatCompletionChunk } from './useEventSource';
4
+ interface Completions {
5
+ chatCompletion: ChatCompletion & {
6
+ structuredResponse?: any;
7
+ };
8
+ chunks: ChatCompletionChunk[];
9
+ fullMessage: string;
10
+ }
11
+ interface HookResponse {
12
+ chatCompletions: Completions[];
13
+ createChatCompletion: (params: {
14
+ openai?: CreateOpenAiChatCompletionParams;
15
+ gemini?: CreateGeminiChatCompletionParams;
16
+ anthropic?: CreateAnthropicChatCompletionParams;
17
+ }) => Promise<ChatCompletion>;
18
+ createStructuredChatCompletion: <T extends ZodTypeAny>(params: {
19
+ openai?: CreateOpenAiChatCompletionParams;
20
+ gemini?: CreateGeminiChatCompletionParams;
21
+ anthropic?: CreateAnthropicChatCompletionParams;
22
+ responseFormat: T;
23
+ }) => Promise<ChatCompletion & {
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;
33
+ }>;
34
+ latestCompletion: Completions | null;
35
+ }
36
+ export declare function useChatCompletions(): HookResponse;
37
+ export {};
@@ -0,0 +1,150 @@
1
+ // hooks/useChatCompletion.ts
2
+ import { createChatCompletion, createChatCompletionStream, } from '@fencyai/js';
3
+ import { useCallback, useEffect, useMemo, useState } from 'react';
4
+ import z from 'zod';
5
+ import { useEventSource } from './useEventSource';
6
+ import { useFency } from './useFency';
7
+ export function useChatCompletions() {
8
+ const fency = useFency();
9
+ const { chunks, setUrl } = useEventSource();
10
+ const [chatCompletions, setChatCompletions] = useState([]);
11
+ const [stream, setStream] = useState(null);
12
+ console.log('v2');
13
+ const createStreamingChatCompletion = useCallback(async (params) => {
14
+ // Step 1: Create stream if not exists
15
+ const s = await createChatCompletionStream({
16
+ pk: fency.fency.publishableKey,
17
+ baseUrl: fency.fency.baseUrl,
18
+ });
19
+ setStream(s);
20
+ // Step 2: Send chat completion
21
+ const chatCompletion = await createChatCompletion({
22
+ pk: fency.fency.publishableKey,
23
+ baseUrl: fency.fency.baseUrl,
24
+ request: {
25
+ streamId: s.id,
26
+ openai: params.openai
27
+ ? {
28
+ model: params.openai.model,
29
+ messages: params.openai.messages,
30
+ }
31
+ : undefined,
32
+ gemini: params.gemini
33
+ ? {
34
+ model: params.gemini.model,
35
+ content: params.gemini.content,
36
+ }
37
+ : undefined,
38
+ anthropic: params.anthropic
39
+ ? {
40
+ model: params.anthropic.model,
41
+ messages: params.anthropic.messages,
42
+ }
43
+ : undefined,
44
+ },
45
+ });
46
+ setChatCompletions((prev) => [...prev, chatCompletion]);
47
+ return {
48
+ chatCompletionStreamId: s.id,
49
+ chatCompletionId: chatCompletion.id,
50
+ };
51
+ }, [fency]);
52
+ const createSynchronousChatCompletion = useCallback(async (params) => {
53
+ const chatCompletion = await createChatCompletion({
54
+ pk: fency.fency.publishableKey,
55
+ baseUrl: fency.fency.baseUrl,
56
+ request: {
57
+ openai: params.openai
58
+ ? {
59
+ model: params.openai.model,
60
+ messages: params.openai.messages,
61
+ }
62
+ : undefined,
63
+ gemini: params.gemini
64
+ ? {
65
+ model: params.gemini.model,
66
+ content: params.gemini.content,
67
+ }
68
+ : undefined,
69
+ anthropic: params.anthropic
70
+ ? {
71
+ model: params.anthropic.model,
72
+ messages: params.anthropic.messages,
73
+ }
74
+ : undefined,
75
+ },
76
+ });
77
+ setChatCompletions((prev) => [...prev, chatCompletion]);
78
+ return chatCompletion;
79
+ }, [fency]);
80
+ const createStructuredChatCompletion = useCallback(async (params) => {
81
+ const jsonSchema = z.toJSONSchema(params.responseFormat);
82
+ const parsedJsonSchema = JSON.stringify(jsonSchema);
83
+ const chatCompletion = await createChatCompletion({
84
+ pk: fency.fency.publishableKey,
85
+ baseUrl: fency.fency.baseUrl,
86
+ request: {
87
+ openai: params.openai
88
+ ? {
89
+ model: params.openai.model,
90
+ responseJsonSchema: parsedJsonSchema,
91
+ messages: params.openai.messages,
92
+ }
93
+ : undefined,
94
+ gemini: params.gemini
95
+ ? {
96
+ model: params.gemini.model,
97
+ responseJsonSchema: parsedJsonSchema,
98
+ content: params.gemini.content,
99
+ }
100
+ : undefined,
101
+ anthropic: params.anthropic
102
+ ? {
103
+ model: params.anthropic.model,
104
+ messages: params.anthropic.messages,
105
+ }
106
+ : undefined,
107
+ },
108
+ });
109
+ setChatCompletions((prev) => [...prev, chatCompletion]);
110
+ if (chatCompletion.response) {
111
+ return {
112
+ ...chatCompletion,
113
+ structuredResponse: params.responseFormat.parse(JSON.parse(chatCompletion.response)),
114
+ };
115
+ }
116
+ throw new Error('No response from chat completion');
117
+ }, [fency]);
118
+ const completions = useMemo(() => {
119
+ const completions = [];
120
+ for (const chatCompletion of chatCompletions) {
121
+ const relevantChunks = chunks
122
+ .filter((chunk) => chunk.chatCompletionId === chatCompletion.id)
123
+ .sort((a, b) => a.timestamp.localeCompare(b.timestamp));
124
+ const fullMessage = relevantChunks
125
+ .map((chunk) => chunk.content)
126
+ .join('');
127
+ completions.push({
128
+ chatCompletion,
129
+ chunks: relevantChunks,
130
+ fullMessage,
131
+ });
132
+ }
133
+ return completions;
134
+ }, [chunks, chatCompletions]);
135
+ const latestCompletion = useMemo(() => {
136
+ return completions[completions.length - 1];
137
+ }, [completions]);
138
+ useEffect(() => {
139
+ if (stream) {
140
+ setUrl(`${fency.fency.baseUrl}/v1/pub/chat-completion-streams/${stream.id}?pk=${fency.fency.publishableKey}`);
141
+ }
142
+ }, [stream, fency.fency.publishableKey, setUrl]);
143
+ return {
144
+ createChatCompletion: createSynchronousChatCompletion,
145
+ createStructuredChatCompletion: createStructuredChatCompletion,
146
+ createStreamingChatCompletion: createStreamingChatCompletion,
147
+ chatCompletions: completions,
148
+ latestCompletion,
149
+ };
150
+ }
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { FencyProvider } from './FencyProvider';
2
- export { useChatCompletion } from './hooks/useChatCompletion';
2
+ export { useChatCompletions } from './hooks/useChatCompletions';
3
3
  export { useFency } from './hooks/useFency';
4
4
  export type { FencyContext, FencyProviderProps } from './FencyProvider';
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // Re-export components and hooks
2
2
  export { FencyProvider } from './FencyProvider';
3
- export { useChatCompletion } from './hooks/useChatCompletion';
3
+ export { useChatCompletions } from './hooks/useChatCompletions';
4
4
  export { useFency } from './hooks/useFency';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fencyai/react",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
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.31",
39
+ "@fencyai/js": "^0.1.33",
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.31",
48
+ "@fencyai/js": "^0.1.33",
49
49
  "react": ">=16.8.0"
50
50
  },
51
- "gitHead": "f39a452d0e2f90f06abc307f8aa04edbb7121680"
51
+ "gitHead": "1da7c448a4e82fb0a4f902e9f8a612e88a5fdcf1"
52
52
  }
@@ -1,32 +0,0 @@
1
- import { AnthropicModel, ChatCompletion, CreateSynchronousChatCompletionParams, GeminiModel, OpenAiModel } from '@fencyai/js';
2
- import z, { ZodTypeAny } from 'zod';
3
- import { ChatCompletionChunk } from './useEventSource';
4
- interface Completions {
5
- chatCompletion: ChatCompletion & {
6
- structuredResponse?: any;
7
- };
8
- chunks: ChatCompletionChunk[];
9
- fullMessage: string;
10
- }
11
- interface HookResponse {
12
- chatCompletions: Completions[];
13
- createStreamingChatCompletion: (params: {
14
- openai?: CreateSynchronousChatCompletionParams<OpenAiModel>;
15
- gemini?: CreateSynchronousChatCompletionParams<GeminiModel>;
16
- anthropic?: CreateSynchronousChatCompletionParams<AnthropicModel>;
17
- }) => Promise<{
18
- chatCompletionStreamId: string;
19
- chatCompletionId: string;
20
- }>;
21
- createSynchronousChatCompletion: <T extends ZodTypeAny>(params: {
22
- openai?: CreateSynchronousChatCompletionParams<OpenAiModel>;
23
- gemini?: CreateSynchronousChatCompletionParams<GeminiModel>;
24
- anthropic?: CreateSynchronousChatCompletionParams<AnthropicModel>;
25
- responseFormat?: T;
26
- }) => Promise<ChatCompletion & {
27
- structuredResponse?: z.infer<T>;
28
- }>;
29
- latestCompletion: Completions | null;
30
- }
31
- export declare function useChatCompletion(): HookResponse;
32
- export {};
@@ -1,116 +0,0 @@
1
- // hooks/useChatCompletion.ts
2
- import { createChatCompletion, createChatCompletionStream, } from '@fencyai/js';
3
- import { useCallback, useEffect, useMemo, useState } from 'react';
4
- import z from 'zod';
5
- import { useEventSource } from './useEventSource';
6
- import { useFency } from './useFency';
7
- export function useChatCompletion() {
8
- const fency = useFency();
9
- const { chunks, setUrl } = useEventSource();
10
- const [chatCompletions, setChatCompletions] = useState([]);
11
- const [stream, setStream] = useState(null);
12
- const createStreamingChatCompletion = useCallback(async (params) => {
13
- // Step 1: Create stream if not exists
14
- const s = await createChatCompletionStream({
15
- pk: fency.fency.publishableKey,
16
- baseUrl: fency.fency.baseUrl,
17
- });
18
- setStream(s);
19
- // Step 2: Send chat completion
20
- const chatCompletion = await createChatCompletion({
21
- pk: fency.fency.publishableKey,
22
- baseUrl: fency.fency.baseUrl,
23
- request: {
24
- chatCompletionStreamId: s.chatCompletionStreamId,
25
- openai: params.openai ? {
26
- model: params.openai.model,
27
- messages: params.openai.messages,
28
- } : undefined,
29
- gemini: params.gemini ? {
30
- model: params.gemini.model,
31
- messages: params.gemini.messages,
32
- } : undefined,
33
- anthropic: params.anthropic ? {
34
- model: params.anthropic.model,
35
- messages: params.anthropic.messages,
36
- } : undefined,
37
- },
38
- });
39
- setChatCompletions((prev) => [...prev, chatCompletion]);
40
- return {
41
- chatCompletionStreamId: s.chatCompletionStreamId,
42
- chatCompletionId: chatCompletion.chatCompletionId,
43
- };
44
- }, [fency]);
45
- const createSynchronousChatCompletion = useCallback(async (params) => {
46
- const jsonSchema = params.responseFormat
47
- ? z.toJSONSchema(params.responseFormat)
48
- : undefined;
49
- const parsedJsonSchema = jsonSchema
50
- ? JSON.stringify(jsonSchema)
51
- : undefined;
52
- const chatCompletion = await createChatCompletion({
53
- pk: fency.fency.publishableKey,
54
- baseUrl: fency.fency.baseUrl,
55
- request: {
56
- openai: params.openai ? {
57
- model: params.openai.model,
58
- responseJsonSchema: parsedJsonSchema,
59
- messages: params.openai.messages,
60
- } : undefined,
61
- gemini: params.gemini ? {
62
- model: params.gemini.model,
63
- responseJsonSchema: parsedJsonSchema,
64
- messages: params.gemini.messages,
65
- } : undefined,
66
- anthropic: params.anthropic ? {
67
- model: params.anthropic.model,
68
- responseJsonSchema: parsedJsonSchema,
69
- messages: params.anthropic.messages,
70
- } : undefined,
71
- },
72
- });
73
- setChatCompletions((prev) => [...prev, chatCompletion]);
74
- if (chatCompletion.responseIsStructured &&
75
- params.responseFormat &&
76
- chatCompletion.response) {
77
- return {
78
- ...chatCompletion,
79
- structuredResponse: params.responseFormat.parse(JSON.parse(chatCompletion.response)),
80
- };
81
- }
82
- return chatCompletion;
83
- }, [fency]);
84
- const completions = useMemo(() => {
85
- const completions = [];
86
- for (const chatCompletion of chatCompletions) {
87
- const relevantChunks = chunks
88
- .filter((chunk) => chunk.chatCompletionId ===
89
- chatCompletion.chatCompletionId)
90
- .sort((a, b) => a.timestamp.localeCompare(b.timestamp));
91
- const fullMessage = relevantChunks
92
- .map((chunk) => chunk.content)
93
- .join('');
94
- completions.push({
95
- chatCompletion,
96
- chunks: relevantChunks,
97
- fullMessage,
98
- });
99
- }
100
- return completions;
101
- }, [chunks, chatCompletions]);
102
- const latestCompletion = useMemo(() => {
103
- return completions[completions.length - 1];
104
- }, [completions]);
105
- useEffect(() => {
106
- if (stream) {
107
- setUrl(`${fency.fency.baseUrl}/v1/pub/chat-completion-streams/${stream.chatCompletionStreamId}?pk=${fency.fency.publishableKey}`);
108
- }
109
- }, [stream, fency.fency.publishableKey, setUrl]);
110
- return {
111
- createStreamingChatCompletion: createStreamingChatCompletion,
112
- createSynchronousChatCompletion: createSynchronousChatCompletion,
113
- chatCompletions: completions,
114
- latestCompletion,
115
- };
116
- }