research-agent-ui 0.1.293 → 0.1.295
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -1
- package/dist/ArticleExtractPanel-BPNXuezE.js +389 -0
- package/dist/ArticleExtractPanel-DAPLUpyx.cjs +2 -0
- package/dist/ChatConversationThread-D1RR0Bcx.cjs +17 -0
- package/dist/ChatConversationThread-DMPdu2sr.js +1428 -0
- package/dist/DownloadsDialog-CCPj0hA8.cjs +1 -0
- package/dist/{DownloadsDialog-bTEDe2DI.js → DownloadsDialog-DvS23Dh-.js} +8 -9
- package/dist/api/handlers/autocomplete.d.ts +6 -9
- package/dist/api/handlers/openai-transcription.d.ts +53 -0
- package/dist/api/handlers/transcript.d.ts +33 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api.cjs +10 -10
- package/dist/api.mjs +373 -182
- package/dist/app/index.d.ts +1 -1
- package/dist/app/useChunkErrorReload.d.ts +13 -2
- package/dist/components/ArticleReader/ArticleReaderMount.d.ts +5 -0
- package/dist/components/ArticleReader/ExtractPanelContext.d.ts +17 -1
- package/dist/components/ChatConversation/MessageBubble/AssistantMessageActions.d.ts +2 -1
- package/dist/components/ChatConversation/background-art.d.ts +3 -1
- package/dist/components/ChatConversation/background-cache.d.ts +41 -0
- package/dist/components/Footer.d.ts +5 -4
- package/dist/components/Footer.stories.d.ts +3 -3
- package/dist/config.cjs +1 -1
- package/dist/config.d.ts +9 -0
- package/dist/config.mjs +4 -3
- package/dist/dialog-7GDz0sWx.cjs +1 -0
- package/dist/dialog-Cufn2u50.js +80 -0
- package/dist/hooks/voice/useKokoroTTS.d.ts +2 -0
- package/dist/hooks/voice/useTextToVoice.d.ts +2 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.mjs +4 -2
- package/dist/lib/file-sources.d.ts +8 -0
- package/dist/lib/google-drive-source.d.ts +100 -0
- package/dist/lib/kokoro.d.ts +14 -2
- package/dist/lib/qwksearch-connect.d.ts +79 -0
- package/dist/settings/index.d.ts +15 -0
- package/dist/src-BqV2Vwpv.js +6375 -0
- package/dist/src-Ckb1ciEL.cjs +34 -0
- package/dist/tooltip-Bl3IdX-I.js +179 -0
- package/dist/tooltip-DmUO6ZUz.cjs +1 -0
- package/dist/types/fileSource.d.ts +9 -0
- package/dist/workspace/QwkSearchWorkspaceApp.d.ts +9 -2
- package/dist/workspace/ResearchWorkspaceView.d.ts +18 -4
- package/dist/workspace.cjs +1 -1
- package/dist/workspace.d.ts +1 -1
- package/dist/workspace.mjs +234 -91
- package/package.json +53 -50
- package/src/app/useChunkErrorReload.ts +92 -0
- package/src/settings/index.ts +23 -0
- package/src/settings/search.json +19 -1
- package/dist/DownloadsDialog-Ca6aRRcP.cjs +0 -1
- package/dist/src-HL9JjPc-.js +0 -8218
- package/dist/src-r4BsCIB4.cjs +0 -51
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require("./dialog-7GDz0sWx.cjs"),t=require("./config.cjs");let n=require("react/jsx-runtime"),r=require("react-native-app-buttons");function i({open:i,onOpenChange:a}){return(0,n.jsx)(e.t,{open:i,onOpenChange:a,children:(0,n.jsxs)(e.n,{className:`w-full max-w-md rounded-2xl bg-light-secondary dark:bg-dark-secondary border border-light-200 dark:border-dark-200 p-6 text-center align-middle shadow-xl`,children:[(0,n.jsx)(e.i,{className:`text-lg font-medium leading-6 dark:text-white`,children:`Download QwkSearch`}),(0,n.jsx)(e.r,{className:`text-sm dark:text-white/70 text-black/70 mt-2`,children:`Get QwkSearch on your browser or desktop.`}),(0,n.jsxs)(`div`,{className:`flex flex-wrap items-center justify-center gap-3 mt-6`,children:[(0,n.jsx)(r.DownloadAppButton,{platform:`chrome-extension`,href:t.researchAgentUIConfig.downloadChromeUrl,autoHighlight:!0}),(0,n.jsx)(r.DownloadAppButton,{platform:`windows`,appId:t.researchAgentUIConfig.downloadWindowsStoreId,autoHighlight:!0})]})]})})}exports.default=i;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { i as e, n as t, r as n, t as r } from "./dialog-Cufn2u50.js";
|
|
2
|
+
import { researchAgentUIConfig as i } from "./config.mjs";
|
|
3
3
|
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
4
4
|
import { DownloadAppButton as s } from "react-native-app-buttons";
|
|
5
|
-
|
|
5
|
+
// src/components/ChatConversation/DownloadsDialog.tsx
|
|
6
6
|
function c({ open: c, onOpenChange: l }) {
|
|
7
|
-
return /* @__PURE__ */ a(
|
|
7
|
+
return /* @__PURE__ */ a(r, {
|
|
8
8
|
open: c,
|
|
9
9
|
onOpenChange: l,
|
|
10
10
|
children: /* @__PURE__ */ o(t, {
|
|
11
11
|
className: "w-full max-w-md rounded-2xl bg-light-secondary dark:bg-dark-secondary border border-light-200 dark:border-dark-200 p-6 text-center align-middle shadow-xl",
|
|
12
12
|
children: [
|
|
13
|
-
/* @__PURE__ */ a(
|
|
13
|
+
/* @__PURE__ */ a(e, {
|
|
14
14
|
className: "text-lg font-medium leading-6 dark:text-white",
|
|
15
15
|
children: "Download QwkSearch"
|
|
16
16
|
}),
|
|
17
|
-
/* @__PURE__ */ a(
|
|
17
|
+
/* @__PURE__ */ a(n, {
|
|
18
18
|
className: "text-sm dark:text-white/70 text-black/70 mt-2",
|
|
19
19
|
children: "Get QwkSearch on your browser or desktop."
|
|
20
20
|
}),
|
|
@@ -22,11 +22,11 @@ function c({ open: c, onOpenChange: l }) {
|
|
|
22
22
|
className: "flex flex-wrap items-center justify-center gap-3 mt-6",
|
|
23
23
|
children: [/* @__PURE__ */ a(s, {
|
|
24
24
|
platform: "chrome-extension",
|
|
25
|
-
href:
|
|
25
|
+
href: i.downloadChromeUrl,
|
|
26
26
|
autoHighlight: !0
|
|
27
27
|
}), /* @__PURE__ */ a(s, {
|
|
28
28
|
platform: "windows",
|
|
29
|
-
appId:
|
|
29
|
+
appId: i.downloadWindowsStoreId,
|
|
30
30
|
autoHighlight: !0
|
|
31
31
|
})]
|
|
32
32
|
})
|
|
@@ -34,5 +34,4 @@ function c({ open: c, onOpenChange: l }) {
|
|
|
34
34
|
})
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
//#endregion
|
|
38
37
|
export { c as default };
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
export declare function createAutocompleteHandler(): {
|
|
8
|
-
GET: (req: Request) => Promise<Response>;
|
|
9
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Search-box autocomplete now lives in the `search-autocomplete`
|
|
3
|
+
* package; re-exported so `research-agent-ui/api` keeps its public surface.
|
|
4
|
+
*/
|
|
5
|
+
export { createAutocompleteHandler, type AutocompleteHandlerOptions, } from "search-autocomplete/server";
|
|
6
|
+
export type { DomainSuggestion } from "search-autocomplete";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview OpenAI-compatible speech-to-text adapter: `GET /v1/models` and
|
|
3
|
+
* `POST /v1/audio/transcriptions`, the two endpoints a client configured with
|
|
4
|
+
* an OpenAI-style "base URL + API key" (Kilo, for one) calls.
|
|
5
|
+
*
|
|
6
|
+
* This is a thin shape adapter around `transcribeAudio` — the same function
|
|
7
|
+
* `/api/agent/transcript` runs — so both routes use one tier → Whisper model
|
|
8
|
+
* mapping and one Workers AI call. What differs is the contract:
|
|
9
|
+
*
|
|
10
|
+
* - the caller must be authorized (the host decides how; see `authorize`),
|
|
11
|
+
* - the tier is validated instead of silently falling back,
|
|
12
|
+
* - only `response_format` `json` (or none) is accepted,
|
|
13
|
+
* - the body is `{ text }` and errors use OpenAI's `{ error: { message, … } }`.
|
|
14
|
+
*
|
|
15
|
+
* Nothing here logs the audio or the transcript.
|
|
16
|
+
*/
|
|
17
|
+
import type { TranscriptDeps } from "../types";
|
|
18
|
+
export type OpenAIAuthResult = {
|
|
19
|
+
authorized: true;
|
|
20
|
+
} | {
|
|
21
|
+
authorized: false;
|
|
22
|
+
status?: number;
|
|
23
|
+
message: string;
|
|
24
|
+
};
|
|
25
|
+
export interface OpenAITranscriptionDeps extends TranscriptDeps {
|
|
26
|
+
/**
|
|
27
|
+
* Decides whether the request may use the API — e.g. by validating an
|
|
28
|
+
* `Authorization: Bearer <key>` header. Runs before the body is read.
|
|
29
|
+
*/
|
|
30
|
+
authorize: (req: Request) => Promise<OpenAIAuthResult>;
|
|
31
|
+
}
|
|
32
|
+
/** The response formats this adapter can honour. */
|
|
33
|
+
export declare const SUPPORTED_RESPONSE_FORMATS: readonly ["json"];
|
|
34
|
+
type ErrorType = "invalid_request_error" | "authentication_error" | "server_error";
|
|
35
|
+
/** An error body in the shape OpenAI clients parse: `{ error: { message, type, param, code } }`. */
|
|
36
|
+
export declare function openAIError(status: number, message: string, type: ErrorType, param?: string | null, code?: string | null): Response;
|
|
37
|
+
/** The model list, in the OpenAI `GET /v1/models` shape. */
|
|
38
|
+
export declare function listTranscriptionModels(): {
|
|
39
|
+
object: "list";
|
|
40
|
+
data: {
|
|
41
|
+
id: "fast" | "large" | "medium" | "small" | "turbo";
|
|
42
|
+
object: "model";
|
|
43
|
+
created: number;
|
|
44
|
+
owned_by: string;
|
|
45
|
+
}[];
|
|
46
|
+
};
|
|
47
|
+
export declare function createOpenAIModelsHandler(deps: Pick<OpenAITranscriptionDeps, "authorize">): {
|
|
48
|
+
GET: (req: Request) => Promise<Response>;
|
|
49
|
+
};
|
|
50
|
+
export declare function createOpenAITranscriptionHandler(deps: OpenAITranscriptionDeps): {
|
|
51
|
+
POST: (req: Request) => Promise<Response>;
|
|
52
|
+
};
|
|
53
|
+
export {};
|
|
@@ -4,8 +4,41 @@
|
|
|
4
4
|
* Maps a requested quality tier ("small"/"medium"/"large"/etc.) to a
|
|
5
5
|
* specific Whisper model binding and requires the Cloudflare AI binding to
|
|
6
6
|
* be present (unavailable in local dev without CF bindings).
|
|
7
|
+
*
|
|
8
|
+
* The transcription itself is `transcribeAudio`, shared by this handler
|
|
9
|
+
* (`/api/agent/transcript`) and the OpenAI-compatible adapter in
|
|
10
|
+
* `./openai-transcription.ts` (`/api/v1/audio/transcriptions`), so the two
|
|
11
|
+
* routes cannot drift apart on which Whisper model a tier means.
|
|
7
12
|
*/
|
|
8
13
|
import type { TranscriptDeps } from "../types";
|
|
14
|
+
/** The quality tiers a caller may ask for, in the order they are listed. */
|
|
15
|
+
export declare const TRANSCRIPTION_MODELS: readonly ["small", "fast", "medium", "turbo", "large"];
|
|
16
|
+
export type TranscriptionModel = (typeof TRANSCRIPTION_MODELS)[number];
|
|
17
|
+
/** The tier used when a request names none. */
|
|
18
|
+
export declare const DEFAULT_TRANSCRIPTION_MODEL: TranscriptionModel;
|
|
19
|
+
export declare function isTranscriptionModel(value: unknown): value is TranscriptionModel;
|
|
20
|
+
/**
|
|
21
|
+
* The Workers AI model behind a tier. An unknown or missing tier falls back
|
|
22
|
+
* to turbo — `/api/agent/transcript` has always been lenient here; the
|
|
23
|
+
* OpenAI-compatible route validates the tier before it gets this far.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getWhisperModel(modelParam: string | null): string;
|
|
26
|
+
export type TranscribeResult = {
|
|
27
|
+
ok: true;
|
|
28
|
+
text: string;
|
|
29
|
+
model: string;
|
|
30
|
+
} | {
|
|
31
|
+
ok: false;
|
|
32
|
+
reason: "ai_unavailable";
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Transcribes `file` with the Whisper model for `modelParam`.
|
|
36
|
+
*
|
|
37
|
+
* Resolves `{ ok: false }` when the Cloudflare AI binding is missing (local
|
|
38
|
+
* dev); a failure inside Workers AI is thrown for the caller to map to a 500.
|
|
39
|
+
* Logs nothing: neither the audio nor the transcript belongs in a log line.
|
|
40
|
+
*/
|
|
41
|
+
export declare function transcribeAudio(deps: TranscriptDeps, file: Blob, modelParam: string | null): Promise<TranscribeResult>;
|
|
9
42
|
export declare function createTranscriptHandler(deps: TranscriptDeps): {
|
|
10
43
|
POST: (req: Request) => Promise<Response>;
|
|
11
44
|
};
|
package/dist/api/index.d.ts
CHANGED
|
@@ -18,5 +18,6 @@ export * from "./handlers/agents";
|
|
|
18
18
|
export * from "./handlers/rewrite";
|
|
19
19
|
export * from "./handlers/voice";
|
|
20
20
|
export * from "./handlers/transcript";
|
|
21
|
+
export * from "./handlers/openai-transcription";
|
|
21
22
|
export * from "./handlers/test-models";
|
|
22
23
|
export * from "./handlers/validate-openrouter";
|
package/dist/api.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-BocRIvOZ.cjs");let t=require("ai"),n=require("chat-agent-toolkit/models/registry");n=e.t(n,1);let r=require("drizzle-orm"),i=require("chat-agent-toolkit/tools/search/titleGeneratorAgent");i=e.t(i,1);let a=require("search-web-api/search/public-searxng"),o=require("
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-BocRIvOZ.cjs");let t=require("ai"),n=require("chat-agent-toolkit/models/registry");n=e.t(n,1);let r=require("drizzle-orm"),i=require("chat-agent-toolkit/tools/search/titleGeneratorAgent");i=e.t(i,1);let a=require("search-web-api/search/public-searxng"),o=require("fuse.js");o=e.t(o,1);let s=require("tldts"),c=require("domain-rank/data/domain-rank-merged.json");c=e.t(c,1);let l=require("chat-agent-toolkit/tools/search/suggestionGeneratorAgent");l=e.t(l,1);let u=require("chat-agent-toolkit/config/model-tester"),d=require("chat-agent-toolkit/config/language-models-database");function f(e){return async e=>{try{let{article:r,chatHistory:i=[],maxQuestions:a=5,chatModel:o}=await e.json();if(!r)return Response.json({error:`Article is required`},{status:400});let s=new n.default,c;try{c=await s.loadChatModel(o?.providerId,o?.key)}catch(e){return Response.json({error:e instanceof Error?e.message:`Failed to load language model`},{status:500})}let l=i.length>0?`\n\nPrevious questions asked:\n${i.filter(e=>e.role===`user`).map(e=>`- ${e.content}`).join(`
|
|
2
2
|
`)}`:``,u=`You are a helpful AI that generates insightful follow-up questions about articles.
|
|
3
3
|
Generate ${a} thought-provoking questions that would help readers understand the article better.
|
|
4
4
|
Return ONLY the questions, one per line, without numbering or bullet points.`,d=`Article content:
|
|
@@ -6,24 +6,24 @@ ${r.slice(0,15e3)}
|
|
|
6
6
|
|
|
7
7
|
${l}
|
|
8
8
|
|
|
9
|
-
Generate ${a} follow-up questions that would help readers dive deeper into this article.`,{text:f}=await(0,t.generateText)({model:c,
|
|
10
|
-
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>e.replace(/^[\d\-\*\.\)]+\s*/,``).trim()).filter(e=>e.length>10).slice(0,a);return Response.json({extract:p,success:!0})}catch(e){return console.error(`Error generating follow-up questions:`,e),Response.json({error:`An error occurred while generating follow-up questions`,details:e instanceof Error?e.message:String(e)},{status:500})}}}function
|
|
9
|
+
Generate ${a} follow-up questions that would help readers dive deeper into this article.`,{text:f}=await(0,t.generateText)({model:c,instructions:u,prompt:d}),p=f.split(`
|
|
10
|
+
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>e.replace(/^[\d\-\*\.\)]+\s*/,``).trim()).filter(e=>e.length>10).slice(0,a);return Response.json({extract:p,success:!0})}catch(e){return console.error(`Error generating follow-up questions:`,e),Response.json({error:`An error occurred while generating follow-up questions`,details:e instanceof Error?e.message:String(e)},{status:500})}}}function p(e){return async e=>{try{let{title:r=``,content:i,maxTips:a=4,chatModel:o}=await e.json();if(!i)return Response.json({error:`Content is required`},{status:400});let s=new n.default,c;try{c=await s.loadChatModel(o?.providerId,o?.key)}catch(e){return Response.json({error:e instanceof Error?e.message:`Failed to load language model`},{status:500})}let l=`You are a helpful AI that surfaces short, useful tips about a page the reader currently has open.
|
|
11
11
|
Generate ${a} concise tips (each a single sentence) highlighting the most useful takeaways or things worth noticing on the page.
|
|
12
12
|
Return ONLY the tips, one per line, without numbering or bullet points.`,u=`Page title: ${r}
|
|
13
13
|
|
|
14
14
|
Page content:
|
|
15
15
|
${i.slice(0,15e3)}
|
|
16
16
|
|
|
17
|
-
Generate ${a} short tips about this page.`,{text:d}=await(0,t.generateText)({model:c,
|
|
18
|
-
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>e.replace(/^[\d\-\*\.\)]+\s*/,``).trim()).filter(e=>e.length>10).slice(0,a);return Response.json({tips:f,success:!0})}catch(e){return console.error(`Error generating page tips:`,e),Response.json({error:`An error occurred while generating page tips`,details:e instanceof Error?e.message:String(e)},{status:500})}}}function
|
|
17
|
+
Generate ${a} short tips about this page.`,{text:d}=await(0,t.generateText)({model:c,instructions:l,prompt:u}),f=d.split(`
|
|
18
|
+
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>e.replace(/^[\d\-\*\.\)]+\s*/,``).trim()).filter(e=>e.length>10).slice(0,a);return Response.json({tips:f,success:!0})}catch(e){return console.error(`Error generating page tips:`,e),Response.json({error:`An error occurred while generating page tips`,details:e instanceof Error?e.message:String(e)},{status:500})}}}function m(e){return async e=>{try{let{title:r=``,content:i,maxTopics:a=4,chatModel:o}=await e.json();if(!i)return Response.json({error:`Content is required`},{status:400});let s=new n.default,c;try{c=await s.loadChatModel(o?.providerId,o?.key)}catch(e){return Response.json({error:e instanceof Error?e.message:`Failed to load language model`},{status:500})}let l=`You are a helpful AI that suggests related searches for a reader based on a page they currently have open.
|
|
19
19
|
Generate ${a} short search queries (each a few words, phrased the way someone would type it into a search box) that dig deeper into topics related to the page.
|
|
20
20
|
Return ONLY the search queries, one per line, without numbering or bullet points.`,u=`Page title: ${r}
|
|
21
21
|
|
|
22
22
|
Page content:
|
|
23
23
|
${i.slice(0,15e3)}
|
|
24
24
|
|
|
25
|
-
Generate ${a} short related search queries for this page.`,{text:d}=await(0,t.generateText)({model:c,
|
|
26
|
-
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>e.replace(/^[\d\-\*\.\)]+\s*/,``).trim()).filter(e=>e.length>2).slice(0,a);return Response.json({topics:f,success:!0})}catch(e){return console.error(`Error generating topic searches:`,e),Response.json({error:`An error occurred while generating topic searches`,details:e instanceof Error?e.message:String(e)},{status:500})}}}function
|
|
25
|
+
Generate ${a} short related search queries for this page.`,{text:d}=await(0,t.generateText)({model:c,instructions:l,prompt:u}),f=d.split(`
|
|
26
|
+
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>e.replace(/^[\d\-\*\.\)]+\s*/,``).trim()).filter(e=>e.length>2).slice(0,a);return Response.json({topics:f,success:!0})}catch(e){return console.error(`Error generating topic searches:`,e),Response.json({error:`An error occurred while generating topic searches`,details:e instanceof Error?e.message:String(e)},{status:500})}}}function h(e){return async e=>{try{let{article:r,question:i,chatHistory:a=[],chatModel:o}=await e.json();if(!r||!i)return Response.json({error:`Article and question are required`},{status:400});let s=new n.default,c;try{c=await s.loadChatModel(o?.providerId,o?.key)}catch(e){return Response.json({error:e instanceof Error?e.message:`Failed to load language model`},{status:500})}let l=a.length>0?`\n\nPrevious conversation:\n${a.map(e=>`${e.role===`user`?`User`:`Assistant`}: ${e.content}`).join(`
|
|
27
27
|
`)}`:``,u=`Article content:
|
|
28
28
|
${r.slice(0,15e3)}
|
|
29
29
|
|
|
@@ -31,8 +31,8 @@ ${l}
|
|
|
31
31
|
|
|
32
32
|
User question: ${i}
|
|
33
33
|
|
|
34
|
-
Please provide a helpful answer based on the article content above.`,{text:d}=await(0,t.generateText)({model:c,
|
|
34
|
+
Please provide a helpful answer based on the article content above.`,{text:d}=await(0,t.generateText)({model:c,instructions:`You are a helpful AI assistant that answers questions about articles.
|
|
35
35
|
Provide clear, concise, and accurate answers based on the article content provided.
|
|
36
|
-
If the answer is not in the article, say so.`},{role:`user`,content:u}]});return Response.json({content:d,success:!0})}catch(e){return console.error(`Error in article Q&A:`,e),Response.json({error:`An error occurred while generating the answer`,details:e instanceof Error?e.message:String(e)},{status:500})}}}function _(e){let{chats:t,messages:n}=e.schema;return{GET:async i=>{try{let i=e.getDB(),a=await e.requireUserId(),o=await i.select({id:t.id,title:t.title,createdAt:t.createdAt,focusMode:t.focusMode,userId:t.userId,files:t.files,messageCount:(0,r.count)(n.id),lastMessageAt:(0,r.max)(n.createdAt)}).from(t).leftJoin(n,(0,r.and)((0,r.eq)(n.chatId,t.id),(0,r.eq)(n.role,`user`))).where((0,r.eq)(t.userId,a)).groupBy(t.id,t.title,t.createdAt,t.focusMode,t.userId,t.files).orderBy(r.sql`${t.createdAt} DESC`);return Response.json({chats:o},{status:200})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({message:`Authentication required`},{status:401}):(console.error(`Error in getting chats: `,e),Response.json({message:`An error has occurred.`},{status:500}))}},DELETE:async i=>{try{let i=e.getDB(),a=await e.requireUserId(),o=await i.query.chats.findMany({where:(0,r.eq)(t.userId,a),columns:{id:!0}});if(o.length>0){let e=o.map(e=>e.id);await i.delete(n).where((0,r.inArray)(n.chatId,e)),await i.delete(t).where((0,r.eq)(t.userId,a))}return Response.json({message:`All chats deleted`},{status:200})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({message:`Authentication required`},{status:401}):(console.error(`Error in deleting all chats: `,e),Response.json({message:`An error has occurred.`},{status:500}))}}}}function ee(e){let{chats:t,messages:n}=e.schema;return{GET:async(i,{params:a})=>{try{let i=e.getDB(),{id:o}=await a,s;try{s=await e.requireUserId()}catch{s=void 0}let c=await i.query.chats.findFirst({where:(0,r.eq)(t.id,o)});if(!c)return Response.json({message:`Chat not found`},{status:404});if(!(c.userId===s||c.isPublic))return Response.json({message:`Unauthorized - this chat is private`},{status:403});let l=await i.query.messages.findMany({where:(0,r.eq)(n.chatId,o)});return Response.json({chat:c,messages:l},{status:200})}catch(e){return console.error(`Error in getting chat by id: `,e),Response.json({message:`An error has occurred.`},{status:500})}},DELETE:async(i,{params:a})=>{try{let i=e.getDB(),{id:o}=await a,s=await e.requireUserId();return await i.query.chats.findFirst({where:(0,r.and)((0,r.eq)(t.id,o),(0,r.eq)(t.userId,s))})?(await i.delete(t).where((0,r.eq)(t.id,o)).execute(),await i.delete(n).where((0,r.eq)(n.chatId,o)).execute(),Response.json({message:`Chat deleted successfully`},{status:200})):Response.json({message:`Chat not found`},{status:404})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({message:`Authentication required`},{status:401}):(console.error(`Error in deleting chat by id: `,e),Response.json({message:`An error has occurred.`},{status:500}))}}}}function v(e){let{chats:t,messages:n}=e.schema;return{GET:async i=>{try{let a=e.getDB(),o=await e.requireUserId(),{searchParams:s}=new URL(i.url),c=s.get(`q`);if(!c||c.trim().length===0)return Response.json({chats:[]},{status:200});let l=`%${c.trim()}%`,u=await a.select({id:t.id,title:t.title,createdAt:t.createdAt,focusMode:t.focusMode,userId:t.userId,files:t.files}).from(t).where((0,r.and)((0,r.eq)(t.userId,o),(0,r.like)(t.title,l))).orderBy(r.sql`${t.createdAt} DESC`),d=await a.selectDistinct({id:t.id,title:t.title,createdAt:t.createdAt,focusMode:t.focusMode,userId:t.userId,files:t.files}).from(n).innerJoin(t,(0,r.eq)(n.chatId,t.id)).where((0,r.and)((0,r.eq)(t.userId,o),(0,r.or)((0,r.like)(n.content,l)))).orderBy(r.sql`${t.createdAt} DESC`),f=[...u,...d],p=Array.from(new Map(f.map(e=>[e.id,e])).values()),m=p.map(e=>e.id),h=m.length?await a.select({chatId:n.chatId,count:r.sql`count(*)`}).from(n).where((0,r.and)(r.sql`${n.chatId} IN (${r.sql.join(m.map(e=>r.sql`${e}`),r.sql`, `)})`,(0,r.eq)(n.role,`user`))).groupBy(n.chatId):[],g=new Map(h.map(e=>[e.chatId,Number(e.count)])),_=p.map(e=>({...e,messageCount:g.get(e.id)||0}));return Response.json({chats:_},{status:200})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({message:`Authentication required`},{status:401}):(console.error(`Error searching chats:`,e),Response.json({message:`An error has occurred.`},{status:500}))}}}}function te(e){let{chats:t}=e.schema;return{POST:async n=>{try{let i=e.getDB(),{chatId:a}=await n.json();if(!a)return Response.json({success:!1,error:`Chat ID is required`},{status:400});let o=await e.requireUserId(),s=await i.query.chats.findFirst({where:(0,r.eq)(t.id,a)});if(!s)return Response.json({success:!1,error:`Chat not found`},{status:404});if(s.userId!==o)return Response.json({success:!1,error:`Unauthorized`},{status:403});await i.update(t).set({isPublic:1}).where((0,r.eq)(t.id,a)).execute();let c=`${new URL(n.url).origin}/c/${a}`;return Response.json({success:!0,data:{chatId:a,shareUrl:c}})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({success:!1,error:`Authentication required`},{status:401}):(console.error(`Error in making chat public: `,e),Response.json({success:!1,error:`An error has occurred.`},{status:500}))}}}}function y(e){let{chats:t}=e.schema;return{POST:async a=>{try{let o=await a.json(),s=o.chatHistory.filter(e=>e.role===`user`||e.role===`assistant`).map(e=>({role:e.role,content:String(e.content??``)}));if(s.length===0)return Response.json({message:`No conversation content`},{status:400});let c=await new n.default().loadChatModel(o.chatModel.providerId,o.chatModel.key),l=await(0,i.default)({chat_history:s},c);if(!l)return Response.json({message:`Failed to generate title`},{status:500});let u=e.getUserId?await e.getUserId():null;if(u&&o.chatId)try{let n=e.getDB(),i=await n.query.chats.findFirst({where:(0,r.eq)(t.id,o.chatId)});i&&i.userId===u&&await n.update(t).set({title:l}).where((0,r.eq)(t.id,o.chatId)).execute()}catch(e){console.error(`Failed to persist chat title:`,e)}return Response.json({title:l},{status:200})}catch(e){return console.error(`Error generating chat title:`,e),Response.json({message:`Failed to generate title`},{status:500})}}}}var b=[`assistant`,`user`,`source`,`suggestion`];function x(e){let t=[],n=e;for(let e=0;n!=null&&e<5;e++)t.push(n instanceof Error?n.message:String(n)),n=n instanceof Error?n.cause:void 0;return t.join(` <- caused by: `)}function S(e){return{POST:async t=>{try{let n=e.getDB(),r=await e.requireUserId(),{chatId:i,messageId:a,role:o,suggestions:s,content:c,sources:l}=await t.json();return!i||!a||!o?Response.json({message:`Missing required fields`},{status:400}):b.includes(o)?(await n.insert(e.messagesSchema).values({chatId:i,userId:r,messageId:a,role:o,content:c||``,suggestions:s||[],sources:l||[],createdAt:new Date().toISOString()}),Response.json({message:`Message saved successfully`},{status:200})):Response.json({message:`Invalid role: ${o}`},{status:400})}catch(e){return console.error(`Error saving message:`,x(e)),Response.json({message:`Failed to save message`},{status:500})}}}}function C(e){return{GET:async t=>{try{let r=new n.default,i=new URL(t.url).searchParams.get(`guest`),a=i===`true`;i===null&&(a=!await e.getSession());let o=(await r.getActiveProviders(a)).filter(e=>!e.chatModels.some(e=>e.key===`error`));return o.length===0?Response.json({providers:[],error:a?`No guest-safe AI providers available. Please sign in for more options.`:`No AI providers configured. Please add OPENROUTER_API_KEY to your environment variables or configure your own API keys in Settings.`},{status:200}):Response.json({providers:o,isGuest:a},{status:200})}catch(e){return console.error(`An error occurred while fetching providers`,e),Response.json({message:`An error has occurred.`},{status:500})}},POST:async e=>{try{let{type:t,config:r}=await e.json();if(!t||!r)return Response.json({message:`Missing required fields.`},{status:400});let i=await new n.default().addProvider(t,r);return Response.json({provider:i},{status:200})}catch(e){return console.error(`An error occurred while creating provider`,e),Response.json({message:`An error has occurred.`},{status:500})}}}}function w(){return{DELETE:async(e,{params:t})=>{try{let{id:e}=await t;return e?(await new n.default().removeProvider(e),Response.json({message:`Provider deleted successfully.`},{status:200})):Response.json({message:`Provider ID is required.`},{status:400})}catch(e){return console.error(`An error occurred while deleting provider`,e.message),Response.json({message:`An error has occurred.`},{status:500})}},PATCH:async(e,{params:t})=>{try{let{config:r}=await e.json(),{id:i}=await t;if(!i||!r)return Response.json({message:`Missing required fields.`},{status:400});let a=await new n.default().updateProvider(i,r);return Response.json({provider:a},{status:200})}catch(e){return console.error(`An error occurred while updating provider`,e.message),Response.json({message:`An error has occurred.`},{status:500})}}}}function T(){return{POST:async(e,{params:t})=>{try{let{id:r}=await t,i=await e.json();return!i.key||!i.name?Response.json({message:`Key and name must be provided`},{status:400}):(await new n.default().addProviderModel(r,i.type,i),Response.json({message:`Model added successfully`},{status:200}))}catch(e){return console.error(`An error occurred while adding provider model`,e),Response.json({message:`An error has occurred.`},{status:500})}},DELETE:async(e,{params:t})=>{try{let{id:r}=await t,i=await e.json();return i.key?(await new n.default().removeProviderModel(r,i.type,i.key),Response.json({message:`Model added successfully`},{status:200})):Response.json({message:`Key and name must be provided`},{status:400})}catch(e){return console.error(`An error occurred while deleting provider model`,e),Response.json({message:`An error has occurred.`},{status:500})}}}}function E(e){return{GET:async t=>{try{let t=e.getConfiguredMCPServers();return Response.json({servers:t},{status:200})}catch(e){return console.error(`An error occurred while fetching MCP servers`,e),Response.json({message:`An error has occurred.`},{status:500})}},POST:async t=>{try{let{type:n,name:r,config:i}=await t.json();if(!n||!r||!i)return Response.json({message:`Missing required fields.`},{status:400});let a=e.configManager.addMCPServer(n,r,i);return Response.json({server:a},{status:200})}catch(e){return console.error(`An error occurred while creating MCP server`,e),Response.json({message:`An error has occurred.`},{status:500})}}}}function D(e){return{DELETE:async(t,{params:n})=>{try{let{id:t}=await n;return t?(e.configManager.removeMCPServer(t),Response.json({message:`MCP server deleted successfully.`},{status:200})):Response.json({message:`MCP Server ID is required.`},{status:400})}catch(e){return console.error(`An error occurred while deleting MCP server`,e.message),Response.json({message:`An error has occurred.`},{status:500})}},PATCH:async(t,{params:n})=>{try{let{name:r,config:i}=await t.json(),{id:a}=await n;if(!a||!r||!i)return Response.json({message:`Missing required fields.`},{status:400});let o=await e.configManager.updateMCPServer(a,r,i);return Response.json({server:o},{status:200})}catch(e){return console.error(`An error occurred while updating MCP server`,e.message),Response.json({message:`An error has occurred.`},{status:500})}}}}function O(e){return{POST:async(t,{params:n})=>{try{let{enabled:r}=await t.json(),{id:i}=await n;if(!i||typeof r!=`boolean`)return Response.json({message:`Missing required fields.`},{status:400});let a=e.configManager.toggleMCPServer(i,r);return Response.json({server:a},{status:200})}catch(e){return console.error(`An error occurred while toggling MCP server`,e.message),Response.json({message:`An error has occurred.`},{status:500})}}}}var k={tech:{query:[`technology news`,`latest tech`,`AI`,`science and innovation`],links:[`techcrunch.com`,`wired.com`,`theverge.com`]},finance:{query:[`finance news`,`economy`,`stock market`,`investing`],links:[`bloomberg.com`,`cnbc.com`,`marketwatch.com`]},art:{query:[`art news`,`culture`,`modern art`,`cultural events`],links:[`artnews.com`,`hyperallergic.com`,`theartnewspaper.com`]},sports:{query:[`sports news`,`latest sports`,`cricket football tennis`],links:[`espn.com`,`bbc.com/sport`,`skysports.com`]},entertainment:{query:[`entertainment news`,`movies`,`TV shows`,`celebrities`],links:[`hollywoodreporter.com`,`variety.com`,`deadline.com`]}};function A(e={}){let t=e.searxngDomain??`https://search.qwksearch.com`;return{GET:async e=>{let n=new URL(e.url).searchParams,r=n.get(`q`),i=n.get(`cat`)||`general`,o=parseInt(n.get(`page`)||`1`,10),s=Number.isFinite(o)&&o>0?o:1,c=n.get(`lang`)||`en-US`,l=n.get(`safesearch`)===`true`,u=n.get(`recency`)||void 0,d=n.get(`publicInstances`)===`true`;if(!r)return Response.json({error:`Query parameter is required`},{status:400});let f=Date.now();try{let e=await(0,a.searchWeb)(r,{category:i,recency:u,safesearch:l,maxRetries:6,privateSearxng:!d&&t,proxy:``,lang:c,page:s});e&&(Array.isArray(e)?e.length>0:e.results&&e.results.length>0)||(e=await(0,a.searchWeb)(r,{category:i,recency:u,safesearch:l,maxRetries:6,privateSearxng:!1,proxy:``,lang:c,page:s}));let n=Date.now()-f;return e?Array.isArray(e)?Response.json({results:e,elapsedTime:n}):Response.json({...e,elapsedTime:n}):Response.json({results:[],suggestions:[],elapsedTime:n})}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(`Search error for q="${r}" cat="${i}" page=${s}: ${t}`,e instanceof Error?e.stack:void 0),Response.json({error:`Search failed`,results:[]},{status:500})}}}}function j(){return{GET:async e=>{try{let t=new URL(e.url).searchParams,n=t.get(`mode`)||`normal`,r=k[t.get(`topic`)||`tech`],i=[];if(n===`normal`){let e=new Set;i=(await Promise.all(r.links.flatMap(e=>r.query.map(async t=>(await(0,a.searchSearxng)(`site:${e} ${t}`,{engines:[`bing news`],pageno:1,language:`en`})).results)))).flat().filter(t=>{let n=t.url?.toLowerCase().trim();return!e.has(n)&&(e.add(n),!0)}).sort(()=>Math.random()-.5)}else i=(await(0,a.searchSearxng)(`site:${r.links[Math.floor(Math.random()*r.links.length)]} ${r.query[Math.floor(Math.random()*r.query.length)]}`,{engines:[`bing news`],pageno:1,language:`en`})).results;return Response.json({blogs:i},{status:200})}catch(e){return console.error(`An error occurred in discover route: ${e}`),Response.json({message:`An error has occurred`},{status:500})}}}}var M=[`google`,`duckduckgo`,`wikipedia`],N=3,P=3,F=Object.entries(l.default).map(([e,t])=>({domain:e,name:typeof t?.[0]==`string`?t[0]:``,rank:typeof t?.[1]==`number`?t[1]:2**53-1})),I=null;function L(){return I||=new s.default(F,{keys:[{name:`name`,weight:.6},{name:`domain`,weight:.4}],threshold:.1,ignoreLocation:!0,includeScore:!0,minMatchCharLength:3}),I}function R(e,t,n){return{domain:e,name:t,favicon:`https://www.google.com/s2/favicons?domain=${encodeURIComponent(e)}&sz=64`,rank:n}}function z(e){let t=(0,c.parse)(e);return t.domain&&t.isIcann?t.hostname:null}function B(e){let t=e.split(/\s+/).filter(Boolean),n=t[t.length-1]||``;if(n.length<3)return[];let r=L().search(n,{limit:12}).sort((e,t)=>Math.round((e.score??1)*10)-Math.round((t.score??1)*10)||e.item.rank-t.item.rank).map(({item:e})=>R(e.domain,e.name,e.rank)),i=z(n);return i&&!r.some(e=>e.domain===i)&&r.unshift(R(i,``,2**53-1)),r.slice(0,P)}async function V(e,t,n){let r=await(0,o.searchAutocompleteMulti)(e,t,n);if(r.length>0)return r;let i=t.split(/\s+/).filter(Boolean),a=Math.min(N,i.length-1);for(let r=a;r>=1;r--){let a=i.slice(-r).join(` `),s=i.slice(0,-r).join(` `),c=await(0,o.searchAutocompleteMulti)(e,a,n);if(c.length>0){let e=new Set;for(let n of c){let r=s?`${s} ${n}`:n;r.toLowerCase()!==t.toLowerCase()&&e.add(r)}if(e.size>0)return Array.from(e)}}return[]}function H(){return{GET:async e=>{let{searchParams:t}=new URL(e.url),n=t.get(`q`)?.trim(),r=t.get(`locale`)||`en-US`,i=t.get(`backends`),a=parseInt(t.get(`limit`)||`8`,10);if(!n)return Response.json({suggestions:[],domains:[]});let o=i?i.split(`,`).map(e=>e.trim()).filter(Boolean):M;try{let e=await V(o,n,r),t=B(n);return Response.json({suggestions:e.slice(0,a),domains:t})}catch(e){return console.error(`Autocomplete error:`,e),Response.json({suggestions:[],domains:[]},{status:500})}}}}function U(){return{POST:async e=>{let t=await e.json(),r=t.chatHistory.filter(e=>e.role===`user`||e.role===`assistant`).map(e=>({role:e.role,content:String(e.content??``)})),i=await new n.default().loadChatModel(t.chatModel.providerId,t.chatModel.key),a=(await(0,u.default)({chat_history:r,maxQuestions:t.maxQuestions,promptTemplate:t.promptTemplate},i)).flatMap(e=>(e.match(/\?/g)||[]).length>1?e.split(/\?/).map(e=>e.trim()).filter(e=>e.length>0).map(e=>e+`?`):[e]);return Response.json({suggestions:a},{status:200})}}}function W(e){return{POST:async t=>{let n;try{n=await t.json()}catch{return Response.json({error:`Invalid JSON input`},{status:500})}n.ip=t.headers?.get?.(`x-forwarded-for`)||t.headers?.get?.(`x-real-ip`)||`unknown`;let i=e.getDB(),a=await e.getUserId(),o=null;return a&&(o=await i.query.user.findFirst({where:(0,r.eq)(e.userSchema.id,a)})),o&&(n.apiKey=o.settings?.providerApiKeys?.find(e=>e.provider==n.provider)?.key),n.apiKey||(n.apiKey=n.provider==`groq`&&e.getEnv(`GROQ_API_KEY`)),n.apiKey?Response.json({error:`Language generation endpoint is deprecated. Please use /api/agent/chat instead.`},{status:501}):Response.json({error:`API key is required`},{status:500})}}}var G=`llama-3.3-70b-versatile`;function K(e){return e instanceof Error?e.message:typeof e==`string`?e:String(e)}async function q(e,t){let n=[];if(t&&e.loadChatModel)try{return await e.loadChatModel(t)}catch(e){n.push(K(e))}let r=e.getEnv(`GROQ_API_KEY`);if(r)return e.createGroq({apiKey:r})(G);if(e.loadChatModel)try{return await e.loadChatModel()}catch(e){n.push(K(e))}throw Error(n.length?`AI service is not configured: ${n.join(`; `)}`:`AI service is not configured. Please contact the administrator.`)}function J(e){return{POST:async t=>{try{let{text:n,prompt:r,stream:i,chatModel:a}=await t.json();if(!n||typeof n!=`string`)return Response.json({error:`Text is required and must be a string`},{status:400});let o;try{o=await q(e,a)}catch(e){let t=K(e);return console.error(`AI rewrite has no usable model:`,t),Response.json({error:t},{status:500})}let s=r||`Rewrite the following text to improve clarity, grammar, and style while maintaining the original meaning and tone. Only return the rewritten text without any explanation or additional commentary:
|
|
36
|
+
If the answer is not in the article, say so.`,prompt:u});return Response.json({content:d,success:!0})}catch(e){return console.error(`Error in article Q&A:`,e),Response.json({error:`An error occurred while generating the answer`,details:e instanceof Error?e.message:String(e)},{status:500})}}}function g(e){let{chats:t,messages:n}=e.schema;return{GET:async i=>{try{let i=e.getDB(),a=await e.requireUserId(),o=await i.select({id:t.id,title:t.title,createdAt:t.createdAt,focusMode:t.focusMode,userId:t.userId,files:t.files,messageCount:(0,r.count)(n.id),lastMessageAt:(0,r.max)(n.createdAt)}).from(t).leftJoin(n,(0,r.and)((0,r.eq)(n.chatId,t.id),(0,r.eq)(n.role,`user`))).where((0,r.eq)(t.userId,a)).groupBy(t.id,t.title,t.createdAt,t.focusMode,t.userId,t.files).orderBy(r.sql`${t.createdAt} DESC`);return Response.json({chats:o},{status:200})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({message:`Authentication required`},{status:401}):(console.error(`Error in getting chats: `,e),Response.json({message:`An error has occurred.`},{status:500}))}},DELETE:async i=>{try{let i=e.getDB(),a=await e.requireUserId(),o=await i.query.chats.findMany({where:(0,r.eq)(t.userId,a),columns:{id:!0}});if(o.length>0){let e=o.map(e=>e.id);await i.delete(n).where((0,r.inArray)(n.chatId,e)),await i.delete(t).where((0,r.eq)(t.userId,a))}return Response.json({message:`All chats deleted`},{status:200})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({message:`Authentication required`},{status:401}):(console.error(`Error in deleting all chats: `,e),Response.json({message:`An error has occurred.`},{status:500}))}}}}function _(e){let{chats:t,messages:n}=e.schema;return{GET:async(i,{params:a})=>{try{let i=e.getDB(),{id:o}=await a,s;try{s=await e.requireUserId()}catch{s=void 0}let c=await i.query.chats.findFirst({where:(0,r.eq)(t.id,o)});if(!c)return Response.json({message:`Chat not found`},{status:404});if(!(c.userId===s||c.isPublic))return Response.json({message:`Unauthorized - this chat is private`},{status:403});let l=await i.query.messages.findMany({where:(0,r.eq)(n.chatId,o)});return Response.json({chat:c,messages:l},{status:200})}catch(e){return console.error(`Error in getting chat by id: `,e),Response.json({message:`An error has occurred.`},{status:500})}},DELETE:async(i,{params:a})=>{try{let i=e.getDB(),{id:o}=await a,s=await e.requireUserId();return await i.query.chats.findFirst({where:(0,r.and)((0,r.eq)(t.id,o),(0,r.eq)(t.userId,s))})?(await i.delete(t).where((0,r.eq)(t.id,o)).execute(),await i.delete(n).where((0,r.eq)(n.chatId,o)).execute(),Response.json({message:`Chat deleted successfully`},{status:200})):Response.json({message:`Chat not found`},{status:404})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({message:`Authentication required`},{status:401}):(console.error(`Error in deleting chat by id: `,e),Response.json({message:`An error has occurred.`},{status:500}))}}}}function v(e){let{chats:t,messages:n}=e.schema;return{GET:async i=>{try{let a=e.getDB(),o=await e.requireUserId(),{searchParams:s}=new URL(i.url),c=s.get(`q`);if(!c||c.trim().length===0)return Response.json({chats:[]},{status:200});let l=`%${c.trim()}%`,u=await a.select({id:t.id,title:t.title,createdAt:t.createdAt,focusMode:t.focusMode,userId:t.userId,files:t.files}).from(t).where((0,r.and)((0,r.eq)(t.userId,o),(0,r.like)(t.title,l))).orderBy(r.sql`${t.createdAt} DESC`),d=await a.selectDistinct({id:t.id,title:t.title,createdAt:t.createdAt,focusMode:t.focusMode,userId:t.userId,files:t.files}).from(n).innerJoin(t,(0,r.eq)(n.chatId,t.id)).where((0,r.and)((0,r.eq)(t.userId,o),(0,r.or)((0,r.like)(n.content,l)))).orderBy(r.sql`${t.createdAt} DESC`),f=[...u,...d],p=Array.from(new Map(f.map(e=>[e.id,e])).values()),m=p.map(e=>e.id),h=m.length?await a.select({chatId:n.chatId,count:r.sql`count(*)`}).from(n).where((0,r.and)(r.sql`${n.chatId} IN (${r.sql.join(m.map(e=>r.sql`${e}`),r.sql`, `)})`,(0,r.eq)(n.role,`user`))).groupBy(n.chatId):[],g=new Map(h.map(e=>[e.chatId,Number(e.count)])),_=p.map(e=>({...e,messageCount:g.get(e.id)||0}));return Response.json({chats:_},{status:200})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({message:`Authentication required`},{status:401}):(console.error(`Error searching chats:`,e),Response.json({message:`An error has occurred.`},{status:500}))}}}}function ee(e){let{chats:t}=e.schema;return{POST:async n=>{try{let i=e.getDB(),{chatId:a}=await n.json();if(!a)return Response.json({success:!1,error:`Chat ID is required`},{status:400});let o=await e.requireUserId(),s=await i.query.chats.findFirst({where:(0,r.eq)(t.id,a)});if(!s)return Response.json({success:!1,error:`Chat not found`},{status:404});if(s.userId!==o)return Response.json({success:!1,error:`Unauthorized`},{status:403});await i.update(t).set({isPublic:1}).where((0,r.eq)(t.id,a)).execute();let c=`${new URL(n.url).origin}/c/${a}`;return Response.json({success:!0,data:{chatId:a,shareUrl:c}})}catch(e){return e instanceof Error&&e.message===`Unauthorized`?Response.json({success:!1,error:`Authentication required`},{status:401}):(console.error(`Error in making chat public: `,e),Response.json({success:!1,error:`An error has occurred.`},{status:500}))}}}}function te(e){let{chats:t}=e.schema;return{POST:async a=>{try{let o=await a.json(),s=o.chatHistory.filter(e=>e.role===`user`||e.role===`assistant`).map(e=>({role:e.role,content:String(e.content??``)}));if(s.length===0)return Response.json({message:`No conversation content`},{status:400});let c=await new n.default().loadChatModel(o.chatModel.providerId,o.chatModel.key),l=await(0,i.default)({chat_history:s},c);if(!l)return Response.json({message:`Failed to generate title`},{status:500});let u=e.getUserId?await e.getUserId():null;if(u&&o.chatId)try{let n=e.getDB(),i=await n.query.chats.findFirst({where:(0,r.eq)(t.id,o.chatId)});i&&i.userId===u&&await n.update(t).set({title:l}).where((0,r.eq)(t.id,o.chatId)).execute()}catch(e){console.error(`Failed to persist chat title:`,e)}return Response.json({title:l},{status:200})}catch(e){return console.error(`Error generating chat title:`,e),Response.json({message:`Failed to generate title`},{status:500})}}}}var ne=[`assistant`,`user`,`source`,`suggestion`];function y(e){let t=[],n=e;for(let e=0;n!=null&&e<5;e++)t.push(n instanceof Error?n.message:String(n)),n=n instanceof Error?n.cause:void 0;return t.join(` <- caused by: `)}function re(e){return{POST:async t=>{try{let n=e.getDB(),r=await e.requireUserId(),{chatId:i,messageId:a,role:o,suggestions:s,content:c,sources:l}=await t.json();return!i||!a||!o?Response.json({message:`Missing required fields`},{status:400}):ne.includes(o)?(await n.insert(e.messagesSchema).values({chatId:i,userId:r,messageId:a,role:o,content:c||``,suggestions:s||[],sources:l||[],createdAt:new Date().toISOString()}),Response.json({message:`Message saved successfully`},{status:200})):Response.json({message:`Invalid role: ${o}`},{status:400})}catch(e){return console.error(`Error saving message:`,y(e)),Response.json({message:`Failed to save message`},{status:500})}}}}function ie(e){return{GET:async t=>{try{let r=new n.default,i=new URL(t.url).searchParams.get(`guest`),a=i===`true`;i===null&&(a=!await e.getSession());let o=(await r.getActiveProviders(a)).filter(e=>!e.chatModels.some(e=>e.key===`error`));return o.length===0?Response.json({providers:[],error:a?`No guest-safe AI providers available. Please sign in for more options.`:`No AI providers configured. Please add OPENROUTER_API_KEY to your environment variables or configure your own API keys in Settings.`},{status:200}):Response.json({providers:o,isGuest:a},{status:200})}catch(e){return console.error(`An error occurred while fetching providers`,e),Response.json({message:`An error has occurred.`},{status:500})}},POST:async e=>{try{let{type:t,config:r}=await e.json();if(!t||!r)return Response.json({message:`Missing required fields.`},{status:400});let i=await new n.default().addProvider(t,r);return Response.json({provider:i},{status:200})}catch(e){return console.error(`An error occurred while creating provider`,e),Response.json({message:`An error has occurred.`},{status:500})}}}}function ae(){return{DELETE:async(e,{params:t})=>{try{let{id:e}=await t;return e?(await new n.default().removeProvider(e),Response.json({message:`Provider deleted successfully.`},{status:200})):Response.json({message:`Provider ID is required.`},{status:400})}catch(e){return console.error(`An error occurred while deleting provider`,e.message),Response.json({message:`An error has occurred.`},{status:500})}},PATCH:async(e,{params:t})=>{try{let{config:r}=await e.json(),{id:i}=await t;if(!i||!r)return Response.json({message:`Missing required fields.`},{status:400});let a=await new n.default().updateProvider(i,r);return Response.json({provider:a},{status:200})}catch(e){return console.error(`An error occurred while updating provider`,e.message),Response.json({message:`An error has occurred.`},{status:500})}}}}function b(){return{POST:async(e,{params:t})=>{try{let{id:r}=await t,i=await e.json();return!i.key||!i.name?Response.json({message:`Key and name must be provided`},{status:400}):(await new n.default().addProviderModel(r,i.type,i),Response.json({message:`Model added successfully`},{status:200}))}catch(e){return console.error(`An error occurred while adding provider model`,e),Response.json({message:`An error has occurred.`},{status:500})}},DELETE:async(e,{params:t})=>{try{let{id:r}=await t,i=await e.json();return i.key?(await new n.default().removeProviderModel(r,i.type,i.key),Response.json({message:`Model added successfully`},{status:200})):Response.json({message:`Key and name must be provided`},{status:400})}catch(e){return console.error(`An error occurred while deleting provider model`,e),Response.json({message:`An error has occurred.`},{status:500})}}}}function oe(e){return{GET:async t=>{try{let t=e.getConfiguredMCPServers();return Response.json({servers:t},{status:200})}catch(e){return console.error(`An error occurred while fetching MCP servers`,e),Response.json({message:`An error has occurred.`},{status:500})}},POST:async t=>{try{let{type:n,name:r,config:i}=await t.json();if(!n||!r||!i)return Response.json({message:`Missing required fields.`},{status:400});let a=e.configManager.addMCPServer(n,r,i);return Response.json({server:a},{status:200})}catch(e){return console.error(`An error occurred while creating MCP server`,e),Response.json({message:`An error has occurred.`},{status:500})}}}}function se(e){return{DELETE:async(t,{params:n})=>{try{let{id:t}=await n;return t?(e.configManager.removeMCPServer(t),Response.json({message:`MCP server deleted successfully.`},{status:200})):Response.json({message:`MCP Server ID is required.`},{status:400})}catch(e){return console.error(`An error occurred while deleting MCP server`,e.message),Response.json({message:`An error has occurred.`},{status:500})}},PATCH:async(t,{params:n})=>{try{let{name:r,config:i}=await t.json(),{id:a}=await n;if(!a||!r||!i)return Response.json({message:`Missing required fields.`},{status:400});let o=await e.configManager.updateMCPServer(a,r,i);return Response.json({server:o},{status:200})}catch(e){return console.error(`An error occurred while updating MCP server`,e.message),Response.json({message:`An error has occurred.`},{status:500})}}}}function ce(e){return{POST:async(t,{params:n})=>{try{let{enabled:r}=await t.json(),{id:i}=await n;if(!i||typeof r!=`boolean`)return Response.json({message:`Missing required fields.`},{status:400});let a=e.configManager.toggleMCPServer(i,r);return Response.json({server:a},{status:200})}catch(e){return console.error(`An error occurred while toggling MCP server`,e.message),Response.json({message:`An error has occurred.`},{status:500})}}}}var le={tech:{query:[`technology news`,`latest tech`,`AI`,`science and innovation`],links:[`techcrunch.com`,`wired.com`,`theverge.com`]},finance:{query:[`finance news`,`economy`,`stock market`,`investing`],links:[`bloomberg.com`,`cnbc.com`,`marketwatch.com`]},art:{query:[`art news`,`culture`,`modern art`,`cultural events`],links:[`artnews.com`,`hyperallergic.com`,`theartnewspaper.com`]},sports:{query:[`sports news`,`latest sports`,`cricket football tennis`],links:[`espn.com`,`bbc.com/sport`,`skysports.com`]},entertainment:{query:[`entertainment news`,`movies`,`TV shows`,`celebrities`],links:[`hollywoodreporter.com`,`variety.com`,`deadline.com`]}};function x(e={}){let t=e.searxngDomain??`https://search.qwksearch.com`;return{GET:async e=>{let n=new URL(e.url).searchParams,r=n.get(`q`),i=n.get(`cat`)||`general`,o=parseInt(n.get(`page`)||`1`,10),s=Number.isFinite(o)&&o>0?o:1,c=n.get(`lang`)||`en-US`,l=n.get(`safesearch`)===`true`,u=n.get(`recency`)||void 0,d=n.get(`publicInstances`)===`true`;if(!r)return Response.json({error:`Query parameter is required`},{status:400});let f=Date.now();try{let e=await(0,a.searchWeb)(r,{category:i,recency:u,safesearch:l,maxRetries:6,privateSearxng:!d&&t,proxy:``,lang:c,page:s});e&&(Array.isArray(e)?e.length>0:e.results&&e.results.length>0)||(e=await(0,a.searchWeb)(r,{category:i,recency:u,safesearch:l,maxRetries:6,privateSearxng:!1,proxy:``,lang:c,page:s}));let n=Date.now()-f;return e?Array.isArray(e)?Response.json({results:e,elapsedTime:n}):Response.json({...e,elapsedTime:n}):Response.json({results:[],suggestions:[],elapsedTime:n})}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(`Search error for q="${r}" cat="${i}" page=${s}: ${t}`,e instanceof Error?e.stack:void 0),Response.json({error:`Search failed`,results:[]},{status:500})}}}}function S(){return{GET:async e=>{try{let t=new URL(e.url).searchParams,n=t.get(`mode`)||`normal`,r=le[t.get(`topic`)||`tech`],i=[];if(n===`normal`){let e=new Set;i=(await Promise.all(r.links.flatMap(e=>r.query.map(async t=>(await(0,a.searchSearxng)(`site:${e} ${t}`,{engines:[`bing news`],pageno:1,language:`en`})).results)))).flat().filter(t=>{let n=t.url?.toLowerCase().trim();return!e.has(n)&&(e.add(n),!0)}).sort(()=>Math.random()-.5)}else i=(await(0,a.searchSearxng)(`site:${r.links[Math.floor(Math.random()*r.links.length)]} ${r.query[Math.floor(Math.random()*r.query.length)]}`,{engines:[`bing news`],pageno:1,language:`en`})).results;return Response.json({blogs:i},{status:200})}catch(e){return console.error(`An error occurred in discover route: ${e}`),Response.json({message:`An error has occurred`},{status:500})}}}}async function C(e,t,n={}){let r=t.fetch??fetch,i=new AbortController,a=setTimeout(()=>i.abort(Error(`Timed out after ${t.timeoutMs??3e3}ms`)),t.timeoutMs??3e3),o=()=>i.abort(t.signal?.reason);t.signal?.aborted&&o(),t.signal?.addEventListener(`abort`,o,{once:!0});try{let t=await r(e,{headers:{"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36`,...n},signal:i.signal});if(!t.ok)throw Error(`HTTP ${t.status} from ${new URL(e).hostname}`);return await t.text()}finally{clearTimeout(a),t.signal?.removeEventListener(`abort`,o)}}function w(e){let t=JSON.parse(e);return Array.isArray(t)&&Array.isArray(t[1])?t[1].filter(e=>typeof e==`string`):[]}var ue={amp:`&`,lt:`<`,gt:`>`,quot:`"`,apos:`'`,nbsp:` `};function de(e){return e.replace(/<[^>]*>/g,``).replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi,(e,t)=>{if(t[0]===`#`){let n=t[1]===`x`||t[1]===`X`?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return Number.isFinite(n)?String.fromCodePoint(n):e}return ue[t.toLowerCase()]??e}).trim()}function T(e=`en-US`){return e.split(/[-_]/)[0].toLowerCase()}var fe=async(e,t={})=>{let n=new URLSearchParams({ie:`utf-8`,json:`1`,prod:`pc`,wd:e}),r=JSON.parse(await C(`https://www.baidu.com/sugrec?${n}`,t));return Array.isArray(r?.g)?r.g.map(e=>e.q):[]},pe=async(e,t={})=>w(await C(`https://api.bing.com/osjson.aspx?${new URLSearchParams({query:e,mkt:t.locale??`en-US`})}`,t)),E=async(e,t={})=>w(await C(`https://search.brave.com/api/suggest?${new URLSearchParams({q:e})}`,t,{Cookie:`country=all`})),D=async(e,t={})=>{let n=(t.locale??`en-US`).toLowerCase().split(/[-_]/).reverse().join(`-`);return w(await C(`https://duckduckgo.com/ac/?type=list&${new URLSearchParams({q:e,kl:n})}`,t))},O={de:`google.de`,fr:`google.fr`,es:`google.es`,it:`google.it`,nl:`google.nl`,pt:`google.pt`,ru:`google.ru`,ja:`google.co.jp`,zh:`google.com.hk`,ko:`google.co.kr`},k=async(e,t={})=>{let n=T(t.locale),r=new URLSearchParams({q:e,client:`gws-wiz`,hl:n}),i=await C(`https://${O[n]??`google.com`}/complete/search?${r}`,t),a=i.indexOf(`[`),o=i.lastIndexOf(`]`)+1;if(a<0||o<=a)return[];let s=JSON.parse(i.slice(a,o));return Array.isArray(s?.[0])?s[0].map(e=>typeof e?.[0]==`string`?de(e[0]):``).filter(Boolean):[]},A=async(e,t={})=>{let n=new URLSearchParams({q:e,locale:(t.locale??`en-US`).replace(`-`,`_`),version:`2`}),r=JSON.parse(await C(`https://api.qwant.com/v3/suggest?${n}`,t));return r?.status===`success`&&Array.isArray(r?.data?.items)?r.data.items.map(e=>e.value):[]},j={da:`dansk`,de:`deutsch`,en:`english`,es:`espanol`,fr:`francais`,nb:`norsk`,nl:`nederlands`,pl:`polski`,pt:`portugues`,sv:`svenska`},M=async(e,t={})=>w(await C(`https://www.startpage.com/suggestions?${new URLSearchParams({q:e,format:`opensearch`,segment:`startpage.defaultffx`,lui:j[T(t.locale)]??`english`})}`,t)),N=new Set([`en`,`de`,`fr`,`es`,`it`,`nl`,`pt`,`ru`,`ja`,`zh`,`ar`,`ko`]),P={baidu:fe,bing:pe,brave:E,duckduckgo:D,google:k,qwant:A,startpage:M,wikipedia:async(e,t={})=>{let n=T(t.locale),r=new URLSearchParams({action:`opensearch`,format:`json`,formatversion:`2`,search:e,namespace:`0`,limit:`10`});return w(await C(`https://${`${N.has(n)?n:`en`}.wikipedia.org`}/w/api.php?${r}`,t))},yandex:async(e,t={})=>w(await C(`https://suggest.yandex.com/suggest-ff.cgi?${new URLSearchParams({part:e})}`,t))};Object.keys(P);function F(e){return Object.prototype.hasOwnProperty.call(P,e)}var I=`google`,L=3;function R(e){let t=e?.trim().toLowerCase();return t===`ddg`?`duckduckgo`:t&&F(t)?t:I}async function z(e,t={}){let n=R(t.engine);try{return await P[n](e,t)}catch(e){return t.signal?.aborted||console.error(`Autocomplete engine '${n}' failed:`,e),[]}}async function B(e,t={}){let n=e=>Array.from(new Set(e)),r=await z(e,t);if(r.length>0)return n(r);let i=e.split(/\s+/).filter(Boolean),a=Math.min(L,i.length-1);for(let n=a;n>=1;n--){if(t.signal?.aborted)return[];let r=i.slice(-n).join(` `),a=i.slice(0,-n).join(` `),o=await z(r,t),s=new Set;for(let t of o){let n=a?`${a} ${t}`:t;n.toLowerCase()!==e.toLowerCase()&&s.add(n)}if(s.size>0)return Array.from(s)}return[]}var me=3,V=null;function he(){if(!V){let e=Object.entries(c.default).map(([e,t])=>({domain:e,name:typeof t?.[0]==`string`?t[0]:``,rank:typeof t?.[1]==`number`?t[1]:2**53-1}));V=new o.default(e,{keys:[{name:`name`,weight:.6},{name:`domain`,weight:.4}],threshold:.1,ignoreLocation:!0,includeScore:!0,minMatchCharLength:3})}return V}function H(e,t,n){return{domain:e,name:t,favicon:`https://www.google.com/s2/favicons?domain=${encodeURIComponent(e)}&sz=64`,rank:n}}function ge(e){let t=(0,s.parse)(e);return t.domain&&t.isIcann?t.hostname:null}function _e(e){let t=e.split(/\s+/).filter(Boolean),n=t[t.length-1]||``;if(n.length<3)return[];let r=he().search(n,{limit:12}).sort((e,t)=>Math.round((e.score??1)*10)-Math.round((t.score??1)*10)||e.item.rank-t.item.rank).map(({item:e})=>H(e.domain,e.name,e.rank)),i=ge(n);return i&&!r.some(e=>e.domain===i)&&r.unshift(H(i,``,2**53-1)),r.slice(0,me)}function ve(e={}){return{GET:async t=>{let{searchParams:n}=new URL(t.url),r=n.get(`q`)?.trim(),i=n.get(`locale`)||`en-US`,a=parseInt(n.get(`limit`)||String(e.defaultLimit??8),10),o=n.get(`engine`)||n.get(`backends`)?.split(`,`)[0]||e.engine;if(!r)return Response.json({suggestions:[],domains:[]});try{let e=await B(r,{engine:R(o),locale:i,signal:t.signal}),n=_e(r);return Response.json({suggestions:e.slice(0,a),domains:n})}catch(e){return console.error(`Autocomplete error:`,e),Response.json({suggestions:[],domains:[]},{status:500})}}}}function ye(){return{POST:async e=>{let t=await e.json(),r=t.chatHistory.filter(e=>e.role===`user`||e.role===`assistant`).map(e=>({role:e.role,content:String(e.content??``)})),i=await new n.default().loadChatModel(t.chatModel.providerId,t.chatModel.key),a=(await(0,l.default)({chat_history:r,maxQuestions:t.maxQuestions,promptTemplate:t.promptTemplate},i)).flatMap(e=>(e.match(/\?/g)||[]).length>1?e.split(/\?/).map(e=>e.trim()).filter(e=>e.length>0).map(e=>e+`?`):[e]);return Response.json({suggestions:a},{status:200})}}}function be(e){return{POST:async t=>{let n;try{n=await t.json()}catch{return Response.json({error:`Invalid JSON input`},{status:500})}n.ip=t.headers?.get?.(`x-forwarded-for`)||t.headers?.get?.(`x-real-ip`)||`unknown`;let i=e.getDB(),a=await e.getUserId(),o=null;return a&&(o=await i.query.user.findFirst({where:(0,r.eq)(e.userSchema.id,a)})),o&&(n.apiKey=o.settings?.providerApiKeys?.find(e=>e.provider==n.provider)?.key),n.apiKey||(n.apiKey=n.provider==`groq`&&e.getEnv(`GROQ_API_KEY`)),n.apiKey?Response.json({error:`Language generation endpoint is deprecated. Please use /api/agent/chat instead.`},{status:501}):Response.json({error:`API key is required`},{status:500})}}}var xe=`llama-3.3-70b-versatile`;function U(e){return e instanceof Error?e.message:typeof e==`string`?e:String(e)}async function Se(e,t){let n=[];if(t&&e.loadChatModel)try{return await e.loadChatModel(t)}catch(e){n.push(U(e))}let r=e.getEnv(`GROQ_API_KEY`);if(r)return e.createGroq({apiKey:r})(xe);if(e.loadChatModel)try{return await e.loadChatModel()}catch(e){n.push(U(e))}throw Error(n.length?`AI service is not configured: ${n.join(`; `)}`:`AI service is not configured. Please contact the administrator.`)}function Ce(e){return{POST:async t=>{try{let{text:n,prompt:r,stream:i,chatModel:a}=await t.json();if(!n||typeof n!=`string`)return Response.json({error:`Text is required and must be a string`},{status:400});let o;try{o=await Se(e,a)}catch(e){let t=U(e);return console.error(`AI rewrite has no usable model:`,t),Response.json({error:t},{status:500})}let s=r||`Rewrite the following text to improve clarity, grammar, and style while maintaining the original meaning and tone. Only return the rewritten text without any explanation or additional commentary:
|
|
37
37
|
|
|
38
|
-
${n}`;if(i&&e.streamText){let{textStream:t}=e.streamText({model:o,prompt:s,temperature:.7}),n=t[Symbol.asyncIterator](),r=await n.next(),i=new ReadableStream({async start(e){let t=new TextEncoder;try{for(r.done||e.enqueue(t.encode(r.value));;){let r=await n.next();if(r.done)break;e.enqueue(t.encode(r.value))}e.close()}catch(t){console.error(`AI rewrite stream error:`,t),e.error(t)}}});return new Response(i,{headers:{"Content-Type":`text/plain; charset=utf-8`,"Cache-Control":`no-store`,"X-Accel-Buffering":`no`}})}let c=(await e.generateText({model:o,prompt:s,temperature:.7})).text.trim();return Response.json({rewrittenText:c})}catch(e){let t=
|
|
38
|
+
${n}`;if(i&&e.streamText){let{textStream:t}=e.streamText({model:o,prompt:s,temperature:.7}),n=t[Symbol.asyncIterator](),r=await n.next(),i=new ReadableStream({async start(e){let t=new TextEncoder;try{for(r.done||e.enqueue(t.encode(r.value));;){let r=await n.next();if(r.done)break;e.enqueue(t.encode(r.value))}e.close()}catch(t){console.error(`AI rewrite stream error:`,t),e.error(t)}}});return new Response(i,{headers:{"Content-Type":`text/plain; charset=utf-8`,"Cache-Control":`no-store`,"X-Accel-Buffering":`no`}})}let c=(await e.generateText({model:o,prompt:s,temperature:.7})).text.trim();return Response.json({rewrittenText:c})}catch(e){let t=U(e);return console.error(`AI rewrite error:`,e),Response.json({error:`Failed to process AI request: ${t}`,details:t},{status:500})}}}}function we(e){return{POST:async t=>{let n,r,i;try{let e=await t.json();n=e.text,r=e.voice||e.speaker||`af_heart`,i=e.provider||`kokoro`}catch{return Response.json({error:`Invalid request body`},{status:400})}if(!n||typeof n!=`string`||n.trim().length===0)return Response.json({error:`text is required`},{status:400});let a=await e.getUserId()??t.headers?.get?.(`x-forwarded-for`)?.split(`,`)[0]?.trim()??t.headers?.get?.(`x-real-ip`)??`unknown`,{allowed:o}=e.checkTTSRateLimit(a);if(!o)return Response.json({error:`Daily TTS limit reached (10/day)`,rateLimited:!0},{status:429});try{let t=await e.generateSpeech({text:n.slice(0,5e3),provider:i,voice:r});return new Response(t.audio,{headers:{"Content-Type":t.contentType,"Cache-Control":`public, max-age=86400`,"Content-Disposition":`inline; filename="speech.${t.contentType.includes(`wav`)?`wav`:`mp3`}"`}})}catch(e){console.error(`[TTS] Error:`,e);let t=e instanceof Error?e.message:`TTS generation failed`;return t.includes(`Cloudflare AI binding`)?Response.json({error:`Deepgram provider requires Cloudflare AI binding. Use 'kokoro' provider instead.`},{status:503}):Response.json({error:t},{status:500})}}}}var W=[`small`,`fast`,`medium`,`turbo`,`large`],G=`turbo`;function K(e){return typeof e==`string`&&W.includes(e)}function q(e){return e===`small`||e===`fast`?`@cf/openai/whisper-tiny-en`:e===`medium`||e===`turbo`?`@cf/openai/whisper-large-v3-turbo`:e===`large`?`@cf/openai/whisper-large-v3`:`@cf/openai/whisper-large-v3-turbo`}async function J(e,t,n){let r=q(n),i;try{i=e.getCloudflareContext().env?.AI}catch{}if(!i)return{ok:!1,reason:`ai_unavailable`};let a=await t.arrayBuffer(),{text:o}=await i.run(r,{audio:[...new Uint8Array(a)]});return{ok:!0,text:o,model:r}}function Te(e){return{POST:async t=>{try{let n=await t.formData(),r=n.get(`file`);if(!r||!(r instanceof File))return Response.json({error:`file is required`},{status:400});let i=await J(e,r,n.get(`model`));return i.ok?Response.json({text:i.text,model:i.model}):Response.json({error:`Cloudflare AI binding not available`},{status:503})}catch(e){return console.error(`Transcript error:`,e),Response.json({error:`Failed to transcribe audio`},{status:500})}}}}var Y=[`json`];function X(e,t,n,r=null,i=null){return Response.json({error:{message:t,type:n,param:r,code:i}},{status:e})}async function Z(e,t){let n=await e.authorize(t);if(n.authorized)return null;let{status:r,message:i}=n;return X(r??401,i,`authentication_error`,null,`invalid_api_key`)}function Q(){return{object:`list`,data:W.map(e=>({id:e,object:`model`,created:0,owned_by:`qwksearch`}))}}function Ee(e){return{GET:async t=>await Z(e,t)||Response.json(Q())}}function De(e){return{POST:async t=>{let n=await Z(e,t);if(n)return n;let r;try{r=await t.formData()}catch{return X(400,"Request body must be multipart/form-data with a `file` field.",`invalid_request_error`,null,`invalid_body`)}let i=r.get(`file`);if(!i||!(i instanceof File))return X(400,"`file` is required.",`invalid_request_error`,`file`,`missing_file`);if(i.size===0)return X(400,"`file` is empty.",`invalid_request_error`,`file`,`empty_file`);let a=r.get(`model`),o=a===null||a===``?G:a;if(!K(o))return X(400,`Unsupported model. Use one of: ${W.join(`, `)}.`,`invalid_request_error`,`model`,`model_not_found`);let s=r.get(`response_format`);if(s!==null&&s!==``&&s!==`json`)return X(400,`Unsupported response_format. Only ${Y.join(`, `)} is supported.`,`invalid_request_error`,`response_format`,`unsupported_response_format`);try{let t=await J(e,i,o);return t.ok?Response.json({text:t.text}):X(503,`Transcription is not available right now.`,`server_error`,null,`ai_unavailable`)}catch(e){return console.error(`[v1/audio/transcriptions] Workers AI failed:`,e instanceof Error?e.name:typeof e),X(500,`Failed to transcribe audio.`,`server_error`,null,`transcription_failed`)}}}}function Oe(){return{POST:async e=>{try{let{providerType:t,apiKey:n,onlyFree:r=!0}=await e.json();if(!t)return Response.json({error:`Provider type is required`},{status:400});if(!n)return Response.json({error:`API key is required`},{status:400});let i=d.LANGUAGE_MODELS.find(e=>e.provider.toLowerCase()===t.toLowerCase());if(!i)return Response.json({error:`Provider ${t} not found`},{status:404});let a=await(0,u.testProviderModels)(t,n,i.models,{onlyFree:r,concurrency:3,timeout:15e3});return Response.json(a)}catch(e){return console.error(`[test-models] Error:`,e),Response.json({error:e.message||`Failed to test models`},{status:500})}}}}var ke=864e5,$=null;function Ae(e){return{GET:async t=>{try{let t=Date.now();if($&&t-$.timestamp<ke)return Response.json({...$.result,cached:!0,cacheAge:t-$.timestamp});let n=await e.validateOpenRouterModels();return $={result:n,timestamp:t},Response.json({...n,cached:!1})}catch(e){return console.error(`[validate-openrouter] GET error:`,e),Response.json({error:e.message||`Validation failed`},{status:500})}},POST:async t=>{try{let{concurrency:n=3,timeout:r=15e3}=await t.json().catch(()=>({})),i=await e.validateOpenRouterModels(n,r);return $={result:i,timestamp:Date.now()},Response.json({...i,cached:!1})}catch(e){return console.error(`[validate-openrouter] POST error:`,e),Response.json({error:e.message||`Validation failed`},{status:500})}}}}exports.DEFAULT_TRANSCRIPTION_MODEL=G,exports.SUPPORTED_RESPONSE_FORMATS=Y,exports.TRANSCRIPTION_MODELS=W,exports.createAgentsHandler=be,exports.createArticleFollowupsHandler=f,exports.createArticleQAHandler=h,exports.createAutocompleteHandler=ve,exports.createChatByIdHandler=_,exports.createChatTitleHandler=te,exports.createChatsHandler=g,exports.createChatsSearchHandler=v,exports.createChatsShareHandler=ee,exports.createDiscoverHandler=S,exports.createMCPServerByIdHandler=se,exports.createMCPServerToggleHandler=ce,exports.createMCPServersHandler=oe,exports.createMessagesHandler=re,exports.createOpenAIModelsHandler=Ee,exports.createOpenAITranscriptionHandler=De,exports.createPageTipsHandler=p,exports.createProviderByIdHandler=ae,exports.createProviderModelsHandler=b,exports.createProvidersHandler=ie,exports.createRewriteHandler=Ce,exports.createSearchHandler=x,exports.createSuggestionsHandler=ye,exports.createTestModelsHandler=Oe,exports.createTopicSearchesHandler=m,exports.createTranscriptHandler=Te,exports.createValidateOpenRouterHandler=Ae,exports.createVoiceHandler=we,exports.describeError=y,exports.getWhisperModel=q,exports.isTranscriptionModel=K,exports.listTranscriptionModels=Q,exports.openAIError=X,exports.transcribeAudio=J;
|