Skip to content

Commit 257239a

Browse files
authored
Merge pull request #46 from OpenSourceAGI/claude/missing-next-static-ai-2co90r
Fix API routing and authentication issues in web app
2 parents 2fe2a38 + 130c468 commit 257239a

6 files changed

Lines changed: 50 additions & 20 deletions

File tree

β€Žapps/qwksearch-web/components/ResearchAgent/components/FileUpload/FileUploadDropdown.tsxβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ const FileUploadDropdown: React.FC<FileUploadDropdownProps> = ({
8686

8787
const checkGoogleDriveConnection = async () => {
8888
try {
89-
const data = await grab('doc/google-docs/auth/status');
89+
const data = await grab('/api/doc/google-docs/auth/status');
9090
setIsGoogleDriveConnected(data.isConnected || false);
9191
} catch {
9292
// silently ignore

β€Žapps/qwksearch-web/components/ResearchAgent/components/FileUpload/useFileHandling.tsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export function useFileHandling({
7878
const formData = new FormData();
7979
uploadable.forEach((f) => formData.append("files", f.file));
8080

81-
const data: { files: ChatFile[] } = await grab("/doc/uploads", {
81+
const data: { files: ChatFile[] } = await grab("/api/doc/uploads", {
8282
method: "POST",
8383
body: formData,
8484
});

β€Žapps/qwksearch-web/lib/api/grab.tsβ€Ž

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@
66
* Replaces grab-url with native fetch for better compatibility.
77
*/
88

9+
/**
10+
* Resolves bare relative paths against the API root. The original grab-url
11+
* package resolved every path against a configured `/api/` base, and call
12+
* sites throughout the app still pass paths like `"config"` or
13+
* `"doc/article"` β€” resolving those against the current page URL would hit
14+
* nonexistent routes (e.g. `/doc/article` instead of `/api/doc/article`).
15+
* Absolute URLs and root-relative (`/...`) paths pass through unchanged.
16+
*/
17+
function resolveApiUrl(url: string): string {
18+
if (/^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith("/")) {
19+
return url;
20+
}
21+
return url.startsWith("api/") ? `/${url}` : `/api/${url}`;
22+
}
23+
924
/**
1025
* Enhanced fetch function that includes credentials by default.
1126
* This ensures authentication cookies are sent with API requests.
@@ -34,7 +49,7 @@ export default async function grab(
3449
delete (enhancedOptions as any).timeout;
3550
delete (enhancedOptions as any).responseType;
3651

37-
const response = await fetch(url, enhancedOptions);
52+
const response = await fetch(resolveApiUrl(url), enhancedOptions);
3853
clearTimeout(timeoutId);
3954

4055
if (!response.ok) {

β€Žapps/qwksearch-web/lib/auth/index.tsβ€Ž

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ async function authBuilder() {
5151
},
5252
{
5353
baseURL: NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
54+
// better-auth rejects credentialed POSTs (e.g. /sign-in/social) with
55+
// 403 INVALID_ORIGIN when the Origin header isn't in trustedOrigins,
56+
// which defaults to only [baseURL]. baseURL follows the
57+
// NEXT_PUBLIC_BASE_URL env var, so a stale/localhost value on the
58+
// deployed Worker silently locks every user out of login. Trust the
59+
// production domains and local dev origins explicitly.
60+
trustedOrigins: [
61+
...(NEXT_PUBLIC_BASE_URL ? [NEXT_PUBLIC_BASE_URL] : []),
62+
"https://qwksearch.com",
63+
"https://www.qwksearch.com",
64+
"http://localhost:3000",
65+
"http://localhost:8787",
66+
],
5467
database: drizzleAdapter(getDB(), {
5568
provider: "sqlite",
5669
schema,

β€Žapps/qwksearch-web/vite.config.tsβ€Ž

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,15 @@ export default defineConfig(({ command }) => ({
4343
},
4444
rolldownOptions: {
4545
// Rolldown (Vite 8.x bundler) needs its own external list.
46-
// AI SDK packages are server-only and must not be bundled into client code.
47-
external: [
48-
"fsevents",
49-
"@mastra/core",
50-
"@mastra/mcp",
51-
"@composio/core",
52-
"ai",
53-
"@ai-sdk/openai",
54-
"@ai-sdk/anthropic",
55-
"@ai-sdk/groq",
56-
"@ai-sdk/google",
57-
"@ai-sdk/google-vertex",
58-
"@ai-sdk/xai",
59-
"@ai-sdk/amazon-bedrock",
60-
"@openrouter/ai-sdk-provider",
61-
],
46+
//
47+
// Do NOT add `ai` / `@ai-sdk/*` here: this list applies to the server
48+
// (rsc/ssr) environments too, and an externalized bare import in a
49+
// Worker chunk fails at runtime with
50+
// No such module "_next/static/ai" imported from "_next/static/route-*.js"
51+
// because workerd resolves bare specifiers relative to the chunk. The
52+
// AI SDK packages never reach the final client bundle anyway (they are
53+
// tree-shaken out), so they must simply be bundled server-side.
54+
external: ["fsevents", "@mastra/core", "@mastra/mcp", "@composio/core"],
6255
},
6356
},
6457
ssr: {

β€Žpackages/extract-webpage/src/suggest-next-words/autocomplete-search-engines.tsβ€Ž

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
import { parseHTML } from "linkedom";
66

7+
// Some suggest APIs (notably Google) return 403 Forbidden for requests
8+
// without a browser-like User-Agent, especially from datacenter/Cloudflare
9+
// egress IPs. Sent by default; per-backend headers can still override it.
10+
const DEFAULT_USER_AGENT =
11+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
12+
713
/**
814
* Fetch wrapper compatible with grab-url interface
915
*/
@@ -15,7 +21,10 @@ async function grab(url: string, options: any = {}): Promise<any> {
1521
try {
1622
const response = await fetch(url, {
1723
...options,
18-
headers: options.headers,
24+
headers: {
25+
"User-Agent": DEFAULT_USER_AGENT,
26+
...options.headers,
27+
},
1928
signal: controller.signal,
2029
});
2130

0 commit comments

Comments
Β (0)