diff --git a/.wundergraph/operations/getChatwootContacts.ts b/.wundergraph/operations/getChatwootContacts.ts new file mode 100644 index 0000000..dcadfa5 --- /dev/null +++ b/.wundergraph/operations/getChatwootContacts.ts @@ -0,0 +1,20 @@ +// .wundergraph/operations/getChatwootContacts.ts +import { createOperation, z } from '../generated/wundergraph.factory'; +import axios from 'axios'; + +export default createOperation.query({ + input: z.object({ + page: z.number().optional(), + }), + handler: async ({ page = 1 }) => { + console.log('Making request to Chatwoot API'); + + const { data } = await axios.get(`https://chatwoot.andert.me/api/v1/accounts/1/contacts?page=${page}`, { + headers: { + api_access_token: process.env.CHATWOOT_API_ACCESS_TOKEN + }, + }); + + return data; + }, +}); \ No newline at end of file diff --git a/.wundergraph/operations/getChatwootConversations.ts b/.wundergraph/operations/getChatwootConversations.ts new file mode 100644 index 0000000..2217967 --- /dev/null +++ b/.wundergraph/operations/getChatwootConversations.ts @@ -0,0 +1,19 @@ +// .wundergraph/operations/getChatwootConversations.ts +import { createOperation, z } from '../generated/wundergraph.factory'; +import axios from 'axios'; + +export default createOperation.query({ + input: z.object({}), + handler: async () => { + console.log('Making request to Chatwoot API'); + + const { data } = await axios.get('https://chatwoot.andert.me/api/v1/accounts/1/conversations?status=open&sort_by=last_activity_at', { + headers: { + api_access_token: process.env.CHATWOOT_API_ACCESS_TOKEN + }, + }); + + + return data; + }, +}); \ No newline at end of file diff --git a/.wundergraph/operations/getPaperless.ts b/.wundergraph/operations/getPaperless.ts index f478b8b..87ce5a7 100644 --- a/.wundergraph/operations/getPaperless.ts +++ b/.wundergraph/operations/getPaperless.ts @@ -6,34 +6,58 @@ export default createOperation.query({ input: z.object({}), handler: async () => { console.log('Making request to Paperless API'); - const { data } = await axios.get('https://paperless.andert.me/api/documents/', { headers: { Authorization: process.env.PAPERLESS_TOKEN, }, + }); - console.log('Received response:', data.results); - // Add download link, thumbnail link, preview link, and PDF data to each document - const documentsWithLinksAndData = await Promise.all(data.results.map(async doc => { + // Add download link, thumbnail link, preview link, PDF data, and metadata to each document + const documentsWithLinksDataAndMetadata = await Promise.all(data.results.map(async doc => { const response = await axios.get(`https://paperless.andert.me/api/documents/${doc.id}/preview/`, { responseType: 'arraybuffer', headers: { Authorization: process.env.PAPERLESS_TOKEN, }, }); + const pdfData = Buffer.from(response.data, 'binary').toString('base64'); + const correspondentResponse = await axios.get(`https://paperless.andert.me/api/correspondents/${doc.correspondent}/`, { + headers: { + Authorization: process.env.PAPERLESS_TOKEN, + }, + }); + const correspondent = correspondentResponse.data; + + const tagsResponse = await Promise.all(doc.tags.map(tag => axios.get(`https://paperless.andert.me/api/tags/${tag}/`, { + headers: { + Authorization: process.env.PAPERLESS_TOKEN, + }, + }))); + const tags = tagsResponse.map(response => response.data); + + const documentTypeResponse = await axios.get(`https://paperless.andert.me/api/document_types/${doc.document_type}/`, { + headers: { + Authorization: process.env.PAPERLESS_TOKEN, + }, + }); + const documentType = documentTypeResponse.data; + return { ...doc, downloadLink: `https://paperless.andert.me/api/documents/${doc.id}/download/`, thumbnailLink: `https://paperless.andert.me/api/documents/${doc.id}/thumb/`, previewLink: `https://paperless.andert.me/api/documents/${doc.id}/preview/`, pdfData, + correspondent, + tags, + document_type: documentType, }; })); - return documentsWithLinksAndData; + return documentsWithLinksDataAndMetadata; }, }); \ No newline at end of file diff --git a/.wundergraph/schemas/directus.graphql b/.wundergraph/schemas/directus.graphql index 53ea6da..04743a1 100644 --- a/.wundergraph/schemas/directus.graphql +++ b/.wundergraph/schemas/directus.graphql @@ -2,41 +2,40 @@ type Query { projects(filter: projects_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): [projects!]! projects_by_id(id: ID!): projects projects_aggregated(groupBy: [String], filter: projects_filter, limit: Int, offset: Int, page: Int, search: String, sort: [String]): [projects_aggregated!]! - todos(filter: todos_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): [todos!]! - todos_by_id(id: ID!): todos - todos_aggregated(groupBy: [String], filter: todos_filter, limit: Int, offset: Int, page: Int, search: String, sort: [String]): [todos_aggregated!]! bookmarks(filter: bookmarks_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): [bookmarks!]! bookmarks_by_id(id: ID!): bookmarks bookmarks_aggregated(groupBy: [String], filter: bookmarks_filter, limit: Int, offset: Int, page: Int, search: String, sort: [String]): [bookmarks_aggregated!]! + todos(filter: todos_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): [todos!]! + todos_by_id(id: ID!): todos + todos_aggregated(groupBy: [String], filter: todos_filter, limit: Int, offset: Int, page: Int, search: String, sort: [String]): [todos_aggregated!]! } type Mutation { create_projects_items(filter: projects_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, data: [create_projects_input!]): [projects!]! create_projects_item(data: create_projects_input!): projects - create_todos_items(filter: todos_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, data: [create_todos_input!]): [todos!]! - create_todos_item(data: create_todos_input!): todos create_bookmarks_items(filter: bookmarks_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, data: [create_bookmarks_input!]): [bookmarks!]! create_bookmarks_item(data: create_bookmarks_input!): bookmarks + create_todos_items(filter: todos_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, data: [create_todos_input!]): [todos!]! + create_todos_item(data: create_todos_input!): todos update_projects_items(filter: projects_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, ids: [ID]!, data: update_projects_input!): [projects!]! update_projects_batch(filter: projects_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, data: [update_projects_input!]): [projects!]! update_projects_item(id: ID!, data: update_projects_input!): projects - update_todos_items(filter: todos_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, ids: [ID]!, data: update_todos_input!): [todos!]! - update_todos_batch(filter: todos_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, data: [update_todos_input!]): [todos!]! - update_todos_item(id: ID!, data: update_todos_input!): todos update_bookmarks_items(filter: bookmarks_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, ids: [ID]!, data: update_bookmarks_input!): [bookmarks!]! update_bookmarks_batch(filter: bookmarks_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, data: [update_bookmarks_input!]): [bookmarks!]! update_bookmarks_item(id: ID!, data: update_bookmarks_input!): bookmarks + update_todos_items(filter: todos_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, ids: [ID]!, data: update_todos_input!): [todos!]! + update_todos_batch(filter: todos_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String, data: [update_todos_input!]): [todos!]! + update_todos_item(id: ID!, data: update_todos_input!): todos delete_projects_items(ids: [ID]!): delete_many delete_projects_item(id: ID!): delete_one - delete_todos_items(ids: [ID]!): delete_many - delete_todos_item(id: ID!): delete_one delete_bookmarks_items(ids: [ID]!): delete_many delete_bookmarks_item(id: ID!): delete_one + delete_todos_items(ids: [ID]!): delete_many + delete_todos_item(id: ID!): delete_one } type Subscription { projects_mutated(event: EventEnum): projects_mutated - todos_mutated(event: EventEnum): todos_mutated directus_dashboards_mutated(event: EventEnum): directus_dashboards_mutated directus_activity_mutated(event: EventEnum): directus_activity_mutated directus_notifications_mutated(event: EventEnum): directus_notifications_mutated @@ -55,6 +54,7 @@ type Subscription { directus_shares_mutated(event: EventEnum): directus_shares_mutated directus_webhooks_mutated(event: EventEnum): directus_webhooks_mutated bookmarks_mutated(event: EventEnum): bookmarks_mutated + todos_mutated(event: EventEnum): todos_mutated } """The `Boolean` scalar type represents `true` or `false`.""" @@ -620,15 +620,16 @@ type projects_mutated { type todos { id: ID! - status: String - sort: Int user_created(filter: directus_users_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): directus_users date_created: Date date_created_func: datetime_functions user_updated(filter: directus_users_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): directus_users date_updated: Date date_updated_func: datetime_functions + enddate: Date + enddate_func: datetime_functions task: String + type: String } type todos_aggregated { @@ -636,27 +637,17 @@ type todos_aggregated { countAll: Int count: todos_aggregated_count countDistinct: todos_aggregated_count - avg: todos_aggregated_fields - sum: todos_aggregated_fields - avgDistinct: todos_aggregated_fields - sumDistinct: todos_aggregated_fields - min: todos_aggregated_fields - max: todos_aggregated_fields } type todos_aggregated_count { id: Int - status: Int - sort: Int user_created: Int date_created: Int user_updated: Int date_updated: Int + enddate: Int task: Int -} - -type todos_aggregated_fields { - sort: Float + type: Int } type todos_mutated { @@ -786,13 +777,13 @@ input create_projects_input { input create_todos_input { id: ID - status: String - sort: Int user_created: create_directus_users_input date_created: Date user_updated: create_directus_users_input date_updated: Date + enddate: Date task: String + type: String } input date_filter_operators { @@ -1073,15 +1064,16 @@ input string_filter_operators { input todos_filter { id: string_filter_operators - status: string_filter_operators - sort: number_filter_operators user_created: directus_users_filter date_created: date_filter_operators date_created_func: datetime_function_filter_operators user_updated: directus_users_filter date_updated: date_filter_operators date_updated_func: datetime_function_filter_operators + enddate: date_filter_operators + enddate_func: datetime_function_filter_operators task: string_filter_operators + type: string_filter_operators _and: [todos_filter] _or: [todos_filter] } @@ -1178,11 +1170,11 @@ input update_projects_input { input update_todos_input { id: ID - status: String - sort: Int user_created: update_directus_users_input date_created: Date user_updated: update_directus_users_input date_updated: Date + enddate: Date task: String + type: String } \ No newline at end of file diff --git a/.wundergraph/schemas/directus_system.graphql b/.wundergraph/schemas/directus_system.graphql index 7a3440d..199bab2 100644 --- a/.wundergraph/schemas/directus_system.graphql +++ b/.wundergraph/schemas/directus_system.graphql @@ -199,7 +199,6 @@ type Mutation { type Subscription { projects_mutated(event: EventEnum): projects_mutated - todos_mutated(event: EventEnum): todos_mutated directus_dashboards_mutated(event: EventEnum): directus_dashboards_mutated directus_activity_mutated(event: EventEnum): directus_activity_mutated directus_notifications_mutated(event: EventEnum): directus_notifications_mutated @@ -218,6 +217,7 @@ type Subscription { directus_shares_mutated(event: EventEnum): directus_shares_mutated directus_webhooks_mutated(event: EventEnum): directus_webhooks_mutated bookmarks_mutated(event: EventEnum): bookmarks_mutated + todos_mutated(event: EventEnum): todos_mutated } """The `Boolean` scalar type represents `true` or `false`.""" @@ -1392,15 +1392,16 @@ type server_info_websocket_rest { type todos { id: ID! - status: String - sort: Int user_created(filter: directus_users_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): directus_users date_created: Date date_created_func: datetime_functions user_updated(filter: directus_users_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): directus_users date_updated: Date date_updated_func: datetime_functions + enddate: Date + enddate_func: datetime_functions task: String + type: String } type todos_mutated { diff --git a/package.json b/package.json index 708d86f..9bd48f0 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "@wundergraph/sdk": "^0.174.5", "@wundergraph/svelte-query": "^0.3.10", "@xstate/svelte": "^2.1.0", + "ai": "^2.2.13", "axios": "^1.4.0", "cookie": "^0.5.0", "dotenv": "^16.3.1", @@ -67,6 +68,7 @@ "jsonwebtoken": "^9.0.1", "jwks-rsa": "^3.0.1", "node-jose": "^2.2.0", + "openai": "^4.8.0", "path": "^0.12.7", "sqlite3": "^5.1.6", "svelte-kit-cookie-session": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0a216d..708d278 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,6 +52,9 @@ dependencies: '@xstate/svelte': specifier: ^2.1.0 version: 2.1.0(svelte@3.54.0)(xstate@4.38.2) + ai: + specifier: ^2.2.13 + version: 2.2.13(react@18.2.0)(solid-js@1.7.12)(svelte@3.54.0)(vue@3.3.4) axios: specifier: ^1.4.0 version: 1.4.0 @@ -79,6 +82,9 @@ dependencies: node-jose: specifier: ^2.2.0 version: 2.2.0 + openai: + specifier: ^4.8.0 + version: 4.8.0 path: specifier: ^0.12.7 version: 0.12.7 @@ -5410,6 +5416,13 @@ packages: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} dev: false + /@types/node-fetch@2.6.5: + resolution: {integrity: sha512-OZsUlr2nxvkqUFLSaY2ZbA+P1q22q+KrlxWOn/38RX+u5kTkYL2mTujEpzUhGkS+K/QCYp9oagfXG39XOzyySg==} + dependencies: + '@types/node': 20.5.8 + form-data: 4.0.0 + dev: false + /@types/node@12.20.55: resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} dev: false @@ -5502,6 +5515,89 @@ packages: '@types/yargs-parser': 21.0.0 dev: false + /@vue/compiler-core@3.3.4: + resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} + dependencies: + '@babel/parser': 7.22.16 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: false + + /@vue/compiler-dom@3.3.4: + resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} + dependencies: + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + dev: false + + /@vue/compiler-sfc@3.3.4: + resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} + dependencies: + '@babel/parser': 7.22.16 + '@vue/compiler-core': 3.3.4 + '@vue/compiler-dom': 3.3.4 + '@vue/compiler-ssr': 3.3.4 + '@vue/reactivity-transform': 3.3.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + magic-string: 0.30.3 + postcss: 8.4.29 + source-map-js: 1.0.2 + dev: false + + /@vue/compiler-ssr@3.3.4: + resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} + dependencies: + '@vue/compiler-dom': 3.3.4 + '@vue/shared': 3.3.4 + dev: false + + /@vue/reactivity-transform@3.3.4: + resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} + dependencies: + '@babel/parser': 7.22.16 + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + magic-string: 0.30.3 + dev: false + + /@vue/reactivity@3.3.4: + resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} + dependencies: + '@vue/shared': 3.3.4 + dev: false + + /@vue/runtime-core@3.3.4: + resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} + dependencies: + '@vue/reactivity': 3.3.4 + '@vue/shared': 3.3.4 + dev: false + + /@vue/runtime-dom@3.3.4: + resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} + dependencies: + '@vue/runtime-core': 3.3.4 + '@vue/shared': 3.3.4 + csstype: 3.1.2 + dev: false + + /@vue/server-renderer@3.3.4(vue@3.3.4): + resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} + peerDependencies: + vue: 3.3.4 + dependencies: + '@vue/compiler-ssr': 3.3.4 + '@vue/shared': 3.3.4 + vue: 3.3.4 + dev: false + + /@vue/shared@3.3.4: + resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + dev: false + /@wagmi/chains@1.7.0(typescript@5.0.2): resolution: {integrity: sha512-TKVeHv0GqP5sV1yQ8BDGYToAFezPnCexbbBpeH14x7ywi5a1dDStPffpt9x+ytE6LJWkZ6pAMs/HNWXBQ5Nqmw==} peerDependencies: @@ -6247,6 +6343,40 @@ packages: dev: false optional: true + /ai@2.2.13(react@18.2.0)(solid-js@1.7.12)(svelte@3.54.0)(vue@3.3.4): + resolution: {integrity: sha512-tq0OpUUryPjSPn7WYhZ7viGUq1d2/L5T0FZawGun9ojYYOzu5eJIAQAnZ2HRTXsFIwuYTb9wAgZUx+sQUDjdnQ==} + engines: {node: '>=14.6'} + peerDependencies: + react: ^18.2.0 + solid-js: ^1.7.7 + svelte: ^3.0.0 || ^4.0.0 + vue: ^3.3.4 + peerDependenciesMeta: + react: + optional: true + solid-js: + optional: true + svelte: + optional: true + vue: + optional: true + dependencies: + eventsource-parser: 1.0.0 + nanoid: 3.3.6 + openai: 4.2.0 + react: 18.2.0 + solid-js: 1.7.12 + solid-swr-store: 0.10.7(solid-js@1.7.12)(swr-store@0.10.6) + sswr: 2.0.0(svelte@3.54.0) + svelte: 3.54.0 + swr: 2.2.0(react@18.2.0) + swr-store: 0.10.6 + swrv: 1.0.4(vue@3.3.4) + vue: 3.3.4 + transitivePeerDependencies: + - encoding + dev: false + /ajv-formats@2.1.1(ajv@8.12.0): resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -6916,6 +7046,10 @@ packages: tslib: 2.6.2 dev: false + /charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + dev: false + /charset@1.0.1: resolution: {integrity: sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==} engines: {node: '>=4.0.0'} @@ -7207,12 +7341,20 @@ packages: which: 2.0.2 dev: false + /crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + dev: false + /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true dev: true + /csstype@3.1.2: + resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + dev: false + /d@1.0.1: resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} dependencies: @@ -7334,6 +7476,11 @@ packages: prop-types: 15.8.1 dev: false + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: false + /destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -7372,6 +7519,13 @@ packages: engines: {node: '>=0.3.1'} dev: false + /digest-fetch@1.3.0: + resolution: {integrity: sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==} + dependencies: + base-64: 0.1.0 + md5: 2.3.0 + dev: false + /dijkstrajs@1.0.3: resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} dev: false @@ -7635,6 +7789,10 @@ packages: hasBin: true dev: false + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: false + /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -7794,6 +7952,11 @@ packages: engines: {node: '>=0.8.x'} dev: false + /eventsource-parser@1.0.0: + resolution: {integrity: sha512-9jgfSCa3dmEme2ES3mPByGXfgZ87VbP97tng1G2nWwWx6bV2nYxm2AWCrbQjXToSe+yYlqaZNtxffR9IeQr95g==} + engines: {node: '>=14.18'} + dev: false + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -8048,6 +8211,10 @@ packages: resolution: {integrity: sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==} dev: false + /form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + dev: false + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -8056,6 +8223,14 @@ packages: combined-stream: 1.0.8 mime-types: 2.1.35 + /formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + dev: false + /forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -8758,6 +8933,10 @@ packages: binary-extensions: 2.2.0 dev: true + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: false + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -9642,7 +9821,6 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} @@ -9699,6 +9877,14 @@ packages: resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} dev: false + /md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + dev: false + /memoize-one@5.2.1: resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} dev: false @@ -10379,6 +10565,11 @@ packages: minimatch: 3.1.2 dev: false + /node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: false + /node-fetch-h2@2.3.0: resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} engines: {node: 4.x || >=6.0.0} @@ -10647,6 +10838,38 @@ packages: - debug dev: false + /openai@4.2.0: + resolution: {integrity: sha512-zfvpO2eITIxIjTG8T6Cek7NB2dMvP/LW0TRUJ4P9E8+qbBNKw00DrtfF64b+fAV2+wUYCVyynT6iSycJ//TtbA==} + hasBin: true + dependencies: + '@types/node': 18.15.13 + '@types/node-fetch': 2.6.5 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + digest-fetch: 1.3.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /openai@4.8.0: + resolution: {integrity: sha512-CnLZvHi2x4pIoGAWCaj3jHi1a6NA4oFBL6mJDSXkIR5A/wv6lven7uL2gxMevjGBLA7OqYqis3Z2PMluiGauVw==} + hasBin: true + dependencies: + '@types/node': 18.15.13 + '@types/node-fetch': 2.6.5 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + digest-fetch: 1.3.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + /openapi-types@12.1.0: resolution: {integrity: sha512-XpeCy01X6L5EpP+6Hc3jWN7rMZJ+/k1lwki/kTmWzbVhdPie3jd5O2ZtedEx8Yp58icJ0osVldLMrTB/zslQXA==} dev: false @@ -11009,7 +11232,6 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true /postman-collection@4.2.0: resolution: {integrity: sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==} @@ -11784,6 +12006,11 @@ packages: engines: {node: '>=0.10.0'} dev: false + /seroval@0.5.1: + resolution: {integrity: sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==} + engines: {node: '>=10'} + dev: false + /serve-static@1.15.0: resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} engines: {node: '>= 0.8.0'} @@ -12003,6 +12230,24 @@ packages: dev: false optional: true + /solid-js@1.7.12: + resolution: {integrity: sha512-QoyoOUKu14iLoGxjxWFIU8+/1kLT4edQ7mZESFPonsEXZ//VJtPKD8Ud1aTKzotj+MNWmSs9YzK6TdY+fO9Eww==} + dependencies: + csstype: 3.1.2 + seroval: 0.5.1 + dev: false + + /solid-swr-store@0.10.7(solid-js@1.7.12)(swr-store@0.10.6): + resolution: {integrity: sha512-A6d68aJmRP471aWqKKPE2tpgOiR5fH4qXQNfKIec+Vap+MGQm3tvXlT8n0I8UgJSlNAsSAUuw2VTviH2h3Vv5g==} + engines: {node: '>=10'} + peerDependencies: + solid-js: ^1.2 + swr-store: ^0.10 + dependencies: + solid-js: 1.7.12 + swr-store: 0.10.6 + dev: false + /sonic-boom@2.8.0: resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==} dependencies: @@ -12028,7 +12273,6 @@ packages: /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: true /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -12106,6 +12350,15 @@ packages: dev: false optional: true + /sswr@2.0.0(svelte@3.54.0): + resolution: {integrity: sha512-mV0kkeBHcjcb0M5NqKtKVg/uTIYNlIIniyDfSGrSfxpEdM9C365jK0z55pl9K0xAkNTJi2OAOVFQpgMPUk+V0w==} + peerDependencies: + svelte: ^4.0.0 + dependencies: + svelte: 3.54.0 + swrev: 4.0.0 + dev: false + /stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -12399,6 +12652,34 @@ packages: - encoding dev: false + /swr-store@0.10.6: + resolution: {integrity: sha512-xPjB1hARSiRaNNlUQvWSVrG5SirCjk2TmaUyzzvk69SZQan9hCJqw/5rG9iL7xElHU784GxRPISClq4488/XVw==} + engines: {node: '>=10'} + dependencies: + dequal: 2.0.3 + dev: false + + /swr@2.2.0(react@18.2.0): + resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + + /swrev@4.0.0: + resolution: {integrity: sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA==} + dev: false + + /swrv@1.0.4(vue@3.3.4): + resolution: {integrity: sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==} + peerDependencies: + vue: '>=3.2.26 < 4' + dependencies: + vue: 3.3.4 + dev: false + /symbol-observable@2.0.3: resolution: {integrity: sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==} engines: {node: '>=0.10'} @@ -13093,6 +13374,16 @@ packages: resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} dev: false + /vue@3.3.4: + resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} + dependencies: + '@vue/compiler-dom': 3.3.4 + '@vue/compiler-sfc': 3.3.4 + '@vue/runtime-dom': 3.3.4 + '@vue/server-renderer': 3.3.4(vue@3.3.4) + '@vue/shared': 3.3.4 + dev: false + /wait-on@7.0.1: resolution: {integrity: sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==} engines: {node: '>=12.0.0'} @@ -13124,6 +13415,11 @@ packages: engines: {node: '>= 8'} dev: false + /web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + dev: false + /web-vitals@3.4.0: resolution: {integrity: sha512-n9fZ5/bG1oeDkyxLWyep0eahrNcPDF6bFqoyispt7xkW0xhDzpUBTgyDKqWDi1twT0MgH4HvvqzpUyh0ZxZV4A==} dev: false diff --git a/src/lib/Ai.svelte b/src/lib/Ai.svelte new file mode 100644 index 0000000..0647792 --- /dev/null +++ b/src/lib/Ai.svelte @@ -0,0 +1,49 @@ + + +
+ +
+
+ + +
+
+
+ + diff --git a/src/lib/JsonViewer.svelte b/src/lib/JsonViewer.svelte new file mode 100644 index 0000000..cbc01b4 --- /dev/null +++ b/src/lib/JsonViewer.svelte @@ -0,0 +1,5 @@ + + +
{JSON.stringify(json, null, 2)}
diff --git a/src/lib/MailViewer.svelte b/src/lib/MailViewer.svelte new file mode 100644 index 0000000..691b486 --- /dev/null +++ b/src/lib/MailViewer.svelte @@ -0,0 +1,14 @@ + + +
diff --git a/src/lib/Wallet.svelte b/src/lib/Wallet.svelte index 88fa6db..0e741ae 100644 --- a/src/lib/Wallet.svelte +++ b/src/lib/Wallet.svelte @@ -96,19 +96,6 @@
-
- -
-
{/each} diff --git a/src/routes/server/api/chat/+server.ts b/src/routes/server/api/chat/+server.ts new file mode 100644 index 0000000..f0947df --- /dev/null +++ b/src/routes/server/api/chat/+server.ts @@ -0,0 +1,34 @@ +import OpenAI from 'openai'; +import { OpenAIStream, StreamingTextResponse } from 'ai'; + +import { env } from '$env/dynamic/private'; +// You may want to replace the above with a static private env variable +// for dead-code elimination and build-time type-checking: +// import { OPENAI_API_KEY } from '$env/static/private' + +import type { RequestHandler } from '../../server/api/chat/$types'; + +// Create an OpenAI API client +const openai = new OpenAI({ + apiKey: env.OPENAI_API_KEY || '', +}); + +export const POST = (async ({ request }) => { + // Extract the `prompt` from the body of the request + const { messages } = await request.json(); + + // Ask OpenAI for a streaming chat completion given the prompt + const response = await openai.chat.completions.create({ + model: 'gpt-3.5-turbo', + stream: true, + messages: messages.map((message: any) => ({ + content: message.content, + role: message.role, + })), + }); + + // Convert the response into a friendly text-stream + const stream = OpenAIStream(response); + // Respond with the stream + return new StreamingTextResponse(stream); +}) satisfies RequestHandler;