research-agent-ui 0.1.93 → 0.1.95

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.
Files changed (59) hide show
  1. package/README.md +0 -3
  2. package/dist/api/handlers/autocomplete.d.ts +1 -0
  3. package/dist/api/handlers/mcpservers.d.ts +7 -0
  4. package/dist/api/handlers/messages.d.ts +7 -0
  5. package/dist/api/handlers/rewrite.d.ts +3 -0
  6. package/dist/api/handlers/transcript.d.ts +7 -0
  7. package/dist/api/handlers/validate-openrouter.d.ts +3 -0
  8. package/dist/api/handlers/voice.d.ts +7 -0
  9. package/dist/api/index.d.ts +3 -0
  10. package/dist/api/types.d.ts +1 -1
  11. package/dist/api.cjs +3 -3
  12. package/dist/api.mjs +5 -4
  13. package/dist/cloudflare/worker.d.ts +1 -0
  14. package/dist/components/ArticleReader/ArticleAIResponse.d.ts +1 -1
  15. package/dist/components/ArticleReader/ArticleActionButtons.d.ts +1 -2
  16. package/dist/components/ArticleReader/ArticleFollowupQuestions.d.ts +1 -1
  17. package/dist/components/ArticleReader/ArticlePanelHeader.d.ts +1 -1
  18. package/dist/components/ArticleReader/ArticlePromptInput.d.ts +1 -1
  19. package/dist/components/ArticleReader/index.d.ts +1 -1
  20. package/dist/components/ChatConversation/DownloadsDialog.d.ts +6 -0
  21. package/dist/components/ChatConversation/background-art.d.ts +3 -0
  22. package/dist/components/ChatHistoryDropdown/HistorySubmenu.d.ts +7 -0
  23. package/dist/components/ChatHistoryDropdown/index.d.ts +1 -1
  24. package/dist/components/ChatHistoryDropdown/useRecentChats.d.ts +13 -0
  25. package/dist/components/FileUpload/FilePreviewCard.d.ts +4 -2
  26. package/dist/components/Footer.d.ts +2 -0
  27. package/dist/components/MessageComposer/ActionBar.d.ts +4 -2
  28. package/dist/components/MessageComposer/MessageInputIconSet.d.ts +4 -2
  29. package/dist/components/MessageComposer/PastedContentCard.d.ts +4 -2
  30. package/dist/config.d.ts +12 -0
  31. package/dist/hooks/useChat/ChatContext.d.ts +14 -0
  32. package/dist/hooks/voice/useSpeechToTranscript.d.ts +17 -2
  33. package/dist/hooks/voice/useVoiceAutoStart.d.ts +6 -0
  34. package/dist/icons/IconSearchAcademic.d.ts +3 -0
  35. package/dist/icons/IconSearchFiles.d.ts +3 -0
  36. package/dist/icons/IconSearchImages.d.ts +3 -0
  37. package/dist/icons/IconSearchNews.d.ts +3 -0
  38. package/dist/icons/IconSearchTech.d.ts +3 -0
  39. package/dist/icons/IconSearchVideos.d.ts +3 -0
  40. package/dist/icons/IconSearchWeb.d.ts +3 -0
  41. package/dist/index.cjs +15 -15
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.mjs +1237 -939
  44. package/dist/lib/composer.d.ts +1 -1
  45. package/dist/lib/file-sources.d.ts +7 -0
  46. package/dist/lib/guest.d.ts +6 -0
  47. package/dist/lib/relative-time.d.ts +1 -1
  48. package/dist/lib/url-autolink.d.ts +1 -2
  49. package/dist/lib/utils.d.ts +3 -0
  50. package/dist/lib/voiceAutoStart.d.ts +22 -0
  51. package/dist/{rolldown-runtime-CMqjfN_6.cjs → rolldown-runtime-BocRIvOZ.cjs} +1 -1
  52. package/dist/settings/index.d.ts +57 -0
  53. package/dist/stories/mocks.d.ts +1 -1
  54. package/dist/types/fileSource.d.ts +3 -0
  55. package/dist/types/research.d.ts +1 -1
  56. package/package.json +29 -11
  57. package/src/settings/index.ts +96 -0
  58. package/src/settings/search.json +161 -0
  59. package/src/settings/sections.json +65 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Shared logic for chat message composers.
2
+ * @fileoverview Shared logic for chat message composers.
3
3
  */
4
4
  /**
5
5
  * Whether a composer has enough to submit. A request is valid when the user
@@ -1,3 +1,10 @@
1
+ /**
2
+ * @fileoverview localStorage-backed CRUD for configured file sources (local, SSH, S3, R2, B2, Google Docs, Turso).
3
+ *
4
+ * Always guarantees a default "Local Files" source is present and tracks
5
+ * which source is currently active; used by the file browser to let users
6
+ * connect and switch between multiple storage backends.
7
+ */
1
8
  import { AnyFileSource } from '../types/fileSource';
2
9
  export type { FileSource, AnyFileSource } from '../types/fileSource';
3
10
  export type { FileSourceType, SSHCredentials, S3Credentials, R2Credentials, B2Credentials, GoogleDocsCredentials, TursoDBCredentials, LocalFileSource, SSHFileSource, S3FileSource, R2FileSource, B2FileSource, GoogleDocsFileSource, TursoDBFileSource } from '../types/fileSource';
@@ -1,3 +1,9 @@
1
+ /**
2
+ * @fileoverview localStorage-backed CRUD for guest (unauthenticated) chat history.
3
+ *
4
+ * Mirrors the shape of server-persisted chats so guest users can create,
5
+ * read, update, and delete chats entirely client-side without an account.
6
+ */
1
7
  import { Message } from "../components/ChatConversation/ChatWindow";
2
8
  import type { ChatFile as File } from "../types/chat";
3
9
  export interface GuestChat {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Formats a timestamp as a compact relative string (e.g. "5 min", "2 hr",
2
+ * @fileoverview Formats a timestamp as a compact relative string (e.g. "5 min", "2 hr",
3
3
  * "3 days"). Used by the home page chat history chips to show how long ago a
4
4
  * conversation was last active, without a trailing "ago".
5
5
  */
@@ -1,7 +1,6 @@
1
1
  /**
2
- * URL Auto-linking Utility
2
+ * @fileoverview URL auto-linking utility: detects plain URLs and email addresses in text and converts them to markdown links.
3
3
  *
4
- * Detects plain URLs (with or without protocol) and converts them to markdown links.
5
4
  * Handles patterns like:
6
5
  * - github.com/kubet/mk-blog
7
6
  * - https://github.com/kubet/mk-blog
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @fileoverview Small shared utilities: Tailwind class merging and human-readable time formatting.
3
+ */
1
4
  import { type ClassValue } from 'clsx';
2
5
  export declare function cn(...inputs: ClassValue[]): string;
3
6
  /**
@@ -0,0 +1,22 @@
1
+ /** Whether the user has opted in to auto-starting dictation. */
2
+ export declare function isVoiceAutoStartEnabled(): boolean;
3
+ /** Persists the user's auto-start preference. */
4
+ export declare function setVoiceAutoStartEnabled(enabled: boolean): void;
5
+ /** Marks auto-start as already fired in this browser. */
6
+ export declare function markVoiceAutoStartTriggered(): void;
7
+ export interface ShouldAutoStartVoiceOptions {
8
+ /** Whether the user opted in via `isVoiceAutoStartEnabled()`. */
9
+ enabled: boolean;
10
+ /** Whether the browser/environment can actually run speech input. */
11
+ isSpeechSupported: boolean;
12
+ /** Whether dictation is already listening. */
13
+ isListening: boolean;
14
+ }
15
+ /**
16
+ * Pure decision of whether to auto-start dictation right now. Does not read
17
+ * or write localStorage itself so it stays trivially testable; callers read
18
+ * the "already triggered" flag and call `markVoiceAutoStartTriggered()`.
19
+ */
20
+ export declare function shouldAutoStartVoice({ enabled, isSpeechSupported, isListening }: ShouldAutoStartVoiceOptions, alreadyTriggered: boolean): boolean;
21
+ /** Whether auto-start has already fired in this browser. */
22
+ export declare function hasVoiceAutoStartTriggered(): boolean;
@@ -1 +1 @@
1
- var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return s}});
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return s}});
@@ -0,0 +1,57 @@
1
+ /** The kind of control a setting is edited with. */
2
+ export type SettingsFieldType = "string" | "password" | "textarea" | "select" | "switch" | "theme";
3
+ /** Where a setting's value lives: browser `localStorage` or the server config. */
4
+ export type SettingsFieldScope = "client" | "server";
5
+ export interface SettingsFieldOption {
6
+ name: string;
7
+ value: string;
8
+ }
9
+ export interface SettingsFieldLink {
10
+ name: string;
11
+ url: string;
12
+ }
13
+ /**
14
+ * A single declarative setting. This is intentionally structurally compatible
15
+ * with `shadcn-settings`' field type so the schema can be passed straight to
16
+ * the renderer, and with the app's own `UIConfigField` union.
17
+ */
18
+ export interface SettingsFieldSchema {
19
+ name: string;
20
+ key: string;
21
+ type: SettingsFieldType;
22
+ required: boolean;
23
+ description: string;
24
+ scope: SettingsFieldScope;
25
+ default?: string | boolean;
26
+ placeholder?: string;
27
+ env?: string;
28
+ options?: SettingsFieldOption[];
29
+ links?: SettingsFieldLink[];
30
+ }
31
+ /** Metadata describing one entry in the settings sidebar/menu. */
32
+ export interface SettingsSectionSchema {
33
+ /** Stable id used for routing and the active-tab state. */
34
+ key: string;
35
+ /** Human-readable label shown in the menu and header. */
36
+ name: string;
37
+ /** One-line summary shown under the header. */
38
+ description: string;
39
+ /** lucide-react icon name; the app maps this to a component. */
40
+ icon: string;
41
+ /** Config namespace this section reads/writes (`config.values[dataAdd]`). */
42
+ dataAdd: string;
43
+ }
44
+ /** Ordered list of settings sections (menu items). */
45
+ export declare const settingsSections: SettingsSectionSchema[];
46
+ /** Field declarations for the "Search Settings" section. */
47
+ export declare const searchSettingsFields: SettingsFieldSchema[];
48
+ /** Every field group keyed by the section `dataAdd` it belongs to. */
49
+ export declare const settingsFieldsBySection: Record<string, SettingsFieldSchema[]>;
50
+ /**
51
+ * Return the full app settings schema. Named like a request because the app
52
+ * asks this module for "the setting info" rather than declaring it inline.
53
+ */
54
+ export declare function getSettingsSchema(): {
55
+ sections: SettingsSectionSchema[];
56
+ fieldsBySection: Record<string, SettingsFieldSchema[]>;
57
+ };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Shared mock data for Storybook stories.
2
+ * @fileoverview Shared mock data for Storybook stories.
3
3
  *
4
4
  * These fixtures let the chat components render in complete isolation — no
5
5
  * API calls, auth session, or chat provider required. Everything a story
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @fileoverview Type definitions for pluggable file storage source backends and their credentials.
3
+ */
1
4
  export type FileSourceType = 'local' | 'ssh' | 's3' | 'r2' | 'b2' | 'gdocs' | 'turso';
2
5
  export interface SSHCredentials {
3
6
  /** SSH host name or IP address. */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Type definitions used by the ResearchAgent area of the ResearchAgent feature.
2
+ * @fileoverview Type definitions used by the ResearchAgent area of the ResearchAgent feature.
3
3
  */
4
4
  import { ChatFile, ChatModelProvider } from "./chat";
5
5
  export type { ChatModelProvider };
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.93",
4
+ "version": "0.1.95",
5
5
  "author": "vtempest",
6
6
  "repository": {
7
7
  "type": "git",
@@ -31,10 +31,18 @@
31
31
  "./file-sources": {
32
32
  "types": "./src/lib/file-sources.ts",
33
33
  "import": "./src/lib/file-sources.ts"
34
+ },
35
+ "./settings": {
36
+ "types": "./src/settings/index.ts",
37
+ "import": "./src/settings/index.ts"
38
+ },
39
+ "./settings/*": {
40
+ "import": "./src/settings/*"
34
41
  }
35
42
  },
36
43
  "files": [
37
44
  "dist",
45
+ "src/settings",
38
46
  "README.md"
39
47
  ],
40
48
  "sideEffects": false,
@@ -46,7 +54,9 @@
46
54
  "type-check": "tsc --noEmit",
47
55
  "storybook": "storybook dev -p 6006",
48
56
  "build-storybook": "storybook build",
49
- "prepublishOnly": "bun run build"
57
+ "prepublishOnly": "bun run build",
58
+ "test": "vitest run",
59
+ "test:coverage": "vitest run --coverage"
50
60
  },
51
61
  "keywords": [
52
62
  "chat",
@@ -70,30 +80,34 @@
70
80
  "@radix-ui/react-tooltip": "^1.2.9",
71
81
  "@ricky0123/vad-web": "^0.0.30",
72
82
  "ai": "^5.0.0",
73
- "chat-agent-toolkit": "^1.2.117",
74
- "domain-rank": "^0.1.106",
75
- "drizzle-orm": "^0.45.2",
76
- "fuse.js": "^7.1.0",
83
+ "chat-agent-toolkit": "^1.2.223",
77
84
  "class-variance-authority": "^0.7.1",
78
85
  "clsx": "^2.1.1",
86
+ "domain-rank": "^0.1.212",
79
87
  "dompurify": "^3.4.9",
80
- "extract-webpage": "^1.2.117",
81
- "search-web-api": "^1.0.75",
88
+ "drizzle-orm": "^0.45.2",
89
+ "extract-webpage": "^1.2.223",
82
90
  "framer-motion": "^12.40.0",
91
+ "fuse.js": "^7.1.0",
83
92
  "grab-url": "^1.6.22",
84
- "kokoro-js": "^1.2.1",
85
- "qwksearch-api-client": "^0.9.64",
86
93
  "html2canvas": "^1.4.1",
94
+ "kokoro-js": "^1.2.1",
87
95
  "lucide-react": "^1.17.0",
88
96
  "markdown-to-jsx": "^9.8.2",
89
97
  "motion": "^12.40.0",
90
98
  "quantum-sphere-loading-icon": "^1.0.3",
99
+ "qwksearch-api-client": "^0.9.170",
91
100
  "react-icons": "^5.6.0",
101
+ "react-native-app-buttons": "^0.1.4",
92
102
  "react-textarea-autosize": "^8.5.9",
103
+ "trending-news-api": "^0.1.0",
104
+ "use-weather-forecast": "^0.1.40",
105
+ "search-web-api": "^1.0.76",
93
106
  "sonner": "^2.0.7",
94
107
  "streamdown": "^2.5.0",
95
108
  "tailwind-merge": "^3.6.0",
96
- "turndown": "^7.2.4"
109
+ "turndown": "^7.2.4",
110
+ "use-voice-control": "^0.1.37"
97
111
  },
98
112
  "devDependencies": {
99
113
  "@cloudflare/workers-types": "^4.20250115.0",
@@ -102,8 +116,11 @@
102
116
  "@types/turndown": "^5.0.5",
103
117
  "@storybook/react-vite": "^9.0.0",
104
118
  "@tailwindcss/vite": "^4.3.0",
119
+ "@testing-library/react": "^16.1.0",
105
120
  "@vitejs/plugin-react": "^6.0.3",
121
+ "@vitest/coverage-v8": "^4.0.18",
106
122
  "itty-router": "^5.0.24",
123
+ "jsdom": "^28.1.0",
107
124
  "storybook": "^9.0.0",
108
125
  "tailwindcss": "^4.3.0",
109
126
  "next": "^16.2.10",
@@ -111,6 +128,7 @@
111
128
  "react-dom": "^19.2.7",
112
129
  "typescript": "^5.7.2",
113
130
  "vite": "^8.1.3",
131
+ "vitest": "^4.0.18",
114
132
  "wrangler": "^3.88.0"
115
133
  },
116
134
  "license": "rights.institute/PROSPER"
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @fileoverview App-specific settings schema, declared as data.
3
+ *
4
+ * These JSON files are the single source of truth for *which* settings the app
5
+ * exposes and how each one should be described and edited. The consuming app
6
+ * "requests" this information at build/runtime and hands it to a renderer (see
7
+ * the `shadcn-settings` package) that turns each declaration into a control.
8
+ *
9
+ * Keeping the schema here — separate from both the server config manager that
10
+ * reads/writes the values and the components that render them — means the list
11
+ * of settings can change without touching rendering or persistence code.
12
+ */
13
+ import sectionsJson from "./sections.json";
14
+ import searchJson from "./search.json";
15
+
16
+ /** The kind of control a setting is edited with. */
17
+ export type SettingsFieldType =
18
+ | "string"
19
+ | "password"
20
+ | "textarea"
21
+ | "select"
22
+ | "switch"
23
+ | "theme";
24
+
25
+ /** Where a setting's value lives: browser `localStorage` or the server config. */
26
+ export type SettingsFieldScope = "client" | "server";
27
+
28
+ export interface SettingsFieldOption {
29
+ name: string;
30
+ value: string;
31
+ }
32
+
33
+ export interface SettingsFieldLink {
34
+ name: string;
35
+ url: string;
36
+ }
37
+
38
+ /**
39
+ * A single declarative setting. This is intentionally structurally compatible
40
+ * with `shadcn-settings`' field type so the schema can be passed straight to
41
+ * the renderer, and with the app's own `UIConfigField` union.
42
+ */
43
+ export interface SettingsFieldSchema {
44
+ name: string;
45
+ key: string;
46
+ type: SettingsFieldType;
47
+ required: boolean;
48
+ description: string;
49
+ scope: SettingsFieldScope;
50
+ default?: string | boolean;
51
+ placeholder?: string;
52
+ env?: string;
53
+ options?: SettingsFieldOption[];
54
+ links?: SettingsFieldLink[];
55
+ }
56
+
57
+ /** Metadata describing one entry in the settings sidebar/menu. */
58
+ export interface SettingsSectionSchema {
59
+ /** Stable id used for routing and the active-tab state. */
60
+ key: string;
61
+ /** Human-readable label shown in the menu and header. */
62
+ name: string;
63
+ /** One-line summary shown under the header. */
64
+ description: string;
65
+ /** lucide-react icon name; the app maps this to a component. */
66
+ icon: string;
67
+ /** Config namespace this section reads/writes (`config.values[dataAdd]`). */
68
+ dataAdd: string;
69
+ }
70
+
71
+ /** Ordered list of settings sections (menu items). */
72
+ export const settingsSections: SettingsSectionSchema[] =
73
+ sectionsJson as unknown as SettingsSectionSchema[];
74
+
75
+ /** Field declarations for the "Search Settings" section. */
76
+ export const searchSettingsFields: SettingsFieldSchema[] =
77
+ searchJson as unknown as SettingsFieldSchema[];
78
+
79
+ /** Every field group keyed by the section `dataAdd` it belongs to. */
80
+ export const settingsFieldsBySection: Record<string, SettingsFieldSchema[]> = {
81
+ search: searchSettingsFields,
82
+ };
83
+
84
+ /**
85
+ * Return the full app settings schema. Named like a request because the app
86
+ * asks this module for "the setting info" rather than declaring it inline.
87
+ */
88
+ export function getSettingsSchema(): {
89
+ sections: SettingsSectionSchema[];
90
+ fieldsBySection: Record<string, SettingsFieldSchema[]>;
91
+ } {
92
+ return {
93
+ sections: settingsSections,
94
+ fieldsBySection: settingsFieldsBySection,
95
+ };
96
+ }
@@ -0,0 +1,161 @@
1
+ [
2
+ {
3
+ "name": "Background Art",
4
+ "key": "showBackgroundArt",
5
+ "type": "switch",
6
+ "required": false,
7
+ "description": "Show a random artistic background on the chat homepage.",
8
+ "default": true,
9
+ "scope": "client"
10
+ },
11
+ {
12
+ "name": "Orb Hover Glow",
13
+ "key": "orbHoverGlow",
14
+ "type": "switch",
15
+ "required": false,
16
+ "description": "Highlight the homepage orb animation with a color glow when you hover over it.",
17
+ "default": false,
18
+ "scope": "client"
19
+ },
20
+ {
21
+ "name": "Cursor Glow Trail",
22
+ "key": "cursorGlowTrail",
23
+ "type": "switch",
24
+ "required": false,
25
+ "description": "Paint a colored glow trail that follows your cursor across the chat homepage background.",
26
+ "default": false,
27
+ "scope": "client"
28
+ },
29
+ {
30
+ "name": "Search Result Glow Effect",
31
+ "key": "searchResultGlow",
32
+ "type": "switch",
33
+ "required": false,
34
+ "description": "Add a cursor-following glow border to source cards in the search results panel.",
35
+ "default": false,
36
+ "scope": "client"
37
+ },
38
+ {
39
+ "name": "TTS Voice",
40
+ "key": "ttsSpeaker",
41
+ "type": "select",
42
+ "required": false,
43
+ "description": "Voice used for read-aloud text-to-speech.",
44
+ "default": "angus",
45
+ "scope": "client",
46
+ "options": [
47
+ { "name": "Angus", "value": "angus" },
48
+ { "name": "Asteria", "value": "asteria" },
49
+ { "name": "Arcas", "value": "arcas" },
50
+ { "name": "Orion", "value": "orion" },
51
+ { "name": "Orpheus", "value": "orpheus" },
52
+ { "name": "Athena", "value": "athena" },
53
+ { "name": "Luna", "value": "luna" },
54
+ { "name": "Zeus", "value": "zeus" },
55
+ { "name": "Perseus", "value": "perseus" },
56
+ { "name": "Helios", "value": "helios" },
57
+ { "name": "Hera", "value": "hera" },
58
+ { "name": "Stella", "value": "stella" }
59
+ ]
60
+ },
61
+ {
62
+ "name": "System Instructions",
63
+ "key": "systemInstructions",
64
+ "type": "textarea",
65
+ "required": false,
66
+ "description": "Add custom behavior or tone for the model.",
67
+ "placeholder": "e.g., \"Respond in a friendly and concise tone\" or \"Use British English and format answers as bullet points.\"",
68
+ "scope": "client"
69
+ },
70
+ {
71
+ "name": "Follow-up Questions",
72
+ "key": "maxFollowupQuestions",
73
+ "type": "select",
74
+ "options": [
75
+ { "name": "2 questions", "value": "2" },
76
+ { "name": "3 questions", "value": "3" },
77
+ { "name": "4 questions (default)", "value": "4" },
78
+ { "name": "5 questions", "value": "5" },
79
+ { "name": "6 questions", "value": "6" }
80
+ ],
81
+ "required": false,
82
+ "description": "Number of follow-up question suggestions to generate after each chat response.",
83
+ "default": "4",
84
+ "scope": "client"
85
+ },
86
+ {
87
+ "name": "SearXNG URL",
88
+ "key": "searxngURL",
89
+ "type": "string",
90
+ "required": false,
91
+ "description": "The URL of your SearXNG instance",
92
+ "placeholder": "http://localhost:4000",
93
+ "default": "",
94
+ "scope": "server",
95
+ "env": "SEARXNG_API_URL"
96
+ },
97
+ {
98
+ "name": "Proxy URL",
99
+ "key": "proxyURL",
100
+ "type": "string",
101
+ "required": false,
102
+ "description": "Optional HTTP/HTTPS/SOCKS5 proxy for outbound search and scrape requests. Format: http://user:pass@host:port or socks5://host:port",
103
+ "placeholder": "http://user:pass@proxy.example.com:8080",
104
+ "default": "",
105
+ "scope": "server",
106
+ "env": "PROXY_URL",
107
+ "links": [
108
+ { "name": "Webshare", "url": "https://www.webshare.io/?referral_code=proxy" },
109
+ { "name": "Bright Data", "url": "https://brightdata.com" },
110
+ { "name": "ProxyMesh", "url": "https://proxymesh.com" },
111
+ { "name": "Free Proxy List", "url": "https://free-proxy-list.net" }
112
+ ]
113
+ },
114
+ {
115
+ "name": "Tavily API Key",
116
+ "key": "tavilyApiKey",
117
+ "type": "password",
118
+ "required": false,
119
+ "description": "Optional. Enter your own Tavily API key to override the site default. Leave blank to use the site-provided key.",
120
+ "placeholder": "tvly-...",
121
+ "default": "",
122
+ "scope": "server",
123
+ "env": "TAVILY_API_KEY"
124
+ },
125
+ {
126
+ "name": "Scrape timeout (seconds)",
127
+ "key": "sourceScrapeTimeout",
128
+ "type": "select",
129
+ "options": [
130
+ { "name": "3 seconds", "value": "3" },
131
+ { "name": "5 seconds (default)", "value": "5" },
132
+ { "name": "10 seconds", "value": "10" },
133
+ { "name": "15 seconds", "value": "15" },
134
+ { "name": "20 seconds", "value": "20" }
135
+ ],
136
+ "required": false,
137
+ "description": "Maximum time to wait when scraping each source URL. Slower timeouts allow more content but increase response time.",
138
+ "default": "5",
139
+ "scope": "server"
140
+ },
141
+ {
142
+ "name": "Weather Locations",
143
+ "key": "weatherLocations",
144
+ "type": "textarea",
145
+ "required": false,
146
+ "description": "Show the homepage weather widget for one or more places. Enter one location per line as \"Label, latitude, longitude\" (for example: Tokyo, 35.68, 139.69). Leave blank to auto-detect your current location.",
147
+ "placeholder": "Tokyo, 35.68, 139.69\nNew York, 40.71, -74.01",
148
+ "scope": "client",
149
+ "default": ""
150
+ },
151
+ {
152
+ "name": "Trending News API URL",
153
+ "key": "trendingNewsApiUrl",
154
+ "type": "string",
155
+ "required": false,
156
+ "description": "Show the homepage trending news widget. Enter the URL of your deployed trending-news-api Cloudflare Worker. Leave blank to hide the widget.",
157
+ "placeholder": "https://trending-news-api.your-subdomain.workers.dev",
158
+ "scope": "client",
159
+ "default": ""
160
+ }
161
+ ]
@@ -0,0 +1,65 @@
1
+ [
2
+ {
3
+ "key": "account",
4
+ "name": "Account",
5
+ "description": "Manage your profile, password, and linked accounts.",
6
+ "icon": "UserCircle",
7
+ "dataAdd": "account"
8
+ },
9
+ {
10
+ "key": "models",
11
+ "name": "Language Models",
12
+ "description": "Connect to AI services and manage connections.",
13
+ "icon": "BrainCog",
14
+ "dataAdd": "modelProviders"
15
+ },
16
+ {
17
+ "key": "mcpservers",
18
+ "name": "Connectors",
19
+ "description": "Configure Model Context Protocol servers.",
20
+ "icon": "Server",
21
+ "dataAdd": "mcpServers"
22
+ },
23
+ {
24
+ "key": "skills-memory",
25
+ "name": "Skills & Memory",
26
+ "description": "Manage agent skills and view your stored memories.",
27
+ "icon": "Brain",
28
+ "dataAdd": "skillsMemory"
29
+ },
30
+ {
31
+ "key": "searchEngines",
32
+ "name": "Search Sources",
33
+ "description": "Manage search engine sources by category.",
34
+ "icon": "Search",
35
+ "dataAdd": "searchEngines"
36
+ },
37
+ {
38
+ "key": "search",
39
+ "name": "Search Settings",
40
+ "description": "Configure search parameters.",
41
+ "icon": "Search",
42
+ "dataAdd": "search"
43
+ },
44
+ {
45
+ "key": "fileSources",
46
+ "name": "Cloud Storage",
47
+ "description": "Manage storage sources (SSH, S3, R2, B2, Google Docs, Turso DB).",
48
+ "icon": "HardDrive",
49
+ "dataAdd": "storage"
50
+ },
51
+ {
52
+ "key": "aiRewriteModes",
53
+ "name": "Rewrite Modes",
54
+ "description": "Customize AI rewrite prompts and add your own modes.",
55
+ "icon": "Wand2",
56
+ "dataAdd": "rewritePrompts"
57
+ },
58
+ {
59
+ "key": "voice",
60
+ "name": "Voice Settings",
61
+ "description": "Configure text-to-speech with Kokoro.js or Cloudflare TTS.",
62
+ "icon": "Volume2",
63
+ "dataAdd": "voice"
64
+ }
65
+ ]