research-agent-ui 0.1.101 → 0.1.102

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/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("extract-webpage/suggest-next-words/autocomplete-search-engines"),s=require("fuse.js");s=e.t(s,1);let 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(`
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("extract-webpage/suggest-next-words/autocomplete-search-engines"),s=require("fuse.js");s=e.t(s,1);let c=require("tldts"),l=require("domain-rank/data/domain-rank-merged.json");l=e.t(l,1);let u=require("chat-agent-toolkit/tools/search/suggestionGeneratorAgent");u=e.t(u,1);let d=require("chat-agent-toolkit/config/model-tester"),f=require("chat-agent-toolkit/config/language-models-database");function p(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:
@@ -7,7 +7,7 @@ ${r.slice(0,15e3)}
7
7
  ${l}
8
8
 
9
9
  Generate ${a} follow-up questions that would help readers dive deeper into this article.`,{text:f}=await(0,t.generateText)({model:c,messages:[{role:`system`,content:u},{role:`user`,content: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{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(`
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 m(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(`
11
11
  `)}`:``,u=`Article content:
12
12
  ${r.slice(0,15e3)}
13
13
 
@@ -17,6 +17,6 @@ User question: ${i}
17
17
 
18
18
  Please provide a helpful answer based on the article content above.`,{text:d}=await(0,t.generateText)({model:c,messages:[{role:`system`,content:`You are a helpful AI assistant that answers questions about articles.
19
19
  Provide clear, concise, and accurate answers based on the article content provided.
20
- 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 m(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 h(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 g(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 _(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 v(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 y=[`assistant`,`user`,`source`,`suggestion`];function b(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 x(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}):y.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:`,b(e)),Response.json({message:`Failed to save message`},{status:500})}}}}function S(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 C(){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 w(){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 T(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 E(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 D(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 O={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 k(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=n.get(`lang`)||`en-US`,c=n.get(`safesearch`)===`true`,l=n.get(`recency`)||void 0,u=n.get(`publicInstances`)===`true`;if(!r)return Response.json({error:`Query parameter is required`},{status:400});let d=Date.now();try{let e=await(0,a.searchWeb)(r,{category:i,recency:l,safesearch:c,maxRetries:6,privateSearxng:!u&&t,proxy:``,lang:s,page:o});e&&(Array.isArray(e)?e.length>0:e.results&&e.results.length>0)||(e=await(0,a.searchWeb)(r,{category:i,recency:l,safesearch:c,maxRetries:6,privateSearxng:!1,proxy:``,lang:s,page:o}));let n=Date.now()-d;return e?Array.isArray(e)?Response.json({results:e,elapsedTime:n}):Response.json({...e,elapsedTime:n}):Response.json({results:[],suggestions:[],elapsedTime:n})}catch(e){return console.error(`Search error:`,e),Response.json({error:`Search failed`,results:[]},{status:500})}}}}function A(){return{GET:async e=>{try{let t=new URL(e.url).searchParams,n=t.get(`mode`)||`normal`,r=O[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 j=[`google`,`duckduckgo`,`wikipedia`],M=3,N=3,P=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})),F=null;function I(){return F||=new s.default(P,{keys:[{name:`name`,weight:.6},{name:`domain`,weight:.4}],threshold:.1,ignoreLocation:!0,includeScore:!0,minMatchCharLength:3}),F}function L(e){let t=e.split(/\s+/).filter(Boolean),n=t[t.length-1]||``;return n.length<3?[]:I().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).slice(0,N).map(({item:e})=>({domain:e.domain,name:e.name,favicon:`https://www.google.com/s2/favicons?domain=${encodeURIComponent(e.domain)}&sz=64`,rank:e.rank}))}async function R(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(M,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 z(){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):j;try{let e=await R(o,n,r),t=L(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 B(){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},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 V(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})}}}function H(e){return{POST:async t=>{try{let{text:n,prompt:r}=await t.json();if(!n||typeof n!=`string`)return Response.json({error:`Text is required and must be a string`},{status:400});let i=e.getEnv(`GROQ_API_KEY`);if(!i)return console.error(`GROQ_API_KEY is not configured`),Response.json({error:`AI service is not configured. Please contact the administrator.`},{status:500});let a=e.createGroq({apiKey:i})(`llama-3.3-70b-versatile`),o=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:
20
+ 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 h(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 g(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 _(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 v(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=n.get(`lang`)||`en-US`,c=n.get(`safesearch`)===`true`,l=n.get(`recency`)||void 0,u=n.get(`publicInstances`)===`true`;if(!r)return Response.json({error:`Query parameter is required`},{status:400});let d=Date.now();try{let e=await(0,a.searchWeb)(r,{category:i,recency:l,safesearch:c,maxRetries:6,privateSearxng:!u&&t,proxy:``,lang:s,page:o});e&&(Array.isArray(e)?e.length>0:e.results&&e.results.length>0)||(e=await(0,a.searchWeb)(r,{category:i,recency:l,safesearch:c,maxRetries:6,privateSearxng:!1,proxy:``,lang:s,page:o}));let n=Date.now()-d;return e?Array.isArray(e)?Response.json({results:e,elapsedTime:n}):Response.json({...e,elapsedTime:n}):Response.json({results:[],suggestions:[],elapsedTime:n})}catch(e){return console.error(`Search error:`,e),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},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})}}}function G(e){return{POST:async t=>{try{let{text:n,prompt:r}=await t.json();if(!n||typeof n!=`string`)return Response.json({error:`Text is required and must be a string`},{status:400});let i=e.getEnv(`GROQ_API_KEY`);if(!i)return console.error(`GROQ_API_KEY is not configured`),Response.json({error:`AI service is not configured. Please contact the administrator.`},{status:500});let a=e.createGroq({apiKey:i})(`llama-3.3-70b-versatile`),o=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:
21
21
 
22
- ${n}`,s=(await e.generateText({model:a,prompt:o,temperature:.7})).text.trim();return Response.json({rewrittenText:s})}catch(e){return console.error(`AI rewrite error:`,e),Response.json({error:`Failed to process AI request. Please try again.`},{status:500})}}}}function U(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})}}}}function W(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`}function G(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=W(n.get(`model`)),a;try{a=e.getCloudflareContext().env?.AI}catch{}if(!a)return Response.json({error:`Cloudflare AI binding not available`},{status:503});let o=await r.arrayBuffer(),{text:s}=await a.run(i,{audio:[...new Uint8Array(o)]});return Response.json({text:s,model:i})}catch(e){return console.error(`Transcript error:`,e),Response.json({error:`Failed to transcribe audio`},{status:500})}}}}function K(){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 q=864e5,J=null;function Y(e){return{GET:async t=>{try{let t=Date.now();if(J&&t-J.timestamp<q)return Response.json({...J.result,cached:!0,cacheAge:t-J.timestamp});let n=await e.validateOpenRouterModels();return J={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 J={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.createAgentsHandler=V,exports.createArticleFollowupsHandler=f,exports.createArticleQAHandler=p,exports.createAutocompleteHandler=z,exports.createChatByIdHandler=h,exports.createChatTitleHandler=v,exports.createChatsHandler=m,exports.createChatsSearchHandler=g,exports.createChatsShareHandler=_,exports.createDiscoverHandler=A,exports.createMCPServerByIdHandler=E,exports.createMCPServerToggleHandler=D,exports.createMCPServersHandler=T,exports.createMessagesHandler=x,exports.createProviderByIdHandler=C,exports.createProviderModelsHandler=w,exports.createProvidersHandler=S,exports.createRewriteHandler=H,exports.createSearchHandler=k,exports.createSuggestionsHandler=B,exports.createTestModelsHandler=K,exports.createTranscriptHandler=G,exports.createValidateOpenRouterHandler=Y,exports.createVoiceHandler=U,exports.describeError=b;
22
+ ${n}`,s=(await e.generateText({model:a,prompt:o,temperature:.7})).text.trim();return Response.json({rewrittenText:s})}catch(e){return console.error(`AI rewrite error:`,e),Response.json({error:`Failed to process AI request. Please try again.`},{status:500})}}}}function K(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})}}}}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`}function J(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=q(n.get(`model`)),a;try{a=e.getCloudflareContext().env?.AI}catch{}if(!a)return Response.json({error:`Cloudflare AI binding not available`},{status:503});let o=await r.arrayBuffer(),{text:s}=await a.run(i,{audio:[...new Uint8Array(o)]});return Response.json({text:s,model:i})}catch(e){return console.error(`Transcript error:`,e),Response.json({error:`Failed to transcribe audio`},{status:500})}}}}function Y(){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=f.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,d.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 X=864e5,Z=null;function Q(e){return{GET:async t=>{try{let t=Date.now();if(Z&&t-Z.timestamp<X)return Response.json({...Z.result,cached:!0,cacheAge:t-Z.timestamp});let n=await e.validateOpenRouterModels();return Z={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 Z={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.createAgentsHandler=W,exports.createArticleFollowupsHandler=p,exports.createArticleQAHandler=m,exports.createAutocompleteHandler=H,exports.createChatByIdHandler=g,exports.createChatTitleHandler=y,exports.createChatsHandler=h,exports.createChatsSearchHandler=_,exports.createChatsShareHandler=v,exports.createDiscoverHandler=j,exports.createMCPServerByIdHandler=D,exports.createMCPServerToggleHandler=O,exports.createMCPServersHandler=E,exports.createMessagesHandler=S,exports.createProviderByIdHandler=w,exports.createProviderModelsHandler=T,exports.createProvidersHandler=C,exports.createRewriteHandler=G,exports.createSearchHandler=A,exports.createSuggestionsHandler=U,exports.createTestModelsHandler=Y,exports.createTranscriptHandler=J,exports.createValidateOpenRouterHandler=Q,exports.createVoiceHandler=K,exports.describeError=x;
package/dist/api.mjs CHANGED
@@ -5,12 +5,13 @@ import u from "chat-agent-toolkit/tools/search/titleGeneratorAgent";
5
5
  import { searchSearxng as d, searchWeb as f } from "search-web-api/search/public-searxng";
6
6
  import { searchAutocompleteMulti as p } from "extract-webpage/suggest-next-words/autocomplete-search-engines";
7
7
  import m from "fuse.js";
8
- import h from "domain-rank/data/domain-rank-merged.json";
9
- import g from "chat-agent-toolkit/tools/search/suggestionGeneratorAgent";
10
- import { testProviderModels as _ } from "chat-agent-toolkit/config/model-tester";
11
- import { LANGUAGE_MODELS as v } from "chat-agent-toolkit/config/language-models-database";
8
+ import { parse as h } from "tldts";
9
+ import g from "domain-rank/data/domain-rank-merged.json";
10
+ import _ from "chat-agent-toolkit/tools/search/suggestionGeneratorAgent";
11
+ import { testProviderModels as v } from "chat-agent-toolkit/config/model-tester";
12
+ import { LANGUAGE_MODELS as y } from "chat-agent-toolkit/config/language-models-database";
12
13
  //#region src/api/handlers/article-followups.ts
13
- function y(n) {
14
+ function b(n) {
14
15
  return async (n) => {
15
16
  try {
16
17
  let { article: r, chatHistory: i = [], maxQuestions: a = 5, chatModel: o } = await n.json();
@@ -52,7 +53,7 @@ Generate ${a} follow-up questions that would help readers dive deeper into this
52
53
  }
53
54
  //#endregion
54
55
  //#region src/api/handlers/article-qa.ts
55
- function b(n) {
56
+ function x(n) {
56
57
  return async (n) => {
57
58
  try {
58
59
  let { article: r, question: i, chatHistory: a = [], chatModel: o } = await n.json();
@@ -94,7 +95,7 @@ Please provide a helpful answer based on the article content above.`, { text: d
94
95
  }
95
96
  //#endregion
96
97
  //#region src/api/handlers/chats.ts
97
- function x(e) {
98
+ function S(e) {
98
99
  let { chats: t, messages: o } = e.schema;
99
100
  return {
100
101
  GET: async (a) => {
@@ -131,7 +132,7 @@ function x(e) {
131
132
  }
132
133
  };
133
134
  }
134
- function S(e) {
135
+ function ee(e) {
135
136
  let { chats: t, messages: r } = e.schema;
136
137
  return {
137
138
  GET: async (n, { params: a }) => {
@@ -237,7 +238,7 @@ function w(e) {
237
238
  }
238
239
  //#endregion
239
240
  //#region src/api/handlers/chat-title.ts
240
- function ee(e) {
241
+ function te(e) {
241
242
  let { chats: n } = e.schema;
242
243
  return { POST: async (r) => {
243
244
  try {
@@ -571,7 +572,7 @@ var L = [
571
572
  "google",
572
573
  "duckduckgo",
573
574
  "wikipedia"
574
- ], R = 3, z = 3, B = Object.entries(h).map(([e, t]) => ({
575
+ ], R = 3, z = 3, B = Object.entries(g).map(([e, t]) => ({
575
576
  domain: e,
576
577
  name: typeof t?.[0] == "string" ? t[0] : "",
577
578
  rank: typeof t?.[1] == "number" ? t[1] : 2 ** 53 - 1
@@ -591,16 +592,25 @@ function H() {
591
592
  minMatchCharLength: 3
592
593
  }), V;
593
594
  }
594
- function U(e) {
595
+ function U(e, t, n) {
596
+ return {
597
+ domain: e,
598
+ name: t,
599
+ favicon: `https://www.google.com/s2/favicons?domain=${encodeURIComponent(e)}&sz=64`,
600
+ rank: n
601
+ };
602
+ }
603
+ function W(e) {
604
+ let t = h(e);
605
+ return t.domain && t.isIcann ? t.hostname : null;
606
+ }
607
+ function G(e) {
595
608
  let t = e.split(/\s+/).filter(Boolean), n = t[t.length - 1] || "";
596
- return n.length < 3 ? [] : H().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).slice(0, z).map(({ item: e }) => ({
597
- domain: e.domain,
598
- name: e.name,
599
- favicon: `https://www.google.com/s2/favicons?domain=${encodeURIComponent(e.domain)}&sz=64`,
600
- rank: e.rank
601
- }));
609
+ if (n.length < 3) return [];
610
+ let r = H().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 }) => U(e.domain, e.name, e.rank)), i = W(n);
611
+ return i && !r.some((e) => e.domain === i) && r.unshift(U(i, "", 2 ** 53 - 1)), r.slice(0, z);
602
612
  }
603
- async function W(e, t, n) {
613
+ async function K(e, t, n) {
604
614
  let r = await p(e, t, n);
605
615
  if (r.length > 0) return r;
606
616
  let i = t.split(/\s+/).filter(Boolean), a = Math.min(R, i.length - 1);
@@ -617,7 +627,7 @@ async function W(e, t, n) {
617
627
  }
618
628
  return [];
619
629
  }
620
- function G() {
630
+ function q() {
621
631
  return { GET: async (e) => {
622
632
  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);
623
633
  if (!n) return Response.json({
@@ -626,7 +636,7 @@ function G() {
626
636
  });
627
637
  let o = i ? i.split(",").map((e) => e.trim()).filter(Boolean) : L;
628
638
  try {
629
- let e = await W(o, n, r), t = U(n);
639
+ let e = await K(o, n, r), t = G(n);
630
640
  return Response.json({
631
641
  suggestions: e.slice(0, a),
632
642
  domains: t
@@ -641,12 +651,12 @@ function G() {
641
651
  }
642
652
  //#endregion
643
653
  //#region src/api/handlers/suggestions.ts
644
- function K() {
654
+ function J() {
645
655
  return { POST: async (e) => {
646
656
  let n = await e.json(), r = n.chatHistory.filter((e) => e.role === "user" || e.role === "assistant").map((e) => ({
647
657
  role: e.role,
648
658
  content: String(e.content ?? "")
649
- })), i = await new t().loadChatModel(n.chatModel.providerId, n.chatModel.key), a = (await g({
659
+ })), i = await new t().loadChatModel(n.chatModel.providerId, n.chatModel.key), a = (await _({
650
660
  chat_history: r,
651
661
  maxQuestions: n.maxQuestions
652
662
  }, i)).flatMap((e) => (e.match(/\?/g) || []).length > 1 ? e.split(/\?/).map((e) => e.trim()).filter((e) => e.length > 0).map((e) => e + "?") : [e]);
@@ -655,7 +665,7 @@ function K() {
655
665
  }
656
666
  //#endregion
657
667
  //#region src/api/handlers/agents.ts
658
- function q(e) {
668
+ function Y(e) {
659
669
  return { POST: async (t) => {
660
670
  let n;
661
671
  try {
@@ -670,7 +680,7 @@ function q(e) {
670
680
  }
671
681
  //#endregion
672
682
  //#region src/api/handlers/rewrite.ts
673
- function J(e) {
683
+ function X(e) {
674
684
  return { POST: async (t) => {
675
685
  try {
676
686
  let { text: n, prompt: r } = await t.json();
@@ -692,7 +702,7 @@ ${n}`, s = (await e.generateText({
692
702
  }
693
703
  //#endregion
694
704
  //#region src/api/handlers/voice.ts
695
- function Y(e) {
705
+ function Z(e) {
696
706
  return { POST: async (t) => {
697
707
  let n, r, i;
698
708
  try {
@@ -727,15 +737,15 @@ function Y(e) {
727
737
  }
728
738
  //#endregion
729
739
  //#region src/api/handlers/transcript.ts
730
- function X(e) {
740
+ function Q(e) {
731
741
  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";
732
742
  }
733
- function Z(e) {
743
+ function ne(e) {
734
744
  return { POST: async (t) => {
735
745
  try {
736
746
  let n = await t.formData(), r = n.get("file");
737
747
  if (!r || !(r instanceof File)) return Response.json({ error: "file is required" }, { status: 400 });
738
- let i = X(n.get("model")), a;
748
+ let i = Q(n.get("model")), a;
739
749
  try {
740
750
  a = e.getCloudflareContext().env?.AI;
741
751
  } catch {}
@@ -752,15 +762,15 @@ function Z(e) {
752
762
  }
753
763
  //#endregion
754
764
  //#region src/api/handlers/test-models.ts
755
- function Q() {
765
+ function re() {
756
766
  return { POST: async (e) => {
757
767
  try {
758
768
  let { providerType: t, apiKey: n, onlyFree: r = !0 } = await e.json();
759
769
  if (!t) return Response.json({ error: "Provider type is required" }, { status: 400 });
760
770
  if (!n) return Response.json({ error: "API key is required" }, { status: 400 });
761
- let i = v.find((e) => e.provider.toLowerCase() === t.toLowerCase());
771
+ let i = y.find((e) => e.provider.toLowerCase() === t.toLowerCase());
762
772
  if (!i) return Response.json({ error: `Provider ${t} not found` }, { status: 404 });
763
- let a = await _(t, n, i.models, {
773
+ let a = await v(t, n, i.models, {
764
774
  onlyFree: r,
765
775
  concurrency: 3,
766
776
  timeout: 15e3
@@ -773,13 +783,13 @@ function Q() {
773
783
  }
774
784
  //#endregion
775
785
  //#region src/api/handlers/validate-openrouter.ts
776
- var te = 864e5, $ = null;
777
- function ne(e) {
786
+ var ie = 864e5, $ = null;
787
+ function ae(e) {
778
788
  return {
779
789
  GET: async (t) => {
780
790
  try {
781
791
  let t = Date.now();
782
- if ($ && t - $.timestamp < te) return Response.json({
792
+ if ($ && t - $.timestamp < ie) return Response.json({
783
793
  ...$.result,
784
794
  cached: !0,
785
795
  cacheAge: t - $.timestamp
@@ -813,4 +823,4 @@ function ne(e) {
813
823
  };
814
824
  }
815
825
  //#endregion
816
- export { q as createAgentsHandler, y as createArticleFollowupsHandler, b as createArticleQAHandler, G as createAutocompleteHandler, S as createChatByIdHandler, ee as createChatTitleHandler, x as createChatsHandler, C as createChatsSearchHandler, w as createChatsShareHandler, I as createDiscoverHandler, M as createMCPServerByIdHandler, N as createMCPServerToggleHandler, j as createMCPServersHandler, D as createMessagesHandler, k as createProviderByIdHandler, A as createProviderModelsHandler, O as createProvidersHandler, J as createRewriteHandler, F as createSearchHandler, K as createSuggestionsHandler, Q as createTestModelsHandler, Z as createTranscriptHandler, ne as createValidateOpenRouterHandler, Y as createVoiceHandler, E as describeError };
826
+ export { Y as createAgentsHandler, b as createArticleFollowupsHandler, x as createArticleQAHandler, q as createAutocompleteHandler, ee as createChatByIdHandler, te as createChatTitleHandler, S as createChatsHandler, C as createChatsSearchHandler, w as createChatsShareHandler, I as createDiscoverHandler, M as createMCPServerByIdHandler, N as createMCPServerToggleHandler, j as createMCPServersHandler, D as createMessagesHandler, k as createProviderByIdHandler, A as createProviderModelsHandler, O as createProvidersHandler, X as createRewriteHandler, F as createSearchHandler, J as createSuggestionsHandler, re as createTestModelsHandler, ne as createTranscriptHandler, ae as createValidateOpenRouterHandler, Z as createVoiceHandler, E as describeError };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "research-agent-ui",
3
3
  "description": "Chat research agent UI: conversation window, article reader, search config, file uploads, and chat history",
4
- "version": "0.1.101",
4
+ "version": "0.1.102",
5
5
  "author": "vtempest",
6
6
  "repository": {
7
7
  "type": "git",
@@ -80,13 +80,13 @@
80
80
  "@radix-ui/react-tooltip": "^1.2.9",
81
81
  "@ricky0123/vad-web": "^0.0.30",
82
82
  "ai": "^5.0.0",
83
- "chat-agent-toolkit": "^1.2.229",
83
+ "chat-agent-toolkit": "^1.2.230",
84
84
  "class-variance-authority": "^0.7.1",
85
85
  "clsx": "^2.1.1",
86
- "domain-rank": "^0.1.218",
86
+ "domain-rank": "^0.1.219",
87
87
  "dompurify": "^3.4.9",
88
88
  "drizzle-orm": "^0.45.2",
89
- "extract-webpage": "^1.2.229",
89
+ "extract-webpage": "^1.2.230",
90
90
  "framer-motion": "^12.40.0",
91
91
  "fuse.js": "^7.1.0",
92
92
  "grab-url": "^1.6.22",
@@ -96,16 +96,17 @@
96
96
  "markdown-to-jsx": "^9.8.2",
97
97
  "motion": "^12.40.0",
98
98
  "quantum-sphere-loading-icon": "^1.0.3",
99
- "qwksearch-api-client": "^0.9.176",
99
+ "qwksearch-api-client": "^0.9.177",
100
100
  "react-icons": "^5.6.0",
101
101
  "react-native-app-buttons": "^0.1.4",
102
102
  "react-textarea-autosize": "^8.5.9",
103
103
  "trending-news-api": "^0.1.0",
104
- "use-weather-forecast": "^0.1.46",
104
+ "use-weather-forecast": "^0.1.47",
105
105
  "search-web-api": "^1.0.83",
106
106
  "sonner": "^2.0.7",
107
107
  "streamdown": "^2.5.0",
108
108
  "tailwind-merge": "^3.6.0",
109
+ "tldts": "^7.4.2",
109
110
  "turndown": "^7.2.4",
110
111
  "use-voice-control": "^0.1.37"
111
112
  },