Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@
"@upstash/redis": "^1.35.0",
"@vercel/analytics": "^1.5.0",
"@vercel/speed-insights": "^1.2.0",
"QCX": ".",
"ai": "^4.3.19",
"build": "^0.1.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cookie": "^0.6.0",
"dotenv": "^16.5.0",
"dotenv": "^17.2.3",
"drizzle-kit": "^0.31.1",
"drizzle-orm": "^0.29.0",
"embla-carousel-react": "^8.6.0",
Expand Down Expand Up @@ -428,6 +427,8 @@

"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],

"@playwright/test": ["@playwright/test@1.56.1", "", { "dependencies": { "playwright": "1.56.1" }, "bin": { "playwright": "cli.js" } }, "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg=="],

"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],

"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
Expand Down Expand Up @@ -1032,8 +1033,6 @@

"@vercel/speed-insights": ["@vercel/speed-insights@1.2.0", "", { "peerDependencies": { "@sveltejs/kit": "^1 || ^2", "next": ">= 13", "react": "^18 || ^19 || ^19.0.0-rc", "svelte": ">= 4", "vue": "^3", "vue-router": "^4" }, "optionalPeers": ["@sveltejs/kit", "next", "react", "svelte", "vue", "vue-router"] }, "sha512-y9GVzrUJ2xmgtQlzFP2KhVRoCglwfRQgjyfY607aU0hh0Un6d0OUyrJkjuAlsV18qR4zfoFPs/BiIj9YDS6Wzw=="],

"QCX": ["QCX@file:", { "dependencies": { "@ai-sdk/amazon-bedrock": "^1.1.6", "@ai-sdk/anthropic": "^1.2.12", "@ai-sdk/google": "^1.2.22", "@ai-sdk/openai": "^1.3.24", "@ai-sdk/xai": "^1.2.18", "@heroicons/react": "^2.2.0", "@hookform/resolvers": "^5.0.1", "@mapbox/mapbox-gl-draw": "^1.5.0", "@modelcontextprotocol/sdk": "^1.13.0", "@radix-ui/react-alert-dialog": "^1.1.10", "@radix-ui/react-avatar": "^1.1.6", "@radix-ui/react-checkbox": "^1.2.2", "@radix-ui/react-collapsible": "^1.1.7", "@radix-ui/react-dialog": "^1.1.10", "@radix-ui/react-dropdown-menu": "^2.1.11", "@radix-ui/react-label": "^2.1.4", "@radix-ui/react-radio-group": "^1.3.4", "@radix-ui/react-separator": "^1.1.4", "@radix-ui/react-slider": "^1.3.2", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-switch": "^1.2.2", "@radix-ui/react-tabs": "^1.1.9", "@radix-ui/react-toast": "^1.2.11", "@radix-ui/react-tooltip": "^1.2.3", "@smithery/cli": "^1.2.5", "@smithery/sdk": "^1.0.4", "@supabase/ssr": "^0.3.0", "@supabase/supabase-js": "^2.0.0", "@tailwindcss/typography": "^0.5.16", "@turf/turf": "^7.2.0", "@types/mapbox__mapbox-gl-draw": "^1.4.8", "@types/pg": "^8.15.4", "@upstash/redis": "^1.35.0", "@vercel/analytics": "^1.5.0", "@vercel/speed-insights": "^1.2.0", "QCX": ".", "ai": "^4.3.19", "build": "^0.1.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cookie": "^0.6.0", "dotenv": "^16.5.0", "drizzle-kit": "^0.31.1", "drizzle-orm": "^0.29.0", "embla-carousel-react": "^8.6.0", "exa-js": "^1.6.13", "framer-motion": "^12.15.0", "katex": "^0.16.22", "lottie-react": "^2.4.1", "lucide-react": "^0.507.0", "mapbox-gl": "^3.11.0", "next": "^15.3.3", "next-themes": "^0.3.0", "open-codex": "^0.1.30", "pg": "^8.16.2", "radix-ui": "^1.3.4", "react": "^19.1.0", "react-dom": "^19.1.0", "react-hook-form": "^7.56.2", "react-icons": "^5.5.0", "react-markdown": "^9.1.0", "react-textarea-autosize": "^8.5.9", "react-toastify": "^10.0.6", "rehype-external-links": "^3.0.0", "rehype-katex": "^7.0.1", "remark-gfm": "^4.0.1", "remark-math": "^6.0.0", "smithery": "^0.5.2", "sonner": "^1.7.4", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", "use-mcp": "^0.0.9", "uuid": "^9.0.0", "zod": "^3.23.8" }, "devDependencies": { "@types/cookie": "^0.6.0", "@types/mapbox-gl": "^3.4.1", "@types/node": "^20.17.30", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "@types/uuid": "^9.0.0", "cross-env": "^7.0.3", "eslint": "^8.57.1", "eslint-config-next": "^14.2.28", "postcss": "^8.5.3", "tailwindcss": "^3.4.17", "typescript": "^5.8.3" } }],

"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],

"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
Expand Down Expand Up @@ -1294,7 +1293,7 @@

"doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="],

"dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
"dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],

"drizzle-kit": ["drizzle-kit@0.31.5", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-+CHgPFzuoTQTt7cOYCV6MOw2w8vqEn/ap1yv4bpZOWL03u7rlVRQhUY0WYT3rHsgVTXwYQDZaSUJSQrMBUKuWg=="],

Expand Down Expand Up @@ -2012,6 +2011,10 @@

"pkce-challenge": ["pkce-challenge@5.0.0", "", {}, "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ=="],

"playwright": ["playwright@1.56.1", "", { "dependencies": { "playwright-core": "1.56.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw=="],

"playwright-core": ["playwright-core@1.56.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ=="],

"point-in-polygon": ["point-in-polygon@1.1.0", "", {}, "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw=="],

"point-in-polygon-hao": ["point-in-polygon-hao@1.2.4", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ=="],
Expand Down Expand Up @@ -2568,8 +2571,6 @@

"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],

"QCX/QCX": ["QCX@file:.", {}],

"ai/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="],

"ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="],
Expand Down Expand Up @@ -2684,6 +2685,8 @@

"open-codex/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],

"open-codex/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],

"open-codex/openai": ["openai@4.104.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" }, "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA=="],

"open-codex/react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="],
Expand All @@ -2698,6 +2701,8 @@

"parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="],

"playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],

"point-in-polygon-hao/robust-predicates": ["robust-predicates@3.0.2", "", {}, "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="],

"rbush/quickselect": ["quickselect@2.0.0", "", {}, "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="],
Expand Down
2 changes: 1 addition & 1 deletion components/search-results-image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const SearchResultsImageSection: React.FC<
}, [api, selectedIndex])

if (!images || images.length === 0) {
return <div className="text-muted-foreground">No images found</div>
return null
}

return (
Expand Down
3 changes: 2 additions & 1 deletion components/search-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export type SearchSectionProps = {

export function SearchSection({ result }: SearchSectionProps) {
const [data, error, pending] = useStreamableValue(result)
const searchResults: TypeSearchResults = data ? JSON.parse(data) : undefined
const searchResults: TypeSearchResults =
data && typeof data === 'string' ? JSON.parse(data) : undefined
Comment on lines +17 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a typeof data === 'string' check is a step in the right direction, but it still leaves JSON.parse unguarded. If the stream yields malformed JSON, this will throw and crash the component during render. Also, since the render condition later checks !pending && data, you could still attempt to read searchResults.query when searchResults is undefined (e.g., if the data was a non-empty string that failed to parse). You should wrap parsing in a try/catch and gate rendering on searchResults rather than data. This aligns with the PR goal of robust, crash-resistant parsing.

Suggestion

Consider safely parsing and gating rendering on searchResults:

  • Wrap JSON.parse in a try/catch and ignore malformed payloads.
  • Gate render on searchResults rather than data to avoid accessing properties on undefined.

Example:

let searchResults: TypeSearchResults | undefined
if (typeof data === 'string' && data.trim()) {
  try {
    searchResults = JSON.parse(data)
  } catch {
    searchResults = undefined
  }
}

return (
  <div>
    {!pending && searchResults ? (
      <>
        <Section size="sm" className="pt-2 pb-0">
          <ToolBadge tool="search">{searchResults.query}</ToolBadge>
        </Section>
        {searchResults.images && searchResults.images.length > 0 && (
          <Section title="Images">
            <SearchResultsImageSection images={searchResults.images} />
          </Section>
        )}
      </>
    ) : null}
  </div>
)

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion

return (
<div>
{!pending && data ? (
Expand Down
1 change: 1 addition & 0 deletions dev.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ next dev --turbo

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A dev.log file with a next dev command appears to have been committed. This looks like a local development artifact and should not be tracked. Keeping it in the repo risks noise and accidental conflicts.

Suggestion

Remove dev.log from version control and add it to .gitignore to prevent future commits. For example, add this to .gitignore:

# Local logs
*.log
/dev.log

I can push a commit that deletes the file and updates .gitignore. Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cookie": "^0.6.0",
"dotenv": "^16.5.0",
"dotenv": "^17.2.3",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raising dotenv from ^16.5.0 to ^17.2.3 is a major version bump and may introduce breaking changes (load semantics, Node.js version support, or import patterns). Please verify project-wide usage (e.g., require('dotenv').config() vs import 'dotenv/config') and consult the release notes to ensure no initialization or runtime behavior is affected.

"drizzle-kit": "^0.31.1",
"drizzle-orm": "^0.29.0",
"embla-carousel-react": "^8.6.0",
Expand Down