altair-graphql-plugin-ai 7.3.0 → 7.3.2

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/src/dev.tsx DELETED
@@ -1,37 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom/client';
3
- import Chat, { ChatProps } from './components/Chat/Chat';
4
-
5
- const chatProps: ChatProps = {
6
- loggedIn: true,
7
- loading: false,
8
- sendMessageIsPending: true,
9
- availableCredits: 0,
10
- activeSession: {
11
- id: '1',
12
- isActive: true,
13
- title: 'title',
14
- userId: 'user-1',
15
- },
16
- messages: [
17
- {
18
- id: '1',
19
- message:
20
- 'Can you generate a GraphQL query to fetch all users with their names and email addresses?',
21
- role: 'USER',
22
- sessionId: '1',
23
- },
24
- {
25
- id: '2',
26
- message:
27
- 'Certainly! Here is a GraphQL query to fetch all users along with their names and email addresses:\n\n```graphql\nquery {\n users {\n id\n name\n email\n }\n}\n```\n\nMake sure your GraphQL server schema includes a `users` query that returns a list of user objects, each containing `id`, `name`, and `email` fields.',
28
- role: 'ASSISTANT',
29
- sessionId: '1',
30
- },
31
- ],
32
- };
33
- ReactDOM.createRoot(document.getElementById('root')!).render(
34
- <React.StrictMode>
35
- <Chat {...chatProps} />
36
- </React.StrictMode>
37
- );
package/src/panel.tsx DELETED
@@ -1,194 +0,0 @@
1
- import { createRoot } from 'react-dom/client';
2
- import { PluginV3Context } from 'altair-graphql-core/build/plugin/v3/context';
3
- import { AltairV3Panel } from 'altair-graphql-core/build/plugin/v3/panel';
4
- import Chat, { ChatProps } from './components/Chat/Chat';
5
- import {
6
- QueryClient,
7
- QueryClientProvider,
8
- useMutation,
9
- useQuery,
10
- } from '@tanstack/react-query';
11
- import toast, { Toaster } from 'react-hot-toast';
12
- import { IMessage, ISendMessageDto } from 'altair-graphql-core/build/ai/types';
13
-
14
- const queryClient = new QueryClient({
15
- defaultOptions: {
16
- queries: {
17
- refetchOnWindowFocus: false,
18
- refetchOnReconnect: false,
19
- retry: false,
20
- },
21
- },
22
- });
23
-
24
- interface PanelProps {
25
- context: PluginV3Context;
26
- }
27
- const Panel = ({ context }: PanelProps) => {
28
- const { data: userInfo, isLoading: userInfoIsLoading } = useQuery({
29
- queryKey: ['userInfo'],
30
- queryFn: () => context.getUserInfo(),
31
- });
32
-
33
- const { data: activeSession, isLoading: activeSessionIsLoading } = useQuery({
34
- queryKey: ['activeSession'],
35
- queryFn: () => context.getActiveAiSession(),
36
- enabled: !!userInfo?.loggedIn,
37
- });
38
-
39
- const { data: availableCredits } = useQuery({
40
- queryKey: ['availableCredits'],
41
- queryFn: () => context.getAvailableCredits(),
42
- enabled: !!userInfo?.loggedIn,
43
- });
44
-
45
- const { data: messages, isLoading: messagesIsLoading } = useQuery({
46
- queryKey: ['sessionMessages', activeSession?.id],
47
- queryFn: () =>
48
- activeSession
49
- ? context.getAiSessionMessages(activeSession.id)
50
- : Promise.resolve([]),
51
- enabled: !!activeSession?.id,
52
- });
53
-
54
- const { mutate: createAiSession, isPending: createSessionIsPending } = useMutation(
55
- {
56
- mutationKey: ['createAiSession'],
57
- mutationFn: () => context.createAiSession(),
58
- onSettled: async () => {
59
- await queryClient.invalidateQueries({ queryKey: ['activeSession'] });
60
- await queryClient.invalidateQueries({ queryKey: ['sessionMessages'] });
61
- },
62
- }
63
- );
64
-
65
- const {
66
- mutate: sendMessage,
67
- isPending: sendMessageIsPending,
68
- error,
69
- } = useMutation({
70
- mutationKey: ['sendMessage'],
71
- mutationFn: async (message: string) => {
72
- if (!activeSession) {
73
- throw new Error('No active session');
74
- }
75
-
76
- const windowState = await context.getCurrentWindowState();
77
- let graphqlQuery = '';
78
- let graphqlVariables = '';
79
- let sdl = '';
80
- if (windowState) {
81
- graphqlQuery = windowState.query;
82
- graphqlVariables = windowState.variables;
83
- sdl = windowState.sdl;
84
- }
85
-
86
- // build message input
87
- const input: ISendMessageDto = {
88
- message,
89
- graphqlQuery,
90
- graphqlVariables,
91
- sdl,
92
- };
93
- return context.sendMessageToAiSession(activeSession.id, input);
94
- },
95
- onMutate: async (message) => {
96
- // Cancel any outgoing refetches
97
- // (so they don't overwrite our optimistic update)
98
- await queryClient.cancelQueries({ queryKey: ['sessionMessages'] });
99
-
100
- // Snapshot the previous value
101
- const previousMessages = queryClient.getQueryData<IMessage[]>([
102
- 'sessionMessages',
103
- ]);
104
-
105
- const sessionId = activeSession?.id ?? '';
106
- const fakeMessage: IMessage = {
107
- id: Math.random().toString(),
108
- message: message,
109
- role: 'USER',
110
- sessionId,
111
- };
112
- // Optimistically update to the new value
113
- queryClient.setQueryData<IMessage[]>(['sessionMessages', sessionId], (old) => [
114
- ...(old ?? []),
115
- fakeMessage,
116
- ]);
117
-
118
- // Return a context object with the snapshotted value
119
- return { previousMessages };
120
- },
121
- // If the mutation fails,
122
- // use the context returned from onMutate to roll back
123
- onError: (_err, _message, context) => {
124
- if (context?.previousMessages) {
125
- queryClient.setQueryData(['todos'], context.previousMessages);
126
- }
127
- },
128
- // Always refetch after error or success:
129
- onSettled: async () => {
130
- // wait for the refetching to complete before marking as not pending
131
- await Promise.all([
132
- queryClient.invalidateQueries({ queryKey: ['sessionMessages'] }),
133
- queryClient.invalidateQueries({ queryKey: ['availableCredits'] }),
134
- ]);
135
- },
136
- });
137
-
138
- if (error) {
139
- console.error(error);
140
- }
141
-
142
- const chatProps: ChatProps = {
143
- loggedIn: !!userInfo?.loggedIn,
144
- loading:
145
- userInfoIsLoading ||
146
- activeSessionIsLoading ||
147
- messagesIsLoading ||
148
- createSessionIsPending,
149
- userInfo,
150
- activeSession,
151
- messages,
152
- sendMessageIsPending,
153
- availableCredits: availableCredits?.total ?? 0,
154
- isPro: userInfo?.plan?.id === 'pro',
155
- onStartNewSession() {
156
- createAiSession();
157
- },
158
- onSendMessage(message) {
159
- sendMessage(message);
160
- },
161
- async onUseQuery(query) {
162
- const windowState = await context.getCurrentWindowState();
163
- if (!windowState) {
164
- return;
165
- }
166
- await context.setQuery(windowState.windowId, query);
167
- },
168
- async onRateMessage(messageId, rating) {
169
- if (!activeSession) {
170
- return;
171
- }
172
- await context.rateAiSessionMessage(activeSession.id, messageId, rating);
173
- toast('Thank you for your feedback!');
174
- },
175
- };
176
-
177
- return (
178
- <>
179
- <Chat {...chatProps} />
180
- <Toaster />
181
- </>
182
- );
183
- };
184
-
185
- export class AiPluginPanel extends AltairV3Panel {
186
- create(ctx: PluginV3Context, container: HTMLElement): void {
187
- const root = createRoot(container);
188
- root.render(
189
- <QueryClientProvider client={queryClient}>
190
- <Panel context={ctx} />
191
- </QueryClientProvider>
192
- );
193
- }
194
- }
package/src/plugin.tsx DELETED
@@ -1,31 +0,0 @@
1
- import { PluginV3 } from 'altair-graphql-core/build/plugin/v3/plugin';
2
- import { PluginV3Context } from 'altair-graphql-core/build/plugin/v3/context';
3
- import { AiPluginPanel } from './panel';
4
- import { AltairPanelLocation } from 'altair-graphql-core/build/plugin/panel';
5
-
6
- class AiPlugin extends PluginV3 {
7
- constructor() {
8
- super({
9
- panels: {
10
- ai: new AiPluginPanel(),
11
- },
12
- });
13
- }
14
-
15
- async initialize(ctx: PluginV3Context) {
16
- console.log('PLUGIN initialize', ctx);
17
- console.log('PLUGIN isElectron', await ctx.getCurrentWindowState());
18
- ctx.on('query.change', (x) => {
19
- console.log('PLUGIN query.change', x);
20
- });
21
-
22
- await ctx.createPanel('ai', {
23
- location: AltairPanelLocation.SIDEBAR,
24
- width: 400,
25
- });
26
- }
27
-
28
- async destroy() {}
29
- }
30
- console.log('AI plugin loaded!');
31
- new AiPlugin();
package/src/utils.ts DELETED
@@ -1,8 +0,0 @@
1
- export const randomSampling = ([...arr], n = 1) => {
2
- let m = arr.length;
3
- while (m) {
4
- const i = Math.floor(Math.random() * m--);
5
- [arr[m], arr[i]] = [arr[i], arr[m]];
6
- }
7
- return arr.slice(0, n);
8
- };
package/src/vite-env.d.ts DELETED
@@ -1 +0,0 @@
1
- /// <reference types="vite/client" />
package/tsconfig.app.json DELETED
@@ -1,27 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "composite": true,
4
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5
- "target": "ES2020",
6
- "useDefineForClassFields": true,
7
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
8
- "module": "ESNext",
9
- "skipLibCheck": true,
10
-
11
- /* Bundler mode */
12
- "moduleResolution": "bundler",
13
- "allowImportingTsExtensions": true,
14
- "resolveJsonModule": true,
15
- "isolatedModules": true,
16
- "moduleDetection": "force",
17
- "noEmit": true,
18
- "jsx": "react-jsx",
19
-
20
- /* Linting */
21
- "strict": true,
22
- "noUnusedLocals": true,
23
- "noUnusedParameters": true,
24
- "noFallthroughCasesInSwitch": true
25
- },
26
- "include": ["src"]
27
- }
package/tsconfig.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "files": [],
3
- "references": [
4
- {
5
- "path": "./tsconfig.app.json"
6
- },
7
- {
8
- "path": "./tsconfig.node.json"
9
- }
10
- ]
11
- }
@@ -1,13 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "composite": true,
4
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5
- "skipLibCheck": true,
6
- "module": "ESNext",
7
- "moduleResolution": "bundler",
8
- "allowSyntheticDefaultImports": true,
9
- "strict": true,
10
- "noEmit": true
11
- },
12
- "include": ["vite.config.ts"]
13
- }
package/vite.config.ts DELETED
@@ -1,22 +0,0 @@
1
- import { defineConfig } from 'vite';
2
- import react from '@vitejs/plugin-react-swc';
3
- import { fileURLToPath } from 'url';
4
-
5
- // https://vitejs.dev/config/
6
- export default defineConfig({
7
- plugins: [react()],
8
- build: {
9
- rollupOptions: {
10
- input: {
11
- plugin: fileURLToPath(new URL('./src/plugin.tsx', import.meta.url)),
12
- },
13
- output: {
14
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
- manualChunks: false as any,
16
- inlineDynamicImports: true,
17
- entryFileNames: '[name].js', // currently does not work for the legacy bundle
18
- assetFileNames: '[name].[ext]', // currently does not work for images
19
- },
20
- },
21
- },
22
- });
File without changes