diff --git a/.github/workflows/cloudrun.yml b/.github/workflows/cloudrun.yml deleted file mode 100644 index ea2f0b65..00000000 --- a/.github/workflows/cloudrun.yml +++ /dev/null @@ -1,2 +0,0 @@ -- name: Deploy to Cloud Run - uses: google-github-actions/deploy-cloudrun@v3 diff --git a/.github/workflows/gcp-auth.yaml b/.github/workflows/gcp-auth.yaml deleted file mode 100644 index 815c2838..00000000 --- a/.github/workflows/gcp-auth.yaml +++ /dev/null @@ -1,2 +0,0 @@ -- name: Authenticate to Google Cloud - uses: google-github-actions/auth@v3 diff --git a/.gitignore b/.gitignore index 36a24b98..874be5dc 100644 --- a/.gitignore +++ b/.gitignore @@ -28,10 +28,6 @@ yarn-error.log* # local env files .env*.local -# log files -dev_server.log -server.log - # vercel .vercel @@ -56,4 +52,4 @@ aef_index.csv # Environment variables with GCP credentials .env.local .env.production.local -*.log +dev_server.log diff --git a/app/actions.tsx b/app/actions.tsx index 9840ce04..7d74ce10 100644 --- a/app/actions.tsx +++ b/app/actions.tsx @@ -20,6 +20,7 @@ import { saveChat, getSystemPrompt } from '@/lib/actions/chat' // Added getSyste import { Chat, AIMessage } from '@/lib/types' import { UserMessage } from '@/components/user-message' import { BotMessage } from '@/components/message' +import { ReasoningDisplay } from '@/components/reasoning-display' import { SearchSection } from '@/components/search-section' import SearchRelated from '@/components/search-related' import { GeoJsonLayer } from '@/components/map/geojson-layer' @@ -92,58 +93,17 @@ async function submit(formData?: FormData, skip?: boolean) { ); - messages.push({ role: 'assistant', content: analysisResult.summary || 'Analysis complete.' }); - - const sanitizedMessages: CoreMessage[] = messages.map(m => { - if (Array.isArray(m.content)) { - return { - ...m, - content: m.content.filter(part => part.type !== 'image') - } as CoreMessage - } - return m - }) - - const relatedQueries = await querySuggestor(uiStream, sanitizedMessages); - uiStream.append( -
- -
- ); - - await new Promise(resolve => setTimeout(resolve, 500)); - - const groupeId = nanoid(); - aiState.done({ - ...aiState.get(), - messages: [ - ...aiState.get().messages, - { - id: groupeId, - role: 'assistant', - content: analysisResult.summary || 'Analysis complete.', - type: 'response' - }, - { - id: groupeId, - role: 'assistant', - content: JSON.stringify(analysisResult), - type: 'resolution_search_result' - }, - { - id: groupeId, - role: 'assistant', - content: JSON.stringify(relatedQueries), - type: 'related' - }, - { - id: groupeId, - role: 'assistant', - content: 'followup', - type: 'followup' - } - ] + ...aiState.get(), + messages: [ + ...aiState.get().messages, + { + id: nanoid(), + role: 'assistant', + content: JSON.stringify(analysisResult), + type: 'resolution_search_result' + } + ] }); isGenerating.done(false); @@ -361,24 +321,41 @@ async function submit(formData?: FormData, skip?: boolean) { let toolOutputs: ToolResultPart[] = [] let errorOccurred = false const streamText = createStreamableValue() - uiStream.update() + const reasoningStream = createStreamableValue() + const actionsStream = createStreamableValue() + console.log('Updating uiStream with Thinking section'); + uiStream.update( +
+ +
+ ) while ( useSpecificAPI ? answer.length === 0 : answer.length === 0 && !errorOccurred ) { - const { fullResponse, hasError, toolResponses } = await researcher( - currentSystemPrompt, - uiStream, - streamText, - messages, - mapProvider, - useSpecificAPI - ) + const { fullResponse, hasError, toolResponses, reasoningResponse } = + await researcher( + currentSystemPrompt, + uiStream, + streamText, + reasoningStream, + actionsStream, + messages, + mapProvider, + useSpecificAPI + ) answer = fullResponse toolOutputs = toolResponses errorOccurred = hasError + if (reasoningResponse) { + console.log('Reasoning response received, marking reasoningStream as done'); + reasoningStream.done(reasoningResponse) + } if (toolOutputs.length > 0) { toolOutputs.map(output => { @@ -636,6 +613,15 @@ export const getUIStateFromAIState = (aiState: AIState): UIState => { const answer = createStreamableValue() answer.done(content) switch (type) { + case 'reasoning': + return { + id, + component: ( +
+ +
+ ) + } case 'response': return { id, @@ -667,12 +653,17 @@ export const getUIStateFromAIState = (aiState: AIState): UIState => { } case 'resolution_search_result': { const analysisResult = JSON.parse(content as string); + const summaryValue = createStreamableValue(); + summaryValue.done(analysisResult.summary); const geoJson = analysisResult.geoJson as FeatureCollection; return { id, component: ( <> +
+ +
{geoJson && ( )} diff --git a/app/globals.css b/app/globals.css index 22f95cba..004897bb 100644 --- a/app/globals.css +++ b/app/globals.css @@ -188,7 +188,7 @@ } .mobile-chat-input-area { - height: auto; + height: 70px; padding: 10px; background-color: hsl(var(--background)); /* border-top: 1px solid hsl(var(--border)); */ /* Removed for cleaner separation */ diff --git a/app/layout.tsx b/app/layout.tsx index a092d4fe..e8774597 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,5 +1,5 @@ import type { Metadata, Viewport } from 'next' -import { Inter as FontSans, Poppins } from 'next/font/google' +import { Inter as FontSans } from 'next/font/google' import './globals.css' import 'katex/dist/katex.min.css'; import { cn } from '@/lib/utils' @@ -22,12 +22,6 @@ const fontSans = FontSans({ variable: '--font-sans' }) -const fontPoppins = Poppins({ - subsets: ['latin'], - variable: '--font-poppins', - weight: ['400', '500', '600', '700'] -}) - const title = '' const description = 'language to Maps' @@ -62,13 +56,7 @@ export default function RootLayout({ }>) { return ( - + diff --git a/bun.lock b/bun.lock index 936916d2..8f5fa1a9 100644 --- a/bun.lock +++ b/bun.lock @@ -34,7 +34,6 @@ "@supabase/ssr": "^0.3.0", "@supabase/supabase-js": "^2.0.0", "@tailwindcss/typography": "^0.5.16", - "@tavily/core": "^0.6.4", "@turf/turf": "^7.2.0", "@types/mapbox__mapbox-gl-draw": "^1.4.8", "@types/pg": "^8.15.4", @@ -139,27 +138,27 @@ "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], - "@aws-sdk/client-bedrock-runtime": ["@aws-sdk/client-bedrock-runtime@3.966.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.966.0", "@aws-sdk/credential-provider-node": "3.966.0", "@aws-sdk/eventstream-handler-node": "3.965.0", "@aws-sdk/middleware-eventstream": "3.965.0", "@aws-sdk/middleware-host-header": "3.965.0", "@aws-sdk/middleware-logger": "3.965.0", "@aws-sdk/middleware-recursion-detection": "3.965.0", "@aws-sdk/middleware-user-agent": "3.966.0", "@aws-sdk/middleware-websocket": "3.965.0", "@aws-sdk/region-config-resolver": "3.965.0", "@aws-sdk/token-providers": "3.966.0", "@aws-sdk/types": "3.965.0", "@aws-sdk/util-endpoints": "3.965.0", "@aws-sdk/util-user-agent-browser": "3.965.0", "@aws-sdk/util-user-agent-node": "3.966.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.1", "@smithy/eventstream-serde-browser": "^4.2.7", "@smithy/eventstream-serde-config-resolver": "^4.3.7", "@smithy/eventstream-serde-node": "^4.2.7", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.2", "@smithy/middleware-retry": "^4.4.18", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.3", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.17", "@smithy/util-defaults-mode-node": "^4.2.20", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Ofk8pTFChNNv9QRjpJGFwy+w2I+UJc6Buz5s7eFemboF899yLq66QSkHs/sByhByf543jO9Lbsauth6BdLSlGg=="], + "@aws-sdk/client-bedrock-runtime": ["@aws-sdk/client-bedrock-runtime@3.967.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.967.0", "@aws-sdk/credential-provider-node": "3.967.0", "@aws-sdk/eventstream-handler-node": "3.965.0", "@aws-sdk/middleware-eventstream": "3.965.0", "@aws-sdk/middleware-host-header": "3.965.0", "@aws-sdk/middleware-logger": "3.965.0", "@aws-sdk/middleware-recursion-detection": "3.965.0", "@aws-sdk/middleware-user-agent": "3.967.0", "@aws-sdk/middleware-websocket": "3.965.0", "@aws-sdk/region-config-resolver": "3.965.0", "@aws-sdk/token-providers": "3.967.0", "@aws-sdk/types": "3.965.0", "@aws-sdk/util-endpoints": "3.965.0", "@aws-sdk/util-user-agent-browser": "3.965.0", "@aws-sdk/util-user-agent-node": "3.967.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.2", "@smithy/eventstream-serde-browser": "^4.2.7", "@smithy/eventstream-serde-config-resolver": "^4.3.7", "@smithy/eventstream-serde-node": "^4.2.7", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.3", "@smithy/middleware-retry": "^4.4.19", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.4", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.18", "@smithy/util-defaults-mode-node": "^4.2.21", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-pFID1Lb/54u413HTpnqQYLJjX+voEKLZyqlpdVHDbxcw8MfalmmSg5PR/uJWGO3kku0LkB+H/Ca5ftL11PTL9w=="], - "@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.966.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.966.0", "@aws-sdk/middleware-host-header": "3.965.0", "@aws-sdk/middleware-logger": "3.965.0", "@aws-sdk/middleware-recursion-detection": "3.965.0", "@aws-sdk/middleware-user-agent": "3.966.0", "@aws-sdk/region-config-resolver": "3.965.0", "@aws-sdk/types": "3.965.0", "@aws-sdk/util-endpoints": "3.965.0", "@aws-sdk/util-user-agent-browser": "3.965.0", "@aws-sdk/util-user-agent-node": "3.966.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.1", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.2", "@smithy/middleware-retry": "^4.4.18", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.3", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.17", "@smithy/util-defaults-mode-node": "^4.2.20", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-hQZDQgqRJclALDo9wK+bb5O+VpO8JcjImp52w9KPSz9XveNRgE9AYfklRJd8qT2Bwhxe6IbnqYEino2wqUMA1w=="], + "@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.967.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.967.0", "@aws-sdk/middleware-host-header": "3.965.0", "@aws-sdk/middleware-logger": "3.965.0", "@aws-sdk/middleware-recursion-detection": "3.965.0", "@aws-sdk/middleware-user-agent": "3.967.0", "@aws-sdk/region-config-resolver": "3.965.0", "@aws-sdk/types": "3.965.0", "@aws-sdk/util-endpoints": "3.965.0", "@aws-sdk/util-user-agent-browser": "3.965.0", "@aws-sdk/util-user-agent-node": "3.967.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.2", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.3", "@smithy/middleware-retry": "^4.4.19", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.4", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.18", "@smithy/util-defaults-mode-node": "^4.2.21", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-7RgUwHcRMJtWme6kCHGUVT+Rn9GmNH+FHm34N9UgMXzUqQlzFMweE7T5E9O8nv3wIp7xFNB20ADaCw9Xdnox1Q=="], - "@aws-sdk/core": ["@aws-sdk/core@3.966.0", "", { "dependencies": { "@aws-sdk/types": "3.965.0", "@aws-sdk/xml-builder": "3.965.0", "@smithy/core": "^3.20.1", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/smithy-client": "^4.10.3", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-QaRVBHD1prdrFXIeFAY/1w4b4S0EFyo/ytzU+rCklEjMRT7DKGXGoHXTWLGz+HD7ovlS5u+9cf8a/LeSOEMzww=="], + "@aws-sdk/core": ["@aws-sdk/core@3.967.0", "", { "dependencies": { "@aws-sdk/types": "3.965.0", "@aws-sdk/xml-builder": "3.965.0", "@smithy/core": "^3.20.2", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/smithy-client": "^4.10.4", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-sJmuP7GrVmlbO6DpXkuf9Mbn6jGNNvy6PLawvaxVF150c8bpNk3w39rerRls6q1dot1dBFV2D29hBXMY1agNMg=="], - "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.966.0", "", { "dependencies": { "@aws-sdk/core": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-sxVKc9PY0SH7jgN/8WxhbKQ7MWDIgaJv1AoAKJkhJ+GM5r09G5Vb2Vl8ALYpsy+r8b+iYpq5dGJj8k2VqxoQMg=="], + "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.967.0", "", { "dependencies": { "@aws-sdk/core": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-+XWw0+f/txeMbEVRtTFZhgSw1ymH1ffaVKkdMBSnw48rfSohJElKmitCqdihagRTZpzh7m8qI6tIQ5t3OUqugw=="], - "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.966.0", "", { "dependencies": { "@aws-sdk/core": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.3", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-VTJDP1jOibVtc5pn5TNE12rhqOO/n10IjkoJi8fFp9BMfmh3iqo70Ppvphz/Pe/R9LcK5Z3h0Z4EB9IXDR6kag=="], + "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.967.0", "", { "dependencies": { "@aws-sdk/core": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.4", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-0/GIAEv5pY5htg6IBMuYccBgzz3oS2DqHjHi396ziTrwlhbrCNX96AbNhQhzAx3LBZUk13sPfeapjyQ7G57Ekg=="], - "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.966.0", "", { "dependencies": { "@aws-sdk/core": "3.966.0", "@aws-sdk/credential-provider-env": "3.966.0", "@aws-sdk/credential-provider-http": "3.966.0", "@aws-sdk/credential-provider-login": "3.966.0", "@aws-sdk/credential-provider-process": "3.966.0", "@aws-sdk/credential-provider-sso": "3.966.0", "@aws-sdk/credential-provider-web-identity": "3.966.0", "@aws-sdk/nested-clients": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-4oQKkYMCUx0mffKuH8LQag1M4Fo5daKVmsLAnjrIqKh91xmCrcWlAFNMgeEYvI1Yy125XeNSaFMfir6oNc2ODA=="], + "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.967.0", "", { "dependencies": { "@aws-sdk/core": "3.967.0", "@aws-sdk/credential-provider-env": "3.967.0", "@aws-sdk/credential-provider-http": "3.967.0", "@aws-sdk/credential-provider-login": "3.967.0", "@aws-sdk/credential-provider-process": "3.967.0", "@aws-sdk/credential-provider-sso": "3.967.0", "@aws-sdk/credential-provider-web-identity": "3.967.0", "@aws-sdk/nested-clients": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-U8dMpaM6Qf6+2Qvp1uG6OcWv1RlrZW7tQkpmzEVWH8HZTGrVHIXXju64NMtIOr7yOnNwd0CKcytuD1QG+phCwQ=="], - "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.966.0", "", { "dependencies": { "@aws-sdk/core": "3.966.0", "@aws-sdk/nested-clients": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-wD1KlqLyh23Xfns/ZAPxebwXixoJJCuDbeJHFrLDpP4D4h3vA2S8nSFgBSFR15q9FhgRfHleClycf6g5K4Ww6w=="], + "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.967.0", "", { "dependencies": { "@aws-sdk/core": "3.967.0", "@aws-sdk/nested-clients": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-kbvZsZL6CBlfnb71zuJdJmBUFZN5utNrcziZr/DZ2olEOkA9vlmizE8i9BUIbmS7ptjgvRnmcY1A966yfhiblw=="], - "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.966.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.966.0", "@aws-sdk/credential-provider-http": "3.966.0", "@aws-sdk/credential-provider-ini": "3.966.0", "@aws-sdk/credential-provider-process": "3.966.0", "@aws-sdk/credential-provider-sso": "3.966.0", "@aws-sdk/credential-provider-web-identity": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-7QCOERGddMw7QbjE+LSAFgwOBpPv4px2ty0GCK7ZiPJGsni2EYmM4TtYnQb9u1WNHmHqIPWMbZR0pKDbyRyHlQ=="], + "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.967.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.967.0", "@aws-sdk/credential-provider-http": "3.967.0", "@aws-sdk/credential-provider-ini": "3.967.0", "@aws-sdk/credential-provider-process": "3.967.0", "@aws-sdk/credential-provider-sso": "3.967.0", "@aws-sdk/credential-provider-web-identity": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-WuNbHs9rfKKSVok4+OBrZf0AHfzDgFYYMxN2G/q6ZfUmY4QmiPyxV5HkNFh1rqDxS9VV6kAZPo0EBmry10idSg=="], - "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.966.0", "", { "dependencies": { "@aws-sdk/core": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-q5kCo+xHXisNbbPAh/DiCd+LZX4wdby77t7GLk0b2U0/mrel4lgy6o79CApe+0emakpOS1nPZS7voXA7vGPz4w=="], + "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.967.0", "", { "dependencies": { "@aws-sdk/core": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-sNCY5JDV0whsfsZ6c2+6eUwH33H7UhKbqvCPbEYlIIa8wkGjCtCyFI3zZIJHVcMKJJ3117vSUFHEkNA7g+8rtw=="], - "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.966.0", "", { "dependencies": { "@aws-sdk/client-sso": "3.966.0", "@aws-sdk/core": "3.966.0", "@aws-sdk/token-providers": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-Rv5aEfbpqsQZzxpX2x+FbSyVFOE3Dngome+exNA8jGzc00rrMZEUnm3J3yAsLp/I2l7wnTfI0r2zMe+T9/nZAQ=="], + "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.967.0", "", { "dependencies": { "@aws-sdk/client-sso": "3.967.0", "@aws-sdk/core": "3.967.0", "@aws-sdk/token-providers": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-0K6kITKNytFjk1UYabYUsTThgU6TQkyW6Wmt8S5zd1A/up7NSQGpp58Rpg9GIf4amQDQwb+p9FGG7emmV8FEeA=="], - "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.966.0", "", { "dependencies": { "@aws-sdk/core": "3.966.0", "@aws-sdk/nested-clients": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-Yv1lc9iic9xg3ywMmIAeXN1YwuvfcClLVdiF2y71LqUgIOupW8B8my84XJr6pmOQuKzZa++c2znNhC9lGsbKyw=="], + "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.967.0", "", { "dependencies": { "@aws-sdk/core": "3.967.0", "@aws-sdk/nested-clients": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-Vkr7S2ec7q/v8i/MzkHcBEdqqfWz3lyb8FDjb+NjslEwdxC3f6XwADRZzWwV1pChfx6SbsvJXKfkcF/pKAelhA=="], "@aws-sdk/eventstream-handler-node": ["@aws-sdk/eventstream-handler-node@3.965.0", "", { "dependencies": { "@aws-sdk/types": "3.965.0", "@smithy/eventstream-codec": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-QriACiXP+/x2xXw8u849BxID+zSUbh/7Gt0Zfaxeye0mIKVeSTid5776rXfrM8wcYhbVXWWZhKd1Du7oPuFwsg=="], @@ -171,15 +170,15 @@ "@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.965.0", "", { "dependencies": { "@aws-sdk/types": "3.965.0", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-6dvD+18Ni14KCRu+tfEoNxq1sIGVp9tvoZDZ7aMvpnA7mDXuRLrOjRQ/TAZqXwr9ENKVGyxcPl0cRK8jk1YWjA=="], - "@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.966.0", "", { "dependencies": { "@aws-sdk/core": "3.966.0", "@aws-sdk/types": "3.965.0", "@aws-sdk/util-endpoints": "3.965.0", "@smithy/core": "^3.20.1", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-MvGoy0vhMluVpSB5GaGJbYLqwbZfZjwEZhneDHdPhgCgQqmCtugnYIIjpUw7kKqWGsmaMQmNEgSFf1zYYmwOyg=="], + "@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.967.0", "", { "dependencies": { "@aws-sdk/core": "3.967.0", "@aws-sdk/types": "3.965.0", "@aws-sdk/util-endpoints": "3.965.0", "@smithy/core": "^3.20.2", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-2qzJzZj5u+cZiG7kz3XJPaTH4ssUY/aet1kwJsUTFKrWeHUf7mZZkDFfkXP5cOffgiOyR5ZkrmJoLKAde9hshg=="], "@aws-sdk/middleware-websocket": ["@aws-sdk/middleware-websocket@3.965.0", "", { "dependencies": { "@aws-sdk/types": "3.965.0", "@aws-sdk/util-format-url": "3.965.0", "@smithy/eventstream-codec": "^4.2.7", "@smithy/eventstream-serde-browser": "^4.2.7", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-BGU92StrWF0EJj8jX5EFvRkX9z4/CVIZfON0nWow8gb5ouKwz47o1rO9CP/k2b3F6g134/0XqwXvrUgIWfjJeA=="], - "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.966.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.966.0", "@aws-sdk/middleware-host-header": "3.965.0", "@aws-sdk/middleware-logger": "3.965.0", "@aws-sdk/middleware-recursion-detection": "3.965.0", "@aws-sdk/middleware-user-agent": "3.966.0", "@aws-sdk/region-config-resolver": "3.965.0", "@aws-sdk/types": "3.965.0", "@aws-sdk/util-endpoints": "3.965.0", "@aws-sdk/util-user-agent-browser": "3.965.0", "@aws-sdk/util-user-agent-node": "3.966.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.1", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.2", "@smithy/middleware-retry": "^4.4.18", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.3", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.17", "@smithy/util-defaults-mode-node": "^4.2.20", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-FRzAWwLNoKiaEWbYhnpnfartIdOgiaBLnPcd3uG1Io+vvxQUeRPhQIy4EfKnT3AuA+g7gzSCjMG2JKoJOplDtQ=="], + "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.967.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.967.0", "@aws-sdk/middleware-host-header": "3.965.0", "@aws-sdk/middleware-logger": "3.965.0", "@aws-sdk/middleware-recursion-detection": "3.965.0", "@aws-sdk/middleware-user-agent": "3.967.0", "@aws-sdk/region-config-resolver": "3.965.0", "@aws-sdk/types": "3.965.0", "@aws-sdk/util-endpoints": "3.965.0", "@aws-sdk/util-user-agent-browser": "3.965.0", "@aws-sdk/util-user-agent-node": "3.967.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.2", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.3", "@smithy/middleware-retry": "^4.4.19", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.4", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.18", "@smithy/util-defaults-mode-node": "^4.2.21", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-PYa7V8w0gaNux6Sz/Z7zrHmPloEE+EKpRxQIOG/D0askTr5Yd4oO2KGgcInf65uHK3f0Z9U4CTUGHZvQvABypA=="], "@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.965.0", "", { "dependencies": { "@aws-sdk/types": "3.965.0", "@smithy/config-resolver": "^4.4.5", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-RoMhu9ly2B0coxn8ctXosPP2WmDD0MkQlZGLjoYHQUOCBmty5qmCxOqBmBDa6wbWbB8xKtMQ/4VXloQOgzjHXg=="], - "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.966.0", "", { "dependencies": { "@aws-sdk/core": "3.966.0", "@aws-sdk/nested-clients": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-8k5cBTicTGYJHhKaweO4gL4fud1KDnLS5fByT6/Xbiu59AxYM4E/h3ds+3jxDMnniCE3gIWpEnyfM9khtmw2lA=="], + "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.967.0", "", { "dependencies": { "@aws-sdk/core": "3.967.0", "@aws-sdk/nested-clients": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-Qnd/nJ0CgeUa7zQczgmdQm0vYUF7pD1G0C+dR1T7huHQHRIsgCWIsCV9wNKzOFluqtcr6YAeuTwvY0+l8XWxnA=="], "@aws-sdk/types": ["@aws-sdk/types@3.965.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jvodoJdMavvg8faN7co58vVJRO5MVep4JFPRzUNCzpJ98BDqWDk/ad045aMJcmxkLzYLS2UAnUmqjJ/tUPNlzQ=="], @@ -191,13 +190,13 @@ "@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.965.0", "", { "dependencies": { "@aws-sdk/types": "3.965.0", "@smithy/types": "^4.11.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-Xiza/zMntQGpkd2dETQeAK8So1pg5+STTzpcdGWxj5q0jGO5ayjqT/q1Q7BrsX5KIr6PvRkl9/V7lLCv04wGjQ=="], - "@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.966.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.966.0", "@aws-sdk/types": "3.965.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-vPPe8V0GLj+jVS5EqFz2NUBgWH35favqxliUOvhp8xBdNRkEjiZm5TqitVtFlxS4RrLY3HOndrWbrP5ejbwl1Q=="], + "@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.967.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.967.0", "@aws-sdk/types": "3.965.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-yUz6pCGxyG4+QaDg0dkdIBphjQp8A9rrbZa/+U3RJgRrW47hy64clFQUROzj5Poy1Ur8ICVXEUpBsSqRuYEU2g=="], "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.965.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-Tcod25/BTupraQwtb+Q+GX8bmEZfxIFjjJ/AvkhUZsZlkPeVluzq1uu3Oeqf145DCdMjzLIN6vab5MrykbDP+g=="], "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.3", "", {}, "sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw=="], - "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], + "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="], "@borewit/text-codec": ["@borewit/text-codec@0.2.1", "", {}, "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw=="], @@ -565,7 +564,7 @@ "@smithy/config-resolver": ["@smithy/config-resolver@4.4.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-HAGoUAFYsUkoSckuKbCPayECeMim8pOu+yLy1zOxt1sifzEbrsRpYa+mKcMdiHKMeiqOibyPG0sFJnmaV/OGEg=="], - "@smithy/core": ["@smithy/core@3.20.2", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.8", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-nc99TseyTwL1bg+T21cyEA5oItNy1XN4aUeyOlXJnvyRW5VSK1oRKRoSM/Iq0KFPuqZMxjBemSZHZCOZbSyBMw=="], + "@smithy/core": ["@smithy/core@3.20.3", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.8", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-iwF1e0+H9vX+4reUA0WjKnc5ueg0Leinl5kI7wsie5bVXoYdzkpINz6NPYhpr/5InOv332a7wNV5AxJyFoVUsQ=="], "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-CmduWdCiILCRNbQWFR0OcZlUPVtyE49Sr8yYL0rZQ4D/wKxiNzBNS/YHemvnbkIWj623fplgkexUd/c9CAKdoA=="], @@ -589,9 +588,9 @@ "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.7", "", { "dependencies": { "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-GszfBfCcvt7kIbJ41LuNa5f0wvQCHhnGx/aDaZJCCT05Ld6x6U2s0xsc/0mBFONBZjQJp2U/0uSJ178OXOwbhg=="], - "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.3", "", { "dependencies": { "@smithy/core": "^3.20.2", "@smithy/middleware-serde": "^4.2.8", "@smithy/node-config-provider": "^4.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-Zb8R35hjBhp1oFhiaAZ9QhClpPHdEDmNDC2UrrB2fqV0oNDUUPH12ovZHB5xi/Rd+pg/BJHOR1q+SfsieSKPQg=="], + "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.4", "", { "dependencies": { "@smithy/core": "^3.20.3", "@smithy/middleware-serde": "^4.2.8", "@smithy/node-config-provider": "^4.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-TFxS6C5bGSc4djD1SLVmstCpfYDjmMnBR4KRDge5HEEtgSINGPKuxLvaAGfSPx5FFoMaTJkj4jJLNFggeWpRoQ=="], - "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.19", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/protocol-http": "^5.3.7", "@smithy/service-error-classification": "^4.2.7", "@smithy/smithy-client": "^4.10.4", "@smithy/types": "^4.11.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-QtisFIjIw2tjMm/ESatjWFVIQb5Xd093z8xhxq/SijLg7Mgo2C2wod47Ib/AHpBLFhwYXPzd7Hp2+JVXfeZyMQ=="], + "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.20", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/protocol-http": "^5.3.7", "@smithy/service-error-classification": "^4.2.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-+UvEn/8HGzh/6zpe9xFGZe7go4/fzflggfeRG/TvdGLoUY7Gw+4RgzKJEPU2NvPo0k/j/o7vvx25ZWyOXeGoxw=="], "@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w=="], @@ -615,7 +614,7 @@ "@smithy/signature-v4": ["@smithy/signature-v4@5.3.7", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-9oNUlqBlFZFOSdxgImA6X5GFuzE7V2H7VG/7E70cdLhidFbdtvxxt81EHgykGK5vq5D3FafH//X+Oy31j3CKOg=="], - "@smithy/smithy-client": ["@smithy/smithy-client@4.10.4", "", { "dependencies": { "@smithy/core": "^3.20.2", "@smithy/middleware-endpoint": "^4.4.3", "@smithy/middleware-stack": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-rHig+BWjhjlHlah67ryaW9DECYixiJo5pQCTEwsJyarRBAwHMMC3iYz5MXXAHXe64ZAMn1NhTUSTFIu1T6n6jg=="], + "@smithy/smithy-client": ["@smithy/smithy-client@4.10.5", "", { "dependencies": { "@smithy/core": "^3.20.3", "@smithy/middleware-endpoint": "^4.4.4", "@smithy/middleware-stack": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-uotYm3WDne01R0DxBqF9J8WZc8gSgdj+uC7Lv/R+GinH4rxcgRLxLDayYkyGAboZlYszly6maQA+NGQ5N4gLhQ=="], "@smithy/types": ["@smithy/types@4.11.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA=="], @@ -631,9 +630,9 @@ "@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], - "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.18", "", { "dependencies": { "@smithy/property-provider": "^4.2.7", "@smithy/smithy-client": "^4.10.4", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-Ao1oLH37YmLyHnKdteMp6l4KMCGBeZEAN68YYe00KAaKFijFELDbRQRm3CNplz7bez1HifuBV0l5uR6eVJLhIg=="], + "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.19", "", { "dependencies": { "@smithy/property-provider": "^4.2.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-5fkC/yE5aepnzcF9dywKefGlJUMM7JEYUOv97TRDLTtGiiAqf7YG80HJWIBR0qWQPQW3dlQ5eFlUsySvt0rGEA=="], - "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.21", "", { "dependencies": { "@smithy/config-resolver": "^4.4.5", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/smithy-client": "^4.10.4", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-e21ASJDirE96kKXZLcYcnn4Zt0WGOvMYc1P8EK0gQeQ3I8PbJWqBKx9AUr/YeFpDkpYwEu1RsPe4UXk2+QL7IA=="], + "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.22", "", { "dependencies": { "@smithy/config-resolver": "^4.4.5", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-f0KNaSK192+kv6GFkUDA0Tvr5B8eU2bFh1EO+cUdlzZ2jap5Zv7KZXa0B/7r/M1+xiYPSIuroxlxQVP1ua9kxg=="], "@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-s4ILhyAvVqhMDYREeTS68R43B1V5aenV5q/V1QpRQJkCXib5BPRo4s7uNdzGtIKxaPHCfU/8YkvPAEvTpxgspg=="], @@ -673,8 +672,6 @@ "@tailwindcss/typography": ["@tailwindcss/typography@0.5.19", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg=="], - "@tavily/core": ["@tavily/core@0.6.4", "", { "dependencies": { "axios": "^1.7.7", "https-proxy-agent": "^7.0.6", "js-tiktoken": "^1.0.14" } }, "sha512-PppC0p2SwkoImLiYFT/uqDyWKPivpVsIM16HUf1Apmtbqg1YhI7Yg5Hq6eYSojC6COVCGXE4CotBnWqUmrai+A=="], - "@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="], "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], @@ -981,25 +978,25 @@ "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.52.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/type-utils": "8.52.0", "@typescript-eslint/utils": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.52.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.53.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.53.0", "@typescript-eslint/type-utils": "8.53.0", "@typescript-eslint/utils": "8.53.0", "@typescript-eslint/visitor-keys": "8.53.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.53.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.52.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.53.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.53.0", "@typescript-eslint/types": "8.53.0", "@typescript-eslint/typescript-estree": "8.53.0", "@typescript-eslint/visitor-keys": "8.53.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg=="], - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.52.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.52.0", "@typescript-eslint/types": "^8.52.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.53.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.53.0", "@typescript-eslint/types": "^8.53.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0" } }, "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.53.0", "", { "dependencies": { "@typescript-eslint/types": "8.53.0", "@typescript-eslint/visitor-keys": "8.53.0" } }, "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g=="], - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.52.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.53.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/utils": "8.52.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.53.0", "", { "dependencies": { "@typescript-eslint/types": "8.53.0", "@typescript-eslint/typescript-estree": "8.53.0", "@typescript-eslint/utils": "8.53.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw=="], - "@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.53.0", "", {}, "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.52.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.52.0", "@typescript-eslint/tsconfig-utils": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.53.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.53.0", "@typescript-eslint/tsconfig-utils": "8.53.0", "@typescript-eslint/types": "8.53.0", "@typescript-eslint/visitor-keys": "8.53.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.52.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.53.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.53.0", "@typescript-eslint/types": "8.53.0", "@typescript-eslint/typescript-estree": "8.53.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.53.0", "", { "dependencies": { "@typescript-eslint/types": "8.53.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], @@ -1119,8 +1116,6 @@ "axe-core": ["axe-core@4.11.1", "", {}, "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A=="], - "axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="], - "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], @@ -1459,13 +1454,11 @@ "fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="], - "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], - "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], + "form-data": ["form-data@2.5.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A=="], "form-data-encoder": ["form-data-encoder@1.7.2", "", {}, "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="], @@ -1575,7 +1568,7 @@ "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], - "hono": ["hono@4.11.3", "", {}, "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w=="], + "hono": ["hono@4.11.4", "", {}, "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA=="], "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="], @@ -1711,8 +1704,6 @@ "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="], - "js-tiktoken": ["js-tiktoken@1.0.21", "", { "dependencies": { "base64-js": "^1.5.1" } }, "sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g=="], - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], @@ -2093,8 +2084,6 @@ "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], - "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "pusher-js": ["pusher-js@8.4.0", "", { "dependencies": { "tweetnacl": "^1.0.3" } }, "sha512-wp3HqIIUc1GRyu1XrP6m2dgyE9MoCsXVsWNlohj0rjSkLf+a0jLvEyVubdg58oMk7bhjBWnFClgp8jfAa6Ak4Q=="], @@ -2625,7 +2614,7 @@ "@turf/tesselate/earcut": ["earcut@2.2.4", "", {}, "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="], - "@types/request/form-data": ["form-data@2.5.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A=="], + "@types/node-fetch/form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], @@ -2833,7 +2822,7 @@ "@modelcontextprotocol/sdk/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "@types/request/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "@types/node-fetch/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], @@ -2877,7 +2866,7 @@ "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], - "@types/request/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "@types/node-fetch/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "open-codex/openai/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], } diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx index c45844d3..3320127c 100644 --- a/components/chat-panel.tsx +++ b/components/chat-panel.tsx @@ -1,8 +1,8 @@ 'use client' -import { useEffect, useState, useRef, ChangeEvent, forwardRef, useImperativeHandle, useCallback } from 'react' +import { useEffect, useState, useRef, ChangeEvent, forwardRef, useImperativeHandle } from 'react' import type { AI, UIState } from '@/app/actions' -import { useUIState, useActions, readStreamableValue } from 'ai/rsc' +import { useUIState, useActions } from 'ai/rsc' // Removed import of useGeospatialToolMcp as it's no longer used/available import { cn } from '@/lib/utils' import { UserMessage } from './user-message' @@ -11,37 +11,24 @@ import { ArrowRight, Plus, Paperclip, X } from 'lucide-react' import Textarea from 'react-textarea-autosize' import { nanoid } from 'nanoid' import { useSettingsStore } from '@/lib/store/settings' -import { PartialRelated } from '@/lib/schema/related' -import { getSuggestions } from '@/lib/actions/suggest' -import { useMapData } from './map/map-data-context' -import SuggestionsDropdown from './suggestions-dropdown' interface ChatPanelProps { messages: UIState input: string setInput: (value: string) => void - onSuggestionsChange?: (suggestions: PartialRelated | null) => void } export interface ChatPanelRef { - handleAttachmentClick: () => void - submitForm: () => void + handleAttachmentClick: () => void; } -export const ChatPanel = forwardRef(({ messages, input, setInput, onSuggestionsChange }, ref) => { +export const ChatPanel = forwardRef(({ messages, input, setInput }, ref) => { const [, setMessages] = useUIState() const { submit, clearChat } = useActions() // Removed mcp instance as it's no longer passed to submit const { mapProvider } = useSettingsStore() const [isMobile, setIsMobile] = useState(false) const [selectedFile, setSelectedFile] = useState(null) - const [suggestions, setSuggestionsState] = useState(null) - const setSuggestions = useCallback((s: PartialRelated | null) => { - setSuggestionsState(s) - onSuggestionsChange?.(s) - }, [onSuggestionsChange, setSuggestionsState]) - const { mapData } = useMapData() - const debounceTimeoutRef = useRef(null) const inputRef = useRef(null) const formRef = useRef(null) const fileInputRef = useRef(null) @@ -49,9 +36,6 @@ export const ChatPanel = forwardRef(({ messages, i useImperativeHandle(ref, () => ({ handleAttachmentClick() { fileInputRef.current?.click() - }, - submitForm() { - formRef.current?.requestSubmit() } })); @@ -89,7 +73,7 @@ export const ChatPanel = forwardRef(({ messages, i const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() - if (!input.trim() && !selectedFile) { + if (!input && !selectedFile) { return } @@ -130,32 +114,6 @@ export const ChatPanel = forwardRef(({ messages, i await clearChat() } - const debouncedGetSuggestions = useCallback( - (value: string) => { - if (debounceTimeoutRef.current) { - clearTimeout(debounceTimeoutRef.current) - } - - const wordCount = value.trim().split(/\s+/).filter(Boolean).length - if (wordCount < 2) { - setSuggestions(null) - return - } - - debounceTimeoutRef.current = setTimeout(async () => { - const suggestionsStream = await getSuggestions(value, mapData) - for await (const partialSuggestions of readStreamableValue( - suggestionsStream - )) { - if (partialSuggestions) { - setSuggestions(partialSuggestions as PartialRelated) - } - } - }, 500) // 500ms debounce delay - }, - [mapData] - ) - useEffect(() => { inputRef.current?.focus() }, []) @@ -194,6 +152,18 @@ export const ChatPanel = forwardRef(({ messages, i : 'sticky bottom-0 bg-background z-10 w-full border-t border-border px-2 py-3 md:px-4' )} > + {selectedFile && ( +
+
+ + {selectedFile.name} + + +
+
+ )}
(({ messages, i 'absolute top-1/2 transform -translate-y-1/2 left-3' )} onClick={handleAttachmentClick} - data-testid="desktop-attachment-button" + data-testid="attachment-button" > @@ -248,7 +218,6 @@ export const ChatPanel = forwardRef(({ messages, i )} onChange={e => { setInput(e.target.value) - debouncedGetSuggestions(e.target.value) }} onKeyDown={e => { if ( @@ -288,21 +257,8 @@ export const ChatPanel = forwardRef(({ messages, i > - {/* Suggestions are now handled by the parent component (chat.tsx) as an overlay */} - {selectedFile && ( -
-
- - {selectedFile.name} - - -
-
- )} ) }) diff --git a/components/chat.tsx b/components/chat.tsx index 04e27ac6..1f398561 100644 --- a/components/chat.tsx +++ b/components/chat.tsx @@ -5,9 +5,6 @@ import { usePathname, useRouter } from 'next/navigation' import { ChatPanel, ChatPanelRef } from './chat-panel' import { ChatMessages } from './chat-messages' import { EmptyScreen } from './empty-screen' -import SuggestionsDropdown from './suggestions-dropdown' -import { PartialRelated } from '@/lib/schema/related' -import { cn } from '@/lib/utils' import { useCalendarToggle } from './calendar-toggle-context' import { CalendarNotepad } from './calendar-notepad' import { MapProvider } from './map/map-provider' @@ -34,17 +31,11 @@ export function Chat({ id }: ChatProps) { const { isCalendarOpen } = useCalendarToggle() const [input, setInput] = useState('') const [showEmptyScreen, setShowEmptyScreen] = useState(false) - const [isSubmitting, setIsSubmitting] = useState(false) - const [suggestions, setSuggestions] = useState(null) const chatPanelRef = useRef(null); const handleAttachment = () => { chatPanelRef.current?.handleAttachmentClick(); }; - - const handleMobileSubmit = () => { - chatPanelRef.current?.submitForm(); - }; useEffect(() => { setShowEmptyScreen(messages.length === 0) @@ -82,23 +73,13 @@ export function Chat({ id }: ChatProps) { // Get mapData to access drawnFeatures const { mapData } = useMapData(); - useEffect(() => { - if (isSubmitting) { - chatPanelRef.current?.submitForm() - setIsSubmitting(false) - } - }, [isSubmitting]) - // useEffect to call the server action when drawnFeatures changes useEffect(() => { - if (id && mapData.drawnFeatures && mapData.cameraState) { + if (id && mapData.drawnFeatures && mapData.drawnFeatures.length > 0) { console.log('Chat.tsx: drawnFeatures changed, calling updateDrawingContext', mapData.drawnFeatures); - updateDrawingContext(id, { - drawnFeatures: mapData.drawnFeatures, - cameraState: mapData.cameraState, - }); + updateDrawingContext(id, mapData.drawnFeatures); } - }, [id, mapData.drawnFeatures, mapData.cameraState]); + }, [id, mapData.drawnFeatures]); // Mobile layout if (isMobile) { @@ -110,48 +91,20 @@ export function Chat({ id }: ChatProps) { {activeView ? : }
- +
- +
-
+
{isCalendarOpen ? ( ) : showEmptyScreen ? ( -
-
- { - setInput(message) - setIsSubmitting(true) - }} - /> -
- {suggestions && ( -
- { - setInput(query) - setSuggestions(null) - // Use a small timeout to ensure state update before submission - setTimeout(() => { - setIsSubmitting(true) - }, 0) - }} - onClose={() => setSuggestions(null)} - className="relative bottom-auto mb-0 w-full shadow-none border-none bg-transparent" - /> -
- )} -
+ { + setInput(message) + }} + /> ) : ( )} @@ -167,50 +120,21 @@ export function Chat({ id }: ChatProps) {
{/* This is the new div for scrolling */} -
+
{isCalendarOpen ? ( ) : ( <> - -
- {showEmptyScreen ? ( - <> -
- { - setInput(message) - setIsSubmitting(true) - }} - /> -
- {suggestions && ( -
- { - setInput(query) - setSuggestions(null) - // Use a small timeout to ensure state update before submission - setTimeout(() => { - setIsSubmitting(true) - }, 0) - }} - onClose={() => setSuggestions(null)} - className="relative bottom-auto mb-0 w-full shadow-none border-none bg-transparent" - /> -
- )} - - ) : ( - - )} -
+ + {showEmptyScreen ? ( + { + setInput(message) + }} + /> + ) : ( + + )} )}
diff --git a/components/header-search-button.tsx b/components/header-search-button.tsx index cdbc5c11..3d076cdc 100644 --- a/components/header-search-button.tsx +++ b/components/header-search-button.tsx @@ -10,8 +10,6 @@ import { AI } from '@/app/actions' import { nanoid } from 'nanoid' import { UserMessage } from './user-message' import { toast } from 'react-toastify' -import { useSettingsStore } from '@/lib/store/settings' -import { useMapData } from './map/map-data-context' // Define an interface for the actions to help TypeScript during build interface HeaderActions { @@ -20,8 +18,6 @@ interface HeaderActions { export function HeaderSearchButton() { const { map } = useMap() - const { mapProvider } = useSettingsStore() - const { mapData } = useMapData() // Cast the actions to our defined interface to avoid build errors const actions = useActions() as unknown as HeaderActions const [, setMessages] = useUIState() @@ -36,11 +32,12 @@ export function HeaderSearchButton() { }, []) const handleResolutionSearch = async () => { - if (mapProvider === 'mapbox' && !map) { + if (!map) { toast.error('Map is not available yet. Please wait for it to load.') return } if (!actions) { + // This should theoretically not happen if the component is used correctly toast.error('Search actions are not available.') return } @@ -56,31 +53,10 @@ export function HeaderSearchButton() { } ]) - let blob: Blob | null = null; - - if (mapProvider === 'mapbox') { - const canvas = map!.getCanvas() - blob = await new Promise(resolve => { - canvas.toBlob(resolve, 'image/png') - }) - } else if (mapProvider === 'google') { - const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY - if (!apiKey || !mapData.cameraState) { - toast.error('Google Maps API key or camera state is not available.') - setIsAnalyzing(false) - return - } - const { center, range } = mapData.cameraState - const zoom = Math.round(Math.log2(40000000 / (range || 1))); - - let staticMapUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${center.lat},${center.lng}&zoom=${zoom}&size=640x480&maptype=satellite&key=${apiKey}`; - - const response = await fetch(staticMapUrl); - if (!response.ok) { - throw new Error('Failed to fetch static map image.'); - } - blob = await response.blob(); - } + const canvas = map.getCanvas() + const blob = await new Promise(resolve => { + canvas.toBlob(resolve, 'image/png') + }) if (!blob) { throw new Error('Failed to capture map image.') diff --git a/components/header.tsx b/components/header.tsx index 644ba8c0..273600e8 100644 --- a/components/header.tsx +++ b/components/header.tsx @@ -19,26 +19,17 @@ import { ProfileToggle } from './profile-toggle' export const Header = () => { const { toggleCalendar } = useCalendarToggle() return ( -
+
-
+
-

- QCX -

@@ -66,6 +57,7 @@ export const Header = () => { {/* Mobile menu buttons */}
+
- - diff --git a/components/profile-toggle.tsx b/components/profile-toggle.tsx index e8c22cba..2d79ccc3 100644 --- a/components/profile-toggle.tsx +++ b/components/profile-toggle.tsx @@ -8,13 +8,10 @@ import { ProfileToggleEnum, useProfileToggle } from "./profile-toggle-context" export function ProfileToggle() { const { toggleProfileSection } = useProfileToggle() const [alignValue, setAlignValue] = useState<'start' | 'end'>("end") - const [isMobile, setIsMobile] = useState(false) useEffect(() => { const handleResize = () => { - const mobile = window.innerWidth < 768 - setIsMobile(mobile) - if (mobile) { + if (window.innerWidth < 768) { setAlignValue("start") // Right align on mobile too } else { setAlignValue("start") // Right align on desktop @@ -35,15 +32,6 @@ export function ProfileToggle() { const handleSectionChange = (section: ProfileToggleEnum) => { toggleProfileSection(section) } - - if (isMobile) { - return ( - - ) - } return ( diff --git a/components/reasoning-display.tsx b/components/reasoning-display.tsx new file mode 100644 index 00000000..6a247b46 --- /dev/null +++ b/components/reasoning-display.tsx @@ -0,0 +1,32 @@ +'use client' + +import { StreamableValue, useStreamableValue } from 'ai/rsc' +import { MemoizedReactMarkdown } from './ui/markdown' + +export function ReasoningDisplay({ + content, + actions +}: { + content: StreamableValue + actions?: StreamableValue +}) { + const [data, error, pending] = useStreamableValue(content) + const [actionsData] = useStreamableValue(actions) + + if (error) { + return
Error
+ } + + return ( +
+ + {data || ''} + + {actionsData && ( + + {actionsData} + + )} +
+ ) +} diff --git a/components/search-related.tsx b/components/search-related.tsx index d4a58b08..f4aa2c8d 100644 --- a/components/search-related.tsx +++ b/components/search-related.tsx @@ -60,7 +60,7 @@ export const SearchRelated: React.FC = ({ {data?.items ?.filter(item => item?.query !== '') .map((item, index) => ( -
+
- ) - })} -
-
- ) -} - -export default SuggestionsDropdown diff --git a/config/model.json b/config/model.json index 8bfa7dac..6d26ada3 100644 --- a/config/model.json +++ b/config/model.json @@ -1,3 +1 @@ -{ - "selectedModel": null -} +{ "selectedModel": "Grok 4.2" } \ No newline at end of file diff --git a/lib/actions/chat.ts b/lib/actions/chat.ts index c257d6e8..6c6ece14 100644 --- a/lib/actions/chat.ts +++ b/lib/actions/chat.ts @@ -162,7 +162,7 @@ export async function saveChat(chat: OldChatType, userId: string): Promise() - - const systemPrompt = `As a helpful assistant, your task is to generate a set of three query suggestions based on the user's partial input. The user is currently interacting with a map, and the following data represents the current map view: ${JSON.stringify(mapData)}. Use this location context to provide relevant suggestions. - - For instance, if the user's partial query is "best coffee near" and the map context is centered on San Francisco, your output should follow this format: - - "{ - "items": [ - { "query": "best coffee near downtown San Francisco" }, - { "query": "top-rated independent coffee shops in SF" }, - { "query": "coffee shops with outdoor seating in San Francisco" } - ] - }" - - Generate three queries that anticipate the user's needs, offering logical next steps for their search. The suggestions should be concise and directly related to the partial query and map context.` - - ;(async () => { - const result = await streamObject({ - model: (await getModel()) as LanguageModel, - system: systemPrompt, - messages: [{ role: 'user', content: query }], - schema: relatedSchema - }) - - for await (const obj of result.partialObjectStream) { - if (obj && typeof obj === 'object' && 'items' in obj) { - objectStream.update(obj as PartialRelated) - } - } - objectStream.done() - })() - - return objectStream.value -} diff --git a/lib/actions/users.ts b/lib/actions/users.ts index 65a00de3..728a4822 100644 --- a/lib/actions/users.ts +++ b/lib/actions/users.ts @@ -1,7 +1,7 @@ // File: lib/actions/users.ts 'use server'; -import { revalidatePath, unstable_noStore as noStore } from 'next/cache'; +import { revalidatePath } from 'next/cache'; import fs from 'fs/promises'; import path from 'path'; @@ -124,32 +124,24 @@ export async function updateSettingsAndUsers( const modelConfigPath = path.resolve(process.cwd(), 'config', 'model.json'); export async function getSelectedModel(): Promise { - noStore(); - console.log(`[DEBUG] getSelectedModel - Reading from path: "${modelConfigPath}"`); try { const data = await fs.readFile(modelConfigPath, 'utf8'); - console.log(`[DEBUG] getSelectedModel - Raw file content: "${data}"`); const config = JSON.parse(data); return config.selectedModel || null; } catch (error) { console.error('Error reading model config:', error); - console.log(`[DEBUG] getSelectedModel - Error reading file:`, error); return null; } } export async function saveSelectedModel(model: string): Promise<{ success: boolean; error?: string }> { - console.log(`[DEBUG] saveSelectedModel - Received model selection: "${model}"`); - console.log(`[DEBUG] saveSelectedModel - Writing to path: "${modelConfigPath}"`); try { const data = JSON.stringify({ selectedModel: model }, null, 2); await fs.writeFile(modelConfigPath, data, 'utf8'); - console.log(`[DEBUG] saveSelectedModel - Successfully wrote to file.`); revalidatePath('/settings'); return { success: true }; } catch (error) { console.error('Error saving model config:', error); - console.log(`[DEBUG] saveSelectedModel - Error writing to file:`, error); return { success: false, error: 'Failed to save selected model.' }; } } diff --git a/lib/agents/inquire.tsx b/lib/agents/inquire.tsx index e15926b7..ee1f9e04 100644 --- a/lib/agents/inquire.tsx +++ b/lib/agents/inquire.tsx @@ -23,7 +23,7 @@ export async function inquire( let finalInquiry: PartialInquiry = {}; const result = await streamObject({ - model: (await getModel()) as LanguageModel, + model: getModel() as LanguageModel, system: `...`, // Your system prompt remains unchanged messages, schema: inquirySchema, diff --git a/lib/agents/query-suggestor.tsx b/lib/agents/query-suggestor.tsx index de2b3749..0c510314 100644 --- a/lib/agents/query-suggestor.tsx +++ b/lib/agents/query-suggestor.tsx @@ -18,7 +18,7 @@ export async function querySuggestor( let finalRelatedQueries: PartialRelated = {} const result = await streamObject({ - model: (await getModel()) as LanguageModel, + model: getModel() as LanguageModel, system: `As a professional web researcher, your task is to generate a set of three queries that explore the subject matter more deeply, building upon the initial query and the information uncovered in its search results. For instance, if the original query was "Starship's third test flight key milestones", your output should follow this format: diff --git a/lib/agents/researcher.tsx b/lib/agents/researcher.tsx index 72a5d737..554d29a1 100644 --- a/lib/agents/researcher.tsx +++ b/lib/agents/researcher.tsx @@ -1,5 +1,5 @@ // lib/agents/researcher.tsx -import { createStreamableUI, createStreamableValue } from 'ai/rsc' +import { createStreamableUI, createStreamableValue, getMutableAIState } from 'ai/rsc' import { CoreMessage, LanguageModel, @@ -12,6 +12,7 @@ import { BotMessage } from '@/components/message' import { getTools } from './tools' import { getModel } from '../utils' import { MapProvider } from '@/lib/store/settings' +import { nanoid } from 'nanoid' // This magic tag lets us write raw multi-line strings with backticks, arrows, etc. const raw = String.raw @@ -78,11 +79,15 @@ export async function researcher( dynamicSystemPrompt: string, uiStream: ReturnType, streamText: ReturnType>, + reasoningStream: ReturnType>, + actionsStream: ReturnType>, messages: CoreMessage[], mapProvider: MapProvider, useSpecificModel?: boolean ) { let fullResponse = '' + let reasoningResponse = '' + let actionsResponse = '' let hasError = false const answerSection = ( @@ -105,7 +110,7 @@ export async function researcher( ) const result = await nonexperimental_streamText({ - model: (await getModel(hasImage)) as LanguageModel, + model: getModel(hasImage) as LanguageModel, maxTokens: 4096, system: systemPromptToUse, messages, @@ -128,8 +133,15 @@ export async function researcher( streamText.update(fullResponse) } break - + case 'reasoning': + if (delta.textDelta) { + reasoningResponse += delta.textDelta + reasoningStream.update(reasoningResponse) + } + break case 'tool-call': + actionsResponse += `\n- ${delta.toolName}` + actionsStream.update(actionsResponse) toolCalls.push(delta) break @@ -157,5 +169,21 @@ export async function researcher( messages.push({ role: 'tool', content: toolResponses }) } - return { result, fullResponse, hasError, toolResponses } + if (reasoningResponse) { + const aiState = getMutableAIState() + aiState.update({ + ...aiState.get(), + messages: [ + ...aiState.get().messages, + { + id: nanoid(), + role: 'assistant', + content: reasoningResponse, + type: 'reasoning' + } + ] + }) + } + + return { result, fullResponse, hasError, toolResponses, reasoningResponse } } diff --git a/lib/agents/resolution-search.tsx b/lib/agents/resolution-search.tsx index 862de078..e95f4128 100644 --- a/lib/agents/resolution-search.tsx +++ b/lib/agents/resolution-search.tsx @@ -47,7 +47,7 @@ Analyze the user's prompt and the image to provide a holistic understanding of t // Use generateObject to get the full object at once. const { object } = await generateObject({ - model: await getModel(hasImage), + model: getModel(hasImage) as any, system: systemPrompt, messages: filteredMessages, schema: resolutionSearchSchema, diff --git a/lib/agents/task-manager.tsx b/lib/agents/task-manager.tsx index 90a72b67..7e6b225a 100644 --- a/lib/agents/task-manager.tsx +++ b/lib/agents/task-manager.tsx @@ -16,7 +16,7 @@ export async function taskManager(messages: CoreMessage[]) { } const result = await generateObject({ - model: (await getModel()) as LanguageModel, + model: getModel() as LanguageModel, system: `As a planet computer, your primary objective is to act as an efficient **Task Manager** for the user's query. Your goal is to minimize unnecessary steps and maximize the efficiency of the subsequent exploration phase (researcher agent). You must first analyze the user's input and determine the optimal course of action. You have two options at your disposal: diff --git a/lib/agents/tools/search.tsx b/lib/agents/tools/search.tsx index 7510a795..3ed9d82d 100644 --- a/lib/agents/tools/search.tsx +++ b/lib/agents/tools/search.tsx @@ -1,6 +1,5 @@ import { createStreamableValue } from 'ai/rsc' import Exa from 'exa-js' -import { tavily } from '@tavily/core' import { searchSchema } from '@/lib/schema/search' import { Card } from '@/components/ui/card' import { SearchSection } from '@/components/search-section' @@ -12,23 +11,11 @@ export const searchTool = ({ uiStream, fullResponse }: ToolProps) => ({ execute: async ({ query, max_results, - search_depth, - include_answer, - topic, - time_range, - include_images, - include_image_descriptions, - include_raw_content + search_depth }: { query: string max_results: number search_depth: 'basic' | 'advanced' - include_answer: boolean - topic?: 'general' | 'news' | 'finance' - time_range?: 'y' | 'year' | 'd' | 'day' | 'month' | 'week' | 'm' | 'w' - include_images: boolean - include_image_descriptions: boolean - include_raw_content: boolean }) => { let hasError = false // Append the search section @@ -43,17 +30,7 @@ export const searchTool = ({ uiStream, fullResponse }: ToolProps) => ({ try { searchResult = searchAPI === 'tavily' - ? await tavilySearch( - filledQuery, - max_results, - search_depth, - include_answer, - topic, - time_range, - include_images, - include_image_descriptions, - include_raw_content - ) + ? await tavilySearch(filledQuery, max_results, search_depth) : await exaSearch(query) } catch (error) { console.error('Search API error:', error) @@ -78,28 +55,31 @@ export const searchTool = ({ uiStream, fullResponse }: ToolProps) => ({ async function tavilySearch( query: string, - max_results: number = 10, - search_depth: 'basic' | 'advanced' = 'basic', - include_answer: boolean = true, - topic?: 'general' | 'news' | 'finance', - time_range?: 'y' | 'year' | 'd' | 'day' | 'month' | 'week' | 'm' | 'w', - include_images: boolean = false, - include_image_descriptions: boolean = false, - include_raw_content: boolean = false + maxResults: number = 10, + searchDepth: 'basic' | 'advanced' = 'basic' ): Promise { - const client = tavily({ apiKey: process.env.TAVILY_API_KEY }) - const response = await client.search(query, { - maxResults: max_results < 5 ? 5 : max_results, - searchDepth: search_depth, - includeAnswer: include_answer, - topic, - timeRange: time_range, - includeImages: include_images, - includeImageDescriptions: include_image_descriptions, - includeRawContent: include_raw_content ? 'text' : undefined + const apiKey = process.env.TAVILY_API_KEY + const response = await fetch('https://api.tavily.com/search', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + api_key: apiKey, + query, + max_results: maxResults < 5 ? 5 : maxResults, + search_depth: searchDepth, + include_images: true, + include_answers: true + }) }) - return { ...response, results: response.results.reverse() } + if (!response.ok) { + throw new Error(`Error: ${response.status}`) + } + + const data = await response.json() + return data } async function exaSearch(query: string, maxResults: number = 10): Promise { diff --git a/lib/agents/writer.tsx b/lib/agents/writer.tsx index f4e4d0ac..59249414 100644 --- a/lib/agents/writer.tsx +++ b/lib/agents/writer.tsx @@ -32,7 +32,7 @@ export async function writer( const systemToUse = dynamicSystemPrompt && dynamicSystemPrompt.trim() !== '' ? dynamicSystemPrompt : default_system_prompt; const result = await nonexperimental_streamText({ - model: (await getModel()) as LanguageModel, + model: getModel() as LanguageModel, maxTokens: 2500, system: systemToUse, // Use the dynamic or default system prompt messages diff --git a/lib/hooks/use-deep-compare-effect.ts b/lib/hooks/use-deep-compare-effect.ts index 67a30ec0..605f0c73 100644 --- a/lib/hooks/use-deep-compare-effect.ts +++ b/lib/hooks/use-deep-compare-effect.ts @@ -18,5 +18,5 @@ export function useDeepCompareEffect( currentDependenciesRef.current = dependencies; } - useEffect(callback, [currentDependenciesRef.current, callback]); + useEffect(callback, [currentDependenciesRef.current]); } diff --git a/lib/schema/search.tsx b/lib/schema/search.tsx index f298500e..0ced1865 100644 --- a/lib/schema/search.tsx +++ b/lib/schema/search.tsx @@ -11,13 +11,7 @@ export const searchSchema = z.object({ search_depth: z .enum(['basic', 'advanced']) .default('basic') - .describe('The depth of the search'), - include_answer: z.boolean().default(true).describe('Include answer in the search results'), - topic: z.enum(['general', 'news', 'finance']).optional().describe('The topic of the search'), - time_range: z.enum(['y', 'year', 'd', 'day', 'month', 'week', 'm', 'w']).optional().describe('The time range for the search'), - include_images: z.boolean().default(false).describe('Include images in the search results'), - include_image_descriptions: z.boolean().default(false).describe('Include image descriptions in the search results'), - include_raw_content: z.boolean().default(false).describe('Include raw content in the search results') + .describe('The depth of the search') }) export type PartialInquiry = DeepPartial diff --git a/lib/types/index.ts b/lib/types/index.ts index c4ea616c..8b4325c9 100644 --- a/lib/types/index.ts +++ b/lib/types/index.ts @@ -74,6 +74,7 @@ export type AIMessage = { | 'end' | 'drawing_context' // Added custom type for drawing context messages | 'resolution_search_result' + | 'reasoning' } export type CalendarNote = { diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 64e8a305..9a856100 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -1,6 +1,5 @@ import { type ClassValue, clsx } from 'clsx' import { twMerge } from 'tailwind-merge' -import { getSelectedModel } from '@/lib/actions/users' import { openai } from '@ai-sdk/openai' import { createOpenAI } from '@ai-sdk/openai' import { createGoogleGenerativeAI } from '@ai-sdk/google' @@ -17,87 +16,62 @@ export function generateUUID(): string { return uuidv4(); } -export async function getModel(requireVision: boolean = false) { - const selectedModel = await getSelectedModel(); +export function getModel(requireVision: boolean = false) { + const xaiApiKey = process.env.XAI_API_KEY + const gemini3ProApiKey = process.env.GEMINI_3_PRO_API_KEY + const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID + const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY + const awsRegion = process.env.AWS_REGION + const bedrockModelId = process.env.BEDROCK_MODEL_ID || 'anthropic.claude-3-5-sonnet-20241022-v2:0' - const xaiApiKey = process.env.XAI_API_KEY; - const gemini3ProApiKey = process.env.GEMINI_3_PRO_API_KEY; - const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID; - const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; - const awsRegion = process.env.AWS_REGION; - const bedrockModelId = process.env.BEDROCK_MODEL_ID || 'anthropic.claude-3-5-sonnet-20241022-v2:0'; - const openaiApiKey = process.env.OPENAI_API_KEY; - - if (selectedModel) { - switch (selectedModel) { - case 'Grok 4.2': - if (xaiApiKey) { - const xai = createXai({ - apiKey: xaiApiKey, - baseURL: 'https://api.x.ai/v1', - }); - try { - return xai('grok-4-fast-non-reasoning'); - } catch (error) { - console.error('Selected model "Grok 4.2" is configured but failed to initialize.', error); - throw new Error('Failed to initialize selected model.'); - } - } else { - console.error('User selected "Grok 4.2" but XAI_API_KEY is not set.'); - throw new Error('Selected model is not configured.'); - } - case 'Gemini 3': - if (gemini3ProApiKey) { - const google = createGoogleGenerativeAI({ - apiKey: gemini3ProApiKey, - }); - try { - return google('gemini-3-pro-preview'); - } catch (error) { - console.error('Selected model "Gemini 3" is configured but failed to initialize.', error); - throw new Error('Failed to initialize selected model.'); - } - } else { - console.error('User selected "Gemini 3" but GEMINI_3_PRO_API_KEY is not set.'); - throw new Error('Selected model is not configured.'); - } - case 'GPT-5.1': - if (openaiApiKey) { - const openai = createOpenAI({ - apiKey: openaiApiKey, - }); - return openai('gpt-4o'); - } else { - console.error('User selected "GPT-5.1" but OPENAI_API_KEY is not set.'); - throw new Error('Selected model is not configured.'); - } + // If vision is required, use a vision-enabled model + if (requireVision && gemini3ProApiKey) { + const google = createGoogleGenerativeAI({ + apiKey: gemini3ProApiKey + }) + try { + return google('gemini-3-pro-preview') + } catch (error) { + console.warn( + 'Gemini 3 Pro API unavailable, falling back to next provider:', + error + ) } } - // Default behavior: Grok -> Gemini -> Bedrock -> OpenAI - if (xaiApiKey) { + // If vision is not required, proceed with the normal model selection + if (!requireVision && xaiApiKey) { const xai = createXai({ apiKey: xaiApiKey, baseURL: 'https://api.x.ai/v1', - }); + }) + // Optionally, add a check for credit status or skip xAI if credits are exhausted try { - return xai('grok-4-fast-non-reasoning'); + return xai('grok-4-fast-non-reasoning') } catch (error) { - console.warn('xAI API unavailable, falling back to next provider:'); + console.warn('xAI API unavailable, falling back to OpenAI:') } } + // Gemini 3 Pro if (gemini3ProApiKey) { const google = createGoogleGenerativeAI({ - apiKey: gemini3ProApiKey, - }); + apiKey: gemini3ProApiKey + }) try { - return google('gemini-3-pro-preview'); + return google('gemini-3-pro-preview', { + experimental_enableReasoning: true + } as any) } catch (error) { - console.warn('Gemini 3 Pro API unavailable, falling back to next provider:', error); + console.warn( + 'Gemini 3 Pro API unavailable, falling back to next provider:', + error + ) } } + // AWS Bedrock + if (awsAccessKeyId && awsSecretAccessKey) { const bedrock = createAmazonBedrock({ bedrockOptions: { @@ -107,15 +81,16 @@ export async function getModel(requireVision: boolean = false) { secretAccessKey: awsSecretAccessKey, }, }, - }); + }) const model = bedrock(bedrockModelId, { additionalModelRequestFields: { top_k: 350 }, - }); - return model; + }) + return model } + // Default fallback (OpenAI gpt-4o supports vision) const openai = createOpenAI({ - apiKey: openaiApiKey, - }); - return openai('gpt-4o'); + apiKey: process.env.OPENAI_API_KEY, + }) + return openai('gpt-4o') } diff --git a/mapbox_mcp/hooks.ts b/mapbox_mcp/hooks.ts index 797f8852..ae317f51 100644 --- a/mapbox_mcp/hooks.ts +++ b/mapbox_mcp/hooks.ts @@ -128,7 +128,7 @@ export const useMCPMapClient = () => { setError(null); try { const response = await generateText({ - model: await getModel(), + model: getModel(), tools: toolsRef.current, system: `You are an expert location data processing engine. Your role is to accurately use the available tools to answer location-based queries and provide structured data. diff --git a/package.json b/package.json index a263674e..1564a383 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ "@supabase/ssr": "^0.3.0", "@supabase/supabase-js": "^2.0.0", "@tailwindcss/typography": "^0.5.16", - "@tavily/core": "^0.6.4", "@turf/turf": "^7.2.0", "@types/mapbox__mapbox-gl-draw": "^1.4.8", "@types/pg": "^8.15.4", diff --git a/reasoning-ui-explanation.md b/reasoning-ui-explanation.md new file mode 100644 index 00000000..dc399f82 --- /dev/null +++ b/reasoning-ui-explanation.md @@ -0,0 +1,27 @@ +## Reasoning UI Explanation + +The reasoning UI is a powerful feature that provides real-time insight into the AI's thinking process. It is built on top of the Vercel AI SDK's streaming capabilities, and it can be easily repurposed to display any kind of streaming data. + +### How it Works + +The reasoning UI is generated through a series of steps: + +1. **Streamable Values:** When a user submits a query, the `submit` function in `app/actions.tsx` creates two `StreamableValue` objects: `reasoningStream` and `actionsStream`. These objects are essentially real-time data streams that can be updated from the server. + +2. **UI Stream Update:** The `submit` function then immediately updates the `uiStream` with the `ReasoningDisplay` component. This component is passed the `reasoningStream` and `actionsStream` as props, and it uses the `useStreamableValue` hook to listen for updates to these streams. + +3. **Agent Logic:** The `researcher` agent in `lib/agents/researcher.tsx` is responsible for processing the AI's output. As the agent receives reasoning tokens and tool calls from the AI, it updates the `reasoningStream` and `actionsStream` with the new data. + +4. **Real-time Rendering:** The `ReasoningDisplay` component automatically re-renders whenever the `reasoningStream` or `actionsStream` are updated, which creates the real-time streaming effect. + +### Repurposing the Reasoning UI + +The reasoning UI can be easily repurposed to display any kind of streaming data. To do this, you would need to: + +1. **Create a new `StreamableValue`:** In the `submit` function, create a new `StreamableValue` for your data. + +2. **Update the `uiStream`:** Update the `uiStream` with a new component that is passed your new `StreamableValue` as a prop. + +3. **Update the agent logic:** In the `researcher` agent, update your new `StreamableValue` with your data. + +By following this pattern, you can create any number of real-time streaming components in your application. diff --git a/tailwind.config.ts b/tailwind.config.ts index 18c0491c..68c971ee 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -75,7 +75,6 @@ const config = { }, fontFamily: { sans: ["var(--font-sans)", ...fontFamily.sans], - poppins: ["var(--font-poppins)", ...fontFamily.sans], }, }, }, diff --git a/tests/map.spec.ts b/tests/map.spec.ts index 5d6aa972..595c4939 100644 --- a/tests/map.spec.ts +++ b/tests/map.spec.ts @@ -3,17 +3,11 @@ import { test, expect } from '@playwright/test'; test.describe('Map functionality', () => { test.beforeEach(async ({ page }) => { await page.goto('/'); - // Wait for either the Mapbox or Google Map to be loaded - await page.waitForSelector('.mapboxgl-canvas, gmp-map-3d'); + // Wait for the map to be loaded + await page.waitForSelector('.mapboxgl-canvas'); }); test('should toggle the map mode', async ({ page }) => { - const isMapbox = await page.locator('.mapboxgl-canvas').isVisible(); - if (!isMapbox) { - test.skip(true, 'Drawing mode test is only for Mapbox'); - return; - } - await page.click('[data-testid="map-toggle"]'); await page.click('[data-testid="map-mode-draw"]'); // Add an assertion here to verify that the map is in drawing mode @@ -23,34 +17,19 @@ test.describe('Map functionality', () => { }); test('should zoom in and out using map controls', async ({ page }) => { - // This test should only run on desktop where the controls are visible - if (page.viewportSize()!.width <= 768) { - test.skip(true, 'Zoom controls are not visible on mobile'); - return; - } - - const isMapbox = await page.locator('.mapboxgl-canvas').isVisible(); - if (!isMapbox) { - test.skip(true, 'Zoom controls test is only for Mapbox'); - return; - } - const hasMap = await page.evaluate(() => Boolean((window as any).map)); if (!hasMap) test.skip(true, 'Map instance not available on window for E2E'); const getZoom = () => page.evaluate(() => (window as any).map.getZoom()); const initialZoom = await getZoom(); - await page.click('.mapboxgl-ctrl-zoom-in'); - await page.evaluate(() => new Promise(res => (window as any).map.once('zoomend', res))); - + await page.waitForFunction(() => (window as any).map.getZoom() > initialZoom); const zoomedInZoom = await getZoom(); expect(zoomedInZoom).toBeGreaterThan(initialZoom); await page.click('.mapboxgl-ctrl-zoom-out'); - await page.evaluate(() => new Promise(res => (window as any).map.once('zoomend', res))); - + await page.waitForFunction(() => (window as any).map.getZoom() < zoomedInZoom); const zoomedOutZoom = await getZoom(); expect(zoomedOutZoom).toBeLessThan(zoomedInZoom); }); diff --git a/tests/mobile.spec.ts b/tests/mobile.spec.ts index d138f4f6..d506f16e 100644 --- a/tests/mobile.spec.ts +++ b/tests/mobile.spec.ts @@ -5,17 +5,23 @@ test.describe('Mobile UI', () => { test.beforeEach(async ({ page }) => { await page.goto('/'); - // Wait for the main chat input to be visible, indicating the app is ready - await page.locator('[data-testid="chat-input"]').waitFor({ state: 'visible', timeout: 30000 }); }); - test('profile toggle button should be disabled', async ({ page }) => { - // Check that the profile toggle is disabled on mobile - await expect(page.locator('.mobile-icons-bar-content [data-testid="profile-toggle"]')).toBeDisabled(); + test('should interact with the mobile icons bar', async ({ page }) => { + // Test a few buttons on the mobile icons bar + await page.click('[data-testid="mobile-new-chat-button"]'); + // Add an assertion to verify the action, e.g., the chat is cleared + const userMessage = page.locator('div.items-end'); + await expect(userMessage).not.toBeVisible(); + + await page.click('[data-testid="profile-toggle"]'); + // Add an assertion to verify the profile menu opens + const accountMenu = page.locator('[data-testid="profile-account"]'); + await expect(accountMenu).toBeVisible(); }); - test('should have an enabled submit button', async ({ page }) => { + test('should have a disabled submit button', async ({ page }) => { const submitButton = page.locator('[data-testid="mobile-submit-button"]'); - await expect(submitButton).toBeEnabled(); + await expect(submitButton).toBeDisabled(); }); });