research-agent-ui 0.1.293 → 0.1.294
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-25tRTnpl.cjs +2 -0
- package/dist/ArticleExtractPanel-D_y16YHG.js +389 -0
- package/dist/ChatConversationThread-BIJ8aNug.js +1428 -0
- package/dist/ChatConversationThread-BoNH0wvs.cjs +17 -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 +161 -208
- 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-GPr1ceY8.js +6165 -0
- package/dist/src-ebmQu_if.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 +54 -51
- 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
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
|
+
/** How the reader should behave once the page is read. */
|
|
3
|
+
export interface OpenPanelOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Write questions about the page as soon as its text is in, when it has
|
|
6
|
+
* none cached — so opening it lands on something to ask, not a blank prompt.
|
|
7
|
+
*/
|
|
8
|
+
suggestQuestions?: boolean;
|
|
9
|
+
}
|
|
2
10
|
interface ExtractPanelContextType {
|
|
3
11
|
isOpen: boolean;
|
|
4
12
|
url: string;
|
|
5
13
|
searchText: string;
|
|
14
|
+
/** Set by the last `openPanel` call; see {@link OpenPanelOptions.suggestQuestions}. */
|
|
15
|
+
suggestQuestions: boolean;
|
|
6
16
|
panelWidth: number;
|
|
7
17
|
setIsOpen: (isOpen: boolean) => void;
|
|
8
18
|
setUrl: (url: string) => void;
|
|
9
19
|
setSearchText: (searchText: string) => void;
|
|
10
20
|
setPanelWidth: (width: number) => void;
|
|
11
|
-
openPanel: (url: string, searchText?: string) => void;
|
|
21
|
+
openPanel: (url: string, searchText?: string, options?: OpenPanelOptions) => void;
|
|
12
22
|
closePanel: () => void;
|
|
13
23
|
}
|
|
14
24
|
export declare const useExtractPanel: () => ExtractPanelContextType;
|
|
25
|
+
/**
|
|
26
|
+
* Like {@link useExtractPanel}, but `undefined` outside an
|
|
27
|
+
* `ExtractPanelProvider` instead of throwing — for components (the homepage
|
|
28
|
+
* widgets) that offer the reader when a host provides one and work without it.
|
|
29
|
+
*/
|
|
30
|
+
export declare const useOptionalExtractPanel: () => ExtractPanelContextType;
|
|
15
31
|
export declare const ExtractPanelProvider: React.FC<{
|
|
16
32
|
children: ReactNode;
|
|
17
33
|
}>;
|
|
@@ -3,6 +3,7 @@ import { Section } from '../../../hooks/useChat';
|
|
|
3
3
|
interface AssistantMessageActionsProps {
|
|
4
4
|
section: Section;
|
|
5
5
|
speechStatus: string;
|
|
6
|
+
isLoadingTTS?: boolean;
|
|
6
7
|
start: () => void;
|
|
7
8
|
stop: () => void;
|
|
8
9
|
handleOpenInLLM: (platform: string) => void;
|
|
@@ -11,5 +12,5 @@ interface AssistantMessageActionsProps {
|
|
|
11
12
|
* Component for message actions related to the assistant's response.
|
|
12
13
|
* Includes rewrite, copy, text-to-speech, export, and external LLM links.
|
|
13
14
|
*/
|
|
14
|
-
declare const AssistantMessageActions: ({ section, speechStatus, start, stop, handleOpenInLLM, }: AssistantMessageActionsProps) => React.JSX.Element;
|
|
15
|
+
declare const AssistantMessageActions: ({ section, speechStatus, isLoadingTTS, start, stop, handleOpenInLLM, }: AssistantMessageActionsProps) => React.JSX.Element;
|
|
15
16
|
export default AssistantMessageActions;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Helper functions providing randomized background artwork URLs and time-of-day greeting strings for the chat homepage.
|
|
3
3
|
*/
|
|
4
|
+
/** Every background artwork, as the full Imgur URL. */
|
|
5
|
+
export declare const BACKGROUND_ARTWORKS: readonly string[];
|
|
4
6
|
/**
|
|
5
7
|
* Gets a random artistic background about graph theory
|
|
6
|
-
* and collective consciousness
|
|
8
|
+
* and collective consciousness
|
|
7
9
|
* @returns {string} Imgur URL of random artistic background
|
|
8
10
|
*/
|
|
9
11
|
export declare function getBackgroundArtwork(): string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** The Cache Storage bucket the artwork lives in. Bump to drop old entries. */
|
|
2
|
+
export declare const BACKGROUND_CACHE_NAME = "qwksearch-background-art-v1";
|
|
3
|
+
/** The `localStorage` key holding the URLs in the cache, oldest first. */
|
|
4
|
+
export declare const BACKGROUND_CACHE_LIST_KEY = "backgroundArtCache";
|
|
5
|
+
/**
|
|
6
|
+
* How many pieces are kept. Once full, the homepage rotates through these and
|
|
7
|
+
* stops downloading, since some of the pieces are multi-megabyte video.
|
|
8
|
+
*/
|
|
9
|
+
export declare const MAX_CACHED_BACKGROUNDS = 10;
|
|
10
|
+
/** A piece larger than this is still shown, but not stored. */
|
|
11
|
+
export declare const MAX_CACHED_BACKGROUND_BYTES: number;
|
|
12
|
+
/**
|
|
13
|
+
* The cached URLs, oldest first. Anything that is not (or is no longer) one of
|
|
14
|
+
* the artworks is dropped, so a stale or hand-edited entry can never be loaded.
|
|
15
|
+
*/
|
|
16
|
+
export declare function readCachedBackgroundList(): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Records `url` as cached (most recent last) and returns the URLs that fell off
|
|
19
|
+
* the end of the list, which the caller deletes from Cache Storage.
|
|
20
|
+
*/
|
|
21
|
+
export declare function rememberCachedBackground(url: string): string[];
|
|
22
|
+
/** Drops `url` from the list, e.g. when its cache entry has gone missing. */
|
|
23
|
+
export declare function forgetCachedBackground(url: string): void;
|
|
24
|
+
/** A random cached piece other than `exclude`, or `null` if there is none. */
|
|
25
|
+
export declare function pickCachedBackground(exclude?: string | null): string | null;
|
|
26
|
+
/** A random piece that is not cached yet, or `null` once every one is. */
|
|
27
|
+
export declare function pickUncachedBackground(): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Reads a cached piece back as an object URL the page can display, without
|
|
30
|
+
* touching the network. Returns `null` if it is not actually in the cache, in
|
|
31
|
+
* which case it is also dropped from the list.
|
|
32
|
+
*/
|
|
33
|
+
export declare function loadCachedBackground(url: string): Promise<string | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Downloads a piece, stores it and records it in the list, evicting the oldest
|
|
36
|
+
* past {@link MAX_CACHED_BACKGROUNDS}. Returns what the page should display:
|
|
37
|
+
* an object URL of the download, or the plain URL where it cannot be cached
|
|
38
|
+
* (no Cache Storage, or the fetch was refused), so the element loads it from
|
|
39
|
+
* the network as it always did. Returns `null` for a failed download.
|
|
40
|
+
*/
|
|
41
|
+
export declare function cacheBackground(url: string): Promise<string | null>;
|
|
@@ -14,10 +14,11 @@ interface FooterProps {
|
|
|
14
14
|
/**
|
|
15
15
|
* Footer component that displays a list of links with optional icons.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* The links render as a single compact line at every width, in normal flow,
|
|
18
|
+
* so the parent decides where it sits (the homepage puts it directly under
|
|
19
|
+
* the weather widget). Below the `sm` breakpoint the icons
|
|
20
|
+
* are dropped and the labels shrink so all of the links fit on one line on a
|
|
21
|
+
* phone.
|
|
21
22
|
*
|
|
22
23
|
* @param listFooterLinks - Array of footer links with their properties
|
|
23
24
|
* @param optionShowIcons - Whether to show icons next to links (default: true)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import Footer from './Footer';
|
|
3
3
|
/**
|
|
4
|
-
* `Footer` renders a compact bar of links (with optional Lucide icons)
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* `Footer` renders a compact bar of links (with optional Lucide icons) in the
|
|
5
|
+
* normal flow, on a single line at every width; below `sm` the
|
|
6
|
+
* icons are hidden so the labels still fit. `icon` values are Lucide icon names.
|
|
7
7
|
*/
|
|
8
8
|
declare const meta: Meta<typeof Footer>;
|
|
9
9
|
export default meta;
|
package/dist/config.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={appName:`QwkSearch`,defaultSummarizePrompt:`Summarize in bullet points and bold topics`,maxArticleLength:1500,downloadChromeUrl:`https://chromewebstore.google.com/detail/tab-manager-ai/manhemnhmipdhdpabojcplebckhckeko`,downloadWindowsStoreId:`9PCGF9GNK460`,footerLinks:[],googleApiKey:``,googleAppId:``,getAutoMediaSearch:()=>!0,appIconUrl:`/apple-touch-icon.png`,trendingNewsApiUrl:`/api/news/trending`,trendingNewsSettingsUrl:`/api/news/settings`};function t(t){Object.assign(e,t)}exports.configureResearchAgentUI=t,exports.researchAgentUIConfig=e;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={appName:`QwkSearch`,defaultSummarizePrompt:`Summarize in bullet points and bold topics`,maxArticleLength:1500,downloadChromeUrl:`https://chromewebstore.google.com/detail/tab-manager-ai/manhemnhmipdhdpabojcplebckhckeko`,downloadWindowsStoreId:`9PCGF9GNK460`,footerLinks:[],googleApiKey:``,googleAppId:``,getAutoMediaSearch:()=>!0,appIconUrl:`/apple-touch-icon.png`,trendingNewsApiUrl:`/api/news/trending`,trendingNewsSettingsUrl:`/api/news/settings`,educationPlaylistsApiUrl:`/api/learn`,educationPlaylistsPageUrl:`/learn`};function t(t){Object.assign(e,t)}exports.configureResearchAgentUI=t,exports.researchAgentUIConfig=e;
|
package/dist/config.d.ts
CHANGED
|
@@ -79,6 +79,15 @@ export interface ResearchAgentUIConfig {
|
|
|
79
79
|
* the local settings alone.
|
|
80
80
|
*/
|
|
81
81
|
trendingNewsSettingsUrl: string;
|
|
82
|
+
/**
|
|
83
|
+
* The education-playlists planner endpoint (`education-playlists/server`
|
|
84
|
+
* mounted by the host). Defaults to this app's `/api/learn`. Set it to an
|
|
85
|
+
* empty string on a host without that route: the homepage widget then plans
|
|
86
|
+
* locally from its bundled catalog, without AI.
|
|
87
|
+
*/
|
|
88
|
+
educationPlaylistsApiUrl: string;
|
|
89
|
+
/** Full-page education playlists view the homepage card links to. Empty hides the link. */
|
|
90
|
+
educationPlaylistsPageUrl: string;
|
|
82
91
|
/**
|
|
83
92
|
* Requests that the settings UI be opened. Lets the consuming app render
|
|
84
93
|
* settings in a modal (e.g. on large desktop screens) instead of navigating
|
package/dist/config.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/config.ts
|
|
2
2
|
var e = {
|
|
3
3
|
appName: "QwkSearch",
|
|
4
4
|
defaultSummarizePrompt: "Summarize in bullet points and bold topics",
|
|
@@ -11,10 +11,11 @@ var e = {
|
|
|
11
11
|
getAutoMediaSearch: () => !0,
|
|
12
12
|
appIconUrl: "/apple-touch-icon.png",
|
|
13
13
|
trendingNewsApiUrl: "/api/news/trending",
|
|
14
|
-
trendingNewsSettingsUrl: "/api/news/settings"
|
|
14
|
+
trendingNewsSettingsUrl: "/api/news/settings",
|
|
15
|
+
educationPlaylistsApiUrl: "/api/learn",
|
|
16
|
+
educationPlaylistsPageUrl: "/learn"
|
|
15
17
|
};
|
|
16
18
|
function t(t) {
|
|
17
19
|
Object.assign(e, t);
|
|
18
20
|
}
|
|
19
|
-
//#endregion
|
|
20
21
|
export { t as configureResearchAgentUI, e as researchAgentUIConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require("./rolldown-runtime-BocRIvOZ.cjs");let t=require("react");t=e.t(t,1);let n=require("react/jsx-runtime"),r=require("lucide-react"),i=require("clsx"),a=require("tailwind-merge"),o=require("@radix-ui/react-dialog");o=e.t(o,1);function s(...e){return(0,a.twMerge)((0,i.clsx)(e))}var c=e=>{let t=new Date(e);return Number.isNaN(t.getTime())?``:t.toLocaleTimeString([],{hour:`numeric`,minute:`2-digit`})},l=(e,t)=>{e=new Date(e),t=new Date(t);let n=Math.floor(Math.abs(t.getTime()-e.getTime())/1e3);return n<60?`${n} second${n===1?``:`s`}`:n<3600?`${Math.floor(n/60)} minute${Math.floor(n/60)===1?``:`s`}`:n<86400?`${Math.floor(n/3600)} hour${Math.floor(n/3600)===1?``:`s`}`:n<31536e3?`${Math.floor(n/86400)} day${Math.floor(n/86400)===1?``:`s`}`:`${Math.floor(n/31536e3)} year${Math.floor(n/31536e3)===1?``:`s`}`};function u({...e}){return(0,n.jsx)(o.Root,{"data-slot":`dialog`,...e})}function d({...e}){return(0,n.jsx)(o.Trigger,{"data-slot":`dialog-trigger`,...e})}function f({...e}){return(0,n.jsx)(o.Portal,{"data-slot":`dialog-portal`,...e})}function p({className:e,...t}){return(0,n.jsx)(o.Overlay,{"data-slot":`dialog-overlay`,className:s(`data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 backdrop-blur-xs`,e),...t})}function m({className:e,children:t,hideCloseButton:i=!1,...a}){return(0,n.jsxs)(f,{"data-slot":`dialog-portal`,children:[(0,n.jsx)(p,{}),(0,n.jsxs)(o.Content,{"data-slot":`dialog-content`,"aria-describedby":a[`aria-describedby`]??void 0,className:s(`z-[9999] bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl border p-6 shadow-lg duration-200`,e),...a,children:[t,!i&&(0,n.jsxs)(o.Close,{className:`ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,children:[(0,n.jsx)(r.XIcon,{}),(0,n.jsx)(`span`,{className:`sr-only`,children:`Close`})]})]})]})}function h({className:e,...t}){return(0,n.jsx)(o.Title,{"data-slot":`dialog-title`,className:s(`text-lg leading-none font-semibold`,e),...t})}function g({className:e,...t}){return(0,n.jsx)(o.Description,{"data-slot":`dialog-description`,className:s(`text-muted-foreground text-sm`,e),...t})}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return u}});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import "react";
|
|
2
|
+
import { jsx as e, jsxs as t } from "react/jsx-runtime";
|
|
3
|
+
import { XIcon as n } from "lucide-react";
|
|
4
|
+
import { clsx as r } from "clsx";
|
|
5
|
+
import { twMerge as i } from "tailwind-merge";
|
|
6
|
+
import * as a from "@radix-ui/react-dialog";
|
|
7
|
+
// src/lib/utils.ts
|
|
8
|
+
function o(...e) {
|
|
9
|
+
return i(r(e));
|
|
10
|
+
}
|
|
11
|
+
var s = (e) => {
|
|
12
|
+
let t = new Date(e);
|
|
13
|
+
return Number.isNaN(t.getTime()) ? "" : t.toLocaleTimeString([], {
|
|
14
|
+
hour: "numeric",
|
|
15
|
+
minute: "2-digit"
|
|
16
|
+
});
|
|
17
|
+
}, c = (e, t) => {
|
|
18
|
+
e = new Date(e), t = new Date(t);
|
|
19
|
+
let n = Math.floor(Math.abs(t.getTime() - e.getTime()) / 1e3);
|
|
20
|
+
return n < 60 ? `${n} second${n === 1 ? "" : "s"}` : n < 3600 ? `${Math.floor(n / 60)} minute${Math.floor(n / 60) === 1 ? "" : "s"}` : n < 86400 ? `${Math.floor(n / 3600)} hour${Math.floor(n / 3600) === 1 ? "" : "s"}` : n < 31536e3 ? `${Math.floor(n / 86400)} day${Math.floor(n / 86400) === 1 ? "" : "s"}` : `${Math.floor(n / 31536e3)} year${Math.floor(n / 31536e3) === 1 ? "" : "s"}`;
|
|
21
|
+
};
|
|
22
|
+
// src/ui/dialog.tsx
|
|
23
|
+
function l({ ...t }) {
|
|
24
|
+
return /* @__PURE__ */ e(a.Root, {
|
|
25
|
+
"data-slot": "dialog",
|
|
26
|
+
...t
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function u({ ...t }) {
|
|
30
|
+
return /* @__PURE__ */ e(a.Trigger, {
|
|
31
|
+
"data-slot": "dialog-trigger",
|
|
32
|
+
...t
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function d({ ...t }) {
|
|
36
|
+
return /* @__PURE__ */ e(a.Portal, {
|
|
37
|
+
"data-slot": "dialog-portal",
|
|
38
|
+
...t
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function f({ className: t, ...n }) {
|
|
42
|
+
return /* @__PURE__ */ e(a.Overlay, {
|
|
43
|
+
"data-slot": "dialog-overlay",
|
|
44
|
+
className: o("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 backdrop-blur-xs", t),
|
|
45
|
+
...n
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function p({ className: r, children: i, hideCloseButton: s = !1, ...c }) {
|
|
49
|
+
return /* @__PURE__ */ t(d, {
|
|
50
|
+
"data-slot": "dialog-portal",
|
|
51
|
+
children: [/* @__PURE__ */ e(f, {}), /* @__PURE__ */ t(a.Content, {
|
|
52
|
+
"data-slot": "dialog-content",
|
|
53
|
+
"aria-describedby": c["aria-describedby"] ?? void 0,
|
|
54
|
+
className: o("z-[9999] bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl border p-6 shadow-lg duration-200", r),
|
|
55
|
+
...c,
|
|
56
|
+
children: [i, !s && /* @__PURE__ */ t(a.Close, {
|
|
57
|
+
className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
58
|
+
children: [/* @__PURE__ */ e(n, {}), /* @__PURE__ */ e("span", {
|
|
59
|
+
className: "sr-only",
|
|
60
|
+
children: "Close"
|
|
61
|
+
})]
|
|
62
|
+
})]
|
|
63
|
+
})]
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function m({ className: t, ...n }) {
|
|
67
|
+
return /* @__PURE__ */ e(a.Title, {
|
|
68
|
+
"data-slot": "dialog-title",
|
|
69
|
+
className: o("text-lg leading-none font-semibold", t),
|
|
70
|
+
...n
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function h({ className: t, ...n }) {
|
|
74
|
+
return /* @__PURE__ */ e(a.Description, {
|
|
75
|
+
"data-slot": "dialog-description",
|
|
76
|
+
className: o("text-muted-foreground text-sm", t),
|
|
77
|
+
...n
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
export { u as a, c, m as i, p as n, o, h as r, s, l as t };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { KokoroLoadProgress } from '../../lib/kokoro';
|
|
1
2
|
type SpeechStatus = 'idle' | 'loading' | 'generating' | 'playing' | 'error';
|
|
2
3
|
interface UseKokoroTTSOptions {
|
|
3
4
|
autoPreload?: boolean;
|
|
@@ -8,6 +9,7 @@ export declare function useKokoroTTS(text: string, options?: UseKokoroTTSOptions
|
|
|
8
9
|
voices: string[];
|
|
9
10
|
selectedVoice: string;
|
|
10
11
|
error: string;
|
|
12
|
+
progress: KokoroLoadProgress;
|
|
11
13
|
warmupModel: () => Promise<void>;
|
|
12
14
|
speak: () => Promise<void>;
|
|
13
15
|
stop: () => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type SpeechStatus = "started" | "stopped";
|
|
1
|
+
type SpeechStatus = "started" | "stopped" | "loading";
|
|
2
2
|
interface TextToSpeechOptions {
|
|
3
3
|
/** Enable mic-based interruption detection while TTS is playing. Only activates if mic permission is already granted. */
|
|
4
4
|
enableInterrupt?: boolean;
|
|
@@ -7,6 +7,7 @@ interface TextToSpeechOptions {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function useTextToSpeech(text: string, options?: TextToSpeechOptions): {
|
|
9
9
|
speechStatus: SpeechStatus;
|
|
10
|
+
isLoading: boolean;
|
|
10
11
|
start: () => Promise<void>;
|
|
11
12
|
stop: () => void;
|
|
12
13
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./config.cjs"),t=require("./src-
|
|
1
|
+
"use client";"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./config.cjs"),t=require("./src-ebmQu_if.cjs"),n=require("./tooltip-DmUO6ZUz.cjs"),r=require("./dialog-7GDz0sWx.cjs");exports.ARTICLE_TOOLBAR_SHORTCUTS=t.D,exports.ArticleAIResponse=t.w,exports.ArticleActionButtons=t.O,exports.ArticleContent=t.S,exports.ArticleFollowupQuestions=t.T,exports.ArticlePanelHeader=t.A,exports.ArticlePromptInput=t.E,exports.ArticleReaderMount=t.R,exports.CategoryDock=t.c,exports.ChatInputBox=t.U,exports.ChatProvider=t.$,exports.ChatWindow=t.L,exports.CookieConsent=t.s,exports.ExtractPanelProvider=n.i,exports.HistoryDialogs=t.B,exports.HistoryDropdown=t.z,exports.KokoroVoiceSelector=t.u,exports.LexicalArticleViewer=t.C,exports.MainViewProvider=t.y,exports.QWKSEARCH_DEFAULT_ORIGIN=t.j,exports.QwkSearchApp=t.n,exports.QwkSearchProviders=t.r,exports.SPOTLIGHT_LINKS=t.v,exports.SPOTLIGHT_PREFIXES=t.h,exports.SessionProvider=n.s,exports.SpotlightPalette=t.p,exports.UnifiedMarkdown=t.x,exports.VoiceSettingsPanel=t.l,exports.buildConnectStartUrl=t.M,exports.cn=r.o,exports.configureResearchAgentUI=e.configureResearchAgentUI,exports.createQwkSearchConnectAuthClient=t.N,exports.formatMessageTime=r.s,exports.formatTimeDifference=r.c,exports.formatToolbarShortcut=t.k,exports.getQwkSearchApiKey=t.P,exports.isChunkLoadError=t.i,exports.isQwkSearchApiRequest=t.F,exports.matchSpotlight=t.g,exports.openSpotlight=t.m,exports.parsePrefix=t._,exports.reloadForChunkError=t.a,exports.researchAgentUIConfig=e.researchAgentUIConfig,exports.setQwkSearchApiKey=t.I,exports.useChat=n.u,exports.useChatState=t.et,exports.useChatTabs=t.t,exports.useChunkErrorReload=t.o,exports.useExtractPanel=n.a,exports.useHistoryState=t.H,exports.useKokoroTTS=t.f,exports.useMainView=t.b,exports.useOptionalExtractPanel=n.o,exports.useSession=n.c,exports.useTextToSpeech=t.d;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,11 @@ export type { Message, ChatTurn, UserMessage, AssistantMessage, SourceMessage, S
|
|
|
6
6
|
export { ChatProvider, useChat, useChatState, } from './hooks/useChat';
|
|
7
7
|
export type { ChatContextValue } from './hooks/useChat';
|
|
8
8
|
export { SessionProvider, useSession } from './hooks/useSession';
|
|
9
|
-
export {
|
|
9
|
+
export { createQwkSearchConnectAuthClient, setQwkSearchApiKey, getQwkSearchApiKey, buildConnectStartUrl, isQwkSearchApiRequest, QWKSEARCH_DEFAULT_ORIGIN, } from './lib/qwksearch-connect';
|
|
10
|
+
export type { QwkSearchConnectSession, QwkSearchConnectOptions, QwkSearchConnectAuthClient, } from './lib/qwksearch-connect';
|
|
11
|
+
export { ExtractPanelProvider, useExtractPanel, useOptionalExtractPanel, } from './components/ArticleReader/ExtractPanelContext';
|
|
12
|
+
export type { OpenPanelOptions } from './components/ArticleReader/ExtractPanelContext';
|
|
13
|
+
export { default as ArticleReaderMount } from './components/ArticleReader/ArticleReaderMount';
|
|
10
14
|
export * from './components/ArticleReader';
|
|
11
15
|
export { default as HistoryDropdown } from './components/ChatHistoryDropdown';
|
|
12
16
|
export { HistoryDialogs } from './components/ChatHistoryDropdown/HistoryDialogs';
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
"use client";
|
|
3
3
|
import { configureResearchAgentUI as e, researchAgentUIConfig as t } from "./config.mjs";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { $ as n, A as r, B as i, C as a, D as o, E as s, F as c, H as l, I as u, L as d, M as f, N as p, O as m, P as h, R as g, S as _, T as v, U as y, _ as b, a as x, b as S, c as C, d as w, et as T, f as E, g as D, h as O, i as k, j as A, k as j, l as M, m as N, n as P, o as F, p as I, r as L, s as R, t as z, u as B, v as V, w as H, x as U, y as W, z as G } from "./src-GPr1ceY8.js";
|
|
5
|
+
import { a as K, c as q, i as J, o as Y, s as X, u as Z } from "./tooltip-Bl3IdX-I.js";
|
|
6
|
+
import { c as Q, o as $, s as ee } from "./dialog-Cufn2u50.js";
|
|
7
|
+
export { o as ARTICLE_TOOLBAR_SHORTCUTS, H as ArticleAIResponse, m as ArticleActionButtons, _ as ArticleContent, v as ArticleFollowupQuestions, r as ArticlePanelHeader, s as ArticlePromptInput, g as ArticleReaderMount, C as CategoryDock, y as ChatInputBox, n as ChatProvider, d as ChatWindow, R as CookieConsent, J as ExtractPanelProvider, i as HistoryDialogs, G as HistoryDropdown, B as KokoroVoiceSelector, a as LexicalArticleViewer, W as MainViewProvider, A as QWKSEARCH_DEFAULT_ORIGIN, P as QwkSearchApp, L as QwkSearchProviders, V as SPOTLIGHT_LINKS, O as SPOTLIGHT_PREFIXES, X as SessionProvider, I as SpotlightPalette, U as UnifiedMarkdown, M as VoiceSettingsPanel, f as buildConnectStartUrl, $ as cn, e as configureResearchAgentUI, p as createQwkSearchConnectAuthClient, ee as formatMessageTime, Q as formatTimeDifference, j as formatToolbarShortcut, h as getQwkSearchApiKey, k as isChunkLoadError, c as isQwkSearchApiRequest, D as matchSpotlight, N as openSpotlight, b as parsePrefix, x as reloadForChunkError, t as researchAgentUIConfig, u as setQwkSearchApiKey, Z as useChat, T as useChatState, z as useChatTabs, F as useChunkErrorReload, K as useExtractPanel, l as useHistoryState, E as useKokoroTTS, S as useMainView, Y as useOptionalExtractPanel, q as useSession, w as useTextToSpeech };
|
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
import { AnyFileSource } from '../types/fileSource';
|
|
9
9
|
export type { FileSource, AnyFileSource } from '../types/fileSource';
|
|
10
10
|
export type { FileSourceType, SSHCredentials, S3Credentials, R2Credentials, B2Credentials, GoogleDocsCredentials, TursoDBCredentials, LocalFileSource, SSHFileSource, S3FileSource, R2FileSource, B2FileSource, GoogleDocsFileSource, TursoDBFileSource } from '../types/fileSource';
|
|
11
|
+
/**
|
|
12
|
+
* Dispatched on `window` whenever the saved source list changes, so a mounted
|
|
13
|
+
* sidebar picks up a source added in settings without a reload. The name is
|
|
14
|
+
* shared with the other copy of these helpers (research-agent-ui's
|
|
15
|
+
* `file-sources` and react-reason-editor-sidebar's) — both write the same
|
|
16
|
+
* localStorage key.
|
|
17
|
+
*/
|
|
18
|
+
export declare const FILE_SOURCES_CHANGED_EVENT = "reason-file-sources-changed";
|
|
11
19
|
export declare function getFileSources(): AnyFileSource[];
|
|
12
20
|
export declare function saveFileSources(sources: AnyFileSource[]): void;
|
|
13
21
|
export declare function addFileSource(source: Omit<AnyFileSource, 'id' | 'createdAt' | 'updatedAt'>): AnyFileSource;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The "Google Drive" storage source on the client: connecting
|
|
3
|
+
* Drive with folder access, browsing folders to sync from settings, turning a
|
|
4
|
+
* synced folder's listing into file-tree documents, and the
|
|
5
|
+
* `FileSourceProvider` that hands those to `ReasonDocs`.
|
|
6
|
+
*
|
|
7
|
+
* Everything goes through this app's `/api/doc/google-docs/*` routes, which
|
|
8
|
+
* hold the Google tokens in HTTP-only cookies; no token reaches this code.
|
|
9
|
+
*/
|
|
10
|
+
import type { Document, ExternalDocumentView } from 'react-reason-editor-sidebar';
|
|
11
|
+
import type { FileSourceProvider } from 'react-reason-editor/reason-docs';
|
|
12
|
+
import type { AnyFileSource, GoogleDocsCredentials } from '../types/fileSource';
|
|
13
|
+
/** Base path of the app's Google Drive routes. */
|
|
14
|
+
export declare const GOOGLE_DRIVE_API = "/api/doc/google-docs";
|
|
15
|
+
export declare const GOOGLE_FOLDER = "application/vnd.google-apps.folder";
|
|
16
|
+
/** One Drive file or folder as the folder-tree route returns it. */
|
|
17
|
+
export interface DriveItem {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
mimeType: string;
|
|
21
|
+
parents?: string[];
|
|
22
|
+
webViewLink?: string;
|
|
23
|
+
size?: string;
|
|
24
|
+
modifiedTime?: string;
|
|
25
|
+
}
|
|
26
|
+
/** A folder chosen for sync. `root` stands for all of My Drive. */
|
|
27
|
+
export interface DriveFolderRef {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
}
|
|
31
|
+
/** An error from a Drive route, with the flags the settings UI acts on. */
|
|
32
|
+
export declare class GoogleDriveError extends Error {
|
|
33
|
+
needsReauth: boolean;
|
|
34
|
+
needsFolderAccess: boolean;
|
|
35
|
+
status: number;
|
|
36
|
+
constructor(message: string, status: number, body?: Record<string, unknown>);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Pulls a Drive folder ID out of whatever the user pasted: a folder link
|
|
40
|
+
* (`drive.google.com/drive/folders/<id>`, with or without `/u/0`), an
|
|
41
|
+
* `?id=` link, "My Drive", or a bare ID. Returns `null` when nothing in it
|
|
42
|
+
* looks like a folder.
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseDriveFolderInput(input: string): string | null;
|
|
45
|
+
/** How a Drive file opens in the workspace. */
|
|
46
|
+
export declare function driveDocumentView(mimeType: string): ExternalDocumentView;
|
|
47
|
+
/** The extension that picks a Drive file's icon in the tree. */
|
|
48
|
+
export declare function driveExtension(item: Pick<DriveItem, 'name' | 'mimeType'>): string | undefined;
|
|
49
|
+
/** Document ID for a Drive file in a source: unique even when two sources share a file. */
|
|
50
|
+
export declare const driveDocumentId: (sourceId: string, fileId: string) => string;
|
|
51
|
+
/** Bytes (or the export) of a Drive file, served by the app. */
|
|
52
|
+
export declare const driveContentUrl: (fileId: string) => string;
|
|
53
|
+
/**
|
|
54
|
+
* Turns synced folders' listings into the flat, `parentId`-linked document
|
|
55
|
+
* list the file tree renders. Each synced folder becomes a top-level folder;
|
|
56
|
+
* a file reachable from two synced folders appears once, under the first.
|
|
57
|
+
* Folders sort before files, then by name, the way Drive shows them.
|
|
58
|
+
*/
|
|
59
|
+
export declare function driveTreesToDocuments(sourceId: string, trees: Array<{
|
|
60
|
+
root: DriveItem;
|
|
61
|
+
items: DriveItem[];
|
|
62
|
+
}>): Document[];
|
|
63
|
+
/** The folders a Google Drive source syncs, newest field first. */
|
|
64
|
+
export declare function sourceFolders(credentials: Partial<GoogleDocsCredentials> | undefined): DriveFolderRef[];
|
|
65
|
+
/**
|
|
66
|
+
* Lists every synced folder of a Google Drive source as tree documents. A
|
|
67
|
+
* folder that fails (unshared, deleted) is skipped as long as another one
|
|
68
|
+
* loads; when all of them fail, the first error is thrown.
|
|
69
|
+
*/
|
|
70
|
+
export declare function listGoogleDriveSource(source: AnyFileSource): Promise<Document[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Cleans a Google Docs HTML export for the editor. Google styles text through
|
|
73
|
+
* generated CSS classes (`.c3{font-weight:700}`) in a `<style>` block, which
|
|
74
|
+
* the editor would drop along with the stylesheet — so bold, italic,
|
|
75
|
+
* underline and strikethrough are turned into tags first. Then every class,
|
|
76
|
+
* inline style and id goes, as do Google's `google.com/url?q=` link
|
|
77
|
+
* redirects, leaving plain semantic HTML.
|
|
78
|
+
*/
|
|
79
|
+
export declare function googleDocHtmlToEditorHtml(html: string): string;
|
|
80
|
+
/** Fetches the body of a Drive document that opens in the editor. */
|
|
81
|
+
export declare function loadGoogleDriveDocumentContent(doc: Document): Promise<string>;
|
|
82
|
+
/** Shows Google Drive storage sources in the `ReasonDocs` file tree. */
|
|
83
|
+
export declare const googleDriveSourceProvider: FileSourceProvider;
|
|
84
|
+
/** Whether Drive is connected, and whether the grant covers folder sync. */
|
|
85
|
+
export declare function getGoogleDriveStatus(): Promise<{
|
|
86
|
+
isConnected: boolean;
|
|
87
|
+
canReadFolders: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
/** One folder and the folders directly inside it, for the settings browser. */
|
|
90
|
+
export declare function browseGoogleDriveFolders(parentId?: string): Promise<{
|
|
91
|
+
folder: DriveFolderRef;
|
|
92
|
+
folders: DriveFolderRef[];
|
|
93
|
+
}>;
|
|
94
|
+
/**
|
|
95
|
+
* Connects Google Drive with folder access in a popup. The popup is opened
|
|
96
|
+
* before the consent URL is fetched, inside the click, so popup blockers let
|
|
97
|
+
* it through. Resolves `true` once the callback page reports success and
|
|
98
|
+
* `false` if the user closes the popup first.
|
|
99
|
+
*/
|
|
100
|
+
export declare function connectGoogleDriveFolders(): Promise<boolean>;
|
package/dist/lib/kokoro.d.ts
CHANGED
|
@@ -5,8 +5,20 @@ interface Backend {
|
|
|
5
5
|
dtype: DType;
|
|
6
6
|
}
|
|
7
7
|
export declare function getRecommendedBackend(): Backend;
|
|
8
|
-
export
|
|
9
|
-
|
|
8
|
+
export type KokoroLoadProgress = {
|
|
9
|
+
status: 'initiate' | 'download' | 'progress' | 'progress_total' | 'done' | 'ready';
|
|
10
|
+
name?: string;
|
|
11
|
+
file?: string;
|
|
12
|
+
progress?: number;
|
|
13
|
+
loaded?: number;
|
|
14
|
+
total?: number;
|
|
15
|
+
files?: Record<string, {
|
|
16
|
+
loaded: number;
|
|
17
|
+
total: number;
|
|
18
|
+
}>;
|
|
19
|
+
};
|
|
20
|
+
export declare function preloadKokoro(progressCallback?: (p: KokoroLoadProgress) => void): Promise<any>;
|
|
21
|
+
export declare function getKokoro(progressCallback?: (p: KokoroLoadProgress) => void): Promise<any>;
|
|
10
22
|
export declare function getVoiceList(): Promise<string[]>;
|
|
11
23
|
export declare function getLoadedBackend(): DeviceMode;
|
|
12
24
|
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Default QwkSearch origin the embed's API calls go to. */
|
|
2
|
+
export declare const QWKSEARCH_DEFAULT_ORIGIN = "https://qwksearch.com";
|
|
3
|
+
/** What the host's session endpoint answers. */
|
|
4
|
+
export interface QwkSearchConnectSession {
|
|
5
|
+
connected: boolean;
|
|
6
|
+
user?: {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
email?: string;
|
|
10
|
+
image?: string | null;
|
|
11
|
+
} | null;
|
|
12
|
+
/** The linked user's QwkSearch API key. */
|
|
13
|
+
apiKey?: string | null;
|
|
14
|
+
/** Lower-case QwkSearch plan key (`"free"`, `"pro"`, …). */
|
|
15
|
+
plan?: string | null;
|
|
16
|
+
/** Stripe Payment Link that upgrades this QwkSearch account, when on a free plan. */
|
|
17
|
+
upgradeUrl?: string | null;
|
|
18
|
+
}
|
|
19
|
+
export interface QwkSearchConnectOptions {
|
|
20
|
+
sessionUrl: string;
|
|
21
|
+
connectUrl: string;
|
|
22
|
+
disconnectUrl: string;
|
|
23
|
+
/** Origin whose `/api/` requests get the key. Defaults to qwksearch.com. */
|
|
24
|
+
qwksearchOrigin?: string;
|
|
25
|
+
/** Called with every session the host reports (e.g. to show the plan). */
|
|
26
|
+
onSession?: (session: QwkSearchConnectSession) => void;
|
|
27
|
+
}
|
|
28
|
+
/** True when `input` targets `<origin>/api/…`. */
|
|
29
|
+
export declare function isQwkSearchApiRequest(input: RequestInfo | URL, origin: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Sets (or with `null`, clears) the QwkSearch API key the embed sends.
|
|
32
|
+
* `origin` defaults to qwksearch.com.
|
|
33
|
+
*/
|
|
34
|
+
export declare function setQwkSearchApiKey(key: string | null, origin?: string): void;
|
|
35
|
+
/** The key currently attached to QwkSearch API requests, if any. */
|
|
36
|
+
export declare function getQwkSearchApiKey(): string | null;
|
|
37
|
+
/** Where `connectUrl` should send the visitor back to: the page they are on. */
|
|
38
|
+
export declare function buildConnectStartUrl(connectUrl: string, returnTo?: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* An auth client for `SessionProvider` (and better-auth-style
|
|
41
|
+
* `useSession()` callers) that signs in through QwkSearch's connect flow.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createQwkSearchConnectAuthClient(options: QwkSearchConnectOptions): {
|
|
44
|
+
/** The last session the host reported (no request). */
|
|
45
|
+
getCachedSession: () => QwkSearchConnectSession;
|
|
46
|
+
/** Re-reads the host's session endpoint (e.g. after an upgrade). */
|
|
47
|
+
refresh: () => Promise<QwkSearchConnectSession>;
|
|
48
|
+
/** Subscribes to session changes; returns an unsubscribe function. */
|
|
49
|
+
subscribe: (listener: () => void) => () => boolean;
|
|
50
|
+
getSession: () => Promise<{
|
|
51
|
+
data: {
|
|
52
|
+
user: {
|
|
53
|
+
id: string;
|
|
54
|
+
name: string;
|
|
55
|
+
email?: string;
|
|
56
|
+
image?: string | null;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
}>;
|
|
60
|
+
oneTap: (_opts?: {
|
|
61
|
+
fetchOptions: {
|
|
62
|
+
onSuccess: () => void;
|
|
63
|
+
};
|
|
64
|
+
}) => void;
|
|
65
|
+
signIn: {
|
|
66
|
+
social: (_opts?: {
|
|
67
|
+
provider: string;
|
|
68
|
+
callbackURL: string;
|
|
69
|
+
}) => void;
|
|
70
|
+
};
|
|
71
|
+
signOut: (opts?: {
|
|
72
|
+
fetchOptions?: {
|
|
73
|
+
onSuccess?: () => void;
|
|
74
|
+
};
|
|
75
|
+
}) => Promise<{
|
|
76
|
+
data: any;
|
|
77
|
+
}>;
|
|
78
|
+
};
|
|
79
|
+
export type QwkSearchConnectAuthClient = ReturnType<typeof createQwkSearchConnectAuthClient>;
|
package/dist/settings/index.d.ts
CHANGED
|
@@ -57,3 +57,18 @@ export declare function getSettingsSchema(): {
|
|
|
57
57
|
sections: SettingsSectionSchema[];
|
|
58
58
|
fieldsBySection: Record<string, SettingsFieldSchema[]>;
|
|
59
59
|
};
|
|
60
|
+
/**
|
|
61
|
+
* One settings section as a standalone page a host can mount in its own
|
|
62
|
+
* settings area — the "external page" form of {@link SettingsSectionSchema}.
|
|
63
|
+
*/
|
|
64
|
+
export interface SettingsPageSchema extends SettingsSectionSchema {
|
|
65
|
+
/** Route the host serves this section at, e.g. `/settings/research/models`. */
|
|
66
|
+
href: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The settings sections as pages under `basePath`, in menu order. A host that
|
|
70
|
+
* embeds the research agent registers these alongside its own settings pages
|
|
71
|
+
* (`basePath` is where it mounts the research settings), so every section the
|
|
72
|
+
* agent exposes is reachable from the host's global settings.
|
|
73
|
+
*/
|
|
74
|
+
export declare function getSettingsPages(basePath?: string): SettingsPageSchema[];
|